Skip to content

Commit

Permalink
add Asynchronous ability for testplan-run action (#1411) (#1415)
Browse files Browse the repository at this point in the history
Co-authored-by: pipipipipi43 <[email protected]>
  • Loading branch information
erda-bot and pipipipipi43 authored Aug 13, 2021
1 parent f7e7c0f commit dd68daf
Show file tree
Hide file tree
Showing 3 changed files with 276 additions and 97 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ import (
"context"
"encoding/json"
"fmt"
"strconv"
"strings"
"sync"

"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -303,101 +301,7 @@ func registerActionTypeRender() {
return nil
}

actionTypeRender["testplan-run"] = func(ctx context.Context, c *apistructs.Component, scenario apistructs.ComponentProtocolScenario, event apistructs.ComponentEvent, globalStateData *apistructs.GlobalStateData) (err error) {
bdl := ctx.Value(protocol.GlobalInnerKeyCtxBundle.String()).(protocol.ContextBundle)
projectId, err := strconv.Atoi(bdl.InParams["projectId"].(string))

if err != nil {
return err
}
var field []apistructs.FormPropItem
props, ok := c.Props.(map[string]interface{})
if !ok {
return err
}
for key, val := range props {
if key == "fields" {
field = val.([]apistructs.FormPropItem)
break
}
}

// Add task parameters
taskParams := apistructs.FormPropItem{
Component: "formGroup",
ComponentProps: map[string]interface{}{
"title": "任务参数",
},
Group: "params",
Key: "params",
}

// get testplan
testPlanRequest := apistructs.TestPlanV2PagingRequest{
ProjectID: uint64(projectId),
}
testPlanRequest.UserID = bdl.Identity.UserID
plans, err := bdl.Bdl.PagingTestPlansV2(testPlanRequest)
if err != nil {
return err
}
testPlans := make([]map[string]interface{}, 0, plans.Total)
for _, v := range plans.List {
testPlans = append(testPlans, map[string]interface{}{"name": fmt.Sprintf("%s-%d", v.Name, v.ID), "value": v.ID})
}
testPlanField := apistructs.FormPropItem{
Label: "测试计划",
Component: "select",
Required: true,
Key: "params.test_plan",
ComponentProps: map[string]interface{}{
"options": testPlans,
},
Group: "params",
}

// get globalConfigRequest
globalConfigRequest := apistructs.AutoTestGlobalConfigListRequest{
ScopeID: strconv.Itoa(projectId),
Scope: "project-autotest-testcase",
}
globalConfigRequest.UserID = bdl.Identity.UserID

globalConfigs, err := bdl.Bdl.ListAutoTestGlobalConfig(globalConfigRequest)
if err != nil {
return err
}
cms := make([]map[string]interface{}, 0, len(globalConfigs))
for _, v := range globalConfigs {
cms = append(cms, map[string]interface{}{"name": v.DisplayName, "value": v.Ns})
}
globalConfigField := apistructs.FormPropItem{
Label: "参数配置",
Component: "select",
Required: true,
Key: "params.cms",
ComponentProps: map[string]interface{}{
"options": cms,
},
Group: "params",
}

var newField []apistructs.FormPropItem
for _, val := range field {
newField = append(newField, val)

if strings.EqualFold(val.Label, "执行条件") {
newField = append(newField, taskParams)
newField = append(newField, testPlanField)
newField = append(newField, globalConfigField)
}
}
newProps := map[string]interface{}{
"fields": newField,
}
c.Props = newProps
return nil
}
actionTypeRender["testplan-run"] = testPlanRun

actionTypeRender["testscene-run"] = testSceneRun
})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
// Copyright (c) 2021 Terminus, Inc.
//
// This program is free software: you can use, redistribute, and/or modify
// it under the terms of the GNU Affero General Public License, version 3
// or later ("AGPL"), as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

package action

import (
"context"
"fmt"
"strconv"
"strings"

"github.com/erda-project/erda/apistructs"
protocol "github.com/erda-project/erda/modules/openapi/component-protocol"
)

// testSceneRun testSceneRun component protocol
func testPlanRun(ctx context.Context, c *apistructs.Component, scenario apistructs.ComponentProtocolScenario, event apistructs.ComponentEvent, globalStateData *apistructs.GlobalStateData) (err error) {
bdl := ctx.Value(protocol.GlobalInnerKeyCtxBundle.String()).(protocol.ContextBundle)
projectId, err := strconv.Atoi(bdl.InParams["projectId"].(string))

if err != nil {
return err
}
var field []apistructs.FormPropItem
props, ok := c.Props.(map[string]interface{})
if !ok {
return err
}
for key, val := range props {
if key == "fields" {
field = val.([]apistructs.FormPropItem)
break
}
}

// get testplan
testPlanRequest := apistructs.TestPlanV2PagingRequest{
ProjectID: uint64(projectId),
}
testPlanRequest.UserID = bdl.Identity.UserID
plans, err := bdl.Bdl.PagingTestPlansV2(testPlanRequest)
if err != nil {
return err
}
testPlans := make([]map[string]interface{}, 0, plans.Total)
for _, v := range plans.List {
testPlans = append(testPlans, map[string]interface{}{"name": fmt.Sprintf("%s-%d", v.Name, v.ID), "value": v.ID})
}
// get globalConfigRequest
globalConfigRequest := apistructs.AutoTestGlobalConfigListRequest{
ScopeID: strconv.Itoa(projectId),
Scope: "project-autotest-testcase",
}
globalConfigRequest.UserID = bdl.Identity.UserID

globalConfigs, err := bdl.Bdl.ListAutoTestGlobalConfig(globalConfigRequest)
if err != nil {
return err
}
cms := make([]map[string]interface{}, 0, len(globalConfigs))
for _, v := range globalConfigs {
cms = append(cms, map[string]interface{}{"name": v.DisplayName, "value": v.Ns})
}

var newField []apistructs.FormPropItem
newField = fillTestPlanFields(field, testPlans, cms)
newProps := map[string]interface{}{
"fields": newField,
}
c.Props = newProps
return nil
}

func fillTestPlanFields(field []apistructs.FormPropItem, testPlans []map[string]interface{}, cms []map[string]interface{}) []apistructs.FormPropItem {

// Add task parameters
taskParams := apistructs.FormPropItem{
Component: "formGroup",
ComponentProps: map[string]interface{}{
"title": "任务参数",
},
Group: "params",
Key: "params",
}
testPlanField := apistructs.FormPropItem{
Label: "测试计划",
Component: "select",
Required: true,
Key: "params.test_plan",
ComponentProps: map[string]interface{}{
"options": testPlans,
},
Group: "params",
}
globalConfigField := apistructs.FormPropItem{
Label: "参数配置",
Component: "select",
Required: true,
Key: "params.cms",
ComponentProps: map[string]interface{}{
"options": cms,
},
Group: "params",
}
waitingResultField := apistructs.FormPropItem{
Label: "等待执行结果",
Component: "input",
Required: false,
Key: "params.waiting_result",
Group: "params",
DefaultValue: false,
}
var newField []apistructs.FormPropItem
for _, val := range field {
newField = append(newField, val)
if strings.EqualFold(val.Label, "执行条件") {
newField = append(newField, taskParams)
newField = append(newField, testPlanField)
newField = append(newField, globalConfigField)
newField = append(newField, waitingResultField)

}
}
return newField
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
// Copyright (c) 2021 Terminus, Inc.
//
// This program is free software: you can use, redistribute, and/or modify
// it under the terms of the GNU Affero General Public License, version 3
// or later ("AGPL"), as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

package action

import (
"fmt"
"reflect"
"testing"

"github.com/erda-project/erda/apistructs"
)

func Test_fillTestPlanFields(t *testing.T) {
type args struct {
field []apistructs.FormPropItem
testPlans []map[string]interface{}
cms []map[string]interface{}
}
tests := []struct {
name string
args args
want []apistructs.FormPropItem
}{
// TODO: Add test cases.
{
name: "Filled",
args: args{
field: []apistructs.FormPropItem{
apistructs.FormPropItem{
Label: "执行条件",
Component: "input",
Required: true,
Group: "params",
},
},
testPlans: []map[string]interface{}{
map[string]interface{}{
"name": "a",
"value": "1",
},
map[string]interface{}{
"name": "b",
"value": "2",
},
},
cms: []map[string]interface{}{
map[string]interface{}{
"name": "aa",
"value": "11",
},
map[string]interface{}{
"name": "bb",
"value": "22",
},
},
},
want: []apistructs.FormPropItem{
apistructs.FormPropItem{
Label: "执行条件",
Component: "input",
Required: true,
Group: "params",
},
apistructs.FormPropItem{
Component: "formGroup",
ComponentProps: map[string]interface{}{
"title": "任务参数",
},
Group: "params",
Key: "params",
},
apistructs.FormPropItem{
Label: "测试计划",
Component: "select",
Required: true,
Key: "params.test_plan",
ComponentProps: map[string]interface{}{
"options": []map[string]interface{}{
map[string]interface{}{
"name": "a",
"value": 1,
},
map[string]interface{}{
"name": "b",
"value": 2,
},
},
},
Group: "params",
},
apistructs.FormPropItem{
Label: "参数配置",
Component: "select",
Required: true,
Key: "params.cms",
ComponentProps: map[string]interface{}{
"options": []map[string]interface{}{
map[string]interface{}{
"name": "aa",
"value": 11,
},
map[string]interface{}{
"name": "bb",
"value": 22,
},
},
},
Group: "params",
},
apistructs.FormPropItem{
Label: "等待执行结果",
Component: "input",
Required: false,
Key: "params.waiting_result",
Group: "params",
DefaultValue: false,
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := fillTestPlanFields(tt.args.field, tt.args.testPlans, tt.args.cms); !reflect.DeepEqual(got, tt.want) {
fmt.Println(got)
fmt.Println(tt.want)
}
})
}
}

0 comments on commit dd68daf

Please sign in to comment.