yapi-plugin-pl-test-dashboard
Version:
YAPI自动化测试结果数据面板插件,支持在YAPI中通过数据可视化的方式查看自动化测试结果。
439 lines (406 loc) • 11.5 kB
JavaScript
import { Bar, Column, Pie, StackedColumn } from '@antv/g2plot'
import { DatePicker, Radio, Tabs } from 'antd'
import 'antd/dist/antd.css'
import axios from 'axios'
import React, { useEffect, useState } from 'react'
import {
getCurrentMonth,
getCurrentWeek,
getProjectId,
} from '../../../utils/index'
import './index.scss'
const { TabPane } = Tabs
const { RangePicker } = DatePicker
const TODAY = new Date(new Date().setHours(0, 0, 0, 0))
export default function TestResult() {
const [sourcePiePlot, setSourcePiePlot] = useState(null)
const [sourceBarPlot, setSourceBarPlot] = useState(null)
// 集合
const [setRateColumnPlot, setSetRateColumnPlot] = useState(null)
const [setCountColumnPlot, setSetCountColumnPlot] = useState(null)
// 用例
const [caseRateColumnPlot, setCaseRateColumnPlot] = useState(null)
const [caseCountColumnPlot, setCaseCountColumnPlot] = useState(null)
const [isSourceDataError, setIsSourceDataError] = useState(false)
const [isSetDataError, setIsSetDataError] = useState(false)
const [isCaseDataError, setIsCaseDataError] = useState(false)
const [selectDate, setSelectDate] = useState('day')
const [activeTabKey, setActiveTabKey] = useState('set')
const [startTime, setStartTime] = useState(TODAY.toISOString())
const [endTime, setEndTime] = useState(new Date().toISOString())
const [projectId, setProjectId] = useState('32')
//
// 改变时间
const handleChangeDateType = (e) => {
setSelectDate(e.target.value)
switch (e.target.value) {
case 'day':
setStartTime(TODAY.toISOString())
setEndTime(new Date().toISOString())
break
case 'week':
const weekDate = getCurrentWeek()
setStartTime(weekDate[0])
setEndTime(weekDate[1])
break
case 'month':
const monthDate = getCurrentMonth()
setStartTime(monthDate[0])
setEndTime(monthDate[1])
break
}
}
const tabOperations = () => {
return (
<div className="operations_content">
<Radio.Group
onChange={handleChangeDateType}
defaultValue={selectDate}
style={{ marginRight: '10px' }}
>
<Radio.Button value="day">今日</Radio.Button>
<Radio.Button value="week">本周</Radio.Button>
<Radio.Button value="month">本月</Radio.Button>
</Radio.Group>
<RangePicker
showTime
onChange={(value, dateString) => {
setSelectDate('')
const start = new Date(dateString[0])
const end = new Date(dateString[1])
setStartTime(start.toISOString())
setEndTime(end.toISOString())
}}
/>
</div>
)
}
const emptyPage = () => {
return (
<div className="empty_page">
<p className="empty_page-text">暂无数据</p>
</div>
)
}
// 初始化数据来源饼图数据
const initSourcePieChart = async () => {
setIsSourceDataError(false)
if (activeTabKey !== 'source') {
return
}
const result = await axios.get(
`/api/plugin/test/dashboard/source?projectId=${getProjectId()}&startTime=${startTime}&endTime=${endTime}`
)
if (result.data && result.data.errcode && result.data.errcode === 40011) {
setIsSourceDataError(true)
return
}
const { percent, count } = result.data
if ((percent && percent.length === 0) || (count && count.length === 0)) {
setIsSourceDataError(true)
return
}
if (sourcePiePlot || sourceBarPlot) {
sourcePiePlot.destroy()
sourceBarPlot.destroy()
}
const _sourcePiePlot = new Pie(document.getElementById('chartSourcePie'), {
forceFit: true,
title: {
visible: true,
text: '数据来源分析(通过率)',
},
color: ['#94b2f3', '#90d9b6', '#db8470'],
radius: 0.8,
data: percent,
angleField: 'value',
colorField: 'type',
label: {
visible: true,
type: 'inner',
formatter: (text, data, index) => {
const value = (data.percent * 100).toFixed(1)
return `${value}%`
},
},
})
_sourcePiePlot.render()
setSourcePiePlot(_sourcePiePlot)
const _sourceBarPlot = new Bar(document.getElementById('chartSourceBar'), {
title: {
visible: true,
text: '数据来源分析(次数)',
},
forceFit: true,
data: count,
xField: 'value',
yField: 'type',
barSize: 30,
xAxis: {
grid: {
visible: true,
},
},
})
_sourceBarPlot.render()
setSourceBarPlot(_sourceBarPlot)
}
// 初始化测试集合柱状图数据
const initSetBarChart = async () => {
setIsSetDataError(false)
if (activeTabKey !== 'set') {
return
}
const result = await axios.get(
`/api/plugin/test/dashboard/set?projectId=${getProjectId()}&startTime=${startTime}&endTime=${endTime}`
)
if (result.data && result.data.errcode && result.data.errcode === 40011) {
setIsSetDataError(true)
console.log(
'initSetBarChart -> Set data is error or empty',
isSetDataError
)
return
}
const { percent, count } = result.data
if ((percent && percent.length === 0) || (count && count.length === 0)) {
setIsSetDataError(true)
console.log(
'initSetBarChart -> Set data is error or empty',
isSetDataError
)
return
}
if (setRateColumnPlot || setCountColumnPlot) {
setRateColumnPlot.destroy()
setCountColumnPlot.destroy()
}
const _setRateColumnPlot = new Column(
document.getElementById('chartSetRateBar'),
{
title: {
visible: true,
text: '测试集合分析(通过率)',
},
forceFit: true,
padding: 'auto',
data: percent,
xField: 'type',
yField: 'value',
tooltip: {
formatter: (text, data, index) => {
const value = (data * 100).toFixed(1)
return {
name: text,
value: `${value}%`,
}
},
},
yAxis: {
label: {
visible: true,
formatter: (text, data, index) => {
const value = (data.value * 100).toFixed(1)
return `${value}%`
},
},
},
barSize: 30,
meta: {
type: {
alias: '测试集合',
},
value: {
alias: '通过率(%)',
},
},
}
)
_setRateColumnPlot.render()
setSetRateColumnPlot(_setRateColumnPlot)
const _setCountColumnPlot = new StackedColumn(
document.getElementById('chartSetStackColumn'),
{
title: {
visible: true,
text: '测试集合分析(次数)',
},
forceFit: true,
data: count,
padding: 'auto',
xField: 'type',
yField: 'value',
barSize: 30,
yAxis: {
min: 0,
},
meta: {
type: {
alias: '测试集合',
},
value: {
alias: '次数',
},
},
stackField: 'series',
}
)
_setCountColumnPlot.render()
setSetCountColumnPlot(_setCountColumnPlot)
}
// 初始化测试用例柱状图数据
const initAnalysisBarChart = async () => {
setIsCaseDataError(false)
if (activeTabKey !== 'analysis') {
return
}
const result = await axios.get(
`/api/plugin/test/dashboard/case?projectId=${getProjectId()}&startTime=${startTime}&endTime=${endTime}`
)
if (result.data && result.data.errcode && result.data.errcode === 40011) {
setIsCaseDataError(true)
return
}
const { percent, count } = result.data
if ((percent && percent.length === 0) || (count && count.length === 0)) {
setIsCaseDataError(true)
return
}
if (caseRateColumnPlot || caseCountColumnPlot) {
caseRateColumnPlot.destroy()
caseCountColumnPlot.destroy()
}
const _caseRateColumnPlot = new Column(
document.getElementById('chartAnalysisBar'),
{
title: {
visible: true,
text: '测试用例分析(通过率)',
},
forceFit: true,
padding: 'auto',
data: percent,
xField: 'type',
yField: 'value',
tooltip: {
formatter: (text, data, index) => {
const value = (data * 100).toFixed(1)
return {
name: text,
value: `${value}%`,
}
},
},
yAxis: {
label: {
visible: true,
formatter: (text, data, index) => {
const value = (data.value * 100).toFixed(1)
return `${value}%`
},
},
},
barSize: 30,
meta: {
type: {
alias: '测试用例',
},
value: {
alias: '通过率(%)',
},
},
}
)
_caseRateColumnPlot.render()
setCaseRateColumnPlot(_caseRateColumnPlot)
const _caseCountColumnPlot = new StackedColumn(
document.getElementById('chartAnalysisColumn'),
{
title: {
visible: true,
text: '测试用例分析(次数)',
},
forceFit: true,
data: count,
padding: 'auto',
xField: 'type',
yField: 'value',
barSize: 30,
yAxis: {
min: 0,
},
meta: {
type: {
alias: '测试用例',
},
value: {
alias: '次数',
},
},
stackField: 'series',
}
)
_caseCountColumnPlot.render()
setCaseCountColumnPlot(_caseCountColumnPlot)
}
const initData = () => {
switch (activeTabKey) {
case 'source':
initSourcePieChart()
break
case 'set':
initSetBarChart()
break
case 'analysis':
initAnalysisBarChart()
break
}
}
useEffect(() => {
initData()
}, [activeTabKey, selectDate])
return (
<Tabs
tabBarExtraContent={tabOperations()}
defaultActiveKey={activeTabKey}
activeKey={activeTabKey}
onChange={(key) => {
setActiveTabKey(key)
}}
>
<TabPane tab="测试集合分析" key="set">
{activeTabKey === 'set' &&
(isSetDataError ? (
emptyPage()
) : (
<div className="dashboard_content-set">
<div id="chartSetRateBar"></div>
<div id="chartSetStackColumn"></div>
</div>
))}
</TabPane>
<TabPane tab="测试用例分析" key="analysis">
{activeTabKey === 'analysis' &&
(isCaseDataError ? (
emptyPage()
) : (
<div className="dashboard_content-analysis">
<div id="chartAnalysisBar"></div>
<div id="chartAnalysisColumn"></div>
</div>
))}
</TabPane>
<TabPane tab="数据来源分析" key="source">
{activeTabKey === 'source' &&
(isSourceDataError ? (
emptyPage()
) : (
<div className="dashboard_content-source">
<div id="chartSourcePie"></div>
<div id="chartSourceBar"></div>
</div>
))}
</TabPane>
</Tabs>
)
}