fix(接口测试): 修复文档结构断言跟随API定义问题

--bug=1008038 --user=赵勇 文档校验断言选择跟随API定义时报错 https://www.tapd.cn/55049933/s/1069713
This commit is contained in:
fit2-zhao 2021-11-18 12:57:00 +08:00 committed by fit2-zhao
parent 0b90066e12
commit 9f86e78b69
3 changed files with 62 additions and 45 deletions

View File

@ -33,7 +33,6 @@ import io.metersphere.base.mapper.*;
import io.metersphere.base.mapper.ext.*; import io.metersphere.base.mapper.ext.*;
import io.metersphere.commons.constants.*; import io.metersphere.commons.constants.*;
import io.metersphere.commons.exception.MSException; import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.json.JSONSchemaToDocumentUtils;
import io.metersphere.commons.json.JSONToDocumentUtils; import io.metersphere.commons.json.JSONToDocumentUtils;
import io.metersphere.commons.utils.*; import io.metersphere.commons.utils.*;
import io.metersphere.controller.request.ResetOrderRequest; import io.metersphere.controller.request.ResetOrderRequest;
@ -1736,35 +1735,25 @@ public class ApiDefinitionService {
public List<DocumentElement> getDocument(String id, String type) { public List<DocumentElement> getDocument(String id, String type) {
ApiDefinitionWithBLOBs bloBs = apiDefinitionMapper.selectByPrimaryKey(id); ApiDefinitionWithBLOBs bloBs = apiDefinitionMapper.selectByPrimaryKey(id);
List<DocumentElement> list = new LinkedList<>(); List<DocumentElement> elements = new LinkedList<>();
if (bloBs != null && StringUtils.isNotEmpty(bloBs.getResponse())) { if (bloBs != null && StringUtils.isNotEmpty(bloBs.getResponse())) {
JSONObject object = JSON.parseObject(bloBs.getResponse()); JSONObject object = JSON.parseObject(bloBs.getResponse());
JSONObject body = (JSONObject) object.get("body"); JSONObject body = (JSONObject) object.get("body");
if (body != null) { if (body != null) {
if (StringUtils.equals(type, "JSON")) { String raw = body.getString("raw");
String jsonSchema = body.getString("jsonSchema"); String dataType = body.getString("type");
String dataType = body.getString("type"); if (StringUtils.isNotEmpty(raw) && StringUtils.isNotEmpty(dataType)) {
if (StringUtils.equalsAny(dataType, "JSON", "JSON-SCHEMA") && StringUtils.isNotEmpty(jsonSchema)) { if (StringUtils.equals(type, "JSON")) {
JSONObject obj = (JSONObject) body.get("jsonSchema"); elements = JSONToDocumentUtils.getDocument(raw, dataType);
if (StringUtils.equals(obj.getString("type"), "array")) { } else if (StringUtils.equals(dataType, "XML")) {
list.add(new DocumentElement().newRoot("array", JSONSchemaToDocumentUtils.getDocument(jsonSchema))); elements = JSONToDocumentUtils.getDocument(raw, type);
} else {
list.add(new DocumentElement().newRoot("object", JSONSchemaToDocumentUtils.getDocument(jsonSchema)));
}
} else {
list.add(new DocumentElement().newRoot("object", null));
}
} else {
String xml = body.getString("raw");
String dataType = body.getString("type");
if (StringUtils.equals(dataType, "XML") && StringUtils.isNotEmpty(xml)) {
list = JSONToDocumentUtils.getDocument(xml, type);
} else {
list.add(new DocumentElement().newRoot("root", null));
} }
} }
} }
} }
return list; if (CollectionUtils.isEmpty(elements)) {
elements.add(new DocumentElement().newRoot("root", null));
}
return elements;
} }
} }

View File

@ -5,6 +5,7 @@ import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.definition.request.assertions.document.DocumentElement; import io.metersphere.api.dto.definition.request.assertions.document.DocumentElement;
import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.LogUtil;
import net.sf.json.util.JSONTokener;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document; import org.dom4j.Document;
import org.dom4j.Element; import org.dom4j.Element;
@ -19,8 +20,18 @@ public class JSONToDocumentUtils {
public static void jsonDataFormatting(JSONArray array, List<DocumentElement> children) { public static void jsonDataFormatting(JSONArray array, List<DocumentElement> children) {
for (int i = 0; i < array.size(); i++) { for (int i = 0; i < array.size(); i++) {
JSONObject element = array.getJSONObject(i); Object value = array.get(i);
jsonDataFormatting(element, children); if (value instanceof JSONObject) {
List<DocumentElement> childrenElements = new LinkedList<>();
children.add(new DocumentElement("", "object", "", childrenElements));
jsonDataFormatting((JSONObject) value, childrenElements);
} else if (value instanceof JSONArray) {
List<DocumentElement> childrenElements = new LinkedList<>();
children.add(new DocumentElement("", "array", "", childrenElements));
jsonDataFormatting((JSONArray) value, childrenElements);
} else {
children.add(new DocumentElement("", "string", value, null));
}
} }
} }
@ -47,12 +58,23 @@ public class JSONToDocumentUtils {
if (StringUtils.equals(type, "JSON")) { if (StringUtils.equals(type, "JSON")) {
List<DocumentElement> roots = new LinkedList<>(); List<DocumentElement> roots = new LinkedList<>();
List<DocumentElement> children = new LinkedList<>(); List<DocumentElement> children = new LinkedList<>();
roots.add(new DocumentElement("root", "root", "object", "", children)); Object typeObject = new JSONTokener(json).nextValue();
JSONObject object = JSON.parseObject(json); if (typeObject instanceof net.sf.json.JSONArray) {
jsonDataFormatting(object, children); roots.add(new DocumentElement().newRoot("array", children));
JSONArray array = JSON.parseArray(json);
jsonDataFormatting(array, children);
} else {
roots.add(new DocumentElement().newRoot("object", children));
JSONObject object = JSON.parseObject(json);
jsonDataFormatting(object, children);
}
return roots; return roots;
} else { } else if (StringUtils.equals(type, "XML")) {
return getXmlDocument(json); return getXmlDocument(json);
} else {
return new LinkedList<DocumentElement>() {{
this.add(new DocumentElement().newRoot("root", null));
}};
} }
} catch (Exception e) { } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e);

View File

@ -47,12 +47,6 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="arrayVerification" width="140" label="校验数组内元素" :render-header="renderHeaderArray">
<template slot-scope="scope">
<el-checkbox v-model="scope.row.arrayVerification" @change="handleCheckOneChange" v-if="scope.row.type==='array'" :disabled="checked"/>
</template>
</el-table-column>
<el-table-column prop="contentVerification" label="内容校验" width="200"> <el-table-column prop="contentVerification" label="内容校验" width="200">
<template slot-scope="scope"> <template slot-scope="scope">
<el-select v-model="scope.row.contentVerification" :placeholder="$t('commons.please_select')" size="mini" :disabled="checked"> <el-select v-model="scope.row.contentVerification" :placeholder="$t('commons.please_select')" size="mini" :disabled="checked">
@ -67,12 +61,24 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('commons.operating')" width="200" fixed="right"> <el-table-column prop="arrayVerification" width="140" label="校验数组内元素" :render-header="renderHeaderArray">
<template slot-scope="scope">
<el-checkbox v-model="scope.row.arrayVerification" @change="handleCheckOneChange" v-if="scope.row.type==='array'" :disabled="checked"/>
</template>
</el-table-column>
<el-table-column :label="$t('commons.operating')" width="130" fixed="right">
<template v-slot:default="scope"> <template v-slot:default="scope">
<span> <span>
<el-button size="mini" type="text" circle @click="addVerification(scope.row)" :disabled="scope.row.type ==='object' ||scope.row.type ==='array' || checked || scope.row.id==='root'">添加校验</el-button> <el-tooltip effect="dark" content="添加校验" placement="top-start">
<el-button size="mini" type="text" @click="addRow(scope.row)" :disabled="(scope.row.type !=='object' && scope.row.type !=='array') || checked">添加子字段</el-button> <el-button icon="el-icon-document-checked" circle type="primary" size="mini" @click="addVerification(scope.row)" :disabled="scope.row.type ==='object' ||scope.row.type ==='array' || checked || scope.row.id==='root'"/>
<el-button size="mini" type="text" @click="remove(scope.row)" :disabled="checked || scope.row.id==='root'">{{ $t('commons.remove') }}</el-button> </el-tooltip>
<el-tooltip effect="dark" content="添加子字段" placement="top-start">
<el-button icon="el-icon-plus" circle type="primary" size="mini" style="margin-left: 10px" @click="addRow(scope.row)" :disabled="(scope.row.type !=='object' && scope.row.type !=='array') || checked"/>
</el-tooltip>
<el-tooltip effect="dark" :content="$t('commons.remove')" placement="top-start">
<el-button icon="el-icon-delete" type="primary" circle size="mini" style="margin-left: 10px" @click="remove(scope.row)" :disabled="checked || scope.row.id==='root'"/>
</el-tooltip>
</span> </span>
</template> </template>
</el-table-column> </el-table-column>
@ -246,7 +252,7 @@ export default {
'span', [ 'span', [
h('el-checkbox', { h('el-checkbox', {
style: 'margin-right:5px;', style: 'margin-right:5px;',
disabled:this.checked, disabled: this.checked,
on: { on: {
change: this.handleCheckAllChange change: this.handleCheckAllChange
}, },
@ -260,7 +266,7 @@ export default {
'span', [ 'span', [
h('el-checkbox', { h('el-checkbox', {
style: 'margin-right:5px;', style: 'margin-right:5px;',
disabled:this.checked, disabled: this.checked,
on: { on: {
change: this.handleType change: this.handleType
} }
@ -274,7 +280,7 @@ export default {
'span', [ 'span', [
h('el-checkbox', { h('el-checkbox', {
style: 'margin-right:5px;', style: 'margin-right:5px;',
disabled:this.checked, disabled: this.checked,
on: { on: {
change: this.handleArray change: this.handleArray
} }
@ -302,7 +308,7 @@ export default {
} }
}, },
handleCheckAllChange(val) { handleCheckAllChange(val) {
if(this.checked){ if (this.checked) {
return; return;
} }
this.tableData.forEach(item => { this.tableData.forEach(item => {
@ -311,7 +317,7 @@ export default {
}) })
}, },
handleType(val) { handleType(val) {
if(this.checked) { if (this.checked) {
return; return;
} }
this.tableData.forEach(item => { this.tableData.forEach(item => {
@ -320,7 +326,7 @@ export default {
}) })
}, },
handleArray(val) { handleArray(val) {
if(this.checked){ if (this.checked) {
return; return;
} }
this.tableData.forEach(item => { this.tableData.forEach(item => {