Skip to content

Commit 59aca9b

Browse files
committed
Approved test run has unique state without it's baseline overwriting
1 parent 770d64d commit 59aca9b

File tree

7 files changed

+275
-24
lines changed

7 files changed

+275
-24
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Migration `20200526195312-approved-test-status-added`
2+
3+
This migration has been generated by Pavel Strunkin at 5/26/2020, 7:53:12 PM.
4+
You can check out the [state of the schema](./schema.prisma) after the migration.
5+
6+
## Database Steps
7+
8+
```sql
9+
ALTER TYPE "TestStatus" ADD VALUE 'approved'
10+
```
11+
12+
## Changes
13+
14+
```diff
15+
diff --git schema.prisma schema.prisma
16+
migration 20200524162125-baseline-history..20200526195312-approved-test-status-added
17+
--- datamodel.dml
18+
+++ datamodel.dml
19+
@@ -3,9 +3,9 @@
20+
}
21+
datasource db {
22+
provider = "postgresql"
23+
- url = "***"
24+
+ url = env("DATABASE_URL")
25+
}
26+
model Build {
27+
id String @default(uuid()) @id
28+
@@ -101,5 +101,6 @@
29+
failed
30+
new
31+
ok
32+
unresolved
33+
+ approved
34+
}
35+
```
36+
37+
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
generator client {
2+
provider = "prisma-client-js"
3+
}
4+
5+
datasource db {
6+
provider = "postgresql"
7+
url = "***"
8+
}
9+
10+
model Build {
11+
id String @default(uuid()) @id
12+
number Int?
13+
branchName String?
14+
status String?
15+
testRuns TestRun[]
16+
projectId String
17+
project Project @relation(fields: [projectId], references: [id])
18+
updatedAt DateTime @updatedAt
19+
createdAt DateTime @default(now())
20+
user User? @relation(fields: [userId], references: [id])
21+
userId String?
22+
}
23+
24+
model Project {
25+
id String @default(uuid()) @id
26+
name String
27+
builds Build[]
28+
testVariations TestVariation[]
29+
updatedAt DateTime @updatedAt
30+
createdAt DateTime @default(now())
31+
}
32+
33+
model TestRun {
34+
id String @default(uuid()) @id
35+
imageName String
36+
diffName String?
37+
diffPercent Float?
38+
diffTollerancePercent Float @default(1.0)
39+
pixelMisMatchCount Int?
40+
status TestStatus
41+
buildId String
42+
build Build @relation(fields: [buildId], references: [id])
43+
testVariationId String
44+
testVariation TestVariation @relation(fields: [testVariationId], references: [id])
45+
updatedAt DateTime @updatedAt
46+
createdAt DateTime @default(now())
47+
// Test variation data
48+
name String @default("")
49+
browser String?
50+
device String?
51+
os String?
52+
viewport String?
53+
baselineName String?
54+
ignoreAreas String @default("[]")
55+
// Baseline
56+
baseline Baseline?
57+
}
58+
59+
model TestVariation {
60+
id String @default(uuid()) @id
61+
name String
62+
browser String?
63+
device String?
64+
os String?
65+
viewport String?
66+
baselineName String?
67+
ignoreAreas String @default("[]")
68+
projectId String
69+
project Project @relation(fields: [projectId], references: [id])
70+
testRuns TestRun[]
71+
baselines Baseline[]
72+
updatedAt DateTime @updatedAt
73+
createdAt DateTime @default(now())
74+
}
75+
76+
model Baseline {
77+
id String @default(uuid()) @id
78+
baselineName String
79+
testVariationId String
80+
testVariation TestVariation @relation(fields: [testVariationId], references: [id])
81+
testRunId String?
82+
testRun TestRun? @relation(fields: [testRunId], references: [id])
83+
updatedAt DateTime @updatedAt
84+
createdAt DateTime @default(now())
85+
}
86+
87+
model User {
88+
id String @default(uuid()) @id
89+
email String @unique
90+
password String
91+
firstName String?
92+
lastName String?
93+
apiKey String @unique
94+
isActive Boolean @default(true)
95+
builds Build[]
96+
updatedAt DateTime @updatedAt
97+
createdAt DateTime @default(now())
98+
}
99+
100+
enum TestStatus {
101+
failed
102+
new
103+
ok
104+
unresolved
105+
approved
106+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"version": "0.3.14-fixed",
3+
"steps": [
4+
{
5+
"tag": "UpdateEnum",
6+
"enum": "TestStatus",
7+
"createdValues": [
8+
"approved"
9+
]
10+
}
11+
]
12+
}

prisma/migrations/migrate.lock

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@
44
# Read more about conflict resolution here: TODO
55

66
20200503001556-init
7-
20200524162125-baseline-history
7+
20200524162125-baseline-history
8+
20200526195312-approved-test-status-added

prisma/schema.prisma

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,4 +102,5 @@ enum TestStatus {
102102
new
103103
ok
104104
unresolved
105+
approved
105106
}

src/test-runs/test-runs.service.spec.ts

Lines changed: 104 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,30 @@ import { TestRunsService } from './test-runs.service';
44
import { PrismaService } from '../prisma/prisma.service';
55
import { StaticService } from '../shared/static/static.service';
66
import { PNG } from 'pngjs';
7-
import { TestStatus } from '@prisma/client';
7+
import { TestStatus, TestRun } from '@prisma/client';
88
import Pixelmatch from 'pixelmatch';
99
import { CreateTestRequestDto } from 'src/test/dto/create-test-request.dto';
1010
import { DiffResult } from './diffResult';
1111

1212
jest.mock('pixelmatch');
1313

14-
const initService = async ({ testRunCreateMock = jest.fn(), getImageMock = jest.fn(), saveImageMock = jest.fn() }) => {
14+
const initService = async ({
15+
testRunUpdateMock = jest.fn(),
16+
testRunFindOneMock = jest.fn(),
17+
testRunCreateMock = jest.fn(),
18+
getImageMock = jest.fn(),
19+
saveImageMock = jest.fn(),
20+
}) => {
1521
const module: TestingModule = await Test.createTestingModule({
1622
providers: [
1723
TestRunsService,
1824
{
1925
provide: PrismaService,
2026
useValue: {
2127
testRun: {
28+
findOne: testRunFindOneMock,
2229
create: testRunCreateMock,
30+
update: testRunUpdateMock,
2331
},
2432
},
2533
},
@@ -38,6 +46,100 @@ const initService = async ({ testRunCreateMock = jest.fn(), getImageMock = jest.
3846
describe('TestRunsService', () => {
3947
let service: TestRunsService;
4048

49+
it('findOne', async () => {
50+
const id = 'some id';
51+
const testRunFindOneMock = jest.fn();
52+
service = await initService({
53+
testRunFindOneMock,
54+
});
55+
56+
service.findOne(id);
57+
58+
expect(testRunFindOneMock).toHaveBeenCalledWith({
59+
where: { id },
60+
include: {
61+
testVariation: true,
62+
},
63+
});
64+
});
65+
66+
it('reject', async () => {
67+
const id = 'some id';
68+
const testRunUpdateMock = jest.fn();
69+
service = await initService({
70+
testRunUpdateMock,
71+
});
72+
73+
service.reject(id);
74+
75+
expect(testRunUpdateMock).toHaveBeenCalledWith({
76+
where: { id },
77+
data: {
78+
status: TestStatus.failed,
79+
},
80+
});
81+
});
82+
83+
describe('approve', () => {
84+
it('can approve', async () => {
85+
const testRun = {
86+
id: 'id',
87+
imageName: 'imageName',
88+
diffTollerancePercent: 12,
89+
status: TestStatus.new,
90+
buildId: 'buildId',
91+
testVariationId: 'testVariationId',
92+
updatedAt: new Date(),
93+
createdAt: new Date(),
94+
name: 'test run name',
95+
ignoreAreas: '[]',
96+
};
97+
const testRunUpdateMock = jest.fn();
98+
const testRunFindOneMock = jest.fn().mockResolvedValueOnce(testRun);
99+
const baselineName = 'some baseline name';
100+
const saveImageMock = jest.fn().mockReturnValueOnce(baselineName);
101+
const getImageMock = jest.fn().mockReturnValueOnce(
102+
new PNG({
103+
width: 10,
104+
height: 10,
105+
})
106+
);
107+
service = await initService({
108+
testRunUpdateMock,
109+
saveImageMock,
110+
getImageMock,
111+
});
112+
service.findOne = testRunFindOneMock;
113+
114+
await service.approve(testRun.id);
115+
116+
expect(testRunFindOneMock).toHaveBeenCalledWith(testRun.id);
117+
expect(getImageMock).toHaveBeenCalledWith(testRun.imageName);
118+
expect(saveImageMock).toHaveBeenCalledTimes(1);
119+
expect(testRunUpdateMock).toHaveBeenCalledWith({
120+
where: { id: testRun.id },
121+
data: {
122+
status: TestStatus.approved,
123+
testVariation: {
124+
update: {
125+
baselineName,
126+
baselines: {
127+
create: {
128+
baselineName,
129+
testRun: {
130+
connect: {
131+
id: testRun.id,
132+
},
133+
},
134+
},
135+
},
136+
},
137+
},
138+
},
139+
});
140+
});
141+
});
142+
41143
describe('create', () => {
42144
const initCreateTestRequestDto: CreateTestRequestDto = {
43145
buildId: 'buildId',

src/test-runs/test-runs.service.ts

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -38,33 +38,25 @@ export class TestRunsService {
3838

3939
// save new baseline
4040
const baseline = this.staticService.getImage(testRun.imageName);
41-
const imageName = this.staticService.saveImage('baseline', PNG.sync.write(baseline));
42-
43-
// add in baseline history
44-
await this.prismaService.baseline.create({
45-
data: {
46-
baselineName: imageName,
47-
testRun: {
48-
connect: {
49-
id: testRun.id,
50-
},
51-
},
52-
testVariation: {
53-
connect: {
54-
id: testRun.testVariationId,
55-
},
56-
},
57-
},
58-
});
41+
const baselineName = this.staticService.saveImage('baseline', PNG.sync.write(baseline));
5942

6043
return this.prismaService.testRun.update({
6144
where: { id },
6245
data: {
63-
baselineName: imageName,
64-
status: TestStatus.ok,
46+
status: TestStatus.approved,
6547
testVariation: {
6648
update: {
67-
baselineName: imageName,
49+
baselineName,
50+
baselines: {
51+
create: {
52+
baselineName,
53+
testRun: {
54+
connect: {
55+
id: testRun.id,
56+
},
57+
},
58+
},
59+
},
6860
},
6961
},
7062
},

0 commit comments

Comments
 (0)