diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-04-14 00:09:57 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-04-14 00:09:57 +0300 |
commit | 08d684dcf589c730a2a9d021451c72efa14d1911 (patch) | |
tree | 42296df77d988aefd0e77e3b5a4dfab886ac0812 /spec | |
parent | 953eb09e086c8f2842512a62e56e32223b5bf974 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
34 files changed, 454 insertions, 632 deletions
diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb index a98ab1059b6..35fe58517d0 100644 --- a/spec/features/admin/admin_settings_spec.rb +++ b/spec/features/admin/admin_settings_spec.rb @@ -450,7 +450,7 @@ RSpec.describe 'Admin updates settings' do visit ci_cd_admin_application_settings_path page.within('.as-registry') do - find('#application_setting_container_registry_expiration_policies_caching.form-check-input').click + find('#application_setting_container_registry_expiration_policies_caching').click click_button 'Save changes' end diff --git a/spec/frontend/commits_spec.js b/spec/frontend/commits_spec.js index 8189ebe6e55..a049a6997f0 100644 --- a/spec/frontend/commits_spec.js +++ b/spec/frontend/commits_spec.js @@ -70,29 +70,17 @@ describe('Commits List', () => { mock.restore(); }); - it('should save the last search string', (done) => { + it('should save the last search string', async () => { commitsList.searchField.val('GitLab'); - commitsList - .filterResults() - .then(() => { - expect(ajaxSpy).toHaveBeenCalled(); - expect(commitsList.lastSearch).toEqual('GitLab'); - - done(); - }) - .catch(done.fail); + await commitsList.filterResults(); + expect(ajaxSpy).toHaveBeenCalled(); + expect(commitsList.lastSearch).toEqual('GitLab'); }); - it('should not make ajax call if the input does not change', (done) => { - commitsList - .filterResults() - .then(() => { - expect(ajaxSpy).not.toHaveBeenCalled(); - expect(commitsList.lastSearch).toEqual(''); - - done(); - }) - .catch(done.fail); + it('should not make ajax call if the input does not change', async () => { + await commitsList.filterResults(); + expect(ajaxSpy).not.toHaveBeenCalled(); + expect(commitsList.lastSearch).toEqual(''); }); }); }); diff --git a/spec/frontend/diffs/components/commit_item_spec.js b/spec/frontend/diffs/components/commit_item_spec.js index fbcc5ecefb3..6574d725180 100644 --- a/spec/frontend/diffs/components/commit_item_spec.js +++ b/spec/frontend/diffs/components/commit_item_spec.js @@ -6,6 +6,8 @@ import Component from '~/diffs/components/commit_item.vue'; import { getTimeago } from '~/lib/utils/datetime_utility'; import CommitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue'; +jest.mock('~/user_popovers'); + const TEST_AUTHOR_NAME = 'test'; const TEST_AUTHOR_EMAIL = 'test+test@gitlab.com'; const TEST_AUTHOR_GRAVATAR = `${TEST_HOST}/avatar/test?s=40`; diff --git a/spec/frontend/gpg_badges_spec.js b/spec/frontend/gpg_badges_spec.js index 44c70f1ad4d..0bb50fc3e6f 100644 --- a/spec/frontend/gpg_badges_spec.js +++ b/spec/frontend/gpg_badges_spec.js @@ -40,30 +40,22 @@ describe('GpgBadges', () => { mock.restore(); }); - it('does not make a request if there is no container element', (done) => { + it('does not make a request if there is no container element', async () => { setFixtures(''); jest.spyOn(axios, 'get').mockImplementation(() => {}); - GpgBadges.fetch() - .then(() => { - expect(axios.get).not.toHaveBeenCalled(); - }) - .then(done) - .catch(done.fail); + await GpgBadges.fetch(); + expect(axios.get).not.toHaveBeenCalled(); }); - it('throws an error if the endpoint is missing', (done) => { + it('throws an error if the endpoint is missing', async () => { setFixtures('<div class="js-signature-container"></div>'); jest.spyOn(axios, 'get').mockImplementation(() => {}); - GpgBadges.fetch() - .then(() => done.fail('Expected error to be thrown')) - .catch((error) => { - expect(error.message).toBe('Missing commit signatures endpoint!'); - expect(axios.get).not.toHaveBeenCalled(); - }) - .then(done) - .catch(done.fail); + await expect(GpgBadges.fetch()).rejects.toEqual( + new Error('Missing commit signatures endpoint!'), + ); + expect(axios.get).not.toHaveBeenCalled(); }); it('fetches commit signatures', async () => { @@ -104,31 +96,23 @@ describe('GpgBadges', () => { }); }); - it('displays a loading spinner', (done) => { + it('displays a loading spinner', async () => { mock.onGet(dummyUrl).replyOnce(200); - GpgBadges.fetch() - .then(() => { - expect(document.querySelector('.js-loading-gpg-badge:empty')).toBe(null); - const spinners = document.querySelectorAll('.js-loading-gpg-badge span.gl-spinner'); + await GpgBadges.fetch(); + expect(document.querySelector('.js-loading-gpg-badge:empty')).toBe(null); + const spinners = document.querySelectorAll('.js-loading-gpg-badge span.gl-spinner'); - expect(spinners.length).toBe(1); - done(); - }) - .catch(done.fail); + expect(spinners.length).toBe(1); }); - it('replaces the loading spinner', (done) => { + it('replaces the loading spinner', async () => { mock.onGet(dummyUrl).replyOnce(200, dummyResponse); - GpgBadges.fetch() - .then(() => { - expect(document.querySelector('.js-loading-gpg-badge')).toBe(null); - const parentContainer = document.querySelector('.parent-container'); + await GpgBadges.fetch(); + expect(document.querySelector('.js-loading-gpg-badge')).toBe(null); + const parentContainer = document.querySelector('.parent-container'); - expect(parentContainer.innerHTML.trim()).toEqual(dummyBadgeHtml); - done(); - }) - .catch(done.fail); + expect(parentContainer.innerHTML.trim()).toEqual(dummyBadgeHtml); }); }); diff --git a/spec/frontend/members/components/table/members_table_spec.js b/spec/frontend/members/components/table/members_table_spec.js index c02f483dac9..298a01e4f4d 100644 --- a/spec/frontend/members/components/table/members_table_spec.js +++ b/spec/frontend/members/components/table/members_table_spec.js @@ -21,6 +21,7 @@ import { BADGE_LABELS_PENDING_OWNER_APPROVAL, TAB_QUERY_PARAM_VALUES, } from '~/members/constants'; +import * as initUserPopovers from '~/user_popovers'; import { member as memberMock, directMember, @@ -256,6 +257,14 @@ describe('MembersTable', () => { }); }); + it('initializes user popovers when mounted', () => { + const initUserPopoversMock = jest.spyOn(initUserPopovers, 'default'); + + createComponent(); + + expect(initUserPopoversMock).toHaveBeenCalled(); + }); + it('adds QA selector to table', () => { createComponent(); diff --git a/spec/frontend/notes/components/notes_app_spec.js b/spec/frontend/notes/components/notes_app_spec.js index 56b19a43d7b..e227af88d3f 100644 --- a/spec/frontend/notes/components/notes_app_spec.js +++ b/spec/frontend/notes/components/notes_app_spec.js @@ -18,6 +18,8 @@ import '~/behaviors/markdown/render_gfm'; import OrderedLayout from '~/vue_shared/components/ordered_layout.vue'; import * as mockData from '../mock_data'; +jest.mock('~/user_popovers', () => jest.fn()); + setTestTimeout(1000); const TYPE_COMMENT_FORM = 'comment-form'; diff --git a/spec/frontend/pages/admin/application_settings/account_and_limits_spec.js b/spec/frontend/pages/admin/application_settings/account_and_limits_spec.js index 9f326dc33c0..3a4f93d4464 100644 --- a/spec/frontend/pages/admin/application_settings/account_and_limits_spec.js +++ b/spec/frontend/pages/admin/application_settings/account_and_limits_spec.js @@ -23,13 +23,12 @@ describe('AccountAndLimits', () => { expect($userInternalRegex.readOnly).toBeTruthy(); }); - it('is checked', (done) => { + it('is checked', () => { if (!$userDefaultExternal.prop('checked')) $userDefaultExternal.click(); expect($userDefaultExternal.prop('checked')).toBeTruthy(); expect($userInternalRegex.placeholder).toEqual(PLACEHOLDER_USER_EXTERNAL_DEFAULT_TRUE); expect($userInternalRegex.readOnly).toBeFalsy(); - done(); }); }); }); diff --git a/spec/frontend/pages/admin/jobs/index/components/stop_jobs_modal_spec.js b/spec/frontend/pages/admin/jobs/index/components/stop_jobs_modal_spec.js index 52648d3ce00..ebf21c01324 100644 --- a/spec/frontend/pages/admin/jobs/index/components/stop_jobs_modal_spec.js +++ b/spec/frontend/pages/admin/jobs/index/components/stop_jobs_modal_spec.js @@ -26,7 +26,7 @@ describe('stop_jobs_modal.vue', () => { }); describe('onSubmit', () => { - it('stops jobs and redirects to overview page', (done) => { + it('stops jobs and redirects to overview page', async () => { const responseURL = `${TEST_HOST}/stop_jobs_modal.vue/jobs`; jest.spyOn(axios, 'post').mockImplementation((url) => { expect(url).toBe(props.url); @@ -37,29 +37,19 @@ describe('stop_jobs_modal.vue', () => { }); }); - vm.onSubmit() - .then(() => { - expect(redirectTo).toHaveBeenCalledWith(responseURL); - }) - .then(done) - .catch(done.fail); + await vm.onSubmit(); + expect(redirectTo).toHaveBeenCalledWith(responseURL); }); - it('displays error if stopping jobs failed', (done) => { + it('displays error if stopping jobs failed', async () => { const dummyError = new Error('stopping jobs failed'); jest.spyOn(axios, 'post').mockImplementation((url) => { expect(url).toBe(props.url); return Promise.reject(dummyError); }); - vm.onSubmit() - .then(done.fail) - .catch((error) => { - expect(error).toBe(dummyError); - expect(redirectTo).not.toHaveBeenCalled(); - }) - .then(done) - .catch(done.fail); + await expect(vm.onSubmit()).rejects.toEqual(dummyError); + expect(redirectTo).not.toHaveBeenCalled(); }); }); }); diff --git a/spec/frontend/pages/dashboard/todos/index/todos_spec.js b/spec/frontend/pages/dashboard/todos/index/todos_spec.js index ef295e7d1ba..ae53afa7fba 100644 --- a/spec/frontend/pages/dashboard/todos/index/todos_spec.js +++ b/spec/frontend/pages/dashboard/todos/index/todos_spec.js @@ -31,15 +31,17 @@ describe('Todos', () => { }); describe('goToTodoUrl', () => { - it('opens the todo url', (done) => { + it('opens the todo url', () => { const todoLink = todoItem.dataset.url; + let expectedUrl = null; visitUrl.mockImplementation((url) => { - expect(url).toEqual(todoLink); - done(); + expectedUrl = url; }); todoItem.click(); + + expect(expectedUrl).toEqual(todoLink); }); describe('meta click', () => { diff --git a/spec/frontend/pages/profiles/show/emoji_menu_spec.js b/spec/frontend/pages/profiles/show/emoji_menu_spec.js index f35fb57aec7..fa6e7e51a60 100644 --- a/spec/frontend/pages/profiles/show/emoji_menu_spec.js +++ b/spec/frontend/pages/profiles/show/emoji_menu_spec.js @@ -46,22 +46,18 @@ describe('EmojiMenu', () => { const dummyEmoji = 'tropical_fish'; const dummyVotesBlock = () => $('<div />'); - it('calls selectEmojiCallback', (done) => { + it('calls selectEmojiCallback', async () => { expect(dummySelectEmojiCallback).not.toHaveBeenCalled(); - emojiMenu.addAward(dummyVotesBlock(), dummyAwardUrl, dummyEmoji, false, () => { - expect(dummySelectEmojiCallback).toHaveBeenCalledWith(dummyEmoji, dummyEmojiTag); - done(); - }); + await emojiMenu.addAward(dummyVotesBlock(), dummyAwardUrl, dummyEmoji, false); + expect(dummySelectEmojiCallback).toHaveBeenCalledWith(dummyEmoji, dummyEmojiTag); }); - it('does not make an axios request', (done) => { + it('does not make an axios request', async () => { jest.spyOn(axios, 'request').mockReturnValue(); - emojiMenu.addAward(dummyVotesBlock(), dummyAwardUrl, dummyEmoji, false, () => { - expect(axios.request).not.toHaveBeenCalled(); - done(); - }); + await emojiMenu.addAward(dummyVotesBlock(), dummyAwardUrl, dummyEmoji, false); + expect(axios.request).not.toHaveBeenCalled(); }); }); diff --git a/spec/frontend/pdf/page_spec.js b/spec/frontend/pdf/page_spec.js index 4e0a6f78b63..07a7f1bb2ff 100644 --- a/spec/frontend/pdf/page_spec.js +++ b/spec/frontend/pdf/page_spec.js @@ -1,4 +1,4 @@ -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import mountComponent from 'helpers/vue_mount_component_helper'; import PageComponent from '~/pdf/page/index.vue'; @@ -14,8 +14,7 @@ describe('Page component', () => { vm.$destroy(); }); - it('renders the page when mounting', (done) => { - const promise = Promise.resolve(); + it('renders the page when mounting', async () => { const testPage = { render: jest.fn().mockReturnValue({ promise: Promise.resolve() }), getViewport: jest.fn().mockReturnValue({}), @@ -28,12 +27,9 @@ describe('Page component', () => { expect(vm.rendering).toBe(true); - promise - .then(() => { - expect(testPage.render).toHaveBeenCalledWith(vm.renderContext); - expect(vm.rendering).toBe(false); - }) - .then(done) - .catch(done.fail); + await nextTick(); + + expect(testPage.render).toHaveBeenCalledWith(vm.renderContext); + expect(vm.rendering).toBe(false); }); }); diff --git a/spec/frontend/pipelines/graph/action_component_spec.js b/spec/frontend/pipelines/graph/action_component_spec.js index fab6e6887b7..6e5aa572ec0 100644 --- a/spec/frontend/pipelines/graph/action_component_spec.js +++ b/spec/frontend/pipelines/graph/action_component_spec.js @@ -48,17 +48,14 @@ describe('pipeline graph action component', () => { }); describe('on click', () => { - it('emits `pipelineActionRequestComplete` after a successful request', (done) => { + it('emits `pipelineActionRequestComplete` after a successful request', async () => { jest.spyOn(wrapper.vm, '$emit'); findButton().trigger('click'); - waitForPromises() - .then(() => { - expect(wrapper.vm.$emit).toHaveBeenCalledWith('pipelineActionRequestComplete'); - done(); - }) - .catch(done.fail); + await waitForPromises(); + + expect(wrapper.vm.$emit).toHaveBeenCalledWith('pipelineActionRequestComplete'); }); it('renders a loading icon while waiting for request', async () => { diff --git a/spec/frontend/pipelines/test_reports/stores/actions_spec.js b/spec/frontend/pipelines/test_reports/stores/actions_spec.js index 84a9f4776b9..d5acb115bc1 100644 --- a/spec/frontend/pipelines/test_reports/stores/actions_spec.js +++ b/spec/frontend/pipelines/test_reports/stores/actions_spec.js @@ -38,29 +38,25 @@ describe('Actions TestReports Store', () => { mock.onGet(summaryEndpoint).replyOnce(200, summary, {}); }); - it('sets testReports and shows tests', (done) => { - testAction( + it('sets testReports and shows tests', () => { + return testAction( actions.fetchSummary, null, state, [{ type: types.SET_SUMMARY, payload: summary }], [{ type: 'toggleLoading' }, { type: 'toggleLoading' }], - done, ); }); - it('should create flash on API error', (done) => { - testAction( + it('should create flash on API error', async () => { + await testAction( actions.fetchSummary, null, { summaryEndpoint: null }, [], [{ type: 'toggleLoading' }, { type: 'toggleLoading' }], - () => { - expect(createFlash).toHaveBeenCalled(); - done(); - }, ); + expect(createFlash).toHaveBeenCalled(); }); }); @@ -73,87 +69,80 @@ describe('Actions TestReports Store', () => { .replyOnce(200, testReports.test_suites[0], {}); }); - it('sets test suite and shows tests', (done) => { + it('sets test suite and shows tests', () => { const suite = testReports.test_suites[0]; const index = 0; - testAction( + return testAction( actions.fetchTestSuite, index, { ...state, testReports }, [{ type: types.SET_SUITE, payload: { suite, index } }], [{ type: 'toggleLoading' }, { type: 'toggleLoading' }], - done, ); }); - it('should create flash on API error', (done) => { + it('should create flash on API error', async () => { const index = 0; - testAction( + await testAction( actions.fetchTestSuite, index, { ...state, testReports, suiteEndpoint: null }, [], [{ type: 'toggleLoading' }, { type: 'toggleLoading' }], - () => { - expect(createFlash).toHaveBeenCalled(); - done(); - }, ); + expect(createFlash).toHaveBeenCalled(); }); describe('when we already have the suite data', () => { - it('should not fetch suite', (done) => { + it('should not fetch suite', () => { const index = 0; testReports.test_suites[0].hasFullSuite = true; - testAction(actions.fetchTestSuite, index, { ...state, testReports }, [], [], done); + return testAction(actions.fetchTestSuite, index, { ...state, testReports }, [], []); }); }); }); describe('set selected suite index', () => { - it('sets selectedSuiteIndex', (done) => { + it('sets selectedSuiteIndex', () => { const selectedSuiteIndex = 0; - testAction( + return testAction( actions.setSelectedSuiteIndex, selectedSuiteIndex, { ...state, hasFullReport: true }, [{ type: types.SET_SELECTED_SUITE_INDEX, payload: selectedSuiteIndex }], [], - done, ); }); }); describe('remove selected suite index', () => { - it('sets selectedSuiteIndex to null', (done) => { - testAction( + it('sets selectedSuiteIndex to null', () => { + return testAction( actions.removeSelectedSuiteIndex, {}, state, [{ type: types.SET_SELECTED_SUITE_INDEX, payload: null }], [], - done, ); }); }); describe('toggles loading', () => { - it('sets isLoading to true', (done) => { - testAction(actions.toggleLoading, {}, state, [{ type: types.TOGGLE_LOADING }], [], done); + it('sets isLoading to true', () => { + return testAction(actions.toggleLoading, {}, state, [{ type: types.TOGGLE_LOADING }], []); }); - it('toggles isLoading to false', (done) => { - testAction( + it('toggles isLoading to false', () => { + return testAction( actions.toggleLoading, {}, { ...state, isLoading: true }, [{ type: types.TOGGLE_LOADING }], [], - done, ); }); }); diff --git a/spec/frontend/projects/commit/store/actions_spec.js b/spec/frontend/projects/commit/store/actions_spec.js index 305257c9ca5..56dffcbd48e 100644 --- a/spec/frontend/projects/commit/store/actions_spec.js +++ b/spec/frontend/projects/commit/store/actions_spec.js @@ -44,12 +44,12 @@ describe('Commit form modal store actions', () => { }); describe('fetchBranches', () => { - it('dispatch correct actions on fetchBranches', (done) => { + it('dispatch correct actions on fetchBranches', () => { jest .spyOn(axios, 'get') .mockImplementation(() => Promise.resolve({ data: { Branches: mockData.mockBranches } })); - testAction( + return testAction( actions.fetchBranches, {}, state, @@ -60,19 +60,15 @@ describe('Commit form modal store actions', () => { }, ], [{ type: 'requestBranches' }], - () => { - done(); - }, ); }); - it('should show flash error and set error in state on fetchBranches failure', (done) => { + it('should show flash error and set error in state on fetchBranches failure', async () => { jest.spyOn(axios, 'get').mockRejectedValue(); - testAction(actions.fetchBranches, {}, state, [], [{ type: 'requestBranches' }], () => { - expect(createFlash).toHaveBeenCalledWith({ message: PROJECT_BRANCHES_ERROR }); - done(); - }); + await testAction(actions.fetchBranches, {}, state, [], [{ type: 'requestBranches' }]); + + expect(createFlash).toHaveBeenCalledWith({ message: PROJECT_BRANCHES_ERROR }); }); }); diff --git a/spec/frontend/reports/accessibility_report/store/actions_spec.js b/spec/frontend/reports/accessibility_report/store/actions_spec.js index 46dbe1ff7a1..bab6c4905a7 100644 --- a/spec/frontend/reports/accessibility_report/store/actions_spec.js +++ b/spec/frontend/reports/accessibility_report/store/actions_spec.js @@ -17,16 +17,15 @@ describe('Accessibility Reports actions', () => { }); describe('setEndpoints', () => { - it('should commit SET_ENDPOINTS mutation', (done) => { + it('should commit SET_ENDPOINTS mutation', () => { const endpoint = 'endpoint.json'; - testAction( + return testAction( actions.setEndpoint, endpoint, localState, [{ type: types.SET_ENDPOINT, payload: endpoint }], [], - done, ); }); }); @@ -46,11 +45,11 @@ describe('Accessibility Reports actions', () => { }); describe('success', () => { - it('should commit REQUEST_REPORT mutation and dispatch receiveReportSuccess', (done) => { + it('should commit REQUEST_REPORT mutation and dispatch receiveReportSuccess', () => { const data = { report: { summary: {} } }; mock.onGet(`${TEST_HOST}/endpoint.json`).reply(200, data); - testAction( + return testAction( actions.fetchReport, null, localState, @@ -61,60 +60,55 @@ describe('Accessibility Reports actions', () => { type: 'receiveReportSuccess', }, ], - done, ); }); }); describe('error', () => { - it('should commit REQUEST_REPORT and RECEIVE_REPORT_ERROR mutations', (done) => { + it('should commit REQUEST_REPORT and RECEIVE_REPORT_ERROR mutations', () => { mock.onGet(`${TEST_HOST}/endpoint.json`).reply(500); - testAction( + return testAction( actions.fetchReport, null, localState, [{ type: types.REQUEST_REPORT }], [{ type: 'receiveReportError' }], - done, ); }); }); }); describe('receiveReportSuccess', () => { - it('should commit RECEIVE_REPORT_SUCCESS mutation with 200', (done) => { - testAction( + it('should commit RECEIVE_REPORT_SUCCESS mutation with 200', () => { + return testAction( actions.receiveReportSuccess, { status: 200, data: mockReport }, localState, [{ type: types.RECEIVE_REPORT_SUCCESS, payload: mockReport }], [{ type: 'stopPolling' }], - done, ); }); - it('should not commit RECEIVE_REPORTS_SUCCESS mutation with 204', (done) => { - testAction( + it('should not commit RECEIVE_REPORTS_SUCCESS mutation with 204', () => { + return testAction( actions.receiveReportSuccess, { status: 204, data: mockReport }, localState, [], [], - done, ); }); }); describe('receiveReportError', () => { - it('should commit RECEIVE_REPORT_ERROR mutation', (done) => { - testAction( + it('should commit RECEIVE_REPORT_ERROR mutation', () => { + return testAction( actions.receiveReportError, null, localState, [{ type: types.RECEIVE_REPORT_ERROR }], [{ type: 'stopPolling' }], - done, ); }); }); diff --git a/spec/frontend/reports/codequality_report/store/actions_spec.js b/spec/frontend/reports/codequality_report/store/actions_spec.js index 1821390786b..71f1a0f4de0 100644 --- a/spec/frontend/reports/codequality_report/store/actions_spec.js +++ b/spec/frontend/reports/codequality_report/store/actions_spec.js @@ -23,7 +23,7 @@ describe('Codequality Reports actions', () => { }); describe('setPaths', () => { - it('should commit SET_PATHS mutation', (done) => { + it('should commit SET_PATHS mutation', () => { const paths = { baseBlobPath: 'baseBlobPath', headBlobPath: 'headBlobPath', @@ -31,13 +31,12 @@ describe('Codequality Reports actions', () => { helpPath: 'codequalityHelpPath', }; - testAction( + return testAction( actions.setPaths, paths, localState, [{ type: types.SET_PATHS, payload: paths }], [], - done, ); }); }); @@ -56,10 +55,10 @@ describe('Codequality Reports actions', () => { }); describe('on success', () => { - it('commits REQUEST_REPORTS and dispatches receiveReportsSuccess', (done) => { + it('commits REQUEST_REPORTS and dispatches receiveReportsSuccess', () => { mock.onGet(endpoint).reply(200, reportIssues); - testAction( + return testAction( actions.fetchReports, null, localState, @@ -70,51 +69,48 @@ describe('Codequality Reports actions', () => { type: 'receiveReportsSuccess', }, ], - done, ); }); }); describe('on error', () => { - it('commits REQUEST_REPORTS and dispatches receiveReportsError', (done) => { + it('commits REQUEST_REPORTS and dispatches receiveReportsError', () => { mock.onGet(endpoint).reply(500); - testAction( + return testAction( actions.fetchReports, null, localState, [{ type: types.REQUEST_REPORTS }], [{ type: 'receiveReportsError', payload: expect.any(Error) }], - done, ); }); }); describe('when base report is not found', () => { - it('commits REQUEST_REPORTS and dispatches receiveReportsError', (done) => { + it('commits REQUEST_REPORTS and dispatches receiveReportsError', () => { const data = { status: STATUS_NOT_FOUND }; mock.onGet(`${TEST_HOST}/codequality_reports.json`).reply(200, data); - testAction( + return testAction( actions.fetchReports, null, localState, [{ type: types.REQUEST_REPORTS }], [{ type: 'receiveReportsError', payload: data }], - done, ); }); }); describe('while waiting for report results', () => { - it('continues polling until it receives data', (done) => { + it('continues polling until it receives data', () => { mock .onGet(endpoint) .replyOnce(204, undefined, pollIntervalHeader) .onGet(endpoint) .reply(200, reportIssues); - Promise.all([ + return Promise.all([ testAction( actions.fetchReports, null, @@ -126,7 +122,6 @@ describe('Codequality Reports actions', () => { type: 'receiveReportsSuccess', }, ], - done, ), axios // wait for initial NO_CONTENT response to be fulfilled @@ -134,24 +129,23 @@ describe('Codequality Reports actions', () => { .then(() => { jest.advanceTimersByTime(pollInterval); }), - ]).catch(done.fail); + ]); }); - it('continues polling until it receives an error', (done) => { + it('continues polling until it receives an error', () => { mock .onGet(endpoint) .replyOnce(204, undefined, pollIntervalHeader) .onGet(endpoint) .reply(500); - Promise.all([ + return Promise.all([ testAction( actions.fetchReports, null, localState, [{ type: types.REQUEST_REPORTS }], [{ type: 'receiveReportsError', payload: expect.any(Error) }], - done, ), axios // wait for initial NO_CONTENT response to be fulfilled @@ -159,35 +153,33 @@ describe('Codequality Reports actions', () => { .then(() => { jest.advanceTimersByTime(pollInterval); }), - ]).catch(done.fail); + ]); }); }); }); describe('receiveReportsSuccess', () => { - it('commits RECEIVE_REPORTS_SUCCESS', (done) => { + it('commits RECEIVE_REPORTS_SUCCESS', () => { const data = { issues: [] }; - testAction( + return testAction( actions.receiveReportsSuccess, data, localState, [{ type: types.RECEIVE_REPORTS_SUCCESS, payload: data }], [], - done, ); }); }); describe('receiveReportsError', () => { - it('commits RECEIVE_REPORTS_ERROR', (done) => { - testAction( + it('commits RECEIVE_REPORTS_ERROR', () => { + return testAction( actions.receiveReportsError, null, localState, [{ type: types.RECEIVE_REPORTS_ERROR, payload: null }], [], - done, ); }); }); diff --git a/spec/frontend/reports/grouped_test_report/store/actions_spec.js b/spec/frontend/reports/grouped_test_report/store/actions_spec.js index bbc3a5dbba5..5876827c548 100644 --- a/spec/frontend/reports/grouped_test_report/store/actions_spec.js +++ b/spec/frontend/reports/grouped_test_report/store/actions_spec.js @@ -24,8 +24,8 @@ describe('Reports Store Actions', () => { }); describe('setPaths', () => { - it('should commit SET_PATHS mutation', (done) => { - testAction( + it('should commit SET_PATHS mutation', () => { + return testAction( setPaths, { endpoint: 'endpoint.json', headBlobPath: '/blob/path' }, mockedState, @@ -36,14 +36,13 @@ describe('Reports Store Actions', () => { }, ], [], - done, ); }); }); describe('requestReports', () => { - it('should commit REQUEST_REPORTS mutation', (done) => { - testAction(requestReports, null, mockedState, [{ type: types.REQUEST_REPORTS }], [], done); + it('should commit REQUEST_REPORTS mutation', () => { + return testAction(requestReports, null, mockedState, [{ type: types.REQUEST_REPORTS }], []); }); }); @@ -62,12 +61,12 @@ describe('Reports Store Actions', () => { }); describe('success', () => { - it('dispatches requestReports and receiveReportsSuccess ', (done) => { + it('dispatches requestReports and receiveReportsSuccess ', () => { mock .onGet(`${TEST_HOST}/endpoint.json`) .replyOnce(200, { summary: {}, suites: [{ name: 'rspec' }] }); - testAction( + return testAction( fetchReports, null, mockedState, @@ -81,7 +80,6 @@ describe('Reports Store Actions', () => { type: 'receiveReportsSuccess', }, ], - done, ); }); }); @@ -91,8 +89,8 @@ describe('Reports Store Actions', () => { mock.onGet(`${TEST_HOST}/endpoint.json`).reply(500); }); - it('dispatches requestReports and receiveReportsError ', (done) => { - testAction( + it('dispatches requestReports and receiveReportsError ', () => { + return testAction( fetchReports, null, mockedState, @@ -105,71 +103,65 @@ describe('Reports Store Actions', () => { type: 'receiveReportsError', }, ], - done, ); }); }); }); describe('receiveReportsSuccess', () => { - it('should commit RECEIVE_REPORTS_SUCCESS mutation with 200', (done) => { - testAction( + it('should commit RECEIVE_REPORTS_SUCCESS mutation with 200', () => { + return testAction( receiveReportsSuccess, { data: { summary: {} }, status: 200 }, mockedState, [{ type: types.RECEIVE_REPORTS_SUCCESS, payload: { summary: {} } }], [], - done, ); }); - it('should not commit RECEIVE_REPORTS_SUCCESS mutation with 204', (done) => { - testAction( + it('should not commit RECEIVE_REPORTS_SUCCESS mutation with 204', () => { + return testAction( receiveReportsSuccess, { data: { summary: {} }, status: 204 }, mockedState, [], [], - done, ); }); }); describe('receiveReportsError', () => { - it('should commit RECEIVE_REPORTS_ERROR mutation', (done) => { - testAction( + it('should commit RECEIVE_REPORTS_ERROR mutation', () => { + return testAction( receiveReportsError, null, mockedState, [{ type: types.RECEIVE_REPORTS_ERROR }], [], - done, ); }); }); describe('openModal', () => { - it('should commit SET_ISSUE_MODAL_DATA', (done) => { - testAction( + it('should commit SET_ISSUE_MODAL_DATA', () => { + return testAction( openModal, { name: 'foo' }, mockedState, [{ type: types.SET_ISSUE_MODAL_DATA, payload: { name: 'foo' } }], [], - done, ); }); }); describe('closeModal', () => { - it('should commit RESET_ISSUE_MODAL_DATA', (done) => { - testAction( + it('should commit RESET_ISSUE_MODAL_DATA', () => { + return testAction( closeModal, {}, mockedState, [{ type: types.RESET_ISSUE_MODAL_DATA, payload: {} }], [], - done, ); }); }); diff --git a/spec/frontend/search_autocomplete_spec.js b/spec/frontend/search_autocomplete_spec.js index c643cf6557d..190f2803324 100644 --- a/spec/frontend/search_autocomplete_spec.js +++ b/spec/frontend/search_autocomplete_spec.js @@ -223,34 +223,22 @@ describe('Search autocomplete dropdown', () => { }); } - it('suggest Projects', (done) => { - // eslint-disable-next-line promise/catch-or-return - triggerAutocomplete().finally(() => { - const list = widget.wrap.find('.dropdown-menu').find('ul'); - const link = "a[href$='/gitlab-org/gitlab-test']"; + it('suggest Projects', async () => { + await triggerAutocomplete(); - expect(list.find(link).length).toBe(1); + const list = widget.wrap.find('.dropdown-menu').find('ul'); + const link = "a[href$='/gitlab-org/gitlab-test']"; - done(); - }); - - // Make sure jest properly acknowledge the `done` invocation - jest.runOnlyPendingTimers(); + expect(list.find(link).length).toBe(1); }); - it('suggest Groups', (done) => { - // eslint-disable-next-line promise/catch-or-return - triggerAutocomplete().finally(() => { - const list = widget.wrap.find('.dropdown-menu').find('ul'); - const link = "a[href$='/gitlab-org']"; + it('suggest Groups', async () => { + await triggerAutocomplete(); - expect(list.find(link).length).toBe(1); - - done(); - }); + const list = widget.wrap.find('.dropdown-menu').find('ul'); + const link = "a[href$='/gitlab-org']"; - // Make sure jest properly acknowledge the `done` invocation - jest.runOnlyPendingTimers(); + expect(list.find(link).length).toBe(1); }); }); diff --git a/spec/frontend/self_monitor/store/actions_spec.js b/spec/frontend/self_monitor/store/actions_spec.js index 6bcb2a713ea..59ee87c4a02 100644 --- a/spec/frontend/self_monitor/store/actions_spec.js +++ b/spec/frontend/self_monitor/store/actions_spec.js @@ -16,27 +16,25 @@ describe('self monitor actions', () => { }); describe('setSelfMonitor', () => { - it('commits the SET_ENABLED mutation', (done) => { - testAction( + it('commits the SET_ENABLED mutation', () => { + return testAction( actions.setSelfMonitor, null, state, [{ type: types.SET_ENABLED, payload: null }], [], - done, ); }); }); describe('resetAlert', () => { - it('commits the SET_ENABLED mutation', (done) => { - testAction( + it('commits the SET_ENABLED mutation', () => { + return testAction( actions.resetAlert, null, state, [{ type: types.SET_SHOW_ALERT, payload: false }], [], - done, ); }); }); @@ -54,8 +52,8 @@ describe('self monitor actions', () => { }); }); - it('dispatches status request with job data', (done) => { - testAction( + it('dispatches status request with job data', () => { + return testAction( actions.requestCreateProject, null, state, @@ -71,12 +69,11 @@ describe('self monitor actions', () => { payload: '123', }, ], - done, ); }); - it('dispatches success with project path', (done) => { - testAction( + it('dispatches success with project path', () => { + return testAction( actions.requestCreateProjectStatus, null, state, @@ -87,7 +84,6 @@ describe('self monitor actions', () => { payload: { project_full_path: '/self-monitor-url' }, }, ], - done, ); }); }); @@ -98,8 +94,8 @@ describe('self monitor actions', () => { mock.onPost(state.createProjectEndpoint).reply(500); }); - it('dispatches error', (done) => { - testAction( + it('dispatches error', () => { + return testAction( actions.requestCreateProject, null, state, @@ -115,14 +111,13 @@ describe('self monitor actions', () => { payload: new Error('Request failed with status code 500'), }, ], - done, ); }); }); describe('requestCreateProjectSuccess', () => { - it('should commit the received data', (done) => { - testAction( + it('should commit the received data', () => { + return testAction( actions.requestCreateProjectSuccess, { project_full_path: '/self-monitor-url' }, state, @@ -146,7 +141,6 @@ describe('self monitor actions', () => { type: 'setSelfMonitor', }, ], - done, ); }); }); @@ -165,8 +159,8 @@ describe('self monitor actions', () => { }); }); - it('dispatches status request with job data', (done) => { - testAction( + it('dispatches status request with job data', () => { + return testAction( actions.requestDeleteProject, null, state, @@ -182,12 +176,11 @@ describe('self monitor actions', () => { payload: '456', }, ], - done, ); }); - it('dispatches success with status', (done) => { - testAction( + it('dispatches success with status', () => { + return testAction( actions.requestDeleteProjectStatus, null, state, @@ -198,7 +191,6 @@ describe('self monitor actions', () => { payload: { status: 'success' }, }, ], - done, ); }); }); @@ -209,8 +201,8 @@ describe('self monitor actions', () => { mock.onDelete(state.deleteProjectEndpoint).reply(500); }); - it('dispatches error', (done) => { - testAction( + it('dispatches error', () => { + return testAction( actions.requestDeleteProject, null, state, @@ -226,14 +218,13 @@ describe('self monitor actions', () => { payload: new Error('Request failed with status code 500'), }, ], - done, ); }); }); describe('requestDeleteProjectSuccess', () => { - it('should commit mutations to remove previously set data', (done) => { - testAction( + it('should commit mutations to remove previously set data', () => { + return testAction( actions.requestDeleteProjectSuccess, null, state, @@ -252,7 +243,6 @@ describe('self monitor actions', () => { { type: types.SET_LOADING, payload: false }, ], [], - done, ); }); }); diff --git a/spec/frontend/serverless/store/actions_spec.js b/spec/frontend/serverless/store/actions_spec.js index 61b9bd121af..5fbecf081a6 100644 --- a/spec/frontend/serverless/store/actions_spec.js +++ b/spec/frontend/serverless/store/actions_spec.js @@ -7,13 +7,22 @@ import { mockServerlessFunctions, mockMetrics } from '../mock_data'; import { adjustMetricQuery } from '../utils'; describe('ServerlessActions', () => { + let mock; + + beforeEach(() => { + mock = new MockAdapter(axios); + }); + + afterEach(() => { + mock.restore(); + }); + describe('fetchFunctions', () => { - it('should successfully fetch functions', (done) => { + it('should successfully fetch functions', () => { const endpoint = '/functions'; - const mock = new MockAdapter(axios); mock.onGet(endpoint).reply(statusCodes.OK, JSON.stringify(mockServerlessFunctions)); - testAction( + return testAction( fetchFunctions, { functionsPath: endpoint }, {}, @@ -22,68 +31,49 @@ describe('ServerlessActions', () => { { type: 'requestFunctionsLoading' }, { type: 'receiveFunctionsSuccess', payload: mockServerlessFunctions }, ], - () => { - mock.restore(); - done(); - }, ); }); - it('should successfully retry', (done) => { + it('should successfully retry', () => { const endpoint = '/functions'; - const mock = new MockAdapter(axios); mock .onGet(endpoint) .reply(() => new Promise((resolve) => setTimeout(() => resolve(200), Infinity))); - testAction( + return testAction( fetchFunctions, { functionsPath: endpoint }, {}, [], [{ type: 'requestFunctionsLoading' }], - () => { - mock.restore(); - done(); - }, ); }); }); describe('fetchMetrics', () => { - it('should return no prometheus', (done) => { + it('should return no prometheus', () => { const endpoint = '/metrics'; - const mock = new MockAdapter(axios); mock.onGet(endpoint).reply(statusCodes.NO_CONTENT); - testAction( + return testAction( fetchMetrics, { metricsPath: endpoint, hasPrometheus: false }, {}, [], [{ type: 'receiveMetricsNoPrometheus' }], - () => { - mock.restore(); - done(); - }, ); }); - it('should successfully fetch metrics', (done) => { + it('should successfully fetch metrics', () => { const endpoint = '/metrics'; - const mock = new MockAdapter(axios); mock.onGet(endpoint).reply(statusCodes.OK, JSON.stringify(mockMetrics)); - testAction( + return testAction( fetchMetrics, { metricsPath: endpoint, hasPrometheus: true }, {}, [], [{ type: 'receiveMetricsSuccess', payload: adjustMetricQuery(mockMetrics) }], - () => { - mock.restore(); - done(); - }, ); }); }); diff --git a/spec/frontend/task_list_spec.js b/spec/frontend/task_list_spec.js index bf470e7e126..fbdb73ae6de 100644 --- a/spec/frontend/task_list_spec.js +++ b/spec/frontend/task_list_spec.js @@ -121,7 +121,7 @@ describe('TaskList', () => { }); describe('update', () => { - it('should disable task list items and make a patch request then enable them again', (done) => { + it('should disable task list items and make a patch request then enable them again', () => { const response = { data: { lock_version: 3 } }; jest.spyOn(taskList, 'enableTaskListItems').mockImplementation(() => {}); jest.spyOn(taskList, 'disableTaskListItems').mockImplementation(() => {}); @@ -156,20 +156,17 @@ describe('TaskList', () => { expect(taskList.onUpdate).toHaveBeenCalled(); - update - .then(() => { - expect(taskList.disableTaskListItems).toHaveBeenCalledWith(event); - expect(axios.patch).toHaveBeenCalledWith(endpoint, patchData); - expect(taskList.enableTaskListItems).toHaveBeenCalledWith(event); - expect(taskList.onSuccess).toHaveBeenCalledWith(response.data); - expect(taskList.lockVersion).toEqual(response.data.lock_version); - }) - .then(done) - .catch(done.fail); + return update.then(() => { + expect(taskList.disableTaskListItems).toHaveBeenCalledWith(event); + expect(axios.patch).toHaveBeenCalledWith(endpoint, patchData); + expect(taskList.enableTaskListItems).toHaveBeenCalledWith(event); + expect(taskList.onSuccess).toHaveBeenCalledWith(response.data); + expect(taskList.lockVersion).toEqual(response.data.lock_version); + }); }); }); - it('should handle request error and enable task list items', (done) => { + it('should handle request error and enable task list items', () => { const response = { data: { error: 1 } }; jest.spyOn(taskList, 'enableTaskListItems').mockImplementation(() => {}); jest.spyOn(taskList, 'onUpdate').mockImplementation(() => {}); @@ -182,12 +179,9 @@ describe('TaskList', () => { expect(taskList.onUpdate).toHaveBeenCalled(); - update - .then(() => { - expect(taskList.enableTaskListItems).toHaveBeenCalledWith(event); - expect(taskList.onError).toHaveBeenCalledWith(response.data); - }) - .then(done) - .catch(done.fail); + return update.then(() => { + expect(taskList.enableTaskListItems).toHaveBeenCalledWith(event); + expect(taskList.onError).toHaveBeenCalledWith(response.data); + }); }); }); diff --git a/spec/frontend/user_lists/store/index/actions_spec.js b/spec/frontend/user_lists/store/index/actions_spec.js index 5cce37de23d..4a8d0afb963 100644 --- a/spec/frontend/user_lists/store/index/actions_spec.js +++ b/spec/frontend/user_lists/store/index/actions_spec.js @@ -24,14 +24,13 @@ describe('~/user_lists/store/index/actions', () => { }); describe('setUserListsOptions', () => { - it('should commit SET_USER_LISTS_OPTIONS mutation', (done) => { - testAction( + it('should commit SET_USER_LISTS_OPTIONS mutation', () => { + return testAction( setUserListsOptions, { page: '1', scope: 'all' }, state, [{ type: types.SET_USER_LISTS_OPTIONS, payload: { page: '1', scope: 'all' } }], [], - done, ); }); }); @@ -42,8 +41,8 @@ describe('~/user_lists/store/index/actions', () => { }); describe('success', () => { - it('dispatches requestUserLists and receiveUserListsSuccess ', (done) => { - testAction( + it('dispatches requestUserLists and receiveUserListsSuccess ', () => { + return testAction( fetchUserLists, null, state, @@ -57,16 +56,15 @@ describe('~/user_lists/store/index/actions', () => { type: 'receiveUserListsSuccess', }, ], - done, ); }); }); describe('error', () => { - it('dispatches requestUserLists and receiveUserListsError ', (done) => { + it('dispatches requestUserLists and receiveUserListsError ', () => { Api.fetchFeatureFlagUserLists.mockRejectedValue(); - testAction( + return testAction( fetchUserLists, null, state, @@ -79,21 +77,20 @@ describe('~/user_lists/store/index/actions', () => { type: 'receiveUserListsError', }, ], - done, ); }); }); }); describe('requestUserLists', () => { - it('should commit RECEIVE_USER_LISTS_SUCCESS mutation', (done) => { - testAction(requestUserLists, null, state, [{ type: types.REQUEST_USER_LISTS }], [], done); + it('should commit RECEIVE_USER_LISTS_SUCCESS mutation', () => { + return testAction(requestUserLists, null, state, [{ type: types.REQUEST_USER_LISTS }], []); }); }); describe('receiveUserListsSuccess', () => { - it('should commit RECEIVE_USER_LISTS_SUCCESS mutation', (done) => { - testAction( + it('should commit RECEIVE_USER_LISTS_SUCCESS mutation', () => { + return testAction( receiveUserListsSuccess, { data: [userList], headers: {} }, state, @@ -104,20 +101,18 @@ describe('~/user_lists/store/index/actions', () => { }, ], [], - done, ); }); }); describe('receiveUserListsError', () => { - it('should commit RECEIVE_USER_LISTS_ERROR mutation', (done) => { - testAction( + it('should commit RECEIVE_USER_LISTS_ERROR mutation', () => { + return testAction( receiveUserListsError, null, state, [{ type: types.RECEIVE_USER_LISTS_ERROR }], [], - done, ); }); }); @@ -132,14 +127,13 @@ describe('~/user_lists/store/index/actions', () => { Api.deleteFeatureFlagUserList.mockResolvedValue(); }); - it('should refresh the user lists', (done) => { - testAction( + it('should refresh the user lists', () => { + return testAction( deleteUserList, userList, state, [], [{ type: 'requestDeleteUserList', payload: userList }, { type: 'fetchUserLists' }], - done, ); }); }); @@ -149,8 +143,8 @@ describe('~/user_lists/store/index/actions', () => { Api.deleteFeatureFlagUserList.mockRejectedValue({ response: { data: 'some error' } }); }); - it('should dispatch receiveDeleteUserListError', (done) => { - testAction( + it('should dispatch receiveDeleteUserListError', () => { + return testAction( deleteUserList, userList, state, @@ -162,15 +156,14 @@ describe('~/user_lists/store/index/actions', () => { payload: { list: userList, error: 'some error' }, }, ], - done, ); }); }); }); describe('receiveDeleteUserListError', () => { - it('should commit RECEIVE_DELETE_USER_LIST_ERROR with the given list', (done) => { - testAction( + it('should commit RECEIVE_DELETE_USER_LIST_ERROR with the given list', () => { + return testAction( receiveDeleteUserListError, { list: userList, error: 'mock error' }, state, @@ -181,22 +174,20 @@ describe('~/user_lists/store/index/actions', () => { }, ], [], - done, ); }); }); describe('clearAlert', () => { - it('should commit RECEIVE_CLEAR_ALERT', (done) => { + it('should commit RECEIVE_CLEAR_ALERT', () => { const alertIndex = 3; - testAction( + return testAction( clearAlert, alertIndex, state, [{ type: 'RECEIVE_CLEAR_ALERT', payload: alertIndex }], [], - done, ); }); }); diff --git a/spec/frontend/user_popovers_spec.js b/spec/frontend/user_popovers_spec.js index f3e0a37e163..745b66fd700 100644 --- a/spec/frontend/user_popovers_spec.js +++ b/spec/frontend/user_popovers_spec.js @@ -18,13 +18,12 @@ describe('User Popovers', () => { return link; }; - const findPopovers = () => { - return Array.from(document.querySelectorAll('[data-testid="user-popover"]')); - }; const dummyUser = { name: 'root' }; const dummyUserStatus = { message: 'active' }; + let popovers; + const triggerEvent = (eventName, el) => { const event = new MouseEvent(eventName, { bubbles: true, @@ -46,49 +45,29 @@ describe('User Popovers', () => { .spyOn(UsersCache, 'retrieveStatusById') .mockImplementation((userId) => userStatusCacheSpy(userId)); - initUserPopovers(document.querySelectorAll(selector), (popoverInstance) => { - const mountingRoot = document.createElement('div'); - document.body.appendChild(mountingRoot); - popoverInstance.$mount(mountingRoot); - }); + popovers = initUserPopovers(document.querySelectorAll(selector)); }); - describe('shows a placeholder popover on hover', () => { - let linksWithUsers; - beforeEach(() => { - linksWithUsers = findFixtureLinks(); - linksWithUsers.forEach((el) => { - triggerEvent('mouseenter', el); - }); - }); + it('initializes a popover for each user link with a user id', () => { + const linksWithUsers = findFixtureLinks(); - it('for initial links', () => { - expect(findPopovers().length).toBe(linksWithUsers.length); - }); - - it('for elements added after initial load', async () => { - const addedLinks = [createUserLink(), createUserLink()]; - addedLinks.forEach((link) => { - document.body.appendChild(link); - }); + expect(linksWithUsers.length).toBe(popovers.length); + }); - await Promise.resolve(); + it('adds popovers to user links added to the DOM tree after the initial call', async () => { + document.body.appendChild(createUserLink()); + document.body.appendChild(createUserLink()); - addedLinks.forEach((link) => { - triggerEvent('mouseenter', link); - }); + const linksWithUsers = findFixtureLinks(); - expect(findPopovers().length).toBe(linksWithUsers.length + addedLinks.length); - }); + expect(linksWithUsers.length).toBe(popovers.length + 2); }); it('does not initialize the user popovers twice for the same element', () => { - const [firstUserLink] = findFixtureLinks(); - triggerEvent('mouseenter', firstUserLink); - triggerEvent('mouseleave', firstUserLink); - triggerEvent('mouseenter', firstUserLink); + const newPopovers = initUserPopovers(document.querySelectorAll(selector)); + const samePopovers = popovers.every((popover, index) => newPopovers[index] === popover); - expect(findPopovers().length).toBe(1); + expect(samePopovers).toBe(true); }); describe('when user link emits mouseenter event', () => { @@ -107,11 +86,11 @@ describe('User Popovers', () => { expect(userLink.dataset.originalTitle).toBeFalsy(); }); - it('populates popover with preloaded user data', () => { + it('populates popovers with preloaded user data', () => { const { name, userId, username } = userLink.dataset; - const [firstPopover] = findFixtureLinks(); + const [firstPopover] = popovers; - expect(firstPopover.user).toEqual( + expect(firstPopover.$props.user).toEqual( expect.objectContaining({ name, userId, diff --git a/spec/frontend/vue_mr_widget/components/approvals/approvals_spec.js b/spec/frontend/vue_mr_widget/components/approvals/approvals_spec.js index 36850e623c7..4985417ad99 100644 --- a/spec/frontend/vue_mr_widget/components/approvals/approvals_spec.js +++ b/spec/frontend/vue_mr_widget/components/approvals/approvals_spec.js @@ -1,3 +1,4 @@ +import { nextTick } from 'vue'; import { GlButton } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import createFlash from '~/flash'; @@ -28,11 +29,6 @@ const testApprovals = () => ({ }); const testApprovalRulesResponse = () => ({ rules: [{ id: 2 }] }); -// For some reason, the `Promise.resolve()` needs to be deferred -// or the timing doesn't work. -const tick = () => Promise.resolve(); -const waitForTick = (done) => tick().then(done).catch(done.fail); - describe('MRWidget approvals', () => { let wrapper; let service; @@ -105,7 +101,7 @@ describe('MRWidget approvals', () => { // eslint-disable-next-line no-restricted-syntax wrapper.setData({ fetchingApprovals: true }); - return tick().then(() => { + return nextTick().then(() => { expect(wrapper.text()).toContain(FETCH_LOADING); }); }); @@ -116,10 +112,10 @@ describe('MRWidget approvals', () => { }); describe('when fetch approvals error', () => { - beforeEach((done) => { + beforeEach(() => { jest.spyOn(service, 'fetchApprovals').mockReturnValue(Promise.reject()); createComponent(); - waitForTick(done); + return nextTick(); }); it('still shows loading message', () => { @@ -133,13 +129,13 @@ describe('MRWidget approvals', () => { describe('action button', () => { describe('when mr is closed', () => { - beforeEach((done) => { + beforeEach(() => { mr.isOpen = false; mr.approvals.user_has_approved = false; mr.approvals.user_can_approve = true; createComponent(); - waitForTick(done); + return nextTick(); }); it('action is not rendered', () => { @@ -148,12 +144,12 @@ describe('MRWidget approvals', () => { }); describe('when user cannot approve', () => { - beforeEach((done) => { + beforeEach(() => { mr.approvals.user_has_approved = false; mr.approvals.user_can_approve = false; createComponent(); - waitForTick(done); + return nextTick(); }); it('action is not rendered', () => { @@ -168,9 +164,9 @@ describe('MRWidget approvals', () => { }); describe('and MR is unapproved', () => { - beforeEach((done) => { + beforeEach(() => { createComponent(); - waitForTick(done); + return nextTick(); }); it('approve action is rendered', () => { @@ -188,10 +184,10 @@ describe('MRWidget approvals', () => { }); describe('with no approvers', () => { - beforeEach((done) => { + beforeEach(() => { mr.approvals.approved_by = []; createComponent(); - waitForTick(done); + return nextTick(); }); it('approve action (with inverted style) is rendered', () => { @@ -204,10 +200,10 @@ describe('MRWidget approvals', () => { }); describe('with approvers', () => { - beforeEach((done) => { + beforeEach(() => { mr.approvals.approved_by = [{ user: { id: 7 } }]; createComponent(); - waitForTick(done); + return nextTick(); }); it('approve additionally action is rendered', () => { @@ -221,9 +217,9 @@ describe('MRWidget approvals', () => { }); describe('when approve action is clicked', () => { - beforeEach((done) => { + beforeEach(() => { createComponent(); - waitForTick(done); + return nextTick(); }); it('shows loading icon', () => { @@ -234,15 +230,15 @@ describe('MRWidget approvals', () => { action.vm.$emit('click'); - return tick().then(() => { + return nextTick().then(() => { expect(action.props('loading')).toBe(true); }); }); describe('and after loading', () => { - beforeEach((done) => { + beforeEach(() => { findAction().vm.$emit('click'); - waitForTick(done); + return nextTick(); }); it('calls service approve', () => { @@ -259,10 +255,10 @@ describe('MRWidget approvals', () => { }); describe('and error', () => { - beforeEach((done) => { + beforeEach(() => { jest.spyOn(service, 'approveMergeRequest').mockReturnValue(Promise.reject()); findAction().vm.$emit('click'); - waitForTick(done); + return nextTick(); }); it('flashes error message', () => { @@ -273,12 +269,12 @@ describe('MRWidget approvals', () => { }); describe('when user has approved', () => { - beforeEach((done) => { + beforeEach(() => { mr.approvals.user_has_approved = true; mr.approvals.user_can_approve = false; createComponent(); - waitForTick(done); + return nextTick(); }); it('revoke action is rendered', () => { @@ -291,9 +287,9 @@ describe('MRWidget approvals', () => { describe('when revoke action is clicked', () => { describe('and successful', () => { - beforeEach((done) => { + beforeEach(() => { findAction().vm.$emit('click'); - waitForTick(done); + return nextTick(); }); it('calls service unapprove', () => { @@ -310,10 +306,10 @@ describe('MRWidget approvals', () => { }); describe('and error', () => { - beforeEach((done) => { + beforeEach(() => { jest.spyOn(service, 'unapproveMergeRequest').mockReturnValue(Promise.reject()); findAction().vm.$emit('click'); - waitForTick(done); + return nextTick(); }); it('flashes error message', () => { @@ -333,11 +329,11 @@ describe('MRWidget approvals', () => { }); describe('and can approve', () => { - beforeEach((done) => { + beforeEach(() => { mr.approvals.user_can_approve = true; createComponent(); - waitForTick(done); + return nextTick(); }); it('is shown', () => { @@ -350,11 +346,11 @@ describe('MRWidget approvals', () => { }); describe('and cannot approve', () => { - beforeEach((done) => { + beforeEach(() => { mr.approvals.user_can_approve = false; createComponent(); - waitForTick(done); + return nextTick(); }); it('is shown', () => { @@ -369,9 +365,9 @@ describe('MRWidget approvals', () => { }); describe('approvals summary', () => { - beforeEach((done) => { + beforeEach(() => { createComponent(); - waitForTick(done); + return nextTick(); }); it('is rendered with props', () => { diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_memory_usage_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_memory_usage_spec.js index c0a30a5093d..f0106914674 100644 --- a/spec/frontend/vue_mr_widget/components/mr_widget_memory_usage_spec.js +++ b/spec/frontend/vue_mr_widget/components/mr_widget_memory_usage_spec.js @@ -175,22 +175,19 @@ describe('MemoryUsage', () => { expect(el.querySelector('.js-usage-info')).toBeDefined(); }); - it('should show loading metrics message while metrics are being loaded', (done) => { + it('should show loading metrics message while metrics are being loaded', async () => { vm.loadingMetrics = true; vm.hasMetrics = false; vm.loadFailed = false; - nextTick(() => { - expect(el.querySelector('.js-usage-info.usage-info-loading')).toBeDefined(); + await nextTick(); - expect(el.querySelector('.js-usage-info .usage-info-load-spinner')).toBeDefined(); - - expect(el.querySelector('.js-usage-info').innerText).toContain(messages.loadingMetrics); - done(); - }); + expect(el.querySelector('.js-usage-info.usage-info-loading')).toBeDefined(); + expect(el.querySelector('.js-usage-info .usage-info-load-spinner')).toBeDefined(); + expect(el.querySelector('.js-usage-info').innerText).toContain(messages.loadingMetrics); }); - it('should show deployment memory usage when metrics are loaded', (done) => { + it('should show deployment memory usage when metrics are loaded', async () => { // ignore BoostrapVue warnings jest.spyOn(console, 'warn').mockImplementation(); @@ -199,37 +196,32 @@ describe('MemoryUsage', () => { vm.loadFailed = false; vm.memoryMetrics = metricsMockData.metrics.memory_values[0].values; - nextTick(() => { - expect(el.querySelector('.memory-graph-container')).toBeDefined(); - expect(el.querySelector('.js-usage-info').innerText).toContain(messages.hasMetrics); - done(); - }); + await nextTick(); + + expect(el.querySelector('.memory-graph-container')).toBeDefined(); + expect(el.querySelector('.js-usage-info').innerText).toContain(messages.hasMetrics); }); - it('should show failure message when metrics loading failed', (done) => { + it('should show failure message when metrics loading failed', async () => { vm.loadingMetrics = false; vm.hasMetrics = false; vm.loadFailed = true; - nextTick(() => { - expect(el.querySelector('.js-usage-info.usage-info-failed')).toBeDefined(); + await nextTick(); - expect(el.querySelector('.js-usage-info').innerText).toContain(messages.loadFailed); - done(); - }); + expect(el.querySelector('.js-usage-info.usage-info-failed')).toBeDefined(); + expect(el.querySelector('.js-usage-info').innerText).toContain(messages.loadFailed); }); - it('should show metrics unavailable message when metrics loading failed', (done) => { + it('should show metrics unavailable message when metrics loading failed', async () => { vm.loadingMetrics = false; vm.hasMetrics = false; vm.loadFailed = false; - nextTick(() => { - expect(el.querySelector('.js-usage-info.usage-info-unavailable')).toBeDefined(); + await nextTick(); - expect(el.querySelector('.js-usage-info').innerText).toContain(messages.metricsUnavailable); - done(); - }); + expect(el.querySelector('.js-usage-info.usage-info-unavailable')).toBeDefined(); + expect(el.querySelector('.js-usage-info').innerText).toContain(messages.metricsUnavailable); }); }); }); diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js index 7d86e453bc7..8efc4d84624 100644 --- a/spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js +++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js @@ -198,14 +198,13 @@ describe('MRWidgetMerged', () => { ); }); - it('hides button to copy commit SHA if SHA does not exist', (done) => { + it('hides button to copy commit SHA if SHA does not exist', async () => { vm.mr.mergeCommitSha = null; - nextTick(() => { - expect(selectors.copyMergeShaButton).toBe(null); - expect(vm.$el.querySelector('.mr-info-list').innerText).not.toContain('with'); - done(); - }); + await nextTick(); + + expect(selectors.copyMergeShaButton).toBe(null); + expect(vm.$el.querySelector('.mr-info-list').innerText).not.toContain('with'); }); it('shows merge commit SHA link', () => { @@ -214,24 +213,22 @@ describe('MRWidgetMerged', () => { expect(selectors.mergeCommitShaLink.href).toBe(vm.mr.mergeCommitPath); }); - it('should not show source branch deleted text', (done) => { + it('should not show source branch deleted text', async () => { vm.mr.sourceBranchRemoved = false; - nextTick(() => { - expect(vm.$el.innerText).not.toContain('The source branch has been deleted'); - done(); - }); + await nextTick(); + + expect(vm.$el.innerText).not.toContain('The source branch has been deleted'); }); - it('should show source branch deleting text', (done) => { + it('should show source branch deleting text', async () => { vm.mr.isRemovingSourceBranch = true; vm.mr.sourceBranchRemoved = false; - nextTick(() => { - expect(vm.$el.innerText).toContain('The source branch is being deleted'); - expect(vm.$el.innerText).not.toContain('The source branch has been deleted'); - done(); - }); + await nextTick(); + + expect(vm.$el.innerText).toContain('The source branch is being deleted'); + expect(vm.$el.innerText).not.toContain('The source branch has been deleted'); }); it('should use mergedEvent mergedAt as tooltip title', () => { diff --git a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js index 5c91046c702..9719e81fe12 100644 --- a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js +++ b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js @@ -189,9 +189,9 @@ describe('MrWidgetOptions', () => { }); describe('when merge request is opened', () => { - beforeEach((done) => { + beforeEach(() => { wrapper.vm.mr.isOpen = true; - nextTick(done); + return nextTick(); }); it('should render collaboration status', () => { @@ -200,9 +200,9 @@ describe('MrWidgetOptions', () => { }); describe('when merge request is not opened', () => { - beforeEach((done) => { + beforeEach(() => { wrapper.vm.mr.isOpen = false; - nextTick(done); + return nextTick(); }); it('should not render collaboration status', () => { @@ -217,9 +217,9 @@ describe('MrWidgetOptions', () => { }); describe('when merge request is opened', () => { - beforeEach((done) => { + beforeEach(() => { wrapper.vm.mr.isOpen = true; - nextTick(done); + return nextTick(); }); it('should not render collaboration status', () => { @@ -231,11 +231,11 @@ describe('MrWidgetOptions', () => { describe('showMergePipelineForkWarning', () => { describe('when the source project and target project are the same', () => { - beforeEach((done) => { + beforeEach(() => { Vue.set(wrapper.vm.mr, 'mergePipelinesEnabled', true); Vue.set(wrapper.vm.mr, 'sourceProjectId', 1); Vue.set(wrapper.vm.mr, 'targetProjectId', 1); - nextTick(done); + return nextTick(); }); it('should be false', () => { @@ -244,11 +244,11 @@ describe('MrWidgetOptions', () => { }); describe('when merge pipelines are not enabled', () => { - beforeEach((done) => { + beforeEach(() => { Vue.set(wrapper.vm.mr, 'mergePipelinesEnabled', false); Vue.set(wrapper.vm.mr, 'sourceProjectId', 1); Vue.set(wrapper.vm.mr, 'targetProjectId', 2); - nextTick(done); + return nextTick(); }); it('should be false', () => { @@ -257,11 +257,11 @@ describe('MrWidgetOptions', () => { }); describe('when merge pipelines are enabled _and_ the source project and target project are different', () => { - beforeEach((done) => { + beforeEach(() => { Vue.set(wrapper.vm.mr, 'mergePipelinesEnabled', true); Vue.set(wrapper.vm.mr, 'sourceProjectId', 1); Vue.set(wrapper.vm.mr, 'targetProjectId', 2); - nextTick(done); + return nextTick(); }); it('should be true', () => { @@ -441,15 +441,10 @@ describe('MrWidgetOptions', () => { expect(setFaviconOverlay).toHaveBeenCalledWith(overlayDataUrl); }); - it('should not call setFavicon when there is no ciStatusFaviconPath', (done) => { + it('should not call setFavicon when there is no ciStatusFaviconPath', async () => { wrapper.vm.mr.ciStatusFaviconPath = null; - wrapper.vm - .setFaviconHelper() - .then(() => { - expect(faviconElement.getAttribute('href')).toEqual(null); - done(); - }) - .catch(done.fail); + await wrapper.vm.setFaviconHelper(); + expect(faviconElement.getAttribute('href')).toEqual(null); }); }); @@ -536,44 +531,36 @@ describe('MrWidgetOptions', () => { expect(wrapper.find('.close-related-link').exists()).toBe(true); }); - it('does not render if state is nothingToMerge', (done) => { + it('does not render if state is nothingToMerge', async () => { wrapper.vm.mr.state = stateKey.nothingToMerge; - nextTick(() => { - expect(wrapper.find('.close-related-link').exists()).toBe(false); - done(); - }); + await nextTick(); + expect(wrapper.find('.close-related-link').exists()).toBe(false); }); }); describe('rendering source branch removal status', () => { - it('renders when user cannot remove branch and branch should be removed', (done) => { + it('renders when user cannot remove branch and branch should be removed', async () => { wrapper.vm.mr.canRemoveSourceBranch = false; wrapper.vm.mr.shouldRemoveSourceBranch = true; wrapper.vm.mr.state = 'readyToMerge'; - nextTick(() => { - const tooltip = wrapper.find('[data-testid="question-o-icon"]'); - - expect(wrapper.text()).toContain('Deletes the source branch'); - expect(tooltip.attributes('title')).toBe( - 'A user with write access to the source branch selected this option', - ); + await nextTick(); + const tooltip = wrapper.find('[data-testid="question-o-icon"]'); - done(); - }); + expect(wrapper.text()).toContain('Deletes the source branch'); + expect(tooltip.attributes('title')).toBe( + 'A user with write access to the source branch selected this option', + ); }); - it('does not render in merged state', (done) => { + it('does not render in merged state', async () => { wrapper.vm.mr.canRemoveSourceBranch = false; wrapper.vm.mr.shouldRemoveSourceBranch = true; wrapper.vm.mr.state = 'merged'; - nextTick(() => { - expect(wrapper.text()).toContain('The source branch has been deleted'); - expect(wrapper.text()).not.toContain('Deletes the source branch'); - - done(); - }); + await nextTick(); + expect(wrapper.text()).toContain('The source branch has been deleted'); + expect(wrapper.text()).not.toContain('Deletes the source branch'); }); }); @@ -607,7 +594,7 @@ describe('MrWidgetOptions', () => { status: SUCCESS, }; - beforeEach((done) => { + beforeEach(() => { wrapper.vm.mr.deployments.push( { ...deploymentMockData, @@ -618,7 +605,7 @@ describe('MrWidgetOptions', () => { }, ); - nextTick(done); + return nextTick(); }); it('renders multiple deployments', () => { @@ -641,7 +628,7 @@ describe('MrWidgetOptions', () => { describe('pipeline for target branch after merge', () => { describe('with information for target branch pipeline', () => { - beforeEach((done) => { + beforeEach(() => { wrapper.vm.mr.state = 'merged'; wrapper.vm.mr.mergePipeline = { id: 127, @@ -749,7 +736,7 @@ describe('MrWidgetOptions', () => { }, cancel_path: '/root/ci-web-terminal/pipelines/127/cancel', }; - nextTick(done); + return nextTick(); }); it('renders pipeline block', () => { @@ -757,7 +744,7 @@ describe('MrWidgetOptions', () => { }); describe('with post merge deployments', () => { - beforeEach((done) => { + beforeEach(() => { wrapper.vm.mr.postMergeDeployments = [ { id: 15, @@ -789,7 +776,7 @@ describe('MrWidgetOptions', () => { }, ]; - nextTick(done); + return nextTick(); }); it('renders post deployment information', () => { @@ -799,10 +786,10 @@ describe('MrWidgetOptions', () => { }); describe('without information for target branch pipeline', () => { - beforeEach((done) => { + beforeEach(() => { wrapper.vm.mr.state = 'merged'; - nextTick(done); + return nextTick(); }); it('does not render pipeline block', () => { @@ -811,10 +798,10 @@ describe('MrWidgetOptions', () => { }); describe('when state is not merged', () => { - beforeEach((done) => { + beforeEach(() => { wrapper.vm.mr.state = 'archived'; - nextTick(done); + return nextTick(); }); it('does not render pipeline block', () => { diff --git a/spec/frontend/vue_mr_widget/stores/artifacts_list/actions_spec.js b/spec/frontend/vue_mr_widget/stores/artifacts_list/actions_spec.js index 9423fa17c44..22562bb4ddb 100644 --- a/spec/frontend/vue_mr_widget/stores/artifacts_list/actions_spec.js +++ b/spec/frontend/vue_mr_widget/stores/artifacts_list/actions_spec.js @@ -22,27 +22,25 @@ describe('Artifacts App Store Actions', () => { }); describe('setEndpoint', () => { - it('should commit SET_ENDPOINT mutation', (done) => { - testAction( + it('should commit SET_ENDPOINT mutation', () => { + return testAction( setEndpoint, 'endpoint.json', mockedState, [{ type: types.SET_ENDPOINT, payload: 'endpoint.json' }], [], - done, ); }); }); describe('requestArtifacts', () => { - it('should commit REQUEST_ARTIFACTS mutation', (done) => { - testAction( + it('should commit REQUEST_ARTIFACTS mutation', () => { + return testAction( requestArtifacts, null, mockedState, [{ type: types.REQUEST_ARTIFACTS }], [], - done, ); }); }); @@ -62,7 +60,7 @@ describe('Artifacts App Store Actions', () => { }); describe('success', () => { - it('dispatches requestArtifacts and receiveArtifactsSuccess ', (done) => { + it('dispatches requestArtifacts and receiveArtifactsSuccess ', () => { mock.onGet(`${TEST_HOST}/endpoint.json`).replyOnce(200, [ { text: 'result.txt', @@ -72,7 +70,7 @@ describe('Artifacts App Store Actions', () => { }, ]); - testAction( + return testAction( fetchArtifacts, null, mockedState, @@ -96,7 +94,6 @@ describe('Artifacts App Store Actions', () => { type: 'receiveArtifactsSuccess', }, ], - done, ); }); }); @@ -106,8 +103,8 @@ describe('Artifacts App Store Actions', () => { mock.onGet(`${TEST_HOST}/endpoint.json`).reply(500); }); - it('dispatches requestArtifacts and receiveArtifactsError ', (done) => { - testAction( + it('dispatches requestArtifacts and receiveArtifactsError ', () => { + return testAction( fetchArtifacts, null, mockedState, @@ -120,45 +117,41 @@ describe('Artifacts App Store Actions', () => { type: 'receiveArtifactsError', }, ], - done, ); }); }); }); describe('receiveArtifactsSuccess', () => { - it('should commit RECEIVE_ARTIFACTS_SUCCESS mutation with 200', (done) => { - testAction( + it('should commit RECEIVE_ARTIFACTS_SUCCESS mutation with 200', () => { + return testAction( receiveArtifactsSuccess, { data: { summary: {} }, status: 200 }, mockedState, [{ type: types.RECEIVE_ARTIFACTS_SUCCESS, payload: { summary: {} } }], [], - done, ); }); - it('should not commit RECEIVE_ARTIFACTS_SUCCESS mutation with 204', (done) => { - testAction( + it('should not commit RECEIVE_ARTIFACTS_SUCCESS mutation with 204', () => { + return testAction( receiveArtifactsSuccess, { data: { summary: {} }, status: 204 }, mockedState, [], [], - done, ); }); }); describe('receiveArtifactsError', () => { - it('should commit RECEIVE_ARTIFACTS_ERROR mutation', (done) => { - testAction( + it('should commit RECEIVE_ARTIFACTS_ERROR mutation', () => { + return testAction( receiveArtifactsError, null, mockedState, [{ type: types.RECEIVE_ARTIFACTS_ERROR }], [], - done, ); }); }); diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/actions_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/actions_spec.js index 2e4c056df61..2bc513e87bf 100644 --- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/actions_spec.js +++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/actions_spec.js @@ -21,87 +21,81 @@ describe('LabelsSelect Actions', () => { }); describe('setInitialState', () => { - it('sets initial store state', (done) => { - testAction( + it('sets initial store state', () => { + return testAction( actions.setInitialState, mockInitialState, state, [{ type: types.SET_INITIAL_STATE, payload: mockInitialState }], [], - done, ); }); }); describe('toggleDropdownButton', () => { - it('toggles dropdown button', (done) => { - testAction( + it('toggles dropdown button', () => { + return testAction( actions.toggleDropdownButton, {}, state, [{ type: types.TOGGLE_DROPDOWN_BUTTON }], [], - done, ); }); }); describe('toggleDropdownContents', () => { - it('toggles dropdown contents', (done) => { - testAction( + it('toggles dropdown contents', () => { + return testAction( actions.toggleDropdownContents, {}, state, [{ type: types.TOGGLE_DROPDOWN_CONTENTS }], [], - done, ); }); }); describe('toggleDropdownContentsCreateView', () => { - it('toggles dropdown create view', (done) => { - testAction( + it('toggles dropdown create view', () => { + return testAction( actions.toggleDropdownContentsCreateView, {}, state, [{ type: types.TOGGLE_DROPDOWN_CONTENTS_CREATE_VIEW }], [], - done, ); }); }); describe('requestLabels', () => { - it('sets value of `state.labelsFetchInProgress` to `true`', (done) => { - testAction(actions.requestLabels, {}, state, [{ type: types.REQUEST_LABELS }], [], done); + it('sets value of `state.labelsFetchInProgress` to `true`', () => { + return testAction(actions.requestLabels, {}, state, [{ type: types.REQUEST_LABELS }], []); }); }); describe('receiveLabelsSuccess', () => { - it('sets provided labels to `state.labels`', (done) => { + it('sets provided labels to `state.labels`', () => { const labels = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }]; - testAction( + return testAction( actions.receiveLabelsSuccess, labels, state, [{ type: types.RECEIVE_SET_LABELS_SUCCESS, payload: labels }], [], - done, ); }); }); describe('receiveLabelsFailure', () => { - it('sets value `state.labelsFetchInProgress` to `false`', (done) => { - testAction( + it('sets value `state.labelsFetchInProgress` to `false`', () => { + return testAction( actions.receiveLabelsFailure, {}, state, [{ type: types.RECEIVE_SET_LABELS_FAILURE }], [], - done, ); }); @@ -125,72 +119,67 @@ describe('LabelsSelect Actions', () => { }); describe('on success', () => { - it('dispatches `requestLabels` & `receiveLabelsSuccess` actions', (done) => { + it('dispatches `requestLabels` & `receiveLabelsSuccess` actions', () => { const labels = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }]; mock.onGet(/labels.json/).replyOnce(200, labels); - testAction( + return testAction( actions.fetchLabels, {}, state, [], [{ type: 'requestLabels' }, { type: 'receiveLabelsSuccess', payload: labels }], - done, ); }); }); describe('on failure', () => { - it('dispatches `requestLabels` & `receiveLabelsFailure` actions', (done) => { + it('dispatches `requestLabels` & `receiveLabelsFailure` actions', () => { mock.onGet(/labels.json/).replyOnce(500, {}); - testAction( + return testAction( actions.fetchLabels, {}, state, [], [{ type: 'requestLabels' }, { type: 'receiveLabelsFailure' }], - done, ); }); }); }); describe('requestCreateLabel', () => { - it('sets value `state.labelCreateInProgress` to `true`', (done) => { - testAction( + it('sets value `state.labelCreateInProgress` to `true`', () => { + return testAction( actions.requestCreateLabel, {}, state, [{ type: types.REQUEST_CREATE_LABEL }], [], - done, ); }); }); describe('receiveCreateLabelSuccess', () => { - it('sets value `state.labelCreateInProgress` to `false`', (done) => { - testAction( + it('sets value `state.labelCreateInProgress` to `false`', () => { + return testAction( actions.receiveCreateLabelSuccess, {}, state, [{ type: types.RECEIVE_CREATE_LABEL_SUCCESS }], [], - done, ); }); }); describe('receiveCreateLabelFailure', () => { - it('sets value `state.labelCreateInProgress` to `false`', (done) => { - testAction( + it('sets value `state.labelCreateInProgress` to `false`', () => { + return testAction( actions.receiveCreateLabelFailure, {}, state, [{ type: types.RECEIVE_CREATE_LABEL_FAILURE }], [], - done, ); }); @@ -214,11 +203,11 @@ describe('LabelsSelect Actions', () => { }); describe('on success', () => { - it('dispatches `requestCreateLabel`, `fetchLabels` & `receiveCreateLabelSuccess` & `toggleDropdownContentsCreateView` actions', (done) => { + it('dispatches `requestCreateLabel`, `fetchLabels` & `receiveCreateLabelSuccess` & `toggleDropdownContentsCreateView` actions', () => { const label = { id: 1 }; mock.onPost(/labels.json/).replyOnce(200, label); - testAction( + return testAction( actions.createLabel, {}, state, @@ -229,38 +218,35 @@ describe('LabelsSelect Actions', () => { { type: 'receiveCreateLabelSuccess' }, { type: 'toggleDropdownContentsCreateView' }, ], - done, ); }); }); describe('on failure', () => { - it('dispatches `requestCreateLabel` & `receiveCreateLabelFailure` actions', (done) => { + it('dispatches `requestCreateLabel` & `receiveCreateLabelFailure` actions', () => { mock.onPost(/labels.json/).replyOnce(500, {}); - testAction( + return testAction( actions.createLabel, {}, state, [], [{ type: 'requestCreateLabel' }, { type: 'receiveCreateLabelFailure' }], - done, ); }); }); }); describe('updateSelectedLabels', () => { - it('updates `state.labels` based on provided `labels` param', (done) => { + it('updates `state.labels` based on provided `labels` param', () => { const labels = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }]; - testAction( + return testAction( actions.updateSelectedLabels, labels, state, [{ type: types.UPDATE_SELECTED_LABELS, payload: { labels } }], [], - done, ); }); }); diff --git a/spec/frontend/vue_shared/security_reports/store/modules/sast/actions_spec.js b/spec/frontend/vue_shared/security_reports/store/modules/sast/actions_spec.js index 6af07273cf6..46bfd7eceb1 100644 --- a/spec/frontend/vue_shared/security_reports/store/modules/sast/actions_spec.js +++ b/spec/frontend/vue_shared/security_reports/store/modules/sast/actions_spec.js @@ -26,8 +26,8 @@ describe('sast report actions', () => { }); describe('setDiffEndpoint', () => { - it(`should commit ${types.SET_DIFF_ENDPOINT} with the correct path`, (done) => { - testAction( + it(`should commit ${types.SET_DIFF_ENDPOINT} with the correct path`, () => { + return testAction( actions.setDiffEndpoint, diffEndpoint, state, @@ -38,20 +38,19 @@ describe('sast report actions', () => { }, ], [], - done, ); }); }); describe('requestDiff', () => { - it(`should commit ${types.REQUEST_DIFF}`, (done) => { - testAction(actions.requestDiff, {}, state, [{ type: types.REQUEST_DIFF }], [], done); + it(`should commit ${types.REQUEST_DIFF}`, () => { + return testAction(actions.requestDiff, {}, state, [{ type: types.REQUEST_DIFF }], []); }); }); describe('receiveDiffSuccess', () => { - it(`should commit ${types.RECEIVE_DIFF_SUCCESS} with the correct response`, (done) => { - testAction( + it(`should commit ${types.RECEIVE_DIFF_SUCCESS} with the correct response`, () => { + return testAction( actions.receiveDiffSuccess, reports, state, @@ -62,14 +61,13 @@ describe('sast report actions', () => { }, ], [], - done, ); }); }); describe('receiveDiffError', () => { - it(`should commit ${types.RECEIVE_DIFF_ERROR} with the correct response`, (done) => { - testAction( + it(`should commit ${types.RECEIVE_DIFF_ERROR} with the correct response`, () => { + return testAction( actions.receiveDiffError, error, state, @@ -80,7 +78,6 @@ describe('sast report actions', () => { }, ], [], - done, ); }); }); @@ -107,9 +104,9 @@ describe('sast report actions', () => { .replyOnce(200, reports.enrichData); }); - it('should dispatch the `receiveDiffSuccess` action', (done) => { + it('should dispatch the `receiveDiffSuccess` action', () => { const { diff, enrichData } = reports; - testAction( + return testAction( actions.fetchDiff, {}, { ...rootState, ...state }, @@ -124,7 +121,6 @@ describe('sast report actions', () => { }, }, ], - done, ); }); }); @@ -135,10 +131,10 @@ describe('sast report actions', () => { mock.onGet(diffEndpoint).replyOnce(200, reports.diff); }); - it('should dispatch the `receiveDiffSuccess` action with empty enrich data', (done) => { + it('should dispatch the `receiveDiffSuccess` action with empty enrich data', () => { const { diff } = reports; const enrichData = []; - testAction( + return testAction( actions.fetchDiff, {}, { ...rootState, ...state }, @@ -153,7 +149,6 @@ describe('sast report actions', () => { }, }, ], - done, ); }); }); @@ -167,14 +162,13 @@ describe('sast report actions', () => { .replyOnce(404); }); - it('should dispatch the `receiveError` action', (done) => { - testAction( + it('should dispatch the `receiveError` action', () => { + return testAction( actions.fetchDiff, {}, { ...rootState, ...state }, [], [{ type: 'requestDiff' }, { type: 'receiveDiffError' }], - done, ); }); }); @@ -188,14 +182,13 @@ describe('sast report actions', () => { .replyOnce(200, reports.enrichData); }); - it('should dispatch the `receiveDiffError` action', (done) => { - testAction( + it('should dispatch the `receiveDiffError` action', () => { + return testAction( actions.fetchDiff, {}, { ...rootState, ...state }, [], [{ type: 'requestDiff' }, { type: 'receiveDiffError' }], - done, ); }); }); diff --git a/spec/frontend/vue_shared/security_reports/store/modules/secret_detection/actions_spec.js b/spec/frontend/vue_shared/security_reports/store/modules/secret_detection/actions_spec.js index d22fee864e7..4f4f653bb72 100644 --- a/spec/frontend/vue_shared/security_reports/store/modules/secret_detection/actions_spec.js +++ b/spec/frontend/vue_shared/security_reports/store/modules/secret_detection/actions_spec.js @@ -26,8 +26,8 @@ describe('secret detection report actions', () => { }); describe('setDiffEndpoint', () => { - it(`should commit ${types.SET_DIFF_ENDPOINT} with the correct path`, (done) => { - testAction( + it(`should commit ${types.SET_DIFF_ENDPOINT} with the correct path`, () => { + return testAction( actions.setDiffEndpoint, diffEndpoint, state, @@ -38,20 +38,19 @@ describe('secret detection report actions', () => { }, ], [], - done, ); }); }); describe('requestDiff', () => { - it(`should commit ${types.REQUEST_DIFF}`, (done) => { - testAction(actions.requestDiff, {}, state, [{ type: types.REQUEST_DIFF }], [], done); + it(`should commit ${types.REQUEST_DIFF}`, () => { + return testAction(actions.requestDiff, {}, state, [{ type: types.REQUEST_DIFF }], []); }); }); describe('receiveDiffSuccess', () => { - it(`should commit ${types.RECEIVE_DIFF_SUCCESS} with the correct response`, (done) => { - testAction( + it(`should commit ${types.RECEIVE_DIFF_SUCCESS} with the correct response`, () => { + return testAction( actions.receiveDiffSuccess, reports, state, @@ -62,14 +61,13 @@ describe('secret detection report actions', () => { }, ], [], - done, ); }); }); describe('receiveDiffError', () => { - it(`should commit ${types.RECEIVE_DIFF_ERROR} with the correct response`, (done) => { - testAction( + it(`should commit ${types.RECEIVE_DIFF_ERROR} with the correct response`, () => { + return testAction( actions.receiveDiffError, error, state, @@ -80,7 +78,6 @@ describe('secret detection report actions', () => { }, ], [], - done, ); }); }); @@ -107,9 +104,10 @@ describe('secret detection report actions', () => { .replyOnce(200, reports.enrichData); }); - it('should dispatch the `receiveDiffSuccess` action', (done) => { + it('should dispatch the `receiveDiffSuccess` action', () => { const { diff, enrichData } = reports; - testAction( + + return testAction( actions.fetchDiff, {}, { ...rootState, ...state }, @@ -124,7 +122,6 @@ describe('secret detection report actions', () => { }, }, ], - done, ); }); }); @@ -135,10 +132,10 @@ describe('secret detection report actions', () => { mock.onGet(diffEndpoint).replyOnce(200, reports.diff); }); - it('should dispatch the `receiveDiffSuccess` action with empty enrich data', (done) => { + it('should dispatch the `receiveDiffSuccess` action with empty enrich data', () => { const { diff } = reports; const enrichData = []; - testAction( + return testAction( actions.fetchDiff, {}, { ...rootState, ...state }, @@ -153,7 +150,6 @@ describe('secret detection report actions', () => { }, }, ], - done, ); }); }); @@ -167,14 +163,13 @@ describe('secret detection report actions', () => { .replyOnce(404); }); - it('should dispatch the `receiveDiffError` action', (done) => { - testAction( + it('should dispatch the `receiveDiffError` action', () => { + return testAction( actions.fetchDiff, {}, { ...rootState, ...state }, [], [{ type: 'requestDiff' }, { type: 'receiveDiffError' }], - done, ); }); }); @@ -188,14 +183,13 @@ describe('secret detection report actions', () => { .replyOnce(200, reports.enrichData); }); - it('should dispatch the `receiveDiffError` action', (done) => { - testAction( + it('should dispatch the `receiveDiffError` action', () => { + return testAction( actions.fetchDiff, {}, { ...rootState, ...state }, [], [{ type: 'requestDiff' }, { type: 'receiveDiffError' }], - done, ); }); }); diff --git a/spec/frontend/vuex_shared/modules/modal/actions_spec.js b/spec/frontend/vuex_shared/modules/modal/actions_spec.js index c151049df2d..928ed7d0d5f 100644 --- a/spec/frontend/vuex_shared/modules/modal/actions_spec.js +++ b/spec/frontend/vuex_shared/modules/modal/actions_spec.js @@ -4,28 +4,28 @@ import * as types from '~/vuex_shared/modules/modal/mutation_types'; describe('Vuex ModalModule actions', () => { describe('open', () => { - it('works', (done) => { + it('works', () => { const data = { id: 7 }; - testAction(actions.open, data, {}, [{ type: types.OPEN, payload: data }], [], done); + return testAction(actions.open, data, {}, [{ type: types.OPEN, payload: data }], []); }); }); describe('close', () => { - it('works', (done) => { - testAction(actions.close, null, {}, [{ type: types.CLOSE }], [], done); + it('works', () => { + return testAction(actions.close, null, {}, [{ type: types.CLOSE }], []); }); }); describe('show', () => { - it('works', (done) => { - testAction(actions.show, null, {}, [{ type: types.SHOW }], [], done); + it('works', () => { + return testAction(actions.show, null, {}, [{ type: types.SHOW }], []); }); }); describe('hide', () => { - it('works', (done) => { - testAction(actions.hide, null, {}, [{ type: types.HIDE }], [], done); + it('works', () => { + return testAction(actions.hide, null, {}, [{ type: types.HIDE }], []); }); }); }); diff --git a/spec/helpers/wiki_helper_spec.rb b/spec/helpers/wiki_helper_spec.rb index 0d04ca2b876..5adcbe3334d 100644 --- a/spec/helpers/wiki_helper_spec.rb +++ b/spec/helpers/wiki_helper_spec.rb @@ -145,4 +145,8 @@ RSpec.describe WikiHelper do expect(subject).to include('wiki-directory-nest-level' => 0) end end + + it_behaves_like 'wiki endpoint helpers' do + let_it_be(:page) { create(:wiki_page) } + end end diff --git a/spec/support/shared_examples/helpers/wiki_helpers_shared_examples.rb b/spec/support/shared_examples/helpers/wiki_helpers_shared_examples.rb new file mode 100644 index 00000000000..c2c27fb65ca --- /dev/null +++ b/spec/support/shared_examples/helpers/wiki_helpers_shared_examples.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'wiki endpoint helpers' do + let(:resource_path) { page.wiki.container.class.to_s.pluralize.downcase } + let(:url) { "/api/v4/#{resource_path}/#{page.wiki.container.id}/wikis/#{page.slug}?version=#{page.version.id}"} + + it 'returns the full endpoint url' do + expect(helper.wiki_page_render_api_endpoint(page)).to end_with(url) + end + + context 'when relative url is set' do + let(:relative_url) { "/gitlab#{url}" } + + it 'returns the full endpoint url with the relative path' do + stub_config_setting(relative_url_root: '/gitlab') + + expect(helper.wiki_page_render_api_endpoint(page)).to end_with(relative_url) + end + end +end |