summaryrefslogtreecommitdiff
path: root/spec/frontend/pipelines/components/dag
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-05-29 18:08:26 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-05-29 18:08:26 +0000
commitb64a8161c9442d82897a341d6bf935dd3e748b06 (patch)
treeb9953db8607d1393aa8ac588a15f184dd8e183f6 /spec/frontend/pipelines/components/dag
parent6e33325c1458cb31b4d36a7eec817fa00ec3faaf (diff)
downloadgitlab-ce-b64a8161c9442d82897a341d6bf935dd3e748b06.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/pipelines/components/dag')
-rw-r--r--spec/frontend/pipelines/components/dag/__snapshots__/dag_graph_spec.js.snap220
-rw-r--r--spec/frontend/pipelines/components/dag/dag_graph_spec.js96
-rw-r--r--spec/frontend/pipelines/components/dag/dag_spec.js96
-rw-r--r--spec/frontend/pipelines/components/dag/mock_data.js348
-rw-r--r--spec/frontend/pipelines/components/dag/utils_spec.js10
5 files changed, 745 insertions, 25 deletions
diff --git a/spec/frontend/pipelines/components/dag/__snapshots__/dag_graph_spec.js.snap b/spec/frontend/pipelines/components/dag/__snapshots__/dag_graph_spec.js.snap
new file mode 100644
index 00000000000..5390c2f8e0c
--- /dev/null
+++ b/spec/frontend/pipelines/components/dag/__snapshots__/dag_graph_spec.js.snap
@@ -0,0 +1,220 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`The DAG graph in the basic case renders the graph svg 1`] = `
+"<svg viewBox=\\"0,0,1000,540\\" width=\\"1000\\" height=\\"540\\">
+ <g fill=\\"none\\" stroke-opacity=\\"0.8\\">
+ <g id=\\"dag-link43\\" class=\\"dag-link gl-cursor-pointer\\">
+ <linearGradient id=\\"dag-grad53\\" gradientUnits=\\"userSpaceOnUse\\" x1=\\"116\\" x2=\\"361.3333333333333\\">
+ <stop offset=\\"0%\\" stop-color=\\"#e17223\\"></stop>
+ <stop offset=\\"100%\\" stop-color=\\"#83ab4a\\"></stop>
+ </linearGradient>
+ <clipPath id=\\"dag-clip63\\">
+ <path d=\\"
+ M100, 129
+ V158
+ H377.3333333333333
+ V100
+ H100
+ Z\\"></path>
+ </clipPath>
+ <path d=\\"M108,129L190,129L190,129L369.3333333333333,129\\" stroke=\\"url(#dag-grad53)\\" style=\\"stroke-linejoin: round;\\" stroke-width=\\"56\\" clip-path=\\"url(#dag-clip63)\\"></path>
+ </g>
+ <g id=\\"dag-link44\\" class=\\"dag-link gl-cursor-pointer\\">
+ <linearGradient id=\\"dag-grad54\\" gradientUnits=\\"userSpaceOnUse\\" x1=\\"377.3333333333333\\" x2=\\"622.6666666666666\\">
+ <stop offset=\\"0%\\" stop-color=\\"#83ab4a\\"></stop>
+ <stop offset=\\"100%\\" stop-color=\\"#6f3500\\"></stop>
+ </linearGradient>
+ <clipPath id=\\"dag-clip64\\">
+ <path d=\\"
+ M361.3333333333333, 129.0000000000002
+ V158.0000000000002
+ H638.6666666666666
+ V100
+ H361.3333333333333
+ Z\\"></path>
+ </clipPath>
+ <path d=\\"M369.3333333333333,129L509.3333333333333,129L509.3333333333333,129.0000000000002L630.6666666666666,129.0000000000002\\" stroke=\\"url(#dag-grad54)\\" style=\\"stroke-linejoin: round;\\" stroke-width=\\"56\\" clip-path=\\"url(#dag-clip64)\\"></path>
+ </g>
+ <g id=\\"dag-link45\\" class=\\"dag-link gl-cursor-pointer\\">
+ <linearGradient id=\\"dag-grad55\\" gradientUnits=\\"userSpaceOnUse\\" x1=\\"116\\" x2=\\"622.6666666666666\\">
+ <stop offset=\\"0%\\" stop-color=\\"#5772ff\\"></stop>
+ <stop offset=\\"100%\\" stop-color=\\"#6f3500\\"></stop>
+ </linearGradient>
+ <clipPath id=\\"dag-clip65\\">
+ <path d=\\"
+ M100, 187.0000000000002
+ V241.00000000000003
+ H638.6666666666666
+ V158.0000000000002
+ H100
+ Z\\"></path>
+ </clipPath>
+ <path d=\\"M108,212.00000000000003L306,212.00000000000003L306,187.0000000000002L630.6666666666666,187.0000000000002\\" stroke=\\"url(#dag-grad55)\\" style=\\"stroke-linejoin: round;\\" stroke-width=\\"56\\" clip-path=\\"url(#dag-clip65)\\"></path>
+ </g>
+ <g id=\\"dag-link46\\" class=\\"dag-link gl-cursor-pointer\\">
+ <linearGradient id=\\"dag-grad56\\" gradientUnits=\\"userSpaceOnUse\\" x1=\\"116\\" x2=\\"361.3333333333333\\">
+ <stop offset=\\"0%\\" stop-color=\\"#b24800\\"></stop>
+ <stop offset=\\"100%\\" stop-color=\\"#006887\\"></stop>
+ </linearGradient>
+ <clipPath id=\\"dag-clip66\\">
+ <path d=\\"
+ M100, 269.9999999999998
+ V324
+ H377.3333333333333
+ V240.99999999999977
+ H100
+ Z\\"></path>
+ </clipPath>
+ <path d=\\"M108,295L338.93333333333334,295L338.93333333333334,269.9999999999998L369.3333333333333,269.9999999999998\\" stroke=\\"url(#dag-grad56)\\" style=\\"stroke-linejoin: round;\\" stroke-width=\\"56\\" clip-path=\\"url(#dag-clip66)\\"></path>
+ </g>
+ <g id=\\"dag-link47\\" class=\\"dag-link gl-cursor-pointer\\">
+ <linearGradient id=\\"dag-grad57\\" gradientUnits=\\"userSpaceOnUse\\" x1=\\"116\\" x2=\\"361.3333333333333\\">
+ <stop offset=\\"0%\\" stop-color=\\"#25d2d2\\"></stop>
+ <stop offset=\\"100%\\" stop-color=\\"#487900\\"></stop>
+ </linearGradient>
+ <clipPath id=\\"dag-clip67\\">
+ <path d=\\"
+ M100, 352.99999999999994
+ V407.00000000000006
+ H377.3333333333333
+ V323.99999999999994
+ H100
+ Z\\"></path>
+ </clipPath>
+ <path d=\\"M108,378.00000000000006L144.66666666666669,378.00000000000006L144.66666666666669,352.99999999999994L369.3333333333333,352.99999999999994\\" stroke=\\"url(#dag-grad57)\\" style=\\"stroke-linejoin: round;\\" stroke-width=\\"56\\" clip-path=\\"url(#dag-clip67)\\"></path>
+ </g>
+ <g id=\\"dag-link48\\" class=\\"dag-link gl-cursor-pointer\\">
+ <linearGradient id=\\"dag-grad58\\" gradientUnits=\\"userSpaceOnUse\\" x1=\\"377.3333333333333\\" x2=\\"622.6666666666666\\">
+ <stop offset=\\"0%\\" stop-color=\\"#006887\\"></stop>
+ <stop offset=\\"100%\\" stop-color=\\"#d84280\\"></stop>
+ </linearGradient>
+ <clipPath id=\\"dag-clip68\\">
+ <path d=\\"
+ M361.3333333333333, 270.0000000000001
+ V299.0000000000001
+ H638.6666666666666
+ V240.99999999999977
+ H361.3333333333333
+ Z\\"></path>
+ </clipPath>
+ <path d=\\"M369.3333333333333,269.9999999999998L464,269.9999999999998L464,270.0000000000001L630.6666666666666,270.0000000000001\\" stroke=\\"url(#dag-grad58)\\" style=\\"stroke-linejoin: round;\\" stroke-width=\\"56\\" clip-path=\\"url(#dag-clip68)\\"></path>
+ </g>
+ <g id=\\"dag-link49\\" class=\\"dag-link gl-cursor-pointer\\">
+ <linearGradient id=\\"dag-grad59\\" gradientUnits=\\"userSpaceOnUse\\" x1=\\"377.3333333333333\\" x2=\\"622.6666666666666\\">
+ <stop offset=\\"0%\\" stop-color=\\"#487900\\"></stop>
+ <stop offset=\\"100%\\" stop-color=\\"#d84280\\"></stop>
+ </linearGradient>
+ <clipPath id=\\"dag-clip69\\">
+ <path d=\\"
+ M361.3333333333333, 328.0000000000001
+ V381.99999999999994
+ H638.6666666666666
+ V299.0000000000001
+ H361.3333333333333
+ Z\\"></path>
+ </clipPath>
+ <path d=\\"M369.3333333333333,352.99999999999994L522,352.99999999999994L522,328.0000000000001L630.6666666666666,328.0000000000001\\" stroke=\\"url(#dag-grad59)\\" style=\\"stroke-linejoin: round;\\" stroke-width=\\"56\\" clip-path=\\"url(#dag-clip69)\\"></path>
+ </g>
+ <g id=\\"dag-link50\\" class=\\"dag-link gl-cursor-pointer\\">
+ <linearGradient id=\\"dag-grad60\\" gradientUnits=\\"userSpaceOnUse\\" x1=\\"377.3333333333333\\" x2=\\"622.6666666666666\\">
+ <stop offset=\\"0%\\" stop-color=\\"#487900\\"></stop>
+ <stop offset=\\"100%\\" stop-color=\\"#3547de\\"></stop>
+ </linearGradient>
+ <clipPath id=\\"dag-clip70\\">
+ <path d=\\"
+ M361.3333333333333, 411
+ V440
+ H638.6666666666666
+ V381.99999999999994
+ H361.3333333333333
+ Z\\"></path>
+ </clipPath>
+ <path d=\\"M369.3333333333333,410.99999999999994L580,410.99999999999994L580,411L630.6666666666666,411\\" stroke=\\"url(#dag-grad60)\\" style=\\"stroke-linejoin: round;\\" stroke-width=\\"56\\" clip-path=\\"url(#dag-clip70)\\"></path>
+ </g>
+ <g id=\\"dag-link51\\" class=\\"dag-link gl-cursor-pointer\\">
+ <linearGradient id=\\"dag-grad61\\" gradientUnits=\\"userSpaceOnUse\\" x1=\\"638.6666666666666\\" x2=\\"884\\">
+ <stop offset=\\"0%\\" stop-color=\\"#d84280\\"></stop>
+ <stop offset=\\"100%\\" stop-color=\\"#006887\\"></stop>
+ </linearGradient>
+ <clipPath id=\\"dag-clip71\\">
+ <path d=\\"
+ M622.6666666666666, 270.1890725105691
+ V299.1890725105691
+ H900
+ V241.0000000000001
+ H622.6666666666666
+ Z\\"></path>
+ </clipPath>
+ <path d=\\"M630.6666666666666,270.0000000000001L861.6,270.0000000000001L861.6,270.1890725105691L892,270.1890725105691\\" stroke=\\"url(#dag-grad61)\\" style=\\"stroke-linejoin: round;\\" stroke-width=\\"56\\" clip-path=\\"url(#dag-clip71)\\"></path>
+ </g>
+ <g id=\\"dag-link52\\" class=\\"dag-link gl-cursor-pointer\\">
+ <linearGradient id=\\"dag-grad62\\" gradientUnits=\\"userSpaceOnUse\\" x1=\\"638.6666666666666\\" x2=\\"884\\">
+ <stop offset=\\"0%\\" stop-color=\\"#3547de\\"></stop>
+ <stop offset=\\"100%\\" stop-color=\\"#275600\\"></stop>
+ </linearGradient>
+ <clipPath id=\\"dag-clip72\\">
+ <path d=\\"
+ M622.6666666666666, 411
+ V440
+ H900
+ V382
+ H622.6666666666666
+ Z\\"></path>
+ </clipPath>
+ <path d=\\"M630.6666666666666,411L679.9999999999999,411L679.9999999999999,411L892,411\\" stroke=\\"url(#dag-grad62)\\" style=\\"stroke-linejoin: round;\\" stroke-width=\\"56\\" clip-path=\\"url(#dag-clip72)\\"></path>
+ </g>
+ </g>
+ <g>
+ <line class=\\"dag-node gl-cursor-pointer\\" id=\\"dag-node73\\" stroke=\\"#e17223\\" stroke-width=\\"16\\" stroke-linecap=\\"round\\" x1=\\"108\\" x2=\\"108\\" y1=\\"104\\" y2=\\"154.00000000000003\\"></line>
+ <line class=\\"dag-node gl-cursor-pointer\\" id=\\"dag-node74\\" stroke=\\"#83ab4a\\" stroke-width=\\"16\\" stroke-linecap=\\"round\\" x1=\\"369\\" x2=\\"369\\" y1=\\"104\\" y2=\\"154\\"></line>
+ <line class=\\"dag-node gl-cursor-pointer\\" id=\\"dag-node75\\" stroke=\\"#5772ff\\" stroke-width=\\"16\\" stroke-linecap=\\"round\\" x1=\\"108\\" x2=\\"108\\" y1=\\"187.00000000000003\\" y2=\\"237.00000000000003\\"></line>
+ <line class=\\"dag-node gl-cursor-pointer\\" id=\\"dag-node76\\" stroke=\\"#b24800\\" stroke-width=\\"16\\" stroke-linecap=\\"round\\" x1=\\"108\\" x2=\\"108\\" y1=\\"270\\" y2=\\"320.00000000000006\\"></line>
+ <line class=\\"dag-node gl-cursor-pointer\\" id=\\"dag-node77\\" stroke=\\"#25d2d2\\" stroke-width=\\"16\\" stroke-linecap=\\"round\\" x1=\\"108\\" x2=\\"108\\" y1=\\"353.00000000000006\\" y2=\\"403.0000000000001\\"></line>
+ <line class=\\"dag-node gl-cursor-pointer\\" id=\\"dag-node78\\" stroke=\\"#6f3500\\" stroke-width=\\"16\\" stroke-linecap=\\"round\\" x1=\\"630\\" x2=\\"630\\" y1=\\"104.0000000000002\\" y2=\\"212.00000000000009\\"></line>
+ <line class=\\"dag-node gl-cursor-pointer\\" id=\\"dag-node79\\" stroke=\\"#006887\\" stroke-width=\\"16\\" stroke-linecap=\\"round\\" x1=\\"369\\" x2=\\"369\\" y1=\\"244.99999999999977\\" y2=\\"294.99999999999994\\"></line>
+ <line class=\\"dag-node gl-cursor-pointer\\" id=\\"dag-node80\\" stroke=\\"#487900\\" stroke-width=\\"16\\" stroke-linecap=\\"round\\" x1=\\"369\\" x2=\\"369\\" y1=\\"327.99999999999994\\" y2=\\"436\\"></line>
+ <line class=\\"dag-node gl-cursor-pointer\\" id=\\"dag-node81\\" stroke=\\"#d84280\\" stroke-width=\\"16\\" stroke-linecap=\\"round\\" x1=\\"630\\" x2=\\"630\\" y1=\\"245.00000000000009\\" y2=\\"353\\"></line>
+ <line class=\\"dag-node gl-cursor-pointer\\" id=\\"dag-node82\\" stroke=\\"#3547de\\" stroke-width=\\"16\\" stroke-linecap=\\"round\\" x1=\\"630\\" x2=\\"630\\" y1=\\"386\\" y2=\\"436\\"></line>
+ <line class=\\"dag-node gl-cursor-pointer\\" id=\\"dag-node83\\" stroke=\\"#006887\\" stroke-width=\\"16\\" stroke-linecap=\\"round\\" x1=\\"892\\" x2=\\"892\\" y1=\\"245.18907251056908\\" y2=\\"295.1890725105691\\"></line>
+ <line class=\\"dag-node gl-cursor-pointer\\" id=\\"dag-node84\\" stroke=\\"#275600\\" stroke-width=\\"16\\" stroke-linecap=\\"round\\" x1=\\"892\\" x2=\\"892\\" y1=\\"386\\" y2=\\"436\\"></line>
+ </g>
+ <g class=\\"gl-font-sm\\">
+ <foreignObject requiredFeatures=\\"http://www.w3.org/TR/SVG11/feature#Extensibility\\" height=\\"58.00000000000003px\\" width=\\"84\\" x=\\"8\\" y=\\"100\\" class=\\"gl-overflow-visible\\">
+ <div class=\\"gl-display-flex gl-pointer-events-none gl-flex-direction-column gl-justify-content-center gl-overflow-wrap-break\\" style=\\"height: 58.00000000000003px; text-align: right;\\">build_a</div>
+ </foreignObject>
+ <foreignObject requiredFeatures=\\"http://www.w3.org/TR/SVG11/feature#Extensibility\\" height=\\"25px\\" width=\\"84\\" x=\\"369.3333333333333\\" y=\\"75\\" class=\\"gl-overflow-visible\\">
+ <div class=\\"gl-display-flex gl-pointer-events-none gl-flex-direction-column gl-justify-content-center gl-overflow-wrap-break\\" style=\\"height: 25px; text-align: left;\\">test_a</div>
+ </foreignObject>
+ <foreignObject requiredFeatures=\\"http://www.w3.org/TR/SVG11/feature#Extensibility\\" height=\\"58px\\" width=\\"84\\" x=\\"8\\" y=\\"183.00000000000003\\" class=\\"gl-overflow-visible\\">
+ <div class=\\"gl-display-flex gl-pointer-events-none gl-flex-direction-column gl-justify-content-center gl-overflow-wrap-break\\" style=\\"height: 58px; text-align: right;\\">test_b</div>
+ </foreignObject>
+ <foreignObject requiredFeatures=\\"http://www.w3.org/TR/SVG11/feature#Extensibility\\" height=\\"58.00000000000006px\\" width=\\"84\\" x=\\"8\\" y=\\"266\\" class=\\"gl-overflow-visible\\">
+ <div class=\\"gl-display-flex gl-pointer-events-none gl-flex-direction-column gl-justify-content-center gl-overflow-wrap-break\\" style=\\"height: 58.00000000000006px; text-align: right;\\">post_test_a</div>
+ </foreignObject>
+ <foreignObject requiredFeatures=\\"http://www.w3.org/TR/SVG11/feature#Extensibility\\" height=\\"58.00000000000006px\\" width=\\"84\\" x=\\"8\\" y=\\"349.00000000000006\\" class=\\"gl-overflow-visible\\">
+ <div class=\\"gl-display-flex gl-pointer-events-none gl-flex-direction-column gl-justify-content-center gl-overflow-wrap-break\\" style=\\"height: 58.00000000000006px; text-align: right;\\">post_test_b</div>
+ </foreignObject>
+ <foreignObject requiredFeatures=\\"http://www.w3.org/TR/SVG11/feature#Extensibility\\" height=\\"25px\\" width=\\"84\\" x=\\"630.6666666666666\\" y=\\"75.0000000000002\\" class=\\"gl-overflow-visible\\">
+ <div class=\\"gl-display-flex gl-pointer-events-none gl-flex-direction-column gl-justify-content-center gl-overflow-wrap-break\\" style=\\"height: 25px; text-align: right;\\">post_test_c</div>
+ </foreignObject>
+ <foreignObject requiredFeatures=\\"http://www.w3.org/TR/SVG11/feature#Extensibility\\" height=\\"25px\\" width=\\"84\\" x=\\"369.3333333333333\\" y=\\"215.99999999999977\\" class=\\"gl-overflow-visible\\">
+ <div class=\\"gl-display-flex gl-pointer-events-none gl-flex-direction-column gl-justify-content-center gl-overflow-wrap-break\\" style=\\"height: 25px; text-align: left;\\">staging_a</div>
+ </foreignObject>
+ <foreignObject requiredFeatures=\\"http://www.w3.org/TR/SVG11/feature#Extensibility\\" height=\\"25px\\" width=\\"84\\" x=\\"369.3333333333333\\" y=\\"298.99999999999994\\" class=\\"gl-overflow-visible\\">
+ <div class=\\"gl-display-flex gl-pointer-events-none gl-flex-direction-column gl-justify-content-center gl-overflow-wrap-break\\" style=\\"height: 25px; text-align: left;\\">staging_b</div>
+ </foreignObject>
+ <foreignObject requiredFeatures=\\"http://www.w3.org/TR/SVG11/feature#Extensibility\\" height=\\"25px\\" width=\\"84\\" x=\\"630.6666666666666\\" y=\\"216.00000000000009\\" class=\\"gl-overflow-visible\\">
+ <div class=\\"gl-display-flex gl-pointer-events-none gl-flex-direction-column gl-justify-content-center gl-overflow-wrap-break\\" style=\\"height: 25px; text-align: right;\\">canary_a</div>
+ </foreignObject>
+ <foreignObject requiredFeatures=\\"http://www.w3.org/TR/SVG11/feature#Extensibility\\" height=\\"25px\\" width=\\"84\\" x=\\"630.6666666666666\\" y=\\"357\\" class=\\"gl-overflow-visible\\">
+ <div class=\\"gl-display-flex gl-pointer-events-none gl-flex-direction-column gl-justify-content-center gl-overflow-wrap-break\\" style=\\"height: 25px; text-align: right;\\">canary_c</div>
+ </foreignObject>
+ <foreignObject requiredFeatures=\\"http://www.w3.org/TR/SVG11/feature#Extensibility\\" height=\\"58px\\" width=\\"84\\" x=\\"908\\" y=\\"241.18907251056908\\" class=\\"gl-overflow-visible\\">
+ <div class=\\"gl-display-flex gl-pointer-events-none gl-flex-direction-column gl-justify-content-center gl-overflow-wrap-break\\" style=\\"height: 58px; text-align: left;\\">production_a</div>
+ </foreignObject>
+ <foreignObject requiredFeatures=\\"http://www.w3.org/TR/SVG11/feature#Extensibility\\" height=\\"58px\\" width=\\"84\\" x=\\"908\\" y=\\"382\\" class=\\"gl-overflow-visible\\">
+ <div class=\\"gl-display-flex gl-pointer-events-none gl-flex-direction-column gl-justify-content-center gl-overflow-wrap-break\\" style=\\"height: 58px; text-align: left;\\">production_d</div>
+ </foreignObject>
+ </g>
+</svg>"
+`;
diff --git a/spec/frontend/pipelines/components/dag/dag_graph_spec.js b/spec/frontend/pipelines/components/dag/dag_graph_spec.js
new file mode 100644
index 00000000000..bc576397967
--- /dev/null
+++ b/spec/frontend/pipelines/components/dag/dag_graph_spec.js
@@ -0,0 +1,96 @@
+import { mount } from '@vue/test-utils';
+import DagGraph from '~/pipelines/components/dag/dag_graph.vue';
+import { createSankey, removeOrphanNodes } from '~/pipelines/components/dag/utils';
+import { parsedData } from './mock_data';
+
+describe('The DAG graph', () => {
+ let wrapper;
+
+ const getGraph = () => wrapper.find('.dag-graph-container > svg');
+ const getAllLinks = () => wrapper.findAll('.dag-link');
+ const getAllNodes = () => wrapper.findAll('.dag-node');
+ const getAllLabels = () => wrapper.findAll('foreignObject');
+
+ const createComponent = (propsData = {}) => {
+ if (wrapper?.destroy) {
+ wrapper.destroy();
+ }
+
+ wrapper = mount(DagGraph, {
+ attachToDocument: true,
+ propsData,
+ data() {
+ return {
+ color: () => {},
+ width: 0,
+ height: 0,
+ };
+ },
+ });
+ };
+
+ beforeEach(() => {
+ createComponent({ graphData: parsedData });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('in the basic case', () => {
+ beforeEach(() => {
+ /*
+ The graph uses random to offset links. To keep the snapshot consistent,
+ we mock Math.random. Wheeeee!
+ */
+ const randomNumber = jest.spyOn(global.Math, 'random');
+ randomNumber.mockImplementation(() => 0.2);
+ createComponent({ graphData: parsedData });
+ });
+
+ it('renders the graph svg', () => {
+ expect(getGraph().exists()).toBe(true);
+ expect(getGraph().html()).toMatchSnapshot();
+ });
+ });
+
+ describe('links', () => {
+ it('renders the expected number of links', () => {
+ expect(getAllLinks()).toHaveLength(parsedData.links.length);
+ });
+
+ it('renders the expected number of gradients', () => {
+ expect(wrapper.findAll('linearGradient')).toHaveLength(parsedData.links.length);
+ });
+
+ it('renders the expected number of clip paths', () => {
+ expect(wrapper.findAll('clipPath')).toHaveLength(parsedData.links.length);
+ });
+ });
+
+ describe('nodes and labels', () => {
+ const sankeyNodes = createSankey()(parsedData).nodes;
+ const processedNodes = removeOrphanNodes(sankeyNodes);
+
+ describe('nodes', () => {
+ it('renders the expected number of nodes', () => {
+ expect(getAllNodes()).toHaveLength(processedNodes.length);
+ });
+ });
+
+ describe('labels', () => {
+ it('renders the expected number of labels as foreignObjects', () => {
+ expect(getAllLabels()).toHaveLength(processedNodes.length);
+ });
+
+ it('renders the title as text', () => {
+ expect(
+ getAllLabels()
+ .at(0)
+ .text(),
+ ).toBe(parsedData.nodes[0].name);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/pipelines/components/dag/dag_spec.js b/spec/frontend/pipelines/components/dag/dag_spec.js
index 31ee4e1a0a1..262682a89c5 100644
--- a/spec/frontend/pipelines/components/dag/dag_spec.js
+++ b/spec/frontend/pipelines/components/dag/dag_spec.js
@@ -1,26 +1,34 @@
-import { mount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import waitForPromises from 'helpers/wait_for_promises';
import { GlAlert } from '@gitlab/ui';
import Dag from '~/pipelines/components/dag/dag.vue';
+import DagGraph from '~/pipelines/components/dag/dag_graph.vue';
-describe('Pipeline DAG graph', () => {
+import {
+ DEFAULT,
+ PARSE_FAILURE,
+ LOAD_FAILURE,
+ UNSUPPORTED_DATA,
+} from '~/pipelines/components/dag//constants';
+import { mockBaseData, tooSmallGraph, unparseableGraph } from './mock_data';
+
+describe('Pipeline DAG graph wrapper', () => {
let wrapper;
- let axiosMock;
+ let mock;
const getAlert = () => wrapper.find(GlAlert);
- const getGraph = () => wrapper.find('[data-testid="dag-graph-container"]');
-
- const dataPath = 'root/test/pipelines/90/dag.json';
+ const getGraph = () => wrapper.find(DagGraph);
+ const getErrorText = type => wrapper.vm.$options.errorTexts[type];
- const createComponent = (propsData = {}, method = mount) => {
- axiosMock = new MockAdapter(axios);
+ const dataPath = '/root/test/pipelines/90/dag.json';
+ const createComponent = (propsData = {}) => {
if (wrapper?.destroy) {
wrapper.destroy();
}
- wrapper = method(Dag, {
+ wrapper = shallowMount(Dag, {
propsData,
data() {
return {
@@ -30,8 +38,12 @@ describe('Pipeline DAG graph', () => {
});
};
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ });
+
afterEach(() => {
- axiosMock.restore();
+ mock.restore();
wrapper.destroy();
wrapper = null;
});
@@ -41,34 +53,80 @@ describe('Pipeline DAG graph', () => {
createComponent({ graphUrl: undefined });
});
- it('shows the alert and not the graph', () => {
+ it('shows the DEFAULT alert and not the graph', () => {
expect(getAlert().exists()).toBe(true);
+ expect(getAlert().text()).toBe(getErrorText(DEFAULT));
expect(getGraph().exists()).toBe(false);
});
});
describe('when there is a dataUrl', () => {
- beforeEach(() => {
- createComponent({ graphUrl: dataPath });
+ describe('but the data fetch fails', () => {
+ beforeEach(() => {
+ mock.onGet(dataPath).replyOnce(500);
+ createComponent({ graphUrl: dataPath });
+ });
+
+ it('shows the LOAD_FAILURE alert and not the graph', () => {
+ return wrapper.vm
+ .$nextTick()
+ .then(waitForPromises)
+ .then(() => {
+ expect(getAlert().exists()).toBe(true);
+ expect(getAlert().text()).toBe(getErrorText(LOAD_FAILURE));
+ expect(getGraph().exists()).toBe(false);
+ });
+ });
});
- it('shows the graph and not the alert', () => {
- expect(getAlert().exists()).toBe(false);
- expect(getGraph().exists()).toBe(true);
+ describe('the data fetch succeeds but the parse fails', () => {
+ beforeEach(() => {
+ mock.onGet(dataPath).replyOnce(200, unparseableGraph);
+ createComponent({ graphUrl: dataPath });
+ });
+
+ it('shows the PARSE_FAILURE alert and not the graph', () => {
+ return wrapper.vm
+ .$nextTick()
+ .then(waitForPromises)
+ .then(() => {
+ expect(getAlert().exists()).toBe(true);
+ expect(getAlert().text()).toBe(getErrorText(PARSE_FAILURE));
+ expect(getGraph().exists()).toBe(false);
+ });
+ });
});
- describe('but the data fetch fails', () => {
+ describe('and the data fetch and parse succeeds', () => {
+ beforeEach(() => {
+ mock.onGet(dataPath).replyOnce(200, mockBaseData);
+ createComponent({ graphUrl: dataPath });
+ });
+
+ it('shows the graph and not the alert', () => {
+ return wrapper.vm
+ .$nextTick()
+ .then(waitForPromises)
+ .then(() => {
+ expect(getAlert().exists()).toBe(false);
+ expect(getGraph().exists()).toBe(true);
+ });
+ });
+ });
+
+ describe('the data fetch and parse succeeds, but the resulting graph is too small', () => {
beforeEach(() => {
- axiosMock.onGet(dataPath).replyOnce(500);
+ mock.onGet(dataPath).replyOnce(200, tooSmallGraph);
createComponent({ graphUrl: dataPath });
});
- it('shows the alert and not the graph', () => {
+ it('shows the UNSUPPORTED_DATA alert and not the graph', () => {
return wrapper.vm
.$nextTick()
.then(waitForPromises)
.then(() => {
expect(getAlert().exists()).toBe(true);
+ expect(getAlert().text()).toBe(getErrorText(UNSUPPORTED_DATA));
expect(getGraph().exists()).toBe(false);
});
});
diff --git a/spec/frontend/pipelines/components/dag/mock_data.js b/spec/frontend/pipelines/components/dag/mock_data.js
index 723cdd3f525..5de8697170a 100644
--- a/spec/frontend/pipelines/components/dag/mock_data.js
+++ b/spec/frontend/pipelines/components/dag/mock_data.js
@@ -3,7 +3,7 @@
as well as non-parallel jobs with spaces in the name to prevent
us relying on spaces as an indicator.
*/
-export default {
+export const mockBaseData = {
stages: [
{
name: 'test',
@@ -42,3 +42,349 @@ export default {
},
],
};
+
+export const tooSmallGraph = {
+ stages: [
+ {
+ name: 'test',
+ groups: [
+ {
+ name: 'jest',
+ size: 2,
+ jobs: [{ name: 'jest 1/2' }, { name: 'jest 2/2' }],
+ },
+ {
+ name: 'rspec',
+ size: 1,
+ jobs: [{ name: 'rspec', needs: ['frontend fixtures'] }],
+ },
+ ],
+ },
+ {
+ name: 'fixtures',
+ groups: [
+ {
+ name: 'frontend fixtures',
+ size: 1,
+ jobs: [{ name: 'frontend fixtures' }],
+ },
+ ],
+ },
+ {
+ name: 'un-needed',
+ groups: [
+ {
+ name: 'un-needed',
+ size: 1,
+ jobs: [{ name: 'un-needed' }],
+ },
+ ],
+ },
+ ],
+};
+
+export const unparseableGraph = [
+ {
+ name: 'test',
+ groups: [
+ {
+ name: 'jest',
+ size: 2,
+ jobs: [{ name: 'jest 1/2', needs: ['frontend fixtures'] }, { name: 'jest 2/2' }],
+ },
+ {
+ name: 'rspec',
+ size: 1,
+ jobs: [{ name: 'rspec', needs: ['frontend fixtures'] }],
+ },
+ ],
+ },
+ {
+ name: 'un-needed',
+ groups: [
+ {
+ name: 'un-needed',
+ size: 1,
+ jobs: [{ name: 'un-needed' }],
+ },
+ ],
+ },
+];
+
+/*
+ This represents data that has been parsed by the wrapper
+*/
+export const parsedData = {
+ nodes: [
+ {
+ name: 'build_a',
+ size: 1,
+ jobs: [
+ {
+ name: 'build_a',
+ },
+ ],
+ category: 'build',
+ },
+ {
+ name: 'build_b',
+ size: 1,
+ jobs: [
+ {
+ name: 'build_b',
+ },
+ ],
+ category: 'build',
+ },
+ {
+ name: 'test_a',
+ size: 1,
+ jobs: [
+ {
+ name: 'test_a',
+ needs: ['build_a'],
+ },
+ ],
+ category: 'test',
+ },
+ {
+ name: 'test_b',
+ size: 1,
+ jobs: [
+ {
+ name: 'test_b',
+ },
+ ],
+ category: 'test',
+ },
+ {
+ name: 'test_c',
+ size: 1,
+ jobs: [
+ {
+ name: 'test_c',
+ },
+ ],
+ category: 'test',
+ },
+ {
+ name: 'test_d',
+ size: 1,
+ jobs: [
+ {
+ name: 'test_d',
+ },
+ ],
+ category: 'test',
+ },
+ {
+ name: 'post_test_a',
+ size: 1,
+ jobs: [
+ {
+ name: 'post_test_a',
+ },
+ ],
+ category: 'post-test',
+ },
+ {
+ name: 'post_test_b',
+ size: 1,
+ jobs: [
+ {
+ name: 'post_test_b',
+ },
+ ],
+ category: 'post-test',
+ },
+ {
+ name: 'post_test_c',
+ size: 1,
+ jobs: [
+ {
+ name: 'post_test_c',
+ needs: ['test_a', 'test_b'],
+ },
+ ],
+ category: 'post-test',
+ },
+ {
+ name: 'staging_a',
+ size: 1,
+ jobs: [
+ {
+ name: 'staging_a',
+ needs: ['post_test_a'],
+ },
+ ],
+ category: 'staging',
+ },
+ {
+ name: 'staging_b',
+ size: 1,
+ jobs: [
+ {
+ name: 'staging_b',
+ needs: ['post_test_b'],
+ },
+ ],
+ category: 'staging',
+ },
+ {
+ name: 'staging_c',
+ size: 1,
+ jobs: [
+ {
+ name: 'staging_c',
+ },
+ ],
+ category: 'staging',
+ },
+ {
+ name: 'staging_d',
+ size: 1,
+ jobs: [
+ {
+ name: 'staging_d',
+ },
+ ],
+ category: 'staging',
+ },
+ {
+ name: 'staging_e',
+ size: 1,
+ jobs: [
+ {
+ name: 'staging_e',
+ },
+ ],
+ category: 'staging',
+ },
+ {
+ name: 'canary_a',
+ size: 1,
+ jobs: [
+ {
+ name: 'canary_a',
+ needs: ['staging_a', 'staging_b'],
+ },
+ ],
+ category: 'canary',
+ },
+ {
+ name: 'canary_b',
+ size: 1,
+ jobs: [
+ {
+ name: 'canary_b',
+ },
+ ],
+ category: 'canary',
+ },
+ {
+ name: 'canary_c',
+ size: 1,
+ jobs: [
+ {
+ name: 'canary_c',
+ needs: ['staging_b'],
+ },
+ ],
+ category: 'canary',
+ },
+ {
+ name: 'production_a',
+ size: 1,
+ jobs: [
+ {
+ name: 'production_a',
+ needs: ['canary_a'],
+ },
+ ],
+ category: 'production',
+ },
+ {
+ name: 'production_b',
+ size: 1,
+ jobs: [
+ {
+ name: 'production_b',
+ },
+ ],
+ category: 'production',
+ },
+ {
+ name: 'production_c',
+ size: 1,
+ jobs: [
+ {
+ name: 'production_c',
+ },
+ ],
+ category: 'production',
+ },
+ {
+ name: 'production_d',
+ size: 1,
+ jobs: [
+ {
+ name: 'production_d',
+ needs: ['canary_c'],
+ },
+ ],
+ category: 'production',
+ },
+ ],
+ links: [
+ {
+ source: 'build_a',
+ target: 'test_a',
+ value: 10,
+ },
+ {
+ source: 'test_a',
+ target: 'post_test_c',
+ value: 10,
+ },
+ {
+ source: 'test_b',
+ target: 'post_test_c',
+ value: 10,
+ },
+ {
+ source: 'post_test_a',
+ target: 'staging_a',
+ value: 10,
+ },
+ {
+ source: 'post_test_b',
+ target: 'staging_b',
+ value: 10,
+ },
+ {
+ source: 'staging_a',
+ target: 'canary_a',
+ value: 10,
+ },
+ {
+ source: 'staging_b',
+ target: 'canary_a',
+ value: 10,
+ },
+ {
+ source: 'staging_b',
+ target: 'canary_c',
+ value: 10,
+ },
+ {
+ source: 'canary_a',
+ target: 'production_a',
+ value: 10,
+ },
+ {
+ source: 'canary_c',
+ target: 'production_d',
+ value: 10,
+ },
+ ],
+};
diff --git a/spec/frontend/pipelines/components/dag/utils_spec.js b/spec/frontend/pipelines/components/dag/utils_spec.js
index 41bb91b4800..be0e4f0ea8e 100644
--- a/spec/frontend/pipelines/components/dag/utils_spec.js
+++ b/spec/frontend/pipelines/components/dag/utils_spec.js
@@ -8,12 +8,12 @@ import {
getMaxNodes,
} from '~/pipelines/components/dag/utils';
-import mockGraphData from './mock_data';
+import { mockBaseData } from './mock_data';
describe('DAG visualization parsing utilities', () => {
- const { nodes, nodeDict } = createNodesStructure(mockGraphData.stages);
+ const { nodes, nodeDict } = createNodesStructure(mockBaseData.stages);
const unfilteredLinks = makeLinksFromNodes(nodes, nodeDict);
- const parsed = parseData(mockGraphData.stages);
+ const parsed = parseData(mockBaseData.stages);
const layoutSettings = {
width: 200,
@@ -30,10 +30,10 @@ describe('DAG visualization parsing utilities', () => {
const parallelJobName = 'jest 1/2';
const singleJobName = 'frontend fixtures';
- const { name, jobs, size } = mockGraphData.stages[0].groups[0];
+ const { name, jobs, size } = mockBaseData.stages[0].groups[0];
it('returns the expected node structure', () => {
- expect(nodes[0]).toHaveProperty('category', mockGraphData.stages[0].name);
+ expect(nodes[0]).toHaveProperty('category', mockBaseData.stages[0].name);
expect(nodes[0]).toHaveProperty('name', name);
expect(nodes[0]).toHaveProperty('jobs', jobs);
expect(nodes[0]).toHaveProperty('size', size);