Commit 3bc2ad90 authored by Phil Hughes's avatar Phil Hughes

Merge branch 'ps-fake-web-worker-jest' into 'master'

Setup fake web worker for jest

See merge request gitlab-org/gitlab!58805
parents 55456542 b2356dca
......@@ -86,6 +86,8 @@ module.exports = (path, options = {}) => {
collectCoverageFrom,
coverageDirectory: coverageDirectory(),
coverageReporters: ['json', 'lcov', 'text-summary', 'clover'],
// We need ignore _worker code coverage since we are manually transforming it
coveragePathIgnorePatterns: ['<rootDir>/node_modules/', '_worker\\.js$'],
cacheDirectory: '<rootDir>/tmp/cache/jest',
modulePathIgnorePatterns: ['<rootDir>/.yarn-cache/'],
reporters,
......@@ -93,6 +95,7 @@ module.exports = (path, options = {}) => {
restoreMocks: true,
transform: {
'^.+\\.(gql|graphql)$': 'jest-transform-graphql',
'^.+_worker\\.js$': './spec/frontend/__helpers__/web_worker_transformer.js',
'^.+\\.js$': 'babel-jest',
'^.+\\.vue$': 'vue-jest',
'^.+\\.(md|zip|png)$': 'jest-raw-loader',
......
import path from 'path';
const isRelative = (pathArg) => pathArg.startsWith('.');
const transformRequirePath = (base, pathArg) => {
if (!isRelative(pathArg)) {
return pathArg;
}
return path.resolve(base, pathArg);
};
const createRelativeRequire = (filename) => {
const rel = path.relative(__dirname, path.dirname(filename));
const base = path.resolve(__dirname, rel);
// reason: Dynamic require should be fine here since the code is dynamically evaluated anyways.
// eslint-disable-next-line import/no-dynamic-require, global-require
return (pathArg) => require(transformRequirePath(base, pathArg));
};
/**
* Simulates a WebWorker module similar to the kind created by Webpack's [`worker-loader`][1]
*
* [1]: https://webpack.js.org/loaders/worker-loader/
*/
export class FakeWebWorker {
/**
* Constructs a new FakeWebWorker instance
*
* @param {String} filename is the full path of the code, which is used to resolve relative imports.
* @param {String} code is the raw code of the web worker, which is dynamically evaluated on construction.
*/
constructor(filename, code) {
let isAlive = true;
const clientTarget = new EventTarget();
const workerTarget = new EventTarget();
this.addEventListener = (...args) => clientTarget.addEventListener(...args);
this.removeEventListener = (...args) => clientTarget.removeEventListener(...args);
this.postMessage = (message) => {
if (!isAlive) {
return;
}
workerTarget.dispatchEvent(new MessageEvent('message', { data: message }));
};
this.terminate = () => {
isAlive = false;
};
const workerScope = {
addEventListener: (...args) => workerTarget.addEventListener(...args),
removeEventListener: (...args) => workerTarget.removeEventListener(...args),
postMessage: (message) => {
if (!isAlive) {
return;
}
clientTarget.dispatchEvent(new MessageEvent('message', { data: message }));
},
};
// reason: `no-new-func` is like `eval` except it only executed on global scope and it's easy
// to pass in local references. `eval` is very unsafe in production, but in our test environment
// we shold be fine.
// eslint-disable-next-line no-new-func
Function('self', 'require', code)(workerScope, createRelativeRequire(filename));
}
}
/* eslint-disable class-methods-use-this */
export default class WebWorkerMock {
addEventListener() {}
removeEventListener() {}
terminate() {}
postMessage() {}
}
/* eslint-disable import/no-commonjs */
const babelJestTransformer = require('babel-jest');
// This Jest will transform the code of a WebWorker module into a FakeWebWorker subclass.
// This is meant to mirror Webpack's [`worker-loader`][1].
// [1]: https://webpack.js.org/loaders/worker-loader/
module.exports = {
process: (contentArg, filename, ...args) => {
const { code: content } = babelJestTransformer.process(contentArg, filename, ...args);
return `const { FakeWebWorker } = require("helpers/web_worker_fake");
module.exports = class JestTransformedWorker extends FakeWebWorker {
constructor() {
super(${JSON.stringify(filename)}, ${JSON.stringify(content)});
}
};`;
},
};
......@@ -258,6 +258,8 @@ describe('DiffsStoreActions', () => {
{ type: types.SET_LOADING, payload: false },
{ type: types.SET_MERGE_REQUEST_DIFFS, payload: diffMetadata.merge_request_diffs },
{ type: types.SET_DIFF_METADATA, payload: noFilesData },
// Workers are synchronous in Jest environment (see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58805)
{ type: types.SET_TREE_DATA, payload: utils.generateTreeList(diffMetadata.diff_files) },
],
[],
() => {
......
export { default } from 'helpers/web_worker_mock';
export { default } from 'helpers/web_worker_mock';
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment