diff --git a/app/assets/javascripts/reports/codequality_report/store/actions.js b/app/assets/javascripts/reports/codequality_report/store/actions.js index e3238207af26b82c1534a9e31993d0aae58adb93..33005ec0e9e13112381c8d1cb23d57654eb7757b 100644 --- a/app/assets/javascripts/reports/codequality_report/store/actions.js +++ b/app/assets/javascripts/reports/codequality_report/store/actions.js @@ -1,4 +1,4 @@ -import axios from '~/lib/utils/axios_utils'; +import pollUntilComplete from '~/lib/utils/poll_until_complete'; import * as types from './mutation_types'; import { parseCodeclimateMetrics } from './utils/codequality_parser'; @@ -10,8 +10,7 @@ export const fetchReports = ({ state, dispatch, commit }) => { if (!state.basePath) { return dispatch('receiveReportsError'); } - return axios - .get(state.reportsPath) + return pollUntilComplete(state.reportsPath) .then(({ data }) => { return dispatch('receiveReportsSuccess', { newIssues: parseCodeclimateMetrics(data.new_errors, state.headBlobPath), diff --git a/spec/frontend/reports/codequality_report/store/actions_spec.js b/spec/frontend/reports/codequality_report/store/actions_spec.js index 9dda024bffd84b344776d14877595ccf47d06f04..2255b6760740f1c5880f979722a8662ad592fe28 100644 --- a/spec/frontend/reports/codequality_report/store/actions_spec.js +++ b/spec/frontend/reports/codequality_report/store/actions_spec.js @@ -7,6 +7,11 @@ import * as actions from '~/reports/codequality_report/store/actions'; import * as types from '~/reports/codequality_report/store/mutation_types'; import { reportIssues, parsedReportIssues } from '../mock_data'; +const pollInterval = 123; +const pollIntervalHeader = { + 'Poll-Interval': pollInterval, +}; + describe('Codequality Reports actions', () => { let localState; let localStore; @@ -39,10 +44,11 @@ describe('Codequality Reports actions', () => { }); describe('fetchReports', () => { + const endpoint = `${TEST_HOST}/codequality_reports.json`; let mock; beforeEach(() => { - localState.reportsPath = `${TEST_HOST}/codequality_reports.json`; + localState.reportsPath = endpoint; localState.basePath = '/base/path'; mock = new MockAdapter(axios); }); @@ -53,7 +59,7 @@ describe('Codequality Reports actions', () => { describe('on success', () => { it('commits REQUEST_REPORTS and dispatches receiveReportsSuccess', (done) => { - mock.onGet(`${TEST_HOST}/codequality_reports.json`).reply(200, reportIssues); + mock.onGet(endpoint).reply(200, reportIssues); testAction( actions.fetchReports, @@ -73,7 +79,7 @@ describe('Codequality Reports actions', () => { describe('on error', () => { it('commits REQUEST_REPORTS and dispatches receiveReportsError', (done) => { - mock.onGet(`${TEST_HOST}/codequality_reports.json`).reply(500); + mock.onGet(endpoint).reply(500); testAction( actions.fetchReports, @@ -100,6 +106,63 @@ describe('Codequality Reports actions', () => { ); }); }); + + describe('while waiting for report results', () => { + it('continues polling until it receives data', (done) => { + mock + .onGet(endpoint) + .replyOnce(204, undefined, pollIntervalHeader) + .onGet(endpoint) + .reply(200, reportIssues); + + Promise.all([ + testAction( + actions.fetchReports, + null, + localState, + [{ type: types.REQUEST_REPORTS }], + [ + { + payload: parsedReportIssues, + type: 'receiveReportsSuccess', + }, + ], + done, + ), + axios + // wait for initial NO_CONTENT response to be fulfilled + .waitForAll() + .then(() => { + jest.advanceTimersByTime(pollInterval); + }), + ]).catch(done.fail); + }); + + it('continues polling until it receives an error', (done) => { + mock + .onGet(endpoint) + .replyOnce(204, undefined, pollIntervalHeader) + .onGet(endpoint) + .reply(500); + + Promise.all([ + testAction( + actions.fetchReports, + null, + localState, + [{ type: types.REQUEST_REPORTS }], + [{ type: 'receiveReportsError', payload: expect.any(Error) }], + done, + ), + axios + // wait for initial NO_CONTENT response to be fulfilled + .waitForAll() + .then(() => { + jest.advanceTimersByTime(pollInterval); + }), + ]).catch(done.fail); + }); + }); }); describe('receiveReportsSuccess', () => {