summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilipa Lacerda <filipa@gitlab.com>2018-05-23 09:02:42 +0000
committerFilipa Lacerda <filipa@gitlab.com>2018-05-23 09:02:42 +0000
commit7e1e35593197417fb4a986e7f3504e2412bd57fe (patch)
tree61c214cfa21783be673bc364f197c55c28aa16d1
parent1623e4ac75d5db61e4f08536f555ac87fce6fc1b (diff)
parentba90742631a5e1a0d1edc546d5d49b59210642bf (diff)
downloadgitlab-ce-7e1e35593197417fb4a986e7f3504e2412bd57fe.tar.gz
Merge branch 'ide-jobs-list' into 'master'
Pipelines store actions & states in web IDE Closes #44604 See merge request gitlab-org/gitlab-ce!18912
-rw-r--r--app/assets/javascripts/api.js16
-rw-r--r--app/assets/javascripts/ide/stores/index.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/actions.js49
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/getters.js7
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/index.js12
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/mutation_types.js7
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/mutations.js53
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/state.js6
-rw-r--r--spec/javascripts/helpers/vuex_action_helper.js2
-rw-r--r--spec/javascripts/ide/mock_data.js47
-rw-r--r--spec/javascripts/ide/stores/modules/pipelines/actions_spec.js289
-rw-r--r--spec/javascripts/ide/stores/modules/pipelines/getters_spec.js71
-rw-r--r--spec/javascripts/ide/stores/modules/pipelines/mutations_spec.js120
13 files changed, 679 insertions, 2 deletions
diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js
index 8ad3d18b302..eb919241318 100644
--- a/app/assets/javascripts/api.js
+++ b/app/assets/javascripts/api.js
@@ -23,6 +23,8 @@ const Api = {
commitPath: '/api/:version/projects/:id/repository/commits',
branchSinglePath: '/api/:version/projects/:id/repository/branches/:branch',
createBranchPath: '/api/:version/projects/:id/repository/branches',
+ pipelinesPath: '/api/:version/projects/:id/pipelines',
+ pipelineJobsPath: '/api/:version/projects/:id/pipelines/:pipeline_id/jobs',
group(groupId, callback) {
const url = Api.buildUrl(Api.groupPath).replace(':id', groupId);
@@ -222,6 +224,20 @@ const Api = {
});
},
+ pipelines(projectPath, params = {}) {
+ const url = Api.buildUrl(this.pipelinesPath).replace(':id', encodeURIComponent(projectPath));
+
+ return axios.get(url, { params });
+ },
+
+ pipelineJobs(projectPath, pipelineId, params = {}) {
+ const url = Api.buildUrl(this.pipelineJobsPath)
+ .replace(':id', encodeURIComponent(projectPath))
+ .replace(':pipeline_id', pipelineId);
+
+ return axios.get(url, { params });
+ },
+
buildUrl(url) {
let urlRoot = '';
if (gon.relative_url_root != null) {
diff --git a/app/assets/javascripts/ide/stores/index.js b/app/assets/javascripts/ide/stores/index.js
index 7c82ce7976b..699710055e3 100644
--- a/app/assets/javascripts/ide/stores/index.js
+++ b/app/assets/javascripts/ide/stores/index.js
@@ -5,6 +5,7 @@ import * as actions from './actions';
import * as getters from './getters';
import mutations from './mutations';
import commitModule from './modules/commit';
+import pipelines from './modules/pipelines';
Vue.use(Vuex);
@@ -15,5 +16,6 @@ export default new Vuex.Store({
getters,
modules: {
commit: commitModule,
+ pipelines,
},
});
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/actions.js b/app/assets/javascripts/ide/stores/modules/pipelines/actions.js
new file mode 100644
index 00000000000..07f7b201f2e
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/actions.js
@@ -0,0 +1,49 @@
+import { __ } from '../../../../locale';
+import Api from '../../../../api';
+import flash from '../../../../flash';
+import * as types from './mutation_types';
+
+export const requestLatestPipeline = ({ commit }) => commit(types.REQUEST_LATEST_PIPELINE);
+export const receiveLatestPipelineError = ({ commit }) => {
+ flash(__('There was an error loading latest pipeline'));
+ commit(types.RECEIVE_LASTEST_PIPELINE_ERROR);
+};
+export const receiveLatestPipelineSuccess = ({ commit }, pipeline) =>
+ commit(types.RECEIVE_LASTEST_PIPELINE_SUCCESS, pipeline);
+
+export const fetchLatestPipeline = ({ dispatch, rootState }, sha) => {
+ dispatch('requestLatestPipeline');
+
+ return Api.pipelines(rootState.currentProjectId, { sha, per_page: '1' })
+ .then(({ data }) => {
+ dispatch('receiveLatestPipelineSuccess', data.pop());
+ })
+ .catch(() => dispatch('receiveLatestPipelineError'));
+};
+
+export const requestJobs = ({ commit }) => commit(types.REQUEST_JOBS);
+export const receiveJobsError = ({ commit }) => {
+ flash(__('There was an error loading jobs'));
+ commit(types.RECEIVE_JOBS_ERROR);
+};
+export const receiveJobsSuccess = ({ commit }, data) => commit(types.RECEIVE_JOBS_SUCCESS, data);
+
+export const fetchJobs = ({ dispatch, state, rootState }, page = '1') => {
+ dispatch('requestJobs');
+
+ Api.pipelineJobs(rootState.currentProjectId, state.latestPipeline.id, {
+ page,
+ })
+ .then(({ data, headers }) => {
+ const nextPage = headers && headers['x-next-page'];
+
+ dispatch('receiveJobsSuccess', data);
+
+ if (nextPage) {
+ dispatch('fetchJobs', nextPage);
+ }
+ })
+ .catch(() => dispatch('receiveJobsError'));
+};
+
+export default () => {};
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/getters.js b/app/assets/javascripts/ide/stores/modules/pipelines/getters.js
new file mode 100644
index 00000000000..d6c91f5b64d
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/getters.js
@@ -0,0 +1,7 @@
+export const hasLatestPipeline = state => !state.isLoadingPipeline && !!state.latestPipeline;
+
+export const failedJobs = state =>
+ state.stages.reduce(
+ (acc, stage) => acc.concat(stage.jobs.filter(job => job.status === 'failed')),
+ [],
+ );
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/index.js b/app/assets/javascripts/ide/stores/modules/pipelines/index.js
new file mode 100644
index 00000000000..b44c3141b81
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/index.js
@@ -0,0 +1,12 @@
+import state from './state';
+import * as actions from './actions';
+import mutations from './mutations';
+import * as getters from './getters';
+
+export default {
+ namespaced: true,
+ state: state(),
+ actions,
+ mutations,
+ getters,
+};
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/mutation_types.js b/app/assets/javascripts/ide/stores/modules/pipelines/mutation_types.js
new file mode 100644
index 00000000000..6b5701670a6
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/mutation_types.js
@@ -0,0 +1,7 @@
+export const REQUEST_LATEST_PIPELINE = 'REQUEST_LATEST_PIPELINE';
+export const RECEIVE_LASTEST_PIPELINE_ERROR = 'RECEIVE_LASTEST_PIPELINE_ERROR';
+export const RECEIVE_LASTEST_PIPELINE_SUCCESS = 'RECEIVE_LASTEST_PIPELINE_SUCCESS';
+
+export const REQUEST_JOBS = 'REQUEST_JOBS';
+export const RECEIVE_JOBS_ERROR = 'RECEIVE_JOBS_ERROR';
+export const RECEIVE_JOBS_SUCCESS = 'RECEIVE_JOBS_SUCCESS';
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js b/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js
new file mode 100644
index 00000000000..2b16e57b386
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js
@@ -0,0 +1,53 @@
+/* eslint-disable no-param-reassign */
+import * as types from './mutation_types';
+
+export default {
+ [types.REQUEST_LATEST_PIPELINE](state) {
+ state.isLoadingPipeline = true;
+ },
+ [types.RECEIVE_LASTEST_PIPELINE_ERROR](state) {
+ state.isLoadingPipeline = false;
+ },
+ [types.RECEIVE_LASTEST_PIPELINE_SUCCESS](state, pipeline) {
+ state.isLoadingPipeline = false;
+
+ if (pipeline) {
+ state.latestPipeline = {
+ id: pipeline.id,
+ status: pipeline.status,
+ };
+ }
+ },
+ [types.REQUEST_JOBS](state) {
+ state.isLoadingJobs = true;
+ },
+ [types.RECEIVE_JOBS_ERROR](state) {
+ state.isLoadingJobs = false;
+ },
+ [types.RECEIVE_JOBS_SUCCESS](state, jobs) {
+ state.isLoadingJobs = false;
+
+ state.stages = jobs.reduce((acc, job) => {
+ let stage = acc.find(s => s.title === job.stage);
+
+ if (!stage) {
+ stage = {
+ title: job.stage,
+ jobs: [],
+ };
+
+ acc.push(stage);
+ }
+
+ stage.jobs = stage.jobs.concat({
+ id: job.id,
+ name: job.name,
+ status: job.status,
+ stage: job.stage,
+ duration: job.duration,
+ });
+
+ return acc;
+ }, state.stages);
+ },
+};
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/state.js b/app/assets/javascripts/ide/stores/modules/pipelines/state.js
new file mode 100644
index 00000000000..6f22542aaea
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/state.js
@@ -0,0 +1,6 @@
+export default () => ({
+ isLoadingPipeline: false,
+ isLoadingJobs: false,
+ latestPipeline: null,
+ stages: [],
+});
diff --git a/spec/javascripts/helpers/vuex_action_helper.js b/spec/javascripts/helpers/vuex_action_helper.js
index 83f29d1b0c2..d6ab0aeeed7 100644
--- a/spec/javascripts/helpers/vuex_action_helper.js
+++ b/spec/javascripts/helpers/vuex_action_helper.js
@@ -55,7 +55,7 @@ export default (action, payload, state, expectedMutations, expectedActions, done
};
// call the action with mocked store and arguments
- action({ commit, state, dispatch }, payload);
+ action({ commit, state, dispatch, rootState: state }, payload);
// check if no mutations should have been dispatched
if (expectedMutations.length === 0) {
diff --git a/spec/javascripts/ide/mock_data.js b/spec/javascripts/ide/mock_data.js
index c059862b9d1..7e641c7984b 100644
--- a/spec/javascripts/ide/mock_data.js
+++ b/spec/javascripts/ide/mock_data.js
@@ -1,4 +1,3 @@
-// eslint-disable-next-line import/prefer-default-export
export const projectData = {
id: 1,
name: 'abcproject',
@@ -14,3 +13,49 @@ export const projectData = {
mergeRequests: {},
merge_requests_enabled: true,
};
+
+export const pipelines = [
+ {
+ id: 1,
+ ref: 'master',
+ sha: '123',
+ status: 'failed',
+ },
+ {
+ id: 2,
+ ref: 'master',
+ sha: '213',
+ status: 'success',
+ },
+];
+
+export const jobs = [
+ {
+ id: 1,
+ name: 'test',
+ status: 'failed',
+ stage: 'test',
+ duration: 1,
+ },
+ {
+ id: 2,
+ name: 'test 2',
+ status: 'failed',
+ stage: 'test',
+ duration: 1,
+ },
+ {
+ id: 3,
+ name: 'test 3',
+ status: 'failed',
+ stage: 'test',
+ duration: 1,
+ },
+ {
+ id: 4,
+ name: 'test 3',
+ status: 'failed',
+ stage: 'build',
+ duration: 1,
+ },
+];
diff --git a/spec/javascripts/ide/stores/modules/pipelines/actions_spec.js b/spec/javascripts/ide/stores/modules/pipelines/actions_spec.js
new file mode 100644
index 00000000000..85fbcf8084b
--- /dev/null
+++ b/spec/javascripts/ide/stores/modules/pipelines/actions_spec.js
@@ -0,0 +1,289 @@
+import MockAdapter from 'axios-mock-adapter';
+import axios from '~/lib/utils/axios_utils';
+import actions, {
+ requestLatestPipeline,
+ receiveLatestPipelineError,
+ receiveLatestPipelineSuccess,
+ fetchLatestPipeline,
+ requestJobs,
+ receiveJobsError,
+ receiveJobsSuccess,
+ fetchJobs,
+} from '~/ide/stores/modules/pipelines/actions';
+import state from '~/ide/stores/modules/pipelines/state';
+import * as types from '~/ide/stores/modules/pipelines/mutation_types';
+import testAction from '../../../../helpers/vuex_action_helper';
+import { pipelines, jobs } from '../../../mock_data';
+
+describe('IDE pipelines actions', () => {
+ let mockedState;
+ let mock;
+
+ beforeEach(() => {
+ mockedState = state();
+ mock = new MockAdapter(axios);
+
+ gon.api_version = 'v4';
+ mockedState.currentProjectId = 'test/project';
+ });
+
+ afterEach(() => {
+ mock.restore();
+ });
+
+ describe('requestLatestPipeline', () => {
+ it('commits request', done => {
+ testAction(
+ requestLatestPipeline,
+ null,
+ mockedState,
+ [{ type: types.REQUEST_LATEST_PIPELINE }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('receiveLatestPipelineError', () => {
+ it('commits error', done => {
+ testAction(
+ receiveLatestPipelineError,
+ null,
+ mockedState,
+ [{ type: types.RECEIVE_LASTEST_PIPELINE_ERROR }],
+ [],
+ done,
+ );
+ });
+
+ it('creates flash message', () => {
+ const flashSpy = spyOnDependency(actions, 'flash');
+
+ receiveLatestPipelineError({ commit() {} });
+
+ expect(flashSpy).toHaveBeenCalled();
+ });
+ });
+
+ describe('receiveLatestPipelineSuccess', () => {
+ it('commits pipeline', done => {
+ testAction(
+ receiveLatestPipelineSuccess,
+ pipelines[0],
+ mockedState,
+ [{ type: types.RECEIVE_LASTEST_PIPELINE_SUCCESS, payload: pipelines[0] }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('fetchLatestPipeline', () => {
+ describe('success', () => {
+ beforeEach(() => {
+ mock.onGet(/\/api\/v4\/projects\/(.*)\/pipelines(.*)/).replyOnce(200, pipelines);
+ });
+
+ it('dispatches request', done => {
+ testAction(
+ fetchLatestPipeline,
+ '123',
+ mockedState,
+ [],
+ [{ type: 'requestLatestPipeline' }, { type: 'receiveLatestPipelineSuccess' }],
+ done,
+ );
+ });
+
+ it('dispatches success with latest pipeline', done => {
+ testAction(
+ fetchLatestPipeline,
+ '123',
+ mockedState,
+ [],
+ [
+ { type: 'requestLatestPipeline' },
+ { type: 'receiveLatestPipelineSuccess', payload: pipelines[0] },
+ ],
+ done,
+ );
+ });
+
+ it('calls axios with correct params', () => {
+ const apiSpy = spyOn(axios, 'get').and.callThrough();
+
+ fetchLatestPipeline({ dispatch() {}, rootState: state }, '123');
+
+ expect(apiSpy).toHaveBeenCalledWith(jasmine.anything(), {
+ params: {
+ sha: '123',
+ per_page: '1',
+ },
+ });
+ });
+ });
+
+ describe('error', () => {
+ beforeEach(() => {
+ mock.onGet(/\/api\/v4\/projects\/(.*)\/pipelines(.*)/).replyOnce(500);
+ });
+
+ it('dispatches error', done => {
+ testAction(
+ fetchLatestPipeline,
+ '123',
+ mockedState,
+ [],
+ [{ type: 'requestLatestPipeline' }, { type: 'receiveLatestPipelineError' }],
+ done,
+ );
+ });
+ });
+ });
+
+ describe('requestJobs', () => {
+ it('commits request', done => {
+ testAction(requestJobs, null, mockedState, [{ type: types.REQUEST_JOBS }], [], done);
+ });
+ });
+
+ describe('receiveJobsError', () => {
+ it('commits error', done => {
+ testAction(
+ receiveJobsError,
+ null,
+ mockedState,
+ [{ type: types.RECEIVE_JOBS_ERROR }],
+ [],
+ done,
+ );
+ });
+
+ it('creates flash message', () => {
+ const flashSpy = spyOnDependency(actions, 'flash');
+
+ receiveJobsError({ commit() {} });
+
+ expect(flashSpy).toHaveBeenCalled();
+ });
+ });
+
+ describe('receiveJobsSuccess', () => {
+ it('commits jobs', done => {
+ testAction(
+ receiveJobsSuccess,
+ jobs,
+ mockedState,
+ [{ type: types.RECEIVE_JOBS_SUCCESS, payload: jobs }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('fetchJobs', () => {
+ let page = '';
+
+ beforeEach(() => {
+ mockedState.latestPipeline = pipelines[0];
+ });
+
+ describe('success', () => {
+ beforeEach(() => {
+ mock.onGet(/\/api\/v4\/projects\/(.*)\/pipelines\/(.*)\/jobs/).replyOnce(() => [
+ 200,
+ jobs,
+ {
+ 'x-next-page': page,
+ },
+ ]);
+ });
+
+ it('dispatches request', done => {
+ testAction(
+ fetchJobs,
+ null,
+ mockedState,
+ [],
+ [{ type: 'requestJobs' }, { type: 'receiveJobsSuccess' }],
+ done,
+ );
+ });
+
+ it('dispatches success with latest pipeline', done => {
+ testAction(
+ fetchJobs,
+ null,
+ mockedState,
+ [],
+ [{ type: 'requestJobs' }, { type: 'receiveJobsSuccess', payload: jobs }],
+ done,
+ );
+ });
+
+ it('dispatches twice for both pages', done => {
+ page = '2';
+
+ testAction(
+ fetchJobs,
+ null,
+ mockedState,
+ [],
+ [
+ { type: 'requestJobs' },
+ { type: 'receiveJobsSuccess', payload: jobs },
+ { type: 'fetchJobs', payload: '2' },
+ { type: 'requestJobs' },
+ { type: 'receiveJobsSuccess', payload: jobs },
+ ],
+ done,
+ );
+ });
+
+ it('calls axios with correct URL', () => {
+ const apiSpy = spyOn(axios, 'get').and.callThrough();
+
+ fetchJobs({ dispatch() {}, state: mockedState, rootState: mockedState });
+
+ expect(apiSpy).toHaveBeenCalledWith('/api/v4/projects/test%2Fproject/pipelines/1/jobs', {
+ params: { page: '1' },
+ });
+ });
+
+ it('calls axios with page next page', () => {
+ const apiSpy = spyOn(axios, 'get').and.callThrough();
+
+ fetchJobs({ dispatch() {}, state: mockedState, rootState: mockedState });
+
+ expect(apiSpy).toHaveBeenCalledWith('/api/v4/projects/test%2Fproject/pipelines/1/jobs', {
+ params: { page: '1' },
+ });
+
+ page = '2';
+
+ fetchJobs({ dispatch() {}, state: mockedState, rootState: mockedState }, page);
+
+ expect(apiSpy).toHaveBeenCalledWith('/api/v4/projects/test%2Fproject/pipelines/1/jobs', {
+ params: { page: '2' },
+ });
+ });
+ });
+
+ describe('error', () => {
+ beforeEach(() => {
+ mock.onGet(/\/api\/v4\/projects\/(.*)\/pipelines(.*)/).replyOnce(500);
+ });
+
+ it('dispatches error', done => {
+ testAction(
+ fetchJobs,
+ null,
+ mockedState,
+ [],
+ [{ type: 'requestJobs' }, { type: 'receiveJobsError' }],
+ done,
+ );
+ });
+ });
+ });
+});
diff --git a/spec/javascripts/ide/stores/modules/pipelines/getters_spec.js b/spec/javascripts/ide/stores/modules/pipelines/getters_spec.js
new file mode 100644
index 00000000000..b2a7e8a9025
--- /dev/null
+++ b/spec/javascripts/ide/stores/modules/pipelines/getters_spec.js
@@ -0,0 +1,71 @@
+import * as getters from '~/ide/stores/modules/pipelines/getters';
+import state from '~/ide/stores/modules/pipelines/state';
+
+describe('IDE pipeline getters', () => {
+ let mockedState;
+
+ beforeEach(() => {
+ mockedState = state();
+ });
+
+ describe('hasLatestPipeline', () => {
+ it('returns false when loading is true', () => {
+ mockedState.isLoadingPipeline = true;
+
+ expect(getters.hasLatestPipeline(mockedState)).toBe(false);
+ });
+
+ it('returns false when pipelines is null', () => {
+ mockedState.latestPipeline = null;
+
+ expect(getters.hasLatestPipeline(mockedState)).toBe(false);
+ });
+
+ it('returns false when loading is true & pipelines is null', () => {
+ mockedState.latestPipeline = null;
+ mockedState.isLoadingPipeline = true;
+
+ expect(getters.hasLatestPipeline(mockedState)).toBe(false);
+ });
+
+ it('returns true when loading is false & pipelines is an object', () => {
+ mockedState.latestPipeline = {
+ id: 1,
+ };
+ mockedState.isLoadingPipeline = false;
+
+ expect(getters.hasLatestPipeline(mockedState)).toBe(true);
+ });
+ });
+
+ describe('failedJobs', () => {
+ it('returns array of failed jobs', () => {
+ mockedState.stages = [
+ {
+ title: 'test',
+ jobs: [{ id: 1, status: 'failed' }, { id: 2, status: 'success' }],
+ },
+ {
+ title: 'build',
+ jobs: [{ id: 3, status: 'failed' }, { id: 4, status: 'failed' }],
+ },
+ ];
+
+ expect(getters.failedJobs(mockedState).length).toBe(3);
+ expect(getters.failedJobs(mockedState)).toEqual([
+ {
+ id: 1,
+ status: jasmine.anything(),
+ },
+ {
+ id: 3,
+ status: jasmine.anything(),
+ },
+ {
+ id: 4,
+ status: jasmine.anything(),
+ },
+ ]);
+ });
+ });
+});
diff --git a/spec/javascripts/ide/stores/modules/pipelines/mutations_spec.js b/spec/javascripts/ide/stores/modules/pipelines/mutations_spec.js
new file mode 100644
index 00000000000..8262e916243
--- /dev/null
+++ b/spec/javascripts/ide/stores/modules/pipelines/mutations_spec.js
@@ -0,0 +1,120 @@
+import mutations from '~/ide/stores/modules/pipelines/mutations';
+import state from '~/ide/stores/modules/pipelines/state';
+import * as types from '~/ide/stores/modules/pipelines/mutation_types';
+import { pipelines, jobs } from '../../../mock_data';
+
+describe('IDE pipelines mutations', () => {
+ let mockedState;
+
+ beforeEach(() => {
+ mockedState = state();
+ });
+
+ describe(types.REQUEST_LATEST_PIPELINE, () => {
+ it('sets loading to true', () => {
+ mutations[types.REQUEST_LATEST_PIPELINE](mockedState);
+
+ expect(mockedState.isLoadingPipeline).toBe(true);
+ });
+ });
+
+ describe(types.RECEIVE_LASTEST_PIPELINE_ERROR, () => {
+ it('sets loading to false', () => {
+ mutations[types.RECEIVE_LASTEST_PIPELINE_ERROR](mockedState);
+
+ expect(mockedState.isLoadingPipeline).toBe(false);
+ });
+ });
+
+ describe(types.RECEIVE_LASTEST_PIPELINE_SUCCESS, () => {
+ it('sets loading to false on success', () => {
+ mutations[types.RECEIVE_LASTEST_PIPELINE_SUCCESS](mockedState, pipelines[0]);
+
+ expect(mockedState.isLoadingPipeline).toBe(false);
+ });
+
+ it('sets latestPipeline', () => {
+ mutations[types.RECEIVE_LASTEST_PIPELINE_SUCCESS](mockedState, pipelines[0]);
+
+ expect(mockedState.latestPipeline).toEqual({
+ id: pipelines[0].id,
+ status: pipelines[0].status,
+ });
+ });
+
+ it('does not set latest pipeline if pipeline is null', () => {
+ mutations[types.RECEIVE_LASTEST_PIPELINE_SUCCESS](mockedState, null);
+
+ expect(mockedState.latestPipeline).toEqual(null);
+ });
+ });
+
+ describe(types.REQUEST_JOBS, () => {
+ it('sets jobs loading to true', () => {
+ mutations[types.REQUEST_JOBS](mockedState);
+
+ expect(mockedState.isLoadingJobs).toBe(true);
+ });
+ });
+
+ describe(types.RECEIVE_JOBS_ERROR, () => {
+ it('sets jobs loading to false', () => {
+ mutations[types.RECEIVE_JOBS_ERROR](mockedState);
+
+ expect(mockedState.isLoadingJobs).toBe(false);
+ });
+ });
+
+ describe(types.RECEIVE_JOBS_SUCCESS, () => {
+ it('sets jobs loading to false on success', () => {
+ mutations[types.RECEIVE_JOBS_SUCCESS](mockedState, jobs);
+
+ expect(mockedState.isLoadingJobs).toBe(false);
+ });
+
+ it('sets stages', () => {
+ mutations[types.RECEIVE_JOBS_SUCCESS](mockedState, jobs);
+
+ expect(mockedState.stages.length).toBe(2);
+ expect(mockedState.stages).toEqual([
+ {
+ title: 'test',
+ jobs: jasmine.anything(),
+ },
+ {
+ title: 'build',
+ jobs: jasmine.anything(),
+ },
+ ]);
+ });
+
+ it('sets jobs in stages', () => {
+ mutations[types.RECEIVE_JOBS_SUCCESS](mockedState, jobs);
+
+ expect(mockedState.stages[0].jobs.length).toBe(3);
+ expect(mockedState.stages[1].jobs.length).toBe(1);
+ expect(mockedState.stages).toEqual([
+ {
+ title: jasmine.anything(),
+ jobs: jobs.filter(job => job.stage === 'test').map(job => ({
+ id: job.id,
+ name: job.name,
+ status: job.status,
+ stage: job.stage,
+ duration: job.duration,
+ })),
+ },
+ {
+ title: jasmine.anything(),
+ jobs: jobs.filter(job => job.stage === 'build').map(job => ({
+ id: job.id,
+ name: job.name,
+ status: job.status,
+ stage: job.stage,
+ duration: job.duration,
+ })),
+ },
+ ]);
+ });
+ });
+});