diff options
Diffstat (limited to 'spec/frontend/vue_shared/components/filtered_search_bar/tokens')
6 files changed, 47 insertions, 348 deletions
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js index f9ce0338d2f..84f0151d9db 100644 --- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js +++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js @@ -14,7 +14,13 @@ import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_t import { mockLabelToken } from '../mock_data'; -jest.mock('~/vue_shared/components/filtered_search_bar/filtered_search_utils'); +jest.mock('~/vue_shared/components/filtered_search_bar/filtered_search_utils', () => ({ + getRecentlyUsedSuggestions: jest.fn(), + setTokenValueToRecentlyUsed: jest.fn(), + stripQuotes: jest.requireActual( + '~/vue_shared/components/filtered_search_bar/filtered_search_utils', + ).stripQuotes, +})); const mockStorageKey = 'recent-tokens-label_name'; @@ -46,13 +52,13 @@ const defaultSlots = { }; const mockProps = { - config: mockLabelToken, + config: { ...mockLabelToken, recentSuggestionsStorageKey: mockStorageKey }, value: { data: '' }, active: false, suggestions: [], suggestionsLoading: false, defaultSuggestions: DEFAULT_NONE_ANY, - recentSuggestionsStorageKey: mockStorageKey, + getActiveTokenValue: (labels, data) => labels.find((label) => label.title === data), }; function createComponent({ @@ -152,30 +158,22 @@ describe('BaseToken', () => { describe('methods', () => { describe('handleTokenValueSelected', () => { - it('calls `setTokenValueToRecentlyUsed` when `recentSuggestionsStorageKey` is defined', () => { - const mockTokenValue = { - id: 1, - title: 'Foo', - }; + const mockTokenValue = mockLabels[0]; - wrapper.vm.handleTokenValueSelected(mockTokenValue); + it('calls `setTokenValueToRecentlyUsed` when `recentSuggestionsStorageKey` is defined', () => { + wrapper.vm.handleTokenValueSelected(mockTokenValue.title); expect(setTokenValueToRecentlyUsed).toHaveBeenCalledWith(mockStorageKey, mockTokenValue); }); it('does not add token from preloadedSuggestions', async () => { - const mockTokenValue = { - id: 1, - title: 'Foo', - }; - wrapper.setProps({ preloadedSuggestions: [mockTokenValue], }); await wrapper.vm.$nextTick(); - wrapper.vm.handleTokenValueSelected(mockTokenValue); + wrapper.vm.handleTokenValueSelected(mockTokenValue.title); expect(setTokenValueToRecentlyUsed).not.toHaveBeenCalled(); }); @@ -190,7 +188,7 @@ describe('BaseToken', () => { const glFilteredSearchToken = wrapperWithNoStubs.find(GlFilteredSearchToken); expect(glFilteredSearchToken.exists()).toBe(true); - expect(glFilteredSearchToken.props('config')).toBe(mockLabelToken); + expect(glFilteredSearchToken.props('config')).toEqual(mockProps.config); wrapperWithNoStubs.destroy(); }); @@ -239,6 +237,7 @@ describe('BaseToken', () => { stubs: { Portal: true }, }); }); + it('emits `fetch-suggestions` event on component after a delay when component emits `input` event', async () => { jest.useFakeTimers(); @@ -250,6 +249,32 @@ describe('BaseToken', () => { expect(wrapperWithNoStubs.emitted('fetch-suggestions')).toBeTruthy(); expect(wrapperWithNoStubs.emitted('fetch-suggestions')[2]).toEqual(['foo']); }); + + describe('when search is started with a quote', () => { + it('emits `fetch-suggestions` with filtered value', async () => { + jest.useFakeTimers(); + + wrapperWithNoStubs.find(GlFilteredSearchToken).vm.$emit('input', { data: '"foo' }); + await wrapperWithNoStubs.vm.$nextTick(); + + jest.runAllTimers(); + + expect(wrapperWithNoStubs.emitted('fetch-suggestions')[2]).toEqual(['foo']); + }); + }); + + describe('when search starts and ends with a quote', () => { + it('emits `fetch-suggestions` with filtered value', async () => { + jest.useFakeTimers(); + + wrapperWithNoStubs.find(GlFilteredSearchToken).vm.$emit('input', { data: '"foo"' }); + await wrapperWithNoStubs.vm.$nextTick(); + + jest.runAllTimers(); + + expect(wrapperWithNoStubs.emitted('fetch-suggestions')[2]).toEqual(['foo']); + }); + }); }); }); }); diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/epic_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/epic_token_spec.js deleted file mode 100644 index 6ee5d50d396..00000000000 --- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/epic_token_spec.js +++ /dev/null @@ -1,169 +0,0 @@ -import { GlFilteredSearchTokenSegment } from '@gitlab/ui'; -import { mount } from '@vue/test-utils'; -import MockAdapter from 'axios-mock-adapter'; -import Vue from 'vue'; -import VueApollo from 'vue-apollo'; -import createMockApollo from 'helpers/mock_apollo_helper'; -import waitForPromises from 'helpers/wait_for_promises'; -import createFlash from '~/flash'; -import axios from '~/lib/utils/axios_utils'; - -import searchEpicsQuery from '~/vue_shared/components/filtered_search_bar/queries/search_epics.query.graphql'; -import EpicToken from '~/vue_shared/components/filtered_search_bar/tokens/epic_token.vue'; -import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue'; - -import { mockEpicToken, mockEpics, mockGroupEpicsQueryResponse } from '../mock_data'; - -jest.mock('~/flash'); -Vue.use(VueApollo); - -const defaultStubs = { - Portal: true, - GlFilteredSearchSuggestionList: { - template: '<div></div>', - methods: { - getValue: () => '=', - }, - }, -}; - -describe('EpicToken', () => { - let mock; - let wrapper; - let fakeApollo; - - const findBaseToken = () => wrapper.findComponent(BaseToken); - - function createComponent( - options = {}, - epicsQueryHandler = jest.fn().mockResolvedValue(mockGroupEpicsQueryResponse), - ) { - fakeApollo = createMockApollo([[searchEpicsQuery, epicsQueryHandler]]); - const { - config = mockEpicToken, - value = { data: '' }, - active = false, - stubs = defaultStubs, - } = options; - return mount(EpicToken, { - apolloProvider: fakeApollo, - propsData: { - config, - value, - active, - }, - provide: { - portalName: 'fake target', - alignSuggestions: function fakeAlignSuggestions() {}, - suggestionsListClass: 'custom-class', - }, - stubs, - }); - } - - beforeEach(() => { - mock = new MockAdapter(axios); - wrapper = createComponent(); - }); - - afterEach(() => { - mock.restore(); - wrapper.destroy(); - }); - - describe('computed', () => { - beforeEach(async () => { - wrapper = createComponent({ - data: { - epics: mockEpics, - }, - }); - - await wrapper.vm.$nextTick(); - }); - }); - - describe('methods', () => { - describe('fetchEpicsBySearchTerm', () => { - it('calls fetchEpics with provided searchTerm param', () => { - jest.spyOn(wrapper.vm, 'fetchEpics'); - - findBaseToken().vm.$emit('fetch-suggestions', 'foo'); - - expect(wrapper.vm.fetchEpics).toHaveBeenCalledWith('foo'); - }); - - it('sets response to `epics` when request is successful', async () => { - jest.spyOn(wrapper.vm, 'fetchEpics').mockResolvedValue({ - data: mockEpics, - }); - - findBaseToken().vm.$emit('fetch-suggestions'); - - await waitForPromises(); - - expect(wrapper.vm.epics).toEqual(mockEpics); - }); - - it('calls `createFlash` with flash error message when request fails', async () => { - jest.spyOn(wrapper.vm, 'fetchEpics').mockRejectedValue({}); - - findBaseToken().vm.$emit('fetch-suggestions', 'foo'); - - await waitForPromises(); - - expect(createFlash).toHaveBeenCalledWith({ - message: 'There was a problem fetching epics.', - }); - }); - - it('sets `loading` to false when request completes', async () => { - jest.spyOn(wrapper.vm, 'fetchEpics').mockRejectedValue({}); - - findBaseToken().vm.$emit('fetch-suggestions', 'foo'); - - await waitForPromises(); - - expect(wrapper.vm.loading).toBe(false); - }); - }); - }); - - describe('template', () => { - const getTokenValueEl = () => wrapper.findAllComponents(GlFilteredSearchTokenSegment).at(2); - - beforeEach(async () => { - wrapper = createComponent({ - value: { data: `${mockEpics[0].title}::&${mockEpics[0].iid}` }, - data: { epics: mockEpics }, - }); - - await wrapper.vm.$nextTick(); - }); - - it('renders BaseToken component', () => { - expect(findBaseToken().exists()).toBe(true); - }); - - it('renders token item when value is selected', () => { - const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment); - - expect(tokenSegments).toHaveLength(3); - expect(tokenSegments.at(2).text()).toBe(`${mockEpics[0].title}::&${mockEpics[0].iid}`); - }); - - it.each` - value | valueType | tokenValueString - ${`${mockEpics[0].title}::&${mockEpics[0].iid}`} | ${'string'} | ${`${mockEpics[0].title}::&${mockEpics[0].iid}`} - ${`${mockEpics[1].title}::&${mockEpics[1].iid}`} | ${'number'} | ${`${mockEpics[1].title}::&${mockEpics[1].iid}`} - `('renders token item when selection is a $valueType', async ({ value, tokenValueString }) => { - wrapper.setProps({ - value: { data: value }, - }); - - await wrapper.vm.$nextTick(); - - expect(getTokenValueEl().text()).toBe(tokenValueString); - }); - }); -}); diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/iteration_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/iteration_token_spec.js deleted file mode 100644 index 44bc16adb97..00000000000 --- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/iteration_token_spec.js +++ /dev/null @@ -1,116 +0,0 @@ -import { - GlFilteredSearchToken, - GlFilteredSearchTokenSegment, - GlFilteredSearchSuggestion, -} from '@gitlab/ui'; -import { mount } from '@vue/test-utils'; -import waitForPromises from 'helpers/wait_for_promises'; -import createFlash from '~/flash'; -import IterationToken from '~/vue_shared/components/filtered_search_bar/tokens/iteration_token.vue'; -import { mockIterationToken, mockIterations } from '../mock_data'; - -jest.mock('~/flash'); - -describe('IterationToken', () => { - const id = 123; - let wrapper; - - const createComponent = ({ - config = mockIterationToken, - value = { data: '' }, - active = false, - stubs = {}, - provide = {}, - } = {}) => - mount(IterationToken, { - propsData: { - active, - config, - value, - }, - provide: { - portalName: 'fake target', - alignSuggestions: function fakeAlignSuggestions() {}, - suggestionsListClass: () => 'custom-class', - ...provide, - }, - stubs, - }); - - afterEach(() => { - wrapper.destroy(); - }); - - describe('when iteration cadence feature is available', () => { - beforeEach(async () => { - wrapper = createComponent({ - active: true, - config: { ...mockIterationToken, initialIterations: mockIterations }, - value: { data: 'i' }, - stubs: { Portal: true }, - provide: { - glFeatures: { - iterationCadences: true, - }, - }, - }); - - await wrapper.setData({ loading: false }); - }); - - it('renders iteration start date and due date', () => { - const suggestions = wrapper.findAll(GlFilteredSearchSuggestion); - - expect(suggestions.at(3).text()).toContain('Nov 5, 2021 - Nov 10, 2021'); - }); - }); - - it('renders iteration value', async () => { - wrapper = createComponent({ value: { data: id } }); - - await wrapper.vm.$nextTick(); - - const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment); - - expect(tokenSegments).toHaveLength(3); // `Iteration` `=` `gitlab-org: #1` - expect(tokenSegments.at(2).text()).toBe(id.toString()); - }); - - it('fetches initial values', () => { - const fetchIterationsSpy = jest.fn().mockResolvedValue(); - - wrapper = createComponent({ - config: { ...mockIterationToken, fetchIterations: fetchIterationsSpy }, - value: { data: id }, - }); - - expect(fetchIterationsSpy).toHaveBeenCalledWith(id); - }); - - it('fetches iterations on user input', () => { - const search = 'hello'; - const fetchIterationsSpy = jest.fn().mockResolvedValue(); - - wrapper = createComponent({ - config: { ...mockIterationToken, fetchIterations: fetchIterationsSpy }, - }); - - wrapper.findComponent(GlFilteredSearchToken).vm.$emit('input', { data: search }); - - expect(fetchIterationsSpy).toHaveBeenCalledWith(search); - }); - - it('renders error message when request fails', async () => { - const fetchIterationsSpy = jest.fn().mockRejectedValue(); - - wrapper = createComponent({ - config: { ...mockIterationToken, fetchIterations: fetchIterationsSpy }, - }); - - await waitForPromises(); - - expect(createFlash).toHaveBeenCalledWith({ - message: 'There was a problem fetching iterations.', - }); - }); -}); diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js index 936841651d1..4a098db33c5 100644 --- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js +++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js @@ -9,18 +9,15 @@ import MockAdapter from 'axios-mock-adapter'; import waitForPromises from 'helpers/wait_for_promises'; import createFlash from '~/flash'; import axios from '~/lib/utils/axios_utils'; -import { sortMilestonesByDueDate } from '~/milestones/milestone_utils'; +import { sortMilestonesByDueDate } from '~/milestones/utils'; -import { - DEFAULT_MILESTONES, - DEFAULT_MILESTONES_GRAPHQL, -} from '~/vue_shared/components/filtered_search_bar/constants'; +import { DEFAULT_MILESTONES } from '~/vue_shared/components/filtered_search_bar/constants'; import MilestoneToken from '~/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue'; import { mockMilestoneToken, mockMilestones, mockRegularMilestone } from '../mock_data'; jest.mock('~/flash'); -jest.mock('~/milestones/milestone_utils'); +jest.mock('~/milestones/utils'); const defaultStubs = { Portal: true, @@ -199,12 +196,12 @@ describe('MilestoneToken', () => { beforeEach(() => { wrapper = createComponent({ active: true, - config: { ...mockMilestoneToken, defaultMilestones: DEFAULT_MILESTONES_GRAPHQL }, + config: { ...mockMilestoneToken, defaultMilestones: DEFAULT_MILESTONES }, }); }); it('finds the correct value from the activeToken', () => { - DEFAULT_MILESTONES_GRAPHQL.forEach(({ value, title }) => { + DEFAULT_MILESTONES.forEach(({ value, title }) => { const activeToken = wrapper.vm.getActiveMilestone([], value); expect(activeToken.title).toEqual(title); diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/release_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/release_token_spec.js index b804ff97b82..b2f246a5985 100644 --- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/release_token_spec.js +++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/release_token_spec.js @@ -8,7 +8,7 @@ import { mockReleaseToken } from '../mock_data'; jest.mock('~/flash'); describe('ReleaseToken', () => { - const id = 123; + const id = '123'; let wrapper; const createComponent = ({ config = mockReleaseToken, value = { data: '' } } = {}) => diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/weight_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/weight_token_spec.js deleted file mode 100644 index 4277899f8db..00000000000 --- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/weight_token_spec.js +++ /dev/null @@ -1,38 +0,0 @@ -import { GlFilteredSearchTokenSegment } from '@gitlab/ui'; -import { mount } from '@vue/test-utils'; -import WeightToken from '~/vue_shared/components/filtered_search_bar/tokens/weight_token.vue'; -import { mockWeightToken } from '../mock_data'; - -jest.mock('~/flash'); - -describe('WeightToken', () => { - const weight = '3'; - let wrapper; - - const createComponent = ({ config = mockWeightToken, value = { data: '' } } = {}) => - mount(WeightToken, { - propsData: { - active: false, - config, - value, - }, - provide: { - portalName: 'fake target', - alignSuggestions: function fakeAlignSuggestions() {}, - suggestionsListClass: () => 'custom-class', - }, - }); - - afterEach(() => { - wrapper.destroy(); - }); - - it('renders weight value', () => { - wrapper = createComponent({ value: { data: weight } }); - - const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment); - - expect(tokenSegments).toHaveLength(3); // `Weight` `=` `3` - expect(tokenSegments.at(2).text()).toBe(weight); - }); -}); |