diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-05-17 16:05:49 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-05-17 16:05:49 +0000 |
commit | 43a25d93ebdabea52f99b05e15b06250cd8f07d7 (patch) | |
tree | dceebdc68925362117480a5d672bcff122fb625b /spec/frontend/projects | |
parent | 20c84b99005abd1c82101dfeff264ac50d2df211 (diff) | |
download | gitlab-ce-0f94cf6ca9d272d8e0fda4a7a597866cf3dc1fc0.tar.gz |
Add latest changes from gitlab-org/gitlab@16-0-stable-eev16.0.0-rc4216-0-stable
Diffstat (limited to 'spec/frontend/projects')
50 files changed, 367 insertions, 322 deletions
diff --git a/spec/frontend/projects/clusters_deprecation_slert/components/clusters_deprecation_alert_spec.js b/spec/frontend/projects/clusters_deprecation_slert/components/clusters_deprecation_alert_spec.js index d230b96ad82..68ea3a4dc4d 100644 --- a/spec/frontend/projects/clusters_deprecation_slert/components/clusters_deprecation_alert_spec.js +++ b/spec/frontend/projects/clusters_deprecation_slert/components/clusters_deprecation_alert_spec.js @@ -26,10 +26,6 @@ describe('ClustersDeprecationAlert', () => { createComponent(); }); - afterEach(() => { - wrapper.destroy(); - }); - describe('template', () => { it('should render a non-dismissible warning alert', () => { expect(findAlert().props()).toMatchObject({ diff --git a/spec/frontend/projects/commit/components/branches_dropdown_spec.js b/spec/frontend/projects/commit/components/branches_dropdown_spec.js index 6aa5a9a5a3a..bff40c2bc39 100644 --- a/spec/frontend/projects/commit/components/branches_dropdown_spec.js +++ b/spec/frontend/projects/commit/components/branches_dropdown_spec.js @@ -12,7 +12,7 @@ describe('BranchesDropdown', () => { let store; const spyFetchBranches = jest.fn(); - const createComponent = (props, state = { isFetching: false }) => { + const createComponent = (props, state = { isFetching: false, branch: '_main_' }) => { store = new Vuex.Store({ getters: { joinedBranches: () => ['_main_', '_branch_1_', '_branch_2_'], @@ -41,8 +41,6 @@ describe('BranchesDropdown', () => { }); afterEach(() => { - wrapper.destroy(); - wrapper = null; spyFetchBranches.mockReset(); }); @@ -61,7 +59,7 @@ describe('BranchesDropdown', () => { }); describe('Selecting Dropdown Item', () => { - it('emits event', async () => { + it('emits event', () => { findDropdown().vm.$emit('select', '_anything_'); expect(wrapper.emitted()).toHaveProperty('input'); @@ -70,13 +68,11 @@ describe('BranchesDropdown', () => { describe('When searching', () => { it('invokes fetchBranches', async () => { - const spy = jest.spyOn(wrapper.vm, 'fetchBranches'); - findDropdown().vm.$emit('search', '_anything_'); await nextTick(); - expect(spy).toHaveBeenCalledWith('_anything_'); + expect(spyFetchBranches).toHaveBeenCalledWith(expect.any(Object), '_anything_'); }); }); }); diff --git a/spec/frontend/projects/commit/components/commit_options_dropdown_spec.js b/spec/frontend/projects/commit/components/commit_options_dropdown_spec.js index 70491405986..7df498f597b 100644 --- a/spec/frontend/projects/commit/components/commit_options_dropdown_spec.js +++ b/spec/frontend/projects/commit/components/commit_options_dropdown_spec.js @@ -85,7 +85,7 @@ describe('BranchesDropdown', () => { expect(findTagItem().exists()).toBe(false); }); - it('does not have a email patches options', () => { + it('does not have a patches options', () => { createComponent({ canEmailPatches: false }); expect(findEmailPatchesItem().exists()).toBe(false); diff --git a/spec/frontend/projects/commit/components/form_modal_spec.js b/spec/frontend/projects/commit/components/form_modal_spec.js index c59cf700e0d..d40e2d7a48c 100644 --- a/spec/frontend/projects/commit/components/form_modal_spec.js +++ b/spec/frontend/projects/commit/components/form_modal_spec.js @@ -1,9 +1,9 @@ import { GlModal, GlForm, GlFormCheckbox, GlSprintf } from '@gitlab/ui'; import { within } from '@testing-library/dom'; -import { shallowMount, mount, createWrapper } from '@vue/test-utils'; +import { createWrapper } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; import { nextTick } from 'vue'; -import { extendedWrapper } from 'helpers/vue_test_utils_helper'; +import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper'; import api from '~/api'; import axios from '~/lib/utils/axios_utils'; import { BV_SHOW_MODAL } from '~/lib/utils/constants'; @@ -21,21 +21,24 @@ describe('CommitFormModal', () => { let store; let axiosMock; - const createComponent = (method, state = {}, provide = {}, propsData = {}) => { + const createComponent = ({ + method = shallowMountExtended, + state = {}, + provide = {}, + propsData = {}, + } = {}) => { store = createStore({ ...mockData.mockModal, ...state }); - wrapper = extendedWrapper( - method(CommitFormModal, { - provide: { - ...provide, - }, - propsData: { ...mockData.modalPropsData, ...propsData }, - store, - attrs: { - static: true, - visible: true, - }, - }), - ); + wrapper = method(CommitFormModal, { + provide: { + ...provide, + }, + propsData: { ...mockData.modalPropsData, ...propsData }, + store, + attrs: { + static: true, + visible: true, + }, + }); }; const findModal = () => wrapper.findComponent(GlModal); @@ -55,7 +58,6 @@ describe('CommitFormModal', () => { }); afterEach(() => { - wrapper.destroy(); axiosMock.restore(); }); @@ -63,13 +65,13 @@ describe('CommitFormModal', () => { it('Listens for opening of modal on mount', () => { jest.spyOn(eventHub, '$on'); - createComponent(shallowMount); + createComponent(); expect(eventHub.$on).toHaveBeenCalledWith(mockData.modalPropsData.openModal, wrapper.vm.show); }); it('Shows modal', () => { - createComponent(shallowMount); + createComponent(); const rootEmit = jest.spyOn(wrapper.vm.$root, '$emit'); wrapper.vm.show(); @@ -78,25 +80,25 @@ describe('CommitFormModal', () => { }); it('Clears the modal state once modal is hidden', () => { - createComponent(shallowMount); + createComponent(); jest.spyOn(store, 'dispatch').mockImplementation(); - wrapper.vm.checked = false; + findCheckBox().vm.$emit('input', false); findModal().vm.$emit('hidden'); expect(store.dispatch).toHaveBeenCalledWith('clearModal'); expect(store.dispatch).toHaveBeenCalledWith('setSelectedBranch', ''); - expect(wrapper.vm.checked).toBe(true); + expect(findCheckBox().attributes('checked')).toBe('true'); }); it('Shows the checkbox for new merge request', () => { - createComponent(shallowMount); + createComponent(); expect(findCheckBox().exists()).toBe(true); }); it('Shows the prepended text', () => { - createComponent(shallowMount, {}, { prependedText: '_prepended_text_' }); + createComponent({ provide: { prependedText: '_prepended_text_' } }); expect(findPrependedText().exists()).toBe(true); expect(findPrependedText().findComponent(GlSprintf).attributes('message')).toBe( @@ -105,25 +107,25 @@ describe('CommitFormModal', () => { }); it('Does not show prepended text', () => { - createComponent(shallowMount); + createComponent(); expect(findPrependedText().exists()).toBe(false); }); it('Does not show extra message text', () => { - createComponent(shallowMount); + createComponent(); expect(findModal().find('[data-testid="appended-text"]').exists()).toBe(false); }); it('Does not show the checkbox for new merge request', () => { - createComponent(shallowMount, { pushCode: false }); + createComponent({ state: { pushCode: false } }); expect(findCheckBox().exists()).toBe(false); }); it('Shows the branch in fork message', () => { - createComponent(shallowMount, { pushCode: false }); + createComponent({ state: { pushCode: false } }); expect(findAppendedText().exists()).toBe(true); expect(findAppendedText().findComponent(GlSprintf).attributes('message')).toContain( @@ -132,7 +134,7 @@ describe('CommitFormModal', () => { }); it('Shows the branch collaboration message', () => { - createComponent(shallowMount, { pushCode: false, branchCollaboration: true }); + createComponent({ state: { pushCode: false, branchCollaboration: true } }); expect(findAppendedText().exists()).toBe(true); expect(findAppendedText().findComponent(GlSprintf).attributes('message')).toContain( @@ -143,17 +145,13 @@ describe('CommitFormModal', () => { describe('Taking action on the form', () => { beforeEach(() => { - createComponent(mount); + createComponent({ method: mountExtended }); }); it('Action primary button dispatches submit action', () => { - const submitSpy = jest.spyOn(findForm().element, 'submit'); - getByText(mockData.modalPropsData.i18n.actionPrimaryText).trigger('click'); - expect(submitSpy).toHaveBeenCalled(); - - submitSpy.mockRestore(); + expect(wrapper.vm.$refs.form.$el.submit).toHaveBeenCalled(); }); it('Changes the start_branch input value', async () => { @@ -165,8 +163,8 @@ describe('CommitFormModal', () => { }); it('Changes the target_project_id input value', async () => { - createComponent(shallowMount, {}, {}, { isCherryPick: true }); - findProjectsDropdown().vm.$emit('selectProject', '_changed_project_value_'); + createComponent({ propsData: { isCherryPick: true } }); + findProjectsDropdown().vm.$emit('input', '_changed_project_value_'); await nextTick(); @@ -175,12 +173,9 @@ describe('CommitFormModal', () => { }); it('action primary button triggers Redis HLL tracking api call', async () => { - createComponent(mount, {}, {}, { primaryActionEventName: 'test_event' }); - + createComponent({ method: mountExtended, propsData: { primaryActionEventName: 'test_event' } }); await nextTick(); - jest.spyOn(findForm().element, 'submit'); - getByText(mockData.modalPropsData.i18n.actionPrimaryText).trigger('click'); expect(api.trackRedisHllUserEvent).toHaveBeenCalledWith('test_event'); diff --git a/spec/frontend/projects/commit/components/projects_dropdown_spec.js b/spec/frontend/projects/commit/components/projects_dropdown_spec.js index 0e213ff388a..baf2ea2656f 100644 --- a/spec/frontend/projects/commit/components/projects_dropdown_spec.js +++ b/spec/frontend/projects/commit/components/projects_dropdown_spec.js @@ -1,6 +1,6 @@ import { GlCollapsibleListbox } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import ProjectsDropdown from '~/projects/commit/components/projects_dropdown.vue'; @@ -38,7 +38,6 @@ describe('ProjectsDropdown', () => { const findDropdown = () => wrapper.findComponent(GlCollapsibleListbox); afterEach(() => { - wrapper.destroy(); spyFetchProjects.mockReset(); }); @@ -48,20 +47,24 @@ describe('ProjectsDropdown', () => { }); describe('Custom events', () => { - it('should emit selectProject if a project is clicked', () => { + it('should emit input if a project is clicked', () => { findDropdown().vm.$emit('select', '1'); - expect(wrapper.emitted('selectProject')).toEqual([['1']]); + expect(wrapper.emitted('input')).toEqual([['1']]); }); }); }); describe('Case insensitive for search term', () => { beforeEach(() => { - createComponent('_PrOjEcT_1_'); + createComponent('_PrOjEcT_1_', { targetProjectId: '1' }); }); - it('renders only the project searched for', () => { + it('renders only the project searched for', async () => { + findDropdown().vm.$emit('search', '_project_1_'); + + await nextTick(); + expect(findDropdown().props('items')).toEqual([{ text: '_project_1_', value: '1' }]); }); }); diff --git a/spec/frontend/projects/commit/store/actions_spec.js b/spec/frontend/projects/commit/store/actions_spec.js index 008710984b9..adb87142fee 100644 --- a/spec/frontend/projects/commit/store/actions_spec.js +++ b/spec/frontend/projects/commit/store/actions_spec.js @@ -1,6 +1,6 @@ import MockAdapter from 'axios-mock-adapter'; import testAction from 'helpers/vuex_action_helper'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import axios from '~/lib/utils/axios_utils'; import { PROJECT_BRANCHES_ERROR } from '~/projects/commit/constants'; import * as actions from '~/projects/commit/store/actions'; @@ -8,7 +8,7 @@ import * as types from '~/projects/commit/store/mutation_types'; import getInitialState from '~/projects/commit/store/state'; import mockData from '../mock_data'; -jest.mock('~/flash.js'); +jest.mock('~/alert'); describe('Commit form modal store actions', () => { let axiosMock; @@ -63,7 +63,7 @@ describe('Commit form modal store actions', () => { ); }); - it('should show flash error and set error in state on fetchBranches failure', async () => { + it('should show an alert and set error in state on fetchBranches failure', async () => { jest.spyOn(axios, 'get').mockRejectedValue(); await testAction(actions.fetchBranches, {}, state, [], [{ type: 'requestBranches' }]); diff --git a/spec/frontend/projects/commit_box/info/init_details_button_spec.js b/spec/frontend/projects/commit_box/info/init_details_button_spec.js new file mode 100644 index 00000000000..bf9c6a4c998 --- /dev/null +++ b/spec/frontend/projects/commit_box/info/init_details_button_spec.js @@ -0,0 +1,47 @@ +import { setHTMLFixture } from 'helpers/fixtures'; +import { initDetailsButton } from '~/projects/commit_box/info/init_details_button'; + +const htmlFixture = ` + <span> + <a href="#" class="js-details-expand"><span class="sub-element">Expand</span></a> + <span class="js-details-content hide">Some branch</span> + </span>`; + +describe('~/projects/commit_box/info/init_details_button', () => { + const findExpandButton = () => document.querySelector('.js-details-expand'); + const findContent = () => document.querySelector('.js-details-content'); + const findExpandSubElement = () => document.querySelector('.sub-element'); + + beforeEach(() => { + setHTMLFixture(htmlFixture); + initDetailsButton(); + }); + + describe('when clicking the expand button', () => { + it('renders the content by removing the `hide` class', () => { + expect(findContent().classList).toContain('hide'); + findExpandButton().click(); + expect(findContent().classList).not.toContain('hide'); + }); + + it('hides the expand button by adding the `gl-display-none` class', () => { + expect(findExpandButton().classList).not.toContain('gl-display-none'); + findExpandButton().click(); + expect(findExpandButton().classList).toContain('gl-display-none'); + }); + }); + + describe('when user clicks on element inside of expand button', () => { + it('renders the content by removing the `hide` class', () => { + expect(findContent().classList).toContain('hide'); + findExpandSubElement().click(); + expect(findContent().classList).not.toContain('hide'); + }); + + it('hides the expand button by adding the `gl-display-none` class', () => { + expect(findExpandButton().classList).not.toContain('gl-display-none'); + findExpandSubElement().click(); + expect(findExpandButton().classList).toContain('gl-display-none'); + }); + }); +}); diff --git a/spec/frontend/projects/commit_box/info/load_branches_spec.js b/spec/frontend/projects/commit_box/info/load_branches_spec.js index e49d92188ed..b00a6378e07 100644 --- a/spec/frontend/projects/commit_box/info/load_branches_spec.js +++ b/spec/frontend/projects/commit_box/info/load_branches_spec.js @@ -4,6 +4,9 @@ import { setHTMLFixture } from 'helpers/fixtures'; import waitForPromises from 'helpers/wait_for_promises'; import { HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_OK } from '~/lib/utils/http_status'; import { loadBranches } from '~/projects/commit_box/info/load_branches'; +import { initDetailsButton } from '~/projects/commit_box/info/init_details_button'; + +jest.mock('~/projects/commit_box/info/init_details_button'); const mockCommitPath = '/commit/abcd/branches'; const mockBranchesRes = @@ -26,6 +29,13 @@ describe('~/projects/commit_box/info/load_branches', () => { mock.onGet(mockCommitPath).reply(HTTP_STATUS_OK, mockBranchesRes); }); + it('initializes the details button', async () => { + loadBranches(); + await waitForPromises(); + + expect(initDetailsButton).toHaveBeenCalled(); + }); + it('loads and renders branches info', async () => { loadBranches(); await waitForPromises(); diff --git a/spec/frontend/projects/commits/components/author_select_spec.js b/spec/frontend/projects/commits/components/author_select_spec.js index 907e0e226b6..630b8feafbc 100644 --- a/spec/frontend/projects/commits/components/author_select_spec.js +++ b/spec/frontend/projects/commits/components/author_select_spec.js @@ -3,6 +3,7 @@ import { shallowMount } from '@vue/test-utils'; import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures'; +import setWindowLocation from 'helpers/set_window_location_helper'; import * as urlUtility from '~/lib/utils/url_utility'; import AuthorSelect from '~/projects/commits/components/author_select.vue'; import { createStore } from '~/projects/commits/store'; @@ -54,7 +55,6 @@ describe('Author Select', () => { }); afterEach(() => { - wrapper.destroy(); resetHTMLFixture(); }); @@ -65,39 +65,23 @@ describe('Author Select', () => { const findDropdownItems = () => wrapper.findAllComponents(GlDropdownItem); describe('user is searching via "filter by commit message"', () => { - it('disables dropdown container', async () => { - // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details - // eslint-disable-next-line no-restricted-syntax - wrapper.setData({ hasSearchParam: true }); + beforeEach(() => { + setWindowLocation(`?search=foo`); + createComponent(); + }); - await nextTick(); + it('does not disable dropdown container', () => { expect(findDropdownContainer().attributes('disabled')).toBeUndefined(); }); - it('has correct tooltip message', async () => { - // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details - // eslint-disable-next-line no-restricted-syntax - wrapper.setData({ hasSearchParam: true }); - - await nextTick(); + it('has correct tooltip message', () => { expect(findDropdownContainer().attributes('title')).toBe( 'Searching by both author and message is currently not supported.', ); }); - it('disables dropdown', async () => { - // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details - // eslint-disable-next-line no-restricted-syntax - wrapper.setData({ hasSearchParam: false }); - - await nextTick(); - expect(findDropdown().attributes('disabled')).toBeUndefined(); - }); - - it('hasSearchParam if user types a truthy string', () => { - wrapper.vm.setSearchParam('false'); - - expect(wrapper.vm.hasSearchParam).toBe(true); + it('disables dropdown', () => { + expect(findDropdown().attributes('disabled')).toBeDefined(); }); }); @@ -107,9 +91,8 @@ describe('Author Select', () => { }); it('displays the current selected author', async () => { - // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details - // eslint-disable-next-line no-restricted-syntax - wrapper.setData({ currentAuthor }); + setWindowLocation(`?author=${currentAuthor}`); + createComponent(); await nextTick(); expect(findDropdown().attributes('text')).toBe(currentAuthor); @@ -147,12 +130,14 @@ describe('Author Select', () => { expect(findDropdownItems().at(0).text()).toBe('Any Author'); }); - it('displays the project authors', async () => { - await nextTick(); + it('displays the project authors', () => { expect(findDropdownItems()).toHaveLength(authors.length + 1); }); it('has the correct props', async () => { + setWindowLocation(`?author=${currentAuthor}`); + createComponent(); + const [{ avatar_url: avatarUrl, username }] = authors; const result = { avatarUrl, @@ -160,16 +145,11 @@ describe('Author Select', () => { isChecked: true, }; - // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details - // eslint-disable-next-line no-restricted-syntax - wrapper.setData({ currentAuthor }); - await nextTick(); expect(findDropdownItems().at(1).props()).toEqual(expect.objectContaining(result)); }); - it("display the author's name", async () => { - await nextTick(); + it("display the author's name", () => { expect(findDropdownItems().at(1).text()).toBe(currentAuthor); }); diff --git a/spec/frontend/projects/commits/store/actions_spec.js b/spec/frontend/projects/commits/store/actions_spec.js index bae9c48fc1e..8afa2a6fb8f 100644 --- a/spec/frontend/projects/commits/store/actions_spec.js +++ b/spec/frontend/projects/commits/store/actions_spec.js @@ -1,13 +1,13 @@ import axios from 'axios'; import MockAdapter from 'axios-mock-adapter'; import testAction from 'helpers/vuex_action_helper'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import { HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_OK } from '~/lib/utils/http_status'; import actions from '~/projects/commits/store/actions'; import * as types from '~/projects/commits/store/mutation_types'; import createState from '~/projects/commits/store/state'; -jest.mock('~/flash'); +jest.mock('~/alert'); describe('Project commits actions', () => { let state; @@ -34,8 +34,8 @@ describe('Project commits actions', () => { ])); }); - describe('shows a flash message when there is an error', () => { - it('creates a flash', () => { + describe('shows an alert when there is an error', () => { + it('creates an alert', () => { const mockDispatchContext = { dispatch: () => {}, commit: () => {}, state }; actions.receiveAuthorsError(mockDispatchContext); diff --git a/spec/frontend/projects/compare/components/app_spec.js b/spec/frontend/projects/compare/components/app_spec.js index 9b052a17caa..ee96f46ea0c 100644 --- a/spec/frontend/projects/compare/components/app_spec.js +++ b/spec/frontend/projects/compare/components/app_spec.js @@ -21,11 +21,6 @@ describe('CompareApp component', () => { }); }; - afterEach(() => { - wrapper.destroy(); - wrapper = null; - }); - beforeEach(() => { createComponent(); }); diff --git a/spec/frontend/projects/compare/components/repo_dropdown_spec.js b/spec/frontend/projects/compare/components/repo_dropdown_spec.js index 21cca857c6a..0b1085470b8 100644 --- a/spec/frontend/projects/compare/components/repo_dropdown_spec.js +++ b/spec/frontend/projects/compare/components/repo_dropdown_spec.js @@ -16,11 +16,6 @@ describe('RepoDropdown component', () => { }); }; - afterEach(() => { - wrapper.destroy(); - wrapper = null; - }); - const findGlDropdown = () => wrapper.findComponent(GlDropdown); const findHiddenInput = () => wrapper.find('input[type="hidden"]'); diff --git a/spec/frontend/projects/compare/components/revision_card_spec.js b/spec/frontend/projects/compare/components/revision_card_spec.js index b23bd91ceda..3c9c61c8903 100644 --- a/spec/frontend/projects/compare/components/revision_card_spec.js +++ b/spec/frontend/projects/compare/components/revision_card_spec.js @@ -16,11 +16,6 @@ describe('RepoDropdown component', () => { }); }; - afterEach(() => { - wrapper.destroy(); - wrapper = null; - }); - beforeEach(() => { createComponent(); }); diff --git a/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js b/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js index 53763bd7d8f..e289569f8ce 100644 --- a/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js +++ b/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js @@ -1,8 +1,8 @@ import { GlDropdown, GlDropdownItem } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import AxiosMockAdapter from 'axios-mock-adapter'; -import { nextTick } from 'vue'; -import { createAlert } from '~/flash'; +import waitForPromises from 'helpers/wait_for_promises'; +import { createAlert } from '~/alert'; import axios from '~/lib/utils/axios_utils'; import { HTTP_STATUS_NOT_FOUND, HTTP_STATUS_OK } from '~/lib/utils/http_status'; import RevisionDropdown from '~/projects/compare/components/revision_dropdown_legacy.vue'; @@ -14,7 +14,7 @@ const defaultProps = { paramsBranch: 'main', }; -jest.mock('~/flash'); +jest.mock('~/alert'); describe('RevisionDropdown component', () => { let wrapper; @@ -35,11 +35,14 @@ describe('RevisionDropdown component', () => { }); afterEach(() => { - wrapper.destroy(); axiosMock.restore(); }); const findGlDropdown = () => wrapper.findComponent(GlDropdown); + const findBranchesDropdownItem = () => + wrapper.findAllComponents('[data-testid="branches-dropdown-item"]'); + const findTagsDropdownItem = () => + wrapper.findAllComponents('[data-testid="tags-dropdown-item"]'); it('sets hidden input', () => { expect(wrapper.find('input[type="hidden"]').attributes('value')).toBe( @@ -58,10 +61,21 @@ describe('RevisionDropdown component', () => { createComponent(); - await axios.waitForAll(); + expect(findBranchesDropdownItem()).toHaveLength(0); + expect(findTagsDropdownItem()).toHaveLength(0); - expect(wrapper.vm.branches).toEqual(Branches); - expect(wrapper.vm.tags).toEqual(Tags); + await waitForPromises(); + + Branches.forEach((branch, index) => { + expect(findBranchesDropdownItem().at(index).text()).toBe(branch); + }); + + Tags.forEach((tag, index) => { + expect(findTagsDropdownItem().at(index).text()).toBe(tag); + }); + + expect(findBranchesDropdownItem()).toHaveLength(Branches.length); + expect(findTagsDropdownItem()).toHaveLength(Tags.length); }); it('sets branches and tags to be an empty array when no tags or branches are given', async () => { @@ -70,16 +84,17 @@ describe('RevisionDropdown component', () => { Tags: undefined, }); - await axios.waitForAll(); + await waitForPromises(); - expect(wrapper.vm.branches).toEqual([]); - expect(wrapper.vm.tags).toEqual([]); + expect(findBranchesDropdownItem()).toHaveLength(0); + expect(findTagsDropdownItem()).toHaveLength(0); }); - it('shows flash message on error', async () => { + it('shows an alert on error', async () => { axiosMock.onGet('some/invalid/path').replyOnce(HTTP_STATUS_NOT_FOUND); - await wrapper.vm.fetchBranchesAndTags(); + await waitForPromises(); + expect(createAlert).toHaveBeenCalled(); }); @@ -102,17 +117,19 @@ describe('RevisionDropdown component', () => { it('emits a "selectRevision" event when a revision is selected', async () => { const findGlDropdownItems = () => wrapper.findAllComponents(GlDropdownItem); const findFirstGlDropdownItem = () => findGlDropdownItems().at(0); + const branchName = 'some-branch'; - // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details - // eslint-disable-next-line no-restricted-syntax - wrapper.setData({ branches: ['some-branch'] }); + axiosMock.onGet(defaultProps.refsProjectPath).replyOnce(HTTP_STATUS_OK, { + Branches: [branchName], + }); - await nextTick(); + createComponent(); + await waitForPromises(); findFirstGlDropdownItem().vm.$emit('click'); expect(wrapper.emitted()).toEqual({ - selectRevision: [[{ direction: 'from', revision: 'some-branch' }]], + selectRevision: [[{ direction: 'from', revision: branchName }]], }); }); }); diff --git a/spec/frontend/projects/compare/components/revision_dropdown_spec.js b/spec/frontend/projects/compare/components/revision_dropdown_spec.js index db4a1158996..1cf99f16601 100644 --- a/spec/frontend/projects/compare/components/revision_dropdown_spec.js +++ b/spec/frontend/projects/compare/components/revision_dropdown_spec.js @@ -2,13 +2,14 @@ import { GlDropdown, GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import AxiosMockAdapter from 'axios-mock-adapter'; import { nextTick } from 'vue'; -import { createAlert } from '~/flash'; +import waitForPromises from 'helpers/wait_for_promises'; +import { createAlert } from '~/alert'; import axios from '~/lib/utils/axios_utils'; import { HTTP_STATUS_NOT_FOUND, HTTP_STATUS_OK } from '~/lib/utils/http_status'; import RevisionDropdown from '~/projects/compare/components/revision_dropdown.vue'; import { revisionDropdownDefaultProps as defaultProps } from './mock_data'; -jest.mock('~/flash'); +jest.mock('~/alert'); describe('RevisionDropdown component', () => { let wrapper; @@ -32,12 +33,15 @@ describe('RevisionDropdown component', () => { }); afterEach(() => { - wrapper.destroy(); axiosMock.restore(); }); const findGlDropdown = () => wrapper.findComponent(GlDropdown); const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType); + const findBranchesDropdownItem = () => + wrapper.findAllComponents('[data-testid="branches-dropdown-item"]'); + const findTagsDropdownItem = () => + wrapper.findAllComponents('[data-testid="tags-dropdown-item"]'); it('sets hidden input', () => { createComponent(); @@ -57,17 +61,29 @@ describe('RevisionDropdown component', () => { createComponent(); - await axios.waitForAll(); - expect(wrapper.vm.branches).toEqual(Branches); - expect(wrapper.vm.tags).toEqual(Tags); + expect(findBranchesDropdownItem()).toHaveLength(0); + expect(findTagsDropdownItem()).toHaveLength(0); + + await waitForPromises(); + + expect(findBranchesDropdownItem()).toHaveLength(Branches.length); + expect(findTagsDropdownItem()).toHaveLength(Tags.length); + + Branches.forEach((branch, index) => { + expect(findBranchesDropdownItem().at(index).text()).toBe(branch); + }); + + Tags.forEach((tag, index) => { + expect(findTagsDropdownItem().at(index).text()).toBe(tag); + }); }); - it('shows flash message on error', async () => { + it('shows an alert on error', async () => { axiosMock.onGet('some/invalid/path').replyOnce(HTTP_STATUS_NOT_FOUND); createComponent(); + await waitForPromises(); - await wrapper.vm.fetchBranchesAndTags(); expect(createAlert).toHaveBeenCalled(); }); @@ -83,17 +99,17 @@ describe('RevisionDropdown component', () => { refsProjectPath: newRefsProjectPath, }); - await axios.waitForAll(); + await waitForPromises(); expect(axios.get).toHaveBeenLastCalledWith(newRefsProjectPath); }); describe('search', () => { - it('shows flash message on error', async () => { + it('shows alert on error', async () => { axiosMock.onGet('some/invalid/path').replyOnce(HTTP_STATUS_NOT_FOUND); createComponent(); + await waitForPromises(); - await wrapper.vm.searchBranchesAndTags(); expect(createAlert).toHaveBeenCalled(); }); @@ -108,7 +124,7 @@ describe('RevisionDropdown component', () => { const mockSearchTerm = 'foobar'; createComponent(); findSearchBox().vm.$emit('input', mockSearchTerm); - await axios.waitForAll(); + await waitForPromises(); expect(axios.get).toHaveBeenCalledWith( defaultProps.refsProjectPath, @@ -141,8 +157,14 @@ describe('RevisionDropdown component', () => { }); it('emits `selectRevision` event when another revision is selected', async () => { + jest.spyOn(axios, 'get').mockResolvedValue({ + data: { + Branches: ['some-branch'], + Tags: [], + }, + }); + createComponent(); - wrapper.vm.branches = ['some-branch']; await nextTick(); findGlDropdown().findAllComponents(GlDropdownItem).at(0).vm.$emit('click'); diff --git a/spec/frontend/projects/components/project_delete_button_spec.js b/spec/frontend/projects/components/project_delete_button_spec.js index 49e3218e5bc..bae76e7eeb6 100644 --- a/spec/frontend/projects/components/project_delete_button_spec.js +++ b/spec/frontend/projects/components/project_delete_button_spec.js @@ -33,11 +33,6 @@ describe('Project remove modal', () => { }); }; - afterEach(() => { - wrapper.destroy(); - wrapper = null; - }); - describe('initialized', () => { beforeEach(() => { createComponent(); diff --git a/spec/frontend/projects/components/shared/delete_button_spec.js b/spec/frontend/projects/components/shared/delete_button_spec.js index 097b18025a3..6b4ef341b0c 100644 --- a/spec/frontend/projects/components/shared/delete_button_spec.js +++ b/spec/frontend/projects/components/shared/delete_button_spec.js @@ -45,11 +45,6 @@ describe('Project remove modal', () => { }); }; - afterEach(() => { - wrapper.destroy(); - wrapper = null; - }); - describe('intialized', () => { beforeEach(() => { createComponent(); @@ -74,7 +69,7 @@ describe('Project remove modal', () => { }); it('the confirm button is disabled', () => { - expect(findConfirmButton().attributes('disabled')).toBe('true'); + expect(findConfirmButton().attributes('disabled')).toBeDefined(); }); }); diff --git a/spec/frontend/projects/details/upload_button_spec.js b/spec/frontend/projects/details/upload_button_spec.js index 50638755260..e9b11ce544a 100644 --- a/spec/frontend/projects/details/upload_button_spec.js +++ b/spec/frontend/projects/details/upload_button_spec.js @@ -27,10 +27,6 @@ describe('UploadButton', () => { wrapper = createComponent(); }); - afterEach(() => { - wrapper.destroy(); - }); - it('displays an upload button', () => { expect(wrapper.findComponent(GlButton).exists()).toBe(true); }); diff --git a/spec/frontend/projects/new/components/app_spec.js b/spec/frontend/projects/new/components/app_spec.js index f6edbab3cca..60d8385eb91 100644 --- a/spec/frontend/projects/new/components/app_spec.js +++ b/spec/frontend/projects/new/components/app_spec.js @@ -6,12 +6,12 @@ describe('Experimental new project creation app', () => { let wrapper; const createComponent = (propsData) => { - wrapper = shallowMount(App, { propsData }); + wrapper = shallowMount(App, { + propsData: { rootPath: '/', projectsUrl: '/dashboard/projects', ...propsData }, + }); }; - afterEach(() => { - wrapper.destroy(); - }); + const findNewNamespacePage = () => wrapper.findComponent(NewNamespacePage); it('passes custom new project guideline text to underlying component', () => { const DEMO_GUIDELINES = 'Demo guidelines'; @@ -34,11 +34,45 @@ describe('Experimental new project creation app', () => { expect( Boolean( - wrapper - .findComponent(NewNamespacePage) + findNewNamespacePage() .props() .panels.find((p) => p.name === 'cicd_for_external_repo'), ), ).toBe(isCiCdAvailable); }); + + it.each` + canImportProjects | outcome + ${false} | ${'do not show Import panel'} + ${true} | ${'show Import panel'} + `('$outcome when canImportProjects is $canImportProjects', ({ canImportProjects }) => { + createComponent({ + canImportProjects, + }); + + expect( + findNewNamespacePage() + .props() + .panels.some((p) => p.name === 'import_project'), + ).toBe(canImportProjects); + }); + + it('creates correct breadcrumbs for top-level projects', () => { + createComponent(); + + expect(findNewNamespacePage().props('initialBreadcrumbs')).toEqual([ + { href: '/', text: 'Your work' }, + { href: '/dashboard/projects', text: 'Projects' }, + { href: '#', text: 'New project' }, + ]); + }); + + it('creates correct breadcrumbs for projects within groups', () => { + createComponent({ parentGroupUrl: '/parent-group', parentGroupName: 'Parent Group' }); + + expect(findNewNamespacePage().props('initialBreadcrumbs')).toEqual([ + { href: '/parent-group', text: 'Parent Group' }, + { href: '#', text: 'New project' }, + ]); + }); }); diff --git a/spec/frontend/projects/new/components/deployment_target_select_spec.js b/spec/frontend/projects/new/components/deployment_target_select_spec.js index f3b22d4a1b9..57b804b632a 100644 --- a/spec/frontend/projects/new/components/deployment_target_select_spec.js +++ b/spec/frontend/projects/new/components/deployment_target_select_spec.js @@ -47,7 +47,6 @@ describe('Deployment target select', () => { }); afterEach(() => { - wrapper.destroy(); resetHTMLFixture(); }); @@ -57,7 +56,7 @@ describe('Deployment target select', () => { it('renders a select with the disabled default option', () => { expect(findSelect().find('option').text()).toBe('Select the deployment target'); - expect(findSelect().find('option').attributes('disabled')).toBe('disabled'); + expect(findSelect().find('option').attributes('disabled')).toBeDefined(); }); describe.each` diff --git a/spec/frontend/projects/new/components/new_project_push_tip_popover_spec.js b/spec/frontend/projects/new/components/new_project_push_tip_popover_spec.js index 16b4493c622..1a43dcb682b 100644 --- a/spec/frontend/projects/new/components/new_project_push_tip_popover_spec.js +++ b/spec/frontend/projects/new/components/new_project_push_tip_popover_spec.js @@ -37,7 +37,6 @@ describe('New project push tip popover', () => { }); afterEach(() => { - wrapper.destroy(); resetHTMLFixture(); }); diff --git a/spec/frontend/projects/new/components/new_project_url_select_spec.js b/spec/frontend/projects/new/components/new_project_url_select_spec.js index 67532cea61e..ceac4435282 100644 --- a/spec/frontend/projects/new/components/new_project_url_select_spec.js +++ b/spec/frontend/projects/new/components/new_project_url_select_spec.js @@ -3,8 +3,8 @@ import { GlDropdown, GlDropdownItem, GlDropdownSectionHeader, - GlSearchBoxByType, GlTruncate, + GlSearchBoxByType, } from '@gitlab/ui'; import { mount, shallowMount } from '@vue/test-utils'; import Vue, { nextTick } from 'vue'; @@ -12,6 +12,7 @@ import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; import { mockTracking, unmockTracking } from 'helpers/tracking_helper'; +import { stubComponent } from 'helpers/stub_component'; import { getIdFromGraphQLId } from '~/graphql_shared/utils'; import eventHub from '~/projects/new/event_hub'; import NewProjectUrlSelect from '~/projects/new/components/new_project_url_select.vue'; @@ -68,6 +69,7 @@ describe('NewProjectUrlSelect component', () => { }; let mockQueryResponse; + let focusInputSpy; const mountComponent = ({ search = '', @@ -78,6 +80,7 @@ describe('NewProjectUrlSelect component', () => { mockQueryResponse = jest.fn().mockResolvedValue({ data: queryResponse }); const requestHandlers = [[searchQuery, mockQueryResponse]]; const apolloProvider = createMockApollo(requestHandlers); + focusInputSpy = jest.fn(); return mountFn(NewProjectUrlSelect, { apolloProvider, @@ -87,13 +90,17 @@ describe('NewProjectUrlSelect component', () => { search, }; }, + stubs: { + GlSearchBoxByType: stubComponent(GlSearchBoxByType, { + methods: { focusInput: focusInputSpy }, + }), + }, }); }; const findButtonLabel = () => wrapper.findComponent(GlButton); const findDropdown = () => wrapper.findComponent(GlDropdown); const findSelectedPath = () => wrapper.findComponent(GlTruncate); - const findInput = () => wrapper.findComponent(GlSearchBoxByType); const findHiddenNamespaceInput = () => wrapper.find(`[name="${defaultProvide.inputName}`); const findHiddenSelectedNamespaceInput = () => @@ -111,10 +118,6 @@ describe('NewProjectUrlSelect component', () => { await waitForPromises(); }; - afterEach(() => { - wrapper.destroy(); - }); - it('renders the root url as a label', () => { wrapper = mountComponent(); @@ -177,13 +180,11 @@ describe('NewProjectUrlSelect component', () => { }); it('focuses on the input when the dropdown is opened', async () => { - wrapper = mountComponent({ mountFn: mount }); - - const spy = jest.spyOn(findInput().vm, 'focusInput'); + wrapper = mountComponent(); await showDropdown(); - expect(spy).toHaveBeenCalledTimes(1); + expect(focusInputSpy).toHaveBeenCalledTimes(1); }); it('renders expected dropdown items', async () => { @@ -246,7 +247,7 @@ describe('NewProjectUrlSelect component', () => { eventHub.$emit('select-template', getIdFromGraphQLId(id), fullPath); }); - it('filters the dropdown items to the selected group and children', async () => { + it('filters the dropdown items to the selected group and children', () => { const listItems = wrapper.findAll('li'); expect(listItems).toHaveLength(3); diff --git a/spec/frontend/projects/pipelines/charts/components/__snapshots__/ci_cd_analytics_area_chart_spec.js.snap b/spec/frontend/projects/pipelines/charts/components/__snapshots__/ci_cd_analytics_area_chart_spec.js.snap index fc51825f15b..61bcd44724c 100644 --- a/spec/frontend/projects/pipelines/charts/components/__snapshots__/ci_cd_analytics_area_chart_spec.js.snap +++ b/spec/frontend/projects/pipelines/charts/components/__snapshots__/ci_cd_analytics_area_chart_spec.js.snap @@ -8,20 +8,20 @@ exports[`CiCdAnalyticsAreaChart matches the snapshot 1`] = ` Some title </p> - <div> - <glareachart-stub - annotations="" - data="[object Object],[object Object]" - height="300" - legendaveragetext="Avg" - legendcurrenttext="Current" - legendlayout="inline" - legendmaxtext="Max" - legendmintext="Min" - option="[object Object]" - thresholds="" - width="0" - /> - </div> + <glareachart-stub + annotations="" + data="[object Object],[object Object]" + height="300" + legendaveragetext="Avg" + legendcurrenttext="Current" + legendlayout="inline" + legendmaxtext="Max" + legendmintext="Min" + legendseriesinfo="" + option="[object Object]" + responsive="" + thresholds="" + width="auto" + /> </div> `; diff --git a/spec/frontend/projects/pipelines/charts/components/app_spec.js b/spec/frontend/projects/pipelines/charts/components/app_spec.js index d8876349c5e..94f421239da 100644 --- a/spec/frontend/projects/pipelines/charts/components/app_spec.js +++ b/spec/frontend/projects/pipelines/charts/components/app_spec.js @@ -49,10 +49,6 @@ describe('ProjectsPipelinesChartsApp', () => { ); } - afterEach(() => { - wrapper.destroy(); - }); - const findGlTabs = () => wrapper.findComponent(GlTabs); const findAllGlTabs = () => wrapper.findAllComponents(GlTab); const findGlTabAtIndex = (index) => findAllGlTabs().at(index); diff --git a/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_area_chart_spec.js b/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_area_chart_spec.js index 2b523467379..5fc121b5c9f 100644 --- a/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_area_chart_spec.js +++ b/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_area_chart_spec.js @@ -28,11 +28,6 @@ describe('CiCdAnalyticsAreaChart', () => { }); }); - afterEach(() => { - wrapper.destroy(); - wrapper = null; - }); - it('matches the snapshot', () => { expect(wrapper.element).toMatchSnapshot(); }); diff --git a/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js b/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js index cf28eda5349..38760a724ff 100644 --- a/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js +++ b/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js @@ -47,13 +47,6 @@ describe('~/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue', ( }, }); - afterEach(() => { - if (wrapper) { - wrapper.destroy(); - wrapper = null; - } - }); - const findMetricsSlot = () => wrapper.findByTestId('metrics-slot'); const findSegmentedControl = () => wrapper.findComponent(SegmentedControlButtonGroup); diff --git a/spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js b/spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js index 8fb59f38ee1..ab2a12219e5 100644 --- a/spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js +++ b/spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js @@ -37,11 +37,6 @@ describe('~/projects/pipelines/charts/components/pipeline_charts.vue', () => { await waitForPromises(); }); - afterEach(() => { - wrapper.destroy(); - wrapper = null; - }); - describe('overall statistics', () => { it('displays the statistics list', () => { const list = wrapper.findComponent(StatisticsList); diff --git a/spec/frontend/projects/pipelines/charts/components/statistics_list_spec.js b/spec/frontend/projects/pipelines/charts/components/statistics_list_spec.js index 57a864cb2c4..24dbc628ce6 100644 --- a/spec/frontend/projects/pipelines/charts/components/statistics_list_spec.js +++ b/spec/frontend/projects/pipelines/charts/components/statistics_list_spec.js @@ -21,10 +21,6 @@ describe('StatisticsList', () => { }); }); - afterEach(() => { - wrapper.destroy(); - }); - it('displays the counts data with labels', () => { expect(wrapper.element).toMatchSnapshot(); }); diff --git a/spec/frontend/projects/prune_unreachable_objects_button_spec.js b/spec/frontend/projects/prune_unreachable_objects_button_spec.js index b345f264ca7..012b19ea3d3 100644 --- a/spec/frontend/projects/prune_unreachable_objects_button_spec.js +++ b/spec/frontend/projects/prune_unreachable_objects_button_spec.js @@ -22,16 +22,11 @@ describe('Project remove modal', () => { wrapper = shallowMountExtended(PruneObjectsButton, { propsData: defaultProps, directives: { - GlModal: createMockDirective(), + GlModal: createMockDirective('gl-modal'), }, }); }; - afterEach(() => { - wrapper.destroy(); - wrapper = null; - }); - describe('intialized', () => { beforeEach(() => { createComponent(); diff --git a/spec/frontend/projects/settings/branch_rules/components/edit/branch_dropdown_spec.js b/spec/frontend/projects/settings/branch_rules/components/edit/branch_dropdown_spec.js index 11f219c1f90..6d3317a5f78 100644 --- a/spec/frontend/projects/settings/branch_rules/components/edit/branch_dropdown_spec.js +++ b/spec/frontend/projects/settings/branch_rules/components/edit/branch_dropdown_spec.js @@ -8,10 +8,10 @@ import BranchDropdown, { import createMockApollo from 'helpers/mock_apollo_helper'; import branchesQuery from '~/projects/settings/branch_rules/queries/branches.query.graphql'; import waitForPromises from 'helpers/wait_for_promises'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; Vue.use(VueApollo); -jest.mock('~/flash'); +jest.mock('~/alert'); describe('Branch dropdown', () => { let wrapper; @@ -46,10 +46,6 @@ describe('Branch dropdown', () => { beforeEach(() => createComponent()); - afterEach(() => { - wrapper.destroy(); - }); - it('renders a GlDropdown component with the correct props', () => { expect(findGlDropdown().props()).toMatchObject({ text: value }); }); diff --git a/spec/frontend/projects/settings/branch_rules/components/edit/index_spec.js b/spec/frontend/projects/settings/branch_rules/components/edit/index_spec.js index 21e63fdb24d..e9982872e03 100644 --- a/spec/frontend/projects/settings/branch_rules/components/edit/index_spec.js +++ b/spec/frontend/projects/settings/branch_rules/components/edit/index_spec.js @@ -24,10 +24,6 @@ describe('Edit branch rule', () => { beforeEach(() => createComponent()); - afterEach(() => { - wrapper.destroy(); - }); - it('gets the branch param from url', () => { expect(getParameterByName).toHaveBeenCalledWith('branch'); }); diff --git a/spec/frontend/projects/settings/branch_rules/components/edit/protections/index_spec.js b/spec/frontend/projects/settings/branch_rules/components/edit/protections/index_spec.js index ee90ff8318f..14edaf31a1f 100644 --- a/spec/frontend/projects/settings/branch_rules/components/edit/protections/index_spec.js +++ b/spec/frontend/projects/settings/branch_rules/components/edit/protections/index_spec.js @@ -26,10 +26,6 @@ describe('Branch Protections', () => { beforeEach(() => createComponent()); - afterEach(() => { - wrapper.destroy(); - }); - it('renders a heading', () => { expect(findHeading().text()).toBe(i18n.protections); }); diff --git a/spec/frontend/projects/settings/branch_rules/components/edit/protections/merge_protections_spec.js b/spec/frontend/projects/settings/branch_rules/components/edit/protections/merge_protections_spec.js index b5fdc46d600..ca561ef87ec 100644 --- a/spec/frontend/projects/settings/branch_rules/components/edit/protections/merge_protections_spec.js +++ b/spec/frontend/projects/settings/branch_rules/components/edit/protections/merge_protections_spec.js @@ -24,10 +24,6 @@ describe('Merge Protections', () => { beforeEach(() => createComponent()); - afterEach(() => { - wrapper.destroy(); - }); - it('renders a form group with the correct label', () => { expect(findFormGroup().text()).toContain(i18n.allowedToMerge); }); diff --git a/spec/frontend/projects/settings/branch_rules/components/edit/protections/push_protections_spec.js b/spec/frontend/projects/settings/branch_rules/components/edit/protections/push_protections_spec.js index 60bb7a51dcb..82998640f17 100644 --- a/spec/frontend/projects/settings/branch_rules/components/edit/protections/push_protections_spec.js +++ b/spec/frontend/projects/settings/branch_rules/components/edit/protections/push_protections_spec.js @@ -24,10 +24,6 @@ describe('Push Protections', () => { beforeEach(() => createComponent()); - afterEach(() => { - wrapper.destroy(); - }); - it('renders a form group with the correct label', () => { expect(findFormGroup().attributes('label')).toBe(i18n.allowedToPush); }); diff --git a/spec/frontend/projects/settings/branch_rules/components/view/index_spec.js b/spec/frontend/projects/settings/branch_rules/components/view/index_spec.js index 714e0df596e..077995ab6e4 100644 --- a/spec/frontend/projects/settings/branch_rules/components/view/index_spec.js +++ b/spec/frontend/projects/settings/branch_rules/components/view/index_spec.js @@ -9,6 +9,10 @@ import Protection from '~/projects/settings/branch_rules/components/view/protect import { I18N, ALL_BRANCHES_WILDCARD, + REQUIRED_ICON, + NOT_REQUIRED_ICON, + REQUIRED_ICON_CLASS, + NOT_REQUIRED_ICON_CLASS, } from '~/projects/settings/branch_rules/components/view/constants'; import branchRulesQuery from 'ee_else_ce/projects/settings/branch_rules/queries/branch_rules_details.query.graphql'; import { sprintf } from '~/locale'; @@ -19,7 +23,7 @@ import { jest.mock('~/lib/utils/url_utility', () => ({ getParameterByName: jest.fn().mockReturnValue('main'), - mergeUrlParams: jest.fn().mockReturnValue('/branches?state=all&search=main'), + mergeUrlParams: jest.fn().mockReturnValue('/branches?state=all&search=%5Emain%24'), joinPaths: jest.fn(), })); @@ -39,12 +43,13 @@ describe('View branch rules', () => { let fakeApollo; const projectPath = 'test/testing'; const protectedBranchesPath = 'protected/branches'; - const branchProtectionsMockRequestHandler = jest - .fn() - .mockResolvedValue(branchProtectionsMockResponse); + const branchProtectionsMockRequestHandler = (response = branchProtectionsMockResponse) => + jest.fn().mockResolvedValue(response); - const createComponent = async () => { - fakeApollo = createMockApollo([[branchRulesQuery, branchProtectionsMockRequestHandler]]); + const createComponent = async (mockResponse) => { + fakeApollo = createMockApollo([ + [branchRulesQuery, branchProtectionsMockRequestHandler(mockResponse)], + ]); wrapper = shallowMountExtended(RuleView, { apolloProvider: fakeApollo, @@ -57,13 +62,13 @@ describe('View branch rules', () => { beforeEach(() => createComponent()); - afterEach(() => wrapper.destroy()); - const findBranchName = () => wrapper.findByTestId('branch'); const findBranchTitle = () => wrapper.findByTestId('branch-title'); const findBranchProtectionTitle = () => wrapper.findByText(I18N.protectBranchTitle); const findBranchProtections = () => wrapper.findAllComponents(Protection); - const findForcePushTitle = () => wrapper.findByText(I18N.allowForcePushDescription); + const findForcePushIcon = () => wrapper.findByTestId('force-push-icon'); + const findForcePushTitle = (title) => wrapper.findByText(title); + const findForcePushDescription = () => wrapper.findByText(I18N.forcePushDescription); const findApprovalsTitle = () => wrapper.findByText(I18N.approvalsTitle); const findStatusChecksTitle = () => wrapper.findByText(I18N.statusChecksTitle); const findMatchingBranchesLink = () => @@ -94,9 +99,12 @@ describe('View branch rules', () => { }); it('renders matching branches link', () => { + const mergeUrlParams = jest.spyOn(util, 'mergeUrlParams'); const matchingBranchesLink = findMatchingBranchesLink(); + + expect(mergeUrlParams).toHaveBeenCalledWith({ state: 'all', search: `^main$` }, ''); expect(matchingBranchesLink.exists()).toBe(true); - expect(matchingBranchesLink.attributes().href).toBe('/branches?state=all&search=main'); + expect(matchingBranchesLink.attributes().href).toBe('/branches?state=all&search=%5Emain%24'); }); it('renders a branch protection title', () => { @@ -123,9 +131,23 @@ describe('View branch rules', () => { }); }); - it('renders force push protection', () => { - expect(findForcePushTitle().exists()).toBe(true); - }); + it.each` + allowForcePush | iconName | iconClass | title + ${true} | ${REQUIRED_ICON} | ${REQUIRED_ICON_CLASS} | ${I18N.allowForcePushTitle} + ${false} | ${NOT_REQUIRED_ICON} | ${NOT_REQUIRED_ICON_CLASS} | ${I18N.doesNotAllowForcePushTitle} + `( + 'renders force push section with the correct icon, title and description', + async ({ allowForcePush, iconName, iconClass, title }) => { + const mockResponse = branchProtectionsMockResponse; + mockResponse.data.project.branchRules.nodes[0].branchProtection.allowForcePush = allowForcePush; + await createComponent(mockResponse); + + expect(findForcePushIcon().props('name')).toBe(iconName); + expect(findForcePushIcon().attributes('class')).toBe(iconClass); + expect(findForcePushTitle(title).exists()).toBe(true); + expect(findForcePushDescription().exists()).toBe(true); + }, + ); it('renders a branch protection component for merge rules', () => { expect(findBranchProtections().at(1).props()).toMatchObject({ diff --git a/spec/frontend/projects/settings/branch_rules/components/view/protection_row_spec.js b/spec/frontend/projects/settings/branch_rules/components/view/protection_row_spec.js index a98b156f94e..1bfd04e10a1 100644 --- a/spec/frontend/projects/settings/branch_rules/components/view/protection_row_spec.js +++ b/spec/frontend/projects/settings/branch_rules/components/view/protection_row_spec.js @@ -18,8 +18,6 @@ describe('Branch rule protection row', () => { beforeEach(() => createComponent()); - afterEach(() => wrapper.destroy()); - const findTitle = () => wrapper.findByText(protectionRowPropsMock.title); const findAvatarsInline = () => wrapper.findComponent(GlAvatarsInline); const findAvatarLinks = () => wrapper.findAllComponents(GlAvatarLink); diff --git a/spec/frontend/projects/settings/branch_rules/components/view/protection_spec.js b/spec/frontend/projects/settings/branch_rules/components/view/protection_spec.js index caf967b4257..f10d8d6d770 100644 --- a/spec/frontend/projects/settings/branch_rules/components/view/protection_spec.js +++ b/spec/frontend/projects/settings/branch_rules/components/view/protection_spec.js @@ -16,8 +16,6 @@ describe('Branch rule protection', () => { beforeEach(() => createComponent()); - afterEach(() => wrapper.destroy()); - const findCard = () => wrapper.findComponent(GlCard); const findHeader = () => wrapper.findByText(protectionPropsMock.header); const findLink = () => wrapper.findComponent(GlLink); diff --git a/spec/frontend/projects/settings/components/default_branch_selector_spec.js b/spec/frontend/projects/settings/components/default_branch_selector_spec.js index ca9a72663d2..9baea5c5517 100644 --- a/spec/frontend/projects/settings/components/default_branch_selector_spec.js +++ b/spec/frontend/projects/settings/components/default_branch_selector_spec.js @@ -19,10 +19,6 @@ describe('projects/settings/components/default_branch_selector', () => { }); }; - afterEach(() => { - wrapper.destroy(); - }); - beforeEach(() => { buildWrapper(); }); @@ -32,7 +28,6 @@ describe('projects/settings/components/default_branch_selector', () => { value: persistedDefaultBranch, enabledRefTypes: [REF_TYPE_BRANCHES], projectId, - refType: null, state: true, toggleButtonClass: null, translations: { diff --git a/spec/frontend/projects/settings/components/new_access_dropdown_spec.js b/spec/frontend/projects/settings/components/new_access_dropdown_spec.js index 26297d0c3ff..f3e536de703 100644 --- a/spec/frontend/projects/settings/components/new_access_dropdown_spec.js +++ b/spec/frontend/projects/settings/components/new_access_dropdown_spec.js @@ -89,15 +89,12 @@ describe('Access Level Dropdown', () => { }); }; - afterEach(() => { - wrapper.destroy(); - }); - const findDropdown = () => wrapper.findComponent(GlDropdown); const findDropdownToggleLabel = () => findDropdown().props('text'); const findAllDropdownItems = () => findDropdown().findAllComponents(GlDropdownItem); const findAllDropdownHeaders = () => findDropdown().findAllComponents(GlDropdownSectionHeader); const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType); + const findDeployKeyDropdownItem = () => wrapper.findByTestId('deploy_key-dropdown-item'); const findDropdownItemWithText = (items, text) => items.filter((item) => item.text().includes(text)).at(0); @@ -142,6 +139,21 @@ describe('Access Level Dropdown', () => { it('renders dropdown item for each access level type', () => { expect(findAllDropdownItems()).toHaveLength(12); }); + + it.each` + accessLevel | shouldRenderDeployKeyItems + ${ACCESS_LEVELS.PUSH} | ${true} + ${ACCESS_LEVELS.CREATE} | ${true} + ${ACCESS_LEVELS.MERGE} | ${false} + `( + 'conditionally renders deploy keys based on access levels', + async ({ accessLevel, shouldRenderDeployKeyItems }) => { + createComponent({ accessLevel }); + await waitForPromises(); + + expect(findDeployKeyDropdownItem().exists()).toBe(shouldRenderDeployKeyItems); + }, + ); }); describe('toggleLabel', () => { diff --git a/spec/frontend/projects/settings/components/shared_runners_toggle_spec.js b/spec/frontend/projects/settings/components/shared_runners_toggle_spec.js index f82ad80135e..f28bc13895e 100644 --- a/spec/frontend/projects/settings/components/shared_runners_toggle_spec.js +++ b/spec/frontend/projects/settings/components/shared_runners_toggle_spec.js @@ -1,7 +1,7 @@ -import { GlAlert, GlToggle, GlTooltip } from '@gitlab/ui'; -import { shallowMount } from '@vue/test-utils'; +import { GlToggle } from '@gitlab/ui'; import MockAxiosAdapter from 'axios-mock-adapter'; import { nextTick } from 'vue'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import waitForPromises from 'helpers/wait_for_promises'; import axios from '~/lib/utils/axios_utils'; import { HTTP_STATUS_OK, HTTP_STATUS_UNAUTHORIZED } from '~/lib/utils/http_status'; @@ -9,14 +9,14 @@ import SharedRunnersToggleComponent from '~/projects/settings/components/shared_ const TEST_UPDATE_PATH = '/test/update_shared_runners'; -jest.mock('~/flash'); +jest.mock('~/alert'); describe('projects/settings/components/shared_runners', () => { let wrapper; let mockAxios; const createComponent = (props = {}) => { - wrapper = shallowMount(SharedRunnersToggleComponent, { + wrapper = shallowMountExtended(SharedRunnersToggleComponent, { propsData: { isEnabled: false, isDisabledAndUnoverridable: false, @@ -28,9 +28,9 @@ describe('projects/settings/components/shared_runners', () => { }); }; - const findErrorAlert = () => wrapper.findComponent(GlAlert); + const findErrorAlert = () => wrapper.findByTestId('error-alert'); + const findUnoverridableAlert = () => wrapper.findByTestId('unoverridable-alert'); const findSharedRunnersToggle = () => wrapper.findComponent(GlToggle); - const findToggleTooltip = () => wrapper.findComponent(GlTooltip); const getToggleValue = () => findSharedRunnersToggle().props('value'); const isToggleLoading = () => findSharedRunnersToggle().props('isLoading'); const isToggleDisabled = () => findSharedRunnersToggle().props('disabled'); @@ -41,8 +41,6 @@ describe('projects/settings/components/shared_runners', () => { }); afterEach(() => { - wrapper.destroy(); - wrapper = null; mockAxios.restore(); }); @@ -57,8 +55,8 @@ describe('projects/settings/components/shared_runners', () => { expect(isToggleDisabled()).toBe(true); }); - it('tooltip should exist explaining why the toggle is disabled', () => { - expect(findToggleTooltip().exists()).toBe(true); + it('alert should exist explaining why the toggle is disabled', () => { + expect(findUnoverridableAlert().exists()).toBe(true); }); }); @@ -74,7 +72,7 @@ describe('projects/settings/components/shared_runners', () => { it('loading icon, error message, and tooltip should not exist', () => { expect(isToggleLoading()).toBe(false); expect(findErrorAlert().exists()).toBe(false); - expect(findToggleTooltip().exists()).toBe(false); + expect(findUnoverridableAlert().exists()).toBe(false); }); describe('with shared runners DISABLED', () => { diff --git a/spec/frontend/projects/settings/components/transfer_project_form_spec.js b/spec/frontend/projects/settings/components/transfer_project_form_spec.js index e091f3e25c3..e12938c3bab 100644 --- a/spec/frontend/projects/settings/components/transfer_project_form_spec.js +++ b/spec/frontend/projects/settings/components/transfer_project_form_spec.js @@ -31,10 +31,6 @@ describe('Transfer project form', () => { const findTransferLocations = () => wrapper.findComponent(TransferLocations); const findConfirmDanger = () => wrapper.findComponent(ConfirmDanger); - afterEach(() => { - wrapper.destroy(); - }); - it('renders the namespace selector and passes `groupTransferLocationsApiMethod` prop', () => { createComponent(); @@ -53,7 +49,7 @@ describe('Transfer project form', () => { it('disables the confirm button by default', () => { createComponent(); - expect(findConfirmDanger().attributes('disabled')).toBe('true'); + expect(findConfirmDanger().attributes('disabled')).toBeDefined(); }); describe('with a selected namespace', () => { @@ -68,17 +64,17 @@ describe('Transfer project form', () => { expect(findTransferLocations().props('value')).toEqual(selectedItem); }); - it('emits the `selectTransferLocation` event when a namespace is selected', async () => { + it('emits the `selectTransferLocation` event when a namespace is selected', () => { const args = [selectedItem.id]; expect(wrapper.emitted('selectTransferLocation')).toEqual([args]); }); - it('enables the confirm button', async () => { + it('enables the confirm button', () => { expect(findConfirmDanger().attributes('disabled')).toBeUndefined(); }); - it('clicking the confirm button emits the `confirm` event', async () => { + it('clicking the confirm button emits the `confirm` event', () => { findConfirmDanger().vm.$emit('confirm'); expect(wrapper.emitted('confirm')).toBeDefined(); diff --git a/spec/frontend/projects/settings/repository/branch_rules/app_spec.js b/spec/frontend/projects/settings/repository/branch_rules/app_spec.js index 56b39f04580..dd534bec25d 100644 --- a/spec/frontend/projects/settings/repository/branch_rules/app_spec.js +++ b/spec/frontend/projects/settings/repository/branch_rules/app_spec.js @@ -7,7 +7,7 @@ import { mountExtended } from 'helpers/vue_test_utils_helper'; import BranchRules from '~/projects/settings/repository/branch_rules/app.vue'; import BranchRule from '~/projects/settings/repository/branch_rules/components/branch_rule.vue'; import branchRulesQuery from 'ee_else_ce/projects/settings/repository/branch_rules/graphql/queries/branch_rules.query.graphql'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import { branchRulesMockResponse, appProvideMock, @@ -22,7 +22,7 @@ import { expandSection } from '~/settings_panels'; import { scrollToElement } from '~/lib/utils/common_utils'; import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; -jest.mock('~/flash'); +jest.mock('~/alert'); jest.mock('~/settings_panels'); jest.mock('~/lib/utils/common_utils'); @@ -41,7 +41,7 @@ describe('Branch rules app', () => { apolloProvider: fakeApollo, provide: appProvideMock, stubs: { GlModal: stubComponent(GlModal, { template: RENDER_ALL_SLOTS_TEMPLATE }) }, - directives: { GlModal: createMockDirective() }, + directives: { GlModal: createMockDirective('gl-modal') }, }); await waitForPromises(); diff --git a/spec/frontend/projects/settings/repository/branch_rules/components/branch_rule_spec.js b/spec/frontend/projects/settings/repository/branch_rules/components/branch_rule_spec.js index 8d0fd390e35..8bea84f4429 100644 --- a/spec/frontend/projects/settings/repository/branch_rules/components/branch_rule_spec.js +++ b/spec/frontend/projects/settings/repository/branch_rules/components/branch_rule_spec.js @@ -71,8 +71,10 @@ describe('Branch rule', () => { }); it('renders a detail button with the correct href', () => { + const encodedBranchName = encodeURIComponent(branchRulePropsMock.name); + expect(findDetailsButton().attributes('href')).toBe( - `${branchRuleProvideMock.branchRulesPath}?branch=${branchRulePropsMock.name}`, + `${branchRuleProvideMock.branchRulesPath}?branch=${encodedBranchName}`, ); }); }); diff --git a/spec/frontend/projects/settings/repository/branch_rules/mock_data.js b/spec/frontend/projects/settings/repository/branch_rules/mock_data.js index de7f6c8b88d..d169397241d 100644 --- a/spec/frontend/projects/settings/repository/branch_rules/mock_data.js +++ b/spec/frontend/projects/settings/repository/branch_rules/mock_data.js @@ -74,7 +74,7 @@ export const branchRuleProvideMock = { }; export const branchRulePropsMock = { - name: 'main', + name: 'branch-with-$speci@l-#-chars', isDefault: true, matchingBranchesCount: 1, branchProtection: { diff --git a/spec/frontend/projects/settings/topics/components/topics_token_selector_spec.js b/spec/frontend/projects/settings/topics/components/topics_token_selector_spec.js index 8b8e7d1454d..b2c03352cdc 100644 --- a/spec/frontend/projects/settings/topics/components/topics_token_selector_spec.js +++ b/spec/frontend/projects/settings/topics/components/topics_token_selector_spec.js @@ -64,7 +64,6 @@ describe('TopicsTokenSelector', () => { }); afterEach(() => { - wrapper.destroy(); div.remove(); input.remove(); }); @@ -84,7 +83,7 @@ describe('TopicsTokenSelector', () => { }); }); - it('passes topic title to the avatar', async () => { + it('passes topic title to the avatar', () => { createComponent(); const avatars = findAllAvatars(); diff --git a/spec/frontend/projects/settings/utils_spec.js b/spec/frontend/projects/settings/utils_spec.js index 319aa4000b5..d85f43778b1 100644 --- a/spec/frontend/projects/settings/utils_spec.js +++ b/spec/frontend/projects/settings/utils_spec.js @@ -1,4 +1,5 @@ -import { getAccessLevels } from '~/projects/settings/utils'; +import { getAccessLevels, generateRefDestinationPath } from '~/projects/settings/utils'; +import setWindowLocation from 'helpers/set_window_location_helper'; import { pushAccessLevelsMockResponse, pushAccessLevelsMockResult } from './mock_data'; describe('Utils', () => { @@ -8,4 +9,25 @@ describe('Utils', () => { expect(pushAccessLevels).toEqual(pushAccessLevelsMockResult); }); }); + + describe('generateRefDestinationPath', () => { + const projectRootPath = 'http://test.host/root/Project1'; + const settingsCi = '-/settings/ci_cd'; + + it.each` + currentPath | selectedRef | result + ${`${projectRootPath}`} | ${undefined} | ${`${projectRootPath}`} + ${`${projectRootPath}`} | ${'test'} | ${`${projectRootPath}`} + ${`${projectRootPath}/${settingsCi}`} | ${'test'} | ${`${projectRootPath}/${settingsCi}?ref=test`} + ${`${projectRootPath}/${settingsCi}`} | ${'branch-hyphen'} | ${`${projectRootPath}/${settingsCi}?ref=branch-hyphen`} + ${`${projectRootPath}/${settingsCi}`} | ${'test/branch'} | ${`${projectRootPath}/${settingsCi}?ref=test%2Fbranch`} + ${`${projectRootPath}/${settingsCi}`} | ${'test/branch-hyphen'} | ${`${projectRootPath}/${settingsCi}?ref=test%2Fbranch-hyphen`} + `( + 'generates the correct destination path for the `$selectedRef` ref and current url $currentPath by outputting $result', + ({ currentPath, selectedRef, result }) => { + setWindowLocation(currentPath); + expect(generateRefDestinationPath(selectedRef)).toBe(result); + }, + ); + }); }); diff --git a/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js b/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js index 5fc9f9ba629..86e4e88e3cf 100644 --- a/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js +++ b/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js @@ -41,7 +41,6 @@ describe('ServiceDeskRoot', () => { afterEach(() => { axiosMock.restore(); - wrapper.destroy(); if (spy) { spy.mockRestore(); } @@ -79,7 +78,7 @@ describe('ServiceDeskRoot', () => { const alertBodyLink = alertEl.findComponent(GlLink); expect(alertBodyLink.exists()).toBe(true); expect(alertBodyLink.attributes('href')).toBe( - '/help/user/project/service_desk.html#using-a-custom-email-address', + '/help/user/project/service_desk.html#use-a-custom-email-address', ); expect(alertBodyLink.text()).toBe('How do I create a custom email address?'); }); @@ -148,7 +147,7 @@ describe('ServiceDeskRoot', () => { await waitForPromises(); }); - it('sends a request to update template', async () => { + it('sends a request to update template', () => { expect(spy).toHaveBeenCalledWith(provideData.endpoint, { issue_template_key: 'Bug', outgoing_name: 'GitLab Support Bot', diff --git a/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js b/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js index f9762491507..84eafc3d0f3 100644 --- a/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js +++ b/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js @@ -27,12 +27,6 @@ describe('ServiceDeskSetting', () => { }), ); - afterEach(() => { - if (wrapper) { - wrapper.destroy(); - } - }); - describe('when isEnabled=true', () => { describe('only isEnabled', () => { describe('as project admin', () => { diff --git a/spec/frontend/projects/settings_service_desk/components/service_desk_template_dropdown_spec.js b/spec/frontend/projects/settings_service_desk/components/service_desk_template_dropdown_spec.js index 6adcfbe8157..7090db5cad7 100644 --- a/spec/frontend/projects/settings_service_desk/components/service_desk_template_dropdown_spec.js +++ b/spec/frontend/projects/settings_service_desk/components/service_desk_template_dropdown_spec.js @@ -19,12 +19,6 @@ describe('ServiceDeskTemplateDropdown', () => { }), ); - afterEach(() => { - if (wrapper) { - wrapper.destroy(); - } - }); - describe('templates dropdown', () => { it('renders a dropdown to choose a template', () => { wrapper = createComponent(); diff --git a/spec/frontend/projects/terraform_notification/terraform_notification_spec.js b/spec/frontend/projects/terraform_notification/terraform_notification_spec.js index 6576ce70d60..1d0faebbcb2 100644 --- a/spec/frontend/projects/terraform_notification/terraform_notification_spec.js +++ b/spec/frontend/projects/terraform_notification/terraform_notification_spec.js @@ -41,10 +41,6 @@ describe('TerraformNotificationBanner', () => { trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn); }); - afterEach(() => { - wrapper.destroy(); - }); - describe('when user has already dismissed the banner', () => { beforeEach(() => { createComponent({ |