Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-06-16 12:09:20 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-06-16 12:09:20 +0300
commit8ae36d93f1a63874b584f0488fde88c1fee999c4 (patch)
treef1788ba1a7fb00248ff008f817f6feea89304339 /spec/frontend/search
parentb394e58cc2e52e17e7991e3d7b705aa383c362ee (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/search')
-rw-r--r--spec/frontend/search/mock_data.js1
-rw-r--r--spec/frontend/search/sidebar/components/label_dropdown_items_spec.js57
-rw-r--r--spec/frontend/search/sidebar/components/label_filter_spec.js322
-rw-r--r--spec/frontend/search/store/actions_spec.js2
-rw-r--r--spec/frontend/search/store/getters_spec.js4
5 files changed, 381 insertions, 5 deletions
diff --git a/spec/frontend/search/mock_data.js b/spec/frontend/search/mock_data.js
index 58824f8023d..7cf8633d749 100644
--- a/spec/frontend/search/mock_data.js
+++ b/spec/frontend/search/mock_data.js
@@ -8,6 +8,7 @@ export const MOCK_QUERY = {
group_id: 1,
language: ['C', 'JavaScript'],
labels: ['60', '37'],
+ search: '*',
};
export const MOCK_GROUP = {
diff --git a/spec/frontend/search/sidebar/components/label_dropdown_items_spec.js b/spec/frontend/search/sidebar/components/label_dropdown_items_spec.js
new file mode 100644
index 00000000000..135b12956b2
--- /dev/null
+++ b/spec/frontend/search/sidebar/components/label_dropdown_items_spec.js
@@ -0,0 +1,57 @@
+import { GlFormCheckbox } from '@gitlab/ui';
+import Vue from 'vue';
+import Vuex from 'vuex';
+import { shallowMount } from '@vue/test-utils';
+import { PROCESS_LABELS_DATA } from 'jest/search/mock_data';
+import LabelDropdownItems from '~/search/sidebar/components/label_filter/label_dropdown_items.vue';
+
+Vue.use(Vuex);
+
+describe('LabelDropdownItems', () => {
+ let wrapper;
+
+ const defaultProps = {
+ labels: PROCESS_LABELS_DATA,
+ };
+
+ const createComponent = (Props = defaultProps) => {
+ wrapper = shallowMount(LabelDropdownItems, {
+ propsData: {
+ ...Props,
+ },
+ });
+ };
+
+ const findAllLabelItems = () => wrapper.findAll('.label-filter-menu-item');
+ const findFirstLabelCheckbox = () => findAllLabelItems().at(0).findComponent(GlFormCheckbox);
+ const findFirstLabelTitle = () => findAllLabelItems().at(0).findComponent('.label-title');
+ const findFirstLabelColor = () =>
+ findAllLabelItems().at(0).findComponent('[data-testid="label-color-indicator"]');
+
+ describe('Renders correctly', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders items', () => {
+ expect(findAllLabelItems().exists()).toBe(true);
+ expect(findAllLabelItems()).toHaveLength(defaultProps.labels.length);
+ });
+
+ it('renders items checkbox', () => {
+ expect(findFirstLabelCheckbox().exists()).toBe(true);
+ });
+
+ it('renders label title', () => {
+ expect(findFirstLabelTitle().exists()).toBe(true);
+ expect(findFirstLabelTitle().text()).toBe(defaultProps.labels[0].title);
+ });
+
+ it('renders label color', () => {
+ expect(findFirstLabelColor().exists()).toBe(true);
+ expect(findFirstLabelColor().attributes('style')).toBe(
+ `background-color: ${defaultProps.labels[0].color};`,
+ );
+ });
+ });
+});
diff --git a/spec/frontend/search/sidebar/components/label_filter_spec.js b/spec/frontend/search/sidebar/components/label_filter_spec.js
new file mode 100644
index 00000000000..c5df374d4ef
--- /dev/null
+++ b/spec/frontend/search/sidebar/components/label_filter_spec.js
@@ -0,0 +1,322 @@
+import {
+ GlAlert,
+ GlLoadingIcon,
+ GlSearchBoxByType,
+ GlLabel,
+ GlDropdownForm,
+ GlFormCheckboxGroup,
+ GlDropdownSectionHeader,
+ GlDropdownDivider,
+} from '@gitlab/ui';
+import Vue from 'vue';
+import Vuex from 'vuex';
+import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import { MOCK_QUERY, MOCK_LABEL_AGGREGATIONS } from 'jest/search/mock_data';
+import LabelFilter from '~/search/sidebar/components/label_filter/index.vue';
+import LabelDropdownItems from '~/search/sidebar/components/label_filter/label_dropdown_items.vue';
+
+import * as actions from '~/search/store/actions';
+import * as getters from '~/search/store/getters';
+import mutations from '~/search/store/mutations';
+import createState from '~/search/store/state';
+
+import {
+ TRACKING_LABEL_FILTER,
+ TRACKING_LABEL_DROPDOWN,
+ TRACKING_LABEL_CHECKBOX,
+ TRACKING_ACTION_SELECT,
+ TRACKING_ACTION_SHOW,
+} from '~/search/sidebar/components/label_filter/tracking';
+
+import { labelFilterData } from '~/search/sidebar/components/label_filter/data';
+
+import {
+ RECEIVE_AGGREGATIONS_SUCCESS,
+ REQUEST_AGGREGATIONS,
+ RECEIVE_AGGREGATIONS_ERROR,
+} from '~/search/store/mutation_types';
+
+Vue.use(Vuex);
+
+const actionSpies = {
+ fetchAllAggregation: jest.fn(),
+ setQuery: jest.fn(),
+ closeLabel: jest.fn(),
+ setLabelFilterSearch: jest.fn(),
+};
+
+describe('GlobalSearchSidebarLabelFilter', () => {
+ let wrapper;
+ let trackingSpy;
+ let config;
+ let store;
+
+ const createComponent = (initialState) => {
+ config = {
+ actions: {
+ ...actions,
+ fetchAllAggregation: actionSpies.fetchAllAggregation,
+ closeLabel: actionSpies.closeLabel,
+ setLabelFilterSearch: actionSpies.setLabelFilterSearch,
+ setQuery: actionSpies.setQuery,
+ },
+ getters,
+ mutations,
+ state: createState({
+ query: MOCK_QUERY,
+ aggregations: MOCK_LABEL_AGGREGATIONS,
+ ...initialState,
+ }),
+ };
+
+ store = new Vuex.Store(config);
+
+ wrapper = mountExtended(LabelFilter, {
+ store,
+ provide: {
+ glFeatures: {
+ searchIssueLabelAggregation: true,
+ },
+ },
+ });
+ };
+
+ const findComponentTitle = () => wrapper.findComponentByTestId('label-filter-title');
+ const findAllSelectedLabelsAbove = () => wrapper.findAllComponents(GlLabel);
+ const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType);
+ const findDropdownForm = () => wrapper.findComponent(GlDropdownForm);
+ const findCheckboxGroup = () => wrapper.findComponent(GlFormCheckboxGroup);
+ const findDropdownSectionHeader = () => wrapper.findComponent(GlDropdownSectionHeader);
+ const findDivider = () => wrapper.findComponent(GlDropdownDivider);
+ const findCheckboxFilter = () => wrapper.findAllComponents(LabelDropdownItems);
+ const findAlert = () => wrapper.findComponent(GlAlert);
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+
+ describe('Renders correctly closed', () => {
+ beforeEach(async () => {
+ createComponent();
+ store.commit(RECEIVE_AGGREGATIONS_SUCCESS, MOCK_LABEL_AGGREGATIONS.data);
+
+ await Vue.nextTick();
+ });
+
+ it('renders component title', () => {
+ expect(findComponentTitle().exists()).toBe(true);
+ });
+
+ it('renders selected labels above search box', () => {
+ expect(findAllSelectedLabelsAbove().exists()).toBe(true);
+ expect(findAllSelectedLabelsAbove()).toHaveLength(2);
+ });
+
+ it('renders search box', () => {
+ expect(findSearchBox().exists()).toBe(true);
+ });
+
+ it("doesn't render dropdown form", () => {
+ expect(findDropdownForm().exists()).toBe(false);
+ });
+
+ it("doesn't render checkbox group", () => {
+ expect(findCheckboxGroup().exists()).toBe(false);
+ });
+
+ it("doesn't render dropdown section header", () => {
+ expect(findDropdownSectionHeader().exists()).toBe(false);
+ });
+
+ it("doesn't render divider", () => {
+ expect(findDivider().exists()).toBe(false);
+ });
+
+ it("doesn't render checkbox filter", () => {
+ expect(findCheckboxFilter().exists()).toBe(false);
+ });
+
+ it("doesn't render alert", () => {
+ expect(findAlert().exists()).toBe(false);
+ });
+
+ it("doesn't render loading icon", () => {
+ expect(findLoadingIcon().exists()).toBe(false);
+ });
+ });
+
+ describe('Renders correctly opened', () => {
+ beforeEach(async () => {
+ createComponent();
+ store.commit(RECEIVE_AGGREGATIONS_SUCCESS, MOCK_LABEL_AGGREGATIONS.data);
+
+ await Vue.nextTick();
+ trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
+ findSearchBox().vm.$emit('focusin');
+ });
+
+ afterEach(() => {
+ unmockTracking();
+ });
+
+ it('renders component title', () => {
+ expect(findComponentTitle().exists()).toBe(true);
+ });
+
+ it('renders selected labels above search box', () => {
+ // default data need to provide at least two selected labels
+ expect(findAllSelectedLabelsAbove().exists()).toBe(true);
+ expect(findAllSelectedLabelsAbove()).toHaveLength(2);
+ });
+
+ it('renders search box', () => {
+ expect(findSearchBox().exists()).toBe(true);
+ });
+
+ it('renders dropdown form', () => {
+ expect(findDropdownForm().exists()).toBe(true);
+ });
+
+ it('renders checkbox group', () => {
+ expect(findCheckboxGroup().exists()).toBe(true);
+ });
+
+ it('renders dropdown section header', () => {
+ expect(findDropdownSectionHeader().exists()).toBe(true);
+ });
+
+ it('renders divider', () => {
+ expect(findDivider().exists()).toBe(true);
+ });
+
+ it('renders checkbox filter', () => {
+ expect(findCheckboxFilter().exists()).toBe(true);
+ });
+
+ it("doesn't render alert", () => {
+ expect(findAlert().exists()).toBe(false);
+ });
+
+ it("doesn't render loading icon", () => {
+ expect(findLoadingIcon().exists()).toBe(false);
+ });
+
+ it('sends tracking information when dropdown is opened', () => {
+ expect(trackingSpy).toHaveBeenCalledWith(TRACKING_ACTION_SHOW, TRACKING_LABEL_DROPDOWN, {
+ label: TRACKING_LABEL_DROPDOWN,
+ });
+ });
+ });
+
+ describe('Renders loading state correctly', () => {
+ beforeEach(async () => {
+ createComponent();
+ store.commit(REQUEST_AGGREGATIONS);
+ await Vue.nextTick();
+
+ findSearchBox().vm.$emit('focusin');
+ });
+
+ it('renders checkbox filter', () => {
+ expect(findCheckboxFilter().exists()).toBe(false);
+ });
+
+ it("doesn't render alert", () => {
+ expect(findAlert().exists()).toBe(false);
+ });
+
+ it('renders loading icon', () => {
+ expect(findLoadingIcon().exists()).toBe(true);
+ });
+ });
+
+ describe('Renders error state correctly', () => {
+ beforeEach(async () => {
+ createComponent();
+ store.commit(RECEIVE_AGGREGATIONS_ERROR);
+ await Vue.nextTick();
+
+ findSearchBox().vm.$emit('focusin');
+ });
+
+ it("doesn't render checkbox filter", () => {
+ expect(findCheckboxFilter().exists()).toBe(false);
+ });
+
+ it('renders alert', () => {
+ expect(findAlert().exists()).toBe(true);
+ });
+
+ it("doesn't render loading icon", () => {
+ expect(findLoadingIcon().exists()).toBe(false);
+ });
+ });
+
+ describe('Actions', () => {
+ describe('dispatch action when component is created', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders checkbox filter', async () => {
+ await Vue.nextTick();
+ expect(actionSpies.fetchAllAggregation).toHaveBeenCalled();
+ });
+ });
+
+ describe('Closing label works correctly', () => {
+ beforeEach(async () => {
+ createComponent();
+ store.commit(RECEIVE_AGGREGATIONS_SUCCESS, MOCK_LABEL_AGGREGATIONS.data);
+ await Vue.nextTick();
+ });
+
+ it('renders checkbox filter', async () => {
+ await findAllSelectedLabelsAbove().at(0).find('.btn-reset').trigger('click');
+ expect(actionSpies.closeLabel).toHaveBeenCalled();
+ });
+ });
+
+ describe('label search input box works properly', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders checkbox filter', () => {
+ findSearchBox().find('input').setValue('test');
+ expect(actionSpies.setLabelFilterSearch).toHaveBeenCalledWith(
+ expect.anything(),
+ expect.objectContaining({
+ value: 'test',
+ }),
+ );
+ });
+ });
+
+ describe('dropdown checkboxes work', () => {
+ beforeEach(async () => {
+ createComponent();
+
+ await findSearchBox().vm.$emit('focusin');
+ await Vue.nextTick();
+
+ trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
+
+ await findCheckboxGroup().vm.$emit('input', 6);
+ await Vue.nextTick();
+ });
+
+ it('trigger event', () => {
+ expect(actionSpies.setQuery).toHaveBeenCalledWith(
+ expect.anything(),
+ expect.objectContaining({ key: labelFilterData?.filterParam, value: 6 }),
+ );
+ });
+
+ it('sends tracking information when checkbox is selected', () => {
+ expect(trackingSpy).toHaveBeenCalledWith(TRACKING_ACTION_SELECT, TRACKING_LABEL_CHECKBOX, {
+ label: TRACKING_LABEL_FILTER,
+ property: 6,
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/search/store/actions_spec.js b/spec/frontend/search/store/actions_spec.js
index 18f7e1ce21c..2051e731647 100644
--- a/spec/frontend/search/store/actions_spec.js
+++ b/spec/frontend/search/store/actions_spec.js
@@ -133,7 +133,7 @@ describe('Global Search Store Actions', () => {
describe('when groupId is set', () => {
it('calls Api.groupProjects with expected parameters', () => {
- actions.fetchProjects({ commit: mockCommit, state }, undefined);
+ actions.fetchProjects({ commit: mockCommit, state }, MOCK_QUERY.search);
expect(Api.groupProjects).toHaveBeenCalledWith(state.query.group_id, state.query.search, {
order_by: 'similarity',
include_subgroups: true,
diff --git a/spec/frontend/search/store/getters_spec.js b/spec/frontend/search/store/getters_spec.js
index 51692cb1ab4..772acb39a57 100644
--- a/spec/frontend/search/store/getters_spec.js
+++ b/spec/frontend/search/store/getters_spec.js
@@ -33,10 +33,6 @@ describe('Global Search Store Getters', () => {
useMockLocationHelper();
});
- afterEach(() => {
- state = cloneDeep(defaultState);
- });
-
describe('frequentGroups', () => {
it('returns the correct data', () => {
state.frequentItems[GROUPS_LOCAL_STORAGE_KEY] = MOCK_GROUPS;