Merge remote-tracking branch 'origin/main'

This commit is contained in:
liqiang-fit2cloud 2022-10-17 14:35:08 +08:00
commit ef9f70a4a8
11 changed files with 129 additions and 111 deletions

View File

@ -2,7 +2,6 @@ package io.metersphere.api.exec.scenario;
import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs;
import io.metersphere.base.mapper.ApiTestEnvironmentMapper;
import io.metersphere.commons.utils.JSON;
import io.metersphere.commons.utils.JSONUtil;
import io.metersphere.utils.LoggerUtil;
import org.apache.commons.collections.MapUtils;
@ -26,6 +25,12 @@ import java.util.Map;
@Service
@Transactional(rollbackFor = Exception.class)
public class ApiEnvironmentRunningParamService {
public static final String COMMON_CONFIG = "commonConfig";
public static final String VARIABLES = "variables";
public static final String VALUE = "value";
public static final String ENABLE = "enable";
public static final String NAME = "name";
public static final String ENV_STR = "MS.ENV.";
@Resource
ApiTestEnvironmentMapper testEnvironmentMapper;
@ -40,10 +45,10 @@ public class ApiEnvironmentRunningParamService {
boolean envNeedUpdate = false;
try {
JSONObject configObj = JSONUtil.parseObject(environment.getConfig());
if (configObj.has("commonConfig")) {
JSONObject commonConfig = configObj.optJSONObject("commonConfig");
if (commonConfig.has("variables")) {
JSONArray variables = commonConfig.optJSONArray("variables");
if (configObj.has(COMMON_CONFIG)) {
JSONObject commonConfig = configObj.optJSONObject(COMMON_CONFIG);
if (commonConfig.has(VARIABLES)) {
JSONArray variables = commonConfig.optJSONArray(VARIABLES);
List<JSONObject> variableList = new LinkedList<>();
for (Map.Entry<String, String> entry : varMap.entrySet()) {
String key = entry.getKey();
@ -52,64 +57,45 @@ public class ApiEnvironmentRunningParamService {
boolean contains = false;
for (int i = 0; i < variables.length(); i++) {
JSONObject jsonObj = variables.optJSONObject(i);
if (jsonObj.has("name") && StringUtils.equals(jsonObj.optString("name"), key)) {
if (jsonObj.has(NAME) && StringUtils.equals(jsonObj.optString(NAME), key)) {
contains = true;
if (jsonObj.has("value") && StringUtils.equals(jsonObj.optString("value"), value)) {
if (jsonObj.has(VALUE) && StringUtils.equals(jsonObj.optString(VALUE), value)) {
break;
} else {
envNeedUpdate = true;
jsonObj.put("value", value);
jsonObj.put(VALUE, value);
}
}
}
if (!contains) {
envNeedUpdate = true;
JSONObject itemObj = new JSONObject();
itemObj.put("name", key);
itemObj.put("value", value);
itemObj.put("enable", true);
itemObj.put(NAME, key);
itemObj.put(VALUE, value);
itemObj.put(ENABLE, true);
if (variableList.size() == 0) {
variableList.add(itemObj);
} else {
variableList.add(variables.length() - 1, itemObj);
}
commonConfig.put("variables", new JSONArray(variableList));
commonConfig.put(VARIABLES, variableList);
}
}
} else {
List<JSONObject> variables = new LinkedList<>();
for (Map.Entry<String, String> entry : varMap.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
JSONObject itemObj = new JSONObject();
itemObj.put("name", key);
itemObj.put("value", value);
itemObj.put("enable", true);
variables.add(itemObj);
}
List<JSONObject> variables = createArray(varMap);
JSONObject emptyObj = new JSONObject();
emptyObj.put("enable", true);
emptyObj.put(ENABLE, true);
variables.add(emptyObj);
commonConfig.put("variables", new JSONArray(variables));
commonConfig.put(VARIABLES, variables);
}
} else {
JSONObject commonConfig = new JSONObject();
List<JSONObject> variables = new LinkedList<>();
for (Map.Entry<String, String> entry : varMap.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
JSONObject itemObj = new JSONObject();
itemObj.put("name", key);
itemObj.put("value", value);
itemObj.put("enable", true);
variables.add(itemObj);
}
List<JSONObject> variables = createArray(varMap);
JSONObject emptyObj = new JSONObject();
emptyObj.put("enable", true);
emptyObj.put(ENABLE, true);
variables.add(emptyObj);
commonConfig.put("variables", new JSONArray(variables));
configObj.put("commonConfig", commonConfig);
commonConfig.put(VARIABLES, variables);
configObj.put(COMMON_CONFIG, commonConfig);
}
if (envNeedUpdate) {
environment.setConfig(configObj.toString());
@ -131,8 +117,8 @@ public class ApiEnvironmentRunningParamService {
continue;
}
String jmeterVarKey = envItem[0];
if (this.checkValidity(jmeterVarKey, "MS.ENV.")) {
String[] envAndKeyArr = jmeterVarKey.substring("MS.ENV.".length()).split("\\.");
if (this.checkValidity(jmeterVarKey, ENV_STR)) {
String[] envAndKeyArr = jmeterVarKey.substring(ENV_STR.length()).split("\\.");
if (ArrayUtils.isEmpty(envAndKeyArr)) {
continue;
}
@ -172,6 +158,18 @@ public class ApiEnvironmentRunningParamService {
}
}
private List<JSONObject> createArray(Map<String, String> varMap) {
List<JSONObject> variables = new LinkedList<>();
for (Map.Entry<String, String> entry : varMap.entrySet()) {
JSONObject itemObj = new JSONObject();
itemObj.put(NAME, entry.getKey());
itemObj.put(VALUE, entry.getValue());
itemObj.put(ENABLE, true);
variables.add(itemObj);
}
return variables;
}
public boolean checkValidity(String str, String regex) {
if (str == null) {
return false;

View File

@ -1,6 +1,8 @@
package io.metersphere.api.parse;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor;
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.dto.scenario.Body;
@ -189,18 +191,18 @@ public abstract class HarScenarioAbstractParser<T> extends ApiImportAbstractPars
}
private void parseBody(Body body, PostmanRequest requestDesc) {
JSONObject postmanBody = requestDesc.getBody();
ObjectNode postmanBody = requestDesc.getBody();
if (postmanBody == null) {
return;
}
String bodyMode = postmanBody.optString("mode");
String bodyMode = postmanBody.get("mode").textValue();
if (StringUtils.isBlank(bodyMode)) {
return;
}
if (StringUtils.equals(bodyMode, PostmanRequestBodyMode.RAW.value())) {
parseRawBody(body, postmanBody, bodyMode);
} else if (StringUtils.equalsAny(bodyMode, PostmanRequestBodyMode.FORM_DATA.value(), PostmanRequestBodyMode.URLENCODED.value())) {
List<PostmanKeyValue> postmanKeyValues = JSON.parseArray(postmanBody.optString(bodyMode), PostmanKeyValue.class);
List<PostmanKeyValue> postmanKeyValues = JSON.parseArray(postmanBody.get(bodyMode).textValue(), PostmanKeyValue.class);
body.setKvs(parseKeyValue(postmanKeyValues));
if (StringUtils.equals(bodyMode, PostmanRequestBodyMode.FORM_DATA.value())) {
body.setType(Body.FORM_DATA);
@ -218,15 +220,15 @@ public abstract class HarScenarioAbstractParser<T> extends ApiImportAbstractPars
return XMLUtil.jsonToXmlStr(object);
}
private void parseRawBody(Body body, JSONObject postmanBody, String bodyMode) {
body.setRaw(postmanBody.optString(bodyMode));
private void parseRawBody(Body body, ObjectNode postmanBody, String bodyMode) {
body.setRaw(postmanBody.get(bodyMode).textValue());
body.setType(MsRequestBodyType.RAW.value());
JSONObject options = postmanBody.optJSONObject("options");
JsonNode options = postmanBody.get("options");
if (options != null) {
JSONObject raw = options.optJSONObject(PostmanRequestBodyMode.RAW.value());
JsonNode raw = options.get(PostmanRequestBodyMode.RAW.value());
if (raw != null) {
String bodyType = "";
switch (raw.optString("language")) {
switch (raw.get("language").textValue()) {
case "json":
bodyType = Body.JSON_STR;
break;

View File

@ -1,6 +1,8 @@
package io.metersphere.api.parse;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.dto.definition.response.HttpResponse;
import io.metersphere.api.dto.scenario.Body;
@ -30,7 +32,8 @@ public abstract class PostmanAbstractParserParser<T> extends ApiImportAbstractPa
}
requestDesc.getAuth(); // todo 认证方式等待优化
PostmanUrl url = requestDesc.getUrl();
MsHTTPSamplerProxy request = buildRequest(requestItem.getName(), url == null ? "" : url.getRaw(), requestDesc.getMethod(), Optional.ofNullable(requestDesc.getBody()).orElse(new JSONObject()).optString("jsonSchema"));
MsHTTPSamplerProxy request = buildRequest(requestItem.getName(), url == null ? "" : url.getRaw(), requestDesc.getMethod(),
requestDesc.getBody().get("jsonSchema") == null ? "" : requestDesc.getBody().get("jsonSchema").textValue());
request.setRest(parseKeyValue(requestDesc.getUrl().getVariable()));
if (StringUtils.isNotBlank(request.getPath())) {
String path = request.getPath().split("\\?")[0];
@ -132,18 +135,20 @@ public abstract class PostmanAbstractParserParser<T> extends ApiImportAbstractPa
}
private void parseBody(Body body, PostmanRequest requestDesc) {
JSONObject postmanBody = requestDesc.getBody();
ObjectNode postmanBody = requestDesc.getBody();
if (postmanBody == null) {
return;
}
String bodyMode = postmanBody.optString("mode");
String bodyMode = postmanBody.get("mode").textValue();
if (StringUtils.isBlank(bodyMode)) {
return;
}
if (StringUtils.equals(bodyMode, PostmanRequestBodyMode.RAW.value())) {
parseRawBody(body, postmanBody, bodyMode);
} else if (StringUtils.equalsAny(bodyMode, PostmanRequestBodyMode.FORM_DATA.value(), PostmanRequestBodyMode.URLENCODED.value())) {
List<PostmanKeyValue> postmanKeyValues = JSON.parseArray(parseVariable(postmanBody.optString(bodyMode)), PostmanKeyValue.class);
String s1 = postmanBody.get(bodyMode).toString();
String s = parseVariable(s1);
List<PostmanKeyValue> postmanKeyValues = JSON.parseArray(s, PostmanKeyValue.class);
body.setKvs(parseKeyValue(postmanKeyValues));
if (StringUtils.equals(bodyMode, PostmanRequestBodyMode.FORM_DATA.value())) {
body.setType(Body.FORM_DATA);
@ -156,15 +161,15 @@ public abstract class PostmanAbstractParserParser<T> extends ApiImportAbstractPa
}
}
private void parseRawBody(Body body, JSONObject postmanBody, String bodyMode) {
body.setRaw(parseVariable(postmanBody.optString(bodyMode)));
private void parseRawBody(Body body, ObjectNode postmanBody, String bodyMode) {
body.setRaw(parseVariable(postmanBody.get(bodyMode).textValue()));
body.setType(MsRequestBodyType.RAW.value());
JSONObject options = postmanBody.optJSONObject("options");
JsonNode options = postmanBody.get("options");
if (options != null) {
JSONObject raw = options.optJSONObject(PostmanRequestBodyMode.RAW.value());
JsonNode raw = options.get(PostmanRequestBodyMode.RAW.value());
if (raw != null) {
String bodyType = "";
switch (raw.optString("language")) {
switch (raw.get("language").textValue()) {
case "json":
bodyType = Body.JSON_STR;
break;

View File

@ -1,6 +1,7 @@
package io.metersphere.api.parse.postman;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.Data;
import org.json.JSONObject;
@ -12,8 +13,8 @@ public class PostmanRequest {
private String method;
private String schema;
private List<PostmanKeyValue> header;
private JSONObject body;
private JSONObject auth;
private ObjectNode body;
private ObjectNode auth;
private PostmanUrl url;
private String description;
}

View File

@ -1,7 +1,6 @@
package io.metersphere.commons.utils;
import io.metersphere.api.exec.engine.EngineSourceParserFactory;
import io.metersphere.commons.utils.LogUtil;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.Element;
@ -190,7 +189,7 @@ public class XMLUtil {
if (list.size() == 1) {
result.put(node.getName(), list.get(0));
} else {
result.put(node.getName(), new JSONArray(list));
result.put(node.getName(), list);
}
} else {
if (!StringUtils.isAllBlank(node.getName(), node.getText())) {

View File

@ -354,9 +354,7 @@ public class MockApiUtils {
if (!((JSONObject) paramJson).keySet().isEmpty()) {
JSONArray bodyParams = returnParams.getBodyParams();
if (bodyParams == null) {
List<Object> paramsArray = new LinkedList<>();
paramsArray.add(paramJson);
bodyParams = new JSONArray(paramsArray);
bodyParams.put(paramJson);
} else {
bodyParams.put(((JSONObject) paramJson));
}
@ -392,9 +390,9 @@ public class MockApiUtils {
requestMockParams.setQueryParamsObj(queryParamsObject);
if (isPostRequest) {
List<Object> jsonArray = new ArrayList<>();
jsonArray.add(queryParamsObject);
requestMockParams.setBodyParams(new JSONArray(jsonArray));
JSONArray jsonArray = new JSONArray();
jsonArray.put(queryParamsObject);
requestMockParams.setBodyParams(jsonArray);
}
return requestMockParams;
}

View File

@ -150,7 +150,7 @@ public class MsHashTreeService {
if (CollectionUtils.isNotEmpty(rules)) {
step.addAll(rules);
}
element.put(HASH_TREE, new JSONArray(step));
element.put(HASH_TREE, step);
}
element.put(REFERENCED, REF);
element.put(DISABLED, true);

View File

@ -1,31 +1,34 @@
<template>
<el-table :data="assertions" :row-style="getRowStyle" :header-cell-style="getRowStyle">
<el-table-column prop="name" :label="$t('api_report.assertions_name')" width="150" show-overflow-tooltip>
<template v-slot:default="scope">
<span>{{ !scope.row.name || scope.row.name === 'null' ? "" : scope.row.name }}</span>
</template>
</el-table-column>
<el-table-column prop="content" v-if="showContent" :label="$t('api_report.assertions_content')" width="300" show-overflow-tooltip/>
<el-table-column prop="message" :label="$t('api_report.assertions_error_message')"/>
<el-table-column prop="pass" :label="$t('api_report.assertions_is_success')" width="180">
<template v-slot:default="{row}">
<el-tag size="mini" type="success" v-if="row.pass">
{{ $t('api_report.success') }}
</el-tag>
<el-tag size="mini" type="danger" v-else>
{{ $t('api_report.fail') }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="script">
<template v-slot:default="{row}">
<div class="assertion-item btn circle" v-if="row.script">
<i class="el-icon-view el-button el-button--primary el-button--mini is-circle" circle
@click="showPage(row.script)"/>
</div>
</template>
</el-table-column>
<el-dialog :title="$t('api_test.request.assertions.script')" :visible.sync="visible" width="900px" append-to-body>
<div>
<el-table :data="assertions" :row-style="getRowStyle" :header-cell-style="getRowStyle">
<el-table-column prop="name" :label="$t('api_report.assertions_name')" width="150" show-overflow-tooltip>
<template v-slot:default="scope">
<span>{{ !scope.row.name || scope.row.name === 'null' ? "" : scope.row.name }}</span>
</template>
</el-table-column>
<el-table-column prop="content" v-if="showContent" :label="$t('api_report.assertions_content')" width="300"
show-overflow-tooltip/>
<el-table-column prop="message" :label="$t('api_report.assertions_error_message')"/>
<el-table-column prop="pass" :label="$t('api_report.assertions_is_success')" width="180">
<template v-slot:default="{row}">
<el-tag size="mini" type="success" v-if="row.pass">
{{ $t('api_report.success') }}
</el-tag>
<el-tag size="mini" type="danger" v-else>
{{ $t('api_report.fail') }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="script">
<template v-slot:default="{row}">
<div class="assertion-item btn circle" v-if="row.script">
<i class="el-icon-view el-button el-button--primary el-button--mini is-circle" circle
@click="showPage(row.script)"/>
</div>
</template>
</el-table-column>
</el-table>
<el-dialog :title="$t('api_test.request.assertions.script')" :visible.sync="visible" width="900px" modal-append-to-body append-to-body>
<el-row type="flex" justify="space-between" align="middle" class="quick-script-block">
<el-col :span="codeSpan" class="script-content">
<ms-code-edit v-if="isCodeEditAlive"
@ -35,7 +38,7 @@
</el-col>
</el-row>
</el-dialog>
</el-table>
</div>
</template>
<script>

View File

@ -1,15 +1,15 @@
import {
ID,
NAME,
PRIORITY,
TAGS,
API_SCENARIO_RESULT,
UPDATE_TIME,
CREATE_TIME,
CREATOR,
FOLLOW_PEOPLE,
ID,
NAME,
OPERATORS,
PRIORITY,
STEP_COUNT,
OPERATORS
TAGS,
UPDATE_TIME
} from "metersphere-frontend/src/components/search/search-components";
export function STEP() {
@ -152,6 +152,12 @@ export const SCENARIO_MODULE_TREE = _getModuleTree({
params: {}
})
export const SCENARIO_MODULE_TRASH_TREE = _getModuleTree({
url: "/api/automation/module/trash/list",
type: "GET",
params: {}
})
export const API_STATUS_TRASH = {
key: "status",
name: 'MsTableSearchSelect',
@ -165,5 +171,5 @@ export const API_STATUS_TRASH = {
}
}
export const API_SCENARIO_CONFIGS_TRASH = [ID, NAME, PRIORITY, TAGS, API_SCENARIO_RESULT, UPDATE_TIME, CREATE_TIME, CREATOR, FOLLOW_PEOPLE, STEP_COUNT, SCENARIO_MODULE_TREE, API_STATUS_TRASH];
export const API_SCENARIO_CONFIGS_TRASH = [ID, NAME, PRIORITY, TAGS, API_SCENARIO_RESULT, UPDATE_TIME, CREATE_TIME, CREATOR, FOLLOW_PEOPLE, STEP_COUNT, SCENARIO_MODULE_TRASH_TREE, API_STATUS_TRASH];

View File

@ -1,16 +1,16 @@
import {Assertions} from "@/business/definition/model/ApiTestModel";
import {getUUID} from "metersphere-frontend/src/utils";
import {
ID,
NAME,
API_METHOD,
API_PATH,
TAGS,
UPDATE_TIME,
CREATE_TIME,
API_PRINCIPAL,
CREATE_TIME,
FOLLOW_PEOPLE,
OPERATORS
ID,
NAME,
OPERATORS,
TAGS,
UPDATE_TIME
} from "metersphere-frontend/src/components/search/search-components";
function _getModuleTree(options) {
@ -32,6 +32,12 @@ export const API_MODULE_TREE = _getModuleTree({
type: "GET",
params: {}
})
export const API_MODULE_TRASH_TREE = _getModuleTree({
url: "/api/module/trash/list",
type: "GET",
params: {}
})
export const API_STATUS_TRASH = {
key: "status",
name: 'MsTableSearchSelect',
@ -45,7 +51,7 @@ export const API_STATUS_TRASH = {
}
}
export const API_DEFINITION_CONFIGS_TRASH = [ID, NAME, API_METHOD, API_PATH, API_STATUS_TRASH, TAGS, UPDATE_TIME, CREATE_TIME, API_PRINCIPAL, API_MODULE_TREE, FOLLOW_PEOPLE];
export const API_DEFINITION_CONFIGS_TRASH = [ID, NAME, API_METHOD, API_PATH, API_STATUS_TRASH, TAGS, UPDATE_TIME, CREATE_TIME, API_PRINCIPAL, API_MODULE_TRASH_TREE, FOLLOW_PEOPLE];
export function getProtocolFilter(protocolType) {
if (protocolType === "HTTP") {

View File

@ -186,7 +186,7 @@ export default {
{
tip: this.$t('commons.delete'), icon: "el-icon-delete", type: "danger",
exec: this.handleDelete,
permission: ['PROJECT_TRACK_REVIEW:READ+DELETE']
permissions: ['PROJECT_TRACK_REVIEW:READ+DELETE']
},
],
};