summaryrefslogtreecommitdiff
path: root/spec/frontend/admin/topics/components/topic_select_spec.js
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/admin/topics/components/topic_select_spec.js')
-rw-r--r--spec/frontend/admin/topics/components/topic_select_spec.js122
1 files changed, 97 insertions, 25 deletions
diff --git a/spec/frontend/admin/topics/components/topic_select_spec.js b/spec/frontend/admin/topics/components/topic_select_spec.js
index f61af6203f0..738cbd88c4c 100644
--- a/spec/frontend/admin/topics/components/topic_select_spec.js
+++ b/spec/frontend/admin/topics/components/topic_select_spec.js
@@ -1,39 +1,66 @@
-import { GlAvatarLabeled, GlDropdown, GlDropdownItem } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
+import { GlAvatarLabeled, GlCollapsibleListbox, GlListboxItem } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
import TopicSelect from '~/admin/topics/components/topic_select.vue';
+import searchProjectTopics from '~/graphql_shared/queries/project_topics_search.query.graphql';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
const mockTopics = [
- { id: 1, name: 'topic1', title: 'Topic 1', avatarUrl: 'avatar.com/topic1.png' },
- { id: 2, name: 'GitLab', title: 'GitLab', avatarUrl: 'avatar.com/GitLab.png' },
+ {
+ id: 'gid://gitlab/Projects::Topic/6',
+ name: 'topic1',
+ title: 'Topic 1',
+ avatarUrl: 'avatar.com/topic1.png',
+ __typename: 'Topic',
+ },
+ {
+ id: 'gid://gitlab/Projects::Topic/5',
+ name: 'gitlab',
+ title: 'GitLab',
+ avatarUrl: 'avatar.com/GitLab.png',
+ __typename: 'Topic',
+ },
];
+const mockTopicsQueryResponse = {
+ data: {
+ topics: {
+ nodes: mockTopics,
+ __typename: 'TopicConnection',
+ },
+ },
+};
+
describe('TopicSelect', () => {
let wrapper;
+ const mockSearchTopicsSuccess = jest.fn().mockResolvedValue(mockTopicsQueryResponse);
+
+ const findListbox = () => wrapper.findComponent(GlCollapsibleListbox);
+ const findAllListboxItems = () => wrapper.findAllComponents(GlListboxItem);
- const findDropdown = () => wrapper.findComponent(GlDropdown);
- const findAllDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
+ function createMockApolloProvider({ mockSearchTopicsQuery = mockSearchTopicsSuccess } = {}) {
+ Vue.use(VueApollo);
+
+ return createMockApollo([[searchProjectTopics, mockSearchTopicsQuery]]);
+ }
- function createComponent(props = {}) {
- wrapper = shallowMount(TopicSelect, {
+ function createComponent({ props = {}, mockApollo } = {}) {
+ wrapper = mount(TopicSelect, {
+ apolloProvider: mockApollo || createMockApolloProvider(),
propsData: props,
data() {
return {
topics: mockTopics,
- search: '',
};
},
- mocks: {
- $apollo: {
- queries: {
- topics: { loading: false },
- },
- },
- },
});
}
afterEach(() => {
wrapper.destroy();
+ jest.clearAllMocks();
});
it('mounts', () => {
@@ -57,17 +84,27 @@ describe('TopicSelect', () => {
it('renders default text if no selected topic', () => {
createComponent();
- expect(findDropdown().props('text')).toBe('Select a topic');
+ expect(findListbox().props('toggleText')).toBe('Select a topic');
});
it('renders selected topic', () => {
- createComponent({ selectedTopic: mockTopics[0] });
+ const mockTopic = mockTopics[0];
- expect(findDropdown().props('text')).toBe('topic1');
+ createComponent({
+ props: {
+ selectedTopic: mockTopic,
+ },
+ });
+
+ expect(findListbox().props('toggleText')).toBe(mockTopic.name);
});
it('renders label', () => {
- createComponent({ labelText: 'my label' });
+ createComponent({
+ props: {
+ labelText: 'my label',
+ },
+ });
expect(wrapper.find('label').text()).toBe('my label');
});
@@ -75,17 +112,52 @@ describe('TopicSelect', () => {
it('renders dropdown items', () => {
createComponent();
- const dropdownItems = findAllDropdownItems();
+ const listboxItems = findAllListboxItems();
+
+ expect(listboxItems.at(0).findComponent(GlAvatarLabeled).props('label')).toBe('Topic 1');
+ expect(listboxItems.at(1).findComponent(GlAvatarLabeled).props('label')).toBe('GitLab');
+ });
+
+ it('dropdown `toggledAriaLabelledBy` prop is not set if `labelText` prop is null', () => {
+ createComponent();
- expect(dropdownItems.at(0).findComponent(GlAvatarLabeled).props('label')).toBe('Topic 1');
- expect(dropdownItems.at(1).findComponent(GlAvatarLabeled).props('label')).toBe('GitLab');
+ expect(findListbox().props('toggle-aria-labelled-by')).toBe(undefined);
});
- it('emits `click` event when topic selected', () => {
+ it('emits `click` event when topic selected', async () => {
createComponent();
- findAllDropdownItems().at(0).vm.$emit('click');
+ await findAllListboxItems().at(0).trigger('click');
expect(wrapper.emitted('click')).toEqual([[mockTopics[0]]]);
});
+
+ describe('when searching a topic', () => {
+ const searchTopic = (searchTerm) => findListbox().vm.$emit('search', searchTerm);
+ const mockSearchTerm = 'gitl';
+
+ it('toggles loading state', async () => {
+ createComponent();
+ jest.runOnlyPendingTimers();
+
+ await searchTopic(mockSearchTerm);
+
+ expect(findListbox().props('searching')).toBe(true);
+
+ await waitForPromises();
+
+ expect(findListbox().props('searching')).toBe(false);
+ });
+
+ it('fetches topics matching search string', async () => {
+ createComponent();
+
+ await searchTopic(mockSearchTerm);
+ jest.runOnlyPendingTimers();
+
+ expect(mockSearchTopicsSuccess).toHaveBeenCalledWith({
+ search: mockSearchTerm,
+ });
+ });
+ });
});