summaryrefslogtreecommitdiff
path: root/spec/frontend/error_tracking/store/list
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/error_tracking/store/list')
-rw-r--r--spec/frontend/error_tracking/store/list/actions_spec.js117
-rw-r--r--spec/frontend/error_tracking/store/list/getters_spec.js33
-rw-r--r--spec/frontend/error_tracking/store/list/mutation_spec.js82
3 files changed, 199 insertions, 33 deletions
diff --git a/spec/frontend/error_tracking/store/list/actions_spec.js b/spec/frontend/error_tracking/store/list/actions_spec.js
new file mode 100644
index 00000000000..7906738f5b0
--- /dev/null
+++ b/spec/frontend/error_tracking/store/list/actions_spec.js
@@ -0,0 +1,117 @@
+import axios from '~/lib/utils/axios_utils';
+import MockAdapter from 'axios-mock-adapter';
+import testAction from 'helpers/vuex_action_helper';
+import httpStatusCodes from '~/lib/utils/http_status';
+import createFlash from '~/flash';
+import * as actions from '~/error_tracking/store/list/actions';
+import * as types from '~/error_tracking/store/list/mutation_types';
+
+jest.mock('~/flash.js');
+
+describe('error tracking actions', () => {
+ let mock;
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ mock.restore();
+ });
+
+ describe('startPolling', () => {
+ it('should start polling for data', done => {
+ const payload = { errors: [{ id: 1 }, { id: 2 }] };
+
+ mock.onGet().reply(httpStatusCodes.OK, payload);
+ testAction(
+ actions.startPolling,
+ {},
+ {},
+ [
+ { type: types.SET_LOADING, payload: true },
+ { type: types.SET_PAGINATION, payload: payload.pagination },
+ { type: types.SET_ERRORS, payload: payload.errors },
+ { type: types.SET_LOADING, payload: false },
+ ],
+ [{ type: 'stopPolling' }],
+ () => {
+ done();
+ },
+ );
+ });
+
+ it('should show flash on API error', done => {
+ mock.onGet().reply(httpStatusCodes.BAD_REQUEST);
+
+ testAction(
+ actions.startPolling,
+ {},
+ {},
+ [{ type: types.SET_LOADING, payload: true }, { type: types.SET_LOADING, payload: false }],
+ [],
+ () => {
+ expect(createFlash).toHaveBeenCalledTimes(1);
+ done();
+ },
+ );
+ });
+ });
+
+ describe('restartPolling', () => {
+ it('should restart polling', () => {
+ testAction(
+ actions.restartPolling,
+ {},
+ {},
+ [{ type: types.SET_ERRORS, payload: [] }, { type: types.SET_LOADING, payload: true }],
+ [],
+ );
+ });
+ });
+
+ describe('searchByQuery', () => {
+ it('should search by query', () => {
+ const query = 'search';
+
+ testAction(
+ actions.searchByQuery,
+ query,
+ {},
+ [
+ { type: types.SET_SEARCH_QUERY, payload: query },
+ { type: types.ADD_RECENT_SEARCH, payload: query },
+ ],
+ [{ type: 'stopPolling' }, { type: 'startPolling' }],
+ );
+ });
+ });
+
+ describe('sortByField', () => {
+ it('should search by query', () => {
+ const field = 'frequency';
+
+ testAction(
+ actions.sortByField,
+ { field },
+ {},
+ [{ type: types.SET_SORT_FIELD, payload: { field } }],
+ [{ type: 'stopPolling' }, { type: 'startPolling' }],
+ );
+ });
+ });
+
+ describe('setEnpoint', () => {
+ it('should set search endpoint', () => {
+ const endpoint = 'https://sentry.io';
+
+ testAction(
+ actions.setEndpoint,
+ { endpoint },
+ {},
+ [{ type: types.SET_ENDPOINT, payload: { endpoint } }],
+ [],
+ );
+ });
+ });
+});
diff --git a/spec/frontend/error_tracking/store/list/getters_spec.js b/spec/frontend/error_tracking/store/list/getters_spec.js
deleted file mode 100644
index 3cd7fa37d44..00000000000
--- a/spec/frontend/error_tracking/store/list/getters_spec.js
+++ /dev/null
@@ -1,33 +0,0 @@
-import * as getters from '~/error_tracking/store/list/getters';
-
-describe('Error Tracking getters', () => {
- let state;
-
- const mockErrors = [
- { title: 'ActiveModel::MissingAttributeError: missing attribute: encrypted_password' },
- { title: 'Grape::Exceptions::MethodNotAllowed: Grape::Exceptions::MethodNotAllowed' },
- { title: 'NoMethodError: undefined method `sanitize_http_headers=' },
- { title: 'NoMethodError: undefined method `pry' },
- ];
-
- beforeEach(() => {
- state = {
- errors: mockErrors,
- };
- });
-
- describe('search results', () => {
- it('should return errors filtered by words in title matching the query', () => {
- const filteredErrors = getters.filterErrorsByTitle(state)('NoMethod');
-
- expect(filteredErrors).not.toContainEqual(mockErrors[0]);
- expect(filteredErrors.length).toBe(2);
- });
-
- it('should not return results if there is no matching query', () => {
- const filteredErrors = getters.filterErrorsByTitle(state)('GitLab');
-
- expect(filteredErrors.length).toBe(0);
- });
- });
-});
diff --git a/spec/frontend/error_tracking/store/list/mutation_spec.js b/spec/frontend/error_tracking/store/list/mutation_spec.js
index 6e021185b4d..44a75b6aa1f 100644
--- a/spec/frontend/error_tracking/store/list/mutation_spec.js
+++ b/spec/frontend/error_tracking/store/list/mutation_spec.js
@@ -1,6 +1,11 @@
+import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import mutations from '~/error_tracking/store/list/mutations';
import * as types from '~/error_tracking/store/list/mutation_types';
+const ADD_RECENT_SEARCH = mutations[types.ADD_RECENT_SEARCH];
+const CLEAR_RECENT_SEARCHES = mutations[types.CLEAR_RECENT_SEARCHES];
+const LOAD_RECENT_SEARCHES = mutations[types.LOAD_RECENT_SEARCHES];
+
describe('Error tracking mutations', () => {
describe('SET_ERRORS', () => {
let state;
@@ -33,4 +38,81 @@ describe('Error tracking mutations', () => {
});
});
});
+
+ describe('recent searches', () => {
+ useLocalStorageSpy();
+ let state;
+
+ beforeEach(() => {
+ state = {
+ indexPath: '/project/errors.json',
+ recentSearches: [],
+ };
+ });
+
+ describe('ADD_RECENT_SEARCH', () => {
+ it('adds search queries to recentSearches and localStorage', () => {
+ ADD_RECENT_SEARCH(state, 'my issue');
+
+ expect(state.recentSearches).toEqual(['my issue']);
+ expect(localStorage.setItem).toHaveBeenCalledWith(
+ 'recent-searches/project/errors.json',
+ '["my issue"]',
+ );
+ });
+
+ it('does not add empty searches', () => {
+ ADD_RECENT_SEARCH(state, '');
+
+ expect(state.recentSearches).toEqual([]);
+ expect(localStorage.setItem).not.toHaveBeenCalled();
+ });
+
+ it('adds new queries to start of the list', () => {
+ state.recentSearches = ['previous', 'searches'];
+
+ ADD_RECENT_SEARCH(state, 'new search');
+
+ expect(state.recentSearches).toEqual(['new search', 'previous', 'searches']);
+ });
+
+ it('limits recentSearches to 5 items', () => {
+ state.recentSearches = [1, 2, 3, 4, 5];
+
+ ADD_RECENT_SEARCH(state, 'new search');
+
+ expect(state.recentSearches).toEqual(['new search', 1, 2, 3, 4]);
+ });
+
+ it('does not add same search query twice', () => {
+ state.recentSearches = ['already', 'searched'];
+
+ ADD_RECENT_SEARCH(state, 'searched');
+
+ expect(state.recentSearches).toEqual(['searched', 'already']);
+ });
+ });
+
+ describe('CLEAR_RECENT_SEARCHES', () => {
+ it('clears recentSearches and localStorage', () => {
+ state.recentSearches = ['first', 'second'];
+
+ CLEAR_RECENT_SEARCHES(state);
+
+ expect(state.recentSearches).toEqual([]);
+ expect(localStorage.removeItem).toHaveBeenCalledWith('recent-searches/project/errors.json');
+ });
+ });
+
+ describe('LOAD_RECENT_SEARCHES', () => {
+ it('loads recent searches from localStorage', () => {
+ jest.spyOn(window.localStorage, 'getItem').mockReturnValue('["first", "second"]');
+
+ LOAD_RECENT_SEARCHES(state);
+
+ expect(state.recentSearches).toEqual(['first', 'second']);
+ expect(localStorage.getItem).toHaveBeenCalledWith('recent-searches/project/errors.json');
+ });
+ });
+ });
});