Skip to content

Commit

Permalink
chore: re-write main parts of GUI mode to typescript (#518)
Browse files Browse the repository at this point in the history
* chore: rename test-tree-builder/gui to typescript

* chore: re-write tests-tree-builder/gui to typescript

* chore: rename report-builder/gui to typescript

* chore: re-write report-buidler/gui to typescript

* chore: rename tool-runner to typescript

* chore: re-write tool-runner/runner to typescript

* chore: re-write gui/constants to typescript

* test: fix unit tests

* fix: minor bug fixes

* chore: update package-lock

* fix: minor bug fixes and review fixes

* fix: get rid of any in report-subscriber and get rid of async in report-builder
  • Loading branch information
shadowusr authored Nov 7, 2023
1 parent 5fd52d4 commit 637b71b
Show file tree
Hide file tree
Showing 51 changed files with 825 additions and 537 deletions.
1 change: 0 additions & 1 deletion .babelignore

This file was deleted.

File renamed without changes.
8 changes: 4 additions & 4 deletions lib/common-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import axios, {AxiosRequestConfig} from 'axios';
import {SUCCESS, FAIL, ERROR, SKIPPED, UPDATED, IDLE, RUNNING, QUEUED, TestStatus} from './constants';

import {UNCHECKED, INDETERMINATE, CHECKED} from './constants/checked-statuses';
import {AssertViewResult, ImageData, ImageBase64, ImageInfoFull, TestError, ImageInfoError} from './types';
import {ImageData, ImageBase64, ImageInfoFull, TestError, ImageInfoError} from './types';
import {ErrorName, ImageDiffError, NoRefImageError} from './errors';
export const getShortMD5 = (str: string): string => {
return crypto.createHash('md5').update(str, 'ascii').digest('hex').substr(0, 7);
Expand Down Expand Up @@ -99,8 +99,8 @@ export const isNoRefImageError = (error?: unknown): error is NoRefImageError =>
return (error as {name?: string})?.name === ErrorName.NO_REF_IMAGE;
};

export const hasNoRefImageErrors = ({assertViewResults = []}: {assertViewResults?: AssertViewResult[]}): boolean => {
return assertViewResults.some((assertViewResult: AssertViewResult) => isNoRefImageError(assertViewResult));
export const hasNoRefImageErrors = ({assertViewResults = []}: {assertViewResults?: {name?: string}[]}): boolean => {
return assertViewResults.some((assertViewResult) => isNoRefImageError(assertViewResult));
};

const hasFailedImages = (result: {imagesInfo?: ImageInfoFull[]}): boolean => {
Expand All @@ -124,7 +124,7 @@ export const getError = (error?: TestError): undefined | Pick<TestError, 'name'
return pick(error, ['name', 'message', 'stack', 'stateName']);
};

export const hasDiff = (assertViewResults: AssertViewResult[]): boolean => {
export const hasDiff = (assertViewResults: {name?: string}[]): boolean => {
return assertViewResults.some((result) => isImageDiffError(result as {name?: string}));
};

Expand Down
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
13 changes: 4 additions & 9 deletions lib/constants/database.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type {ValueOf} from 'type-fest';
import {ValueOf} from 'type-fest';

// TODO: change to enums
export const DB_TYPES = {int: 'INT', text: 'TEXT'} as const;
Expand All @@ -19,12 +19,7 @@ export const DB_COLUMNS = {
TIMESTAMP: 'timestamp'
} as const;

type DbColumn = {
name: ValueOf<typeof DB_COLUMNS>;
type: ValueOf<typeof DB_TYPES>;
}

export const SUITES_TABLE_COLUMNS: DbColumn[] = [
export const SUITES_TABLE_COLUMNS = [
{name: DB_COLUMNS.SUITE_PATH, type: DB_TYPES.text},
{name: DB_COLUMNS.SUITE_NAME, type: DB_TYPES.text},
{name: DB_COLUMNS.NAME, type: DB_TYPES.text},
Expand All @@ -39,7 +34,7 @@ export const SUITES_TABLE_COLUMNS: DbColumn[] = [
{name: DB_COLUMNS.MULTIPLE_TABS, type: DB_TYPES.int}, //boolean - 0 or 1
{name: DB_COLUMNS.STATUS, type: DB_TYPES.text},
{name: DB_COLUMNS.TIMESTAMP, type: DB_TYPES.int}
];
] as const;

export const DB_MAX_AVAILABLE_PAGE_SIZE = 65536; // helps to speed up queries
export const DB_SUITES_TABLE_NAME = 'suites';
Expand All @@ -48,4 +43,4 @@ export const DATABASE_URLS_JSON_NAME = 'databaseUrls.json';
export const DB_COLUMN_INDEXES = SUITES_TABLE_COLUMNS.reduce((acc: Record<string, number>, {name}, index) => {
acc[name] = index;
return acc;
}, {});
}, {}) as { [K in ValueOf<typeof DB_COLUMNS>]: number };
3 changes: 2 additions & 1 deletion lib/db-utils/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {logger} from '../common-utils';
import {DB_MAX_AVAILABLE_PAGE_SIZE, DB_SUITES_TABLE_NAME, SUITES_TABLE_COLUMNS, DB_COLUMN_INDEXES} from '../constants';
import {DbUrlsJsonData, RawSuitesRow, ReporterConfig} from '../types';
import type {Database, Statement} from 'better-sqlite3';
import {ReadonlyDeep} from 'type-fest';

export const selectAllQuery = (tableName: string): string => `SELECT * FROM ${tableName}`;
export const selectAllSuitesQuery = (): string => selectAllQuery(DB_SUITES_TABLE_NAME);
Expand Down Expand Up @@ -76,7 +77,7 @@ export const mergeTables = ({db, dbPaths, getExistingTables = (): string[] => []
}
};

function createTableQuery(tableName: string, columns: { name: string, type: string }[]): string {
function createTableQuery(tableName: string, columns: ReadonlyDeep<{name: string, type: string }[]>): string {
const formattedColumns = columns
.map(({name, type}) => `${name} ${type}`)
.join(', ');
Expand Down
4 changes: 2 additions & 2 deletions lib/gui/api/facade.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict';

const EventEmitter2 = require('eventemitter2');
const guiEvents = require('../constants/gui-events');
const {GuiEvents} = require('../constants/gui-events');

module.exports = class ApiFacade extends EventEmitter2 {
static create() {
Expand All @@ -11,6 +11,6 @@ module.exports = class ApiFacade extends EventEmitter2 {
constructor() {
super();

this.events = guiEvents;
this.events = GuiEvents;
}
};
13 changes: 0 additions & 13 deletions lib/gui/constants/client-events.js

This file was deleted.

17 changes: 17 additions & 0 deletions lib/gui/constants/client-events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {ValueOf} from 'type-fest';

export const ClientEvents = {
BEGIN_SUITE: 'beginSuite',
BEGIN_STATE: 'beginState',

TEST_RESULT: 'testResult',

RETRY: 'retry',
ERROR: 'err',

END: 'end'
} as const;

export type ClientEvents = typeof ClientEvents;

export type ClientEvent = ValueOf<ClientEvents>;
6 changes: 0 additions & 6 deletions lib/gui/constants/custom-gui-control-types.js

This file was deleted.

3 changes: 3 additions & 0 deletions lib/gui/constants/custom-gui-control-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const CONTROL_TYPE_BUTTON = 'button';

export const CONTROL_TYPE_RADIOBUTTON = 'radiobutton';
6 changes: 0 additions & 6 deletions lib/gui/constants/gui-events.js

This file was deleted.

10 changes: 10 additions & 0 deletions lib/gui/constants/gui-events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {ValueOf} from 'type-fest';

export const GuiEvents = {
SERVER_INIT: 'serverInit',
SERVER_READY: 'serverReady'
} as const;

export type GuiEvents = typeof GuiEvents;

export type GuiEvent = ValueOf<GuiEvents>;
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';
7 changes: 0 additions & 7 deletions lib/gui/constants/server.js

This file was deleted.

5 changes: 5 additions & 0 deletions lib/gui/constants/server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const MAX_REQUEST_SIZE = '100mb';

export const KEEP_ALIVE_TIMEOUT = 120 * 1000;

export const HEADERS_TIMEOUT = 125 * 1000;
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');
});
}
};
}
2 changes: 1 addition & 1 deletion lib/gui/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const bodyParser = require('body-parser');
const {INTERNAL_SERVER_ERROR, OK} = require('http-codes');

const App = require('./app');
const {MAX_REQUEST_SIZE, KEEP_ALIVE_TIMEOUT, HEADERS_TIMEOUT} = require('./constants/server');
const {MAX_REQUEST_SIZE, KEEP_ALIVE_TIMEOUT, HEADERS_TIMEOUT} = require('./constants');
const {initializeCustomGui, runCustomGuiAction} = require('../server-utils');
const {logger} = require('../common-utils');
const initPluginsRoutes = require('./routes/plugins');
Expand Down
14 changes: 7 additions & 7 deletions lib/gui/tool-runner/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ const chalk = require('chalk');
const Promise = require('bluebird');
const looksSame = require('looks-same');

const Runner = require('./runner');
const subscribeOnToolEvents = require('./report-subscriber');
const GuiReportBuilder = require('../../report-builder/gui');
const EventSource = require('../event-source');
const {createTestRunner} = require('./runner');
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 Expand Up @@ -150,7 +150,7 @@ module.exports = class ToolRunner {
}

if (shouldRevertReference) {
await reporterHelper.revertReferenceImage(formattedResult, stateName);
await reporterHelper.revertReferenceImage(removedResult, formattedResult, stateName);
}

if (previousExpectedPath) {
Expand Down Expand Up @@ -202,7 +202,7 @@ module.exports = class ToolRunner {
run(tests = []) {
const {grep, set: sets, browser: browsers} = this._globalOpts;

return Runner.create(this._collection, tests)
return createTestRunner(this._collection, tests)
.run((collection) => this._hermione.run(collection, {grep, sets, browsers}));
}

Expand Down Expand Up @@ -250,7 +250,7 @@ module.exports = class ToolRunner {
return _.extend(imageInfo, {expectedImg: refImg});
});

const res = _.merge({}, rawTest, {assertViewResults, imagesInfo, sessionId, attempt, origAttempt: attempt, meta: {url}, updated: true});
const res = _.merge({}, rawTest, {assertViewResults, imagesInfo, sessionId, attempt, meta: {url}, updated: true});

// _.merge can't fully clone test object since hermione@7+
// TODO: use separate object to represent test results. Do not extend test object with test results
Expand Down
Loading

0 comments on commit 637b71b

Please sign in to comment.