Commit 321284e5 authored by Tomas Bulva's avatar Tomas Bulva

Issue 323331 - createFlash called twice in search fetchProjects

Changelog: changed
parent 71a5063e
...@@ -234,7 +234,7 @@ const Api = { ...@@ -234,7 +234,7 @@ const Api = {
return axios return axios
.get(url, { .get(url, {
params: Object.assign(defaults, options), params: { ...defaults, ...options },
}) })
.then(({ data, headers }) => { .then(({ data, headers }) => {
callback(data); callback(data);
...@@ -445,7 +445,7 @@ const Api = { ...@@ -445,7 +445,7 @@ const Api = {
}, },
// Return group projects list. Filtered by query // Return group projects list. Filtered by query
groupProjects(groupId, query, options, callback) { groupProjects(groupId, query, options, callback = () => {}, useCustomErrorHandler = false) {
const url = Api.buildUrl(Api.groupProjectsPath).replace(':id', groupId); const url = Api.buildUrl(Api.groupProjectsPath).replace(':id', groupId);
const defaults = { const defaults = {
search: query, search: query,
...@@ -455,14 +455,21 @@ const Api = { ...@@ -455,14 +455,21 @@ const Api = {
.get(url, { .get(url, {
params: { ...defaults, ...options }, params: { ...defaults, ...options },
}) })
.then(({ data }) => (callback ? callback(data) : data)) .then(({ data, headers }) => {
.catch(() => { callback(data);
return { data, headers };
})
.catch((error) => {
if (useCustomErrorHandler) {
throw error;
}
createFlash({ createFlash({
message: __('Something went wrong while fetching projects'), message: __('Something went wrong while fetching projects'),
}); });
if (callback) {
callback(); callback();
}
}); });
}, },
......
...@@ -18,31 +18,35 @@ export const fetchGroups = ({ commit }, search) => { ...@@ -18,31 +18,35 @@ export const fetchGroups = ({ commit }, search) => {
}); });
}; };
export const fetchProjects = ({ commit, state }, search) => { export const fetchProjects = ({ commit, state }, search, emptyCallback = () => {}) => {
commit(types.REQUEST_PROJECTS); commit(types.REQUEST_PROJECTS);
const groupId = state.query?.group_id; const groupId = state.query?.group_id;
const callback = (data) => {
if (data) { const handleCatch = () => {
commit(types.RECEIVE_PROJECTS_SUCCESS, data); createFlash({ message: __('There was an error fetching projects') });
} else { commit(types.RECEIVE_PROJECTS_ERROR);
createFlash({ message: __('There was an error fetching projects') }); };
commit(types.RECEIVE_PROJECTS_ERROR); const handleSuccess = ({ data }) => {
} commit(types.RECEIVE_PROJECTS_SUCCESS, data);
}; };
if (groupId) { if (groupId) {
// TODO (https://gitlab.com/gitlab-org/gitlab/-/issues/323331): For errors `createFlash` is called twice; in `callback` and in `Api.groupProjects`
Api.groupProjects( Api.groupProjects(
groupId, groupId,
search, search,
{ order_by: 'similarity', with_shared: false, include_subgroups: true }, {
callback, order_by: 'similarity',
); with_shared: false,
include_subgroups: true,
},
emptyCallback,
true,
)
.then(handleSuccess)
.catch(handleCatch);
} else { } else {
// The .catch() is due to the API method not handling a rejection properly // The .catch() is due to the API method not handling a rejection properly
Api.projects(search, { order_by: 'similarity' }, callback).catch(() => { Api.projects(search, { order_by: 'similarity' }).then(handleSuccess).catch(handleCatch);
callback();
});
} }
}; };
......
...@@ -49,6 +49,7 @@ const noop = () => {}; ...@@ -49,6 +49,7 @@ const noop = () => {};
* expectedActions: [], * expectedActions: [],
* }) * })
*/ */
export default ( export default (
actionArg, actionArg,
payloadArg, payloadArg,
......
...@@ -2,6 +2,9 @@ import MockAdapter from 'axios-mock-adapter'; ...@@ -2,6 +2,9 @@ import MockAdapter from 'axios-mock-adapter';
import Api, { DEFAULT_PER_PAGE } from '~/api'; import Api, { DEFAULT_PER_PAGE } from '~/api';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import httpStatus from '~/lib/utils/http_status'; import httpStatus from '~/lib/utils/http_status';
import createFlash from '~/flash';
jest.mock('~/flash');
describe('Api', () => { describe('Api', () => {
const dummyApiVersion = 'v3000'; const dummyApiVersion = 'v3000';
...@@ -675,6 +678,33 @@ describe('Api', () => { ...@@ -675,6 +678,33 @@ describe('Api', () => {
done(); done();
}); });
}); });
it('uses flesh on error by default', async () => {
const groupId = '123456';
const query = 'dummy query';
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups/${groupId}/projects.json`;
const flashCallback = (callCount) => {
expect(createFlash).toHaveBeenCalledTimes(callCount);
createFlash.mockClear();
};
mock.onGet(expectedUrl).reply(500, null);
const response = await Api.groupProjects(groupId, query, {}, () => {}).then(() => {
flashCallback(1);
});
expect(response).toBeUndefined();
});
it('NOT uses flesh on error with param useCustomErrorHandler', async () => {
const groupId = '123456';
const query = 'dummy query';
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups/${groupId}/projects.json`;
mock.onGet(expectedUrl).reply(500, null);
const apiCall = Api.groupProjects(groupId, query, {}, () => {}, true);
await expect(apiCall).rejects.toThrow();
});
}); });
describe('groupShareWithGroup', () => { describe('groupShareWithGroup', () => {
......
...@@ -56,7 +56,7 @@ describe('Global Search Store Actions', () => { ...@@ -56,7 +56,7 @@ describe('Global Search Store Actions', () => {
${actions.fetchGroups} | ${{ method: 'onGet', code: 200, res: MOCK_GROUPS }} | ${'success'} | ${[{ type: types.REQUEST_GROUPS }, { type: types.RECEIVE_GROUPS_SUCCESS, payload: MOCK_GROUPS }]} | ${0} ${actions.fetchGroups} | ${{ method: 'onGet', code: 200, res: MOCK_GROUPS }} | ${'success'} | ${[{ type: types.REQUEST_GROUPS }, { type: types.RECEIVE_GROUPS_SUCCESS, payload: MOCK_GROUPS }]} | ${0}
${actions.fetchGroups} | ${{ method: 'onGet', code: 500, res: null }} | ${'error'} | ${[{ type: types.REQUEST_GROUPS }, { type: types.RECEIVE_GROUPS_ERROR }]} | ${1} ${actions.fetchGroups} | ${{ method: 'onGet', code: 500, res: null }} | ${'error'} | ${[{ type: types.REQUEST_GROUPS }, { type: types.RECEIVE_GROUPS_ERROR }]} | ${1}
${actions.fetchProjects} | ${{ method: 'onGet', code: 200, res: MOCK_PROJECTS }} | ${'success'} | ${[{ type: types.REQUEST_PROJECTS }, { type: types.RECEIVE_PROJECTS_SUCCESS, payload: MOCK_PROJECTS }]} | ${0} ${actions.fetchProjects} | ${{ method: 'onGet', code: 200, res: MOCK_PROJECTS }} | ${'success'} | ${[{ type: types.REQUEST_PROJECTS }, { type: types.RECEIVE_PROJECTS_SUCCESS, payload: MOCK_PROJECTS }]} | ${0}
${actions.fetchProjects} | ${{ method: 'onGet', code: 500, res: null }} | ${'error'} | ${[{ type: types.REQUEST_PROJECTS }, { type: types.RECEIVE_PROJECTS_ERROR }]} | ${2} ${actions.fetchProjects} | ${{ method: 'onGet', code: 500, res: null }} | ${'error'} | ${[{ type: types.REQUEST_PROJECTS }, { type: types.RECEIVE_PROJECTS_ERROR }]} | ${1}
`(`axios calls`, ({ action, axiosMock, type, expectedMutations, flashCallCount }) => { `(`axios calls`, ({ action, axiosMock, type, expectedMutations, flashCallCount }) => {
describe(action.name, () => { describe(action.name, () => {
describe(`on ${type}`, () => { describe(`on ${type}`, () => {
...@@ -121,8 +121,8 @@ describe('Global Search Store Actions', () => { ...@@ -121,8 +121,8 @@ describe('Global Search Store Actions', () => {
describe('when groupId is set', () => { describe('when groupId is set', () => {
it('calls Api.groupProjects with expected parameters', () => { it('calls Api.groupProjects with expected parameters', () => {
actions.fetchProjects({ commit: mockCommit, state }); const callbackTest = jest.fn();
actions.fetchProjects({ commit: mockCommit, state }, undefined, callbackTest);
expect(Api.groupProjects).toHaveBeenCalledWith( expect(Api.groupProjects).toHaveBeenCalledWith(
state.query.group_id, state.query.group_id,
state.query.search, state.query.search,
...@@ -131,7 +131,8 @@ describe('Global Search Store Actions', () => { ...@@ -131,7 +131,8 @@ describe('Global Search Store Actions', () => {
include_subgroups: true, include_subgroups: true,
with_shared: false, with_shared: false,
}, },
expect.any(Function), callbackTest,
true,
); );
expect(Api.projects).not.toHaveBeenCalled(); expect(Api.projects).not.toHaveBeenCalled();
}); });
...@@ -144,15 +145,10 @@ describe('Global Search Store Actions', () => { ...@@ -144,15 +145,10 @@ describe('Global Search Store Actions', () => {
it('calls Api.projects', () => { it('calls Api.projects', () => {
actions.fetchProjects({ commit: mockCommit, state }); actions.fetchProjects({ commit: mockCommit, state });
expect(Api.groupProjects).not.toHaveBeenCalled(); expect(Api.groupProjects).not.toHaveBeenCalled();
expect(Api.projects).toHaveBeenCalledWith( expect(Api.projects).toHaveBeenCalledWith(state.query.search, {
state.query.search, order_by: 'similarity',
{ });
order_by: 'similarity',
},
expect.any(Function),
);
}); });
}); });
}); });
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment