2020-08-28 18:10:51 +00:00
|
|
|
import {
|
|
|
|
GlFilteredSearchSuggestion,
|
|
|
|
GlFilteredSearchTokenSegment,
|
2020-09-14 18:09:48 +00:00
|
|
|
GlDropdownDivider,
|
2020-08-28 18:10:51 +00:00
|
|
|
} from '@gitlab/ui';
|
2021-02-14 18:09:20 +00:00
|
|
|
import { mount } from '@vue/test-utils';
|
2020-08-03 15:09:44 +00:00
|
|
|
import MockAdapter from 'axios-mock-adapter';
|
|
|
|
import waitForPromises from 'helpers/wait_for_promises';
|
|
|
|
import {
|
|
|
|
mockRegularLabel,
|
|
|
|
mockLabels,
|
|
|
|
} from 'jest/vue_shared/components/sidebar/labels_select_vue/mock_data';
|
2021-06-02 21:10:00 +00:00
|
|
|
import createFlash from '~/flash';
|
2020-08-17 21:09:56 +00:00
|
|
|
import axios from '~/lib/utils/axios_utils';
|
|
|
|
|
2020-08-28 18:10:51 +00:00
|
|
|
import {
|
|
|
|
DEFAULT_LABELS,
|
2021-05-13 18:10:32 +00:00
|
|
|
DEFAULT_NONE_ANY,
|
2020-08-28 18:10:51 +00:00
|
|
|
} from '~/vue_shared/components/filtered_search_bar/constants';
|
2021-05-20 12:10:26 +00:00
|
|
|
import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue';
|
2020-08-17 21:09:56 +00:00
|
|
|
import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label_token.vue';
|
2020-08-03 15:09:44 +00:00
|
|
|
|
|
|
|
import { mockLabelToken } from '../mock_data';
|
|
|
|
|
|
|
|
jest.mock('~/flash');
|
2020-08-28 18:10:51 +00:00
|
|
|
const defaultStubs = {
|
|
|
|
Portal: true,
|
2021-05-20 12:10:26 +00:00
|
|
|
BaseToken,
|
2020-08-28 18:10:51 +00:00
|
|
|
GlFilteredSearchSuggestionList: {
|
|
|
|
template: '<div></div>',
|
|
|
|
methods: {
|
|
|
|
getValue: () => '=',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2020-09-02 06:10:47 +00:00
|
|
|
function createComponent(options = {}) {
|
|
|
|
const {
|
|
|
|
config = mockLabelToken,
|
|
|
|
value = { data: '' },
|
|
|
|
active = false,
|
|
|
|
stubs = defaultStubs,
|
2021-06-16 12:10:18 +00:00
|
|
|
listeners = {},
|
2020-09-02 06:10:47 +00:00
|
|
|
} = options;
|
|
|
|
return mount(LabelToken, {
|
2020-08-03 15:09:44 +00:00
|
|
|
propsData: {
|
|
|
|
config,
|
|
|
|
value,
|
|
|
|
active,
|
|
|
|
},
|
|
|
|
provide: {
|
|
|
|
portalName: 'fake target',
|
|
|
|
alignSuggestions: function fakeAlignSuggestions() {},
|
2020-11-13 12:09:03 +00:00
|
|
|
suggestionsListClass: 'custom-class',
|
2020-08-03 15:09:44 +00:00
|
|
|
},
|
2020-08-28 18:10:51 +00:00
|
|
|
stubs,
|
2021-06-16 12:10:18 +00:00
|
|
|
listeners,
|
2020-08-03 15:09:44 +00:00
|
|
|
});
|
2020-09-02 06:10:47 +00:00
|
|
|
}
|
2020-08-03 15:09:44 +00:00
|
|
|
|
|
|
|
describe('LabelToken', () => {
|
|
|
|
let mock;
|
|
|
|
let wrapper;
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
mock = new MockAdapter(axios);
|
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
mock.restore();
|
|
|
|
wrapper.destroy();
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('methods', () => {
|
2020-08-28 18:10:51 +00:00
|
|
|
beforeEach(() => {
|
|
|
|
wrapper = createComponent();
|
|
|
|
});
|
|
|
|
|
2021-05-20 12:10:26 +00:00
|
|
|
describe('getActiveLabel', () => {
|
|
|
|
it('returns label object from labels array based on provided `currentValue` param', () => {
|
|
|
|
expect(wrapper.vm.getActiveLabel(mockLabels, 'foo label')).toEqual(mockRegularLabel);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2021-03-26 12:09:15 +00:00
|
|
|
describe('getLabelName', () => {
|
|
|
|
it('returns value of `name` or `title` property present in provided label param', () => {
|
|
|
|
let mockLabel = {
|
|
|
|
title: 'foo',
|
|
|
|
};
|
|
|
|
|
|
|
|
expect(wrapper.vm.getLabelName(mockLabel)).toBe(mockLabel.title);
|
|
|
|
|
|
|
|
mockLabel = {
|
|
|
|
name: 'foo',
|
|
|
|
};
|
|
|
|
|
|
|
|
expect(wrapper.vm.getLabelName(mockLabel)).toBe(mockLabel.name);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-08-03 15:09:44 +00:00
|
|
|
describe('fetchLabelBySearchTerm', () => {
|
|
|
|
it('calls `config.fetchLabels` with provided searchTerm param', () => {
|
|
|
|
jest.spyOn(wrapper.vm.config, 'fetchLabels');
|
|
|
|
|
|
|
|
wrapper.vm.fetchLabelBySearchTerm('foo');
|
|
|
|
|
|
|
|
expect(wrapper.vm.config.fetchLabels).toHaveBeenCalledWith('foo');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('sets response to `labels` when request is succesful', () => {
|
|
|
|
jest.spyOn(wrapper.vm.config, 'fetchLabels').mockResolvedValue(mockLabels);
|
|
|
|
|
|
|
|
wrapper.vm.fetchLabelBySearchTerm('foo');
|
|
|
|
|
|
|
|
return waitForPromises().then(() => {
|
|
|
|
expect(wrapper.vm.labels).toEqual(mockLabels);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('calls `createFlash` with flash error message when request fails', () => {
|
|
|
|
jest.spyOn(wrapper.vm.config, 'fetchLabels').mockRejectedValue({});
|
|
|
|
|
|
|
|
wrapper.vm.fetchLabelBySearchTerm('foo');
|
|
|
|
|
|
|
|
return waitForPromises().then(() => {
|
2021-06-02 21:10:00 +00:00
|
|
|
expect(createFlash).toHaveBeenCalledWith({
|
|
|
|
message: 'There was a problem fetching labels.',
|
|
|
|
});
|
2020-08-03 15:09:44 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('sets `loading` to false when request completes', () => {
|
|
|
|
jest.spyOn(wrapper.vm.config, 'fetchLabels').mockRejectedValue({});
|
|
|
|
|
|
|
|
wrapper.vm.fetchLabelBySearchTerm('foo');
|
|
|
|
|
|
|
|
return waitForPromises().then(() => {
|
|
|
|
expect(wrapper.vm.loading).toBe(false);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('template', () => {
|
2021-05-13 18:10:32 +00:00
|
|
|
const defaultLabels = DEFAULT_NONE_ANY;
|
2020-08-28 18:10:51 +00:00
|
|
|
|
2020-08-03 15:09:44 +00:00
|
|
|
beforeEach(async () => {
|
|
|
|
wrapper = createComponent({ value: { data: `"${mockRegularLabel.title}"` } });
|
|
|
|
|
|
|
|
wrapper.setData({
|
|
|
|
labels: mockLabels,
|
|
|
|
});
|
|
|
|
|
|
|
|
await wrapper.vm.$nextTick();
|
|
|
|
});
|
|
|
|
|
2021-05-20 12:10:26 +00:00
|
|
|
it('renders base-token component', () => {
|
|
|
|
const baseTokenEl = wrapper.find(BaseToken);
|
|
|
|
|
|
|
|
expect(baseTokenEl.exists()).toBe(true);
|
|
|
|
expect(baseTokenEl.props()).toMatchObject({
|
2021-06-18 18:10:13 +00:00
|
|
|
suggestions: mockLabels,
|
2021-05-20 12:10:26 +00:00
|
|
|
fnActiveTokenValue: wrapper.vm.getActiveLabel,
|
|
|
|
});
|
2020-08-03 15:09:44 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it('renders token item when value is selected', () => {
|
|
|
|
const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
|
|
|
|
|
|
|
|
expect(tokenSegments).toHaveLength(3); // Label, =, "Foo Label"
|
|
|
|
expect(tokenSegments.at(2).text()).toBe(`~${mockRegularLabel.title}`); // "Foo Label"
|
2020-12-23 12:10:26 +00:00
|
|
|
expect(tokenSegments.at(2).find('.gl-token').attributes('style')).toBe(
|
|
|
|
'background-color: rgb(186, 218, 85); color: rgb(255, 255, 255);',
|
|
|
|
);
|
2020-08-03 15:09:44 +00:00
|
|
|
});
|
2020-08-28 18:10:51 +00:00
|
|
|
|
|
|
|
it('renders provided defaultLabels as suggestions', async () => {
|
|
|
|
wrapper = createComponent({
|
|
|
|
active: true,
|
|
|
|
config: { ...mockLabelToken, defaultLabels },
|
|
|
|
stubs: { Portal: true },
|
|
|
|
});
|
|
|
|
const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
|
|
|
|
const suggestionsSegment = tokenSegments.at(2);
|
|
|
|
suggestionsSegment.vm.$emit('activate');
|
|
|
|
await wrapper.vm.$nextTick();
|
|
|
|
|
|
|
|
const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
|
|
|
|
|
|
|
|
expect(suggestions).toHaveLength(defaultLabels.length);
|
|
|
|
defaultLabels.forEach((label, index) => {
|
|
|
|
expect(suggestions.at(index).text()).toBe(label.text);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-09-02 06:10:47 +00:00
|
|
|
it('does not render divider when no defaultLabels', async () => {
|
|
|
|
wrapper = createComponent({
|
|
|
|
active: true,
|
|
|
|
config: { ...mockLabelToken, defaultLabels: [] },
|
|
|
|
stubs: { Portal: true },
|
|
|
|
});
|
|
|
|
const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
|
|
|
|
const suggestionsSegment = tokenSegments.at(2);
|
|
|
|
suggestionsSegment.vm.$emit('activate');
|
|
|
|
await wrapper.vm.$nextTick();
|
|
|
|
|
2020-12-25 09:10:31 +00:00
|
|
|
expect(wrapper.find(GlFilteredSearchSuggestion).exists()).toBe(false);
|
|
|
|
expect(wrapper.find(GlDropdownDivider).exists()).toBe(false);
|
2020-09-02 06:10:47 +00:00
|
|
|
});
|
|
|
|
|
2021-06-16 12:10:18 +00:00
|
|
|
it('renders `DEFAULT_LABELS` as default suggestions', () => {
|
2020-08-28 18:10:51 +00:00
|
|
|
wrapper = createComponent({
|
|
|
|
active: true,
|
|
|
|
config: { ...mockLabelToken },
|
|
|
|
stubs: { Portal: true },
|
|
|
|
});
|
|
|
|
const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
|
|
|
|
const suggestionsSegment = tokenSegments.at(2);
|
|
|
|
suggestionsSegment.vm.$emit('activate');
|
|
|
|
|
|
|
|
const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
|
|
|
|
|
|
|
|
expect(suggestions).toHaveLength(DEFAULT_LABELS.length);
|
|
|
|
DEFAULT_LABELS.forEach((label, index) => {
|
|
|
|
expect(suggestions.at(index).text()).toBe(label.text);
|
|
|
|
});
|
|
|
|
});
|
2021-06-16 12:10:18 +00:00
|
|
|
|
|
|
|
it('emits listeners in the base-token', () => {
|
|
|
|
const mockInput = jest.fn();
|
|
|
|
wrapper = createComponent({
|
|
|
|
listeners: {
|
|
|
|
input: mockInput,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
wrapper.findComponent(BaseToken).vm.$emit('input', [{ data: 'mockData', operator: '=' }]);
|
|
|
|
|
|
|
|
expect(mockInput).toHaveBeenLastCalledWith([{ data: 'mockData', operator: '=' }]);
|
|
|
|
});
|
2020-08-03 15:09:44 +00:00
|
|
|
});
|
|
|
|
});
|