summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Hughes <me@iamphill.com>2018-05-14 16:30:52 +0100
committerPhil Hughes <me@iamphill.com>2018-05-22 11:11:36 +0100
commitba90742631a5e1a0d1edc546d5d49b59210642bf (patch)
tree67b8e75ae82003cf502ba7303bf6d586224949cb
parent50985f54baf9a4d7e840e22ce8914f0bc919f5d8 (diff)
downloadgitlab-ce-ide-jobs-list.tar.gz
group jobs into stageside-jobs-list
-rw-r--r--app/assets/javascripts/api.js4
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/actions.js14
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/getters.js7
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/mutations.js30
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/state.js2
-rw-r--r--spec/javascripts/ide/mock_data.js7
-rw-r--r--spec/javascripts/ide/stores/modules/pipelines/actions_spec.js51
-rw-r--r--spec/javascripts/ide/stores/modules/pipelines/getters_spec.js31
-rw-r--r--spec/javascripts/ide/stores/modules/pipelines/mutations_spec.js52
9 files changed, 171 insertions, 27 deletions
diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js
index e16d520024b..eb919241318 100644
--- a/app/assets/javascripts/api.js
+++ b/app/assets/javascripts/api.js
@@ -230,12 +230,12 @@ const Api = {
return axios.get(url, { params });
},
- pipelineJobs(projectPath, pipelineId) {
+ pipelineJobs(projectPath, pipelineId, params = {}) {
const url = Api.buildUrl(this.pipelineJobsPath)
.replace(':id', encodeURIComponent(projectPath))
.replace(':pipeline_id', pipelineId);
- return axios.get(url);
+ return axios.get(url, { params });
},
buildUrl(url) {
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/actions.js b/app/assets/javascripts/ide/stores/modules/pipelines/actions.js
index 146a0e72354..07f7b201f2e 100644
--- a/app/assets/javascripts/ide/stores/modules/pipelines/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/actions.js
@@ -28,12 +28,20 @@ export const receiveJobsError = ({ commit }) => {
};
export const receiveJobsSuccess = ({ commit }, data) => commit(types.RECEIVE_JOBS_SUCCESS, data);
-export const fetchJobs = ({ dispatch, state, rootState }) => {
+export const fetchJobs = ({ dispatch, state, rootState }, page = '1') => {
dispatch('requestJobs');
- Api.pipelineJobs(rootState.currentProjectId, state.latestPipeline.id)
- .then(({ data }) => {
+ 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'));
};
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/getters.js b/app/assets/javascripts/ide/stores/modules/pipelines/getters.js
index 8344bb1b34e..d6c91f5b64d 100644
--- a/app/assets/javascripts/ide/stores/modules/pipelines/getters.js
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/getters.js
@@ -1,2 +1,7 @@
-// eslint-disable-next-line import/prefer-default-export
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/mutations.js b/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js
index 382775de10a..2b16e57b386 100644
--- a/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js
@@ -26,12 +26,28 @@ export default {
},
[types.RECEIVE_JOBS_SUCCESS](state, jobs) {
state.isLoadingJobs = false;
- state.jobs = jobs.map(job => ({
- id: job.id,
- name: job.name,
- status: job.status,
- stage: job.stage,
- duration: job.duration,
- }));
+
+ 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
index deb376f07d6..6f22542aaea 100644
--- a/app/assets/javascripts/ide/stores/modules/pipelines/state.js
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/state.js
@@ -2,5 +2,5 @@ export default () => ({
isLoadingPipeline: false,
isLoadingJobs: false,
latestPipeline: null,
- jobs: [],
+ stages: [],
});
diff --git a/spec/javascripts/ide/mock_data.js b/spec/javascripts/ide/mock_data.js
index 4a565ec57ce..7e641c7984b 100644
--- a/spec/javascripts/ide/mock_data.js
+++ b/spec/javascripts/ide/mock_data.js
@@ -51,4 +51,11 @@ export const jobs = [
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
index b7f04642dcd..85fbcf8084b 100644
--- a/spec/javascripts/ide/stores/modules/pipelines/actions_spec.js
+++ b/spec/javascripts/ide/stores/modules/pipelines/actions_spec.js
@@ -182,13 +182,21 @@ describe('IDE pipelines actions', () => {
});
describe('fetchJobs', () => {
+ let page = '';
+
beforeEach(() => {
mockedState.latestPipeline = pipelines[0];
});
describe('success', () => {
beforeEach(() => {
- mock.onGet(/\/api\/v4\/projects\/(.*)\/pipelines\/(.*)\/jobs/).replyOnce(200, jobs);
+ mock.onGet(/\/api\/v4\/projects\/(.*)\/pipelines\/(.*)\/jobs/).replyOnce(() => [
+ 200,
+ jobs,
+ {
+ 'x-next-page': page,
+ },
+ ]);
});
it('dispatches request', done => {
@@ -213,12 +221,51 @@ describe('IDE pipelines actions', () => {
);
});
+ 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');
+ 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' },
+ });
});
});
diff --git a/spec/javascripts/ide/stores/modules/pipelines/getters_spec.js b/spec/javascripts/ide/stores/modules/pipelines/getters_spec.js
index 4514896b5ea..b2a7e8a9025 100644
--- a/spec/javascripts/ide/stores/modules/pipelines/getters_spec.js
+++ b/spec/javascripts/ide/stores/modules/pipelines/getters_spec.js
@@ -37,4 +37,35 @@ describe('IDE pipeline getters', () => {
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
index 59e218ef0a6..8262e916243 100644
--- a/spec/javascripts/ide/stores/modules/pipelines/mutations_spec.js
+++ b/spec/javascripts/ide/stores/modules/pipelines/mutations_spec.js
@@ -72,19 +72,49 @@ describe('IDE pipelines mutations', () => {
expect(mockedState.isLoadingJobs).toBe(false);
});
- it('sets jobs', () => {
+ it('sets stages', () => {
mutations[types.RECEIVE_JOBS_SUCCESS](mockedState, jobs);
- expect(mockedState.jobs.length).toBe(3);
- expect(mockedState.jobs).toEqual(
- jobs.map(job => ({
- id: job.id,
- name: job.name,
- status: job.status,
- stage: job.stage,
- duration: job.duration,
- })),
- );
+ 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,
+ })),
+ },
+ ]);
});
});
});