Resolve "Add graph value to hover"
This commit is contained in:
parent
78b044a1c7
commit
1dc051fb62
9 changed files with 373 additions and 365 deletions
|
@ -69,8 +69,8 @@
|
|||
currentFlagPosition: 0,
|
||||
showFlag: false,
|
||||
showFlagContent: false,
|
||||
showDeployInfo: true,
|
||||
timeSeries: [],
|
||||
realPixelRatio: 1,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -87,10 +87,7 @@
|
|||
},
|
||||
|
||||
innerViewBox() {
|
||||
if ((this.baseGraphWidth - 150) > 0) {
|
||||
return `0 0 ${this.baseGraphWidth - 150} ${this.baseGraphHeight}`;
|
||||
}
|
||||
return '0 0 0 0';
|
||||
return `0 0 ${this.baseGraphWidth - 150} ${this.baseGraphHeight}`;
|
||||
},
|
||||
|
||||
axisTransform() {
|
||||
|
@ -102,6 +99,10 @@
|
|||
paddingBottom: `${(Math.ceil(this.baseGraphHeight * 100) / this.baseGraphWidth) || 0}%`,
|
||||
};
|
||||
},
|
||||
|
||||
deploymentFlagData() {
|
||||
return this.reducedDeploymentData.find(deployment => deployment.showDeploymentFlag);
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
@ -122,6 +123,10 @@
|
|||
this.graphHeight = this.graphHeight - this.margin.top - this.margin.bottom;
|
||||
this.baseGraphHeight = this.graphHeight;
|
||||
this.baseGraphWidth = this.graphWidth;
|
||||
|
||||
// pixel offsets inside the svg and outside are not 1:1
|
||||
this.realPixelRatio = (this.$refs.baseSvg.clientWidth / this.baseGraphWidth);
|
||||
|
||||
this.renderAxesPaths();
|
||||
this.formatDeployments();
|
||||
},
|
||||
|
@ -261,6 +266,11 @@
|
|||
:line-color="path.lineColor"
|
||||
:area-color="path.areaColor"
|
||||
/>
|
||||
<graph-deployment
|
||||
:deployment-data="reducedDeploymentData"
|
||||
:graph-height="graphHeight"
|
||||
:graph-height-offset="graphHeightOffset"
|
||||
/>
|
||||
<rect
|
||||
class="prometheus-graph-overlay"
|
||||
:width="(graphWidth - 70)"
|
||||
|
@ -269,24 +279,21 @@
|
|||
ref="graphOverlay"
|
||||
@mousemove="handleMouseOverGraph($event)">
|
||||
</rect>
|
||||
<graph-deployment
|
||||
:show-deploy-info="showDeployInfo"
|
||||
:deployment-data="reducedDeploymentData"
|
||||
:graph-width="graphWidth"
|
||||
:graph-height="graphHeight"
|
||||
:graph-height-offset="graphHeightOffset"
|
||||
/>
|
||||
<graph-flag
|
||||
v-if="showFlag"
|
||||
:current-x-coordinate="currentXCoordinate"
|
||||
:current-data="currentData"
|
||||
:current-flag-position="currentFlagPosition"
|
||||
:graph-height="graphHeight"
|
||||
:graph-height-offset="graphHeightOffset"
|
||||
:show-flag-content="showFlagContent"
|
||||
/>
|
||||
</svg>
|
||||
</svg>
|
||||
<graph-flag
|
||||
:real-pixel-ratio="realPixelRatio"
|
||||
:current-x-coordinate="currentXCoordinate"
|
||||
:current-data="currentData"
|
||||
:graph-height="graphHeight"
|
||||
:graph-height-offset="graphHeightOffset"
|
||||
:show-flag-content="showFlagContent"
|
||||
:time-series="timeSeries"
|
||||
:unit-of-display="unitOfDisplay"
|
||||
:current-data-index="currentDataIndex"
|
||||
:legend-title="legendTitle"
|
||||
:deployment-flag-data="deploymentFlagData"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,13 +1,6 @@
|
|||
<script>
|
||||
import { dateFormatWithName, timeFormat } from '../../utils/date_time_formatters';
|
||||
import Icon from '../../../vue_shared/components/icon.vue';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
showDeployInfo: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
deploymentData: {
|
||||
type: Array,
|
||||
required: true,
|
||||
|
@ -20,14 +13,6 @@
|
|||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
graphWidth: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
components: {
|
||||
Icon,
|
||||
},
|
||||
|
||||
computed: {
|
||||
|
@ -37,52 +22,17 @@
|
|||
},
|
||||
|
||||
methods: {
|
||||
refText(d) {
|
||||
return d.tag ? d.ref : d.sha.slice(0, 8);
|
||||
},
|
||||
|
||||
formatTime(deploymentTime) {
|
||||
return timeFormat(deploymentTime);
|
||||
},
|
||||
|
||||
formatDate(deploymentTime) {
|
||||
return dateFormatWithName(deploymentTime);
|
||||
},
|
||||
|
||||
nameDeploymentClass(deployment) {
|
||||
return `deploy-info-${deployment.id}`;
|
||||
},
|
||||
|
||||
transformDeploymentGroup(deployment) {
|
||||
return `translate(${Math.floor(deployment.xPos) + 1}, 20)`;
|
||||
},
|
||||
|
||||
positionFlag(deployment) {
|
||||
let xPosition = 3;
|
||||
if (deployment.xPos > (this.graphWidth - 225)) {
|
||||
xPosition = -142;
|
||||
}
|
||||
return xPosition;
|
||||
},
|
||||
|
||||
svgContainerHeight(tag) {
|
||||
let svgHeight = 80;
|
||||
if (!tag) {
|
||||
svgHeight -= 20;
|
||||
}
|
||||
return svgHeight;
|
||||
return `translate(${Math.floor(deployment.xPos) - 5}, 20)`;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<g
|
||||
class="deploy-info"
|
||||
v-if="showDeployInfo">
|
||||
<g class="deploy-info">
|
||||
<g
|
||||
v-for="(deployment, index) in deploymentData"
|
||||
:key="index"
|
||||
:class="nameDeploymentClass(deployment)"
|
||||
:transform="transformDeploymentGroup(deployment)">
|
||||
<rect
|
||||
x="0"
|
||||
|
@ -99,81 +49,6 @@
|
|||
:y2="calculatedHeight"
|
||||
stroke="#000">
|
||||
</line>
|
||||
<svg
|
||||
v-if="deployment.showDeploymentFlag"
|
||||
class="js-deploy-info-box"
|
||||
:x="positionFlag(deployment)"
|
||||
y="0"
|
||||
width="134"
|
||||
:height="svgContainerHeight(deployment.tag)">
|
||||
<rect
|
||||
class="rect-text-metric deploy-info-rect rect-metric"
|
||||
x="1"
|
||||
y="1"
|
||||
rx="2"
|
||||
width="132"
|
||||
:height="svgContainerHeight(deployment.tag) - 2">
|
||||
</rect>
|
||||
<text
|
||||
class="deploy-info-text text-metric-bold"
|
||||
transform="translate(5, 2)">
|
||||
Deployed
|
||||
</text>
|
||||
<!--The date info-->
|
||||
<g transform="translate(5, 20)">
|
||||
<text class="deploy-info-text">
|
||||
{{formatDate(deployment.time)}}
|
||||
</text>
|
||||
<text
|
||||
class="deploy-info-text text-metric-bold"
|
||||
x="62">
|
||||
{{formatTime(deployment.time)}}
|
||||
</text>
|
||||
</g>
|
||||
<line
|
||||
class="divider-line"
|
||||
x1="0"
|
||||
y1="38"
|
||||
x2="132"
|
||||
:y2="38"
|
||||
stroke="#000">
|
||||
</line>
|
||||
<!--Commit information-->
|
||||
<g transform="translate(5, 40)">
|
||||
<icon
|
||||
name="commit"
|
||||
:width="12"
|
||||
:height="12"
|
||||
:y="3">
|
||||
</icon>
|
||||
<a :xlink:href="deployment.commitUrl">
|
||||
<text
|
||||
class="deploy-info-text deploy-info-text-link"
|
||||
transform="translate(20, 2)">
|
||||
{{refText(deployment)}}
|
||||
</text>
|
||||
</a>
|
||||
</g>
|
||||
<!--Tag information-->
|
||||
<g
|
||||
transform="translate(5, 55)"
|
||||
v-if="deployment.tag">
|
||||
<icon
|
||||
name="label"
|
||||
:width="12"
|
||||
:height="12"
|
||||
:y="5">
|
||||
</icon>
|
||||
<a :xlink:href="deployment.tagUrl">
|
||||
<text
|
||||
class="deploy-info-text deploy-info-text-link"
|
||||
transform="translate(20, 2)"
|
||||
y="2">
|
||||
{{deployment.tag}}
|
||||
</text>
|
||||
</a>
|
||||
</g>
|
||||
</svg>
|
||||
</g>
|
||||
<svg
|
||||
height="0"
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<script>
|
||||
import { dateFormat, timeFormat } from '../../utils/date_time_formatters';
|
||||
import { formatRelevantDigits } from '../../../lib/utils/number_utils';
|
||||
import Icon from '../../../vue_shared/components/icon.vue';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -7,14 +9,15 @@
|
|||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
currentFlagPosition: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
currentData: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
deploymentFlagData: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
graphHeight: {
|
||||
type: Number,
|
||||
required: true,
|
||||
|
@ -23,71 +26,173 @@
|
|||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
realPixelRatio: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
showFlagContent: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
timeSeries: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
unitOfDisplay: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
currentDataIndex: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
legendTitle: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
circleColorRgb: '#8fbce8',
|
||||
};
|
||||
components: {
|
||||
Icon,
|
||||
},
|
||||
|
||||
computed: {
|
||||
formatTime() {
|
||||
return timeFormat(this.currentData.time);
|
||||
return this.deploymentFlagData ?
|
||||
timeFormat(this.deploymentFlagData.time) :
|
||||
timeFormat(this.currentData.time);
|
||||
},
|
||||
|
||||
formatDate() {
|
||||
return dateFormat(this.currentData.time);
|
||||
return this.deploymentFlagData ?
|
||||
dateFormat(this.deploymentFlagData.time) :
|
||||
dateFormat(this.currentData.time);
|
||||
},
|
||||
|
||||
calculatedHeight() {
|
||||
return this.graphHeight - this.graphHeightOffset;
|
||||
cursorStyle() {
|
||||
const xCoordinate = this.deploymentFlagData ?
|
||||
this.deploymentFlagData.xPos :
|
||||
this.currentXCoordinate;
|
||||
|
||||
const offsetTop = 20 * this.realPixelRatio;
|
||||
const offsetLeft = (70 + xCoordinate) * this.realPixelRatio;
|
||||
const height = (this.graphHeight - this.graphHeightOffset) * this.realPixelRatio;
|
||||
|
||||
return {
|
||||
top: `${offsetTop}px`,
|
||||
left: `${offsetLeft}px`,
|
||||
height: `${height}px`,
|
||||
};
|
||||
},
|
||||
|
||||
flagOrientation() {
|
||||
if (this.currentXCoordinate * this.realPixelRatio > 120) {
|
||||
return 'left';
|
||||
}
|
||||
return 'right';
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
seriesMetricValue(series) {
|
||||
const index = this.deploymentFlagData ?
|
||||
this.deploymentFlagData.seriesIndex :
|
||||
this.currentDataIndex;
|
||||
const value = series.values[index] &&
|
||||
series.values[index].value;
|
||||
if (isNaN(value)) {
|
||||
return '-';
|
||||
}
|
||||
return `${formatRelevantDigits(value)}${this.unitOfDisplay}`;
|
||||
},
|
||||
|
||||
seriesMetricLabel(index, series) {
|
||||
if (this.timeSeries.length < 2) {
|
||||
return this.legendTitle;
|
||||
}
|
||||
if (series.metricTag) {
|
||||
return series.metricTag;
|
||||
}
|
||||
return `series ${index + 1}`;
|
||||
},
|
||||
|
||||
strokeDashArray(type) {
|
||||
if (type === 'dashed') return '6, 3';
|
||||
if (type === 'dotted') return '3, 3';
|
||||
return null;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<g class="mouse-over-flag">
|
||||
<line
|
||||
class="selected-metric-line"
|
||||
:x1="currentXCoordinate"
|
||||
:y1="0"
|
||||
:x2="currentXCoordinate"
|
||||
:y2="calculatedHeight"
|
||||
transform="translate(-5, 20)">
|
||||
</line>
|
||||
<svg
|
||||
<div
|
||||
class="prometheus-graph-cursor"
|
||||
:style="cursorStyle"
|
||||
>
|
||||
<div
|
||||
v-if="showFlagContent"
|
||||
class="rect-text-metric"
|
||||
:x="currentFlagPosition"
|
||||
y="0">
|
||||
<rect
|
||||
class="rect-metric"
|
||||
x="4"
|
||||
y="1"
|
||||
rx="2"
|
||||
width="90"
|
||||
height="40"
|
||||
transform="translate(-3, 20)">
|
||||
</rect>
|
||||
<text
|
||||
class="text-metric text-metric-bold"
|
||||
x="16"
|
||||
y="35"
|
||||
transform="translate(-5, 20)">
|
||||
{{formatTime}}
|
||||
</text>
|
||||
<text
|
||||
class="text-metric"
|
||||
x="16"
|
||||
y="15"
|
||||
transform="translate(-5, 20)">
|
||||
{{formatDate}}
|
||||
</text>
|
||||
</svg>
|
||||
</g>
|
||||
class="prometheus-graph-flag popover"
|
||||
:class="flagOrientation"
|
||||
>
|
||||
<div class="arrow"></div>
|
||||
<div class="popover-title">
|
||||
<h5 v-if="this.deploymentFlagData">
|
||||
Deployed
|
||||
</h5>
|
||||
{{formatDate}} at
|
||||
<strong>{{formatTime}}</strong>
|
||||
</div>
|
||||
<div
|
||||
v-if="this.deploymentFlagData"
|
||||
class="popover-content deploy-meta-content"
|
||||
>
|
||||
<div>
|
||||
<icon
|
||||
name="commit"
|
||||
:size="12">
|
||||
</icon>
|
||||
<a :href="deploymentFlagData.commitUrl">
|
||||
{{deploymentFlagData.sha.slice(0, 8)}}
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
v-if="deploymentFlagData.tag">
|
||||
<icon
|
||||
name="label"
|
||||
:size="12">
|
||||
</icon>
|
||||
<a :href="deploymentFlagData.tagUrl">
|
||||
{{deploymentFlagData.ref}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="popover-content">
|
||||
<table>
|
||||
<tr
|
||||
v-for="(series, index) in timeSeries"
|
||||
:key="index"
|
||||
>
|
||||
<td>
|
||||
<svg width="15" height="6">
|
||||
<line
|
||||
:stroke="series.lineColor"
|
||||
:stroke-dasharray="strokeDashArray(series.lineStyle)"
|
||||
stroke-width="4"
|
||||
x1="0"
|
||||
x2="15"
|
||||
y1="2"
|
||||
y2="2">
|
||||
</line>
|
||||
</svg>
|
||||
</td>
|
||||
<td>{{seriesMetricLabel(index, series)}}</td>
|
||||
<td>
|
||||
<strong>{{seriesMetricValue(series)}}</strong>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -29,15 +29,18 @@ const mixins = {
|
|||
time.setSeconds(this.timeSeries[0].values[0].time.getSeconds());
|
||||
|
||||
if (xPos >= 0) {
|
||||
const seriesIndex = bisectDate(this.timeSeries[0].values, time, 1);
|
||||
|
||||
deploymentDataArray.push({
|
||||
id: deployment.id,
|
||||
time,
|
||||
sha: deployment.sha,
|
||||
commitUrl: `${this.projectPath}/commit/${deployment.sha}`,
|
||||
tag: deployment.tag,
|
||||
tagUrl: `${this.tagsPath}/${deployment.tag}`,
|
||||
tagUrl: deployment.tag ? `${this.tagsPath}/${deployment.ref.name}` : null,
|
||||
ref: deployment.ref.name,
|
||||
xPos,
|
||||
seriesIndex,
|
||||
showDeploymentFlag: false,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ const d3 = {
|
|||
timeYear,
|
||||
};
|
||||
|
||||
export const dateFormat = d3.time('%b %-d, %Y');
|
||||
export const dateFormat = d3.time('%a, %b %-d');
|
||||
export const timeFormat = d3.time('%-I:%M%p');
|
||||
export const dateFormatWithName = d3.time('%a, %b %-d');
|
||||
export const bisectDate = d3.bisector(d => d.time).left;
|
||||
|
|
|
@ -248,6 +248,73 @@
|
|||
}
|
||||
}
|
||||
|
||||
.prometheus-graph-cursor {
|
||||
position: absolute;
|
||||
background: $theme-gray-600;
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
.prometheus-graph-flag {
|
||||
display: block;
|
||||
min-width: 160px;
|
||||
|
||||
h5 {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
td {
|
||||
vertical-align: middle;
|
||||
|
||||
+ td {
|
||||
padding-left: 5px;
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
|
||||
.deploy-meta-content {
|
||||
border-bottom: 1px solid $white-dark;
|
||||
|
||||
svg {
|
||||
height: 15px;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
}
|
||||
|
||||
&.popover {
|
||||
&.left {
|
||||
left: auto;
|
||||
right: 0;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
&.right {
|
||||
left: 0;
|
||||
right: auto;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
> .arrow {
|
||||
top: 40px;
|
||||
}
|
||||
|
||||
> .popover-title,
|
||||
> .popover-content {
|
||||
padding: 5px 8px;
|
||||
font-size: 12px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.prometheus-svg-container {
|
||||
position: relative;
|
||||
height: 0;
|
||||
|
|
5
changelogs/unreleased/38030-add-graph-value-to-hover.yml
Normal file
5
changelogs/unreleased/38030-add-graph-value-to-hover.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Display graph values on hover within monitoring page
|
||||
merge_request: 16261
|
||||
author:
|
||||
type: changed
|
|
@ -11,155 +11,11 @@ const createComponent = (propsData) => {
|
|||
};
|
||||
|
||||
describe('MonitoringDeployment', () => {
|
||||
const reducedDeploymentData = [deploymentData[0]];
|
||||
reducedDeploymentData[0].ref = reducedDeploymentData[0].ref.name;
|
||||
reducedDeploymentData[0].xPos = 10;
|
||||
reducedDeploymentData[0].time = new Date(reducedDeploymentData[0].created_at);
|
||||
describe('Methods', () => {
|
||||
it('refText shows the ref when a tag is available', () => {
|
||||
reducedDeploymentData[0].tag = '1.0';
|
||||
const component = createComponent({
|
||||
showDeployInfo: false,
|
||||
deploymentData: reducedDeploymentData,
|
||||
graphWidth: 440,
|
||||
graphHeight: 300,
|
||||
graphHeightOffset: 120,
|
||||
});
|
||||
|
||||
expect(
|
||||
component.refText(reducedDeploymentData[0]),
|
||||
).toEqual(reducedDeploymentData[0].ref);
|
||||
});
|
||||
|
||||
it('refText shows the sha when no tag is available', () => {
|
||||
reducedDeploymentData[0].tag = null;
|
||||
const component = createComponent({
|
||||
showDeployInfo: false,
|
||||
deploymentData: reducedDeploymentData,
|
||||
graphHeight: 300,
|
||||
graphWidth: 440,
|
||||
graphHeightOffset: 120,
|
||||
});
|
||||
|
||||
expect(
|
||||
component.refText(reducedDeploymentData[0]),
|
||||
).toContain('f5bcd1');
|
||||
});
|
||||
|
||||
it('nameDeploymentClass creates a class with the prefix deploy-info-', () => {
|
||||
const component = createComponent({
|
||||
showDeployInfo: false,
|
||||
deploymentData: reducedDeploymentData,
|
||||
graphHeight: 300,
|
||||
graphWidth: 440,
|
||||
graphHeightOffset: 120,
|
||||
});
|
||||
|
||||
expect(
|
||||
component.nameDeploymentClass(reducedDeploymentData[0]),
|
||||
).toContain('deploy-info');
|
||||
});
|
||||
|
||||
it('transformDeploymentGroup translates an available deployment', () => {
|
||||
const component = createComponent({
|
||||
showDeployInfo: false,
|
||||
deploymentData: reducedDeploymentData,
|
||||
graphHeight: 300,
|
||||
graphWidth: 440,
|
||||
graphHeightOffset: 120,
|
||||
});
|
||||
|
||||
expect(
|
||||
component.transformDeploymentGroup(reducedDeploymentData[0]),
|
||||
).toContain('translate(11, 20)');
|
||||
});
|
||||
|
||||
it('hides the deployment flag', () => {
|
||||
reducedDeploymentData[0].showDeploymentFlag = false;
|
||||
const component = createComponent({
|
||||
showDeployInfo: true,
|
||||
deploymentData: reducedDeploymentData,
|
||||
graphWidth: 440,
|
||||
graphHeight: 300,
|
||||
graphHeightOffset: 120,
|
||||
});
|
||||
|
||||
expect(component.$el.querySelector('.js-deploy-info-box')).toBeNull();
|
||||
});
|
||||
|
||||
it('positions the flag to the left when the xPos is too far right', () => {
|
||||
reducedDeploymentData[0].showDeploymentFlag = false;
|
||||
reducedDeploymentData[0].xPos = 250;
|
||||
const component = createComponent({
|
||||
showDeployInfo: true,
|
||||
deploymentData: reducedDeploymentData,
|
||||
graphWidth: 440,
|
||||
graphHeight: 300,
|
||||
graphHeightOffset: 120,
|
||||
});
|
||||
|
||||
expect(
|
||||
component.positionFlag(reducedDeploymentData[0]),
|
||||
).toBeLessThan(0);
|
||||
});
|
||||
|
||||
it('shows the deployment flag', () => {
|
||||
reducedDeploymentData[0].showDeploymentFlag = true;
|
||||
const component = createComponent({
|
||||
showDeployInfo: true,
|
||||
deploymentData: reducedDeploymentData,
|
||||
graphHeight: 300,
|
||||
graphWidth: 440,
|
||||
graphHeightOffset: 120,
|
||||
});
|
||||
|
||||
expect(
|
||||
component.$el.querySelector('.js-deploy-info-box').style.display,
|
||||
).not.toEqual('display: none;');
|
||||
});
|
||||
|
||||
it('contains date, refs and the "deployed" text', () => {
|
||||
reducedDeploymentData[0].showDeploymentFlag = true;
|
||||
const component = createComponent({
|
||||
showDeployInfo: true,
|
||||
deploymentData: reducedDeploymentData,
|
||||
graphHeight: 300,
|
||||
graphWidth: 440,
|
||||
graphHeightOffset: 120,
|
||||
});
|
||||
|
||||
expect(
|
||||
component.$el.querySelectorAll('.deploy-info-text'),
|
||||
).toContainText('Deployed');
|
||||
|
||||
expect(
|
||||
component.$el.querySelectorAll('.deploy-info-text'),
|
||||
).toContainText('Wed, May 31');
|
||||
|
||||
expect(
|
||||
component.$el.querySelectorAll('.deploy-info-text'),
|
||||
).toContainText(component.refText(reducedDeploymentData[0]));
|
||||
});
|
||||
|
||||
it('contains a link to the commit contents', () => {
|
||||
reducedDeploymentData[0].showDeploymentFlag = true;
|
||||
const component = createComponent({
|
||||
showDeployInfo: true,
|
||||
deploymentData: reducedDeploymentData,
|
||||
graphHeight: 300,
|
||||
graphWidth: 440,
|
||||
graphHeightOffset: 120,
|
||||
});
|
||||
|
||||
expect(
|
||||
component.$el.querySelectorAll('.deploy-info-text-link')[0].parentElement.getAttribute('xlink:href'),
|
||||
).not.toEqual('');
|
||||
});
|
||||
|
||||
it('should contain a hidden gradient', () => {
|
||||
const component = createComponent({
|
||||
showDeployInfo: true,
|
||||
deploymentData: reducedDeploymentData,
|
||||
deploymentData,
|
||||
graphHeight: 300,
|
||||
graphWidth: 440,
|
||||
graphHeightOffset: 120,
|
||||
|
@ -168,11 +24,25 @@ describe('MonitoringDeployment', () => {
|
|||
expect(component.$el.querySelector('#shadow-gradient')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('transformDeploymentGroup translates an available deployment', () => {
|
||||
const component = createComponent({
|
||||
showDeployInfo: false,
|
||||
deploymentData,
|
||||
graphHeight: 300,
|
||||
graphWidth: 440,
|
||||
graphHeightOffset: 120,
|
||||
});
|
||||
|
||||
expect(
|
||||
component.transformDeploymentGroup({ xPos: 16 }),
|
||||
).toContain('translate(11, 20)');
|
||||
});
|
||||
|
||||
describe('Computed props', () => {
|
||||
it('calculatedHeight', () => {
|
||||
const component = createComponent({
|
||||
showDeployInfo: true,
|
||||
deploymentData: reducedDeploymentData,
|
||||
deploymentData,
|
||||
graphHeight: 300,
|
||||
graphWidth: 440,
|
||||
graphHeightOffset: 120,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import Vue from 'vue';
|
||||
import GraphFlag from '~/monitoring/components/graph/flag.vue';
|
||||
import { deploymentData } from '../mock_data';
|
||||
|
||||
const createComponent = (propsData) => {
|
||||
const Component = Vue.extend(GraphFlag);
|
||||
|
@ -9,11 +10,6 @@ const createComponent = (propsData) => {
|
|||
}).$mount();
|
||||
};
|
||||
|
||||
function getCoordinate(component, selector, coordinate) {
|
||||
const coordinateVal = component.$el.querySelector(selector).getAttribute(coordinate);
|
||||
return parseInt(coordinateVal, 10);
|
||||
}
|
||||
|
||||
const defaultValuesComponent = {
|
||||
currentXCoordinate: 200,
|
||||
currentYCoordinate: 100,
|
||||
|
@ -25,31 +21,111 @@ const defaultValuesComponent = {
|
|||
graphHeight: 300,
|
||||
graphHeightOffset: 120,
|
||||
showFlagContent: true,
|
||||
realPixelRatio: 1,
|
||||
timeSeries: [{
|
||||
values: [{
|
||||
time: new Date('2017-06-04T18:17:33.501Z'),
|
||||
value: '1.49609375',
|
||||
}],
|
||||
}],
|
||||
unitOfDisplay: 'ms',
|
||||
currentDataIndex: 0,
|
||||
legendTitle: 'Average',
|
||||
};
|
||||
|
||||
const deploymentFlagData = {
|
||||
...deploymentData[0],
|
||||
ref: deploymentData[0].ref.name,
|
||||
xPos: 10,
|
||||
time: new Date(deploymentData[0].created_at),
|
||||
};
|
||||
|
||||
describe('GraphFlag', () => {
|
||||
it('has a line and a circle located at the currentXCoordinate and currentYCoordinate', () => {
|
||||
const component = createComponent(defaultValuesComponent);
|
||||
let component;
|
||||
|
||||
expect(getCoordinate(component, '.selected-metric-line', 'x1'))
|
||||
.toEqual(component.currentXCoordinate);
|
||||
expect(getCoordinate(component, '.selected-metric-line', 'x2'))
|
||||
.toEqual(component.currentXCoordinate);
|
||||
it('has a line at the currentXCoordinate', () => {
|
||||
component = createComponent(defaultValuesComponent);
|
||||
|
||||
expect(component.$el.style.left)
|
||||
.toEqual(`${70 + component.currentXCoordinate}px`);
|
||||
});
|
||||
|
||||
it('has a SVG with the class rect-text-metric at the currentFlagPosition', () => {
|
||||
const component = createComponent(defaultValuesComponent);
|
||||
describe('Deployment flag', () => {
|
||||
it('shows a deployment flag when deployment data provided', () => {
|
||||
const deploymentFlagComponent = createComponent({
|
||||
...defaultValuesComponent,
|
||||
deploymentFlagData,
|
||||
});
|
||||
|
||||
const svg = component.$el.querySelector('.rect-text-metric');
|
||||
expect(svg.tagName).toEqual('svg');
|
||||
expect(parseInt(svg.getAttribute('x'), 10)).toEqual(component.currentFlagPosition);
|
||||
expect(
|
||||
deploymentFlagComponent.$el.querySelector('.popover-title'),
|
||||
).toContainText('Deployed');
|
||||
});
|
||||
|
||||
it('contains the ref when a tag is available', () => {
|
||||
const deploymentFlagComponent = createComponent({
|
||||
...defaultValuesComponent,
|
||||
deploymentFlagData: {
|
||||
...deploymentFlagData,
|
||||
sha: 'f5bcd1d9dac6fa4137e2510b9ccd134ef2e84187',
|
||||
tag: true,
|
||||
ref: '1.0',
|
||||
},
|
||||
});
|
||||
|
||||
expect(
|
||||
deploymentFlagComponent.$el.querySelector('.deploy-meta-content'),
|
||||
).toContainText('f5bcd1d9');
|
||||
|
||||
expect(
|
||||
deploymentFlagComponent.$el.querySelector('.deploy-meta-content'),
|
||||
).toContainText('1.0');
|
||||
});
|
||||
|
||||
it('does not contain the ref when a tag is unavailable', () => {
|
||||
const deploymentFlagComponent = createComponent({
|
||||
...defaultValuesComponent,
|
||||
deploymentFlagData: {
|
||||
...deploymentFlagData,
|
||||
sha: 'f5bcd1d9dac6fa4137e2510b9ccd134ef2e84187',
|
||||
tag: false,
|
||||
ref: '1.0',
|
||||
},
|
||||
});
|
||||
|
||||
expect(
|
||||
deploymentFlagComponent.$el.querySelector('.deploy-meta-content'),
|
||||
).toContainText('f5bcd1d9');
|
||||
|
||||
expect(
|
||||
deploymentFlagComponent.$el.querySelector('.deploy-meta-content'),
|
||||
).not.toContainText('1.0');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Computed props', () => {
|
||||
it('calculatedHeight', () => {
|
||||
const component = createComponent(defaultValuesComponent);
|
||||
beforeEach(() => {
|
||||
component = createComponent(defaultValuesComponent);
|
||||
});
|
||||
|
||||
expect(component.calculatedHeight).toEqual(180);
|
||||
it('formatTime', () => {
|
||||
expect(component.formatTime).toMatch(/\d:17PM/);
|
||||
});
|
||||
|
||||
it('formatDate', () => {
|
||||
expect(component.formatDate).toEqual('Sun, Jun 4');
|
||||
});
|
||||
|
||||
it('cursorStyle', () => {
|
||||
expect(component.cursorStyle).toEqual({
|
||||
top: '20px',
|
||||
left: '270px',
|
||||
height: '180px',
|
||||
});
|
||||
});
|
||||
|
||||
it('flagOrientation', () => {
|
||||
expect(component.flagOrientation).toEqual('left');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue