diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-02-18 09:45:46 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-02-18 09:45:46 +0000 |
commit | a7b3560714b4d9cc4ab32dffcd1f74a284b93580 (patch) | |
tree | 7452bd5c3545c2fa67a28aa013835fb4fa071baf /spec/frontend/groups | |
parent | ee9173579ae56a3dbfe5afe9f9410c65bb327ca7 (diff) | |
download | gitlab-ce-a7b3560714b4d9cc4ab32dffcd1f74a284b93580.tar.gz |
Add latest changes from gitlab-org/gitlab@14-8-stable-eev14.8.0-rc42
Diffstat (limited to 'spec/frontend/groups')
-rw-r--r-- | spec/frontend/groups/components/app_spec.js | 66 | ||||
-rw-r--r-- | spec/frontend/groups/components/group_folder_spec.js | 6 | ||||
-rw-r--r-- | spec/frontend/groups/components/groups_spec.js | 26 | ||||
-rw-r--r-- | spec/frontend/groups/components/invite_members_banner_spec.js | 4 | ||||
-rw-r--r-- | spec/frontend/groups/components/item_actions_spec.js | 38 | ||||
-rw-r--r-- | spec/frontend/groups/components/transfer_group_form_spec.js | 131 | ||||
-rw-r--r-- | spec/frontend/groups/landing_spec.js | 5 | ||||
-rw-r--r-- | spec/frontend/groups/transfer_edit_spec.js | 31 |
8 files changed, 209 insertions, 98 deletions
diff --git a/spec/frontend/groups/components/app_spec.js b/spec/frontend/groups/components/app_spec.js index bc8c6460cf4..848e50c86ba 100644 --- a/spec/frontend/groups/components/app_spec.js +++ b/spec/frontend/groups/components/app_spec.js @@ -1,7 +1,7 @@ import { GlModal, GlLoadingIcon } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import AxiosMockAdapter from 'axios-mock-adapter'; -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import waitForPromises from 'helpers/wait_for_promises'; import createFlash from '~/flash'; import appComponent from '~/groups/components/app.vue'; @@ -58,7 +58,7 @@ describe('AppComponent', () => { wrapper = null; }); - beforeEach(() => { + beforeEach(async () => { mock = new AxiosMockAdapter(axios); mock.onGet('/dashboard/groups.json').reply(200, mockGroups); Vue.component('GroupFolder', groupFolderComponent); @@ -66,7 +66,7 @@ describe('AppComponent', () => { createShallowComponent(); getGroupsSpy = jest.spyOn(vm.service, 'getGroups'); - return vm.$nextTick(); + await nextTick(); }); describe('computed', () => { @@ -280,6 +280,7 @@ describe('AppComponent', () => { expect(vm.targetParentGroup).toBe(null); vm.showLeaveGroupModal(group, mockParentGroupItem); + expect(vm.isModalVisible).toBe(true); expect(vm.targetGroup).not.toBe(null); expect(vm.targetParentGroup).not.toBe(null); }); @@ -290,6 +291,7 @@ describe('AppComponent', () => { expect(vm.groupLeaveConfirmationMessage).toBe(''); vm.showLeaveGroupModal(group, mockParentGroupItem); + expect(vm.isModalVisible).toBe(true); expect(vm.groupLeaveConfirmationMessage).toBe( `Are you sure you want to leave the "${group.fullName}" group?`, ); @@ -397,66 +399,60 @@ describe('AppComponent', () => { }); describe('created', () => { - it('should bind event listeners on eventHub', () => { + it('should bind event listeners on eventHub', async () => { jest.spyOn(eventHub, '$on').mockImplementation(() => {}); createShallowComponent(); - return vm.$nextTick().then(() => { - expect(eventHub.$on).toHaveBeenCalledWith('fetchPage', expect.any(Function)); - expect(eventHub.$on).toHaveBeenCalledWith('toggleChildren', expect.any(Function)); - expect(eventHub.$on).toHaveBeenCalledWith('showLeaveGroupModal', expect.any(Function)); - expect(eventHub.$on).toHaveBeenCalledWith('updatePagination', expect.any(Function)); - expect(eventHub.$on).toHaveBeenCalledWith('updateGroups', expect.any(Function)); - }); + await nextTick(); + expect(eventHub.$on).toHaveBeenCalledWith('fetchPage', expect.any(Function)); + expect(eventHub.$on).toHaveBeenCalledWith('toggleChildren', expect.any(Function)); + expect(eventHub.$on).toHaveBeenCalledWith('showLeaveGroupModal', expect.any(Function)); + expect(eventHub.$on).toHaveBeenCalledWith('updatePagination', expect.any(Function)); + expect(eventHub.$on).toHaveBeenCalledWith('updateGroups', expect.any(Function)); }); - it('should initialize `searchEmptyMessage` prop with correct string when `hideProjects` is `false`', () => { + it('should initialize `searchEmptyMessage` prop with correct string when `hideProjects` is `false`', async () => { createShallowComponent(); - return vm.$nextTick().then(() => { - expect(vm.searchEmptyMessage).toBe('No groups or projects matched your search'); - }); + await nextTick(); + expect(vm.searchEmptyMessage).toBe('No groups or projects matched your search'); }); - it('should initialize `searchEmptyMessage` prop with correct string when `hideProjects` is `true`', () => { + it('should initialize `searchEmptyMessage` prop with correct string when `hideProjects` is `true`', async () => { createShallowComponent(true); - return vm.$nextTick().then(() => { - expect(vm.searchEmptyMessage).toBe('No groups matched your search'); - }); + await nextTick(); + expect(vm.searchEmptyMessage).toBe('No groups matched your search'); }); }); describe('beforeDestroy', () => { - it('should unbind event listeners on eventHub', () => { + it('should unbind event listeners on eventHub', async () => { jest.spyOn(eventHub, '$off').mockImplementation(() => {}); createShallowComponent(); wrapper.destroy(); - return vm.$nextTick().then(() => { - expect(eventHub.$off).toHaveBeenCalledWith('fetchPage', expect.any(Function)); - expect(eventHub.$off).toHaveBeenCalledWith('toggleChildren', expect.any(Function)); - expect(eventHub.$off).toHaveBeenCalledWith('showLeaveGroupModal', expect.any(Function)); - expect(eventHub.$off).toHaveBeenCalledWith('updatePagination', expect.any(Function)); - expect(eventHub.$off).toHaveBeenCalledWith('updateGroups', expect.any(Function)); - }); + await nextTick(); + expect(eventHub.$off).toHaveBeenCalledWith('fetchPage', expect.any(Function)); + expect(eventHub.$off).toHaveBeenCalledWith('toggleChildren', expect.any(Function)); + expect(eventHub.$off).toHaveBeenCalledWith('showLeaveGroupModal', expect.any(Function)); + expect(eventHub.$off).toHaveBeenCalledWith('updatePagination', expect.any(Function)); + expect(eventHub.$off).toHaveBeenCalledWith('updateGroups', expect.any(Function)); }); }); describe('template', () => { - it('should render loading icon', () => { + it('should render loading icon', async () => { vm.isLoading = true; - return vm.$nextTick().then(() => { - expect(wrapper.find(GlLoadingIcon).exists()).toBe(true); - }); + await nextTick(); + expect(wrapper.find(GlLoadingIcon).exists()).toBe(true); }); - it('should render groups tree', () => { + it('should render groups tree', async () => { vm.store.state.groups = [mockParentGroupItem]; vm.isLoading = false; - return vm.$nextTick().then(() => { - expect(vm.$el.querySelector('.groups-list-tree-container')).toBeDefined(); - }); + await nextTick(); + expect(vm.$el.querySelector('.groups-list-tree-container')).toBeDefined(); }); it('renders modal confirmation dialog', () => { diff --git a/spec/frontend/groups/components/group_folder_spec.js b/spec/frontend/groups/components/group_folder_spec.js index 1d8e10479b6..98b7c2dd6c6 100644 --- a/spec/frontend/groups/components/group_folder_spec.js +++ b/spec/frontend/groups/components/group_folder_spec.js @@ -1,4 +1,4 @@ -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import groupFolderComponent from '~/groups/components/group_folder.vue'; import groupItemComponent from '~/groups/components/group_item.vue'; @@ -18,13 +18,13 @@ const createComponent = (groups = mockGroups, parentGroup = mockParentGroupItem) describe('GroupFolderComponent', () => { let vm; - beforeEach(() => { + beforeEach(async () => { Vue.component('GroupItem', groupItemComponent); vm = createComponent(); vm.$mount(); - return Vue.nextTick(); + await nextTick(); }); afterEach(() => { diff --git a/spec/frontend/groups/components/groups_spec.js b/spec/frontend/groups/components/groups_spec.js index 0ec1ef5a49e..590b4fb3d57 100644 --- a/spec/frontend/groups/components/groups_spec.js +++ b/spec/frontend/groups/components/groups_spec.js @@ -1,4 +1,4 @@ -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import mountComponent from 'helpers/vue_mount_component_helper'; import groupFolderComponent from '~/groups/components/group_folder.vue'; @@ -21,13 +21,13 @@ const createComponent = (searchEmpty = false) => { describe('GroupsComponent', () => { let vm; - beforeEach(() => { + beforeEach(async () => { Vue.component('GroupFolder', groupFolderComponent); Vue.component('GroupItem', groupItemComponent); vm = createComponent(); - return vm.$nextTick(); + await nextTick(); }); afterEach(() => { @@ -52,20 +52,18 @@ describe('GroupsComponent', () => { }); describe('template', () => { - it('should render component template correctly', () => { - return vm.$nextTick().then(() => { - expect(vm.$el.querySelector('.groups-list-tree-container')).toBeDefined(); - expect(vm.$el.querySelector('.group-list-tree')).toBeDefined(); - expect(vm.$el.querySelector('.gl-pagination')).toBeDefined(); - expect(vm.$el.querySelectorAll('.has-no-search-results').length).toBe(0); - }); + it('should render component template correctly', async () => { + await nextTick(); + expect(vm.$el.querySelector('.groups-list-tree-container')).toBeDefined(); + expect(vm.$el.querySelector('.group-list-tree')).toBeDefined(); + expect(vm.$el.querySelector('.gl-pagination')).toBeDefined(); + expect(vm.$el.querySelectorAll('.has-no-search-results').length).toBe(0); }); - it('should render empty search message when `searchEmpty` is `true`', () => { + it('should render empty search message when `searchEmpty` is `true`', async () => { vm.searchEmpty = true; - return vm.$nextTick().then(() => { - expect(vm.$el.querySelector('.has-no-search-results')).toBeDefined(); - }); + await nextTick(); + expect(vm.$el.querySelector('.has-no-search-results')).toBeDefined(); }); }); }); diff --git a/spec/frontend/groups/components/invite_members_banner_spec.js b/spec/frontend/groups/components/invite_members_banner_spec.js index c81edad499c..1924f400861 100644 --- a/spec/frontend/groups/components/invite_members_banner_spec.js +++ b/spec/frontend/groups/components/invite_members_banner_spec.js @@ -1,6 +1,7 @@ import { GlBanner } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; +import { nextTick } from 'vue'; import { mockTracking, unmockTracking } from 'helpers/tracking_helper'; import InviteMembersBanner from '~/groups/components/invite_members_banner.vue'; import eventHub from '~/invite_members/event_hub'; @@ -75,7 +76,6 @@ describe('InviteMembersBanner', () => { it('calls openModal through the eventHub', () => { expect(eventHub.$emit).toHaveBeenCalledWith('openModal', { - inviteeType: 'members', source: 'invite_members_banner', }); }); @@ -140,7 +140,7 @@ describe('InviteMembersBanner', () => { expect(wrapper.find(GlBanner).exists()).toBe(true); wrapper.find(GlBanner).vm.$emit('close'); - await wrapper.vm.$nextTick(); + await nextTick(); expect(wrapper.find(GlBanner).exists()).toBe(false); }); }); diff --git a/spec/frontend/groups/components/item_actions_spec.js b/spec/frontend/groups/components/item_actions_spec.js index ffbdf9b1aa6..3ceb038dd3c 100644 --- a/spec/frontend/groups/components/item_actions_spec.js +++ b/spec/frontend/groups/components/item_actions_spec.js @@ -1,4 +1,4 @@ -import { shallowMount } from '@vue/test-utils'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import ItemActions from '~/groups/components/item_actions.vue'; import eventHub from '~/groups/event_hub'; import { mockParentGroupItem, mockChildren } from '../mock_data'; @@ -13,7 +13,7 @@ describe('ItemActions', () => { }; const createComponent = (props = {}) => { - wrapper = shallowMount(ItemActions, { + wrapper = shallowMountExtended(ItemActions, { propsData: { ...defaultProps, ...props }, }); }; @@ -23,8 +23,10 @@ describe('ItemActions', () => { wrapper = null; }); - const findEditGroupBtn = () => wrapper.find('[data-testid="edit-group-btn"]'); - const findLeaveGroupBtn = () => wrapper.find('[data-testid="leave-group-btn"]'); + const findEditGroupBtn = () => wrapper.findByTestId(`edit-group-${mockParentGroupItem.id}-btn`); + const findLeaveGroupBtn = () => wrapper.findByTestId(`leave-group-${mockParentGroupItem.id}-btn`); + const findRemoveGroupBtn = () => + wrapper.findByTestId(`remove-group-${mockParentGroupItem.id}-btn`); describe('template', () => { let group; @@ -34,6 +36,7 @@ describe('ItemActions', () => { ...mockParentGroupItem, canEdit: true, canLeave: true, + canRemove: true, }; createComponent({ group }); }); @@ -41,21 +44,21 @@ describe('ItemActions', () => { it('renders component template correctly', () => { createComponent(); - expect(wrapper.classes()).toContain('controls'); + expect(wrapper.classes()).toContain('gl-display-flex', 'gl-justify-content-end', 'gl-ml-5'); }); - it('renders "Edit group" button with correct attribute values', () => { + it('renders "Edit" group button with correct attribute values', () => { const button = findEditGroupBtn(); expect(button.exists()).toBe(true); - expect(button.props('icon')).toBe('pencil'); - expect(button.attributes('aria-label')).toBe('Edit group'); + expect(button.attributes('href')).toBe(mockParentGroupItem.editPath); }); - it('renders "Leave this group" button with correct attribute values', () => { - const button = findLeaveGroupBtn(); + it('renders "Delete" group button with correct attribute values', () => { + const button = findRemoveGroupBtn(); expect(button.exists()).toBe(true); - expect(button.props('icon')).toBe('leave'); - expect(button.attributes('aria-label')).toBe('Leave this group'); + expect(button.attributes('href')).toBe( + `${mockParentGroupItem.editPath}#js-remove-group-form`, + ); }); it('emits `showLeaveGroupModal` event in the event hub', () => { @@ -103,4 +106,15 @@ describe('ItemActions', () => { expect(findEditGroupBtn().exists()).toBe(false); }); + + it('does not render delete button if group can not be edited', () => { + createComponent({ + group: { + ...mockParentGroupItem, + canRemove: false, + }, + }); + + expect(findRemoveGroupBtn().exists()).toBe(false); + }); }); diff --git a/spec/frontend/groups/components/transfer_group_form_spec.js b/spec/frontend/groups/components/transfer_group_form_spec.js new file mode 100644 index 00000000000..6dc760f4f7c --- /dev/null +++ b/spec/frontend/groups/components/transfer_group_form_spec.js @@ -0,0 +1,131 @@ +import { GlAlert, GlSprintf } from '@gitlab/ui'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import Component from '~/groups/components/transfer_group_form.vue'; +import ConfirmDanger from '~/vue_shared/components/confirm_danger/confirm_danger.vue'; +import NamespaceSelect from '~/vue_shared/components/namespace_select/namespace_select.vue'; + +describe('Transfer group form', () => { + let wrapper; + + const confirmButtonText = 'confirm'; + const confirmationPhrase = 'confirmation-phrase'; + const paidGroupHelpLink = 'some/fake/link'; + const groupNamespaces = [ + { + id: 1, + humanName: 'Group 1', + }, + { + id: 2, + humanName: 'Group 2', + }, + ]; + + const defaultProps = { + groupNamespaces, + paidGroupHelpLink, + isPaidGroup: false, + confirmationPhrase, + confirmButtonText, + }; + + const createComponent = (propsData = {}) => + shallowMountExtended(Component, { + propsData: { + ...defaultProps, + ...propsData, + }, + stubs: { GlSprintf }, + }); + + const findAlert = () => wrapper.findComponent(GlAlert); + const findConfirmDanger = () => wrapper.findComponent(ConfirmDanger); + const findNamespaceSelect = () => wrapper.findComponent(NamespaceSelect); + const findHiddenInput = () => wrapper.find('[name="new_parent_group_id"]'); + + afterEach(() => { + wrapper.destroy(); + }); + + describe('default', () => { + beforeEach(() => { + wrapper = createComponent(); + }); + + it('renders the namespace select component', () => { + expect(findNamespaceSelect().exists()).toBe(true); + }); + + it('sets the namespace select properties', () => { + expect(findNamespaceSelect().props()).toMatchObject({ + defaultText: 'Select parent group', + fullWidth: false, + includeHeaders: false, + emptyNamespaceTitle: 'No parent group', + includeEmptyNamespace: true, + groupNamespaces, + }); + }); + + it('renders the hidden input field', () => { + expect(findHiddenInput().exists()).toBe(true); + expect(findHiddenInput().attributes('value')).toBeUndefined(); + }); + + it('does not render the alert message', () => { + expect(findAlert().exists()).toBe(false); + }); + + it('renders the confirm danger component', () => { + expect(findConfirmDanger().exists()).toBe(true); + }); + + it('sets the confirm danger properties', () => { + expect(findConfirmDanger().props()).toMatchObject({ + buttonClass: 'qa-transfer-button', + disabled: true, + buttonText: confirmButtonText, + phrase: confirmationPhrase, + }); + }); + }); + + describe('with a selected project', () => { + const [firstGroup] = groupNamespaces; + beforeEach(() => { + wrapper = createComponent(); + findNamespaceSelect().vm.$emit('select', firstGroup); + }); + + it('sets the confirm danger disabled property to false', () => { + expect(findConfirmDanger().props()).toMatchObject({ disabled: false }); + }); + + it('sets the hidden input field', () => { + expect(findHiddenInput().exists()).toBe(true); + expect(parseInt(findHiddenInput().attributes('value'), 10)).toBe(firstGroup.id); + }); + + it('emits "confirm" event when the danger modal is confirmed', () => { + expect(wrapper.emitted('confirm')).toBeUndefined(); + + findConfirmDanger().vm.$emit('confirm'); + + expect(wrapper.emitted('confirm')).toHaveLength(1); + }); + }); + + describe('isPaidGroup = true', () => { + beforeEach(() => { + wrapper = createComponent({ isPaidGroup: true }); + }); + + it('disables the transfer button', () => { + expect(findConfirmDanger().props()).toMatchObject({ disabled: true }); + }); + + it('hides the namespace selector button', () => { + expect(findNamespaceSelect().exists()).toBe(false); + }); + }); +}); diff --git a/spec/frontend/groups/landing_spec.js b/spec/frontend/groups/landing_spec.js index f90f541eb96..d60adea202b 100644 --- a/spec/frontend/groups/landing_spec.js +++ b/spec/frontend/groups/landing_spec.js @@ -159,7 +159,10 @@ describe('Landing', () => { }); it('should call Cookies.set', () => { - expect(Cookies.set).toHaveBeenCalledWith(test.cookieName, 'true', { expires: 365 }); + expect(Cookies.set).toHaveBeenCalledWith(test.cookieName, 'true', { + expires: 365, + secure: false, + }); }); }); diff --git a/spec/frontend/groups/transfer_edit_spec.js b/spec/frontend/groups/transfer_edit_spec.js deleted file mode 100644 index bc070920d02..00000000000 --- a/spec/frontend/groups/transfer_edit_spec.js +++ /dev/null @@ -1,31 +0,0 @@ -import $ from 'jquery'; - -import { loadHTMLFixture } from 'helpers/fixtures'; -import setupTransferEdit from '~/groups/transfer_edit'; - -describe('setupTransferEdit', () => { - const formSelector = '.js-group-transfer-form'; - const targetSelector = '#new_parent_group_id'; - - beforeEach(() => { - loadHTMLFixture('groups/edit.html'); - setupTransferEdit(formSelector, targetSelector); - }); - - it('disables submit button on load', () => { - expect($(formSelector).find(':submit').prop('disabled')).toBe(true); - }); - - it('enables submit button when selection changes to non-empty value', () => { - const lastValue = $(formSelector).find(targetSelector).find('.dropdown-content li').last(); - $(formSelector).find(targetSelector).val(lastValue).trigger('change'); - - expect($(formSelector).find(':submit').prop('disabled')).toBeFalsy(); - }); - - it('disables submit button when selection changes to empty value', () => { - $(formSelector).find(targetSelector).val('').trigger('change'); - - expect($(formSelector).find(':submit').prop('disabled')).toBe(true); - }); -}); |