diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-06-16 12:09:20 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-06-16 12:09:20 +0300 |
commit | 8ae36d93f1a63874b584f0488fde88c1fee999c4 (patch) | |
tree | f1788ba1a7fb00248ff008f817f6feea89304339 /spec/frontend/super_sidebar | |
parent | b394e58cc2e52e17e7991e3d7b705aa383c362ee (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/super_sidebar')
11 files changed, 252 insertions, 146 deletions
diff --git a/spec/frontend/super_sidebar/components/global_search/command_palette/__snapshots__/command_autocomplete_item_spec.js.snap b/spec/frontend/super_sidebar/components/global_search/command_palette/__snapshots__/command_autocomplete_item_spec.js.snap deleted file mode 100644 index 3c52cc195db..00000000000 --- a/spec/frontend/super_sidebar/components/global_search/command_palette/__snapshots__/command_autocomplete_item_spec.js.snap +++ /dev/null @@ -1,19 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`CommandAutocompleteItem should render user item 1`] = ` -<div - class="gl-display-flex gl-align-items-center" -> - <gl-icon-stub - class="gl-mr-3" - name="users" - size="16" - /> - - <span - class="gl-text-gray-900" - > - Manage > Activity - </span> -</div> -`; diff --git a/spec/frontend/super_sidebar/components/global_search/command_palette/__snapshots__/search_item_spec.js.snap b/spec/frontend/super_sidebar/components/global_search/command_palette/__snapshots__/search_item_spec.js.snap new file mode 100644 index 00000000000..d16d137db2f --- /dev/null +++ b/spec/frontend/super_sidebar/components/global_search/command_palette/__snapshots__/search_item_spec.js.snap @@ -0,0 +1,122 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`SearchItem should render the item 1`] = ` +<div + class="gl-display-flex gl-align-items-center" +> + <gl-avatar-stub + alt="avatar" + aria-hidden="true" + class="gl-mr-3" + entityid="37" + entityname="" + shape="rect" + size="16" + src="https://www.gravatar.com/avatar/a9638f4ec70148d51e56bf05ad41e993?s=80&d=identicon" + /> + + <!----> + + <span + class="gl-display-flex gl-flex-direction-column" + > + <span + class="gl-text-gray-900" + /> + + <!----> + </span> +</div> +`; + +exports[`SearchItem should render the item 2`] = ` +<div + class="gl-display-flex gl-align-items-center" +> + <!----> + + <gl-icon-stub + class="gl-mr-3" + name="users" + size="16" + /> + + <span + class="gl-display-flex gl-flex-direction-column" + > + <span + class="gl-text-gray-900" + > + Manage > Activity + </span> + + <!----> + </span> +</div> +`; + +exports[`SearchItem should render the item 3`] = ` +<div + class="gl-display-flex gl-align-items-center" +> + <gl-avatar-stub + alt="avatar" + aria-hidden="true" + class="gl-mr-3" + entityid="1" + entityname="MockProject1" + shape="rect" + size="32" + src="/project/avatar/1/avatar.png" + /> + + <!----> + + <span + class="gl-display-flex gl-flex-direction-column" + > + <span + class="gl-text-gray-900" + > + MockProject1 + </span> + + <span + class="gl-font-sm gl-text-gray-500" + > + Gitlab Org / MockProject1 + </span> + </span> +</div> +`; + +exports[`SearchItem should render the item 4`] = ` +<div + class="gl-display-flex gl-align-items-center" +> + <gl-avatar-stub + alt="avatar" + aria-hidden="true" + class="gl-mr-3" + entityid="7" + entityname="Flight" + shape="rect" + size="16" + src="" + /> + + <!----> + + <span + class="gl-display-flex gl-flex-direction-column" + > + <span + class="gl-text-gray-900" + > + Dismiss Cipher with no integrity + </span> + + <!----> + </span> +</div> +`; diff --git a/spec/frontend/super_sidebar/components/global_search/command_palette/__snapshots__/user_autocomplete_item_spec.js.snap b/spec/frontend/super_sidebar/components/global_search/command_palette/__snapshots__/user_autocomplete_item_spec.js.snap deleted file mode 100644 index 431cdce2955..00000000000 --- a/spec/frontend/super_sidebar/components/global_search/command_palette/__snapshots__/user_autocomplete_item_spec.js.snap +++ /dev/null @@ -1,34 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`UserAutocompleteItem should render user item 1`] = ` -<div - class="gl-display-flex gl-align-items-center" -> - <gl-avatar-stub - alt="avatar" - aria-hidden="true" - class="gl-mr-3" - entityid="37" - entityname="Cole Dickinson" - shape="rect" - size="16" - src="https://www.gravatar.com/avatar/a9638f4ec70148d51e56bf05ad41e993?s=80&d=identicon" - /> - - <span - class="gl-display-flex gl-flex-direction-column" - > - <span - class="gl-text-gray-900" - > - Cole Dickinson - </span> - - <span - class="gl-font-sm gl-text-gray-500" - > - reported_user_14 - </span> - </span> -</div> -`; diff --git a/spec/frontend/super_sidebar/components/global_search/command_palette/command_autocomplete_item_spec.js b/spec/frontend/super_sidebar/components/global_search/command_palette/command_autocomplete_item_spec.js deleted file mode 100644 index 2597812acaf..00000000000 --- a/spec/frontend/super_sidebar/components/global_search/command_palette/command_autocomplete_item_spec.js +++ /dev/null @@ -1,25 +0,0 @@ -import { shallowMount } from '@vue/test-utils'; -import CommandAutocompleteItem from '~/super_sidebar/components/global_search/command_palette/command_autocomplete_item.vue'; -import { linksReducer } from '~/super_sidebar/components/global_search/command_palette/utils'; -import { LINKS } from './mock_data'; - -describe('CommandAutocompleteItem', () => { - let wrapper; - - const createComponent = () => { - wrapper = shallowMount(CommandAutocompleteItem, { - propsData: { - command: LINKS.reduce(linksReducer, [])[1], - searchQuery: 'root', - }, - }); - }; - - beforeEach(() => { - createComponent(); - }); - - it('should render user item', () => { - expect(wrapper.element).toMatchSnapshot(); - }); -}); diff --git a/spec/frontend/super_sidebar/components/global_search/command_palette/command_palette_items_spec.js b/spec/frontend/super_sidebar/components/global_search/command_palette/command_palette_items_spec.js index bd1e0dbc15d..21d085dc0fb 100644 --- a/spec/frontend/super_sidebar/components/global_search/command_palette/command_palette_items_spec.js +++ b/spec/frontend/super_sidebar/components/global_search/command_palette/command_palette_items_spec.js @@ -7,11 +7,13 @@ import { COMMAND_HANDLE, USERS_GROUP_TITLE, USER_HANDLE, + SEARCH_SCOPE, } from '~/super_sidebar/components/global_search/command_palette/constants'; import { - userMapper, + commandMapper, linksReducer, } from '~/super_sidebar/components/global_search/command_palette/utils'; +import { getFormattedItem } from '~/super_sidebar/components/global_search/utils'; import axios from '~/lib/utils/axios_utils'; import { HTTP_STATUS_OK } from '~/lib/utils/http_status'; import waitForPromises from 'helpers/wait_for_promises'; @@ -21,6 +23,8 @@ const links = LINKS.reduce(linksReducer, []); describe('CommandPaletteItems', () => { let wrapper; + const autocompletePath = '/autocomplete'; + const searchContext = { project: { id: 1 }, group: { id: 2 } }; const createComponent = (props) => { wrapper = shallowMount(CommandPaletteItems, { @@ -36,32 +40,34 @@ describe('CommandPaletteItems', () => { provide: { commandPaletteCommands: COMMANDS, commandPaletteLinks: LINKS, + autocompletePath, + searchContext, }, }); }; const findItems = () => wrapper.findAllComponents(GlDisclosureDropdownItem); - const findGroup = () => wrapper.findComponent(GlDisclosureDropdownGroup); + const findGroups = () => wrapper.findAllComponents(GlDisclosureDropdownGroup); const findLoader = () => wrapper.findComponent(GlLoadingIcon); describe('COMMANDS & LINKS', () => { it('renders all commands initially', () => { createComponent(); - const commandGroup = COMMANDS[0]; + const commandGroup = COMMANDS.map(commandMapper)[0]; expect(findItems()).toHaveLength(commandGroup.items.length); - expect(findGroup().props('group')).toEqual({ + expect(findGroups().at(0).props('group')).toEqual({ name: commandGroup.name, items: commandGroup.items, }); }); describe('with search query', () => { - it('should filter comamnds and links by the search query', async () => { + it('should filter commands and links by the search query', async () => { jest.spyOn(fuzzaldrinPlus, 'filter'); createComponent({ searchQuery: 'mr' }); const searchQuery = 'todo'; await wrapper.setProps({ searchQuery }); - const commandGroup = COMMANDS[0]; + const commandGroup = COMMANDS.map(commandMapper)[0]; expect(fuzzaldrinPlus.filter).toHaveBeenCalledWith( commandGroup.items, searchQuery, @@ -84,14 +90,14 @@ describe('CommandPaletteItems', () => { }); }); - describe('USERS', () => { + describe('USERS, ISSUES, PROJECTS', () => { let mockAxios; beforeEach(() => { mockAxios = new MockAdapter(axios); }); - it('should NOT start search for users by the search query which is less than 3 chars', () => { + it('should NOT start search by the search query which is less than 3 chars', () => { jest.spyOn(axios, 'get'); const searchQuery = 'us'; createComponent({ handle: USER_HANDLE, searchQuery }); @@ -101,24 +107,18 @@ describe('CommandPaletteItems', () => { expect(findLoader().exists()).toBe(false); }); - it('should start search for users by the search query with 3+ chars and display a loader', () => { + it('should start scoped search with 3+ chars and display a loader', () => { jest.spyOn(axios, 'get'); const searchQuery = 'user'; createComponent({ handle: USER_HANDLE, searchQuery }); expect(axios.get).toHaveBeenCalledWith( - expect.any(String), - expect.objectContaining({ - params: { - search: searchQuery, - }, - }), + `${autocompletePath}?term=${searchQuery}&project_id=${searchContext.project.id}&filter=search&scope=${SEARCH_SCOPE[USER_HANDLE]}`, ); - expect(findLoader().exists()).toBe(true); }); - it('should render returned users', async () => { + it('should render returned items', async () => { mockAxios.onGet().replyOnce(HTTP_STATUS_OK, USERS); const searchQuery = 'user'; @@ -126,9 +126,9 @@ describe('CommandPaletteItems', () => { await waitForPromises(); expect(findItems()).toHaveLength(USERS.length); - expect(findGroup().props('group')).toEqual({ + expect(findGroups().at(0).props('group')).toMatchObject({ name: USERS_GROUP_TITLE, - items: USERS.map(userMapper), + items: USERS.map(getFormattedItem), }); }); diff --git a/spec/frontend/super_sidebar/components/global_search/command_palette/fake_search_input_spec.js b/spec/frontend/super_sidebar/components/global_search/command_palette/fake_search_input_spec.js index 0aeb4c89d06..a8e91395303 100644 --- a/spec/frontend/super_sidebar/components/global_search/command_palette/fake_search_input_spec.js +++ b/spec/frontend/super_sidebar/components/global_search/command_palette/fake_search_input_spec.js @@ -1,8 +1,9 @@ import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import FakeSearchInput from '~/super_sidebar/components/global_search/command_palette/fake_search_input.vue'; import { + SEARCH_SCOPE_PLACEHOLDER, + COMMON_HANDLES, COMMAND_HANDLE, - SEARCH_SCOPE, } from '~/super_sidebar/components/global_search/command_palette/constants'; describe('FakeSearchInput', () => { @@ -27,10 +28,13 @@ describe('FakeSearchInput', () => { }); describe('placeholder', () => { - it('should render the placeholder for its search scope when there is no user input', () => { - createComponent(); - expect(findSearchScopePlaceholder().text()).toBe(SEARCH_SCOPE[COMMAND_HANDLE]); - }); + it.each(COMMON_HANDLES)( + 'should render the placeholder for the %s scope when there is no user input', + (scope) => { + createComponent({ scope }); + expect(findSearchScopePlaceholder().text()).toBe(SEARCH_SCOPE_PLACEHOLDER[scope]); + }, + ); it('should NOT render the placeholder when there is user input', () => { createComponent({ userInput: 'todo' }); diff --git a/spec/frontend/super_sidebar/components/global_search/command_palette/mock_data.js b/spec/frontend/super_sidebar/components/global_search/command_palette/mock_data.js index 726339f56a1..ec65a43d549 100644 --- a/spec/frontend/super_sidebar/components/global_search/command_palette/mock_data.js +++ b/spec/frontend/super_sidebar/components/global_search/command_palette/mock_data.js @@ -5,17 +5,19 @@ export const COMMANDS = [ { text: 'New project/repository', href: '/projects/new', - keywords: ['new', 'project', 'repository'], }, { text: 'New group', href: '/groups/new', - keywords: ['new', 'group'], }, { text: 'New snippet', href: '/-/snippets/new', - keywords: ['new', 'snippet'], + }, + { + text: 'Invite members', + href: '/-/snippets/new', + component: 'invite_members', }, ], }, @@ -61,6 +63,33 @@ export const LINKS = [ }, ]; +export const TRANSFORMED_LINKS = [ + { + href: '/flightjs/Flight/activity', + icon: 'users', + keywords: 'Manage', + text: 'Manage', + }, + { + href: '/flightjs/Flight/activity', + icon: 'users', + keywords: 'Activity', + text: 'Manage > Activity', + }, + { + href: '/flightjs/Flight/-/project_members', + icon: 'users', + keywords: 'Members', + text: 'Manage > Members', + }, + { + href: '/flightjs/Flight/-/labels', + icon: 'users', + keywords: 'Labels', + text: 'Manage > Labels', + }, +]; + export const USERS = [ { id: 37, @@ -83,3 +112,22 @@ export const USERS = [ web_url: 'http://127.0.0.1:3000/reported_user_7', }, ]; + +export const PROJECT = { + category: 'Projects', + id: 1, + label: 'Gitlab Org / MockProject1', + value: 'MockProject1', + url: 'project/1', + avatar_url: '/project/avatar/1/avatar.png', +}; + +export const ISSUE = { + avatar_url: '', + category: 'Recent issues', + id: 516, + label: 'Dismiss Cipher with no integrity', + project_id: 7, + project_name: 'Flight', + url: '/flightjs/Flight/-/issues/37', +}; diff --git a/spec/frontend/super_sidebar/components/global_search/command_palette/search_item_spec.js b/spec/frontend/super_sidebar/components/global_search/command_palette/search_item_spec.js new file mode 100644 index 00000000000..c7e49310588 --- /dev/null +++ b/spec/frontend/super_sidebar/components/global_search/command_palette/search_item_spec.js @@ -0,0 +1,33 @@ +import { shallowMount } from '@vue/test-utils'; +import SearchItem from '~/super_sidebar/components/global_search/command_palette/search_item.vue'; +import { getFormattedItem } from '~/super_sidebar/components/global_search/utils'; +import { linksReducer } from '~/super_sidebar/components/global_search/command_palette/utils'; +import { USERS, LINKS, PROJECT, ISSUE } from './mock_data'; + +jest.mock('~/lib/utils/highlight', () => ({ + __esModule: true, + default: (text) => text, +})); +const mockUser = getFormattedItem(USERS[0]); +const mockCommand = LINKS.reduce(linksReducer, [])[1]; +const mockProject = getFormattedItem(PROJECT); +const mockIssue = getFormattedItem(ISSUE); + +describe('SearchItem', () => { + let wrapper; + + const createComponent = (item) => { + wrapper = shallowMount(SearchItem, { + propsData: { + item, + searchQuery: 'root', + }, + }); + }; + + it.each([mockUser, mockCommand, mockProject, mockIssue])('should render the item', (item) => { + createComponent(item); + + expect(wrapper.element).toMatchSnapshot(); + }); +}); diff --git a/spec/frontend/super_sidebar/components/global_search/command_palette/user_autocomplete_item_spec.js b/spec/frontend/super_sidebar/components/global_search/command_palette/user_autocomplete_item_spec.js deleted file mode 100644 index 5abb56228a4..00000000000 --- a/spec/frontend/super_sidebar/components/global_search/command_palette/user_autocomplete_item_spec.js +++ /dev/null @@ -1,25 +0,0 @@ -import { shallowMount } from '@vue/test-utils'; -import UserAutocompleteItem from '~/super_sidebar/components/global_search/command_palette/user_autocomplete_item.vue'; -import { userMapper } from '~/super_sidebar/components/global_search/command_palette/utils'; -import { USERS } from './mock_data'; - -describe('UserAutocompleteItem', () => { - let wrapper; - - const createComponent = () => { - wrapper = shallowMount(UserAutocompleteItem, { - propsData: { - user: USERS.map(userMapper)[0], - searchQuery: 'root', - }, - }); - }; - - beforeEach(() => { - createComponent(); - }); - - it('should render user item', () => { - expect(wrapper.element).toMatchSnapshot(); - }); -}); diff --git a/spec/frontend/super_sidebar/components/global_search/command_palette/utils_spec.js b/spec/frontend/super_sidebar/components/global_search/command_palette/utils_spec.js index 74a5247add5..0b75787723e 100644 --- a/spec/frontend/super_sidebar/components/global_search/command_palette/utils_spec.js +++ b/spec/frontend/super_sidebar/components/global_search/command_palette/utils_spec.js @@ -1,15 +1,18 @@ -import { userMapper } from '~/super_sidebar/components/global_search/command_palette/utils'; -import { USERS } from './mock_data'; +import { + commandMapper, + linksReducer, +} from '~/super_sidebar/components/global_search/command_palette/utils'; +import { COMMANDS, LINKS, TRANSFORMED_LINKS } from './mock_data'; -describe('userMapper', () => { - it('should transform users response', () => { - const user = USERS[0]; - expect(userMapper(user)).toEqual({ - id: user.id, - username: user.username, - text: user.name, - href: user.web_url, - avatar_url: user.avatar_url, - }); +describe('linksReducer', () => { + it('should transform links', () => { + expect(LINKS.reduce(linksReducer, [])).toEqual(TRANSFORMED_LINKS); + }); +}); + +describe('commandMapper', () => { + it('should temporarily remove the `invite_members` item', () => { + const initialCommandsLength = COMMANDS[0].items.length; + expect(COMMANDS.map(commandMapper)[0].items).toHaveLength(initialCommandsLength - 1); }); }); diff --git a/spec/frontend/super_sidebar/components/global_search/components/global_search_spec.js b/spec/frontend/super_sidebar/components/global_search/components/global_search_spec.js index 0a6d5919207..9b7b9e288df 100644 --- a/spec/frontend/super_sidebar/components/global_search/components/global_search_spec.js +++ b/spec/frontend/super_sidebar/components/global_search/components/global_search_spec.js @@ -11,8 +11,7 @@ import FakeSearchInput from '~/super_sidebar/components/global_search/command_pa import CommandPaletteItems from '~/super_sidebar/components/global_search/command_palette/command_palette_items.vue'; import { SEARCH_OR_COMMAND_MODE_PLACEHOLDER, - COMMAND_HANDLE, - USER_HANDLE, + COMMON_HANDLES, } from '~/super_sidebar/components/global_search/command_palette/constants'; import { SEARCH_INPUT_DESCRIPTION, @@ -320,8 +319,8 @@ describe('GlobalSearchModal', () => { }); }); - describe.each([COMMAND_HANDLE, USER_HANDLE])( - 'when FF `command_palette` is enabled', + describe.each(COMMON_HANDLES)( + 'when FF `command_palette` is enabled and search handle is %s', (handle) => { beforeEach(() => { createComponent({ search: handle }, undefined, undefined, { |