Skip to content

chore: improve test runtime by replacing ts-jest with swc #4336

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 19 commits into from
Jun 4, 2021
Merged
Show file tree
Hide file tree
Changes from 17 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 .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
.dependabot/
.github/
.prettierignore
.swcrc
.yarnrc
.vs/
AppXManifest.xml
Expand Down
13 changes: 13 additions & 0 deletions .swcrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"jsc": {
"parser": {
"syntax": "typescript",
"tsx": true
}
},
"module": {
"type": "commonjs",
"noInterop": true
},
"env": {}
}
1 change: 1 addition & 0 deletions copyright-header.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"./.dependabot",
"./.git",
"./.github",
"./.swcrc",
"./.vs",
"./.vscode",
"./dist",
Expand Down
7 changes: 1 addition & 6 deletions jest.config.base.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,6 @@ module.exports = {
coverageDirectory: '<rootDir>/test-results/unit/coverage',
coverageReporters: ['text', 'lcov', 'cobertura'],
displayName: '<should be overriden by individual jest.configs>',
globals: {
'ts-jest': {
tsconfig: '<rootDir>/tsconfig.json',
},
},
moduleDirectories: ['node_modules'],
moduleFileExtensions: ['ts', 'js', 'json'],
moduleNameMapper: {
Expand All @@ -49,6 +44,6 @@ module.exports = {
testMatch: ['**/*.spec.[tj]s', '**/*.test.[tj]s'],
testPathIgnorePatterns: ['/dist/', '/out/'],
transform: {
'^.+\\.(ts|tsx)$': 'ts-jest',
'^.+\\.(ts|tsx|js|jsx)$': [`${__dirname}/src/tests/common/swc-transformer`],
},
};
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
"workspaces": [
"packages/*"
],
"browserslist": [
"chrome 88",
"edge 88",
"firefox 87"
],
"scripts": {
"ada-cat": "grunt ada-cat",
"assessment": "npm-run-all --serial scss:clean fastpass build:all test test:e2e test:unified",
Expand Down Expand Up @@ -83,6 +88,7 @@
"devDependencies": {
"7zip-bin": "^5.1.1",
"@electron/get": "^1.12.4",
"@swc/core": "^1.2.59",
"@types/applicationinsights-js": "^1.0.7",
"@types/chrome": "0.0.144",
"@types/enzyme": "^3.10.8",
Expand Down Expand Up @@ -155,7 +161,6 @@
"source-map-loader": "^3.0.0",
"spectron": "^13.0.0",
"terser-webpack-plugin": "^5.1.3",
"ts-jest": "^27.0.2",
"ts-loader": "^9.2.2",
"typed-scss-modules": "^4.1.1",
"typemoq": "^2.1.0",
Expand Down
1 change: 0 additions & 1 deletion packages/report-e2e-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
"jest-file-snapshot": "^0.5.0",
"jest-junit": "^12.1.0",
"prettier": "^2.3.0",
"ts-jest": "^27.0.2",
"typescript": "^4.3.2"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
//
// The use of function() {} syntax over arrow functions is important for IE compat (see #1875).
//
// The "istanbul ignore next" excludes the function from code coverage to prevent code cov from
// injecting functions that interfere with eval in the unit tests.
// The "istanbul ignore file" excludes this file from code coverage, which would otherwise cause
// unit testing with --coverage=true to inject code coverage marker functions that would prevent
// tests from being able to eval() the generated code.
//
/* istanbul ignore next */
// @ts-expect-error unused const is a workaround for https://github.com/swc-project/swc/issues/1165
/* istanbul ignore file */ const swcIssue1165Workaround = true;

export const addEventListenerForCollapsibleSection = function (doc: Document): void {
const collapsibles = doc.getElementsByClassName('collapsible-container');

Expand Down
40 changes: 0 additions & 40 deletions src/scanner/processor.ts

This file was deleted.

6 changes: 2 additions & 4 deletions src/scanner/result-decorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { HyperlinkDefinition } from 'common/types/hyperlink-definition';
import { DocumentUtils } from './document-utils';
import { AxeRule, RuleResult, ScanResults } from './iruleresults';
import { MessageDecorator } from './message-decorator';
import { Processor } from './processor';

export class ResultDecorator {
constructor(
Expand Down Expand Up @@ -36,11 +35,10 @@ export class ResultDecorator {
): RuleResult[] {
return ruleResults.reduce((filteredArray: RuleResult[], result: AxeRule) => {
this.messageDecorator.decorateResultWithMessages(result);
const processedResult = Processor.suppressChecksByMessages(result, !isInapplicable);

if (processedResult != null) {
if (result != null) {
filteredArray.push({
...processedResult,
...result,
guidanceLinks: this.mapAxeTagsToGuidanceLinks(result.tags),
helpUrl: this.getHelpUrl(result.id, result.helpUrl),
});
Expand Down
38 changes: 38 additions & 0 deletions src/tests/common/swc-transformer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
const { readFileSync } = require('fs');
const { join } = require('path');
const { transformSync } = require('@swc/core');
const { merge } = require('lodash');

// This file can be replaced by @swc/jest once https://github.com/swc-project/jest/issues/8 resolves

const swcrcPath = join(__dirname, '..', '..', '..', '.swcrc');
const swcrc = JSON.parse(readFileSync(swcrcPath));

const jestTransformOverrides = {
jsc: {
transform: {
hidden: {
jest: true,
},
},
},
module: {
type: 'commonjs',
},
};

const baseTransformOptions = merge({}, swcrc, jestTransformOverrides);

module.exports = {
process: (src, path) => {
Copy link
Contributor

@karanbirsingh karanbirsingh Jun 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like Jest docs recommend implementing getCacheKey as well, although swc-jest transformer also doesn't seem to have it. Do you know if this would provide us any benefits?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent question; I didn't look at the jest transformer docs at all to be honest, I was mostly adapting from swc-jest's transformer (it would be better to contribute .swcrc support back to them, but I'm blocked on legal approval to sign their CLA before I can do that). I'll investigate this after standup!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed offline; will investigate improvements to the transformer in a separate PR (ideally against the swc-project/jest repo directly)

if (/\.(t|j)sx?$/.test(path)) {
const transformOptions = merge({}, baseTransformOptions, {
filename: path,
});
return transformSync(src, transformOptions);
}
return src;
},
};
17 changes: 17 additions & 0 deletions src/tests/unit/common/webextension-polyfill-ts-setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

// webextension-polyfill errors on import if a global "chrome" variable is not defined
const mockChromeGlobalRequired = (window as any).chrome == null;
if (mockChromeGlobalRequired) {
(window as any).chrome = { runtime: { id: 'mocked' } };
}

// This must be "require" and not "import" to avoid swc hoisting the statement above the window
// setup. See https://github.com/swc-project/swc/issues/1686 and
// https://github.com/microsoft/TypeScript/pull/39764
require('webextension-polyfill-ts');

if (mockChromeGlobalRequired) {
delete (window as any).chrome;
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

// webextension-polyfill errors on import if a global "chrome" variable is not defined
expect((window as any).chrome).toBeUndefined();
(window as any).chrome = { runtime: { id: 'mocked' } };
import 'webextension-polyfill-ts';
delete (window as any).chrome;
// This must be the first import, otherwise importing webextension-polyfill-ts from within
// adapter implementations will fail
import 'tests/unit/common/webextension-polyfill-ts-setup';

import { BrowserAdapterFactory } from 'common/browser-adapters/browser-adapter-factory';
import { ChromiumAdapter } from 'common/browser-adapters/chromium-adapter';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,37 @@

exports[`CollapsibleScriptProvider produces script source that matches snapshot 1`] = `
"(function (doc) {
const collapsibles = doc.getElementsByClassName('collapsible-container');

const collapsibles = doc.getElementsByClassName(\\"collapsible-container\\");
for (let index = 0; index < collapsibles.length; index++) {
const container = collapsibles.item(index);
const button = container === null || container === void 0 ? void 0 : container.querySelector('.collapsible-control');

const button =
container === null || container === void 0
? void 0
: container.querySelector(\\".collapsible-control\\");
if (button == null) {
continue;
}

button.addEventListener('click', function () {
var _a;

const content = (_a = button.parentElement) === null || _a === void 0 ? void 0 : _a.nextElementSibling;

button.addEventListener(\\"click\\", function () {
var ref;
const content =
(ref = button.parentElement) === null || ref === void 0
? void 0
: ref.nextElementSibling;
if (content == null) {
throw Error(\`Expected button element's parent to have a next sibling\`);
}

const wasExpandedBefore = button.getAttribute('aria-expanded') === 'false' ? false : true;
const wasExpandedBefore =
button.getAttribute(\\"aria-expanded\\") === \\"false\\" ? false : true;
const isExpandedAfter = !wasExpandedBefore;
button.setAttribute('aria-expanded', isExpandedAfter + '');
content.setAttribute('aria-hidden', !isExpandedAfter + '');

button.setAttribute(\\"aria-expanded\\", isExpandedAfter + \\"\\");
content.setAttribute(\\"aria-hidden\\", !isExpandedAfter + \\"\\");
if (isExpandedAfter) {
container.classList.remove('collapsed');
container.classList.remove(\\"collapsed\\");
} else {
container.classList.add('collapsed');
container.classList.add(\\"collapsed\\");
}
});
}
})(document)"
})(document);
"
`;
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
import { isFunction } from 'lodash';
import { format } from 'prettier';
import {
addEventListenerForCollapsibleSection,
getDefaultAddListenerForCollapsibleSection,
Expand All @@ -9,7 +10,10 @@ import { It, Mock, MockBehavior, Times } from 'typemoq';

describe('CollapsibleScriptProvider', () => {
it('produces script source that matches snapshot', () => {
expect(getDefaultAddListenerForCollapsibleSection()).toMatchSnapshot();
const source = getDefaultAddListenerForCollapsibleSection();
// Required to get a consistent snapshot with --coverage=false vs --coverage=true
const formattedSource = format(source, { parser: 'babel' }).replace(/\n\n/g, '\n');
expect(formattedSource).toMatchSnapshot();
});

it('produces script source that does not use IE-incompatible arrow functions', () => {
Expand Down
Loading