summaryrefslogtreecommitdiff
path: root/spec/frontend/vue_shared/components/filtered_search_bar/tokens
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/vue_shared/components/filtered_search_bar/tokens')
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js57
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/epic_token_spec.js169
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/iteration_token_spec.js116
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js13
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/release_token_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/weight_token_spec.js38
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);
- });
-});