diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-08-08 15:07:09 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-08-08 15:07:09 +0300 |
commit | e44c3e4832e43c77e9c29fad6e49f8d6066d7f5c (patch) | |
tree | 892f4505093dd5ffd60e238a8b74b35f021654ae /spec/frontend | |
parent | aa1c2a29b8ddc82141f826eacd169d3d7ff66611 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend')
5 files changed, 192 insertions, 63 deletions
diff --git a/spec/frontend/super_sidebar/components/context_switcher_spec.js b/spec/frontend/super_sidebar/components/context_switcher_spec.js index 4317f451377..dd8f39e7cb7 100644 --- a/spec/frontend/super_sidebar/components/context_switcher_spec.js +++ b/spec/frontend/super_sidebar/components/context_switcher_spec.js @@ -15,7 +15,7 @@ import { trackContextAccess, formatContextSwitcherItems } from '~/super_sidebar/ import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants'; import waitForPromises from 'helpers/wait_for_promises'; import { stubComponent } from 'helpers/stub_component'; -import { searchUserProjectsAndGroupsResponseMock } from '../mock_data'; +import { contextSwitcherLinks, searchUserProjectsAndGroupsResponseMock } from '../mock_data'; jest.mock('~/super_sidebar/utils', () => ({ getStorageKeyFor: jest.requireActual('~/super_sidebar/utils').getStorageKeyFor, @@ -26,9 +26,6 @@ jest.mock('~/super_sidebar/utils', () => ({ })); const focusInputMock = jest.fn(); -const persistentLinks = [ - { title: 'Explore', link: '/explore', icon: 'compass', link_classes: 'persistent-link-class' }, -]; const username = 'root'; const projectsPath = 'projectsPath'; const groupsPath = 'groupsPath'; @@ -71,8 +68,10 @@ describe('ContextSwitcher component', () => { wrapper = shallowMountExtended(ContextSwitcher, { apolloProvider: mockApollo, + provide: { + contextSwitcherLinks, + }, propsData: { - persistentLinks, username, projectsPath, groupsPath, @@ -107,14 +106,14 @@ describe('ContextSwitcher component', () => { createWrapper(); }); - it('renders the persistent links', () => { + it('renders the context switcher links', () => { const navItems = findNavItems(); const firstNavItem = navItems.at(0); - expect(navItems.length).toBe(persistentLinks.length); - expect(firstNavItem.props('item')).toBe(persistentLinks[0]); + expect(navItems.length).toBe(contextSwitcherLinks.length); + expect(firstNavItem.props('item')).toBe(contextSwitcherLinks[0]); expect(firstNavItem.props('linkClasses')).toEqual({ - [persistentLinks[0].link_classes]: persistentLinks[0].link_classes, + [contextSwitcherLinks[0].link_classes]: contextSwitcherLinks[0].link_classes, }); }); diff --git a/spec/frontend/super_sidebar/components/global_search/components/global_search_default_items_spec.js b/spec/frontend/super_sidebar/components/global_search/components/global_search_default_items_spec.js index 52e9aa52c14..0fb6585e8ca 100644 --- a/spec/frontend/super_sidebar/components/global_search/components/global_search_default_items_spec.js +++ b/spec/frontend/super_sidebar/components/global_search/components/global_search_default_items_spec.js @@ -4,36 +4,42 @@ import Vuex from 'vuex'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import GlobalSearchDefaultItems from '~/super_sidebar/components/global_search/components/global_search_default_items.vue'; import { MOCK_SEARCH_CONTEXT, MOCK_DEFAULT_SEARCH_OPTIONS } from '../mock_data'; +import { contextSwitcherLinks } from '../../../mock_data'; Vue.use(Vuex); describe('GlobalSearchDefaultItems', () => { let wrapper; - const createComponent = (initialState, props) => { + const createComponent = ({ + storeState, + mockDefaultSearchOptions = MOCK_DEFAULT_SEARCH_OPTIONS, + ...options + } = {}) => { const store = new Vuex.Store({ state: { searchContext: MOCK_SEARCH_CONTEXT, - ...initialState, + ...storeState, }, getters: { - defaultSearchOptions: () => MOCK_DEFAULT_SEARCH_OPTIONS, + defaultSearchOptions: () => mockDefaultSearchOptions, }, }); wrapper = shallowMountExtended(GlobalSearchDefaultItems, { store, - propsData: { - ...props, + provide: { + contextSwitcherLinks, }, stubs: { GlDisclosureDropdownGroup, }, + ...options, }); }; - const findItems = () => wrapper.findAllComponents(GlDisclosureDropdownItem); - const findItemsData = () => findItems().wrappers.map((w) => w.props('item')); + const findGroups = () => wrapper.findAllComponents(GlDisclosureDropdownGroup); + const findItems = (root = wrapper) => root.findAllComponents(GlDisclosureDropdownItem); describe('template', () => { describe('Dropdown items', () => { @@ -41,12 +47,39 @@ describe('GlobalSearchDefaultItems', () => { createComponent(); }); - it('renders item for each option in defaultSearchOptions', () => { - expect(findItems()).toHaveLength(MOCK_DEFAULT_SEARCH_OPTIONS.length); + it('renders two groups', () => { + const groups = findGroups(); + + expect(groups).toHaveLength(2); + + const actualNames = groups.wrappers.map((group) => group.props('group').name); + expect(actualNames).toEqual(['Places', 'All GitLab']); + }); + + it('renders context switcher links in first group', () => { + const group = findGroups().at(0); + expect(group.props('group').name).toBe('Places'); + + const items = findItems(group); + expect(items).toHaveLength(contextSwitcherLinks.length); + }); + + it('renders default search options in second group', () => { + const group = findGroups().at(1); + expect(group.props('group').name).toBe('All GitLab'); + + const items = findItems(group); + expect(items).toHaveLength(MOCK_DEFAULT_SEARCH_OPTIONS.length); + }); + }); + + describe('Empty groups', () => { + beforeEach(() => { + createComponent({ mockDefaultSearchOptions: [], provide: { contextSwitcherLinks: [] } }); }); - it('provides the `item` prop to the `GlDisclosureDropdownItem` component', () => { - expect(findItemsData()).toStrictEqual(MOCK_DEFAULT_SEARCH_OPTIONS); + it('does not render groups with no items', () => { + expect(findGroups()).toHaveLength(0); }); }); @@ -55,13 +88,15 @@ describe('GlobalSearchDefaultItems', () => { ${null} | ${null} | ${'All GitLab'} ${{ name: 'Test Group' }} | ${null} | ${'Test Group'} ${{ name: 'Test Group' }} | ${{ name: 'Test Project' }} | ${'Test Project'} - `('Group Header', ({ group, project, groupHeader }) => { + `('Current context header', ({ group, project, groupHeader }) => { describe(`when group is ${group?.name} and project is ${project?.name}`, () => { beforeEach(() => { createComponent({ - searchContext: { - group, - project, + storeState: { + searchContext: { + group, + project, + }, }, }); }); diff --git a/spec/frontend/super_sidebar/components/global_search/mock_data.js b/spec/frontend/super_sidebar/components/global_search/mock_data.js index ad7e7b0b30b..dfa8b458844 100644 --- a/spec/frontend/super_sidebar/components/global_search/mock_data.js +++ b/spec/frontend/super_sidebar/components/global_search/mock_data.js @@ -62,6 +62,24 @@ export const MOCK_SEARCH_CONTEXT = { group_metadata: {}, }; +export const MOCK_GROUP_SEARCH_CONTEXT = { + ...MOCK_SEARCH_CONTEXT, + group: MOCK_GROUP, + group_metadata: { + issues_path: `${MOCK_GROUP.path}/issues`, + mr_path: `${MOCK_GROUP.path}/merge_requests`, + }, +}; + +export const MOCK_PROJECT_SEARCH_CONTEXT = { + ...MOCK_GROUP_SEARCH_CONTEXT, + project: MOCK_PROJECT, + project_metadata: { + issues_path: `${MOCK_PROJECT.path}/issues`, + mr_path: `${MOCK_PROJECT.path}/merge_requests`, + }, +}; + export const MOCK_DEFAULT_SEARCH_OPTIONS = [ { text: MSG_ISSUES_ASSIGNED_TO_ME, diff --git a/spec/frontend/super_sidebar/components/global_search/store/getters_spec.js b/spec/frontend/super_sidebar/components/global_search/store/getters_spec.js index 68583d04b31..de636d1feec 100644 --- a/spec/frontend/super_sidebar/components/global_search/store/getters_spec.js +++ b/spec/frontend/super_sidebar/components/global_search/store/getters_spec.js @@ -7,6 +7,8 @@ import { MOCK_MR_PATH, MOCK_AUTOCOMPLETE_PATH, MOCK_SEARCH_CONTEXT, + MOCK_GROUP_SEARCH_CONTEXT, + MOCK_PROJECT_SEARCH_CONTEXT, MOCK_DEFAULT_SEARCH_OPTIONS, MOCK_SCOPED_SEARCH_OPTIONS, MOCK_SCOPED_SEARCH_GROUP, @@ -74,37 +76,47 @@ describe('Global Search Store Getters', () => { }); describe.each` - group | group_metadata | project | project_metadata | expectedPath - ${null} | ${null} | ${null} | ${null} | ${MOCK_ISSUE_PATH} - ${{ name: 'Test Group' }} | ${{ issues_path: 'group/path' }} | ${null} | ${null} | ${'group/path'} - ${{ name: 'Test Group' }} | ${{ issues_path: 'group/path' }} | ${{ name: 'Test Project' }} | ${{ issues_path: 'project/path' }} | ${'project/path'} - `('scopedIssuesPath', ({ group, group_metadata, project, project_metadata, expectedPath }) => { - describe(`when group is ${group?.name} and project is ${project?.name}`, () => { - beforeEach(() => { - createState({ - searchContext: { - group, - group_metadata, - project, - project_metadata, - }, + group | group_metadata | project | project_metadata | user | expectedPath + ${null} | ${null} | ${null} | ${null} | ${'a_user'} | ${MOCK_ISSUE_PATH} + ${null} | ${null} | ${null} | ${null} | ${null} | ${false} + ${{ name: 'Test Group' }} | ${{ issues_path: 'group/path' }} | ${null} | ${null} | ${null} | ${'group/path'} + ${{ name: 'Test Group' }} | ${{ issues_path: 'group/path' }} | ${{ id: '123' }} | ${{ issues_path: 'project/path' }} | ${null} | ${'project/path'} + ${{ name: 'Test Group' }} | ${{ issues_path: 'group/path' }} | ${{ id: '123' }} | ${{}} | ${null} | ${false} + `( + 'scopedIssuesPath', + ({ group, group_metadata, project, project_metadata, user, expectedPath }) => { + describe(`when group is ${group?.name} and project is ${project?.name}`, () => { + beforeEach(() => { + window.gon.current_username = user; + + createState({ + searchContext: { + group, + group_metadata, + project, + project_metadata, + }, + }); }); - }); - it(`should return ${expectedPath}`, () => { - expect(getters.scopedIssuesPath(state)).toBe(expectedPath); + it(`should return ${expectedPath}`, () => { + expect(getters.scopedIssuesPath(state)).toBe(expectedPath); + }); }); - }); - }); + }, + ); describe.each` - group | group_metadata | project | project_metadata | expectedPath - ${null} | ${null} | ${null} | ${null} | ${MOCK_MR_PATH} - ${{ name: 'Test Group' }} | ${{ mr_path: 'group/path' }} | ${null} | ${null} | ${'group/path'} - ${{ name: 'Test Group' }} | ${{ mr_path: 'group/path' }} | ${{ name: 'Test Project' }} | ${{ mr_path: 'project/path' }} | ${'project/path'} - `('scopedMRPath', ({ group, group_metadata, project, project_metadata, expectedPath }) => { + group | group_metadata | project | project_metadata | user | expectedPath + ${null} | ${null} | ${null} | ${null} | ${'a_user'} | ${MOCK_MR_PATH} + ${null} | ${null} | ${null} | ${null} | ${null} | ${false} + ${{ name: 'Test Group' }} | ${{ mr_path: 'group/path' }} | ${null} | ${null} | ${null} | ${'group/path'} + ${{ name: 'Test Group' }} | ${{ mr_path: 'group/path' }} | ${{ name: 'Test Project' }} | ${{ mr_path: 'project/path' }} | ${null} | ${'project/path'} + `('scopedMRPath', ({ group, group_metadata, project, project_metadata, user, expectedPath }) => { describe(`when group is ${group?.name} and project is ${project?.name}`, () => { beforeEach(() => { + window.gon.current_username = user; + createState({ searchContext: { group, @@ -227,27 +239,88 @@ describe('Global Search Store Getters', () => { }); describe('defaultSearchOptions', () => { - const mockGetters = { - scopedIssuesPath: MOCK_ISSUE_PATH, - scopedMRPath: MOCK_MR_PATH, - }; + let mockGetters; beforeEach(() => { createState(); - window.gon.current_username = MOCK_USERNAME; + mockGetters = { + scopedIssuesPath: MOCK_ISSUE_PATH, + scopedMRPath: MOCK_MR_PATH, + }; }); - it('returns the correct array', () => { - expect(getters.defaultSearchOptions(state, mockGetters)).toStrictEqual( - MOCK_DEFAULT_SEARCH_OPTIONS, - ); + describe('with a user', () => { + beforeEach(() => { + window.gon.current_username = MOCK_USERNAME; + }); + + it('returns the correct array', () => { + expect(getters.defaultSearchOptions(state, mockGetters)).toStrictEqual( + MOCK_DEFAULT_SEARCH_OPTIONS, + ); + }); + + it('returns the correct array if issues path is false', () => { + mockGetters.scopedIssuesPath = undefined; + expect(getters.defaultSearchOptions(state, mockGetters)).toStrictEqual( + MOCK_DEFAULT_SEARCH_OPTIONS.slice(2, MOCK_DEFAULT_SEARCH_OPTIONS.length), + ); + }); }); - it('returns the correct array if issues path is false', () => { - mockGetters.scopedIssuesPath = undefined; - expect(getters.defaultSearchOptions(state, mockGetters)).toStrictEqual( - MOCK_DEFAULT_SEARCH_OPTIONS.slice(2, MOCK_DEFAULT_SEARCH_OPTIONS.length), - ); + describe('without a user', () => { + describe('with no project or group context', () => { + beforeEach(() => { + mockGetters = { + scopedIssuesPath: false, + scopedMRPath: false, + }; + }); + + it('returns an empty array', () => { + expect(getters.defaultSearchOptions(state, mockGetters)).toEqual([]); + }); + }); + + describe('with a group context', () => { + beforeEach(() => { + createState({ + searchContext: MOCK_GROUP_SEARCH_CONTEXT, + }); + + mockGetters = { + scopedIssuesPath: state.searchContext.group_metadata.issues_path, + scopedMRPath: state.searchContext.group_metadata.mr_path, + }; + }); + + it('returns recent issues/merge requests options', () => { + expect(getters.defaultSearchOptions(state, mockGetters)).toEqual([ + { href: '/mock-group/issues', text: 'Recent issues' }, + { href: '/mock-group/merge_requests', text: 'Recent merge requests' }, + ]); + }); + }); + + describe('with a project context', () => { + beforeEach(() => { + createState({ + searchContext: MOCK_PROJECT_SEARCH_CONTEXT, + }); + + mockGetters = { + scopedIssuesPath: state.searchContext.project_metadata.issues_path, + scopedMRPath: state.searchContext.project_metadata.mr_path, + }; + }); + + it('returns recent issues/merge requests options', () => { + expect(getters.defaultSearchOptions(state, mockGetters)).toEqual([ + { href: '/mock-project/issues', text: 'Recent issues' }, + { href: '/mock-project/merge_requests', text: 'Recent merge requests' }, + ]); + }); + }); }); }); diff --git a/spec/frontend/super_sidebar/mock_data.js b/spec/frontend/super_sidebar/mock_data.js index df45360a898..0d34329c60d 100644 --- a/spec/frontend/super_sidebar/mock_data.js +++ b/spec/frontend/super_sidebar/mock_data.js @@ -71,6 +71,10 @@ export const mergeRequestMenuGroup = [ }, ]; +export const contextSwitcherLinks = [ + { title: 'Explore', link: '/explore', icon: 'compass', link_classes: 'persistent-link-class' }, +]; + export const sidebarData = { is_logged_in: true, current_menu_items: [], @@ -104,7 +108,7 @@ export const sidebarData = { gitlab_version_check: { severity: 'success' }, gitlab_com_and_canary: false, canary_toggle_com_url: 'https://next.gitlab.com', - context_switcher_links: [], + context_switcher_links: contextSwitcherLinks, search: { search_path: '/search', }, |