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>2021-06-30 09:07:17 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-06-30 09:07:17 +0300
commit28fd41cf28bfac77fe877b6cce83594c1f9f21a1 (patch)
treef40a522a22db6518445b243b5244207416665f01 /spec/frontend/search
parentdbb27a91536f29550f7714356ab499d318e9d7e2 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/search')
-rw-r--r--spec/frontend/search/mock_data.js2
-rw-r--r--spec/frontend/search/store/actions_spec.js86
-rw-r--r--spec/frontend/search/store/mutations_spec.js9
-rw-r--r--spec/frontend/search/store/utils_spec.js147
-rw-r--r--spec/frontend/search/topbar/components/group_filter_spec.js49
-rw-r--r--spec/frontend/search/topbar/components/project_filter_spec.js35
6 files changed, 315 insertions, 13 deletions
diff --git a/spec/frontend/search/mock_data.js b/spec/frontend/search/mock_data.js
index fbe01f372b0..ad082e98a41 100644
--- a/spec/frontend/search/mock_data.js
+++ b/spec/frontend/search/mock_data.js
@@ -63,3 +63,5 @@ export const MOCK_SORT_OPTIONS = [
},
},
];
+
+export const MOCK_LS_KEY = 'mock-ls-key';
diff --git a/spec/frontend/search/store/actions_spec.js b/spec/frontend/search/store/actions_spec.js
index bb711b3af81..8c53d913108 100644
--- a/spec/frontend/search/store/actions_spec.js
+++ b/spec/frontend/search/store/actions_spec.js
@@ -5,9 +5,11 @@ import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import * as urlUtils from '~/lib/utils/url_utility';
import * as actions from '~/search/store/actions';
+import { GROUPS_LOCAL_STORAGE_KEY, PROJECTS_LOCAL_STORAGE_KEY } from '~/search/store/constants';
import * as types from '~/search/store/mutation_types';
import createState from '~/search/store/state';
-import { MOCK_QUERY, MOCK_GROUPS, MOCK_PROJECT, MOCK_PROJECTS } from '../mock_data';
+import * as storeUtils from '~/search/store/utils';
+import { MOCK_QUERY, MOCK_GROUPS, MOCK_PROJECT, MOCK_PROJECTS, MOCK_GROUP } from '../mock_data';
jest.mock('~/flash');
jest.mock('~/lib/utils/url_utility', () => ({
@@ -141,4 +143,86 @@ describe('Global Search Store Actions', () => {
});
});
});
+
+ describe('loadFrequentGroups', () => {
+ beforeEach(() => {
+ storeUtils.loadDataFromLS = jest.fn().mockReturnValue(MOCK_GROUPS);
+ });
+
+ it(`calls loadDataFromLS with ${GROUPS_LOCAL_STORAGE_KEY} and LOAD_FREQUENT_ITEMS mutation`, async () => {
+ await testAction({
+ action: actions.loadFrequentGroups,
+ state,
+ expectedMutations: [
+ {
+ type: types.LOAD_FREQUENT_ITEMS,
+ payload: { key: GROUPS_LOCAL_STORAGE_KEY, data: MOCK_GROUPS },
+ },
+ ],
+ });
+
+ expect(storeUtils.loadDataFromLS).toHaveBeenCalledWith(GROUPS_LOCAL_STORAGE_KEY);
+ });
+ });
+
+ describe('loadFrequentProjects', () => {
+ beforeEach(() => {
+ storeUtils.loadDataFromLS = jest.fn().mockReturnValue(MOCK_PROJECTS);
+ });
+
+ it(`calls loadDataFromLS with ${PROJECTS_LOCAL_STORAGE_KEY} and LOAD_FREQUENT_ITEMS mutation`, async () => {
+ await testAction({
+ action: actions.loadFrequentProjects,
+ state,
+ expectedMutations: [
+ {
+ type: types.LOAD_FREQUENT_ITEMS,
+ payload: { key: PROJECTS_LOCAL_STORAGE_KEY, data: MOCK_PROJECTS },
+ },
+ ],
+ });
+
+ expect(storeUtils.loadDataFromLS).toHaveBeenCalledWith(PROJECTS_LOCAL_STORAGE_KEY);
+ });
+ });
+
+ describe('setFrequentGroup', () => {
+ beforeEach(() => {
+ storeUtils.setFrequentItemToLS = jest.fn();
+ });
+
+ it(`calls setFrequentItemToLS with ${GROUPS_LOCAL_STORAGE_KEY} and item data`, async () => {
+ await testAction({
+ action: actions.setFrequentGroup,
+ payload: MOCK_GROUP,
+ state,
+ });
+
+ expect(storeUtils.setFrequentItemToLS).toHaveBeenCalledWith(
+ GROUPS_LOCAL_STORAGE_KEY,
+ state.frequentItems,
+ MOCK_GROUP,
+ );
+ });
+ });
+
+ describe('setFrequentProject', () => {
+ beforeEach(() => {
+ storeUtils.setFrequentItemToLS = jest.fn();
+ });
+
+ it(`calls setFrequentItemToLS with ${PROJECTS_LOCAL_STORAGE_KEY} and item data`, async () => {
+ await testAction({
+ action: actions.setFrequentProject,
+ payload: MOCK_PROJECT,
+ state,
+ });
+
+ expect(storeUtils.setFrequentItemToLS).toHaveBeenCalledWith(
+ PROJECTS_LOCAL_STORAGE_KEY,
+ state.frequentItems,
+ MOCK_PROJECT,
+ );
+ });
+ });
});
diff --git a/spec/frontend/search/store/mutations_spec.js b/spec/frontend/search/store/mutations_spec.js
index df94ba40ff2..a60718a972d 100644
--- a/spec/frontend/search/store/mutations_spec.js
+++ b/spec/frontend/search/store/mutations_spec.js
@@ -71,4 +71,13 @@ describe('Global Search Store Mutations', () => {
expect(state.query[payload.key]).toBe(payload.value);
});
});
+
+ describe('LOAD_FREQUENT_ITEMS', () => {
+ it('sets frequentItems[key] to data', () => {
+ const payload = { key: 'test-key', data: [1, 2, 3] };
+ mutations[types.LOAD_FREQUENT_ITEMS](state, payload);
+
+ expect(state.frequentItems[payload.key]).toStrictEqual(payload.data);
+ });
+ });
});
diff --git a/spec/frontend/search/store/utils_spec.js b/spec/frontend/search/store/utils_spec.js
new file mode 100644
index 00000000000..e5364500464
--- /dev/null
+++ b/spec/frontend/search/store/utils_spec.js
@@ -0,0 +1,147 @@
+import { useLocalStorageSpy } from 'helpers/local_storage_helper';
+import { MAX_FREQUENCY } from '~/search/store/constants';
+import { loadDataFromLS, setFrequentItemToLS } from '~/search/store/utils';
+import { MOCK_LS_KEY, MOCK_GROUPS } from '../mock_data';
+
+useLocalStorageSpy();
+jest.mock('~/lib/utils/accessor', () => ({
+ isLocalStorageAccessSafe: jest.fn().mockReturnValue(true),
+}));
+
+describe('Global Search Store Utils', () => {
+ afterEach(() => {
+ localStorage.clear();
+ });
+
+ describe('loadDataFromLS', () => {
+ let res;
+
+ describe('with valid data', () => {
+ beforeEach(() => {
+ localStorage.setItem(MOCK_LS_KEY, JSON.stringify(MOCK_GROUPS));
+ res = loadDataFromLS(MOCK_LS_KEY);
+ });
+
+ it('returns parsed array', () => {
+ expect(res).toStrictEqual(MOCK_GROUPS);
+ });
+ });
+
+ describe('with invalid data', () => {
+ beforeEach(() => {
+ localStorage.setItem(MOCK_LS_KEY, '[}');
+ res = loadDataFromLS(MOCK_LS_KEY);
+ });
+
+ it('wipes local storage and returns an empty array', () => {
+ expect(localStorage.removeItem).toHaveBeenCalledWith(MOCK_LS_KEY);
+ expect(res).toStrictEqual([]);
+ });
+ });
+ });
+
+ describe('setFrequentItemToLS', () => {
+ const frequentItems = {};
+
+ describe('with existing data', () => {
+ describe(`when frequency is less than ${MAX_FREQUENCY}`, () => {
+ beforeEach(() => {
+ frequentItems[MOCK_LS_KEY] = [{ id: MOCK_GROUPS[0].id, frequency: 1 }];
+ setFrequentItemToLS(MOCK_LS_KEY, frequentItems, MOCK_GROUPS[0]);
+ });
+
+ it('adds 1 to the frequency and calls localStorage.setItem', () => {
+ expect(localStorage.setItem).toHaveBeenCalledWith(
+ MOCK_LS_KEY,
+ JSON.stringify([{ id: MOCK_GROUPS[0].id, frequency: 2 }]),
+ );
+ });
+ });
+
+ describe(`when frequency is equal to ${MAX_FREQUENCY}`, () => {
+ beforeEach(() => {
+ frequentItems[MOCK_LS_KEY] = [{ id: MOCK_GROUPS[0].id, frequency: MAX_FREQUENCY }];
+ setFrequentItemToLS(MOCK_LS_KEY, frequentItems, MOCK_GROUPS[0]);
+ });
+
+ it(`does not further increase frequency past ${MAX_FREQUENCY} and calls localStorage.setItem`, () => {
+ expect(localStorage.setItem).toHaveBeenCalledWith(
+ MOCK_LS_KEY,
+ JSON.stringify([{ id: MOCK_GROUPS[0].id, frequency: MAX_FREQUENCY }]),
+ );
+ });
+ });
+ });
+
+ describe('with no existing data', () => {
+ beforeEach(() => {
+ frequentItems[MOCK_LS_KEY] = [];
+ setFrequentItemToLS(MOCK_LS_KEY, frequentItems, MOCK_GROUPS[0]);
+ });
+
+ it('adds a new entry with frequency 1 and calls localStorage.setItem', () => {
+ expect(localStorage.setItem).toHaveBeenCalledWith(
+ MOCK_LS_KEY,
+ JSON.stringify([{ id: MOCK_GROUPS[0].id, frequency: 1 }]),
+ );
+ });
+ });
+
+ describe('with multiple entries', () => {
+ beforeEach(() => {
+ frequentItems[MOCK_LS_KEY] = [
+ { id: MOCK_GROUPS[0].id, frequency: 1 },
+ { id: MOCK_GROUPS[1].id, frequency: 1 },
+ ];
+ setFrequentItemToLS(MOCK_LS_KEY, frequentItems, MOCK_GROUPS[1]);
+ });
+
+ it('sorts the array by most frequent', () => {
+ expect(localStorage.setItem).toHaveBeenCalledWith(
+ MOCK_LS_KEY,
+ JSON.stringify([
+ { id: MOCK_GROUPS[1].id, frequency: 2 },
+ { id: MOCK_GROUPS[0].id, frequency: 1 },
+ ]),
+ );
+ });
+ });
+
+ describe('with max entries', () => {
+ beforeEach(() => {
+ frequentItems[MOCK_LS_KEY] = [
+ { id: 1, frequency: 5 },
+ { id: 2, frequency: 4 },
+ { id: 3, frequency: 3 },
+ { id: 4, frequency: 2 },
+ { id: 5, frequency: 1 },
+ ];
+ setFrequentItemToLS(MOCK_LS_KEY, frequentItems, { id: 6 });
+ });
+
+ it('removes the least frequent', () => {
+ expect(localStorage.setItem).toHaveBeenCalledWith(
+ MOCK_LS_KEY,
+ JSON.stringify([
+ { id: 1, frequency: 5 },
+ { id: 2, frequency: 4 },
+ { id: 3, frequency: 3 },
+ { id: 4, frequency: 2 },
+ { id: 6, frequency: 1 },
+ ]),
+ );
+ });
+ });
+
+ describe('with null data loaded in', () => {
+ beforeEach(() => {
+ frequentItems[MOCK_LS_KEY] = null;
+ setFrequentItemToLS(MOCK_LS_KEY, frequentItems, MOCK_GROUPS[0]);
+ });
+
+ it('wipes local storage', () => {
+ expect(localStorage.removeItem).toHaveBeenCalledWith(MOCK_LS_KEY);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/search/topbar/components/group_filter_spec.js b/spec/frontend/search/topbar/components/group_filter_spec.js
index 15b46f9c058..3b460402537 100644
--- a/spec/frontend/search/topbar/components/group_filter_spec.js
+++ b/spec/frontend/search/topbar/components/group_filter_spec.js
@@ -1,13 +1,14 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import { MOCK_GROUP, MOCK_QUERY } from 'jest/search/mock_data';
import { visitUrl, setUrlParams } from '~/lib/utils/url_utility';
+import { GROUPS_LOCAL_STORAGE_KEY } from '~/search/store/constants';
import GroupFilter from '~/search/topbar/components/group_filter.vue';
import SearchableDropdown from '~/search/topbar/components/searchable_dropdown.vue';
import { ANY_OPTION, GROUP_DATA, PROJECT_DATA } from '~/search/topbar/constants';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
jest.mock('~/lib/utils/url_utility', () => ({
visitUrl: jest.fn(),
@@ -19,6 +20,8 @@ describe('GroupFilter', () => {
const actionSpies = {
fetchGroups: jest.fn(),
+ setFrequentGroup: jest.fn(),
+ loadFrequentGroups: jest.fn(),
};
const defaultProps = {
@@ -35,7 +38,6 @@ describe('GroupFilter', () => {
});
wrapper = shallowMount(GroupFilter, {
- localVue,
store,
propsData: {
...defaultProps,
@@ -77,14 +79,35 @@ describe('GroupFilter', () => {
});
});
- describe('when @change is emitted', () => {
+ describe('when @change is emitted with Any', () => {
+ beforeEach(() => {
+ createComponent();
+
+ findSearchableDropdown().vm.$emit('change', ANY_OPTION);
+ });
+
+ it('calls setUrlParams with group null, project id null, and then calls visitUrl', () => {
+ expect(setUrlParams).toHaveBeenCalledWith({
+ [GROUP_DATA.queryParam]: null,
+ [PROJECT_DATA.queryParam]: null,
+ });
+
+ expect(visitUrl).toHaveBeenCalled();
+ });
+
+ it('does not call setFrequentGroup', () => {
+ expect(actionSpies.setFrequentGroup).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('when @change is emitted with a group', () => {
beforeEach(() => {
createComponent();
findSearchableDropdown().vm.$emit('change', MOCK_GROUP);
});
- it('calls calls setUrlParams with group id, project id null, and visitUrl', () => {
+ it('calls setUrlParams with group id, project id null, and then calls visitUrl', () => {
expect(setUrlParams).toHaveBeenCalledWith({
[GROUP_DATA.queryParam]: MOCK_GROUP.id,
[PROJECT_DATA.queryParam]: null,
@@ -92,6 +115,10 @@ describe('GroupFilter', () => {
expect(visitUrl).toHaveBeenCalled();
});
+
+ it(`calls setFrequentGroup with the group and ${GROUPS_LOCAL_STORAGE_KEY}`, () => {
+ expect(actionSpies.setFrequentGroup).toHaveBeenCalledWith(expect.any(Object), MOCK_GROUP);
+ });
});
});
@@ -118,4 +145,14 @@ describe('GroupFilter', () => {
});
});
});
+
+ describe('onCreate', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('calls loadFrequentGroups', () => {
+ expect(actionSpies.loadFrequentGroups).toHaveBeenCalledTimes(1);
+ });
+ });
});
diff --git a/spec/frontend/search/topbar/components/project_filter_spec.js b/spec/frontend/search/topbar/components/project_filter_spec.js
index 3bd0769b34a..d260df4120b 100644
--- a/spec/frontend/search/topbar/components/project_filter_spec.js
+++ b/spec/frontend/search/topbar/components/project_filter_spec.js
@@ -1,13 +1,14 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import { MOCK_PROJECT, MOCK_QUERY } from 'jest/search/mock_data';
import { visitUrl, setUrlParams } from '~/lib/utils/url_utility';
+import { PROJECTS_LOCAL_STORAGE_KEY } from '~/search/store/constants';
import ProjectFilter from '~/search/topbar/components/project_filter.vue';
import SearchableDropdown from '~/search/topbar/components/searchable_dropdown.vue';
import { ANY_OPTION, GROUP_DATA, PROJECT_DATA } from '~/search/topbar/constants';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
jest.mock('~/lib/utils/url_utility', () => ({
visitUrl: jest.fn(),
@@ -19,6 +20,8 @@ describe('ProjectFilter', () => {
const actionSpies = {
fetchProjects: jest.fn(),
+ setFrequentProject: jest.fn(),
+ loadFrequentProjects: jest.fn(),
};
const defaultProps = {
@@ -35,7 +38,6 @@ describe('ProjectFilter', () => {
});
wrapper = shallowMount(ProjectFilter, {
- localVue,
store,
propsData: {
...defaultProps,
@@ -84,12 +86,16 @@ describe('ProjectFilter', () => {
findSearchableDropdown().vm.$emit('change', ANY_OPTION);
});
- it('calls setUrlParams with project id, not group id, then calls visitUrl', () => {
+ it('calls setUrlParams with null, no group id, then calls visitUrl', () => {
expect(setUrlParams).toHaveBeenCalledWith({
- [PROJECT_DATA.queryParam]: ANY_OPTION.id,
+ [PROJECT_DATA.queryParam]: null,
});
expect(visitUrl).toHaveBeenCalled();
});
+
+ it('does not call setFrequentProject', () => {
+ expect(actionSpies.setFrequentProject).not.toHaveBeenCalled();
+ });
});
describe('with a Project', () => {
@@ -104,6 +110,13 @@ describe('ProjectFilter', () => {
});
expect(visitUrl).toHaveBeenCalled();
});
+
+ it(`calls setFrequentProject with the group and ${PROJECTS_LOCAL_STORAGE_KEY}`, () => {
+ expect(actionSpies.setFrequentProject).toHaveBeenCalledWith(
+ expect.any(Object),
+ MOCK_PROJECT,
+ );
+ });
});
});
});
@@ -131,4 +144,14 @@ describe('ProjectFilter', () => {
});
});
});
+
+ describe('onCreate', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('calls loadFrequentProjects', () => {
+ expect(actionSpies.loadFrequentProjects).toHaveBeenCalledTimes(1);
+ });
+ });
});