diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-12-20 13:37:47 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-12-20 13:37:47 +0000 |
commit | aee0a117a889461ce8ced6fcf73207fe017f1d99 (patch) | |
tree | 891d9ef189227a8445d83f35c1b0fc99573f4380 /spec/frontend/mocks | |
parent | 8d46af3258650d305f53b819eabf7ab18d22f59e (diff) | |
download | gitlab-ce-aee0a117a889461ce8ced6fcf73207fe017f1d99.tar.gz |
Add latest changes from gitlab-org/gitlab@14-6-stable-eev14.6.0-rc42
Diffstat (limited to 'spec/frontend/mocks')
-rw-r--r-- | spec/frontend/mocks/ce/lib/utils/axios_utils.js | 78 | ||||
-rw-r--r-- | spec/frontend/mocks/mocks_helper.js | 58 | ||||
-rw-r--r-- | spec/frontend/mocks/mocks_helper_spec.js | 131 |
3 files changed, 0 insertions, 267 deletions
diff --git a/spec/frontend/mocks/ce/lib/utils/axios_utils.js b/spec/frontend/mocks/ce/lib/utils/axios_utils.js deleted file mode 100644 index 674563b9f28..00000000000 --- a/spec/frontend/mocks/ce/lib/utils/axios_utils.js +++ /dev/null @@ -1,78 +0,0 @@ -import EventEmitter from 'events'; - -const axios = jest.requireActual('~/lib/utils/axios_utils').default; - -axios.isMock = true; - -// Fail tests for unmocked requests -axios.defaults.adapter = (config) => { - const message = - `Unexpected unmocked request: ${JSON.stringify(config, null, 2)}\n` + - 'Consider using the `axios-mock-adapter` module in tests.'; - const error = new Error(message); - error.config = config; - global.fail(error); - throw error; -}; - -// Count active requests and provide a way to wait for them -let activeRequests = 0; -const events = new EventEmitter(); -const onRequest = () => { - activeRequests += 1; -}; - -// Use setImmediate to alloow the response interceptor to finish -const onResponse = (config) => { - activeRequests -= 1; - setImmediate(() => { - events.emit('response', config); - }); -}; - -const subscribeToResponse = (predicate = () => true) => - new Promise((resolve) => { - const listener = (config = {}) => { - if (predicate(config)) { - events.off('response', listener); - resolve(config); - } - }; - - events.on('response', listener); - - // If a request has been made synchronously, setImmediate waits for it to be - // processed and the counter incremented. - setImmediate(listener); - }); - -/** - * Registers a callback function to be run after a request to the given URL finishes. - */ -axios.waitFor = (url) => subscribeToResponse(({ url: configUrl }) => configUrl === url); - -/** - * Registers a callback function to be run after all requests have finished. If there are no requests waiting, the callback is executed immediately. - */ -axios.waitForAll = () => subscribeToResponse(() => activeRequests === 0); - -axios.countActiveRequests = () => activeRequests; - -axios.interceptors.request.use((config) => { - onRequest(); - return config; -}); - -// Remove the global counter -axios.interceptors.response.use( - (response) => { - onResponse(response.config); - return response; - }, - (err) => { - onResponse(err.config); - return Promise.reject(err); - }, -); - -export default axios; diff --git a/spec/frontend/mocks/mocks_helper.js b/spec/frontend/mocks/mocks_helper.js deleted file mode 100644 index 295483cd64c..00000000000 --- a/spec/frontend/mocks/mocks_helper.js +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @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)); - -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!`, - ); - } - } - }); - }); -}; diff --git a/spec/frontend/mocks/mocks_helper_spec.js b/spec/frontend/mocks/mocks_helper_spec.js deleted file mode 100644 index 0abe5c6b949..00000000000 --- a/spec/frontend/mocks/mocks_helper_spec.js +++ /dev/null @@ -1,131 +0,0 @@ -/* eslint-disable global-require */ - -import path from 'path'; - -import axios from '~/lib/utils/axios_utils'; - -const absPath = path.join.bind(null, __dirname); - -jest.mock('fs'); -jest.mock('readdir-enhanced'); - -describe('mocks_helper.js', () => { - let setupManualMocks; - const setMock = jest.fn().mockName('setMock'); - let fs; - let readdir; - - beforeAll(() => { - jest.resetModules(); - jest.setMock = jest.fn().mockName('jest.setMock'); - fs = require('fs'); - readdir = require('readdir-enhanced'); - - // We need to provide setupManualMocks with a mock function that pretends to do the setup of - // the mock. This is because we can't mock jest.setMock across files. - setupManualMocks = () => require('./mocks_helper').setupManualMocks(setMock); - }); - - afterEach(() => { - fs.existsSync.mockReset(); - readdir.sync.mockReset(); - setMock.mockReset(); - }); - - it('enumerates through mock file roots', () => { - setupManualMocks(); - expect(fs.existsSync).toHaveBeenCalledTimes(1); - expect(fs.existsSync).toHaveBeenNthCalledWith(1, absPath('ce')); - - expect(readdir.sync).toHaveBeenCalledTimes(0); - }); - - it("doesn't traverse the directory tree infinitely", () => { - fs.existsSync.mockReturnValue(true); - readdir.sync.mockReturnValue([]); - setupManualMocks(); - - const readdirSpy = readdir.sync; - expect(readdirSpy).toHaveBeenCalled(); - readdirSpy.mock.calls.forEach((call) => { - expect(call[1].deep).toBeLessThan(100); - }); - }); - - it('sets up mocks for CE (the ~/ prefix)', () => { - fs.existsSync.mockImplementation((root) => root.endsWith('ce')); - readdir.sync.mockReturnValue(['root.js', 'lib/utils/util.js']); - setupManualMocks(); - - expect(readdir.sync).toHaveBeenCalledTimes(1); - expect(readdir.sync.mock.calls[0][0]).toBe(absPath('ce')); - - expect(setMock).toHaveBeenCalledTimes(2); - expect(setMock).toHaveBeenNthCalledWith(1, '~/root', './ce/root'); - expect(setMock).toHaveBeenNthCalledWith(2, '~/lib/utils/util', './ce/lib/utils/util'); - }); - - it('sets up mocks for all roots', () => { - const files = { - [absPath('ce')]: ['root', 'lib/utils/util'], - [absPath('node')]: ['jquery', '@babel/core'], - }; - - fs.existsSync.mockReturnValue(true); - readdir.sync.mockImplementation((root) => files[root]); - setupManualMocks(); - - expect(readdir.sync).toHaveBeenCalledTimes(1); - expect(readdir.sync.mock.calls[0][0]).toBe(absPath('ce')); - - expect(setMock).toHaveBeenCalledTimes(2); - expect(setMock).toHaveBeenNthCalledWith(1, '~/root', './ce/root'); - expect(setMock).toHaveBeenNthCalledWith(2, '~/lib/utils/util', './ce/lib/utils/util'); - }); - - it('fails when given a virtual mock', () => { - fs.existsSync.mockImplementation((p) => p.endsWith('ce')); - readdir.sync.mockReturnValue(['virtual', 'shouldntBeImported']); - setMock.mockImplementation(() => { - throw new Error('Could not locate module'); - }); - - expect(setupManualMocks).toThrow( - new Error("A manual mock was defined for module ~/virtual, but the module doesn't exist!"), - ); - - expect(readdir.sync).toHaveBeenCalledTimes(1); - expect(readdir.sync.mock.calls[0][0]).toBe(absPath('ce')); - }); - - describe('auto-injection', () => { - it('handles ambiguous paths', () => { - jest.isolateModules(() => { - const axios2 = require('../../../app/assets/javascripts/lib/utils/axios_utils').default; - expect(axios2.isMock).toBe(true); - }); - }); - - it('survives jest.isolateModules()', (done) => { - jest.isolateModules(() => { - const axios2 = require('~/lib/utils/axios_utils').default; - expect(axios2.isMock).toBe(true); - done(); - }); - }); - - it('can be unmocked and remocked', () => { - jest.dontMock('~/lib/utils/axios_utils'); - jest.resetModules(); - const axios2 = require('~/lib/utils/axios_utils').default; - expect(axios2).not.toBe(axios); - expect(axios2.isMock).toBeUndefined(); - - jest.doMock('~/lib/utils/axios_utils'); - jest.resetModules(); - const axios3 = require('~/lib/utils/axios_utils').default; - expect(axios3).not.toBe(axios2); - expect(axios3.isMock).toBe(true); - }); - }); -}); |