diff options
Diffstat (limited to 'spec/frontend/monitoring')
19 files changed, 583 insertions, 671 deletions
diff --git a/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap b/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap index 681fb05a6c4..bd2e818df4f 100644 --- a/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap +++ b/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap @@ -8,6 +8,28 @@ exports[`Dashboard template matches the default snapshot 1`] = ` metricsdashboardbasepath="/monitoring/monitor-project/-/environments/1/metrics" metricsendpoint="/monitoring/monitor-project/-/environments/1/additional_metrics.json" > + <div> + <gl-alert-stub + class="mb-3" + dismissible="true" + dismisslabel="Dismiss" + primarybuttonlink="" + primarybuttontext="" + secondarybuttonlink="" + secondarybuttontext="" + title="Feature deprecation and removal" + variant="danger" + > + <gl-sprintf-stub + message="The metrics, logs and tracing features were deprecated in GitLab 14.7 and are %{epicStart} scheduled for removal %{epicEnd} in GitLab 15.0." + /> + + <gl-sprintf-stub + message="For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}." + /> + </gl-alert-stub> + </div> + <div class="prometheus-graphs-header d-sm-flex flex-sm-wrap pt-2 pr-1 pb-0 pl-2 border-bottom bg-gray-light" > 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 79b223d96e4..47366b345a8 100644 --- a/spec/frontend/monitoring/components/embeds/embed_group_spec.js +++ b/spec/frontend/monitoring/components/embeds/embed_group_spec.js @@ -1,5 +1,6 @@ import { GlButton, GlCard } from '@gitlab/ui'; -import { createLocalVue, mount, shallowMount } from '@vue/test-utils'; +import { mount, shallowMount } from '@vue/test-utils'; +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'; @@ -12,8 +13,7 @@ import { multipleEmbedProps, } from './mock_data'; -const localVue = createLocalVue(); -localVue.use(Vuex); +Vue.use(Vuex); describe('Embed Group', () => { let wrapper; @@ -23,7 +23,6 @@ describe('Embed Group', () => { function mountComponent({ urls = [TEST_HOST], shallow = true, stubs } = {}) { const mountMethod = shallow ? shallowMount : mount; wrapper = mountMethod(EmbedGroup, { - localVue, store, propsData: { urls, @@ -76,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/embeds/metric_embed_spec.js b/spec/frontend/monitoring/components/embeds/metric_embed_spec.js index 90647f50b14..f9f1be4f277 100644 --- a/spec/frontend/monitoring/components/embeds/metric_embed_spec.js +++ b/spec/frontend/monitoring/components/embeds/metric_embed_spec.js @@ -1,4 +1,5 @@ -import { createLocalVue, shallowMount } from '@vue/test-utils'; +import { shallowMount } from '@vue/test-utils'; +import Vue from 'vue'; import Vuex from 'vuex'; import { setHTMLFixture } from 'helpers/fixtures'; import { TEST_HOST } from 'helpers/test_constants'; @@ -6,8 +7,7 @@ import DashboardPanel from '~/monitoring/components/dashboard_panel.vue'; import MetricEmbed from '~/monitoring/components/embeds/metric_embed.vue'; import { groups, initialState, metricsData, metricsWithData } from './mock_data'; -const localVue = createLocalVue(); -localVue.use(Vuex); +Vue.use(Vuex); describe('MetricEmbed', () => { let wrapper; @@ -17,7 +17,6 @@ describe('MetricEmbed', () => { function mountComponent() { wrapper = shallowMount(MetricEmbed, { - localVue, store, propsData: { dashboardUrl: TEST_HOST, 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/monitoring/router_spec.js b/spec/frontend/monitoring/router_spec.js index b027d60f61e..7758dd351b7 100644 --- a/spec/frontend/monitoring/router_spec.js +++ b/spec/frontend/monitoring/router_spec.js @@ -1,4 +1,5 @@ -import { mount, createLocalVue } from '@vue/test-utils'; +import { mount } from '@vue/test-utils'; +import Vue from 'vue'; import VueRouter from 'vue-router'; import Dashboard from '~/monitoring/components/dashboard.vue'; import DashboardPage from '~/monitoring/pages/dashboard_page.vue'; @@ -25,8 +26,7 @@ describe('Monitoring router', () => { let store; const createWrapper = (basePath, routeArg) => { - const localVue = createLocalVue(); - localVue.use(VueRouter); + Vue.use(VueRouter); router = createRouter(basePath); if (routeArg !== undefined) { @@ -34,7 +34,6 @@ describe('Monitoring router', () => { } return mount(MockApp, { - localVue, store, router, }); |