diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-01-25 12:14:14 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-01-25 12:14:14 +0000 |
commit | 868c8c35fbddd439f4df76a5954e2a1caa2af3cc (patch) | |
tree | b7bad2964729ba58b6f84ecf36bc72f939a4c900 /spec | |
parent | d2bb55891e78ae23506bee26a30165f3520b47e5 (diff) | |
download | gitlab-ce-868c8c35fbddd439f4df76a5954e2a1caa2af3cc.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
230 files changed, 2089 insertions, 2405 deletions
diff --git a/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js b/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js index 12fc08c303c..acd80ed8db2 100644 --- a/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js +++ b/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js @@ -1,6 +1,7 @@ import { GlLoadingIcon, GlAlert } from '@gitlab/ui'; -import { mount, createLocalVue } from '@vue/test-utils'; +import { mount } from '@vue/test-utils'; import AxiosMockAdapter from 'axios-mock-adapter'; +import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createHttpIntegrationMutation from 'ee_else_ce/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql'; import updateHttpIntegrationMutation from 'ee_else_ce/alerts_settings/graphql/mutations/update_http_integration.mutation.graphql'; @@ -49,8 +50,6 @@ import mockIntegrations from './mocks/integrations.json'; jest.mock('~/flash'); -const localVue = createLocalVue(); - describe('AlertsSettingsWrapper', () => { let wrapper; let fakeApollo; @@ -111,7 +110,7 @@ describe('AlertsSettingsWrapper', () => { function createComponentWithApollo({ destroyHandler = jest.fn().mockResolvedValue(destroyIntegrationResponse), } = {}) { - localVue.use(VueApollo); + Vue.use(VueApollo); destroyIntegrationHandler = destroyHandler; const requestHandlers = [ @@ -122,7 +121,6 @@ describe('AlertsSettingsWrapper', () => { fakeApollo = createMockApollo(requestHandlers); wrapper = mount(AlertsSettingsWrapper, { - localVue, apolloProvider: fakeApollo, provide: { alertSettings: { diff --git a/spec/frontend/artifacts_settings/components/keep_latest_artifact_checkbox_spec.js b/spec/frontend/artifacts_settings/components/keep_latest_artifact_checkbox_spec.js index bfa8274f0eb..3ba0280deb3 100644 --- a/spec/frontend/artifacts_settings/components/keep_latest_artifact_checkbox_spec.js +++ b/spec/frontend/artifacts_settings/components/keep_latest_artifact_checkbox_spec.js @@ -1,5 +1,6 @@ import { GlFormCheckbox, GlLink } from '@gitlab/ui'; -import { shallowMount, createLocalVue } from '@vue/test-utils'; +import { shallowMount } from '@vue/test-utils'; +import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import UpdateKeepLatestArtifactProjectSetting from '~/artifacts_settings/graphql/mutations/update_keep_latest_artifact_project_setting.mutation.graphql'; @@ -7,8 +8,7 @@ import GetKeepLatestArtifactApplicationSetting from '~/artifacts_settings/graphq import GetKeepLatestArtifactProjectSetting from '~/artifacts_settings/graphql/queries/get_keep_latest_artifact_project_setting.query.graphql'; import KeepLatestArtifactCheckbox from '~/artifacts_settings/keep_latest_artifact_checkbox.vue'; -const localVue = createLocalVue(); -localVue.use(VueApollo); +Vue.use(VueApollo); const keepLatestArtifactProjectMock = { data: { @@ -73,7 +73,6 @@ describe('Keep latest artifact checkbox', () => { stubs: { GlFormCheckbox, }, - localVue, apolloProvider, }); }; diff --git a/spec/frontend/boards/board_list_helper.js b/spec/frontend/boards/board_list_helper.js index d0f14bd37c1..04192489817 100644 --- a/spec/frontend/boards/board_list_helper.js +++ b/spec/frontend/boards/board_list_helper.js @@ -1,4 +1,5 @@ -import { createLocalVue, shallowMount } from '@vue/test-utils'; +import { shallowMount } from '@vue/test-utils'; +import Vue from 'vue'; import VueApollo from 'vue-apollo'; import Vuex from 'vuex'; @@ -33,9 +34,8 @@ export default function createComponent({ }, issuesCount, } = {}) { - const localVue = createLocalVue(); - localVue.use(VueApollo); - localVue.use(Vuex); + Vue.use(VueApollo); + Vue.use(Vuex); const fakeApollo = createMockApollo([ [listQuery, jest.fn().mockResolvedValue(boardListQueryResponse(issuesCount))], @@ -85,7 +85,6 @@ export default function createComponent({ const component = shallowMount(BoardList, { apolloProvider: fakeApollo, - localVue, store, propsData: { disabled: false, diff --git a/spec/frontend/clusters_list/components/install_agent_modal_spec.js b/spec/frontend/clusters_list/components/install_agent_modal_spec.js index 5edc504aecb..6ad3d61cec7 100644 --- a/spec/frontend/clusters_list/components/install_agent_modal_spec.js +++ b/spec/frontend/clusters_list/components/install_agent_modal_spec.js @@ -1,5 +1,5 @@ import { GlAlert, GlButton, GlFormInputGroup, GlSprintf } from '@gitlab/ui'; -import { createLocalVue } from '@vue/test-utils'; +import Vue from 'vue'; import VueApollo from 'vue-apollo'; import { sprintf } from '~/locale'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; @@ -32,8 +32,7 @@ import { } from '../mocks/apollo'; import ModalStub from '../stubs'; -const localVue = createLocalVue(); -localVue.use(VueApollo); +Vue.use(VueApollo); const projectPath = 'path/to/project'; const kasAddress = 'kas.example.com'; @@ -95,7 +94,6 @@ describe('InstallAgentModal', () => { GlSprintf, GlModal: ModalStub, }, - localVue, apolloProvider, provide, propsData, diff --git a/spec/frontend/design_management/pages/index_spec.js b/spec/frontend/design_management/pages/index_spec.js index ce74569f219..5a2f3bdeef8 100644 --- a/spec/frontend/design_management/pages/index_spec.js +++ b/spec/frontend/design_management/pages/index_spec.js @@ -1,6 +1,7 @@ import { GlEmptyState } from '@gitlab/ui'; -import { createLocalVue, shallowMount } from '@vue/test-utils'; -import { nextTick } from 'vue'; +import { shallowMount } from '@vue/test-utils'; +import Vue, { nextTick } from 'vue'; + import VueApollo, { ApolloMutation } from 'vue-apollo'; import VueRouter from 'vue-router'; import VueDraggable from 'vuedraggable'; @@ -49,9 +50,8 @@ jest.spyOn(utils, 'getPageLayoutElement').mockReturnValue(mockPageEl); const scrollIntoViewMock = jest.fn(); HTMLElement.prototype.scrollIntoView = scrollIntoViewMock; -const localVue = createLocalVue(); const router = createRouter(); -localVue.use(VueRouter); +Vue.use(VueRouter); const mockDesigns = [ { @@ -159,7 +159,6 @@ describe('Design management index page', () => { }; }, mocks: { $apollo }, - localVue, router, stubs: { DesignDestroyer, ApolloMutation, VueDraggable, ...stubs }, attachTo: document.body, @@ -175,7 +174,7 @@ describe('Design management index page', () => { function createComponentWithApollo({ moveHandler = jest.fn().mockResolvedValue(moveDesignMutationResponse), }) { - localVue.use(VueApollo); + Vue.use(VueApollo); moveDesignHandler = moveHandler; const requestHandlers = [ @@ -186,7 +185,6 @@ describe('Design management index page', () => { fakeApollo = createMockApollo(requestHandlers); wrapper = shallowMount(Index, { - localVue, apolloProvider: fakeApollo, router, stubs: { VueDraggable }, diff --git a/spec/frontend/diffs/components/collapsed_files_warning_spec.js b/spec/frontend/diffs/components/collapsed_files_warning_spec.js index 050d32413ad..9726df55c6f 100644 --- a/spec/frontend/diffs/components/collapsed_files_warning_spec.js +++ b/spec/frontend/diffs/components/collapsed_files_warning_spec.js @@ -19,7 +19,7 @@ async function files(store, count) { const copies = Array(count).fill(file); store.state.diffs.diffFiles.push(...copies); - return nextTick(); + await nextTick(); } describe('CollapsedFilesWarning', () => { @@ -84,7 +84,7 @@ describe('CollapsedFilesWarning', () => { getAlertCloseButton().element.click(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.find('[data-testid="root"]').exists()).toBe(false); }); diff --git a/spec/frontend/diffs/components/compare_versions_spec.js b/spec/frontend/diffs/components/compare_versions_spec.js index 1ef927f5e9e..f11b60a9238 100644 --- a/spec/frontend/diffs/components/compare_versions_spec.js +++ b/spec/frontend/diffs/components/compare_versions_spec.js @@ -1,5 +1,5 @@ import { mount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import getDiffWithCommit from 'test_fixtures/merge_request_diffs/with_commit.json'; import setWindowLocation from 'helpers/set_window_location_helper'; @@ -232,14 +232,13 @@ describe('CompareVersions', () => { expect(link.element.getAttribute('href')).toEqual(PREV_COMMIT_URL); }); - it('triggers the correct Vuex action on click', () => { + it('triggers the correct Vuex action on click', async () => { const link = getPrevCommitNavElement(); link.trigger('click'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.vm.moveToNeighboringCommit).toHaveBeenCalledWith({ - direction: 'previous', - }); + await nextTick(); + expect(wrapper.vm.moveToNeighboringCommit).toHaveBeenCalledWith({ + direction: 'previous', }); }); @@ -267,13 +266,12 @@ describe('CompareVersions', () => { expect(link.element.getAttribute('href')).toEqual(NEXT_COMMIT_URL); }); - it('triggers the correct Vuex action on click', () => { + it('triggers the correct Vuex action on click', async () => { const link = getNextCommitNavElement(); link.trigger('click'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.vm.moveToNeighboringCommit).toHaveBeenCalledWith({ direction: 'next' }); - }); + await nextTick(); + expect(wrapper.vm.moveToNeighboringCommit).toHaveBeenCalledWith({ direction: 'next' }); }); it('renders a disabled button when there is no next commit', () => { diff --git a/spec/frontend/diffs/components/diff_file_header_spec.js b/spec/frontend/diffs/components/diff_file_header_spec.js index 1beaae6e16d..320fb395c3b 100644 --- a/spec/frontend/diffs/components/diff_file_header_spec.js +++ b/spec/frontend/diffs/components/diff_file_header_spec.js @@ -1,5 +1,5 @@ import { shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import { cloneDeep } from 'lodash'; import Vuex from 'vuex'; @@ -125,30 +125,27 @@ describe('DiffFileHeader component', () => { expect(findCollapseIcon().props('name')).toBe(icon); }); - it('when header is clicked emits toggleFile', () => { + it('when header is clicked emits toggleFile', async () => { createComponent(); findHeader().trigger('click'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted().toggleFile).toBeDefined(); - }); + await nextTick(); + expect(wrapper.emitted().toggleFile).toBeDefined(); }); - it('when collapseIcon is clicked emits toggleFile', () => { + it('when collapseIcon is clicked emits toggleFile', async () => { createComponent({ props: { collapsible: true } }); findCollapseIcon().vm.$emit('click', new Event('click')); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted().toggleFile).toBeDefined(); - }); + await nextTick(); + expect(wrapper.emitted().toggleFile).toBeDefined(); }); - it('when other element in header is clicked does not emits toggleFile', () => { + it('when other element in header is clicked does not emits toggleFile', async () => { createComponent({ props: { collapsible: true } }); findTitleLink().trigger('click'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted().toggleFile).not.toBeDefined(); - }); + await nextTick(); + expect(wrapper.emitted().toggleFile).not.toBeDefined(); }); describe('copy to clipboard', () => { diff --git a/spec/frontend/diffs/components/diff_file_spec.js b/spec/frontend/diffs/components/diff_file_spec.js index e185b817fca..a0aa4c784bf 100644 --- a/spec/frontend/diffs/components/diff_file_spec.js +++ b/spec/frontend/diffs/components/diff_file_spec.js @@ -160,7 +160,7 @@ describe('DiffFile', () => { last, })); - await wrapper.vm.$nextTick(); + await nextTick(); expect(eventHub.$emit).toHaveBeenCalledTimes(events.length); events.forEach((event) => { @@ -184,13 +184,13 @@ describe('DiffFile', () => { makeFileAutomaticallyCollapsed(store); - await wrapper.vm.$nextTick(); // Wait for store updates to flow into the component + await nextTick(); // Wait for store updates to flow into the component toggleFile(wrapper); - await wrapper.vm.$nextTick(); // Wait for the load to resolve - await wrapper.vm.$nextTick(); // Wait for the idleCallback - await wrapper.vm.$nextTick(); // Wait for nextTick inside postRender + await nextTick(); // Wait for the load to resolve + await nextTick(); // Wait for the idleCallback + await nextTick(); // Wait for nextTick inside postRender expect(eventHub.$emit).toHaveBeenCalledTimes(2); expect(eventHub.$emit).toHaveBeenCalledWith(EVT_PERF_MARK_FIRST_DIFF_FILE_SHOWN); @@ -214,7 +214,7 @@ describe('DiffFile', () => { markFileToBeRendered(store); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.find(DiffContentComponent).exists()).toBe(true); }); @@ -264,7 +264,7 @@ describe('DiffFile', () => { it('performs the normal file toggle when the file is collapsed', async () => { makeFileAutomaticallyCollapsed(store); - await wrapper.vm.$nextTick(); + await nextTick(); eventHub.$emit(EVT_EXPAND_ALL_FILES); @@ -274,7 +274,7 @@ describe('DiffFile', () => { it('does nothing when the file is not collapsed', async () => { eventHub.$emit(EVT_EXPAND_ALL_FILES); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.vm.handleToggle).not.toHaveBeenCalled(); }); @@ -286,7 +286,7 @@ describe('DiffFile', () => { }); it('should not have any content at all', async () => { - await wrapper.vm.$nextTick(); + await nextTick(); expect(findDiffContentArea(wrapper).element.children.length).toBe(0); }); @@ -392,7 +392,7 @@ describe('DiffFile', () => { readableText, }); - await wrapper.vm.$nextTick(); + await nextTick(); toggleFile(wrapper); }; @@ -440,7 +440,7 @@ describe('DiffFile', () => { makeFileAutomaticallyCollapsed(store); wrapper.vm.requestDiff(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findLoader(wrapper).exists()).toBe(true); }); @@ -451,7 +451,7 @@ describe('DiffFile', () => { ({ wrapper, store } = createComponent({ file: getUnreadableFile() })); makeFileAutomaticallyCollapsed(store); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findDiffContentArea(wrapper).html()).toContain( 'Files with large changes are collapsed by default.', @@ -470,7 +470,7 @@ describe('DiffFile', () => { markFileToBeRendered(store); changeViewerType(store, mode); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.classes('has-body')).toBe(true); expect(wrapper.find(DiffContentComponent).exists()).toBe(true); @@ -496,7 +496,7 @@ describe('DiffFile', () => { }, }); - await wrapper.vm.$nextTick(); + await nextTick(); const button = wrapper.find('[data-testid="blob-button"]'); @@ -521,7 +521,7 @@ describe('DiffFile', () => { ({ wrapper, store } = createComponent({ file, props: { viewDiffsFileByFile: true } })); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findLoader(wrapper).exists()).toBe(true); }); diff --git a/spec/frontend/diffs/components/diff_gutter_avatars_spec.js b/spec/frontend/diffs/components/diff_gutter_avatars_spec.js index 5884a9ebd3a..c18f0b721da 100644 --- a/spec/frontend/diffs/components/diff_gutter_avatars_spec.js +++ b/spec/frontend/diffs/components/diff_gutter_avatars_spec.js @@ -1,4 +1,5 @@ import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import DiffGutterAvatars from '~/diffs/components/diff_gutter_avatars.vue'; import discussionsMockData from '../mock_data/diff_discussions'; @@ -35,12 +36,11 @@ describe('DiffGutterAvatars', () => { expect(findCollapseButton().exists()).toBe(true); }); - it('should emit toggleDiscussions event on button click', () => { + it('should emit toggleDiscussions event on button click', async () => { findCollapseButton().trigger('click'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted().toggleLineDiscussions).toBeTruthy(); - }); + await nextTick(); + expect(wrapper.emitted().toggleLineDiscussions).toBeTruthy(); }); }); @@ -65,20 +65,18 @@ describe('DiffGutterAvatars', () => { expect(findMoreCount().text()).toBe('+2'); }); - it('should emit toggleDiscussions event on avatars click', () => { + it('should emit toggleDiscussions event on avatars click', async () => { findUserAvatars().at(0).trigger('click'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted().toggleLineDiscussions).toBeTruthy(); - }); + await nextTick(); + expect(wrapper.emitted().toggleLineDiscussions).toBeTruthy(); }); - it('should emit toggleDiscussions event on more count text click', () => { + it('should emit toggleDiscussions event on more count text click', async () => { findMoreCount().trigger('click'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted().toggleLineDiscussions).toBeTruthy(); - }); + await nextTick(); + expect(wrapper.emitted().toggleLineDiscussions).toBeTruthy(); }); }); diff --git a/spec/frontend/diffs/components/tree_list_spec.js b/spec/frontend/diffs/components/tree_list_spec.js index f03792295df..963805f4792 100644 --- a/spec/frontend/diffs/components/tree_list_spec.js +++ b/spec/frontend/diffs/components/tree_list_spec.js @@ -1,5 +1,5 @@ import { shallowMount, mount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import TreeList from '~/diffs/components/tree_list.vue'; import createStore from '~/diffs/store/modules'; @@ -91,12 +91,11 @@ describe('Diffs tree list component', () => { expect(getFileRows().at(1).html()).toContain('app'); }); - it('hides file stats', () => { + it('hides file stats', async () => { wrapper.setProps({ hideFileStats: true }); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.find('.file-row-stats').exists()).toBe(false); - }); + await nextTick(); + expect(wrapper.find('.file-row-stats').exists()).toBe(false); }); it('calls toggleTreeOpen when clicking folder', () => { @@ -117,20 +116,18 @@ describe('Diffs tree list component', () => { }); }); - it('renders as file list when renderTreeList is false', () => { + it('renders as file list when renderTreeList is false', async () => { wrapper.vm.$store.state.diffs.renderTreeList = false; - return wrapper.vm.$nextTick().then(() => { - expect(getFileRows()).toHaveLength(1); - }); + await nextTick(); + expect(getFileRows()).toHaveLength(1); }); - it('renders file paths when renderTreeList is false', () => { + it('renders file paths when renderTreeList is false', async () => { wrapper.vm.$store.state.diffs.renderTreeList = false; - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.find('.file-row').html()).toContain('index.js'); - }); + await nextTick(); + expect(wrapper.find('.file-row').html()).toContain('index.js'); }); }); @@ -142,14 +139,13 @@ describe('Diffs tree list component', () => { store.state.diffs.viewedDiffFileIds = viewedDiffFileIds; }); - it('passes the viewedDiffFileIds to the FileTree', () => { + it('passes the viewedDiffFileIds to the FileTree', async () => { createComponent(shallowMount); - return wrapper.vm.$nextTick().then(() => { - // Have to use $attrs['viewed-files'] because we are passing down an object - // and attributes('') stringifies values (e.g. [object])... - expect(wrapper.find(FileTree).vm.$attrs['viewed-files']).toBe(viewedDiffFileIds); - }); + await nextTick(); + // Have to use $attrs['viewed-files'] because we are passing down an object + // and attributes('') stringifies values (e.g. [object])... + expect(wrapper.find(FileTree).vm.$attrs['viewed-files']).toBe(viewedDiffFileIds); }); }); }); diff --git a/spec/frontend/environments/canary_update_modal_spec.js b/spec/frontend/environments/canary_update_modal_spec.js index c7129ee1320..22d13558a84 100644 --- a/spec/frontend/environments/canary_update_modal_spec.js +++ b/spec/frontend/environments/canary_update_modal_spec.js @@ -1,5 +1,6 @@ import { GlAlert, GlModal } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import waitForPromises from 'helpers/wait_for_promises'; import CanaryUpdateModal from '~/environments/components/canary_update_modal.vue'; import updateCanaryIngress from '~/environments/graphql/mutations/update_canary_ingress.mutation.graphql'; @@ -86,7 +87,7 @@ describe('/environments/components/canary_update_modal.vue', () => { mutate.mockResolvedValue({ data: { environmentsCanaryIngressUpdate: { errors: [] } } }); modal.vm.$emit('primary'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findAlert().exists()).toBe(false); }); @@ -95,7 +96,7 @@ describe('/environments/components/canary_update_modal.vue', () => { mutate.mockResolvedValue({ data: { environmentsCanaryIngressUpdate: { errors: ['error'] } } }); modal.vm.$emit('primary'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findAlert().text()).toBe('error'); }); @@ -105,7 +106,7 @@ describe('/environments/components/canary_update_modal.vue', () => { modal.vm.$emit('primary'); await waitForPromises(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findAlert().text()).toBe('Something went wrong. Please try again later'); }); @@ -114,12 +115,12 @@ describe('/environments/components/canary_update_modal.vue', () => { mutate.mockResolvedValue({ data: { environmentsCanaryIngressUpdate: { errors: ['error'] } } }); modal.vm.$emit('primary'); - await wrapper.vm.$nextTick(); + await nextTick(); const alert = findAlert(); alert.vm.$emit('dismiss'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(alert.exists()).toBe(false); }); diff --git a/spec/frontend/environments/deploy_board_component_spec.js b/spec/frontend/environments/deploy_board_component_spec.js index 24e94867afd..2033cf00cff 100644 --- a/spec/frontend/environments/deploy_board_component_spec.js +++ b/spec/frontend/environments/deploy_board_component_spec.js @@ -1,6 +1,6 @@ import { GlTooltip, GlIcon, GlLoadingIcon } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import CanaryIngress from '~/environments/components/canary_ingress.vue'; import DeployBoard from '~/environments/components/deploy_board.vue'; import { deployBoardMockData, environment } from './mock_data'; @@ -24,7 +24,7 @@ describe('Deploy Board', () => { describe('with valid data', () => { beforeEach((done) => { wrapper = createComponent(); - wrapper.vm.$nextTick(done); + nextTick(done); }); it('should render percentage with completion value provided', () => { @@ -79,7 +79,7 @@ describe('Deploy Board', () => { isEmpty: true, logsPath, }); - wrapper.vm.$nextTick(done); + nextTick(done); }); it('should render the empty state', () => { @@ -98,7 +98,7 @@ describe('Deploy Board', () => { isEmpty: false, logsPath, }); - wrapper.vm.$nextTick(done); + nextTick(done); }); it('should render loading spinner', () => { @@ -116,7 +116,7 @@ describe('Deploy Board', () => { deployBoardData: deployBoardMockData, }); ({ statuses } = wrapper.vm); - wrapper.vm.$nextTick(done); + nextTick(done); }); it('with all the possible statuses', () => { diff --git a/spec/frontend/environments/environment_actions_spec.js b/spec/frontend/environments/environment_actions_spec.js index 1b68a692db8..336c207428e 100644 --- a/spec/frontend/environments/environment_actions_spec.js +++ b/spec/frontend/environments/environment_actions_spec.js @@ -1,6 +1,6 @@ import { GlDropdown, GlDropdownItem, GlLoadingIcon, GlIcon } from '@gitlab/ui'; import { shallowMount, mount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; import { TEST_HOST } from 'helpers/test_constants'; import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; @@ -108,7 +108,7 @@ describe('EnvironmentActions Component', () => { jest.spyOn(window, 'confirm').mockImplementation(() => confirm); findDropdownItem(scheduledJobAction).vm.$emit('click'); - await wrapper.vm.$nextTick(); + await nextTick(); }; beforeEach(() => { diff --git a/spec/frontend/environments/environment_table_spec.js b/spec/frontend/environments/environment_table_spec.js index 1851163ac68..c7582e4b06d 100644 --- a/spec/frontend/environments/environment_table_spec.js +++ b/spec/frontend/environments/environment_table_spec.js @@ -1,4 +1,5 @@ import { mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import CanaryUpdateModal from '~/environments/components/canary_update_modal.vue'; import DeployBoard from '~/environments/components/deploy_board.vue'; import EnvironmentTable from '~/environments/components/environments_table.vue'; @@ -181,7 +182,7 @@ describe('Environment table', () => { }); wrapper.find(DeployBoard).vm.$emit('changeCanaryWeight', 40); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.find(CanaryUpdateModal).props()).toMatchObject({ weight: 40, diff --git a/spec/frontend/environments/environments_app_spec.js b/spec/frontend/environments/environments_app_spec.js index cd05ecbfb53..92d1820681c 100644 --- a/spec/frontend/environments/environments_app_spec.js +++ b/spec/frontend/environments/environments_app_spec.js @@ -1,6 +1,7 @@ import { GlTabs } from '@gitlab/ui'; import { mount, shallowMount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; +import { nextTick } from 'vue'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import Container from '~/environments/components/container.vue'; import DeployBoard from '~/environments/components/deploy_board.vue'; @@ -186,14 +187,13 @@ describe('Environment', () => { expect(wrapper.find('.folder-icon[data-testid="chevron-right-icon"]').exists()).toBe(false); }); - it('should close an opened folder', () => { + it('should close an opened folder', async () => { expect(wrapper.find('.folder-icon[data-testid="chevron-down-icon"]').exists()).toBe(true); // close folder wrapper.find('.folder-name').trigger('click'); - wrapper.vm.$nextTick(() => { - expect(wrapper.find('.folder-icon[data-testid="chevron-down-icon"]').exists()).toBe(false); - }); + await nextTick(); + expect(wrapper.find('.folder-icon[data-testid="chevron-down-icon"]').exists()).toBe(false); }); it('should show children environments', () => { diff --git a/spec/frontend/error_tracking/components/error_details_spec.js b/spec/frontend/error_tracking/components/error_details_spec.js index 02baa31289e..493a96c207b 100644 --- a/spec/frontend/error_tracking/components/error_details_spec.js +++ b/spec/frontend/error_tracking/components/error_details_spec.js @@ -8,7 +8,7 @@ import { GlSprintf, } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import { severityLevel, @@ -139,32 +139,30 @@ describe('ErrorDetails', () => { mountComponent(); }); - it('when before timeout, still shows loading', () => { + it('when before timeout, still shows loading', async () => { Date.now.mockReturnValue(endTime - 1); wrapper.vm.onNoApolloResult(); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.find(GlLoadingIcon).exists()).toBe(true); - expect(createFlash).not.toHaveBeenCalled(); - expect(mocks.$apollo.queries.error.stopPolling).not.toHaveBeenCalled(); - }); + await nextTick(); + expect(wrapper.find(GlLoadingIcon).exists()).toBe(true); + expect(createFlash).not.toHaveBeenCalled(); + expect(mocks.$apollo.queries.error.stopPolling).not.toHaveBeenCalled(); }); - it('when timeout is hit and no apollo result, stops loading and shows flash', () => { + it('when timeout is hit and no apollo result, stops loading and shows flash', async () => { Date.now.mockReturnValue(endTime + 1); wrapper.vm.onNoApolloResult(); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.find(GlLoadingIcon).exists()).toBe(false); - expect(wrapper.find(GlLink).exists()).toBe(false); - expect(createFlash).toHaveBeenCalledWith({ - message: 'Could not connect to Sentry. Refresh the page to try again.', - type: 'warning', - }); - expect(mocks.$apollo.queries.error.stopPolling).toHaveBeenCalled(); + await nextTick(); + expect(wrapper.find(GlLoadingIcon).exists()).toBe(false); + expect(wrapper.find(GlLink).exists()).toBe(false); + expect(createFlash).toHaveBeenCalledWith({ + message: 'Could not connect to Sentry. Refresh the page to try again.', + type: 'warning', }); + expect(mocks.$apollo.queries.error.stopPolling).toHaveBeenCalled(); }); }); @@ -224,7 +222,7 @@ describe('ErrorDetails', () => { }); describe('Badges', () => { - it('should show language and error level badges', () => { + it('should show language and error level badges', async () => { // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax wrapper.setData({ @@ -232,12 +230,11 @@ describe('ErrorDetails', () => { tags: { level: 'error', logger: 'ruby' }, }, }); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.findAll(GlBadge).length).toBe(2); - }); + await nextTick(); + expect(wrapper.findAll(GlBadge).length).toBe(2); }); - it('should NOT show the badge if the tag is not present', () => { + it('should NOT show the badge if the tag is not present', async () => { // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax wrapper.setData({ @@ -245,14 +242,13 @@ describe('ErrorDetails', () => { tags: { level: 'error' }, }, }); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.findAll(GlBadge).length).toBe(1); - }); + await nextTick(); + expect(wrapper.findAll(GlBadge).length).toBe(1); }); it.each(Object.keys(severityLevel))( 'should set correct severity level variant for %s badge', - (level) => { + async (level) => { // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax wrapper.setData({ @@ -260,15 +256,14 @@ describe('ErrorDetails', () => { tags: { level: severityLevel[level] }, }, }); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.find(GlBadge).props('variant')).toEqual( - severityLevelVariant[severityLevel[level]], - ); - }); + await nextTick(); + expect(wrapper.find(GlBadge).props('variant')).toEqual( + severityLevelVariant[severityLevel[level]], + ); }, ); - it('should fallback for ERROR severityLevelVariant when severityLevel is unknown', () => { + it('should fallback for ERROR severityLevelVariant when severityLevel is unknown', async () => { // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax wrapper.setData({ @@ -276,32 +271,29 @@ describe('ErrorDetails', () => { tags: { level: 'someNewErrorLevel' }, }, }); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.find(GlBadge).props('variant')).toEqual( - severityLevelVariant[severityLevel.ERROR], - ); - }); + await nextTick(); + expect(wrapper.find(GlBadge).props('variant')).toEqual( + severityLevelVariant[severityLevel.ERROR], + ); }); }); describe('Stacktrace', () => { - it('should show stacktrace', () => { + it('should show stacktrace', async () => { store.state.details.loadingStacktrace = false; - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.find(GlLoadingIcon).exists()).toBe(false); - expect(wrapper.find(Stacktrace).exists()).toBe(true); - expect(findAlert().exists()).toBe(false); - }); + await nextTick(); + expect(wrapper.find(GlLoadingIcon).exists()).toBe(false); + expect(wrapper.find(Stacktrace).exists()).toBe(true); + expect(findAlert().exists()).toBe(false); }); - it('should NOT show stacktrace if no entries and show Alert message', () => { + it('should NOT show stacktrace if no entries and show Alert message', async () => { store.state.details.loadingStacktrace = false; store.getters = { 'details/sentryUrl': () => 'sentry.io', 'details/stacktrace': () => [] }; - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.find(GlLoadingIcon).exists()).toBe(false); - expect(wrapper.find(Stacktrace).exists()).toBe(false); - expect(findAlert().text()).toBe('No stack trace for this error'); - }); + await nextTick(); + expect(wrapper.find(GlLoadingIcon).exists()).toBe(false); + expect(wrapper.find(Stacktrace).exists()).toBe(false); + expect(findAlert().text()).toBe('No stack trace for this error'); }); }); @@ -338,10 +330,10 @@ describe('ErrorDetails', () => { }); describe('when error is unresolved', () => { - beforeEach(() => { + beforeEach(async () => { store.state.details.errorStatus = errorStatus.UNRESOLVED; - return wrapper.vm.$nextTick(); + await nextTick(); }); it('displays Ignore and Resolve buttons', () => { @@ -365,10 +357,10 @@ describe('ErrorDetails', () => { }); describe('when error is ignored', () => { - beforeEach(() => { + beforeEach(async () => { store.state.details.errorStatus = errorStatus.IGNORED; - return wrapper.vm.$nextTick(); + await nextTick(); }); it('displays Undo Ignore and Resolve buttons', () => { @@ -392,10 +384,10 @@ describe('ErrorDetails', () => { }); describe('when error is resolved', () => { - beforeEach(() => { + beforeEach(async () => { store.state.details.errorStatus = errorStatus.RESOLVED; - return wrapper.vm.$nextTick(); + await nextTick(); }); it('displays Ignore and Unresolve buttons', () => { @@ -417,7 +409,7 @@ describe('ErrorDetails', () => { ); }); - it('should show alert with closed issueId', () => { + it('should show alert with closed issueId', async () => { const closedIssueId = 123; // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax @@ -426,10 +418,9 @@ describe('ErrorDetails', () => { closedIssueId, }); - return wrapper.vm.$nextTick().then(() => { - expect(findAlert().exists()).toBe(true); - expect(findAlert().text()).toContain(`#${closedIssueId}`); - }); + await nextTick(); + expect(findAlert().exists()).toBe(true); + expect(findAlert().text()).toContain(`#${closedIssueId}`); }); }); }); @@ -495,7 +486,7 @@ describe('ErrorDetails', () => { '/gitlab-org/gitlab-test/commit/7975be0116940bf2ad4321f79d02a55c5f7779aa'; const findGitLabCommitLink = () => wrapper.find(`[href$="${gitlabCommitPath}"]`); - it('should display a link', () => { + it('should display a link', async () => { mocks.$apollo.queries.error.loading = false; // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax @@ -505,12 +496,11 @@ describe('ErrorDetails', () => { gitlabCommitPath, }, }); - return wrapper.vm.$nextTick().then(() => { - expect(findGitLabCommitLink().exists()).toBe(true); - }); + await nextTick(); + expect(findGitLabCommitLink().exists()).toBe(true); }); - it('should not display a link', () => { + it('should not display a link', async () => { mocks.$apollo.queries.error.loading = false; // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax @@ -519,9 +509,8 @@ describe('ErrorDetails', () => { gitlabCommit: null, }, }); - return wrapper.vm.$nextTick().then(() => { - expect(findGitLabCommitLink().exists()).toBe(false); - }); + await nextTick(); + expect(findGitLabCommitLink().exists()).toBe(false); }); }); diff --git a/spec/frontend/error_tracking/components/error_tracking_actions_spec.js b/spec/frontend/error_tracking/components/error_tracking_actions_spec.js index e21c40423c3..7ed4e5f6b05 100644 --- a/spec/frontend/error_tracking/components/error_tracking_actions_spec.js +++ b/spec/frontend/error_tracking/components/error_tracking_actions_spec.js @@ -1,5 +1,6 @@ import { GlButton } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import ErrorTrackingActions from '~/error_tracking/components/error_tracking_actions.vue'; describe('Error Tracking Actions', () => { @@ -37,13 +38,12 @@ describe('Error Tracking Actions', () => { const findButtons = () => wrapper.findAll(GlButton); describe('when error status is unresolved', () => { - it('renders the correct actions buttons to allow ignore and resolve', () => { + it('renders the correct actions buttons to allow ignore and resolve', async () => { expect(findButtons().exists()).toBe(true); - return wrapper.vm.$nextTick().then(() => { - expect(findButtons().at(0).attributes('title')).toBe('Ignore'); - expect(findButtons().at(1).attributes('title')).toBe('Resolve'); - }); + await nextTick(); + expect(findButtons().at(0).attributes('title')).toBe('Ignore'); + expect(findButtons().at(1).attributes('title')).toBe('Resolve'); }); }); @@ -52,12 +52,11 @@ describe('Error Tracking Actions', () => { mountComponent({ error: { status: 'ignored' } }); }); - it('renders the correct action button to undo ignore', () => { + it('renders the correct action button to undo ignore', async () => { expect(findButtons().exists()).toBe(true); - return wrapper.vm.$nextTick().then(() => { - expect(findButtons().at(0).attributes('title')).toBe('Undo Ignore'); - }); + await nextTick(); + expect(findButtons().at(0).attributes('title')).toBe('Undo Ignore'); }); }); @@ -66,12 +65,11 @@ describe('Error Tracking Actions', () => { mountComponent({ error: { status: 'resolved' } }); }); - it('renders the correct action button to undo unresolve', () => { + it('renders the correct action button to undo unresolve', async () => { expect(findButtons().exists()).toBe(true); - return wrapper.vm.$nextTick().then(() => { - expect(findButtons().at(1).attributes('title')).toBe('Unresolve'); - }); + await nextTick(); + expect(findButtons().at(1).attributes('title')).toBe('Unresolve'); }); }); }); diff --git a/spec/frontend/error_tracking/components/error_tracking_list_spec.js b/spec/frontend/error_tracking/components/error_tracking_list_spec.js index fc89e778127..d4d145b5840 100644 --- a/spec/frontend/error_tracking/components/error_tracking_list_spec.js +++ b/spec/frontend/error_tracking/components/error_tracking_list_spec.js @@ -1,6 +1,6 @@ import { GlEmptyState, GlLoadingIcon, GlFormInput, GlPagination, GlDropdown } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import stubChildren from 'helpers/stub_children'; import ErrorTrackingActions from '~/error_tracking/components/error_tracking_actions.vue'; @@ -316,15 +316,14 @@ describe('ErrorTrackingList', () => { expect(findRecentSearchesDropdown().text()).toContain("You don't have any recent searches"); }); - it('shows items', () => { + it('shows items', async () => { store.state.list.recentSearches = ['great', 'search']; - return wrapper.vm.$nextTick().then(() => { - const dropdownItems = wrapper.findAll('.filtered-search-box li'); - expect(dropdownItems.length).toBe(3); - expect(dropdownItems.at(0).text()).toBe('great'); - expect(dropdownItems.at(1).text()).toBe('search'); - }); + await nextTick(); + const dropdownItems = wrapper.findAll('.filtered-search-box li'); + expect(dropdownItems.length).toBe(3); + expect(dropdownItems.at(0).text()).toBe('great'); + expect(dropdownItems.at(1).text()).toBe('search'); }); describe('clear', () => { @@ -336,23 +335,21 @@ describe('ErrorTrackingList', () => { expect(clearRecentButton().exists()).toBe(false); }); - it('is visible when list has items', () => { + it('is visible when list has items', async () => { store.state.list.recentSearches = ['some', 'searches']; - return wrapper.vm.$nextTick().then(() => { - expect(clearRecentButton().exists()).toBe(true); - expect(clearRecentButton().text()).toBe('Clear recent searches'); - }); + await nextTick(); + expect(clearRecentButton().exists()).toBe(true); + expect(clearRecentButton().text()).toBe('Clear recent searches'); }); - it('clears items on click', () => { + it('clears items on click', async () => { store.state.list.recentSearches = ['some', 'searches']; - return wrapper.vm.$nextTick().then(() => { - clearRecentButton().vm.$emit('click'); + await nextTick(); + clearRecentButton().vm.$emit('click'); - expect(actions.clearRecentSearches).toHaveBeenCalledTimes(1); - }); + expect(actions.clearRecentSearches).toHaveBeenCalledTimes(1); }); }); }); @@ -387,7 +384,7 @@ describe('ErrorTrackingList', () => { describe('and the user is not on the first page', () => { describe('and the previous button is clicked', () => { - beforeEach(() => { + beforeEach(async () => { store.state.list.loading = false; mountComponent({ stubs: { @@ -398,7 +395,7 @@ describe('ErrorTrackingList', () => { // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax wrapper.setData({ pageValue: 2 }); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('fetches the previous page of results', () => { diff --git a/spec/frontend/error_tracking_settings/components/app_spec.js b/spec/frontend/error_tracking_settings/components/app_spec.js index a67e927910e..4d19ec047ef 100644 --- a/spec/frontend/error_tracking_settings/components/app_spec.js +++ b/spec/frontend/error_tracking_settings/components/app_spec.js @@ -79,12 +79,11 @@ describe('error tracking settings app', () => { expect(wrapper.find('.js-error-tracking-button').attributes('disabled')).toBeFalsy(); }); - it('disables the button when saving', () => { + it('disables the button when saving', async () => { store.state.settingsLoading = true; - return wrapper.vm.$nextTick(() => { - expect(wrapper.find('.js-error-tracking-button').attributes('disabled')).toBeTruthy(); - }); + await nextTick(); + expect(wrapper.find('.js-error-tracking-button').attributes('disabled')).toBeTruthy(); }); }); diff --git a/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js b/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js index bf33d76d834..1ba5a505f57 100644 --- a/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js +++ b/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js @@ -1,6 +1,6 @@ import { GlDropdown, GlDropdownItem } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import { pick, clone } from 'lodash'; import Vuex from 'vuex'; import ProjectDropdown from '~/error_tracking_settings/components/project_dropdown.vue'; @@ -63,10 +63,10 @@ describe('error tracking settings project dropdown', () => { }); describe('populated project list', () => { - beforeEach(() => { + beforeEach(async () => { wrapper.setProps({ projects: clone(projectList), hasProjects: true }); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('renders the dropdown', () => { @@ -83,9 +83,9 @@ describe('error tracking settings project dropdown', () => { describe('selected project', () => { const selectedProject = clone(projectList[0]); - beforeEach(() => { + beforeEach(async () => { wrapper.setProps({ projects: clone(projectList), selectedProject, hasProjects: true }); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('does not show helper text', () => { @@ -95,13 +95,13 @@ describe('error tracking settings project dropdown', () => { }); describe('invalid project selected', () => { - beforeEach(() => { + beforeEach(async () => { wrapper.setProps({ projects: clone(projectList), selectedProject: staleProject, isProjectInvalid: true, }); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('displays a error', () => { diff --git a/spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js b/spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js index f244da228b3..4a0242b4a46 100644 --- a/spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js +++ b/spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js @@ -1,5 +1,6 @@ import { GlModal, GlSprintf, GlAlert } from '@gitlab/ui'; +import { nextTick } from 'vue'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import Component from '~/feature_flags/components/configure_feature_flags_modal.vue'; @@ -56,7 +57,7 @@ describe('Configure Feature Flags Modal', () => { it('should emit a `token` event when clicking on the Primary action', async () => { findGlModal().vm.$emit('secondary', mockEvent); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.emitted('token')).toEqual([[]]); expect(mockEvent.preventDefault).toHaveBeenCalled(); }); @@ -64,7 +65,7 @@ describe('Configure Feature Flags Modal', () => { it('should clear the project name input after generating the token', async () => { findProjectNameInput().vm.$emit('input', provide.projectName); findGlModal().vm.$emit('primary', mockEvent); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findProjectNameInput().attributes('value')).toBe(''); }); @@ -116,7 +117,7 @@ describe('Configure Feature Flags Modal', () => { it('should enable the secondary action', async () => { findProjectNameInput().vm.$emit('input', provide.projectName); - await wrapper.vm.$nextTick(); + await nextTick(); const [{ disabled }] = findSecondaryAction().attributes; expect(disabled).toBe(false); }); diff --git a/spec/frontend/feature_flags/components/edit_feature_flag_spec.js b/spec/frontend/feature_flags/components/edit_feature_flag_spec.js index 721b7249abc..05709cd05e6 100644 --- a/spec/frontend/feature_flags/components/edit_feature_flag_spec.js +++ b/spec/frontend/feature_flags/components/edit_feature_flag_spec.js @@ -1,7 +1,7 @@ import { GlToggle, GlAlert } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import { mockTracking } from 'helpers/tracking_helper'; import waitForPromises from 'helpers/wait_for_promises'; @@ -12,6 +12,7 @@ import createStore from '~/feature_flags/store/edit'; import axios from '~/lib/utils/axios_utils'; Vue.use(Vuex); + describe('Edit feature flag form', () => { let wrapper; let mock; @@ -66,13 +67,12 @@ describe('Edit feature flag form', () => { }); describe('with error', () => { - it('should render the error', () => { + it('should render the error', async () => { store.dispatch('receiveUpdateFeatureFlagError', { message: ['The name is required'] }); - return wrapper.vm.$nextTick(() => { - const warningGlAlert = findWarningGlAlert(); - expect(warningGlAlert.exists()).toEqual(true); - expect(warningGlAlert.text()).toContain('The name is required'); - }); + await nextTick(); + const warningGlAlert = findWarningGlAlert(); + expect(warningGlAlert.exists()).toEqual(true); + expect(warningGlAlert.text()).toContain('The name is required'); }); }); diff --git a/spec/frontend/feature_flags/components/empty_state_spec.js b/spec/frontend/feature_flags/components/empty_state_spec.js index 86d0c1a05fd..4ac82ae44a6 100644 --- a/spec/frontend/feature_flags/components/empty_state_spec.js +++ b/spec/frontend/feature_flags/components/empty_state_spec.js @@ -1,5 +1,6 @@ import { GlAlert, GlEmptyState, GlLink, GlLoadingIcon } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import EmptyState from '~/feature_flags/components/empty_state.vue'; const DEFAULT_PROPS = { @@ -123,7 +124,7 @@ describe('feature_flags/components/feature_flags_tab.vue', () => { beforeEach(async () => { wrapper = factory(); - await wrapper.vm.$nextTick(); + await nextTick(); slot = wrapper.find('[data-testid="test-slot"]'); }); diff --git a/spec/frontend/feature_flags/components/environments_dropdown_spec.js b/spec/frontend/feature_flags/components/environments_dropdown_spec.js index 9194db3a182..cca472012e9 100644 --- a/spec/frontend/feature_flags/components/environments_dropdown_spec.js +++ b/spec/frontend/feature_flags/components/environments_dropdown_spec.js @@ -1,6 +1,7 @@ import { GlLoadingIcon, GlButton, GlSearchBoxByType } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; +import { nextTick } from 'vue'; import waitForPromises from 'helpers/wait_for_promises'; import { TEST_HOST } from 'spec/test_constants'; import EnvironmentsDropdown from '~/feature_flags/components/environments_dropdown.vue'; @@ -54,7 +55,7 @@ describe('Feature flags > Environments dropdown ', () => { factory(); findEnvironmentSearchInput().vm.$emit('focus'); await waitForPromises(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.find('.dropdown-content > ul').exists()).toBe(true); expect(wrapper.findAll('.dropdown-content > ul > li').exists()).toBe(true); }); @@ -66,7 +67,7 @@ describe('Feature flags > Environments dropdown ', () => { factory(); findEnvironmentSearchInput().vm.$emit('keyup'); await waitForPromises(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.find('.dropdown-content > ul').exists()).toBe(true); expect(wrapper.findAll('.dropdown-content > ul > li').exists()).toBe(true); }); @@ -80,7 +81,7 @@ describe('Feature flags > Environments dropdown ', () => { findEnvironmentSearchInput().vm.$emit('focus'); findEnvironmentSearchInput().vm.$emit('input', 'production'); await waitForPromises(); - await wrapper.vm.$nextTick(); + await nextTick(); }); it('sets filter value', () => { @@ -103,7 +104,7 @@ describe('Feature flags > Environments dropdown ', () => { .filter((b) => b.text() === 'production') .at(0); button.vm.$emit('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.emitted('selectEnvironment')).toEqual([['production']]); }); }); @@ -111,7 +112,7 @@ describe('Feature flags > Environments dropdown ', () => { describe('on click clear button', () => { beforeEach(async () => { wrapper.find(GlButton).vm.$emit('click'); - await wrapper.vm.$nextTick(); + await nextTick(); }); it('resets filter value', () => { @@ -132,12 +133,12 @@ describe('Feature flags > Environments dropdown ', () => { findEnvironmentSearchInput().vm.$emit('focus'); findEnvironmentSearchInput().vm.$emit('input', 'production'); await waitForPromises(); - await wrapper.vm.$nextTick(); + await nextTick(); }); it('emits create event', async () => { wrapper.findAll(GlButton).at(0).vm.$emit('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.emitted('createClicked')).toEqual([['production']]); }); }); diff --git a/spec/frontend/feature_flags/components/feature_flags_spec.js b/spec/frontend/feature_flags/components/feature_flags_spec.js index 141db7c0eb3..728c6abb23a 100644 --- a/spec/frontend/feature_flags/components/feature_flags_spec.js +++ b/spec/frontend/feature_flags/components/feature_flags_spec.js @@ -1,6 +1,6 @@ import { GlAlert, GlEmptyState, GlLoadingIcon } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import MockAdapter from 'axios-mock-adapter'; import Vuex from 'vuex'; import waitForPromises from 'helpers/wait_for_promises'; @@ -172,7 +172,7 @@ describe('Feature flags', () => { factory(); await waitForPromises(); - await wrapper.vm.$nextTick(); + await nextTick(); emptyState = wrapper.findComponent(GlEmptyState); }); diff --git a/spec/frontend/feature_flags/components/feature_flags_table_spec.js b/spec/frontend/feature_flags/components/feature_flags_table_spec.js index d06d60ae310..99864a95f59 100644 --- a/spec/frontend/feature_flags/components/feature_flags_table_spec.js +++ b/spec/frontend/feature_flags/components/feature_flags_table_spec.js @@ -1,5 +1,6 @@ import { GlToggle, GlBadge } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import { trimText } from 'helpers/text_helper'; import { mockTracking } from 'helpers/tracking_helper'; import FeatureFlagsTable from '~/feature_flags/components/feature_flags_table.vue'; @@ -148,13 +149,12 @@ describe('Feature flag table', () => { }); }); - it('should trigger a toggle event', () => { + it('should trigger a toggle event', async () => { toggle.vm.$emit('change'); const flag = { ...props.featureFlags[0], active: !props.featureFlags[0].active }; - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted('toggle-flag')).toEqual([[flag]]); - }); + await nextTick(); + expect(wrapper.emitted('toggle-flag')).toEqual([[flag]]); }); it('tracks a click', () => { diff --git a/spec/frontend/feature_flags/components/form_spec.js b/spec/frontend/feature_flags/components/form_spec.js index c0f9638390a..3ad1225906b 100644 --- a/spec/frontend/feature_flags/components/form_spec.js +++ b/spec/frontend/feature_flags/components/form_spec.js @@ -1,5 +1,6 @@ import { GlButton } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import Api from '~/api'; import Form from '~/feature_flags/components/form.vue'; @@ -126,28 +127,26 @@ describe('feature flag form', () => { expect(wrapper.findAll(Strategy)).toHaveLength(2); }); - it('adds an all users strategy when clicking the Add button', () => { + it('adds an all users strategy when clicking the Add button', async () => { wrapper.find(GlButton).vm.$emit('click'); - return wrapper.vm.$nextTick().then(() => { - const strategies = wrapper.findAll(Strategy); + await nextTick(); + const strategies = wrapper.findAll(Strategy); - expect(strategies).toHaveLength(3); - expect(strategies.at(2).props('strategy')).toEqual(allUsersStrategy); - }); + expect(strategies).toHaveLength(3); + expect(strategies.at(2).props('strategy')).toEqual(allUsersStrategy); }); - it('should remove a strategy on delete', () => { + it('should remove a strategy on delete', async () => { const strategy = { type: ROLLOUT_STRATEGY_PERCENT_ROLLOUT, parameters: { percentage: '30' }, scopes: [], }; wrapper.find(Strategy).vm.$emit('delete'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.findAll(Strategy)).toHaveLength(1); - expect(wrapper.find(Strategy).props('strategy')).not.toEqual(strategy); - }); + await nextTick(); + expect(wrapper.findAll(Strategy)).toHaveLength(1); + expect(wrapper.find(Strategy).props('strategy')).not.toEqual(strategy); }); }); }); diff --git a/spec/frontend/feature_flags/components/new_environments_dropdown_spec.js b/spec/frontend/feature_flags/components/new_environments_dropdown_spec.js index 6342ac0bda7..63fa5d19982 100644 --- a/spec/frontend/feature_flags/components/new_environments_dropdown_spec.js +++ b/spec/frontend/feature_flags/components/new_environments_dropdown_spec.js @@ -1,6 +1,7 @@ import { GlLoadingIcon, GlSearchBoxByType, GlDropdownItem } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; +import { nextTick } from 'vue'; import NewEnvironmentsDropdown from '~/feature_flags/components/new_environments_dropdown.vue'; import axios from '~/lib/utils/axios_utils'; import httpStatusCodes from '~/lib/utils/http_status'; @@ -47,16 +48,13 @@ describe('New Environments Dropdown', () => { describe('with empty results', () => { let item; - beforeEach(() => { + beforeEach(async () => { axiosMock.onGet(TEST_HOST).reply(200, []); wrapper.find(GlSearchBoxByType).vm.$emit('focus'); wrapper.find(GlSearchBoxByType).vm.$emit('input', TEST_SEARCH); - return axios - .waitForAll() - .then(() => wrapper.vm.$nextTick()) - .then(() => { - item = wrapper.find(GlDropdownItem); - }); + await axios.waitForAll(); + await nextTick(); + item = wrapper.find(GlDropdownItem); }); it('should display a Create item label', () => { diff --git a/spec/frontend/feature_flags/components/new_feature_flag_spec.js b/spec/frontend/feature_flags/components/new_feature_flag_spec.js index f14c674353b..9c1657bc0d2 100644 --- a/spec/frontend/feature_flags/components/new_feature_flag_spec.js +++ b/spec/frontend/feature_flags/components/new_feature_flag_spec.js @@ -1,6 +1,6 @@ import { GlAlert } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import { TEST_HOST } from 'spec/test_constants'; import Form from '~/feature_flags/components/form.vue'; @@ -51,13 +51,12 @@ describe('New feature flag form', () => { }); describe('with error', () => { - it('should render the error', () => { + it('should render the error', async () => { store.dispatch('receiveCreateFeatureFlagError', { message: ['The name is required'] }); - return wrapper.vm.$nextTick(() => { - const warningGlAlert = findWarningGlAlert(); - expect(warningGlAlert.at(0).exists()).toBe(true); - expect(warningGlAlert.at(0).text()).toContain('The name is required'); - }); + await nextTick(); + const warningGlAlert = findWarningGlAlert(); + expect(warningGlAlert.at(0).exists()).toBe(true); + expect(warningGlAlert.at(0).text()).toContain('The name is required'); }); }); diff --git a/spec/frontend/feature_flags/components/strategies/flexible_rollout_spec.js b/spec/frontend/feature_flags/components/strategies/flexible_rollout_spec.js index 07aa456e69e..56b14d80ab3 100644 --- a/spec/frontend/feature_flags/components/strategies/flexible_rollout_spec.js +++ b/spec/frontend/feature_flags/components/strategies/flexible_rollout_spec.js @@ -1,5 +1,6 @@ import { GlFormInput, GlFormSelect } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import FlexibleRollout from '~/feature_flags/components/strategies/flexible_rollout.vue'; import ParameterFormGroup from '~/feature_flags/components/strategies/parameter_form_group.vue'; import { PERCENT_ROLLOUT_GROUP_ID } from '~/feature_flags/constants'; @@ -51,7 +52,7 @@ describe('feature_flags/components/strategies/flexible_rollout.vue', () => { it('emits a change when the percentage value changes', async () => { percentageInput.setValue('75'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.emitted('change')).toEqual([ [ { diff --git a/spec/frontend/feature_flags/components/strategies/gitlab_user_list_spec.js b/spec/frontend/feature_flags/components/strategies/gitlab_user_list_spec.js index ebfcba6316b..3b69194494f 100644 --- a/spec/frontend/feature_flags/components/strategies/gitlab_user_list_spec.js +++ b/spec/frontend/feature_flags/components/strategies/gitlab_user_list_spec.js @@ -1,6 +1,6 @@ import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlLoadingIcon } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import Api from '~/api'; import GitlabUserList from '~/feature_flags/components/strategies/gitlab_user_list.vue'; @@ -71,7 +71,7 @@ describe('~/feature_flags/components/strategies/gitlab_user_list.vue', () => { ); const searchWrapper = wrapper.find(GlSearchBoxByType); searchWrapper.vm.$emit('input', 'new'); - await wrapper.vm.$nextTick(); + await nextTick(); const loadingIcon = wrapper.find(GlLoadingIcon); expect(loadingIcon.exists()).toBe(true); @@ -79,7 +79,7 @@ describe('~/feature_flags/components/strategies/gitlab_user_list.vue', () => { r({ data: [userList] }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(loadingIcon.exists()).toBe(false); }); diff --git a/spec/frontend/feature_flags/components/strategies/percent_rollout_spec.js b/spec/frontend/feature_flags/components/strategies/percent_rollout_spec.js index 442f7faf161..180697e93e4 100644 --- a/spec/frontend/feature_flags/components/strategies/percent_rollout_spec.js +++ b/spec/frontend/feature_flags/components/strategies/percent_rollout_spec.js @@ -1,5 +1,6 @@ import { GlFormInput } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import ParameterFormGroup from '~/feature_flags/components/strategies/parameter_form_group.vue'; import PercentRollout from '~/feature_flags/components/strategies/percent_rollout.vue'; import { PERCENT_ROLLOUT_GROUP_ID } from '~/feature_flags/constants'; @@ -39,7 +40,7 @@ describe('~/feature_flags/components/strategies/percent_rollout.vue', () => { it('emits a change when the value changes', async () => { input.setValue('75'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.emitted('change')).toEqual([ [{ parameters: { percentage: '75', groupId: PERCENT_ROLLOUT_GROUP_ID } }], ]); diff --git a/spec/frontend/feature_flags/components/strategy_spec.js b/spec/frontend/feature_flags/components/strategy_spec.js index 2464583b636..aee3873721c 100644 --- a/spec/frontend/feature_flags/components/strategy_spec.js +++ b/spec/frontend/feature_flags/components/strategy_spec.js @@ -1,6 +1,6 @@ import { GlAlert, GlFormSelect, GlLink, GlToken, GlButton } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import { last } from 'lodash'; import Vuex from 'vuex'; import Api from '~/api'; @@ -85,11 +85,11 @@ describe('Feature flags strategy', () => { let propsData; let strategy; - beforeEach(() => { + beforeEach(async () => { strategy = { name, parameters: {}, scopes: [] }; propsData = { strategy, index: 0 }; factory({ propsData, provide }); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('should set the select to match the strategy name', () => { @@ -138,19 +138,18 @@ describe('Feature flags strategy', () => { factory({ propsData, provide }); }); - it('should revert to all-environments scope when last scope is removed', () => { + it('should revert to all-environments scope when last scope is removed', async () => { const token = wrapper.find(GlToken); token.vm.$emit('close'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.findAll(GlToken)).toHaveLength(0); - expect(last(wrapper.emitted('change'))).toEqual([ - { - name: ROLLOUT_STRATEGY_PERCENT_ROLLOUT, - parameters: { percentage: '50', groupId: PERCENT_ROLLOUT_GROUP_ID }, - scopes: [{ environmentScope: '*' }], - }, - ]); - }); + await nextTick(); + expect(wrapper.findAll(GlToken)).toHaveLength(0); + expect(last(wrapper.emitted('change'))).toEqual([ + { + name: ROLLOUT_STRATEGY_PERCENT_ROLLOUT, + parameters: { percentage: '50', groupId: PERCENT_ROLLOUT_GROUP_ID }, + scopes: [{ environmentScope: '*' }], + }, + ]); }); }); @@ -167,56 +166,52 @@ describe('Feature flags strategy', () => { factory({ propsData, provide }); }); - it('should change the parameters if a different strategy is chosen', () => { + it('should change the parameters if a different strategy is chosen', async () => { const select = wrapper.find(GlFormSelect); select.setValue(ROLLOUT_STRATEGY_ALL_USERS); - return wrapper.vm.$nextTick().then(() => { - expect(last(wrapper.emitted('change'))).toEqual([ - { - name: ROLLOUT_STRATEGY_ALL_USERS, - parameters: {}, - scopes: [{ environmentScope: '*' }], - }, - ]); - }); + await nextTick(); + expect(last(wrapper.emitted('change'))).toEqual([ + { + name: ROLLOUT_STRATEGY_ALL_USERS, + parameters: {}, + scopes: [{ environmentScope: '*' }], + }, + ]); }); - it('should display selected scopes', () => { + it('should display selected scopes', async () => { const dropdown = wrapper.find(NewEnvironmentsDropdown); dropdown.vm.$emit('add', 'production'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.findAll(GlToken)).toHaveLength(1); - expect(wrapper.find(GlToken).text()).toBe('production'); - }); + await nextTick(); + expect(wrapper.findAll(GlToken)).toHaveLength(1); + expect(wrapper.find(GlToken).text()).toBe('production'); }); - it('should display all selected scopes', () => { + it('should display all selected scopes', async () => { const dropdown = wrapper.find(NewEnvironmentsDropdown); dropdown.vm.$emit('add', 'production'); dropdown.vm.$emit('add', 'staging'); - return wrapper.vm.$nextTick().then(() => { - const tokens = wrapper.findAll(GlToken); - expect(tokens).toHaveLength(2); - expect(tokens.at(0).text()).toBe('production'); - expect(tokens.at(1).text()).toBe('staging'); - }); + await nextTick(); + const tokens = wrapper.findAll(GlToken); + expect(tokens).toHaveLength(2); + expect(tokens.at(0).text()).toBe('production'); + expect(tokens.at(1).text()).toBe('staging'); }); - it('should emit selected scopes', () => { + it('should emit selected scopes', async () => { const dropdown = wrapper.find(NewEnvironmentsDropdown); dropdown.vm.$emit('add', 'production'); - return wrapper.vm.$nextTick().then(() => { - expect(last(wrapper.emitted('change'))).toEqual([ - { - name: ROLLOUT_STRATEGY_PERCENT_ROLLOUT, - parameters: { percentage: '50', groupId: PERCENT_ROLLOUT_GROUP_ID }, - scopes: [ - { environmentScope: '*', shouldBeDestroyed: true }, - { environmentScope: 'production' }, - ], - }, - ]); - }); + await nextTick(); + expect(last(wrapper.emitted('change'))).toEqual([ + { + name: ROLLOUT_STRATEGY_PERCENT_ROLLOUT, + parameters: { percentage: '50', groupId: PERCENT_ROLLOUT_GROUP_ID }, + scopes: [ + { environmentScope: '*', shouldBeDestroyed: true }, + { environmentScope: 'production' }, + ], + }, + ]); }); it('should emit a delete if the delete button is clicked', () => { @@ -236,39 +231,36 @@ describe('Feature flags strategy', () => { factory({ propsData, provide }); }); - it('should display selected scopes', () => { + it('should display selected scopes', async () => { const dropdown = wrapper.find(NewEnvironmentsDropdown); dropdown.vm.$emit('add', 'production'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.findAll(GlToken)).toHaveLength(1); - expect(wrapper.find(GlToken).text()).toBe('production'); - }); + await nextTick(); + expect(wrapper.findAll(GlToken)).toHaveLength(1); + expect(wrapper.find(GlToken).text()).toBe('production'); }); - it('should display all selected scopes', () => { + it('should display all selected scopes', async () => { const dropdown = wrapper.find(NewEnvironmentsDropdown); dropdown.vm.$emit('add', 'production'); dropdown.vm.$emit('add', 'staging'); - return wrapper.vm.$nextTick().then(() => { - const tokens = wrapper.findAll(GlToken); - expect(tokens).toHaveLength(2); - expect(tokens.at(0).text()).toBe('production'); - expect(tokens.at(1).text()).toBe('staging'); - }); + await nextTick(); + const tokens = wrapper.findAll(GlToken); + expect(tokens).toHaveLength(2); + expect(tokens.at(0).text()).toBe('production'); + expect(tokens.at(1).text()).toBe('staging'); }); - it('should emit selected scopes', () => { + it('should emit selected scopes', async () => { const dropdown = wrapper.find(NewEnvironmentsDropdown); dropdown.vm.$emit('add', 'production'); - return wrapper.vm.$nextTick().then(() => { - expect(last(wrapper.emitted('change'))).toEqual([ - { - name: ROLLOUT_STRATEGY_PERCENT_ROLLOUT, - parameters: { percentage: '50', groupId: PERCENT_ROLLOUT_GROUP_ID }, - scopes: [{ environmentScope: 'production' }], - }, - ]); - }); + await nextTick(); + expect(last(wrapper.emitted('change'))).toEqual([ + { + name: ROLLOUT_STRATEGY_PERCENT_ROLLOUT, + parameters: { percentage: '50', groupId: PERCENT_ROLLOUT_GROUP_ID }, + scopes: [{ environmentScope: 'production' }], + }, + ]); }); }); }); diff --git a/spec/frontend/feature_highlight/feature_highlight_popover_spec.js b/spec/frontend/feature_highlight/feature_highlight_popover_spec.js index e5e3974e103..650f9eb1bbc 100644 --- a/spec/frontend/feature_highlight/feature_highlight_popover_spec.js +++ b/spec/frontend/feature_highlight/feature_highlight_popover_spec.js @@ -1,5 +1,6 @@ import { GlPopover, GlLink, GlButton } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import { POPOVER_TARGET_ID } from '~/feature_highlight/constants'; import { dismiss } from '~/feature_highlight/feature_highlight_helper'; import FeatureHighlightPopover from '~/feature_highlight/feature_highlight_popover.vue'; @@ -71,7 +72,7 @@ describe('feature_highlight/feature_highlight_popover', () => { it('hides the popover target', async () => { await findDismissButton().trigger('click'); findPopover().vm.$emit('hidden'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findPopoverTarget().exists()).toBe(false); }); diff --git a/spec/frontend/frequent_items/components/app_spec.js b/spec/frontend/frequent_items/components/app_spec.js index a94cb3e2fcc..ba989bf53ab 100644 --- a/spec/frontend/frequent_items/components/app_spec.js +++ b/spec/frontend/frequent_items/components/app_spec.js @@ -1,5 +1,5 @@ import MockAdapter from 'axios-mock-adapter'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import { useLocalStorageSpy } from 'helpers/local_storage_helper'; import { mountExtended } from 'helpers/vue_test_utils_helper'; @@ -97,7 +97,7 @@ describe('Frequent Items App Component', () => { triggerDropdownOpen(); store.state[TEST_VUEX_MODULE].isLoadingItems = true; - await wrapper.vm.$nextTick(); + await nextTick(); const loading = findLoading(); @@ -119,7 +119,7 @@ describe('Frequent Items App Component', () => { expect(findFrequentItems().length).toBe(1); triggerDropdownOpen(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findFrequentItems().length).toBe(expectedResult.length); expect(findFrequentItemsList().props()).toEqual({ @@ -135,7 +135,7 @@ describe('Frequent Items App Component', () => { mock.onGet(/\/api\/v4\/projects.json(.*)$/).replyOnce(200, mockSearchedProjects.data); setSearch('gitlab'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findLoading().exists()).toBe(true); diff --git a/spec/frontend/frequent_items/components/frequent_items_list_spec.js b/spec/frontend/frequent_items/components/frequent_items_list_spec.js index 5d09a588b1d..beaab1913d0 100644 --- a/spec/frontend/frequent_items/components/frequent_items_list_spec.js +++ b/spec/frontend/frequent_items/components/frequent_items_list_spec.js @@ -1,5 +1,5 @@ import { mount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import frequentItemsListComponent from '~/frequent_items/components/frequent_items_list.vue'; import frequentItemsListItemComponent from '~/frequent_items/components/frequent_items_list_item.vue'; @@ -44,7 +44,7 @@ describe('FrequentItemsListComponent', () => { wrapper.setProps({ items: mockFrequentProjects, }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.vm.isListEmpty).toBe(false); }); @@ -63,7 +63,7 @@ describe('FrequentItemsListComponent', () => { wrapper.setProps({ isFetchFailed: false, }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.vm.listEmptyMessage).toBe('Projects you visit often will appear here'); }); @@ -81,7 +81,7 @@ describe('FrequentItemsListComponent', () => { wrapper.setProps({ isFetchFailed: false, }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.vm.listEmptyMessage).toBe('Sorry, no projects matched your search'); }); @@ -89,25 +89,23 @@ describe('FrequentItemsListComponent', () => { }); describe('template', () => { - it('should render component element with list of projects', () => { + it('should render component element with list of projects', async () => { createComponent(); - return wrapper.vm.$nextTick(() => { - expect(wrapper.classes('frequent-items-list-container')).toBe(true); - expect(wrapper.findAll({ ref: 'frequentItemsList' })).toHaveLength(1); - expect(wrapper.findAll(frequentItemsListItemComponent)).toHaveLength(5); - }); + await nextTick(); + expect(wrapper.classes('frequent-items-list-container')).toBe(true); + expect(wrapper.findAll({ ref: 'frequentItemsList' })).toHaveLength(1); + expect(wrapper.findAll(frequentItemsListItemComponent)).toHaveLength(5); }); - it('should render component element with empty message', () => { + it('should render component element with empty message', async () => { createComponent({ items: [], }); - return wrapper.vm.$nextTick(() => { - expect(wrapper.vm.$el.querySelectorAll('li.section-empty')).toHaveLength(1); - expect(wrapper.findAll(frequentItemsListItemComponent)).toHaveLength(0); - }); + await nextTick(); + expect(wrapper.vm.$el.querySelectorAll('li.section-empty')).toHaveLength(1); + expect(wrapper.findAll(frequentItemsListItemComponent)).toHaveLength(0); }); }); }); diff --git a/spec/frontend/frequent_items/components/frequent_items_search_input_spec.js b/spec/frontend/frequent_items/components/frequent_items_search_input_spec.js index e1e2a42d330..d0a4cf70f5f 100644 --- a/spec/frontend/frequent_items/components/frequent_items_search_input_spec.js +++ b/spec/frontend/frequent_items/components/frequent_items_search_input_spec.js @@ -1,6 +1,6 @@ import { GlSearchBoxByType } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import { mockTracking, unmockTracking } from 'helpers/tracking_helper'; import searchComponent from '~/frequent_items/components/frequent_items_search_input.vue'; @@ -61,7 +61,7 @@ describe('FrequentItemsSearchInputComponent', () => { findSearchBoxByType().vm.$emit('input', value); - await wrapper.vm.$nextTick(); + await nextTick(); expect(trackingSpy).toHaveBeenCalledWith(undefined, 'type_search_query', { label: 'projects_dropdown_frequent_items_search_input', diff --git a/spec/frontend/grafana_integration/components/grafana_integration_spec.js b/spec/frontend/grafana_integration/components/grafana_integration_spec.js index d5338430054..d2111194097 100644 --- a/spec/frontend/grafana_integration/components/grafana_integration_spec.js +++ b/spec/frontend/grafana_integration/components/grafana_integration_spec.js @@ -1,5 +1,6 @@ import { GlButton } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import { TEST_HOST } from 'helpers/test_constants'; import { mountExtended } from 'helpers/vue_test_utils_helper'; import createFlash from '~/flash'; @@ -93,29 +94,28 @@ describe('grafana integration component', () => { }, ]; - it('submits form on click', () => { + it('submits form on click', async () => { axios.patch.mockResolvedValue(); findSubmitButton(wrapper).trigger('click'); expect(axios.patch).toHaveBeenCalledWith(...endpointRequest); - return wrapper.vm.$nextTick().then(() => expect(refreshCurrentPage).toHaveBeenCalled()); + await nextTick(); + expect(refreshCurrentPage).toHaveBeenCalled(); }); - it('creates flash banner on error', () => { + it('creates flash banner on error', async () => { const message = 'mockErrorMessage'; axios.patch.mockRejectedValue({ response: { data: { message } } }); findSubmitButton().trigger('click'); expect(axios.patch).toHaveBeenCalledWith(...endpointRequest); - return wrapper.vm - .$nextTick() - .then(jest.runAllTicks) - .then(() => - expect(createFlash).toHaveBeenCalledWith({ - message: `There was an error saving your changes. ${message}`, - }), - ); + + await nextTick(); + await jest.runAllTicks(); + expect(createFlash).toHaveBeenCalledWith({ + message: `There was an error saving your changes. ${message}`, + }); }); }); }); diff --git a/spec/frontend/group_settings/components/shared_runners_form_spec.js b/spec/frontend/group_settings/components/shared_runners_form_spec.js index 617d91178e4..26e9cd39cfd 100644 --- a/spec/frontend/group_settings/components/shared_runners_form_spec.js +++ b/spec/frontend/group_settings/components/shared_runners_form_spec.js @@ -1,6 +1,7 @@ import { GlLoadingIcon, GlAlert } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import MockAxiosAdapter from 'axios-mock-adapter'; +import { nextTick } from 'vue'; import waitForPromises from 'helpers/wait_for_promises'; import SharedRunnersForm from '~/group_settings/components/shared_runners_form.vue'; import axios from '~/lib/utils/axios_utils'; @@ -76,7 +77,7 @@ describe('group_settings/components/shared_runners_form', () => { findEnabledToggle().vm.$emit('change', true); - await wrapper.vm.$nextTick(); + await nextTick(); expect(isLoadingIconVisible()).toBe(true); diff --git a/spec/frontend/groups/components/invite_members_banner_spec.js b/spec/frontend/groups/components/invite_members_banner_spec.js index c81edad499c..ef784018205 100644 --- a/spec/frontend/groups/components/invite_members_banner_spec.js +++ b/spec/frontend/groups/components/invite_members_banner_spec.js @@ -1,6 +1,7 @@ import { GlBanner } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; +import { nextTick } from 'vue'; import { mockTracking, unmockTracking } from 'helpers/tracking_helper'; import InviteMembersBanner from '~/groups/components/invite_members_banner.vue'; import eventHub from '~/invite_members/event_hub'; @@ -140,7 +141,7 @@ describe('InviteMembersBanner', () => { expect(wrapper.find(GlBanner).exists()).toBe(true); wrapper.find(GlBanner).vm.$emit('close'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.find(GlBanner).exists()).toBe(false); }); }); diff --git a/spec/frontend/header_search/components/app_spec.js b/spec/frontend/header_search/components/app_spec.js index 3200c6614f1..dcbeeeffb2d 100644 --- a/spec/frontend/header_search/components/app_spec.js +++ b/spec/frontend/header_search/components/app_spec.js @@ -1,5 +1,5 @@ import { GlSearchBoxByType } from '@gitlab/ui'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import HeaderSearchApp from '~/header_search/components/app.vue'; @@ -202,7 +202,7 @@ describe('HeaderSearchApp', () => { expect(findHeaderSearchDropdown().exists()).toBe(false); findHeaderSearchInput().vm.$emit('focus'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findHeaderSearchDropdown().exists()).toBe(true); }); @@ -211,7 +211,7 @@ describe('HeaderSearchApp', () => { expect(findHeaderSearchDropdown().exists()).toBe(false); findHeaderSearchInput().vm.$emit('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findHeaderSearchDropdown().exists()).toBe(true); }); @@ -265,7 +265,7 @@ describe('HeaderSearchApp', () => { expect(findHeaderSearchDropdown().exists()).toBe(true); findDropdownKeyboardNavigation().vm.$emit('tab'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findHeaderSearchDropdown().exists()).toBe(false); }); @@ -284,7 +284,7 @@ describe('HeaderSearchApp', () => { it(`when currentFocusIndex changes to ${MOCK_INDEX} updates the data to searchOptions[${MOCK_INDEX}]`, async () => { findDropdownKeyboardNavigation().vm.$emit('change', MOCK_INDEX); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.vm.currentFocusedOption).toBe(MOCK_DEFAULT_SEARCH_OPTIONS[MOCK_INDEX]); }); }); @@ -299,7 +299,7 @@ describe('HeaderSearchApp', () => { it('onKey-enter submits a search', async () => { findHeaderSearchInput().vm.$emit('keydown', new KeyboardEvent({ key: ENTER_KEY })); - await wrapper.vm.$nextTick(); + await nextTick(); expect(visitUrl).toHaveBeenCalledWith(MOCK_SEARCH_QUERY); }); @@ -316,7 +316,7 @@ describe('HeaderSearchApp', () => { it('onKey-enter clicks the selected dropdown item rather than submitting a search', async () => { findDropdownKeyboardNavigation().vm.$emit('change', MOCK_INDEX); - await wrapper.vm.$nextTick(); + await nextTick(); findHeaderSearchInput().vm.$emit('keydown', new KeyboardEvent({ key: ENTER_KEY })); expect(visitUrl).toHaveBeenCalledWith(MOCK_DEFAULT_SEARCH_OPTIONS[MOCK_INDEX].url); }); diff --git a/spec/frontend/header_search/components/header_search_autocomplete_items_spec.js b/spec/frontend/header_search/components/header_search_autocomplete_items_spec.js index bec0cbc8a5c..502f10ff771 100644 --- a/spec/frontend/header_search/components/header_search_autocomplete_items_spec.js +++ b/spec/frontend/header_search/components/header_search_autocomplete_items_spec.js @@ -1,6 +1,6 @@ import { GlDropdownItem, GlLoadingIcon, GlAvatar } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import HeaderSearchAutocompleteItems from '~/header_search/components/header_search_autocomplete_items.vue'; import { @@ -143,7 +143,7 @@ describe('HeaderSearchAutocompleteItems', () => { wrapper.setProps({ currentFocusedOption: MOCK_SORTED_AUTOCOMPLETE_OPTIONS[0] }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(scrollSpy).toHaveBeenCalledWith(false); scrollSpy.mockRestore(); diff --git a/spec/frontend/ide/components/branches/search_list_spec.js b/spec/frontend/ide/components/branches/search_list_spec.js index 35e006a26ce..b6e3274153a 100644 --- a/spec/frontend/ide/components/branches/search_list_spec.js +++ b/spec/frontend/ide/components/branches/search_list_spec.js @@ -1,6 +1,6 @@ import { GlLoadingIcon } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import Item from '~/ide/components/branches/item.vue'; import List from '~/ide/components/branches/search_list.vue'; @@ -50,13 +50,12 @@ describe('IDE branches search list', () => { expect(wrapper.find(GlLoadingIcon).exists()).toBe(true); }); - it('renders branches not found when search is not empty and branches list is empty', () => { + it('renders branches not found when search is not empty and branches list is empty', async () => { createComponent({ branches: [] }); wrapper.find('input[type="search"]').setValue('something'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.text()).toContain(__('No branches found')); - }); + await nextTick(); + expect(wrapper.text()).toContain(__('No branches found')); }); describe('with branches', () => { diff --git a/spec/frontend/ide/components/commit_sidebar/form_spec.js b/spec/frontend/ide/components/commit_sidebar/form_spec.js index 83d1bbb842e..2f191d2dac8 100644 --- a/spec/frontend/ide/components/commit_sidebar/form_spec.js +++ b/spec/frontend/ide/components/commit_sidebar/form_spec.js @@ -1,6 +1,6 @@ import { GlModal } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import { stubComponent } from 'helpers/stub_component'; import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; import waitForPromises from 'helpers/wait_for_promises'; @@ -98,7 +98,7 @@ describe('IDE commit form', () => { it(`at view=${viewFn.name}, ${buttonFn.name} has disabled=${disabled} tooltip=${tooltip}`, async () => { viewFn(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(buttonFn()).toEqual({ disabled, @@ -116,7 +116,7 @@ describe('IDE commit form', () => { goToEditView(); - await wrapper.vm.$nextTick(); + await nextTick(); }); it('renders commit button in compact mode', () => { @@ -135,7 +135,7 @@ describe('IDE commit form', () => { it('when begin commit button is clicked, shows form', async () => { findBeginCommitButton().vm.$emit('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findForm().exists()).toBe(true); }); @@ -143,7 +143,7 @@ describe('IDE commit form', () => { it('when begin commit button is clicked, sets activity view', async () => { findBeginCommitButton().vm.$emit('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(store.state.currentActivityView).toBe(leftSidebarViews.commit.name); }); @@ -153,14 +153,14 @@ describe('IDE commit form', () => { setLastCommitMessage('test'); goToEditView(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findForm().exists()).toBe(true); // Now test that it collapses when lastCommitMsg is cleared setLastCommitMessage(''); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findForm().exists()).toBe(false); }); @@ -177,7 +177,7 @@ describe('IDE commit form', () => { goToCommitView(); - await wrapper.vm.$nextTick(); + await nextTick(); }); afterEach(() => { @@ -188,12 +188,12 @@ describe('IDE commit form', () => { expect(findForm().exists()).toBe(false); store.state.stagedFiles = []; - await wrapper.vm.$nextTick(); + await nextTick(); expect(findForm().exists()).toBe(false); store.state.stagedFiles.push('test'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findForm().exists()).toBe(false); }); @@ -208,7 +208,7 @@ describe('IDE commit form', () => { goToCommitView(); - await wrapper.vm.$nextTick(); + await nextTick(); }); it('shows form', () => { @@ -222,7 +222,7 @@ describe('IDE commit form', () => { describe('when no changed files', () => { beforeEach(async () => { store.state.stagedFiles = []; - await wrapper.vm.$nextTick(); + await nextTick(); }); it('hides form', () => { @@ -231,7 +231,7 @@ describe('IDE commit form', () => { it('expands again when staged files are added', async () => { store.state.stagedFiles.push('test'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findForm().exists()).toBe(true); }); @@ -240,7 +240,7 @@ describe('IDE commit form', () => { it('updates commitMessage in store on input', async () => { setCommitMessageInput('testing commit message'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(store.state.commit.commitMessage).toBe('testing commit message'); }); @@ -253,14 +253,14 @@ describe('IDE commit form', () => { it('resets commitMessage when clicking discard button', async () => { setCommitMessageInput('testing commit message'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findCommitMessageInput().props('text')).toBe('testing commit message'); // Test that commitMessage is cleared on click findDiscardDraftButton().vm.$emit('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findCommitMessageInput().props('text')).toBe(''); }); @@ -274,11 +274,11 @@ describe('IDE commit form', () => { goToCommitView(); - await wrapper.vm.$nextTick(); + await nextTick(); setCommitMessageInput('testing commit message'); - await wrapper.vm.$nextTick(); + await nextTick(); jest.spyOn(store, 'dispatch').mockResolvedValue(); }); @@ -291,7 +291,7 @@ describe('IDE commit form', () => { it('when cannot push code, submitting does nothing', async () => { store.state.projects.abcproject.userPermissions.pushCode = false; - await wrapper.vm.$nextTick(); + await nextTick(); submitForm(); @@ -309,7 +309,7 @@ describe('IDE commit form', () => { const error = createError(); store.state.commit.commitError = error; - await wrapper.vm.$nextTick(); + await nextTick(); expect(modal.vm.show).toHaveBeenCalled(); expect(modal.props()).toMatchObject({ @@ -342,7 +342,7 @@ describe('IDE commit form', () => { async ({ commitError, expectedActions }) => { store.state.commit.commitError = commitError('test message'); - await wrapper.vm.$nextTick(); + await nextTick(); wrapper.find(GlModal).vm.$emit('ok'); diff --git a/spec/frontend/ide/components/error_message_spec.js b/spec/frontend/ide/components/error_message_spec.js index 28278aa656f..17568158131 100644 --- a/spec/frontend/ide/components/error_message_spec.js +++ b/spec/frontend/ide/components/error_message_spec.js @@ -1,6 +1,6 @@ import { GlLoadingIcon } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import ErrorMessage from '~/ide/components/error_message.vue'; @@ -86,19 +86,15 @@ describe('IDE error message component', () => { expect(actionMock).toHaveBeenCalledWith(message.actionPayload); }); - it('does not dispatch action when already loading', () => { + it('does not dispatch action when already loading', async () => { findActionButton().trigger('click'); actionMock.mockReset(); - return wrapper.vm.$nextTick(() => { - findActionButton().trigger('click'); - - return wrapper.vm.$nextTick().then(() => { - expect(actionMock).not.toHaveBeenCalled(); - }); - }); + findActionButton().trigger('click'); + await nextTick(); + expect(actionMock).not.toHaveBeenCalled(); }); - it('shows loading icon when loading', () => { + it('shows loading icon when loading', async () => { let resolveAction; actionMock.mockImplementation( () => @@ -108,19 +104,16 @@ describe('IDE error message component', () => { ); findActionButton().trigger('click'); - return wrapper.vm.$nextTick(() => { - expect(wrapper.find(GlLoadingIcon).isVisible()).toBe(true); - resolveAction(); - }); + await nextTick(); + expect(wrapper.find(GlLoadingIcon).isVisible()).toBe(true); + resolveAction(); }); - it('hides loading icon when operation finishes', () => { + it('hides loading icon when operation finishes', async () => { findActionButton().trigger('click'); - return actionMock() - .then(() => wrapper.vm.$nextTick()) - .then(() => { - expect(wrapper.find(GlLoadingIcon).isVisible()).toBe(false); - }); + await actionMock(); + await nextTick(); + expect(wrapper.find(GlLoadingIcon).isVisible()).toBe(false); }); }); }); diff --git a/spec/frontend/ide/components/file_templates/dropdown_spec.js b/spec/frontend/ide/components/file_templates/dropdown_spec.js index 426a65dd918..e54b322b9db 100644 --- a/spec/frontend/ide/components/file_templates/dropdown_spec.js +++ b/spec/frontend/ide/components/file_templates/dropdown_spec.js @@ -1,6 +1,6 @@ import { GlLoadingIcon } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import $ from 'jquery'; import Vuex from 'vuex'; import Dropdown from '~/ide/components/file_templates/dropdown.vue'; @@ -54,15 +54,14 @@ describe('IDE file templates dropdown component', () => { wrapper = null; }); - it('calls clickItem on click', () => { + it('calls clickItem on click', async () => { const itemData = { name: 'test.yml ' }; createComponent({ props: { data: [itemData] } }); const item = findItemButtons().at(0); item.trigger('click'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted().click[0][0]).toBe(itemData); - }); + await nextTick(); + expect(wrapper.emitted().click[0][0]).toBe(itemData); }); it('renders dropdown title', () => { @@ -111,7 +110,7 @@ describe('IDE file templates dropdown component', () => { expect(items.wrappers.map((x) => x.text())).toEqual(templates.map((x) => x.name)); }); - it('searches template data', () => { + it('searches template data', async () => { const templates = [{ name: 'match 1' }, { name: 'other' }, { name: 'match 2' }]; const matches = ['match 1', 'match 2']; createComponent({ @@ -119,12 +118,11 @@ describe('IDE file templates dropdown component', () => { state: { templates }, }); findSearch().setValue('match'); - return wrapper.vm.$nextTick().then(() => { - const items = findItemButtons(); + await nextTick(); + const items = findItemButtons(); - expect(items.length).toBe(matches.length); - expect(items.wrappers.map((x) => x.text())).toEqual(matches); - }); + expect(items.length).toBe(matches.length); + expect(items.wrappers.map((x) => x.text())).toEqual(matches); }); it('does not render input when `searchable` is true & `showLoading` is true', () => { @@ -159,17 +157,16 @@ describe('IDE file templates dropdown component', () => { expect(findSearch().exists()).toBe(true); }); - it('searches data', () => { + it('searches data', async () => { const data = [{ name: 'match 1' }, { name: 'other' }, { name: 'match 2' }]; const matches = ['match 1', 'match 2']; createComponent({ props: { searchable: true, data } }); findSearch().setValue('match'); - return wrapper.vm.$nextTick().then(() => { - const items = findItemButtons(); + await nextTick(); + const items = findItemButtons(); - expect(items.length).toBe(matches.length); - expect(items.wrappers.map((x) => x.text())).toEqual(matches); - }); + expect(items.length).toBe(matches.length); + expect(items.wrappers.map((x) => x.text())).toEqual(matches); }); }); }); diff --git a/spec/frontend/ide/components/ide_file_row_spec.js b/spec/frontend/ide/components/ide_file_row_spec.js index 5f287078aa1..baf3d7cca9d 100644 --- a/spec/frontend/ide/components/ide_file_row_spec.js +++ b/spec/frontend/ide/components/ide_file_row_spec.js @@ -1,5 +1,5 @@ import { mount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import FileRowExtra from '~/ide/components/file_row_extra.vue'; import IdeFileRow from '~/ide/components/ide_file_row.vue'; @@ -43,7 +43,7 @@ describe('Ide File Row component', () => { const findFileRow = () => wrapper.find(FileRow); const hasDropdownOpen = () => findFileRowExtra().props('dropdownOpen'); - it('fileRow component has listeners', () => { + it('fileRow component has listeners', async () => { const toggleTreeOpen = jest.fn(); createComponent( {}, @@ -56,9 +56,8 @@ describe('Ide File Row component', () => { findFileRow().vm.$emit('toggleTreeOpen'); - return wrapper.vm.$nextTick().then(() => { - expect(toggleTreeOpen).toHaveBeenCalled(); - }); + await nextTick(); + expect(toggleTreeOpen).toHaveBeenCalled(); }); describe('default', () => { @@ -85,32 +84,30 @@ describe('Ide File Row component', () => { }); describe('with open dropdown', () => { - beforeEach(() => { + beforeEach(async () => { createComponent(); findFileRowExtra().vm.$emit('toggle', true); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('shows open dropdown', () => { expect(hasDropdownOpen()).toBe(true); }); - it('hides dropdown when mouseleave', () => { + it('hides dropdown when mouseleave', async () => { findFileRow().vm.$emit('mouseleave'); - return wrapper.vm.$nextTick().then(() => { - expect(hasDropdownOpen()).toEqual(false); - }); + await nextTick(); + expect(hasDropdownOpen()).toEqual(false); }); - it('hides dropdown on toggle', () => { + it('hides dropdown on toggle', async () => { findFileRowExtra().vm.$emit('toggle', false); - return wrapper.vm.$nextTick().then(() => { - expect(hasDropdownOpen()).toEqual(false); - }); + await nextTick(); + expect(hasDropdownOpen()).toEqual(false); }); }); }); diff --git a/spec/frontend/ide/components/ide_review_spec.js b/spec/frontend/ide/components/ide_review_spec.js index 47270b6e1e9..13d20761263 100644 --- a/spec/frontend/ide/components/ide_review_spec.js +++ b/spec/frontend/ide/components/ide_review_spec.js @@ -1,5 +1,5 @@ import { mount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import { keepAlive } from 'helpers/keep_alive_component_helper'; import { trimText } from 'helpers/text_helper'; @@ -74,14 +74,14 @@ describe('IDE review mode', () => { }); describe('merge request', () => { - beforeEach(() => { + beforeEach(async () => { store.state.currentMergeRequestId = '1'; store.state.projects.abcproject.mergeRequests['1'] = { iid: 123, web_url: 'testing123', }; - return wrapper.vm.$nextTick(); + await nextTick(); }); it('renders edit dropdown', () => { @@ -91,7 +91,7 @@ describe('IDE review mode', () => { it('renders merge request link & IID', async () => { store.state.viewer = 'mrdiff'; - await wrapper.vm.$nextTick(); + await nextTick(); expect(trimText(wrapper.text())).toContain('Merge request (!123)'); }); @@ -99,7 +99,7 @@ describe('IDE review mode', () => { it('changes text to latest changes when viewer is not mrdiff', async () => { store.state.viewer = 'diff'; - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.text()).toContain('Latest changes'); }); diff --git a/spec/frontend/ide/components/ide_side_bar_spec.js b/spec/frontend/ide/components/ide_side_bar_spec.js index af8f6b79c7f..34f14ef23a4 100644 --- a/spec/frontend/ide/components/ide_side_bar_spec.js +++ b/spec/frontend/ide/components/ide_side_bar_spec.js @@ -1,6 +1,6 @@ import { GlSkeletonLoading } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import waitForPromises from 'helpers/wait_for_promises'; import IdeReview from '~/ide/components/ide_review.vue'; @@ -45,7 +45,7 @@ describe('IdeSidebar', () => { store.state.loading = true; - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.findAll(GlSkeletonLoading)).toHaveLength(3); }); @@ -60,7 +60,7 @@ describe('IdeSidebar', () => { store.state.currentActivityView = leftSidebarViews.review.name; await waitForPromises(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.find(IdeTree).exists()).toBe(false); expect(wrapper.find(IdeReview).exists()).toBe(true); @@ -68,7 +68,7 @@ describe('IdeSidebar', () => { store.state.currentActivityView = leftSidebarViews.commit.name; await waitForPromises(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.find(IdeTree).exists()).toBe(false); expect(wrapper.find(IdeReview).exists()).toBe(false); @@ -84,7 +84,7 @@ describe('IdeSidebar', () => { view, }); await waitForPromises(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.find(IdeTree).exists()).toBe(tree); expect(wrapper.find(IdeReview).exists()).toBe(review); @@ -99,7 +99,7 @@ describe('IdeSidebar', () => { store.state.currentActivityView = leftSidebarViews.commit.name; await waitForPromises(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.find(IdeTree).exists()).toBe(false); expect(wrapper.find(RepoCommitSection).exists()).toBe(true); @@ -107,7 +107,7 @@ describe('IdeSidebar', () => { store.state.currentActivityView = leftSidebarViews.edit.name; await waitForPromises(); - await wrapper.vm.$nextTick(); + await nextTick(); // reference to the elements remains the same, meaning the components were kept alive expect(wrapper.find(IdeTree).element).toEqual(ideTreeComponent); diff --git a/spec/frontend/ide/components/jobs/stage_spec.js b/spec/frontend/ide/components/jobs/stage_spec.js index 9accd81a2ba..f158c59cd32 100644 --- a/spec/frontend/ide/components/jobs/stage_spec.js +++ b/spec/frontend/ide/components/jobs/stage_spec.js @@ -1,5 +1,6 @@ import { GlLoadingIcon } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import Item from '~/ide/components/jobs/item.vue'; import Stage from '~/ide/components/jobs/stage.vue'; import { stages, jobs } from '../../mock_data'; @@ -47,23 +48,21 @@ describe('IDE pipeline stage', () => { expect(wrapper.find(GlLoadingIcon).exists()).toBe(true); }); - it('emits toggleCollaped event with stage id when clicking header', () => { + it('emits toggleCollaped event with stage id when clicking header', async () => { const id = 5; createComponent({ stage: { ...defaultProps.stage, id } }); findHeader().trigger('click'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted().toggleCollapsed[0][0]).toBe(id); - }); + await nextTick(); + expect(wrapper.emitted().toggleCollapsed[0][0]).toBe(id); }); - it('emits clickViewLog entity with job', () => { + it('emits clickViewLog entity with job', async () => { const [job] = defaultProps.stage.jobs; createComponent(); wrapper.findAll(Item).at(0).vm.$emit('clickViewLog', job); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted().clickViewLog[0][0]).toBe(job); - }); + await nextTick(); + expect(wrapper.emitted().clickViewLog[0][0]).toBe(job); }); it('renders stage details & icon', () => { diff --git a/spec/frontend/ide/components/merge_requests/list_spec.js b/spec/frontend/ide/components/merge_requests/list_spec.js index 81c7321b22c..583671a0af6 100644 --- a/spec/frontend/ide/components/merge_requests/list_spec.js +++ b/spec/frontend/ide/components/merge_requests/list_spec.js @@ -1,6 +1,6 @@ import { GlLoadingIcon } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import Item from '~/ide/components/merge_requests/item.vue'; import List from '~/ide/components/merge_requests/list.vue'; @@ -66,33 +66,28 @@ describe('IDE merge requests list', () => { expect(wrapper.find(GlLoadingIcon).exists()).toBe(true); }); - it('renders no search results text when search is not empty', () => { + it('renders no search results text when search is not empty', async () => { createComponent(); findTokenedInput().vm.$emit('input', 'something'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.text()).toContain('No merge requests found'); - }); + await nextTick(); + expect(wrapper.text()).toContain('No merge requests found'); }); - it('clicking on search type, sets currentSearchType and loads merge requests', () => { + it('clicking on search type, sets currentSearchType and loads merge requests', async () => { createComponent(); findTokenedInput().vm.$emit('focus'); - return wrapper.vm - .$nextTick() - .then(() => { - findSearchTypeButtons().at(0).trigger('click'); - return wrapper.vm.$nextTick(); - }) - .then(() => { - const searchType = wrapper.vm.$options.searchTypes[0]; + await nextTick(); + findSearchTypeButtons().at(0).trigger('click'); - expect(findTokenedInput().props('tokens')).toEqual([searchType]); - expect(fetchMergeRequestsMock).toHaveBeenCalledWith(expect.any(Object), { - type: searchType.type, - search: '', - }); - }); + await nextTick(); + const searchType = wrapper.vm.$options.searchTypes[0]; + + expect(findTokenedInput().props('tokens')).toEqual([searchType]); + expect(fetchMergeRequestsMock).toHaveBeenCalledWith(expect.any(Object), { + type: searchType.type, + search: '', + }); }); describe('with merge requests', () => { @@ -119,16 +114,15 @@ describe('IDE merge requests list', () => { }); describe('when searching merge requests', () => { - it('calls `loadMergeRequests` on input in search field', () => { + it('calls `loadMergeRequests` on input in search field', async () => { createComponent(defaultStateWithMergeRequests); const input = findTokenedInput(); input.vm.$emit('input', 'something'); - return wrapper.vm.$nextTick().then(() => { - expect(fetchMergeRequestsMock).toHaveBeenCalledWith(expect.any(Object), { - search: 'something', - type: '', - }); + await nextTick(); + expect(fetchMergeRequestsMock).toHaveBeenCalledWith(expect.any(Object), { + search: 'something', + type: '', }); }); }); @@ -143,9 +137,9 @@ describe('IDE merge requests list', () => { }); describe('without search value', () => { - beforeEach(() => { + beforeEach(async () => { input.vm.$emit('focus'); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('shows search types', () => { @@ -155,22 +149,20 @@ describe('IDE merge requests list', () => { ); }); - it('hides search types when search changes', () => { + it('hides search types when search changes', async () => { input.vm.$emit('input', 'something'); - return wrapper.vm.$nextTick().then(() => { - expect(findSearchTypeButtons().exists()).toBe(false); - }); + await nextTick(); + expect(findSearchTypeButtons().exists()).toBe(false); }); describe('with search type', () => { - beforeEach(() => { + beforeEach(async () => { findSearchTypeButtons().at(0).trigger('click'); - return wrapper.vm - .$nextTick() - .then(() => input.vm.$emit('focus')) - .then(() => wrapper.vm.$nextTick()); + await nextTick(); + await input.vm.$emit('focus'); + await nextTick(); }); it('does not show search types', () => { @@ -180,10 +172,10 @@ describe('IDE merge requests list', () => { }); describe('with search value', () => { - beforeEach(() => { + beforeEach(async () => { input.vm.$emit('input', 'something'); input.vm.$emit('focus'); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('does not show search types', () => { diff --git a/spec/frontend/ide/components/panes/right_spec.js b/spec/frontend/ide/components/panes/right_spec.js index da9f0286cfb..d12acd6dc4c 100644 --- a/spec/frontend/ide/components/panes/right_spec.js +++ b/spec/frontend/ide/components/panes/right_spec.js @@ -1,5 +1,5 @@ import { shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import CollapsibleSidebar from '~/ide/components/panes/collapsible_sidebar.vue'; import RightPane from '~/ide/components/panes/right.vue'; @@ -86,19 +86,18 @@ describe('ide/components/panes/right.vue', () => { createComponent(); }); - it('adds terminal tab', () => { + it('adds terminal tab', async () => { store.state.terminal.isVisible = true; - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.find(CollapsibleSidebar).props('extensionTabs')).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - show: true, - title: 'Terminal', - }), - ]), - ); - }); + await nextTick(); + expect(wrapper.find(CollapsibleSidebar).props('extensionTabs')).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + show: true, + title: 'Terminal', + }), + ]), + ); }); it('hides terminal tab when not visible', () => { diff --git a/spec/frontend/ide/components/preview/clientside_spec.js b/spec/frontend/ide/components/preview/clientside_spec.js index 08e9a069cf6..0c0ddcbbfd3 100644 --- a/spec/frontend/ide/components/preview/clientside_spec.js +++ b/spec/frontend/ide/components/preview/clientside_spec.js @@ -1,6 +1,6 @@ import { GlLoadingIcon } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import smooshpack from 'smooshpack'; import Vuex from 'vuex'; import Clientside from '~/ide/components/preview/clientside.vue'; @@ -351,39 +351,36 @@ describe('IDE clientside preview', () => { }); describe('template', () => { - it('renders ide-preview element when showPreview is true', () => { + it('renders ide-preview element when showPreview is true', async () => { createComponent({ getters: { packageJson: dummyPackageJson } }); // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax wrapper.setData({ loading: false }); - return wrapper.vm.$nextTick(() => { - expect(wrapper.find('#ide-preview').exists()).toBe(true); - }); + await nextTick(); + expect(wrapper.find('#ide-preview').exists()).toBe(true); }); - it('renders empty state', () => { + it('renders empty state', async () => { createComponent(); // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax wrapper.setData({ loading: false }); - return wrapper.vm.$nextTick(() => { - expect(wrapper.text()).toContain( - 'Preview your web application using Web IDE client-side evaluation.', - ); - }); + await nextTick(); + expect(wrapper.text()).toContain( + 'Preview your web application using Web IDE client-side evaluation.', + ); }); - it('renders loading icon', () => { + it('renders loading icon', async () => { createComponent(); // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax wrapper.setData({ loading: true }); - return wrapper.vm.$nextTick(() => { - expect(wrapper.find(GlLoadingIcon).exists()).toBe(true); - }); + await nextTick(); + expect(wrapper.find(GlLoadingIcon).exists()).toBe(true); }); }); diff --git a/spec/frontend/ide/components/preview/navigator_spec.js b/spec/frontend/ide/components/preview/navigator_spec.js index ee760364c7e..a199f4704f7 100644 --- a/spec/frontend/ide/components/preview/navigator_spec.js +++ b/spec/frontend/ide/components/preview/navigator_spec.js @@ -1,6 +1,7 @@ import { GlLoadingIcon } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import { listen } from 'codesandbox-api'; +import { nextTick } from 'vue'; import { TEST_HOST } from 'helpers/test_constants'; import ClientsideNavigator from '~/ide/components/preview/navigator.vue'; @@ -29,31 +30,28 @@ describe('IDE clientside preview navigator', () => { wrapper.destroy(); }); - it('renders readonly URL bar', () => { + it('renders readonly URL bar', async () => { listenHandler({ type: 'urlchange', url: manager.bundlerURL }); - return wrapper.vm.$nextTick(() => { - expect(wrapper.find('input[readonly]').element.value).toBe('/'); - }); + await nextTick(); + expect(wrapper.find('input[readonly]').element.value).toBe('/'); }); it('renders loading icon by default', () => { expect(wrapper.find(GlLoadingIcon).exists()).toBe(true); }); - it('removes loading icon when done event is fired', () => { + it('removes loading icon when done event is fired', async () => { listenHandler({ type: 'done' }); - return wrapper.vm.$nextTick(() => { - expect(wrapper.find(GlLoadingIcon).exists()).toBe(false); - }); + await nextTick(); + expect(wrapper.find(GlLoadingIcon).exists()).toBe(false); }); - it('does not count visiting same url multiple times', () => { + it('does not count visiting same url multiple times', async () => { listenHandler({ type: 'done' }); listenHandler({ type: 'done', url: `${TEST_HOST}/url1` }); listenHandler({ type: 'done', url: `${TEST_HOST}/url1` }); - return wrapper.vm.$nextTick().then(() => { - expect(findBackButton().attributes('disabled')).toBe('disabled'); - }); + await nextTick(); + expect(findBackButton().attributes('disabled')).toBe('disabled'); }); it('unsubscribes from listen on destroy', () => { @@ -64,107 +62,93 @@ describe('IDE clientside preview navigator', () => { }); describe('back button', () => { - beforeEach(() => { + beforeEach(async () => { listenHandler({ type: 'done' }); listenHandler({ type: 'urlchange', url: TEST_HOST }); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('is disabled by default', () => { expect(findBackButton().attributes('disabled')).toBe('disabled'); }); - it('is enabled when there is previous entry', () => { + it('is enabled when there is previous entry', async () => { listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url1` }); - return wrapper.vm.$nextTick().then(() => { - findBackButton().trigger('click'); - expect(findBackButton().attributes('disabled')).toBeFalsy(); - }); + await nextTick(); + findBackButton().trigger('click'); + expect(findBackButton().attributes('disabled')).toBeFalsy(); }); - it('is disabled when there is no previous entry', () => { + it('is disabled when there is no previous entry', async () => { listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url1` }); - return wrapper.vm - .$nextTick() - .then(() => { - findBackButton().trigger('click'); - - return wrapper.vm.$nextTick(); - }) - .then(() => { - expect(findBackButton().attributes('disabled')).toBe('disabled'); - }); + + await nextTick(); + findBackButton().trigger('click'); + + await nextTick(); + expect(findBackButton().attributes('disabled')).toBe('disabled'); }); - it('updates manager iframe src', () => { + it('updates manager iframe src', async () => { listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url1` }); listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url2` }); - return wrapper.vm.$nextTick().then(() => { - findBackButton().trigger('click'); + await nextTick(); + findBackButton().trigger('click'); - expect(manager.iframe.src).toBe(`${TEST_HOST}/url1`); - }); + expect(manager.iframe.src).toBe(`${TEST_HOST}/url1`); }); }); describe('forward button', () => { - beforeEach(() => { + beforeEach(async () => { listenHandler({ type: 'done' }); listenHandler({ type: 'urlchange', url: TEST_HOST }); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('is disabled by default', () => { expect(findForwardButton().attributes('disabled')).toBe('disabled'); }); - it('is enabled when there is next entry', () => { + it('is enabled when there is next entry', async () => { listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url1` }); - return wrapper.vm - .$nextTick() - .then(() => { - findBackButton().trigger('click'); - return wrapper.vm.$nextTick(); - }) - .then(() => { - expect(findForwardButton().attributes('disabled')).toBeFalsy(); - }); + + await nextTick(); + findBackButton().trigger('click'); + + await nextTick(); + expect(findForwardButton().attributes('disabled')).toBeFalsy(); }); - it('is disabled when there is no next entry', () => { + it('is disabled when there is no next entry', async () => { listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url1` }); - return wrapper.vm - .$nextTick() - .then(() => { - findBackButton().trigger('click'); - return wrapper.vm.$nextTick(); - }) - .then(() => { - findForwardButton().trigger('click'); - return wrapper.vm.$nextTick(); - }) - .then(() => { - expect(findForwardButton().attributes('disabled')).toBe('disabled'); - }); + + await nextTick(); + findBackButton().trigger('click'); + + await nextTick(); + findForwardButton().trigger('click'); + + await nextTick(); + expect(findForwardButton().attributes('disabled')).toBe('disabled'); }); - it('updates manager iframe src', () => { + it('updates manager iframe src', async () => { listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url1` }); listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url2` }); - return wrapper.vm.$nextTick().then(() => { - findBackButton().trigger('click'); + await nextTick(); + findBackButton().trigger('click'); - expect(manager.iframe.src).toBe(`${TEST_HOST}/url1`); - }); + expect(manager.iframe.src).toBe(`${TEST_HOST}/url1`); }); }); describe('refresh button', () => { const url = `${TEST_HOST}/some_url`; - beforeEach(() => { + beforeEach(async () => { listenHandler({ type: 'done' }); listenHandler({ type: 'urlchange', url }); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('calls refresh with current path', () => { diff --git a/spec/frontend/ide/components/repo_tabs_spec.js b/spec/frontend/ide/components/repo_tabs_spec.js index 843c00d9943..1cfc1f12745 100644 --- a/spec/frontend/ide/components/repo_tabs_spec.js +++ b/spec/frontend/ide/components/repo_tabs_spec.js @@ -1,5 +1,5 @@ import { mount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import RepoTabs from '~/ide/components/repo_tabs.vue'; import { createStore } from '~/ide/stores'; @@ -29,17 +29,14 @@ describe('RepoTabs', () => { wrapper.destroy(); }); - it('renders a list of tabs', (done) => { + it('renders a list of tabs', async () => { store.state.openFiles[0].active = true; - wrapper.vm.$nextTick(() => { - const tabs = [...wrapper.vm.$el.querySelectorAll('.multi-file-tab')]; + await nextTick(); + const tabs = [...wrapper.vm.$el.querySelectorAll('.multi-file-tab')]; - expect(tabs.length).toEqual(2); - expect(tabs[0].parentNode.classList.contains('active')).toEqual(true); - expect(tabs[1].parentNode.classList.contains('active')).toEqual(false); - - done(); - }); + expect(tabs.length).toEqual(2); + expect(tabs[0].parentNode.classList.contains('active')).toEqual(true); + expect(tabs[1].parentNode.classList.contains('active')).toEqual(false); }); }); diff --git a/spec/frontend/ide/components/resizable_panel_spec.js b/spec/frontend/ide/components/resizable_panel_spec.js index cdd089c5588..55b9423aba8 100644 --- a/spec/frontend/ide/components/resizable_panel_spec.js +++ b/spec/frontend/ide/components/resizable_panel_spec.js @@ -1,5 +1,5 @@ import { shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import ResizablePanel from '~/ide/components/resizable_panel.vue'; import { SIDE_LEFT, SIDE_RIGHT } from '~/ide/constants'; @@ -99,15 +99,14 @@ describe('~/ide/components/resizable_panel', () => { }); }); - it('when resizer emits update:size, changes inline width', () => { + it('when resizer emits update:size, changes inline width', async () => { const newSize = TEST_WIDTH - 100; const resizer = findResizer(); resizer.vm.$emit('update:size', newSize); - return wrapper.vm.$nextTick().then(() => { - expect(findInlineStyle()).toBe(createInlineStyle(newSize)); - }); + await nextTick(); + expect(findInlineStyle()).toBe(createInlineStyle(newSize)); }); }); }); diff --git a/spec/frontend/ide/components/terminal/session_spec.js b/spec/frontend/ide/components/terminal/session_spec.js index c988138e9c4..6a70ddb46a8 100644 --- a/spec/frontend/ide/components/terminal/session_spec.js +++ b/spec/frontend/ide/components/terminal/session_spec.js @@ -1,6 +1,6 @@ import { GlButton } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import TerminalSession from '~/ide/components/terminal/session.vue'; import Terminal from '~/ide/components/terminal/terminal.vue'; @@ -67,32 +67,30 @@ describe('IDE TerminalSession', () => { }); [STARTING, PENDING, RUNNING].forEach((status) => { - it(`show stop button when status is ${status}`, () => { + it(`show stop button when status is ${status}`, async () => { state.session = { status }; factory(); const button = findButton(); button.vm.$emit('click'); - return wrapper.vm.$nextTick().then(() => { - expect(button.text()).toEqual('Stop Terminal'); - expect(actions.stopSession).toHaveBeenCalled(); - }); + await nextTick(); + expect(button.text()).toEqual('Stop Terminal'); + expect(actions.stopSession).toHaveBeenCalled(); }); }); [STOPPING, STOPPED].forEach((status) => { - it(`show stop button when status is ${status}`, () => { + it(`show stop button when status is ${status}`, async () => { state.session = { status }; factory(); const button = findButton(); button.vm.$emit('click'); - return wrapper.vm.$nextTick().then(() => { - expect(button.text()).toEqual('Restart Terminal'); - expect(actions.restartSession).toHaveBeenCalled(); - }); + await nextTick(); + expect(button.text()).toEqual('Restart Terminal'); + expect(actions.restartSession).toHaveBeenCalled(); }); }); }); diff --git a/spec/frontend/ide/components/terminal/terminal_controls_spec.js b/spec/frontend/ide/components/terminal/terminal_controls_spec.js index 416096083f0..71ec0dca89d 100644 --- a/spec/frontend/ide/components/terminal/terminal_controls_spec.js +++ b/spec/frontend/ide/components/terminal/terminal_controls_spec.js @@ -1,4 +1,5 @@ import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import ScrollButton from '~/ide/components/jobs/detail/scroll_button.vue'; import TerminalControls from '~/ide/components/terminal/terminal_controls.vue'; @@ -39,27 +40,25 @@ describe('IDE TerminalControls', () => { ); }); - it('emits "scroll-up" when click up button', () => { + it('emits "scroll-up" when click up button', async () => { factory({ propsData: { canScrollUp: true } }); expect(wrapper.emitted()).toEqual({}); buttons.at(0).vm.$emit('click'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted('scroll-up')).toEqual([[]]); - }); + await nextTick(); + expect(wrapper.emitted('scroll-up')).toEqual([[]]); }); - it('emits "scroll-down" when click down button', () => { + it('emits "scroll-down" when click down button', async () => { factory({ propsData: { canScrollDown: true } }); expect(wrapper.emitted()).toEqual({}); buttons.at(1).vm.$emit('click'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted('scroll-down')).toEqual([[]]); - }); + await nextTick(); + expect(wrapper.emitted('scroll-down')).toEqual([[]]); }); }); diff --git a/spec/frontend/incidents/components/incidents_list_spec.js b/spec/frontend/incidents/components/incidents_list_spec.js index 48545ffd2d6..1be6007d844 100644 --- a/spec/frontend/incidents/components/incidents_list_spec.js +++ b/spec/frontend/incidents/components/incidents_list_spec.js @@ -1,5 +1,6 @@ import { GlAlert, GlLoadingIcon, GlTable, GlAvatar, GlEmptyState } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import IncidentsList from '~/incidents/components/incidents_list.vue'; import { I18N, @@ -210,7 +211,7 @@ describe('Incidents List', () => { it('sets button loading on click', async () => { findCreateIncidentBtn().vm.$emit('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findCreateIncidentBtn().attributes('loading')).toBe('true'); }); @@ -233,7 +234,7 @@ describe('Incidents List', () => { it('should track create new incident button', async () => { findCreateIncidentBtn().vm.$emit('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(Tracking.event).toHaveBeenCalled(); }); }); @@ -263,10 +264,10 @@ describe('Incidents List', () => { const columnHeader = () => wrapper.find(`[${attr}="${value}"]`); expect(columnHeader().attributes('aria-sort')).toBe(initialSort); columnHeader().trigger('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(columnHeader().attributes('aria-sort')).toBe(firstSort); columnHeader().trigger('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(columnHeader().attributes('aria-sort')).toBe(nextSort); }, ); @@ -287,7 +288,7 @@ describe('Incidents List', () => { it('should track incident creation events', async () => { findCreateIncidentBtn().vm.$emit('click'); - await wrapper.vm.$nextTick(); + await nextTick(); const { category, action } = trackIncidentCreateNewOptions; expect(Tracking.event).toHaveBeenCalledWith(category, action); }); diff --git a/spec/frontend/integrations/edit/components/active_checkbox_spec.js b/spec/frontend/integrations/edit/components/active_checkbox_spec.js index 0dc31616166..c335b593f7d 100644 --- a/spec/frontend/integrations/edit/components/active_checkbox_spec.js +++ b/spec/frontend/integrations/edit/components/active_checkbox_spec.js @@ -1,6 +1,7 @@ import { GlFormCheckbox } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import ActiveCheckbox from '~/integrations/edit/components/active_checkbox.vue'; import { createStore } from '~/integrations/edit/store'; @@ -68,7 +69,7 @@ describe('ActiveCheckbox', () => { it('switches the form value', async () => { findInputInCheckbox().trigger('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findGlFormCheckbox().vm.$attrs.checked).toBe(false); }); }); diff --git a/spec/frontend/integrations/edit/components/confirmation_modal_spec.js b/spec/frontend/integrations/edit/components/confirmation_modal_spec.js index 805d3971994..cbe3402727a 100644 --- a/spec/frontend/integrations/edit/components/confirmation_modal_spec.js +++ b/spec/frontend/integrations/edit/components/confirmation_modal_spec.js @@ -1,6 +1,7 @@ import { GlModal } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import ConfirmationModal from '~/integrations/edit/components/confirmation_modal.vue'; import { createStore } from '~/integrations/edit/store'; @@ -40,7 +41,7 @@ describe('ConfirmationModal', () => { findGlModal().vm.$emit('primary'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.emitted().submit).toHaveLength(1); }); diff --git a/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js b/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js index 18afbf25bf0..33fd08a5959 100644 --- a/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js +++ b/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js @@ -1,4 +1,5 @@ import { GlFormCheckbox, GlFormInput } from '@gitlab/ui'; +import { nextTick } from 'vue'; import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper'; import JiraIssuesFields from '~/integrations/edit/components/jira_issues_fields.vue'; @@ -193,7 +194,7 @@ describe('JiraIssuesFields', () => { await setEnableCheckbox(true); expect(findJiraForVulnerabilities().attributes('show-full-feature')).toBe('true'); wrapper.setProps({ showJiraVulnerabilitiesIntegration: false }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findJiraForVulnerabilities().attributes('show-full-feature')).toBeUndefined(); }); diff --git a/spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js b/spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js index 9e01371f542..49fbebb9396 100644 --- a/spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js +++ b/spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js @@ -1,4 +1,5 @@ import { GlFormCheckbox } from '@gitlab/ui'; +import { nextTick } from 'vue'; import { mountExtended } from 'helpers/vue_test_utils_helper'; import JiraTriggerFields from '~/integrations/edit/components/jira_trigger_fields.vue'; @@ -71,12 +72,11 @@ describe('JiraTriggerFields', () => { }); describe('on enable comments', () => { - it('shows comment detail', () => { + it('shows comment detail', async () => { findCommentSettingsCheckbox().vm.$emit('input', true); - return wrapper.vm.$nextTick().then(() => { - expect(findCommentDetail().isVisible()).toBe(true); - }); + await nextTick(); + expect(findCommentDetail().isVisible()).toBe(true); }); }); }); @@ -107,7 +107,7 @@ describe('JiraTriggerFields', () => { }); describe('initialJiraIssueTransitionAutomatic is false, initialJiraIssueTransitionId is not set', () => { - it('selects automatic transitions when enabling transitions', () => { + it('selects automatic transitions when enabling transitions', async () => { createComponent({ initialTriggerCommit: true, initialEnableComments: true, @@ -117,11 +117,10 @@ describe('JiraTriggerFields', () => { expect(checkbox.element.checked).toBe(false); checkbox.trigger('click'); - return wrapper.vm.$nextTick().then(() => { - const [radio1, radio2] = findIssueTransitionModeRadios().wrappers; - expect(radio1.element.checked).toBe(true); - expect(radio2.element.checked).toBe(false); - }); + await nextTick(); + const [radio1, radio2] = findIssueTransitionModeRadios().wrappers; + expect(radio1.element.checked).toBe(true); + expect(radio2.element.checked).toBe(false); }); }); diff --git a/spec/frontend/invite_members/components/import_a_project_modal_spec.js b/spec/frontend/invite_members/components/import_a_project_modal_spec.js index fecbf84fb57..6db881d5c75 100644 --- a/spec/frontend/invite_members/components/import_a_project_modal_spec.js +++ b/spec/frontend/invite_members/components/import_a_project_modal_spec.js @@ -1,5 +1,6 @@ import { GlFormGroup, GlSprintf, GlModal } from '@gitlab/ui'; import MockAdapter from 'axios-mock-adapter'; +import { nextTick } from 'vue'; import { stubComponent } from 'helpers/stub_component'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import waitForPromises from 'helpers/wait_for_promises'; @@ -91,7 +92,7 @@ describe('ImportAProjectModal', () => { it('sets isLoading to true when the Invite button is clicked', async () => { clickImportButton(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findImportButton().props('loading')).toBe(true); }); @@ -157,7 +158,7 @@ describe('ImportAProjectModal', () => { clickCancelButton(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(formGroupInvalidFeedback()).toBe(''); expect(formGroupErrorState()).not.toBe(false); diff --git a/spec/frontend/invite_members/components/invite_members_modal_spec.js b/spec/frontend/invite_members/components/invite_members_modal_spec.js index 3ab89b3dff2..8b02d916045 100644 --- a/spec/frontend/invite_members/components/invite_members_modal_spec.js +++ b/spec/frontend/invite_members/components/invite_members_modal_spec.js @@ -8,6 +8,7 @@ import { GlModal, } from '@gitlab/ui'; import MockAdapter from 'axios-mock-adapter'; +import { nextTick } from 'vue'; import { stubComponent } from 'helpers/stub_component'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import waitForPromises from 'helpers/wait_for_promises'; @@ -508,7 +509,7 @@ describe('InviteMembersModal', () => { findMembersSelect().vm.$emit('clear'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(membersFormGroupInvalidFeedback()).toBe(''); expect(findMembersFormGroup().props('state')).not.toBe(false); @@ -518,7 +519,7 @@ describe('InviteMembersModal', () => { it('clears the error when the cancel button is clicked', async () => { clickCancelButton(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(membersFormGroupInvalidFeedback()).toBe(''); expect(findMembersFormGroup().props('state')).not.toBe(false); @@ -528,7 +529,7 @@ describe('InviteMembersModal', () => { it('clears the error when the modal is hidden', async () => { wrapper.findComponent(GlModal).vm.$emit('hide'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(membersFormGroupInvalidFeedback()).toBe(''); expect(findMembersFormGroup().props('state')).not.toBe(false); diff --git a/spec/frontend/issuable/components/related_issuable_item_spec.js b/spec/frontend/issuable/components/related_issuable_item_spec.js index 6a896ccd21a..6b48f83041a 100644 --- a/spec/frontend/issuable/components/related_issuable_item_spec.js +++ b/spec/frontend/issuable/components/related_issuable_item_spec.js @@ -1,4 +1,5 @@ import { mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import { TEST_HOST } from 'helpers/test_constants'; import IssueDueDate from '~/boards/components/issue_due_date.vue'; import { formatDate } from '~/lib/utils/datetime_utility'; @@ -105,7 +106,7 @@ describe('RelatedIssuableItem', () => { state: 'closed', closedAt: '2018-12-01T00:00:00.00Z', }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(tokenState().classes('issue-token-state-icon-closed')).toBe(true); }); @@ -140,7 +141,7 @@ describe('RelatedIssuableItem', () => { closedAt: '2018-12-01T00:00:00.00Z', }, }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.find(IssueDueDate).props('closed')).toBe(true); }); @@ -172,14 +173,14 @@ describe('RelatedIssuableItem', () => { // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax wrapper.setData({ removeDisabled: true }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findRemoveButton().attributes('disabled')).toEqual('disabled'); }); it('triggers onRemoveRequest when clicked', async () => { findRemoveButton().trigger('click'); - await wrapper.vm.$nextTick(); + await nextTick(); const { relatedIssueRemoveRequest } = wrapper.emitted(); expect(relatedIssueRemoveRequest.length).toBe(1); diff --git a/spec/frontend/issuable/related_issues/components/add_issuable_form_spec.js b/spec/frontend/issuable/related_issues/components/add_issuable_form_spec.js index ff6922989cb..2ae32e89605 100644 --- a/spec/frontend/issuable/related_issues/components/add_issuable_form_spec.js +++ b/spec/frontend/issuable/related_issues/components/add_issuable_form_spec.js @@ -1,4 +1,5 @@ import { mount, shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import AddIssuableForm from '~/related_issues/components/add_issuable_form.vue'; import IssueToken from '~/related_issues/components/issue_token.vue'; import { issuableTypesMap, linkedIssueTypesMap, PathIdSeparator } from '~/related_issues/constants'; @@ -194,63 +195,55 @@ describe('AddIssuableForm', () => { }); describe('when the form is submitted', () => { - it('emits an event with a "relates_to" link type when the "relates to" radio input selected', (done) => { + it('emits an event with a "relates_to" link type when the "relates to" radio input selected', async () => { jest.spyOn(wrapper.vm, '$emit').mockImplementation(() => {}); wrapper.vm.linkedIssueType = linkedIssueTypesMap.RELATES_TO; wrapper.vm.onFormSubmit(); - wrapper.vm.$nextTick(() => { - expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormSubmit', { - pendingReferences: '', - linkedIssueType: linkedIssueTypesMap.RELATES_TO, - }); - done(); + await nextTick(); + expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormSubmit', { + pendingReferences: '', + linkedIssueType: linkedIssueTypesMap.RELATES_TO, }); }); - it('emits an event with a "blocks" link type when the "blocks" radio input selected', (done) => { + it('emits an event with a "blocks" link type when the "blocks" radio input selected', async () => { jest.spyOn(wrapper.vm, '$emit').mockImplementation(() => {}); wrapper.vm.linkedIssueType = linkedIssueTypesMap.BLOCKS; wrapper.vm.onFormSubmit(); - wrapper.vm.$nextTick(() => { - expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormSubmit', { - pendingReferences: '', - linkedIssueType: linkedIssueTypesMap.BLOCKS, - }); - done(); + await nextTick(); + expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormSubmit', { + pendingReferences: '', + linkedIssueType: linkedIssueTypesMap.BLOCKS, }); }); - it('emits an event with a "is_blocked_by" link type when the "is blocked by" radio input selected', (done) => { + it('emits an event with a "is_blocked_by" link type when the "is blocked by" radio input selected', async () => { jest.spyOn(wrapper.vm, '$emit').mockImplementation(() => {}); wrapper.vm.linkedIssueType = linkedIssueTypesMap.IS_BLOCKED_BY; wrapper.vm.onFormSubmit(); - wrapper.vm.$nextTick(() => { - expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormSubmit', { - pendingReferences: '', - linkedIssueType: linkedIssueTypesMap.IS_BLOCKED_BY, - }); - done(); + await nextTick(); + expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormSubmit', { + pendingReferences: '', + linkedIssueType: linkedIssueTypesMap.IS_BLOCKED_BY, }); }); - it('shows error message when error is present', (done) => { + it('shows error message when error is present', async () => { const itemAddFailureMessage = 'Something went wrong while submitting.'; wrapper.setProps({ hasError: true, itemAddFailureMessage, }); - wrapper.vm.$nextTick(() => { - expect(wrapper.find('.gl-field-error').exists()).toBe(true); - expect(wrapper.find('.gl-field-error').text()).toContain(itemAddFailureMessage); - done(); - }); + await nextTick(); + expect(wrapper.find('.gl-field-error').exists()).toBe(true); + expect(wrapper.find('.gl-field-error').text()).toContain(itemAddFailureMessage); }); }); }); diff --git a/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js b/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js index 01de4da7900..b59717a1f60 100644 --- a/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js +++ b/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js @@ -1,5 +1,6 @@ import { mount, shallowMount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; +import { nextTick } from 'vue'; import waitForPromises from 'helpers/wait_for_promises'; import { defaultProps, @@ -210,40 +211,37 @@ describe('RelatedIssuesRoot', () => { }), ); - it('when canceling and hiding add issuable form', () => { + it('when canceling and hiding add issuable form', async () => { wrapper.vm.onPendingFormCancel(); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.vm.isFormVisible).toEqual(false); - expect(wrapper.vm.inputValue).toEqual(''); - expect(wrapper.vm.state.pendingReferences).toHaveLength(0); - }); + await nextTick(); + expect(wrapper.vm.isFormVisible).toEqual(false); + expect(wrapper.vm.inputValue).toEqual(''); + expect(wrapper.vm.state.pendingReferences).toHaveLength(0); }); }); describe('fetchRelatedIssues', () => { beforeEach(() => createComponent()); - it('sets isFetching while fetching', () => { + it('sets isFetching while fetching', async () => { wrapper.vm.fetchRelatedIssues(); expect(wrapper.vm.isFetching).toEqual(true); - return waitForPromises().then(() => { - expect(wrapper.vm.isFetching).toEqual(false); - }); + await waitForPromises(); + expect(wrapper.vm.isFetching).toEqual(false); }); - it('should fetch related issues', () => { + it('should fetch related issues', async () => { mock.onGet(defaultProps.endpoint).reply(200, [issuable1, issuable2]); wrapper.vm.fetchRelatedIssues(); - return waitForPromises().then(() => { - expect(wrapper.vm.state.relatedIssues).toHaveLength(2); - expect(wrapper.vm.state.relatedIssues[0].id).toEqual(issuable1.id); - expect(wrapper.vm.state.relatedIssues[1].id).toEqual(issuable2.id); - }); + await waitForPromises(); + expect(wrapper.vm.state.relatedIssues).toHaveLength(2); + expect(wrapper.vm.state.relatedIssues[0].id).toEqual(issuable1.id); + expect(wrapper.vm.state.relatedIssues[1].id).toEqual(issuable2.id); }); }); diff --git a/spec/frontend/issues/list/components/new_issue_dropdown_spec.js b/spec/frontend/issues/list/components/new_issue_dropdown_spec.js index 7bec3d13d44..2c8cf9caf5d 100644 --- a/spec/frontend/issues/list/components/new_issue_dropdown_spec.js +++ b/spec/frontend/issues/list/components/new_issue_dropdown_spec.js @@ -1,5 +1,6 @@ import { GlDropdown, GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui'; -import { createLocalVue, mount, shallowMount } from '@vue/test-utils'; +import { mount, shallowMount } from '@vue/test-utils'; +import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; @@ -17,8 +18,7 @@ import { describe('NewIssueDropdown component', () => { let wrapper; - const localVue = createLocalVue(); - localVue.use(VueApollo); + Vue.use(VueApollo); const mountComponent = ({ search = '', @@ -29,7 +29,6 @@ describe('NewIssueDropdown component', () => { const apolloProvider = createMockApollo(requestHandlers); return mountFn(NewIssueDropdown, { - localVue, apolloProvider, provide: { fullPath: 'mushroom-kingdom', diff --git a/spec/frontend/issues/new/components/title_suggestions_spec.js b/spec/frontend/issues/new/components/title_suggestions_spec.js index f6b93cc5a62..0a64890e4ca 100644 --- a/spec/frontend/issues/new/components/title_suggestions_spec.js +++ b/spec/frontend/issues/new/components/title_suggestions_spec.js @@ -1,4 +1,5 @@ import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import TitleSuggestions from '~/issues/new/components/title_suggestions.vue'; import TitleSuggestionsItem from '~/issues/new/components/title_suggestions_item.vue'; @@ -22,12 +23,11 @@ describe('Issue title suggestions component', () => { wrapper.destroy(); }); - it('does not render with empty search', () => { + it('does not render with empty search', async () => { wrapper.setProps({ search: '' }); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.isVisible()).toBe(false); - }); + await nextTick(); + expect(wrapper.isVisible()).toBe(false); }); describe('with data', () => { @@ -37,28 +37,26 @@ describe('Issue title suggestions component', () => { data = { issues: [{ id: 1 }, { id: 2 }] }; }); - it('renders component', () => { + it('renders component', async () => { // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax wrapper.setData(data); - return wrapper.vm.$nextTick(() => { - expect(wrapper.findAll('li').length).toBe(data.issues.length); - }); + await nextTick(); + expect(wrapper.findAll('li').length).toBe(data.issues.length); }); - it('does not render with empty search', () => { + it('does not render with empty search', async () => { wrapper.setProps({ search: '' }); // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax wrapper.setData(data); - return wrapper.vm.$nextTick(() => { - expect(wrapper.isVisible()).toBe(false); - }); + await nextTick(); + expect(wrapper.isVisible()).toBe(false); }); - it('does not render when loading', () => { + it('does not render when loading', async () => { // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax wrapper.setData({ @@ -66,49 +64,44 @@ describe('Issue title suggestions component', () => { loading: 1, }); - return wrapper.vm.$nextTick(() => { - expect(wrapper.isVisible()).toBe(false); - }); + await nextTick(); + expect(wrapper.isVisible()).toBe(false); }); - it('does not render with empty issues data', () => { + it('does not render with empty issues data', async () => { // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax wrapper.setData({ issues: [] }); - return wrapper.vm.$nextTick(() => { - expect(wrapper.isVisible()).toBe(false); - }); + await nextTick(); + expect(wrapper.isVisible()).toBe(false); }); - it('renders list of issues', () => { + it('renders list of issues', async () => { // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax wrapper.setData(data); - return wrapper.vm.$nextTick(() => { - expect(wrapper.findAll(TitleSuggestionsItem).length).toBe(2); - }); + await nextTick(); + expect(wrapper.findAll(TitleSuggestionsItem).length).toBe(2); }); - it('adds margin class to first item', () => { + it('adds margin class to first item', async () => { // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax wrapper.setData(data); - return wrapper.vm.$nextTick(() => { - expect(wrapper.findAll('li').at(0).classes()).toContain('gl-mb-3'); - }); + await nextTick(); + expect(wrapper.findAll('li').at(0).classes()).toContain('gl-mb-3'); }); - it('does not add margin class to last item', () => { + it('does not add margin class to last item', async () => { // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax wrapper.setData(data); - return wrapper.vm.$nextTick(() => { - expect(wrapper.findAll('li').at(1).classes()).not.toContain('gl-mb-3'); - }); + await nextTick(); + expect(wrapper.findAll('li').at(1).classes()).not.toContain('gl-mb-3'); }); }); }); diff --git a/spec/frontend/issues/show/components/app_spec.js b/spec/frontend/issues/show/components/app_spec.js index 02db82b84dc..ac2717a5028 100644 --- a/spec/frontend/issues/show/components/app_spec.js +++ b/spec/frontend/issues/show/components/app_spec.js @@ -145,33 +145,30 @@ describe('Issuable output', () => { }); }); - it('shows actions if permissions are correct', () => { + it('shows actions if permissions are correct', async () => { wrapper.vm.showForm = true; - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.find('.markdown-selector').exists()).toBe(true); - }); + await nextTick(); + expect(wrapper.find('.markdown-selector').exists()).toBe(true); }); - it('does not show actions if permissions are incorrect', () => { + it('does not show actions if permissions are incorrect', async () => { wrapper.vm.showForm = true; wrapper.setProps({ canUpdate: false }); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.find('.markdown-selector').exists()).toBe(false); - }); + await nextTick(); + expect(wrapper.find('.markdown-selector').exists()).toBe(false); }); - it('does not update formState if form is already open', () => { + it('does not update formState if form is already open', async () => { wrapper.vm.updateAndShowForm(); wrapper.vm.state.titleText = 'testing 123'; wrapper.vm.updateAndShowForm(); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.vm.store.formState.title).not.toBe('testing 123'); - }); + await nextTick(); + expect(wrapper.vm.store.formState.title).not.toBe('testing 123'); }); describe('Pinned links propagated', () => { @@ -186,31 +183,29 @@ describe('Issuable output', () => { }); describe('updateIssuable', () => { - it('fetches new data after update', () => { + it('fetches new data after update', async () => { const updateStoreSpy = jest.spyOn(wrapper.vm, 'updateStoreState'); const getDataSpy = jest.spyOn(wrapper.vm.service, 'getData'); jest.spyOn(wrapper.vm.service, 'updateIssuable').mockResolvedValue({ data: { web_url: window.location.pathname }, }); - return wrapper.vm.updateIssuable().then(() => { - expect(updateStoreSpy).toHaveBeenCalled(); - expect(getDataSpy).toHaveBeenCalled(); - }); + await wrapper.vm.updateIssuable(); + expect(updateStoreSpy).toHaveBeenCalled(); + expect(getDataSpy).toHaveBeenCalled(); }); - it('correctly updates issuable data', () => { + it('correctly updates issuable data', async () => { const spy = jest.spyOn(wrapper.vm.service, 'updateIssuable').mockResolvedValue({ data: { web_url: window.location.pathname }, }); - return wrapper.vm.updateIssuable().then(() => { - expect(spy).toHaveBeenCalledWith(wrapper.vm.formState); - expect(eventHub.$emit).toHaveBeenCalledWith('close.form'); - }); + await wrapper.vm.updateIssuable(); + expect(spy).toHaveBeenCalledWith(wrapper.vm.formState); + expect(eventHub.$emit).toHaveBeenCalledWith('close.form'); }); - it('does not redirect if issue has not moved', () => { + it('does not redirect if issue has not moved', async () => { jest.spyOn(wrapper.vm.service, 'updateIssuable').mockResolvedValue({ data: { web_url: window.location.pathname, @@ -218,12 +213,11 @@ describe('Issuable output', () => { }, }); - return wrapper.vm.updateIssuable().then(() => { - expect(visitUrl).not.toHaveBeenCalled(); - }); + await wrapper.vm.updateIssuable(); + expect(visitUrl).not.toHaveBeenCalled(); }); - it('does not redirect if issue has not moved and user has switched tabs', () => { + it('does not redirect if issue has not moved and user has switched tabs', async () => { jest.spyOn(wrapper.vm.service, 'updateIssuable').mockResolvedValue({ data: { web_url: '', @@ -231,12 +225,11 @@ describe('Issuable output', () => { }, }); - return wrapper.vm.updateIssuable().then(() => { - expect(visitUrl).not.toHaveBeenCalled(); - }); + await wrapper.vm.updateIssuable(); + expect(visitUrl).not.toHaveBeenCalled(); }); - it('redirects if returned web_url has changed', () => { + it('redirects if returned web_url has changed', async () => { jest.spyOn(wrapper.vm.service, 'updateIssuable').mockResolvedValue({ data: { web_url: '/testing-issue-move', @@ -246,108 +239,95 @@ describe('Issuable output', () => { wrapper.vm.updateIssuable(); - return wrapper.vm.updateIssuable().then(() => { - expect(visitUrl).toHaveBeenCalledWith('/testing-issue-move'); - }); + await wrapper.vm.updateIssuable(); + expect(visitUrl).toHaveBeenCalledWith('/testing-issue-move'); }); describe('shows dialog when issue has unsaved changed', () => { - it('confirms on title change', () => { + it('confirms on title change', async () => { wrapper.vm.showForm = true; wrapper.vm.state.titleText = 'title has changed'; const e = { returnValue: null }; wrapper.vm.handleBeforeUnloadEvent(e); - return wrapper.vm.$nextTick().then(() => { - expect(e.returnValue).not.toBeNull(); - }); + await nextTick(); + expect(e.returnValue).not.toBeNull(); }); - it('confirms on description change', () => { + it('confirms on description change', async () => { wrapper.vm.showForm = true; wrapper.vm.state.descriptionText = 'description has changed'; const e = { returnValue: null }; wrapper.vm.handleBeforeUnloadEvent(e); - return wrapper.vm.$nextTick().then(() => { - expect(e.returnValue).not.toBeNull(); - }); + await nextTick(); + expect(e.returnValue).not.toBeNull(); }); - it('does nothing when nothing has changed', () => { + it('does nothing when nothing has changed', async () => { const e = { returnValue: null }; wrapper.vm.handleBeforeUnloadEvent(e); - return wrapper.vm.$nextTick().then(() => { - expect(e.returnValue).toBeNull(); - }); + await nextTick(); + expect(e.returnValue).toBeNull(); }); }); describe('error when updating', () => { - it('closes form on error', () => { + it('closes form on error', async () => { jest.spyOn(wrapper.vm.service, 'updateIssuable').mockRejectedValue(); - return wrapper.vm.updateIssuable().then(() => { - expect(eventHub.$emit).not.toHaveBeenCalledWith('close.form'); - expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe( - `Error updating issue`, - ); - }); + await wrapper.vm.updateIssuable(); + expect(eventHub.$emit).not.toHaveBeenCalledWith('close.form'); + expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe( + `Error updating issue`, + ); }); - it('returns the correct error message for issuableType', () => { + it('returns the correct error message for issuableType', async () => { jest.spyOn(wrapper.vm.service, 'updateIssuable').mockRejectedValue(); wrapper.setProps({ issuableType: 'merge request' }); - return wrapper.vm - .$nextTick() - .then(wrapper.vm.updateIssuable) - .then(() => { - expect(eventHub.$emit).not.toHaveBeenCalledWith('close.form'); - expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe( - `Error updating merge request`, - ); - }); + await nextTick(); + await wrapper.vm.updateIssuable(); + expect(eventHub.$emit).not.toHaveBeenCalledWith('close.form'); + expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe( + `Error updating merge request`, + ); }); - it('shows error message from backend if exists', () => { + it('shows error message from backend if exists', async () => { const msg = 'Custom error message from backend'; jest .spyOn(wrapper.vm.service, 'updateIssuable') .mockRejectedValue({ response: { data: { errors: [msg] } } }); - return wrapper.vm.updateIssuable().then(() => { - expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe( - `${wrapper.vm.defaultErrorMessage}. ${msg}`, - ); - }); + await wrapper.vm.updateIssuable(); + expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe( + `${wrapper.vm.defaultErrorMessage}. ${msg}`, + ); }); }); }); describe('updateAndShowForm', () => { - it('shows locked warning if form is open & data is different', () => { - return wrapper.vm - .$nextTick() - .then(() => { - wrapper.vm.updateAndShowForm(); - - wrapper.vm.poll.makeRequest(); - - return new Promise((resolve) => { - wrapper.vm.$watch('formState.lockedWarningVisible', (value) => { - if (value) { - resolve(); - } - }); - }); - }) - .then(() => { - expect(wrapper.vm.formState.lockedWarningVisible).toBe(true); - expect(wrapper.vm.formState.lock_version).toBe(1); - expect(findAlert().exists()).toBe(true); + it('shows locked warning if form is open & data is different', async () => { + await nextTick(); + wrapper.vm.updateAndShowForm(); + + wrapper.vm.poll.makeRequest(); + + await new Promise((resolve) => { + wrapper.vm.$watch('formState.lockedWarningVisible', (value) => { + if (value) { + resolve(); + } }); + }); + + expect(wrapper.vm.formState.lockedWarningVisible).toBe(true); + expect(wrapper.vm.formState.lock_version).toBe(1); + expect(findAlert().exists()).toBe(true); }); }); @@ -398,12 +378,11 @@ describe('Issuable output', () => { expect(wrapper.find('.btn-edit').exists()).toBe(true); }); - it('should render if showInlineEditButton', () => { + it('should render if showInlineEditButton', async () => { wrapper.setProps({ showInlineEditButton: true }); - return wrapper.vm.$nextTick(() => { - expect(wrapper.find('.btn-edit').exists()).toBe(true); - }); + await nextTick(); + expect(wrapper.find('.btn-edit').exists()).toBe(true); }); }); diff --git a/spec/frontend/issues/show/components/fields/type_spec.js b/spec/frontend/issues/show/components/fields/type_spec.js index 7f7b16583e6..3333ceffca9 100644 --- a/spec/frontend/issues/show/components/fields/type_spec.js +++ b/spec/frontend/issues/show/components/fields/type_spec.js @@ -1,5 +1,6 @@ import { GlFormGroup, GlDropdown, GlDropdownItem, GlIcon } from '@gitlab/ui'; -import { shallowMount, createLocalVue } from '@vue/test-utils'; +import { shallowMount } from '@vue/test-utils'; +import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; @@ -10,8 +11,7 @@ import { updateIssueStateQueryResponse, } from '../../mock_data/apollo_mock'; -const localVue = createLocalVue(); -localVue.use(VueApollo); +Vue.use(VueApollo); describe('Issue type field component', () => { let wrapper; @@ -43,7 +43,6 @@ describe('Issue type field component', () => { fakeApollo = createMockApollo([], mockResolvers); wrapper = shallowMount(IssueTypeField, { - localVue, apolloProvider: fakeApollo, data() { return { @@ -93,7 +92,7 @@ describe('Issue type field component', () => { it('updates the `issue_type` in the apollo cache when the value is changed', async () => { findTypeFromDropDownItems().at(1).vm.$emit('click', issuableTypes.incident); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findTypeFromDropDown().attributes('value')).toBe(issuableTypes.incident); }); diff --git a/spec/frontend/issues/show/components/form_spec.js b/spec/frontend/issues/show/components/form_spec.js index db49d2635ba..5c0fe991b22 100644 --- a/spec/frontend/issues/show/components/form_spec.js +++ b/spec/frontend/issues/show/components/form_spec.js @@ -1,5 +1,6 @@ import { GlAlert } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import Autosave from '~/autosave'; import DescriptionTemplate from '~/issues/show/components/fields/description_template.vue'; import IssueTypeField from '~/issues/show/components/fields/type.vue'; @@ -148,7 +149,7 @@ describe('Inline edit form component', () => { formState: { ...defaultProps.formState, lock_version: 'lock version from server' }, }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findAlert().exists()).toBe(true); }); }); diff --git a/spec/frontend/issues/show/components/header_actions_spec.js b/spec/frontend/issues/show/components/header_actions_spec.js index d09bf6faa13..4a557a60b94 100644 --- a/spec/frontend/issues/show/components/header_actions_spec.js +++ b/spec/frontend/issues/show/components/header_actions_spec.js @@ -1,5 +1,5 @@ import { GlButton, GlDropdown, GlDropdownItem, GlLink, GlModal } from '@gitlab/ui'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import { shallowMount } from '@vue/test-utils'; import Vuex from 'vuex'; import { mockTracking } from 'helpers/tracking_helper'; @@ -153,7 +153,7 @@ describe('HeaderActions component', () => { it('dispatches a custom event to update the issue page', async () => { findToggleIssueStateButton().vm.$emit('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(dispatchEventSpy).toHaveBeenCalledTimes(1); }); diff --git a/spec/frontend/jira_connect/branches/components/new_branch_form_spec.js b/spec/frontend/jira_connect/branches/components/new_branch_form_spec.js index 7326b84ad54..901d9b5c267 100644 --- a/spec/frontend/jira_connect/branches/components/new_branch_form_spec.js +++ b/spec/frontend/jira_connect/branches/components/new_branch_form_spec.js @@ -1,5 +1,6 @@ import { GlAlert, GlForm, GlFormInput, GlButton } from '@gitlab/ui'; -import { shallowMount, createLocalVue } from '@vue/test-utils'; +import { shallowMount } from '@vue/test-utils'; +import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; @@ -45,8 +46,6 @@ const mockCreateBranchMutationWithErrors = jest const mockCreateBranchMutationFailed = jest.fn().mockRejectedValue(new Error('GraphQL error')); const mockMutationLoading = jest.fn().mockReturnValue(new Promise(() => {})); -const localVue = createLocalVue(); - describe('NewBranchForm', () => { let wrapper; @@ -66,7 +65,7 @@ describe('NewBranchForm', () => { function createMockApolloProvider({ mockCreateBranchMutation = mockCreateBranchMutationSuccess, } = {}) { - localVue.use(VueApollo); + Vue.use(VueApollo); const mockApollo = createMockApollo([[createBranchMutation, mockCreateBranchMutation]]); @@ -75,7 +74,6 @@ describe('NewBranchForm', () => { function createComponent({ mockApollo, provide } = {}) { wrapper = shallowMount(NewBranchForm, { - localVue, apolloProvider: mockApollo || createMockApolloProvider(), provide: { initialBranchName: '', diff --git a/spec/frontend/jira_connect/branches/components/project_dropdown_spec.js b/spec/frontend/jira_connect/branches/components/project_dropdown_spec.js index ec4cb2739f8..6c344ec2667 100644 --- a/spec/frontend/jira_connect/branches/components/project_dropdown_spec.js +++ b/spec/frontend/jira_connect/branches/components/project_dropdown_spec.js @@ -1,5 +1,6 @@ import { GlDropdown, GlDropdownItem, GlLoadingIcon, GlSearchBoxByType } from '@gitlab/ui'; -import { mount, shallowMount, createLocalVue } from '@vue/test-utils'; +import { mount, shallowMount } from '@vue/test-utils'; +import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; @@ -7,8 +8,6 @@ import ProjectDropdown from '~/jira_connect/branches/components/project_dropdown import { PROJECTS_PER_PAGE } from '~/jira_connect/branches/constants'; import getProjectsQuery from '~/jira_connect/branches/graphql/queries/get_projects.query.graphql'; -const localVue = createLocalVue(); - const mockProjects = [ { id: 'test', @@ -62,7 +61,7 @@ describe('ProjectDropdown', () => { const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType); function createMockApolloProvider({ mockGetProjectsQuery = mockGetProjectsQuerySuccess } = {}) { - localVue.use(VueApollo); + Vue.use(VueApollo); const mockApollo = createMockApollo([[getProjectsQuery, mockGetProjectsQuery]]); @@ -71,7 +70,6 @@ describe('ProjectDropdown', () => { function createComponent({ mockApollo, props, mountFn = shallowMount } = {}) { wrapper = mountFn(ProjectDropdown, { - localVue, apolloProvider: mockApollo || createMockApolloProvider(), propsData: props, }); @@ -101,7 +99,7 @@ describe('ProjectDropdown', () => { beforeEach(async () => { createComponent(); await waitForPromises(); - await wrapper.vm.$nextTick(); + await nextTick(); }); it('sets dropdown `loading` prop to `false`', () => { diff --git a/spec/frontend/jira_connect/branches/components/source_branch_dropdown_spec.js b/spec/frontend/jira_connect/branches/components/source_branch_dropdown_spec.js index 9dd11dd6345..161bcc8c86d 100644 --- a/spec/frontend/jira_connect/branches/components/source_branch_dropdown_spec.js +++ b/spec/frontend/jira_connect/branches/components/source_branch_dropdown_spec.js @@ -1,5 +1,6 @@ import { GlDropdown, GlDropdownItem, GlLoadingIcon, GlSearchBoxByType } from '@gitlab/ui'; -import { mount, shallowMount, createLocalVue } from '@vue/test-utils'; +import { mount, shallowMount } from '@vue/test-utils'; +import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; @@ -7,8 +8,6 @@ import SourceBranchDropdown from '~/jira_connect/branches/components/source_bran import { BRANCHES_PER_PAGE } from '~/jira_connect/branches/constants'; import getProjectQuery from '~/jira_connect/branches/graphql/queries/get_project.query.graphql'; -const localVue = createLocalVue(); - const mockProject = { id: 'test', fullPath: 'test-path', @@ -45,7 +44,7 @@ describe('SourceBranchDropdown', () => { }; function createMockApolloProvider({ getProjectQueryLoading = false } = {}) { - localVue.use(VueApollo); + Vue.use(VueApollo); const mockApollo = createMockApollo([ [getProjectQuery, getProjectQueryLoading ? mockQueryLoading : mockGetProjectQuery], @@ -56,7 +55,6 @@ describe('SourceBranchDropdown', () => { function createComponent({ mockApollo, props, mountFn = shallowMount } = {}) { wrapper = mountFn(SourceBranchDropdown, { - localVue, apolloProvider: mockApollo || createMockApolloProvider(), propsData: props, }); diff --git a/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item_spec.js b/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item_spec.js index 15e9a740c83..b0d5859cd31 100644 --- a/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item_spec.js +++ b/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item_spec.js @@ -1,5 +1,6 @@ import { GlButton } from '@gitlab/ui'; import { mount, shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import waitForPromises from 'helpers/wait_for_promises'; import * as JiraConnectApi from '~/jira_connect/subscriptions/api'; @@ -63,7 +64,7 @@ describe('GroupsListItem', () => { clickLinkButton(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findLinkButton().props('loading')).toBe(true); diff --git a/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_spec.js b/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_spec.js index 04aba8bda23..660368cd99c 100644 --- a/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_spec.js +++ b/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_spec.js @@ -1,5 +1,6 @@ import { GlAlert, GlLoadingIcon, GlSearchBoxByType, GlPagination } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import waitForPromises from 'helpers/wait_for_promises'; import { fetchGroups } from '~/jira_connect/subscriptions/api'; @@ -61,7 +62,7 @@ describe('GroupsList', () => { fetchGroups.mockReturnValue(new Promise(() => {})); createComponent(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findGlLoadingIcon().exists()).toBe(true); }); @@ -124,7 +125,7 @@ describe('GroupsList', () => { findFirstItem().vm.$emit('error', errorMessage); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findGlAlert().exists()).toBe(true); expect(findGlAlert().text()).toContain(errorMessage); @@ -139,7 +140,7 @@ describe('GroupsList', () => { fetchGroups.mockReturnValue(new Promise(() => {})); findSearchBox().vm.$emit('input', mockSearchTeam); - await wrapper.vm.$nextTick(); + await nextTick(); }); it('calls `fetchGroups` with search term', () => { diff --git a/spec/frontend/jira_connect/subscriptions/components/app_spec.js b/spec/frontend/jira_connect/subscriptions/components/app_spec.js index 47fe96262ee..8d6a97bc0ea 100644 --- a/spec/frontend/jira_connect/subscriptions/components/app_spec.js +++ b/spec/frontend/jira_connect/subscriptions/components/app_spec.js @@ -1,6 +1,7 @@ import { GlAlert, GlLink, GlEmptyState } from '@gitlab/ui'; import { mount, shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import JiraConnectApp from '~/jira_connect/subscriptions/components/app.vue'; import AddNamespaceButton from '~/jira_connect/subscriptions/components/add_namespace_button.vue'; import SignInButton from '~/jira_connect/subscriptions/components/sign_in_button.vue'; @@ -116,7 +117,7 @@ describe('JiraConnectApp', () => { createComponent(); store.commit(SET_ALERT, { message, variant }); - await wrapper.vm.$nextTick(); + await nextTick(); const alert = findAlert(); @@ -134,10 +135,10 @@ describe('JiraConnectApp', () => { createComponent(); store.commit(SET_ALERT, { message: 'test message' }); - await wrapper.vm.$nextTick(); + await nextTick(); findAlert().vm.$emit('dismiss'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findAlert().exists()).toBe(false); }); @@ -149,7 +150,7 @@ describe('JiraConnectApp', () => { message: __('test message %{linkStart}test link%{linkEnd}'), linkUrl: 'https://gitlab.com', }); - await wrapper.vm.$nextTick(); + await nextTick(); const alertLink = findAlertLink(); diff --git a/spec/frontend/jira_connect/subscriptions/components/subscriptions_list_spec.js b/spec/frontend/jira_connect/subscriptions/components/subscriptions_list_spec.js index 4e4a2b58600..2aad533f677 100644 --- a/spec/frontend/jira_connect/subscriptions/components/subscriptions_list_spec.js +++ b/spec/frontend/jira_connect/subscriptions/components/subscriptions_list_spec.js @@ -1,5 +1,6 @@ import { GlButton } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import waitForPromises from 'helpers/wait_for_promises'; import * as JiraConnectApi from '~/jira_connect/subscriptions/api'; @@ -71,7 +72,7 @@ describe('SubscriptionsList', () => { clickUnlinkButton(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findUnlinkButton().props('loading')).toBe(true); diff --git a/spec/frontend/jobs/bridge/app_spec.js b/spec/frontend/jobs/bridge/app_spec.js index cd7c2fd5322..210dcfa364b 100644 --- a/spec/frontend/jobs/bridge/app_spec.js +++ b/spec/frontend/jobs/bridge/app_spec.js @@ -1,5 +1,6 @@ -import { nextTick } from 'vue'; -import { shallowMount, createLocalVue } from '@vue/test-utils'; +import Vue, { nextTick } from 'vue'; +import { shallowMount } from '@vue/test-utils'; + import { GlBreakpointInstance } from '@gitlab/ui/dist/utils'; import { GlLoadingIcon } from '@gitlab/ui'; import VueApollo from 'vue-apollo'; @@ -17,9 +18,6 @@ import { mockPipelineQueryResponse, } from './mock_data'; -const localVue = createLocalVue(); -localVue.use(VueApollo); - describe('Bridge Show Page', () => { let wrapper; let mockApollo; @@ -47,10 +45,10 @@ describe('Bridge Show Page', () => { const createComponentWithApollo = () => { const handlers = [[getPipelineQuery, mockPipelineQuery]]; + Vue.use(VueApollo); mockApollo = createMockApollo(handlers); createComponent({ - localVue, apolloProvider: mockApollo, mocks: {}, }); diff --git a/spec/frontend/jobs/components/job_app_spec.js b/spec/frontend/jobs/components/job_app_spec.js index a6e98013d88..d4e1e711777 100644 --- a/spec/frontend/jobs/components/job_app_spec.js +++ b/spec/frontend/jobs/components/job_app_spec.js @@ -1,6 +1,6 @@ import { GlLoadingIcon } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import MockAdapter from 'axios-mock-adapter'; import Vuex from 'vuex'; import delayedJobFixture from 'test_fixtures/jobs/delayed.json'; @@ -45,7 +45,7 @@ describe('Job App', () => { wrapper = mount(JobApp, { propsData: { ...props }, store }); }; - const setupAndMount = ({ jobData = {}, jobLogData = {} } = {}) => { + const setupAndMount = async ({ jobData = {}, jobLogData = {} } = {}) => { mock.onGet(initSettings.endpoint).replyOnce(200, { ...job, ...jobData }); mock.onGet(`${initSettings.pagePath}/trace.json`).reply(200, jobLogData); @@ -53,12 +53,10 @@ describe('Job App', () => { createComponent(); - return asyncInit - .then(() => { - jest.runOnlyPendingTimers(); - }) - .then(() => axios.waitForAll()) - .then(() => wrapper.vm.$nextTick()); + await asyncInit; + jest.runOnlyPendingTimers(); + await axios.waitForAll(); + await nextTick(); }; const findLoadingComponent = () => wrapper.find(GlLoadingIcon); diff --git a/spec/frontend/jobs/components/job_container_item_spec.js b/spec/frontend/jobs/components/job_container_item_spec.js index 6b488821bc1..eb2b0184e5f 100644 --- a/spec/frontend/jobs/components/job_container_item_spec.js +++ b/spec/frontend/jobs/components/job_container_item_spec.js @@ -1,5 +1,6 @@ import { GlIcon, GlLink } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import delayedJobFixture from 'test_fixtures/jobs/delayed.json'; import JobContainerItem from '~/jobs/components/job_container_item.vue'; import CiIcon from '~/vue_shared/components/ci_icon.vue'; @@ -87,7 +88,7 @@ describe('JobContainerItem', () => { }); it('displays remaining time in tooltip', async () => { - await wrapper.vm.$nextTick(); + await nextTick(); const link = wrapper.findComponent(GlLink); diff --git a/spec/frontend/jobs/components/job_log_controllers_spec.js b/spec/frontend/jobs/components/job_log_controllers_spec.js index 0ba07522243..226322a2951 100644 --- a/spec/frontend/jobs/components/job_log_controllers_spec.js +++ b/spec/frontend/jobs/components/job_log_controllers_spec.js @@ -1,4 +1,5 @@ import { mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import JobLogControllers from '~/jobs/components/job_log_controllers.vue'; describe('Job log controllers', () => { @@ -111,7 +112,7 @@ describe('Job log controllers', () => { it('emits scrollJobLogTop event on click', async () => { findScrollTop().trigger('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.emitted().scrollJobLogTop).toHaveLength(1); }); @@ -133,7 +134,7 @@ describe('Job log controllers', () => { it('does not emit scrollJobLogTop event on click', async () => { findScrollTop().trigger('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.emitted().scrollJobLogTop).toBeUndefined(); }); @@ -149,7 +150,7 @@ describe('Job log controllers', () => { it('emits scrollJobLogBottom event on click', async () => { findScrollBottom().trigger('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.emitted().scrollJobLogBottom).toHaveLength(1); }); @@ -171,7 +172,7 @@ describe('Job log controllers', () => { it('does not emit scrollJobLogBottom event on click', async () => { findScrollBottom().trigger('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.emitted().scrollJobLogBottom).toBeUndefined(); }); diff --git a/spec/frontend/jobs/components/log/collapsible_section_spec.js b/spec/frontend/jobs/components/log/collapsible_section_spec.js index 96bdf03796b..22ddc8b1c2d 100644 --- a/spec/frontend/jobs/components/log/collapsible_section_spec.js +++ b/spec/frontend/jobs/components/log/collapsible_section_spec.js @@ -1,4 +1,5 @@ import { mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import CollapsibleSection from '~/jobs/components/log/collapsible_section.vue'; import { collapsibleSectionClosed, collapsibleSectionOpened } from './mock_data'; @@ -69,7 +70,7 @@ describe('Job Log Collapsible Section', () => { }); }); - it('emits onClickCollapsibleLine on click', () => { + it('emits onClickCollapsibleLine on click', async () => { createComponent({ section: collapsibleSectionOpened, jobLogEndpoint, @@ -77,8 +78,7 @@ describe('Job Log Collapsible Section', () => { findCollapsibleLine().trigger('click'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted('onClickCollapsibleLine').length).toBe(1); - }); + await nextTick(); + expect(wrapper.emitted('onClickCollapsibleLine').length).toBe(1); }); }); diff --git a/spec/frontend/jobs/components/log/line_header_spec.js b/spec/frontend/jobs/components/log/line_header_spec.js index 9763e2f437b..8055fe64d95 100644 --- a/spec/frontend/jobs/components/log/line_header_spec.js +++ b/spec/frontend/jobs/components/log/line_header_spec.js @@ -1,4 +1,5 @@ import { mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import DurationBadge from '~/jobs/components/log/duration_badge.vue'; import LineHeader from '~/jobs/components/log/line_header.vue'; import LineNumber from '~/jobs/components/log/line_number.vue'; @@ -75,12 +76,11 @@ describe('Job Log Header Line', () => { createComponent(data); }); - it('emits toggleLine event', () => { + it('emits toggleLine event', async () => { wrapper.trigger('click'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted().toggleLine.length).toBe(1); - }); + await nextTick(); + expect(wrapper.emitted().toggleLine.length).toBe(1); }); }); diff --git a/spec/frontend/jobs/components/sidebar_spec.js b/spec/frontend/jobs/components/sidebar_spec.js index 500a1b48950..6e327725627 100644 --- a/spec/frontend/jobs/components/sidebar_spec.js +++ b/spec/frontend/jobs/components/sidebar_spec.js @@ -1,4 +1,5 @@ import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import ArtifactsBlock from '~/jobs/components/artifacts_block.vue'; import JobRetryForwardDeploymentModal from '~/jobs/components/job_retry_forward_deployment_modal.vue'; @@ -189,7 +190,7 @@ describe('Sidebar details block', () => { locked: false, }; - await wrapper.vm.$nextTick(); + await nextTick(); expect(findArtifactsBlock().exists()).toBe(true); }); diff --git a/spec/frontend/jobs/components/table/job_table_app_spec.js b/spec/frontend/jobs/components/table/job_table_app_spec.js index 389bcf670c9..7808a22e1f6 100644 --- a/spec/frontend/jobs/components/table/job_table_app_spec.js +++ b/spec/frontend/jobs/components/table/job_table_app_spec.js @@ -1,5 +1,6 @@ import { GlSkeletonLoader, GlAlert, GlEmptyState, GlPagination } from '@gitlab/ui'; -import { createLocalVue, mount, shallowMount } from '@vue/test-utils'; +import { mount, shallowMount } from '@vue/test-utils'; +import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; @@ -10,8 +11,7 @@ import JobsTableTabs from '~/jobs/components/table/jobs_table_tabs.vue'; import { mockJobsQueryResponse, mockJobsQueryEmptyResponse } from '../../mock_data'; const projectPath = 'gitlab-org/gitlab'; -const localVue = createLocalVue(); -localVue.use(VueApollo); +Vue.use(VueApollo); describe('Job table app', () => { let wrapper; @@ -50,7 +50,6 @@ describe('Job table app', () => { provide: { projectPath, }, - localVue, apolloProvider: createMockApolloProvider(handler), }); }; @@ -124,7 +123,7 @@ describe('Job table app', () => { }, }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findPrevious().exists()).toBe(true); expect(findNext().exists()).toBe(true); diff --git a/spec/frontend/jobs/mixins/delayed_job_mixin_spec.js b/spec/frontend/jobs/mixins/delayed_job_mixin_spec.js index 63dcd72f967..1d3845b19bb 100644 --- a/spec/frontend/jobs/mixins/delayed_job_mixin_spec.js +++ b/spec/frontend/jobs/mixins/delayed_job_mixin_spec.js @@ -1,4 +1,5 @@ import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import delayedJobFixture from 'test_fixtures/jobs/delayed.json'; import delayedJobMixin from '~/jobs/mixins/delayed_job_mixin'; @@ -34,7 +35,7 @@ describe('DelayedJobMixin', () => { }); it('does not update remaining time after mounting', async () => { - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.text()).toBe('00:00:00'); }); @@ -57,7 +58,7 @@ describe('DelayedJobMixin', () => { }, }); - await wrapper.vm.$nextTick(); + await nextTick(); }); it('sets remaining time', () => { @@ -68,7 +69,7 @@ describe('DelayedJobMixin', () => { remainingTimeInMilliseconds = 41000; jest.advanceTimersByTime(1000); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.text()).toBe('00:00:41'); }); }); @@ -104,7 +105,7 @@ describe('DelayedJobMixin', () => { }, }); - await wrapper.vm.$nextTick(); + await nextTick(); }); it('sets remaining time', () => { @@ -115,7 +116,7 @@ describe('DelayedJobMixin', () => { remainingTimeInMilliseconds = 41000; jest.advanceTimersByTime(1000); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.text()).toBe('00:00:41'); }); }); diff --git a/spec/frontend/logs/components/environment_logs_spec.js b/spec/frontend/logs/components/environment_logs_spec.js index b107708ac2c..84dc0bdf6cd 100644 --- a/spec/frontend/logs/components/environment_logs_spec.js +++ b/spec/frontend/logs/components/environment_logs_spec.js @@ -1,5 +1,6 @@ import { GlSprintf, GlDropdown, GlDropdownItem } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import { scrollDown } from '~/lib/utils/scroll_utils'; import EnvironmentLogs from '~/logs/components/environment_logs.vue'; @@ -338,35 +339,32 @@ describe('EnvironmentLogs', () => { expect(store.dispatch).not.toHaveBeenCalledWith(`${module}/fetchMoreLogsPrepend`, undefined); }); - it('`scroll` on a scrollable target results in enabled scroll buttons', () => { + it('`scroll` on a scrollable target results in enabled scroll buttons', async () => { const target = { scrollTop: 10, clientHeight: 10, scrollHeight: 21 }; state.logs.isLoading = true; findInfiniteScroll().vm.$emit('scroll', { target }); - return wrapper.vm.$nextTick(() => { - expect(findLogControlButtons().props('scrollDownButtonDisabled')).toEqual(false); - }); + await nextTick(); + expect(findLogControlButtons().props('scrollDownButtonDisabled')).toEqual(false); }); - it('`scroll` on a non-scrollable target in disabled scroll buttons', () => { + it('`scroll` on a non-scrollable target in disabled scroll buttons', async () => { const target = { scrollTop: 10, clientHeight: 10, scrollHeight: 20 }; state.logs.isLoading = true; findInfiniteScroll().vm.$emit('scroll', { target }); - return wrapper.vm.$nextTick(() => { - expect(findLogControlButtons().props('scrollDownButtonDisabled')).toEqual(true); - }); + await nextTick(); + expect(findLogControlButtons().props('scrollDownButtonDisabled')).toEqual(true); }); - it('`scroll` on no target results in disabled scroll buttons', () => { + it('`scroll` on no target results in disabled scroll buttons', async () => { state.logs.isLoading = true; findInfiniteScroll().vm.$emit('scroll', { target: undefined }); - return wrapper.vm.$nextTick(() => { - expect(findLogControlButtons().props('scrollDownButtonDisabled')).toEqual(true); - }); + await nextTick(); + expect(findLogControlButtons().props('scrollDownButtonDisabled')).toEqual(true); }); }); }); diff --git a/spec/frontend/logs/components/log_control_buttons_spec.js b/spec/frontend/logs/components/log_control_buttons_spec.js index 9c1617e4daa..e249272b87d 100644 --- a/spec/frontend/logs/components/log_control_buttons_spec.js +++ b/spec/frontend/logs/components/log_control_buttons_spec.js @@ -1,5 +1,6 @@ import { GlButton } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import LogControlButtons from '~/logs/components/log_control_buttons.vue'; describe('LogControlButtons', () => { @@ -33,7 +34,7 @@ describe('LogControlButtons', () => { expect(findRefreshBtn().is(GlButton)).toBe(true); }); - it('emits a `refresh` event on click on `refresh` button', () => { + it('emits a `refresh` event on click on `refresh` button', async () => { initWrapper(); // An `undefined` value means no event was emitted @@ -41,16 +42,15 @@ describe('LogControlButtons', () => { findRefreshBtn().vm.$emit('click'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted('refresh')).toHaveLength(1); - }); + await nextTick(); + expect(wrapper.emitted('refresh')).toHaveLength(1); }); describe('when scrolling actions are enabled', () => { - beforeEach(() => { + beforeEach(async () => { // mock scrolled to the middle of a long page initWrapper(); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('click on "scroll to top" scrolls up', () => { @@ -71,19 +71,18 @@ describe('LogControlButtons', () => { }); describe('when scrolling actions are disabled', () => { - beforeEach(() => { + beforeEach(async () => { initWrapper({ listeners: {} }); - return wrapper.vm.$nextTick(); + await nextTick(); }); - it('buttons are disabled', () => { - return wrapper.vm.$nextTick(() => { - expect(findScrollToTop().exists()).toBe(false); - expect(findScrollToBottom().exists()).toBe(false); - // This should be enabled when gitlab-ui contains: - // https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/1149 - // expect(findScrollToBottom().is('[disabled]')).toBe(true); - }); + it('buttons are disabled', async () => { + await nextTick(); + expect(findScrollToTop().exists()).toBe(false); + expect(findScrollToBottom().exists()).toBe(false); + // This should be enabled when gitlab-ui contains: + // https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/1149 + // expect(findScrollToBottom().is('[disabled]')).toBe(true); }); }); }); diff --git a/spec/frontend/merge_conflicts/components/merge_conflict_resolver_app_spec.js b/spec/frontend/merge_conflicts/components/merge_conflict_resolver_app_spec.js index fabf65742f5..750fff9b0aa 100644 --- a/spec/frontend/merge_conflicts/components/merge_conflict_resolver_app_spec.js +++ b/spec/frontend/merge_conflicts/components/merge_conflict_resolver_app_spec.js @@ -1,6 +1,6 @@ import { GlSprintf } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import InlineConflictLines from '~/merge_conflicts/components/inline_conflict_lines.vue'; import ParallelConflictLines from '~/merge_conflicts/components/parallel_conflict_lines.vue'; @@ -93,7 +93,7 @@ describe('Merge Conflict Resolver App', () => { expect(inlineButton.props('selected')).toBe(false); inlineButton.vm.$emit('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(inlineButton.props('selected')).toBe(true); }); @@ -111,7 +111,7 @@ describe('Merge Conflict Resolver App', () => { mountComponent(); findSideBySideButton().vm.$emit('click'); - await wrapper.vm.$nextTick(); + await nextTick(); const parallelConflictLinesComponent = findParallelConflictLines(findFiles().at(0)); diff --git a/spec/frontend/monitoring/components/charts/stacked_column_spec.js b/spec/frontend/monitoring/components/charts/stacked_column_spec.js index f47728313c6..9cab3650f28 100644 --- a/spec/frontend/monitoring/components/charts/stacked_column_spec.js +++ b/spec/frontend/monitoring/components/charts/stacked_column_spec.js @@ -2,6 +2,7 @@ import { GlStackedColumnChart, GlChartLegend } from '@gitlab/ui/dist/charts'; import { shallowMount, mount } from '@vue/test-utils'; import { cloneDeep } from 'lodash'; import timezoneMock from 'timezone-mock'; +import { nextTick } from 'vue'; import StackedColumnChart from '~/monitoring/components/charts/stacked_column.vue'; import { stackedColumnGraphData } from '../../graph_data'; @@ -34,9 +35,9 @@ describe('Stacked column chart component', () => { }); describe('when graphData is present', () => { - beforeEach(() => { + beforeEach(async () => { createWrapper(); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('chart is rendered', () => { @@ -116,25 +117,24 @@ describe('Stacked column chart component', () => { expect(xAxis.axisLabel.formatter('2020-01-30T12:01:00.000Z')).toBe('4:01 AM'); }); - it('date is shown in UTC', () => { + it('date is shown in UTC', async () => { wrapper.setProps({ timezone: 'UTC' }); - return wrapper.vm.$nextTick().then(() => { - const { xAxis } = findChart().props('option'); - expect(xAxis.axisLabel.formatter('2020-01-30T12:01:00.000Z')).toBe('12:01 PM'); - }); + await nextTick(); + const { xAxis } = findChart().props('option'); + expect(xAxis.axisLabel.formatter('2020-01-30T12:01:00.000Z')).toBe('12:01 PM'); }); }); }); describe('when graphData has results missing', () => { - beforeEach(() => { + beforeEach(async () => { const graphData = cloneDeep(stackedColumnMockedData); graphData.metrics[0].result = null; createWrapper({ graphData }); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('chart is rendered', () => { @@ -147,7 +147,7 @@ describe('Stacked column chart component', () => { wrapper = createWrapper({}, mount); }); - it('allows user to override legend label texts using props', () => { + it('allows user to override legend label texts using props', async () => { const legendRelatedProps = { legendMinText: 'legendMinText', legendMaxText: 'legendMaxText', @@ -158,9 +158,8 @@ describe('Stacked column chart component', () => { ...legendRelatedProps, }); - return wrapper.vm.$nextTick().then(() => { - expect(findChart().props()).toMatchObject(legendRelatedProps); - }); + await nextTick(); + expect(findChart().props()).toMatchObject(legendRelatedProps); }); it('should render a tabular legend layout by default', () => { diff --git a/spec/frontend/monitoring/components/charts/time_series_spec.js b/spec/frontend/monitoring/components/charts/time_series_spec.js index ff6f0b9b0c7..73abd81d889 100644 --- a/spec/frontend/monitoring/components/charts/time_series_spec.js +++ b/spec/frontend/monitoring/components/charts/time_series_spec.js @@ -7,6 +7,7 @@ import { } from '@gitlab/ui/dist/charts'; import { mount, shallowMount } from '@vue/test-utils'; import timezoneMock from 'timezone-mock'; +import { nextTick } from 'vue'; import { TEST_HOST } from 'helpers/test_constants'; import { setTestTimeout } from 'helpers/timeout'; import { shallowWrapperContainsSlotText } from 'helpers/vue_test_utils_helper'; @@ -70,12 +71,12 @@ describe('Time series component', () => { describe('general functions', () => { const findChart = () => wrapper.find({ ref: 'chart' }); - beforeEach(() => { + beforeEach(async () => { createWrapper({}, mount); - return wrapper.vm.$nextTick(); + await nextTick(); }); - it('allows user to override legend label texts using props', () => { + it('allows user to override legend label texts using props', async () => { const legendRelatedProps = { legendMinText: 'legendMinText', legendMaxText: 'legendMaxText', @@ -86,9 +87,8 @@ describe('Time series component', () => { ...legendRelatedProps, }); - return wrapper.vm.$nextTick().then(() => { - expect(findChart().props()).toMatchObject(legendRelatedProps); - }); + await nextTick(); + expect(findChart().props()).toMatchObject(legendRelatedProps); }); it('chart sets a default height', () => { @@ -96,14 +96,13 @@ describe('Time series component', () => { expect(wrapper.props('height')).toBe(chartHeight); }); - it('chart has a configurable height', () => { + it('chart has a configurable height', async () => { const mockHeight = 599; createWrapper(); wrapper.setProps({ height: mockHeight }); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.props('height')).toBe(mockHeight); - }); + await nextTick(); + expect(wrapper.props('height')).toBe(mockHeight); }); describe('events', () => { @@ -112,7 +111,7 @@ describe('Time series component', () => { let startValue; let endValue; - beforeEach(() => { + beforeEach(async () => { eChartMock = { handlers: {}, getOption: () => ({ @@ -132,9 +131,8 @@ describe('Time series component', () => { }; createWrapper({}, mount); - return wrapper.vm.$nextTick(() => { - findChart().vm.$emit('created', eChartMock); - }); + await nextTick(); + findChart().vm.$emit('created', eChartMock); }); it('handles datazoom event from chart', () => { @@ -203,10 +201,10 @@ describe('Time series component', () => { }); describe('when series is of line type', () => { - beforeEach(() => { + beforeEach(async () => { createWrapper({}, mount); wrapper.vm.formatTooltipText(mockLineSeriesData()); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('formats tooltip title', () => { @@ -241,34 +239,31 @@ describe('Time series component', () => { timezoneMock.unregister(); }); - it('formats tooltip title in local timezone by default', () => { + it('formats tooltip title in local timezone by default', async () => { createWrapper(); wrapper.vm.formatTooltipText(mockLineSeriesData()); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.vm.tooltip.title).toBe('16 Jul 2019, 3:14AM (GMT-0700)'); - }); + await nextTick(); + expect(wrapper.vm.tooltip.title).toBe('16 Jul 2019, 3:14AM (GMT-0700)'); }); - it('formats tooltip title in local timezone', () => { + it('formats tooltip title in local timezone', async () => { createWrapper({ timezone: 'LOCAL' }); wrapper.vm.formatTooltipText(mockLineSeriesData()); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.vm.tooltip.title).toBe('16 Jul 2019, 3:14AM (GMT-0700)'); - }); + await nextTick(); + expect(wrapper.vm.tooltip.title).toBe('16 Jul 2019, 3:14AM (GMT-0700)'); }); - it('formats tooltip title in UTC format', () => { + it('formats tooltip title in UTC format', async () => { createWrapper({ timezone: 'UTC' }); wrapper.vm.formatTooltipText(mockLineSeriesData()); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.vm.tooltip.title).toBe('16 Jul 2019, 10:14AM (UTC)'); - }); + await nextTick(); + expect(wrapper.vm.tooltip.title).toBe('16 Jul 2019, 10:14AM (UTC)'); }); }); }); describe('when series is of scatter type, for deployments', () => { - beforeEach(() => { + beforeEach(async () => { wrapper.vm.formatTooltipText({ ...mockAnnotationsSeriesData, seriesData: mockAnnotationsSeriesData.seriesData.map((data) => ({ @@ -276,7 +271,7 @@ describe('Time series component', () => { data: annotationsMetadata, })), }); - return wrapper.vm.$nextTick; + await nextTick(); }); it('set tooltip type to deployments', () => { @@ -297,9 +292,9 @@ describe('Time series component', () => { }); describe('when series is of scatter type and deployments data is missing', () => { - beforeEach(() => { + beforeEach(async () => { wrapper.vm.formatTooltipText(mockAnnotationsSeriesData); - return wrapper.vm.$nextTick; + await nextTick(); }); it('formats tooltip title', () => { @@ -397,14 +392,13 @@ describe('Time series component', () => { }); }); - it('is not set if time range is not set or incorrectly set', () => { + it('is not set if time range is not set or incorrectly set', async () => { wrapper.setProps({ timeRange: {}, }); - return wrapper.vm.$nextTick(() => { - expect(getChartOptions().xAxis).not.toHaveProperty('min'); - expect(getChartOptions().xAxis).not.toHaveProperty('max'); - }); + await nextTick(); + expect(getChartOptions().xAxis).not.toHaveProperty('min'); + expect(getChartOptions().xAxis).not.toHaveProperty('max'); }); }); @@ -430,17 +424,16 @@ describe('Time series component', () => { option2: 'option2', }; - it('arbitrary options', () => { + it('arbitrary options', async () => { wrapper.setProps({ option: mockOption, }); - return wrapper.vm.$nextTick().then(() => { - expect(getChartOptions()).toEqual(expect.objectContaining(mockOption)); - }); + await nextTick(); + expect(getChartOptions()).toEqual(expect.objectContaining(mockOption)); }); - it('additional series', () => { + it('additional series', async () => { wrapper.setProps({ option: { series: [ @@ -453,15 +446,14 @@ describe('Time series component', () => { }, }); - return wrapper.vm.$nextTick().then(() => { - const optionSeries = getChartOptions().series; + await nextTick(); + const optionSeries = getChartOptions().series; - expect(optionSeries.length).toEqual(2); - expect(optionSeries[0].name).toEqual(mockSeriesName); - }); + expect(optionSeries.length).toEqual(2); + expect(optionSeries[0].name).toEqual(mockSeriesName); }); - it('additional y-axis data', () => { + it('additional y-axis data', async () => { const mockCustomYAxisOption = { name: 'Custom y-axis label', axisLabel: { @@ -475,14 +467,13 @@ describe('Time series component', () => { }, }); - return wrapper.vm.$nextTick().then(() => { - const { yAxis } = getChartOptions(); + await nextTick(); + const { yAxis } = getChartOptions(); - expect(yAxis[0]).toMatchObject(mockCustomYAxisOption); - }); + expect(yAxis[0]).toMatchObject(mockCustomYAxisOption); }); - it('additional x axis data', () => { + it('additional x axis data', async () => { const mockCustomXAxisOption = { name: 'Custom x axis label', }; @@ -493,11 +484,10 @@ describe('Time series component', () => { }, }); - return wrapper.vm.$nextTick().then(() => { - const { xAxis } = getChartOptions(); + await nextTick(); + const { xAxis } = getChartOptions(); - expect(xAxis).toMatchObject(mockCustomXAxisOption); - }); + expect(xAxis).toMatchObject(mockCustomXAxisOption); }); }); @@ -625,12 +615,12 @@ describe('Time series component', () => { describe(`GitLab UI: ${dynamicComponent.chartType}`, () => { const findChartComponent = () => wrapper.find(dynamicComponent.component); - beforeEach(() => { + beforeEach(async () => { createWrapper( { graphData: timeSeriesGraphData({ type: dynamicComponent.chartType }) }, mount, ); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('exists', () => { @@ -645,22 +635,21 @@ describe('Time series component', () => { expect(props.formatTooltipText).toBe(wrapper.vm.formatTooltipText); }); - it('receives a tooltip title', () => { + it('receives a tooltip title', async () => { const mockTitle = 'mockTitle'; wrapper.vm.tooltip.title = mockTitle; - return wrapper.vm.$nextTick(() => { - expect( - shallowWrapperContainsSlotText(findChartComponent(), 'tooltip-title', mockTitle), - ).toBe(true); - }); + await nextTick(); + expect( + shallowWrapperContainsSlotText(findChartComponent(), 'tooltip-title', mockTitle), + ).toBe(true); }); describe('when tooltip is showing deployment data', () => { const mockSha = 'mockSha'; const commitUrl = `${mockProjectDir}/-/commit/${mockSha}`; - beforeEach(() => { + beforeEach(async () => { // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax wrapper.setData({ @@ -668,7 +657,7 @@ describe('Time series component', () => { type: 'deployments', }, }); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('uses deployment title', () => { @@ -677,16 +666,15 @@ describe('Time series component', () => { ).toBe(true); }); - it('renders clickable commit sha in tooltip content', () => { + it('renders clickable commit sha in tooltip content', async () => { wrapper.vm.tooltip.sha = mockSha; wrapper.vm.tooltip.commitUrl = commitUrl; - return wrapper.vm.$nextTick(() => { - const commitLink = wrapper.find(GlLink); + await nextTick(); + const commitLink = wrapper.find(GlLink); - expect(shallowWrapperContainsSlotText(commitLink, 'default', mockSha)).toBe(true); - expect(commitLink.attributes('href')).toEqual(commitUrl); - }); + expect(shallowWrapperContainsSlotText(commitLink, 'default', mockSha)).toBe(true); + expect(commitLink.attributes('href')).toEqual(commitUrl); }); }); }); @@ -696,11 +684,11 @@ describe('Time series component', () => { describe('with multiple time series', () => { describe('General functions', () => { - beforeEach(() => { + beforeEach(async () => { const graphData = timeSeriesGraphData({ type: panelTypes.AREA_CHART, multiMetric: true }); createWrapper({ graphData }, mount); - return wrapper.vm.$nextTick(); + await nextTick(); }); describe('Color match', () => { @@ -742,9 +730,9 @@ describe('Time series component', () => { describe('legend layout', () => { const findLegend = () => wrapper.find(GlChartLegend); - beforeEach(() => { + beforeEach(async () => { createWrapper({}, mount); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('should render a tabular legend layout by default', () => { diff --git a/spec/frontend/monitoring/components/create_dashboard_modal_spec.js b/spec/frontend/monitoring/components/create_dashboard_modal_spec.js index 8202d423ff3..88de3467580 100644 --- a/spec/frontend/monitoring/components/create_dashboard_modal_spec.js +++ b/spec/frontend/monitoring/components/create_dashboard_modal_spec.js @@ -1,5 +1,6 @@ import { GlModal } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import CreateDashboardModal from '~/monitoring/components/create_dashboard_modal.vue'; describe('Create dashboard modal', () => { @@ -32,13 +33,12 @@ describe('Create dashboard modal', () => { wrapper.destroy(); }); - it('has button that links to the project url', () => { + it('has button that links to the project url', async () => { findRepoButton().trigger('click'); - return wrapper.vm.$nextTick().then(() => { - expect(findRepoButton().exists()).toBe(true); - expect(findRepoButton().attributes('href')).toBe(defaultProps.projectPath); - }); + await nextTick(); + expect(findRepoButton().exists()).toBe(true); + expect(findRepoButton().attributes('href')).toBe(defaultProps.projectPath); }); it('has button that links to the docs', () => { diff --git a/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js b/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js index f2116c1f478..d0d0c3071d5 100644 --- a/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js +++ b/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js @@ -1,5 +1,6 @@ import { GlDropdownItem, GlModal } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import CustomMetricsFormFields from '~/custom_metrics/components/custom_metrics_form_fields.vue'; import { redirectTo } from '~/lib/utils/url_utility'; import ActionsMenu from '~/monitoring/components/dashboard_actions_menu.vue'; @@ -60,22 +61,20 @@ describe('Actions menu', () => { }); describe('add metric item', () => { - it('is rendered when custom metrics are available', () => { + it('is rendered when custom metrics are available', async () => { createShallowWrapper(); - return wrapper.vm.$nextTick(() => { - expect(findAddMetricItem().exists()).toBe(true); - }); + await nextTick(); + expect(findAddMetricItem().exists()).toBe(true); }); - it('is not rendered when custom metrics are not available', () => { + it('is not rendered when custom metrics are not available', async () => { createShallowWrapper({ addingMetricsAvailable: false, }); - return wrapper.vm.$nextTick(() => { - expect(findAddMetricItem().exists()).toBe(false); - }); + await nextTick(); + expect(findAddMetricItem().exists()).toBe(false); }); describe('when available', () => { @@ -119,30 +118,23 @@ describe('Actions menu', () => { origPage = document.body.dataset.page; document.body.dataset.page = 'projects:environments:metrics'; - wrapper.vm.$nextTick(done); + nextTick(done); }); afterEach(() => { document.body.dataset.page = origPage; }); - it('is tracked', (done) => { + it('is tracked', async () => { const submitButton = findAddMetricModalSubmitButton().vm; - wrapper.vm.$nextTick(() => { - submitButton.$el.click(); - wrapper.vm.$nextTick(() => { - expect(Tracking.event).toHaveBeenCalledWith( - document.body.dataset.page, - 'click_button', - { - label: 'add_new_metric', - property: 'modal', - value: undefined, - }, - ); - done(); - }); + await nextTick(); + submitButton.$el.click(); + await nextTick(); + expect(Tracking.event).toHaveBeenCalledWith(document.body.dataset.page, 'click_button', { + label: 'add_new_metric', + property: 'modal', + value: undefined, }); }); }); @@ -172,14 +164,13 @@ describe('Actions menu', () => { ); }); - it('is disabled for ootb dashboards', () => { + it('is disabled for ootb dashboards', async () => { createShallowWrapper({ isOotbDashboard: true, }); - return wrapper.vm.$nextTick(() => { - expect(findAddPanelItemDisabled().exists()).toBe(true); - }); + await nextTick(); + expect(findAddPanelItemDisabled().exists()).toBe(true); }); it('is visible for custom dashboards', () => { @@ -256,16 +247,15 @@ describe('Actions menu', () => { expect(findDuplicateDashboardModal().exists()).toBe(true); }); - it('clicking on item opens up the duplicate dashboard modal', () => { + it('clicking on item opens up the duplicate dashboard modal', async () => { const modalId = 'duplicateDashboard'; const modalTrigger = findDuplicateDashboardItem(); const rootEmit = jest.spyOn(wrapper.vm.$root, '$emit'); modalTrigger.trigger('click'); - return wrapper.vm.$nextTick().then(() => { - expect(rootEmit.mock.calls[0]).toContainEqual(modalId); - }); + await nextTick(); + expect(rootEmit.mock.calls[0]).toContainEqual(modalId); }); }); @@ -300,16 +290,15 @@ describe('Actions menu', () => { setupAllDashboards(store, dashboardGitResponse[0].path); }); - it('redirects to the newly created dashboard', () => { + it('redirects to the newly created dashboard', async () => { const newDashboard = dashboardGitResponse[1]; const newDashboardUrl = 'root/sandbox/-/metrics/dashboard.yml'; findDuplicateDashboardModal().vm.$emit('dashboardDuplicated', newDashboard); - return wrapper.vm.$nextTick().then(() => { - expect(redirectTo).toHaveBeenCalled(); - expect(redirectTo).toHaveBeenCalledWith(newDashboardUrl); - }); + await nextTick(); + expect(redirectTo).toHaveBeenCalled(); + expect(redirectTo).toHaveBeenCalledWith(newDashboardUrl); }); }); }); @@ -330,32 +319,30 @@ describe('Actions menu', () => { expect(findStarDashboardItem().attributes('disabled')).toBeFalsy(); }); - it('is disabled when starring is taking place', () => { + it('is disabled when starring is taking place', async () => { store.commit(`monitoringDashboard/${types.REQUEST_DASHBOARD_STARRING}`); - return wrapper.vm.$nextTick(() => { - expect(findStarDashboardItem().exists()).toBe(true); - expect(findStarDashboardItem().attributes('disabled')).toBe('true'); - }); + await nextTick(); + expect(findStarDashboardItem().exists()).toBe(true); + expect(findStarDashboardItem().attributes('disabled')).toBe('true'); }); - it('on click it dispatches a toggle star action', () => { + it('on click it dispatches a toggle star action', async () => { findStarDashboardItem().vm.$emit('click'); - return wrapper.vm.$nextTick().then(() => { - expect(store.dispatch).toHaveBeenCalledWith( - 'monitoringDashboard/toggleStarredValue', - undefined, - ); - }); + await nextTick(); + expect(store.dispatch).toHaveBeenCalledWith( + 'monitoringDashboard/toggleStarredValue', + undefined, + ); }); describe('when dashboard is not starred', () => { - beforeEach(() => { + beforeEach(async () => { store.commit(`monitoringDashboard/${types.SET_INITIAL_STATE}`, { currentDashboard: dashboardGitResponse[0].path, }); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('item text shows "Star dashboard"', () => { @@ -364,11 +351,11 @@ describe('Actions menu', () => { }); describe('when dashboard is starred', () => { - beforeEach(() => { + beforeEach(async () => { store.commit(`monitoringDashboard/${types.SET_INITIAL_STATE}`, { currentDashboard: dashboardGitResponse[1].path, }); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('item text shows "Unstar dashboard"', () => { @@ -403,16 +390,15 @@ describe('Actions menu', () => { expect(findCreateDashboardModal().exists()).toBe(true); }); - it('clicking opens up the modal', () => { + it('clicking opens up the modal', async () => { const modalId = 'createDashboard'; const modalTrigger = findCreateDashboardItem(); const rootEmit = jest.spyOn(wrapper.vm.$root, '$emit'); modalTrigger.trigger('click'); - return wrapper.vm.$nextTick().then(() => { - expect(rootEmit.mock.calls[0]).toContainEqual(modalId); - }); + await nextTick(); + expect(rootEmit.mock.calls[0]).toContainEqual(modalId); }); it('modal gets passed correct props', () => { diff --git a/spec/frontend/monitoring/components/dashboard_header_spec.js b/spec/frontend/monitoring/components/dashboard_header_spec.js index 8be7d641953..e28c2913949 100644 --- a/spec/frontend/monitoring/components/dashboard_header_spec.js +++ b/spec/frontend/monitoring/components/dashboard_header_spec.js @@ -1,5 +1,6 @@ import { GlDropdownItem, GlSearchBoxByType, GlLoadingIcon, GlButton } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import { redirectTo } from '~/lib/utils/url_utility'; import ActionsMenu from '~/monitoring/components/dashboard_actions_menu.vue'; import DashboardHeader from '~/monitoring/components/dashboard_header.vue'; @@ -110,9 +111,9 @@ describe('Dashboard header', () => { }); describe('when environments data is not loaded', () => { - beforeEach(() => { + beforeEach(async () => { setupStoreWithDashboard(store); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('there are no environments listed', () => { @@ -124,13 +125,13 @@ describe('Dashboard header', () => { const currentDashboard = dashboardGitResponse[0].path; const currentEnvironmentName = environmentData[0].name; - beforeEach(() => { + beforeEach(async () => { setupStoreWithData(store); store.state.monitoringDashboard.projectPath = mockProjectPath; store.state.monitoringDashboard.currentDashboard = currentDashboard; store.state.monitoringDashboard.currentEnvironmentName = currentEnvironmentName; - return wrapper.vm.$nextTick(); + await nextTick(); }); it('renders dropdown items with the environment name', () => { @@ -159,51 +160,41 @@ describe('Dashboard header', () => { expect(selectedItems.at(0).text()).toBe(currentEnvironmentName); }); - it('filters rendered dropdown items', () => { + it('filters rendered dropdown items', async () => { const searchTerm = 'production'; const resultEnvs = environmentData.filter(({ name }) => name.indexOf(searchTerm) !== -1); setSearchTerm(searchTerm); - return wrapper.vm.$nextTick().then(() => { - expect(findEnvsDropdownItems()).toHaveLength(resultEnvs.length); - }); + await nextTick(); + expect(findEnvsDropdownItems()).toHaveLength(resultEnvs.length); }); - it('does not filter dropdown items if search term is empty string', () => { + it('does not filter dropdown items if search term is empty string', async () => { const searchTerm = ''; setSearchTerm(searchTerm); - return wrapper.vm.$nextTick(() => { - expect(findEnvsDropdownItems()).toHaveLength(environmentData.length); - }); + await nextTick(); + expect(findEnvsDropdownItems()).toHaveLength(environmentData.length); }); - it("shows error message if search term doesn't match", () => { + it("shows error message if search term doesn't match", async () => { const searchTerm = 'does-not-exist'; setSearchTerm(searchTerm); - return wrapper.vm.$nextTick(() => { - expect(findEnvsDropdownSearchMsg().isVisible()).toBe(true); - }); + await nextTick(); + expect(findEnvsDropdownSearchMsg().isVisible()).toBe(true); }); - it('shows loading element when environments fetch is still loading', () => { + it('shows loading element when environments fetch is still loading', async () => { store.commit(`monitoringDashboard/${types.REQUEST_ENVIRONMENTS_DATA}`); - return wrapper.vm - .$nextTick() - .then(() => { - expect(findEnvsDropdownLoadingIcon().exists()).toBe(true); - }) - .then(() => { - store.commit( - `monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`, - environmentData, - ); - }) - .then(() => { - expect(findEnvsDropdownLoadingIcon().exists()).toBe(false); - }); + await nextTick(); + expect(findEnvsDropdownLoadingIcon().exists()).toBe(true); + await store.commit( + `monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`, + environmentData, + ); + expect(findEnvsDropdownLoadingIcon().exists()).toBe(false); }); }); }); @@ -262,11 +253,11 @@ describe('Dashboard header', () => { }); describe('external dashboard link', () => { - beforeEach(() => { + beforeEach(async () => { store.state.monitoringDashboard.externalDashboardUrl = '/mockUrl'; createShallowWrapper(); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('shows the link', () => { @@ -295,82 +286,78 @@ describe('Dashboard header', () => { }); describe('adding metrics prop', () => { - it.each(ootbDashboards)('gets passed true if current dashboard is OOTB', (dashboardPath) => { - createShallowWrapper({ customMetricsAvailable: true }); + it.each(ootbDashboards)( + 'gets passed true if current dashboard is OOTB', + async (dashboardPath) => { + createShallowWrapper({ customMetricsAvailable: true }); - store.state.monitoringDashboard.emptyState = false; - setupAllDashboards(store, dashboardPath); + store.state.monitoringDashboard.emptyState = false; + setupAllDashboards(store, dashboardPath); - return wrapper.vm.$nextTick().then(() => { + await nextTick(); expect(findActionsMenu().props('addingMetricsAvailable')).toBe(true); - }); - }); + }, + ); it.each(customDashboards)( 'gets passed false if current dashboard is custom', - (dashboardPath) => { + async (dashboardPath) => { createShallowWrapper({ customMetricsAvailable: true }); store.state.monitoringDashboard.emptyState = false; setupAllDashboards(store, dashboardPath); - return wrapper.vm.$nextTick().then(() => { - expect(findActionsMenu().props('addingMetricsAvailable')).toBe(false); - }); + await nextTick(); + expect(findActionsMenu().props('addingMetricsAvailable')).toBe(false); }, ); - it('gets passed false if empty state is shown', () => { + it('gets passed false if empty state is shown', async () => { createShallowWrapper({ customMetricsAvailable: true }); store.state.monitoringDashboard.emptyState = true; setupAllDashboards(store, ootbDashboards[0]); - return wrapper.vm.$nextTick().then(() => { - expect(findActionsMenu().props('addingMetricsAvailable')).toBe(false); - }); + await nextTick(); + expect(findActionsMenu().props('addingMetricsAvailable')).toBe(false); }); - it('gets passed false if custom metrics are not available', () => { + it('gets passed false if custom metrics are not available', async () => { createShallowWrapper({ customMetricsAvailable: false }); store.state.monitoringDashboard.emptyState = false; setupAllDashboards(store, ootbDashboards[0]); - return wrapper.vm.$nextTick().then(() => { - expect(findActionsMenu().props('addingMetricsAvailable')).toBe(false); - }); + await nextTick(); + expect(findActionsMenu().props('addingMetricsAvailable')).toBe(false); }); }); - it('custom metrics path gets passed', () => { + it('custom metrics path gets passed', async () => { const path = 'https://path/to/customMetrics'; createShallowWrapper({ customMetricsPath: path }); - return wrapper.vm.$nextTick().then(() => { - expect(findActionsMenu().props('customMetricsPath')).toBe(path); - }); + await nextTick(); + expect(findActionsMenu().props('customMetricsPath')).toBe(path); }); - it('validate query path gets passed', () => { + it('validate query path gets passed', async () => { const path = 'https://path/to/validateQuery'; createShallowWrapper({ validateQueryPath: path }); - return wrapper.vm.$nextTick().then(() => { - expect(findActionsMenu().props('validateQueryPath')).toBe(path); - }); + await nextTick(); + expect(findActionsMenu().props('validateQueryPath')).toBe(path); }); - it('default branch gets passed', () => { + it('default branch gets passed', async () => { const branch = 'branchName'; createShallowWrapper({ defaultBranch: branch }); - return wrapper.vm.$nextTick().then(() => { - expect(findActionsMenu().props('defaultBranch')).toBe(branch); - }); + await nextTick(); + expect(findActionsMenu().props('defaultBranch')).toBe(branch); }); }); @@ -385,40 +372,36 @@ describe('Dashboard header', () => { store.state.monitoringDashboard.operationsSettingsPath = ''; }); - it('is rendered when the user can access the project settings and path to settings is available', () => { + it('is rendered when the user can access the project settings and path to settings is available', async () => { store.state.monitoringDashboard.canAccessOperationsSettings = true; store.state.monitoringDashboard.operationsSettingsPath = url; - return wrapper.vm.$nextTick(() => { - expect(findSettingsButton().exists()).toBe(true); - }); + await nextTick(); + expect(findSettingsButton().exists()).toBe(true); }); - it('is not rendered when the user can not access the project settings', () => { + it('is not rendered when the user can not access the project settings', async () => { store.state.monitoringDashboard.canAccessOperationsSettings = false; store.state.monitoringDashboard.operationsSettingsPath = url; - return wrapper.vm.$nextTick(() => { - expect(findSettingsButton().exists()).toBe(false); - }); + await nextTick(); + expect(findSettingsButton().exists()).toBe(false); }); - it('is not rendered when the path to settings is unavailable', () => { + it('is not rendered when the path to settings is unavailable', async () => { store.state.monitoringDashboard.canAccessOperationsSettings = false; store.state.monitoringDashboard.operationsSettingsPath = ''; - return wrapper.vm.$nextTick(() => { - expect(findSettingsButton().exists()).toBe(false); - }); + await nextTick(); + expect(findSettingsButton().exists()).toBe(false); }); - it('leads to the project settings page', () => { + it('leads to the project settings page', async () => { store.state.monitoringDashboard.canAccessOperationsSettings = true; store.state.monitoringDashboard.operationsSettingsPath = url; - return wrapper.vm.$nextTick(() => { - expect(findSettingsButton().attributes('href')).toBe(url); - }); + await nextTick(); + expect(findSettingsButton().attributes('href')).toBe(url); }); }); }); diff --git a/spec/frontend/monitoring/components/dashboard_panel_builder_spec.js b/spec/frontend/monitoring/components/dashboard_panel_builder_spec.js index 400ac2e8f85..f19ef6c6fb7 100644 --- a/spec/frontend/monitoring/components/dashboard_panel_builder_spec.js +++ b/spec/frontend/monitoring/components/dashboard_panel_builder_spec.js @@ -1,5 +1,6 @@ import { GlCard, GlForm, GlFormTextarea, GlAlert } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import DashboardPanel from '~/monitoring/components/dashboard_panel.vue'; import DashboardPanelBuilder from '~/monitoring/components/dashboard_panel_builder.vue'; import { createStore } from '~/monitoring/stores'; @@ -90,21 +91,20 @@ describe('dashboard invalid url parameters', () => { expect(mockShowToast).toHaveBeenCalledTimes(1); }); - it('on submit fetches a panel preview', () => { + it('on submit fetches a panel preview', async () => { findForm().vm.$emit('submit', new Event('submit')); - return wrapper.vm.$nextTick().then(() => { - expect(store.dispatch).toHaveBeenCalledWith( - 'monitoringDashboard/fetchPanelPreview', - expect.stringContaining('title:'), - ); - }); + await nextTick(); + expect(store.dispatch).toHaveBeenCalledWith( + 'monitoringDashboard/fetchPanelPreview', + expect.stringContaining('title:'), + ); }); describe('when form is submitted', () => { - beforeEach(() => { + beforeEach(async () => { store.commit(`monitoringDashboard/${types.REQUEST_PANEL_PREVIEW}`, 'mock yml content'); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('submit button is disabled', () => { @@ -118,23 +118,21 @@ describe('dashboard invalid url parameters', () => { expect(findTimeRangePicker().exists()).toBe(true); }); - it('when changed does not trigger data fetch unless preview panel button is clicked', () => { + it('when changed does not trigger data fetch unless preview panel button is clicked', async () => { // mimic initial state where SET_PANEL_PREVIEW_IS_SHOWN is set to false store.commit(`monitoringDashboard/${types.SET_PANEL_PREVIEW_IS_SHOWN}`, false); - return wrapper.vm.$nextTick(() => { - expect(store.dispatch).not.toHaveBeenCalled(); - }); + await nextTick(); + expect(store.dispatch).not.toHaveBeenCalled(); }); - it('when changed triggers data fetch if preview panel button is clicked', () => { + it('when changed triggers data fetch if preview panel button is clicked', async () => { findForm().vm.$emit('submit', new Event('submit')); store.commit(`monitoringDashboard/${types.SET_PANEL_PREVIEW_TIME_RANGE}`, mockTimeRange); - return wrapper.vm.$nextTick(() => { - expect(store.dispatch).toHaveBeenCalled(); - }); + await nextTick(); + expect(store.dispatch).toHaveBeenCalled(); }); }); @@ -143,27 +141,25 @@ describe('dashboard invalid url parameters', () => { expect(findRefreshButton().exists()).toBe(true); }); - it('when clicked does not trigger data fetch unless preview panel button is clicked', () => { + it('when clicked does not trigger data fetch unless preview panel button is clicked', async () => { // mimic initial state where SET_PANEL_PREVIEW_IS_SHOWN is set to false store.commit(`monitoringDashboard/${types.SET_PANEL_PREVIEW_IS_SHOWN}`, false); - return wrapper.vm.$nextTick(() => { - expect(store.dispatch).not.toHaveBeenCalled(); - }); + await nextTick(); + expect(store.dispatch).not.toHaveBeenCalled(); }); - it('when clicked triggers data fetch if preview panel button is clicked', () => { + it('when clicked triggers data fetch if preview panel button is clicked', async () => { // mimic state where preview is visible. SET_PANEL_PREVIEW_IS_SHOWN is set to true store.commit(`monitoringDashboard/${types.SET_PANEL_PREVIEW_IS_SHOWN}`, true); findRefreshButton().vm.$emit('click'); - return wrapper.vm.$nextTick(() => { - expect(store.dispatch).toHaveBeenCalledWith( - 'monitoringDashboard/fetchPanelPreviewMetrics', - undefined, - ); - }); + await nextTick(); + expect(store.dispatch).toHaveBeenCalledWith( + 'monitoringDashboard/fetchPanelPreviewMetrics', + undefined, + ); }); }); @@ -190,9 +186,9 @@ describe('dashboard invalid url parameters', () => { describe('when there is an error', () => { const mockError = 'an error occurred!'; - beforeEach(() => { + beforeEach(async () => { store.commit(`monitoringDashboard/${types.RECEIVE_PANEL_PREVIEW_FAILURE}`, mockError); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('displays an alert', () => { @@ -204,19 +200,18 @@ describe('dashboard invalid url parameters', () => { expect(findPanel().props('graphData')).toBe(null); }); - it('changing time range should not refetch data', () => { + it('changing time range should not refetch data', async () => { store.commit(`monitoringDashboard/${types.SET_PANEL_PREVIEW_TIME_RANGE}`, mockTimeRange); - return wrapper.vm.$nextTick(() => { - expect(store.dispatch).not.toHaveBeenCalled(); - }); + await nextTick(); + expect(store.dispatch).not.toHaveBeenCalled(); }); }); describe('when panel data is available', () => { - beforeEach(() => { + beforeEach(async () => { store.commit(`monitoringDashboard/${types.RECEIVE_PANEL_PREVIEW_SUCCESS}`, mockPanel); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('displays no alert', () => { diff --git a/spec/frontend/monitoring/components/dashboard_panel_spec.js b/spec/frontend/monitoring/components/dashboard_panel_spec.js index 9a73dc820af..7bd062b81f1 100644 --- a/spec/frontend/monitoring/components/dashboard_panel_spec.js +++ b/spec/frontend/monitoring/components/dashboard_panel_spec.js @@ -2,6 +2,7 @@ import { GlDropdownItem } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import AxiosMockAdapter from 'axios-mock-adapter'; import Vuex from 'vuex'; +import { nextTick } from 'vue'; import { setTestTimeout } from 'helpers/timeout'; import axios from '~/lib/utils/axios_utils'; import invalidUrl from '~/lib/utils/invalid_url'; @@ -186,7 +187,7 @@ describe('Dashboard Panel', () => { expect(findCopyLink().exists()).toBe(false); }); - it('should emit `timerange` event when a zooming in/out in a chart occcurs', () => { + it('should emit `timerange` event when a zooming in/out in a chart occcurs', async () => { const timeRange = { start: '2020-01-01T00:00:00.000Z', end: '2020-01-01T01:00:00.000Z', @@ -196,9 +197,8 @@ describe('Dashboard Panel', () => { findTimeChart().vm.$emit('datazoom', timeRange); - return wrapper.vm.$nextTick(() => { - expect(wrapper.vm.$emit).toHaveBeenCalledWith('timerangezoom', timeRange); - }); + await nextTick(); + expect(wrapper.vm.$emit).toHaveBeenCalledWith('timerangezoom', timeRange); }); it('includes a default group id', () => { @@ -253,16 +253,15 @@ describe('Dashboard Panel', () => { describe('computed', () => { describe('fixedCurrentTimeRange', () => { - it('returns fixed time for valid time range', () => { + it('returns fixed time for valid time range', async () => { state.timeRange = mockTimeRange; - return wrapper.vm.$nextTick(() => { - expect(findTimeChart().props('timeRange')).toEqual( - expect.objectContaining({ - start: expect.any(String), - end: expect.any(String), - }), - ); - }); + await nextTick(); + expect(findTimeChart().props('timeRange')).toEqual( + expect.objectContaining({ + start: expect.any(String), + end: expect.any(String), + }), + ); }); it.each` @@ -271,11 +270,10 @@ describe('Dashboard Panel', () => { ${undefined} | ${{}} ${null} | ${{}} ${'2020-12-03'} | ${{}} - `('returns $output for invalid input like $input', ({ input, output }) => { + `('returns $output for invalid input like $input', async ({ input, output }) => { state.timeRange = input; - return wrapper.vm.$nextTick(() => { - expect(findTimeChart().props('timeRange')).toEqual(output); - }); + await nextTick(); + expect(findTimeChart().props('timeRange')).toEqual(output); }); }); }); @@ -285,17 +283,16 @@ describe('Dashboard Panel', () => { const findEditCustomMetricLink = () => wrapper.find({ ref: 'editMetricLink' }); const mockEditPath = '/root/kubernetes-gke-project/prometheus/metrics/23/edit'; - beforeEach(() => { + beforeEach(async () => { createWrapper(); - - return wrapper.vm.$nextTick(); + await nextTick(); }); it('is not present if the panel is not a custom metric', () => { expect(findEditCustomMetricLink().exists()).toBe(false); }); - it('is present when the panel contains an edit_path property', () => { + it('is present when the panel contains an edit_path property', async () => { wrapper.setProps({ graphData: { ...graphData, @@ -308,14 +305,13 @@ describe('Dashboard Panel', () => { }, }); - return wrapper.vm.$nextTick(() => { - expect(findEditCustomMetricLink().exists()).toBe(true); - expect(findEditCustomMetricLink().text()).toBe('Edit metric'); - expect(findEditCustomMetricLink().attributes('href')).toBe(mockEditPath); - }); + await nextTick(); + expect(findEditCustomMetricLink().exists()).toBe(true); + expect(findEditCustomMetricLink().text()).toBe('Edit metric'); + expect(findEditCustomMetricLink().attributes('href')).toBe(mockEditPath); }); - it('shows an "Edit metrics" link pointing to settingsPath for a panel with multiple metrics', () => { + it('shows an "Edit metrics" link pointing to settingsPath for a panel with multiple metrics', async () => { wrapper.setProps({ graphData: { ...graphData, @@ -332,63 +328,58 @@ describe('Dashboard Panel', () => { }, }); - return wrapper.vm.$nextTick(() => { - expect(findEditCustomMetricLink().text()).toBe('Edit metrics'); - expect(findEditCustomMetricLink().attributes('href')).toBe(dashboardProps.settingsPath); - }); + await nextTick(); + expect(findEditCustomMetricLink().text()).toBe('Edit metrics'); + expect(findEditCustomMetricLink().attributes('href')).toBe(dashboardProps.settingsPath); }); }); describe('View Logs dropdown item', () => { const findViewLogsLink = () => wrapper.find({ ref: 'viewLogsLink' }); - beforeEach(() => { + beforeEach(async () => { createWrapper(); - return wrapper.vm.$nextTick(); + await nextTick(); }); - it('is not present by default', () => - wrapper.vm.$nextTick(() => { - expect(findViewLogsLink().exists()).toBe(false); - })); + it('is not present by default', async () => { + await nextTick(); + expect(findViewLogsLink().exists()).toBe(false); + }); - it('is not present if a time range is not set', () => { + it('is not present if a time range is not set', async () => { state.logsPath = mockLogsPath; state.timeRange = null; - return wrapper.vm.$nextTick(() => { - expect(findViewLogsLink().exists()).toBe(false); - }); + await nextTick(); + expect(findViewLogsLink().exists()).toBe(false); }); - it('is not present if the logs path is default', () => { + it('is not present if the logs path is default', async () => { state.logsPath = invalidUrl; state.timeRange = mockTimeRange; - return wrapper.vm.$nextTick(() => { - expect(findViewLogsLink().exists()).toBe(false); - }); + await nextTick(); + expect(findViewLogsLink().exists()).toBe(false); }); - it('is not present if the logs path is not set', () => { + it('is not present if the logs path is not set', async () => { state.logsPath = null; state.timeRange = mockTimeRange; - return wrapper.vm.$nextTick(() => { - expect(findViewLogsLink().exists()).toBe(false); - }); + await nextTick(); + expect(findViewLogsLink().exists()).toBe(false); }); - it('is present when logs path and time a range is present', () => { + it('is present when logs path and time a range is present', async () => { state.logsPath = mockLogsPath; state.timeRange = mockTimeRange; - return wrapper.vm.$nextTick(() => { - expect(findViewLogsLink().attributes('href')).toMatch(mockLogsHref); - }); + await nextTick(); + expect(findViewLogsLink().attributes('href')).toMatch(mockLogsHref); }); - it('it is overridden when a datazoom event is received', () => { + it('it is overridden when a datazoom event is received', async () => { state.logsPath = mockLogsPath; state.timeRange = mockTimeRange; @@ -399,13 +390,12 @@ describe('Dashboard Panel', () => { findTimeChart().vm.$emit('datazoom', zoomedTimeRange); - return wrapper.vm.$nextTick(() => { - const start = encodeURIComponent(zoomedTimeRange.start); - const end = encodeURIComponent(zoomedTimeRange.end); - expect(findViewLogsLink().attributes('href')).toMatch( - `${mockLogsPath}?start=${start}&end=${end}`, - ); - }); + await nextTick(); + const start = encodeURIComponent(zoomedTimeRange.start); + const end = encodeURIComponent(zoomedTimeRange.end); + expect(findViewLogsLink().attributes('href')).toMatch( + `${mockLogsPath}?start=${start}&end=${end}`, + ); }); }); @@ -447,7 +437,7 @@ describe('Dashboard Panel', () => { }); describe('when downloading metrics data as CSV', () => { - beforeEach(() => { + beforeEach(async () => { wrapper = shallowMount(DashboardPanel, { propsData: { clipboardText: exampleText, @@ -459,7 +449,7 @@ describe('Dashboard Panel', () => { }, store, }); - return wrapper.vm.$nextTick(); + await nextTick(); }); afterEach(() => { @@ -509,29 +499,26 @@ describe('Dashboard Panel', () => { }); }); - it('handles namespaced time range and logs path state', () => { + it('handles namespaced time range and logs path state', async () => { store.state[mockNamespace].timeRange = mockTimeRange; store.state[mockNamespace].logsPath = mockLogsPath; - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.find({ ref: 'viewLogsLink' }).attributes().href).toBe(mockLogsHref); - }); + await nextTick(); + expect(wrapper.find({ ref: 'viewLogsLink' }).attributes().href).toBe(mockLogsHref); }); - it('handles namespaced deployment data state', () => { + it('handles namespaced deployment data state', async () => { store.state[mockNamespace].deploymentData = mockDeploymentData; - return wrapper.vm.$nextTick().then(() => { - expect(findTimeChart().props().deploymentData).toEqual(mockDeploymentData); - }); + await nextTick(); + expect(findTimeChart().props().deploymentData).toEqual(mockDeploymentData); }); - it('handles namespaced project path state', () => { + it('handles namespaced project path state', async () => { store.state[mockNamespace].projectPath = mockProjectPath; - return wrapper.vm.$nextTick().then(() => { - expect(findTimeChart().props().projectPath).toBe(mockProjectPath); - }); + await nextTick(); + expect(findTimeChart().props().projectPath).toBe(mockProjectPath); }); it('it renders a time series chart with no errors', () => { diff --git a/spec/frontend/monitoring/components/dashboard_spec.js b/spec/frontend/monitoring/components/dashboard_spec.js index 7730e7f347f..6c5972e1140 100644 --- a/spec/frontend/monitoring/components/dashboard_spec.js +++ b/spec/frontend/monitoring/components/dashboard_spec.js @@ -1,5 +1,6 @@ import MockAdapter from 'axios-mock-adapter'; import VueDraggable from 'vuedraggable'; +import { nextTick } from 'vue'; import setWindowLocation from 'helpers/set_window_location_helper'; import { TEST_HOST } from 'helpers/test_constants'; import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper'; @@ -77,51 +78,47 @@ describe('Dashboard', () => { }); describe('request information to the server', () => { - it('calls to set time range and fetch data', () => { + it('calls to set time range and fetch data', async () => { createShallowWrapper({ hasMetrics: true }); - return wrapper.vm.$nextTick().then(() => { - expect(store.dispatch).toHaveBeenCalledWith( - 'monitoringDashboard/setTimeRange', - expect.any(Object), - ); + await nextTick(); + expect(store.dispatch).toHaveBeenCalledWith( + 'monitoringDashboard/setTimeRange', + expect.any(Object), + ); - expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/fetchData', undefined); - }); + expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/fetchData', undefined); }); - it('shows up a loading state', () => { + it('shows up a loading state', async () => { store.state.monitoringDashboard.emptyState = dashboardEmptyStates.LOADING; createShallowWrapper({ hasMetrics: true }); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.find(EmptyState).exists()).toBe(true); - expect(wrapper.find(EmptyState).props('selectedState')).toBe(dashboardEmptyStates.LOADING); - }); + await nextTick(); + expect(wrapper.find(EmptyState).exists()).toBe(true); + expect(wrapper.find(EmptyState).props('selectedState')).toBe(dashboardEmptyStates.LOADING); }); - it('hides the group panels when showPanels is false', () => { + it('hides the group panels when showPanels is false', async () => { createMountedWrapper({ hasMetrics: true, showPanels: false }); setupStoreWithData(store); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.vm.emptyState).toBeNull(); - expect(wrapper.findAll('.prometheus-panel')).toHaveLength(0); - }); + await nextTick(); + expect(wrapper.vm.emptyState).toBeNull(); + expect(wrapper.findAll('.prometheus-panel')).toHaveLength(0); }); - it('fetches the metrics data with proper time window', () => { + it('fetches the metrics data with proper time window', async () => { createMountedWrapper({ hasMetrics: true }); - return wrapper.vm.$nextTick().then(() => { - expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/fetchData', undefined); - expect(store.dispatch).toHaveBeenCalledWith( - 'monitoringDashboard/setTimeRange', - expect.objectContaining({ duration: { seconds: 28800 } }), - ); - }); + await nextTick(); + expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/fetchData', undefined); + expect(store.dispatch).toHaveBeenCalledWith( + 'monitoringDashboard/setTimeRange', + expect.objectContaining({ duration: { seconds: 28800 } }), + ); }); }); @@ -133,69 +130,63 @@ describe('Dashboard', () => { .at(index); }; - beforeEach(() => { + beforeEach(async () => { createMountedWrapper({ hasMetrics: true }); - - return wrapper.vm.$nextTick(); + await nextTick(); }); describe('when the graph group has an even number of panels', () => { - it('2 panels - all panel wrappers take half width of their parent', () => { + it('2 panels - all panel wrappers take half width of their parent', async () => { setupStoreWithDataForPanelCount(store, 2); - wrapper.vm.$nextTick(() => { - expect(findPanelLayoutWrapperAt(0).classes('col-lg-6')).toBe(true); - expect(findPanelLayoutWrapperAt(1).classes('col-lg-6')).toBe(true); - }); + await nextTick(); + expect(findPanelLayoutWrapperAt(0).classes('col-lg-6')).toBe(true); + expect(findPanelLayoutWrapperAt(1).classes('col-lg-6')).toBe(true); }); - it('4 panels - all panel wrappers take half width of their parent', () => { + it('4 panels - all panel wrappers take half width of their parent', async () => { setupStoreWithDataForPanelCount(store, 4); - wrapper.vm.$nextTick(() => { - expect(findPanelLayoutWrapperAt(0).classes('col-lg-6')).toBe(true); - expect(findPanelLayoutWrapperAt(1).classes('col-lg-6')).toBe(true); - expect(findPanelLayoutWrapperAt(2).classes('col-lg-6')).toBe(true); - expect(findPanelLayoutWrapperAt(3).classes('col-lg-6')).toBe(true); - }); + await nextTick(); + expect(findPanelLayoutWrapperAt(0).classes('col-lg-6')).toBe(true); + expect(findPanelLayoutWrapperAt(1).classes('col-lg-6')).toBe(true); + expect(findPanelLayoutWrapperAt(2).classes('col-lg-6')).toBe(true); + expect(findPanelLayoutWrapperAt(3).classes('col-lg-6')).toBe(true); }); }); describe('when the graph group has an odd number of panels', () => { - it('1 panel - panel wrapper does not take half width of its parent', () => { + it('1 panel - panel wrapper does not take half width of its parent', async () => { setupStoreWithDataForPanelCount(store, 1); - wrapper.vm.$nextTick(() => { - expect(findPanelLayoutWrapperAt(0).classes('col-lg-6')).toBe(false); - }); + await nextTick(); + expect(findPanelLayoutWrapperAt(0).classes('col-lg-6')).toBe(false); }); - it('3 panels - all panels but last take half width of their parents', () => { + it('3 panels - all panels but last take half width of their parents', async () => { setupStoreWithDataForPanelCount(store, 3); - wrapper.vm.$nextTick(() => { - expect(findPanelLayoutWrapperAt(0).classes('col-lg-6')).toBe(true); - expect(findPanelLayoutWrapperAt(1).classes('col-lg-6')).toBe(true); - expect(findPanelLayoutWrapperAt(2).classes('col-lg-6')).toBe(false); - }); + await nextTick(); + expect(findPanelLayoutWrapperAt(0).classes('col-lg-6')).toBe(true); + expect(findPanelLayoutWrapperAt(1).classes('col-lg-6')).toBe(true); + expect(findPanelLayoutWrapperAt(2).classes('col-lg-6')).toBe(false); }); - it('5 panels - all panels but last take half width of their parents', () => { + it('5 panels - all panels but last take half width of their parents', async () => { setupStoreWithDataForPanelCount(store, 5); - wrapper.vm.$nextTick(() => { - expect(findPanelLayoutWrapperAt(0).classes('col-lg-6')).toBe(true); - expect(findPanelLayoutWrapperAt(1).classes('col-lg-6')).toBe(true); - expect(findPanelLayoutWrapperAt(2).classes('col-lg-6')).toBe(true); - expect(findPanelLayoutWrapperAt(3).classes('col-lg-6')).toBe(true); - expect(findPanelLayoutWrapperAt(4).classes('col-lg-6')).toBe(false); - }); + await nextTick(); + expect(findPanelLayoutWrapperAt(0).classes('col-lg-6')).toBe(true); + expect(findPanelLayoutWrapperAt(1).classes('col-lg-6')).toBe(true); + expect(findPanelLayoutWrapperAt(2).classes('col-lg-6')).toBe(true); + expect(findPanelLayoutWrapperAt(3).classes('col-lg-6')).toBe(true); + expect(findPanelLayoutWrapperAt(4).classes('col-lg-6')).toBe(false); }); }); }); describe('dashboard validation warning', () => { - it('displays a warning if there are validation warnings', () => { + it('displays a warning if there are validation warnings', async () => { createMountedWrapper({ hasMetrics: true }); store.commit( @@ -203,12 +194,11 @@ describe('Dashboard', () => { true, ); - return wrapper.vm.$nextTick().then(() => { - expect(createFlash).toHaveBeenCalled(); - }); + await nextTick(); + expect(createFlash).toHaveBeenCalled(); }); - it('does not display a warning if there are no validation warnings', () => { + it('does not display a warning if there are no validation warnings', async () => { createMountedWrapper({ hasMetrics: true }); store.commit( @@ -216,9 +206,8 @@ describe('Dashboard', () => { false, ); - return wrapper.vm.$nextTick().then(() => { - expect(createFlash).not.toHaveBeenCalled(); - }); + await nextTick(); + expect(createFlash).not.toHaveBeenCalled(); }); }); @@ -233,7 +222,7 @@ describe('Dashboard', () => { setWindowLocation(location); }); - it('when the URL points to a panel it expands', () => { + it('when the URL points to a panel it expands', async () => { const panelGroup = metricsDashboardViewModel.panelGroups[0]; const panel = panelGroup.panels[0]; @@ -246,32 +235,30 @@ describe('Dashboard', () => { createMountedWrapper({ hasMetrics: true }); setupStoreWithData(store); - return wrapper.vm.$nextTick().then(() => { - expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/setExpandedPanel', { - group: panelGroup.group, - panel: expect.objectContaining({ - title: panel.title, - y_label: panel.y_label, - }), - }); + await nextTick(); + expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/setExpandedPanel', { + group: panelGroup.group, + panel: expect.objectContaining({ + title: panel.title, + y_label: panel.y_label, + }), }); }); - it('when the URL does not link to any panel, no panel is expanded', () => { + it('when the URL does not link to any panel, no panel is expanded', async () => { setSearch(); createMountedWrapper({ hasMetrics: true }); setupStoreWithData(store); - return wrapper.vm.$nextTick().then(() => { - expect(store.dispatch).not.toHaveBeenCalledWith( - 'monitoringDashboard/setExpandedPanel', - expect.anything(), - ); - }); + await nextTick(); + expect(store.dispatch).not.toHaveBeenCalledWith( + 'monitoringDashboard/setExpandedPanel', + expect.anything(), + ); }); - it('when the URL points to an incorrect panel it shows an error', () => { + it('when the URL points to an incorrect panel it shows an error', async () => { const panelGroup = metricsDashboardViewModel.panelGroups[0]; const panel = panelGroup.panels[0]; @@ -284,13 +271,12 @@ describe('Dashboard', () => { createMountedWrapper({ hasMetrics: true }); setupStoreWithData(store); - return wrapper.vm.$nextTick().then(() => { - expect(createFlash).toHaveBeenCalled(); - expect(store.dispatch).not.toHaveBeenCalledWith( - 'monitoringDashboard/setExpandedPanel', - expect.anything(), - ); - }); + await nextTick(); + expect(createFlash).toHaveBeenCalled(); + expect(store.dispatch).not.toHaveBeenCalledWith( + 'monitoringDashboard/setExpandedPanel', + expect.anything(), + ); }); }); @@ -319,7 +305,7 @@ describe('Dashboard', () => { window.history.pushState.mockRestore(); }); - it('URL is updated with panel parameters', () => { + it('URL is updated with panel parameters', async () => { createMountedWrapper({ hasMetrics: true }); expandPanel(group, panel); @@ -329,17 +315,16 @@ describe('Dashboard', () => { y_label: panel.y_label, }); - return wrapper.vm.$nextTick(() => { - expect(window.history.pushState).toHaveBeenCalledTimes(1); - expect(window.history.pushState).toHaveBeenCalledWith( - expect.anything(), // state - expect.any(String), // document title - expect.stringContaining(`${expectedSearch}`), - ); - }); + await nextTick(); + expect(window.history.pushState).toHaveBeenCalledTimes(1); + expect(window.history.pushState).toHaveBeenCalledWith( + expect.anything(), // state + expect.any(String), // document title + expect.stringContaining(`${expectedSearch}`), + ); }); - it('URL is updated with panel parameters and custom dashboard', () => { + it('URL is updated with panel parameters and custom dashboard', async () => { const dashboard = 'dashboard.yml'; store.commit(`monitoringDashboard/${types.SET_INITIAL_STATE}`, { @@ -355,36 +340,34 @@ describe('Dashboard', () => { y_label: panel.y_label, }); - return wrapper.vm.$nextTick(() => { - expect(window.history.pushState).toHaveBeenCalledTimes(1); - expect(window.history.pushState).toHaveBeenCalledWith( - expect.anything(), // state - expect.any(String), // document title - expect.stringContaining(`${expectedSearch}`), - ); - }); + await nextTick(); + expect(window.history.pushState).toHaveBeenCalledTimes(1); + expect(window.history.pushState).toHaveBeenCalledWith( + expect.anything(), // state + expect.any(String), // document title + expect.stringContaining(`${expectedSearch}`), + ); }); - it('URL is updated with no parameters', () => { + it('URL is updated with no parameters', async () => { expandPanel(group, panel); createMountedWrapper({ hasMetrics: true }); expandPanel(null, null); - return wrapper.vm.$nextTick(() => { - expect(window.history.pushState).toHaveBeenCalledTimes(1); - expect(window.history.pushState).toHaveBeenCalledWith( - expect.anything(), // state - expect.any(String), // document title - expect.not.stringMatching(/group|title|y_label/), // no panel params - ); - }); + await nextTick(); + expect(window.history.pushState).toHaveBeenCalledTimes(1); + expect(window.history.pushState).toHaveBeenCalledWith( + expect.anything(), // state + expect.any(String), // document title + expect.not.stringMatching(/group|title|y_label/), // no panel params + ); }); }); describe('when all panels in the first group are loading', () => { const findGroupAt = (i) => wrapper.findAll(GraphGroup).at(i); - beforeEach(() => { + beforeEach(async () => { setupStoreWithDashboard(store); const { panels } = store.state.monitoringDashboard.dashboard.panelGroups[0]; @@ -396,7 +379,7 @@ describe('Dashboard', () => { createShallowWrapper(); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('a loading icon appears in the first group', () => { @@ -409,7 +392,7 @@ describe('Dashboard', () => { }); describe('when all requests have been committed by the store', () => { - beforeEach(() => { + beforeEach(async () => { store.commit(`monitoringDashboard/${types.SET_INITIAL_STATE}`, { currentEnvironmentName: 'production', currentDashboard: dashboardGitResponse[0].path, @@ -418,26 +401,25 @@ describe('Dashboard', () => { createMountedWrapper({ hasMetrics: true }); setupStoreWithData(store); - return wrapper.vm.$nextTick(); + await nextTick(); }); - it('it does not show loading icons in any group', () => { + it('it does not show loading icons in any group', async () => { setupStoreWithData(store); - wrapper.vm.$nextTick(() => { - wrapper.findAll(GraphGroup).wrappers.forEach((groupWrapper) => { - expect(groupWrapper.props('isLoading')).toBe(false); - }); + await nextTick(); + wrapper.findAll(GraphGroup).wrappers.forEach((groupWrapper) => { + expect(groupWrapper.props('isLoading')).toBe(false); }); }); }); describe('variables section', () => { - beforeEach(() => { + beforeEach(async () => { createShallowWrapper({ hasMetrics: true }); setupStoreWithData(store); store.state.monitoringDashboard.variables = storeVariables; - return wrapper.vm.$nextTick(); + await nextTick(); }); it('shows the variables section', () => { @@ -446,12 +428,11 @@ describe('Dashboard', () => { }); describe('links section', () => { - beforeEach(() => { + beforeEach(async () => { createShallowWrapper({ hasMetrics: true }); setupStoreWithData(store); setupStoreWithLinks(store); - - return wrapper.vm.$nextTick(); + await nextTick(); }); it('shows the links section', () => { @@ -464,10 +445,10 @@ describe('Dashboard', () => { const findExpandedPanel = () => wrapper.find({ ref: 'expandedPanel' }); describe('when the panel is not expanded', () => { - beforeEach(() => { + beforeEach(async () => { createShallowWrapper({ hasMetrics: true }); setupStoreWithData(store); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('expanded panel is not visible', () => { @@ -502,7 +483,7 @@ describe('Dashboard', () => { template: `<div><slot name="top-left"/></div>`, }; - beforeEach(() => { + beforeEach(async () => { createShallowWrapper({ hasMetrics: true }, { stubs: { DashboardPanel: MockPanel } }); setupStoreWithData(store); @@ -517,8 +498,7 @@ describe('Dashboard', () => { }); jest.spyOn(store, 'dispatch'); - - return wrapper.vm.$nextTick(); + await nextTick(); }); it('displays a single panel and others are hidden', () => { @@ -561,13 +541,12 @@ describe('Dashboard', () => { }); describe('when one of the metrics is missing', () => { - beforeEach(() => { + beforeEach(async () => { createShallowWrapper({ hasMetrics: true }); setupStoreWithDashboard(store); setMetricResult({ store, result: [], panel: 2 }); - - return wrapper.vm.$nextTick(); + await nextTick(); }); it('shows a group empty area', () => { @@ -590,14 +569,13 @@ describe('Dashboard', () => { const findDraggablePanels = () => wrapper.findAll('.js-draggable-panel'); const findRearrangeButton = () => wrapper.find('.js-rearrange-button'); - beforeEach(() => { + beforeEach(async () => { // call original dispatch store.dispatch.mockRestore(); createShallowWrapper({ hasMetrics: true }); setupStoreWithData(store); - - return wrapper.vm.$nextTick(); + await nextTick(); }); it('wraps vuedraggable', () => { @@ -611,9 +589,9 @@ describe('Dashboard', () => { }); describe('when rearrange is enabled', () => { - beforeEach(() => { + beforeEach(async () => { wrapper.setProps({ rearrangePanelsAvailable: true }); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('displays rearrange button', () => { @@ -624,9 +602,9 @@ describe('Dashboard', () => { const findFirstDraggableRemoveButton = () => findDraggablePanels().at(0).find('.js-draggable-remove'); - beforeEach(() => { + beforeEach(async () => { findRearrangeButton().vm.$emit('click'); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('it enables draggables', () => { @@ -634,7 +612,7 @@ describe('Dashboard', () => { expect(findEnabledDraggables().wrappers).toEqual(findDraggables().wrappers); }); - it('metrics can be swapped', () => { + it('metrics can be swapped', async () => { const firstDraggable = findDraggables().at(0); const mockMetrics = [...metricsDashboardViewModel.panelGroups[0].panels]; @@ -645,43 +623,40 @@ describe('Dashboard', () => { [mockMetrics[0], mockMetrics[1]] = [mockMetrics[1], mockMetrics[0]]; firstDraggable.vm.$emit('input', mockMetrics); - return wrapper.vm.$nextTick(() => { - const { panels } = wrapper.vm.dashboard.panelGroups[0]; + await nextTick(); + const { panels } = wrapper.vm.dashboard.panelGroups[0]; - expect(panels[1].title).toEqual(firstTitle); - expect(panels[0].title).toEqual(secondTitle); - }); + expect(panels[1].title).toEqual(firstTitle); + expect(panels[0].title).toEqual(secondTitle); }); - it('shows a remove button, which removes a panel', () => { + it('shows a remove button, which removes a panel', async () => { expect(findFirstDraggableRemoveButton().find('a').exists()).toBe(true); expect(findDraggablePanels().length).toEqual(metricsDashboardPanelCount); findFirstDraggableRemoveButton().trigger('click'); - return wrapper.vm.$nextTick(() => { - expect(findDraggablePanels().length).toEqual(metricsDashboardPanelCount - 1); - }); + await nextTick(); + expect(findDraggablePanels().length).toEqual(metricsDashboardPanelCount - 1); }); - it('it disables draggables when clicked again', () => { + it('it disables draggables when clicked again', async () => { findRearrangeButton().vm.$emit('click'); - return wrapper.vm.$nextTick(() => { - expect(findRearrangeButton().attributes('pressed')).toBeFalsy(); - expect(findEnabledDraggables().length).toBe(0); - }); + await nextTick(); + expect(findRearrangeButton().attributes('pressed')).toBeFalsy(); + expect(findEnabledDraggables().length).toBe(0); }); }); }); }); describe('cluster health', () => { - beforeEach(() => { + beforeEach(async () => { createShallowWrapper({ hasMetrics: true, showHeader: false }); // all_dashboards is not defined in health dashboards store.commit(`monitoringDashboard/${types.SET_ALL_DASHBOARDS}`, undefined); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('hides dashboard header by default', () => { @@ -706,34 +681,31 @@ describe('Dashboard', () => { document.title = ''; }); - it('is prepended with the overview dashboard name by default', () => { + it('is prepended with the overview dashboard name by default', async () => { setupAllDashboards(store); - return wrapper.vm.$nextTick().then(() => { - expect(document.title.startsWith(`${overviewDashboardName} · `)).toBe(true); - }); + await nextTick(); + expect(document.title.startsWith(`${overviewDashboardName} · `)).toBe(true); }); - it('is prepended with dashboard name if path is known', () => { + it('is prepended with dashboard name if path is known', async () => { const dashboard = dashboardGitResponse[1]; const currentDashboard = dashboard.path; setupAllDashboards(store, currentDashboard); - return wrapper.vm.$nextTick().then(() => { - expect(document.title.startsWith(`${dashboard.display_name} · `)).toBe(true); - }); + await nextTick(); + expect(document.title.startsWith(`${dashboard.display_name} · `)).toBe(true); }); - it('is prepended with the overview dashboard name if path is not known', () => { + it('is prepended with the overview dashboard name if path is not known', async () => { setupAllDashboards(store, 'unknown/path'); - return wrapper.vm.$nextTick().then(() => { - expect(document.title.startsWith(`${overviewDashboardName} · `)).toBe(true); - }); + await nextTick(); + expect(document.title.startsWith(`${overviewDashboardName} · `)).toBe(true); }); - it('is not modified when dashboard name is not provided', () => { + it('is not modified when dashboard name is not provided', async () => { const dashboard = { ...dashboardGitResponse[1], display_name: null }; const currentDashboard = dashboard.path; @@ -743,9 +715,8 @@ describe('Dashboard', () => { currentDashboard, }); - return wrapper.vm.$nextTick().then(() => { - expect(document.title).toBe(originalTitle); - }); + await nextTick(); + expect(document.title).toBe(originalTitle); }); }); @@ -756,14 +727,13 @@ describe('Dashboard', () => { const getClipboardTextFirstPanel = () => wrapper.findAll(DashboardPanel).at(panelIndex).props('clipboardText'); - beforeEach(() => { + beforeEach(async () => { setupStoreWithData(store); store.commit(`monitoringDashboard/${types.SET_INITIAL_STATE}`, { currentDashboard, }); createShallowWrapper({ hasMetrics: true }); - - return wrapper.vm.$nextTick(); + await nextTick(); }); it('contains a link to the dashboard', () => { @@ -785,7 +755,7 @@ describe('Dashboard', () => { // the dashboard panels have a ref attribute set. const getDashboardPanel = () => wrapper.find({ ref: panelRef }); - beforeEach(() => { + beforeEach(async () => { setupStoreWithData(store); store.commit(`monitoringDashboard/${types.SET_INITIAL_STATE}`, { currentDashboard, @@ -795,8 +765,7 @@ describe('Dashboard', () => { // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax wrapper.setData({ hoveredPanel: panelRef }); - - return wrapper.vm.$nextTick(); + await nextTick(); }); it('contains a ref attribute inside a DashboardPanel component', () => { diff --git a/spec/frontend/monitoring/components/dashboard_url_time_spec.js b/spec/frontend/monitoring/components/dashboard_url_time_spec.js index e6785f34597..246dd598d19 100644 --- a/spec/frontend/monitoring/components/dashboard_url_time_spec.js +++ b/spec/frontend/monitoring/components/dashboard_url_time_spec.js @@ -1,5 +1,6 @@ import { mount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; +import { nextTick } from 'vue'; import createFlash from '~/flash'; import axios from '~/lib/utils/axios_utils'; import { @@ -51,23 +52,22 @@ describe('dashboard invalid url parameters', () => { queryToObject.mockReset(); }); - it('passes default url parameters to the time range picker', () => { + it('passes default url parameters to the time range picker', async () => { queryToObject.mockReturnValue({}); createMountedWrapper(); - return wrapper.vm.$nextTick().then(() => { - expect(findDateTimePicker().props('value')).toEqual(defaultTimeRange); + await nextTick(); + expect(findDateTimePicker().props('value')).toEqual(defaultTimeRange); - expect(store.dispatch).toHaveBeenCalledWith( - 'monitoringDashboard/setTimeRange', - expect.any(Object), - ); - expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/fetchData', undefined); - }); + expect(store.dispatch).toHaveBeenCalledWith( + 'monitoringDashboard/setTimeRange', + expect.any(Object), + ); + expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/fetchData', undefined); }); - it('passes a fixed time range in the URL to the time range picker', () => { + it('passes a fixed time range in the URL to the time range picker', async () => { const params = { start: '2019-01-01T00:00:00.000Z', end: '2019-01-10T00:00:00.000Z', @@ -77,37 +77,35 @@ describe('dashboard invalid url parameters', () => { createMountedWrapper(); - return wrapper.vm.$nextTick().then(() => { - expect(findDateTimePicker().props('value')).toEqual(params); + await nextTick(); + expect(findDateTimePicker().props('value')).toEqual(params); - expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/setTimeRange', params); - expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/fetchData', undefined); - }); + expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/setTimeRange', params); + expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/fetchData', undefined); }); - it('passes a rolling time range in the URL to the time range picker', () => { + it('passes a rolling time range in the URL to the time range picker', async () => { queryToObject.mockReturnValue({ duration_seconds: '120', }); createMountedWrapper(); - return wrapper.vm.$nextTick().then(() => { - const expectedTimeRange = { - duration: { seconds: 60 * 2 }, - }; + await nextTick(); + const expectedTimeRange = { + duration: { seconds: 60 * 2 }, + }; - expect(findDateTimePicker().props('value')).toMatchObject(expectedTimeRange); + expect(findDateTimePicker().props('value')).toMatchObject(expectedTimeRange); - expect(store.dispatch).toHaveBeenCalledWith( - 'monitoringDashboard/setTimeRange', - expectedTimeRange, - ); - expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/fetchData', undefined); - }); + expect(store.dispatch).toHaveBeenCalledWith( + 'monitoringDashboard/setTimeRange', + expectedTimeRange, + ); + expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/fetchData', undefined); }); - it('shows an error message and loads a default time range if invalid url parameters are passed', () => { + it('shows an error message and loads a default time range if invalid url parameters are passed', async () => { queryToObject.mockReturnValue({ start: '<script>alert("XSS")</script>', end: '<script>alert("XSS")</script>', @@ -115,37 +113,35 @@ describe('dashboard invalid url parameters', () => { createMountedWrapper(); - return wrapper.vm.$nextTick().then(() => { - expect(createFlash).toHaveBeenCalled(); + await nextTick(); + expect(createFlash).toHaveBeenCalled(); - expect(findDateTimePicker().props('value')).toEqual(defaultTimeRange); + expect(findDateTimePicker().props('value')).toEqual(defaultTimeRange); - expect(store.dispatch).toHaveBeenCalledWith( - 'monitoringDashboard/setTimeRange', - defaultTimeRange, - ); - expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/fetchData', undefined); - }); + expect(store.dispatch).toHaveBeenCalledWith( + 'monitoringDashboard/setTimeRange', + defaultTimeRange, + ); + expect(store.dispatch).toHaveBeenCalledWith('monitoringDashboard/fetchData', undefined); }); - it('redirects to different time range', () => { + it('redirects to different time range', async () => { const toUrl = `${mockProjectDir}/-/environments/1/metrics`; removeParams.mockReturnValueOnce(toUrl); createMountedWrapper(); - return wrapper.vm.$nextTick().then(() => { - findDateTimePicker().vm.$emit('input', { - duration: { seconds: 120 }, - }); - - // redirect to with new parameters - expect(mergeUrlParams).toHaveBeenCalledWith({ duration_seconds: '120' }, toUrl); - expect(redirectTo).toHaveBeenCalledTimes(1); + await nextTick(); + findDateTimePicker().vm.$emit('input', { + duration: { seconds: 120 }, }); + + // redirect to with new parameters + expect(mergeUrlParams).toHaveBeenCalledWith({ duration_seconds: '120' }, toUrl); + expect(redirectTo).toHaveBeenCalledTimes(1); }); - it('changes the url when a panel moves the time slider', () => { + it('changes the url when a panel moves the time slider', async () => { const timeRange = { start: '2020-01-01T00:00:00.000Z', end: '2020-01-01T01:00:00.000Z', @@ -155,12 +151,11 @@ describe('dashboard invalid url parameters', () => { createMountedWrapper(); - return wrapper.vm.$nextTick().then(() => { - wrapper.vm.onTimeRangeZoom(timeRange); + await nextTick(); + wrapper.vm.onTimeRangeZoom(timeRange); - expect(updateHistory).toHaveBeenCalled(); - expect(wrapper.vm.selectedTimeRange.start.toString()).toBe(timeRange.start); - expect(wrapper.vm.selectedTimeRange.end.toString()).toBe(timeRange.end); - }); + expect(updateHistory).toHaveBeenCalled(); + expect(wrapper.vm.selectedTimeRange.start.toString()).toBe(timeRange.start); + expect(wrapper.vm.selectedTimeRange.end.toString()).toBe(timeRange.end); }); }); diff --git a/spec/frontend/monitoring/components/embeds/embed_group_spec.js b/spec/frontend/monitoring/components/embeds/embed_group_spec.js index f6229afd180..47366b345a8 100644 --- a/spec/frontend/monitoring/components/embeds/embed_group_spec.js +++ b/spec/frontend/monitoring/components/embeds/embed_group_spec.js @@ -1,6 +1,6 @@ import { GlButton, GlCard } from '@gitlab/ui'; import { mount, shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import { TEST_HOST } from 'helpers/test_constants'; import EmbedGroup from '~/monitoring/components/embeds/embed_group.vue'; @@ -75,16 +75,14 @@ describe('Embed Group', () => { expect(wrapper.find('.gl-card-body').classes()).not.toContain('d-none'); }); - it('collapses when clicked', (done) => { + it('collapses when clicked', async () => { metricsWithDataGetter.mockReturnValue([1]); mountComponent({ shallow: false, stubs: { MetricEmbed: true } }); wrapper.find(GlButton).trigger('click'); - wrapper.vm.$nextTick(() => { - expect(wrapper.find('.gl-card-body').classes()).toContain('d-none'); - done(); - }); + await nextTick(); + expect(wrapper.find('.gl-card-body').classes()).toContain('d-none'); }); }); diff --git a/spec/frontend/monitoring/components/graph_group_spec.js b/spec/frontend/monitoring/components/graph_group_spec.js index 625dd3f0b33..c5b45564089 100644 --- a/spec/frontend/monitoring/components/graph_group_spec.js +++ b/spec/frontend/monitoring/components/graph_group_spec.js @@ -1,5 +1,6 @@ import { GlLoadingIcon, GlIcon } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import GraphGroup from '~/monitoring/components/graph_group.vue'; describe('Graph group component', () => { @@ -38,13 +39,12 @@ describe('Graph group component', () => { expect(findCaretIcon().props('name')).toBe('angle-down'); }); - it('should show the angle-right caret icon when the user collapses the group', () => { + it('should show the angle-right caret icon when the user collapses the group', async () => { findToggleButton().trigger('click'); - return wrapper.vm.$nextTick().then(() => { - expect(findContent().isVisible()).toBe(false); - expect(findCaretIcon().props('name')).toBe('angle-right'); - }); + await nextTick(); + expect(findContent().isVisible()).toBe(false); + expect(findCaretIcon().props('name')).toBe('angle-right'); }); it('should contain a tab index for the collapse button', () => { @@ -53,15 +53,14 @@ describe('Graph group component', () => { expect(groupToggle.attributes('tabindex')).toBeDefined(); }); - it('should show the open the group when collapseGroup is set to true', () => { + it('should show the open the group when collapseGroup is set to true', async () => { wrapper.setProps({ collapseGroup: true, }); - return wrapper.vm.$nextTick().then(() => { - expect(findContent().isVisible()).toBe(true); - expect(findCaretIcon().props('name')).toBe('angle-down'); - }); + await nextTick(); + expect(findContent().isVisible()).toBe(true); + expect(findCaretIcon().props('name')).toBe('angle-down'); }); }); @@ -77,12 +76,11 @@ describe('Graph group component', () => { expect(findCaretIcon().props('name')).toBe('angle-right'); }); - it('should show the angle-right caret icon when collapseGroup is false', () => { + it('should show the angle-right caret icon when collapseGroup is false', async () => { findToggleButton().trigger('click'); - return wrapper.vm.$nextTick().then(() => { - expect(findCaretIcon().props('name')).toBe('angle-down'); - }); + await nextTick(); + expect(findCaretIcon().props('name')).toBe('angle-down'); }); it('should call collapse the graph group content when enter is pressed on the caret icon', () => { @@ -137,15 +135,14 @@ describe('Graph group component', () => { expect(findCaretIcon().exists()).toBe(false); }); - it('should show the panel content when collapse is set to false', () => { + it('should show the panel content when collapse is set to false', async () => { wrapper.setProps({ collapseGroup: false, }); - return wrapper.vm.$nextTick().then(() => { - expect(findContent().isVisible()).toBe(true); - expect(findCaretIcon().exists()).toBe(false); - }); + await nextTick(); + expect(findContent().isVisible()).toBe(true); + expect(findCaretIcon().exists()).toBe(false); }); }); }); diff --git a/spec/frontend/monitoring/components/links_section_spec.js b/spec/frontend/monitoring/components/links_section_spec.js index e37abf6722a..c9b5aeeecb8 100644 --- a/spec/frontend/monitoring/components/links_section_spec.js +++ b/spec/frontend/monitoring/components/links_section_spec.js @@ -36,7 +36,7 @@ describe('Links Section component', () => { expect(findLinks().length).toBe(0); }); - it('renders a link inside a section', () => { + it('renders a link inside a section', async () => { setState([ { title: 'GitLab Website', @@ -44,23 +44,21 @@ describe('Links Section component', () => { }, ]); - return wrapper.vm.$nextTick(() => { - expect(findLinks()).toHaveLength(1); - const firstLink = findLinks().at(0); + await nextTick(); + expect(findLinks()).toHaveLength(1); + const firstLink = findLinks().at(0); - expect(firstLink.attributes('href')).toBe('https://gitlab.com'); - expect(firstLink.text()).toBe('GitLab Website'); - }); + expect(firstLink.attributes('href')).toBe('https://gitlab.com'); + expect(firstLink.text()).toBe('GitLab Website'); }); - it('renders multiple links inside a section', () => { + it('renders multiple links inside a section', async () => { const links = new Array(10) .fill(null) .map((_, i) => ({ title: `Title ${i}`, url: `https://gitlab.com/projects/${i}` })); setState(links); - return wrapper.vm.$nextTick(() => { - expect(findLinks()).toHaveLength(10); - }); + await nextTick(); + expect(findLinks()).toHaveLength(10); }); }); diff --git a/spec/frontend/monitoring/components/refresh_button_spec.js b/spec/frontend/monitoring/components/refresh_button_spec.js index 248cf32d54b..0e45cc021c5 100644 --- a/spec/frontend/monitoring/components/refresh_button_spec.js +++ b/spec/frontend/monitoring/components/refresh_button_spec.js @@ -1,6 +1,7 @@ import { GlDropdown, GlDropdownItem, GlButton } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import Visibility from 'visibilityjs'; +import { nextTick } from 'vue'; import RefreshButton from '~/monitoring/components/refresh_button.vue'; import { createStore } from '~/monitoring/stores'; @@ -79,9 +80,9 @@ describe('RefreshButton', () => { describe('when a refresh rate is chosen', () => { const optIndex = 2; // Other option than "Off" - beforeEach(() => { + beforeEach(async () => { findOptionAt(optIndex).vm.$emit('click'); - return wrapper.vm.$nextTick; + await nextTick(); }); it('refresh rate appears in the dropdown', () => { @@ -101,7 +102,7 @@ describe('RefreshButton', () => { jest.runOnlyPendingTimers(); expectFetchDataToHaveBeenCalledTimes(2); - await wrapper.vm.$nextTick(); + await nextTick(); jest.runOnlyPendingTimers(); expectFetchDataToHaveBeenCalledTimes(3); @@ -113,7 +114,7 @@ describe('RefreshButton', () => { jest.runOnlyPendingTimers(); expectFetchDataToHaveBeenCalledTimes(1); - await wrapper.vm.$nextTick(); + await nextTick(); jest.runOnlyPendingTimers(); expectFetchDataToHaveBeenCalledTimes(1); @@ -128,9 +129,9 @@ describe('RefreshButton', () => { }); describe('when "Off" refresh rate is chosen', () => { - beforeEach(() => { + beforeEach(async () => { findOptionAt(0).vm.$emit('click'); - return wrapper.vm.$nextTick; + await nextTick(); }); it('refresh rate is "Off" in the dropdown', () => { diff --git a/spec/frontend/monitoring/components/variables/dropdown_field_spec.js b/spec/frontend/monitoring/components/variables/dropdown_field_spec.js index f5ee32e78e6..643bbb39f04 100644 --- a/spec/frontend/monitoring/components/variables/dropdown_field_spec.js +++ b/spec/frontend/monitoring/components/variables/dropdown_field_spec.js @@ -1,5 +1,6 @@ import { GlDropdown, GlDropdownItem } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import DropdownField from '~/monitoring/components/variables/dropdown_field.vue'; describe('Custom variable component', () => { @@ -53,14 +54,13 @@ describe('Custom variable component', () => { expect(findDropdown().exists()).toBe(true); }); - it('changing dropdown items triggers update', () => { + it('changing dropdown items triggers update', async () => { createShallowWrapper(); jest.spyOn(wrapper.vm, '$emit'); findDropdownItems().at(1).vm.$emit('click'); - return wrapper.vm.$nextTick(() => { - expect(wrapper.vm.$emit).toHaveBeenCalledWith('input', 'canary'); - }); + await nextTick(); + expect(wrapper.vm.$emit).toHaveBeenCalledWith('input', 'canary'); }); }); diff --git a/spec/frontend/monitoring/components/variables/text_field_spec.js b/spec/frontend/monitoring/components/variables/text_field_spec.js index c879803fddd..3073b3968aa 100644 --- a/spec/frontend/monitoring/components/variables/text_field_spec.js +++ b/spec/frontend/monitoring/components/variables/text_field_spec.js @@ -1,5 +1,6 @@ import { GlFormInput } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import TextField from '~/monitoring/components/variables/text_field.vue'; describe('Text variable component', () => { @@ -23,15 +24,14 @@ describe('Text variable component', () => { expect(findInput().exists()).toBe(true); }); - it('always has a default value', () => { + it('always has a default value', async () => { createShallowWrapper(); - return wrapper.vm.$nextTick(() => { - expect(findInput().attributes('value')).toBe(propsData.value); - }); + await nextTick(); + expect(findInput().attributes('value')).toBe(propsData.value); }); - it('triggers keyup enter', () => { + it('triggers keyup enter', async () => { createShallowWrapper(); jest.spyOn(wrapper.vm, '$emit'); @@ -39,12 +39,11 @@ describe('Text variable component', () => { findInput().trigger('input'); findInput().trigger('keyup.enter'); - return wrapper.vm.$nextTick(() => { - expect(wrapper.vm.$emit).toHaveBeenCalledWith('input', 'prod-pod'); - }); + await nextTick(); + expect(wrapper.vm.$emit).toHaveBeenCalledWith('input', 'prod-pod'); }); - it('triggers blur enter', () => { + it('triggers blur enter', async () => { createShallowWrapper(); jest.spyOn(wrapper.vm, '$emit'); @@ -52,8 +51,7 @@ describe('Text variable component', () => { findInput().trigger('input'); findInput().trigger('blur'); - return wrapper.vm.$nextTick(() => { - expect(wrapper.vm.$emit).toHaveBeenCalledWith('input', 'canary-pod'); - }); + await nextTick(); + expect(wrapper.vm.$emit).toHaveBeenCalledWith('input', 'canary-pod'); }); }); diff --git a/spec/frontend/monitoring/components/variables_section_spec.js b/spec/frontend/monitoring/components/variables_section_spec.js index 6157de0dafe..64b93bd3027 100644 --- a/spec/frontend/monitoring/components/variables_section_spec.js +++ b/spec/frontend/monitoring/components/variables_section_spec.js @@ -1,5 +1,6 @@ import { shallowMount } from '@vue/test-utils'; import Vuex from 'vuex'; +import { nextTick } from 'vue'; import { updateHistory, mergeUrlParams } from '~/lib/utils/url_utility'; import DropdownField from '~/monitoring/components/variables/dropdown_field.vue'; import TextField from '~/monitoring/components/variables/text_field.vue'; @@ -40,11 +41,11 @@ describe('Metrics dashboard/variables section component', () => { }); describe('when variables are set', () => { - beforeEach(() => { + beforeEach(async () => { store.state.monitoringDashboard.variables = storeVariables; createShallowWrapper(); - return wrapper.vm.$nextTick; + await nextTick(); }); it('shows the variables section', () => { @@ -83,34 +84,32 @@ describe('Metrics dashboard/variables section component', () => { createShallowWrapper(); }); - it('merges the url params and refreshes the dashboard when a text-based variables inputs are updated', () => { + it('merges the url params and refreshes the dashboard when a text-based variables inputs are updated', async () => { const firstInput = findTextInputs().at(0); firstInput.vm.$emit('input', 'test'); - return wrapper.vm.$nextTick(() => { - expect(updateVariablesAndFetchData).toHaveBeenCalled(); - expect(mergeUrlParams).toHaveBeenCalledWith( - convertVariablesForURL(storeVariables), - window.location.href, - ); - expect(updateHistory).toHaveBeenCalled(); - }); + await nextTick(); + expect(updateVariablesAndFetchData).toHaveBeenCalled(); + expect(mergeUrlParams).toHaveBeenCalledWith( + convertVariablesForURL(storeVariables), + window.location.href, + ); + expect(updateHistory).toHaveBeenCalled(); }); - it('merges the url params and refreshes the dashboard when a custom-based variables inputs are updated', () => { + it('merges the url params and refreshes the dashboard when a custom-based variables inputs are updated', async () => { const firstInput = findCustomInputs().at(0); firstInput.vm.$emit('input', 'test'); - return wrapper.vm.$nextTick(() => { - expect(updateVariablesAndFetchData).toHaveBeenCalled(); - expect(mergeUrlParams).toHaveBeenCalledWith( - convertVariablesForURL(storeVariables), - window.location.href, - ); - expect(updateHistory).toHaveBeenCalled(); - }); + await nextTick(); + expect(updateVariablesAndFetchData).toHaveBeenCalled(); + expect(mergeUrlParams).toHaveBeenCalledWith( + convertVariablesForURL(storeVariables), + window.location.href, + ); + expect(updateHistory).toHaveBeenCalled(); }); it('does not merge the url params and refreshes the dashboard if the value entered is not different that is what currently stored', () => { diff --git a/spec/frontend/mr_popover/mr_popover_spec.js b/spec/frontend/mr_popover/mr_popover_spec.js index 36ad82e93a5..23f97073e9e 100644 --- a/spec/frontend/mr_popover/mr_popover_spec.js +++ b/spec/frontend/mr_popover/mr_popover_spec.js @@ -1,4 +1,5 @@ import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import MRPopover from '~/mr_popover/components/mr_popover.vue'; import CiIcon from '~/vue_shared/components/ci_icon.vue'; @@ -25,16 +26,15 @@ describe('MR Popover', () => { }); }); - it('shows skeleton-loader while apollo is loading', () => { + it('shows skeleton-loader while apollo is loading', async () => { wrapper.vm.$apollo.queries.mergeRequest.loading = true; - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.element).toMatchSnapshot(); - }); + await nextTick(); + expect(wrapper.element).toMatchSnapshot(); }); describe('loaded state', () => { - it('matches the snapshot', () => { + it('matches the snapshot', async () => { // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax wrapper.setData({ @@ -51,12 +51,11 @@ describe('MR Popover', () => { }, }); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.element).toMatchSnapshot(); - }); + await nextTick(); + expect(wrapper.element).toMatchSnapshot(); }); - it('does not show CI Icon if there is no pipeline data', () => { + it('does not show CI Icon if there is no pipeline data', async () => { // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax wrapper.setData({ @@ -69,15 +68,13 @@ describe('MR Popover', () => { }, }); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.find(CiIcon).exists()).toBe(false); - }); + await nextTick(); + expect(wrapper.find(CiIcon).exists()).toBe(false); }); - it('falls back to cached MR title when request fails', () => { - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.text()).toContain('MR Title'); - }); + it('falls back to cached MR title when request fails', async () => { + await nextTick(); + expect(wrapper.text()).toContain('MR Title'); }); }); }); diff --git a/spec/frontend/nav/components/responsive_app_spec.js b/spec/frontend/nav/components/responsive_app_spec.js index 4af8c6020bc..76b8ebdc92f 100644 --- a/spec/frontend/nav/components/responsive_app_spec.js +++ b/spec/frontend/nav/components/responsive_app_spec.js @@ -1,4 +1,5 @@ import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import ResponsiveApp from '~/nav/components/responsive_app.vue'; import ResponsiveHeader from '~/nav/components/responsive_header.vue'; import ResponsiveHome from '~/nav/components/responsive_home.vue'; @@ -62,7 +63,7 @@ describe('~/nav/components/responsive_app.vue', () => { wrapper.vm.$root.$emit(evt); - await wrapper.vm.$nextTick(); + await nextTick(); }, Promise.resolve()); expect(hasMobileOverlayVisible()).toBe(expectation); @@ -97,7 +98,7 @@ describe('~/nav/components/responsive_app.vue', () => { findHome().vm.$emit('menu-item-click', { view }); - await wrapper.vm.$nextTick(); + await nextTick(); }); it('shows header', () => { diff --git a/spec/frontend/notes/components/comment_form_spec.js b/spec/frontend/notes/components/comment_form_spec.js index 16dbf60cef4..1e4d9f313f0 100644 --- a/spec/frontend/notes/components/comment_form_spec.js +++ b/spec/frontend/notes/components/comment_form_spec.js @@ -466,8 +466,8 @@ describe('issue_comment_form component', () => { await findCloseReopenButton().trigger('click'); - await wrapper.vm.$nextTick; - await wrapper.vm.$nextTick; + await nextTick; + await nextTick; expect(createFlash).toHaveBeenCalledWith({ message: `Something went wrong while closing the ${type}. Please try again later.`, @@ -502,8 +502,8 @@ describe('issue_comment_form component', () => { await findCloseReopenButton().trigger('click'); - await wrapper.vm.$nextTick; - await wrapper.vm.$nextTick; + await nextTick; + await nextTick; expect(createFlash).toHaveBeenCalledWith({ message: `Something went wrong while reopening the ${type}. Please try again later.`, @@ -521,7 +521,7 @@ describe('issue_comment_form component', () => { await findCloseReopenButton().trigger('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(refreshUserMergeRequestCounts).toHaveBeenCalled(); }); @@ -581,7 +581,7 @@ describe('issue_comment_form component', () => { // check checkbox checkbox.element.checked = shouldCheckboxBeChecked; checkbox.trigger('change'); - await wrapper.vm.$nextTick(); + await nextTick(); // submit comment findCommentButton().trigger('click'); diff --git a/spec/frontend/notes/components/diff_discussion_header_spec.js b/spec/frontend/notes/components/diff_discussion_header_spec.js index fa34a5e8d39..9f94dd693cb 100644 --- a/spec/frontend/notes/components/diff_discussion_header_spec.js +++ b/spec/frontend/notes/components/diff_discussion_header_spec.js @@ -1,5 +1,6 @@ import { mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import diffDiscussionHeader from '~/notes/components/diff_discussion_header.vue'; import createStore from '~/notes/stores'; @@ -24,16 +25,15 @@ describe('diff_discussion_header component', () => { wrapper.destroy(); }); - it('should render user avatar', () => { + it('should render user avatar', async () => { const discussion = { ...discussionMock }; discussion.diff_file = mockDiffFile; discussion.diff_discussion = true; wrapper.setProps({ discussion }); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.find('.user-avatar-link').exists()).toBe(true); - }); + await nextTick(); + expect(wrapper.find('.user-avatar-link').exists()).toBe(true); }); describe('action text', () => { @@ -41,7 +41,7 @@ describe('diff_discussion_header component', () => { const truncatedCommitId = commitId.substr(0, 8); let commitElement; - beforeEach((done) => { + beforeEach(async () => { store.state.diffs = { projectPath: 'something', }; @@ -58,41 +58,30 @@ describe('diff_discussion_header component', () => { }, }); - wrapper.vm - .$nextTick() - .then(() => { - commitElement = wrapper.find('.commit-sha'); - }) - .then(done) - .catch(done.fail); + await nextTick(); + commitElement = wrapper.find('.commit-sha'); }); describe('for diff threads without a commit id', () => { - it('should show started a thread on the diff text', (done) => { + it('should show started a thread on the diff text', async () => { Object.assign(wrapper.vm.discussion, { for_commit: false, commit_id: null, }); - wrapper.vm.$nextTick(() => { - expect(wrapper.text()).toContain('started a thread on the diff'); - - done(); - }); + await nextTick(); + expect(wrapper.text()).toContain('started a thread on the diff'); }); - it('should show thread on older version text', (done) => { + it('should show thread on older version text', async () => { Object.assign(wrapper.vm.discussion, { for_commit: false, commit_id: null, active: false, }); - wrapper.vm.$nextTick(() => { - expect(wrapper.text()).toContain('started a thread on an old version of the diff'); - - done(); - }); + await nextTick(); + expect(wrapper.text()).toContain('started a thread on an old version of the diff'); }); }); @@ -105,31 +94,25 @@ describe('diff_discussion_header component', () => { }); describe('for diff thread with a commit id', () => { - it('should display started thread on commit header', (done) => { + it('should display started thread on commit header', async () => { wrapper.vm.discussion.for_commit = false; - wrapper.vm.$nextTick(() => { - expect(wrapper.text()).toContain(`started a thread on commit ${truncatedCommitId}`); - - expect(commitElement).not.toBe(null); + await nextTick(); + expect(wrapper.text()).toContain(`started a thread on commit ${truncatedCommitId}`); - done(); - }); + expect(commitElement).not.toBe(null); }); - it('should display outdated change on commit header', (done) => { + it('should display outdated change on commit header', async () => { wrapper.vm.discussion.for_commit = false; wrapper.vm.discussion.active = false; - wrapper.vm.$nextTick(() => { - expect(wrapper.text()).toContain( - `started a thread on an outdated change in commit ${truncatedCommitId}`, - ); + await nextTick(); + expect(wrapper.text()).toContain( + `started a thread on an outdated change in commit ${truncatedCommitId}`, + ); - expect(commitElement).not.toBe(null); - - done(); - }); + expect(commitElement).not.toBe(null); }); }); }); diff --git a/spec/frontend/notes/components/discussion_counter_spec.js b/spec/frontend/notes/components/discussion_counter_spec.js index 924c89c6345..a856d002d2e 100644 --- a/spec/frontend/notes/components/discussion_counter_spec.js +++ b/spec/frontend/notes/components/discussion_counter_spec.js @@ -1,6 +1,6 @@ import { GlButton } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import DiscussionCounter from '~/notes/components/discussion_counter.vue'; import notesModule from '~/notes/stores/modules'; @@ -113,7 +113,7 @@ describe('DiscussionCounter component', () => { expect(setExpandDiscussionsFn).toHaveBeenCalledTimes(1); }); - it('collapses all discussions if expanded', () => { + it('collapses all discussions if expanded', async () => { updateStoreWithExpanded(true); expect(wrapper.vm.allExpanded).toBe(true); @@ -121,13 +121,12 @@ describe('DiscussionCounter component', () => { toggleAllButton.vm.$emit('click'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.vm.allExpanded).toBe(false); - expect(toggleAllButton.props('icon')).toBe('angle-down'); - }); + await nextTick(); + expect(wrapper.vm.allExpanded).toBe(false); + expect(toggleAllButton.props('icon')).toBe('angle-down'); }); - it('expands all discussions if collapsed', () => { + it('expands all discussions if collapsed', async () => { updateStoreWithExpanded(false); expect(wrapper.vm.allExpanded).toBe(false); @@ -135,10 +134,9 @@ describe('DiscussionCounter component', () => { toggleAllButton.vm.$emit('click'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.vm.allExpanded).toBe(true); - expect(toggleAllButton.props('icon')).toBe('angle-up'); - }); + await nextTick(); + expect(wrapper.vm.allExpanded).toBe(true); + expect(toggleAllButton.props('icon')).toBe('angle-up'); }); }); }); diff --git a/spec/frontend/notes/components/discussion_filter_spec.js b/spec/frontend/notes/components/discussion_filter_spec.js index 1f97bb97415..27206bddbfc 100644 --- a/spec/frontend/notes/components/discussion_filter_spec.js +++ b/spec/frontend/notes/components/discussion_filter_spec.js @@ -1,6 +1,6 @@ import { GlDropdown } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import AxiosMockAdapter from 'axios-mock-adapter'; import Vuex from 'vuex'; import { TEST_HOST } from 'helpers/test_constants'; @@ -151,13 +151,11 @@ describe('DiscussionFilter component', () => { window.mrTabs = undefined; }); - it('only renders when discussion tab is active', (done) => { + it('only renders when discussion tab is active', async () => { eventHub.$emit('MergeRequestTabChange', 'commit'); - wrapper.vm.$nextTick(() => { - expect(wrapper.html()).toBe(''); - done(); - }); + await nextTick(); + expect(wrapper.html()).toBe(''); }); }); @@ -166,58 +164,48 @@ describe('DiscussionFilter component', () => { window.location.hash = ''; }); - it('updates the filter when the URL links to a note', (done) => { + it('updates the filter when the URL links to a note', async () => { window.location.hash = `note_${discussionMock.notes[0].id}`; wrapper.vm.currentValue = discussionFiltersMock[2].value; wrapper.vm.handleLocationHash(); - wrapper.vm.$nextTick(() => { - expect(wrapper.vm.currentValue).toBe(DISCUSSION_FILTERS_DEFAULT_VALUE); - done(); - }); + await nextTick(); + expect(wrapper.vm.currentValue).toBe(DISCUSSION_FILTERS_DEFAULT_VALUE); }); - it('does not update the filter when the current filter is "Show all activity"', (done) => { + it('does not update the filter when the current filter is "Show all activity"', async () => { window.location.hash = `note_${discussionMock.notes[0].id}`; wrapper.vm.handleLocationHash(); - wrapper.vm.$nextTick(() => { - expect(wrapper.vm.currentValue).toBe(DISCUSSION_FILTERS_DEFAULT_VALUE); - done(); - }); + await nextTick(); + expect(wrapper.vm.currentValue).toBe(DISCUSSION_FILTERS_DEFAULT_VALUE); }); - it('only updates filter when the URL links to a note', (done) => { + it('only updates filter when the URL links to a note', async () => { window.location.hash = `testing123`; wrapper.vm.handleLocationHash(); - wrapper.vm.$nextTick(() => { - expect(wrapper.vm.currentValue).toBe(DISCUSSION_FILTERS_DEFAULT_VALUE); - done(); - }); + await nextTick(); + expect(wrapper.vm.currentValue).toBe(DISCUSSION_FILTERS_DEFAULT_VALUE); }); - it('fetches discussions when there is a hash', (done) => { + it('fetches discussions when there is a hash', async () => { window.location.hash = `note_${discussionMock.notes[0].id}`; wrapper.vm.currentValue = discussionFiltersMock[2].value; jest.spyOn(wrapper.vm, 'selectFilter').mockImplementation(() => {}); wrapper.vm.handleLocationHash(); - wrapper.vm.$nextTick(() => { - expect(wrapper.vm.selectFilter).toHaveBeenCalled(); - done(); - }); + await nextTick(); + expect(wrapper.vm.selectFilter).toHaveBeenCalled(); }); - it('does not fetch discussions when there is no hash', (done) => { + it('does not fetch discussions when there is no hash', async () => { window.location.hash = ''; jest.spyOn(wrapper.vm, 'selectFilter').mockImplementation(() => {}); wrapper.vm.handleLocationHash(); - wrapper.vm.$nextTick(() => { - expect(wrapper.vm.selectFilter).not.toHaveBeenCalled(); - done(); - }); + await nextTick(); + expect(wrapper.vm.selectFilter).not.toHaveBeenCalled(); }); }); }); diff --git a/spec/frontend/notes/components/discussion_notes_spec.js b/spec/frontend/notes/components/discussion_notes_spec.js index 59ac75f00e6..3506b6ac9f3 100644 --- a/spec/frontend/notes/components/discussion_notes_spec.js +++ b/spec/frontend/notes/components/discussion_notes_spec.js @@ -1,6 +1,7 @@ import { getByRole } from '@testing-library/dom'; import { shallowMount, mount } from '@vue/test-utils'; import '~/behaviors/markdown/render_gfm'; +import { nextTick } from 'vue'; import DiscussionNotes from '~/notes/components/discussion_notes.vue'; import NoteableNote from '~/notes/components/noteable_note.vue'; import { SYSTEM_NOTE } from '~/notes/constants'; @@ -135,28 +136,25 @@ describe('DiscussionNotes', () => { createComponent({ shouldGroupReplies: true, isExpanded: true }); }); - it('emits deleteNote when first note emits handleDeleteNote', () => { + it('emits deleteNote when first note emits handleDeleteNote', async () => { findNoteAtIndex(0).vm.$emit('handleDeleteNote'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted().deleteNote).toBeTruthy(); - }); + await nextTick(); + expect(wrapper.emitted().deleteNote).toBeTruthy(); }); - it('emits startReplying when first note emits startReplying', () => { + it('emits startReplying when first note emits startReplying', async () => { findNoteAtIndex(0).vm.$emit('startReplying'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted().startReplying).toBeTruthy(); - }); + await nextTick(); + expect(wrapper.emitted().startReplying).toBeTruthy(); }); - it('emits deleteNote when second note emits handleDeleteNote', () => { + it('emits deleteNote when second note emits handleDeleteNote', async () => { findNoteAtIndex(1).vm.$emit('handleDeleteNote'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted().deleteNote).toBeTruthy(); - }); + await nextTick(); + expect(wrapper.emitted().deleteNote).toBeTruthy(); }); }); @@ -167,12 +165,11 @@ describe('DiscussionNotes', () => { note = wrapper.find('.notes > *'); }); - it('emits deleteNote when first note emits handleDeleteNote', () => { + it('emits deleteNote when first note emits handleDeleteNote', async () => { note.vm.$emit('handleDeleteNote'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted().deleteNote).toBeTruthy(); - }); + await nextTick(); + expect(wrapper.emitted().deleteNote).toBeTruthy(); }); }); }); diff --git a/spec/frontend/notes/components/discussion_resolve_button_spec.js b/spec/frontend/notes/components/discussion_resolve_button_spec.js index 64e061830b9..ca0c0ca6de8 100644 --- a/spec/frontend/notes/components/discussion_resolve_button_spec.js +++ b/spec/frontend/notes/components/discussion_resolve_button_spec.js @@ -1,5 +1,6 @@ import { GlButton } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import resolveDiscussionButton from '~/notes/components/discussion_resolve_button.vue'; const buttonTitle = 'Resolve discussion'; @@ -26,15 +27,14 @@ describe('resolveDiscussionButton', () => { wrapper.destroy(); }); - it('should emit a onClick event on button click', () => { + it('should emit a onClick event on button click', async () => { const button = wrapper.find(GlButton); button.vm.$emit('click'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted()).toEqual({ - onClick: [[]], - }); + await nextTick(); + expect(wrapper.emitted()).toEqual({ + onClick: [[]], }); }); @@ -57,7 +57,7 @@ describe('resolveDiscussionButton', () => { expect(button.props('loading')).toEqual(true); }); - it('should only show a loading spinner while resolving', () => { + it('should only show a loading spinner while resolving', async () => { factory({ propsData: { isResolving: false, @@ -67,8 +67,7 @@ describe('resolveDiscussionButton', () => { const button = wrapper.find(GlButton); - wrapper.vm.$nextTick(() => { - expect(button.props('loading')).toEqual(false); - }); + await nextTick(); + expect(button.props('loading')).toEqual(false); }); }); diff --git a/spec/frontend/notes/components/noteable_note_spec.js b/spec/frontend/notes/components/noteable_note_spec.js index 038aff3be04..c7115a5911b 100644 --- a/spec/frontend/notes/components/noteable_note_spec.js +++ b/spec/frontend/notes/components/noteable_note_spec.js @@ -1,5 +1,5 @@ import { mount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import waitForPromises from 'helpers/wait_for_promises'; @@ -107,11 +107,11 @@ describe('issue_note', () => { line, }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findMultilineComment().text()).toBe('Comment on lines 1 to 2'); }); - it('should only render if it has everything it needs', () => { + it('should only render if it has everything it needs', async () => { const position = { line_range: { start: { @@ -140,12 +140,11 @@ describe('issue_note', () => { line, }); - return wrapper.vm.$nextTick().then(() => { - expect(findMultilineComment().exists()).toBe(false); - }); + await nextTick(); + expect(findMultilineComment().exists()).toBe(false); }); - it('should not render if has single line comment', () => { + it('should not render if has single line comment', async () => { const position = { line_range: { start: { @@ -174,9 +173,8 @@ describe('issue_note', () => { line, }); - return wrapper.vm.$nextTick().then(() => { - expect(findMultilineComment().exists()).toBe(false); - }); + await nextTick(); + expect(findMultilineComment().exists()).toBe(false); }); it('should not render if `line_range` is unavailable', () => { @@ -204,7 +202,7 @@ describe('issue_note', () => { line, }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.findComponent(UserAvatarLink).props('imgSize')).toBe(24); }); @@ -318,13 +316,13 @@ describe('issue_note', () => { callback: () => {}, }); - await wrapper.vm.$nextTick(); + await nextTick(); let noteBodyProps = noteBody.props(); expect(noteBodyProps.note.note_html).toBe(`<p>${updatedText}</p>\n`); noteBody.vm.$emit('cancelForm', {}); - await wrapper.vm.$nextTick(); + await nextTick(); noteBodyProps = noteBody.props(); diff --git a/spec/frontend/notes/components/timeline_toggle_spec.js b/spec/frontend/notes/components/timeline_toggle_spec.js index 0b304e5181b..84fa3008835 100644 --- a/spec/frontend/notes/components/timeline_toggle_spec.js +++ b/spec/frontend/notes/components/timeline_toggle_spec.js @@ -1,6 +1,6 @@ import { GlButton } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import TimelineToggle, { timelineEnabledTooltip, @@ -64,7 +64,7 @@ describe('Timeline toggle', () => { it('should set correct UI state', async () => { store.state.isTimelineEnabled = true; findGlButton().vm.$emit('click', mockEvent); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findGlButton().attributes('title')).toBe(timelineEnabledTooltip); expect(findGlButton().attributes('selected')).toBe('true'); expect(mockEvent.currentTarget.blur).toHaveBeenCalled(); @@ -72,7 +72,7 @@ describe('Timeline toggle', () => { it('should track Snowplow event', async () => { store.state.isTimelineEnabled = true; - await wrapper.vm.$nextTick(); + await nextTick(); findGlButton().trigger('click'); @@ -97,7 +97,7 @@ describe('Timeline toggle', () => { it('should set correct UI state', async () => { store.state.isTimelineEnabled = false; findGlButton().vm.$emit('click', mockEvent); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findGlButton().attributes('title')).toBe(timelineDisabledTooltip); expect(findGlButton().attributes('selected')).toBe(undefined); expect(mockEvent.currentTarget.blur).toHaveBeenCalled(); @@ -105,7 +105,7 @@ describe('Timeline toggle', () => { it('should track Snowplow event', async () => { store.state.isTimelineEnabled = false; - await wrapper.vm.$nextTick(); + await nextTick(); findGlButton().trigger('click'); diff --git a/spec/frontend/notes/mixins/discussion_navigation_spec.js b/spec/frontend/notes/mixins/discussion_navigation_spec.js index 3daf23c83cf..1f71947b3cd 100644 --- a/spec/frontend/notes/mixins/discussion_navigation_spec.js +++ b/spec/frontend/notes/mixins/discussion_navigation_spec.js @@ -93,14 +93,13 @@ describe('Discussion navigation mixin', () => { expect(store.dispatch).toHaveBeenCalledWith('setCurrentDiscussionId', null); }); - it('triggers the jumpToNextDiscussion action when the previous store action succeeds', () => { + it('triggers the jumpToNextDiscussion action when the previous store action succeeds', async () => { store.dispatch.mockResolvedValue(); vm.jumpToFirstUnresolvedDiscussion(); - return vm.$nextTick().then(() => { - expect(vm.jumpToNextDiscussion).toHaveBeenCalled(); - }); + await nextTick(); + expect(vm.jumpToNextDiscussion).toHaveBeenCalled(); }); }); @@ -126,11 +125,11 @@ describe('Discussion navigation mixin', () => { }); describe('on `show` active tab', () => { - beforeEach(() => { + beforeEach(async () => { window.mrTabs.currentAction = 'show'; wrapper.vm[fn](...args); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('sets current discussion', () => { @@ -150,11 +149,11 @@ describe('Discussion navigation mixin', () => { }); describe('on `diffs` active tab', () => { - beforeEach(() => { + beforeEach(async () => { window.mrTabs.currentAction = 'diffs'; wrapper.vm[fn](...args); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('sets current discussion', () => { @@ -178,11 +177,11 @@ describe('Discussion navigation mixin', () => { }); describe('on `other` active tab', () => { - beforeEach(() => { + beforeEach(async () => { window.mrTabs.currentAction = 'other'; wrapper.vm[fn](...args); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('sets current discussion', () => { diff --git a/spec/frontend/notifications/components/custom_notifications_modal_spec.js b/spec/frontend/notifications/components/custom_notifications_modal_spec.js index 7a036d25559..c5d201c3aec 100644 --- a/spec/frontend/notifications/components/custom_notifications_modal_spec.js +++ b/spec/frontend/notifications/components/custom_notifications_modal_spec.js @@ -2,6 +2,7 @@ import { GlSprintf, GlModal, GlFormGroup, GlFormCheckbox, GlLoadingIcon } from ' import { shallowMount } from '@vue/test-utils'; import axios from 'axios'; import MockAdapter from 'axios-mock-adapter'; +import { nextTick } from 'vue'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import waitForPromises from 'helpers/wait_for_promises'; import httpStatus from '~/lib/utils/http_status'; @@ -97,7 +98,7 @@ describe('CustomNotificationsModal', () => { ], }); - await wrapper.vm.$nextTick(); + await nextTick(); }); it.each` @@ -222,7 +223,7 @@ describe('CustomNotificationsModal', () => { ], }); - await wrapper.vm.$nextTick(); + await nextTick(); findCheckboxAt(1).vm.$emit('change', true); @@ -252,7 +253,7 @@ describe('CustomNotificationsModal', () => { ], }); - await wrapper.vm.$nextTick(); + await nextTick(); findCheckboxAt(1).vm.$emit('change', true); diff --git a/spec/frontend/operation_settings/components/metrics_settings_spec.js b/spec/frontend/operation_settings/components/metrics_settings_spec.js index 258c6eae692..c1fa1d24a82 100644 --- a/spec/frontend/operation_settings/components/metrics_settings_spec.js +++ b/spec/frontend/operation_settings/components/metrics_settings_spec.js @@ -1,5 +1,6 @@ import { GlButton, GlLink, GlFormGroup, GlFormInput, GlFormSelect } from '@gitlab/ui'; import { mount, shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import { TEST_HOST } from 'helpers/test_constants'; import createFlash from '~/flash'; import axios from '~/lib/utils/axios_utils'; @@ -181,17 +182,18 @@ describe('operation settings external dashboard component', () => { expect(submit.text()).toBe('Save Changes'); }); - it('submits form on click', () => { + it('submits form on click', async () => { mountComponent(false); axios.patch.mockResolvedValue(); findSubmitButton().trigger('click'); expect(axios.patch).toHaveBeenCalledWith(...endpointRequest); - return wrapper.vm.$nextTick().then(() => expect(refreshCurrentPage).toHaveBeenCalled()); + await nextTick(); + expect(refreshCurrentPage).toHaveBeenCalled(); }); - it('creates flash banner on error', () => { + it('creates flash banner on error', async () => { mountComponent(false); const message = 'mockErrorMessage'; axios.patch.mockRejectedValue({ response: { data: { message } } }); @@ -199,14 +201,11 @@ describe('operation settings external dashboard component', () => { expect(axios.patch).toHaveBeenCalledWith(...endpointRequest); - return wrapper.vm - .$nextTick() - .then(jest.runAllTicks) - .then(() => - expect(createFlash).toHaveBeenCalledWith({ - message: `There was an error saving your changes. ${message}`, - }), - ); + await nextTick(); + await jest.runAllTicks(); + expect(createFlash).toHaveBeenCalledWith({ + message: `There was an error saving your changes. ${message}`, + }); }); }); }); diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/details_header_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/details_header_spec.js index 5278e730ec9..f4c22d9bfa7 100644 --- a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/details_header_spec.js +++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/details_header_spec.js @@ -1,6 +1,7 @@ import { GlDropdownItem, GlIcon, GlDropdown } from '@gitlab/ui'; import { shallowMount, createLocalVue } from '@vue/test-utils'; import VueApollo from 'vue-apollo'; +import { nextTick } from 'vue'; import { useFakeDate } from 'helpers/fake_date'; import createMockApollo from 'helpers/mock_apollo_helper'; import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; @@ -54,8 +55,8 @@ describe('Details Header', () => { const waitForMetadataItems = async () => { // Metadata items are printed by a loop in the title-area and it takes two ticks for them to be available - await wrapper.vm.$nextTick(); - await wrapper.vm.$nextTick(); + await nextTick(); + await nextTick(); }; const mountComponent = ({ diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js index 7d9f89518d5..ef6c4a1fa32 100644 --- a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js +++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js @@ -1,5 +1,5 @@ -import { shallowMount, createLocalVue } from '@vue/test-utils'; -import { nextTick } from 'vue'; +import { shallowMount } from '@vue/test-utils'; +import Vue, { nextTick } from 'vue'; import { GlEmptyState } from '@gitlab/ui'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; @@ -22,8 +22,6 @@ import { import { FILTERED_SEARCH_TERM } from '~/packages_and_registries/shared/constants'; import { tagsMock, imageTagsMock, tagsPageInfo } from '../../mock_data'; -const localVue = createLocalVue(); - describe('Tags List', () => { let wrapper; let apolloProvider; @@ -50,13 +48,12 @@ describe('Tags List', () => { }; const mountComponent = ({ propsData = { isMobile: false, id: 1 } } = {}) => { - localVue.use(VueApollo); + Vue.use(VueApollo); const requestHandlers = [[getContainerRepositoryTagsQuery, resolver]]; apolloProvider = createMockApollo(requestHandlers); wrapper = shallowMount(component, { - localVue, apolloProvider, propsData, stubs: { RegistryList }, diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/registry_header_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/registry_header_spec.js index 92cfeb7633e..c91a9c0f0fb 100644 --- a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/registry_header_spec.js +++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/registry_header_spec.js @@ -1,5 +1,6 @@ import { GlSprintf } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import Component from '~/packages_and_registries/container_registry/explorer/components/list_page/registry_header.vue'; import { CONTAINER_REGISTRY_TITLE, @@ -21,7 +22,7 @@ describe('registry_header', () => { const findImagesCountSubHeader = () => wrapper.find('[data-testid="images-count"]'); const findExpirationPolicySubHeader = () => wrapper.find('[data-testid="expiration-policy"]'); - const mountComponent = (propsData, slots) => { + const mountComponent = async (propsData, slots) => { wrapper = shallowMount(Component, { stubs: { GlSprintf, @@ -30,7 +31,7 @@ describe('registry_header', () => { propsData, slots, }); - return wrapper.vm.$nextTick(); + await nextTick(); }; afterEach(() => { diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js index 1f8cda55f39..c602b37c3b5 100644 --- a/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js +++ b/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js @@ -1,7 +1,8 @@ import { GlKeysetPagination, GlEmptyState } from '@gitlab/ui'; -import { shallowMount, createLocalVue } from '@vue/test-utils'; +import { shallowMount } from '@vue/test-utils'; +import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; -import { nextTick } from 'vue'; + import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; import axios from '~/lib/utils/axios_utils'; @@ -39,8 +40,6 @@ import { } from '../mock_data'; import { DeleteModal } from '../stubs'; -const localVue = createLocalVue(); - describe('Details Page', () => { let wrapper; let apolloProvider; @@ -85,7 +84,7 @@ describe('Details Page', () => { options, config = defaultConfig, } = {}) => { - localVue.use(VueApollo); + Vue.use(VueApollo); const requestHandlers = [ [getContainerRepositoryDetailsQuery, resolver], @@ -96,7 +95,6 @@ describe('Details Page', () => { apolloProvider = createMockApollo(requestHandlers); wrapper = shallowMount(component, { - localVue, apolloProvider, stubs: { DeleteModal, diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/pages/list_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/pages/list_spec.js index c4984d1b6ae..bda0f3616a4 100644 --- a/spec/frontend/packages_and_registries/container_registry/explorer/pages/list_spec.js +++ b/spec/frontend/packages_and_registries/container_registry/explorer/pages/list_spec.js @@ -1,6 +1,7 @@ import { GlSkeletonLoader, GlSprintf, GlAlert } from '@gitlab/ui'; -import { shallowMount, createLocalVue } from '@vue/test-utils'; -import { nextTick } from 'vue'; +import { shallowMount } from '@vue/test-utils'; +import Vue, { nextTick } from 'vue'; + import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; @@ -38,8 +39,6 @@ import { } from '../mock_data'; import { GlModal, GlEmptyState } from '../stubs'; -const localVue = createLocalVue(); - describe('List Page', () => { let wrapper; let apolloProvider; @@ -75,7 +74,7 @@ describe('List Page', () => { config = { isGroupPage: false }, query = {}, } = {}) => { - localVue.use(VueApollo); + Vue.use(VueApollo); const requestHandlers = [ [getContainerRepositoriesQuery, resolver], @@ -86,7 +85,6 @@ describe('List Page', () => { apolloProvider = createMockApollo(requestHandlers); wrapper = shallowMount(component, { - localVue, apolloProvider, stubs: { GlModal, diff --git a/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js b/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js index 842b63ac0d5..79894e25889 100644 --- a/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js +++ b/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js @@ -5,7 +5,7 @@ import { GlSprintf, GlEmptyState, } from '@gitlab/ui'; -import { createLocalVue } from '@vue/test-utils'; +import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; @@ -21,8 +21,6 @@ import getDependencyProxyDetailsQuery from '~/packages_and_registries/dependency import { proxyDetailsQuery, proxyData, pagination, proxyManifests } from './mock_data'; -const localVue = createLocalVue(); - describe('DependencyProxyApp', () => { let wrapper; let apolloProvider; @@ -35,14 +33,13 @@ describe('DependencyProxyApp', () => { }; function createComponent({ provide = provideDefaults } = {}) { - localVue.use(VueApollo); + Vue.use(VueApollo); const requestHandlers = [[getDependencyProxyDetailsQuery, resolver]]; apolloProvider = createMockApollo(requestHandlers); wrapper = shallowMountExtended(DependencyProxyApp, { - localVue, apolloProvider, provide, stubs: { diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/details_title_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/details_title_spec.js index 95b70cb010d..b504f7489ab 100644 --- a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/details_title_spec.js +++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/details_title_spec.js @@ -1,5 +1,5 @@ import { shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import component from '~/packages_and_registries/infrastructure_registry/details/components/details_title.vue'; import TitleArea from '~/vue_shared/components/registry/title_area.vue'; @@ -11,7 +11,10 @@ describe('PackageTitle', () => { let wrapper; let store; - function createComponent({ packageFiles = mavenFiles, packageEntity = terraformModule } = {}) { + async function createComponent({ + packageFiles = mavenFiles, + packageEntity = terraformModule, + } = {}) { store = new Vuex.Store({ state: { packageEntity, @@ -28,7 +31,7 @@ describe('PackageTitle', () => { TitleArea, }, }); - return wrapper.vm.$nextTick(); + await nextTick(); } const findTitleArea = () => wrapper.findComponent(TitleArea); diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_spec.js index 5efd23f8d7e..fed82653016 100644 --- a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_spec.js +++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_spec.js @@ -1,6 +1,6 @@ import { GlTable, GlPagination, GlModal } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import { last } from 'lodash'; import Vuex from 'vuex'; import stubChildren from 'helpers/stub_children'; @@ -120,16 +120,15 @@ describe('packages_list', () => { mountComponent(); }); - it('setItemToBeDeleted sets itemToBeDeleted and open the modal', () => { + it('setItemToBeDeleted sets itemToBeDeleted and open the modal', async () => { const mockModalShow = jest.spyOn(wrapper.vm.$refs.packageListDeleteModal, 'show'); const item = last(wrapper.vm.list); findPackagesListRow().vm.$emit('packageToDelete', item); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.vm.itemToBeDeleted).toEqual(item); - expect(mockModalShow).toHaveBeenCalled(); - }); + await nextTick(); + expect(wrapper.vm.itemToBeDeleted).toEqual(item); + expect(mockModalShow).toHaveBeenCalled(); }); it('deleteItemConfirmation resets itemToBeDeleted', () => { @@ -140,15 +139,14 @@ describe('packages_list', () => { expect(wrapper.vm.itemToBeDeleted).toEqual(null); }); - it('deleteItemConfirmation emit package:delete', () => { + it('deleteItemConfirmation emit package:delete', async () => { const itemToBeDeleted = { id: 2 }; // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax wrapper.setData({ itemToBeDeleted }); wrapper.vm.deleteItemConfirmation(); - return wrapper.vm.$nextTick(() => { - expect(wrapper.emitted('package:delete')[0]).toEqual([itemToBeDeleted]); - }); + await nextTick(); + expect(wrapper.emitted('package:delete')[0]).toEqual([itemToBeDeleted]); }); it('deleteItemCanceled resets itemToBeDeleted', () => { diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/shared/package_list_row_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/shared/package_list_row_spec.js index 1052fdd1dda..79c1b18c9f9 100644 --- a/spec/frontend/packages_and_registries/infrastructure_registry/components/shared/package_list_row_spec.js +++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/shared/package_list_row_spec.js @@ -1,4 +1,5 @@ import { GlLink } from '@gitlab/ui'; +import { nextTick } from 'vue'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; @@ -126,7 +127,7 @@ describe('packages_list_row', () => { findDeleteButton().vm.$emit('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.emitted('packageToDelete')).toBeTruthy(); expect(wrapper.emitted('packageToDelete')[0]).toEqual([packageWithoutTags]); }); diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/package_title_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/package_title_spec.js index 6ad6007c9da..5da9cfffaae 100644 --- a/spec/frontend/packages_and_registries/package_registry/components/details/package_title_spec.js +++ b/spec/frontend/packages_and_registries/package_registry/components/details/package_title_spec.js @@ -1,5 +1,6 @@ import { GlIcon, GlSprintf } from '@gitlab/ui'; import { GlBreakpointInstance } from '@gitlab/ui/dist/utils'; +import { nextTick } from 'vue'; import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import PackageTags from '~/packages_and_registries/shared/components/package_tags.vue'; @@ -24,7 +25,7 @@ const packageWithTags = { describe('PackageTitle', () => { let wrapper; - function createComponent(packageEntity = packageWithTags) { + async function createComponent(packageEntity = packageWithTags) { wrapper = shallowMountExtended(PackageTitle, { propsData: { packageEntity }, stubs: { @@ -35,7 +36,7 @@ describe('PackageTitle', () => { GlResizeObserver: createMockDirective(), }, }); - return wrapper.vm.$nextTick(); + await nextTick(); } const findTitleArea = () => wrapper.findComponent(TitleArea); @@ -71,7 +72,7 @@ describe('PackageTitle', () => { await createComponent(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findPackageBadges()).toHaveLength(packageTags().length); }); @@ -85,7 +86,7 @@ describe('PackageTitle', () => { const { value } = getBinding(wrapper.element, 'gl-resize-observer'); value(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findPackageBadges()).toHaveLength(packageTags().length); }); }); diff --git a/spec/frontend/packages_and_registries/package_registry/components/functional/delete_package_spec.js b/spec/frontend/packages_and_registries/package_registry/components/functional/delete_package_spec.js index 5de30829fa5..14a70def7d0 100644 --- a/spec/frontend/packages_and_registries/package_registry/components/functional/delete_package_spec.js +++ b/spec/frontend/packages_and_registries/package_registry/components/functional/delete_package_spec.js @@ -1,4 +1,4 @@ -import { createLocalVue } from '@vue/test-utils'; +import Vue from 'vue'; import VueApollo from 'vue-apollo'; import waitForPromises from 'helpers/wait_for_promises'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; @@ -16,8 +16,6 @@ import { jest.mock('~/flash'); -const localVue = createLocalVue(); - describe('DeletePackage', () => { let wrapper; let apolloProvider; @@ -27,7 +25,7 @@ describe('DeletePackage', () => { const eventPayload = { id: '1' }; function createComponent(propsData = {}) { - localVue.use(VueApollo); + Vue.use(VueApollo); const requestHandlers = [ [getPackagesQuery, resolver], @@ -37,7 +35,6 @@ describe('DeletePackage', () => { wrapper = shallowMountExtended(DeletePackage, { propsData, - localVue, apolloProvider, scopedSlots: { default(props) { diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js b/spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js index 05f20f8150b..12a3eaa3873 100644 --- a/spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js +++ b/spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js @@ -1,5 +1,5 @@ import { GlSprintf } from '@gitlab/ui'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import VueRouter from 'vue-router'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; @@ -119,7 +119,7 @@ describe('packages_list_row', () => { findDeleteButton().vm.$emit('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.emitted('packageToDelete')).toBeTruthy(); expect(wrapper.emitted('packageToDelete')[0]).toEqual([packageWithoutTags]); }); diff --git a/spec/frontend/packages_and_registries/package_registry/pages/details_spec.js b/spec/frontend/packages_and_registries/package_registry/pages/details_spec.js index 637e2edf3be..b9fbaad7734 100644 --- a/spec/frontend/packages_and_registries/package_registry/pages/details_spec.js +++ b/spec/frontend/packages_and_registries/package_registry/pages/details_spec.js @@ -1,6 +1,6 @@ import { GlEmptyState, GlBadge, GlTabs, GlTab } from '@gitlab/ui'; -import { createLocalVue } from '@vue/test-utils'; -import { nextTick } from 'vue'; +import Vue, { nextTick } from 'vue'; + import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import { useMockLocationHelper } from 'helpers/mock_window_location_helper'; @@ -41,8 +41,6 @@ import { jest.mock('~/flash'); useMockLocationHelper(); -const localVue = createLocalVue(); - describe('PackagesApp', () => { let wrapper; let apolloProvider; @@ -64,7 +62,7 @@ describe('PackagesApp', () => { fileDeleteMutationResolver = jest.fn().mockResolvedValue(packageDestroyFileMutation()), routeId = '1', } = {}) { - localVue.use(VueApollo); + Vue.use(VueApollo); const requestHandlers = [ [getPackageDetails, resolver], @@ -73,7 +71,6 @@ describe('PackagesApp', () => { apolloProvider = createMockApollo(requestHandlers); wrapper = shallowMountExtended(PackagesApp, { - localVue, apolloProvider, provide, stubs: { diff --git a/spec/frontend/packages_and_registries/package_registry/pages/list_spec.js b/spec/frontend/packages_and_registries/package_registry/pages/list_spec.js index 8121d9c7dbd..0e74fbbc6d9 100644 --- a/spec/frontend/packages_and_registries/package_registry/pages/list_spec.js +++ b/spec/frontend/packages_and_registries/package_registry/pages/list_spec.js @@ -1,8 +1,8 @@ import { GlEmptyState, GlSprintf, GlLink } from '@gitlab/ui'; -import { createLocalVue } from '@vue/test-utils'; +import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; -import { nextTick } from 'vue'; + import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; @@ -27,8 +27,6 @@ import { packagesListQuery, packageData, pagination } from '../mock_data'; jest.mock('~/lib/utils/common_utils'); jest.mock('~/flash'); -const localVue = createLocalVue(); - describe('PackagesListApp', () => { let wrapper; let apolloProvider; @@ -61,13 +59,12 @@ describe('PackagesListApp', () => { resolver = jest.fn().mockResolvedValue(packagesListQuery()), provide = defaultProvide, } = {}) => { - localVue.use(VueApollo); + Vue.use(VueApollo); const requestHandlers = [[getPackagesQuery, resolver]]; apolloProvider = createMockApollo(requestHandlers); wrapper = shallowMountExtended(ListPage, { - localVue, apolloProvider, provide, stubs: { diff --git a/spec/frontend/packages_and_registries/settings/group/components/dependency_proxy_settings_spec.js b/spec/frontend/packages_and_registries/settings/group/components/dependency_proxy_settings_spec.js index f6c1d212b51..94f56e5c979 100644 --- a/spec/frontend/packages_and_registries/settings/group/components/dependency_proxy_settings_spec.js +++ b/spec/frontend/packages_and_registries/settings/group/components/dependency_proxy_settings_spec.js @@ -1,5 +1,5 @@ import { GlSprintf, GlToggle } from '@gitlab/ui'; -import { createLocalVue } from '@vue/test-utils'; +import Vue from 'vue'; import VueApollo from 'vue-apollo'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import createMockApollo from 'helpers/mock_apollo_helper'; @@ -33,8 +33,6 @@ import { jest.mock('~/flash'); jest.mock('~/packages_and_registries/settings/group/graphql/utils/optimistic_responses'); -const localVue = createLocalVue(); - describe('DependencyProxySettings', () => { let wrapper; let apolloProvider; @@ -47,7 +45,7 @@ describe('DependencyProxySettings', () => { groupDependencyProxyPath: 'group_dependency_proxy_path', }; - localVue.use(VueApollo); + Vue.use(VueApollo); const mountComponent = ({ provide = defaultProvide, @@ -63,7 +61,6 @@ describe('DependencyProxySettings', () => { apolloProvider = createMockApollo(requestHandlers); wrapper = shallowMountExtended(component, { - localVue, apolloProvider, provide, propsData: { diff --git a/spec/frontend/packages_and_registries/settings/group/components/group_settings_app_spec.js b/spec/frontend/packages_and_registries/settings/group/components/group_settings_app_spec.js index 933dac7f5a8..5c30074a6af 100644 --- a/spec/frontend/packages_and_registries/settings/group/components/group_settings_app_spec.js +++ b/spec/frontend/packages_and_registries/settings/group/components/group_settings_app_spec.js @@ -1,7 +1,8 @@ import { GlAlert } from '@gitlab/ui'; -import { shallowMount, createLocalVue } from '@vue/test-utils'; +import { shallowMount } from '@vue/test-utils'; +import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; -import { nextTick } from 'vue'; + import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; import PackagesSettings from '~/packages_and_registries/settings/group/components/packages_settings.vue'; @@ -19,8 +20,6 @@ import { jest.mock('~/flash'); -const localVue = createLocalVue(); - describe('Group Settings App', () => { let wrapper; let apolloProvider; @@ -36,14 +35,13 @@ describe('Group Settings App', () => { resolver = jest.fn().mockResolvedValue(groupPackageSettingsMock), provide = defaultProvide, } = {}) => { - localVue.use(VueApollo); + Vue.use(VueApollo); const requestHandlers = [[getGroupPackagesSettingsQuery, resolver]]; apolloProvider = createMockApollo(requestHandlers); wrapper = shallowMount(component, { - localVue, apolloProvider, provide, mocks: { diff --git a/spec/frontend/packages_and_registries/settings/group/components/package_settings_spec.js b/spec/frontend/packages_and_registries/settings/group/components/package_settings_spec.js index 693af21e24a..d92d42e7834 100644 --- a/spec/frontend/packages_and_registries/settings/group/components/package_settings_spec.js +++ b/spec/frontend/packages_and_registries/settings/group/components/package_settings_spec.js @@ -1,5 +1,5 @@ import { GlSprintf, GlLink } from '@gitlab/ui'; -import { createLocalVue } from '@vue/test-utils'; +import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import createMockApollo from 'helpers/mock_apollo_helper'; @@ -28,8 +28,6 @@ import { jest.mock('~/flash'); jest.mock('~/packages_and_registries/settings/group/graphql/utils/optimistic_responses'); -const localVue = createLocalVue(); - describe('Packages Settings', () => { let wrapper; let apolloProvider; @@ -42,14 +40,13 @@ describe('Packages Settings', () => { const mountComponent = ({ mutationResolver = jest.fn().mockResolvedValue(groupPackageSettingsMutationMock()), } = {}) => { - localVue.use(VueApollo); + Vue.use(VueApollo); const requestHandlers = [[updateNamespacePackageSettings, mutationResolver]]; apolloProvider = createMockApollo(requestHandlers); wrapper = shallowMountExtended(component, { - localVue, apolloProvider, provide: defaultProvide, propsData: { @@ -252,7 +249,7 @@ describe('Packages Settings', () => { emitMavenSettingsUpdate(); - await wrapper.vm.$nextTick(); + await nextTick(); // errors are reset on mutation call expect(findMavenDuplicatedSettings().props('duplicateExceptionRegexError')).toBe(''); diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/registry_settings_app_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/registry_settings_app_spec.js index cad5d4db033..a6c929844b1 100644 --- a/spec/frontend/packages_and_registries/settings/project/settings/components/registry_settings_app_spec.js +++ b/spec/frontend/packages_and_registries/settings/project/settings/components/registry_settings_app_spec.js @@ -1,5 +1,6 @@ import { GlAlert, GlSprintf, GlLink } from '@gitlab/ui'; -import { shallowMount, createLocalVue } from '@vue/test-utils'; +import { shallowMount } from '@vue/test-utils'; +import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; @@ -20,8 +21,6 @@ import { containerExpirationPolicyData, } from '../mock_data'; -const localVue = createLocalVue(); - describe('Registry Settings App', () => { let wrapper; let fakeApollo; @@ -56,13 +55,12 @@ describe('Registry Settings App', () => { }; const mountComponentWithApollo = ({ provide = defaultProvidedValues, resolver } = {}) => { - localVue.use(VueApollo); + Vue.use(VueApollo); const requestHandlers = [[expirationPolicyQuery, resolver]]; fakeApollo = createMockApollo(requestHandlers); mountComponent(provide, { - localVue, apolloProvider: fakeApollo, }); }; diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/settings_form_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/settings_form_spec.js index bc104a25ef9..625aa37fc0f 100644 --- a/spec/frontend/packages_and_registries/settings/project/settings/components/settings_form_spec.js +++ b/spec/frontend/packages_and_registries/settings/project/settings/components/settings_form_spec.js @@ -1,5 +1,6 @@ import { shallowMount, createLocalVue } from '@vue/test-utils'; import VueApollo from 'vue-apollo'; +import { nextTick } from 'vue'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; import { GlCard, GlLoadingIcon } from 'jest/packages_and_registries/shared/stubs'; @@ -201,7 +202,7 @@ describe('Settings Form', () => { finder().vm.$emit('input', 'foo'); expect(finder().props('error')).toEqual('bar'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(finder().props('error')).toEqual(''); }); @@ -213,7 +214,7 @@ describe('Settings Form', () => { finder().vm.$emit('validation', false); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findSaveButton().props('disabled')).toBe(true); }); @@ -252,7 +253,7 @@ describe('Settings Form', () => { findForm().trigger('reset'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findKeepRegexInput().props('error')).toBe(''); expect(findRemoveRegexInput().props('error')).toBe(''); @@ -319,7 +320,7 @@ describe('Settings Form', () => { findForm().trigger('submit'); await waitForPromises(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(UPDATE_SETTINGS_SUCCESS_MESSAGE); }); @@ -335,7 +336,7 @@ describe('Settings Form', () => { findForm().trigger('submit'); await waitForPromises(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('foo'); }); @@ -349,7 +350,7 @@ describe('Settings Form', () => { findForm().trigger('submit'); await waitForPromises(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(UPDATE_SETTINGS_ERROR_MESSAGE); }); @@ -368,7 +369,7 @@ describe('Settings Form', () => { findForm().trigger('submit'); await waitForPromises(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findKeepRegexInput().props('error')).toEqual('baz'); }); diff --git a/spec/frontend/pages/admin/projects/components/namespace_select_spec.js b/spec/frontend/pages/admin/projects/components/namespace_select_spec.js index 1fcc00489e3..f10b202f4d7 100644 --- a/spec/frontend/pages/admin/projects/components/namespace_select_spec.js +++ b/spec/frontend/pages/admin/projects/components/namespace_select_spec.js @@ -1,4 +1,5 @@ import { mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import Api from '~/api'; import NamespaceSelect from '~/pages/admin/projects/components/namespace_select.vue'; @@ -55,14 +56,14 @@ describe('Dropdown select component', () => { mountDropdown({ fieldName: 'namespace-input' }); // wait for dropdown options to populate - await wrapper.vm.$nextTick(); + await nextTick(); expect(findDropdownOption('user: Administrator').exists()).toBe(true); expect(findDropdownOption('group: GitLab Org').exists()).toBe(true); expect(findDropdownOption('group: Foobar').exists()).toBe(false); findDropdownOption('user: Administrator').trigger('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findNamespaceInput().attributes('value')).toBe('10'); expect(findDropdownToggle().text()).toBe('user: Administrator'); @@ -72,7 +73,7 @@ describe('Dropdown select component', () => { mountDropdown(); // wait for dropdown options to populate - await wrapper.vm.$nextTick(); + await nextTick(); findDropdownOption('group: GitLab Org').trigger('click'); diff --git a/spec/frontend/pages/profiles/password_prompt/password_prompt_modal_spec.js b/spec/frontend/pages/profiles/password_prompt/password_prompt_modal_spec.js index b722ac1e97b..c30b996437d 100644 --- a/spec/frontend/pages/profiles/password_prompt/password_prompt_modal_spec.js +++ b/spec/frontend/pages/profiles/password_prompt/password_prompt_modal_spec.js @@ -1,4 +1,5 @@ import { GlModal } from '@gitlab/ui'; +import { nextTick } from 'vue'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import { I18N_PASSWORD_PROMPT_CANCEL_BUTTON, @@ -62,7 +63,7 @@ describe('Password prompt modal', () => { setPassword(mockPassword); submitModal(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(handleConfirmPasswordSpy).toHaveBeenCalledTimes(1); expect(handleConfirmPasswordSpy).toHaveBeenCalledWith(mockPassword); @@ -73,7 +74,7 @@ describe('Password prompt modal', () => { expect(findConfirmBtnDisabledState()).toBe(true); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findConfirmBtnDisabledState()).toBe(false); }); @@ -84,7 +85,7 @@ describe('Password prompt modal', () => { expect(findConfirmBtnDisabledState()).toBe(true); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findConfirmBtnDisabledState()).toBe(true); }); diff --git a/spec/frontend/pages/projects/forks/new/components/fork_form_spec.js b/spec/frontend/pages/projects/forks/new/components/fork_form_spec.js index dd617b1ffc2..dc5f1cb9e61 100644 --- a/spec/frontend/pages/projects/forks/new/components/fork_form_spec.js +++ b/spec/frontend/pages/projects/forks/new/components/fork_form_spec.js @@ -4,6 +4,7 @@ import { mount, shallowMount } from '@vue/test-utils'; import axios from 'axios'; import AxiosMockAdapter from 'axios-mock-adapter'; import { kebabCase } from 'lodash'; +import { nextTick } from 'vue'; import createFlash from '~/flash'; import httpStatus from '~/lib/utils/http_status'; import * as urlUtility from '~/lib/utils/url_utility'; @@ -217,7 +218,7 @@ describe('ForkForm component', () => { it('changes to kebab case when project name changes', async () => { const newInput = `${projectPath}1`; findForkNameInput().vm.$emit('input', newInput); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findForkSlugInput().attributes('value')).toBe(kebabCase(newInput)); }); @@ -225,7 +226,7 @@ describe('ForkForm component', () => { it('does not change to kebab case when project slug is changed manually', async () => { const newInput = `${projectPath}1`; findForkSlugInput().vm.$emit('input', newInput); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findForkSlugInput().attributes('value')).toBe(newInput); }); @@ -273,7 +274,7 @@ describe('ForkForm component', () => { expect(wrapper.vm.form.fields.visibility.value).toBe('public'); await findFormSelectOptions().at(1).setSelected(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(getByRole(wrapper.element, 'radio', { name: /private/i }).checked).toBe(true); }); @@ -283,7 +284,7 @@ describe('ForkForm component', () => { await findFormSelectOptions().at(1).setSelected(); - await wrapper.vm.$nextTick(); + await nextTick(); const container = getByRole(wrapper.element, 'radiogroup', { name: /visibility/i }); const visibilityRadios = getAllByRole(container, 'radio'); @@ -419,7 +420,7 @@ describe('ForkForm component', () => { const form = wrapper.find(GlForm); await form.trigger('submit'); - await wrapper.vm.$nextTick(); + await nextTick(); }; describe('with invalid form', () => { diff --git a/spec/frontend/pages/projects/graphs/code_coverage_spec.js b/spec/frontend/pages/projects/graphs/code_coverage_spec.js index 1f9029b40c7..0f763e3220a 100644 --- a/spec/frontend/pages/projects/graphs/code_coverage_spec.js +++ b/spec/frontend/pages/projects/graphs/code_coverage_spec.js @@ -3,6 +3,7 @@ import { GlAreaChart } from '@gitlab/ui/dist/charts'; import { shallowMount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; +import { nextTick } from 'vue'; import waitForPromises from 'helpers/wait_for_promises'; import axios from '~/lib/utils/axios_utils'; import httpStatusCodes from '~/lib/utils/http_status'; @@ -143,7 +144,7 @@ describe('Code Coverage', () => { it('updates the selected dropdown option with an icon', async () => { findSecondDropdownItem().vm.$emit('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findFirstDropdownItem().attributes('ischecked')).toBeFalsy(); expect(findSecondDropdownItem().attributes('ischecked')).toBeTruthy(); @@ -155,7 +156,7 @@ describe('Code Coverage', () => { findSecondDropdownItem().vm.$emit('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.vm.selectedDailyCoverage).not.toBe(originalSelectedData); expect(wrapper.vm.selectedDailyCoverage).toBe(expectedData); diff --git a/spec/frontend/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js b/spec/frontend/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js index f3d76ca2c1b..ae5404f2d13 100644 --- a/spec/frontend/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js +++ b/spec/frontend/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js @@ -1,5 +1,6 @@ import { GlIcon } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import { trimText } from 'helpers/text_helper'; import IntervalPatternInput from '~/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue'; @@ -98,7 +99,7 @@ describe('Interval Pattern Input Component', () => { it('when a default option is selected', async () => { selectEveryDayRadio(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findCustomInput().attributes('disabled')).toBeUndefined(); }); @@ -106,7 +107,7 @@ describe('Interval Pattern Input Component', () => { it('when the custom option is selected', async () => { selectCustomRadio(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findCustomInput().attributes('disabled')).toBeUndefined(); }); @@ -150,11 +151,11 @@ describe('Interval Pattern Input Component', () => { it('when everyday is selected, update value', async () => { selectEveryWeekRadio(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findCustomInput().element.value).toBe(cronIntervalPresets.everyWeek); selectEveryDayRadio(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findCustomInput().element.value).toBe(cronIntervalPresets.everyDay); }); }); @@ -170,7 +171,7 @@ describe('Interval Pattern Input Component', () => { act(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findCustomInput().element.value).toBe(expectedValue); }); @@ -189,7 +190,7 @@ describe('Interval Pattern Input Component', () => { findCustomInput().setValue(newValue); - await wrapper.vm.$nextTick; + await nextTick; expect(findSelectedRadioKey()).toBe(customKey); }); diff --git a/spec/frontend/pages/projects/pipeline_schedules/shared/components/pipeline_schedule_callout_spec.js b/spec/frontend/pages/projects/pipeline_schedules/shared/components/pipeline_schedule_callout_spec.js index 5fed9fcaad2..2f61b5e9800 100644 --- a/spec/frontend/pages/projects/pipeline_schedules/shared/components/pipeline_schedule_callout_spec.js +++ b/spec/frontend/pages/projects/pipeline_schedules/shared/components/pipeline_schedule_callout_spec.js @@ -1,6 +1,7 @@ import { GlButton } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import Cookies from 'js-cookie'; +import { nextTick } from 'vue'; import PipelineSchedulesCallout from '~/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue'; const cookieKey = 'pipeline_schedules_callout_dismissed'; @@ -27,7 +28,7 @@ describe('Pipeline Schedule Callout', () => { Cookies.set(cookieKey, true); createComponent(); - await wrapper.vm.$nextTick(); + await nextTick(); }); afterEach(() => { @@ -71,7 +72,7 @@ describe('Pipeline Schedule Callout', () => { findDismissCalloutBtn().vm.$emit('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findInnerContentOfCallout().exists()).toBe(false); }); @@ -90,7 +91,7 @@ describe('Pipeline Schedule Callout', () => { it('is hidden when close button is clicked', async () => { findDismissCalloutBtn().vm.$emit('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findInnerContentOfCallout().exists()).toBe(false); }); diff --git a/spec/frontend/pages/projects/shared/permissions/components/project_setting_row_spec.js b/spec/frontend/pages/projects/shared/permissions/components/project_setting_row_spec.js index 7cbcbdcdd1f..6230809a6aa 100644 --- a/spec/frontend/pages/projects/shared/permissions/components/project_setting_row_spec.js +++ b/spec/frontend/pages/projects/shared/permissions/components/project_setting_row_spec.js @@ -1,5 +1,6 @@ import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import projectSettingRow from '~/pages/projects/shared/permissions/components/project_setting_row.vue'; describe('Project Setting Row', () => { @@ -18,43 +19,39 @@ describe('Project Setting Row', () => { wrapper.destroy(); }); - it('should show the label if it is set', () => { + it('should show the label if it is set', async () => { wrapper.setProps({ label: 'Test label' }); - return wrapper.vm.$nextTick(() => { - expect(wrapper.find('label').text()).toEqual('Test label'); - }); + await nextTick(); + expect(wrapper.find('label').text()).toEqual('Test label'); }); it('should hide the label if it is not set', () => { expect(wrapper.find('label').exists()).toBe(false); }); - it('should show the help icon with the correct help path if it is set', () => { + it('should show the help icon with the correct help path if it is set', async () => { wrapper.setProps({ label: 'Test label', helpPath: '/123' }); - return wrapper.vm.$nextTick(() => { - const link = wrapper.find('a'); + await nextTick(); + const link = wrapper.find('a'); - expect(link.exists()).toBe(true); - expect(link.attributes().href).toEqual('/123'); - }); + expect(link.exists()).toBe(true); + expect(link.attributes().href).toEqual('/123'); }); - it('should hide the help icon if no help path is set', () => { + it('should hide the help icon if no help path is set', async () => { wrapper.setProps({ label: 'Test label' }); - return wrapper.vm.$nextTick(() => { - expect(wrapper.find('a').exists()).toBe(false); - }); + await nextTick(); + expect(wrapper.find('a').exists()).toBe(false); }); - it('should show the help text if it is set', () => { + it('should show the help text if it is set', async () => { wrapper.setProps({ helpText: 'Test text' }); - return wrapper.vm.$nextTick(() => { - expect(wrapper.find('span').text()).toEqual('Test text'); - }); + await nextTick(); + expect(wrapper.find('span').text()).toEqual('Test text'); }); it('should hide the help text if it is set', () => { diff --git a/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js b/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js index fd581eebd1e..1f964e8bae2 100644 --- a/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js +++ b/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js @@ -48,10 +48,10 @@ describe('WikiForm', () => { return format.find(`option[value=${value}]`).setSelected(); }; - const triggerFormSubmit = () => { + const triggerFormSubmit = async () => { findForm().element.dispatchEvent(new Event('submit')); - return nextTick(); + await nextTick(); }; const dispatchBeforeUnload = () => { @@ -574,7 +574,7 @@ describe('WikiForm', () => { wrapper.findComponent(GlModal).vm.$emit('primary'); - await wrapper.vm.$nextTick(); + await nextTick(); }); it('switches to classic editor', () => { diff --git a/spec/frontend/performance_bar/components/add_request_spec.js b/spec/frontend/performance_bar/components/add_request_spec.js index c5247a43f27..5422481439e 100644 --- a/spec/frontend/performance_bar/components/add_request_spec.js +++ b/spec/frontend/performance_bar/components/add_request_spec.js @@ -1,4 +1,5 @@ import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import AddRequest from '~/performance_bar/components/add_request.vue'; describe('add request form', () => { @@ -17,9 +18,9 @@ describe('add request form', () => { }); describe('when clicking the button', () => { - beforeEach(() => { + beforeEach(async () => { wrapper.find('button').trigger('click'); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('shows the form', () => { @@ -27,9 +28,9 @@ describe('add request form', () => { }); describe('when pressing escape', () => { - beforeEach(() => { + beforeEach(async () => { wrapper.find('input').trigger('keyup.esc'); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('hides the input', () => { @@ -38,12 +39,11 @@ describe('add request form', () => { }); describe('when submitting the form', () => { - beforeEach(() => { + beforeEach(async () => { wrapper.find('input').setValue('http://gitlab.example.com/users/root/calendar.json'); - return wrapper.vm.$nextTick().then(() => { - wrapper.find('input').trigger('keyup.enter'); - return wrapper.vm.$nextTick(); - }); + await nextTick(); + wrapper.find('input').trigger('keyup.enter'); + await nextTick(); }); it('emits an event to add the request', () => { @@ -57,11 +57,10 @@ describe('add request form', () => { expect(wrapper.find('input').exists()).toBe(false); }); - it('clears the value for next time', () => { + it('clears the value for next time', async () => { wrapper.find('button').trigger('click'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.find('input').text()).toEqual(''); - }); + await nextTick(); + expect(wrapper.find('input').text()).toEqual(''); }); }); }); diff --git a/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js b/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js index d813d67b94b..35315db39f8 100644 --- a/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js +++ b/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js @@ -1,5 +1,6 @@ import { GlIcon, GlLink, GlLoadingIcon, GlSprintf } from '@gitlab/ui'; -import { shallowMount, createLocalVue } from '@vue/test-utils'; +import { shallowMount } from '@vue/test-utils'; +import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; @@ -8,8 +9,7 @@ import getPipelineQuery from '~/pipeline_editor/graphql/queries/pipeline.query.g import PipelineEditorMiniGraph from '~/pipeline_editor/components/header/pipeline_editor_mini_graph.vue'; import { mockCommitSha, mockProjectPipeline, mockProjectFullPath } from '../../mock_data'; -const localVue = createLocalVue(); -localVue.use(VueApollo); +Vue.use(VueApollo); describe('Pipeline Status', () => { let wrapper; @@ -21,7 +21,6 @@ describe('Pipeline Status', () => { mockApollo = createMockApollo(handlers); wrapper = shallowMount(PipelineStatus, { - localVue, apolloProvider: mockApollo, propsData: { commitSha: mockCommitSha, diff --git a/spec/frontend/pipeline_editor/components/header/pipline_editor_mini_graph_spec.js b/spec/frontend/pipeline_editor/components/header/pipline_editor_mini_graph_spec.js index 2f26b4d145c..aae8656b4ad 100644 --- a/spec/frontend/pipeline_editor/components/header/pipline_editor_mini_graph_spec.js +++ b/spec/frontend/pipeline_editor/components/header/pipline_editor_mini_graph_spec.js @@ -1,4 +1,5 @@ -import { shallowMount, createLocalVue } from '@vue/test-utils'; +import { shallowMount } from '@vue/test-utils'; +import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; @@ -8,8 +9,7 @@ import getLinkedPipelinesQuery from '~/projects/commit_box/info/graphql/queries/ import { PIPELINE_FAILURE } from '~/pipeline_editor/constants'; import { mockLinkedPipelines, mockProjectFullPath, mockProjectPipeline } from '../../mock_data'; -const localVue = createLocalVue(); -localVue.use(VueApollo); +Vue.use(VueApollo); describe('Pipeline Status', () => { let wrapper; @@ -36,7 +36,6 @@ describe('Pipeline Status', () => { createComponent({ hasStages, options: { - localVue, apolloProvider: mockApollo, }, }); diff --git a/spec/frontend/pipeline_editor/components/header/validation_segment_spec.js b/spec/frontend/pipeline_editor/components/header/validation_segment_spec.js index 570323826d1..1ad621e6f45 100644 --- a/spec/frontend/pipeline_editor/components/header/validation_segment_spec.js +++ b/spec/frontend/pipeline_editor/components/header/validation_segment_spec.js @@ -1,6 +1,7 @@ import VueApollo from 'vue-apollo'; import { GlIcon } from '@gitlab/ui'; -import { shallowMount, createLocalVue } from '@vue/test-utils'; +import { shallowMount } from '@vue/test-utils'; +import Vue from 'vue'; import { escape } from 'lodash'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import createMockApollo from 'helpers/mock_apollo_helper'; @@ -24,8 +25,7 @@ import { mockYmlHelpPagePath, } from '../../mock_data'; -const localVue = createLocalVue(); -localVue.use(VueApollo); +Vue.use(VueApollo); describe('Validation segment component', () => { let wrapper; @@ -45,7 +45,6 @@ describe('Validation segment component', () => { wrapper = extendedWrapper( shallowMount(ValidationSegment, { - localVue, apolloProvider: mockApollo, provide: { ymlHelpPagePath: mockYmlHelpPagePath, diff --git a/spec/frontend/pipeline_new/components/pipeline_new_form_spec.js b/spec/frontend/pipeline_new/components/pipeline_new_form_spec.js index 9e2bf1bd367..eec55091efa 100644 --- a/spec/frontend/pipeline_new/components/pipeline_new_form_spec.js +++ b/spec/frontend/pipeline_new/components/pipeline_new_form_spec.js @@ -1,6 +1,7 @@ import { GlForm, GlSprintf, GlLoadingIcon } from '@gitlab/ui'; import { mount, shallowMount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; +import { nextTick } from 'vue'; import CreditCardValidationRequiredAlert from 'ee_component/billings/components/cc_validation_required_alert.vue'; import { TEST_HOST } from 'helpers/test_constants'; import waitForPromises from 'helpers/wait_for_promises'; @@ -122,7 +123,7 @@ describe('Pipeline New Form', () => { it('removes ci variable row on remove icon button click', async () => { findRemoveIcons().at(1).trigger('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findVariableRows()).toHaveLength(2); }); @@ -132,7 +133,7 @@ describe('Pipeline New Form', () => { input.element.value = 'test_var_2'; input.trigger('change'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findVariableRows()).toHaveLength(4); expect(findKeyInputs().at(3).element.value).toBe(''); @@ -205,7 +206,7 @@ describe('Pipeline New Form', () => { mainInput.element.value = 'build_var'; mainInput.trigger('change'); - await wrapper.vm.$nextTick(); + await nextTick(); selectBranch('branch-1'); @@ -215,7 +216,7 @@ describe('Pipeline New Form', () => { branchOneInput.element.value = 'deploy_var'; branchOneInput.trigger('change'); - await wrapper.vm.$nextTick(); + await nextTick(); selectBranch('main'); @@ -309,7 +310,7 @@ describe('Pipeline New Form', () => { findKeyInputs().at(0).element.value = 'yml_var_modified'; findKeyInputs().at(0).trigger('change'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findVariableRows().at(0).text()).not.toContain(mockYmlDesc); }); @@ -418,7 +419,7 @@ describe('Pipeline New Form', () => { findCCAlert().vm.$emit('dismiss'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findCCAlert().exists()).toBe(false); expect(wrapper.vm.$data.error).toBe(null); diff --git a/spec/frontend/pipelines/components/dag/dag_annotations_spec.js b/spec/frontend/pipelines/components/dag/dag_annotations_spec.js index 1941a7f2777..212f8e19a6d 100644 --- a/spec/frontend/pipelines/components/dag/dag_annotations_spec.js +++ b/spec/frontend/pipelines/components/dag/dag_annotations_spec.js @@ -1,5 +1,6 @@ import { GlButton } from '@gitlab/ui'; import { shallowMount, mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import DagAnnotations from '~/pipelines/components/dag/dag_annotations.vue'; import { singleNote, multiNote } from './mock_data'; @@ -82,26 +83,24 @@ describe('The DAG annotations', () => { }); describe('clicking hide', () => { - it('hides listed items and changes text to show', () => { + it('hides listed items and changes text to show', async () => { expect(getAllTextBlocks().length).toBe(Object.keys(multiNote).length); expect(getToggleButton().text()).toBe('Hide list'); getToggleButton().trigger('click'); - return wrapper.vm.$nextTick().then(() => { - expect(getAllTextBlocks().length).toBe(0); - expect(getToggleButton().text()).toBe('Show list'); - }); + await nextTick(); + expect(getAllTextBlocks().length).toBe(0); + expect(getToggleButton().text()).toBe('Show list'); }); }); describe('clicking show', () => { - it('shows listed items and changes text to hide', () => { + it('shows listed items and changes text to hide', async () => { getToggleButton().trigger('click'); getToggleButton().trigger('click'); - return wrapper.vm.$nextTick().then(() => { - expect(getAllTextBlocks().length).toBe(Object.keys(multiNote).length); - expect(getToggleButton().text()).toBe('Hide list'); - }); + await nextTick(); + expect(getAllTextBlocks().length).toBe(Object.keys(multiNote).length); + expect(getToggleButton().text()).toBe('Hide list'); }); }); }); diff --git a/spec/frontend/pipelines/components/dag/dag_spec.js b/spec/frontend/pipelines/components/dag/dag_spec.js index 14030930657..d78df3eb35e 100644 --- a/spec/frontend/pipelines/components/dag/dag_spec.js +++ b/spec/frontend/pipelines/components/dag/dag_spec.js @@ -1,5 +1,6 @@ import { GlAlert, GlEmptyState } from '@gitlab/ui'; import { mount, shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import { ADD_NOTE, REMOVE_NOTE, REPLACE_NOTES } from '~/pipelines/components/dag/constants'; import Dag from '~/pipelines/components/dag/dag.vue'; import DagAnnotations from '~/pipelines/components/dag/dag_annotations.vue'; @@ -153,11 +154,11 @@ describe('Pipeline DAG graph wrapper', () => { expect(getNotes().exists()).toBe(false); getGraph().vm.$emit('update-annotation', { type: ADD_NOTE, data: currentNote }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(getNotes().exists()).toBe(true); getGraph().vm.$emit('update-annotation', { type: REMOVE_NOTE, data: currentNote }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(getNotes().exists()).toBe(false); }); @@ -165,11 +166,11 @@ describe('Pipeline DAG graph wrapper', () => { expect(getNotes().exists()).toBe(false); getGraph().vm.$emit('update-annotation', { type: REPLACE_NOTES, data: multiNote }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(getNotes().exists()).toBe(true); getGraph().vm.$emit('update-annotation', { type: REPLACE_NOTES, data: {} }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(getNotes().exists()).toBe(false); }); }); diff --git a/spec/frontend/pipelines/components/jobs/jobs_app_spec.js b/spec/frontend/pipelines/components/jobs/jobs_app_spec.js index 547c0cdda5e..65814ad9a7f 100644 --- a/spec/frontend/pipelines/components/jobs/jobs_app_spec.js +++ b/spec/frontend/pipelines/components/jobs/jobs_app_spec.js @@ -1,5 +1,6 @@ import { GlIntersectionObserver, GlSkeletonLoader } from '@gitlab/ui'; -import { createLocalVue, shallowMount } from '@vue/test-utils'; +import { shallowMount } from '@vue/test-utils'; +import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; @@ -9,8 +10,7 @@ import JobsTable from '~/jobs/components/table/jobs_table.vue'; import getPipelineJobsQuery from '~/pipelines/graphql/queries/get_pipeline_jobs.query.graphql'; import { mockPipelineJobsQueryResponse } from '../../mock_data'; -const localVue = createLocalVue(); -localVue.use(VueApollo); +Vue.use(VueApollo); jest.mock('~/flash'); @@ -36,7 +36,6 @@ describe('Jobs app', () => { fullPath: 'root/ci-project', pipelineIid: 1, }, - localVue, apolloProvider: createMockApolloProvider(resolver), }); }; diff --git a/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js b/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js index 661c8d99477..97b59a09518 100644 --- a/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js +++ b/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js @@ -1,6 +1,7 @@ import { GlFilteredSearch } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; +import { nextTick } from 'vue'; import Api from '~/api'; import axios from '~/lib/utils/axios_utils'; import PipelinesFilteredSearch from '~/pipelines/components/pipelines_list/pipelines_filtered_search.vue'; @@ -103,46 +104,42 @@ describe('Pipelines filtered search', () => { expect(wrapper.emitted('filterPipelines')[0]).toEqual([mockSearch]); }); - it('disables tag name token when branch name token is active', () => { + it('disables tag name token when branch name token is active', async () => { findFilteredSearch().vm.$emit('input', [ { type: 'ref', value: { data: 'branch-1', operator: '=' } }, { type: 'filtered-search-term', value: { data: '' } }, ]); - return wrapper.vm.$nextTick().then(() => { - expect(findBranchToken().disabled).toBe(false); - expect(findTagToken().disabled).toBe(true); - }); + await nextTick(); + expect(findBranchToken().disabled).toBe(false); + expect(findTagToken().disabled).toBe(true); }); - it('disables branch name token when tag name token is active', () => { + it('disables branch name token when tag name token is active', async () => { findFilteredSearch().vm.$emit('input', [ { type: 'tag', value: { data: 'tag-1', operator: '=' } }, { type: 'filtered-search-term', value: { data: '' } }, ]); - return wrapper.vm.$nextTick().then(() => { - expect(findBranchToken().disabled).toBe(true); - expect(findTagToken().disabled).toBe(false); - }); + await nextTick(); + expect(findBranchToken().disabled).toBe(true); + expect(findTagToken().disabled).toBe(false); }); - it('resets tokens disabled state on clear', () => { + it('resets tokens disabled state on clear', async () => { findFilteredSearch().vm.$emit('clearInput'); - return wrapper.vm.$nextTick().then(() => { - expect(findBranchToken().disabled).toBe(false); - expect(findTagToken().disabled).toBe(false); - }); + await nextTick(); + expect(findBranchToken().disabled).toBe(false); + expect(findTagToken().disabled).toBe(false); }); - it('resets tokens disabled state when clearing tokens by backspace', () => { + it('resets tokens disabled state when clearing tokens by backspace', async () => { findFilteredSearch().vm.$emit('input', [{ type: 'filtered-search-term', value: { data: '' } }]); - return wrapper.vm.$nextTick().then(() => { - expect(findBranchToken().disabled).toBe(false); - expect(findTagToken().disabled).toBe(false); - }); + await nextTick(); + expect(findBranchToken().disabled).toBe(false); + expect(findTagToken().disabled).toBe(false); }); describe('Url query params', () => { diff --git a/spec/frontend/pipelines/graph/action_component_spec.js b/spec/frontend/pipelines/graph/action_component_spec.js index 177b026491c..f3aae21163b 100644 --- a/spec/frontend/pipelines/graph/action_component_spec.js +++ b/spec/frontend/pipelines/graph/action_component_spec.js @@ -1,6 +1,7 @@ import { GlButton } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; +import { nextTick } from 'vue'; import waitForPromises from 'helpers/wait_for_promises'; import axios from '~/lib/utils/axios_utils'; import ActionComponent from '~/pipelines/components/jobs_shared/action_component.vue'; @@ -33,16 +34,11 @@ describe('pipeline graph action component', () => { expect(wrapper.attributes('title')).toBe('bar'); }); - it('should update bootstrap tooltip when title changes', (done) => { + it('should update bootstrap tooltip when title changes', async () => { wrapper.setProps({ tooltipText: 'changed' }); - wrapper.vm - .$nextTick() - .then(() => { - expect(wrapper.attributes('title')).toBe('changed'); - }) - .then(done) - .catch(done.fail); + await nextTick(); + expect(wrapper.attributes('title')).toBe('changed'); }); it('should render an svg', () => { @@ -64,13 +60,11 @@ describe('pipeline graph action component', () => { .catch(done.fail); }); - it('renders a loading icon while waiting for request', (done) => { + it('renders a loading icon while waiting for request', async () => { findButton().trigger('click'); - wrapper.vm.$nextTick(() => { - expect(wrapper.find('.js-action-icon-loading').exists()).toBe(true); - done(); - }); + await nextTick(); + expect(wrapper.find('.js-action-icon-loading').exists()).toBe(true); }); }); }); diff --git a/spec/frontend/pipelines/graph/job_item_spec.js b/spec/frontend/pipelines/graph/job_item_spec.js index 06f1fa4c827..a6b3a96144a 100644 --- a/spec/frontend/pipelines/graph/job_item_spec.js +++ b/spec/frontend/pipelines/graph/job_item_spec.js @@ -1,4 +1,5 @@ import { mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import JobItem from '~/pipelines/components/graph/job_item.vue'; describe('pipeline graph job item', () => { @@ -74,22 +75,19 @@ describe('pipeline graph job item', () => { }); describe('name with link', () => { - it('should render the job name and status with a link', (done) => { + it('should render the job name and status with a link', async () => { createWrapper({ job: mockJob }); - wrapper.vm.$nextTick(() => { - const link = wrapper.find('a'); + await nextTick(); + const link = wrapper.find('a'); - expect(link.attributes('href')).toBe(mockJob.status.detailsPath); + expect(link.attributes('href')).toBe(mockJob.status.detailsPath); - expect(link.attributes('title')).toBe(`${mockJob.name} - ${mockJob.status.label}`); + expect(link.attributes('title')).toBe(`${mockJob.name} - ${mockJob.status.label}`); - expect(wrapper.find('.ci-status-icon-success').exists()).toBe(true); - - expect(wrapper.text()).toBe(mockJob.name); + expect(wrapper.find('.ci-status-icon-success').exists()).toBe(true); - done(); - }); + expect(wrapper.text()).toBe(mockJob.name); }); }); diff --git a/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js b/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js index 5897da4b8c2..ca283f3b4ce 100644 --- a/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js +++ b/spec/frontend/pipelines/graph/linked_pipelines_column_spec.js @@ -1,4 +1,5 @@ -import { mount, shallowMount, createLocalVue } from '@vue/test-utils'; +import { mount, shallowMount } from '@vue/test-utils'; +import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; @@ -41,13 +42,11 @@ describe('Linked Pipelines Column', () => { const findPipelineGraph = () => wrapper.find(PipelineGraph); const findExpandButton = () => wrapper.find('[data-testid="expand-pipeline-button"]'); - const localVue = createLocalVue(); - localVue.use(VueApollo); + Vue.use(VueApollo); const createComponent = ({ apolloProvider, mountFn = shallowMount, props = {} } = {}) => { wrapper = mountFn(LinkedPipelinesColumn, { apolloProvider, - localVue, propsData: { ...defaultProps, ...props, @@ -108,7 +107,7 @@ describe('Linked Pipelines Column', () => { expect(layersFn).not.toHaveBeenCalled(); await clickExpandButtonAndAwaitTimers(); await wrapper.setProps({ viewType: LAYER_VIEW }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(layersFn).toHaveBeenCalledTimes(1); await wrapper.setProps({ viewType: STAGE_VIEW }); await wrapper.setProps({ viewType: LAYER_VIEW }); diff --git a/spec/frontend/pipelines/pipeline_triggerer_spec.js b/spec/frontend/pipelines/pipeline_triggerer_spec.js index ffb2721f159..701b1691c7b 100644 --- a/spec/frontend/pipelines/pipeline_triggerer_spec.js +++ b/spec/frontend/pipelines/pipeline_triggerer_spec.js @@ -1,4 +1,5 @@ import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import pipelineTriggerer from '~/pipelines/components/pipelines_list/pipeline_triggerer.vue'; import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue'; @@ -47,15 +48,14 @@ describe('Pipelines Triggerer', () => { }); }); - it('should render "API" when no triggerer is provided', () => { + it('should render "API" when no triggerer is provided', async () => { wrapper.setProps({ pipeline: { user: null, }, }); - return wrapper.vm.$nextTick(() => { - expect(wrapper.find('.js-pipeline-url-api').text()).toEqual('API'); - }); + await nextTick(); + expect(wrapper.find('.js-pipeline-url-api').text()).toEqual('API'); }); }); diff --git a/spec/frontend/pipelines/pipelines_actions_spec.js b/spec/frontend/pipelines/pipelines_actions_spec.js index c4bfec8ae14..a8af30a5710 100644 --- a/spec/frontend/pipelines/pipelines_actions_spec.js +++ b/spec/frontend/pipelines/pipelines_actions_spec.js @@ -1,6 +1,7 @@ import { GlDropdown, GlDropdownItem } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; +import { nextTick } from 'vue'; import waitForPromises from 'helpers/wait_for_promises'; import { TEST_HOST } from 'spec/test_constants'; import createFlash from '~/flash'; @@ -68,7 +69,7 @@ describe('Pipelines Actions dropdown', () => { findAllDropdownItems().at(0).vm.$emit('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findDropdown().props('loading')).toBe(true); await waitForPromises(); @@ -80,7 +81,7 @@ describe('Pipelines Actions dropdown', () => { findAllDropdownItems().at(0).vm.$emit('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findDropdown().props('loading')).toBe(true); await waitForPromises(); diff --git a/spec/frontend/popovers/components/popovers_spec.js b/spec/frontend/popovers/components/popovers_spec.js index 2751a878e51..6fdcd34ae83 100644 --- a/spec/frontend/popovers/components/popovers_spec.js +++ b/spec/frontend/popovers/components/popovers_spec.js @@ -1,5 +1,6 @@ import { GlPopover } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import { useMockMutationObserver } from 'helpers/mock_dom_observer'; import Popovers from '~/popovers/components/popovers.vue'; @@ -7,10 +8,10 @@ describe('popovers/components/popovers.vue', () => { const { trigger: triggerMutate } = useMockMutationObserver(); let wrapper; - const buildWrapper = (...targets) => { + const buildWrapper = async (...targets) => { wrapper = shallowMount(Popovers); wrapper.vm.addPopovers(targets); - return wrapper.vm.$nextTick(); + await nextTick(); }; const createPopoverTarget = (options = {}) => { @@ -49,7 +50,7 @@ describe('popovers/components/popovers.vue', () => { buildWrapper(target); wrapper.vm.addPopovers([target]); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.findAll(GlPopover)).toHaveLength(1); }); @@ -86,7 +87,7 @@ describe('popovers/components/popovers.vue', () => { await buildWrapper(createPopoverTarget(), createPopoverTarget()); wrapper.vm.dispose(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(allPopovers()).toHaveLength(0); }); @@ -97,7 +98,7 @@ describe('popovers/components/popovers.vue', () => { await buildWrapper(target, createPopoverTarget()); wrapper.vm.dispose(target); - await wrapper.vm.$nextTick(); + await nextTick(); expect(allPopovers()).toHaveLength(1); }); @@ -109,13 +110,13 @@ describe('popovers/components/popovers.vue', () => { await buildWrapper(target); wrapper.vm.addPopovers([target, createPopoverTarget()]); - await wrapper.vm.$nextTick(); + await nextTick(); triggerMutate(document.body, { entry: { removedNodes: [target] }, options: { childList: true }, }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(allPopovers()).toHaveLength(1); }); diff --git a/spec/frontend/profile/account/components/update_username_spec.js b/spec/frontend/profile/account/components/update_username_spec.js index bda07af4feb..e342b7c4ba1 100644 --- a/spec/frontend/profile/account/components/update_username_spec.js +++ b/spec/frontend/profile/account/components/update_username_spec.js @@ -1,6 +1,7 @@ import { GlModal } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; +import { nextTick } from 'vue'; import { TEST_HOST } from 'helpers/test_constants'; import createFlash from '~/flash'; import axios from '~/lib/utils/axios_utils'; @@ -58,7 +59,7 @@ describe('UpdateUsername component', () => { it('has a disabled button if the username was not changed', async () => { const { openModalBtn } = findElements(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(openModalBtn.props('disabled')).toBe(true); }); @@ -69,7 +70,7 @@ describe('UpdateUsername component', () => { input.element.value = 'newUsername'; input.trigger('input'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(openModalBtn.props('disabled')).toBe(false); }); @@ -83,7 +84,7 @@ describe('UpdateUsername component', () => { // eslint-disable-next-line no-restricted-syntax wrapper.setData({ newUsername }); - await wrapper.vm.$nextTick(); + await nextTick(); }); it('confirmation modal contains proper header and body', async () => { @@ -100,7 +101,7 @@ describe('UpdateUsername component', () => { jest.spyOn(axios, 'put'); await wrapper.vm.onConfirm(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(axios.put).toHaveBeenCalledWith(actionUrl, { user: { username: newUsername } }); }); @@ -117,7 +118,7 @@ describe('UpdateUsername component', () => { }); await wrapper.vm.onConfirm(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(input.attributes('disabled')).toBe(undefined); expect(openModalBtn.props('disabled')).toBe(true); diff --git a/spec/frontend/projects/commit/components/branches_dropdown_spec.js b/spec/frontend/projects/commit/components/branches_dropdown_spec.js index 30556cdeae1..e2848e615c3 100644 --- a/spec/frontend/projects/commit/components/branches_dropdown_spec.js +++ b/spec/frontend/projects/commit/components/branches_dropdown_spec.js @@ -1,6 +1,6 @@ import { GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants'; @@ -115,7 +115,7 @@ describe('BranchesDropdown', () => { findSearchBoxByType().vm.$emit('input', '_anything_'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(spy).toHaveBeenCalledWith('_anything_'); expect(wrapper.vm.searchTerm).toBe('_anything_'); diff --git a/spec/frontend/projects/commit/components/form_modal_spec.js b/spec/frontend/projects/commit/components/form_modal_spec.js index 93e2ae13628..79e9dab935d 100644 --- a/spec/frontend/projects/commit/components/form_modal_spec.js +++ b/spec/frontend/projects/commit/components/form_modal_spec.js @@ -2,6 +2,7 @@ import { GlModal, GlForm, GlFormCheckbox, GlSprintf } from '@gitlab/ui'; import { within } from '@testing-library/dom'; import { shallowMount, mount, createWrapper } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; +import { nextTick } from 'vue'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import api from '~/api'; import axios from '~/lib/utils/axios_utils'; @@ -156,7 +157,7 @@ describe('CommitFormModal', () => { it('Changes the start_branch input value', async () => { findBranchesDropdown().vm.$emit('selectBranch', '_changed_branch_value_'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findStartBranch().attributes('value')).toBe('_changed_branch_value_'); }); @@ -165,7 +166,7 @@ describe('CommitFormModal', () => { createComponent(shallowMount, {}, {}, { isCherryPick: true }); findProjectsDropdown().vm.$emit('selectProject', '_changed_project_value_'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findTargetProject().attributes('value')).toBe('_changed_project_value_'); }); @@ -174,7 +175,7 @@ describe('CommitFormModal', () => { it('action primary button triggers Redis HLL tracking api call', async () => { createComponent(mount, {}, {}, { primaryActionEventName: 'test_event' }); - await wrapper.vm.$nextTick(); + await nextTick(); jest.spyOn(findForm().element, 'submit'); diff --git a/spec/frontend/projects/commits/components/author_select_spec.js b/spec/frontend/projects/commits/components/author_select_spec.js index eda61758101..4e567ab030e 100644 --- a/spec/frontend/projects/commits/components/author_select_spec.js +++ b/spec/frontend/projects/commits/components/author_select_spec.js @@ -1,6 +1,6 @@ import { GlDropdown, GlDropdownSectionHeader, GlSearchBoxByType, GlDropdownItem } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import * as urlUtility from '~/lib/utils/url_utility'; import AuthorSelect from '~/projects/commits/components/author_select.vue'; @@ -63,36 +63,33 @@ describe('Author Select', () => { const findDropdownItems = () => wrapper.findAll(GlDropdownItem); describe('user is searching via "filter by commit message"', () => { - it('disables dropdown container', () => { + it('disables dropdown container', async () => { // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax wrapper.setData({ hasSearchParam: true }); - return wrapper.vm.$nextTick().then(() => { - expect(findDropdownContainer().attributes('disabled')).toBeFalsy(); - }); + await nextTick(); + expect(findDropdownContainer().attributes('disabled')).toBeFalsy(); }); - it('has correct tooltip message', () => { + it('has correct tooltip message', async () => { // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax wrapper.setData({ hasSearchParam: true }); - return wrapper.vm.$nextTick().then(() => { - expect(findDropdownContainer().attributes('title')).toBe( - 'Searching by both author and message is currently not supported.', - ); - }); + await nextTick(); + expect(findDropdownContainer().attributes('title')).toBe( + 'Searching by both author and message is currently not supported.', + ); }); - it('disables dropdown', () => { + it('disables dropdown', async () => { // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax wrapper.setData({ hasSearchParam: false }); - return wrapper.vm.$nextTick().then(() => { - expect(findDropdown().attributes('disabled')).toBeFalsy(); - }); + await nextTick(); + expect(findDropdown().attributes('disabled')).toBeFalsy(); }); it('hasSearchParam if user types a truthy string', () => { @@ -107,14 +104,13 @@ describe('Author Select', () => { expect(findDropdown().attributes('text')).toBe('Author'); }); - it('displays the current selected author', () => { + it('displays the current selected author', async () => { // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax wrapper.setData({ currentAuthor }); - return wrapper.vm.$nextTick().then(() => { - expect(findDropdown().attributes('text')).toBe(currentAuthor); - }); + await nextTick(); + expect(findDropdown().attributes('text')).toBe(currentAuthor); }); it('displays correct header text', () => { @@ -149,13 +145,12 @@ describe('Author Select', () => { expect(findDropdownItems().at(0).text()).toBe('Any Author'); }); - it('displays the project authors', () => { - return wrapper.vm.$nextTick().then(() => { - expect(findDropdownItems()).toHaveLength(authors.length + 1); - }); + it('displays the project authors', async () => { + await nextTick(); + expect(findDropdownItems()).toHaveLength(authors.length + 1); }); - it('has the correct props', () => { + it('has the correct props', async () => { const [{ avatar_url, username }] = authors; const result = { avatarUrl: avatar_url, @@ -167,15 +162,13 @@ describe('Author Select', () => { // eslint-disable-next-line no-restricted-syntax wrapper.setData({ currentAuthor }); - return wrapper.vm.$nextTick().then(() => { - expect(findDropdownItems().at(1).props()).toEqual(expect.objectContaining(result)); - }); + await nextTick(); + expect(findDropdownItems().at(1).props()).toEqual(expect.objectContaining(result)); }); - it("display the author's name", () => { - return wrapper.vm.$nextTick().then(() => { - expect(findDropdownItems().at(1).text()).toBe(currentAuthor); - }); + it("display the author's name", async () => { + await nextTick(); + expect(findDropdownItems().at(1).text()).toBe(currentAuthor); }); it('passes selected author to redirectPath', () => { diff --git a/spec/frontend/projects/compare/components/app_spec.js b/spec/frontend/projects/compare/components/app_spec.js index 7989a6f3d74..18e7f2e0f6e 100644 --- a/spec/frontend/projects/compare/components/app_spec.js +++ b/spec/frontend/projects/compare/components/app_spec.js @@ -1,5 +1,6 @@ import { GlButton } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import CompareApp from '~/projects/compare/components/app.vue'; import RevisionCard from '~/projects/compare/components/revision_card.vue'; import { appDefaultProps as defaultProps } from './mock_data'; @@ -91,7 +92,7 @@ describe('CompareApp component', () => { project, }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findTargetRevisionCard().props('selectedProject')).toEqual( expect.objectContaining(project), @@ -106,7 +107,7 @@ describe('CompareApp component', () => { revision, }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findSourceRevisionCard().props('paramsBranch')).toBe(revision); }); @@ -125,7 +126,7 @@ describe('CompareApp component', () => { it('swaps revisions when clicked', async () => { findSwapRevisionsButton().vm.$emit('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findTargetRevisionCard().props('paramsBranch')).toBe(defaultProps.paramsTo); expect(findSourceRevisionCard().props('paramsBranch')).toBe(defaultProps.paramsFrom); diff --git a/spec/frontend/projects/compare/components/repo_dropdown_spec.js b/spec/frontend/projects/compare/components/repo_dropdown_spec.js index 27a7a32ebca..98aec347e4b 100644 --- a/spec/frontend/projects/compare/components/repo_dropdown_spec.js +++ b/spec/frontend/projects/compare/components/repo_dropdown_spec.js @@ -1,5 +1,6 @@ import { GlDropdown, GlDropdownItem } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import RepoDropdown from '~/projects/compare/components/repo_dropdown.vue'; import { revisionCardDefaultProps as defaultProps } from './mock_data'; @@ -39,7 +40,7 @@ describe('RepoDropdown component', () => { it('does not emit `changeTargetProject` event', async () => { wrapper.vm.emitTargetProject('foo'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.emitted('changeTargetProject')).toBeUndefined(); }); }); @@ -67,13 +68,13 @@ describe('RepoDropdown component', () => { it('updates the hidden input value when onClick method is triggered', async () => { const repoId = '1'; wrapper.vm.onClick({ id: repoId }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findHiddenInput().attributes('value')).toBe(repoId); }); it('emits `selectProject` event when another target project is selected', async () => { findGlDropdown().findAll(GlDropdownItem).at(0).vm.$emit('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.emitted('selectProject')[0][0]).toEqual({ direction: 'from', diff --git a/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js b/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js index eb80d57fb3c..102f95f65da 100644 --- a/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js +++ b/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js @@ -1,6 +1,7 @@ import { GlDropdown, GlDropdownItem } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import AxiosMockAdapter from 'axios-mock-adapter'; +import { nextTick } from 'vue'; import createFlash from '~/flash'; import axios from '~/lib/utils/axios_utils'; import RevisionDropdown from '~/projects/compare/components/revision_dropdown_legacy.vue'; @@ -105,7 +106,7 @@ describe('RevisionDropdown component', () => { // eslint-disable-next-line no-restricted-syntax wrapper.setData({ branches: ['some-branch'] }); - await wrapper.vm.$nextTick(); + await nextTick(); findFirstGlDropdownItem().vm.$emit('click'); diff --git a/spec/frontend/projects/compare/components/revision_dropdown_spec.js b/spec/frontend/projects/compare/components/revision_dropdown_spec.js index 118bb68585e..c8a90848492 100644 --- a/spec/frontend/projects/compare/components/revision_dropdown_spec.js +++ b/spec/frontend/projects/compare/components/revision_dropdown_spec.js @@ -1,6 +1,7 @@ import { GlDropdown, GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import AxiosMockAdapter from 'axios-mock-adapter'; +import { nextTick } from 'vue'; import createFlash from '~/flash'; import axios from '~/lib/utils/axios_utils'; import RevisionDropdown from '~/projects/compare/components/revision_dropdown.vue'; @@ -141,7 +142,7 @@ describe('RevisionDropdown component', () => { it('emits `selectRevision` event when another revision is selected', async () => { createComponent(); wrapper.vm.branches = ['some-branch']; - await wrapper.vm.$nextTick(); + await nextTick(); findGlDropdown().findAll(GlDropdownItem).at(0).vm.$emit('click'); diff --git a/spec/frontend/projects/new/components/new_project_url_select_spec.js b/spec/frontend/projects/new/components/new_project_url_select_spec.js index be6592530fc..921f5b74278 100644 --- a/spec/frontend/projects/new/components/new_project_url_select_spec.js +++ b/spec/frontend/projects/new/components/new_project_url_select_spec.js @@ -6,7 +6,7 @@ import { GlSearchBoxByType, } from '@gitlab/ui'; import { mount, shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; @@ -95,7 +95,7 @@ describe('NewProjectUrlSelect component', () => { const clickDropdownItem = async () => { wrapper.findComponent(GlDropdownItem).vm.$emit('click'); - await wrapper.vm.$nextTick(); + await nextTick(); }; const showDropdown = async () => { diff --git a/spec/frontend/projects/pipelines/charts/components/app_spec.js b/spec/frontend/projects/pipelines/charts/components/app_spec.js index 574756322c7..9c94925c817 100644 --- a/spec/frontend/projects/pipelines/charts/components/app_spec.js +++ b/spec/frontend/projects/pipelines/charts/components/app_spec.js @@ -1,5 +1,6 @@ import { GlTabs, GlTab } from '@gitlab/ui'; import { merge } from 'lodash'; +import { nextTick } from 'vue'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import setWindowLocation from 'helpers/set_window_location_helper'; import { TEST_HOST } from 'helpers/test_constants'; @@ -99,7 +100,7 @@ describe('ProjectsPipelinesChartsApp', () => { tabs.vm.$emit('input', 1); - await wrapper.vm.$nextTick(); + await nextTick(); expect(tabs.attributes('value')).toBe('1'); }); @@ -115,7 +116,7 @@ describe('ProjectsPipelinesChartsApp', () => { tabs.vm.$emit('input', 0); - await wrapper.vm.$nextTick(); + await nextTick(); expect(updateHistory).not.toHaveBeenCalled(); }); @@ -183,7 +184,7 @@ describe('ProjectsPipelinesChartsApp', () => { popstateHandler(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findGlTabs().attributes('value')).toBe('1'); }); diff --git a/spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js b/spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js index 2ee2ffdb96b..3c91b913e67 100644 --- a/spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js +++ b/spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js @@ -1,5 +1,6 @@ import { GlColumnChart } from '@gitlab/ui/dist/charts'; -import { createLocalVue, shallowMount } from '@vue/test-utils'; +import { shallowMount } from '@vue/test-utils'; +import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; @@ -11,8 +12,7 @@ import CiCdAnalyticsCharts from '~/vue_shared/components/ci_cd_analytics/ci_cd_a import { mockPipelineCount, mockPipelineStatistics } from '../mock_data'; const projectPath = 'gitlab-org/gitlab'; -const localVue = createLocalVue(); -localVue.use(VueApollo); +Vue.use(VueApollo); describe('~/projects/pipelines/charts/components/pipeline_charts.vue', () => { let wrapper; @@ -31,7 +31,6 @@ describe('~/projects/pipelines/charts/components/pipeline_charts.vue', () => { provide: { projectPath, }, - localVue, apolloProvider: createMockApolloProvider(), }); diff --git a/spec/frontend/projects/settings/components/shared_runners_toggle_spec.js b/spec/frontend/projects/settings/components/shared_runners_toggle_spec.js index 0c5bbe2a115..0a05832ceb6 100644 --- a/spec/frontend/projects/settings/components/shared_runners_toggle_spec.js +++ b/spec/frontend/projects/settings/components/shared_runners_toggle_spec.js @@ -1,6 +1,7 @@ import { GlAlert, GlToggle, GlTooltip } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import MockAxiosAdapter from 'axios-mock-adapter'; +import { nextTick } from 'vue'; import waitForPromises from 'helpers/wait_for_promises'; import axios from '~/lib/utils/axios_utils'; import SharedRunnersToggleComponent from '~/projects/settings/components/shared_runners_toggle.vue'; @@ -121,7 +122,7 @@ describe('projects/settings/components/shared_runners', () => { expect(isToggleLoading()).toBe(false); findSharedRunnersToggle().vm.$emit('change', true); - await wrapper.vm.$nextTick(); + await nextTick(); expect(isToggleLoading()).toBe(true); await waitForPromises(); diff --git a/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js b/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js index 875c58583df..57e515723e5 100644 --- a/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js +++ b/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js @@ -139,7 +139,7 @@ describe('ServiceDeskSetting', () => { input.setValue('abc_A.'); input.trigger('blur'); - await wrapper.vm.$nextTick(); + await nextTick(); const errorText = wrapper.find('.invalid-feedback'); expect(errorText.exists()).toBe(true); diff --git a/spec/frontend/ref/components/ref_selector_spec.js b/spec/frontend/ref/components/ref_selector_spec.js index b4e50c8f634..e1fc60f0d92 100644 --- a/spec/frontend/ref/components/ref_selector_spec.js +++ b/spec/frontend/ref/components/ref_selector_spec.js @@ -137,19 +137,19 @@ describe('Ref selector component', () => { findSearchBox().vm.$emit('input', newQuery); }; - const selectFirstBranch = () => { + const selectFirstBranch = async () => { findFirstBranchDropdownItem().vm.$emit('click'); - return wrapper.vm.$nextTick(); + await nextTick(); }; - const selectFirstTag = () => { + const selectFirstTag = async () => { findFirstTagDropdownItem().vm.$emit('click'); - return wrapper.vm.$nextTick(); + await nextTick(); }; - const selectFirstCommit = () => { + const selectFirstCommit = async () => { findFirstCommitDropdownItem().vm.$emit('click'); - return wrapper.vm.$nextTick(); + await nextTick(); }; const waitForRequests = ({ andClearMocks } = { andClearMocks: false }) => @@ -219,12 +219,11 @@ describe('Ref selector component', () => { return waitForRequests(); }); - it('renders the updated ref name', () => { + it('renders the updated ref name', async () => { wrapper.setProps({ value: updatedRef }); - return nextTick().then(() => { - expect(findButtonContent().text()).toBe(updatedRef); - }); + await nextTick(); + expect(findButtonContent().text()).toBe(updatedRef); }); }); @@ -546,9 +545,8 @@ describe('Ref selector component', () => { await selectFirstBranch(); - return nextTick().then(() => { - expect(findButtonContent().text()).toBe(fixtures.branches[0].name); - }); + await nextTick(); + expect(findButtonContent().text()).toBe(fixtures.branches[0].name); }); it("updates the v-model binding with the branch's name", async () => { @@ -566,9 +564,8 @@ describe('Ref selector component', () => { await selectFirstTag(); - return nextTick().then(() => { - expect(findButtonContent().text()).toBe(fixtures.tags[0].name); - }); + await nextTick(); + expect(findButtonContent().text()).toBe(fixtures.tags[0].name); }); it("updates the v-model binding with the tag's name", async () => { @@ -586,9 +583,8 @@ describe('Ref selector component', () => { await selectFirstCommit(); - return nextTick().then(() => { - expect(findButtonContent().text()).toBe(fixtures.commit.id); - }); + await nextTick(); + expect(findButtonContent().text()).toBe(fixtures.commit.id); }); it("updates the v-model binding with the commit's full SHA", async () => { diff --git a/spec/frontend/related_issues/components/related_issuable_input_spec.js b/spec/frontend/related_issues/components/related_issuable_input_spec.js index 79b228454f4..7d11e3cffb0 100644 --- a/spec/frontend/related_issues/components/related_issuable_input_spec.js +++ b/spec/frontend/related_issues/components/related_issuable_input_spec.js @@ -1,4 +1,5 @@ import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import { TEST_HOST } from 'helpers/test_constants'; import RelatedIssuableInput from '~/related_issues/components/related_issuable_input.vue'; import { issuableTypesMap, PathIdSeparator } from '~/related_issues/constants'; @@ -82,7 +83,7 @@ describe('RelatedIssuableInput', () => { wrapper.find('li').trigger('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(document.activeElement).toBe(wrapper.find({ ref: 'input' }).element); }); diff --git a/spec/frontend/releases/components/app_edit_new_spec.js b/spec/frontend/releases/components/app_edit_new_spec.js index 029d720f7b9..0a0a683b56d 100644 --- a/spec/frontend/releases/components/app_edit_new_spec.js +++ b/spec/frontend/releases/components/app_edit_new_spec.js @@ -3,6 +3,7 @@ import axios from 'axios'; import MockAdapter from 'axios-mock-adapter'; import { merge } from 'lodash'; import Vuex from 'vuex'; +import { nextTick } from 'vue'; import originalRelease from 'test_fixtures/api/releases/release.json'; import setWindowLocation from 'helpers/set_window_location_helper'; import { TEST_HOST } from 'helpers/test_constants'; @@ -71,7 +72,7 @@ describe('Release edit/new component', () => { }, }); - await wrapper.vm.$nextTick(); + await nextTick(); wrapper.element.querySelectorAll('input').forEach((input) => jest.spyOn(input, 'focus')); }; diff --git a/spec/frontend/releases/components/app_index_apollo_client_spec.js b/spec/frontend/releases/components/app_index_apollo_client_spec.js index 53ee5b223ad..9881ef9bc9f 100644 --- a/spec/frontend/releases/components/app_index_apollo_client_spec.js +++ b/spec/frontend/releases/components/app_index_apollo_client_spec.js @@ -1,5 +1,5 @@ import { cloneDeep } from 'lodash'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; import originalAllReleasesQueryResponse from 'test_fixtures/graphql/releases/graphql/queries/all_releases.query.graphql.json'; import createMockApollo from 'helpers/mock_apollo_helper'; @@ -296,7 +296,7 @@ describe('app_index_apollo_client.vue', () => { mockQueryParams = { after }; findPagination().vm.$emit('next', after); - await wrapper.vm.$nextTick(); + await nextTick(); expect(queryMock.mock.calls).toEqual([ [expect.objectContaining({ before })], @@ -321,7 +321,7 @@ describe('app_index_apollo_client.vue', () => { it('requeries the GraphQL endpoint and updates the URL when the sort is changed', async () => { findSort().vm.$emit('input', CREATED_ASC); - await wrapper.vm.$nextTick(); + await nextTick(); expect(queryMock.mock.calls).toEqual([ [expect.objectContaining({ sort: DEFAULT_SORT })], @@ -337,7 +337,7 @@ describe('app_index_apollo_client.vue', () => { it('does not requery the GraphQL endpoint or update the URL if the sort is updated to the same value', async () => { findSort().vm.$emit('input', DEFAULT_SORT); - await wrapper.vm.$nextTick(); + await nextTick(); expect(queryMock.mock.calls).toEqual([ [expect.objectContaining({ sort: DEFAULT_SORT })], @@ -370,7 +370,7 @@ describe('app_index_apollo_client.vue', () => { findSort().vm.$emit('input', CREATED_ASC); - await wrapper.vm.$nextTick(); + await nextTick(); }); it(`resets the page's "${paramName}" pagination cursor when the sort is changed`, () => { diff --git a/spec/frontend/releases/components/evidence_block_spec.js b/spec/frontend/releases/components/evidence_block_spec.js index 973428257b7..f0d02884305 100644 --- a/spec/frontend/releases/components/evidence_block_spec.js +++ b/spec/frontend/releases/components/evidence_block_spec.js @@ -1,5 +1,6 @@ import { GlLink, GlIcon } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import originalRelease from 'test_fixtures/api/releases/release.json'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; import { truncateSha } from '~/lib/utils/text_utility'; @@ -51,12 +52,11 @@ describe('Evidence Block', () => { expect(wrapper.find('.js-short').text()).toBe(truncateSha(release.evidences[0].sha)); }); - it('renders the long sha after expansion', () => { + it('renders the long sha after expansion', async () => { wrapper.find('.js-text-expander-prepend').trigger('click'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.find('.js-expanded').text()).toBe(release.evidences[0].sha); - }); + await nextTick(); + expect(wrapper.find('.js-expanded').text()).toBe(release.evidences[0].sha); }); }); diff --git a/spec/frontend/releases/components/release_block_footer_spec.js b/spec/frontend/releases/components/release_block_footer_spec.js index f645dc309d7..b095e9e1d78 100644 --- a/spec/frontend/releases/components/release_block_footer_spec.js +++ b/spec/frontend/releases/components/release_block_footer_spec.js @@ -1,6 +1,7 @@ import { GlLink, GlIcon } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; import { cloneDeep } from 'lodash'; +import { nextTick } from 'vue'; import originalRelease from 'test_fixtures/api/releases/release.json'; import { trimText } from 'helpers/text_helper'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; @@ -14,7 +15,7 @@ describe('Release block footer', () => { let wrapper; let release; - const factory = (props = {}) => { + const factory = async (props = {}) => { wrapper = mount(ReleaseBlockFooter, { propsData: { ...convertObjectPropsToCamelCase(release, { deep: true }), @@ -22,7 +23,7 @@ describe('Release block footer', () => { }, }); - return wrapper.vm.$nextTick(); + await nextTick(); }; beforeEach(() => { diff --git a/spec/frontend/releases/components/release_block_milestone_info_spec.js b/spec/frontend/releases/components/release_block_milestone_info_spec.js index 146b2cc7490..84a0080965b 100644 --- a/spec/frontend/releases/components/release_block_milestone_info_spec.js +++ b/spec/frontend/releases/components/release_block_milestone_info_spec.js @@ -1,5 +1,6 @@ import { GlProgressBar, GlLink, GlBadge, GlButton } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import originalRelease from 'test_fixtures/api/releases/release.json'; import { trimText } from 'helpers/text_helper'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; @@ -12,12 +13,12 @@ describe('Release block milestone info', () => { let wrapper; let milestones; - const factory = (props) => { + const factory = async (props) => { wrapper = mount(ReleaseBlockMilestoneInfo, { propsData: props, }); - return wrapper.vm.$nextTick(); + await nextTick(); }; beforeEach(() => { @@ -105,10 +106,10 @@ describe('Release block milestone info', () => { return factory({ milestones: lotsOfMilestones }); }); - const clickShowMoreFewerButton = () => { + const clickShowMoreFewerButton = async () => { milestoneListContainer().find(GlButton).trigger('click'); - return wrapper.vm.$nextTick(); + await nextTick(); }; const milestoneListText = () => trimText(milestoneListContainer().text()); @@ -117,19 +118,16 @@ describe('Release block milestone info', () => { expect(milestoneListText()).toContain(`Milestones ${abbreviatedListString} • show 10 more`); }); - it('renders all milestones when "show more" is clicked', () => - clickShowMoreFewerButton().then(() => { - expect(milestoneListText()).toContain(`Milestones ${fullListString} • show fewer`); - })); + it('renders all milestones when "show more" is clicked', async () => { + await clickShowMoreFewerButton(); + expect(milestoneListText()).toContain(`Milestones ${fullListString} • show fewer`); + }); - it('returns to the original view when "show fewer" is clicked', () => - clickShowMoreFewerButton() - .then(clickShowMoreFewerButton) - .then(() => { - expect(milestoneListText()).toContain( - `Milestones ${abbreviatedListString} • show 10 more`, - ); - })); + it('returns to the original view when "show fewer" is clicked', async () => { + await clickShowMoreFewerButton(); + await clickShowMoreFewerButton(); + expect(milestoneListText()).toContain(`Milestones ${abbreviatedListString} • show 10 more`); + }); }); const expectAllZeros = () => { diff --git a/spec/frontend/releases/components/release_block_spec.js b/spec/frontend/releases/components/release_block_spec.js index a847c32b8f1..c4910ae9b2f 100644 --- a/spec/frontend/releases/components/release_block_spec.js +++ b/spec/frontend/releases/components/release_block_spec.js @@ -1,5 +1,6 @@ import { mount } from '@vue/test-utils'; import $ from 'jquery'; +import { nextTick } from 'vue'; import originalRelease from 'test_fixtures/api/releases/release.json'; import * as commonUtils from '~/lib/utils/common_utils'; import * as urlUtility from '~/lib/utils/url_utility'; @@ -13,7 +14,7 @@ describe('Release block', () => { let wrapper; let release; - const factory = (releaseProp, featureFlags = {}) => { + const factory = async (releaseProp, featureFlags = {}) => { wrapper = mount(ReleaseBlock, { propsData: { release: releaseProp, @@ -25,7 +26,7 @@ describe('Release block', () => { }, }); - return wrapper.vm.$nextTick(); + await nextTick(); }; const milestoneListLabel = () => wrapper.find('.js-milestone-list-label'); diff --git a/spec/frontend/releases/components/tag_field_new_spec.js b/spec/frontend/releases/components/tag_field_new_spec.js index 0f416e46dba..c13b513f87e 100644 --- a/spec/frontend/releases/components/tag_field_new_spec.js +++ b/spec/frontend/releases/components/tag_field_new_spec.js @@ -1,6 +1,6 @@ import { GlDropdownItem } from '@gitlab/ui'; import { mount, shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import { __ } from '~/locale'; import TagFieldNew from '~/releases/components/tag_field_new.vue'; import createStore from '~/releases/stores'; @@ -153,7 +153,7 @@ describe('releases/components/tag_field_new', () => { * Should be passed either 'shown' or 'hidden' */ const expectValidationMessageToBe = async (state) => { - await wrapper.vm.$nextTick(); + await nextTick(); expect(findTagNameFormGroup().element).toHaveClass( state === 'shown' ? 'is-invalid' : 'is-valid', diff --git a/spec/frontend/repository/components/blob_content_viewer_spec.js b/spec/frontend/repository/components/blob_content_viewer_spec.js index 3384fd599b4..70808a3c7b1 100644 --- a/spec/frontend/repository/components/blob_content_viewer_spec.js +++ b/spec/frontend/repository/components/blob_content_viewer_spec.js @@ -1,8 +1,9 @@ import { GlLoadingIcon } from '@gitlab/ui'; -import { mount, shallowMount, createLocalVue } from '@vue/test-utils'; +import { mount, shallowMount } from '@vue/test-utils'; +import Vue, { nextTick } from 'vue'; import axios from 'axios'; import MockAdapter from 'axios-mock-adapter'; -import { nextTick } from 'vue'; + import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; @@ -36,11 +37,10 @@ jest.mock('~/lib/utils/common_utils'); let wrapper; let mockResolver; -const localVue = createLocalVue(); const mockAxios = new MockAdapter(axios); const createComponent = async (mockData = {}, mountFn = shallowMount) => { - localVue.use(VueApollo); + Vue.use(VueApollo); const { blob = simpleViewerMock, @@ -75,7 +75,6 @@ const createComponent = async (mockData = {}, mountFn = shallowMount) => { wrapper = extendedWrapper( mountFn(BlobContentViewer, { - localVue, apolloProvider: fakeApollo, propsData: propsMock, mixins: [{ data: () => ({ ref: refMock }) }], diff --git a/spec/frontend/repository/components/blob_controls_spec.js b/spec/frontend/repository/components/blob_controls_spec.js index 03e389ea5cb..6da1861ea7c 100644 --- a/spec/frontend/repository/components/blob_controls_spec.js +++ b/spec/frontend/repository/components/blob_controls_spec.js @@ -1,6 +1,6 @@ -import { createLocalVue } from '@vue/test-utils'; +import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; -import { nextTick } from 'vue'; + import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; import BlobControls from '~/repository/components/blob_controls.vue'; @@ -16,10 +16,8 @@ let router; let wrapper; let mockResolver; -const localVue = createLocalVue(); - const createComponent = async () => { - localVue.use(VueApollo); + Vue.use(VueApollo); const project = { ...blobControlsDataMock }; const projectPath = 'some/project'; @@ -31,7 +29,6 @@ const createComponent = async () => { mockResolver = jest.fn().mockResolvedValue({ data: { project } }); wrapper = shallowMountExtended(BlobControls, { - localVue, router, apolloProvider: createMockApollo([[blobControlsQuery, mockResolver]]), propsData: { projectPath }, diff --git a/spec/frontend/repository/components/breadcrumbs_spec.js b/spec/frontend/repository/components/breadcrumbs_spec.js index ad2cbd70187..0e300291d05 100644 --- a/spec/frontend/repository/components/breadcrumbs_spec.js +++ b/spec/frontend/repository/components/breadcrumbs_spec.js @@ -1,5 +1,6 @@ import { GlDropdown } from '@gitlab/ui'; import { shallowMount, RouterLinkStub } from '@vue/test-utils'; +import { nextTick } from 'vue'; import Breadcrumbs from '~/repository/components/breadcrumbs.vue'; import UploadBlobModal from '~/repository/components/upload_blob_modal.vue'; import NewDirectoryModal from '~/repository/components/new_directory_modal.vue'; @@ -79,7 +80,7 @@ describe('Repository breadcrumbs component', () => { // eslint-disable-next-line no-restricted-syntax wrapper.setData({ userPermissions: { forkProject: false, createMergeRequestIn: false } }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.find(GlDropdown).exists()).toBe(false); }); @@ -106,7 +107,7 @@ describe('Repository breadcrumbs component', () => { // eslint-disable-next-line no-restricted-syntax wrapper.setData({ userPermissions: { forkProject: true, createMergeRequestIn: true } }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.find(GlDropdown).exists()).toBe(true); }); @@ -125,7 +126,7 @@ describe('Repository breadcrumbs component', () => { // eslint-disable-next-line no-restricted-syntax wrapper.setData({ $apollo: { queries: { userPermissions: { loading: false } } } }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findUploadBlobModal().exists()).toBe(true); }); @@ -149,7 +150,7 @@ describe('Repository breadcrumbs component', () => { // eslint-disable-next-line no-restricted-syntax wrapper.setData({ $apollo: { queries: { userPermissions: { loading: false } } } }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findNewDirectoryModal().exists()).toBe(true); }); diff --git a/spec/frontend/repository/components/upload_blob_modal_spec.js b/spec/frontend/repository/components/upload_blob_modal_spec.js index 6b8b0752485..bf024baa627 100644 --- a/spec/frontend/repository/components/upload_blob_modal_spec.js +++ b/spec/frontend/repository/components/upload_blob_modal_spec.js @@ -2,6 +2,7 @@ import { GlModal, GlFormInput, GlFormTextarea, GlToggle, GlAlert } from '@gitlab import { shallowMount } from '@vue/test-utils'; import axios from 'axios'; import MockAdapter from 'axios-mock-adapter'; +import { nextTick } from 'vue'; import waitForPromises from 'helpers/wait_for_promises'; import createFlash from '~/flash'; import httpStatusCodes from '~/lib/utils/http_status'; @@ -113,7 +114,7 @@ describe('UploadBlobModal', () => { // eslint-disable-next-line no-restricted-syntax wrapper.setData({ target: 'Not main' }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findMrToggle().exists()).toBe(true); }); @@ -202,7 +203,7 @@ describe('UploadBlobModal', () => { wrapper.vm.uploadFile = jest.fn(); wrapper.vm.replaceFile = jest.fn(); wrapper.vm.submitForm(); - await wrapper.vm.$nextTick(); + await nextTick(); }; const submitRequest = async () => { diff --git a/spec/frontend/runner/admin_runner_edit/admin_runner_edit_app_spec.js b/spec/frontend/runner/admin_runner_edit/admin_runner_edit_app_spec.js index 9a9438417ee..e694fbf86a3 100644 --- a/spec/frontend/runner/admin_runner_edit/admin_runner_edit_app_spec.js +++ b/spec/frontend/runner/admin_runner_edit/admin_runner_edit_app_spec.js @@ -1,4 +1,5 @@ -import { createLocalVue, mount, shallowMount } from '@vue/test-utils'; +import { mount, shallowMount } from '@vue/test-utils'; +import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; @@ -18,8 +19,7 @@ jest.mock('~/runner/sentry_utils'); const mockRunnerGraphqlId = runnerData.data.runner.id; const mockRunnerId = `${getIdFromGraphQLId(mockRunnerGraphqlId)}`; -const localVue = createLocalVue(); -localVue.use(VueApollo); +Vue.use(VueApollo); describe('AdminRunnerEditApp', () => { let wrapper; @@ -29,7 +29,6 @@ describe('AdminRunnerEditApp', () => { const createComponentWithApollo = ({ props = {}, mountFn = shallowMount } = {}) => { wrapper = mountFn(AdminRunnerEditApp, { - localVue, apolloProvider: createMockApollo([[getRunnerQuery, mockRunnerQuery]]), propsData: { runnerId: mockRunnerId, diff --git a/spec/frontend/runner/components/registration/registration_dropdown_spec.js b/spec/frontend/runner/components/registration/registration_dropdown_spec.js index 2685d387ef2..26d3f852a1e 100644 --- a/spec/frontend/runner/components/registration/registration_dropdown_spec.js +++ b/spec/frontend/runner/components/registration/registration_dropdown_spec.js @@ -1,8 +1,9 @@ import { GlDropdown, GlDropdownItem, GlDropdownForm } from '@gitlab/ui'; -import { createLocalVue, createWrapper } from '@vue/test-utils'; -import { nextTick } from 'vue'; +import { mount, shallowMount, createWrapper } from '@vue/test-utils'; +import Vue, { nextTick } from 'vue'; + import VueApollo from 'vue-apollo'; -import { shallowMountExtended, mountExtended } from 'helpers/vue_test_utils_helper'; +import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import createMockApollo from 'helpers/mock_apollo_helper'; import RegistrationDropdown from '~/runner/components/registration/registration_dropdown.vue'; @@ -33,15 +34,17 @@ describe('RegistrationDropdown', () => { const findToggleMaskButton = () => wrapper.findByTestId('toggle-masked'); - const createComponent = ({ props = {}, ...options } = {}, mountFn = shallowMountExtended) => { - wrapper = mountFn(RegistrationDropdown, { - propsData: { - registrationToken: mockToken, - type: INSTANCE_TYPE, - ...props, - }, - ...options, - }); + const createComponent = ({ props = {}, ...options } = {}, mountFn = shallowMount) => { + wrapper = extendedWrapper( + mountFn(RegistrationDropdown, { + propsData: { + registrationToken: mockToken, + type: INSTANCE_TYPE, + ...props, + }, + ...options, + }), + ); }; it.each` @@ -50,7 +53,7 @@ describe('RegistrationDropdown', () => { ${GROUP_TYPE} | ${'Register a group runner'} ${PROJECT_TYPE} | ${'Register a project runner'} `('Dropdown text for type $type is "$text"', () => { - createComponent({ props: { type: INSTANCE_TYPE } }, mountExtended); + createComponent({ props: { type: INSTANCE_TYPE } }, mount); expect(wrapper.text()).toContain('Register an instance runner'); }); @@ -71,8 +74,7 @@ describe('RegistrationDropdown', () => { }); describe('When the dropdown item is clicked', () => { - const localVue = createLocalVue(); - localVue.use(VueApollo); + Vue.use(VueApollo); const requestHandlers = [ [getRunnerPlatformsQuery, jest.fn().mockResolvedValue(mockGraphqlRunnerPlatforms)], @@ -85,13 +87,12 @@ describe('RegistrationDropdown', () => { beforeEach(async () => { createComponent( { - localVue, // Mock load modal contents from API apolloProvider: createMockApollo(requestHandlers), // Use `attachTo` to find the modal attachTo: document.body, }, - mountExtended, + mount, ); await findRegistrationInstructionsDropdownItem().trigger('click'); @@ -129,7 +130,7 @@ describe('RegistrationDropdown', () => { }); it('Displays masked value by default', () => { - createComponent({}, mountExtended); + createComponent({}, mount); expect(findTokenDropdownItem().text()).toMatchInterpolatedText( `Registration token ${maskToken}`, @@ -152,7 +153,7 @@ describe('RegistrationDropdown', () => { }); it('Updates the token when it gets reset', async () => { - createComponent({}, mountExtended); + createComponent({}, mount); const newToken = 'mock1'; diff --git a/spec/frontend/runner/components/registration/registration_token_reset_dropdown_item_spec.js b/spec/frontend/runner/components/registration/registration_token_reset_dropdown_item_spec.js index d8cdec0eafc..43b9aa9c413 100644 --- a/spec/frontend/runner/components/registration/registration_token_reset_dropdown_item_spec.js +++ b/spec/frontend/runner/components/registration/registration_token_reset_dropdown_item_spec.js @@ -1,7 +1,8 @@ -import Vue, { nextTick } from 'vue'; import { GlDropdownItem, GlLoadingIcon, GlToast, GlModal } from '@gitlab/ui'; +import { shallowMount } from '@vue/test-utils'; +import Vue, { nextTick } from 'vue'; + import VueApollo from 'vue-apollo'; -import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; import { createAlert } from '~/flash'; @@ -32,7 +33,7 @@ describe('RegistrationTokenResetDropdownItem', () => { const clickSubmit = () => findModal().vm.$emit('primary', mockEvent); const createComponent = ({ props, provide = {} } = {}) => { - wrapper = shallowMountExtended(RegistrationTokenResetDropdownItem, { + wrapper = shallowMount(RegistrationTokenResetDropdownItem, { provide, propsData: { type: INSTANCE_TYPE, diff --git a/spec/frontend/runner/group_runners/group_runners_app_spec.js b/spec/frontend/runner/group_runners/group_runners_app_spec.js index 6becc1ba743..7872cfd6cf4 100644 --- a/spec/frontend/runner/group_runners/group_runners_app_spec.js +++ b/spec/frontend/runner/group_runners/group_runners_app_spec.js @@ -1,6 +1,7 @@ import Vue, { nextTick } from 'vue'; import { GlLink } from '@gitlab/ui'; import { shallowMount, mount } from '@vue/test-utils'; + import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import setWindowLocation from 'helpers/set_window_location_helper'; diff --git a/spec/frontend/serverless/survey_banner_spec.js b/spec/frontend/serverless/survey_banner_spec.js index 4682c2328c3..022aa47c113 100644 --- a/spec/frontend/serverless/survey_banner_spec.js +++ b/spec/frontend/serverless/survey_banner_spec.js @@ -1,6 +1,7 @@ import { GlBanner } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import Cookies from 'js-cookie'; +import { nextTick } from 'vue'; import SurveyBanner from '~/serverless/survey_banner.vue'; describe('Knative survey banner', () => { @@ -27,7 +28,7 @@ describe('Knative survey banner', () => { expect(wrapper.find(GlBanner).exists()).toBe(true); }); - it('should close the banner and set a cookie when close button is clicked', () => { + it('should close the banner and set a cookie when close button is clicked', async () => { jest.spyOn(Cookies, 'get').mockReturnValue(undefined); jest.spyOn(Cookies, 'set'); mountBanner(); @@ -35,10 +36,9 @@ describe('Knative survey banner', () => { expect(wrapper.find(GlBanner).exists()).toBe(true); wrapper.find(GlBanner).vm.$emit('close'); - return wrapper.vm.$nextTick().then(() => { - expect(Cookies.set).toHaveBeenCalledWith('hide_serverless_survey', 'true', { expires: 3650 }); - expect(wrapper.find(GlBanner).exists()).toBe(false); - }); + await nextTick(); + expect(Cookies.set).toHaveBeenCalledWith('hide_serverless_survey', 'true', { expires: 3650 }); + expect(wrapper.find(GlBanner).exists()).toBe(false); }); it('should not render the banner when the cookie is set', () => { diff --git a/spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js b/spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js index 0c6ed998747..c105810e11c 100644 --- a/spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js +++ b/spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js @@ -1,5 +1,6 @@ import { GlModal, GlFormCheckbox } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import { initEmojiMock, clearEmojiMock } from 'helpers/emoji'; import * as UserApi from '~/api/user_api'; import EmojiPicker from '~/emoji/components/picker.vue'; @@ -48,7 +49,7 @@ describe('SetStatusModalWrapper', () => { const findAvailabilityCheckbox = () => wrapper.find(GlFormCheckbox); const findClearStatusAtMessage = () => wrapper.find('[data-testid="clear-status-at-message"]'); - const initModal = ({ mockOnUpdateSuccess = true, mockOnUpdateFailure = true } = {}) => { + const initModal = async ({ mockOnUpdateSuccess = true, mockOnUpdateFailure = true } = {}) => { const modal = findModal(); // mock internal emoji methods wrapper.vm.showEmojiMenu = jest.fn(); @@ -57,7 +58,7 @@ describe('SetStatusModalWrapper', () => { if (mockOnUpdateFailure) wrapper.vm.onUpdateFail = jest.fn(); modal.vm.$emit('shown'); - return wrapper.vm.$nextTick(); + await nextTick(); }; afterEach(() => { @@ -207,7 +208,7 @@ describe('SetStatusModalWrapper', () => { it('clicking "removeStatus" clears the emoji and message fields', async () => { findModal().vm.$emit('secondary'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findFormField('message').element.value).toBe(''); expect(findFormField('emoji').element.value).toBe(''); @@ -215,7 +216,7 @@ describe('SetStatusModalWrapper', () => { it('clicking "setStatus" submits the user status', async () => { findModal().vm.$emit('primary'); - await wrapper.vm.$nextTick(); + await nextTick(); // set the availability status findAvailabilityCheckbox().vm.$emit('input', true); @@ -224,7 +225,7 @@ describe('SetStatusModalWrapper', () => { wrapper.find('[data-testid="thirtyMinutes"]').vm.$emit('click'); findModal().vm.$emit('primary'); - await wrapper.vm.$nextTick(); + await nextTick(); const commonParams = { emoji: defaultEmoji, @@ -246,7 +247,7 @@ describe('SetStatusModalWrapper', () => { it('calls the "onUpdateSuccess" handler', async () => { findModal().vm.$emit('primary'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.vm.onUpdateSuccess).toHaveBeenCalled(); }); @@ -262,7 +263,7 @@ describe('SetStatusModalWrapper', () => { it('displays a toast success message', async () => { findModal().vm.$emit('primary'); - await wrapper.vm.$nextTick(); + await nextTick(); expect($toast.show).toHaveBeenCalledWith('Status updated'); }); @@ -279,7 +280,7 @@ describe('SetStatusModalWrapper', () => { it('calls the "onUpdateFail" handler', async () => { findModal().vm.$emit('primary'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.vm.onUpdateFail).toHaveBeenCalled(); }); @@ -295,7 +296,7 @@ describe('SetStatusModalWrapper', () => { it('flashes an error message', async () => { findModal().vm.$emit('primary'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(createFlash).toHaveBeenCalledWith({ message: "Sorry, we weren't able to set your status. Please try again later.", diff --git a/spec/frontend/sidebar/assignees_realtime_spec.js b/spec/frontend/sidebar/assignees_realtime_spec.js index ecf33d6de37..2249a1c08b8 100644 --- a/spec/frontend/sidebar/assignees_realtime_spec.js +++ b/spec/frontend/sidebar/assignees_realtime_spec.js @@ -1,4 +1,5 @@ -import { shallowMount, createLocalVue } from '@vue/test-utils'; +import { shallowMount } from '@vue/test-utils'; +import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import AssigneesRealtime from '~/sidebar/components/assignees/assignees_realtime.vue'; @@ -7,8 +8,7 @@ import SidebarMediator from '~/sidebar/sidebar_mediator'; import getIssueAssigneesQuery from '~/vue_shared/components/sidebar/queries/get_issue_assignees.query.graphql'; import Mock, { issuableQueryResponse, subscriptionNullResponse } from './mock_data'; -const localVue = createLocalVue(); -localVue.use(VueApollo); +Vue.use(VueApollo); describe('Assignees Realtime', () => { let wrapper; @@ -38,7 +38,6 @@ describe('Assignees Realtime', () => { mediator, }, apolloProvider: fakeApollo, - localVue, }); }; diff --git a/spec/frontend/sidebar/assignees_spec.js b/spec/frontend/sidebar/assignees_spec.js index b3a67f18f82..a4474ead956 100644 --- a/spec/frontend/sidebar/assignees_spec.js +++ b/spec/frontend/sidebar/assignees_spec.js @@ -1,5 +1,6 @@ import { GlIcon } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import { trimText } from 'helpers/text_helper'; import UsersMockHelper from 'helpers/user_mock_data_helper'; import Assignee from '~/sidebar/components/assignees/assignees.vue'; @@ -59,7 +60,7 @@ describe('Assignee component', () => { expect(componentTextNoUsers).toContain('assign yourself'); }); - it('emits the assign-self event when "assign yourself" is clicked', () => { + it('emits the assign-self event when "assign yourself" is clicked', async () => { createWrapper({ ...getDefaultProps(), editable: true, @@ -68,9 +69,8 @@ describe('Assignee component', () => { jest.spyOn(wrapper.vm, '$emit'); wrapper.find('[data-testid="assign-yourself"]').trigger('click'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted('assign-self')).toBeTruthy(); - }); + await nextTick(); + expect(wrapper.emitted('assign-self')).toBeTruthy(); }); }); diff --git a/spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js b/spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js index 76a00f5a826..3045b8c5842 100644 --- a/spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js +++ b/spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js @@ -1,6 +1,7 @@ import { GlSearchBoxByType, GlDropdown } from '@gitlab/ui'; -import { shallowMount, createLocalVue } from '@vue/test-utils'; -import { nextTick } from 'vue'; +import { shallowMount } from '@vue/test-utils'; +import Vue, { nextTick } from 'vue'; + import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; @@ -23,8 +24,7 @@ const updateIssueAssigneesMutationSuccess = jest .mockResolvedValue(updateIssueAssigneesMutationResponse); const mockError = jest.fn().mockRejectedValue('Error!'); -const localVue = createLocalVue(); -localVue.use(VueApollo); +Vue.use(VueApollo); const initialAssignees = [ { @@ -59,7 +59,6 @@ describe('Sidebar assignees widget', () => { [updateIssueAssigneesMutation, updateIssueAssigneesMutationHandler], ]); wrapper = shallowMount(SidebarAssigneesWidget, { - localVue, apolloProvider: fakeApollo, propsData: { iid: '1', diff --git a/spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js b/spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js index 84b192aaf41..c870bbecd76 100644 --- a/spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js +++ b/spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js @@ -1,5 +1,6 @@ import { GlLoadingIcon } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue'; describe('boards sidebar remove issue', () => { @@ -71,7 +72,7 @@ describe('boards sidebar remove issue', () => { createComponent({ canUpdate: true, slots }); findEditButton().vm.$emit('click'); - await wrapper.vm.$nextTick; + await nextTick; expect(findCollapsed().isVisible()).toBe(false); expect(findExpanded().isVisible()).toBe(true); @@ -82,14 +83,14 @@ describe('boards sidebar remove issue', () => { beforeEach(async () => { createComponent({ canUpdate: true }); findEditButton().vm.$emit('click'); - await wrapper.vm.$nextTick(); + await nextTick(); }); it('hides expanded section and displays collapsed section', async () => { expect(findExpanded().isVisible()).toBe(true); document.body.click(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findCollapsed().isVisible()).toBe(true); expect(findExpanded().isVisible()).toBe(false); @@ -101,7 +102,7 @@ describe('boards sidebar remove issue', () => { findEditButton().vm.$emit('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.emitted().open.length).toBe(1); }); @@ -111,7 +112,7 @@ describe('boards sidebar remove issue', () => { findEditButton().vm.$emit('click'); - await wrapper.vm.$nextTick(); + await nextTick(); wrapper.vm.collapse({ emitEvent: false }); diff --git a/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js b/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js index c72c23a3a60..90aae85e1ca 100644 --- a/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js +++ b/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js @@ -1,4 +1,5 @@ import { mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import { TEST_HOST } from 'helpers/test_constants'; import UsersMockHelper from 'helpers/user_mock_data_helper'; import AssigneeAvatarLink from '~/sidebar/components/assignees/assignee_avatar_link.vue'; @@ -84,10 +85,10 @@ describe('UncollapsedAssigneeList component', () => { }); describe('when more button is clicked', () => { - beforeEach(() => { + beforeEach(async () => { findMoreButton().trigger('click'); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('shows "show less" label', () => { diff --git a/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js b/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js index 707215d0739..1de71e52264 100644 --- a/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js +++ b/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js @@ -1,5 +1,6 @@ -import { shallowMount, createLocalVue } from '@vue/test-utils'; -import { nextTick } from 'vue'; +import { shallowMount } from '@vue/test-utils'; +import Vue, { nextTick } from 'vue'; + import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; @@ -15,8 +16,7 @@ import { issueConfidentialityResponse } from '../../mock_data'; jest.mock('~/flash'); -const localVue = createLocalVue(); -localVue.use(VueApollo); +Vue.use(VueApollo); describe('Sidebar Confidentiality Widget', () => { let wrapper; @@ -32,7 +32,6 @@ describe('Sidebar Confidentiality Widget', () => { fakeApollo = createMockApollo([[issueConfidentialQuery, confidentialQueryHandler]]); wrapper = shallowMount(SidebarConfidentialityWidget, { - localVue, apolloProvider: fakeApollo, provide: { canUpdate: true, diff --git a/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js b/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js index d7471d99477..3ddd41c0bd4 100644 --- a/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js +++ b/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js @@ -8,9 +8,9 @@ import { GlLoadingIcon, } from '@gitlab/ui'; import * as Sentry from '@sentry/browser'; -import { createLocalVue, shallowMount, mount } from '@vue/test-utils'; +import { shallowMount, mount } from '@vue/test-utils'; +import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; - import createMockApollo from 'helpers/mock_apollo_helper'; import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; @@ -37,8 +37,6 @@ import { jest.mock('~/flash'); -const localVue = createLocalVue(); - describe('SidebarDropdownWidget', () => { let wrapper; let mockApollo; @@ -78,7 +76,7 @@ describe('SidebarDropdownWidget', () => { // It then emits `shown` event in a watcher for `visible` // Hence we need both of these: await waitForPromises(); - await wrapper.vm.$nextTick(); + await nextTick(); }; const waitForApollo = async () => { @@ -108,7 +106,7 @@ describe('SidebarDropdownWidget', () => { projectMilestonesSpy = jest.fn().mockResolvedValue(mockProjectMilestonesResponse), currentMilestoneSpy = jest.fn().mockResolvedValue(noCurrentMilestoneResponse), } = {}) => { - localVue.use(VueApollo); + Vue.use(VueApollo); mockApollo = createMockApollo([ [projectMilestonesQuery, projectMilestonesSpy], [projectIssueMilestoneQuery, currentMilestoneSpy], @@ -117,7 +115,6 @@ describe('SidebarDropdownWidget', () => { wrapper = extendedWrapper( mount(SidebarDropdownWidget, { - localVue, provide: { canUpdate: true }, apolloProvider: mockApollo, propsData: { @@ -354,7 +351,7 @@ describe('SidebarDropdownWidget', () => { }); it(`calls createFlash with "${expectedMsg}"`, async () => { - await wrapper.vm.$nextTick(); + await nextTick(); expect(createFlash).toHaveBeenCalledWith({ message: expectedMsg, captureError: true, @@ -377,7 +374,7 @@ describe('SidebarDropdownWidget', () => { findSearchBox().vm.$emit('input', 'non existing milestones'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findDropdownText().text()).toBe('No milestone found'); }); @@ -482,7 +479,7 @@ describe('SidebarDropdownWidget', () => { it('sends a projectMilestones query with the entered search term "foo"', async () => { findSearchBox().vm.$emit('input', mockSearchTerm); - await wrapper.vm.$nextTick(); + await nextTick(); // Account for debouncing jest.runAllTimers(); diff --git a/spec/frontend/sidebar/components/time_tracking/report_spec.js b/spec/frontend/sidebar/components/time_tracking/report_spec.js index 64d143615a0..2b17e6dd6c3 100644 --- a/spec/frontend/sidebar/components/time_tracking/report_spec.js +++ b/spec/frontend/sidebar/components/time_tracking/report_spec.js @@ -1,6 +1,7 @@ import { GlLoadingIcon } from '@gitlab/ui'; import { getAllByRole, getByRole } from '@testing-library/dom'; -import { shallowMount, createLocalVue, mount } from '@vue/test-utils'; +import { shallowMount, mount } from '@vue/test-utils'; +import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; @@ -13,8 +14,7 @@ import { getIssueTimelogsQueryResponse, getMrTimelogsQueryResponse } from './moc jest.mock('~/flash'); describe('Issuable Time Tracking Report', () => { - const localVue = createLocalVue(); - localVue.use(VueApollo); + Vue.use(VueApollo); let wrapper; let fakeApollo; const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon); @@ -37,7 +37,6 @@ describe('Issuable Time Tracking Report', () => { issuableType, }, propsData: { limitToHours, issuableId: '1' }, - localVue, apolloProvider: fakeApollo, }); }; diff --git a/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js b/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js index eb202a8cfcc..835e700e63c 100644 --- a/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js +++ b/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js @@ -1,5 +1,6 @@ import { mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import { stubTransition } from 'helpers/stub_transition'; import { createMockDirective } from 'helpers/vue_mock_directive'; import TimeTracker from '~/sidebar/components/time_tracking/time_tracker.vue'; @@ -161,7 +162,7 @@ describe('Issuable Time Tracker', () => { it('should show the correct tooltip text', async () => { expect(findByTestId('timeTrackingComparisonPane').exists()).toBe(true); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findComparisonMeter()).toBe('Time remaining: 26h 23m'); }); @@ -179,7 +180,7 @@ describe('Issuable Time Tracker', () => { }, }, }); - await wrapper.vm.$nextTick(); + await nextTick(); }); it('should display the human readable version of time estimated', () => { @@ -282,7 +283,7 @@ describe('Issuable Time Tracker', () => { }, }, }); - await wrapper.vm.$nextTick(); + await nextTick(); }); it('should not show the "Help" pane by default', () => { @@ -292,19 +293,19 @@ describe('Issuable Time Tracker', () => { it('should show the "Help" pane when help button is clicked', async () => { findHelpButton().trigger('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findByTestId('helpPane').exists()).toBe(true); }); it('should not show the "Help" pane when help button is clicked and then closed', async () => { findHelpButton().trigger('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findByTestId('helpPane').exists()).toBe(true); findCloseHelpButton().trigger('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findByTestId('helpPane').exists()).toBe(false); }); @@ -315,7 +316,7 @@ describe('Issuable Time Tracker', () => { it('refetches issuableTimeTracking query when eventHub emits `timeTracker:refresh` event', async () => { SidebarEventHub.$emit('timeTracker:refresh'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(issuableTimeTrackingRefetchSpy).toHaveBeenCalled(); }); diff --git a/spec/frontend/sidebar/components/todo_toggle/sidebar_todo_widget_spec.js b/spec/frontend/sidebar/components/todo_toggle/sidebar_todo_widget_spec.js index 2fef3ab9293..ea931782d1e 100644 --- a/spec/frontend/sidebar/components/todo_toggle/sidebar_todo_widget_spec.js +++ b/spec/frontend/sidebar/components/todo_toggle/sidebar_todo_widget_spec.js @@ -1,6 +1,6 @@ import { GlIcon, GlButton } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; @@ -119,7 +119,7 @@ describe('Sidebar Todo Widget', () => { it('emits `todoUpdated` event on click on icon', async () => { wrapper.find(GlIcon).vm.$emit('click', event); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.emitted('todoUpdated')).toEqual([[false]]); }); }); diff --git a/spec/frontend/sidebar/lock/edit_form_buttons_spec.js b/spec/frontend/sidebar/lock/edit_form_buttons_spec.js index 1673425947e..971744edb0f 100644 --- a/spec/frontend/sidebar/lock/edit_form_buttons_spec.js +++ b/spec/frontend/sidebar/lock/edit_form_buttons_spec.js @@ -1,4 +1,5 @@ import { mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import createFlash from '~/flash'; import { createStore as createMrStore } from '~/mr_notes/stores'; import createStore from '~/notes/stores'; @@ -118,15 +119,13 @@ describe('EditFormButtons', () => { }); it('resets loading', async () => { - await wrapper.vm.$nextTick().then(() => { - expect(findLockToggle().props('loading')).toBe(false); - }); + await nextTick(); + expect(findLockToggle().props('loading')).toBe(false); }); - it('emits close form', () => { - return wrapper.vm.$nextTick().then(() => { - expect(eventHub.$emit).toHaveBeenCalledWith('closeLockForm'); - }); + it('emits close form', async () => { + await nextTick(); + expect(eventHub.$emit).toHaveBeenCalledWith('closeLockForm'); }); it('does not flash an error message', () => { @@ -153,15 +152,13 @@ describe('EditFormButtons', () => { }); it('resets loading', async () => { - await wrapper.vm.$nextTick().then(() => { - expect(findLockToggle().props('loading')).toBe(false); - }); + await nextTick(); + expect(findLockToggle().props('loading')).toBe(false); }); - it('emits close form', () => { - return wrapper.vm.$nextTick().then(() => { - expect(eventHub.$emit).toHaveBeenCalledWith('closeLockForm'); - }); + it('emits close form', async () => { + await nextTick(); + expect(eventHub.$emit).toHaveBeenCalledWith('closeLockForm'); }); it('calls flash with the correct message', () => { diff --git a/spec/frontend/sidebar/lock/issuable_lock_form_spec.js b/spec/frontend/sidebar/lock/issuable_lock_form_spec.js index 1743e114bb0..7bf7e563a01 100644 --- a/spec/frontend/sidebar/lock/issuable_lock_form_spec.js +++ b/spec/frontend/sidebar/lock/issuable_lock_form_spec.js @@ -1,4 +1,5 @@ import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import { mockTracking, triggerEvent } from 'helpers/tracking_helper'; import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; import { createStore as createMrStore } from '~/mr_notes/stores'; @@ -80,13 +81,12 @@ describe('IssuableLockForm', () => { }); describe('when not editable', () => { - it('does not display the edit form when opened if not editable', () => { + it('does not display the edit form when opened if not editable', async () => { expect(findEditForm().exists()).toBe(false); findSidebarCollapseIcon().trigger('click'); - return wrapper.vm.$nextTick().then(() => { - expect(findEditForm().exists()).toBe(false); - }); + await nextTick(); + expect(findEditForm().exists()).toBe(false); }); }); @@ -102,13 +102,12 @@ describe('IssuableLockForm', () => { }); describe("when 'Edit' is clicked", () => { - it('displays the edit form when editable', () => { + it('displays the edit form when editable', async () => { expect(findEditForm().exists()).toBe(false); findEditLink().trigger('click'); - return wrapper.vm.$nextTick().then(() => { - expect(findEditForm().exists()).toBe(true); - }); + await nextTick(); + expect(findEditForm().exists()).toBe(true); }); it('tracks the event ', () => { @@ -123,13 +122,12 @@ describe('IssuableLockForm', () => { }); describe('When sidebar is collapsed', () => { - it('displays the edit form when opened', () => { + it('displays the edit form when opened', async () => { expect(findEditForm().exists()).toBe(false); findSidebarCollapseIcon().trigger('click'); - return wrapper.vm.$nextTick().then(() => { - expect(findEditForm().exists()).toBe(true); - }); + await nextTick(); + expect(findEditForm().exists()).toBe(true); }); it('renders a tooltip with the lock status text', () => { diff --git a/spec/frontend/sidebar/sidebar_assignees_spec.js b/spec/frontend/sidebar/sidebar_assignees_spec.js index dc121dcb897..5f77e21c1f8 100644 --- a/spec/frontend/sidebar/sidebar_assignees_spec.js +++ b/spec/frontend/sidebar/sidebar_assignees_spec.js @@ -1,6 +1,7 @@ import { shallowMount } from '@vue/test-utils'; import axios from 'axios'; import AxiosMockAdapter from 'axios-mock-adapter'; +import { nextTick } from 'vue'; import Assigness from '~/sidebar/components/assignees/assignees.vue'; import AssigneesRealtime from '~/sidebar/components/assignees/assignees_realtime.vue'; import SidebarAssignees from '~/sidebar/components/assignees/sidebar_assignees.vue'; @@ -74,16 +75,15 @@ describe('sidebar assignees', () => { expect(mediator.store.assignees.length).toBe(1); }); - it('hides assignees until fetched', () => { + it('hides assignees until fetched', async () => { createComponent(); expect(wrapper.find(Assigness).exists()).toBe(false); wrapper.vm.store.isFetching.assignees = false; - return wrapper.vm.$nextTick(() => { - expect(wrapper.find(Assigness).exists()).toBe(true); - }); + await nextTick(); + expect(wrapper.find(Assigness).exists()).toBe(true); }); describe('when realTimeIssueSidebar is turned on', () => { diff --git a/spec/frontend/sidebar/todo_spec.js b/spec/frontend/sidebar/todo_spec.js index 6829e688c65..9316268d2ad 100644 --- a/spec/frontend/sidebar/todo_spec.js +++ b/spec/frontend/sidebar/todo_spec.js @@ -1,6 +1,7 @@ import { GlLoadingIcon, GlIcon } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import SidebarTodos from '~/sidebar/components/todo_toggle/todo.vue'; const defaultProps = { @@ -49,13 +50,12 @@ describe('SidebarTodo', () => { ); describe('template', () => { - it('emits `toggleTodo` event when clicked on button', () => { + it('emits `toggleTodo` event when clicked on button', async () => { createComponent(); wrapper.find('button').trigger('click'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted().toggleTodo).toBeTruthy(); - }); + await nextTick(); + expect(wrapper.emitted().toggleTodo).toBeTruthy(); }); it('renders component container element with proper data attributes', () => { diff --git a/spec/frontend/snippets/components/edit_spec.js b/spec/frontend/snippets/components/edit_spec.js index 80a8b8ec489..9f608765183 100644 --- a/spec/frontend/snippets/components/edit_spec.js +++ b/spec/frontend/snippets/components/edit_spec.js @@ -1,7 +1,8 @@ import { GlLoadingIcon } from '@gitlab/ui'; -import { shallowMount, createLocalVue } from '@vue/test-utils'; +import { shallowMount } from '@vue/test-utils'; +import Vue, { nextTick } from 'vue'; import { merge } from 'lodash'; -import { nextTick } from 'vue'; + import VueApollo, { ApolloMutation } from 'vue-apollo'; import { useFakeDate } from 'helpers/fake_date'; import createMockApollo from 'helpers/mock_apollo_helper'; @@ -78,8 +79,7 @@ const getApiData = ({ blobActions: [], }); -const localVue = createLocalVue(); -localVue.use(VueApollo); +Vue.use(VueApollo); describe('Snippet Edit app', () => { useFakeDate(); @@ -141,7 +141,6 @@ describe('Snippet Edit app', () => { wrapper = shallowMount(SnippetEditApp, { apolloProvider, - localVue, stubs: { ApolloMutation, FormFooterActions, diff --git a/spec/frontend/snippets/components/snippet_blob_actions_edit_spec.js b/spec/frontend/snippets/components/snippet_blob_actions_edit_spec.js index 2693b26aeae..8174ba5c693 100644 --- a/spec/frontend/snippets/components/snippet_blob_actions_edit_spec.js +++ b/spec/frontend/snippets/components/snippet_blob_actions_edit_spec.js @@ -1,5 +1,6 @@ import { shallowMount } from '@vue/test-utils'; import { times } from 'lodash'; +import { nextTick } from 'vue'; import SnippetBlobActionsEdit from '~/snippets/components/snippet_blob_actions_edit.vue'; import SnippetBlobEdit from '~/snippets/components/snippet_blob_edit.vue'; import { @@ -193,7 +194,7 @@ describe('snippets/components/snippet_blob_actions_edit', () => { it('emits an action when content changes again', async () => { triggerBlobUpdate(0, { content }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(getLastActions()).toEqual([testEntries.updated.diff]); }); diff --git a/spec/frontend/snippets/components/snippet_header_spec.js b/spec/frontend/snippets/components/snippet_header_spec.js index daa9d6345b0..1b9d170556b 100644 --- a/spec/frontend/snippets/components/snippet_header_spec.js +++ b/spec/frontend/snippets/components/snippet_header_spec.js @@ -2,6 +2,7 @@ import { GlButton, GlModal, GlDropdown } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; import { ApolloMutation } from 'vue-apollo'; import MockAdapter from 'axios-mock-adapter'; +import { nextTick } from 'vue'; import { useMockLocationHelper } from 'helpers/mock_window_location_helper'; import waitForPromises from 'helpers/wait_for_promises'; import { Blob, BinaryBlob } from 'jest/blob/components/mock_data'; @@ -245,7 +246,7 @@ describe('Snippet header component', () => { // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax wrapper.setData({ canCreateSnippet: true }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findButtonsAsModel()).toEqual( expect.arrayContaining([ @@ -348,33 +349,31 @@ describe('Snippet header component', () => { describe('in case of successful mutation, closes modal and redirects to correct listing', () => { useMockLocationHelper(); - const createDeleteSnippet = (snippetProps = {}) => { + const createDeleteSnippet = async (snippetProps = {}) => { createComponent({ snippetProps, }); wrapper.vm.closeDeleteModal = jest.fn(); wrapper.vm.deleteSnippet(); - return wrapper.vm.$nextTick(); + await nextTick(); }; - it('redirects to dashboard/snippets for personal snippet', () => { - return createDeleteSnippet().then(() => { - expect(wrapper.vm.closeDeleteModal).toHaveBeenCalled(); - expect(window.location.pathname).toBe(`${gon.relative_url_root}dashboard/snippets`); - }); + it('redirects to dashboard/snippets for personal snippet', async () => { + await createDeleteSnippet(); + expect(wrapper.vm.closeDeleteModal).toHaveBeenCalled(); + expect(window.location.pathname).toBe(`${gon.relative_url_root}dashboard/snippets`); }); - it('redirects to project snippets for project snippet', () => { + it('redirects to project snippets for project snippet', async () => { const fullPath = 'foo/bar'; - return createDeleteSnippet({ + await createDeleteSnippet({ project: { fullPath, }, - }).then(() => { - expect(wrapper.vm.closeDeleteModal).toHaveBeenCalled(); - expect(window.location.pathname).toBe(`${fullPath}/-/snippets`); }); + expect(wrapper.vm.closeDeleteModal).toHaveBeenCalled(); + expect(window.location.pathname).toBe(`${fullPath}/-/snippets`); }); }); }); diff --git a/spec/frontend/static_site_editor/components/edit_meta_controls_spec.js b/spec/frontend/static_site_editor/components/edit_meta_controls_spec.js index 7a8834933e0..f6b29e98e5f 100644 --- a/spec/frontend/static_site_editor/components/edit_meta_controls_spec.js +++ b/spec/frontend/static_site_editor/components/edit_meta_controls_spec.js @@ -1,6 +1,7 @@ import { GlDropdown, GlDropdownItem, GlFormInput, GlFormTextarea } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import EditMetaControls from '~/static_site_editor/components/edit_meta_controls.vue'; import { mergeRequestMeta, mergeRequestTemplates } from '../mock_data'; @@ -38,11 +39,11 @@ describe('~/static_site_editor/components/edit_meta_controls.vue', () => { const findGlFormTextAreaDescription = () => wrapper.find(GlFormTextarea); - beforeEach(() => { + beforeEach(async () => { buildWrapper(); buildMocks(); - return wrapper.vm.$nextTick(); + await nextTick(); }); afterEach(() => { diff --git a/spec/frontend/static_site_editor/components/edit_meta_modal_spec.js b/spec/frontend/static_site_editor/components/edit_meta_modal_spec.js index 3a336f6a230..bf3f8b7f571 100644 --- a/spec/frontend/static_site_editor/components/edit_meta_modal_spec.js +++ b/spec/frontend/static_site_editor/components/edit_meta_modal_spec.js @@ -1,6 +1,7 @@ import { GlModal } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; +import { nextTick } from 'vue'; import { useLocalStorageSpy } from 'helpers/local_storage_helper'; import axios from '~/lib/utils/axios_utils'; import EditMetaControls from '~/static_site_editor/components/edit_meta_controls.vue'; @@ -50,14 +51,14 @@ describe('~/static_site_editor/components/edit_meta_modal.vue', () => { const findEditMetaControls = () => wrapper.find(EditMetaControls); const findLocalStorageSync = () => wrapper.find(LocalStorageSync); - beforeEach(() => { + beforeEach(async () => { localStorage.setItem(MR_META_LOCAL_STORAGE_KEY); buildMockAxios(); buildWrapper(); buildMockRefs(); - return wrapper.vm.$nextTick(); + await nextTick(); }); afterEach(() => { @@ -77,7 +78,7 @@ describe('~/static_site_editor/components/edit_meta_modal.vue', () => { findLocalStorageSync().vm.$emit('input', localStorageMeta); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findEditMetaControls().props()).toEqual(localStorageMeta); }); @@ -134,13 +135,13 @@ describe('~/static_site_editor/components/edit_meta_modal.vue', () => { it('sets the currentTemplate on the changeTemplate event', async () => { findEditMetaControls().vm.$emit('changeTemplate', template1); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findEditMetaControls().props().currentTemplate).toBe(template1); findEditMetaControls().vm.$emit('changeTemplate', null); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findEditMetaControls().props().currentTemplate).toBe(null); }); @@ -148,7 +149,7 @@ describe('~/static_site_editor/components/edit_meta_modal.vue', () => { it('updates the description on the changeTemplate event', async () => { findEditMetaControls().vm.$emit('changeTemplate', template1); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findEditMetaControls().props().description).toEqual(template1.content); }); @@ -164,7 +165,7 @@ describe('~/static_site_editor/components/edit_meta_modal.vue', () => { findEditMetaControls().vm.$emit('updateSettings', newMeta); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findLocalStorageSync().props('value')).toEqual(newMeta); }); diff --git a/spec/frontend/static_site_editor/pages/home_spec.js b/spec/frontend/static_site_editor/pages/home_spec.js index 4f6f2bb3c76..6571d295c36 100644 --- a/spec/frontend/static_site_editor/pages/home_spec.js +++ b/spec/frontend/static_site_editor/pages/home_spec.js @@ -1,4 +1,5 @@ import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import { mockTracking, unmockTracking } from 'helpers/tracking_helper'; import EditArea from '~/static_site_editor/components/edit_area.vue'; import EditMetaModal from '~/static_site_editor/components/edit_meta_modal.vue'; @@ -179,7 +180,7 @@ describe('static_site_editor/pages/home', () => { }); describe('when preparing submission', () => { - it('calls the show method when the edit-area submit event is emitted', () => { + it('calls the show method when the edit-area submit event is emitted', async () => { buildWrapper(); const mockInstance = { show: jest.fn() }; @@ -187,9 +188,8 @@ describe('static_site_editor/pages/home', () => { findEditArea().vm.$emit('submit', { content }); - return wrapper.vm.$nextTick().then(() => { - expect(mockInstance.show).toHaveBeenCalled(); - }); + await nextTick(); + expect(mockInstance.show).toHaveBeenCalled(); }); }); @@ -200,13 +200,13 @@ describe('static_site_editor/pages/home', () => { .mockRejectedValueOnce(new Error(submitChangesError)); }; - beforeEach(() => { + beforeEach(async () => { setupMutateMock(); buildWrapper({ content }); findEditMetaModal().vm.$emit('primary', mergeRequestMeta); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('displays submit changes error message', () => { @@ -221,12 +221,11 @@ describe('static_site_editor/pages/home', () => { expect(mutateMock).toHaveBeenCalled(); }); - it('hides submit changes error message when dismiss button is clicked', () => { + it('hides submit changes error message when dismiss button is clicked', async () => { findSubmitChangesError().vm.$emit('dismiss'); - return wrapper.vm.$nextTick().then(() => { - expect(findSubmitChangesError().exists()).toBe(false); - }); + await nextTick(); + expect(findSubmitChangesError().exists()).toBe(false); }); }); @@ -234,7 +233,7 @@ describe('static_site_editor/pages/home', () => { const newContent = `new ${content}`; const formattedMarkdown = `formatted ${content}`; - beforeEach(() => { + beforeEach(async () => { mutateMock.mockResolvedValueOnce(hasSubmittedChangesMutationPayload).mockResolvedValueOnce({ data: { submitContentChanges: savedContentMeta, @@ -249,7 +248,7 @@ describe('static_site_editor/pages/home', () => { findEditMetaModal().vm.$emit('primary', mergeRequestMeta); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('dispatches hasSubmittedChanges mutation', () => { diff --git a/spec/frontend/terraform/components/states_table_actions_spec.js b/spec/frontend/terraform/components/states_table_actions_spec.js index fbe55306f37..a6c80b95af4 100644 --- a/spec/frontend/terraform/components/states_table_actions_spec.js +++ b/spec/frontend/terraform/components/states_table_actions_spec.js @@ -1,5 +1,6 @@ import { GlDropdown, GlModal, GlSprintf } from '@gitlab/ui'; -import { createLocalVue, shallowMount } from '@vue/test-utils'; +import { shallowMount } from '@vue/test-utils'; +import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; @@ -9,8 +10,7 @@ import lockStateMutation from '~/terraform/graphql/mutations/lock_state.mutation import removeStateMutation from '~/terraform/graphql/mutations/remove_state.mutation.graphql'; import unlockStateMutation from '~/terraform/graphql/mutations/unlock_state.mutation.graphql'; -const localVue = createLocalVue(); -localVue.use(VueApollo); +Vue.use(VueApollo); describe('StatesTableActions', () => { let lockResponse; @@ -58,20 +58,19 @@ describe('StatesTableActions', () => { ); }; - const createComponent = (propsData = defaultProps) => { + const createComponent = async (propsData = defaultProps) => { const apolloProvider = createMockApolloProvider(); toast = jest.fn(); wrapper = shallowMount(StateActions, { apolloProvider, - localVue, propsData, mocks: { $toast: { show: toast } }, stubs: { GlDropdown, GlModal, GlSprintf }, }); - return wrapper.vm.$nextTick(); + await nextTick(); }; const findActionsDropdown = () => wrapper.findComponent(GlDropdown); diff --git a/spec/frontend/terraform/components/states_table_spec.js b/spec/frontend/terraform/components/states_table_spec.js index 100e577f514..9dbc8335851 100644 --- a/spec/frontend/terraform/components/states_table_spec.js +++ b/spec/frontend/terraform/components/states_table_spec.js @@ -1,5 +1,6 @@ import { GlIcon, GlLoadingIcon, GlTooltip } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import { useFakeDate } from 'helpers/fake_date'; import StatesTable from '~/terraform/components/states_table.vue'; import StateActions from '~/terraform/components/states_table_actions.vue'; @@ -106,9 +107,9 @@ describe('StatesTable', () => { ], }; - const createComponent = (propsData = defaultProps) => { + const createComponent = async (propsData = defaultProps) => { wrapper = mount(StatesTable, { propsData }); - return wrapper.vm.$nextTick(); + await nextTick(); }; const findActions = () => wrapper.findAll(StateActions); diff --git a/spec/frontend/terraform/components/terraform_list_spec.js b/spec/frontend/terraform/components/terraform_list_spec.js index 8e565df81ae..803f1723645 100644 --- a/spec/frontend/terraform/components/terraform_list_spec.js +++ b/spec/frontend/terraform/components/terraform_list_spec.js @@ -1,5 +1,6 @@ import { GlAlert, GlBadge, GlKeysetPagination, GlLoadingIcon, GlTab } from '@gitlab/ui'; -import { createLocalVue, shallowMount } from '@vue/test-utils'; +import { shallowMount } from '@vue/test-utils'; +import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; @@ -8,8 +9,7 @@ import StatesTable from '~/terraform/components/states_table.vue'; import TerraformList from '~/terraform/components/terraform_list.vue'; import getStatesQuery from '~/terraform/graphql/queries/get_states.query.graphql'; -const localVue = createLocalVue(); -localVue.use(VueApollo); +Vue.use(VueApollo); describe('TerraformList', () => { let wrapper; @@ -45,7 +45,6 @@ describe('TerraformList', () => { const apolloProvider = createMockApollo([[getStatesQuery, statsQueryResponse]], mockResolvers); wrapper = shallowMount(TerraformList, { - localVue, apolloProvider, propsData, stubs: { diff --git a/spec/frontend/token_access/token_access_spec.js b/spec/frontend/token_access/token_access_spec.js index c4e29a52f1c..5aaeebd5af4 100644 --- a/spec/frontend/token_access/token_access_spec.js +++ b/spec/frontend/token_access/token_access_spec.js @@ -1,5 +1,5 @@ import { GlToggle, GlLoadingIcon } from '@gitlab/ui'; -import { createLocalVue } from '@vue/test-utils'; +import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper'; @@ -22,9 +22,8 @@ import { const projectPath = 'root/my-repo'; const error = new Error('Error'); -const localVue = createLocalVue(); -localVue.use(VueApollo); +Vue.use(VueApollo); jest.mock('~/flash'); @@ -52,7 +51,6 @@ describe('TokenAccess component', () => { const createComponent = (requestHandlers, mountFn = shallowMountExtended) => { wrapper = mountFn(TokenAccess, { - localVue, provide: { fullPath: projectPath, }, diff --git a/spec/frontend/tooltips/components/tooltips_spec.js b/spec/frontend/tooltips/components/tooltips_spec.js index 9b703b74a1a..eef352a72ff 100644 --- a/spec/frontend/tooltips/components/tooltips_spec.js +++ b/spec/frontend/tooltips/components/tooltips_spec.js @@ -1,5 +1,6 @@ import { GlTooltip } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import { useMockMutationObserver } from 'helpers/mock_dom_observer'; import Tooltips from '~/tooltips/components/tooltips.vue'; @@ -46,7 +47,7 @@ describe('tooltips/components/tooltips.vue', () => { it('attaches tooltips to the targets specified', async () => { wrapper.vm.addTooltips([target]); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.find(GlTooltip).props('target')).toBe(target); }); @@ -56,7 +57,7 @@ describe('tooltips/components/tooltips.vue', () => { wrapper.vm.addTooltips([target]); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.find(GlTooltip).exists()).toBe(false); }); @@ -65,7 +66,7 @@ describe('tooltips/components/tooltips.vue', () => { wrapper.vm.addTooltips([target]); wrapper.vm.addTooltips([target]); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.findAll(GlTooltip)).toHaveLength(1); }); @@ -73,7 +74,7 @@ describe('tooltips/components/tooltips.vue', () => { it('sets tooltip content from title attribute', async () => { wrapper.vm.addTooltips([target]); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.find(GlTooltip).text()).toBe(target.getAttribute('title')); }); @@ -85,7 +86,7 @@ describe('tooltips/components/tooltips.vue', () => { }); wrapper.vm.addTooltips([target]); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.find(GlTooltip).html()).toContain(target.getAttribute('title')); }); @@ -94,7 +95,7 @@ describe('tooltips/components/tooltips.vue', () => { const config = { show: true }; target = createTooltipTarget(); wrapper.vm.addTooltips([target], config); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.find(GlTooltip).props()).toMatchObject(config); }); @@ -110,7 +111,7 @@ describe('tooltips/components/tooltips.vue', () => { target = createTooltipTarget({ [attribute]: value }); wrapper.vm.addTooltips([target]); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.find(GlTooltip).props(prop)).toBe(value); }, @@ -124,10 +125,10 @@ describe('tooltips/components/tooltips.vue', () => { it('removes all tooltips when elements is nil', async () => { wrapper.vm.addTooltips([createTooltipTarget(), createTooltipTarget()]); - await wrapper.vm.$nextTick(); + await nextTick(); wrapper.vm.dispose(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(allTooltips()).toHaveLength(0); }); @@ -136,10 +137,10 @@ describe('tooltips/components/tooltips.vue', () => { const target = createTooltipTarget(); wrapper.vm.addTooltips([target, createTooltipTarget()]); - await wrapper.vm.$nextTick(); + await nextTick(); wrapper.vm.dispose(target); - await wrapper.vm.$nextTick(); + await nextTick(); expect(allTooltips()).toHaveLength(1); }); @@ -154,13 +155,13 @@ describe('tooltips/components/tooltips.vue', () => { const target = createTooltipTarget(); wrapper.vm.addTooltips([target, createTooltipTarget()]); - await wrapper.vm.$nextTick(); + await nextTick(); triggerMutate(document.body, { entry: { removedNodes: [target] }, options: { childList: true }, }); - await wrapper.vm.$nextTick(); + await nextTick(); expect(allTooltips()).toHaveLength(1); }); @@ -175,7 +176,7 @@ describe('tooltips/components/tooltips.vue', () => { wrapper.vm.addTooltips([target]); - await wrapper.vm.$nextTick(); + await nextTick(); wrapper.vm.triggerEvent(target, event); @@ -195,14 +196,14 @@ describe('tooltips/components/tooltips.vue', () => { wrapper.vm.addTooltips([target]); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.find(GlTooltip).text()).toBe(currentTitle); target.setAttribute('title', newTitle); wrapper.vm.fixTitle(target); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.find(GlTooltip).text()).toBe(newTitle); }); @@ -225,7 +226,7 @@ describe('tooltips/components/tooltips.vue', () => { buildWrapper(); wrapper.vm.addTooltips([createTooltipTarget()]); - await wrapper.vm.$nextTick(); + await nextTick(); wrapper.findComponent(GlTooltip).vm.$emit('hidden'); expect(wrapper.emitted('hidden')).toHaveLength(1); diff --git a/spec/frontend/user_lists/components/add_user_modal_spec.js b/spec/frontend/user_lists/components/add_user_modal_spec.js index c9ad40ed228..cd04836a8c4 100644 --- a/spec/frontend/user_lists/components/add_user_modal_spec.js +++ b/spec/frontend/user_lists/components/add_user_modal_spec.js @@ -1,4 +1,5 @@ import { mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import AddUserModal from '~/user_lists/components/add_user_modal.vue'; describe('Add User Modal', () => { @@ -30,7 +31,7 @@ describe('Add User Modal', () => { it('should clear the input after emitting', async () => { click('confirm-add-user-ids'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.find('#add-user-ids').element.value).toBe(''); }); @@ -42,7 +43,7 @@ describe('Add User Modal', () => { it('should clear the input after cancelling', async () => { click('cancel-add-user-ids'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.find('#add-user-ids').element.value).toBe(''); }); diff --git a/spec/frontend/user_lists/components/edit_user_list_spec.js b/spec/frontend/user_lists/components/edit_user_list_spec.js index 4731f4b9c02..7cafe5e1f56 100644 --- a/spec/frontend/user_lists/components/edit_user_list_spec.js +++ b/spec/frontend/user_lists/components/edit_user_list_spec.js @@ -1,6 +1,6 @@ import { GlAlert, GlLoadingIcon } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import waitForPromises from 'helpers/wait_for_promises'; import Api from '~/api'; @@ -77,11 +77,11 @@ describe('user_lists/components/edit_user_list', () => { }); describe('update', () => { - beforeEach(() => { + beforeEach(async () => { Api.fetchFeatureFlagUserList.mockResolvedValue({ data: userList }); factory(); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('should link to the documentation', () => { @@ -99,11 +99,11 @@ describe('user_lists/components/edit_user_list', () => { }); describe('success', () => { - beforeEach(() => { + beforeEach(async () => { Api.updateFeatureFlagUserList.mockResolvedValue({ data: userList }); setInputValue('test'); clickSave(); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('should create a user list with the entered name', () => { @@ -139,7 +139,7 @@ describe('user_lists/components/edit_user_list', () => { it('should dismiss the error if dismiss is clicked', async () => { alert.find('button').trigger('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(alert.exists()).toBe(false); }); diff --git a/spec/frontend/user_lists/components/new_user_list_spec.js b/spec/frontend/user_lists/components/new_user_list_spec.js index 1cce53c7963..5eb44970fe4 100644 --- a/spec/frontend/user_lists/components/new_user_list_spec.js +++ b/spec/frontend/user_lists/components/new_user_list_spec.js @@ -1,6 +1,6 @@ import { GlAlert } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import waitForPromises from 'helpers/wait_for_promises'; import Api from '~/api'; @@ -43,11 +43,11 @@ describe('user_lists/components/new_user_list', () => { describe('create', () => { describe('success', () => { - beforeEach(() => { + beforeEach(async () => { Api.createFeatureFlagUserList.mockResolvedValue({ data: userList }); setInputValue('test'); click('save-user-list'); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('should create a user list with the entered name', () => { @@ -82,7 +82,7 @@ describe('user_lists/components/new_user_list', () => { it('should dismiss the error when the dismiss button is clicked', async () => { alert.find('button').trigger('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(alert.exists()).toBe(false); }); diff --git a/spec/frontend/user_lists/components/user_list_spec.js b/spec/frontend/user_lists/components/user_list_spec.js index f016b5091d9..88dad06938b 100644 --- a/spec/frontend/user_lists/components/user_list_spec.js +++ b/spec/frontend/user_lists/components/user_list_spec.js @@ -1,7 +1,7 @@ import { GlAlert, GlEmptyState, GlLoadingIcon } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; import { uniq } from 'lodash'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import Api from '~/api'; import UserList from '~/user_lists/components/user_list.vue'; @@ -57,12 +57,12 @@ describe('User List', () => { describe('success', () => { let userIds; - beforeEach(() => { + beforeEach(async () => { userIds = parseUserIds(userList.user_xids); Api.fetchFeatureFlagUserList.mockResolvedValueOnce({ data: userList }); factory(); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('requests the user list on mount', () => { @@ -101,10 +101,10 @@ describe('User List', () => { beforeEach(async () => { Api.updateFeatureFlagUserList.mockResolvedValue(userList); click('add-users'); - await wrapper.vm.$nextTick(); + await nextTick(); wrapper.find('#add-user-ids').setValue(`${stringifyUserIds(newIds)},`); click('confirm-add-user-ids'); - await wrapper.vm.$nextTick(); + await nextTick(); [[, { user_xids: receivedUserIds }]] = Api.updateFeatureFlagUserList.mock.calls; parsedReceivedUserIds = parseUserIds(receivedUserIds); }); @@ -140,7 +140,7 @@ describe('User List', () => { beforeEach(async () => { Api.updateFeatureFlagUserList.mockResolvedValue(userList); click('delete-user-id'); - await wrapper.vm.$nextTick(); + await nextTick(); [[, { user_xids: receivedUserIds }]] = Api.updateFeatureFlagUserList.mock.calls; }); @@ -159,11 +159,11 @@ describe('User List', () => { describe('error', () => { const findAlert = () => wrapper.find(GlAlert); - beforeEach(() => { + beforeEach(async () => { Api.fetchFeatureFlagUserList.mockRejectedValue(); factory(); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('displays the alert message', () => { @@ -175,18 +175,18 @@ describe('User List', () => { const alert = findAlert(); alert.find('button').trigger('click'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(alert.exists()).toBe(false); }); }); describe('empty list', () => { - beforeEach(() => { + beforeEach(async () => { Api.fetchFeatureFlagUserList.mockResolvedValueOnce({ data: { ...userList, user_xids: '' } }); factory(); - return wrapper.vm.$nextTick(); + await nextTick(); }); it('displays an empty state', () => { diff --git a/spec/frontend/user_lists/components/user_lists_table_spec.js b/spec/frontend/user_lists/components/user_lists_table_spec.js index 7f4d510a39c..63587703392 100644 --- a/spec/frontend/user_lists/components/user_lists_table_spec.js +++ b/spec/frontend/user_lists/components/user_lists_table_spec.js @@ -1,6 +1,7 @@ import { GlModal } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; import * as timeago from 'timeago.js'; +import { nextTick } from 'vue'; import UserListsTable from '~/user_lists/components/user_lists_table.vue'; import { userList } from '../../feature_flags/mock_data'; @@ -56,43 +57,40 @@ describe('User Lists Table', () => { }); describe('delete button', () => { - it('should display the confirmation modal', () => { + it('should display the confirmation modal', async () => { const modal = wrapper.find(GlModal); wrapper.find('[data-testid="delete-user-list"]').trigger('click'); - return wrapper.vm.$nextTick().then(() => { - expect(modal.text()).toContain(`Delete ${userList.name}?`); - expect(modal.text()).toContain(`User list ${userList.name} will be removed.`); - }); + await nextTick(); + expect(modal.text()).toContain(`Delete ${userList.name}?`); + expect(modal.text()).toContain(`User list ${userList.name} will be removed.`); }); }); describe('confirmation modal', () => { let modal; - beforeEach(() => { + beforeEach(async () => { modal = wrapper.find(GlModal); wrapper.find('button').trigger('click'); - return wrapper.vm.$nextTick(); + await nextTick(); }); - it('should emit delete with list on confirmation', () => { + it('should emit delete with list on confirmation', async () => { modal.find('[data-testid="modal-confirm"]').trigger('click'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted('delete')).toEqual([[userLists[0]]]); - }); + await nextTick(); + expect(wrapper.emitted('delete')).toEqual([[userLists[0]]]); }); - it('should not emit delete with list when not confirmed', () => { + it('should not emit delete with list when not confirmed', async () => { modal.find('button').trigger('click'); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.emitted('delete')).toBeUndefined(); - }); + await nextTick(); + expect(wrapper.emitted('delete')).toBeUndefined(); }); }); }); diff --git a/spec/frontend/whats_new/components/app_spec.js b/spec/frontend/whats_new/components/app_spec.js index 45f28c2c51b..945727cd664 100644 --- a/spec/frontend/whats_new/components/app_spec.js +++ b/spec/frontend/whats_new/components/app_spec.js @@ -1,6 +1,6 @@ import { GlDrawer, GlInfiniteScroll } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import { mockTracking, unmockTracking, triggerEvent } from 'helpers/tracking_helper'; import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; @@ -67,7 +67,7 @@ describe('App', () => { { title: 'Whats New Drawer', url: 'www.url.com', release: 3.11 }, ]; wrapper.vm.$store.state.drawerBodyHeight = MOCK_DRAWER_BODY_HEIGHT; - await wrapper.vm.$nextTick(); + await nextTick(); }; afterEach(() => { @@ -108,7 +108,7 @@ describe('App', () => { it.each([true, false])('passes open property', async (openState) => { wrapper.vm.$store.state.open = openState; - await wrapper.vm.$nextTick(); + await nextTick(); expect(getDrawer().props('open')).toBe(openState); }); diff --git a/spec/lib/gitlab/database/no_cross_db_foreign_keys_spec.rb b/spec/lib/gitlab/database/no_cross_db_foreign_keys_spec.rb index ab584f92716..1f70fbd440c 100644 --- a/spec/lib/gitlab/database/no_cross_db_foreign_keys_spec.rb +++ b/spec/lib/gitlab/database/no_cross_db_foreign_keys_spec.rb @@ -38,7 +38,6 @@ RSpec.describe 'cross-database foreign keys' do ci_stages.project_id ci_subscriptions_projects.downstream_project_id ci_subscriptions_projects.upstream_project_id - ci_triggers.project_id ci_unit_tests.project_id ci_variables.project_id dast_site_profiles_pipelines.ci_pipeline_id diff --git a/spec/models/ci/trigger_spec.rb b/spec/models/ci/trigger_spec.rb index b9f7e44f3e8..c9ae8519c63 100644 --- a/spec/models/ci/trigger_spec.rb +++ b/spec/models/ci/trigger_spec.rb @@ -68,4 +68,11 @@ RSpec.describe Ci::Trigger do let!(:model) { create(:ci_trigger, owner: parent) } end end + + context 'loose foreign key on ci_triggers.project_id' do + it_behaves_like 'cleanup by a loose foreign key' do + let!(:parent) { create(:project) } + let!(:model) { create(:ci_trigger, project: parent) } + end + end end |