Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-11-02 21:12:04 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-11-02 21:12:04 +0300
commiteed7260f13c0a3139876e3659603f3d803e8fcd7 (patch)
treef877bb301ff936d73516241ad608271bc5a624fd /spec/frontend/vue_shared/components
parentef211f6aff22891e232a700b61d2d3bf567ed6bf (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/vue_shared/components')
-rw-r--r--spec/frontend/vue_shared/components/entity_select/entity_select_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/list_selector/group_item_spec.js55
-rw-r--r--spec/frontend/vue_shared/components/list_selector/index_spec.js123
-rw-r--r--spec/frontend/vue_shared/components/list_selector/mock_data.js24
-rw-r--r--spec/frontend/vue_shared/components/list_selector/user_item_spec.js (renamed from spec/frontend/vue_shared/components/list_selector/user_spec.js)6
5 files changed, 193 insertions, 19 deletions
diff --git a/spec/frontend/vue_shared/components/entity_select/entity_select_spec.js b/spec/frontend/vue_shared/components/entity_select/entity_select_spec.js
index 72d9f699821..1376133ec37 100644
--- a/spec/frontend/vue_shared/components/entity_select/entity_select_spec.js
+++ b/spec/frontend/vue_shared/components/entity_select/entity_select_spec.js
@@ -71,7 +71,7 @@ describe('EntitySelect', () => {
fetchItemsMock = jest.fn().mockImplementation(() => ({ items: [itemMock], totalPages: 1 }));
});
- describe('GlCollapsableListbox props', () => {
+ describe('GlCollapsibleListbox props', () => {
beforeEach(() => {
createComponent();
});
@@ -81,7 +81,7 @@ describe('EntitySelect', () => {
${'block'} | ${block}
${'toggleClass'} | ${toggleClass}
${'headerText'} | ${headerText}
- `('passes the $prop prop to GlCollapsableListbox', ({ prop, expectedValue }) => {
+ `('passes the $prop prop to GlCollapsibleListbox', ({ prop, expectedValue }) => {
expect(findListbox().props(prop)).toBe(expectedValue);
});
});
diff --git a/spec/frontend/vue_shared/components/list_selector/group_item_spec.js b/spec/frontend/vue_shared/components/list_selector/group_item_spec.js
new file mode 100644
index 00000000000..b59e4c734c1
--- /dev/null
+++ b/spec/frontend/vue_shared/components/list_selector/group_item_spec.js
@@ -0,0 +1,55 @@
+import { GlAvatar } from '@gitlab/ui';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import GroupItem from '~/vue_shared/components/list_selector/group_item.vue';
+
+describe('GroupItem spec', () => {
+ let wrapper;
+
+ const MOCK_GROUP = { fullName: 'Group 1', name: 'group1', avatarUrl: 'some/avatar.jpg' };
+
+ const createComponent = (props) => {
+ wrapper = mountExtended(GroupItem, {
+ propsData: {
+ data: MOCK_GROUP,
+ ...props,
+ },
+ });
+ };
+
+ const findAvatar = () => wrapper.findComponent(GlAvatar);
+ const findDeleteButton = () => wrapper.findByRole('button', { fullName: 'Delete Group 1' });
+
+ beforeEach(() => createComponent());
+
+ it('renders an Avatar component', () => {
+ expect(findAvatar().props('size')).toBe(32);
+ expect(findAvatar().attributes()).toMatchObject({
+ src: MOCK_GROUP.avatarUrl,
+ alt: MOCK_GROUP.fullName,
+ });
+ });
+
+ it('renders a fullName and name', () => {
+ expect(wrapper.text()).toContain('Group 1');
+ expect(wrapper.text()).toContain('@group1');
+ });
+
+ it('does not render a delete button by default', () => {
+ expect(findDeleteButton().exists()).toBe(false);
+ });
+
+ describe('Delete button', () => {
+ beforeEach(() => createComponent({ canDelete: true }));
+
+ it('renders a delete button', () => {
+ expect(findDeleteButton().exists()).toBe(true);
+ expect(findDeleteButton().props('icon')).toBe('remove');
+ });
+
+ it('emits a delete event if the delete button is clicked', () => {
+ findDeleteButton().trigger('click');
+
+ expect(wrapper.emitted('delete')).toEqual([[MOCK_GROUP.name]]);
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/list_selector/index_spec.js b/spec/frontend/vue_shared/components/list_selector/index_spec.js
index 96074519857..4222a28afe8 100644
--- a/spec/frontend/vue_shared/components/list_selector/index_spec.js
+++ b/spec/frontend/vue_shared/components/list_selector/index_spec.js
@@ -3,11 +3,13 @@ import VueApollo from 'vue-apollo';
import { GlCard, GlIcon, GlCollapsibleListbox, GlSearchBoxByType } from '@gitlab/ui';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import ListSelector from '~/vue_shared/components/list_selector/index.vue';
-import User from '~/vue_shared/components/list_selector/user.vue';
+import UserItem from '~/vue_shared/components/list_selector/user_item.vue';
+import GroupItem from '~/vue_shared/components/list_selector/group_item.vue';
import usersAutocompleteQuery from '~/graphql_shared/queries/users_autocomplete.query.graphql';
+import groupsAutocompleteQuery from '~/graphql_shared/queries/groups_autocomplete.query.graphql';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import { USERS_RESPONSE_MOCK } from './mock_data';
+import { USERS_RESPONSE_MOCK, GROUPS_RESPONSE_MOCK } from './mock_data';
Vue.use(VueApollo);
@@ -15,21 +17,31 @@ describe('List Selector spec', () => {
let wrapper;
let fakeApollo;
- const MOCK_PROPS = {
+ const USERS_MOCK_PROPS = {
title: 'Users',
projectPath: 'some/project/path',
type: 'users',
};
+ const GROUPS_MOCK_PROPS = {
+ title: 'Groups',
+ projectPath: 'some/project/path',
+ type: 'groups',
+ };
+
const usersAutocompleteQuerySuccess = jest.fn().mockResolvedValue(USERS_RESPONSE_MOCK);
+ const groupsAutocompleteQuerySuccess = jest.fn().mockResolvedValue(GROUPS_RESPONSE_MOCK);
- const createComponent = async (props) => {
- fakeApollo = createMockApollo([[usersAutocompleteQuery, usersAutocompleteQuerySuccess]]);
+ const createComponent = async (
+ props,
+ query = usersAutocompleteQuery,
+ queryResponse = usersAutocompleteQuerySuccess,
+ ) => {
+ fakeApollo = createMockApollo([[query, queryResponse]]);
wrapper = mountExtended(ListSelector, {
apolloProvider: fakeApollo,
propsData: {
- ...MOCK_PROPS,
...props,
},
});
@@ -38,21 +50,23 @@ describe('List Selector spec', () => {
};
const findCard = () => wrapper.findComponent(GlCard);
- const findTitle = () => wrapper.findByText(MOCK_PROPS.title);
+ const findTitle = () => findCard().find('[data-testid="list-selector-title"]');
const findIcon = () => wrapper.findComponent(GlIcon);
const findListBox = () => wrapper.findComponent(GlCollapsibleListbox);
const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType);
- const findAllUserComponents = () => wrapper.findAllComponents(User);
+ const findAllUserComponents = () => wrapper.findAllComponents(UserItem);
+ const findAllGroupComponents = () => wrapper.findAllComponents(GroupItem);
describe('Users type', () => {
- beforeEach(() => createComponent({ type: 'users' }));
+ beforeEach(() => createComponent(USERS_MOCK_PROPS));
it('renders a Card component', () => {
expect(findCard().exists()).toBe(true);
});
- it('renders a title', () => {
+ it('renders a correct title', () => {
expect(findTitle().exists()).toBe(true);
+ expect(findTitle().text()).toContain('Users');
});
it('renders the correct icon', () => {
@@ -81,7 +95,7 @@ describe('List Selector spec', () => {
it('calls query with correct variables when Search box receives an input', () => {
expect(usersAutocompleteQuerySuccess).toHaveBeenCalledWith({
- fullPath: MOCK_PROPS.projectPath,
+ fullPath: USERS_MOCK_PROPS.projectPath,
isProject: true,
search,
});
@@ -108,11 +122,11 @@ describe('List Selector spec', () => {
describe('selected items', () => {
const selectedUser = { username: 'root' };
const selectedItems = [selectedUser];
- beforeEach(() => createComponent({ selectedItems }));
+ beforeEach(() => createComponent({ ...USERS_MOCK_PROPS, selectedItems }));
it('renders a heading with the total selected items', () => {
- expect(findCard().text()).toContain('Users');
- expect(findCard().text()).toContain('1');
+ expect(findTitle().text()).toContain('Users');
+ expect(findTitle().text()).toContain('1');
});
it('renders a user component for each selected item', () => {
@@ -131,4 +145,85 @@ describe('List Selector spec', () => {
});
});
});
+
+ describe('Groups type', () => {
+ beforeEach(() =>
+ createComponent(GROUPS_MOCK_PROPS, groupsAutocompleteQuery, groupsAutocompleteQuerySuccess),
+ );
+
+ it('renders a correct title', () => {
+ expect(findTitle().exists()).toBe(true);
+ expect(findTitle().text()).toContain('Groups');
+ });
+
+ it('renders the correct icon', () => {
+ expect(findIcon().props('name')).toBe('group');
+ });
+
+ it('does not call query when search box has not received an input', () => {
+ expect(groupsAutocompleteQuerySuccess).not.toHaveBeenCalled();
+ expect(findAllGroupComponents().length).toBe(0);
+ });
+
+ describe('searching', () => {
+ const searchResponse = GROUPS_RESPONSE_MOCK.data.groups.nodes;
+ const search = 'foo';
+
+ const emitSearchInput = async () => {
+ findSearchBox().vm.$emit('input', search);
+ await waitForPromises();
+ };
+
+ beforeEach(() => emitSearchInput());
+
+ it('calls query with correct variables when Search box receives an input', () => {
+ expect(groupsAutocompleteQuerySuccess).toHaveBeenCalledWith({
+ search,
+ });
+ });
+
+ it('renders a List box component with the correct props', () => {
+ expect(findListBox().props()).toMatchObject({ multiple: true, items: searchResponse });
+ });
+
+ it('renders a group component for each search result', () => {
+ expect(findAllGroupComponents().length).toBe(searchResponse.length);
+ });
+
+ it('emits an event when a search result is selected', () => {
+ const firstSearchResult = searchResponse[0];
+ findAllGroupComponents().at(0).vm.$emit('select', firstSearchResult.name);
+
+ expect(wrapper.emitted('select')).toEqual([
+ [{ ...firstSearchResult, text: 'Flightjs', value: 'Flightjs' }],
+ ]);
+ });
+ });
+
+ describe('selected items', () => {
+ const selectedGroup = { name: 'Flightjs' };
+ const selectedItems = [selectedGroup];
+ beforeEach(() => createComponent({ ...GROUPS_MOCK_PROPS, selectedItems }));
+
+ it('renders a heading with the total selected items', () => {
+ expect(findTitle().text()).toContain('Groups');
+ expect(findTitle().text()).toContain('1');
+ });
+
+ it('renders a group component for each selected item', () => {
+ expect(findAllGroupComponents().length).toBe(selectedItems.length);
+ expect(findAllGroupComponents().at(0).props()).toMatchObject({
+ data: selectedGroup,
+ canDelete: true,
+ });
+ });
+
+ it('emits a delete event when a delete event is emitted from the group component', () => {
+ const name = 'Flightjs';
+ findAllGroupComponents().at(0).vm.$emit('delete', name);
+
+ expect(wrapper.emitted('delete')).toEqual([[name]]);
+ });
+ });
+ });
});
diff --git a/spec/frontend/vue_shared/components/list_selector/mock_data.js b/spec/frontend/vue_shared/components/list_selector/mock_data.js
index ce5d209a938..25ecac9632b 100644
--- a/spec/frontend/vue_shared/components/list_selector/mock_data.js
+++ b/spec/frontend/vue_shared/components/list_selector/mock_data.js
@@ -23,3 +23,27 @@ export const USERS_RESPONSE_MOCK = {
},
},
};
+
+export const GROUPS_RESPONSE_MOCK = {
+ data: {
+ groups: {
+ nodes: [
+ {
+ id: 'gid://gitlab/Group/33',
+ name: 'Flightjs',
+ fullName: 'Flightjs',
+ avatarUrl: null,
+ __typename: 'Group',
+ },
+ {
+ id: 'gid://gitlab/Group/34',
+ name: 'Flight 2',
+ fullName: 'Flight2',
+ avatarUrl: null,
+ __typename: 'Group',
+ },
+ ],
+ __typename: 'GroupConnection',
+ },
+ },
+};
diff --git a/spec/frontend/vue_shared/components/list_selector/user_spec.js b/spec/frontend/vue_shared/components/list_selector/user_item_spec.js
index 5ce21f6672b..d84a29c67e0 100644
--- a/spec/frontend/vue_shared/components/list_selector/user_spec.js
+++ b/spec/frontend/vue_shared/components/list_selector/user_item_spec.js
@@ -1,14 +1,14 @@
import { GlAvatar } from '@gitlab/ui';
import { mountExtended } from 'helpers/vue_test_utils_helper';
-import User from '~/vue_shared/components/list_selector/user.vue';
+import UserItem from '~/vue_shared/components/list_selector/user_item.vue';
-describe('User spec', () => {
+describe('UserItem spec', () => {
let wrapper;
const MOCK_USER = { name: 'Admin', username: 'root', avatarUrl: 'some/avatar.jpg' };
const createComponent = (props) => {
- wrapper = mountExtended(User, {
+ wrapper = mountExtended(UserItem, {
propsData: {
data: MOCK_USER,
...props,