-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Expand file tree
/
Copy pathcompat.go
More file actions
171 lines (157 loc) · 5.22 KB
/
compat.go
File metadata and controls
171 lines (157 loc) · 5.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
package hrp
import (
"fmt"
"strings"
"github.com/pkg/errors"
"github.com/httprunner/httprunner/v5/code"
"github.com/httprunner/httprunner/v5/internal/builtin"
"github.com/httprunner/httprunner/v5/uixt/option"
)
// ConvertCaseCompatibility converts TestCase compatible with Golang engine style
func ConvertCaseCompatibility(tc *TestCaseDef) (err error) {
defer func() {
if p := recover(); p != nil {
err = fmt.Errorf("[MakeCompat] convert compat testcase error: %v", p)
}
}()
for _, step := range tc.Steps {
// 1. deal with request body compatibility
convertCompatRequestBody(step.Request)
// 2. deal with validators compatibility
err = convertCompatValidator(step.Validators)
if err != nil {
return err
}
// 3. deal with extract expr including hyphen
convertExtract(step.Extract)
// 4. deal with mobile step compatibility
if step.Android != nil {
convertCompatMobileStep(step.Android)
} else if step.IOS != nil {
convertCompatMobileStep(step.IOS)
} else if step.Harmony != nil {
convertCompatMobileStep(step.Harmony)
}
}
return nil
}
func convertCompatRequestBody(request *Request) {
if request != nil && request.Body == nil {
if request.Json != nil {
if request.Headers == nil {
request.Headers = make(map[string]string)
}
request.Headers["Content-Type"] = "application/json; charset=utf-8"
request.Body = request.Json
request.Json = nil
} else if request.Data != nil {
request.Body = request.Data
request.Data = nil
}
}
}
func convertCompatValidator(Validators []interface{}) (err error) {
for i, iValidator := range Validators {
if _, ok := iValidator.(Validator); ok {
continue
}
var validatorMap map[string]interface{}
if v, ok := iValidator.(map[string]interface{}); ok {
validatorMap = v
} else if v, ok := iValidator.(map[interface{}]interface{}); ok {
// convert map[interface{}]interface{} to map[string]interface{}
validatorMap = make(map[string]interface{})
for key, value := range v {
strKey := fmt.Sprintf("%v", key)
validatorMap[strKey] = value
}
} else {
return errors.Wrap(code.InvalidCaseError,
fmt.Sprintf("unexpected validator format: %v", iValidator))
}
validator := Validator{}
iCheck, checkExisted := validatorMap["check"]
iAssert, assertExisted := validatorMap["assert"]
iExpect, expectExisted := validatorMap["expect"]
// validator check priority: Golang > Python engine style
if checkExisted && assertExisted && expectExisted {
// Golang engine style
validator.Check = iCheck.(string)
validator.Assert = iAssert.(string)
validator.Expect = iExpect
if iMsg, msgExisted := validatorMap["msg"]; msgExisted {
validator.Message = iMsg.(string)
}
validator.Check = convertJmespathExpr(validator.Check)
Validators[i] = validator
continue
}
if len(validatorMap) == 1 {
// Python engine style
for assertMethod, iValidatorContent := range validatorMap {
validatorContent := iValidatorContent.([]interface{})
if len(validatorContent) > 3 {
return errors.Wrap(code.InvalidCaseError,
fmt.Sprintf("unexpected validator format: %v", validatorMap))
}
validator.Check = validatorContent[0].(string)
validator.Assert = assertMethod
validator.Expect = validatorContent[1]
if len(validatorContent) == 3 {
validator.Message = validatorContent[2].(string)
}
}
validator.Check = convertJmespathExpr(validator.Check)
Validators[i] = validator
continue
}
return errors.Wrap(code.InvalidCaseError,
fmt.Sprintf("unexpected validator format: %v", validatorMap))
}
return nil
}
// convertExtract deals with extract expr including hyphen
func convertExtract(extract map[string]string) {
for key, value := range extract {
extract[key] = convertJmespathExpr(value)
}
}
func convertCompatMobileStep(mobileUI *MobileUI) {
if mobileUI == nil {
return
}
for i := 0; i < len(mobileUI.Actions); i++ {
ma := mobileUI.Actions[i]
actionOptions := option.NewActionOptions(ma.GetOptions()...)
// append tap_cv params to screenshot_with_ui_types option
if ma.Method == option.ACTION_TapByCV {
uiTypes, _ := builtin.ConvertToStringSlice(ma.Params)
ma.ActionOptions.ScreenShotWithUITypes = append(ma.ActionOptions.ScreenShotWithUITypes, uiTypes...)
ma.ActionOptions.ScreenShotWithUpload = true
}
// set default max_retry_times to 10 for swipe_to_tap_texts
if ma.Method == option.ACTION_SwipeToTapTexts && actionOptions.MaxRetryTimes == 0 {
ma.ActionOptions.MaxRetryTimes = 10
}
// set default max_retry_times to 10 for swipe_to_tap_text
if ma.Method == option.ACTION_SwipeToTapText && actionOptions.MaxRetryTimes == 0 {
ma.ActionOptions.MaxRetryTimes = 10
}
mobileUI.Actions[i] = ma
}
}
// convertJmespathExpr deals with limited jmespath expression conversion
func convertJmespathExpr(checkExpr string) string {
if strings.Contains(checkExpr, textExtractorSubRegexp) {
return checkExpr
}
checkItems := strings.Split(checkExpr, ".")
for i, checkItem := range checkItems {
checkItem = strings.Trim(checkItem, "\"")
lowerItem := strings.ToLower(checkItem)
if strings.HasPrefix(lowerItem, "content-") || lowerItem == "user-agent" {
checkItems[i] = fmt.Sprintf("\"%s\"", checkItem)
}
}
return strings.Join(checkItems, ".")
}