diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-08-01 15:12:10 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-08-01 15:12:10 +0300 |
commit | 9c5341dd0832c3af377191c461c800e1aa048b10 (patch) | |
tree | e1343570ed06960c320200c8a35f2675a6ec2b48 /spec/frontend | |
parent | 46f35a616740504125aaf2c7d20a8bc7ff755ec1 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend')
24 files changed, 136 insertions, 100 deletions
diff --git a/spec/frontend/__helpers__/mocks/axios_utils.js b/spec/frontend/__helpers__/mocks/axios_utils.js index b1efd29dc8d..60644c84a57 100644 --- a/spec/frontend/__helpers__/mocks/axios_utils.js +++ b/spec/frontend/__helpers__/mocks/axios_utils.js @@ -1,4 +1,6 @@ import EventEmitter from 'events'; +// eslint-disable-next-line no-restricted-syntax +import { setImmediate } from 'timers'; const axios = jest.requireActual('~/lib/utils/axios_utils').default; diff --git a/spec/frontend/__helpers__/vuex_action_helper.js b/spec/frontend/__helpers__/vuex_action_helper.js index ab2637d6024..bdd5a0a9034 100644 --- a/spec/frontend/__helpers__/vuex_action_helper.js +++ b/spec/frontend/__helpers__/vuex_action_helper.js @@ -1,5 +1,7 @@ -/** - * Helper for testing action with expected mutations inspired in +// eslint-disable-next-line no-restricted-syntax +import { setImmediate } from 'timers'; + +/** Helper for testing action with expected mutations inspired in * https://vuex.vuejs.org/en/testing.html * * @param {(Function|Object)} action to be tested, or object of named parameters diff --git a/spec/frontend/__helpers__/wait_for_promises.js b/spec/frontend/__helpers__/wait_for_promises.js index 753c3c5d92b..5a15b8b74b5 100644 --- a/spec/frontend/__helpers__/wait_for_promises.js +++ b/spec/frontend/__helpers__/wait_for_promises.js @@ -1,4 +1,2 @@ -export default () => - new Promise((resolve) => { - requestAnimationFrame(resolve); - }); +// eslint-disable-next-line no-restricted-syntax +export default () => new Promise(jest.requireActual('timers').setImmediate); diff --git a/spec/frontend/__helpers__/web_worker_transformer.js b/spec/frontend/__helpers__/web_worker_transformer.js index 5b2f7d77947..767ab3f5675 100644 --- a/spec/frontend/__helpers__/web_worker_transformer.js +++ b/spec/frontend/__helpers__/web_worker_transformer.js @@ -6,7 +6,7 @@ const babelJestTransformer = require('babel-jest'); // [1]: https://webpack.js.org/loaders/worker-loader/ module.exports = { process: (contentArg, filename, ...args) => { - const { code: content } = babelJestTransformer.process(contentArg, filename, ...args); + const { code: content } = babelJestTransformer.default.process(contentArg, filename, ...args); return `const { FakeWebWorker } = require("helpers/web_worker_fake"); module.exports = class JestTransformedWorker extends FakeWebWorker { diff --git a/spec/frontend/boards/project_select_spec.js b/spec/frontend/boards/project_select_spec.js index c45cd545155..769d34a4ada 100644 --- a/spec/frontend/boards/project_select_spec.js +++ b/spec/frontend/boards/project_select_spec.js @@ -10,7 +10,6 @@ import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; 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'; @@ -133,7 +132,7 @@ describe('ProjectSelect component', () => { const dropdownToggle = findGlDropdown().find('.dropdown-toggle'); await dropdownToggle.trigger('click'); - await waitForPromises(); + jest.runOnlyPendingTimers(); await nextTick(); const searchInput = findGlDropdown().findComponent(GlFormInput).element; diff --git a/spec/frontend/captcha/wait_for_captcha_to_be_solved_spec.js b/spec/frontend/captcha/wait_for_captcha_to_be_solved_spec.js index 08d031a4fa7..2263d2bbeed 100644 --- a/spec/frontend/captcha/wait_for_captcha_to_be_solved_spec.js +++ b/spec/frontend/captcha/wait_for_captcha_to_be_solved_spec.js @@ -1,3 +1,4 @@ +import { nextTick } from 'vue'; import CaptchaModal from '~/captcha/captcha_modal.vue'; import { waitForCaptchaToBeSolved } from '~/captcha/wait_for_captcha_to_be_solved'; @@ -15,7 +16,7 @@ describe('waitForCaptchaToBeSolved', () => { it('opens a modal, resolves with captcha response on success', async () => { CaptchaModal.mounted.mockImplementationOnce(function mounted() { - requestAnimationFrame(() => { + return nextTick().then(() => { this.$emit('receivedCaptchaResponse', response); this.$emit('hidden'); }); @@ -36,7 +37,7 @@ describe('waitForCaptchaToBeSolved', () => { it("opens a modal, rejects with error in case the captcha isn't solved", async () => { CaptchaModal.mounted.mockImplementationOnce(function mounted() { - requestAnimationFrame(() => { + return nextTick().then(() => { this.$emit('receivedCaptchaResponse', null); this.$emit('hidden'); }); diff --git a/spec/frontend/clusters_list/components/install_agent_modal_spec.js b/spec/frontend/clusters_list/components/install_agent_modal_spec.js index 29884675b24..964dd005a27 100644 --- a/spec/frontend/clusters_list/components/install_agent_modal_spec.js +++ b/spec/frontend/clusters_list/components/install_agent_modal_spec.js @@ -150,7 +150,6 @@ describe('InstallAgentModal', () => { }); it("doesn't render agent installation instructions", () => { - expect(findModal().text()).not.toContain(i18n.basicInstallTitle); expect(findModal().findComponent(GlFormInputGroup).exists()).toBe(false); expect(findModal().findComponent(GlAlert).exists()).toBe(false); }); diff --git a/spec/frontend/groups/components/app_spec.js b/spec/frontend/groups/components/app_spec.js index 9e4666ffc70..a6bbea648d2 100644 --- a/spec/frontend/groups/components/app_spec.js +++ b/spec/frontend/groups/components/app_spec.js @@ -85,30 +85,6 @@ describe('AppComponent', () => { await nextTick(); }); - describe('computed', () => { - describe('groups', () => { - it('should return list of groups from store', () => { - jest.spyOn(vm.store, 'getGroups').mockImplementation(() => {}); - - const { groups } = vm; - - expect(vm.store.getGroups).toHaveBeenCalled(); - expect(groups).not.toBeDefined(); - }); - }); - - describe('pageInfo', () => { - it('should return pagination info from store', () => { - jest.spyOn(vm.store, 'getPaginationInfo').mockImplementation(() => {}); - - const { pageInfo } = vm; - - expect(vm.store.getPaginationInfo).toHaveBeenCalled(); - expect(pageInfo).not.toBeDefined(); - }); - }); - }); - describe('methods', () => { describe('fetchGroups', () => { it('should call `getGroups` with all the params provided', () => { diff --git a/spec/frontend/ide/components/ide_sidebar_nav_spec.js b/spec/frontend/ide/components/ide_sidebar_nav_spec.js index 2ea0c250794..33b33fb62fd 100644 --- a/spec/frontend/ide/components/ide_sidebar_nav_spec.js +++ b/spec/frontend/ide/components/ide_sidebar_nav_spec.js @@ -8,12 +8,12 @@ import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants'; const TEST_TABS = [ { title: 'Lorem', - icon: 'angle-up', + icon: 'chevron-lg-up', views: [{ name: 'lorem-1' }, { name: 'lorem-2' }], }, { title: 'Ipsum', - icon: 'angle-down', + icon: 'chevron-lg-down', views: [{ name: 'ipsum-1' }, { name: 'ipsum-2' }], }, ]; diff --git a/spec/frontend/lib/utils/common_utils_spec.js b/spec/frontend/lib/utils/common_utils_spec.js index 7cf101a5e59..73846aeac96 100644 --- a/spec/frontend/lib/utils/common_utils_spec.js +++ b/spec/frontend/lib/utils/common_utils_spec.js @@ -292,16 +292,11 @@ describe('common_utils', () => { const spy = jest.fn(); const debouncedSpy = commonUtils.debounceByAnimationFrame(spy); - return new Promise((resolve) => { - window.requestAnimationFrame(() => { - debouncedSpy(); - debouncedSpy(); - window.requestAnimationFrame(() => { - expect(spy).toHaveBeenCalledTimes(1); - resolve(); - }); - }); - }); + debouncedSpy(); + debouncedSpy(); + jest.runOnlyPendingTimers(); + + expect(spy).toHaveBeenCalledTimes(1); }); }); diff --git a/spec/frontend/lib/utils/rails_ujs_spec.js b/spec/frontend/lib/utils/rails_ujs_spec.js index c10301523c9..da9cc5c6f3c 100644 --- a/spec/frontend/lib/utils/rails_ujs_spec.js +++ b/spec/frontend/lib/utils/rails_ujs_spec.js @@ -18,14 +18,12 @@ function mockXHRResponse({ responseText, responseContentType } = {}) { .mockReturnValue(responseContentType); jest.spyOn(global.XMLHttpRequest.prototype, 'send').mockImplementation(function send() { - requestAnimationFrame(() => { - Object.defineProperties(this, { - readyState: { value: XMLHttpRequest.DONE }, - status: { value: 200 }, - response: { value: responseText }, - }); - this.onreadystatechange(); + Object.defineProperties(this, { + readyState: { value: XMLHttpRequest.DONE }, + status: { value: 200 }, + response: { value: responseText }, }); + this.onreadystatechange(); }); } diff --git a/spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js b/spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js index d990d5ad22b..cf28ffeabed 100644 --- a/spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js +++ b/spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js @@ -4,6 +4,7 @@ import VueApollo from 'vue-apollo'; import Vue, { nextTick } from 'vue'; import createMockApollo from 'helpers/mock_apollo_helper'; import setWindowLocation from 'helpers/set_window_location_helper'; +import waitForPromises from 'helpers/wait_for_promises'; import CiConfigMergedPreview from '~/pipeline_editor/components/editor/ci_config_merged_preview.vue'; import CiLint from '~/pipeline_editor/components/lint/ci_lint.vue'; import CiValidate from '~/pipeline_editor/components/validate/ci_validate.vue'; @@ -22,6 +23,7 @@ import { } from '~/pipeline_editor/constants'; import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue'; import getBlobContent from '~/pipeline_editor/graphql/queries/blob_content.query.graphql'; +import getAppStatus from '~/pipeline_editor/graphql/queries/client/app_status.query.graphql'; import { mockBlobContentQueryResponse, mockCiLintPath, @@ -81,6 +83,15 @@ describe('Pipeline editor tabs component', () => { const createComponentWithApollo = ({ props, provide = {}, mountFn = shallowMount } = {}) => { const handlers = [[getBlobContent, mockBlobContentData]]; mockApollo = createMockApollo(handlers); + mockApollo.clients.defaultClient.cache.writeQuery({ + query: getAppStatus, + data: { + app: { + __typename: 'PipelineEditorApp', + status: EDITOR_APP_STATUS_VALID, + }, + }, + }); createComponent({ props, @@ -203,7 +214,7 @@ describe('Pipeline editor tabs component', () => { }); describe('if badge has been dismissed before', () => { - beforeEach(() => { + it('does not render badge if it has been dismissed before', async () => { localStorage.setItem(VALIDATE_TAB_BADGE_DISMISSED_KEY, 'true'); mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponse); createComponentWithApollo({ @@ -217,9 +228,9 @@ describe('Pipeline editor tabs component', () => { validateTabIllustrationPath: 'path/to/svg', }, }); - }); - it('does not render badge if it has been dismissed before', () => { + await waitForPromises(); + expect(findBadge().exists()).toBe(false); }); }); diff --git a/spec/frontend/pipelines/components/pipelines_list/pipeline_stage_spec.js b/spec/frontend/pipelines/components/pipelines_list/pipeline_stage_spec.js index 1ff32b03344..e712cdeaea2 100644 --- a/spec/frontend/pipelines/components/pipelines_list/pipeline_stage_spec.js +++ b/spec/frontend/pipelines/components/pipelines_list/pipeline_stage_spec.js @@ -1,4 +1,5 @@ import { GlDropdown } from '@gitlab/ui'; +import { nextTick } from 'vue'; import { mount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; import CiIcon from '~/vue_shared/components/ci_icon.vue'; @@ -61,11 +62,10 @@ describe('Pipelines stage component', () => { const findMergeTrainWarning = () => wrapper.find('[data-testid="warning-message-merge-trains"]'); const findLoadingState = () => wrapper.find('[data-testid="pipeline-stage-loading-state"]'); - const openStageDropdown = () => { - findDropdownToggle().trigger('click'); - return new Promise((resolve) => { - wrapper.vm.$root.$on('bv::dropdown::show', resolve); - }); + const openStageDropdown = async () => { + await findDropdownToggle().trigger('click'); + await waitForPromises(); + await nextTick(); }; describe('loading state', () => { @@ -77,7 +77,10 @@ describe('Pipelines stage component', () => { await openStageDropdown(); }); - it('displays loading state while jobs are being fetched', () => { + it('displays loading state while jobs are being fetched', async () => { + jest.runOnlyPendingTimers(); + await nextTick(); + expect(findLoadingState().exists()).toBe(true); expect(findLoadingState().text()).toBe(PipelineStage.i18n.loadingText); }); @@ -98,46 +101,41 @@ describe('Pipelines stage component', () => { expect(glTooltipDirectiveMock.mock.calls[0][1].modifiers.ds0).toBe(true); }); - it('should render a dropdown with the status icon', () => { + it('renders a dropdown with the status icon', () => { expect(findDropdown().exists()).toBe(true); expect(findDropdownToggle().exists()).toBe(true); expect(findCiIcon().exists()).toBe(true); }); - it('should render a borderless ci-icon', () => { + it('renders a borderless ci-icon', () => { expect(findCiIcon().exists()).toBe(true); expect(findCiIcon().props('isBorderless')).toBe(true); expect(findCiIcon().classes('borderless')).toBe(true); }); - it('should render a ci-icon with a custom border class', () => { + it('renders a ci-icon with a custom border class', () => { expect(findCiIcon().exists()).toBe(true); expect(findCiIcon().classes('gl-border')).toBe(true); }); }); - describe('when update dropdown is changed', () => { - beforeEach(() => { - createComponent(); - }); - }); - describe('when user opens dropdown and stage request is successful', () => { beforeEach(async () => { mock.onGet(dropdownPath).reply(200, stageReply); createComponent(); await openStageDropdown(); + await jest.runAllTimers(); await axios.waitForAll(); }); - it('should render the received data and emit `clickedDropdown` event', async () => { + it('renders the received data and emit `clickedDropdown` event', async () => { expect(findDropdownMenu().text()).toContain(stageReply.latest_statuses[0].name); expect(findDropdownMenuTitle().text()).toContain(stageReply.name); expect(eventHub.$emit).toHaveBeenCalledWith('clickedDropdown'); }); - it('should refresh when updateDropdown is set to true', async () => { + it('refreshes when updateDropdown is set to true', async () => { expect(mock.history.get).toHaveLength(1); wrapper.setProps({ updateDropdown: true }); @@ -148,15 +146,14 @@ describe('Pipelines stage component', () => { }); describe('when user opens dropdown and stage request fails', () => { - beforeEach(async () => { + it('should close the dropdown', async () => { mock.onGet(dropdownPath).reply(500); createComponent(); await openStageDropdown(); await axios.waitForAll(); - }); + await waitForPromises(); - it('should close the dropdown', () => { expect(findDropdown().classes('show')).toBe(false); }); }); @@ -181,26 +178,29 @@ describe('Pipelines stage component', () => { it('should update the stage to request the new endpoint provided', async () => { await openStageDropdown(); - await axios.waitForAll(); + jest.runOnlyPendingTimers(); + await waitForPromises(); expect(findDropdownMenu().text()).toContain('this is the updated content'); }); }); describe('pipelineActionRequestComplete', () => { - beforeEach(() => { + beforeEach(async () => { mock.onGet(dropdownPath).reply(200, stageReply); mock.onPost(`${stageReply.latest_statuses[0].status.action.path}.json`).reply(200); createComponent(); + await waitForPromises(); + await nextTick(); }); const clickCiAction = async () => { await openStageDropdown(); - await axios.waitForAll(); + jest.runOnlyPendingTimers(); + await waitForPromises(); - findCiActionBtn().trigger('click'); - await axios.waitForAll(); + await findCiActionBtn().trigger('click'); }; it('closes dropdown when job item action is clicked', async () => { @@ -211,29 +211,30 @@ describe('Pipelines stage component', () => { expect(hidden).toHaveBeenCalledTimes(0); await clickCiAction(); + await waitForPromises(); expect(hidden).toHaveBeenCalledTimes(1); }); it('emits `pipelineActionRequestComplete` when job item action is clicked', async () => { await clickCiAction(); + await waitForPromises(); expect(wrapper.emitted('pipelineActionRequestComplete')).toHaveLength(1); }); }); describe('With merge trains enabled', () => { - beforeEach(async () => { + it('shows a warning on the dropdown', async () => { mock.onGet(dropdownPath).reply(200, stageReply); createComponent({ isMergeTrain: true, }); await openStageDropdown(); - await axios.waitForAll(); - }); + jest.runOnlyPendingTimers(); + await waitForPromises(); - it('shows a warning on the dropdown', () => { const warning = findMergeTrainWarning(); expect(warning.text()).toBe('Merge train pipeline jobs can not be retried'); diff --git a/spec/frontend/pipelines/pipelines_spec.js b/spec/frontend/pipelines/pipelines_spec.js index ad6d650670a..0bed24e588e 100644 --- a/spec/frontend/pipelines/pipelines_spec.js +++ b/spec/frontend/pipelines/pipelines_spec.js @@ -45,6 +45,7 @@ describe('Pipelines', () => { ciLintPath: '/ci/lint', resetCachePath: `${mockProjectPath}/settings/ci_cd/reset_cache`, newPipelinePath: `${mockProjectPath}/pipelines/new`, + ciRunnerSettingsPath: `${mockProjectPath}/-/settings/ci_cd#js-runners-settings`, }; @@ -654,7 +655,12 @@ describe('Pipelines', () => { // Mock init a polling cycle wrapper.vm.poll.options.notificationCallback(true); - findStagesDropdownToggle().trigger('click'); + await findStagesDropdownToggle().trigger('click'); + jest.runOnlyPendingTimers(); + + // cancelMock is getting overwritten in pipelines_service.js#L29 + // so we have to spy on it again here + cancelMock = jest.spyOn(wrapper.vm.service.cancelationSource, 'cancel'); await waitForPromises(); @@ -664,7 +670,8 @@ describe('Pipelines', () => { }); it('stops polling & restarts polling', async () => { - findStagesDropdownToggle().trigger('click'); + await findStagesDropdownToggle().trigger('click'); + jest.runOnlyPendingTimers(); await waitForPromises(); expect(cancelMock).not.toHaveBeenCalled(); diff --git a/spec/frontend/runner/admin_runner_show/admin_runner_show_app_spec.js b/spec/frontend/runner/admin_runner_show/admin_runner_show_app_spec.js index f820951cffc..509681c5a77 100644 --- a/spec/frontend/runner/admin_runner_show/admin_runner_show_app_spec.js +++ b/spec/frontend/runner/admin_runner_show/admin_runner_show_app_spec.js @@ -14,6 +14,7 @@ import RunnerPauseButton from '~/runner/components/runner_pause_button.vue'; import RunnerDeleteButton from '~/runner/components/runner_delete_button.vue'; import RunnerEditButton from '~/runner/components/runner_edit_button.vue'; import RunnersJobs from '~/runner/components/runner_jobs.vue'; + import runnerQuery from '~/runner/graphql/show/runner.query.graphql'; import AdminRunnerShowApp from '~/runner/admin_runner_show/admin_runner_show_app.vue'; import { captureException } from '~/runner/sentry_utils'; @@ -182,17 +183,19 @@ describe('AdminRunnerShowApp', () => { }); describe('When loading', () => { - beforeEach(() => { + it('does not show runner details', () => { mockRunnerQueryResult(); createComponent(); - }); - it('does not show runner details', () => { expect(findRunnerDetails().exists()).toBe(false); }); it('does not show runner jobs', () => { + mockRunnerQueryResult(); + + createComponent(); + expect(findRunnersJobs().exists()).toBe(false); }); }); 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 fac99ed395a..bff1cb1164d 100644 --- a/spec/frontend/runner/admin_runners/admin_runners_app_spec.js +++ b/spec/frontend/runner/admin_runners/admin_runners_app_spec.js @@ -50,6 +50,7 @@ import { allRunnersDataPaginated, onlineContactTimeoutSecs, staleTimeoutSecs, + emptyPageInfo, emptyStateSvgPath, emptyStateFilteredSvgPath, } from '../mock_data'; @@ -380,13 +381,20 @@ describe('AdminRunnersApp', () => { beforeEach(async () => { mockRunnersHandler.mockResolvedValue({ data: { - runners: { nodes: [] }, + runners: { + nodes: [], + pageInfo: emptyPageInfo, + }, }, }); await createComponent(); }); + it('shows no errors', () => { + expect(createAlert).not.toHaveBeenCalled(); + }); + it('shows an empty state', () => { expect(findRunnerListEmptyState().props('isSearchFiltered')).toBe(false); }); diff --git a/spec/frontend/runner/components/runner_assigned_item_spec.js b/spec/frontend/runner/components/runner_assigned_item_spec.js index 1ff6983fbe7..cc09046c000 100644 --- a/spec/frontend/runner/components/runner_assigned_item_spec.js +++ b/spec/frontend/runner/components/runner_assigned_item_spec.js @@ -1,10 +1,12 @@ -import { GlAvatar } from '@gitlab/ui'; +import { GlAvatar, GlBadge } from '@gitlab/ui'; +import { s__ } from '~/locale'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import RunnerAssignedItem from '~/runner/components/runner_assigned_item.vue'; import { AVATAR_SHAPE_OPTION_RECT } from '~/vue_shared/constants'; const mockHref = '/group/project'; const mockName = 'Project'; +const mockDescription = 'Project description'; const mockFullName = 'Group / Project'; const mockAvatarUrl = '/avatar.png'; @@ -12,6 +14,7 @@ describe('RunnerAssignedItem', () => { let wrapper; const findAvatar = () => wrapper.findByTestId('item-avatar'); + const findBadge = () => wrapper.findComponent(GlBadge); const createComponent = ({ props = {} } = {}) => { wrapper = shallowMountExtended(RunnerAssignedItem, { @@ -20,6 +23,7 @@ describe('RunnerAssignedItem', () => { name: mockName, fullName: mockFullName, avatarUrl: mockAvatarUrl, + description: mockDescription, ...props, }, }); @@ -51,4 +55,14 @@ describe('RunnerAssignedItem', () => { expect(groupFullName.attributes('href')).toBe(mockHref); }); + + it('Shows description', () => { + expect(wrapper.text()).toContain(mockDescription); + }); + + it('Shows owner badge', () => { + createComponent({ props: { isOwner: true } }); + + expect(findBadge().text()).toBe(s__('Runner|Owner')); + }); }); diff --git a/spec/frontend/runner/components/runner_projects_spec.js b/spec/frontend/runner/components/runner_projects_spec.js index 6932b3b5197..c988fb8477d 100644 --- a/spec/frontend/runner/components/runner_projects_spec.js +++ b/spec/frontend/runner/components/runner_projects_spec.js @@ -95,6 +95,7 @@ describe('RunnerProjects', () => { name, fullName: nameWithNamespace, avatarUrl, + isOwner: true, // first project is always owner }); }); diff --git a/spec/frontend/runner/group_runner_show/group_runner_show_app_spec.js b/spec/frontend/runner/group_runner_show/group_runner_show_app_spec.js index d80a15f1fc3..cee1d436942 100644 --- a/spec/frontend/runner/group_runner_show/group_runner_show_app_spec.js +++ b/spec/frontend/runner/group_runner_show/group_runner_show_app_spec.js @@ -178,13 +178,10 @@ describe('GroupRunnerShowApp', () => { }); describe('When loading', () => { - beforeEach(() => { + it('does not show runner details', () => { mockRunnerQueryResult(); createComponent(); - }); - - it('does not show runner details', () => { expect(findRunnerDetails().exists()).toBe(false); }); }); 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 2aa631f270f..99b6273627c 100644 --- a/spec/frontend/runner/group_runners/group_runners_app_spec.js +++ b/spec/frontend/runner/group_runners/group_runners_app_spec.js @@ -47,6 +47,7 @@ import { groupRunnersCountData, onlineContactTimeoutSecs, staleTimeoutSecs, + emptyPageInfo, emptyStateSvgPath, emptyStateFilteredSvgPath, } from '../mock_data'; @@ -331,13 +332,20 @@ describe('GroupRunnersApp', () => { data: { group: { id: '1', - runners: { nodes: [] }, + runners: { + edges: [], + pageInfo: emptyPageInfo, + }, }, }, }); await createComponent(); }); + it('shows no errors', () => { + expect(createAlert).not.toHaveBeenCalled(); + }); + it('shows an empty state', async () => { expect(findRunnerListEmptyState().exists()).toBe(true); }); diff --git a/spec/frontend/runner/mock_data.js b/spec/frontend/runner/mock_data.js index e5472ace817..e73d888bd9f 100644 --- a/spec/frontend/runner/mock_data.js +++ b/spec/frontend/runner/mock_data.js @@ -19,6 +19,14 @@ import groupRunnersCountData from 'test_fixtures/graphql/runner/list/group_runne import { RUNNER_PAGE_SIZE } from '~/runner/constants'; +const emptyPageInfo = { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: '', + endCursor: '', +}; + // Other mock data // Mock searches and their corresponding urls @@ -233,6 +241,7 @@ export { groupRunnersData, groupRunnersDataPaginated, groupRunnersCountData, + emptyPageInfo, runnerData, runnerWithGroupData, runnerProjectsData, diff --git a/spec/frontend/sidebar/components/incidents/escalation_status_spec.js b/spec/frontend/sidebar/components/incidents/escalation_status_spec.js index 8d8c10d10f1..83764cb6739 100644 --- a/spec/frontend/sidebar/components/incidents/escalation_status_spec.js +++ b/spec/frontend/sidebar/components/incidents/escalation_status_spec.js @@ -1,4 +1,5 @@ import { GlDropdown, GlDropdownItem } from '@gitlab/ui'; +import { nextTick } from 'vue'; import waitForPromises from 'helpers/wait_for_promises'; import { mountExtended } from 'helpers/vue_test_utils_helper'; import EscalationStatus from '~/sidebar/components/incidents/escalation_status.vue'; @@ -61,6 +62,8 @@ describe('EscalationStatus', () => { createComponent(); // Open dropdown await toggleDropdown(); + jest.runOnlyPendingTimers(); + await nextTick(); expect(findDropdownMenu().classes('show')).toBe(true); @@ -74,6 +77,8 @@ describe('EscalationStatus', () => { createComponent({ preventDropdownClose: true }); // Open dropdown await toggleDropdown(); + jest.runOnlyPendingTimers(); + await nextTick(); expect(findDropdownMenu().classes('show')).toBe(true); diff --git a/spec/frontend/test_setup.js b/spec/frontend/test_setup.js index b4626625f31..bcd7c651fa7 100644 --- a/spec/frontend/test_setup.js +++ b/spec/frontend/test_setup.js @@ -1,4 +1,6 @@ /* Setup for unit test environment */ +// eslint-disable-next-line no-restricted-syntax +import { setImmediate } from 'timers'; import 'helpers/shared_test_setup'; import { initializeTestTimeout } from 'helpers/timeout'; diff --git a/spec/frontend/work_items/components/work_item_assignees_spec.js b/spec/frontend/work_items/components/work_item_assignees_spec.js index 299949a4baa..547034bad45 100644 --- a/spec/frontend/work_items/components/work_item_assignees_spec.js +++ b/spec/frontend/work_items/components/work_item_assignees_spec.js @@ -204,7 +204,7 @@ describe('WorkItemAssignees component', () => { expect(findTokenSelector().props('dropdownItems')).toHaveLength(2); }); - it('should search for users with correct key after text input', async () => { + it('searches for users with correct key after text input', async () => { const searchKey = 'Hello'; findTokenSelector().vm.$emit('focus'); |