diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-09-20 14:18:08 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-09-20 14:18:08 +0300 |
commit | 5afcbe03ead9ada87621888a31a62652b10a7e4f (patch) | |
tree | 9918b67a0d0f0bafa6542e839a8be37adf73102d /spec/frontend/ci/job_details/store/actions_spec.js | |
parent | c97c0201564848c1f53226fe19d71fdcc472f7d0 (diff) |
Add latest changes from gitlab-org/gitlab@16-4-stable-eev16.4.0-rc42
Diffstat (limited to 'spec/frontend/ci/job_details/store/actions_spec.js')
-rw-r--r-- | spec/frontend/ci/job_details/store/actions_spec.js | 502 |
1 files changed, 502 insertions, 0 deletions
diff --git a/spec/frontend/ci/job_details/store/actions_spec.js b/spec/frontend/ci/job_details/store/actions_spec.js new file mode 100644 index 00000000000..bb5c1fe32bd --- /dev/null +++ b/spec/frontend/ci/job_details/store/actions_spec.js @@ -0,0 +1,502 @@ +import MockAdapter from 'axios-mock-adapter'; +import { TEST_HOST } from 'helpers/test_constants'; +import testAction from 'helpers/vuex_action_helper'; +import { + setJobEndpoint, + setJobLogOptions, + clearEtagPoll, + stopPolling, + requestJob, + fetchJob, + receiveJobSuccess, + receiveJobError, + scrollTop, + scrollBottom, + requestJobLog, + fetchJobLog, + startPollingJobLog, + stopPollingJobLog, + receiveJobLogSuccess, + receiveJobLogError, + toggleCollapsibleLine, + requestJobsForStage, + fetchJobsForStage, + receiveJobsForStageSuccess, + receiveJobsForStageError, + hideSidebar, + showSidebar, + toggleSidebar, +} from '~/ci/job_details/store/actions'; +import * as types from '~/ci/job_details/store/mutation_types'; +import state from '~/ci/job_details/store/state'; +import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_OK } from '~/lib/utils/http_status'; + +describe('Job State actions', () => { + let mockedState; + + beforeEach(() => { + mockedState = state(); + }); + + describe('setJobEndpoint', () => { + it('should commit SET_JOB_ENDPOINT mutation', () => { + return testAction( + setJobEndpoint, + 'job/872324.json', + mockedState, + [{ type: types.SET_JOB_ENDPOINT, payload: 'job/872324.json' }], + [], + ); + }); + }); + + describe('setJobLogOptions', () => { + it('should commit SET_JOB_LOG_OPTIONS mutation', () => { + return testAction( + setJobLogOptions, + { pagePath: 'job/872324/trace.json' }, + mockedState, + [{ type: types.SET_JOB_LOG_OPTIONS, payload: { pagePath: 'job/872324/trace.json' } }], + [], + ); + }); + }); + + describe('hideSidebar', () => { + it('should commit HIDE_SIDEBAR mutation', () => { + return testAction(hideSidebar, null, mockedState, [{ type: types.HIDE_SIDEBAR }], []); + }); + }); + + describe('showSidebar', () => { + it('should commit SHOW_SIDEBAR mutation', () => { + return testAction(showSidebar, null, mockedState, [{ type: types.SHOW_SIDEBAR }], []); + }); + }); + + describe('toggleSidebar', () => { + describe('when isSidebarOpen is true', () => { + it('should dispatch hideSidebar', () => { + return testAction(toggleSidebar, null, mockedState, [], [{ type: 'hideSidebar' }]); + }); + }); + + describe('when isSidebarOpen is false', () => { + it('should dispatch showSidebar', () => { + mockedState.isSidebarOpen = false; + + return testAction(toggleSidebar, null, mockedState, [], [{ type: 'showSidebar' }]); + }); + }); + }); + + describe('requestJob', () => { + it('should commit REQUEST_JOB mutation', () => { + return testAction(requestJob, null, mockedState, [{ type: types.REQUEST_JOB }], []); + }); + }); + + 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', () => { + mock + .onGet(`${TEST_HOST}/endpoint.json`) + .replyOnce(HTTP_STATUS_OK, { id: 121212, name: 'karma' }); + + return testAction( + fetchJob, + null, + mockedState, + [], + [ + { + type: 'requestJob', + }, + { + payload: { id: 121212, name: 'karma' }, + type: 'receiveJobSuccess', + }, + ], + ); + }); + }); + + describe('error', () => { + beforeEach(() => { + mock.onGet(`${TEST_HOST}/endpoint.json`).reply(HTTP_STATUS_INTERNAL_SERVER_ERROR); + }); + + it('dispatches requestJob and receiveJobError', () => { + return testAction( + fetchJob, + null, + mockedState, + [], + [ + { + type: 'requestJob', + }, + { + type: 'receiveJobError', + }, + ], + ); + }); + }); + }); + + describe('receiveJobSuccess', () => { + it('should commit RECEIVE_JOB_SUCCESS mutation', () => { + return testAction( + receiveJobSuccess, + { id: 121232132 }, + mockedState, + [{ type: types.RECEIVE_JOB_SUCCESS, payload: { id: 121232132 } }], + [], + ); + }); + }); + + describe('receiveJobError', () => { + it('should commit RECEIVE_JOB_ERROR mutation', () => { + return testAction( + receiveJobError, + null, + mockedState, + [{ type: types.RECEIVE_JOB_ERROR }], + [], + ); + }); + }); + + describe('scrollTop', () => { + it('should dispatch toggleScrollButtons action', () => { + return testAction(scrollTop, null, mockedState, [], [{ type: 'toggleScrollButtons' }]); + }); + }); + + describe('scrollBottom', () => { + it('should dispatch toggleScrollButtons action', () => { + return testAction(scrollBottom, null, mockedState, [], [{ type: 'toggleScrollButtons' }]); + }); + }); + + describe('requestJobLog', () => { + it('should commit REQUEST_JOB_LOG mutation', () => { + return testAction(requestJobLog, null, mockedState, [{ type: types.REQUEST_JOB_LOG }], []); + }); + }); + + describe('fetchJobLog', () => { + let mock; + + beforeEach(() => { + mockedState.jobLogEndpoint = `${TEST_HOST}/endpoint`; + mock = new MockAdapter(axios); + }); + + afterEach(() => { + mock.restore(); + stopPolling(); + clearEtagPoll(); + }); + + describe('success', () => { + it('dispatches requestJobLog, receiveJobLogSuccess and stopPollingJobLog when job is complete', () => { + mock.onGet(`${TEST_HOST}/endpoint/trace.json`).replyOnce(HTTP_STATUS_OK, { + html: 'I, [2018-08-17T22:57:45.707325 #1841] INFO -- :', + complete: true, + }); + + return testAction( + fetchJobLog, + null, + mockedState, + [], + [ + { + type: 'toggleScrollisInBottom', + payload: true, + }, + { + payload: { + html: 'I, [2018-08-17T22:57:45.707325 #1841] INFO -- :', + complete: true, + }, + type: 'receiveJobLogSuccess', + }, + { + type: 'stopPollingJobLog', + }, + ], + ); + }); + + describe('when job is incomplete', () => { + let jobLogPayload; + + beforeEach(() => { + jobLogPayload = { + html: 'I, [2018-08-17T22:57:45.707325 #1841] INFO -- :', + complete: false, + }; + + mock.onGet(`${TEST_HOST}/endpoint/trace.json`).replyOnce(HTTP_STATUS_OK, jobLogPayload); + }); + + it('dispatches startPollingJobLog', () => { + return testAction( + fetchJobLog, + null, + mockedState, + [], + [ + { type: 'toggleScrollisInBottom', payload: true }, + { type: 'receiveJobLogSuccess', payload: jobLogPayload }, + { type: 'startPollingJobLog' }, + ], + ); + }); + + it('does not dispatch startPollingJobLog when timeout is non-empty', () => { + mockedState.jobLogTimeout = 1; + + return testAction( + fetchJobLog, + null, + mockedState, + [], + [ + { type: 'toggleScrollisInBottom', payload: true }, + { type: 'receiveJobLogSuccess', payload: jobLogPayload }, + ], + ); + }); + }); + }); + + describe('error', () => { + beforeEach(() => { + mock.onGet(`${TEST_HOST}/endpoint/trace.json`).reply(HTTP_STATUS_INTERNAL_SERVER_ERROR); + }); + + it('dispatches requestJobLog and receiveJobLogError', () => { + return testAction( + fetchJobLog, + null, + mockedState, + [], + [ + { + type: 'receiveJobLogError', + }, + ], + ); + }); + }); + }); + + describe('startPollingJobLog', () => { + let dispatch; + let commit; + + beforeEach(() => { + dispatch = jest.fn(); + commit = jest.fn(); + + startPollingJobLog({ dispatch, commit }); + }); + + afterEach(() => { + jest.clearAllTimers(); + }); + + it('should save the timeout id but not call fetchJobLog', () => { + expect(commit).toHaveBeenCalledWith(types.SET_JOB_LOG_TIMEOUT, expect.any(Number)); + expect(commit.mock.calls[0][1]).toBeGreaterThan(0); + + expect(dispatch).not.toHaveBeenCalledWith('fetchJobLog'); + }); + + describe('after timeout has passed', () => { + beforeEach(() => { + jest.advanceTimersByTime(4000); + }); + + it('should clear the timeout id and fetchJobLog', () => { + expect(commit).toHaveBeenCalledWith(types.SET_JOB_LOG_TIMEOUT, 0); + expect(dispatch).toHaveBeenCalledWith('fetchJobLog'); + }); + }); + }); + + describe('stopPollingJobLog', () => { + 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_JOB_LOG mutation', async () => { + const jobLogTimeout = 7; + + await testAction( + stopPollingJobLog, + null, + { ...mockedState, jobLogTimeout }, + [{ type: types.SET_JOB_LOG_TIMEOUT, payload: 0 }, { type: types.STOP_POLLING_JOB_LOG }], + [], + ); + expect(window.clearTimeout).toHaveBeenCalledWith(jobLogTimeout); + }); + }); + + describe('receiveJobLogSuccess', () => { + it('should commit RECEIVE_JOB_LOG_SUCCESS mutation', () => { + return testAction( + receiveJobLogSuccess, + 'hello world', + mockedState, + [{ type: types.RECEIVE_JOB_LOG_SUCCESS, payload: 'hello world' }], + [], + ); + }); + }); + + describe('receiveJobLogError', () => { + it('should commit stop polling job log', () => { + return testAction(receiveJobLogError, null, mockedState, [], [{ type: 'stopPollingJobLog' }]); + }); + }); + + describe('toggleCollapsibleLine', () => { + it('should commit TOGGLE_COLLAPSIBLE_LINE mutation', () => { + return testAction( + toggleCollapsibleLine, + { isClosed: true }, + mockedState, + [{ type: types.TOGGLE_COLLAPSIBLE_LINE, payload: { isClosed: true } }], + [], + ); + }); + }); + + describe('requestJobsForStage', () => { + it('should commit REQUEST_JOBS_FOR_STAGE mutation', () => { + return testAction( + requestJobsForStage, + { name: 'deploy' }, + mockedState, + [{ type: types.REQUEST_JOBS_FOR_STAGE, payload: { name: 'deploy' } }], + [], + ); + }); + }); + + describe('fetchJobsForStage', () => { + let mock; + + beforeEach(() => { + mock = new MockAdapter(axios); + }); + + afterEach(() => { + mock.restore(); + }); + + describe('success', () => { + it('dispatches requestJobsForStage and receiveJobsForStageSuccess', () => { + mock.onGet(`${TEST_HOST}/jobs.json`).replyOnce(HTTP_STATUS_OK, { + latest_statuses: [{ id: 121212, name: 'build' }], + retried: [], + }); + + return 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', + }, + ], + ); + }); + }); + + describe('error', () => { + beforeEach(() => { + mock.onGet(`${TEST_HOST}/jobs.json`).reply(HTTP_STATUS_INTERNAL_SERVER_ERROR); + }); + + it('dispatches requestJobsForStage and receiveJobsForStageError', () => { + return testAction( + fetchJobsForStage, + { dropdown_path: `${TEST_HOST}/jobs.json` }, + mockedState, + [], + [ + { + type: 'requestJobsForStage', + payload: { dropdown_path: `${TEST_HOST}/jobs.json` }, + }, + { + type: 'receiveJobsForStageError', + }, + ], + ); + }); + }); + }); + + describe('receiveJobsForStageSuccess', () => { + it('should commit RECEIVE_JOBS_FOR_STAGE_SUCCESS mutation', () => { + return testAction( + receiveJobsForStageSuccess, + [{ id: 121212, name: 'karma' }], + mockedState, + [{ type: types.RECEIVE_JOBS_FOR_STAGE_SUCCESS, payload: [{ id: 121212, name: 'karma' }] }], + [], + ); + }); + }); + + describe('receiveJobsForStageError', () => { + it('should commit RECEIVE_JOBS_FOR_STAGE_ERROR mutation', () => { + return testAction( + receiveJobsForStageError, + null, + mockedState, + [{ type: types.RECEIVE_JOBS_FOR_STAGE_ERROR }], + [], + ); + }); + }); +}); |