Merge branch 'dev' of https://git.mesalab.cn/cyber-narrator/cn-ui into dev
# Conflicts: # src/views/charts2/charts/networkOverview/NetworkOverviewLine.vue
This commit is contained in:
@@ -2,6 +2,8 @@ module.exports = {
|
|||||||
roots: [
|
roots: [
|
||||||
'<rootDir>/test'
|
'<rootDir>/test'
|
||||||
],
|
],
|
||||||
|
verbose: true,
|
||||||
|
setupFilesAfterEnv: ['<rootDir>/test/init.js'],
|
||||||
testMatch: [
|
testMatch: [
|
||||||
'<rootDir>/test/**/__tests__/**/*.{vue,js,jsx,ts,tsx}',
|
'<rootDir>/test/**/__tests__/**/*.{vue,js,jsx,ts,tsx}',
|
||||||
'<rootDir>/test/**/*.{spec,test}.{vue,js,jsx,ts,tsx}'
|
'<rootDir>/test/**/*.{spec,test}.{vue,js,jsx,ts,tsx}'
|
||||||
|
|||||||
14
src/Test.vue
14
src/Test.vue
@@ -1,21 +1,29 @@
|
|||||||
<template>
|
<template>
|
||||||
<span data-test="count">{{count}}</span>
|
<span test-id="count">{{count}}</span>
|
||||||
<button data-test="button" @click="click">click</button>
|
<span test-id="title">{{getData.title}}</span>
|
||||||
|
<button test-id="button" @click="click">click</button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
/* vue-jest的测试示例 */
|
/* vue-jest的测试示例 */
|
||||||
import VueRouter from 'vue-router'
|
import VueRouter from 'vue-router'
|
||||||
|
import axios from 'axios'
|
||||||
export default {
|
export default {
|
||||||
name: 'Test',
|
name: 'Test',
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
count: 0
|
count: 0,
|
||||||
|
getData: { id: 1, title: 'title' }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
click () {
|
click () {
|
||||||
this.count++
|
this.count++
|
||||||
|
},
|
||||||
|
async getPosts () {
|
||||||
|
axios.get('/api/posts').then(response => {
|
||||||
|
this.getData = response.data
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { hasButton } from '@/permission'
|
import { hasButton } from '@/permission'
|
||||||
import { dateFormatByAppearance } from '@/utils/date-util'
|
import { dateFormatByAppearance } from '@/utils/date-util'
|
||||||
import { storageKey } from '@/utils/constants'
|
|
||||||
export default {
|
export default {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
@@ -21,7 +20,9 @@ export default {
|
|||||||
query: false
|
query: false
|
||||||
},
|
},
|
||||||
timeout: null,
|
timeout: null,
|
||||||
debounceFunc: null
|
debounceFunc: null,
|
||||||
|
// 是否正在单元测试
|
||||||
|
isUnitTesting: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|||||||
@@ -1103,10 +1103,5 @@ export function getNameByEventType (type) {
|
|||||||
case 'high dns response time': {
|
case 'high dns response time': {
|
||||||
return 'dns response time'
|
return 'dns response time'
|
||||||
}
|
}
|
||||||
// 目前ui并未找到此类型,添加以防不测
|
|
||||||
case 'high http resopnse time':
|
|
||||||
default: {
|
|
||||||
return 'http response time'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,10 +17,11 @@
|
|||||||
<div :class="item.class"></div>
|
<div :class="item.class"></div>
|
||||||
<div class="mpackets-name">{{$t(item.name)}}</div>
|
<div class="mpackets-name">{{$t(item.name)}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="line-value-unit">
|
<div class="line-value-unit" :test-id="`tabContent${index}`">
|
||||||
<span class="line-value-unit-number">{{unitConvert(item.analysis.avg, unitTypes.number)[0]}}</span>
|
<span class="line-value-unit-number">{{unitConvert(item.analysis.avg, unitTypes.number)[0]}}</span>
|
||||||
<span class="line-value-unit-number2">
|
<span class="line-value-unit-number2">
|
||||||
<span>{{unitConvert(item.analysis.avg, unitTypes.number)[1]}}</span><span v-if="item.unitType">{{item.unitType}}</span>
|
<span>{{unitConvert(item.analysis.avg, unitTypes.number)[1]}}</span>
|
||||||
|
<span v-if="item.unitType">{{item.unitType}}</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -46,7 +47,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div style="height: calc(100% - 74px); position: relative">
|
<div style="height: calc(100% - 74px); position: relative">
|
||||||
<chart-no-data v-if="isNoData && !showError"></chart-no-data>
|
<chart-no-data v-if="isNoData && !showError"></chart-no-data>
|
||||||
<div class="chart-drawing" v-show="showMarkLine && !isNoData && !showError" id="overviewLineChart"></div>
|
<div class="chart-drawing" v-show="showMarkLine && !isNoData && !showError" ref="overviewLineChart"></div>
|
||||||
<!-- todo 后续改动,此处为框选返回-->
|
<!-- todo 后续改动,此处为框选返回-->
|
||||||
<!-- <div id="brushBtn" style="position: absolute;left: 0;top: 0;" v-show="mouseDownFlag">-->
|
<!-- <div id="brushBtn" style="position: absolute;left: 0;top: 0;" v-show="mouseDownFlag">-->
|
||||||
<!-- <el-button @click.stop="backBrushHistory">返回</el-button>-->
|
<!-- <el-button @click.stop="backBrushHistory">返回</el-button>-->
|
||||||
@@ -63,7 +64,7 @@ import { unitTypes, chartColor3, chartColor4 } from '@/utils/constants.js'
|
|||||||
import { ref, shallowRef } from 'vue'
|
import { ref, shallowRef } from 'vue'
|
||||||
import { stackedLineTooltipFormatter } from '@/views/charts/charts/tools'
|
import { stackedLineTooltipFormatter } from '@/views/charts/charts/tools'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import { get } from '@/utils/http'
|
import axios from 'axios'
|
||||||
import { api } from '@/utils/api'
|
import { api } from '@/utils/api'
|
||||||
import { getSecond } from '@/utils/date-util'
|
import { getSecond } from '@/utils/date-util'
|
||||||
import ChartNoData from '@/views/charts/charts/ChartNoData'
|
import ChartNoData from '@/views/charts/charts/ChartNoData'
|
||||||
@@ -205,7 +206,8 @@ export default {
|
|||||||
}
|
}
|
||||||
this.toggleLoading(true)
|
this.toggleLoading(true)
|
||||||
|
|
||||||
get(api.netWorkOverview.totalTrafficAnalysis, params).then((res) => {
|
axios.get(api.netWorkOverview.totalTrafficAnalysis, { params: params }).then(response => {
|
||||||
|
const res = response.data
|
||||||
this.errorMsg = res.message
|
this.errorMsg = res.message
|
||||||
|
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
@@ -260,163 +262,163 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
echartsInit (echartsData, show) {
|
echartsInit (echartsData, show) {
|
||||||
if (this.lineTab) {
|
// echarts内容在单元测试时不执行
|
||||||
this.handleActiveBar()
|
if (!this.isUnitTesting) {
|
||||||
echartsData = echartsData.filter(t => t.show === true && t.invertTab === false)
|
if (this.lineTab) {
|
||||||
} else {
|
this.handleActiveBar()
|
||||||
echartsData = echartsData.filter(t => t.show === true)
|
echartsData = echartsData.filter(t => t.show === true && t.invertTab === false)
|
||||||
}
|
} else {
|
||||||
const _this = this
|
echartsData = echartsData.filter(t => t.show === true)
|
||||||
// !this.myChart && (this.myChart = echarts.init(dom))
|
|
||||||
// 此处为验证是否因dom未销毁,导致图表出错,后续可能会改
|
|
||||||
let dom = null
|
|
||||||
dom = document.getElementById('overviewLineChart')
|
|
||||||
|
|
||||||
this.chartOption = stackedLineChartOption
|
|
||||||
const chartOption = this.chartOption.series[0]
|
|
||||||
this.chartOption.series = echartsData.map((t, i) => {
|
|
||||||
return {
|
|
||||||
...chartOption,
|
|
||||||
name: t.name,
|
|
||||||
lineStyle: {
|
|
||||||
color: chartColor3[t.positioning],
|
|
||||||
width: 1
|
|
||||||
},
|
|
||||||
stack: t.name !== 'network.total' ? 'network.total' : '',
|
|
||||||
symbolSize: function (value) {
|
|
||||||
return _this.symbolSizeSortChange(i, value[0])
|
|
||||||
},
|
|
||||||
emphasis: {
|
|
||||||
itemStyle: {
|
|
||||||
borderColor: chartColor4[t.positioning],
|
|
||||||
borderWidth: 2,
|
|
||||||
shadowColor: chartColor4[t.positioning],
|
|
||||||
shadowBlur: this.sizes[t.positioning] + 2
|
|
||||||
}
|
|
||||||
},
|
|
||||||
areaStyle: {
|
|
||||||
opacity: 0.1,
|
|
||||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
|
||||||
{
|
|
||||||
offset: 0,
|
|
||||||
color: chartColor3[t.positioning]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
offset: 1,
|
|
||||||
color: chartColor3[t.positioning]
|
|
||||||
}
|
|
||||||
])
|
|
||||||
},
|
|
||||||
data: t.data.map(v => [Number(v[0]) * 1000, Number(v[1]), 'number']),
|
|
||||||
markLine: {
|
|
||||||
silent: true,
|
|
||||||
lineStyle: {
|
|
||||||
color: '#B4B1A8'
|
|
||||||
},
|
|
||||||
symbol: 'none',
|
|
||||||
label: {
|
|
||||||
formatter (params) {
|
|
||||||
const arr = unitConvert(params.value, unitTypes.number).join('')
|
|
||||||
return _this.lineRefer + '(' + arr + echartsData[0].unitType + ')'
|
|
||||||
},
|
|
||||||
position: 'insideStartTop',
|
|
||||||
color: '#717171',
|
|
||||||
fontFamily: 'NotoSansSChineseRegular'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
const _this = this
|
||||||
if (!show) {
|
// !this.myChart && (this.myChart = echarts.init(dom))
|
||||||
this.chartOption.series.forEach((t) => {
|
// 此处为验证是否因dom未销毁,导致图表出错,后续可能会改
|
||||||
t.markLine.label.show = false
|
this.chartOption = stackedLineChartOption
|
||||||
t.markLine = []
|
const chartOption = this.chartOption.series[0]
|
||||||
})
|
this.chartOption.series = echartsData.map((t, i) => {
|
||||||
}
|
return {
|
||||||
if (this.lineRefer === 'Average' && show) {
|
...chartOption,
|
||||||
this.chartOption.series.forEach((t, i) => {
|
name: t.name,
|
||||||
t.markLine.label.show = true
|
lineStyle: {
|
||||||
t.markLine.data = [
|
color: chartColor3[t.positioning],
|
||||||
{
|
width: 1
|
||||||
yAxis: echartsData[i].analysis.avg
|
},
|
||||||
}
|
stack: t.name !== 'network.total' ? 'network.total' : '',
|
||||||
]
|
symbolSize: function (value) {
|
||||||
})
|
return _this.symbolSizeSortChange(i, value[0])
|
||||||
} else if (this.lineRefer === '95th Percentile' && show) {
|
},
|
||||||
this.chartOption.series.forEach((t, i) => {
|
emphasis: {
|
||||||
t.markLine.label.show = true
|
itemStyle: {
|
||||||
t.markLine.data = [
|
borderColor: chartColor4[t.positioning],
|
||||||
{ yAxis: echartsData[i].analysis.p95 }
|
borderWidth: 2,
|
||||||
]
|
shadowColor: chartColor4[t.positioning],
|
||||||
})
|
shadowBlur: this.sizes[t.positioning] + 2
|
||||||
} else if (this.lineRefer === 'Maximum' && show) {
|
|
||||||
this.chartOption.series.forEach((t, i) => {
|
|
||||||
t.markLine.label.show = true
|
|
||||||
t.markLine.data = [
|
|
||||||
{ yAxis: echartsData[i].analysis.max }
|
|
||||||
]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.chartOption.tooltip.formatter = (params) => {
|
|
||||||
params.forEach(t => {
|
|
||||||
t.seriesName = this.$t(t.seriesName)
|
|
||||||
this.mpackets.forEach(e => {
|
|
||||||
if (this.$t(e.name) === t.seriesName) {
|
|
||||||
t.borderColor = chartColor3[e.positioning]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
return stackedLineTooltipFormatter(params)
|
|
||||||
}
|
|
||||||
this.showMarkLine = true
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.myChart = echarts.init(dom)
|
|
||||||
this.myChart.setOption(this.chartOption)
|
|
||||||
// 设置参见官网:https://echarts.apache.org/zh/api.html#action.brush.brush
|
|
||||||
this.myChart.dispatchAction({
|
|
||||||
// 刷选模式的开关。使用此 action 可将当前鼠标变为可刷选状态。事实上,点击 toolbox 中的 brush 按钮时,就是通过这个 action,将当前普通鼠标变为刷选器的。
|
|
||||||
type: 'takeGlobalCursor',
|
|
||||||
// 如果想变为“可刷选状态”,必须设置。不设置则会关闭“可刷选状态”。
|
|
||||||
key: 'brush',
|
|
||||||
brushOption: {
|
|
||||||
// 参见 brush 组件的 brushType。如果设置为 false 则关闭“可刷选状态”。
|
|
||||||
brushType: 'lineX',
|
|
||||||
xAxisIndex: 'all',
|
|
||||||
// 单击清除选框
|
|
||||||
brushMode: 'single',
|
|
||||||
// 选择完毕再返回所选数据
|
|
||||||
throttleType: 'debounce'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const self = this
|
|
||||||
|
|
||||||
this.myChart.on('brushEnd', function (params) {
|
|
||||||
self.myChart.dispatchAction({
|
|
||||||
type: 'brush',
|
|
||||||
areas: [] // 删除选框
|
|
||||||
})
|
|
||||||
if (!self.mouseDownFlag) {
|
|
||||||
// 避免点击空白区域报错
|
|
||||||
if (params.areas !== undefined && params.areas.length > 0) {
|
|
||||||
self.brushHistory.unshift({
|
|
||||||
startTime: _.cloneDeep(self.timeFilter.startTime) * 1000,
|
|
||||||
endTime: _.cloneDeep(self.timeFilter.endTime) * 1000
|
|
||||||
})
|
|
||||||
|
|
||||||
const rangeObj = {
|
|
||||||
startTime: Math.ceil(params.areas[0].coordRange[0]),
|
|
||||||
endTime: Math.ceil(params.areas[0].coordRange[1])
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
// todo 目前暂定框选最小范围为5分钟,后续可能会变动
|
areaStyle: {
|
||||||
if (rangeObj.endTime - rangeObj.startTime < 5 * 60 * 1000) {
|
opacity: 0.1,
|
||||||
rangeObj.startTime = rangeObj.endTime - 5 * 60 * 1000
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||||
|
{
|
||||||
|
offset: 0,
|
||||||
|
color: chartColor3[t.positioning]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offset: 1,
|
||||||
|
color: chartColor3[t.positioning]
|
||||||
|
}
|
||||||
|
])
|
||||||
|
},
|
||||||
|
data: t.data.map(v => [Number(v[0]) * 1000, Number(v[1]), 'number']),
|
||||||
|
markLine: {
|
||||||
|
silent: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: '#B4B1A8'
|
||||||
|
},
|
||||||
|
symbol: 'none',
|
||||||
|
label: {
|
||||||
|
formatter (params) {
|
||||||
|
const arr = unitConvert(params.value, unitTypes.number).join('')
|
||||||
|
return _this.lineRefer + '(' + arr + echartsData[0].unitType + ')'
|
||||||
|
},
|
||||||
|
position: 'insideStartTop',
|
||||||
|
color: '#717171',
|
||||||
|
fontFamily: 'NotoSansSChineseRegular'
|
||||||
}
|
}
|
||||||
_this.$store.commit('setRangeEchartsData', rangeObj)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
if (!show) {
|
||||||
|
this.chartOption.series.forEach((t) => {
|
||||||
|
t.markLine.label.show = false
|
||||||
|
t.markLine = []
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (this.lineRefer === 'Average' && show) {
|
||||||
|
this.chartOption.series.forEach((t, i) => {
|
||||||
|
t.markLine.label.show = true
|
||||||
|
t.markLine.data = [
|
||||||
|
{
|
||||||
|
yAxis: echartsData[i].analysis.avg
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
} else if (this.lineRefer === '95th Percentile' && show) {
|
||||||
|
this.chartOption.series.forEach((t, i) => {
|
||||||
|
t.markLine.label.show = true
|
||||||
|
t.markLine.data = [
|
||||||
|
{ yAxis: echartsData[i].analysis.p95 }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
} else if (this.lineRefer === 'Maximum' && show) {
|
||||||
|
this.chartOption.series.forEach((t, i) => {
|
||||||
|
t.markLine.label.show = true
|
||||||
|
t.markLine.data = [
|
||||||
|
{ yAxis: echartsData[i].analysis.max }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.chartOption.tooltip.formatter = (params) => {
|
||||||
|
params.forEach(t => {
|
||||||
|
t.seriesName = this.$t(t.seriesName)
|
||||||
|
this.mpackets.forEach(e => {
|
||||||
|
if (this.$t(e.name) === t.seriesName) {
|
||||||
|
t.borderColor = chartColor3[e.positioning]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return stackedLineTooltipFormatter(params)
|
||||||
|
}
|
||||||
|
this.showMarkLine = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.myChart = echarts.init(this.$refs.overviewLineChart)
|
||||||
|
this.myChart.setOption(this.chartOption)
|
||||||
|
// 设置参见官网:https://echarts.apache.org/zh/api.html#action.brush.brush
|
||||||
|
this.myChart.dispatchAction({
|
||||||
|
// 刷选模式的开关。使用此 action 可将当前鼠标变为可刷选状态。事实上,点击 toolbox 中的 brush 按钮时,就是通过这个 action,将当前普通鼠标变为刷选器的。
|
||||||
|
type: 'takeGlobalCursor',
|
||||||
|
// 如果想变为“可刷选状态”,必须设置。不设置则会关闭“可刷选状态”。
|
||||||
|
key: 'brush',
|
||||||
|
brushOption: {
|
||||||
|
// 参见 brush 组件的 brushType。如果设置为 false 则关闭“可刷选状态”。
|
||||||
|
brushType: 'lineX',
|
||||||
|
xAxisIndex: 'all',
|
||||||
|
// 单击清除选框
|
||||||
|
brushMode: 'single',
|
||||||
|
// 选择完毕再返回所选数据
|
||||||
|
throttleType: 'debounce'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const self = this
|
||||||
|
|
||||||
|
this.myChart.on('brushEnd', function (params) {
|
||||||
|
self.myChart.dispatchAction({
|
||||||
|
type: 'brush',
|
||||||
|
areas: [] // 删除选框
|
||||||
|
})
|
||||||
|
if (!self.mouseDownFlag) {
|
||||||
|
// 避免点击空白区域报错
|
||||||
|
if (params.areas !== undefined && params.areas.length > 0) {
|
||||||
|
self.brushHistory.unshift({
|
||||||
|
startTime: _.cloneDeep(self.timeFilter.startTime) * 1000,
|
||||||
|
endTime: _.cloneDeep(self.timeFilter.endTime) * 1000
|
||||||
|
})
|
||||||
|
|
||||||
|
const rangeObj = {
|
||||||
|
startTime: Math.ceil(params.areas[0].coordRange[0]),
|
||||||
|
endTime: Math.ceil(params.areas[0].coordRange[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo 目前暂定框选最小范围为5分钟,后续可能会变动
|
||||||
|
if (rangeObj.endTime - rangeObj.startTime < 5 * 60 * 1000) {
|
||||||
|
rangeObj.startTime = rangeObj.endTime - 5 * 60 * 1000
|
||||||
|
}
|
||||||
|
_this.$store.commit('setRangeEchartsData', rangeObj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
activeChange (item, index) {
|
activeChange (item, index) {
|
||||||
if (this.isNoData) return
|
if (this.isNoData) return
|
||||||
@@ -489,32 +491,34 @@ export default {
|
|||||||
referenceSelectChange (val) {
|
referenceSelectChange (val) {
|
||||||
this.lineRefer = val
|
this.lineRefer = val
|
||||||
let echartsData
|
let echartsData
|
||||||
const chartOption = this.myChart.getOption()
|
|
||||||
if (this.lineTab) {
|
if (this.lineTab) {
|
||||||
echartsData = this.mpackets.filter(t => t.show === true && t.invertTab === false)
|
echartsData = this.mpackets.filter(t => t.show === true && t.invertTab === false)
|
||||||
} else {
|
} else {
|
||||||
echartsData = this.mpackets.filter(t => t.show === true)
|
echartsData = this.mpackets.filter(t => t.show === true)
|
||||||
}
|
}
|
||||||
if (this.lineRefer === 'Average' && this.showMarkLine) {
|
if (!this.isUnitTesting) {
|
||||||
chartOption.series.forEach((t, i) => {
|
const chartOption = this.myChart.getOption()
|
||||||
if (t.name === echartsData[0].name) {
|
if (this.lineRefer === 'Average' && this.showMarkLine) {
|
||||||
t.markLine.data = [{ yAxis: echartsData[0].analysis.avg }]
|
chartOption.series.forEach((t, i) => {
|
||||||
}
|
if (t.name === echartsData[0].name) {
|
||||||
})
|
t.markLine.data = [{ yAxis: echartsData[0].analysis.avg }]
|
||||||
} else if (this.lineRefer === '95th Percentile' && this.showMarkLine) {
|
}
|
||||||
chartOption.series.forEach((t, i) => {
|
})
|
||||||
if (t.name === echartsData[0].name) {
|
} else if (this.lineRefer === '95th Percentile' && this.showMarkLine) {
|
||||||
t.markLine.data = [{ yAxis: echartsData[0].analysis.p95 }]
|
chartOption.series.forEach((t, i) => {
|
||||||
}
|
if (t.name === echartsData[0].name) {
|
||||||
})
|
t.markLine.data = [{ yAxis: echartsData[0].analysis.p95 }]
|
||||||
} else if (this.lineRefer === 'Maximum' && this.showMarkLine) {
|
}
|
||||||
chartOption.series.forEach((t, i) => {
|
})
|
||||||
if (t.name === echartsData[0].name) {
|
} else if (this.lineRefer === 'Maximum' && this.showMarkLine) {
|
||||||
t.markLine.data = [{ yAxis: echartsData[0].analysis.max }]
|
chartOption.series.forEach((t, i) => {
|
||||||
}
|
if (t.name === echartsData[0].name) {
|
||||||
})
|
t.markLine.data = [{ yAxis: echartsData[0].analysis.max }]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.myChart.setOption(chartOption)
|
||||||
}
|
}
|
||||||
this.myChart.setOption(chartOption)
|
|
||||||
},
|
},
|
||||||
symbolSizeSortChange (index, time) {
|
symbolSizeSortChange (index, time) {
|
||||||
const dataIntegrationArray = []
|
const dataIntegrationArray = []
|
||||||
|
|||||||
@@ -1,34 +1,51 @@
|
|||||||
import Test from '../src/Test'
|
import Test from '../src/Test'
|
||||||
import { mount } from '@vue/test-utils'
|
import { mount } from '@vue/test-utils'
|
||||||
|
import { getNameByEventType } from '@/utils/tools'
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
// 模拟vue-router库,否则组件中引用vue-router的代码报错
|
// 模拟的axios返回数据
|
||||||
jest.mock('vue-router', () => {
|
const mockPostList = { data: { id: 2, title: 'title2' } }
|
||||||
return {
|
|
||||||
useRouter: function () { return { currentRoute: '/' } }
|
describe('单元测试demo', () => {
|
||||||
}
|
test('Vue组件--点击按钮后count的值+1', async () => {
|
||||||
})
|
// 加载vue组件,获得实例
|
||||||
test('点击按钮后count的值+1', async () => {
|
const wrapper = mount(Test)
|
||||||
// 加载vue组件,获得实例
|
// 取到文本和按钮的dom
|
||||||
const wrapper = mount(Test)
|
const textNode = await wrapper.get('[test-id="count"]')
|
||||||
|
const button = await wrapper.get('[test-id="button"]')
|
||||||
// 取到文本和按钮的dom
|
// 断言文本dom的内容是否是'0'
|
||||||
const textNode = await wrapper.get('[data-test="count"]')
|
expect(textNode.text()).toContain('0')
|
||||||
const button = await wrapper.get('[data-test="button"]')
|
// 模拟按钮dom点击,执行click()方法
|
||||||
// 断言文本dom的内容是否是'0'
|
await button.trigger('click')
|
||||||
expect(textNode.text()).toContain('0')
|
// 断言点击按钮后文本dom的内容是否是'1'
|
||||||
// 模拟按钮dom点击,执行click()方法
|
expect(textNode.text()).toContain('1')
|
||||||
await button.trigger('click')
|
// 再次点击
|
||||||
// 断言点击按钮后文本dom的内容是否是'1'
|
await button.trigger('click')
|
||||||
expect(textNode.text()).toContain('1')
|
// 断言点击按钮后文本dom的内容是否是'2'
|
||||||
// 再次点击
|
expect(textNode.text()).toBe('2')
|
||||||
await button.trigger('click')
|
|
||||||
// 断言点击按钮后文本dom的内容是否是'2'
|
/* 更多断言类型:https://jestjs.io/zh-Hans/docs/expect */
|
||||||
expect(textNode.text()).toContain('2')
|
})
|
||||||
|
|
||||||
// 通过wrapper.vm.xxx直接执行click方法、获取data的数据
|
test('Vue组件--直接获取vue实例中的data和method', async () => {
|
||||||
expect(wrapper.vm.count).toEqual(2)
|
// 模拟axios返回数据
|
||||||
await wrapper.vm.click()
|
axios.get.mockResolvedValue(mockPostList)
|
||||||
expect(wrapper.vm.count).toEqual(3)
|
// 加载vue组件,获得实例
|
||||||
|
const wrapper = mount(Test)
|
||||||
// 更多断言类型:https://jestjs.io/zh-Hans/docs/expect
|
const textNode2 = await wrapper.get('[test-id="title"]')
|
||||||
|
// 通过wrapper.vm.xxx直接执行click方法、获取data的数据
|
||||||
|
expect(wrapper.vm.count).toEqual(0)
|
||||||
|
await wrapper.vm.click()
|
||||||
|
expect(wrapper.vm.count).toBe(1)
|
||||||
|
|
||||||
|
expect(textNode2.text()).toEqual('title')
|
||||||
|
await wrapper.vm.getPosts()
|
||||||
|
await wrapper.vm.$nextTick(() => {
|
||||||
|
expect(textNode2.text()).toBe('title2')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('js方法--getNameByEventType', async () => {
|
||||||
|
expect(getNameByEventType('http error')).toBe('http error ratio')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
36
test/init.js
Normal file
36
test/init.js
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import 'jest-canvas-mock'
|
||||||
|
import axios from 'axios'
|
||||||
|
import { config } from '@vue/test-utils'
|
||||||
|
|
||||||
|
/* 开启测试 */
|
||||||
|
config.global.mocks.isUnitTesting = true
|
||||||
|
/* 初始化dayjs */
|
||||||
|
const dayjs = require('dayjs')
|
||||||
|
const utc = require('dayjs/plugin/utc')
|
||||||
|
const timezone = require('dayjs/plugin/timezone')
|
||||||
|
const advancedFormat = require('dayjs/plugin/advancedFormat')
|
||||||
|
const weekday = require('dayjs/plugin/weekday')
|
||||||
|
dayjs.extend(utc)
|
||||||
|
dayjs.extend(timezone)
|
||||||
|
dayjs.extend(advancedFormat)
|
||||||
|
dayjs.extend(weekday)
|
||||||
|
window.$dayJs = dayjs
|
||||||
|
|
||||||
|
/* 模拟vue-router库,否则组件中引用vue-router的代码报错 */
|
||||||
|
jest.mock('vue-router', () => {
|
||||||
|
return {
|
||||||
|
useRouter: function () { return { currentRoute: '/' } },
|
||||||
|
useRoute: function () { return { query: {} } },
|
||||||
|
createWebHashHistory: jest.fn(),
|
||||||
|
createRouter: jest.fn().mockReturnValue({
|
||||||
|
beforeEach: jest.fn()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/* 模拟axios */
|
||||||
|
jest.mock('axios')
|
||||||
|
/* 模拟$t */
|
||||||
|
config.global.mocks.$t = key => key
|
||||||
|
/* 消除warn */
|
||||||
|
jest.spyOn(console, 'warn').mockImplementation(() => {})
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
import NetworkOverviewLine from '@/views/charts2/charts/networkOverview/NetworkOverviewLine'
|
||||||
|
import { mount } from '@vue/test-utils'
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
const mockGet = {
|
||||||
|
data: {"status":200,"code":200,"success":true,"message":null,"formatType":"json","data":{"resultType":"object","result":[{"type":"bytes","totalBitsRate":{"values":[[1673247564,"96801019.52"]],"analysis":{"avg":"112042808.24","max":"301842105.76","min":"52096324","p95":"168089003.35199997"}},"inboundBitsRate":{"values":[[1673247564,"11814508.48"]],"analysis":{"avg":"18587597.36","max":"137528138.88","min":"3181142.88","p95":"49561521.447999954"}},"outboundBitsRate":{"values":[[1673247564,"84282965.52"]],"analysis":{"avg":"87557861.44","max":"290402258","min":"45337684.48","p95":"121041718.81199999"}},"internalBitsRate":{"values":[[1673247564,"9125.12"]],"analysis":{"avg":"278114.32","max":"2215460.48","min":"0","p95":"923494.5719999998"}},"throughBitsRate":{"values":[[1673247564,"694420.48"]],"analysis":{"avg":"5619235.12","max":"42455480.24","min":"262607.76","p95":"13559588.195999999"}},"other":{"values":[[1673247564,"0.00"]],"analysis":{"avg":"0.01","max":"0.08","min":"0.00","p95":"0.08"}}},{"type":"packets","totalPacketsRate":{"values":[[1673247564,"12077.53"]],"analysis":{"avg":"14062.37","max":"32840.42","min":"6564.17","p95":"20923.167999999987"}},"inboundPacketsRate":{"values":[[1673247564,"3865.58"]],"analysis":{"avg":"4241.61","max":"15460.03","min":"1918.22","p95":"8549.799999999997"}},"outboundPacketsRate":{"values":[[1673247564,"8118.89"]],"analysis":{"avg":"9170.98","max":"27134.58","min":"4510.25","p95":"13690.540999999996"}},"internalPacketsRate":{"values":[[1673247564,"15.89"]],"analysis":{"avg":"35.95","max":"276.47","min":"0.00","p95":"122.49749999999999"}},"throughPacketsRate":{"values":[[1673247564,"77.17"]],"analysis":{"avg":"613.82","max":"3768.56","min":"42.92","p95":"1279.757499999999"}},"other":{"values":[[1673247564,"0.00"]],"analysis":{"avg":"0","max":"0.01","min":"0.00","p95":"0.01"}}},{"type":"sessions","totalSessionsRate":{"values":[[1673247564,"29.92"]],"analysis":{"avg":"29.89","max":"29.92","min":"29.67","p95":"29.92"}}}]},"msg":"OK"}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('NetworkOverviewLine.vue测试', () => {
|
||||||
|
test('Metric=Bits/s', async () => {
|
||||||
|
// 模拟axios返回数据
|
||||||
|
axios.get.mockResolvedValue(mockGet)
|
||||||
|
// 加载vue组件,获得实例
|
||||||
|
const wrapper = mount(NetworkOverviewLine, {
|
||||||
|
propsData: {
|
||||||
|
timeFilter: {
|
||||||
|
dateRangeValue: -1,
|
||||||
|
startTime: 1673244000000,
|
||||||
|
endTime: 1673247600000
|
||||||
|
},
|
||||||
|
chart: {"id":1,"name":"network overview line","i18n":"","panelId":1,"pid":0,"type":102,"x":0,"y":0,"w":19,"h":6,"params":{},"cby":1,"ctime":"2022-07-06 16:59:22","uby":1,"utime":"2022-07-06 16:59:22","remark":"","state":1,"system":0,"buildIn":0,"uuser":{"id":1,"name":null,"username":"admin","salt":null,"lang":null,"theme":null,"lastLoginIp":null,"lastLoginTime":null,"ctime":null,"cby":null,"email":null,"mobile":null,"status":null,"source":null,"buildIn":null,"roleIds":null,"usergroupIds":null,"roles":null,"apiKeyId":null},"cuser":{"id":1,"name":null,"username":"admin","salt":null,"lang":null,"theme":null,"lastLoginIp":null,"lastLoginTime":null,"ctime":null,"cby":null,"email":null,"mobile":null,"status":null,"source":null,"buildIn":null,"roleIds":null,"usergroupIds":null,"roles":null,"apiKeyId":null},"children":[],"parent":null,"panel":{"id":1,"name":"Network Overview","i18n":null,"type":null,"params":null,"cby":null,"ctime":null,"uby":null,"utime":null,"remark":null,"state":null,"buildIn":null,"uuser":null,"cuser":null},"i":1,"category":"echarts","firstShow":false,"moved":false}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const textNode0 = await wrapper.get('[test-id="tabContent0"]')
|
||||||
|
const textNode1 = await wrapper.get('[test-id="tabContent1"]')
|
||||||
|
const textNode2 = await wrapper.get('[test-id="tabContent2"]')
|
||||||
|
// 延迟1秒等待渲染。使用wrapper.vm.$nextTick有时不管用
|
||||||
|
await new Promise(resolve => setTimeout(() => {
|
||||||
|
expect(textNode0.text()).toEqual('112.04Mbps')
|
||||||
|
expect(textNode1.text()).toEqual('18.59Mbps')
|
||||||
|
expect(textNode2.text()).toEqual('87.56Mbps')
|
||||||
|
resolve()
|
||||||
|
}, 1000))
|
||||||
|
})
|
||||||
|
test('Metric=Packets/s', async () => {
|
||||||
|
// 模拟axios返回数据
|
||||||
|
axios.get.mockResolvedValue(mockGet)
|
||||||
|
// 加载vue组件,获得实例
|
||||||
|
const wrapper = mount(NetworkOverviewLine, {
|
||||||
|
propsData: {
|
||||||
|
timeFilter: {
|
||||||
|
dateRangeValue: -1,
|
||||||
|
startTime: 1673244000000,
|
||||||
|
endTime: 1673247600000
|
||||||
|
},
|
||||||
|
metric: 'Packets/s',
|
||||||
|
chart: {"id":1,"name":"network overview line","i18n":"","panelId":1,"pid":0,"type":102,"x":0,"y":0,"w":19,"h":6,"params":{},"cby":1,"ctime":"2022-07-06 16:59:22","uby":1,"utime":"2022-07-06 16:59:22","remark":"","state":1,"system":0,"buildIn":0,"uuser":{"id":1,"name":null,"username":"admin","salt":null,"lang":null,"theme":null,"lastLoginIp":null,"lastLoginTime":null,"ctime":null,"cby":null,"email":null,"mobile":null,"status":null,"source":null,"buildIn":null,"roleIds":null,"usergroupIds":null,"roles":null,"apiKeyId":null},"cuser":{"id":1,"name":null,"username":"admin","salt":null,"lang":null,"theme":null,"lastLoginIp":null,"lastLoginTime":null,"ctime":null,"cby":null,"email":null,"mobile":null,"status":null,"source":null,"buildIn":null,"roleIds":null,"usergroupIds":null,"roles":null,"apiKeyId":null},"children":[],"parent":null,"panel":{"id":1,"name":"Network Overview","i18n":null,"type":null,"params":null,"cby":null,"ctime":null,"uby":null,"utime":null,"remark":null,"state":null,"buildIn":null,"uuser":null,"cuser":null},"i":1,"category":"echarts","firstShow":false,"moved":false}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const textNode0 = await wrapper.get('[test-id="tabContent0"]')
|
||||||
|
const textNode1 = await wrapper.get('[test-id="tabContent1"]')
|
||||||
|
const textNode2 = await wrapper.get('[test-id="tabContent2"]')
|
||||||
|
await new Promise(res => setTimeout(() => {
|
||||||
|
expect(textNode0.text()).toEqual('14.06Kpackets/s')
|
||||||
|
expect(textNode1.text()).toEqual('4.24Kpackets/s')
|
||||||
|
expect(textNode2.text()).toEqual('9.17Kpackets/s')
|
||||||
|
res()
|
||||||
|
}, 1000))
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user