Commit 727fa810 authored by Illya Klymov's avatar Illya Klymov

Merge branch 'leipert-enable-asyncawait-in-jest' into 'master'

Enable async/await in Jest

See merge request gitlab-org/gitlab!23606
parents f01672e5 646c773f
import { __ } from '~/locale'; import { __ } from '~/locale';
class RecentSearchesServiceError { class RecentSearchesServiceError extends Error {
constructor(message) { constructor(message) {
super(message || __('Recent Searches Service is unavailable'));
this.name = 'RecentSearchesServiceError'; this.name = 'RecentSearchesServiceError';
this.message = message || __('Recent Searches Service is unavailable');
} }
} }
// Can't use `extends` for builtin prototypes and get true inheritance yet
RecentSearchesServiceError.prototype = Error.prototype;
export default RecentSearchesServiceError; export default RecentSearchesServiceError;
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
const BABEL_ENV = process.env.BABEL_ENV || process.env.NODE_ENV || null; const BABEL_ENV = process.env.BABEL_ENV || process.env.NODE_ENV || null;
const presets = [ let presets = [
[ [
'@babel/preset-env', '@babel/preset-env',
{ {
...@@ -49,6 +49,17 @@ if (isJest) { ...@@ -49,6 +49,17 @@ if (isJest) {
https://gitlab.com/gitlab-org/gitlab-foss/issues/58390 https://gitlab.com/gitlab-org/gitlab-foss/issues/58390
*/ */
plugins.push('babel-plugin-dynamic-import-node'); plugins.push('babel-plugin-dynamic-import-node');
presets = [
[
'@babel/preset-env',
{
targets: {
node: 'current',
},
},
],
];
} }
module.exports = { presets, plugins, sourceType: 'unambiguous' }; module.exports = { presets, plugins, sourceType: 'unambiguous' };
...@@ -38,7 +38,6 @@ describe('Branches Select', () => { ...@@ -38,7 +38,6 @@ describe('Branches Select', () => {
const search = (term = '') => { const search = (term = '') => {
$input.select2('search', term); $input.select2('search', term);
jest.runAllTimers();
}; };
beforeEach(() => { beforeEach(() => {
...@@ -48,7 +47,6 @@ describe('Branches Select', () => { ...@@ -48,7 +47,6 @@ describe('Branches Select', () => {
}); });
afterEach(() => { afterEach(() => {
jest.clearAllTimers();
wrapper.destroy(); wrapper.destroy();
}); });
......
...@@ -17,6 +17,7 @@ describe('EE Approvals MRRules', () => { ...@@ -17,6 +17,7 @@ describe('EE Approvals MRRules', () => {
let wrapper; let wrapper;
let store; let store;
let approvalRules; let approvalRules;
let OriginalMutationObserver;
const factory = () => { const factory = () => {
if (approvalRules) { if (approvalRules) {
...@@ -51,6 +52,11 @@ describe('EE Approvals MRRules', () => { ...@@ -51,6 +52,11 @@ describe('EE Approvals MRRules', () => {
}; };
beforeEach(() => { beforeEach(() => {
OriginalMutationObserver = global.MutationObserver;
global.MutationObserver = jest
.fn()
.mockImplementation(args => new OriginalMutationObserver(args));
store = createStoreOptions(MREditModule()); store = createStoreOptions(MREditModule());
store.modules.approvals.state = { store.modules.approvals.state = {
hasLoaded: true, hasLoaded: true,
...@@ -64,16 +70,14 @@ describe('EE Approvals MRRules', () => { ...@@ -64,16 +70,14 @@ describe('EE Approvals MRRules', () => {
wrapper = null; wrapper = null;
store = null; store = null;
approvalRules = null; approvalRules = null;
global.MutationObserver = OriginalMutationObserver;
}); });
describe('when editing a MR', () => { describe('when editing a MR', () => {
const initialTargetBranch = 'master'; const initialTargetBranch = 'master';
let targetBranchInputElement; let targetBranchInputElement;
let MutationObserverSpy;
beforeEach(() => { beforeEach(() => {
MutationObserverSpy = jest.spyOn(global, 'MutationObserver');
targetBranchInputElement = document.createElement('input'); targetBranchInputElement = document.createElement('input');
targetBranchInputElement.id = 'merge_request_target_branch'; targetBranchInputElement.id = 'merge_request_target_branch';
targetBranchInputElement.value = initialTargetBranch; targetBranchInputElement.value = initialTargetBranch;
...@@ -91,7 +95,6 @@ describe('EE Approvals MRRules', () => { ...@@ -91,7 +95,6 @@ describe('EE Approvals MRRules', () => {
afterEach(() => { afterEach(() => {
targetBranchInputElement.parentNode.removeChild(targetBranchInputElement); targetBranchInputElement.parentNode.removeChild(targetBranchInputElement);
MutationObserverSpy.mockClear();
}); });
it('sets the target branch data to be the same value as the target branch dropdown', () => { it('sets the target branch data to be the same value as the target branch dropdown', () => {
...@@ -103,20 +106,20 @@ describe('EE Approvals MRRules', () => { ...@@ -103,20 +106,20 @@ describe('EE Approvals MRRules', () => {
it('updates the target branch data when the target branch dropdown is changed', () => { it('updates the target branch data when the target branch dropdown is changed', () => {
factory(); factory();
const newValue = setTargetBranchInputValue(); const newValue = setTargetBranchInputValue();
callTargetBranchHandler(MutationObserverSpy); callTargetBranchHandler(global.MutationObserver);
expect(wrapper.vm.targetBranch).toBe(newValue); expect(wrapper.vm.targetBranch).toBe(newValue);
}); });
it('re-fetches rules when target branch has changed', () => { it('re-fetches rules when target branch has changed', () => {
factory(); factory();
setTargetBranchInputValue(); setTargetBranchInputValue();
callTargetBranchHandler(MutationObserverSpy); callTargetBranchHandler(global.MutationObserver);
expect(store.modules.approvals.actions.fetchRules).toHaveBeenCalled(); expect(store.modules.approvals.actions.fetchRules).toHaveBeenCalled();
}); });
it('disconnects MutationObserver when component gets destroyed', () => { it('disconnects MutationObserver when component gets destroyed', () => {
const mockDisconnect = jest.fn(); const mockDisconnect = jest.fn();
MutationObserverSpy.mockImplementation(() => ({ global.MutationObserver.mockImplementation(() => ({
disconnect: mockDisconnect, disconnect: mockDisconnect,
observe: jest.fn(), observe: jest.fn(),
})); }));
......
...@@ -3,15 +3,14 @@ import { TEST_HOST } from 'helpers/test_constants'; ...@@ -3,15 +3,14 @@ import { TEST_HOST } from 'helpers/test_constants';
import { issuableTypesMap, PathIdSeparator } from 'ee/related_issues/constants'; import { issuableTypesMap, PathIdSeparator } from 'ee/related_issues/constants';
import RelatedIssuableInput from 'ee/related_issues/components/related_issuable_input.vue'; import RelatedIssuableInput from 'ee/related_issues/components/related_issuable_input.vue';
jest.mock('ee_else_ce/gfm_auto_complete', () => ({ jest.mock('ee_else_ce/gfm_auto_complete', () => {
__esModule: true, return function gfmAutoComplete() {
default() {
return { return {
constructor() {}, constructor() {},
setup() {}, setup() {},
}; };
}, };
})); });
describe('RelatedIssuableInput', () => { describe('RelatedIssuableInput', () => {
let propsData; let propsData;
......
...@@ -4,9 +4,8 @@ import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; ...@@ -4,9 +4,8 @@ import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import { Blob as MockBlob } from './mock_data'; import { Blob as MockBlob } from './mock_data';
import { numberToHumanSize } from '~/lib/utils/number_utils'; import { numberToHumanSize } from '~/lib/utils/number_utils';
const mockHumanReadableSize = 'a lot';
jest.mock('~/lib/utils/number_utils', () => ({ jest.mock('~/lib/utils/number_utils', () => ({
numberToHumanSize: jest.fn(() => mockHumanReadableSize), numberToHumanSize: jest.fn(() => 'a lot'),
})); }));
describe('Blob Header Filepath', () => { describe('Blob Header Filepath', () => {
...@@ -57,7 +56,7 @@ describe('Blob Header Filepath', () => { ...@@ -57,7 +56,7 @@ describe('Blob Header Filepath', () => {
it('renders filesize in a human-friendly format', () => { it('renders filesize in a human-friendly format', () => {
createComponent(); createComponent();
expect(numberToHumanSize).toHaveBeenCalled(); expect(numberToHumanSize).toHaveBeenCalled();
expect(wrapper.vm.blobSize).toBe(mockHumanReadableSize); expect(wrapper.vm.blobSize).toBe('a lot');
}); });
it('renders a slot and prepends its contents to the existing one', () => { it('renders a slot and prepends its contents to the existing one', () => {
......
...@@ -4,6 +4,7 @@ import './element_scroll_to'; ...@@ -4,6 +4,7 @@ import './element_scroll_to';
import './form_element'; import './form_element';
import './get_client_rects'; import './get_client_rects';
import './inner_text'; import './inner_text';
import './mutation_observer';
import './window_scroll_to'; import './window_scroll_to';
import './scroll_by'; import './scroll_by';
import './size_properties'; import './size_properties';
......
/* eslint-disable class-methods-use-this */
class MutationObserverStub {
disconnect() {}
observe() {}
}
global.MutationObserver = MutationObserverStub;
...@@ -69,24 +69,19 @@ describe('IDE commit form', () => { ...@@ -69,24 +69,19 @@ describe('IDE commit form', () => {
}); });
}); });
it('collapses if lastCommitMsg is set to empty and current view is not commit view', () => { it('collapses if lastCommitMsg is set to empty and current view is not commit view', async () => {
store.state.lastCommitMsg = 'abc'; store.state.lastCommitMsg = 'abc';
store.state.currentActivityView = leftSidebarViews.edit.name; store.state.currentActivityView = leftSidebarViews.edit.name;
await vm.$nextTick();
return vm // if commit message is set, form is uncollapsed
.$nextTick() expect(vm.isCompact).toBe(false);
.then(() => {
// if commit message is set, form is uncollapsed
expect(vm.isCompact).toBe(false);
store.state.lastCommitMsg = ''; store.state.lastCommitMsg = '';
await vm.$nextTick();
return vm.$nextTick(); // collapsed when set to empty
}) expect(vm.isCompact).toBe(true);
.then(() => {
// collapsed when set to empty
expect(vm.isCompact).toBe(true);
});
}); });
}); });
......
...@@ -4,6 +4,7 @@ import DashboardPanel from '~/monitoring/components/dashboard_panel.vue'; ...@@ -4,6 +4,7 @@ import DashboardPanel from '~/monitoring/components/dashboard_panel.vue';
import { TEST_HOST } from 'helpers/test_constants'; import { TEST_HOST } from 'helpers/test_constants';
import MetricEmbed from '~/monitoring/components/embeds/metric_embed.vue'; import MetricEmbed from '~/monitoring/components/embeds/metric_embed.vue';
import { groups, initialState, metricsData, metricsWithData } from './mock_data'; import { groups, initialState, metricsData, metricsWithData } from './mock_data';
import { setHTMLFixture } from 'helpers/fixtures';
const localVue = createLocalVue(); const localVue = createLocalVue();
localVue.use(Vuex); localVue.use(Vuex);
...@@ -25,6 +26,8 @@ describe('MetricEmbed', () => { ...@@ -25,6 +26,8 @@ describe('MetricEmbed', () => {
} }
beforeEach(() => { beforeEach(() => {
setHTMLFixture('<div class="layout-page"></div>');
actions = { actions = {
setInitialState: jest.fn(), setInitialState: jest.fn(),
setShowErrorBanner: jest.fn(), setShowErrorBanner: jest.fn(),
......
...@@ -7,6 +7,7 @@ import linkedPipelinesColumn from '~/pipelines/components/graph/linked_pipelines ...@@ -7,6 +7,7 @@ import linkedPipelinesColumn from '~/pipelines/components/graph/linked_pipelines
import graphJSON from './mock_data'; import graphJSON from './mock_data';
import linkedPipelineJSON from './linked_pipelines_mock_data'; import linkedPipelineJSON from './linked_pipelines_mock_data';
import PipelinesMediator from '~/pipelines/pipeline_details_mediator'; import PipelinesMediator from '~/pipelines/pipeline_details_mediator';
import { setHTMLFixture } from 'helpers/fixtures';
describe('graph component', () => { describe('graph component', () => {
const store = new PipelineStore(); const store = new PipelineStore();
...@@ -15,6 +16,10 @@ describe('graph component', () => { ...@@ -15,6 +16,10 @@ describe('graph component', () => {
let wrapper; let wrapper;
beforeEach(() => {
setHTMLFixture('<div class="layout-page"></div>');
});
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
wrapper = null; wrapper = null;
......
...@@ -43,15 +43,6 @@ Object.assign(global, { ...@@ -43,15 +43,6 @@ Object.assign(global, {
preloadFixtures() {}, preloadFixtures() {},
}); });
Object.assign(global, {
MutationObserver() {
return {
disconnect() {},
observe() {},
};
},
});
// custom-jquery-matchers was written for an old Jest version, we need to make it compatible // custom-jquery-matchers was written for an old Jest version, we need to make it compatible
Object.entries(jqueryMatchers).forEach(([matcherName, matcherFactory]) => { Object.entries(jqueryMatchers).forEach(([matcherName, matcherFactory]) => {
// Don't override existing Jest matcher // Don't override existing Jest matcher
...@@ -69,12 +60,6 @@ expect.extend(customMatchers); ...@@ -69,12 +60,6 @@ expect.extend(customMatchers);
// Tech debt issue TBD // Tech debt issue TBD
testUtilsConfig.logModifiedComponents = false; testUtilsConfig.logModifiedComponents = false;
// Basic stub for MutationObserver
global.MutationObserver = () => ({
disconnect: () => {},
observe: () => {},
});
Object.assign(global, { Object.assign(global, {
requestIdleCallback(cb) { requestIdleCallback(cb) {
const start = Date.now(); const start = Date.now();
......
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