60 lines
2.3 KiB
JavaScript
60 lines
2.3 KiB
JavaScript
|
/**
|
||
|
* @module
|
||
|
*
|
||
|
* This module implements auto-injected manual mocks that are cleaner than Jest's approach.
|
||
|
*
|
||
|
* See https://docs.gitlab.com/ee/development/testing_guide/frontend_testing.html
|
||
|
*/
|
||
|
|
||
|
import fs from 'fs';
|
||
|
import path from 'path';
|
||
|
|
||
|
import readdir from 'readdir-enhanced';
|
||
|
|
||
|
const MAX_DEPTH = 20;
|
||
|
const prefixMap = [
|
||
|
// E.g. the mock ce/foo/bar maps to require path ~/foo/bar
|
||
|
{ mocksRoot: 'ce', requirePrefix: '~' },
|
||
|
// { mocksRoot: 'ee', requirePrefix: 'ee' }, // We'll deal with EE-specific mocks later
|
||
|
// { mocksRoot: 'virtual', requirePrefix: '' }, // We'll deal with virtual mocks later
|
||
|
];
|
||
|
|
||
|
const mockFileFilter = stats => stats.isFile() && stats.path.endsWith('.js');
|
||
|
|
||
|
const getMockFiles = root => readdir.sync(root, { deep: MAX_DEPTH, filter: mockFileFilter });
|
||
|
|
||
|
// Function that performs setting a mock. This has to be overridden by the unit test, because
|
||
|
// jest.setMock can't be overwritten across files.
|
||
|
// Use require() because jest.setMock expects the CommonJS exports object
|
||
|
const defaultSetMock = (srcPath, mockPath) =>
|
||
|
jest.mock(srcPath, () => jest.requireActual(mockPath));
|
||
|
|
||
|
// eslint-disable-next-line import/prefer-default-export
|
||
|
export const setupManualMocks = function setupManualMocks(setMock = defaultSetMock) {
|
||
|
prefixMap.forEach(({ mocksRoot, requirePrefix }) => {
|
||
|
const mocksRootAbsolute = path.join(__dirname, mocksRoot);
|
||
|
if (!fs.existsSync(mocksRootAbsolute)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
getMockFiles(path.join(__dirname, mocksRoot)).forEach(mockPath => {
|
||
|
const mockPathNoExt = mockPath.substring(0, mockPath.length - path.extname(mockPath).length);
|
||
|
const sourcePath = path.join(requirePrefix, mockPathNoExt);
|
||
|
const mockPathRelative = `./${path.join(mocksRoot, mockPathNoExt)}`;
|
||
|
|
||
|
try {
|
||
|
setMock(sourcePath, mockPathRelative);
|
||
|
} catch (e) {
|
||
|
if (e.message.includes('Could not locate module')) {
|
||
|
// The corresponding mocked module doesn't exist. Raise a better error.
|
||
|
// Eventualy, we may support virtual mocks (mocks whose path doesn't directly correspond
|
||
|
// to a module, like with the `ee_else_ce` prefix).
|
||
|
throw new Error(
|
||
|
`A manual mock was defined for module ${sourcePath}, but the module doesn't exist!`,
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
};
|