feat: support providing the suggested body fields (#127)
This commit is contained in:
parent
7bd43cc4a5
commit
3040a92501
|
@ -4,6 +4,7 @@ import type { TabsPaneContext } from 'element-plus'
|
|||
import { ElMessage } from 'element-plus'
|
||||
import { Edit, Delete } from '@element-plus/icons-vue'
|
||||
import JsonViewer from 'vue-json-viewer'
|
||||
import _ from 'lodash';
|
||||
|
||||
const props = defineProps({
|
||||
name: String,
|
||||
|
@ -53,6 +54,9 @@ function sendRequest() {
|
|||
}
|
||||
if (e.body !== '') {
|
||||
testResult.value.bodyObject = JSON.parse(e.body)
|
||||
|
||||
console.log(flattenObject(testResult.value.bodyObject))
|
||||
console.log(Object.getOwnPropertyNames(flattenObject(testResult.value.bodyObject)))
|
||||
}
|
||||
}).catch(e => {
|
||||
requestLoading.value = false
|
||||
|
@ -61,6 +65,32 @@ function sendRequest() {
|
|||
});
|
||||
}
|
||||
|
||||
const queryBodyFields = (queryString: string, cb: any) => {
|
||||
if (!testResult.value.bodyObject || !flattenObject(testResult.value.bodyObject)) {
|
||||
cb([])
|
||||
return
|
||||
}
|
||||
const keys = Object.getOwnPropertyNames(flattenObject(testResult.value.bodyObject))
|
||||
if (keys.length <= 0) {
|
||||
cb([])
|
||||
return
|
||||
}
|
||||
|
||||
const pairs = [] as Pair[]
|
||||
keys.forEach(e => {
|
||||
pairs.push({
|
||||
key: e,
|
||||
value: e,
|
||||
} as Pair)
|
||||
});
|
||||
|
||||
const results = queryString
|
||||
? pairs.filter(createFilter(queryString))
|
||||
: pairs
|
||||
// call callback function to return suggestions
|
||||
cb(results)
|
||||
}
|
||||
|
||||
interface Pair {
|
||||
key: string,
|
||||
value: string
|
||||
|
@ -319,6 +349,41 @@ const createFilter = (queryString: string) => {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
function flattenObject(obj: any): any {
|
||||
function _flattenPairs(obj: any, prefix: string): [string, any][] {
|
||||
if (!_.isObject(obj)) {
|
||||
return [prefix, obj];
|
||||
}
|
||||
|
||||
return _.toPairs(obj).reduce((final: [string, any][], nPair: [string, any]) => {
|
||||
const flattened = _flattenPairs(nPair[1], `${prefix}.${nPair[0]}`);
|
||||
if (flattened.length === 2 && !_.isObject(flattened[0]) && !_.isObject(flattened[1])) {
|
||||
return final.concat([flattened as [string, any]]);
|
||||
} else {
|
||||
return final.concat(flattened);
|
||||
}
|
||||
}, []);
|
||||
}
|
||||
|
||||
if (!_.isObject(obj)) {
|
||||
return JSON.stringify(obj);
|
||||
}
|
||||
|
||||
const pairs: [string, any][] = _.toPairs(obj).reduce((final: [string, any][], pair: [string, any]) => {
|
||||
const flattened = _flattenPairs(pair[1], pair[0]);
|
||||
if (flattened.length === 2 && !_.isObject(flattened[0]) && !_.isObject(flattened[1])) {
|
||||
return final.concat([flattened as [string, any]]);
|
||||
} else {
|
||||
return final.concat(flattened);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return pairs.reduce((acc: any, pair: [string, any]) => {
|
||||
acc[pair[0]] = pair[1];
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -403,7 +468,13 @@ const createFilter = (queryString: string) => {
|
|||
<el-table :data="testCaseWithSuite.data.response.bodyFieldsExpect" style="width: 100%">
|
||||
<el-table-column label="Key" width="180">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.key" placeholder="Key" @change="bodyFiledExpectChange" />
|
||||
<el-autocomplete
|
||||
v-model="scope.row.key"
|
||||
:fetch-suggestions="queryBodyFields"
|
||||
clearable
|
||||
placeholder="Key"
|
||||
@change="bodyFiledExpectChange"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Value">
|
||||
|
|
3
go.mod
3
go.mod
|
@ -41,6 +41,9 @@ require (
|
|||
github.com/shopspring/decimal v1.2.0 // indirect
|
||||
github.com/spf13/cast v1.3.1 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/tidwall/gjson v1.14.4 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.1 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
golang.org/x/crypto v0.3.0 // indirect
|
||||
|
|
7
go.sum
7
go.sum
|
@ -83,6 +83,13 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
|
||||
github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
|
||||
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
|
||||
|
|
|
@ -17,7 +17,7 @@ import (
|
|||
"github.com/linuxsuren/api-testing/pkg/runner/kubernetes"
|
||||
"github.com/linuxsuren/api-testing/pkg/testing"
|
||||
fakeruntime "github.com/linuxsuren/go-fake-runtime"
|
||||
unstructured "github.com/linuxsuren/unstructured/pkg"
|
||||
"github.com/tidwall/gjson"
|
||||
"github.com/xeipuuv/gojsonschema"
|
||||
)
|
||||
|
||||
|
@ -341,20 +341,22 @@ func verifyResponseBodyData(caseName string, expect testing.Response, responseBo
|
|||
|
||||
for key, expectVal := range expect.BodyFieldsExpect {
|
||||
var val interface{}
|
||||
var ok bool
|
||||
if val, ok, err = unstructured.NestedField(bodyMap, strings.Split(key, "/")...); err != nil {
|
||||
err = fmt.Errorf("failed to get field: %s, %v", key, err)
|
||||
return
|
||||
} else if !ok {
|
||||
err = fmt.Errorf("not found field: %s", key)
|
||||
return
|
||||
} else if !reflect.DeepEqual(expectVal, val) {
|
||||
if reflect.TypeOf(expectVal).Kind() == reflect.Int {
|
||||
if strings.Compare(fmt.Sprintf("%v", expectVal), fmt.Sprintf("%v", val)) == 0 {
|
||||
continue
|
||||
|
||||
result := gjson.Get(string(responseBodyData), key)
|
||||
if result.Exists() {
|
||||
val = result.Value()
|
||||
|
||||
if !reflect.DeepEqual(expectVal, val) {
|
||||
if reflect.TypeOf(expectVal).Kind() == reflect.Int {
|
||||
if strings.Compare(fmt.Sprintf("%v", expectVal), fmt.Sprintf("%v", val)) == 0 {
|
||||
continue
|
||||
}
|
||||
}
|
||||
err = fmt.Errorf("field[%s] expect value: %v, actual: %v", key, expectVal, val)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("field[%s] expect value: %v, actual: %v", key, expectVal, val)
|
||||
} else {
|
||||
err = fmt.Errorf("not found field: %s", key)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
@ -206,14 +206,14 @@ func TestTestCase(t *testing.T) {
|
|||
Request: fooRequst,
|
||||
Expect: atest.Response{
|
||||
BodyFieldsExpect: map[string]interface{}{
|
||||
"items[1]": "bar",
|
||||
"0.items": "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
prepare: defaultPrepare,
|
||||
verify: func(t *testing.T, output interface{}, err error) {
|
||||
assert.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), "failed to get field")
|
||||
assert.Contains(t, err.Error(), "not found field")
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue