From 87c3917dc37c1e0a0d5aff9abb226eb8e2851083 Mon Sep 17 00:00:00 2001 From: Pavlo Strunkin Date: Wed, 17 Mar 2021 15:02:07 +0200 Subject: [PATCH 1/2] Compare vs latest main branch baseline after autoApprove closes: https://github.com/Visual-Regression-Tracker/Visual-Regression-Tracker/issues/242 --- src/test-runs/test-runs.service.ts | 80 +++++++++++++++++------------- test/test-runs.e2e-spec.ts | 15 ++++-- 2 files changed, 57 insertions(+), 38 deletions(-) diff --git a/src/test-runs/test-runs.service.ts b/src/test-runs/test-runs.service.ts index a2bee821..a3037773 100644 --- a/src/test-runs/test-runs.service.ts +++ b/src/test-runs/test-runs.service.ts @@ -78,7 +78,15 @@ export class TestRunsService { return new TestRunResultDto(testRunWithResult, testVariation); } - async approve(id: string, merge: boolean, autoApprove?: boolean): Promise { + /** + * Confirm difference for testRun + * + * @param id + * @param merge replaces main branch baseline with feature one + * @param autoApprove set auto approve status + * @returns + */ + async approve(id: string, merge = false, autoApprove = false): Promise { this.logger.log(`Approving testRun: ${id} merge: ${merge} autoApprove: ${autoApprove}`); const status = autoApprove ? TestStatus.autoApproved : TestStatus.approved; const testRun = await this.findOne(id); @@ -88,6 +96,7 @@ export class TestRunsService { const baselineName = this.staticService.saveImage('baseline', PNG.sync.write(baseline)); let testRunUpdated: TestRun; if (merge || testRun.branchName === testRun.baselineBranchName) { + // update existing test variation testRunUpdated = await this.prismaService.testRun.update({ where: { id }, data: { @@ -95,14 +104,14 @@ export class TestRunsService { testVariation: { update: { baselineName, - baselines: { - create: { - baselineName, - testRun: { - connect: { - id: testRun.id, - }, - }, + }, + }, + baseline: { + create: { + baselineName, + testVariation: { + connect: { + id: testRun.testVariationId, }, }, }, @@ -110,36 +119,37 @@ export class TestRunsService { }, }); } else { - const newTestVariation = await this.prismaService.testVariation.create({ - data: { - project: { connect: { id: testRun.testVariation.projectId } }, - baselineName, - ...getTestVariationUniqueData(testRun), - ignoreAreas: testRun.ignoreAreas, - comment: testRun.comment, - branchName: testRun.branchName, - }, - }); - await this.prismaService.baseline.create({ - data: { - baselineName, - testVariation: { - connect: { id: newTestVariation.id }, - }, - testRun: { - connect: { - id: testRun.id, - }, - }, - }, - }); + // create new feature branch test variation testRunUpdated = await this.prismaService.testRun.update({ where: { id }, data: { status, - testVariation: { - connect: { id: newTestVariation.id }, - }, + baseline: autoApprove + ? undefined + : { + create: { + baselineName, + testVariation: { + create: { + baselineName, + ...getTestVariationUniqueData(testRun), + ignoreAreas: testRun.ignoreAreas, + comment: testRun.comment, + branchName: testRun.branchName, + project: { + connect: { + id: testRun.testVariation.projectId, + }, + }, + testRuns: { + connect: { + id, + }, + }, + }, + }, + }, + }, }, }); } diff --git a/test/test-runs.e2e-spec.ts b/test/test-runs.e2e-spec.ts index 0ce5d36e..357db4ff 100644 --- a/test/test-runs.e2e-spec.ts +++ b/test/test-runs.e2e-spec.ts @@ -90,7 +90,7 @@ describe('TestRuns (e2e)', () => { expect(testRun.status).toBe(TestStatus.ok); }); - it('Auto approve not rebased feature branch', async () => { + it('Auto approve not rebased feature branch then Ok after rebase', async () => { const { testRun: testRun1 } = await haveTestRunCreated( buildsService, testRunsService, @@ -108,9 +108,18 @@ describe('TestRuns (e2e)', () => { ); await testRunsService.approve(testRun2.id, false, false); - const { testRun } = await haveTestRunCreated(buildsService, testRunsService, project.id, 'develop', image_v1); + const { testRun: notRebasedTestRun } = await haveTestRunCreated( + buildsService, + testRunsService, + project.id, + 'develop', + image_v1 + ); + expect(notRebasedTestRun.status).toBe(TestStatus.autoApproved); - expect(testRun.status).toBe(TestStatus.autoApproved); + const { testRun: rebasedTestRun } = await haveTestRunCreated(buildsService, testRunsService, project.id, 'develop', image_v2); + + expect(rebasedTestRun.status).toBe(TestStatus.ok); }); it('Auto approve merged feature into feature branch', async () => { From 8903c21b7a815a214594f516c472fc7e50a5e61b Mon Sep 17 00:00:00 2001 From: Pavlo Strunkin Date: Wed, 17 Mar 2021 19:50:42 +0200 Subject: [PATCH 2/2] tests are added --- src/test-runs/test-runs.service.spec.ts | 90 +++++++++-------- test/test-runs.e2e-spec.ts | 124 +++++++++++++++++++++--- test/test-variations.e2e-spec.ts | 2 +- 3 files changed, 158 insertions(+), 58 deletions(-) diff --git a/src/test-runs/test-runs.service.spec.ts b/src/test-runs/test-runs.service.spec.ts index 835e0f80..699d0446 100644 --- a/src/test-runs/test-runs.service.spec.ts +++ b/src/test-runs/test-runs.service.spec.ts @@ -226,7 +226,7 @@ describe('TestRunsService', () => { }); service.findOne = testRunFindOneMock; - await service.approve(testRun.id, false); + await service.approve(testRun.id); expect(testRunFindOneMock).toHaveBeenCalledWith(testRun.id); expect(getImageMock).toHaveBeenCalledWith(testRun.imageName); @@ -238,14 +238,14 @@ describe('TestRunsService', () => { testVariation: { update: { baselineName, - baselines: { - create: { - baselineName, - testRun: { - connect: { - id: testRun.id, - }, - }, + }, + }, + baseline: { + create: { + baselineName, + testVariation: { + connect: { + id: testRun.testVariationId, }, }, }, @@ -318,14 +318,14 @@ describe('TestRunsService', () => { testVariation: { update: { baselineName, - baselines: { - create: { - baselineName, - testRun: { - connect: { - id: testRun.id, - }, - }, + }, + }, + baseline: { + create: { + baselineName, + testVariation: { + connect: { + id: testRun.testVariationId, }, }, }, @@ -427,39 +427,37 @@ describe('TestRunsService', () => { expect(testRunFindOneMock).toHaveBeenCalledWith(testRun.id); expect(getImageMock).toHaveBeenCalledWith(testRun.imageName); expect(saveImageMock).toHaveBeenCalledTimes(1); - expect(testVariationCreateMock).toBeCalledWith({ - data: { - project: { connect: { id: testRun.testVariation.projectId } }, - baselineName, - name: testRun.name, - browser: testRun.browser, - device: testRun.device, - os: testRun.os, - viewport: testRun.viewport, - ignoreAreas: testRun.ignoreAreas, - comment: testRun.comment, - branchName: testRun.branchName, - }, - }); - expect(baselineCreateMock).toHaveBeenCalledWith({ - data: { - baselineName, - testVariation: { - connect: { id: newTestVariation.id }, - }, - testRun: { - connect: { - id: testRun.id, - }, - }, - }, - }); expect(testRunUpdateMock).toHaveBeenCalledWith({ where: { id: testRun.id }, data: { status: TestStatus.approved, - testVariation: { - connect: { id: newTestVariation.id }, + baseline: { + create: { + baselineName, + testVariation: { + create: { + baselineName, + name: testRun.name, + browser: testRun.browser, + device: testRun.device, + os: testRun.os, + viewport: testRun.viewport, + ignoreAreas: testRun.ignoreAreas, + comment: testRun.comment, + branchName: testRun.branchName, + project: { + connect: { + id: testRun.testVariation.projectId, + }, + }, + testRuns: { + connect: { + id: testRun.id, + }, + }, + }, + }, + }, }, }, }); diff --git a/test/test-runs.e2e-spec.ts b/test/test-runs.e2e-spec.ts index 041abf6d..a78e3f8c 100644 --- a/test/test-runs.e2e-spec.ts +++ b/test/test-runs.e2e-spec.ts @@ -8,6 +8,8 @@ import { TestRunsService } from '../src/test-runs/test-runs.service'; import { ProjectsService } from '../src/projects/projects.service'; import { Project, TestStatus } from '@prisma/client'; import { BuildsService } from '../src/builds/builds.service'; +import { PrismaService } from '../src/prisma/prisma.service'; +import { TestVariationsService } from '../src/test-variations/test-variations.service'; jest.useFakeTimers(); @@ -17,9 +19,13 @@ describe('TestRuns (e2e)', () => { let usersService: UsersService; let projecstService: ProjectsService; let buildsService: BuildsService; + let testVariationsService: TestVariationsService; let user: UserLoginResponseDto; let project: Project; + const image_v1 = './test/image.png'; + const image_v2 = './test/image_edited.png'; + beforeAll(async () => { const moduleFixture: TestingModule = await Test.createTestingModule({ imports: [AppModule], @@ -30,6 +36,7 @@ describe('TestRuns (e2e)', () => { usersService = moduleFixture.get(UsersService); projecstService = moduleFixture.get(ProjectsService); buildsService = moduleFixture.get(BuildsService); + testVariationsService = moduleFixture.get(TestVariationsService); await app.init(); }); @@ -50,9 +57,6 @@ describe('TestRuns (e2e)', () => { }); describe('POST /', () => { - const image_v1 = './test/image.png'; - const image_v2 = './test/image_edited.png'; - it('New if no baseline', async () => { const { testRun } = await haveTestRunCreated(buildsService, testRunsService, project.id, 'develop', image_v1); @@ -67,7 +71,7 @@ describe('TestRuns (e2e)', () => { project.mainBranchName, image_v1 ); - await testRunsService.approve(testRun1.id, false, false); + await testRunsService.approve(testRun1.id); const { testRun } = await haveTestRunCreated(buildsService, testRunsService, project.id, 'develop', image_v2); @@ -82,7 +86,7 @@ describe('TestRuns (e2e)', () => { project.mainBranchName, image_v1 ); - await testRunsService.approve(testRun1.id, false, false); + await testRunsService.approve(testRun1.id); const { testRun } = await haveTestRunCreated(buildsService, testRunsService, project.id, 'develop', image_v1); @@ -97,7 +101,7 @@ describe('TestRuns (e2e)', () => { project.mainBranchName, image_v1 ); - await testRunsService.approve(testRun1.id, false, false); + await testRunsService.approve(testRun1.id); const { testRun: testRun2 } = await haveTestRunCreated( buildsService, testRunsService, @@ -105,7 +109,7 @@ describe('TestRuns (e2e)', () => { project.mainBranchName, image_v2 ); - await testRunsService.approve(testRun2.id, false, false); + await testRunsService.approve(testRun2.id); const { testRun: notRebasedTestRun } = await haveTestRunCreated( buildsService, @@ -116,7 +120,13 @@ describe('TestRuns (e2e)', () => { ); expect(notRebasedTestRun.status).toBe(TestStatus.autoApproved); - const { testRun: rebasedTestRun } = await haveTestRunCreated(buildsService, testRunsService, project.id, 'develop', image_v2); + const { testRun: rebasedTestRun } = await haveTestRunCreated( + buildsService, + testRunsService, + project.id, + 'develop', + image_v2 + ); expect(rebasedTestRun.status).toBe(TestStatus.ok); }); @@ -129,7 +139,7 @@ describe('TestRuns (e2e)', () => { 'feature1', image_v1 ); - await testRunsService.approve(testRun1.id, false, false); + await testRunsService.approve(testRun1.id); const { testRun } = await haveTestRunCreated(buildsService, testRunsService, project.id, 'feature2', image_v1); @@ -144,7 +154,7 @@ describe('TestRuns (e2e)', () => { project.mainBranchName, image_v1 ); - await testRunsService.approve(testRun1.id, false, false); + await testRunsService.approve(testRun1.id); const { testRun: testRun2 } = await haveTestRunCreated( buildsService, testRunsService, @@ -152,7 +162,7 @@ describe('TestRuns (e2e)', () => { 'develop', image_v2 ); - await testRunsService.approve(testRun2.id, false, false); + await testRunsService.approve(testRun2.id); const { testRun } = await haveTestRunCreated( buildsService, @@ -165,4 +175,96 @@ describe('TestRuns (e2e)', () => { expect(testRun.status).toBe(TestStatus.autoApproved); }); }); + + describe('POST /approve', () => { + it('approve changes in existing testVariation', async () => { + const { testRun: testRun1 } = await haveTestRunCreated( + buildsService, + testRunsService, + project.id, + project.mainBranchName, + image_v1 + ); + + const result = await testRunsService.approve(testRun1.id); + + expect(result.status).toBe(TestStatus.approved); + const testVariation = await testVariationsService.getDetails(result.testVariationId); + expect(testVariation.baselines).toHaveLength(1); + }); + + it('approve changes in existing testVariation with merge', async () => { + const { testRun: testRun1 } = await haveTestRunCreated( + buildsService, + testRunsService, + project.id, + project.mainBranchName, + image_v1 + ); + const mainBranchResult = await testRunsService.approve(testRun1.id); + const { testRun: testRun2 } = await haveTestRunCreated( + buildsService, + testRunsService, + project.id, + 'develop', + image_v2, + true + ); + + const featureBranchResult = await testRunsService.approve(testRun2.id, true); + + expect(featureBranchResult.status).toBe(TestStatus.approved); + expect(featureBranchResult.merge).toBe(true); + const mainBranchTestVariation = await testVariationsService.getDetails(mainBranchResult.testVariationId); + expect(mainBranchTestVariation.baselines).toHaveLength(2); + expect(mainBranchTestVariation.baselines.shift().baselineName).toBe(mainBranchTestVariation.baselineName); + }); + + it('approve feature branch testVariation', async () => { + const { testRun: testRun1 } = await haveTestRunCreated( + buildsService, + testRunsService, + project.id, + project.mainBranchName, + image_v1 + ); + const mainBranchResult = await testRunsService.approve(testRun1.id); + const { testRun: testRun2 } = await haveTestRunCreated( + buildsService, + testRunsService, + project.id, + 'develop', + image_v2 + ); + + const featureBranchResult = await testRunsService.approve(testRun2.id); + + expect(featureBranchResult.status).toBe(TestStatus.approved); + const mainBranchTestVariation = await testVariationsService.getDetails(mainBranchResult.testVariationId); + expect(mainBranchTestVariation.baselines).toHaveLength(1); + }); + + it('autoApprove feature branch testVariation', async () => { + const { testRun: testRun1 } = await haveTestRunCreated( + buildsService, + testRunsService, + project.id, + project.mainBranchName, + image_v1 + ); + const mainBranchResult = await testRunsService.approve(testRun1.id); + const { testRun: testRun2 } = await haveTestRunCreated( + buildsService, + testRunsService, + project.id, + 'develop', + image_v2 + ); + + const featureBranchResult = await testRunsService.approve(testRun2.id, false, true); + + expect(featureBranchResult.status).toBe(TestStatus.autoApproved); + expect(mainBranchResult.testVariationId).toBe(featureBranchResult.testVariationId); + }); + }); }); diff --git a/test/test-variations.e2e-spec.ts b/test/test-variations.e2e-spec.ts index 89d73596..94ecdb4b 100644 --- a/test/test-variations.e2e-spec.ts +++ b/test/test-variations.e2e-spec.ts @@ -57,7 +57,7 @@ describe('TestVariations (e2e)', () => { it('can delete', async () => { const { testRun } = await haveTestRunCreated(buildsService, testRunsService, project.id, 'develop', image_v1); - await testRunsService.approve(testRun.id, false); + await testRunsService.approve(testRun.id); await testVariationsService.delete(testRun.testVariationId);