Commit da35fe75 authored by Olena Horal-Koretska's avatar Olena Horal-Koretska

Merge branch '239861-refactor-add-tests' into 'master'

Integrate Vue mixin into component and update tests

Closes #239861

See merge request gitlab-org/gitlab!42944
parents b067399c 7d39ac06
<script> <script>
import { escape, capitalize } from 'lodash';
import { GlLoadingIcon } from '@gitlab/ui'; import { GlLoadingIcon } from '@gitlab/ui';
import StageColumnComponent from './stage_column_component.vue'; import StageColumnComponent from './stage_column_component.vue';
import GraphMixin from '../../mixins/graph_component_mixin';
import GraphWidthMixin from '../../mixins/graph_width_mixin'; import GraphWidthMixin from '../../mixins/graph_width_mixin';
import LinkedPipelinesColumn from './linked_pipelines_column.vue'; import LinkedPipelinesColumn from './linked_pipelines_column.vue';
import GraphBundleMixin from '../../mixins/graph_pipeline_bundle_mixin'; import GraphBundleMixin from '../../mixins/graph_pipeline_bundle_mixin';
...@@ -13,7 +13,7 @@ export default { ...@@ -13,7 +13,7 @@ export default {
GlLoadingIcon, GlLoadingIcon,
LinkedPipelinesColumn, LinkedPipelinesColumn,
}, },
mixins: [GraphMixin, GraphWidthMixin, GraphBundleMixin], mixins: [GraphWidthMixin, GraphBundleMixin],
props: { props: {
isLoading: { isLoading: {
type: Boolean, type: Boolean,
...@@ -51,6 +51,9 @@ export default { ...@@ -51,6 +51,9 @@ export default {
}; };
}, },
computed: { computed: {
graph() {
return this.pipeline.details?.stages;
},
hasTriggeredBy() { hasTriggeredBy() {
return ( return (
this.type !== this.$options.downstream && this.type !== this.$options.downstream &&
...@@ -92,6 +95,39 @@ export default { ...@@ -92,6 +95,39 @@ export default {
}, },
}, },
methods: { methods: {
capitalizeStageName(name) {
const escapedName = escape(name);
return capitalize(escapedName);
},
isFirstColumn(index) {
return index === 0;
},
stageConnectorClass(index, stage) {
let className;
// If it's the first stage column and only has one job
if (this.isFirstColumn(index) && stage.groups.length === 1) {
className = 'no-margin';
} else if (index > 0) {
// If it is not the first column
className = 'left-margin';
}
return className;
},
refreshPipelineGraph() {
this.$emit('refreshPipelineGraph');
},
/**
* CSS class is applied:
* - if pipeline graph contains only one stage column component
*
* @param {number} index
* @returns {boolean}
*/
shouldAddRightMargin(index) {
return !(index === this.graph.length - 1);
},
handleClickedDownstream(pipeline, clickedIndex, downstreamNode) { handleClickedDownstream(pipeline, clickedIndex, downstreamNode) {
/** /**
* Calculates the margin top of the clicked downstream pipeline by * Calculates the margin top of the clicked downstream pipeline by
......
import { escape } from 'lodash';
export default {
props: {
isLoading: {
type: Boolean,
required: true,
},
pipeline: {
type: Object,
required: true,
},
},
computed: {
graph() {
return this.pipeline.details && this.pipeline.details.stages;
},
},
methods: {
capitalizeStageName(name) {
const escapedName = escape(name);
return escapedName.charAt(0).toUpperCase() + escapedName.slice(1);
},
isFirstColumn(index) {
return index === 0;
},
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;
},
refreshPipelineGraph() {
this.$emit('refreshPipelineGraph');
},
/**
* CSS class is applied:
* - if pipeline graph contains only one stage column component
*
* @param {number} index
* @returns {boolean}
*/
shouldAddRightMargin(index) {
return !(index === this.graph.length - 1);
},
},
};
...@@ -3,23 +3,27 @@ import { mount } from '@vue/test-utils'; ...@@ -3,23 +3,27 @@ import { mount } from '@vue/test-utils';
import { setHTMLFixture } from 'helpers/fixtures'; import { setHTMLFixture } from 'helpers/fixtures';
import PipelineStore from '~/pipelines/stores/pipeline_store'; import PipelineStore from '~/pipelines/stores/pipeline_store';
import graphComponent from '~/pipelines/components/graph/graph_component.vue'; import graphComponent from '~/pipelines/components/graph/graph_component.vue';
import stageColumnComponent from '~/pipelines/components/graph/stage_column_component.vue'; import StageColumnComponent from '~/pipelines/components/graph/stage_column_component.vue';
import linkedPipelinesColumn from '~/pipelines/components/graph/linked_pipelines_column.vue'; import linkedPipelinesColumn from '~/pipelines/components/graph/linked_pipelines_column.vue';
import graphJSON from './mock_data'; import graphJSON from './mock_data';
import linkedPipelineJSON from './linked_pipelines_mock_data'; import linkedPipelineJSON from './linked_pipelines_mock_data';
import PipelinesMediator from '~/pipelines/pipeline_details_mediator'; import PipelinesMediator from '~/pipelines/pipeline_details_mediator';
describe('graph component', () => { describe('graph component', () => {
const store = new PipelineStore(); let store;
store.storePipeline(linkedPipelineJSON); let mediator;
const mediator = new PipelinesMediator({ endpoint: '' });
let wrapper; let wrapper;
const findExpandPipelineBtn = () => wrapper.find('[data-testid="expandPipelineButton"]'); const findExpandPipelineBtn = () => wrapper.find('[data-testid="expandPipelineButton"]');
const findAllExpandPipelineBtns = () => wrapper.findAll('[data-testid="expandPipelineButton"]'); const findAllExpandPipelineBtns = () => wrapper.findAll('[data-testid="expandPipelineButton"]');
const findStageColumns = () => wrapper.findAll(StageColumnComponent);
const findStageColumnAt = i => findStageColumns().at(i);
beforeEach(() => { beforeEach(() => {
mediator = new PipelinesMediator({ endpoint: '' });
store = new PipelineStore();
store.storePipeline(linkedPipelineJSON);
setHTMLFixture('<div class="layout-page"></div>'); setHTMLFixture('<div class="layout-page"></div>');
}); });
...@@ -43,7 +47,7 @@ describe('graph component', () => { ...@@ -43,7 +47,7 @@ describe('graph component', () => {
}); });
describe('with data', () => { describe('with data', () => {
it('should render the graph', () => { beforeEach(() => {
wrapper = mount(graphComponent, { wrapper = mount(graphComponent, {
propsData: { propsData: {
isLoading: false, isLoading: false,
...@@ -51,26 +55,17 @@ describe('graph component', () => { ...@@ -51,26 +55,17 @@ describe('graph component', () => {
mediator, mediator,
}, },
}); });
});
it('renders the graph', () => {
expect(wrapper.find('.js-pipeline-graph').exists()).toBe(true); expect(wrapper.find('.js-pipeline-graph').exists()).toBe(true);
expect(wrapper.find(stageColumnComponent).classes()).toContain('no-margin');
expect(
wrapper
.findAll(stageColumnComponent)
.at(1)
.classes(),
).toContain('left-margin');
expect(wrapper.find('.stage-column:nth-child(2) .build:nth-child(1)').classes()).toContain(
'left-connector',
);
expect(wrapper.find('.loading-icon').exists()).toBe(false); expect(wrapper.find('.loading-icon').exists()).toBe(false);
expect(wrapper.find('.stage-column-list').exists()).toBe(true); expect(wrapper.find('.stage-column-list').exists()).toBe(true);
}); });
it('renders columns in the graph', () => {
expect(findStageColumns()).toHaveLength(graphJSON.details.stages.length);
});
}); });
describe('when linked pipelines are present', () => { describe('when linked pipelines are present', () => {
...@@ -93,26 +88,26 @@ describe('graph component', () => { ...@@ -93,26 +88,26 @@ describe('graph component', () => {
expect(wrapper.find('.fa-spinner').exists()).toBe(false); expect(wrapper.find('.fa-spinner').exists()).toBe(false);
}); });
it('should include the stage column list', () => { it('should include the stage column', () => {
expect(wrapper.find(stageColumnComponent).exists()).toBe(true); expect(findStageColumnAt(0).exists()).toBe(true);
});
it('should include the no-margin class on the first child if there is only one job', () => {
const firstStageColumnElement = wrapper.find(stageColumnComponent);
expect(firstStageColumnElement.classes()).toContain('no-margin');
}); });
it('should include the has-only-one-job class on the first child', () => { it('stage column should have no-margin, gl-mr-26, has-only-one-job classes if there is only one job', () => {
const firstStageColumnElement = wrapper.find('.stage-column-list .stage-column'); expect(findStageColumnAt(0).classes()).toEqual(
expect.arrayContaining(['no-margin', 'gl-mr-26', 'has-only-one-job']),
expect(firstStageColumnElement.classes()).toContain('has-only-one-job'); );
}); });
it('should include the left-margin class on the second child', () => { it('should include the left-margin class on the second child', () => {
const firstStageColumnElement = wrapper.find('.stage-column-list .stage-column:last-child'); expect(findStageColumnAt(1).classes('left-margin')).toBe(true);
});
expect(firstStageColumnElement.classes()).toContain('left-margin'); it('should include the left-connector class in the build of the second child', () => {
expect(
findStageColumnAt(1)
.find('.build:nth-child(1)')
.classes('left-connector'),
).toBe(true);
}); });
it('should include the js-has-linked-pipelines flag', () => { it('should include the js-has-linked-pipelines flag', () => {
...@@ -134,12 +129,7 @@ describe('graph component', () => { ...@@ -134,12 +129,7 @@ describe('graph component', () => {
describe('stageConnectorClass', () => { describe('stageConnectorClass', () => {
it('it returns left-margin when there is a triggerer', () => { it('it returns left-margin when there is a triggerer', () => {
expect( expect(findStageColumnAt(1).classes('left-margin')).toBe(true);
wrapper
.findAll(stageColumnComponent)
.at(1)
.classes(),
).toContain('left-margin');
}); });
}); });
}); });
...@@ -248,6 +238,16 @@ describe('graph component', () => { ...@@ -248,6 +238,16 @@ describe('graph component', () => {
.catch(done.fail); .catch(done.fail);
}); });
}); });
describe('when column requests a refresh', () => {
beforeEach(() => {
findStageColumnAt(0).vm.$emit('refreshPipelineGraph');
});
it('refreshPipelineGraph is emitted', () => {
expect(wrapper.emitted().refreshPipelineGraph).toHaveLength(1);
});
});
}); });
}); });
}); });
...@@ -268,7 +268,7 @@ describe('graph component', () => { ...@@ -268,7 +268,7 @@ describe('graph component', () => {
it('should include the first column with a no margin', () => { it('should include the first column with a no margin', () => {
const firstColumn = wrapper.find('.stage-column'); const firstColumn = wrapper.find('.stage-column');
expect(firstColumn.classes()).toContain('no-margin'); expect(firstColumn.classes('no-margin')).toBe(true);
}); });
it('should not render a linked pipelines column', () => { it('should not render a linked pipelines column', () => {
...@@ -278,16 +278,11 @@ describe('graph component', () => { ...@@ -278,16 +278,11 @@ describe('graph component', () => {
describe('stageConnectorClass', () => { describe('stageConnectorClass', () => {
it('it returns no-margin when no triggerer and there is one job', () => { it('it returns no-margin when no triggerer and there is one job', () => {
expect(wrapper.find(stageColumnComponent).classes()).toContain('no-margin'); expect(findStageColumnAt(0).classes('no-margin')).toBe(true);
}); });
it('it returns left-margin when no triggerer and not the first stage', () => { it('it returns left-margin when no triggerer and not the first stage', () => {
expect( expect(findStageColumnAt(1).classes('left-margin')).toBe(true);
wrapper
.findAll(stageColumnComponent)
.at(1)
.classes(),
).toContain('left-margin');
}); });
}); });
}); });
...@@ -302,12 +297,9 @@ describe('graph component', () => { ...@@ -302,12 +297,9 @@ describe('graph component', () => {
}, },
}); });
expect( expect(findStageColumnAt(1).props('title')).toEqual(
wrapper 'Deploy &lt;img src=x onerror=alert(document.domain)&gt;',
.find('.stage-column:nth-child(2) .stage-name') );
.text()
.trim(),
).toEqual('Deploy &lt;img src=x onerror=alert(document.domain)&gt;');
}); });
}); });
}); });
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