diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-12-14 18:08:04 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-12-14 18:08:04 +0300 |
commit | 8c4225a66b12683bcf1bba9bb9328fcf65395b6d (patch) | |
tree | d3b583abd26fcbbcbf0db828aee2b940414e1649 /spec/frontend | |
parent | 075c890053f626018ba680e4da21a93743acb244 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend')
18 files changed, 438 insertions, 317 deletions
diff --git a/spec/frontend/boards/components/board_card_move_to_position_spec.js b/spec/frontend/boards/components/board_card_move_to_position_spec.js index 46e0724fc4a..8dee3c77787 100644 --- a/spec/frontend/boards/components/board_card_move_to_position_spec.js +++ b/spec/frontend/boards/components/board_card_move_to_position_spec.js @@ -1,18 +1,17 @@ import { shallowMount } from '@vue/test-utils'; import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; -import { GlCollapsibleListbox, GlListboxItem } from '@gitlab/ui'; +import { GlDropdown, GlDropdownItem } from '@gitlab/ui'; import BoardCardMoveToPosition from '~/boards/components/board_card_move_to_position.vue'; import { mockList, mockIssue2, mockIssue, mockIssue3, mockIssue4 } from 'jest/boards/mock_data'; import { mockTracking, unmockTracking } from 'helpers/tracking_helper'; -import { BOARD_CARD_MOVE_TO_POSITION_OPTIONS } from '~/boards/constants'; Vue.use(Vuex); const dropdownOptions = [ - BOARD_CARD_MOVE_TO_POSITION_OPTIONS[0].text, - BOARD_CARD_MOVE_TO_POSITION_OPTIONS[1].text, + BoardCardMoveToPosition.i18n.moveToStartText, + BoardCardMoveToPosition.i18n.moveToEndText, ]; describe('Board Card Move to position', () => { @@ -54,7 +53,8 @@ describe('Board Card Move to position', () => { ...propsData, }, stubs: { - GlCollapsibleListbox, + GlDropdown, + GlDropdownItem, }, }); }; @@ -68,8 +68,8 @@ describe('Board Card Move to position', () => { wrapper.destroy(); }); - const findMoveToPositionDropdown = () => wrapper.findComponent(GlCollapsibleListbox); - const findDropdownItems = () => findMoveToPositionDropdown().findAllComponents(GlListboxItem); + const findMoveToPositionDropdown = () => wrapper.findComponent(GlDropdown); + const findDropdownItems = () => findMoveToPositionDropdown().findAllComponents(GlDropdownItem); const findDropdownItemAtIndex = (index) => findDropdownItems().at(index); describe('Dropdown', () => { @@ -80,6 +80,7 @@ describe('Board Card Move to position', () => { }); it('is opened on the click of vertical ellipsis and has 2 dropdown items when number of list items < 10', () => { + findMoveToPositionDropdown().vm.$emit('click'); expect(findDropdownItems()).toHaveLength(dropdownOptions.length); }); }); @@ -96,17 +97,18 @@ describe('Board Card Move to position', () => { }); it.each` - dropdownIndex | dropdownLabel | trackLabel | positionInList - ${0} | ${BOARD_CARD_MOVE_TO_POSITION_OPTIONS[0].text} | ${'move_to_start'} | ${0} - ${1} | ${BOARD_CARD_MOVE_TO_POSITION_OPTIONS[1].text} | ${'move_to_end'} | ${-1} + dropdownIndex | dropdownLabel | trackLabel | positionInList + ${0} | ${BoardCardMoveToPosition.i18n.moveToStartText} | ${'move_to_start'} | ${0} + ${1} | ${BoardCardMoveToPosition.i18n.moveToEndText} | ${'move_to_end'} | ${-1} `( 'on click of dropdown index $dropdownIndex with label $dropdownLabel should call moveItem action with tracking label $trackLabel', async ({ dropdownIndex, dropdownLabel, trackLabel, positionInList }) => { - await findMoveToPositionDropdown().vm.$emit( - 'select', - BOARD_CARD_MOVE_TO_POSITION_OPTIONS[dropdownIndex].value, - ); + await findMoveToPositionDropdown().vm.$emit('click'); + expect(findDropdownItemAtIndex(dropdownIndex).text()).toBe(dropdownLabel); + await findDropdownItemAtIndex(dropdownIndex).vm.$emit('click', { + stopPropagation: () => {}, + }); await nextTick(); diff --git a/spec/frontend/boards/components/board_filtered_search_spec.js b/spec/frontend/boards/components/board_filtered_search_spec.js index db94b392694..e80c66f7fb8 100644 --- a/spec/frontend/boards/components/board_filtered_search_spec.js +++ b/spec/frontend/boards/components/board_filtered_search_spec.js @@ -17,7 +17,7 @@ import { TOKEN_TYPE_WEIGHT, } from '~/vue_shared/components/filtered_search_bar/constants'; import FilteredSearchBarRoot from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue'; -import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue'; +import UserToken from '~/vue_shared/components/filtered_search_bar/tokens/user_token.vue'; import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label_token.vue'; import { createStore } from '~/boards/stores'; @@ -49,9 +49,9 @@ describe('BoardFilteredSearch', () => { { value: '!=', description: 'is not' }, ], symbol: '@', - token: AuthorToken, + token: UserToken, unique: true, - fetchAuthors: () => new Promise(() => {}), + fetchUsers: () => new Promise(() => {}), }, ]; diff --git a/spec/frontend/boards/components/issue_board_filtered_search_spec.js b/spec/frontend/boards/components/issue_board_filtered_search_spec.js index e4a6a2b8b76..513561307cd 100644 --- a/spec/frontend/boards/components/issue_board_filtered_search_spec.js +++ b/spec/frontend/boards/components/issue_board_filtered_search_spec.js @@ -23,14 +23,14 @@ describe('IssueBoardFilter', () => { }); }; - let fetchAuthorsSpy; + let fetchUsersSpy; let fetchLabelsSpy; beforeEach(() => { - fetchAuthorsSpy = jest.fn(); + fetchUsersSpy = jest.fn(); fetchLabelsSpy = jest.fn(); issueBoardFilters.mockReturnValue({ - fetchAuthors: fetchAuthorsSpy, + fetchUsers: fetchUsersSpy, fetchLabels: fetchLabelsSpy, }); }); @@ -59,7 +59,7 @@ describe('IssueBoardFilter', () => { const tokens = mockTokens( fetchLabelsSpy, - fetchAuthorsSpy, + fetchUsersSpy, wrapper.vm.fetchMilestones, isSignedIn, ); diff --git a/spec/frontend/boards/mock_data.js b/spec/frontend/boards/mock_data.js index 30b2320097c..df41eb05eae 100644 --- a/spec/frontend/boards/mock_data.js +++ b/spec/frontend/boards/mock_data.js @@ -21,7 +21,7 @@ import { TOKEN_TYPE_RELEASE, TOKEN_TYPE_TYPE, } from '~/vue_shared/components/filtered_search_bar/constants'; -import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue'; +import UserToken from '~/vue_shared/components/filtered_search_bar/tokens/user_token.vue'; import EmojiToken from '~/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue'; import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label_token.vue'; import MilestoneToken from '~/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue'; @@ -758,16 +758,16 @@ export const mockConfidentialToken = { ], }; -export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, isSignedIn) => [ +export const mockTokens = (fetchLabels, fetchUsers, fetchMilestones, isSignedIn) => [ { icon: 'user', title: TOKEN_TITLE_ASSIGNEE, type: TOKEN_TYPE_ASSIGNEE, operators: OPERATORS_IS_NOT, - token: AuthorToken, + token: UserToken, unique: true, - fetchAuthors, - preloadedAuthors: [], + fetchUsers, + preloadedUsers: [], }, { icon: 'pencil', @@ -775,10 +775,10 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, isSignedI type: TOKEN_TYPE_AUTHOR, operators: OPERATORS_IS_NOT, symbol: '@', - token: AuthorToken, + token: UserToken, unique: true, - fetchAuthors, - preloadedAuthors: [], + fetchUsers, + preloadedUsers: [], }, { icon: 'labels', diff --git a/spec/frontend/design_management/components/upload/__snapshots__/design_version_dropdown_spec.js.snap b/spec/frontend/design_management/components/upload/__snapshots__/design_version_dropdown_spec.js.snap index 2b706d21f51..1acbf14db88 100644 --- a/spec/frontend/design_management/components/upload/__snapshots__/design_version_dropdown_spec.js.snap +++ b/spec/frontend/design_management/components/upload/__snapshots__/design_version_dropdown_spec.js.snap @@ -1,163 +1,229 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Design management design version dropdown component renders design version dropdown button 1`] = ` -<gl-dropdown-stub +<gl-base-dropdown-stub + ariahaspopup="listbox" category="primary" - clearalltext="Clear all" - clearalltextclass="gl-px-5" - headertext="" - hideheaderborder="true" - highlighteditemstitle="Selected" - highlighteditemstitleclass="gl-px-5" + icon="" issueiid="" projectpath="" size="small" - text="Showing latest version" + toggleid="dropdown-toggle-btn-2" + toggletext="Showing latest version" variant="default" > - <gl-dropdown-item-stub - avatarurl="" - iconcolor="" - iconname="" - iconrightarialabel="" - iconrightname="" - ischeckcentered="true" - ischecked="true" - ischeckitem="true" - secondarytext="" + <!----> + + <!----> + + <ul + aria-labelledby="dropdown-toggle-btn-2" + class="gl-dropdown-contents gl-list-style-none gl-pl-0 gl-mb-0" + id="listbox" + role="listbox" + tabindex="-1" > - <strong> - Version - 2 - (latest) - </strong> - - <div - class="gl-text-gray-600 gl-mt-1" + <gl-listbox-item-stub + ischeckcentered="true" > - <div> - Adminstrator - </div> - - <time-ago-stub - class="text-1" - cssclass="" - time="2021-08-09T06:05:00Z" - tooltipplacement="bottom" - /> - </div> - </gl-dropdown-item-stub> - <gl-dropdown-item-stub - avatarurl="" - iconcolor="" - iconname="" - iconrightarialabel="" - iconrightname="" - ischeckcentered="true" - ischeckitem="true" - secondarytext="" - > - <strong> - Version - 1 - - </strong> - - <div - class="gl-text-gray-600 gl-mt-1" + <span + class="gl-display-flex gl-align-items-center" + > + <div + class="gl-avatar gl-avatar-identicon gl-avatar-circle gl-avatar-s32 gl-avatar-identicon-bg1" + > + + + + </div> + + <span + class="gl-display-flex gl-flex-direction-column" + > + <span + class="gl-font-weight-bold" + > + Version 2 (latest) + </span> + + <span + class="gl-text-gray-600 gl-mt-1" + > + <span + class="gl-display-block" + > + Adminstrator + </span> + + <time-ago-stub + class="text-1" + cssclass="" + time="2021-08-09T06:05:00Z" + tooltipplacement="bottom" + /> + </span> + </span> + </span> + </gl-listbox-item-stub> + <gl-listbox-item-stub + ischeckcentered="true" > - <div> - Adminstrator - </div> - - <time-ago-stub - class="text-1" - cssclass="" - time="2021-08-09T06:05:00Z" - tooltipplacement="bottom" - /> - </div> - </gl-dropdown-item-stub> -</gl-dropdown-stub> + <span + class="gl-display-flex gl-align-items-center" + > + <div + class="gl-avatar gl-avatar-identicon gl-avatar-circle gl-avatar-s32 gl-avatar-identicon-bg1" + > + + + + </div> + + <span + class="gl-display-flex gl-flex-direction-column" + > + <span + class="gl-font-weight-bold" + > + Version 1 + </span> + + <span + class="gl-text-gray-600 gl-mt-1" + > + <span + class="gl-display-block" + > + Adminstrator + </span> + + <time-ago-stub + class="text-1" + cssclass="" + time="2021-08-09T06:05:00Z" + tooltipplacement="bottom" + /> + </span> + </span> + </span> + </gl-listbox-item-stub> + </ul> + + <!----> + +</gl-base-dropdown-stub> `; exports[`Design management design version dropdown component renders design version list 1`] = ` -<gl-dropdown-stub +<gl-base-dropdown-stub + ariahaspopup="listbox" category="primary" - clearalltext="Clear all" - clearalltextclass="gl-px-5" - headertext="" - hideheaderborder="true" - highlighteditemstitle="Selected" - highlighteditemstitleclass="gl-px-5" + icon="" issueiid="" projectpath="" size="small" - text="Showing latest version" + toggleid="dropdown-toggle-btn-4" + toggletext="Showing latest version" variant="default" > - <gl-dropdown-item-stub - avatarurl="" - iconcolor="" - iconname="" - iconrightarialabel="" - iconrightname="" - ischeckcentered="true" - ischecked="true" - ischeckitem="true" - secondarytext="" + <!----> + + <!----> + + <ul + aria-labelledby="dropdown-toggle-btn-4" + class="gl-dropdown-contents gl-list-style-none gl-pl-0 gl-mb-0" + id="listbox" + role="listbox" + tabindex="-1" > - <strong> - Version - 2 - (latest) - </strong> - - <div - class="gl-text-gray-600 gl-mt-1" + <gl-listbox-item-stub + ischeckcentered="true" > - <div> - Adminstrator - </div> - - <time-ago-stub - class="text-1" - cssclass="" - time="2021-08-09T06:05:00Z" - tooltipplacement="bottom" - /> - </div> - </gl-dropdown-item-stub> - <gl-dropdown-item-stub - avatarurl="" - iconcolor="" - iconname="" - iconrightarialabel="" - iconrightname="" - ischeckcentered="true" - ischeckitem="true" - secondarytext="" - > - <strong> - Version - 1 - - </strong> - - <div - class="gl-text-gray-600 gl-mt-1" + <span + class="gl-display-flex gl-align-items-center" + > + <div + class="gl-avatar gl-avatar-identicon gl-avatar-circle gl-avatar-s32 gl-avatar-identicon-bg1" + > + + + + </div> + + <span + class="gl-display-flex gl-flex-direction-column" + > + <span + class="gl-font-weight-bold" + > + Version 2 (latest) + </span> + + <span + class="gl-text-gray-600 gl-mt-1" + > + <span + class="gl-display-block" + > + Adminstrator + </span> + + <time-ago-stub + class="text-1" + cssclass="" + time="2021-08-09T06:05:00Z" + tooltipplacement="bottom" + /> + </span> + </span> + </span> + </gl-listbox-item-stub> + <gl-listbox-item-stub + ischeckcentered="true" > - <div> - Adminstrator - </div> - - <time-ago-stub - class="text-1" - cssclass="" - time="2021-08-09T06:05:00Z" - tooltipplacement="bottom" - /> - </div> - </gl-dropdown-item-stub> -</gl-dropdown-stub> + <span + class="gl-display-flex gl-align-items-center" + > + <div + class="gl-avatar gl-avatar-identicon gl-avatar-circle gl-avatar-s32 gl-avatar-identicon-bg1" + > + + + + </div> + + <span + class="gl-display-flex gl-flex-direction-column" + > + <span + class="gl-font-weight-bold" + > + Version 1 + </span> + + <span + class="gl-text-gray-600 gl-mt-1" + > + <span + class="gl-display-block" + > + Adminstrator + </span> + + <time-ago-stub + class="text-1" + cssclass="" + time="2021-08-09T06:05:00Z" + tooltipplacement="bottom" + /> + </span> + </span> + </span> + </gl-listbox-item-stub> + </ul> + + <!----> + +</gl-base-dropdown-stub> `; diff --git a/spec/frontend/design_management/components/upload/design_version_dropdown_spec.js b/spec/frontend/design_management/components/upload/design_version_dropdown_spec.js index 7c26ab9739b..1e9f286a0ec 100644 --- a/spec/frontend/design_management/components/upload/design_version_dropdown_spec.js +++ b/spec/frontend/design_management/components/upload/design_version_dropdown_spec.js @@ -1,4 +1,4 @@ -import { GlDropdown, GlDropdownItem, GlSprintf } from '@gitlab/ui'; +import { GlAvatar, GlCollapsibleListbox, GlListboxItem } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import { nextTick } from 'vue'; import DesignVersionDropdown from '~/design_management/components/upload/design_version_dropdown.vue'; @@ -32,7 +32,7 @@ describe('Design management design version dropdown component', () => { mocks: { $route, }, - stubs: { GlSprintf }, + stubs: { GlAvatar, GlCollapsibleListbox }, }); // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details @@ -46,7 +46,9 @@ describe('Design management design version dropdown component', () => { wrapper.destroy(); }); - const findVersionLink = (index) => wrapper.findAllComponents(GlDropdownItem).at(index); + const findListbox = () => wrapper.findComponent(GlCollapsibleListbox); + const findAllListboxItems = () => wrapper.findAllComponents(GlListboxItem); + const findVersionLink = (index) => wrapper.findAllComponents(GlListboxItem).at(index); it('renders design version dropdown button', async () => { createComponent(); @@ -76,35 +78,36 @@ describe('Design management design version dropdown component', () => { createComponent(); await nextTick(); - expect(wrapper.findComponent(GlDropdown).attributes('text')).toBe('Showing latest version'); + + expect(findListbox().props('toggleText')).toBe('Showing latest version'); }); it('displays latest version text when only 1 version is present', async () => { createComponent({ maxVersions: 1 }); await nextTick(); - expect(wrapper.findComponent(GlDropdown).attributes('text')).toBe('Showing latest version'); + expect(findListbox().props('toggleText')).toBe('Showing latest version'); }); it('displays version text when the current version is not the latest', async () => { createComponent({ $route: designRouteFactory(PREVIOUS_VERSION_ID) }); await nextTick(); - expect(wrapper.findComponent(GlDropdown).attributes('text')).toBe(`Showing version #1`); + expect(findListbox().props('toggleText')).toBe(`Showing version #1`); }); it('displays latest version text when the current version is the latest', async () => { createComponent({ $route: designRouteFactory(LATEST_VERSION_ID) }); await nextTick(); - expect(wrapper.findComponent(GlDropdown).attributes('text')).toBe('Showing latest version'); + expect(findListbox().props('toggleText')).toBe('Showing latest version'); }); it('should have the same length as apollo query', async () => { createComponent(); await nextTick(); - expect(wrapper.findAllComponents(GlDropdownItem)).toHaveLength(wrapper.vm.allVersions.length); + expect(findAllListboxItems()).toHaveLength(wrapper.vm.allVersions.length); }); it('should render TimeAgo', async () => { diff --git a/spec/frontend/groups/components/app_spec.js b/spec/frontend/groups/components/app_spec.js index 091ec17d58e..140609161d4 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, { nextTick } from 'vue'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import waitForPromises from 'helpers/wait_for_promises'; import { createAlert } from '~/flash'; import appComponent from '~/groups/components/app.vue'; @@ -10,8 +10,6 @@ import groupItemComponent from '~/groups/components/group_item.vue'; import eventHub from '~/groups/event_hub'; import GroupsService from '~/groups/service/groups_service'; import GroupsStore from '~/groups/store/groups_store'; -import EmptyState from '~/groups/components/empty_state.vue'; -import GroupsComponent from '~/groups/components/groups.vue'; import axios from '~/lib/utils/axios_utils'; import * as urlUtilities from '~/lib/utils/url_utility'; import setWindowLocation from 'helpers/set_window_location_helper'; @@ -43,7 +41,7 @@ describe('AppComponent', () => { const createShallowComponent = ({ propsData = {} } = {}) => { store.state.pageInfo = mockPageInfo; - wrapper = shallowMount(appComponent, { + wrapper = shallowMountExtended(appComponent, { propsData: { store, service, @@ -51,6 +49,9 @@ describe('AppComponent', () => { containerId: 'js-groups-tree', ...propsData, }, + scopedSlots: { + 'empty-state': '<div data-testid="empty-state" />', + }, mocks: { $toast, }, @@ -68,6 +69,7 @@ describe('AppComponent', () => { mock.onGet('/dashboard/groups.json').reply(200, mockGroups); Vue.component('GroupFolder', groupFolderComponent); Vue.component('GroupItem', groupItemComponent); + setWindowLocation('?filter=foobar'); document.body.innerHTML = ` <div id="js-groups-tree"> @@ -149,13 +151,13 @@ describe('AppComponent', () => { expect(vm.fetchGroups).toHaveBeenCalledWith({ page: null, - filterGroupsBy: null, + filterGroupsBy: 'foobar', sortBy: null, updatePagination: true, archived: null, }); return fetchPromise.then(() => { - expect(vm.updateGroups).toHaveBeenCalled(); + expect(vm.updateGroups).toHaveBeenCalledWith(mockSearchedGroups, true); }); }); }); @@ -375,32 +377,16 @@ describe('AppComponent', () => { expect(vm.store.setSearchedGroups).toHaveBeenCalledWith(mockGroups); }); - it('should set `isSearchEmpty` prop based on groups count and `filter` query param', () => { - setWindowLocation('?filter=foobar'); - createShallowComponent(); - - vm.updateGroups(mockGroups); - - expect(vm.isSearchEmpty).toBe(false); - - vm.updateGroups([]); - - expect(vm.isSearchEmpty).toBe(true); - }); - describe.each` - action | groups | fromSearch | shouldRenderEmptyState | searchEmpty - ${'subgroups_and_projects'} | ${[]} | ${false} | ${true} | ${false} - ${''} | ${[]} | ${false} | ${false} | ${false} - ${'subgroups_and_projects'} | ${mockGroups} | ${false} | ${false} | ${false} - ${'subgroups_and_projects'} | ${[]} | ${true} | ${false} | ${true} + groups | fromSearch | shouldRenderEmptyState | shouldRenderSearchEmptyState + ${[]} | ${false} | ${true} | ${false} + ${mockGroups} | ${false} | ${false} | ${false} + ${[]} | ${true} | ${false} | ${true} `( - 'when `action` is $action, `groups` is $groups, and `fromSearch` is $fromSearch', - ({ action, groups, fromSearch, shouldRenderEmptyState, searchEmpty }) => { + 'when `groups` is $groups, and `fromSearch` is $fromSearch', + ({ groups, fromSearch, shouldRenderEmptyState, shouldRenderSearchEmptyState }) => { it(`${shouldRenderEmptyState ? 'renders' : 'does not render'} empty state`, async () => { - createShallowComponent({ - propsData: { action, renderEmptyState: true }, - }); + createShallowComponent(); await waitForPromises(); @@ -408,28 +394,14 @@ describe('AppComponent', () => { await nextTick(); - expect(wrapper.findComponent(EmptyState).exists()).toBe(shouldRenderEmptyState); - expect(wrapper.findComponent(GroupsComponent).props('searchEmpty')).toBe(searchEmpty); + expect(wrapper.findByTestId('empty-state').exists()).toBe(shouldRenderEmptyState); + expect(wrapper.findByTestId('search-empty-state').exists()).toBe( + shouldRenderSearchEmptyState, + ); }); }, ); }); - - describe('when `action` is subgroups_and_projects, `groups` is [], `fromSearch` is `false`, and `renderEmptyState` is `false`', () => { - it('renders legacy empty state', async () => { - createShallowComponent({ - propsData: { action: 'subgroups_and_projects' }, - }); - - vm.updateGroups([], false); - - await nextTick(); - - expect( - document.querySelector('[data-testid="legacy-empty-state"]').classList.contains('hidden'), - ).toBe(false); - }); - }); }); describe('created', () => { diff --git a/spec/frontend/groups/components/empty_states/archived_projects_empty_state_spec.js b/spec/frontend/groups/components/empty_states/archived_projects_empty_state_spec.js new file mode 100644 index 00000000000..be61ffa92b4 --- /dev/null +++ b/spec/frontend/groups/components/empty_states/archived_projects_empty_state_spec.js @@ -0,0 +1,27 @@ +import { GlEmptyState } from '@gitlab/ui'; + +import { mountExtended } from 'helpers/vue_test_utils_helper'; +import ArchivedProjectsEmptyState from '~/groups/components/empty_states/archived_projects_empty_state.vue'; + +let wrapper; + +const defaultProvide = { + newProjectIllustration: '/assets/illustrations/project-create-new-sm.svg', +}; + +const createComponent = () => { + wrapper = mountExtended(ArchivedProjectsEmptyState, { + provide: defaultProvide, + }); +}; + +describe('ArchivedProjectsEmptyState', () => { + it('renders empty state', () => { + createComponent(); + + expect(wrapper.findComponent(GlEmptyState).props()).toMatchObject({ + title: ArchivedProjectsEmptyState.i18n.title, + svgPath: defaultProvide.newProjectIllustration, + }); + }); +}); diff --git a/spec/frontend/groups/components/empty_states/shared_projects_empty_state_spec.js b/spec/frontend/groups/components/empty_states/shared_projects_empty_state_spec.js new file mode 100644 index 00000000000..c4ace1be1f3 --- /dev/null +++ b/spec/frontend/groups/components/empty_states/shared_projects_empty_state_spec.js @@ -0,0 +1,27 @@ +import { GlEmptyState } from '@gitlab/ui'; + +import { mountExtended } from 'helpers/vue_test_utils_helper'; +import SharedProjectsEmptyState from '~/groups/components/empty_states/shared_projects_empty_state.vue'; + +let wrapper; + +const defaultProvide = { + newProjectIllustration: '/assets/illustrations/project-create-new-sm.svg', +}; + +const createComponent = () => { + wrapper = mountExtended(SharedProjectsEmptyState, { + provide: defaultProvide, + }); +}; + +describe('SharedProjectsEmptyState', () => { + it('renders empty state', () => { + createComponent(); + + expect(wrapper.findComponent(GlEmptyState).props()).toMatchObject({ + title: SharedProjectsEmptyState.i18n.title, + svgPath: defaultProvide.newProjectIllustration, + }); + }); +}); diff --git a/spec/frontend/groups/components/empty_state_spec.js b/spec/frontend/groups/components/empty_states/subgroups_and_projects_empty_state_spec.js index fbeaa32b1ec..75edc602fbf 100644 --- a/spec/frontend/groups/components/empty_state_spec.js +++ b/spec/frontend/groups/components/empty_states/subgroups_and_projects_empty_state_spec.js @@ -1,7 +1,7 @@ import { GlEmptyState } from '@gitlab/ui'; import { mountExtended } from 'jest/__helpers__/vue_test_utils_helper'; -import EmptyState from '~/groups/components/empty_state.vue'; +import SubgroupsAndProjectsEmptyState from '~/groups/components/empty_states/subgroups_and_projects_empty_state.vue'; let wrapper; @@ -16,7 +16,7 @@ const defaultProvide = { }; const createComponent = ({ provide = {} } = {}) => { - wrapper = mountExtended(EmptyState, { + wrapper = mountExtended(SubgroupsAndProjectsEmptyState, { provide: { ...defaultProvide, ...provide, @@ -30,18 +30,18 @@ afterEach(() => { const findNewSubgroupLink = () => wrapper.findByRole('link', { - name: new RegExp(EmptyState.i18n.withLinks.subgroup.title), + name: new RegExp(SubgroupsAndProjectsEmptyState.i18n.withLinks.subgroup.title), }); const findNewProjectLink = () => wrapper.findByRole('link', { - name: new RegExp(EmptyState.i18n.withLinks.project.title), + name: new RegExp(SubgroupsAndProjectsEmptyState.i18n.withLinks.project.title), }); const findNewSubgroupIllustration = () => - wrapper.findByRole('img', { name: EmptyState.i18n.withLinks.subgroup.title }); + wrapper.findByRole('img', { name: SubgroupsAndProjectsEmptyState.i18n.withLinks.subgroup.title }); const findNewProjectIllustration = () => - wrapper.findByRole('img', { name: EmptyState.i18n.withLinks.project.title }); + wrapper.findByRole('img', { name: SubgroupsAndProjectsEmptyState.i18n.withLinks.project.title }); -describe('EmptyState', () => { +describe('SubgroupsAndProjectsEmptyState', () => { describe('when user has permission to create a subgroup', () => { it('renders `Create new subgroup` link', () => { createComponent(); @@ -69,8 +69,8 @@ describe('EmptyState', () => { createComponent({ provide: { canCreateSubgroups: false, canCreateProjects: false } }); expect(wrapper.findComponent(GlEmptyState).props()).toMatchObject({ - title: EmptyState.i18n.withoutLinks.title, - description: EmptyState.i18n.withoutLinks.description, + title: SubgroupsAndProjectsEmptyState.i18n.withoutLinks.title, + description: SubgroupsAndProjectsEmptyState.i18n.withoutLinks.description, svgPath: defaultProvide.emptySubgroupIllustration, }); }); diff --git a/spec/frontend/groups/components/groups_spec.js b/spec/frontend/groups/components/groups_spec.js index 0cbb6cc8309..cae29a8f15a 100644 --- a/spec/frontend/groups/components/groups_spec.js +++ b/spec/frontend/groups/components/groups_spec.js @@ -16,7 +16,6 @@ describe('GroupsComponent', () => { const defaultPropsData = { groups: mockGroups, pageInfo: mockPageInfo, - searchEmpty: false, }; const createComponent = ({ propsData } = {}) => { @@ -69,14 +68,5 @@ describe('GroupsComponent', () => { expect(findPaginationLinks().exists()).toBe(true); expect(wrapper.findComponent(GlEmptyState).exists()).toBe(false); }); - - it('should render empty search message when `searchEmpty` is `true`', () => { - createComponent({ propsData: { searchEmpty: true } }); - - expect(wrapper.findComponent(GlEmptyState).props()).toMatchObject({ - title: GroupsComponent.i18n.emptyStateTitle, - description: GroupsComponent.i18n.emptyStateDescription, - }); - }); }); }); diff --git a/spec/frontend/groups/components/overview_tabs_spec.js b/spec/frontend/groups/components/overview_tabs_spec.js index b9c392243de..d1ae2c4be17 100644 --- a/spec/frontend/groups/components/overview_tabs_spec.js +++ b/spec/frontend/groups/components/overview_tabs_spec.js @@ -5,6 +5,9 @@ import { mountExtended } from 'helpers/vue_test_utils_helper'; import OverviewTabs from '~/groups/components/overview_tabs.vue'; import GroupsApp from '~/groups/components/app.vue'; import GroupFolderComponent from '~/groups/components/group_folder.vue'; +import SubgroupsAndProjectsEmptyState from '~/groups/components/empty_states/subgroups_and_projects_empty_state.vue'; +import SharedProjectsEmptyState from '~/groups/components/empty_states/shared_projects_empty_state.vue'; +import ArchivedProjectsEmptyState from '~/groups/components/empty_states/archived_projects_empty_state.vue'; import GroupsStore from '~/groups/store/groups_store'; import GroupsService from '~/groups/service/groups_service'; import { createRouter } from '~/groups/init_overview_tabs'; @@ -16,6 +19,7 @@ import { OVERVIEW_TABS_SORTING_ITEMS, } from '~/groups/constants'; import axios from '~/lib/utils/axios_utils'; +import waitForPromises from 'helpers/wait_for_promises'; Vue.component('GroupFolder', GroupFolderComponent); const router = createRouter(); @@ -68,6 +72,7 @@ describe('OverviewTabs', () => { beforeEach(() => { axiosMock = new AxiosMockAdapter(axios); + axiosMock.onGet({ data: [] }); }); afterEach(() => { @@ -75,7 +80,7 @@ describe('OverviewTabs', () => { axiosMock.restore(); }); - it('renders `Subgroups and projects` tab with `GroupsApp` component', async () => { + it('renders `Subgroups and projects` tab with `GroupsApp` component with correct empty state', async () => { await createComponent(); const tabPanel = findTabPanels().at(0); @@ -89,11 +94,14 @@ describe('OverviewTabs', () => { store: new GroupsStore({ showSchemaMarkup: true }), service: new GroupsService(defaultProvide.endpoints[ACTIVE_TAB_SUBGROUPS_AND_PROJECTS]), hideProjects: false, - renderEmptyState: true, }); + + await waitForPromises(); + + expect(wrapper.findComponent(SubgroupsAndProjectsEmptyState).exists()).toBe(true); }); - it('renders `Shared projects` tab and renders `GroupsApp` component after clicking tab', async () => { + it('renders `Shared projects` tab and renders `GroupsApp` component with correct empty state after clicking tab', async () => { await createComponent(); const tabPanel = findTabPanels().at(1); @@ -110,13 +118,16 @@ describe('OverviewTabs', () => { store: new GroupsStore(), service: new GroupsService(defaultProvide.endpoints[ACTIVE_TAB_SHARED]), hideProjects: false, - renderEmptyState: false, }); expect(tabPanel.vm.$attrs.lazy).toBe(false); + + await waitForPromises(); + + expect(wrapper.findComponent(SharedProjectsEmptyState).exists()).toBe(true); }); - it('renders `Archived projects` tab and renders `GroupsApp` component after clicking tab', async () => { + it('renders `Archived projects` tab and renders `GroupsApp` component with correct empty state after clicking tab', async () => { await createComponent(); const tabPanel = findTabPanels().at(2); @@ -133,10 +144,13 @@ describe('OverviewTabs', () => { store: new GroupsStore(), service: new GroupsService(defaultProvide.endpoints[ACTIVE_TAB_ARCHIVED]), hideProjects: false, - renderEmptyState: false, }); expect(tabPanel.vm.$attrs.lazy).toBe(false); + + await waitForPromises(); + + expect(wrapper.findComponent(ArchivedProjectsEmptyState).exists()).toBe(true); }); it('sets `lazy` prop to `false` for initially active tab and `true` for all other tabs', async () => { diff --git a/spec/frontend/issuable/components/issuable_header_warnings_spec.js b/spec/frontend/issuable/components/issuable_header_warnings_spec.js index e3a36dc8820..98a81478cb6 100644 --- a/spec/frontend/issuable/components/issuable_header_warnings_spec.js +++ b/spec/frontend/issuable/components/issuable_header_warnings_spec.js @@ -57,6 +57,7 @@ describe('IssuableHeaderWarnings', () => { beforeEach(() => { store.getters.getNoteableData.confidential = confidentialStatus; store.getters.getNoteableData.discussion_locked = lockStatus; + store.getters.getNoteableData.targetType = issuableType; createComponent({ store, provide: { hidden: hiddenStatus } }); }); @@ -84,7 +85,7 @@ describe('IssuableHeaderWarnings', () => { if (hiddenStatus) { expect(hiddenIcon.attributes('title')).toBe( - 'This issue is hidden because its author has been banned', + `This ${issuableType} is hidden because its author has been banned`, ); expect(getBinding(hiddenIcon.element, 'gl-tooltip')).not.toBeUndefined(); } diff --git a/spec/frontend/issues/list/components/issues_list_app_spec.js b/spec/frontend/issues/list/components/issues_list_app_spec.js index d404225333a..4c5d8ce3cd1 100644 --- a/spec/frontend/issues/list/components/issues_list_app_spec.js +++ b/spec/frontend/issues/list/components/issues_list_app_spec.js @@ -535,8 +535,8 @@ describe('CE IssuesListApp component', () => { it('does not render My-Reaction or Confidential tokens', () => { expect(findIssuableList().props('searchTokens')).not.toMatchObject([ - { type: TOKEN_TYPE_AUTHOR, preloadedAuthors: [mockCurrentUser] }, - { type: TOKEN_TYPE_ASSIGNEE, preloadedAuthors: [mockCurrentUser] }, + { type: TOKEN_TYPE_AUTHOR, preloadedUsers: [mockCurrentUser] }, + { type: TOKEN_TYPE_ASSIGNEE, preloadedUsers: [mockCurrentUser] }, { type: TOKEN_TYPE_MY_REACTION }, { type: TOKEN_TYPE_CONFIDENTIAL }, ]); @@ -584,13 +584,13 @@ describe('CE IssuesListApp component', () => { }); it('renders all tokens alphabetically', () => { - const preloadedAuthors = [ + const preloadedUsers = [ { ...mockCurrentUser, id: convertToGraphQLId('User', mockCurrentUser.id) }, ]; expect(findIssuableList().props('searchTokens')).toMatchObject([ - { type: TOKEN_TYPE_ASSIGNEE, preloadedAuthors }, - { type: TOKEN_TYPE_AUTHOR, preloadedAuthors }, + { type: TOKEN_TYPE_ASSIGNEE, preloadedUsers }, + { type: TOKEN_TYPE_AUTHOR, preloadedUsers }, { type: TOKEN_TYPE_CONFIDENTIAL }, { type: TOKEN_TYPE_CONTACT }, { type: TOKEN_TYPE_LABEL }, diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js b/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js index dd4d4a0b542..b2f4c780f51 100644 --- a/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js +++ b/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js @@ -22,7 +22,7 @@ import { TOKEN_TYPE_RELEASE, TOKEN_TYPE_SOURCE_BRANCH, } from '~/vue_shared/components/filtered_search_bar/constants'; -import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue'; +import UserToken from '~/vue_shared/components/filtered_search_bar/tokens/user_token.vue'; import BranchToken from '~/vue_shared/components/filtered_search_bar/tokens/branch_token.vue'; import EmojiToken from '~/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue'; import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label_token.vue'; @@ -31,7 +31,7 @@ import ReleaseToken from '~/vue_shared/components/filtered_search_bar/tokens/rel import CrmContactToken from '~/vue_shared/components/filtered_search_bar/tokens/crm_contact_token.vue'; import CrmOrganizationToken from '~/vue_shared/components/filtered_search_bar/tokens/crm_organization_token.vue'; -export const mockAuthor1 = { +export const mockUser1 = { id: 1, name: 'Administrator', username: 'root', @@ -40,7 +40,7 @@ export const mockAuthor1 = { web_url: 'http://0.0.0.0:3000/root', }; -export const mockAuthor2 = { +export const mockUser2 = { id: 2, name: 'Claudio Beer', username: 'ericka_terry', @@ -49,7 +49,7 @@ export const mockAuthor2 = { web_url: 'http://0.0.0.0:3000/ericka_terry', }; -export const mockAuthor3 = { +export const mockUser3 = { id: 6, name: 'Shizue Hartmann', username: 'junita.weimann', @@ -58,7 +58,7 @@ export const mockAuthor3 = { web_url: 'http://0.0.0.0:3000/junita.weimann', }; -export const mockAuthors = [mockAuthor1, mockAuthor2, mockAuthor3]; +export const mockUsers = [mockUser1, mockUser2, mockUser3]; export const mockBranches = [{ name: 'Main' }, { name: 'v1.x' }, { name: 'my-Branch' }]; @@ -232,10 +232,10 @@ export const mockAuthorToken = { title: TOKEN_TITLE_AUTHOR, unique: false, symbol: '@', - token: AuthorToken, + token: UserToken, operators: OPERATORS_IS, fetchPath: 'gitlab-org/gitlab-test', - fetchAuthors: Api.projectUsers.bind(Api), + fetchUsers: Api.projectUsers.bind(Api), }; export const mockLabelToken = { diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/user_token_spec.js index 69a0dc6469c..32cb74d5f80 100644 --- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js +++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/user_token_spec.js @@ -12,10 +12,10 @@ import { createAlert } from '~/flash'; import axios from '~/lib/utils/axios_utils'; import { OPTIONS_NONE_ANY } from '~/vue_shared/components/filtered_search_bar/constants'; -import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue'; +import UserToken from '~/vue_shared/components/filtered_search_bar/tokens/user_token.vue'; import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue'; -import { mockAuthorToken, mockAuthors } from '../mock_data'; +import { mockAuthorToken, mockUsers } from '../mock_data'; jest.mock('~/flash'); const defaultStubs = { @@ -28,7 +28,7 @@ const defaultStubs = { }, }; -const mockPreloadedAuthors = [ +const mockPreloadedUsers = [ { id: 13, name: 'Administrator', @@ -46,7 +46,7 @@ function createComponent(options = {}) { data = {}, listeners = {}, } = options; - return mount(AuthorToken, { + return mount(UserToken, { propsData: { config, value, @@ -66,7 +66,7 @@ function createComponent(options = {}) { }); } -describe('AuthorToken', () => { +describe('UserToken', () => { const originalGon = window.gon; const currentUserLength = 1; let mock; @@ -85,40 +85,40 @@ describe('AuthorToken', () => { }); describe('methods', () => { - describe('fetchAuthors', () => { + describe('fetchUsers', () => { beforeEach(() => { wrapper = createComponent(); }); - it('calls `config.fetchAuthors` with provided searchTerm param', () => { - jest.spyOn(wrapper.vm.config, 'fetchAuthors'); + it('calls `config.fetchUsers` with provided searchTerm param', () => { + jest.spyOn(wrapper.vm.config, 'fetchUsers'); - getBaseToken().vm.$emit('fetch-suggestions', mockAuthors[0].username); + getBaseToken().vm.$emit('fetch-suggestions', mockUsers[0].username); - expect(wrapper.vm.config.fetchAuthors).toHaveBeenCalledWith( + expect(wrapper.vm.config.fetchUsers).toHaveBeenCalledWith( mockAuthorToken.fetchPath, - mockAuthors[0].username, + mockUsers[0].username, ); }); - it('sets response to `authors` when request is succesful', () => { - jest.spyOn(wrapper.vm.config, 'fetchAuthors').mockResolvedValue(mockAuthors); + it('sets response to `users` when request is successful', () => { + jest.spyOn(wrapper.vm.config, 'fetchUsers').mockResolvedValue(mockUsers); getBaseToken().vm.$emit('fetch-suggestions', 'root'); return waitForPromises().then(() => { - expect(getBaseToken().props('suggestions')).toEqual(mockAuthors); + expect(getBaseToken().props('suggestions')).toEqual(mockUsers); }); }); // TODO: rm when completed https://gitlab.com/gitlab-org/gitlab/-/issues/345756 describe('when there are null users presents', () => { - const mockAuthorsWithNullUser = mockAuthors.concat([null]); + const mockUsersWithNullUser = mockUsers.concat([null]); beforeEach(() => { jest - .spyOn(wrapper.vm.config, 'fetchAuthors') - .mockResolvedValue({ data: mockAuthorsWithNullUser }); + .spyOn(wrapper.vm.config, 'fetchUsers') + .mockResolvedValue({ data: mockUsersWithNullUser }); getBaseToken().vm.$emit('fetch-suggestions', 'root'); }); @@ -126,7 +126,7 @@ describe('AuthorToken', () => { describe('when res.data is present', () => { it('filters the successful response when null values are present', () => { return waitForPromises().then(() => { - expect(getBaseToken().props('suggestions')).toEqual(mockAuthors); + expect(getBaseToken().props('suggestions')).toEqual(mockUsers); }); }); }); @@ -134,14 +134,14 @@ describe('AuthorToken', () => { describe('when response is an array', () => { it('filters the successful response when null values are present', () => { return waitForPromises().then(() => { - expect(getBaseToken().props('suggestions')).toEqual(mockAuthors); + expect(getBaseToken().props('suggestions')).toEqual(mockUsers); }); }); }); }); it('calls `createAlert` with flash error message when request fails', () => { - jest.spyOn(wrapper.vm.config, 'fetchAuthors').mockRejectedValue({}); + jest.spyOn(wrapper.vm.config, 'fetchUsers').mockRejectedValue({}); getBaseToken().vm.$emit('fetch-suggestions', 'root'); @@ -153,7 +153,7 @@ describe('AuthorToken', () => { }); it('sets `loading` to false when request completes', async () => { - jest.spyOn(wrapper.vm.config, 'fetchAuthors').mockRejectedValue({}); + jest.spyOn(wrapper.vm.config, 'fetchUsers').mockRejectedValue({}); getBaseToken().vm.$emit('fetch-suggestions', 'root'); @@ -174,23 +174,23 @@ describe('AuthorToken', () => { it('renders base-token component', () => { wrapper = createComponent({ - value: { data: mockAuthors[0].username }, - data: { authors: mockAuthors }, + value: { data: mockUsers[0].username }, + data: { users: mockUsers }, }); const baseTokenEl = getBaseToken(); expect(baseTokenEl.exists()).toBe(true); expect(baseTokenEl.props()).toMatchObject({ - suggestions: mockAuthors, - getActiveTokenValue: wrapper.vm.getActiveAuthor, + suggestions: mockUsers, + getActiveTokenValue: wrapper.vm.getActiveUser, }); }); it('renders token item when value is selected', async () => { wrapper = createComponent({ - value: { data: mockAuthors[0].username }, - data: { authors: mockAuthors }, + value: { data: mockUsers[0].username }, + data: { users: mockUsers }, stubs: { Portal: true }, }); @@ -201,20 +201,20 @@ describe('AuthorToken', () => { const tokenValue = tokenSegments.at(2); - expect(tokenValue.findComponent(GlAvatar).props('src')).toBe(mockAuthors[0].avatar_url); - expect(tokenValue.text()).toBe(mockAuthors[0].name); // "Administrator" + expect(tokenValue.findComponent(GlAvatar).props('src')).toBe(mockUsers[0].avatar_url); + expect(tokenValue.text()).toBe(mockUsers[0].name); // "Administrator" }); - it('renders token value with correct avatarUrl from author object', async () => { + it('renders token value with correct avatarUrl from user object', async () => { const getAvatarEl = () => wrapper.findAllComponents(GlFilteredSearchTokenSegment).at(2).findComponent(GlAvatar); wrapper = createComponent({ - value: { data: mockAuthors[0].username }, + value: { data: mockUsers[0].username }, data: { - authors: [ + users: [ { - ...mockAuthors[0], + ...mockUsers[0], }, ], }, @@ -223,15 +223,15 @@ describe('AuthorToken', () => { await nextTick(); - expect(getAvatarEl().props('src')).toBe(mockAuthors[0].avatar_url); + expect(getAvatarEl().props('src')).toBe(mockUsers[0].avatar_url); // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // eslint-disable-next-line no-restricted-syntax wrapper.setData({ - authors: [ + users: [ { - ...mockAuthors[0], - avatarUrl: mockAuthors[0].avatar_url, + ...mockUsers[0], + avatarUrl: mockUsers[0].avatar_url, avatar_url: undefined, }, ], @@ -239,14 +239,14 @@ describe('AuthorToken', () => { await nextTick(); - expect(getAvatarEl().props('src')).toBe(mockAuthors[0].avatar_url); + expect(getAvatarEl().props('src')).toBe(mockUsers[0].avatar_url); }); - it('renders provided defaultAuthors as suggestions', async () => { - const defaultAuthors = OPTIONS_NONE_ANY; + it('renders provided defaultUsers as suggestions', async () => { + const defaultUsers = OPTIONS_NONE_ANY; wrapper = createComponent({ active: true, - config: { ...mockAuthorToken, defaultAuthors, preloadedAuthors: mockPreloadedAuthors }, + config: { ...mockAuthorToken, defaultUsers, preloadedUsers: mockPreloadedUsers }, stubs: { Portal: true }, }); @@ -254,16 +254,16 @@ describe('AuthorToken', () => { const suggestions = wrapper.findAllComponents(GlFilteredSearchSuggestion); - expect(suggestions).toHaveLength(defaultAuthors.length + currentUserLength); - defaultAuthors.forEach((label, index) => { + expect(suggestions).toHaveLength(defaultUsers.length + currentUserLength); + defaultUsers.forEach((label, index) => { expect(suggestions.at(index).text()).toBe(label.text); }); }); - it('does not render divider when no defaultAuthors', async () => { + it('does not render divider when no defaultUsers', async () => { wrapper = createComponent({ active: true, - config: { ...mockAuthorToken, defaultAuthors: [] }, + config: { ...mockAuthorToken, defaultUsers: [] }, stubs: { Portal: true }, }); const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment); @@ -277,7 +277,7 @@ describe('AuthorToken', () => { it('renders `OPTIONS_NONE_ANY` as default suggestions', async () => { wrapper = createComponent({ active: true, - config: { ...mockAuthorToken, preloadedAuthors: mockPreloadedAuthors }, + config: { ...mockAuthorToken, preloadedUsers: mockPreloadedUsers }, stubs: { Portal: true }, }); @@ -308,8 +308,8 @@ describe('AuthorToken', () => { active: true, config: { ...mockAuthorToken, - preloadedAuthors: mockPreloadedAuthors, - defaultAuthors: [], + preloadedUsers: mockPreloadedUsers, + defaultUsers: [], }, stubs: { Portal: true }, }); diff --git a/spec/frontend/vue_shared/components/markdown_drawer/markdown_drawer_spec.js b/spec/frontend/vue_shared/components/markdown_drawer/markdown_drawer_spec.js index 8edcb905096..2b311b75f85 100644 --- a/spec/frontend/vue_shared/components/markdown_drawer/markdown_drawer_spec.js +++ b/spec/frontend/vue_shared/components/markdown_drawer/markdown_drawer_spec.js @@ -1,5 +1,5 @@ import { GlDrawer, GlAlert, GlSkeletonLoader } from '@gitlab/ui'; -import { nextTick } from 'vue'; +import Vue, { nextTick } from 'vue'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import MarkdownDrawer, { cache } from '~/vue_shared/components/markdown_drawer/markdown_drawer.vue'; import { getRenderedMarkdown } from '~/vue_shared/components/markdown_drawer/utils/fetch'; @@ -82,7 +82,10 @@ describe('MarkdownDrawer', () => { contentTop.mockClear(); }); - it(`computes offsetTop ${hasNavbar ? 'with' : 'without'} .navbar-gitlab`, () => { + it(`computes offsetTop ${hasNavbar ? 'with' : 'without'} .navbar-gitlab`, async () => { + wrapper.vm.getDrawerTop(); + await Vue.nextTick(); + expect(findDrawer().attributes('headerheight')).toBe(`${navbarHeight}px`); }); }); @@ -95,11 +98,11 @@ describe('MarkdownDrawer', () => { renderGLFMSpy = jest.spyOn(MarkdownDrawer.methods, 'renderGLFM'); fetchMarkdownSpy = jest.spyOn(MarkdownDrawer.methods, 'fetchMarkdown'); global.document.querySelector = jest.fn(() => ({ - getBoundingClientRect: jest.fn(() => ({ bottom: 100 })), dataset: { page: 'test', }, })); + contentTop.mockReturnValue(100); createComponent(); await nextTick(); }); @@ -118,12 +121,28 @@ describe('MarkdownDrawer', () => { expect(fetchMarkdownSpy).toHaveBeenCalledTimes(2); }); - it('for open triggers renderGLFM', async () => { + it('triggers renderGLFM in openDrawer', async () => { wrapper.vm.fetchMarkdown(); wrapper.vm.openDrawer(); await nextTick(); expect(renderGLFMSpy).toHaveBeenCalled(); }); + + it('triggers height calculation in openDrawer', async () => { + expect(findDrawer().attributes('headerheight')).toBe(`${0}px`); + wrapper.vm.fetchMarkdown(); + wrapper.vm.openDrawer(); + await nextTick(); + expect(findDrawer().attributes('headerheight')).toBe(`${100}px`); + }); + + it('triggers height calculation in toggleDrawer', async () => { + expect(findDrawer().attributes('headerheight')).toBe(`${0}px`); + wrapper.vm.fetchMarkdown(); + wrapper.vm.toggleDrawer(); + await nextTick(); + expect(findDrawer().attributes('headerheight')).toBe(`${100}px`); + }); }); describe('Markdown fetching', () => { diff --git a/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js b/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js index c0cc54d8e2e..86a63db0d9e 100644 --- a/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js +++ b/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js @@ -10,7 +10,7 @@ import { TOKEN_TYPE_AUTHOR, } from '~/vue_shared/components/filtered_search_bar/constants'; import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue'; -import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue'; +import UserToken from '~/vue_shared/components/filtered_search_bar/tokens/user_token.vue'; import PageWrapper from '~/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue'; import mockItems from './mocks/items.json'; import mockFilters from './mocks/items_filters.json'; @@ -298,10 +298,10 @@ describe('AlertManagementEmptyState', () => { title: TOKEN_TITLE_AUTHOR, unique: true, symbol: '@', - token: AuthorToken, + token: UserToken, operators: OPERATORS_IS, fetchPath: '/link', - fetchAuthors: expect.any(Function), + fetchUsers: expect.any(Function), }, { type: TOKEN_TYPE_ASSIGNEE, @@ -309,10 +309,10 @@ describe('AlertManagementEmptyState', () => { title: TOKEN_TITLE_ASSIGNEE, unique: true, symbol: '@', - token: AuthorToken, + token: UserToken, operators: OPERATORS_IS, fetchPath: '/link', - fetchAuthors: expect.any(Function), + fetchUsers: expect.any(Function), }, ]); expect(Filters().props('recentSearchesStorageKey')).toBe('items'); |