Skip to content

Commit

Permalink
test: fix unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
shadowusr committed Nov 7, 2023
1 parent 7701373 commit 057aac0
Show file tree
Hide file tree
Showing 14 changed files with 104 additions and 122 deletions.
2 changes: 1 addition & 1 deletion lib/config/custom-gui-asserts.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {isUndefined, isArray, isEmpty, isFunction, isPlainObject, isString} from 'lodash';
import CustomGuiControlTypes from '../gui/constants/custom-gui-control-types';
import * as CustomGuiControlTypes from '../gui/constants/custom-gui-control-types';

const SUPPORTED_CONTROL_TYPES: string[] = Object.values(CustomGuiControlTypes);

Expand Down
4 changes: 4 additions & 0 deletions lib/gui/constants/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './client-events';
export * from './custom-gui-control-types';
export * from './gui-events';
export * from './server';
14 changes: 7 additions & 7 deletions lib/gui/event-source.js → lib/gui/event-source.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
'use strict';
import {Response} from 'express';
import stringify from 'json-stringify-safe';

const stringify = require('json-stringify-safe');

module.exports = class EventSource {
export class EventSource {
private _connections: Response[];
constructor() {
this._connections = [];
}

addConnection(connection) {
addConnection(connection: Response): void {
this._connections.push(connection);
}

emit(event, data) {
emit(event: string, data?: unknown): void {
this._connections.forEach(function(connection) {
connection.write('event: ' + event + '\n');
connection.write('data: ' + stringify(data) + '\n');
connection.write('\n\n');
});
}
};
}
6 changes: 3 additions & 3 deletions lib/gui/tool-runner/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ const Promise = require('bluebird');
const looksSame = require('looks-same');

const {createTestRunner} = require('./runner');
const subscribeOnToolEvents = require('./report-subscriber');
const GuiReportBuilder = require('../../report-builder/gui');
const EventSource = require('../event-source');
const {subscribeOnToolEvents} = require('./report-subscriber');
const {GuiReportBuilder} = require('../../report-builder/gui');
const {EventSource} = require('../event-source');
const {logger} = require('../../common-utils');
const reporterHelper = require('../../reporter-helpers');
const {UPDATED, SKIPPED, IDLE} = require('../../constants/test-statuses');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,38 @@
'use strict';

const os = require('os');
const PQueue = require('p-queue');
const {ClientEvents} = require('../constants/client-events');
const {getSuitePath} = require('../../plugin-utils');
const {createWorkers} = require('../../workers/create-workers');
const {logError, formatTestResult} = require('../../server-utils');
const {hasDiff} = require('../../common-utils');
const {TestStatus, RUNNING, SUCCESS, SKIPPED} = require('../../constants');

let workers;

module.exports = (hermione, reportBuilder, client, reportPath) => {
import os from 'os';
import PQueue from 'p-queue';
import Hermione from 'hermione';
import {ClientEvents} from '../constants';
import {getSuitePath} from '../../plugin-utils';
import {createWorkers} from '../../workers/create-workers';
import {logError, formatTestResult} from '../../server-utils';
import {hasDiff} from '../../common-utils';
import {TestStatus, RUNNING, SUCCESS, SKIPPED} from '../../constants';
import {GuiReportBuilder} from '../../report-builder/gui';
import {EventSource} from '../event-source';
import {HermioneTestResult} from '../../types';
import {HermioneTestAdapter, ReporterTestResult} from '../../test-adapter';
import {ImageDiffError} from '../../errors';

let workers: ReturnType<typeof createWorkers>;

type CreateWorkersRunner = Parameters<typeof createWorkers>[0];

export const subscribeOnToolEvents = (hermione: Hermione, reportBuilder: GuiReportBuilder, client: EventSource, reportPath: string): void => {
const queue = new PQueue({concurrency: os.cpus().length});
const {imageHandler} = reportBuilder;

function failHandler(testResult, formattedResult) {
const actions = [imageHandler.saveTestImages(formattedResult, workers)];
async function failHandler(formattedResult: ReporterTestResult): Promise<void> {
const actions: Promise<unknown>[] = [imageHandler.saveTestImages(formattedResult, workers)];

if (formattedResult.errorDetails) {
actions.push(formattedResult.saveErrorDetails(reportPath));
actions.push((formattedResult as HermioneTestAdapter).saveErrorDetails(reportPath));
}

return Promise.all(actions);
await Promise.all(actions);
}

hermione.on(hermione.events.RUNNER_START, (runner) => {
workers = createWorkers(runner);
workers = createWorkers(runner as unknown as CreateWorkersRunner);
});

hermione.on(hermione.events.SUITE_BEGIN, (suite) => {
Expand All @@ -41,7 +47,7 @@ module.exports = (hermione, reportBuilder, client, reportPath) => {
});

hermione.on(hermione.events.TEST_BEGIN, (data) => {
const formattedResult = formatTestResult(data, RUNNING, reportBuilder);
const formattedResult = formatTestResult(data as HermioneTestResult, RUNNING, reportBuilder);
formattedResult.attempt = reportBuilder.getCurrAttempt(formattedResult);

reportBuilder.addRunning(formattedResult);
Expand All @@ -65,11 +71,11 @@ module.exports = (hermione, reportBuilder, client, reportPath) => {

hermione.on(hermione.events.RETRY, (testResult) => {
queue.add(async () => {
const status = hasDiff(testResult.assertViewResults) ? TestStatus.FAIL : TestStatus.ERROR;
const status = hasDiff(testResult.assertViewResults as ImageDiffError[]) ? TestStatus.FAIL : TestStatus.ERROR;
const formattedResult = formatTestResult(testResult, status, reportBuilder);
formattedResult.attempt = reportBuilder.getCurrAttempt(formattedResult);

await failHandler(testResult, formattedResult);
await failHandler(formattedResult);
reportBuilder.addRetry(formattedResult);

const testBranch = reportBuilder.getTestBranch(formattedResult.id);
Expand All @@ -79,11 +85,11 @@ module.exports = (hermione, reportBuilder, client, reportPath) => {

hermione.on(hermione.events.TEST_FAIL, (testResult) => {
queue.add(async () => {
const status = hasDiff(testResult.assertViewResults) ? TestStatus.FAIL : TestStatus.ERROR;
const status = hasDiff(testResult.assertViewResults as ImageDiffError[]) ? TestStatus.FAIL : TestStatus.ERROR;
const formattedResult = formatTestResult(testResult, status, reportBuilder);
formattedResult.attempt = reportBuilder.getCurrAttempt(formattedResult);

await failHandler(testResult, formattedResult);
await failHandler(formattedResult);
status === TestStatus.FAIL
? reportBuilder.addFail(formattedResult)
: reportBuilder.addError(formattedResult);
Expand All @@ -95,10 +101,10 @@ module.exports = (hermione, reportBuilder, client, reportPath) => {

hermione.on(hermione.events.TEST_PENDING, async (testResult) => {
queue.add(async () => {
const formattedResult = formatTestResult(testResult, SKIPPED, reportBuilder);
const formattedResult = formatTestResult(testResult as HermioneTestResult, SKIPPED, reportBuilder);
formattedResult.attempt = reportBuilder.getCurrAttempt(formattedResult);

await failHandler(testResult, formattedResult);
await failHandler(formattedResult);
reportBuilder.addSkipped(formattedResult);

const testBranch = reportBuilder.getTestBranch(formattedResult.id);
Expand All @@ -110,7 +116,7 @@ module.exports = (hermione, reportBuilder, client, reportPath) => {
try {
await queue.onIdle();
client.emit(ClientEvents.END);
} catch (err) {
} catch (err: any) {
logError(err);
}
});
Expand Down
2 changes: 1 addition & 1 deletion lib/report-builder/gui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ export class GuiReportBuilder extends StaticReportBuilder {
formattedResult.attempt = formattedResult.attempt - 1;

removedResult = resultId;
} else if (previousImage) {
} else {
updatedImage = this._testsTree.updateImageInfo(imageId, previousImage);
}

Expand Down
5 changes: 3 additions & 2 deletions lib/tests-tree-builder/gui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,13 +184,14 @@ export class GuiTestsTreeBuilder extends BaseTestsTreeBuilder {
this._tree.browsers.allIds.forEach((browserId) => this._reuseBrowser(testsTree, browserId));
}

updateImageInfo(imageId: string, imageInfo: TreeImage): TreeImage {
updateImageInfo(imageId: string, imageInfo?: TreeImage | null): TreeImage {
const currentImage = this._tree.images.byId[imageId];
// TODO: check TreeImage type. Is it correct to let it consist of id and parentId?
const updatedImage: TreeImage = {
...imageInfo,
id: currentImage.id,
parentId: currentImage.parentId
};
} as TreeImage;

this._tree.images.byId[imageId] = updatedImage;

Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,13 @@
"@playwright/test": "^1.37.1",
"@swc/core": "^1.3.64",
"@types/better-sqlite3": "^7.6.4",
"@types/bluebird": "^3.5.3",
"@types/chai": "^4.3.5",
"@types/debug": "^4.1.8",
"@types/enzyme": "^3.10.13",
"@types/express": "4.16",
"@types/fs-extra": "^7.0.0",
"@types/json-stringify-safe": "^5.0.2",
"@types/lodash": "^4.14.195",
"@types/nested-error-stacks": "^2.1.0",
"@types/opener": "^1.4.0",
Expand Down
43 changes: 10 additions & 33 deletions test/unit/lib/gui/tool-runner/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,23 @@ const path = require('path');
const fs = require('fs-extra');
const _ = require('lodash');
const proxyquire = require('proxyquire');
const GuiReportBuilder = require('lib/report-builder/gui');
const {GuiReportBuilder} = require('lib/report-builder/gui');
const {LOCAL_DATABASE_NAME} = require('lib/constants/database');
const {logger} = require('lib/common-utils');
const Runner = require('lib/gui/tool-runner/runner');
const {stubTool, stubConfig, mkImagesInfo, mkState, mkSuite} = require('test/unit/utils');

describe('lib/gui/tool-runner/index', () => {
const sandbox = sinon.createSandbox();
let reportBuilder;
let ToolGuiReporter;
let reportSubscriber;
let subscribeOnToolEvents;
let hermione;
let getTestsTreeFromDatabase;
let looksSame;
let removeReferenceImage;
let revertReferenceImage;
let toolRunnerUtils;
let createTestRunner;

const mkTestCollection_ = (testsTree = {}) => {
return {
Expand Down Expand Up @@ -67,6 +67,8 @@ describe('lib/gui/tool-runner/index', () => {
beforeEach(() => {
hermione = stubTool();

createTestRunner = sinon.stub();

toolRunnerUtils = {
findTestResult: sandbox.stub(),
formatId: sandbox.stub().returns('some-id')
Expand All @@ -75,7 +77,7 @@ describe('lib/gui/tool-runner/index', () => {
reportBuilder = sinon.createStubInstance(GuiReportBuilder);
reportBuilder.getUpdatedAttempt.returns(0);

reportSubscriber = sandbox.stub().named('reportSubscriber').resolves();
subscribeOnToolEvents = sandbox.stub().named('reportSubscriber').resolves();
looksSame = sandbox.stub().named('looksSame').resolves({equal: true});
removeReferenceImage = sandbox.stub().resolves();
revertReferenceImage = sandbox.stub().resolves();
Expand All @@ -87,7 +89,8 @@ describe('lib/gui/tool-runner/index', () => {

ToolGuiReporter = proxyquire(`lib/gui/tool-runner`, {
'looks-same': looksSame,
'./report-subscriber': reportSubscriber,
'./runner': {createTestRunner},
'./report-subscriber': {subscribeOnToolEvents},
'./utils': toolRunnerUtils,
'../../db-utils/server': {getTestsTreeFromDatabase},
'../../reporter-helpers': {
Expand Down Expand Up @@ -206,7 +209,7 @@ describe('lib/gui/tool-runner/index', () => {
const gui = initGuiReporter(hermione, {paths: ['foo']});

return gui.initialize()
.then(() => assert.callOrder(reportSubscriber, hermione.readTests));
.then(() => assert.callOrder(subscribeOnToolEvents, hermione.readTests));
});

it('should initialize report builder after read tests for the correct order of events', async () => {
Expand Down Expand Up @@ -303,32 +306,6 @@ describe('lib/gui/tool-runner/index', () => {
});
});
});

it('should pass "origAttempt" to the ReportBuilder.addUpdate method to be able to calculate status properly', async () => {
const tests = [{
id: 'some-id',
fullTitle: () => 'some-title',
browserId: 'yabro',
attempt: 10,
suite: {path: ['suite1']},
state: {},
metaInfo: {},
imagesInfo: []
}];

const getScreenshotPath = sandbox.stub().returns('/ref/path1');
const config = stubConfig({
browsers: {yabro: {getScreenshotPath}}
});

const hermione = mkHermione_(config, {'some-title.yabro': tests[0]});
const gui = initGuiReporter(hermione);
await gui.initialize();

await gui.updateReferenceImage(tests);

assert.calledOnceWith(reportBuilder.addUpdated, sinon.match({origAttempt: 10}));
});
});

describe('undoAcceptImages', () => {
Expand Down Expand Up @@ -502,7 +479,7 @@ describe('lib/gui/tool-runner/index', () => {
beforeEach(() => {
runner = {run: sandbox.stub().resolves()};
collection = mkTestCollection_();
sandbox.stub(Runner, 'create').withArgs(collection).returns(runner);
createTestRunner.withArgs(collection).returns(runner);
hermione.readTests.resolves(collection);
});

Expand Down
Loading

0 comments on commit 057aac0

Please sign in to comment.