Skip to content

Commit 245d406

Browse files
authored
Test Run pagination added (#93)
* Test Run pagination added Visual-Regression-Tracker/Visual-Regression-Tracker#180
1 parent 0a5b99f commit 245d406

File tree

7 files changed

+151
-34
lines changed

7 files changed

+151
-34
lines changed

.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
JWT_SECRET='jwtPrivateKey'
22
JWT_LIFE_TIME=1d
33

4-
BODY_PARSER_JSON_LIMIT="1mb"
4+
BODY_PARSER_JSON_LIMIT="5mb"
55

66
APP_PORT=4200
77
APP_FRONTEND_URL=http://localhost:8080
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { ApiProperty } from '@nestjs/swagger';
2+
import { Pagination } from '../../shared/dto/pagination.dto';
3+
import { TestRunDto } from './testRun.dto';
4+
5+
export class PaginatedTestRunDto extends Pagination {
6+
@ApiProperty({ type: [TestRunDto] })
7+
data: TestRunDto[];
8+
}

src/test-runs/dto/testRun.dto.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { ApiProperty } from '@nestjs/swagger';
2+
import { TestRun, TestStatus } from '@prisma/client';
3+
4+
export class TestRunDto {
5+
@ApiProperty()
6+
id: string;
7+
@ApiProperty()
8+
buildId: string;
9+
@ApiProperty()
10+
imageName: string;
11+
@ApiProperty()
12+
diffName: string;
13+
@ApiProperty()
14+
diffPercent: number;
15+
@ApiProperty()
16+
diffTollerancePercent: number;
17+
@ApiProperty()
18+
status: TestStatus;
19+
@ApiProperty()
20+
testVariationId: string;
21+
@ApiProperty()
22+
name: string;
23+
@ApiProperty()
24+
baselineName: string;
25+
@ApiProperty()
26+
os: string;
27+
@ApiProperty()
28+
browser: string;
29+
@ApiProperty()
30+
viewport: string;
31+
@ApiProperty()
32+
device: string;
33+
@ApiProperty()
34+
ignoreAreas: string;
35+
@ApiProperty()
36+
tempIgnoreAreas: string;
37+
@ApiProperty()
38+
comment?: string;
39+
@ApiProperty()
40+
branchName: string;
41+
@ApiProperty()
42+
baselineBranchName: string;
43+
@ApiProperty()
44+
merge: boolean;
45+
46+
constructor(testRun: TestRun) {
47+
this.id = testRun.id;
48+
this.buildId = testRun.buildId;
49+
this.imageName = testRun.imageName;
50+
this.diffName = testRun.diffName;
51+
this.diffPercent = testRun.diffPercent;
52+
this.diffTollerancePercent = testRun.diffTollerancePercent;
53+
this.status = testRun.status;
54+
this.testVariationId = testRun.testVariationId;
55+
this.name = testRun.name;
56+
this.baselineName = testRun.baselineName;
57+
this.os = testRun.os;
58+
this.browser = testRun.browser;
59+
this.viewport = testRun.viewport;
60+
this.device = testRun.device;
61+
this.ignoreAreas = testRun.ignoreAreas;
62+
this.tempIgnoreAreas = testRun.tempIgnoreAreas;
63+
this.comment = testRun.comment;
64+
this.branchName = testRun.branchName;
65+
this.baselineBranchName = testRun.baselineBranchName;
66+
this.merge = testRun.merge;
67+
}
68+
}
Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,19 @@
1-
import { TestRun, TestStatus, TestVariation } from '@prisma/client';
1+
import { TestRun, TestVariation } from '@prisma/client';
22
import { ApiProperty } from '@nestjs/swagger';
3+
import { TestRunDto } from './testRun.dto';
34

4-
export class TestRunResultDto {
5-
@ApiProperty()
6-
id: string;
7-
@ApiProperty()
8-
imageName: string;
9-
@ApiProperty()
10-
diffName?: string;
11-
@ApiProperty()
12-
baselineName?: string;
13-
@ApiProperty()
14-
diffPercent: number;
15-
@ApiProperty()
16-
diffTollerancePercent?: number;
5+
export class TestRunResultDto extends TestRunDto {
176
@ApiProperty()
187
pixelMisMatchCount?: number;
198
@ApiProperty()
20-
status: TestStatus;
21-
@ApiProperty()
229
url: string;
2310
@ApiProperty()
24-
merge: boolean;
11+
baselineName: string;
2512

2613
constructor(testRun: TestRun, testVariation: TestVariation) {
27-
this.id = testRun.id;
28-
this.imageName = testRun.imageName;
29-
this.diffName = testRun.diffName;
14+
super(testRun);
3015
this.baselineName = testVariation.baselineName;
31-
this.diffPercent = testRun.diffPercent;
32-
this.diffTollerancePercent = testRun.diffTollerancePercent;
3316
this.pixelMisMatchCount = testRun.pixelMisMatchCount;
34-
this.status = testRun.status;
35-
this.merge = testRun.merge;
3617
this.url = `${process.env.APP_FRONTEND_URL}/${testVariation.projectId}?buildId=${testRun.buildId}&testId=${testRun.id}`;
3718
}
3819
}

src/test-runs/test-runs.controller.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
Query,
1111
Post,
1212
ParseBoolPipe,
13+
ParseIntPipe,
1314
} from '@nestjs/common';
1415
import { ApiTags, ApiParam, ApiBearerAuth, ApiQuery, ApiSecurity, ApiOkResponse } from '@nestjs/swagger';
1516
import { JwtAuthGuard } from '../auth/guards/auth.guard';
@@ -20,18 +21,23 @@ import { CommentDto } from '../shared/dto/comment.dto';
2021
import { TestRunResultDto } from './dto/testRunResult.dto';
2122
import { ApiGuard } from '../auth/guards/api.guard';
2223
import { CreateTestRequestDto } from './dto/create-test-request.dto';
24+
import { PaginatedTestRunDto } from './dto/testRun-paginated.dto';
2325

2426
@ApiTags('test-runs')
2527
@Controller('test-runs')
2628
export class TestRunsController {
2729
constructor(private testRunsService: TestRunsService) {}
2830

2931
@Get()
30-
@ApiQuery({ name: 'buildId', required: true })
32+
@ApiOkResponse({ type: PaginatedTestRunDto })
3133
@ApiBearerAuth()
3234
@UseGuards(JwtAuthGuard)
33-
get(@Query('buildId', new ParseUUIDPipe()) buildId: string): Promise<TestRun[]> {
34-
return this.testRunsService.findMany(buildId);
35+
get(
36+
@Query('buildId', new ParseUUIDPipe()) buildId: string,
37+
@Query('take', new ParseIntPipe()) take: number,
38+
@Query('skip', new ParseIntPipe()) skip: number
39+
): Promise<PaginatedTestRunDto> {
40+
return this.testRunsService.findMany(buildId, take, skip);
3541
}
3642

3743
@Get('recalculateDiff/:id')

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

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { EventsGateway } from '../shared/events/events.gateway';
1414
import { CommentDto } from '../shared/dto/comment.dto';
1515
import { TestVariationsService } from '../test-variations/test-variations.service';
1616
import { convertBaselineDataToQuery } from '../shared/dto/baseline-data.dto';
17+
import { TestRunDto } from './dto/testRun.dto';
1718

1819
jest.mock('pixelmatch');
1920
jest.mock('./dto/testRunResult.dto');
@@ -24,6 +25,7 @@ const initService = async ({
2425
testRunFindUniqueMock = jest.fn(),
2526
testRunFindManyMock = jest.fn(),
2627
testRunCreateMock = jest.fn(),
28+
testRunCountMock = jest.fn(),
2729
getImageMock = jest.fn(),
2830
saveImageMock = jest.fn(),
2931
deleteImageMock = jest.fn(),
@@ -50,6 +52,7 @@ const initService = async ({
5052
findUnique: testRunFindUniqueMock,
5153
create: testRunCreateMock,
5254
update: testRunUpdateMock,
55+
count: testRunCountMock,
5356
},
5457
testVariation: {
5558
create: testVariationCreateMock,
@@ -782,15 +785,53 @@ describe('TestRunsService', () => {
782785

783786
it('findMany', async () => {
784787
const buildId = 'some id';
785-
const testRunFindManyMock = jest.fn();
788+
const testRun: TestRun = {
789+
id: '10fb5e02-64e0-4cf5-9f17-c00ab3c96658',
790+
imageName: '1592423768112.screenshot.png',
791+
diffName: 'diffName',
792+
diffPercent: 12,
793+
diffTollerancePercent: 1,
794+
pixelMisMatchCount: 123,
795+
status: 'new',
796+
buildId: buildId,
797+
testVariationId: '3bc4a5bc-006e-4d43-8e4e-eaa132627fca',
798+
updatedAt: new Date(),
799+
createdAt: new Date(),
800+
name: 'ss2f77',
801+
browser: 'chromium',
802+
device: null,
803+
os: null,
804+
viewport: '1800x1600',
805+
baselineName: null,
806+
ignoreAreas: '[]',
807+
tempIgnoreAreas: '[]',
808+
comment: 'some comment',
809+
baselineBranchName: 'master',
810+
branchName: 'develop',
811+
merge: false,
812+
};
813+
const testRunFindManyMock = jest.fn().mockResolvedValueOnce([testRun]);
814+
const testRunCountMock = jest.fn().mockResolvedValueOnce(30);
786815
service = await initService({
787816
testRunFindManyMock,
817+
testRunCountMock,
788818
});
789819

790-
await service.findMany(buildId);
820+
const result = await service.findMany(buildId, 10, 1);
791821

792822
expect(testRunFindManyMock).toHaveBeenCalledWith({
793823
where: { buildId },
824+
take: 10,
825+
skip: 1,
826+
});
827+
expect(testRunCountMock).toHaveBeenCalledWith({
828+
where: { buildId },
829+
});
830+
expect(result).toEqual({
831+
data: [new TestRunDto(testRun)],
832+
take: 10,
833+
skip: 1,
834+
total: 30,
794835
});
795836
});
796837

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

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import { CommentDto } from '../shared/dto/comment.dto';
1212
import { TestRunResultDto } from '../test-runs/dto/testRunResult.dto';
1313
import { TestVariationsService } from '../test-variations/test-variations.service';
1414
import { convertBaselineDataToQuery } from '../shared/dto/baseline-data.dto';
15+
import { TestRunDto } from './dto/testRun.dto';
16+
import { PaginatedTestRunDto } from './dto/testRun-paginated.dto';
1517

1618
@Injectable()
1719
export class TestRunsService {
@@ -23,10 +25,21 @@ export class TestRunsService {
2325
private eventsGateway: EventsGateway
2426
) {}
2527

26-
async findMany(buildId: string): Promise<TestRun[]> {
27-
return this.prismaService.testRun.findMany({
28-
where: { buildId },
29-
});
28+
async findMany(buildId: string, take: number, skip: number): Promise<PaginatedTestRunDto> {
29+
const [total, list] = await Promise.all([
30+
this.prismaService.testRun.count({ where: { buildId } }),
31+
this.prismaService.testRun.findMany({
32+
where: { buildId },
33+
take,
34+
skip,
35+
}),
36+
]);
37+
return {
38+
data: list.map((item) => new TestRunDto(item)),
39+
total,
40+
take,
41+
skip,
42+
};
3043
}
3144

3245
async findOne(

0 commit comments

Comments
 (0)