refactor: 全局XPath断言支持html内容断言

--story=1012971 --user=赵勇 【接口测试】项目环境-断言支持html格式 https://www.tapd.cn/55049933/s/1412762

Signed-off-by: fit2-zhao <yong.zhao@fit2cloud.com>
This commit is contained in:
fit2-zhao 2023-09-05 14:17:28 +08:00 committed by fit2-zhao
parent 261be2818d
commit 163d79ff0e
2 changed files with 160 additions and 135 deletions

View File

@ -1,94 +1,111 @@
<template>
<div v-loading="loading">
<div class="assertion-item-editing regex" v-if="assertions.regex.length > 0">
<div> {{ $t("api_test.request.assertions.regex") }}</div>
<div>{{ $t('api_test.request.assertions.regex') }}</div>
<div class="regex-item" v-for="(regex, index) in assertions.regex" :key="index">
<ms-api-assertion-regex
:is-read-only="isReadOnly"
:list="assertions.regex"
:regex="regex"
:edit="true"
:index="index"/>
:index="index" />
</div>
</div>
<div class="assertion-item-editing json_path" v-if="assertions.jsonPath.length > 0">
<div> {{ 'JSONPath' }}</div>
<div>{{ 'JSONPath' }}</div>
<div class="regex-item" v-for="(jsonPath, index) in assertions.jsonPath" :key="index">
<ms-api-assertion-json-path
:is-read-only="isReadOnly"
:list="assertions.jsonPath"
:json-path="jsonPath"
:edit="true"
:index="index"/>
:index="index" />
</div>
</div>
<div class="assertion-item-editing x_path" v-if="assertions.xpath2.length > 0">
<div> {{ 'XPath' }}</div>
<div>
XPath
<el-select v-model="assertions.xpathType" size="mini" v-loading="loading" @change="reload">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
<el-tooltip placement="top">
<div slot="content">
{{ $t('api_test.request.assertions.assert_info') }}
</div>
<i class="el-icon-question" style="cursor: pointer" />
</el-tooltip>
</div>
<div class="regex-item" v-for="(xPath, index) in assertions.xpath2" :key="index">
<ms-api-assertion-x-path2
:is-read-only="isReadOnly"
:list="assertions.xpath2"
:x-path2="xPath"
:edit="true"
:index="index"/>
:index="index" />
</div>
</div>
<div class="assertion-item-editing jsr223" v-if="assertions.jsr223.length > 0">
<div> {{ $t("api_test.request.assertions.script") }}</div>
<div>{{ $t('api_test.request.assertions.script') }}</div>
<div class="regex-item" v-for="(assertion, index) in assertions.jsr223" :key="index">
<ms-api-assertion-jsr223
:is-read-only="isReadOnly"
:list="assertions.jsr223"
:assertion="assertion"
:edit="true"
:index="index"/>
:index="index" />
</div>
</div>
<div class="assertion-item-editing response-time" v-if="isShow">
<div> {{ $t("api_test.request.assertions.response_time") }}</div>
<div>{{ $t('api_test.request.assertions.response_time') }}</div>
<ms-api-assertion-duration
:is-read-only="isReadOnly"
v-model="assertions.duration.value"
:duration="assertions.duration"
:edit="true"/>
:edit="true" />
</div>
<div class="assertion-item-editing response-time" v-if="isDocument">
<div>
<el-row :gutter="10" type="flex" justify="space-between" align="middle">
<el-col>
{{ assertions.document.type }}-{{ $t("api_test.definition.request.document_structure") }}
</el-col>
<el-col> {{ assertions.document.type }}-{{ $t('api_test.definition.request.document_structure') }} </el-col>
<el-col class="assertion-remove-btn">
<el-tooltip :content="$t('test_resource_pool.enable_disable')" placement="top">
<el-switch v-model="assertions.document.enable" class="enable-switch" size="mini"
:disabled="assertions.disabled" style="width: 30px;margin-right: 10px"/>
<el-switch
v-model="assertions.document.enable"
class="enable-switch"
size="mini"
:disabled="assertions.disabled"
style="width: 30px; margin-right: 10px" />
</el-tooltip>
<el-tooltip effect="dark" :content="$t('commons.remove')" placement="top-start">
<el-button icon="el-icon-delete" type="danger" size="mini" circle @click="remove()"
:disabled="(assertions.disabled && !assertions.root)"/>
<el-button
icon="el-icon-delete"
type="danger"
size="mini"
circle
@click="remove()"
:disabled="assertions.disabled && !assertions.root" />
</el-tooltip>
</el-col>
</el-row>
</div>
<ms-document-body :document="assertions.document" :apiId="apiId" :isReadOnly="isReadOnly" @remove="remove"/>
<ms-document-body :document="assertions.document" :apiId="apiId" :isReadOnly="isReadOnly" @remove="remove" />
</div>
</div>
</template>
<script>
import MsApiAssertionRegex from "./ApiAssertionRegex";
import MsApiAssertionDuration from "./ApiAssertionDuration";
import MsApiAssertionJsonPath from "./ApiAssertionJsonPath";
import MsApiAssertionJsr223 from "./ApiAssertionJsr223";
import MsApiAssertionXPath2 from "./ApiAssertionXPath2";
import MsApiAssertionRegex from './ApiAssertionRegex';
import MsApiAssertionDuration from './ApiAssertionDuration';
import MsApiAssertionJsonPath from './ApiAssertionJsonPath';
import MsApiAssertionJsr223 from './ApiAssertionJsr223';
import MsApiAssertionXPath2 from './ApiAssertionXPath2';
export default {
name: "MsApiAssertionsEdit",
name: 'MsApiAssertionsEdit',
components: {
MsApiAssertionXPath2,
@ -96,7 +113,7 @@ export default {
MsApiAssertionJsonPath,
MsApiAssertionDuration,
MsApiAssertionRegex,
MsDocumentBody: () => import("./document/DocumentBody"),
MsDocumentBody: () => import('./document/DocumentBody'),
},
props: {
@ -105,13 +122,17 @@ export default {
apiId: String,
isReadOnly: {
type: Boolean,
default: false
}
default: false,
},
},
data() {
return {
loading: false,
}
options: [
{ value: 'html', label: 'html' },
{ value: 'xml', label: 'xml' },
],
};
},
computed: {
isShow() {
@ -119,30 +140,34 @@ export default {
return rt.value && rt.value !== 0;
},
isDocument() {
return this.assertions.document && this.assertions.document.data && (this.assertions.document.data.json.length > 0 || this.assertions.document.data.xml.length > 0);
}
return (
this.assertions.document &&
this.assertions.document.data &&
(this.assertions.document.data.json.length > 0 || this.assertions.document.data.xml.length > 0)
);
},
},
watch: {
reloadData() {
this.reload();
}
},
},
methods: {
remove() {
this.assertions.document = {
type: "JSON",
data: {xmlFollowAPI: false, jsonFollowAPI: false, json: [], xml: []},
enable: true
type: 'JSON',
data: { xmlFollowAPI: false, jsonFollowAPI: false, json: [], xml: [] },
enable: true,
};
},
reload() {
this.loading = true
this.loading = true;
this.$nextTick(() => {
this.loading = false
})
this.loading = false;
});
},
}
}
},
};
</script>
<style scoped>
@ -152,19 +177,19 @@ export default {
}
.assertion-item-editing.regex {
border-left: 2px solid #7B0274;
border-left: 2px solid #7b0274;
}
.assertion-item-editing.json_path {
border-left: 2px solid #44B3D2;
border-left: 2px solid #44b3d2;
}
.assertion-item-editing.response-time {
border-left: 2px solid #DD0240;
border-left: 2px solid #dd0240;
}
.assertion-item-editing.jsr223 {
border-left: 2px solid #1FDD02;
border-left: 2px solid #1fdd02;
}
.assertion-item-editing.x_path {

View File

@ -3,62 +3,59 @@
<div class="assertion-add" :draggable="draggable">
<el-row :gutter="10">
<el-col :span="4">
<el-select :disabled="isReadOnly" class="assertion-item" v-model="type"
:placeholder="$t('api_test.request.assertions.select_type')" size="small">
<el-option :label="$t('api_test.request.assertions.text')" :value="options.TEXT"/>
<el-option :label="$t('api_test.request.assertions.regex')" :value="options.REGEX"/>
<el-option :label="'JSONPath'" :value="options.JSON_PATH"/>
<el-option :label="'XPath'" :value="options.XPATH2"/>
<el-option :label="$t('api_test.request.assertions.response_time')" :value="options.DURATION"/>
<el-option :label="$t('api_test.request.assertions.jsr223')" :value="options.JSR223"/>
<el-option :label="$t('api_test.definition.request.document_structure')" :value="options.DOCUMENT"/>
<el-select
:disabled="isReadOnly"
class="assertion-item"
v-model="type"
:placeholder="$t('api_test.request.assertions.select_type')"
size="small">
<el-option :label="$t('api_test.request.assertions.text')" :value="options.TEXT" />
<el-option :label="$t('api_test.request.assertions.regex')" :value="options.REGEX" />
<el-option :label="'JSONPath'" :value="options.JSON_PATH" />
<el-option :label="'XPath'" :value="options.XPATH2" />
<el-option :label="$t('api_test.request.assertions.response_time')" :value="options.DURATION" />
<el-option :label="$t('api_test.request.assertions.jsr223')" :value="options.JSR223" />
<el-option :label="$t('api_test.definition.request.document_structure')" :value="options.DOCUMENT" />
</el-select>
</el-col>
<el-col :span="20">
<global-assertion-text
:is-read-only="isReadOnly"
:list="assertions.regex"
:callback="after"
v-if="type === options.TEXT"
/>
:is-read-only="isReadOnly"
:list="assertions.regex"
:callback="after"
v-if="type === options.TEXT" />
<ms-api-assertion-regex
:is-read-only="isReadOnly"
:list="assertions.regex"
:callback="after"
v-if="type === options.REGEX"
/>
:is-read-only="isReadOnly"
:list="assertions.regex"
:callback="after"
v-if="type === options.REGEX" />
<ms-api-assertion-json-path
:is-read-only="isReadOnly"
:list="assertions.jsonPath"
:callback="after"
v-if="type === options.JSON_PATH"
/>
:is-read-only="isReadOnly"
:list="assertions.jsonPath"
:callback="after"
v-if="type === options.JSON_PATH" />
<ms-api-assertion-x-path2
:is-read-only="isReadOnly"
:list="assertions.xpath2"
:callback="after"
v-if="type === options.XPATH2"
/>
:is-read-only="isReadOnly"
:list="assertions.xpath2"
:callback="after"
v-if="type === options.XPATH2" />
<ms-api-assertion-duration
v-model="time"
:is-read-only="isReadOnly"
:duration="assertions.duration"
:callback="after"
v-if="type === options.DURATION"
/>
v-model="time"
:is-read-only="isReadOnly"
:duration="assertions.duration"
:callback="after"
v-if="type === options.DURATION" />
<ms-api-assertion-jsr223
:is-read-only="isReadOnly"
:list="assertions.jsr223"
:callback="after"
v-if="type === options.JSR223"
/>
:is-read-only="isReadOnly"
:list="assertions.jsr223"
:callback="after"
v-if="type === options.JSR223" />
<ms-api-assertion-document
:is-read-only="isReadOnly"
v-model="time"
:document="assertions.document"
:callback="after"
v-if="type === options.DOCUMENT"
/>
:is-read-only="isReadOnly"
v-model="time"
:document="assertions.document"
:callback="after"
v-if="type === options.DOCUMENT" />
<el-button v-if="!type" :disabled="true" type="primary" size="small">
{{ $t('api_test.request.assertions.add') }}
</el-button>
@ -67,43 +64,42 @@
</div>
<api-json-path-suggest-button
v-if="isShowJsonPathSuggest"
:open-tip="$t('api_test.request.assertions.json_path_suggest')"
:clear-tip="$t('api_test.request.assertions.json_path_clear')"
@open="suggestJsonOpen"
@clear="clearJson"/>
v-if="isShowJsonPathSuggest"
:open-tip="$t('api_test.request.assertions.json_path_suggest')"
:clear-tip="$t('api_test.request.assertions.json_path_clear')"
@open="suggestJsonOpen"
@clear="clearJson" />
<ms-api-assertions-edit
:is-read-only="isReadOnly"
:assertions="assertions"
:apiId="apiId"
:reloadData="reloadData"
style="margin-bottom: 20px"/>
:is-read-only="isReadOnly"
:assertions="assertions"
:apiId="apiId"
:reloadData="reloadData"
style="margin-bottom: 20px" />
<api-jsonpath-suggest
:tip="$t('api_test.request.extract.suggest_tip')"
@addSuggest="addJsonPathSuggest"
ref="jsonpathSuggest"/>
:tip="$t('api_test.request.extract.suggest_tip')"
@addSuggest="addJsonPathSuggest"
ref="jsonpathSuggest" />
</div>
</template>
<script>
import GlobalAssertionText from "./GlobalAssertionText";
import MsApiAssertionRegex from "./ApiAssertionRegex";
import MsApiAssertionDuration from "./ApiAssertionDuration";
import {ASSERTION_TYPE, JSONPath} from "../../../model/ApiTestModel";
import MsApiAssertionsEdit from "./ApiAssertionsEdit";
import MsApiAssertionJsonPath from "./ApiAssertionJsonPath";
import MsApiAssertionJsr223 from "./ApiAssertionJsr223";
import MsApiAssertionXPath2 from "./ApiAssertionXPath2";
import {getUUID} from "../../../utils";
import ApiJsonPathSuggestButton
from "./ApiJsonPathSuggestButton";
import ApiJsonpathSuggest from "./ApiJsonpathSuggest";
import MsApiAssertionDocument from "./document/DocumentHeader";
import GlobalAssertionText from './GlobalAssertionText';
import MsApiAssertionRegex from './ApiAssertionRegex';
import MsApiAssertionDuration from './ApiAssertionDuration';
import { ASSERTION_TYPE, JSONPath } from '../../../model/ApiTestModel';
import MsApiAssertionsEdit from './ApiAssertionsEdit';
import MsApiAssertionJsonPath from './ApiAssertionJsonPath';
import MsApiAssertionJsr223 from './ApiAssertionJsr223';
import MsApiAssertionXPath2 from './ApiAssertionXPath2';
import { getUUID } from '../../../utils';
import ApiJsonPathSuggestButton from './ApiJsonPathSuggestButton';
import ApiJsonpathSuggest from './ApiJsonpathSuggest';
import MsApiAssertionDocument from './document/DocumentHeader';
export default {
name: "GlobalAssertions",
name: 'GlobalAssertions',
components: {
ApiJsonpathSuggest,
ApiJsonPathSuggestButton,
@ -136,31 +132,34 @@ export default {
response: {},
customizeStyle: {
type: String,
default: "margin-top: 10px"
default: 'margin-top: 10px',
},
isReadOnly: {
type: Boolean,
default: false
default: false,
},
isShowJsonPathSuggest: {
type: Boolean,
default: true
}
default: true,
},
},
data() {
return {
options: ASSERTION_TYPE,
time: "",
type: "",
time: '',
type: '',
loading: false,
reloadData: "",
}
reloadData: '',
};
},
created() {
if (!this.assertions.xpathType) {
this.assertions.xpathType = 'xml';
}
},
methods: {
after() {
this.type = "";
this.type = '';
this.reloadData = getUUID().substring(0, 8);
this.reload();
},
@ -175,13 +174,13 @@ export default {
return;
}
this.$refs.jsonpathSuggest.open(this.response.responseResult.body);
})
});
},
reload() {
this.loading = true
this.loading = true;
this.$nextTick(() => {
this.loading = false
})
this.loading = false;
});
},
active() {
this.assertions.active = !this.assertions.active;
@ -197,7 +196,8 @@ export default {
jsonItem.setJSONPathDescription();
let expect = jsonItem.expect;
if (expect) {
expect = expect.replaceAll('\\', '\\\\')
expect = expect
.replaceAll('\\', '\\\\')
.replaceAll('(', '\\(')
.replaceAll(')', '\\)')
.replaceAll('+', '\\+')
@ -213,9 +213,9 @@ export default {
},
clearJson() {
this.assertions.jsonPath = [];
}
}
}
},
},
};
</script>
<style scoped>
@ -227,7 +227,7 @@ export default {
padding: 10px;
margin: 5px 0;
border-radius: 5px;
border: #DCDFE6 solid 1px;
border: #dcdfe6 solid 1px;
}
.icon.is-active {