diff options
Diffstat (limited to 'spec/frontend/blob/filepath_form/components/template_selector_spec.js')
-rw-r--r-- | spec/frontend/blob/filepath_form/components/template_selector_spec.js | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/spec/frontend/blob/filepath_form/components/template_selector_spec.js b/spec/frontend/blob/filepath_form/components/template_selector_spec.js new file mode 100644 index 00000000000..b1419320e1e --- /dev/null +++ b/spec/frontend/blob/filepath_form/components/template_selector_spec.js @@ -0,0 +1,167 @@ +import { GlCollapsibleListbox } from '@gitlab/ui'; +import { shallowMount } from '@vue/test-utils'; +import { nextTick } from 'vue'; +import TemplateSelector from '~/blob/filepath_form/components/template_selector.vue'; +import SuggestGitlabCiYml from '~/blob/suggest_gitlab_ci_yml/components/popover.vue'; +import { Templates as TemplatesMock, SuggestCiYmlData as SuggestCiYmlDataMock } from './mock_data'; + +describe('Template Selector component', () => { + let wrapper; + + const findListbox = () => wrapper.findComponent(GlCollapsibleListbox); + const findSuggestCiYmlPopover = () => wrapper.findComponent(SuggestGitlabCiYml); + const findDisplayedTemplates = () => + findListbox() + .props('items') + .reduce((acc, item) => [...acc, ...item.options], []) + .map((template) => template.value); + + const getTemplateKeysFromMock = (key) => + Object.values(TemplatesMock[key]) + .reduce((acc, items) => [...acc, ...items], []) + .map((template) => template.key); + + const createComponent = (props = {}) => { + wrapper = shallowMount(TemplateSelector, { + propsData: { + filename: '', + templates: TemplatesMock, + ...props, + }, + }); + }; + + describe('when filename input is empty', () => { + beforeEach(() => { + createComponent(); + }); + + it('does not render listbox', () => { + expect(findListbox().exists()).toBe(false); + }); + + it('does not render suggest-ci-yml popover', () => { + expect(findSuggestCiYmlPopover().exists()).toBe(false); + }); + }); + + describe.each` + filename | key + ${'LICENSE'} | ${'licenses'} + ${'Dockerfile'} | ${'dockerfile_names'} + ${'.gitignore'} | ${'gitignore_names'} + ${'.gitlab-ci.yml'} | ${'gitlab_ci_ymls'} + `('when filename is $filename', ({ filename, key }) => { + beforeEach(() => { + createComponent({ filename }); + }); + + it('renders listbox with correct props', () => { + expect(findListbox().exists()).toBe(true); + expect(findListbox().props('toggleText')).toBe('Apply a template'); + expect(findListbox().props('searchPlaceholder')).toBe('Filter'); + expect(findDisplayedTemplates()).toEqual(getTemplateKeysFromMock(key)); + }); + + it('does not render suggest-ci-yml popover', () => { + expect(findSuggestCiYmlPopover().exists()).toBe(false); + }); + }); + + describe('when filename input is .gitlab-ci.yml with suggestCiYmlData prop', () => { + beforeEach(() => { + createComponent({ filename: '.gitlab-ci.yml', suggestCiYmlData: SuggestCiYmlDataMock }); + }); + + it('renders listbox with correct props', () => { + expect(findListbox().exists()).toBe(true); + expect(findListbox().props('toggleText')).toBe('Apply a template'); + expect(findListbox().props('searchPlaceholder')).toBe('Filter'); + }); + + it('renders suggest-ci-yml popover', () => { + expect(findSuggestCiYmlPopover().exists()).toBe(true); + }); + }); + + describe('has filename that matches template pattern', () => { + const filename = 'LICENSE'; + const templates = TemplatesMock.licenses.Other; + + describe('has initial template prop', () => { + const initialTemplate = TemplatesMock.licenses.Other[0]; + + beforeEach(() => { + createComponent({ filename, initialTemplate: initialTemplate.key }); + }); + + it('renders listbox toggle button with selected template name', () => { + expect(findListbox().props('toggleText')).toBe(initialTemplate.name); + }); + + it('selected template is checked', () => { + expect(findListbox().props('selected')).toBe(initialTemplate.key); + }); + }); + + describe('when template is selected', () => { + beforeEach(() => { + createComponent({ filename }); + findListbox().vm.$emit('select', templates[0].key); + }); + + it('emit `selected` event with selected template', () => { + const licenseSelectorType = { + key: 'licenses', + name: 'LICENSE', + pattern: /^(.+\/)?(licen[sc]e|copying)($|\.)/i, + type: 'licenses', + }; + + const { template, type } = wrapper.emitted('selected')[0][0]; + expect(template).toBe(templates[0]); + expect(type).toMatchObject(licenseSelectorType); + }); + + it('set loading state to true', () => { + expect(findListbox().props('loading')).toBe(true); + }); + + describe('when stopLoading callback from `selected` event is called', () => { + it('set loading state to false', async () => { + const { stopLoading } = wrapper.emitted('selected')[0][0]; + + stopLoading(); + await nextTick(); + + expect(findListbox().props('loading')).toBe(false); + }); + }); + }); + + describe('when searching for filter', () => { + const searchTerm = 'GNU'; + + beforeEach(() => { + createComponent({ filename: 'LICENSE' }); + findListbox().vm.$emit('search', searchTerm); + }); + + it('shows matching templates', () => { + const displayedTemplates = findDisplayedTemplates(); + const matchingTemplate = templates.find((template) => + template.name.toLowerCase().includes(searchTerm.toLowerCase()), + ); + expect(displayedTemplates).toContain(matchingTemplate?.key); + }); + + it('hides non-matching templates', () => { + const displayedTemplates = findDisplayedTemplates(); + const nonMatchingTemplate = templates.find( + (template) => !template.name.includes(searchTerm), + ); + expect(displayedTemplates).not.toContain(nonMatchingTemplate?.key); + }); + }); + }); +}); |