diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-07-15 00:09:55 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-07-15 00:09:55 +0300 |
commit | cde60c9291a22ff0921f703568c4daef4a65ead7 (patch) | |
tree | 15d6d3f5cbe339c00a39a60e7f8b7be295c8a739 /spec/frontend | |
parent | 6d2fcd332783033432e4de1d8b1de6720e20f557 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend')
56 files changed, 285 insertions, 314 deletions
diff --git a/spec/frontend/access_tokens/components/projects_field_spec.js b/spec/frontend/access_tokens/components/projects_field_spec.js index a9e0799d114..1c4fe7bb168 100644 --- a/spec/frontend/access_tokens/components/projects_field_spec.js +++ b/spec/frontend/access_tokens/components/projects_field_spec.js @@ -1,3 +1,4 @@ +import { nextTick } from 'vue'; import { within, fireEvent } from '@testing-library/dom'; import { mount } from '@vue/test-utils'; import ProjectsField from '~/access_tokens/components/projects_field.vue'; @@ -118,11 +119,10 @@ describe('ProjectsField', () => { }); describe('when radio is changed back to "All projects"', () => { - beforeEach(() => { - fireEvent.click(findAllProjectsRadio()); - }); + it('removes the hidden input value', async () => { + fireEvent.change(findAllProjectsRadio()); + await nextTick(); - it('removes the hidden input value', () => { expect(findHiddenInput().attributes('value')).toBe(''); }); }); diff --git a/spec/frontend/admin/signup_restrictions/components/signup_form_spec.js b/spec/frontend/admin/signup_restrictions/components/signup_form_spec.js index 5b4f954b672..31a0c2b07e4 100644 --- a/spec/frontend/admin/signup_restrictions/components/signup_form_spec.js +++ b/spec/frontend/admin/signup_restrictions/components/signup_form_spec.js @@ -1,6 +1,6 @@ import { GlButton, GlModal } from '@gitlab/ui'; -import { within, fireEvent } from '@testing-library/dom'; -import { shallowMount, mount } from '@vue/test-utils'; +import { within } from '@testing-library/dom'; +import { shallowMount, mount, createWrapper } from '@vue/test-utils'; import { stubComponent } from 'helpers/stub_component'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import SignupForm from '~/pages/admin/application_settings/general/components/signup_form.vue'; @@ -121,7 +121,7 @@ describe('Signup Form', () => { describe('when user clicks on file radio', () => { beforeEach(() => { - fireEvent.click(findDenyListFileRadio()); + createWrapper(findDenyListFileRadio()).setChecked(true); }); it('has raw list not selected', () => { @@ -165,7 +165,7 @@ describe('Signup Form', () => { describe('when user clicks on raw list radio', () => { beforeEach(() => { - fireEvent.click(findDenyListRawRadio()); + createWrapper(findDenyListRawRadio()).setChecked(true); }); it('has raw list selected', () => { diff --git a/spec/frontend/admin/statistics_panel/components/app_spec.js b/spec/frontend/admin/statistics_panel/components/app_spec.js index 3cfb6feeb86..bac542e72fb 100644 --- a/spec/frontend/admin/statistics_panel/components/app_spec.js +++ b/spec/frontend/admin/statistics_panel/components/app_spec.js @@ -64,7 +64,7 @@ describe('Admin statistics app', () => { createComponent(); expect(findStats(index).text()).toContain(label); - expect(findStats(index).text()).toContain(count); + expect(findStats(index).text()).toContain(count.toString()); }); }); }); diff --git a/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js b/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js index 018303fcae7..7d9d2875cf8 100644 --- a/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js +++ b/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js @@ -265,7 +265,6 @@ describe('AlertsSettingsForm', () => { }); it('should not allow a user to test invalid JSON', async () => { - jest.useFakeTimers(); await findJsonTextArea().setValue('Invalid JSON'); jest.runAllTimers(); @@ -278,7 +277,6 @@ describe('AlertsSettingsForm', () => { }); it('should allow for the form to be automatically saved if the test payload is successfully submitted', async () => { - jest.useFakeTimers(); await findJsonTextArea().setValue('{ "value": "value" }'); jest.runAllTimers(); diff --git a/spec/frontend/behaviors/shortcuts/keybindings_spec.js b/spec/frontend/behaviors/shortcuts/keybindings_spec.js index 3ad44a16ae1..1f7e1b24e78 100644 --- a/spec/frontend/behaviors/shortcuts/keybindings_spec.js +++ b/spec/frontend/behaviors/shortcuts/keybindings_spec.js @@ -11,9 +11,7 @@ import { } from '~/behaviors/shortcuts/keybindings'; describe('~/behaviors/shortcuts/keybindings', () => { - beforeAll(() => { - useLocalStorageSpy(); - }); + useLocalStorageSpy(); const setupCustomizations = (customizationsAsString) => { localStorage.clear(); diff --git a/spec/frontend/boards/project_select_spec.js b/spec/frontend/boards/project_select_spec.js index bd79060c54f..c45cd545155 100644 --- a/spec/frontend/boards/project_select_spec.js +++ b/spec/frontend/boards/project_select_spec.js @@ -1,16 +1,16 @@ import { GlDropdown, GlDropdownItem, + GlFormInput, GlSearchBoxByType, GlLoadingIcon, - GlFormInput, } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; -import waitForPromises from 'helpers/wait_for_promises'; import ProjectSelect from '~/boards/components/project_select.vue'; import defaultState from '~/boards/stores/state'; +import waitForPromises from 'helpers/wait_for_promises'; import { mockList, mockActiveGroupProjects } from './mock_data'; @@ -21,7 +21,7 @@ describe('ProjectSelect component', () => { let store; const findLabel = () => wrapper.find("[data-testid='header-label']"); - const findGlDropdown = () => wrapper.find(GlDropdown); + const findGlDropdown = () => wrapper.findComponent(GlDropdown); const findGlDropdownLoadingIcon = () => findGlDropdown().find('button:first-child').find(GlLoadingIcon); const findGlSearchBoxByType = () => wrapper.find(GlSearchBoxByType); @@ -137,7 +137,7 @@ describe('ProjectSelect component', () => { await nextTick(); const searchInput = findGlDropdown().findComponent(GlFormInput).element; - expect(document.activeElement).toEqual(searchInput); + expect(document.activeElement).toBe(searchInput); }); }); diff --git a/spec/frontend/clusters_list/components/clusters_spec.js b/spec/frontend/clusters_list/components/clusters_spec.js index c150a7f05d0..5c7635c1617 100644 --- a/spec/frontend/clusters_list/components/clusters_spec.js +++ b/spec/frontend/clusters_list/components/clusters_spec.js @@ -103,11 +103,9 @@ describe('Clusters', () => { }); describe('when is loaded as a child component', () => { - beforeEach(() => { + it("shouldn't render pagination buttons", () => { createWrapper({ limit: 6 }); - }); - it("shouldn't render pagination buttons", () => { expect(findPaginatedButtons().exists()).toBe(false); }); }); diff --git a/spec/frontend/custom_metrics/components/custom_metrics_form_fields_spec.js b/spec/frontend/custom_metrics/components/custom_metrics_form_fields_spec.js index 2001f5c1441..bd4ed950f9d 100644 --- a/spec/frontend/custom_metrics/components/custom_metrics_form_fields_spec.js +++ b/spec/frontend/custom_metrics/components/custom_metrics_form_fields_spec.js @@ -1,3 +1,4 @@ +import { nextTick } from 'vue'; import { mount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; import { TEST_HOST } from 'helpers/test_constants'; @@ -148,6 +149,7 @@ describe('custom metrics form fields component', () => { it('expect loading message to display', async () => { const queryInput = wrapper.find(`input[name="${queryInputName}"]`); queryInput.setValue('query'); + await nextTick(); expect(wrapper.text()).toContain('Validating query'); }); diff --git a/spec/frontend/cycle_analytics/path_navigation_spec.js b/spec/frontend/cycle_analytics/path_navigation_spec.js index e8c4ebd3a38..fa9eadbd071 100644 --- a/spec/frontend/cycle_analytics/path_navigation_spec.js +++ b/spec/frontend/cycle_analytics/path_navigation_spec.js @@ -85,7 +85,7 @@ describe('Project PathNavigation', () => { const result = findPathNavigationTitles(); transformedProjectStagePathData.forEach(({ title, metric }, index) => { expect(result[index]).toContain(title); - expect(result[index]).toContain(metric); + expect(result[index]).toContain(metric.toString()); }); }); diff --git a/spec/frontend/cycle_analytics/value_stream_metrics_spec.js b/spec/frontend/cycle_analytics/value_stream_metrics_spec.js index df86b10cba3..23e41f35b00 100644 --- a/spec/frontend/cycle_analytics/value_stream_metrics_spec.js +++ b/spec/frontend/cycle_analytics/value_stream_metrics_spec.js @@ -55,10 +55,10 @@ describe('ValueStreamMetrics', () => { describe('with successful requests', () => { beforeEach(() => { mockGetValueStreamSummaryMetrics = jest.fn().mockResolvedValue({ data: metricsData }); - wrapper = createComponent(); }); it('will display a loader with pending requests', async () => { + wrapper = createComponent(); await nextTick(); expect(wrapper.findComponent(GlSkeletonLoader).exists()).toBe(true); @@ -66,6 +66,7 @@ describe('ValueStreamMetrics', () => { describe('with data loaded', () => { beforeEach(async () => { + wrapper = createComponent(); await waitForPromises(); }); diff --git a/spec/frontend/diffs/components/settings_dropdown_spec.js b/spec/frontend/diffs/components/settings_dropdown_spec.js index 693fc5bfd8f..2ec11ba86fd 100644 --- a/spec/frontend/diffs/components/settings_dropdown_spec.js +++ b/spec/frontend/diffs/components/settings_dropdown_spec.js @@ -1,6 +1,5 @@ import { mount } from '@vue/test-utils'; -import { nextTick } from 'vue'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import SettingsDropdown from '~/diffs/components/settings_dropdown.vue'; @@ -139,9 +138,7 @@ describe('Diff settings dropdown component', () => { const checkbox = wrapper.findByTestId('show-whitespace'); const { checked } = checkbox.element; - checkbox.trigger('click'); - - await nextTick(); + await checkbox.setChecked(false); expect(store.dispatch).toHaveBeenCalledWith('diffs/setShowWhitespace', { showWhitespace: !checked, @@ -182,9 +179,7 @@ describe('Diff settings dropdown component', () => { Object.assign(origStore.state.diffs, { viewDiffsFileByFile: start }), }); - getFileByFileCheckbox(wrapper).trigger('click'); - - await nextTick(); + await getFileByFileCheckbox(wrapper).setChecked(setting); expect(store.dispatch).toHaveBeenCalledWith('diffs/setFileByFile', { fileByFile: setting, diff --git a/spec/frontend/dirty_submit/dirty_submit_form_spec.js b/spec/frontend/dirty_submit/dirty_submit_form_spec.js index bcbe824bd9f..f24bb7374a3 100644 --- a/spec/frontend/dirty_submit/dirty_submit_form_spec.js +++ b/spec/frontend/dirty_submit/dirty_submit_form_spec.js @@ -55,7 +55,6 @@ describe('DirtySubmitForm', () => { describe('throttling tests', () => { beforeEach(() => { throttle.mockImplementation(lodash.throttle); - jest.useFakeTimers(); }); afterEach(() => { diff --git a/spec/frontend/environments/environment_item_spec.js b/spec/frontend/environments/environment_item_spec.js index 0761d04229c..1c86a66d9b8 100644 --- a/spec/frontend/environments/environment_item_spec.js +++ b/spec/frontend/environments/environment_item_spec.js @@ -68,7 +68,7 @@ describe('Environment item', () => { describe('With deployment', () => { it('should render deployment internal id', () => { expect(wrapper.find('.deployment-column span').text()).toContain( - environment.last_deployment.iid, + environment.last_deployment.iid.toString(), ); expect(wrapper.find('.deployment-column span').text()).toContain('#'); @@ -400,7 +400,7 @@ describe('Environment item', () => { }); it('should render the number of children in a badge', () => { - expect(wrapper.find('.folder-name .badge').text()).toContain(folder.size); + expect(wrapper.find('.folder-name .badge').text()).toContain(folder.size.toString()); }); it('should not render the "Upcoming deployment" column', () => { diff --git a/spec/frontend/environments/environments_app_spec.js b/spec/frontend/environments/environments_app_spec.js index 91b75c850bd..57f98c81124 100644 --- a/spec/frontend/environments/environments_app_spec.js +++ b/spec/frontend/environments/environments_app_spec.js @@ -204,9 +204,9 @@ describe('~/environments/components/environments_app.vue', () => { const [available, stopped] = wrapper.findAllByRole('tab').wrappers; expect(available.text()).toContain(__('Available')); - expect(available.text()).toContain(resolvedEnvironmentsApp.availableCount); + expect(available.text()).toContain(resolvedEnvironmentsApp.availableCount.toString()); expect(stopped.text()).toContain(__('Stopped')); - expect(stopped.text()).toContain(resolvedEnvironmentsApp.stoppedCount); + expect(stopped.text()).toContain(resolvedEnvironmentsApp.stoppedCount.toString()); }); it('should change the requested scope on tab change', async () => { diff --git a/spec/frontend/gfm_auto_complete_spec.js b/spec/frontend/gfm_auto_complete_spec.js index 552377e3381..072cf34d0ef 100644 --- a/spec/frontend/gfm_auto_complete_spec.js +++ b/spec/frontend/gfm_auto_complete_spec.js @@ -738,7 +738,7 @@ describe('GfmAutoComplete', () => { $textarea.trigger('focus').val(text).caret('pos', -1); $textarea.trigger('keyup'); - return new Promise(window.requestAnimationFrame); + jest.runOnlyPendingTimers(); }; const getDropdownItems = () => { @@ -747,10 +747,11 @@ describe('GfmAutoComplete', () => { return [].map.call(items, (item) => item.textContent.trim()); }; - const expectLabels = ({ input, output }) => - triggerDropdown(input).then(() => { - expect(getDropdownItems()).toEqual(output.map((label) => label.title)); - }); + const expectLabels = ({ input, output }) => { + triggerDropdown(input); + + expect(getDropdownItems()).toEqual(output.map((label) => label.title)); + }; describe('with no labels assigned', () => { beforeEach(() => { diff --git a/spec/frontend/import_entities/import_groups/components/import_table_spec.js b/spec/frontend/import_entities/import_groups/components/import_table_spec.js index 0279ad454d2..24881237b85 100644 --- a/spec/frontend/import_entities/import_groups/components/import_table_spec.js +++ b/spec/frontend/import_entities/import_groups/components/import_table_spec.js @@ -50,11 +50,11 @@ describe('import table', () => { const findPaginationDropdownText = () => findPaginationDropdown().find('button').text(); const findSelectionCount = () => wrapper.find('[data-test-id="selection-count"]'); - const triggerSelectAllCheckbox = () => - wrapper.find('thead input[type=checkbox]').trigger('click'); + const triggerSelectAllCheckbox = (checked = true) => + wrapper.find('thead input[type=checkbox]').setChecked(checked); const selectRow = (idx) => - wrapper.findAll('tbody td input[type=checkbox]').at(idx).trigger('click'); + wrapper.findAll('tbody td input[type=checkbox]').at(idx).setChecked(true); const createComponent = ({ bulkImportSourceGroups, importGroups }) => { apolloProvider = createMockApollo([], { @@ -388,7 +388,7 @@ describe('import table', () => { expect(findSelectionCount().text()).toMatchInterpolatedText('0 selected'); await triggerSelectAllCheckbox(); expect(findSelectionCount().text()).toMatchInterpolatedText('2 selected'); - await triggerSelectAllCheckbox(); + await triggerSelectAllCheckbox(false); expect(findSelectionCount().text()).toMatchInterpolatedText('0 selected'); }); diff --git a/spec/frontend/integrations/edit/components/active_checkbox_spec.js b/spec/frontend/integrations/edit/components/active_checkbox_spec.js index 633389578a0..1f7a5f0dbc9 100644 --- a/spec/frontend/integrations/edit/components/active_checkbox_spec.js +++ b/spec/frontend/integrations/edit/components/active_checkbox_spec.js @@ -1,7 +1,6 @@ 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'; @@ -74,22 +73,13 @@ describe('ActiveCheckbox', () => { expect(findGlFormCheckbox().vm.$attrs.checked).toBe(true); }); - describe('on checkbox click', () => { - it('switches the form value', async () => { - findInputInCheckbox().trigger('click'); - - await nextTick(); - expect(findGlFormCheckbox().vm.$attrs.checked).toBe(false); - }); - }); - it('emits `toggle-integration-active` event with `true` on mount', () => { expect(wrapper.emitted('toggle-integration-active')[0]).toEqual([true]); }); describe('on checkbox `change` event', () => { - it('emits `toggle-integration-active` event', () => { - findGlFormCheckbox().vm.$emit('change', false); + it('emits `toggle-integration-active` event', async () => { + await findInputInCheckbox().setChecked(false); expect(wrapper.emitted('toggle-integration-active')[1]).toEqual([false]); }); 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 49fbebb9396..6011b3e6edc 100644 --- a/spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js +++ b/spec/frontend/integrations/edit/components/jira_trigger_fields_spec.js @@ -115,9 +115,8 @@ describe('JiraTriggerFields', () => { const checkbox = findIssueTransitionEnabled(); expect(checkbox.element.checked).toBe(false); - checkbox.trigger('click'); + await checkbox.setChecked(true); - await nextTick(); const [radio1, radio2] = findIssueTransitionModeRadios().wrappers; expect(radio1.element.checked).toBe(true); expect(radio2.element.checked).toBe(false); diff --git a/spec/frontend/issues/show/components/incidents/highlight_bar_spec.js b/spec/frontend/issues/show/components/incidents/highlight_bar_spec.js index a4910d63bb5..155ae703e48 100644 --- a/spec/frontend/issues/show/components/incidents/highlight_bar_spec.js +++ b/spec/frontend/issues/show/components/incidents/highlight_bar_spec.js @@ -74,7 +74,7 @@ describe('Highlight Bar', () => { }); it('renders a number of alert events', () => { - expect(wrapper.text()).toContain(alert.eventCount); + expect(wrapper.text()).toContain(alert.eventCount.toString()); }); }); diff --git a/spec/frontend/issues/show/components/incidents/timeline_events_tab_spec.js b/spec/frontend/issues/show/components/incidents/timeline_events_tab_spec.js index 993df59c5fa..7efa6ad8829 100644 --- a/spec/frontend/issues/show/components/incidents/timeline_events_tab_spec.js +++ b/spec/frontend/issues/show/components/incidents/timeline_events_tab_spec.js @@ -89,22 +89,28 @@ describe('TimelineEventsTab', () => { describe('timelineEventsQuery', () => { let mockApollo; - beforeEach(() => { + const setup = () => { mockApollo = createMockApolloProvider(); mountComponent({ mockApollo }); - }); + }; it('should request data', () => { + setup(); + expect(listResponse).toHaveBeenCalled(); }); it('should show the loading state', () => { + setup(); + expect(findEmptyState().exists()).toBe(false); expect(findLoadingSpinner().exists()).toBe(true); }); it('should render the list', async () => { + setup(); await waitForPromises(); + expect(findEmptyState().exists()).toBe(false); expect(findTimelineEventsList().props('timelineEvents')).toHaveLength(3); }); diff --git a/spec/frontend/jobs/components/jobs_container_spec.js b/spec/frontend/jobs/components/jobs_container_spec.js index 1cde72682a2..127570b8184 100644 --- a/spec/frontend/jobs/components/jobs_container_spec.js +++ b/spec/frontend/jobs/components/jobs_container_spec.js @@ -106,7 +106,7 @@ describe('Jobs List block', () => { }); expect(findJob().text()).toBe(job.name); - expect(findJob().text()).not.toContain(job.id); + expect(findJob().text()).not.toContain(job.id.toString()); }); it('renders job id when job name is not available', () => { 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 4e54d2d3a1d..374768c3ee4 100644 --- a/spec/frontend/jobs/components/table/job_table_app_spec.js +++ b/spec/frontend/jobs/components/table/job_table_app_spec.js @@ -6,7 +6,7 @@ import { GlLoadingIcon, } 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 { s__ } from '~/locale'; import createMockApollo from 'helpers/mock_apollo_helper'; @@ -75,17 +75,17 @@ describe('Job table app', () => { }); describe('loading state', () => { - beforeEach(() => { + it('should display skeleton loader when loading', () => { createComponent(); - }); - it('should display skeleton loader when loading', () => { expect(findSkeletonLoader().exists()).toBe(true); expect(findTable().exists()).toBe(false); expect(findLoadingSpinner().exists()).toBe(false); }); it('when switching tabs only the skeleton loader should show', () => { + createComponent(); + findTabs().vm.$emit('fetchJobsByStatus', null); expect(findSkeletonLoader().exists()).toBe(true); @@ -117,15 +117,17 @@ describe('Job table app', () => { }); describe('when infinite scrolling is triggered', () => { - beforeEach(() => { + it('does not display a skeleton loader', () => { triggerInfiniteScroll(); - }); - it('does not display a skeleton loader', () => { expect(findSkeletonLoader().exists()).toBe(false); }); it('handles infinite scrolling by calling fetch more', async () => { + triggerInfiniteScroll(); + + await nextTick(); + const pageSize = 30; expect(findLoadingSpinner().exists()).toBe(true); diff --git a/spec/frontend/lib/utils/navigation_utility_spec.js b/spec/frontend/lib/utils/navigation_utility_spec.js index 632a8904578..6d3a871eb33 100644 --- a/spec/frontend/lib/utils/navigation_utility_spec.js +++ b/spec/frontend/lib/utils/navigation_utility_spec.js @@ -81,8 +81,6 @@ describe('initPrefetchLinks', () => { const mouseOverEvent = new Event('mouseover'); beforeEach(() => { - jest.useFakeTimers(); - jest.spyOn(global, 'setTimeout'); jest.spyOn(newLink, 'removeEventListener'); }); diff --git a/spec/frontend/milestones/components/milestone_combobox_spec.js b/spec/frontend/milestones/components/milestone_combobox_spec.js index afd85fb78ce..a8e3d13dca0 100644 --- a/spec/frontend/milestones/components/milestone_combobox_spec.js +++ b/spec/frontend/milestones/components/milestone_combobox_spec.js @@ -154,9 +154,9 @@ describe('Milestone combobox component', () => { }; describe('initialization behavior', () => { - beforeEach(createComponent); - it('initializes the dropdown with milestones when mounted', () => { + createComponent(); + return waitForRequests().then(() => { expect(projectMilestonesApiCallSpy).toHaveBeenCalledTimes(1); expect(groupMilestonesApiCallSpy).toHaveBeenCalledTimes(1); @@ -164,6 +164,8 @@ describe('Milestone combobox component', () => { }); it('shows a spinner while network requests are in progress', () => { + createComponent(); + expect(findLoadingIcon().exists()).toBe(true); return waitForRequests().then(() => { @@ -172,6 +174,8 @@ describe('Milestone combobox component', () => { }); it('shows additional links', () => { + createComponent(); + const links = wrapper.findAll('[data-testid="milestone-combobox-extra-links"]'); links.wrappers.forEach((item, idx) => { expect(item.text()).toBe(extraLinks[idx].text); diff --git a/spec/frontend/monitoring/components/dashboard_spec.js b/spec/frontend/monitoring/components/dashboard_spec.js index 6c5972e1140..90171cfc65e 100644 --- a/spec/frontend/monitoring/components/dashboard_spec.js +++ b/spec/frontend/monitoring/components/dashboard_spec.js @@ -75,6 +75,7 @@ describe('Dashboard', () => { if (store.dispatch.mockReset) { store.dispatch.mockReset(); } + wrapper.destroy(); }); describe('request information to the server', () => { @@ -569,28 +570,37 @@ describe('Dashboard', () => { const findDraggablePanels = () => wrapper.findAll('.js-draggable-panel'); const findRearrangeButton = () => wrapper.find('.js-rearrange-button'); - beforeEach(async () => { + const setup = async () => { // call original dispatch store.dispatch.mockRestore(); createShallowWrapper({ hasMetrics: true }); setupStoreWithData(store); await nextTick(); - }); + }; + + it('wraps vuedraggable', async () => { + await setup(); - it('wraps vuedraggable', () => { expect(findDraggablePanels().exists()).toBe(true); expect(findDraggablePanels().length).toEqual(metricsDashboardPanelCount); }); - it('is disabled by default', () => { + it('is disabled by default', async () => { + await setup(); + expect(findRearrangeButton().exists()).toBe(false); expect(findEnabledDraggables().length).toBe(0); }); describe('when rearrange is enabled', () => { beforeEach(async () => { - wrapper.setProps({ rearrangePanelsAvailable: true }); + // call original dispatch + store.dispatch.mockRestore(); + + createShallowWrapper({ hasMetrics: true, rearrangePanelsAvailable: true }); + setupStoreWithData(store); + await nextTick(); }); @@ -602,17 +612,18 @@ describe('Dashboard', () => { const findFirstDraggableRemoveButton = () => findDraggablePanels().at(0).find('.js-draggable-remove'); - beforeEach(async () => { + it('it enables draggables', async () => { findRearrangeButton().vm.$emit('click'); await nextTick(); - }); - it('it enables draggables', () => { expect(findRearrangeButton().attributes('pressed')).toBeTruthy(); expect(findEnabledDraggables().wrappers).toEqual(findDraggables().wrappers); }); it('metrics can be swapped', async () => { + findRearrangeButton().vm.$emit('click'); + await nextTick(); + const firstDraggable = findDraggables().at(0); const mockMetrics = [...metricsDashboardViewModel.panelGroups[0].panels]; @@ -624,6 +635,7 @@ describe('Dashboard', () => { firstDraggable.vm.$emit('input', mockMetrics); await nextTick(); + const { panels } = wrapper.vm.dashboard.panelGroups[0]; expect(panels[1].title).toEqual(firstTitle); @@ -631,18 +643,23 @@ describe('Dashboard', () => { }); it('shows a remove button, which removes a panel', async () => { + findRearrangeButton().vm.$emit('click'); + await nextTick(); + expect(findFirstDraggableRemoveButton().find('a').exists()).toBe(true); expect(findDraggablePanels().length).toEqual(metricsDashboardPanelCount); - findFirstDraggableRemoveButton().trigger('click'); + await findFirstDraggableRemoveButton().trigger('click'); - await nextTick(); expect(findDraggablePanels().length).toEqual(metricsDashboardPanelCount - 1); }); it('it disables draggables when clicked again', async () => { findRearrangeButton().vm.$emit('click'); await nextTick(); + + findRearrangeButton().vm.$emit('click'); + await nextTick(); expect(findRearrangeButton().attributes('pressed')).toBeFalsy(); expect(findEnabledDraggables().length).toBe(0); }); diff --git a/spec/frontend/notes/components/notes_app_spec.js b/spec/frontend/notes/components/notes_app_spec.js index acd27dab4eb..36a68118fa7 100644 --- a/spec/frontend/notes/components/notes_app_spec.js +++ b/spec/frontend/notes/components/notes_app_spec.js @@ -44,22 +44,6 @@ describe('note_app', () => { .wrappers.map((node) => (node.is(CommentForm) ? TYPE_COMMENT_FORM : TYPE_NOTES_LIST)); }; - /** - * waits for fetchNotes() to complete - */ - const waitForDiscussionsRequest = () => - new Promise((resolve) => { - const { vm } = wrapper.find(NotesApp); - const unwatch = vm.$watch('isFetching', (isFetching) => { - if (isFetching) { - return; - } - - unwatch(); - resolve(); - }); - }); - beforeEach(() => { $('body').attr('data-page', 'projects:merge_requests:show'); @@ -95,7 +79,7 @@ describe('note_app', () => { axiosMock.onAny().reply(200, []); wrapper = mountComponent(); - return waitForDiscussionsRequest(); + return waitForPromises(); }); afterEach(() => { @@ -129,7 +113,7 @@ describe('note_app', () => { axiosMock.onAny().reply(mockData.getIndividualNoteResponse); wrapper = mountComponent(); - return waitForDiscussionsRequest(); + return waitForPromises(); }); afterEach(() => { @@ -172,7 +156,7 @@ describe('note_app', () => { axiosMock.onAny().reply(mockData.getIndividualNoteResponse); store.state.commentsDisabled = true; wrapper = mountComponent(); - return waitForDiscussionsRequest(); + return waitForPromises(); }); afterEach(() => { @@ -197,7 +181,7 @@ describe('note_app', () => { store.state.isTimelineEnabled = true; wrapper = mountComponent(); - return waitForDiscussionsRequest(); + return waitForPromises(); }); afterEach(() => { @@ -210,14 +194,13 @@ describe('note_app', () => { }); describe('while fetching data', () => { - beforeEach(() => { + beforeEach(async () => { setHTMLFixture('<div class="js-discussions-count"></div>'); - axiosMock.onAny().reply(200, []); wrapper = mountComponent(); }); afterEach(() => { - return waitForDiscussionsRequest().then(() => resetHTMLFixture()); + return waitForPromises().then(() => resetHTMLFixture()); }); it('renders skeleton notes', () => { @@ -241,7 +224,7 @@ describe('note_app', () => { beforeEach(() => { axiosMock.onAny().reply(mockData.getIndividualNoteResponse); wrapper = mountComponent(); - return waitForDiscussionsRequest().then(() => { + return waitForPromises().then(() => { wrapper.find('.js-note-edit').trigger('click'); }); }); @@ -263,7 +246,7 @@ describe('note_app', () => { beforeEach(() => { axiosMock.onAny().reply(mockData.getDiscussionNoteResponse); wrapper = mountComponent(); - return waitForDiscussionsRequest().then(() => { + return waitForPromises().then(() => { wrapper.find('.js-note-edit').trigger('click'); }); }); @@ -286,7 +269,7 @@ describe('note_app', () => { beforeEach(() => { axiosMock.onAny().reply(mockData.getIndividualNoteResponse); wrapper = mountComponent(); - return waitForDiscussionsRequest(); + return waitForPromises(); }); it('should render markdown docs url', () => { @@ -308,7 +291,7 @@ describe('note_app', () => { beforeEach(() => { axiosMock.onAny().reply(mockData.getIndividualNoteResponse); wrapper = mountComponent(); - return waitForDiscussionsRequest(); + return waitForPromises(); }); it('should render markdown docs url', async () => { @@ -336,7 +319,7 @@ describe('note_app', () => { beforeEach(() => { axiosMock.onAny().reply(200, []); wrapper = mountComponent(); - return waitForDiscussionsRequest(); + return waitForPromises(); }); it('dispatches toggleAward after toggleAward event', () => { @@ -372,7 +355,7 @@ describe('note_app', () => { beforeEach(() => { axiosMock.onAny().reply(mockData.getIndividualNoteResponse); wrapper = mountComponent(); - return waitForDiscussionsRequest(); + return waitForPromises(); }); it('should listen hashchange event', () => { diff --git a/spec/frontend/notes/stores/actions_spec.js b/spec/frontend/notes/stores/actions_spec.js index bf69d24bcb9..02b27eca196 100644 --- a/spec/frontend/notes/stores/actions_spec.js +++ b/spec/frontend/notes/stores/actions_spec.js @@ -15,6 +15,7 @@ import * as utils from '~/notes/stores/utils'; import updateIssueLockMutation from '~/sidebar/components/lock/mutations/update_issue_lock.mutation.graphql'; import updateMergeRequestLockMutation from '~/sidebar/components/lock/mutations/update_merge_request_lock.mutation.graphql'; import mrWidgetEventHub from '~/vue_merge_request_widget/event_hub'; +import waitForPromises from 'helpers/wait_for_promises'; import { resetStore } from '../helpers'; import { discussionMock, @@ -254,9 +255,7 @@ describe('Actions Notes Store', () => { jest.advanceTimersByTime(time); } - return new Promise((resolve) => { - requestAnimationFrame(resolve); - }); + return waitForPromises(); }; const advanceXMoreIntervals = async (number) => { const timeoutLength = pollInterval * number; @@ -365,7 +364,6 @@ describe('Actions Notes Store', () => { }); it('hides the error display if it exists on success', async () => { - jest.mock(); failureMock(); await startPolling(); @@ -668,7 +666,6 @@ describe('Actions Notes Store', () => { describe('updateOrCreateNotes', () => { it('Prevents `fetchDiscussions` being called multiple times within time limit', () => { - jest.useFakeTimers(); const note = { id: 1234, type: notesConstants.DIFF_NOTE }; const getters = { notesById: {} }; state = { discussions: [note], notesData: { discussionsPath: '' } }; 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 fe4a2c06f1c..f2901148e17 100644 --- a/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js +++ b/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js @@ -38,6 +38,8 @@ const dummyGon = { let originalGon; const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups/${dummyGrouptId}/dependency_proxy/cache`; +Vue.use(VueApollo); + describe('DependencyProxyApp', () => { let wrapper; let apolloProvider; @@ -51,8 +53,6 @@ describe('DependencyProxyApp', () => { }; function createComponent({ provide = provideDefaults } = {}) { - Vue.use(VueApollo); - const requestHandlers = [[getDependencyProxyDetailsQuery, resolver]]; apolloProvider = createMockApollo(requestHandlers); @@ -103,19 +103,21 @@ describe('DependencyProxyApp', () => { describe('when the dependency proxy is available', () => { describe('when is loading', () => { - beforeEach(() => { + it('renders the skeleton loader', () => { createComponent(); - }); - it('renders the skeleton loader', () => { expect(findSkeletonLoader().exists()).toBe(true); }); it('does not render a form group with label', () => { + createComponent(); + expect(findFormGroup().exists()).toBe(false); }); it('does not show the main section', () => { + createComponent(); + expect(findMainArea().exists()).toBe(false); }); }); @@ -215,23 +217,26 @@ describe('DependencyProxyApp', () => { }); describe('triggering page event on list', () => { - beforeEach(async () => { + it('re-renders the skeleton loader', async () => { findManifestList().vm.$emit('next-page'); - await nextTick(); - }); - it('re-renders the skeleton loader', () => { expect(findSkeletonLoader().exists()).toBe(true); }); - it('renders form group with label', () => { + it('renders form group with label', async () => { + findManifestList().vm.$emit('next-page'); + await nextTick(); + expect(findFormGroup().attributes('label')).toEqual( expect.stringMatching(DependencyProxyApp.i18n.proxyImagePrefix), ); }); - it('does not show the main section', () => { + it('does not show the main section', async () => { + findManifestList().vm.$emit('next-page'); + await nextTick(); + expect(findMainArea().exists()).toBe(false); }); }); diff --git a/spec/frontend/packages_and_registries/settings/group/components/duplicates_settings_spec.js b/spec/frontend/packages_and_registries/settings/group/components/duplicates_settings_spec.js index 21da6ae541b..3eecdeb5b1f 100644 --- a/spec/frontend/packages_and_registries/settings/group/components/duplicates_settings_spec.js +++ b/spec/frontend/packages_and_registries/settings/group/components/duplicates_settings_spec.js @@ -44,7 +44,7 @@ describe('Duplicates Settings', () => { expect(findToggle().exists()).toBe(true); expect(findToggle().props()).toMatchObject({ label: DUPLICATES_TOGGLE_LABEL, - value: defaultProps.duplicatesAllowed, + value: !defaultProps.duplicatesAllowed, }); }); @@ -54,7 +54,7 @@ describe('Duplicates Settings', () => { findToggle().vm.$emit('change', false); expect(wrapper.emitted('update')).toStrictEqual([ - [{ [defaultProps.modelNames.allowed]: false }], + [{ [defaultProps.modelNames.allowed]: 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 efbfd83a071..2a0fde45384 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 @@ -400,10 +400,6 @@ describe('ForkForm component', () => { ); }; - beforeEach(() => { - setupComponent(); - }); - const selectedMockNamespaceIndex = 1; const namespaceId = MOCK_NAMESPACES_RESPONSE[selectedMockNamespaceIndex].id; @@ -425,10 +421,14 @@ describe('ForkForm component', () => { it('does not make POST request', async () => { jest.spyOn(axios, 'post'); + setupComponent(); + expect(axios.post).not.toHaveBeenCalled(); }); it('does not redirect the current page', async () => { + setupComponent(); + await submitForm(); expect(urlUtility.redirectTo).not.toHaveBeenCalled(); @@ -452,13 +452,10 @@ describe('ForkForm component', () => { }); describe('with valid form', () => { - beforeEach(() => { - fillForm(); - }); - it('make POST request with project param', async () => { jest.spyOn(axios, 'post'); + setupComponent(); await submitForm(); const { @@ -486,6 +483,7 @@ describe('ForkForm component', () => { const webUrl = `new/fork-project`; jest.spyOn(axios, 'post').mockResolvedValue({ data: { web_url: webUrl } }); + setupComponent(); await submitForm(); expect(urlUtility.redirectTo).toHaveBeenCalledWith(webUrl); @@ -496,6 +494,7 @@ describe('ForkForm component', () => { jest.spyOn(axios, 'post').mockRejectedValue(dummyError); + setupComponent(); await submitForm(); expect(urlUtility.redirectTo).not.toHaveBeenCalled(); 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 d5b4b3c22d8..99df5b58d90 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 @@ -31,10 +31,10 @@ describe('Interval Pattern Input Component', () => { wrapper.findAll('input[type="radio"]').wrappers.find((x) => x.element.checked); const findIcon = () => wrapper.findComponent(GlIcon); const findSelectedRadioKey = () => findSelectedRadio()?.attributes('data-testid'); - const selectEveryDayRadio = () => findEveryDayRadio().trigger('click'); - const selectEveryWeekRadio = () => findEveryWeekRadio().trigger('click'); - const selectEveryMonthRadio = () => findEveryMonthRadio().trigger('click'); - const selectCustomRadio = () => findCustomRadio().trigger('click'); + const selectEveryDayRadio = () => findEveryDayRadio().setChecked(true); + const selectEveryWeekRadio = () => findEveryWeekRadio().setChecked(true); + const selectEveryMonthRadio = () => findEveryMonthRadio().setChecked(true); + const selectCustomRadio = () => findCustomRadio().setChecked(true); const createWrapper = (props = {}, data = {}) => { if (wrapper) { diff --git a/spec/frontend/pipelines/components/jobs/failed_jobs_app_spec.js b/spec/frontend/pipelines/components/jobs/failed_jobs_app_spec.js index 3b5632a8a4e..bfbb5f934b9 100644 --- a/spec/frontend/pipelines/components/jobs/failed_jobs_app_spec.js +++ b/spec/frontend/pipelines/components/jobs/failed_jobs_app_spec.js @@ -49,15 +49,15 @@ describe('Failed Jobs App', () => { }); describe('loading spinner', () => { - beforeEach(() => { + it('displays loading spinner when fetching failed jobs', () => { createComponent(resolverSpy); - }); - it('displays loading spinner when fetching failed jobs', () => { expect(findLoadingSpinner().exists()).toBe(true); }); it('hides loading spinner after the failed jobs have been fetched', async () => { + createComponent(resolverSpy); + await waitForPromises(); expect(findLoadingSpinner().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 81e19a6c221..89b6f764b2f 100644 --- a/spec/frontend/pipelines/components/jobs/jobs_app_spec.js +++ b/spec/frontend/pipelines/components/jobs/jobs_app_spec.js @@ -50,20 +50,23 @@ describe('Jobs app', () => { }); describe('loading spinner', () => { - beforeEach(async () => { + const setup = async () => { createComponent(resolverSpy); await waitForPromises(); triggerInfiniteScroll(); - }); + }; + + it('displays loading spinner when fetching more jobs', async () => { + await setup(); - it('displays loading spinner when fetching more jobs', () => { expect(findLoadingSpinner().exists()).toBe(true); expect(findSkeletonLoader().exists()).toBe(false); }); it('hides loading spinner after jobs have been fetched', async () => { + await setup(); await waitForPromises(); expect(findLoadingSpinner().exists()).toBe(false); diff --git a/spec/frontend/pipelines/graph/graph_view_selector_spec.js b/spec/frontend/pipelines/graph/graph_view_selector_spec.js index f574f4dccc5..4e79c7e73cc 100644 --- a/spec/frontend/pipelines/graph/graph_view_selector_spec.js +++ b/spec/frontend/pipelines/graph/graph_view_selector_spec.js @@ -91,7 +91,6 @@ describe('the graph view selector component', () => { describe('events', () => { beforeEach(() => { - jest.useFakeTimers(); createComponent({ mountFn: mount, props: { diff --git a/spec/frontend/pipelines/graph/job_group_dropdown_spec.js b/spec/frontend/pipelines/graph/job_group_dropdown_spec.js index 5d8e70bac31..d8afb33e148 100644 --- a/spec/frontend/pipelines/graph/job_group_dropdown_spec.js +++ b/spec/frontend/pipelines/graph/job_group_dropdown_spec.js @@ -79,7 +79,7 @@ describe('job group dropdown component', () => { it('renders button with group name and size', () => { expect(findButton().text()).toContain(group.name); - expect(findButton().text()).toContain(group.size); + expect(findButton().text()).toContain(group.size.toString()); }); it('renders dropdown with jobs', () => { diff --git a/spec/frontend/pipelines/graph/linked_pipeline_spec.js b/spec/frontend/pipelines/graph/linked_pipeline_spec.js index fd97c2dbe77..cdeaa0db61d 100644 --- a/spec/frontend/pipelines/graph/linked_pipeline_spec.js +++ b/spec/frontend/pipelines/graph/linked_pipeline_spec.js @@ -103,7 +103,7 @@ describe('Linked pipeline', () => { expect(findCardTooltip().text()).toContain(mockPipeline.project.name); expect(findCardTooltip().text()).toContain(mockPipeline.status.label); expect(findCardTooltip().text()).toContain(mockPipeline.sourceJob.name); - expect(findCardTooltip().text()).toContain(mockPipeline.id); + expect(findCardTooltip().text()).toContain(mockPipeline.id.toString()); }); it('should display multi-project label when pipeline project id is not the same as triggered pipeline project id', () => { diff --git a/spec/frontend/pipelines/pipelines_spec.js b/spec/frontend/pipelines/pipelines_spec.js index de9f394db43..ad6d650670a 100644 --- a/spec/frontend/pipelines/pipelines_spec.js +++ b/spec/frontend/pipelines/pipelines_spec.js @@ -665,7 +665,6 @@ describe('Pipelines', () => { it('stops polling & restarts polling', async () => { findStagesDropdownToggle().trigger('click'); - await waitForPromises(); expect(cancelMock).not.toHaveBeenCalled(); diff --git a/spec/frontend/protected_branches/protected_branch_edit_spec.js b/spec/frontend/protected_branches/protected_branch_edit_spec.js index d842e00d850..6ef1b58a956 100644 --- a/spec/frontend/protected_branches/protected_branch_edit_spec.js +++ b/spec/frontend/protected_branches/protected_branch_edit_spec.js @@ -114,27 +114,30 @@ describe('ProtectedBranchEdit', () => { }); describe('when clicked', () => { - beforeEach(() => { + beforeEach(async () => { mock.onPatch(TEST_URL, { protected_branch: { [patchParam]: true } }).replyOnce(200, {}); - - toggle.click(); }); - it('checks and disables button', () => { + it('checks and disables button', async () => { + await toggle.click(); + expect(toggle).toHaveClass(IS_CHECKED_CLASS); expect(toggle.querySelector(IS_LOADING_SELECTOR)).not.toBe(null); expect(toggle).toHaveClass(IS_DISABLED_CLASS); }); - it('sends update to BE', () => - axios.waitForAll().then(() => { - // Args are asserted in the `.onPatch` call - expect(mock.history.patch).toHaveLength(1); + it('sends update to BE', async () => { + await toggle.click(); + + await axios.waitForAll(); - expect(toggle).not.toHaveClass(IS_DISABLED_CLASS); - expect(toggle.querySelector(IS_LOADING_SELECTOR)).toBe(null); - expect(createFlash).not.toHaveBeenCalled(); - })); + // Args are asserted in the `.onPatch` call + expect(mock.history.patch).toHaveLength(1); + + expect(toggle).not.toHaveClass(IS_DISABLED_CLASS); + expect(toggle.querySelector(IS_LOADING_SELECTOR)).toBe(null); + expect(createFlash).not.toHaveBeenCalled(); + }); }); describe('when clicked and BE error', () => { @@ -143,10 +146,11 @@ describe('ProtectedBranchEdit', () => { toggle.click(); }); - it('flashes error', () => - axios.waitForAll().then(() => { - expect(createFlash).toHaveBeenCalled(); - })); + it('flashes error', async () => { + await axios.waitForAll(); + + expect(createFlash).toHaveBeenCalled(); + }); }); }); }); diff --git a/spec/frontend/ref/components/ref_selector_spec.js b/spec/frontend/ref/components/ref_selector_spec.js index e1fc60f0d92..882cb2c1199 100644 --- a/spec/frontend/ref/components/ref_selector_spec.js +++ b/spec/frontend/ref/components/ref_selector_spec.js @@ -162,9 +162,9 @@ describe('Ref selector component', () => { }); describe('initialization behavior', () => { - beforeEach(createComponent); - it('initializes the dropdown with branches and tags when mounted', () => { + createComponent(); + return waitForRequests().then(() => { expect(branchesApiCallSpy).toHaveBeenCalledTimes(1); expect(tagsApiCallSpy).toHaveBeenCalledTimes(1); @@ -173,6 +173,8 @@ describe('Ref selector component', () => { }); it('shows a spinner while network requests are in progress', () => { + createComponent(); + expect(findLoadingIcon().exists()).toBe(true); return waitForRequests().then(() => { diff --git a/spec/frontend/reports/components/grouped_issues_list_spec.js b/spec/frontend/reports/components/grouped_issues_list_spec.js index c6eebf05dd7..95ef0bcbcc7 100644 --- a/spec/frontend/reports/components/grouped_issues_list_spec.js +++ b/spec/frontend/reports/components/grouped_issues_list_spec.js @@ -17,7 +17,6 @@ describe('Grouped Issues List', () => { afterEach(() => { wrapper.destroy(); - wrapper = null; }); it('renders a smart virtual list with the correct props', () => { @@ -35,13 +34,15 @@ describe('Grouped Issues List', () => { }); describe('without data', () => { - beforeEach(createComponent); + beforeEach(() => { + createComponent(); + }); it.each(['unresolved', 'resolved'])('does not a render a header for %s issues', (issueName) => { expect(findHeading(issueName).exists()).toBe(false); }); - it.each('resolved', 'unresolved')('does not render report items for %s issues', () => { + it.each(['resolved', 'unresolved'])('does not render report items for %s issues', () => { expect(wrapper.find(ReportItem).exists()).toBe(false); }); }); diff --git a/spec/frontend/repository/components/table/row_spec.js b/spec/frontend/repository/components/table/row_spec.js index 628ac9270cd..13b09e57473 100644 --- a/spec/frontend/repository/components/table/row_spec.js +++ b/spec/frontend/repository/components/table/row_spec.js @@ -244,8 +244,6 @@ describe('Repository table row component', () => { }); describe('row visibility', () => { - beforeAll(() => jest.useFakeTimers()); - beforeEach(() => { factory({ id: '1', @@ -260,12 +258,13 @@ describe('Repository table row component', () => { afterAll(() => jest.useRealTimers()); it('emits a `row-appear` event', async () => { + const setTimeoutSpy = jest.spyOn(global, 'setTimeout'); findIntersectionObserver().vm.$emit('appear'); jest.runAllTimers(); - expect(setTimeout).toHaveBeenCalledTimes(1); - expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), ROW_APPEAR_DELAY); + expect(setTimeoutSpy).toHaveBeenCalledTimes(1); + expect(setTimeoutSpy).toHaveBeenLastCalledWith(expect.any(Function), ROW_APPEAR_DELAY); expect(vm.emitted('row-appear')).toEqual([[123]]); }); }); diff --git a/spec/frontend/runner/admin_runners/admin_runners_app_spec.js b/spec/frontend/runner/admin_runners/admin_runners_app_spec.js index 42a951f93a9..2d3f19fe12a 100644 --- a/spec/frontend/runner/admin_runners/admin_runners_app_spec.js +++ b/spec/frontend/runner/admin_runners/admin_runners_app_spec.js @@ -14,6 +14,7 @@ import { s__ } from '~/locale'; import { getIdFromGraphQLId } from '~/graphql_shared/utils'; import { updateHistory } from '~/lib/utils/url_utility'; +import { upgradeStatusTokenConfig } from 'ee_else_ce/runner/components/search_tokens/upgrade_status_token_config'; import { createLocalState } from '~/runner/graphql/list/local_state'; import AdminRunnersApp from '~/runner/admin_runners/admin_runners_app.vue'; import RunnerTypeTabs from '~/runner/components/runner_type_tabs.vue'; @@ -40,10 +41,9 @@ import { STATUS_STALE, RUNNER_PAGE_SIZE, } from '~/runner/constants'; -import adminRunnersQuery from '~/runner/graphql/list/admin_runners.query.graphql'; +import adminRunnersQuery from 'ee_else_ce/runner/graphql/list/admin_runners.query.graphql'; import adminRunnersCountQuery from '~/runner/graphql/list/admin_runners_count.query.graphql'; import { captureException } from '~/runner/sentry_utils'; -import FilteredSearch from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue'; import { runnersData, @@ -86,7 +86,6 @@ describe('AdminRunnersApp', () => { const findRunnerPagination = () => extendedWrapper(wrapper.findComponent(RunnerPagination)); const findRunnerPaginationNext = () => findRunnerPagination().findByLabelText('Go to next page'); const findRunnerFilteredSearchBar = () => wrapper.findComponent(RunnerFilteredSearchBar); - const findFilteredSearch = () => wrapper.findComponent(FilteredSearch); const createComponent = ({ props = {}, @@ -207,9 +206,9 @@ describe('AdminRunnersApp', () => { }); it('sets tokens in the filtered search', () => { - createComponent({ mountFn: mountExtended }); + createComponent(); - expect(findFilteredSearch().props('tokens')).toEqual([ + expect(findRunnerFilteredSearchBar().props('tokens')).toEqual([ expect.objectContaining({ type: PARAM_KEY_PAUSED, options: expect.any(Array), @@ -222,6 +221,7 @@ describe('AdminRunnersApp', () => { type: PARAM_KEY_TAG, recentSuggestionsStorageKey: `${ADMIN_FILTERED_SEARCH_NAMESPACE}-recent-tags`, }), + upgradeStatusTokenConfig, ]); }); diff --git a/spec/frontend/runner/components/runner_pause_button_spec.js b/spec/frontend/runner/components/runner_pause_button_spec.js index 9ebb30b6ed7..79f9183d136 100644 --- a/spec/frontend/runner/components/runner_pause_button_spec.js +++ b/spec/frontend/runner/components/runner_pause_button_spec.js @@ -1,4 +1,4 @@ -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import { GlButton } from '@gitlab/ui'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; @@ -115,15 +115,20 @@ describe('RunnerPauseButton', () => { }); describe(`Immediately after the ${icon} button is clicked`, () => { - beforeEach(async () => { + const setup = async () => { findBtn().vm.$emit('click'); - }); + await nextTick(); + }; it('The button has a loading state', async () => { + await setup(); + expect(findBtn().props('loading')).toBe(true); }); it('The stale tooltip is removed', async () => { + await setup(); + expect(getTooltip()).toBe(''); }); }); @@ -237,15 +242,20 @@ describe('RunnerPauseButton', () => { }); describe('Immediately after the button is clicked', () => { - beforeEach(async () => { + const setup = async () => { findBtn().vm.$emit('click'); - }); + await nextTick(); + }; it('The button has a loading state', async () => { + await setup(); + expect(findBtn().props('loading')).toBe(true); }); it('The stale tooltip is removed', async () => { + await setup(); + expect(getTooltip()).toBe(''); }); }); diff --git a/spec/frontend/runner/components/search_tokens/tag_token_spec.js b/spec/frontend/runner/components/search_tokens/tag_token_spec.js index 52557ff716d..22f0561ca5f 100644 --- a/spec/frontend/runner/components/search_tokens/tag_token_spec.js +++ b/spec/frontend/runner/components/search_tokens/tag_token_spec.js @@ -134,8 +134,6 @@ describe('TagToken', () => { describe('when the users filters suggestions', () => { beforeEach(async () => { findGlFilteredSearchToken().vm.$emit('input', { data: mockSearchTerm }); - - jest.runAllTimers(); }); it('requests filtered tags suggestions', async () => { @@ -145,6 +143,7 @@ describe('TagToken', () => { }); it('shows the loading icon', async () => { + findGlFilteredSearchToken().vm.$emit('input', { data: mockSearchTerm }); await nextTick(); expect(findGlLoadingIcon().exists()).toBe(true); 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 3249f54d1be..4c011d5852d 100644 --- a/spec/frontend/runner/group_runners/group_runners_app_spec.js +++ b/spec/frontend/runner/group_runners/group_runners_app_spec.js @@ -43,7 +43,6 @@ import getGroupRunnersQuery from '~/runner/graphql/list/group_runners.query.grap import getGroupRunnersCountQuery from '~/runner/graphql/list/group_runners_count.query.graphql'; import GroupRunnersApp from '~/runner/group_runners/group_runners_app.vue'; import { captureException } from '~/runner/sentry_utils'; -import FilteredSearch from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue'; import { groupRunnersData, groupRunnersDataPaginated, @@ -85,7 +84,6 @@ describe('GroupRunnersApp', () => { const findRunnerPagination = () => extendedWrapper(wrapper.findComponent(RunnerPagination)); const findRunnerPaginationNext = () => findRunnerPagination().findByLabelText('Go to next page'); const findRunnerFilteredSearchBar = () => wrapper.findComponent(RunnerFilteredSearchBar); - const findFilteredSearch = () => wrapper.findComponent(FilteredSearch); const createComponent = ({ props = {}, mountFn = shallowMountExtended, ...options } = {}) => { const handlers = [ @@ -186,9 +184,9 @@ describe('GroupRunnersApp', () => { }); it('sets tokens in the filtered search', () => { - createComponent({ mountFn: mountExtended }); + createComponent(); - const tokens = findFilteredSearch().props('tokens'); + const tokens = findRunnerFilteredSearchBar().props('tokens'); expect(tokens).toEqual([ expect.objectContaining({ diff --git a/spec/frontend/runner/runner_search_utils_spec.js b/spec/frontend/runner/runner_search_utils_spec.js index 23bf80cb875..6f954143ab1 100644 --- a/spec/frontend/runner/runner_search_utils_spec.js +++ b/spec/frontend/runner/runner_search_utils_spec.js @@ -5,7 +5,7 @@ import { fromSearchToUrl, fromSearchToVariables, isSearchFiltered, -} from '~/runner/runner_search_utils'; +} from 'ee_else_ce/runner/runner_search_utils'; import { mockSearchExamples } from './mock_data'; describe('search_params.js', () => { diff --git a/spec/frontend/security_configuration/components/training_provider_list_spec.js b/spec/frontend/security_configuration/components/training_provider_list_spec.js index 5632b2b9c2c..184c16fda6e 100644 --- a/spec/frontend/security_configuration/components/training_provider_list_spec.js +++ b/spec/frontend/security_configuration/components/training_provider_list_spec.js @@ -36,7 +36,6 @@ import { testProjectPath, testProviderIds, testProviderName, - tempProviderLogos, } from '../mock_data'; Vue.use(VueApollo); @@ -54,6 +53,31 @@ const TEST_TRAINING_PROVIDERS_ALL_ENABLED = getSecurityTrainingProvidersData({ }); const TEST_TRAINING_PROVIDERS_DEFAULT = TEST_TRAINING_PROVIDERS_ALL_DISABLED; +const TEMP_PROVIDER_LOGOS = { + Kontra: { + svg: '<svg>Kontra</svg>', + }, + 'Secure Code Warrior': { + svg: '<svg>Secure Code Warrior</svg>', + }, +}; +jest.mock('~/security_configuration/components/constants', () => { + return { + TEMP_PROVIDER_URLS: jest.requireActual('~/security_configuration/components/constants') + .TEMP_PROVIDER_URLS, + // NOTE: Jest hoists all mocks to the top so we can't use TEMP_PROVIDER_LOGOS + // here directly. + TEMP_PROVIDER_LOGOS: { + Kontra: { + svg: '<svg>Kontra</svg>', + }, + 'Secure Code Warrior': { + svg: '<svg>Secure Code Warrior</svg>', + }, + }, + }; +}); + describe('TrainingProviderList component', () => { let wrapper; let apolloProvider; @@ -217,7 +241,6 @@ describe('TrainingProviderList component', () => { describe('provider logo', () => { beforeEach(async () => { - wrapper.vm.$options.TEMP_PROVIDER_LOGOS = tempProviderLogos; await waitForQueryToBeLoaded(); }); @@ -231,9 +254,9 @@ describe('TrainingProviderList component', () => { expect(findLogos().at(provider).attributes('role')).toBe('presentation'); }); - it.each(providerIndexArray)('renders the svg content for provider %s', (provider) => { + it.each(providerIndexArray)('renders the svg content for provider %s', async (provider) => { expect(findLogos().at(provider).html()).toContain( - tempProviderLogos[testProviderName[provider]].svg, + TEMP_PROVIDER_LOGOS[testProviderName[provider]].svg, ); }); }); @@ -482,7 +505,7 @@ describe('TrainingProviderList component', () => { ${'backend error'} | ${jest.fn().mockReturnValue(dismissUserCalloutErrorResponse)} ${'network error'} | ${jest.fn().mockRejectedValue()} `('when dismissing the callout and a "$errorType" happens', ({ mutationHandler }) => { - beforeEach(async () => { + it('logs the error to sentry', async () => { jest.spyOn(Sentry, 'captureException').mockImplementation(); createApolloProvider({ @@ -500,9 +523,7 @@ describe('TrainingProviderList component', () => { await waitForQueryToBeLoaded(); toggleFirstProvider(); - }); - it('logs the error to sentry', async () => { expect(Sentry.captureException).not.toHaveBeenCalled(); await waitForMutationToBeLoaded(); diff --git a/spec/frontend/security_configuration/mock_data.js b/spec/frontend/security_configuration/mock_data.js index 18a480bf082..2fe3b59cea3 100644 --- a/spec/frontend/security_configuration/mock_data.js +++ b/spec/frontend/security_configuration/mock_data.js @@ -100,14 +100,3 @@ export const updateSecurityTrainingProvidersErrorResponse = { }, }, }; - -// Will remove once this issue is resolved where the svg path will be available in the GraphQL query -// https://gitlab.com/gitlab-org/gitlab/-/issues/346899 -export const tempProviderLogos = { - [testProviderName[0]]: { - svg: `<svg>${[testProviderName[0]]}</svg>`, - }, - [testProviderName[1]]: { - svg: `<svg>${[testProviderName[1]]}</svg>`, - }, -}; diff --git a/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js b/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js index 3ddd41c0bd4..8ebd2dabfc2 100644 --- a/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js +++ b/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js @@ -107,6 +107,7 @@ describe('SidebarDropdownWidget', () => { currentMilestoneSpy = jest.fn().mockResolvedValue(noCurrentMilestoneResponse), } = {}) => { Vue.use(VueApollo); + mockApollo = createMockApollo([ [projectMilestonesQuery, projectMilestonesSpy], [projectIssueMilestoneQuery, currentMilestoneSpy], @@ -415,11 +416,9 @@ describe('SidebarDropdownWidget', () => { describe('when currentAttribute is not equal to attribute id', () => { describe('when update is successful', () => { - beforeEach(() => { + it('calls setIssueAttribute mutation', () => { findDropdownItemWithText(mockMilestone2.title).vm.$emit('click'); - }); - it('calls setIssueAttribute mutation', () => { expect(milestoneMutationSpy).toHaveBeenCalledWith({ iid: mockIssue.iid, attributeId: getIdFromGraphQLId(mockMilestone2.id), @@ -428,6 +427,8 @@ describe('SidebarDropdownWidget', () => { }); it('sets the value returned from the mutation to currentAttribute', async () => { + findDropdownItemWithText(mockMilestone2.title).vm.$emit('click'); + await nextTick(); expect(findSelectedAttribute().text()).toBe(mockMilestone2.title); }); }); diff --git a/spec/frontend/tracking/tracking_spec.js b/spec/frontend/tracking/tracking_spec.js index 08da3a9a465..4871644d99f 100644 --- a/spec/frontend/tracking/tracking_spec.js +++ b/spec/frontend/tracking/tracking_spec.js @@ -412,7 +412,7 @@ describe('Tracking', () => { Tracking.setAnonymousUrls(); expect(snowplowSpy).not.toHaveBeenCalledWith('setReferrerUrl', testUrl); - expect(localStorage.getItem(URLS_CACHE_STORAGE_KEY)).not.toContain(oldTimestamp); + expect(localStorage.getItem(URLS_CACHE_STORAGE_KEY)).not.toContain(oldTimestamp.toString()); }); }); }); diff --git a/spec/frontend/vue_mr_widget/deployment/deployment_action_button_spec.js b/spec/frontend/vue_mr_widget/deployment/deployment_action_button_spec.js index 8c5036e35f6..7e7438bcc0f 100644 --- a/spec/frontend/vue_mr_widget/deployment/deployment_action_button_spec.js +++ b/spec/frontend/vue_mr_widget/deployment/deployment_action_button_spec.js @@ -60,7 +60,7 @@ describe('Deployment action button', () => { it('renders slot and icon prop correctly', () => { expect(wrapper.find(GlIcon).exists()).toBe(true); - expect(wrapper.text()).toContain(actionButtonMocks[DEPLOYING]); + expect(wrapper.text()).toContain(actionButtonMocks[DEPLOYING].toString()); }); }); diff --git a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js index 1b93d13f3f2..8a3680a5358 100644 --- a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js +++ b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js @@ -43,6 +43,13 @@ jest.mock('~/smart_interval'); jest.mock('~/lib/utils/favicon'); +jest.mock('@sentry/browser', () => ({ + setExtra: jest.fn(), + setExtras: jest.fn(), + captureMessage: jest.fn(), + captureException: jest.fn(), +})); + Vue.use(VueApollo); describe('MrWidgetOptions', () => { @@ -67,24 +74,16 @@ describe('MrWidgetOptions', () => { afterEach(() => { mock.restore(); wrapper.destroy(); - wrapper = null; gl.mrWidgetData = {}; gon.features = {}; }); - const createComponent = (mrData = mockData, options = {}, glFeatures = {}) => { - if (wrapper) { - wrapper.destroy(); - } - + const createComponent = (mrData = mockData, options = {}) => { wrapper = mount(MrWidgetOptions, { propsData: { mrData: { ...mrData }, }, - provide: { - glFeatures, - }, ...options, }); @@ -522,7 +521,7 @@ describe('MrWidgetOptions', () => { describe('rendering relatedLinks', () => { beforeEach(() => { - createComponent({ + return createComponent({ ...mockData, issues_links: { closing: ` @@ -532,8 +531,10 @@ describe('MrWidgetOptions', () => { `, }, }); + }); - return nextTick(); + afterEach(() => { + wrapper.destroy(); }); it('renders if there are relatedLinks', () => { @@ -876,8 +877,8 @@ describe('MrWidgetOptions', () => { }); describe('given feature flag is enabled', () => { - beforeEach(() => { - createComponent(); + beforeEach(async () => { + await createComponent(); wrapper.vm.mr.hasCI = false; }); @@ -931,8 +932,6 @@ describe('MrWidgetOptions', () => { }); afterEach(() => { - pollRequest.mockRestore(); - registeredExtensions.extensions = []; }); @@ -984,16 +983,14 @@ describe('MrWidgetOptions', () => { describe('expansion', () => { it('hides collapse button', async () => { registerExtension(workingExtension(false)); - createComponent(); - await waitForPromises(); + await createComponent(); expect(findExtensionToggleButton().exists()).toBe(false); }); it('shows collapse button', async () => { registerExtension(workingExtension(true)); - createComponent(); - await waitForPromises(); + await createComponent(); expect(findExtensionToggleButton().exists()).toBe(true); }); @@ -1011,17 +1008,7 @@ describe('MrWidgetOptions', () => { }); afterEach(() => { - pollRequest.mockRestore(); - registeredExtensions.extensions = []; - - // Clear all left-over timeouts that may be registered in the poll class - let id = window.setTimeout(() => {}, 0); - - while (id > 0) { - window.clearTimeout(id); - id -= 1; - } }); describe('success - multi polling', () => { @@ -1072,27 +1059,10 @@ describe('MrWidgetOptions', () => { describe('success', () => { it('does not make additional requests after poll is successful', async () => { registerExtension(pollingExtension); - await createComponent(); - // called two times due to parent component polling (mount) and extension polling - expect(pollRequest).toHaveBeenCalledTimes(2); - }); - it('keeps polling when poll-interval header is provided', async () => { - registerExtension({ - ...pollingExtension, - methods: { - ...pollingExtension.methods, - fetchCollapsedData() { - return Promise.resolve({ - data: {}, - headers: { 'poll-interval': 1 }, - status: 204, - }); - }, - }, - }); await createComponent(); - expect(findWidgetTestExtension().html()).toContain('Test extension loading...'); + + expect(pollRequest).toHaveBeenCalledTimes(6); }); }); @@ -1100,9 +1070,7 @@ describe('MrWidgetOptions', () => { it('sets data when polling is complete', async () => { registerExtension(pollingFullDataExtension); - createComponent(); - - await waitForPromises(); + await createComponent(); api.trackRedisHllUserEvent.mockClear(); api.trackRedisCounterEvent.mockClear(); @@ -1128,62 +1096,44 @@ describe('MrWidgetOptions', () => { }); describe('error', () => { - let captureException; - - beforeEach(() => { - captureException = jest.spyOn(Sentry, 'captureException'); - + it('does not make additional requests after poll has failed', async () => { registerExtension(pollingErrorExtension); + await createComponent(); - createComponent(); + expect(pollRequest).toHaveBeenCalledTimes(6); }); - it('does not make additional requests after poll has failed', () => { - // called two times due to parent component polling (mount) and extension polling - expect(pollRequest).toHaveBeenCalledTimes(2); - }); + it('captures sentry error and displays error when poll has failed', async () => { + registerExtension(pollingErrorExtension); + await createComponent(); - it('captures sentry error and displays error when poll has failed', () => { - expect(captureException).toHaveBeenCalledTimes(1); - expect(captureException).toHaveBeenCalledWith(new Error('Fetch error')); + expect(Sentry.captureException).toHaveBeenCalledTimes(5); + expect(Sentry.captureException).toHaveBeenCalledWith(new Error('Fetch error')); expect(wrapper.findComponent(StatusIcon).props('iconName')).toBe('failed'); }); }); }); describe('mock extension errors', () => { - let captureException; - - const itHandlesTheException = () => { - expect(captureException).toHaveBeenCalledTimes(1); - expect(captureException).toHaveBeenCalledWith(new Error('Fetch error')); - expect(wrapper.findComponent(StatusIcon).props('iconName')).toBe('failed'); - }; - - beforeEach(() => { - captureException = jest.spyOn(Sentry, 'captureException'); - }); - afterEach(() => { registeredExtensions.extensions = []; - captureException = null; }); it('handles collapsed data fetch errors', async () => { registerExtension(collapsedDataErrorExtension); - createComponent(); - await waitForPromises(); + await createComponent(); expect( wrapper.find('[data-testid="widget-extension"] [data-testid="toggle-button"]').exists(), ).toBe(false); - itHandlesTheException(); + expect(Sentry.captureException).toHaveBeenCalledTimes(5); + expect(Sentry.captureException).toHaveBeenCalledWith(new Error('Fetch error')); + expect(wrapper.findComponent(StatusIcon).props('iconName')).toBe('failed'); }); it('handles full data fetch errors', async () => { registerExtension(fullDataErrorExtension); - createComponent(); - await waitForPromises(); + await createComponent(); expect(wrapper.findComponent(StatusIcon).props('iconName')).not.toBe('error'); wrapper @@ -1193,7 +1143,9 @@ describe('MrWidgetOptions', () => { await nextTick(); await waitForPromises(); - itHandlesTheException(); + expect(Sentry.captureException).toHaveBeenCalledTimes(1); + expect(Sentry.captureException).toHaveBeenCalledWith(new Error('Fetch error')); + expect(wrapper.findComponent(StatusIcon).props('iconName')).toBe('failed'); }); }); diff --git a/spec/frontend/vue_shared/components/color_select_dropdown/color_select_root_spec.js b/spec/frontend/vue_shared/components/color_select_dropdown/color_select_root_spec.js index 93b59800c27..4c69a7f1e46 100644 --- a/spec/frontend/vue_shared/components/color_select_dropdown/color_select_root_spec.js +++ b/spec/frontend/vue_shared/components/color_select_dropdown/color_select_root_spec.js @@ -84,15 +84,15 @@ describe('LabelsSelectRoot', () => { }); describe('if the variant is `sidebar`', () => { - beforeEach(() => { + it('renders SidebarEditableItem component', () => { createComponent(); - }); - it('renders SidebarEditableItem component', () => { expect(findSidebarEditableItem().exists()).toBe(true); }); it('renders correct props for the SidebarEditableItem component', () => { + createComponent(); + expect(findSidebarEditableItem().props()).toMatchObject({ title: wrapper.vm.$options.i18n.widgetTitle, canEdit: defaultProps.allowEdit, @@ -161,16 +161,20 @@ describe('LabelsSelectRoot', () => { }); describe('when updating color for epic', () => { - beforeEach(() => { + const setup = () => { createComponent(); findDropdownContents().vm.$emit('setColor', color); - }); + }; it('sets the loading state', () => { + setup(); + expect(findSidebarEditableItem().props('loading')).toBe(true); }); it('updates color correctly after successful mutation', async () => { + setup(); + await waitForPromises(); expect(findDropdownValue().props('selectedColor').color).toEqual( updateColorMutationResponse.data.updateIssuableColor.issuable.color, diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js index ca8cd419d87..a0126c2bd63 100644 --- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js +++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js @@ -418,8 +418,6 @@ describe('BaseToken', () => { }); it('does not emit `fetch-suggestions` event on component after a delay when component emits `input` event', async () => { - jest.useFakeTimers(); - findGlFilteredSearchToken().vm.$emit('input', { data: 'foo' }); await nextTick(); @@ -437,8 +435,6 @@ describe('BaseToken', () => { }); it('emits `fetch-suggestions` event on component after a delay when component emits `input` event', async () => { - jest.useFakeTimers(); - findGlFilteredSearchToken().vm.$emit('input', { data: 'foo' }); await nextTick(); diff --git a/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js b/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js index 8270ff31574..51a936c0509 100644 --- a/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js +++ b/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js @@ -195,7 +195,7 @@ describe('AlertManagementEmptyState', () => { tabs.forEach((tab, i) => { const status = ITEMS_STATUS_TABS[i].status.toLowerCase(); expect(tab.attributes('data-testid')).toContain(ITEMS_STATUS_TABS[i].status); - expect(badges.at(i).text()).toContain(itemsCount[status]); + expect(badges.at(i).text()).toContain(itemsCount[status].toString()); }); }); }); diff --git a/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js index 7173abe1316..a38dcd626f4 100644 --- a/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js +++ b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js @@ -79,7 +79,7 @@ describe('RunnerInstructionsModal component', () => { } }; - beforeEach(async () => { + beforeEach(() => { runnerPlatformsHandler = jest.fn().mockResolvedValue(mockGraphqlRunnerPlatforms); runnerSetupInstructionsHandler = jest.fn().mockResolvedValue(mockGraphqlInstructions); }); @@ -259,11 +259,11 @@ describe('RunnerInstructionsModal component', () => { }); describe('when apollo is loading', () => { - beforeEach(() => { + it('should show a skeleton loader', async () => { createComponent(); - }); + await nextTick(); + await nextTick(); - it('should show a skeleton loader', async () => { expect(findSkeletonLoader().exists()).toBe(true); expect(findGlLoadingIcon().exists()).toBe(false); @@ -275,6 +275,8 @@ describe('RunnerInstructionsModal component', () => { }); it('once loaded, should not show a loading state', async () => { + createComponent(); + await waitForPromises(); expect(findSkeletonLoader().exists()).toBe(false); |