diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-20 14:34:42 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-20 14:34:42 +0000 |
commit | 9f46488805e86b1bc341ea1620b866016c2ce5ed (patch) | |
tree | f9748c7e287041e37d6da49e0a29c9511dc34768 /spec/frontend/jobs/store | |
parent | dfc92d081ea0332d69c8aca2f0e745cb48ae5e6d (diff) | |
download | gitlab-ce-9f46488805e86b1bc341ea1620b866016c2ce5ed.tar.gz |
Add latest changes from gitlab-org/gitlab@13-0-stable-ee
Diffstat (limited to 'spec/frontend/jobs/store')
-rw-r--r-- | spec/frontend/jobs/store/actions_spec.js | 512 | ||||
-rw-r--r-- | spec/frontend/jobs/store/helpers.js | 6 | ||||
-rw-r--r-- | spec/frontend/jobs/store/mutations_spec.js | 2 |
3 files changed, 519 insertions, 1 deletions
diff --git a/spec/frontend/jobs/store/actions_spec.js b/spec/frontend/jobs/store/actions_spec.js new file mode 100644 index 00000000000..91bd5521f70 --- /dev/null +++ b/spec/frontend/jobs/store/actions_spec.js @@ -0,0 +1,512 @@ +import MockAdapter from 'axios-mock-adapter'; +import testAction from 'helpers/vuex_action_helper'; +import { TEST_HOST } from '../../helpers/test_constants'; +import axios from '~/lib/utils/axios_utils'; +import { + setJobEndpoint, + setTraceOptions, + clearEtagPoll, + stopPolling, + requestJob, + fetchJob, + receiveJobSuccess, + receiveJobError, + scrollTop, + scrollBottom, + requestTrace, + fetchTrace, + startPollingTrace, + stopPollingTrace, + receiveTraceSuccess, + receiveTraceError, + toggleCollapsibleLine, + requestJobsForStage, + fetchJobsForStage, + receiveJobsForStageSuccess, + receiveJobsForStageError, + hideSidebar, + showSidebar, + toggleSidebar, +} from '~/jobs/store/actions'; +import state from '~/jobs/store/state'; +import * as types from '~/jobs/store/mutation_types'; + +describe('Job State actions', () => { + let mockedState; + + beforeEach(() => { + mockedState = state(); + }); + + describe('setJobEndpoint', () => { + it('should commit SET_JOB_ENDPOINT mutation', done => { + testAction( + setJobEndpoint, + 'job/872324.json', + mockedState, + [{ type: types.SET_JOB_ENDPOINT, payload: 'job/872324.json' }], + [], + done, + ); + }); + }); + + describe('setTraceOptions', () => { + it('should commit SET_TRACE_OPTIONS mutation', done => { + testAction( + setTraceOptions, + { pagePath: 'job/872324/trace.json' }, + mockedState, + [{ type: types.SET_TRACE_OPTIONS, payload: { pagePath: 'job/872324/trace.json' } }], + [], + done, + ); + }); + }); + + describe('hideSidebar', () => { + it('should commit HIDE_SIDEBAR mutation', done => { + testAction(hideSidebar, null, mockedState, [{ type: types.HIDE_SIDEBAR }], [], done); + }); + }); + + describe('showSidebar', () => { + it('should commit HIDE_SIDEBAR mutation', done => { + testAction(showSidebar, null, mockedState, [{ type: types.SHOW_SIDEBAR }], [], done); + }); + }); + + describe('toggleSidebar', () => { + describe('when isSidebarOpen is true', () => { + it('should dispatch hideSidebar', done => { + testAction(toggleSidebar, null, mockedState, [], [{ type: 'hideSidebar' }], done); + }); + }); + + describe('when isSidebarOpen is false', () => { + it('should dispatch showSidebar', done => { + mockedState.isSidebarOpen = false; + + testAction(toggleSidebar, null, mockedState, [], [{ type: 'showSidebar' }], done); + }); + }); + }); + + describe('requestJob', () => { + it('should commit REQUEST_JOB mutation', done => { + testAction(requestJob, null, mockedState, [{ type: types.REQUEST_JOB }], [], done); + }); + }); + + describe('fetchJob', () => { + let mock; + + beforeEach(() => { + mockedState.jobEndpoint = `${TEST_HOST}/endpoint.json`; + mock = new MockAdapter(axios); + }); + + afterEach(() => { + mock.restore(); + stopPolling(); + clearEtagPoll(); + }); + + describe('success', () => { + it('dispatches requestJob and receiveJobSuccess ', done => { + mock.onGet(`${TEST_HOST}/endpoint.json`).replyOnce(200, { id: 121212, name: 'karma' }); + + testAction( + fetchJob, + null, + mockedState, + [], + [ + { + type: 'requestJob', + }, + { + payload: { id: 121212, name: 'karma' }, + type: 'receiveJobSuccess', + }, + ], + done, + ); + }); + }); + + describe('error', () => { + beforeEach(() => { + mock.onGet(`${TEST_HOST}/endpoint.json`).reply(500); + }); + + it('dispatches requestJob and receiveJobError ', done => { + testAction( + fetchJob, + null, + mockedState, + [], + [ + { + type: 'requestJob', + }, + { + type: 'receiveJobError', + }, + ], + done, + ); + }); + }); + }); + + describe('receiveJobSuccess', () => { + it('should commit RECEIVE_JOB_SUCCESS mutation', done => { + testAction( + receiveJobSuccess, + { id: 121232132 }, + mockedState, + [{ type: types.RECEIVE_JOB_SUCCESS, payload: { id: 121232132 } }], + [], + done, + ); + }); + }); + + describe('receiveJobError', () => { + it('should commit RECEIVE_JOB_ERROR mutation', done => { + testAction(receiveJobError, null, mockedState, [{ type: types.RECEIVE_JOB_ERROR }], [], done); + }); + }); + + describe('scrollTop', () => { + it('should dispatch toggleScrollButtons action', done => { + testAction(scrollTop, null, mockedState, [], [{ type: 'toggleScrollButtons' }], done); + }); + }); + + describe('scrollBottom', () => { + it('should dispatch toggleScrollButtons action', done => { + testAction(scrollBottom, null, mockedState, [], [{ type: 'toggleScrollButtons' }], done); + }); + }); + + describe('requestTrace', () => { + it('should commit REQUEST_TRACE mutation', done => { + testAction(requestTrace, null, mockedState, [{ type: types.REQUEST_TRACE }], [], done); + }); + }); + + describe('fetchTrace', () => { + let mock; + + beforeEach(() => { + mockedState.traceEndpoint = `${TEST_HOST}/endpoint`; + mock = new MockAdapter(axios); + }); + + afterEach(() => { + mock.restore(); + stopPolling(); + clearEtagPoll(); + }); + + describe('success', () => { + it('dispatches requestTrace, receiveTraceSuccess and stopPollingTrace when job is complete', done => { + mock.onGet(`${TEST_HOST}/endpoint/trace.json`).replyOnce(200, { + html: 'I, [2018-08-17T22:57:45.707325 #1841] INFO -- :', + complete: true, + }); + + testAction( + fetchTrace, + null, + mockedState, + [], + [ + { + type: 'toggleScrollisInBottom', + payload: true, + }, + { + payload: { + html: 'I, [2018-08-17T22:57:45.707325 #1841] INFO -- :', + complete: true, + }, + type: 'receiveTraceSuccess', + }, + { + type: 'stopPollingTrace', + }, + ], + done, + ); + }); + + describe('when job is incomplete', () => { + let tracePayload; + + beforeEach(() => { + tracePayload = { + html: 'I, [2018-08-17T22:57:45.707325 #1841] INFO -- :', + complete: false, + }; + + mock.onGet(`${TEST_HOST}/endpoint/trace.json`).replyOnce(200, tracePayload); + }); + + it('dispatches startPollingTrace', done => { + testAction( + fetchTrace, + null, + mockedState, + [], + [ + { type: 'toggleScrollisInBottom', payload: true }, + { type: 'receiveTraceSuccess', payload: tracePayload }, + { type: 'startPollingTrace' }, + ], + done, + ); + }); + + it('does not dispatch startPollingTrace when timeout is non-empty', done => { + mockedState.traceTimeout = 1; + + testAction( + fetchTrace, + null, + mockedState, + [], + [ + { type: 'toggleScrollisInBottom', payload: true }, + { type: 'receiveTraceSuccess', payload: tracePayload }, + ], + done, + ); + }); + }); + }); + + describe('error', () => { + beforeEach(() => { + mock.onGet(`${TEST_HOST}/endpoint/trace.json`).reply(500); + }); + + it('dispatches requestTrace and receiveTraceError ', done => { + testAction( + fetchTrace, + null, + mockedState, + [], + [ + { + type: 'receiveTraceError', + }, + ], + done, + ); + }); + }); + }); + + describe('startPollingTrace', () => { + let dispatch; + let commit; + + beforeEach(() => { + dispatch = jest.fn(); + commit = jest.fn(); + + startPollingTrace({ dispatch, commit }); + }); + + afterEach(() => { + jest.clearAllTimers(); + }); + + it('should save the timeout id but not call fetchTrace', () => { + expect(commit).toHaveBeenCalledWith(types.SET_TRACE_TIMEOUT, expect.any(Number)); + expect(commit.mock.calls[0][1]).toBeGreaterThan(0); + + expect(dispatch).not.toHaveBeenCalledWith('fetchTrace'); + }); + + describe('after timeout has passed', () => { + beforeEach(() => { + jest.advanceTimersByTime(4000); + }); + + it('should clear the timeout id and fetchTrace', () => { + expect(commit).toHaveBeenCalledWith(types.SET_TRACE_TIMEOUT, 0); + expect(dispatch).toHaveBeenCalledWith('fetchTrace'); + }); + }); + }); + + describe('stopPollingTrace', () => { + let origTimeout; + + beforeEach(() => { + // Can't use spyOn(window, 'clearTimeout') because this caused unrelated specs to timeout + // https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23838#note_280277727 + origTimeout = window.clearTimeout; + window.clearTimeout = jest.fn(); + }); + + afterEach(() => { + window.clearTimeout = origTimeout; + }); + + it('should commit STOP_POLLING_TRACE mutation ', done => { + const traceTimeout = 7; + + testAction( + stopPollingTrace, + null, + { ...mockedState, traceTimeout }, + [{ type: types.SET_TRACE_TIMEOUT, payload: 0 }, { type: types.STOP_POLLING_TRACE }], + [], + ) + .then(() => { + expect(window.clearTimeout).toHaveBeenCalledWith(traceTimeout); + }) + .then(done) + .catch(done.fail); + }); + }); + + describe('receiveTraceSuccess', () => { + it('should commit RECEIVE_TRACE_SUCCESS mutation ', done => { + testAction( + receiveTraceSuccess, + 'hello world', + mockedState, + [{ type: types.RECEIVE_TRACE_SUCCESS, payload: 'hello world' }], + [], + done, + ); + }); + }); + + describe('receiveTraceError', () => { + it('should commit stop polling trace', done => { + testAction(receiveTraceError, null, mockedState, [], [{ type: 'stopPollingTrace' }], done); + }); + }); + + describe('toggleCollapsibleLine', () => { + it('should commit TOGGLE_COLLAPSIBLE_LINE mutation ', done => { + testAction( + toggleCollapsibleLine, + { isClosed: true }, + mockedState, + [{ type: types.TOGGLE_COLLAPSIBLE_LINE, payload: { isClosed: true } }], + [], + done, + ); + }); + }); + + describe('requestJobsForStage', () => { + it('should commit REQUEST_JOBS_FOR_STAGE mutation ', done => { + testAction( + requestJobsForStage, + { name: 'deploy' }, + mockedState, + [{ type: types.REQUEST_JOBS_FOR_STAGE, payload: { name: 'deploy' } }], + [], + done, + ); + }); + }); + + describe('fetchJobsForStage', () => { + let mock; + + beforeEach(() => { + mock = new MockAdapter(axios); + }); + + afterEach(() => { + mock.restore(); + }); + + describe('success', () => { + it('dispatches requestJobsForStage and receiveJobsForStageSuccess ', done => { + mock + .onGet(`${TEST_HOST}/jobs.json`) + .replyOnce(200, { latest_statuses: [{ id: 121212, name: 'build' }], retried: [] }); + + testAction( + fetchJobsForStage, + { dropdown_path: `${TEST_HOST}/jobs.json` }, + mockedState, + [], + [ + { + type: 'requestJobsForStage', + payload: { dropdown_path: `${TEST_HOST}/jobs.json` }, + }, + { + payload: [{ id: 121212, name: 'build' }], + type: 'receiveJobsForStageSuccess', + }, + ], + done, + ); + }); + }); + + describe('error', () => { + beforeEach(() => { + mock.onGet(`${TEST_HOST}/jobs.json`).reply(500); + }); + + it('dispatches requestJobsForStage and receiveJobsForStageError', done => { + testAction( + fetchJobsForStage, + { dropdown_path: `${TEST_HOST}/jobs.json` }, + mockedState, + [], + [ + { + type: 'requestJobsForStage', + payload: { dropdown_path: `${TEST_HOST}/jobs.json` }, + }, + { + type: 'receiveJobsForStageError', + }, + ], + done, + ); + }); + }); + }); + + describe('receiveJobsForStageSuccess', () => { + it('should commit RECEIVE_JOBS_FOR_STAGE_SUCCESS mutation ', done => { + testAction( + receiveJobsForStageSuccess, + [{ id: 121212, name: 'karma' }], + mockedState, + [{ type: types.RECEIVE_JOBS_FOR_STAGE_SUCCESS, payload: [{ id: 121212, name: 'karma' }] }], + [], + done, + ); + }); + }); + + describe('receiveJobsForStageError', () => { + it('should commit RECEIVE_JOBS_FOR_STAGE_ERROR mutation ', done => { + testAction( + receiveJobsForStageError, + null, + mockedState, + [{ type: types.RECEIVE_JOBS_FOR_STAGE_ERROR }], + [], + done, + ); + }); + }); +}); diff --git a/spec/frontend/jobs/store/helpers.js b/spec/frontend/jobs/store/helpers.js new file mode 100644 index 00000000000..81a769b4a6e --- /dev/null +++ b/spec/frontend/jobs/store/helpers.js @@ -0,0 +1,6 @@ +import state from '~/jobs/store/state'; + +// eslint-disable-next-line import/prefer-default-export +export const resetStore = store => { + store.replaceState(state()); +}; diff --git a/spec/frontend/jobs/store/mutations_spec.js b/spec/frontend/jobs/store/mutations_spec.js index d77690ffac0..3557d3b94b6 100644 --- a/spec/frontend/jobs/store/mutations_spec.js +++ b/spec/frontend/jobs/store/mutations_spec.js @@ -59,7 +59,7 @@ describe('Jobs Store Mutations', () => { describe('when traceSize is bigger than the total size', () => { it('sets isTraceSizeVisible to false', () => { - const copy = Object.assign({}, stateCopy, { traceSize: 5118460, size: 2321312 }); + const copy = { ...stateCopy, traceSize: 5118460, size: 2321312 }; mutations[types.RECEIVE_TRACE_SUCCESS](copy, { total: 511846 }); |