提交 0ef1ca8b 编写于 作者: aaronchen2k2k's avatar aaronchen2k2k

submit test result to zentao

上级 ec514306
......@@ -126,9 +126,14 @@ type ZtfReport struct {
TestTool commConsts.UnitTestTool `json:"testTool"`
ProductId int `json:"productId,omitempty"`
TaskId int `json:"taskId,omitempty"`
ExecBy commConsts.ExecBy `json:"execBy,omitempty"`
ExecById int `json:"execById,omitempty"`
// run with ci tool
ZentaoData string `json:"zentaoData"`
BuildUrl string `json:"buildUrl"`
Pass int `json:"pass"`
Fail int `json:"fail"`
Skip int `json:"skip"`
......
......@@ -14,8 +14,8 @@ import (
)
type ConfigCtrl struct {
BaseCtrl
ProjectService *service.ProjectService `inject:""`
BaseCtrl
}
func NewConfigCtrl() *ConfigCtrl {
......
......@@ -11,6 +11,7 @@ import (
type FileCtrl struct {
FileService *service.FileService `inject:""`
BaseCtrl
}
func NewFileCtrl() *FileCtrl {
......
package controller
import (
commDomain "github.com/aaronchen2k/deeptest/internal/comm/domain"
"github.com/aaronchen2k/deeptest/internal/pkg/domain"
logUtils "github.com/aaronchen2k/deeptest/internal/pkg/lib/log"
"github.com/aaronchen2k/deeptest/internal/server/modules/v1/service"
"github.com/kataras/iris/v12"
)
type TestBugCtrl struct {
TestBugService *service.TestBugService `inject:""`
BaseCtrl
}
func NewTestBugCtrl() *TestBugCtrl {
return &TestBugCtrl{}
}
// Gen 生成缺陷
func (c *TestBugCtrl) Gen(ctx iris.Context) {
req := commDomain.ZtfBug{}
if err := ctx.ReadJSON(&req); err != nil {
logUtils.Errorf("参数验证失败,错误%s", err.Error())
ctx.JSON(domain.Response{Code: domain.SystemErr.Code, Data: nil, Msg: err.Error()})
return
}
err := c.TestBugService.Submit(req)
if err != nil {
ctx.JSON(domain.Response{
Code: c.ErrCode(err),
Data: nil,
})
return
}
ctx.JSON(domain.Response{Code: domain.NoErr.Code, Data: nil, Msg: domain.NoErr.Msg})
}
// Submit 提交
func (c *TestBugCtrl) Submit(ctx iris.Context) {
req := commDomain.ZtfBug{}
if err := ctx.ReadJSON(&req); err != nil {
logUtils.Errorf("参数验证失败,错误%s", err.Error())
ctx.JSON(domain.Response{Code: domain.SystemErr.Code, Data: nil, Msg: err.Error()})
return
}
err := c.TestBugService.Submit(req)
if err != nil {
ctx.JSON(domain.Response{
Code: c.ErrCode(err),
Data: nil,
})
return
}
ctx.JSON(domain.Response{Code: domain.NoErr.Code, Data: nil, Msg: domain.NoErr.Msg})
}
......@@ -10,7 +10,6 @@ import (
type TestExecCtrl struct {
TestExecService *service.TestExecService `inject:""`
BaseCtrl
}
......
package controller
import (
"github.com/aaronchen2k/deeptest/internal/pkg/domain"
logUtils "github.com/aaronchen2k/deeptest/internal/pkg/lib/log"
serverDomain "github.com/aaronchen2k/deeptest/internal/server/modules/v1/domain"
"github.com/aaronchen2k/deeptest/internal/server/modules/v1/service"
"github.com/kataras/iris/v12"
)
type TestResultCtrl struct {
TestResultService *service.TestResultService `inject:""`
BaseCtrl
}
func NewTestResultCtrl() *TestResultCtrl {
return &TestResultCtrl{}
}
// Submit 提交
func (c *TestResultCtrl) Submit(ctx iris.Context) {
projectPath := ctx.URLParam("currProject")
req := serverDomain.ZentaoResult{}
if err := ctx.ReadJSON(&req); err != nil {
logUtils.Errorf("参数验证失败,错误%s", err.Error())
ctx.JSON(domain.Response{Code: domain.SystemErr.Code, Data: nil, Msg: err.Error()})
return
}
if req.Seq == "" {
logUtils.Errorf("参数解析失败")
ctx.JSON(domain.Response{Code: domain.ParamErr.Code, Data: nil, Msg: domain.ParamErr.Msg})
return
}
err := c.TestResultService.Submit(req, projectPath)
if err != nil {
ctx.JSON(domain.Response{
Code: c.ErrCode(err),
Data: nil,
})
return
}
ctx.JSON(domain.Response{Code: domain.NoErr.Code, Data: nil, Msg: domain.NoErr.Msg})
}
package controller
import (
"github.com/kataras/iris/v12"
"github.com/aaronchen2k/deeptest/internal/pkg/domain"
logUtils "github.com/aaronchen2k/deeptest/internal/pkg/lib/log"
)
type TestCtrl struct {
}
func NewTestCtrl() *TestCtrl {
return &TestCtrl{}
}
func (c *TestCtrl) Test(ctx iris.Context) {
logUtils.Warn("测试")
ctx.JSON(domain.Response{Code: domain.NoErr.Code, Data: nil, Msg: domain.NoErr.Msg})
}
......@@ -29,3 +29,9 @@ type ZentaoTask struct {
Id int `json:"id"`
Name string `json:"name"`
}
type ZentaoResult struct {
Seq string `json:"seq"`
ProductId string `json:"productId"`
TaskId string `json:"taskId"`
}
......@@ -11,7 +11,6 @@ import (
)
type IndexModule struct {
TestModule *index.TestModule `inject:""`
FileModule *index.FileModule `inject:""`
ZentaoModule *index.ZentaoModule `inject:""`
......@@ -22,6 +21,8 @@ type IndexModule struct {
TestScriptModule *index.TestScriptModule `inject:""`
TestExecModule *index.TestExecModule `inject:""`
TestResultModule *index.TestResultModule `inject:""`
TestBugModule *index.TestBugModule `inject:""`
TestSuiteModule *index.TestSuiteModule `inject:""`
TestSetModule *index.TestSetModule `inject:""`
}
......@@ -42,7 +43,6 @@ func (m *IndexModule) Party() module.WebModule {
}
}
modules := []module.WebModule{
m.TestModule.Party(),
m.FileModule.Party(),
m.ZentaoModule.Party(),
......@@ -51,6 +51,8 @@ func (m *IndexModule) Party() module.WebModule {
m.ProjectModule.Party(),
m.TestScriptModule.Party(),
m.TestExecModule.Party(),
m.TestBugModule.Party(),
m.TestResultModule.Party(),
}
return module.NewModule(serverConfig.ApiPath, handler, modules...)
}
......@@ -2,22 +2,24 @@ package index
import (
"github.com/aaronchen2k/deeptest/internal/server/core/module"
"github.com/aaronchen2k/deeptest/internal/server/middleware"
"github.com/aaronchen2k/deeptest/internal/server/modules/v1/controller"
"github.com/kataras/iris/v12"
)
type TestModule struct {
TestCtrl *controller.TestCtrl `inject:""`
type TestBugModule struct {
TestBugCtrl *controller.TestBugCtrl `inject:""`
}
func NewTestModule() *TestModule {
return &TestModule{}
func NewTestBugModule() *TestBugModule {
return &TestBugModule{}
}
// Party 产品
func (m *TestModule) Party() module.WebModule {
// Party 测试结果
func (m *TestBugModule) Party() module.WebModule {
handler := func(index iris.Party) {
index.Get("/", m.TestCtrl.Test).Name = "测试"
index.Use(middleware.InitCheck())
index.Post("/{seq:string}", m.TestBugCtrl.Submit).Name = "提交缺陷"
}
return module.NewModule("/test", handler)
return module.NewModule("/bug", handler)
}
package index
import (
"github.com/aaronchen2k/deeptest/internal/server/core/module"
"github.com/aaronchen2k/deeptest/internal/server/middleware"
"github.com/aaronchen2k/deeptest/internal/server/modules/v1/controller"
"github.com/kataras/iris/v12"
)
type TestResultModule struct {
TestResultCtrl *controller.TestResultCtrl `inject:""`
}
func NewTestResultModule() *TestResultModule {
return &TestResultModule{}
}
// Party 测试结果
func (m *TestResultModule) Party() module.WebModule {
handler := func(index iris.Party) {
index.Use(middleware.InitCheck())
index.Post("/", m.TestResultCtrl.Submit).Name = "提交测试结果"
}
return module.NewModule("/result", handler)
}
package service
import (
commDomain "github.com/aaronchen2k/deeptest/internal/comm/domain"
)
type TestBugService struct {
}
func NewTestBugService() *TestBugService {
return &TestBugService{}
}
func (s *TestBugService) Submit(bug commDomain.ZtfBug) (err error) {
//zentaoUtils.CommitBug(bug)
return
}
......@@ -26,7 +26,7 @@ func (s *TestExecService) List(projectPath string) (ret []serverDomain.TestRepor
for _, seq := range reportFiles {
var summary serverDomain.TestReportSummary
report, err1 := analysisUtils.GetReport(projectPath, seq)
report, err1 := analysisUtils.ReadReport(projectPath, seq)
if err1 != nil { // ignore wrong json result
continue
}
......@@ -40,7 +40,7 @@ func (s *TestExecService) List(projectPath string) (ret []serverDomain.TestRepor
}
func (s *TestExecService) Get(projectPath string, seq string) (report commDomain.ZtfReport, err error) {
return analysisUtils.GetReport(projectPath, seq)
return analysisUtils.ReadReport(projectPath, seq)
}
func (s *TestExecService) Delete(projectPath string, seq string) (err error) {
......
package service
import (
serverDomain "github.com/aaronchen2k/deeptest/internal/server/modules/v1/domain"
analysisUtils "github.com/aaronchen2k/deeptest/internal/server/modules/v1/utils/analysis"
zentaoUtils "github.com/aaronchen2k/deeptest/internal/server/modules/v1/utils/zentao"
)
type TestResultService struct {
}
func NewTestResultService() *TestResultService {
return &TestResultService{}
}
func (s *TestResultService) Submit(result serverDomain.ZentaoResult, projectPath string) (err error) {
report, err := analysisUtils.ReadReport(projectPath, result.Seq)
if err != nil {
return
}
zentaoUtils.CommitResult(report, result, projectPath)
return
}
......@@ -20,7 +20,7 @@ func FilterCaseByResult(cases []string, req serverDomain.WsReq) (ret []string) {
}
func getCaseIdMapFromReport(req serverDomain.WsReq) (ret map[string]commConsts.ResultStatus, err error) {
report, err := GetReport(req.ProjectPath, req.Seq)
report, err := ReadReport(req.ProjectPath, req.Seq)
if err != nil {
logUtils.Errorf("fail to get case ids for %s %s", req.ProjectPath, req.Seq)
return
......
......@@ -22,7 +22,7 @@ func ListReport(projectPath string) (reportFiles []string) {
return
}
func GetReport(projectPath string, seq string) (report commDomain.ZtfReport, err error) {
func ReadReport(projectPath string, seq string) (report commDomain.ZtfReport, err error) {
pth := filepath.Join(projectPath, commConsts.LogDirName, seq, commConsts.ResultJson)
content := fileUtils.ReadFileBuf(pth)
......
package zentaoUtils
/*func CommitBug(bug commDomain.ZtfBug) (err error) {
bug := vari.CurrBug
stepIds := vari.CurrBugStepIds
conf := configUtils.ReadCurrConfig()
ok = Login(conf.Url, conf.Account, conf.Password)
if !ok {
msg = "login failed"
return
}
productId := bug.Product
bug.Steps = strings.Replace(bug.Steps, " ", " ", -1)
// bug-create-1-0-caseID=1,version=3,resultID=93,runID=0,stepIdList=9_12_
// bug-create-1-0-caseID=1,version=3,resultID=84,runID=6,stepIdList=9_12_,testtask=2,projectID=1,buildID=1
extras := fmt.Sprintf("caseID=%s,version=0,resultID=0,runID=0,stepIdList=%s",
bug.Case, stepIds)
// $productID, $branch = '', $extras = ''
params := ""
if vari.RequestType == constant.RequestTypePathInfo {
params = fmt.Sprintf("%s-0-%s", productId, extras)
} else {
params = fmt.Sprintf("productID=%s&branch=0&$extras=%s", productId, extras)
}
params = ""
url := conf.Url + zentaoUtils.GenApiUri("bug", "create", params)
body, ok := client.PostObject(url, bug, true)
if !ok {
msg = "post request failed"
return
}
json, err1 := simplejson.NewJson([]byte(body))
if err1 != nil {
ok = false
msg = "parse json failed"
return
}
msg, err2 := json.Get("message").String()
if err2 != nil {
ok = false
msg = "parse json failed"
return
}
if ok {
msg = i118Utils.Sprintf("success_to_report_bug", bug.Case)
return
} else {
return
}
}
func PrepareBug(resultDir string, caseIdStr string) (commDomain.ZtfBug, string) {
caseId, err := strconv.Atoi(caseIdStr)
if err != nil {
return model.Bug{}, ""
}
report := testingService.GetZTFTestReportForSubmit(resultDir)
for _, cs := range report.FuncResult {
if cs.Id != caseId {
continue
}
product := cs.ProductId
GetBugFiledOptions(product)
title := cs.Title
module := GetFirstNoEmptyVal(vari.ZenTaoBugFields.Modules)
typ := GetFirstNoEmptyVal(vari.ZenTaoBugFields.Categories)
openedBuild := map[string]string{"0": "trunk"}
severity := GetFirstNoEmptyVal(vari.ZenTaoBugFields.Severities)
priority := GetFirstNoEmptyVal(vari.ZenTaoBugFields.Priorities)
caseId := cs.Id
uid := uuid.NewV4().String()
caseVersion := "0"
oldTaskID := "0"
stepIds := ""
steps := make([]string, 0)
for _, step := range cs.Steps {
if !step.Status {
stepIds += step.Id + "_"
}
stepsContent := testingService.GetStepText(step)
steps = append(steps, stepsContent)
}
bug := model.Bug{Title: title,
Module: module, Type: typ, OpenedBuild: openedBuild, Severity: severity, Pri: priority,
Product: strconv.Itoa(product), Case: strconv.Itoa(caseId),
Steps: strings.Join(steps, "\n"),
Uid: uid, CaseVersion: caseVersion, OldTaskID: oldTaskID,
}
return bug, stepIds
}
return model.Bug{}, ""
}*/
package zentaoUtils
import (
commDomain "github.com/aaronchen2k/deeptest/internal/comm/domain"
httpUtils "github.com/aaronchen2k/deeptest/internal/pkg/lib/http"
i118Utils "github.com/aaronchen2k/deeptest/internal/pkg/lib/i118"
logUtils "github.com/aaronchen2k/deeptest/internal/pkg/lib/log"
serverDomain "github.com/aaronchen2k/deeptest/internal/server/modules/v1/domain"
configUtils "github.com/aaronchen2k/deeptest/internal/server/modules/v1/utils/config"
"github.com/bitly/go-simplejson"
"github.com/fatih/color"
"os"
"strconv"
"strings"
)
func CommitResult(report commDomain.ZtfReport, result serverDomain.ZentaoResult, projectPath string) {
report.ProductId, _ = strconv.Atoi(result.ProductId)
report.TaskId, _ = strconv.Atoi(result.TaskId)
// for ci tool
report.ZentaoData = os.Getenv("ZENTAO_DATA")
report.BuildUrl = os.Getenv("BUILD_URL")
config := configUtils.LoadByProjectPath(projectPath)
Login(config)
url := config.Url + GenApiUri("ci", "commitResult", "")
bytes, ok := httpUtils.Post(url, report, false)
if ok {
json, err1 := simplejson.NewJson(bytes)
if err1 == nil {
result, err2 := json.Get("result").String()
if err2 != nil || result != "success" {
ok = false
}
} else {
ok = false
}
}
msg := ""
if ok {
msg += color.GreenString(i118Utils.Sprintf("success_to_submit_test_result"))
} else {
msg = i118Utils.Sprintf("fail_to_submit_test_result")
if strings.Index(string(bytes), "login") > -1 {
msg = i118Utils.Sprintf("fail_to_login")
}
msg = color.RedString(msg)
}
logUtils.Infof(msg)
}
......@@ -241,7 +241,7 @@ func Login(config commDomain.ProjectConf) bool {
if ok {
if commConsts.Verbose {
logUtils.Infof(i118Utils.Sprintf("success_to_login"), bodyBytes)
logUtils.Infof(i118Utils.Sprintf("success_to_login"), string(bodyBytes))
}
} else {
logUtils.Errorf(i118Utils.Sprintf("fail_to_login"))
......
......@@ -27,7 +27,7 @@ import {useStore} from "vuex";
import {ProjectData} from "@/store/project";
import ProjectCreateForm from "@/views/component/project/create.vue";
import {createProject} from "@/services/project";
import {addClass, hideMenu, removeClass} from "@/utils/dom";
import {hideMenu} from "@/utils/dom";
interface RightTopProject {
projects: ComputedRef<any[]>;
......
<template>
<a-modal
:destroy-on-close="true"
:mask-closable="false"
title="新建项目"
:visible="visible"
:onCancel="onCancel"
>
<template #footer>
<a-button key="back" @click="() => onCancel()">取消</a-button>
<a-button key="submit" type="primary" @click="onFinish">确定</a-button>
</template>
<div>
<a-form :labelCol="{ span: 4 }" :wrapper-col="{span:20}">
<a-form-item label="项目路径" v-bind="validateInfos.path">
<a-input v-model:value="modelRef.path" placeholder="" />
</a-form-item>
<a-form-item label="项目类型" v-bind="validateInfos.type">
<a-select v-model:value="modelRef.type">
<a-select-option key="func" value="func">ZTF自动化</a-select-option>
<a-select-option key="unit" value="unit">单元测试</a-select-option>
</a-select>
</a-form-item>
</a-form>
</div>
</a-modal>
</template>
<script lang="ts">
import {defineComponent, onMounted, PropType, reactive, ref, Ref} from "vue";
import {Interpreter} from "@/views/config/data";
import {useI18n} from "vue-i18n";
import {Form} from "ant-design-vue";
import { validateInfos } from 'ant-design-vue/lib/form/useForm';
interface BugFormSetupData {
modelRef: Ref<Interpreter>
validateInfos: validateInfos
onFinish: () => Promise<void>;
}
export default defineComponent({
name: 'BugForm',
props: {
visible: {
type: Boolean,
required: true
},
onCancel: {
type: Function,
required: true
},
onSubmit: {
type: Function as PropType<(values: any) => void>,
required: true
}
},
components: {},
setup(props): BugFormSetupData {
const { t } = useI18n();
const modelRef = reactive<any>({path: '', type: 'func'})
const rulesRef = reactive({
path: [ { required: true, message: '请输入项目完整路径' } ],
type: [ { required: true, message: '请选择项目类型' } ],
});
const { validate, validateInfos } = Form.useForm(modelRef, rulesRef);
const onFinish = async () => {
console.log('onFinish')
validate().then(() => {
props.onSubmit(modelRef);
}).catch(err => { console.log('') })
}
onMounted(()=> {
console.log('onMounted')
})
return {
modelRef,
validateInfos,
onFinish
}
}
})
</script>
\ No newline at end of file
<template>
<a-modal
title="新建项目"
:destroy-on-close="true"
:mask-closable="false"
:visible="true"
:onCancel="onCancel"
>
<template #footer>
<a-button key="back" @click="() => onCancel()">取消</a-button>
<a-button key="submit" type="primary" @click="onFinish">确定</a-button>
</template>
<div>
<a-form :label-col="labelCol" :wrapper-col="wrapperCol">
<a-form-item label="产品" v-bind="validateInfos.productId">
<a-select v-model:value="modelRef.productId" @change="selectProduct">
<a-select-option key="" value="">&nbsp;</a-select-option>
<a-select-option v-for="item in products" :key="item.id" :value="item.id+''">{{item.name}}</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="任务" v-bind="validateInfos.taskId">
<a-select v-model:value="modelRef.taskId">
<a-select-option key="" value="">&nbsp;</a-select-option>
<a-select-option v-for="item in tasks" :key="item.id" :value="item.id+''">{{ item.name }}</a-select-option>
</a-select>
</a-form-item>
</a-form>
</div>
</a-modal>
</template>
<script lang="ts">
import {ComputedRef, defineComponent, onMounted, PropType, reactive, ref, Ref} from "vue";
import {Interpreter} from "@/views/config/data";
import { validateInfos } from 'ant-design-vue/lib/form/useForm';
import {message, Form} from 'ant-design-vue';
import {queryProduct, queryTask} from "@/services/zentao";
const useForm = Form.useForm;
interface ResultFormSetupData {
modelRef: Ref<Interpreter>
onFinish: () => Promise<void>;
labelCol: any
wrapperCol: any
rules: any
validate: any
validateInfos: validateInfos,
resetFields: () => void;
products: Ref<any[]>;
tasks: Ref<any[]>;
selectProduct: (item) => void;
}
export default defineComponent({
name: 'ResultForm',
props: {
onCancel: {
type: Function,
required: true
},
onSubmit: {
type: Function as PropType<(values: any) => void>,
required: true
}
},
components: {},
setup(props): ResultFormSetupData {
const rules = reactive({
productId: [
{ required: true, message: '请选择产品' },
],
taskId: [
{ required: true, message: '请选择任务' },
],
});
const modelRef = reactive<any>({})
let products = ref([])
let tasks = ref([])
const { resetFields, validate, validateInfos } = useForm(modelRef, rules);
const listProduct = () => {
queryProduct().then((jsn) => {
products.value = jsn.data
})
}
listProduct()
const selectProduct = (item) => {
if (!item) return
queryTask(item).then((jsn) => {
tasks.value = jsn.data
})
}
const onFinish = async () => {
console.log('onFinish', modelRef.value)
validate().then(() => {
props.onSubmit(modelRef);
}).catch(err => { console.log('') })
}
onMounted(()=> {
console.log('onMounted')
})
return {
labelCol: { span: 6 },
wrapperCol: { span: 16 },
rules,
validate,
validateInfos,
resetFields,
products,
tasks,
selectProduct,
modelRef,
onFinish,
}
}
})
</script>
\ No newline at end of file
import request from '@/utils/request';
const apiPath = 'file';
export async function listUserHome(parentDir): Promise<any> {
const params = {parentDir: parentDir}
return request({
url: `/${apiPath}/listDir`,
method: 'get',
params
});
}
......@@ -101,7 +101,7 @@ import {useRouter} from "vue-router";
import {momentTimeDef, percentDef} from "@/utils/datetime";
import {execByDef, resultStatusDef, testEnvDef, testTypeDef} from "@/utils/testing";
interface DesignExecutionPageSetupData {
interface UnitTestResultPageSetupData {
report: Ref;
columns: any[]
......@@ -120,8 +120,8 @@ interface DesignExecutionPageSetupData {
}
export default defineComponent({
name: 'ExecutionResultPage',
setup(): DesignExecutionPageSetupData {
name: 'UnitTestResultPage',
setup(): UnitTestResultPageSetupData {
const execBy = execByDef
const momentTime = momentTimeDef
const percent = percentDef
......
......@@ -2,11 +2,11 @@
<div class="indexlayout-main-conent">
<a-card :bordered="false">
<template #title>
执行结果详情
执行结果详情
</template>
<template #extra>
<div class="opt">
<a-button @click="submitResult()">提交结果到禅道</a-button>
<a-button @click="openResultForm()" type="primary">提交结果到禅道</a-button>
<a-button type="link" @click="() => back()">返回</a-button>
</div>
......@@ -27,20 +27,22 @@
<a-col :span="2" class="t-bord t-label-right">结束时间</a-col>
<a-col :span="4">{{ momentTime(report.endTime) }}</a-col>
<a-col :span="2" class="t-bord t-label-right">耗时</a-col>
<a-col :span="4">{{report.duration}}秒</a-col>
<a-col :span="4">{{ report.duration }}秒</a-col>
</a-row>
<a-row>
<a-col :span="2" class="t-bord t-label-right">用例数</a-col>
<a-col :span="4">{{ momentTime(report.startTime) }}</a-col>
<a-col :span="2" class="t-bord t-label-right">通过</a-col>
<a-col :span="4">{{report.pass}}({{percent(report.pass, report.total)}})</a-col>
<a-col :span="4">{{ report.pass }}({{ percent(report.pass, report.total) }})</a-col>
<a-col :span="2" class="t-bord t-label-right">失败</a-col>
<a-col :span="4">{{report.fail}}({{percent(report.fail, report.total)}})</a-col>
<a-col :span="4">{{ report.fail }}({{ percent(report.fail, report.total) }})</a-col>
<a-col :span="2" class="t-bord t-label-right">跳过</a-col>
<a-col :span="4">{{report.skip}}({{percent(report.skip, report.total)}})</a-col>
<a-col :span="4">{{ report.skip }}({{ percent(report.skip, report.total) }})</a-col>
</a-row>
<a-row><a-col :span="2" class="t-bord t-label-right">用例详情</a-col></a-row>
<a-row>
<a-col :span="2" class="t-bord t-label-right">用例详情</a-col>
</a-row>
<a-row>
<a-col :span="2"></a-col>
<a-col :span="22">
......@@ -50,10 +52,10 @@
row-key="id"
:pagination="false">
<template #seq="{ record }">
{{record.id}}
{{ record.id }}
</template>
<template #duration="{ record }">
{{record.duration}}
{{ record.duration }}
</template>
<template #status="{ record }">
<span :class="'t-'+record.status">{{ resultStatus(record.status) }}</span>
......@@ -63,8 +65,8 @@
<a-button type="link" @click="showInfo(record.id)">查看错误</a-button>
<a-modal v-model:visible="visibleMap[record.id]" width="1000px"
@ok="closeInfo(record.id)"
title="错误信息" >
<p>{{jsonStr(record.failure)}}</p>
title="错误信息">
<p>{{ jsonStr(record.failure) }}</p>
</a-modal>
</template>
</template>
......@@ -73,38 +75,49 @@
</a-row>
</div>
<result-form
v-if="resultFormVisible"
:data="resultFormData"
:onSubmit="submitResultForm"
:onCancel="cancelResultForm"
/>
</a-card>
</div>
</template>
<script lang="ts">
import {
defineComponent,
onMounted,
Ref,
ref,
computed, reactive
} from "vue";
import { useStore } from 'vuex';
import {computed, defineComponent, onMounted, reactive, Ref, ref} from "vue";
import {useStore} from 'vuex';
import {StateType as ListStateType} from "@/views/exec/store";
import {useRouter} from "vue-router";
import {momentTimeDef, percentDef} from "@/utils/datetime";
import {execByDef, resultStatusDef, testEnvDef, testTypeDef} from "@/utils/testing";
import {jsonStrDef} from "@/utils/dom";
import {notification} from "ant-design-vue";
import {submitResultToZentao} from "@/views/exec/service";
import ResultForm from './component/result.vue'
import {queryProduct} from "@/services/zentao";
interface DesignExecutionPageSetupData {
interface UnitTestResultPageSetupData {
report: Ref;
columns: any[]
loading: Ref<boolean>;
exec: (scope) => void;
submitResult: () => void;
back: () => void;
visibleMap: Ref
showInfo: (id) => void;
closeInfo: (id) => void;
resultFormData: Ref
resultFormVisible: Ref<boolean>;
setResultFormVisible: (val: boolean) => void;
openResultForm: () => void
submitResultForm: (model) => void
cancelResultForm: () => void;
execBy: (record) => string;
momentTime: (tm) => string;
percent: (numb, total) => string;
......@@ -115,122 +128,162 @@ interface DesignExecutionPageSetupData {
}
export default defineComponent({
name: 'ExecutionResultPage',
setup(): DesignExecutionPageSetupData {
const execBy = execByDef
const momentTime = momentTimeDef
const percent = percentDef
const testEnv = testEnvDef
const testType = testTypeDef
const resultStatus = resultStatusDef
const jsonStr = jsonStrDef
const visibleMap = reactive<any>({})
const router = useRouter();
const store = useStore<{ History: ListStateType}>();
const columns = [
{
title: '序号',
dataIndex: 'seq',
width: 150,
customRender: ({text, index}: { text: any; index: number}) => index + 1,
},
{
title: '用例',
dataIndex: 'title',
slots: { customRender: 'title' },
},
{
title: '套件',
dataIndex: 'testSuite',
},
{
title: '耗时(秒)',
dataIndex: 'duration',
slots: { customRender: 'duration' },
},
{
title: '状态',
dataIndex: 'status',
slots: { customRender: 'status' },
},
{
title: '信息',
dataIndex: 'info',
slots: { customRender: 'info' },
},
]
const report = computed<any>(() => store.state.History.item);
const loading = ref<boolean>(true);
const seq = router.currentRoute.value.params.seq
console.log('seq', seq)
const get = async (): Promise<void> => {
loading.value = true;
await store.dispatch('History/get', seq);
loading.value = false;
}
get()
const exec = (scope):void => {
console.log(report)
const productId = report.value.productId
const execBy = report.value.execBy
const execById = report.value.execById
if (execBy === 'case') router.push(`/exec/run/${execBy}/${seq}/${scope}`)
else router.push(`/exec/run/${execBy}/${productId}/${execById}/${seq}/${scope}`)
}
const submitResult = ():void => {
console.log('submitResult')
}
const showInfo = (id):void => {
visibleMap[id] = true
}
const closeInfo = (id):void => {
visibleMap[id] = false
}
const back = ():void => {
router.push(`/exec/history`)
}
onMounted(() => {
console.log('onMounted')
name: 'UnitTestResultPage',
components: {
ResultForm
},
setup(): UnitTestResultPageSetupData {
const execBy = execByDef
const momentTime = momentTimeDef
const percent = percentDef
const testEnv = testEnvDef
const testType = testTypeDef
const resultStatus = resultStatusDef
const jsonStr = jsonStrDef
const visibleMap = reactive<any>({})
const router = useRouter();
const store = useStore<{ History: ListStateType }>();
const columns = [
{
title: '序号',
dataIndex: 'seq',
width: 150,
customRender: ({text, index}: { text: any; index: number }) => index + 1,
},
{
title: '用例',
dataIndex: 'title',
slots: {customRender: 'title'},
},
{
title: '套件',
dataIndex: 'testSuite',
},
{
title: '耗时(秒)',
dataIndex: 'duration',
slots: {customRender: 'duration'},
},
{
title: '状态',
dataIndex: 'status',
slots: {customRender: 'status'},
},
{
title: '信息',
dataIndex: 'info',
slots: {customRender: 'info'},
},
]
const report = computed<any>(() => store.state.History.item);
const loading = ref<boolean>(true);
const seq = router.currentRoute.value.params.seq as string
const get = async (): Promise<void> => {
loading.value = true;
await store.dispatch('History/get', seq);
loading.value = false;
}
get()
const exec = (scope): void => {
console.log(report)
const productId = report.value.productId
const execBy = report.value.execBy
const execById = report.value.execById
if (execBy === 'case') router.push(`/exec/run/${execBy}/${seq}/${scope}`)
else router.push(`/exec/run/${execBy}/${productId}/${execById}/${seq}/${scope}`)
}
const resultFormData = ref({})
const resultFormVisible = ref<boolean>(false);
const setResultFormVisible = (val: boolean) => {
resultFormVisible.value = val;
}
const openResultForm = () => {
console.log('openResultForm')
setResultFormVisible(true)
}
const submitResultForm = (formData) => {
console.log('submitResultForm', formData)
const data = Object.assign({seq: seq}, formData)
console.log('data', data)
submitResultToZentao(data).then((json) => {
console.log('json', json)
if (json.code === 0) {
notification.success({
message: '提交成功',
});
setResultFormVisible(false)
} else {
notification.error({
message: '提交失败',
description: json.msg,
});
}
})
}
const cancelResultForm = () => {
setResultFormVisible(false);
}
return {
report,
columns,
loading,
exec,
submitResult,
back,
visibleMap,
showInfo,
closeInfo,
execBy,
momentTime,
percent,
testEnv,
testType,
resultStatus,
jsonStr,
}
const showInfo = (id): void => {
visibleMap[id] = true
}
const closeInfo = (id): void => {
visibleMap[id] = false
}
const back = (): void => {
router.push(`/exec/history`)
}
onMounted(() => {
console.log('onMounted')
})
return {
report,
columns,
loading,
exec,
back,
visibleMap,
showInfo,
closeInfo,
resultFormData,
resultFormVisible,
setResultFormVisible,
openResultForm,
submitResultForm,
cancelResultForm,
execBy,
momentTime,
percent,
testEnv,
testType,
resultStatus,
jsonStr,
}
}
})
</script>
<style lang="less" scoped>
.main {
padding: 20px;
}
.main {
padding: 20px;
}
</style>
......@@ -56,4 +56,18 @@ export function genExecInfo(jsn: WsMsg, i: number): string {
export function SetWidth(content: string, width: number): string{
return `<span style="display: inline-block; width: ${width}px; text-align: right; padding-right: 6px;">${content}</span>`;
}
export function submitResultToZentao(data: any): Promise<any> {
return request({
url: `/result`,
method: 'post',
data: data,
});
}
export function submitBugToZentao(seq: string): Promise<any> {
return request({
url: `/bug/${seq}`,
method: 'post',
});
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册