Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from "./visualRegressionTracker";
export * from "./testRunResult";
export * from "./types";
46 changes: 46 additions & 0 deletions lib/testRunResult.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import TestRunResult from "./testRunResult";
import { TestRunResponse, TestStatus } from "./types";

describe("TestRunResult", () => {
it("only required images", () => {
const testRunResponse: TestRunResponse = {
url: "url",
status: TestStatus.ok,
pixelMisMatchCount: 12,
diffPercent: 0.12,
diffTollerancePercent: 0,
id: "some id",
imageName: "imageName",
merge: false,
};

const result = new TestRunResult(testRunResponse, "http://localhost");

expect(result.testRunResponse).toBe(testRunResponse);
expect(result.imageUrl).toBe("http://localhost/imageName");
expect(result.diffUrl).toBeUndefined();
expect(result.baselineUrl).toBeUndefined();
});

it("all image", () => {
const testRunResponse: TestRunResponse = {
url: "url",
status: TestStatus.ok,
pixelMisMatchCount: 12,
diffPercent: 0.12,
diffTollerancePercent: 0,
id: "some id",
imageName: "imageName",
diffName: "diffName",
baselineName: "baselineName",
merge: false,
};

const result = new TestRunResult(testRunResponse, "http://localhost");

expect(result.testRunResponse).toBe(testRunResponse);
expect(result.imageUrl).toBe("http://localhost/imageName");
expect(result.diffUrl).toBe("http://localhost/diffName");
expect(result.baselineUrl).toBe("http://localhost/baselineName");
});
});
19 changes: 19 additions & 0 deletions lib/testRunResult.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { TestRunResponse } from "./types";

export default class TestRunResult {
testRunResponse: TestRunResponse;
imageUrl: string;
diffUrl?: string;
baselineUrl?: string;

constructor(testRunResponse: TestRunResponse, apiUrl: string) {
this.testRunResponse = testRunResponse;
this.imageUrl = apiUrl.concat("/").concat(testRunResponse.imageName);
this.diffUrl =
testRunResponse.diffName &&
apiUrl.concat("/").concat(testRunResponse.diffName);
this.baselineUrl =
testRunResponse.baselineName &&
apiUrl.concat("/").concat(testRunResponse.baselineName);
}
}
6 changes: 3 additions & 3 deletions lib/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export * from "./build";
export * from "./config";
export * from "./testRun";
export * from "./testRunResult";
export * from "./testRunStatus";
export * from "./response/buildResponse";
export * from "./response/testRunResponse";
export * from "./testStatus";
2 changes: 1 addition & 1 deletion lib/types/build.ts → lib/types/response/buildResponse.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export interface Build {
export interface BuildResponse {
id: string;
projectId: string;
}
14 changes: 14 additions & 0 deletions lib/types/response/testRunResponse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { TestStatus } from "../testStatus";

export interface TestRunResponse {
id: string;
imageName: string;
diffName?: string;
baselineName?: string;
diffPercent: number;
diffTollerancePercent?: number;
pixelMisMatchCount?: number;
status: TestStatus;
url: string;
merge: boolean;
}
9 changes: 0 additions & 9 deletions lib/types/testRunResult.ts

This file was deleted.

2 changes: 1 addition & 1 deletion lib/types/testRunStatus.ts → lib/types/testStatus.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export enum TestRunStatus {
export enum TestStatus {
new = "new",
ok = "ok",
unresolved = "unresolved",
Expand Down
127 changes: 75 additions & 52 deletions lib/visualRegressionTracker.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
import { VisualRegressionTracker } from "./visualRegressionTracker";
import { Config, Build, TestRun, TestRunResult, TestRunStatus } from "./types";
import {
Config,
BuildResponse,
TestRun,
TestRunResponse,
TestStatus,
} from "./types";
import { mocked } from "ts-jest/utils";
import TestRunResult from "./testRunResult";
import axios, { AxiosError, AxiosResponse } from "axios";

jest.mock("axios");
const mockedAxios = mocked(axios, true);

jest.mock("./testRunResult");
const mockedTestRunResult = mocked(TestRunResult, true);

const axiosError404: AxiosError = {
isAxiosError: true,
config: {},
Expand Down Expand Up @@ -118,68 +128,39 @@ describe("VisualRegressionTracker", () => {
};

it("should track success", async () => {
const testRunResult: TestRunResult = {
const testRunResponse: TestRunResponse = {
url: "url",
status: TestRunStatus.ok,
status: TestStatus.ok,
pixelMisMatchCount: 12,
diffPercent: 0.12,
diffTollerancePercent: 0,
id: "some id",
imageName: "imageName",
diffName: "diffName",
baselineName: "baselineName",
merge: false,
};
vrt["submitTestResult"] = jest.fn().mockResolvedValueOnce(testRunResult);
vrt["submitTestResult"] = jest
.fn()
.mockResolvedValueOnce(testRunResponse);
vrt["processTestRun"] = jest.fn();

await vrt.track(testRun);

expect(vrt["submitTestResult"]).toHaveBeenCalledWith(testRun);
});

describe.each<[TestRunStatus.new | TestRunStatus.unresolved, string]>([
[TestRunStatus.new, "No baseline: "],
[TestRunStatus.unresolved, "Difference found: "],
])("should track error", (status, expectedMessage) => {
const testRunResultMock: TestRunResult = {
url: "http://foo.bar",
status: TestRunStatus.ok,
pixelMisMatchCount: 12,
diffPercent: 0.12,
diffTollerancePercent: 0,
};

beforeEach(() => {
testRunResultMock.status = status;
});

it(`disabled soft assert should throw exception if status ${status}`, async () => {
vrt["config"].enableSoftAssert = false;
vrt["submitTestResult"] = jest
.fn()
.mockResolvedValueOnce(testRunResultMock);

await expect(vrt.track(testRun)).rejects.toThrowError(
new Error(expectedMessage.concat(testRunResultMock.url))
);
});

it(`enabled soft assert should log error if status ${status}`, async () => {
console.error = jest.fn();
vrt["config"].enableSoftAssert = true;
vrt["submitTestResult"] = jest
.fn()
.mockResolvedValueOnce(testRunResultMock);

await vrt.track(testRun);

expect(console.error).toHaveBeenCalledWith(
expectedMessage.concat(testRunResultMock.url)
);
});
expect(vrt["processTestRun"]).toHaveBeenCalledWith(testRunResponse);
expect(mockedTestRunResult).toHaveBeenCalledWith(
testRunResponse,
"http://localhost:4200"
);
});
});

describe("start", () => {
test("should start build", async () => {
const buildId = "1312";
const projectId = "asd";
const build: Build = {
const build: BuildResponse = {
id: buildId,
projectId: projectId,
};
Expand Down Expand Up @@ -261,12 +242,15 @@ describe("VisualRegressionTracker", () => {

describe("submitTestResults", () => {
it("should submit test run", async () => {
const testRunResult: TestRunResult = {
const testRunResponse: TestRunResponse = {
url: "url",
status: TestRunStatus.unresolved,
status: TestStatus.unresolved,
pixelMisMatchCount: 12,
diffPercent: 0.12,
diffTollerancePercent: 0,
id: "some id",
imageName: "imageName",
merge: false,
};
const testRun: TestRun = {
name: "name",
Expand All @@ -280,11 +264,11 @@ describe("VisualRegressionTracker", () => {
const projectId = "asd";
vrt["buildId"] = buildId;
vrt["projectId"] = projectId;
mockedAxios.post.mockResolvedValueOnce({ data: testRunResult });
mockedAxios.post.mockResolvedValueOnce({ data: testRunResponse });

const result = await vrt["submitTestResult"](testRun);

expect(result).toBe(testRunResult);
expect(result).toBe(testRunResponse);
expect(mockedAxios.post).toHaveBeenCalledWith(
`${config.apiUrl}/test-runs`,
{
Expand Down Expand Up @@ -337,7 +321,7 @@ describe("VisualRegressionTracker", () => {
});

test("handleResponse", async () => {
const build: Build = {
const build: BuildResponse = {
id: "id",
projectId: "projectId",
};
Expand Down Expand Up @@ -375,4 +359,43 @@ describe("VisualRegressionTracker", () => {
);
});
});

describe.each<[TestStatus.new | TestStatus.unresolved, string]>([
[TestStatus.new, "No baseline: "],
[TestStatus.unresolved, "Difference found: "],
])("processTestRun", (status, expectedMessage) => {
const testRunResponse: TestRunResponse = {
url: "http://foo.bar",
status: TestStatus.ok,
pixelMisMatchCount: 12,
diffPercent: 0.12,
diffTollerancePercent: 0,
id: "some id",
imageName: "imageName",
merge: false,
};

beforeEach(() => {
testRunResponse.status = status;
});

it(`disabled soft assert should throw exception if status ${status}`, () => {
vrt["config"].enableSoftAssert = false;

expect(() => vrt["processTestRun"](testRunResponse)).toThrowError(
new Error(expectedMessage.concat(testRunResponse.url))
);
});

it(`enabled soft assert should log error if status ${status}`, () => {
console.error = jest.fn();
vrt["config"].enableSoftAssert = true;

vrt["processTestRun"](testRunResponse);

expect(console.error).toHaveBeenCalledWith(
expectedMessage.concat(testRunResponse.url)
);
});
});
});
34 changes: 24 additions & 10 deletions lib/visualRegressionTracker.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { Config, Build, TestRun, TestRunResult, TestRunStatus } from "./types";
import {
Config,
BuildResponse,
TestRun,
TestRunResponse,
TestStatus,
} from "./types";
import TestRunResult from "./testRunResult";
import axios, { AxiosRequestConfig, AxiosResponse, AxiosError } from "axios";

export class VisualRegressionTracker {
Expand Down Expand Up @@ -26,7 +33,7 @@ export class VisualRegressionTracker {
project: this.config.project,
};

const build: Build = await axios
const build: BuildResponse = await axios
.post(`${this.config.apiUrl}/builds`, data, this.axiosConfig)
.then(this.handleResponse)
.catch(this.handleException);
Expand All @@ -50,7 +57,7 @@ export class VisualRegressionTracker {
.catch(this.handleException);
}

private async submitTestResult(test: TestRun): Promise<TestRunResult> {
private async submitTestResult(test: TestRun): Promise<TestRunResponse> {
if (!this.isStarted()) {
throw new Error("Visual Regression Tracker has not been started");
}
Expand Down Expand Up @@ -89,17 +96,24 @@ export class VisualRegressionTracker {
}
}

async track(test: TestRun) {
const result = await this.submitTestResult(test);
async track(test: TestRun): Promise<TestRunResult> {
const testRunResponse = await this.submitTestResult(test);

this.processTestRun(testRunResponse);

return new TestRunResult(testRunResponse, this.config.apiUrl);
}

private processTestRun(testRunResponse: TestRunResponse): void {
let errorMessage: string | undefined;
switch (result.status) {
case TestRunStatus.new: {
errorMessage = `No baseline: ${result.url}`;
switch (testRunResponse.status) {
case TestStatus.new: {
errorMessage = `No baseline: ${testRunResponse.url}`;
break;
}
case TestRunStatus.unresolved: {
errorMessage = `Difference found: ${result.url}`;
case TestStatus.unresolved: {
errorMessage = `Difference found: ${testRunResponse.url}`;
break;
}
}

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@visual-regression-tracker/sdk-js",
"version": "4.2.0",
"version": "4.3.0",
"description": "",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down