Commit 2a12a3f7 authored by Filipa Lacerda's avatar Filipa Lacerda Committed by Kamil Trzciński

Creates mixin for repeated code between ce/ee

Exports the repeated code between ce and ee
for the graph component into a reusable mixin
parent 8ef5ee8e
......@@ -2,8 +2,8 @@ import Vue from 'vue';
import Flash from '~/flash';
import Translate from '~/vue_shared/translate';
import { __ } from '~/locale';
import PipelinesMediator from './pipeline_details_mediator';
import pipelineGraph from 'ee/pipelines/components/graph/graph_component.vue';
import PipelinesMediator from './pipeline_details_mediator';
import pipelineHeader from './components/header_component.vue';
import eventHub from './event_hub';
import GraphEEMixin from 'ee/pipelines/mixins/graph_pipeline_bundle_mixin'; // eslint-disable-line import/order
......@@ -29,15 +29,6 @@ export default () => {
mediator,
};
},
methods: {
requestRefreshPipelineGraph() {
// When an action is clicked
// (wether in the dropdown or in the main nodes, we refresh the big graph)
this.mediator
.refreshPipeline()
.catch(() => Flash(__('An error occurred while making the request.')));
},
},
render(createElement) {
return createElement('pipeline-graph', {
props: {
......@@ -47,14 +38,10 @@ export default () => {
},
on: {
refreshPipelineGraph: this.requestRefreshPipelineGraph,
// EE-only start
// refreshTriggeredPipelineGraph: this.mediator.refreshTriggeredByPipelineGraph,
// refreshTriggeredByPipelineGraph: this.mediator.refreshTriggeredByPipelineGraph,
onClickTriggeredBy: (parentPipeline, pipeline) =>
this.clickTriggeredByPipeline(parentPipeline, pipeline),
onClickTriggered: (parentPipeline, pipeline) =>
this.clickTriggeredPipeline(parentPipeline, pipeline),
// EE-only end
},
});
},
......
<script>
import _ from 'underscore';
import { GlLoadingIcon } from '@gitlab/ui';
import LinkedPipelinesColumn from 'ee/pipelines/components/graph/linked_pipelines_column.vue';
import EEGraphMixin from 'ee/pipelines/mixins/graph_component_mixin';
import StageColumnComponent from '~/pipelines/components/graph/stage_column_component.vue';
import GraphEEMixin from 'ee/pipelines/mixins/graph_pipeline_bundle_mixin'; // eslint-disable-line import/order
import GraphMixin from '~/pipelines/mixins/graph_component_mixin';
import LinkedPipelinesColumn from 'ee/pipelines/components/graph/linked_pipelines_column.vue';
import GraphEEMixin from 'ee/pipelines/mixins/graph_pipeline_bundle_mixin';
export default {
name: 'PipelineGraph',
components: {
LinkedPipelinesColumn,
StageColumnComponent,
GlLoadingIcon,
LinkedPipelinesColumn,
},
mixins: [EEGraphMixin, GraphEEMixin],
mixins: [GraphMixin, GraphEEMixin],
props: {
isLoading: {
type: Boolean,
......@@ -37,35 +37,57 @@ export default {
default: 'main',
},
},
upstream: 'upstream',
downstream: 'downstream',
data() {
return {
triggeredTopIndex: 1,
};
},
computed: {
graph() {
return this.pipeline.details && this.pipeline.details.stages;
hasTriggeredBy() {
return (
this.type !== this.$options.downstream &&
this.pipeline.triggered_by &&
this.pipeline.triggered_by != null
);
},
triggeredByPipelines() {
return this.pipeline.triggered_by;
},
methods: {
// todo filipa: move this into a ce mixin
capitalizeStageName(name) {
const escapedName = _.escape(name);
return escapedName.charAt(0).toUpperCase() + escapedName.slice(1);
hasTriggered() {
return (
this.type !== this.$options.upstream &&
this.pipeline.triggered &&
this.pipeline.triggered.length > 0
);
},
isFirstColumn(index) {
return index === 0;
triggeredPipelines() {
return this.pipeline.triggered;
},
expandedTriggeredBy() {
return (
this.pipeline.triggered_by &&
_.isArray(this.pipeline.triggered_by) &&
this.pipeline.triggered_by.find(el => el.isExpanded)
);
},
expandedTriggered() {
return this.pipeline.triggered && this.pipeline.triggered.find(el => el.isExpanded);
},
stageConnectorClass(index, stage) {
let className;
// If it's the first stage column and only has one job
if (index === 0 && stage.groups.length === 1) {
className = 'no-margin';
} else if (index > 0) {
// If it is not the first column
className = 'left-margin';
}
return className;
/**
* Calculates the margin top of the clicked downstream pipeline by
* adding the height of each linked pipeline and the margin
*/
marginTop() {
return `${this.triggeredTopIndex * 52}px`;
},
refreshPipelineGraph() {
this.$emit('refreshPipelineGraph');
},
methods: {
handleClickedDownstream(pipeline, clickedIndex) {
this.triggeredTopIndex = clickedIndex;
this.$emit('onClickTriggered', this.pipeline, pipeline);
},
hasOnlyOneJob(stage) {
return stage.groups.length === 1;
......@@ -79,19 +101,21 @@ export default {
class="pipeline-visualization pipeline-graph"
:class="{ 'pipeline-tab-content': !isLinkedPipeline }"
>
<div class="text-center" v-if="isLoading"><gl-loading-icon :size="3" /></div>
<div v-if="isLoading" class="m-auto"><gl-loading-icon :size="3" /></div>
<pipeline-graph
v-if="type !== $options.downstream && expandedTriggeredBy"
type="upstream"
class="d-inline-block upstream-pipeline"
v-if="expandedTriggeredBy && type !== 'downstream'"
:class="`js-upstream-pipeline-${expandedTriggeredBy.id}`"
:is-loading="false"
:pipeline="expandedTriggeredBy"
:is-linked-pipeline="true"
:mediator="mediator"
@onClickTriggeredBy="
(parentPipeline, pipeline) => this.clickTriggeredByPipeline(parentPipeline, pipeline)
(parentPipeline, pipeline) => clickTriggeredByPipeline(parentPipeline, pipeline)
"
@refreshPipelineGraph="requestRefreshPipelineGraph"
/>
<linked-pipelines-column
......@@ -99,7 +123,9 @@ export default {
:linked-pipelines="triggeredByPipelines"
:column-title="__('Upstream')"
graph-position="left"
@linkedPipelineClick="pipeline => $emit('onClickTriggeredBy', this.pipeline, pipeline)"
@linkedPipelineClick="
linkedPipeline => $emit('onClickTriggeredBy', pipeline, linkedPipeline)
"
/>
<ul
......@@ -135,17 +161,19 @@ export default {
/>
<pipeline-graph
v-if="type !== $options.upstream && expandedTriggered"
type="downstream"
class="d-inline-block"
v-if="expandedTriggered && type !== 'upstream'"
:class="`js-downstream-pipeline-${expandedTriggered.id}`"
:is-loading="false"
:pipeline="expandedTriggered"
:is-linked-pipeline="true"
:style="{ 'margin-top': marginTop }"
:mediator="mediator"
@onClickTriggered="
(parentPipeline, pipeline) => this.clickTriggeredPipeline(parentPipeline, pipeline)
(parentPipeline, pipeline) => clickTriggeredPipeline(parentPipeline, pipeline)
"
:mediator="mediator"
@refreshPipelineGraph="requestRefreshPipelineGraph"
/>
</div>
</div>
......
export default {
triggeredPipelines: 'triggeredPipelines',
triggeredByPipelines: 'triggeredByPipelines',
triggeredBy: 'triggered_by',
triggered: 'triggered',
};
// todo filipa: move this to the ee graph component
import _ from 'underscore';
export default {
data() {
return {
triggeredTopIndex: 1,
};
},
computed: {
hasTriggeredBy() {
return (
this.type !== 'downstream' &&
this.pipeline.triggered_by &&
this.pipeline.triggered_by != null
);
},
triggeredByPipelines() {
return this.pipeline.triggered_by;
},
hasTriggered() {
return (
this.type !== 'upstream' && this.pipeline.triggered && this.pipeline.triggered.length > 0
);
},
triggeredPipelines() {
return this.pipeline.triggered;
},
expandedTriggeredBy() {
return (
this.pipeline.triggered_by &&
_.isArray(this.pipeline.triggered_by) &&
this.pipeline.triggered_by.find(el => el.isExpanded)
);
},
expandedTriggered() {
return this.pipeline.triggered && this.pipeline.triggered.find(el => el.isExpanded);
},
/**
* Calculates the margin top of the clicked downstream pipeline by
* adding the height of each linked pipeline and the margin
*/
marginTop() {
return `${this.triggeredTopIndex * 52}px`;
},
},
methods: {
// TODO FILIPA: REMOVE THIS
refreshTriggeredPipelineGraph() {
this.$emit('refreshTriggeredPipelineGraph');
},
refreshTriggeredByPipelineGraph() {
this.$emit('refreshTriggeredByPipelineGraph');
},
handleClickedDownstream(pipeline, clickedIndex) {
//filipa: figure out the clickIndex thing
this.triggeredTopIndex = clickedIndex;
this.$emit('onClickTriggered', this.pipeline, pipeline);
},
},
};
import flash from '~/flash';
import { __ } from '~/locale';
export default {
methods: {
/**
......@@ -34,5 +37,12 @@ export default {
'closeTriggeredPipeline',
);
},
requestRefreshPipelineGraph() {
// When an action is clicked
// (wether in the dropdown or in the main nodes, we refresh the big graph)
this.mediator
.refreshPipeline()
.catch(() => flash(__('An error occurred while making the request.')));
},
},
};
import Vue from 'vue';
import _ from 'underscore';
import CePipelineStore from '~/pipelines/stores/pipeline_store';
import data from '../mock.json';
import Vue from 'vue';
/**
* Extends CE store with the logic to handle the upstream/downstream pipelines
*/
export default class PipelineStore extends CePipelineStore {
constructor() {
super();
}
/**
* For the triggered pipelines adds the `isExpanded` key
*
......@@ -20,7 +15,6 @@ export default class PipelineStore extends CePipelineStore {
* @param {Object} pipeline
*/
storePipeline(pipeline = {}) {
pipeline = Object.assign({}, data);
super.storePipeline(pipeline);
if (pipeline.triggered_by) {
......@@ -47,19 +41,15 @@ export default class PipelineStore extends CePipelineStore {
parseTriggeredByPipelines(pipeline) {
// keep old value in case it's opened because we're polling
Vue.set(pipeline, 'isExpanded', pipeline.isExpanded || false);
if (pipeline.triggered_by) {
if (!_.isArray(pipeline.triggered_by)) {
pipeline.triggered_by = [pipeline.triggered_by];
Object.assign(pipeline, { triggered_by: [pipeline.triggered_by] });
}
this.parseTriggeredByPipelines(pipeline.triggered_by[0]);
}
// if (pipeline.triggered && pipeline.triggered.length) {
// pipeline.triggered.forEach(el => this.parseTriggeredPipelines(el));
// }
}
parsePipeline(pipeline) {}
/**
* Recursively parses the triggered pipelines
* @param {Array} parentPipeline
......@@ -72,11 +62,6 @@ export default class PipelineStore extends CePipelineStore {
if (pipeline.triggered && pipeline.triggered.length > 0) {
pipeline.triggered.forEach(el => this.parseTriggeredPipelines(el));
}
// if (pipeline.triggered_by) {
// pipeline.triggered_by = [pipeline.triggered_by];
// this.parseTriggeredByPipelines(pipeline.triggered_by[0]);
// }
}
/**
......@@ -85,7 +70,7 @@ export default class PipelineStore extends CePipelineStore {
* @param {Object} pipeline
*/
resetTriggeredByPipeline(parentPipeline, pipeline) {
parentPipeline.triggered_by.forEach(el => this.closePipeline(el));
parentPipeline.triggered_by.forEach(el => PipelineStore.closePipeline(el));
if (pipeline.triggered_by && pipeline.triggered_by) {
this.resetTriggeredByPipeline(pipeline, pipeline.triggered_by);
......@@ -100,7 +85,7 @@ export default class PipelineStore extends CePipelineStore {
// first we need to reset all triggeredBy pipelines
this.resetTriggeredByPipeline(parentPipeline, pipeline);
this.openPipeline(pipeline);
PipelineStore.openPipeline(pipeline);
}
/**
......@@ -109,60 +94,61 @@ export default class PipelineStore extends CePipelineStore {
* @param {Object} pipeline
*/
closeTriggeredByPipeline(pipeline) {
this.closePipeline(pipeline);
PipelineStore.closePipeline(pipeline);
if (pipeline.triggered_by && pipeline.triggered_by.length) {
pipeline.triggered_by.forEach(triggeredBy => this.closeTriggeredByPipeline(triggeredBy));
}
}
/**
* On click, will close the given pipeline and all the nested triggered ones
* Recursively closes all triggered pipelines for the given one.
*
* @param {Object} pipeline
*/
closeTriggeredPipeline(pipeline) {
this.closePipeline(pipeline);
resetTriggeredPipelines(parentPipeline, pipeline) {
parentPipeline.triggered.forEach(el => this.closePipeline(el));
if (pipeline.triggered && pipeline.triggered.length) {
pipeline.triggered.forEach(triggered => this.closeTriggeredPipeline(triggered));
pipeline.triggered.forEach(el => this.resetTriggeredPipelines(pipeline, el));
}
}
/**
* Utility function, Closes the given pipeline
* Opens the clicked triggered pipeline and closes all other ones.
*
* @param {Object} pipeline
*/
closePipeline(pipeline) {
Vue.set(pipeline, 'isExpanded', false);
openTriggeredPipeline(parentPipeline, pipeline) {
this.resetTriggeredPipelines(parentPipeline, pipeline);
PipelineStore.openPipeline(pipeline);
}
/**
* Utility function, Opens the given pipeline
* On click, will close the given pipeline and all the nested triggered ones
* @param {Object} pipeline
*/
openPipeline(pipeline) {
Vue.set(pipeline, 'isExpanded', true);
closeTriggeredPipeline(pipeline) {
PipelineStore.closePipeline(pipeline);
if (pipeline.triggered && pipeline.triggered.length) {
pipeline.triggered.forEach(triggered => this.closeTriggeredPipeline(triggered));
}
}
/**
* Opens the clicked triggered pipeline and closes all other ones.
*
* Utility function, Closes the given pipeline
* @param {Object} pipeline
*/
openTriggeredPipeline(parentPipeline, pipeline) {
this.resetTriggeredPipelines(parentPipeline, pipeline);
this.openPipeline(pipeline);
static closePipeline(pipeline) {
Vue.set(pipeline, 'isExpanded', false);
}
/**
* Recursively closes all triggered pipelines for the given one.
*
* Utility function, Opens the given pipeline
* @param {Object} pipeline
*/
resetTriggeredPipelines(parentPipeline, pipeline) {
parentPipeline.triggered.forEach(el => this.closePipeline(el));
if (pipeline.triggered && pipeline.triggered.length) {
pipeline.triggered.forEach(el => this.resetTriggeredPipelines(pipeline, el));
}
static openPipeline(pipeline) {
Vue.set(pipeline, 'isExpanded', true);
}
}
---
title: Recursively expands upstream and downstream pipelines
merge_request:
author:
type: changed
import Vue from 'vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import PipelineStore from 'ee/pipelines/stores/pipeline_store';
import graphComponent from 'ee/pipelines/components/graph/graph_component.vue';
import pipelineJSON from 'spec/pipelines/graph/mock_data';
import linkedPipelineJSON from 'ee_spec/pipelines/graph/linked_pipelines_mock_data';
const graphJSON = Object.assign(pipelineJSON, {
triggered: linkedPipelineJSON.triggered,
triggered_by: linkedPipelineJSON.triggered_by,
});
import linkedPipelineJSON from 'ee_spec/pipelines/linked_pipelines_mock.json';
import PipelinesMediator from '~/pipelines/pipeline_details_mediator';
import graphJSON from 'spec/pipelines/graph/mock_data';
describe('graph component', () => {
const GraphComponent = Vue.extend(graphComponent);
const store = new PipelineStore();
store.storePipeline(linkedPipelineJSON);
const mediator = new PipelinesMediator({ endpoint: '' });
let component;
afterEach(() => {
......@@ -22,6 +23,7 @@ describe('graph component', () => {
component = mountComponent(GraphComponent, {
isLoading: true,
pipeline: {},
mediator,
});
expect(component.$el.querySelector('.loading-icon')).toBeDefined();
......@@ -32,9 +34,8 @@ describe('graph component', () => {
beforeEach(() => {
component = mountComponent(GraphComponent, {
isLoading: false,
pipeline: graphJSON,
triggeredByPipelines: [linkedPipelineJSON.triggered_by],
triggeredPipelines: linkedPipelineJSON.triggered,
pipeline: store.state.pipeline,
mediator,
});
});
......@@ -95,6 +96,14 @@ describe('graph component', () => {
});
describe('linked pipelines components', () => {
beforeEach(() => {
component = mountComponent(GraphComponent, {
isLoading: false,
pipeline: store.state.pipeline,
mediator,
});
});
it('should render an upstream pipelines column', () => {
expect(component.$el.querySelector('.linked-pipelines-column')).not.toBeNull();
expect(component.$el.innerHTML).toContain('Upstream');
......@@ -106,57 +115,63 @@ describe('graph component', () => {
});
describe('triggered by', () => {
describe('on click', () => {
it('should emit `onClickTriggeredBy` when triggered by linked pipeline is clicked', () => {
spyOn(component, '$emit');
component.$el.querySelector('#js-linked-pipeline-129').click();
component.$el.querySelector('#js-linked-pipeline-12').click();
expect(component.$emit).toHaveBeenCalledWith(
'onClickTriggeredBy',
linkedPipelineJSON.triggered_by,
component.pipeline,
component.pipeline.triggered_by[0],
);
});
});
describe('with expanded pipeline', () => {
it('should render expanded pipeline', () => {
// expand the pipeline
store.state.pipeline.triggered_by[0].isExpanded = true;
describe('with expanded triggered by pipeline', () => {
it('should render expanded upstream pipeline', () => {
component = mountComponent(GraphComponent, {
isLoading: false,
pipeline: graphJSON,
triggeredByPipelines: [
Object.assign({}, linkedPipelineJSON.triggered_by, { isExpanded: true }),
],
triggeredPipelines: linkedPipelineJSON.triggered,
triggeredBy: linkedPipelineJSON.triggered_by,
pipeline: store.state.pipeline,
mediator,
});
expect(component.$el.querySelector('.upstream-pipeline')).not.toBeNull();
expect(component.$el.querySelector('.js-upstream-pipeline-12')).not.toBeNull();
});
});
});
describe('triggered ', () => {
it('should emit `onClickTriggered` when triggered linked pipeline is clicked', () => {
describe('triggered', () => {
describe('on click', () => {
it('should emit `onClickTriggered`', () => {
spyOn(component, '$emit');
component.$el.querySelector('#js-linked-pipeline-132').click();
component.$el.querySelector('#js-linked-pipeline-34993051').click();
expect(component.$emit).toHaveBeenCalledWith(
'onClickTriggered',
linkedPipelineJSON.triggered[0],
component.pipeline,
component.pipeline.triggered[0],
);
});
});
describe('with expanded pipeline', () => {
it('should render expanded pipeline', () => {
// expand the pipeline
store.state.pipeline.triggered[0].isExpanded = true;
describe('with expanded triggered pipeline', () => {
it('should render expanded downstream pipeline', () => {
component = mountComponent(GraphComponent, {
isLoading: false,
pipeline: graphJSON,
triggeredByPipelines: [linkedPipelineJSON.triggered_by],
triggeredPipelines: [
Object.assign({}, linkedPipelineJSON.triggered[0], { isExpanded: true }),
],
triggered: linkedPipelineJSON.triggered[0],
pipeline: store.state.pipeline,
mediator,
});
expect(component.$el.querySelector('.downstream-pipeline')).not.toBeNull();
expect(component.$el.querySelector('.js-downstream-pipeline-34993051')).not.toBeNull();
});
});
});
......@@ -165,10 +180,11 @@ describe('graph component', () => {
describe('when linked pipelines are not present', () => {
beforeEach(() => {
const pipeline = Object.assign(graphJSON, { triggered: null, triggered_by: null });
const pipeline = Object.assign(linkedPipelineJSON, { triggered: null, triggered_by: null });
component = mountComponent(GraphComponent, {
isLoading: false,
pipeline,
mediator,
});
});
......@@ -200,6 +216,7 @@ describe('graph component', () => {
component = mountComponent(GraphComponent, {
isLoading: false,
pipeline: graphJSON,
mediator,
});
expect(
......
......@@ -15,10 +15,7 @@ describe('Linked pipeline', () => {
describe('rendered output', () => {
const props = {
pipelineId: mockPipeline.id,
pipelinePath: mockPipeline.path,
pipelineStatus: mockPipeline.details.status,
projectName: mockPipeline.project.name,
pipeline: mockPipeline,
};
beforeEach(() => {
......@@ -36,7 +33,7 @@ describe('Linked pipeline', () => {
});
it('should render the project name', () => {
expect(vm.$el.innerText).toContain(props.projectName);
expect(vm.$el.innerText).toContain(props.pipeline.project.name);
});
it('should render an svg within the status container', () => {
......@@ -55,7 +52,7 @@ describe('Linked pipeline', () => {
});
it('should render the pipeline id', () => {
expect(vm.$el.innerText).toContain(`#${props.pipelineId}`);
expect(vm.$el.innerText).toContain(`#${props.pipeline.id}`);
});
it('should correctly compute the tooltip text', () => {
......@@ -74,11 +71,7 @@ describe('Linked pipeline', () => {
describe('on click', () => {
const props = {
pipelineId: mockPipeline.id,
pipelinePath: mockPipeline.path,
pipelineStatus: mockPipeline.details.status,
projectName: mockPipeline.project.name,
isLoading: false,
pipeline: mockPipeline,
};
beforeEach(() => {
......@@ -96,10 +89,10 @@ describe('Linked pipeline', () => {
spyOn(vm.$root, '$emit');
vm.$el.querySelector('button').click();
expect(vm.$root.$emit).toHaveBeenCalledWith(
expect(vm.$root.$emit.calls.argsFor(0)).toEqual([
'bv::hide::tooltip',
`js-linked-pipeline-${props.pipelineId}`,
);
'js-linked-pipeline-132',
]);
});
});
});
......@@ -607,7 +607,7 @@
"action": {
"icon": "retry",
"title": "Retry",
"path": "/gitlab-com/gitlab-docs/-/jobs/114984694/retry",
"path": "/h5bp/html5-boilerplate/-/jobs/528/retry",
"method": "post",
"button_title": "Retry this job"
}
......@@ -641,7 +641,7 @@
"action": {
"icon": "retry",
"title": "Retry",
"path": "/gitlab-com/gitlab-docs/-/jobs/114984694/retry",
"path": "/h5bp/html5-boilerplate/-/jobs/528/retry",
"method": "post",
"button_title": "Retry this job"
}
......@@ -810,7 +810,7 @@
},
"project": {
"id": 1794617,
"name": "Filipa Rocks",
"name": "Test",
"full_path": "/gitlab-com/gitlab-docs",
"full_name": "GitLab.com / GitLab Docs"
},
......@@ -1557,7 +1557,7 @@
"action": {
"icon": "retry",
"title": "Retry",
"path": "/gitlab-com/gitlab-docs/-/jobs/114984694/retry",
"path": "/h5bp/html5-boilerplate/-/jobs/528/retry",
"method": "post",
"button_title": "Retry this job"
}
......@@ -1591,7 +1591,7 @@
"action": {
"icon": "retry",
"title": "Retry",
"path": "/gitlab-com/gitlab-docs/-/jobs/114984694/retry",
"path": "/h5bp/html5-boilerplate/-/jobs/528/retry",
"method": "post",
"button_title": "Retry this job"
}
......
import PipelineStore from 'ee/pipelines/stores/pipeline_store';
import pipelineWithTriggered from './pipeline_with_triggered.json';
import pipelineWithTriggeredBy from './pipeline_with_triggered_by.json';
import pipelineWithBoth from './pipeline_with_triggered_triggered_by.json';
import pipeline from './pipeline.json';
import LinkedPipelines from '../linked_pipelines_mock.json';
describe('EE Pipeline store', () => {
let store;
let data;
beforeEach(() => {
store = new PipelineStore();
data = Object.assign({}, LinkedPipelines);
});
describe('storePipeline', () => {
describe('triggeredPipelines ', () => {
describe('with triggered pipelines', () => {
it('saves parsed pipelines', () => {
store.storePipeline(pipelineWithTriggered);
expect(store.triggeredPipelines.length).toEqual(pipelineWithTriggered.triggered.length);
expect(store.triggeredPipelines[0]).toEqual(
Object.assign({}, pipelineWithTriggered.triggered[0], {
isLoading: false,
isCollpased: true,
}),
);
});
beforeAll(() => {
store.storePipeline(data);
});
describe('without triggered pipelines', () => {
it('triggeredPipelines should be an empty array', () => {
store.storePipeline({ triggered: [] });
describe('triggered_by', () => {
it('sets triggered_by as an array', () => {
expect(store.state.pipeline.triggered_by.length).toEqual(1);
});
expect(store.triggeredPipelines).toEqual([]);
it('adds isExpanding key set to false', () => {
expect(store.state.pipeline.triggered_by[0].isExpanded).toEqual(false);
});
it('parses nested triggered_by', () => {
expect(store.state.pipeline.triggered_by[0].triggered_by.length).toEqual(1);
expect(store.state.pipeline.triggered_by[0].triggered_by[0].isExpanded).toEqual(false);
});
});
describe('triggeredByPipelines', () => {
describe('with triggered_by pipeline', () => {
store.storePipeline(pipelineWithTriggeredBy);
expect(store.pipelineWithTriggeredBy.length).toEqual(1);
expect(store.triggeredByPipelines[0]).toEqual(
Object.assign({}, pipelineWithTriggeredBy.triggered_by, {
isLoading: false,
isCollpased: true,
}),
);
describe('triggered', () => {
it('adds isExpanding key set to false for each triggered pipeline', () => {
store.state.pipeline.triggered.forEach(pipeline => {
expect(pipeline.isExpanded).toEqual(false);
});
describe('without triggered_by pipeline', () => {
it('triggeredByPipelines should be an empty array', () => {
store.storePipeline({ triggered_by: null });
expect(store.triggeredByPipelines).toEqual([]);
});
it('parses nested triggered pipelines', () => {
store.state.pipeline.triggered[1].triggered.forEach(pipeline => {
expect(pipeline.isExpanded).toEqual(false);
});
});
});
describe('downstream', () => {
beforeAll(() => {
store.storePipeline(pipelineWithBoth);
});
describe('requestTriggeredPipeline', () => {
describe('resetTriggeredByPipeline', () => {
beforeEach(() => {
store.requestTriggeredPipeline(store.triggeredPipelines[0]);
store.storePipeline(data);
});
it('sets isLoading to true for the requested pipeline', () => {
expect(store.triggeredPipelines[0].isLoading).toEqual(true);
});
it('closes the pipeline & nested ones', () => {
store.state.pipeline.triggered_by[0].isExpanded = true;
store.state.pipeline.triggered_by[0].triggered_by[0].isExpanded = true;
it('sets isExpanded to true for the requested pipeline', () => {
expect(store.triggeredPipelines[0].isExpanded).toEqual(true);
});
store.resetTriggeredByPipeline(store.state.pipeline, store.state.pipeline.triggered_by[0]);
it('sets isLoading to false for the other pipelines', () => {
expect(store.triggeredPipelines[1].isLoading).toEqual(false);
});
it('sets isExpanded to false for the other pipelines', () => {
expect(store.triggeredPipelines[1].isExpanded).toEqual(false);
expect(store.state.pipeline.triggered_by[0].isExpanded).toEqual(false);
expect(store.state.pipeline.triggered_by[0].triggered_by[0].isExpanded).toEqual(false);
});
});
describe('receiveTriggeredPipelineSuccess', () => {
it('updates the given pipeline and sets it as the visible one', () => {
const receivedPipeline = store.triggeredPipelines[0];
describe('openTriggeredByPipeline', () => {
beforeEach(() => {
store.storePipeline(data);
});
store.receiveTriggeredPipelineSuccess(receivedPipeline);
it('opens the given pipeline', () => {
store.openTriggeredByPipeline(store.state.pipeline, store.state.pipeline.triggered_by[0]);
expect(store.triggeredPipelines[0].isLoading).toEqual(false);
expect(store.triggered).toEqual(receivedPipeline);
expect(store.state.pipeline.triggered_by[0].isExpanded).toEqual(true);
});
});
describe('receiveTriggeredPipelineError', () => {
it('resets the given pipeline and resets it as the visible one', () => {
const receivedPipeline = store.triggeredPipelines[0];
describe('closeTriggeredByPipeline', () => {
beforeEach(() => {
store.storePipeline(data);
});
store.receiveTriggeredPipelineError(receivedPipeline);
it('closes the given pipeline', () => {
// open it first
store.openTriggeredByPipeline(store.state.pipeline, store.state.pipeline.triggered_by[0]);
expect(store.triggeredPipelines[0].isLoading).toEqual(false);
expect(store.triggeredPipelines[0].isExpanded).toEqual(false);
store.closeTriggeredByPipeline(store.state.pipeline, store.state.pipeline.triggered_by[0]);
expect(store.triggered).toEqual({});
});
expect(store.state.pipeline.triggered_by[0].isExpanded).toEqual(false);
});
});
describe('upstream', () => {
describe('requestTriggeredByPipeline', () => {
describe('resetTriggeredPipelines', () => {
beforeEach(() => {
store.requestTriggeredByPipeline(store.triggeredByPipelines[0]);
store.storePipeline(data);
});
it('sets isLoading to true for the requested pipeline', () => {
expect(store.triggeredByPipelines[0].isLoading).toEqual(true);
});
it('closes the pipeline & nested ones', () => {
store.state.pipeline.triggered[0].isExpanded = true;
store.state.pipeline.triggered[0].triggered[0].isExpanded = true;
it('sets isExpanded to true for the requested pipeline', () => {
expect(store.triggeredByPipelines[0].isExpanded).toEqual(true);
store.resetTriggeredPipeline(store.state.pipeline, store.state.pipeline.triggered[0]);
expect(store.state.pipeline.triggered[0].isExpanded).toEqual(false);
expect(store.state.pipeline.triggered[0].triggered[0].isExpanded).toEqual(false);
});
});
describe('receiveTriggeredByPipelineSuccess', () => {
it('updates the given pipeline and sets it as the visible one', () => {
const receivedPipeline = store.triggeredByPipelines[0];
describe('openTriggeredPipeline', () => {
beforeEach(() => {
store.storePipeline(data);
});
store.receiveTriggeredByPipelineSuccess(receivedPipeline);
it('opens the given pipeline', () => {
store.openTriggeredPipeline(store.state.pipeline, store.state.pipeline.triggered[0]);
expect(store.triggeredByPipelines[0].isLoading).toEqual(false);
expect(store.triggeredBy).toEqual(receivedPipeline);
expect(store.state.pipeline.triggered[0].isExpanded).toEqual(true);
});
});
describe('receiveTriggeredByPipelineError', () => {
it('resets the given pipeline and resets it as the visible one', () => {
const receivedPipeline = store.triggeredByPipelines[0];
describe('closeTriggeredPipeline', () => {
beforeEach(() => {
store.storePipeline(data);
});
store.receiveTriggeredByPipelineError(receivedPipeline);
it('closes the given pipeline', () => {
// open it first
store.openTriggeredPipeline(store.state.pipeline, store.state.pipeline.triggered[0]);
expect(store.triggeredByPipelines[0].isLoading).toEqual(false);
expect(store.triggeredByPipelines[0].isExpanded).toEqual(false);
store.closeTriggeredPipeline(store.state.pipeline, store.state.pipeline.triggered[0]);
expect(store.triggeredBy).toEqual({});
});
expect(store.state.pipeline.triggered[0].isExpanded).toEqual(false);
});
});
});
......@@ -685,12 +685,6 @@ msgstr ""
msgid "An error occured while fetching the releases. Please try again."
msgstr ""
msgid "An error occured while fetching this downstream pipeline. Please try again"
msgstr ""
msgid "An error occured while fetching this upstream pipeline. Please try again"
msgstr ""
msgid "An error occurred adding a draft to the discussion."
msgstr ""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment