feat(Mock优化): #1003356 Mock服务期望及响应配置优化

【Mock服务期望及响应配置优化】
https://www.tapd.cn/55049933/prong/stories/view/1155049933001003356
This commit is contained in:
song-tianyang 2021-10-20 19:44:52 +08:00 committed by song-tianyang
parent 5453dcdcec
commit 6392190f54
27 changed files with 3465 additions and 326 deletions

View File

@ -1,6 +1,6 @@
package io.metersphere.api.controller; package io.metersphere.api.controller;
import io.metersphere.api.service.ApiDefinitionService; import io.metersphere.api.dto.mock.MockApiUtils;
import io.metersphere.api.service.MockConfigService; import io.metersphere.api.service.MockConfigService;
import io.metersphere.api.tcp.TCPPool; import io.metersphere.api.tcp.TCPPool;
import io.metersphere.base.domain.Project; import io.metersphere.base.domain.Project;
@ -11,6 +11,7 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.util.Map;
/** /**
* @author song.tianyang * @author song.tianyang
@ -30,7 +31,8 @@ public class MockApiController {
@NoResultHolder @NoResultHolder
public String postRequest(@PathVariable String projectSystemId, HttpServletRequest request, HttpServletResponse response) { public String postRequest(@PathVariable String projectSystemId, HttpServletRequest request, HttpServletResponse response) {
Project project = projectService.findBySystemId(projectSystemId); Project project = projectService.findBySystemId(projectSystemId);
String returnStr = mockConfigService.checkReturnWithMockExpectByBodyParam("POST", project, request, response); Map<String,String> requestHeaderMap = MockApiUtils.getHttpRequestHeader(request);
String returnStr = mockConfigService.checkReturnWithMockExpectByBodyParam("POST", requestHeaderMap,project, request, response);
return returnStr; return returnStr;
} }
@ -38,7 +40,8 @@ public class MockApiController {
@NoResultHolder @NoResultHolder
public String getRequest(@PathVariable String projectSystemId, HttpServletRequest request, HttpServletResponse response) { public String getRequest(@PathVariable String projectSystemId, HttpServletRequest request, HttpServletResponse response) {
Project project = projectService.findBySystemId(projectSystemId); Project project = projectService.findBySystemId(projectSystemId);
String returnStr = mockConfigService.checkReturnWithMockExpectByUrlParam("GET", project, request, response); Map<String,String> requestHeaderMap = MockApiUtils.getHttpRequestHeader(request);
String returnStr = mockConfigService.checkReturnWithMockExpectByUrlParam("GET", requestHeaderMap, project, request, response);
return returnStr; return returnStr;
} }
@ -46,7 +49,8 @@ public class MockApiController {
@NoResultHolder @NoResultHolder
public String putRequest(@PathVariable String projectSystemId, HttpServletRequest request, HttpServletResponse response) { public String putRequest(@PathVariable String projectSystemId, HttpServletRequest request, HttpServletResponse response) {
Project project = projectService.findBySystemId(projectSystemId); Project project = projectService.findBySystemId(projectSystemId);
String returnStr = mockConfigService.checkReturnWithMockExpectByBodyParam("PUT", project, request, response); Map<String,String> requestHeaderMap = MockApiUtils.getHttpRequestHeader(request);
String returnStr = mockConfigService.checkReturnWithMockExpectByBodyParam("PUT", requestHeaderMap, project, request, response);
return returnStr; return returnStr;
} }
@ -54,7 +58,8 @@ public class MockApiController {
@NoResultHolder @NoResultHolder
public String patchRequest(@PathVariable String projectSystemId, HttpServletRequest request, HttpServletResponse response) { public String patchRequest(@PathVariable String projectSystemId, HttpServletRequest request, HttpServletResponse response) {
Project project = projectService.findBySystemId(projectSystemId); Project project = projectService.findBySystemId(projectSystemId);
String returnStr = mockConfigService.checkReturnWithMockExpectByBodyParam("PATCH", project, request, response); Map<String,String> requestHeaderMap = MockApiUtils.getHttpRequestHeader(request);
String returnStr = mockConfigService.checkReturnWithMockExpectByBodyParam("PATCH", requestHeaderMap, project, request, response);
return returnStr; return returnStr;
} }
@ -62,7 +67,8 @@ public class MockApiController {
@NoResultHolder @NoResultHolder
public String deleteRequest(@PathVariable String projectSystemId, HttpServletRequest request, HttpServletResponse response) { public String deleteRequest(@PathVariable String projectSystemId, HttpServletRequest request, HttpServletResponse response) {
Project project = projectService.findBySystemId(projectSystemId); Project project = projectService.findBySystemId(projectSystemId);
String returnStr = mockConfigService.checkReturnWithMockExpectByUrlParam("DELETE", project, request, response); Map<String,String> requestHeaderMap = MockApiUtils.getHttpRequestHeader(request);
String returnStr = mockConfigService.checkReturnWithMockExpectByUrlParam("DELETE", requestHeaderMap, project, request, response);
return returnStr; return returnStr;
} }
@ -70,7 +76,8 @@ public class MockApiController {
@NoResultHolder @NoResultHolder
public String optionsRequest(@PathVariable String projectSystemId, HttpServletRequest request, HttpServletResponse response) { public String optionsRequest(@PathVariable String projectSystemId, HttpServletRequest request, HttpServletResponse response) {
Project project = projectService.findBySystemId(projectSystemId); Project project = projectService.findBySystemId(projectSystemId);
String returnStr = mockConfigService.checkReturnWithMockExpectByUrlParam("OPTIONS", project, request, response); Map<String,String> requestHeaderMap = MockApiUtils.getHttpRequestHeader(request);
String returnStr = mockConfigService.checkReturnWithMockExpectByUrlParam("OPTIONS", requestHeaderMap, project, request, response);
return returnStr; return returnStr;
} }
@ -78,7 +85,8 @@ public class MockApiController {
@NoResultHolder @NoResultHolder
public void headRequest(@PathVariable String projectSystemId, HttpServletRequest request, HttpServletResponse response) { public void headRequest(@PathVariable String projectSystemId, HttpServletRequest request, HttpServletResponse response) {
Project project = projectService.findBySystemId(projectSystemId); Project project = projectService.findBySystemId(projectSystemId);
mockConfigService.checkReturnWithMockExpectByUrlParam("HEAD", project, request, response); Map<String,String> requestHeaderMap = MockApiUtils.getHttpRequestHeader(request);
mockConfigService.checkReturnWithMockExpectByUrlParam("HEAD", requestHeaderMap, project, request, response);
} }
@GetMapping("/getTcpMockPortStatus/") @GetMapping("/getTcpMockPortStatus/")

View File

@ -1,5 +1,6 @@
package io.metersphere.api.controller; package io.metersphere.api.controller;
import io.metersphere.api.dto.mock.MockApiUtils;
import io.metersphere.api.dto.mockconfig.MockConfigRequest; import io.metersphere.api.dto.mockconfig.MockConfigRequest;
import io.metersphere.api.dto.mockconfig.MockExpectConfigRequest; import io.metersphere.api.dto.mockconfig.MockExpectConfigRequest;
import io.metersphere.api.dto.mockconfig.response.MockConfigResponse; import io.metersphere.api.dto.mockconfig.response.MockConfigResponse;
@ -10,6 +11,7 @@ import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
import io.metersphere.base.domain.MockExpectConfig; import io.metersphere.base.domain.MockExpectConfig;
import io.metersphere.base.domain.MockExpectConfigWithBLOBs; import io.metersphere.base.domain.MockExpectConfigWithBLOBs;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.List; import java.util.List;
@ -34,11 +36,25 @@ public class MockConfigController {
return mockConfigService.genMockConfig(request); return mockConfigService.genMockConfig(request);
} }
@PostMapping("/updateMockExpectConfig") @PostMapping(value ="/updateMockExpectConfig", consumes = {"multipart/form-data"})
public MockExpectConfig updateMockExpectConfig(@RequestBody MockExpectConfigRequest request) { public MockExpectConfig updateMockExpectConfig(@RequestPart("request")MockExpectConfigRequest request, @RequestPart(value = "files", required = false) List<MultipartFile> bodyFiles) {
return mockConfigService.updateMockExpectConfig(request); return mockConfigService.updateMockExpectConfig(request,bodyFiles);
} }
@PostMapping(value ="/updateMockExpectConfigStatus")
public MockExpectConfig updateMockExpectConfig(@RequestBody MockExpectConfigRequest request) {
return mockConfigService.updateMockExpectConfigStatus(request);
}
// @PostMapping(value = "/create", consumes = {"multipart/form-data"})
// @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ_CREATE_API)
// @MsAuditLog(module = "api_definition", type = OperLogConstants.CREATE, title = "#request.name", content = "#msClass.getLogDetails(#request.id)", msClass = ApiDefinitionService.class)
// @SendNotice(taskType = NoticeConstants.TaskType.API_DEFINITION_TASK, event = NoticeConstants.Event.CREATE, mailTemplate = "api/DefinitionCreate", subject = "接口定义通知")
// public ApiDefinitionWithBLOBs create(@RequestPart("request") SaveApiDefinitionRequest request, @RequestPart(value = "files", required = false) List<MultipartFile> bodyFiles) {
// checkPermissionService.checkProjectOwner(request.getProjectId());
// return apiDefinitionService.create(request, bodyFiles);
// }
@GetMapping("/mockExpectConfig/{id}") @GetMapping("/mockExpectConfig/{id}")
public MockExpectConfigResponse selectMockExpectConfig(@PathVariable String id) { public MockExpectConfigResponse selectMockExpectConfig(@PathVariable String id) {
MockExpectConfigWithBLOBs config = mockConfigService.findMockExpectConfigById(id); MockExpectConfigWithBLOBs config = mockConfigService.findMockExpectConfigById(id);
@ -58,4 +74,12 @@ public class MockConfigController {
List<Map<String, String>> apiParams = mockConfigService.getApiParamsByApiDefinitionBLOBs(apiDefinitionWithBLOBs); List<Map<String, String>> apiParams = mockConfigService.getApiParamsByApiDefinitionBLOBs(apiDefinitionWithBLOBs);
return apiParams; return apiParams;
} }
@GetMapping("/getApiResponse/{id}")
public Map<String, String> getApiResponse(@PathVariable String id) {
ApiDefinitionWithBLOBs apiDefinitionWithBLOBs = apiDefinitionService.getBLOBs(id);
Map<String, String> returnMap = MockApiUtils.getApiResponse(apiDefinitionWithBLOBs.getResponse());
return returnMap;
}
} }

View File

@ -0,0 +1,418 @@
package io.metersphere.api.dto.mock;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONValidator;
import io.metersphere.api.dto.mockconfig.response.JsonSchemaReturnObj;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.json.JSONSchemaGenerator;
import io.metersphere.commons.utils.XMLUtils;
import io.metersphere.jmeter.utils.ScriptEngineUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.jmeter.protocol.java.sampler.JSR223Sampler;
import org.apache.jmeter.samplers.SampleResult;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
/**
* @author song.tianyang
* @Date 2021/10/14 3:00 下午
*/
public class MockApiUtils {
public static Map<String,String> getHttpRequestHeader(HttpServletRequest request){
Map<String,String> returnMap = new HashMap<>();
Enumeration<String> headers = request.getHeaderNames();
while (headers.hasMoreElements()){
String header = headers.nextElement();
String headerValue = request.getHeader(header);
returnMap.put(header,headerValue);
}
return returnMap;
}
public static boolean matchRequestHeader(JSONArray mockExpectHeaderArray, Map<String, String> requestHeaderMap) {
Map<String,String> mockExpectHeaders = new HashMap<>();
for(int i = 0; i < mockExpectHeaderArray.size(); i++){
JSONObject obj = mockExpectHeaderArray.getJSONObject(i);
if(obj.containsKey("name") && obj.containsKey("value") && obj.containsKey("enable")){
boolean enable = obj.getBoolean("enable");
if(enable){
mockExpectHeaders.put(obj.getString("name"),obj.getString("value"));
}
}
}
if(MapUtils.isEmpty(requestHeaderMap) && MapUtils.isNotEmpty(mockExpectHeaders)){
return false;
}else {
for (Map.Entry<String, String> entry: mockExpectHeaders.entrySet()){
String key = entry.getKey();
String value = entry.getValue();
if(!requestHeaderMap.containsKey(key)){
return false;
}else {
if(!StringUtils.equals(value,requestHeaderMap.get(key))){
return false;
}
}
}
return true;
}
}
public static JSONArray getExpectBodyParams(JSONObject bodyObj) {
JSONArray returnJsonArray = new JSONArray();
try {
String type = bodyObj.getString("type");
if (StringUtils.equalsIgnoreCase(type, "JSON")) {
//判断是否是JsonSchema
boolean isJsonSchema = false;
if (bodyObj.containsKey("format")) {
String foramtValue = String.valueOf(bodyObj.get("format"));
if (StringUtils.equals("JSON-SCHEMA", foramtValue)) {
isJsonSchema = true;
}
}
String jsonString = "";
if (isJsonSchema) {
if (bodyObj.containsKey("jsonSchema") && bodyObj.getJSONObject("jsonSchema").containsKey("properties")) {
String bodyRetunStr = bodyObj.getJSONObject("jsonSchema").getJSONObject("properties").toJSONString();
jsonString = JSONSchemaGenerator.getJson(bodyRetunStr);
// JSONObject bodyReturnObj = JSONObject.parseObject(bodyRetunStr);
// JSONObject returnObj = parseJsonSchema(bodyReturnObj);
// returnStr = returnObj.toJSONString();
}
} else {
if (bodyObj.containsKey("raw")) {
jsonString = bodyObj.getString("raw");
}
}
JSONValidator jsonValidator = JSONValidator.from(jsonString);
if (StringUtils.equalsIgnoreCase("Array", jsonValidator.getType().name())) {
returnJsonArray = JSONArray.parseArray(jsonString);
} else if (StringUtils.equalsIgnoreCase("Object", jsonValidator.getType().name())) {
JSONObject jsonObject = JSONObject.parseObject(jsonString);
returnJsonArray.add(jsonObject);
}
} else if (StringUtils.equalsIgnoreCase(type, "XML")) {
if (bodyObj.containsKey("raw")) {
String xmlStr = bodyObj.getString("raw");
JSONObject matchObj = XMLUtils.XmlToJson(xmlStr);
returnJsonArray.add(matchObj);
}
} else if (StringUtils.equalsIgnoreCase(type, "Raw")) {
if (bodyObj.containsKey("raw")) {
String raw = bodyObj.getString("raw");
JSONObject rawObject = new JSONObject();
rawObject.put("raw",raw);
returnJsonArray.add(rawObject);
}
} else if (StringUtils.equalsAnyIgnoreCase(type, "Form Data", "WWW_FORM")) {
if (bodyObj.containsKey("kvs")) {
JSONObject bodyParamArr = new JSONObject();
JSONArray kvsArr = bodyObj.getJSONArray("kvs");
for (int i = 0; i < kvsArr.size(); i++) {
JSONObject kv = kvsArr.getJSONObject(i);
if (kv.containsKey("name")) {
String values = kv.getString("value");
if (StringUtils.isEmpty(values)) {
values = "";
} else {
try {
values = values.startsWith("@") ? ScriptEngineUtils.buildFunctionCallString(values) : values;
} catch (Exception e) {
}
}
bodyParamArr.put(kv.getString("name"), values);
}
}
returnJsonArray.add(bodyParamArr);
}
}
}catch (Exception e){}
return returnJsonArray;
}
public static JSONObject parseJsonSchema(JSONObject bodyReturnObj) {
JSONObject returnObj = new JSONObject();
if (bodyReturnObj == null) {
return returnObj;
}
Set<String> keySet = bodyReturnObj.keySet();
for (String key : keySet) {
try {
JsonSchemaReturnObj obj = bodyReturnObj.getObject(key, JsonSchemaReturnObj.class);
if (StringUtils.equals("object", obj.getType())) {
JSONObject itemObj = parseJsonSchema(obj.getProperties());
if (!itemObj.isEmpty()) {
returnObj.put(key, itemObj);
}
} else if (StringUtils.equals("array", obj.getType())) {
if (obj.getItems() != null) {
JSONObject itemObj = obj.getItems();
if (itemObj.containsKey("type")) {
if (StringUtils.equals("object", itemObj.getString("type")) && itemObj.containsKey("properties")) {
JSONObject arrayObj = itemObj.getJSONObject("properties");
JSONObject parseObj = parseJsonSchema(arrayObj);
JSONArray array = new JSONArray();
array.add(parseObj);
returnObj.put(key, array);
} else if (StringUtils.equals("string", itemObj.getString("type")) && itemObj.containsKey("mock")) {
JsonSchemaReturnObj arrayObj = JSONObject.toJavaObject(itemObj, JsonSchemaReturnObj.class);
String value = getMockValues(arrayObj.getMockValue());
JSONArray array = new JSONArray();
array.add(value);
returnObj.put(key, array);
}
}
}
} else {
String values = obj.getMockValue();
if (StringUtils.isEmpty(values)) {
values = "";
} else {
try {
values = values.startsWith("@") ? ScriptEngineUtils.buildFunctionCallString(values) : values;
} catch (Exception e) {
}
}
returnObj.put(key, values);
}
} catch (Exception e) {
e.printStackTrace();
}
}
return returnObj;
}
private static String getMockValues(String values) {
if (StringUtils.isEmpty(values)) {
values = "";
} else {
try {
values = values.startsWith("@") ? ScriptEngineUtils.buildFunctionCallString(values) : values;
} catch (Exception e) {
}
}
return values;
}
public static JSONObject getParams(JSONArray array) {
JSONObject returnObject = new JSONObject();
for(int i = 0; i < array.size();i ++){
JSONObject obj = array.getJSONObject(i);
if(obj.containsKey("name") && obj.containsKey("value") && obj.containsKey("enable")){
boolean isEnable = obj.getBoolean("enable");
if(isEnable){
returnObject.put(obj.getString("name"),obj.getString("value"));
}
}
}
return returnObject;
}
public static Map<String, String> getApiResponse(String response) {
Map<String, String> returnMap = new HashMap<>();
String returnStr = "";
if(StringUtils.isNotEmpty(response)){
try {
JSONObject respObj = JSONObject.parseObject(response);
if (respObj.containsKey("body")) {
JSONObject bodyObj = respObj.getJSONObject("body");
if (bodyObj.containsKey("type")) {
String type = bodyObj.getString("type");
if (StringUtils.equals(type, "JSON")) {
//判断是否是JsonSchema
boolean isJsonSchema = false;
if (bodyObj.containsKey("format")) {
String foramtValue = String.valueOf(bodyObj.get("format"));
if (StringUtils.equals("JSON-SCHEMA", foramtValue)) {
isJsonSchema = true;
}
}
if (isJsonSchema) {
if (bodyObj.containsKey("jsonSchema") && bodyObj.getJSONObject("jsonSchema").containsKey("properties")) {
String bodyRetunStr = bodyObj.getJSONObject("jsonSchema").getJSONObject("properties").toJSONString();
JSONObject bodyReturnObj = JSONObject.parseObject(bodyRetunStr);
JSONObject returnObj = MockApiUtils.parseJsonSchema(bodyReturnObj);
returnStr = returnObj.toJSONString();
}
} else {
if (bodyObj.containsKey("raw")) {
returnStr = bodyObj.getString("raw");
}
}
} else if (StringUtils.equalsAny(type, "XML", "Raw")) {
if (bodyObj.containsKey("raw")) {
String raw = bodyObj.getString("raw");
returnStr = raw;
}
} else if (StringUtils.equalsAny(type, "Form Data", "WWW_FORM")) {
Map<String, String> paramMap = new LinkedHashMap<>();
if (bodyObj.containsKey("kvs")) {
JSONArray bodyParamArr = new JSONArray();
JSONArray kvsArr = bodyObj.getJSONArray("kvs");
for (int i = 0; i < kvsArr.size(); i++) {
JSONObject kv = kvsArr.getJSONObject(i);
if (kv.containsKey("name")) {
String values = kv.getString("value");
if (StringUtils.isEmpty(values)) {
values = "";
} else {
try {
values = values.startsWith("@") ? ScriptEngineUtils.buildFunctionCallString(values) : values;
} catch (Exception e) {
}
}
paramMap.put(kv.getString("name"), values);
}
}
}
returnStr = JSONObject.toJSONString(paramMap);
}
}
}
}catch (Exception e){
MSException.throwException(e);
}
}
returnMap.put("returnMsg",returnStr);
return returnMap;
}
public static String getResultByResponseResult(JSONObject bodyObj,String url, Map<String,String> headerMap,RequestMockParams requestMockParams) {
if(bodyObj == null && bodyObj.isEmpty()){
return "";
}else {
String returnStr = "";
if(bodyObj.containsKey("type")){
String type = bodyObj.getString("type");
if (StringUtils.equals(type, "JSON")) {
//判断是否是JsonSchema
boolean isJsonSchema = false;
if (bodyObj.containsKey("format")) {
String foramtValue = String.valueOf(bodyObj.get("format"));
if (StringUtils.equals("JSON-SCHEMA", foramtValue)) {
isJsonSchema = true;
}
}
if (isJsonSchema) {
if (bodyObj.containsKey("jsonSchema") && bodyObj.getJSONObject("jsonSchema").containsKey("properties")) {
String bodyRetunStr = bodyObj.getJSONObject("jsonSchema").getJSONObject("properties").toJSONString();
JSONObject bodyReturnObj = JSONObject.parseObject(bodyRetunStr);
JSONObject returnObj = MockApiUtils.parseJsonSchema(bodyReturnObj);
returnStr = returnObj.toJSONString();
}
} else {
if (bodyObj.containsKey("raw")) {
returnStr = bodyObj.getString("raw");
}
}
} else if(StringUtils.equalsAnyIgnoreCase(type,"Raw")){
if (bodyObj.containsKey("raw")) {
String raw = bodyObj.getString("raw");
returnStr = raw;
}
} else if(StringUtils.equalsAnyIgnoreCase(type,"XML")){
if (bodyObj.containsKey("xmlHeader")) {
String xmlHeader = bodyObj.getString("xmlHeader");
if(!StringUtils.startsWith(xmlHeader,"<?") && !StringUtils.endsWith(xmlHeader,"?>")){
returnStr = "<?"+xmlHeader+"?>\r\n";
}else {
returnStr = xmlHeader;
}
}
if (bodyObj.containsKey("xmlRaw")) {
String raw = bodyObj.getString("xmlRaw");
returnStr = returnStr + raw;
}
} else if(StringUtils.equalsAnyIgnoreCase(type,"fromApi")){
if (bodyObj.containsKey("apiRspRaw")) {
String raw = bodyObj.getString("apiRspRaw");
returnStr = raw;
}
} else if(StringUtils.equalsAnyIgnoreCase(type,"script")){
if (bodyObj.containsKey("scriptObject")) {
JSONObject scriptObj = bodyObj.getJSONObject("scriptObject");
String script = scriptObj.getString("script");
String scriptLanguage =scriptObj.getString("scriptLanguage");
returnStr = parseScript(script,url,headerMap,requestMockParams);
runScript(script,scriptLanguage);
}
}
}
return returnStr;
}
}
private static String parseScript(String script,String url,Map<String,String> headerMap,RequestMockParams requestMockParams) {
String returnMsg = "";
if(StringUtils.isNotEmpty(script)){
String [] scriptRowArr = StringUtils.split(script,"\n");
for (String scriptRow : scriptRowArr) {
scriptRow = scriptRow.trim();
if(StringUtils.startsWith(scriptRow,"returnMsg.add(") && StringUtils.endsWith(scriptRow,")")){
scriptRow = scriptRow.substring(14,scriptRow.length()-1).trim();
if(StringUtils.equalsIgnoreCase(scriptRow,"@address")){
returnMsg += url;
}else if(StringUtils.startsWith(scriptRow,"@header(${") && StringUtils.endsWith(scriptRow,"})")){
String paramName = scriptRow.substring(10,scriptRow.length()-2);
if(headerMap.containsKey(paramName)){
returnMsg += headerMap.get(paramName);
}
}else if(StringUtils.startsWith(scriptRow,"@body(${") && StringUtils.endsWith(scriptRow,"})")){
String paramName = scriptRow.substring(8,scriptRow.length()-2);
if(requestMockParams.getBodyParams() != null && requestMockParams.getBodyParams().size() > 0){
JSONObject bodyParamObj = requestMockParams.getBodyParams().getJSONObject(0);
if(bodyParamObj.containsKey(paramName)){
returnMsg += String.valueOf(bodyParamObj.get(paramName));
}
}
}else if(StringUtils.equalsIgnoreCase(scriptRow,"@bodyRaw")){
if(requestMockParams.getBodyParams() != null && requestMockParams.getBodyParams().size() > 0){
JSONObject bodyParamObj = requestMockParams.getBodyParams().getJSONObject(0);
if(bodyParamObj.containsKey("raw")){
returnMsg += String.valueOf(bodyParamObj.get("raw"));
}
}
}else if(StringUtils.startsWith(scriptRow,"@query(${") && StringUtils.endsWith(scriptRow,"})")){
String paramName = scriptRow.substring(9,scriptRow.length()-2);
if(requestMockParams.getQueryParamsObj() != null && requestMockParams.getQueryParamsObj().containsKey(paramName)){
returnMsg += String.valueOf(requestMockParams.getQueryParamsObj().get(paramName));
}
}else if(StringUtils.startsWith(scriptRow,"@rest(${") && StringUtils.endsWith(scriptRow,"})")){
String paramName = scriptRow.substring(8,scriptRow.length()-2);
if(requestMockParams.getRestParamsObj() != null && requestMockParams.getRestParamsObj().containsKey(paramName)){
returnMsg += String.valueOf(requestMockParams.getRestParamsObj().get(paramName));
}
}else {
returnMsg += scriptRow;
}
}
}
}
return returnMsg;
}
private static void runScript(String script, String scriptLanguage) {
JSR223Sampler jmeterScriptSampler = new JSR223Sampler();
jmeterScriptSampler.setScriptLanguage(scriptLanguage);
jmeterScriptSampler.setScript(script);
SampleResult result = jmeterScriptSampler.sample(null);
System.out.println(result.getResponseData());
}
}

View File

@ -0,0 +1,42 @@
package io.metersphere.api.dto.mock;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.Getter;
import lombok.Setter;
/**
* @author song.tianyang
* @Date 2021/10/14 4:32 下午
*/
@Getter
@Setter
public class RequestMockParams {
private JSONObject restParamsObj;
private JSONObject queryParamsObj;
private JSONArray bodyParams;
public JSONObject getParamsObj(){
JSONObject returnObj = new JSONObject();
if(restParamsObj != null){
for (String key : restParamsObj.keySet()) {
Object value = restParamsObj.get(key);
returnObj.put(key,value);
}
}
if(queryParamsObj != null){
for (String key : queryParamsObj.keySet()) {
Object value = queryParamsObj.get(key);
returnObj.put(key,value);
}
}
return returnObj;
}
public boolean isEmpty() {
return (restParamsObj == null || restParamsObj.isEmpty()) &&
(queryParamsObj == null || queryParamsObj.isEmpty())&&
(bodyParams == null || bodyParams.isEmpty());
}
}

View File

@ -27,4 +27,6 @@ public class MockExpectConfigRequest {
private Object response; private Object response;
private String status; private String status;
private String copyId;
} }

View File

@ -560,9 +560,9 @@ public class ApiDefinitionService {
if (CollectionUtils.isEmpty(sameRequest)) { if (CollectionUtils.isEmpty(sameRequest)) {
//postman 可能含有前置脚本接口定义去掉脚本 //postman 可能含有前置脚本接口定义去掉脚本
apiDefinition.setOrder(getImportNextOrder(apiTestImportRequest.getProjectId())); apiDefinition.setOrder(getImportNextOrder(apiTestImportRequest.getProjectId()));
batchMapper.insert(apiDefinition);
String originId = apiDefinition.getId(); String originId = apiDefinition.getId();
apiDefinition.setId(UUID.randomUUID().toString()); apiDefinition.setId(UUID.randomUUID().toString());
batchMapper.insert(apiDefinition);
String requestStr = setImportHashTree(apiDefinition); String requestStr = setImportHashTree(apiDefinition);
reSetImportCasesApiId(cases, originId, apiDefinition.getId()); reSetImportCasesApiId(cases, originId, apiDefinition.getId());
apiDefinition.setRequest(requestStr); apiDefinition.setRequest(requestStr);
@ -1014,6 +1014,7 @@ public class ApiDefinitionService {
if (apiImport.getEsbApiParamsMap() != null) { if (apiImport.getEsbApiParamsMap() != null) {
String apiId = item.getId(); String apiId = item.getId();
EsbApiParamsWithBLOBs model = apiImport.getEsbApiParamsMap().get(apiId); EsbApiParamsWithBLOBs model = apiImport.getEsbApiParamsMap().get(apiId);
request.setModeId("fullCoverage");//标准版ESB数据导入不区分是否覆盖默认都为覆盖
importCreate(item, batchMapper, apiTestCaseMapper, request, apiImport.getCases(), apiImport.getMocks(), project.getRepeatable()); importCreate(item, batchMapper, apiTestCaseMapper, request, apiImport.getCases(), apiImport.getMocks(), project.getRepeatable());
if (model != null) { if (model != null) {
apiImport.getEsbApiParamsMap().remove(apiId); apiImport.getEsbApiParamsMap().remove(apiId);

View File

@ -295,6 +295,9 @@ public class ApiModuleService extends NodeTreeService<ApiModuleDTO> {
if (StringUtils.isNotBlank(node.getId())) { if (StringUtils.isNotBlank(node.getId())) {
criteria.andIdNotEqualTo(node.getId()); criteria.andIdNotEqualTo(node.getId());
} }
if(StringUtils.isNotEmpty(node.getProtocol())){
criteria.andProtocolEqualTo(node.getProtocol());
}
return apiModuleMapper.selectByExample(example); return apiModuleMapper.selectByExample(example);
} }

View File

@ -9,6 +9,8 @@ import io.metersphere.api.dto.automation.EsbDataStruct;
import io.metersphere.api.dto.automation.TcpTreeTableDataStruct; import io.metersphere.api.dto.automation.TcpTreeTableDataStruct;
import io.metersphere.api.dto.automation.parse.TcpTreeTableDataParser; import io.metersphere.api.dto.automation.parse.TcpTreeTableDataParser;
import io.metersphere.api.dto.definition.parse.ApiDefinitionImport; import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
import io.metersphere.api.dto.mock.MockApiUtils;
import io.metersphere.api.dto.mock.RequestMockParams;
import io.metersphere.api.dto.mockconfig.MockConfigImportDTO; import io.metersphere.api.dto.mockconfig.MockConfigImportDTO;
import io.metersphere.api.dto.mockconfig.MockConfigRequest; import io.metersphere.api.dto.mockconfig.MockConfigRequest;
import io.metersphere.api.dto.mockconfig.MockExpectConfigRequest; import io.metersphere.api.dto.mockconfig.MockExpectConfigRequest;
@ -30,6 +32,7 @@ import org.apache.ibatis.session.SqlSession;
import org.json.XML; import org.json.XML;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.xml.sax.InputSource; import org.xml.sax.InputSource;
import javax.annotation.Resource; import javax.annotation.Resource;
@ -165,7 +168,21 @@ public class MockConfigService {
return returnRsp; return returnRsp;
} }
public MockExpectConfig updateMockExpectConfig(MockExpectConfigRequest request) { public MockExpectConfig updateMockExpectConfigStatus(MockExpectConfigRequest request) {
if (StringUtils.isNotEmpty(request.getId()) && StringUtils.isNotEmpty(request.getStatus())) {
MockExpectConfigWithBLOBs model = new MockExpectConfigWithBLOBs();
long timeStmp = System.currentTimeMillis();
model.setId(request.getId());
model.setUpdateTime(timeStmp);
model.setStatus(request.getStatus());
mockExpectConfigMapper.updateByPrimaryKeySelective(model);
return model;
} else {
return null;
}
}
public MockExpectConfig updateMockExpectConfig(MockExpectConfigRequest request, List<MultipartFile> bodyFiles) {
boolean isSave = false; boolean isSave = false;
if (StringUtils.isEmpty(request.getId())) { if (StringUtils.isEmpty(request.getId())) {
isSave = true; isSave = true;
@ -200,6 +217,10 @@ public class MockConfigService {
} else { } else {
mockExpectConfigMapper.updateByPrimaryKeySelective(model); mockExpectConfigMapper.updateByPrimaryKeySelective(model);
} }
if (StringUtils.isNotEmpty(request.getCopyId())) {
FileUtils.copyBdyFile(request.getCopyId(), model.getId());
}
FileUtils.createBodyFiles(model.getId(), bodyFiles);
return model; return model;
} }
@ -212,14 +233,268 @@ public class MockConfigService {
} }
} }
public MockExpectConfigResponse findExpectConfig(List<MockExpectConfigResponse> mockExpectConfigList, JSONObject reqJsonObj) { public MockExpectConfigResponse findExpectConfig(Map<String, String> requestHeaderMap, List<MockExpectConfigResponse> mockExpectConfigList, RequestMockParams requestMockParams) {
MockExpectConfigResponse returnModel = null; MockExpectConfigResponse returnModel = null;
if (reqJsonObj == null || reqJsonObj.isEmpty()) { if (requestMockParams == null || requestMockParams.isEmpty()) {
//如果参数为空则匹配请求为空的期望
for (MockExpectConfigResponse model : mockExpectConfigList) { for (MockExpectConfigResponse model : mockExpectConfigList) {
if (!model.isStatus()) { if (!model.isStatus()) {
continue; continue;
} }
JSONObject requestObj = model.getRequest();
MockExpectConfigResponse resultModel = null;
if (requestObj.containsKey("params")) {
resultModel = this.getEmptyRequestMockExpectByParams(requestHeaderMap, model);
} else {
resultModel = this.getEmptyRequestMockExpect(model);
}
if (resultModel != null) {
return resultModel;
}
}
}
for (MockExpectConfigResponse model : mockExpectConfigList) {
try {
if (!model.isStatus()) {
continue;
}
JSONObject mockExpectRequestObj = model.getRequest();
boolean mathing = false;
if (mockExpectRequestObj.containsKey("params")) {
mathing = this.isRequestMockExpectMatchingByParams(requestHeaderMap, mockExpectRequestObj, requestMockParams);
} else {
mathing = this.isRequestMockExpectMatching(mockExpectRequestObj, requestMockParams.getQueryParamsObj());
}
if (mathing) {
returnModel = model;
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return returnModel;
}
private boolean isRequestMockExpectMatchingByParams(Map<String, String> requestHeaderMap, JSONObject mockExpectRequestObj, RequestMockParams requestMockParams) {
JSONObject expectParamsObj = mockExpectRequestObj.getJSONObject("params");
if (expectParamsObj.containsKey("headers")) {
//检测headers
JSONArray headerArr = expectParamsObj.getJSONArray("headers");
for (int i = 0; i < headerArr.size(); i++) {
JSONObject jsonObject = headerArr.getJSONObject(i);
if (jsonObject.containsKey("enable") && jsonObject.containsKey("name") && jsonObject.containsKey("value")) {
boolean isEnable = jsonObject.getBoolean("enable");
if (isEnable) {
String headerName = jsonObject.getString("name");
String headerValue = jsonObject.getString("value");
if (!requestHeaderMap.containsKey(headerName) || !StringUtils.equals(requestHeaderMap.get(headerName), headerValue)) {
return false;
}
}
}
}
}
JSONArray jsonArray = requestMockParams.getBodyParams();
if (jsonArray == null) {
//url or get 参数
JSONArray argumentsArray = expectParamsObj.getJSONArray("arguments");
JSONArray restArray = expectParamsObj.getJSONArray("rest");
JSONObject urlRequestParamObj = MockApiUtils.getParams(argumentsArray);
JSONObject restRequestParamObj = MockApiUtils.getParams(restArray);
if (requestMockParams.getQueryParamsObj() == null || requestMockParams.getQueryParamsObj().isEmpty()) {
return JsonStructUtils.checkJsonObjCompliance(requestMockParams.getRestParamsObj(), restRequestParamObj);
} else if (requestMockParams.getRestParamsObj() == null || requestMockParams.getRestParamsObj().isEmpty()) {
return JsonStructUtils.checkJsonObjCompliance(requestMockParams.getQueryParamsObj(), urlRequestParamObj);
} else {
return JsonStructUtils.checkJsonObjCompliance(requestMockParams.getQueryParamsObj(), urlRequestParamObj)
&& JsonStructUtils.checkJsonObjCompliance(requestMockParams.getRestParamsObj(), restRequestParamObj);
}
} else {
// body参数
JSONObject expectBodyObject = expectParamsObj.getJSONObject("body");
JSONArray mockExpectJsonArray = MockApiUtils.getExpectBodyParams(expectBodyObject);
return JsonStructUtils.checkJsonArrayCompliance(jsonArray, mockExpectJsonArray);
}
// JSONObject mockExpectJson = new JSONObject();
// if (isJsonParam) {
// String jsonParams = mockExpectRequestObj.getString("jsonData");
// JSONValidator jsonValidator = JSONValidator.from(jsonParams);
// if (StringUtils.equalsIgnoreCase("Array", jsonValidator.getType().name())) {
// JSONArray mockExpectArr = JSONArray.parseArray(jsonParams);
// for (int expectIndex = 0; expectIndex < mockExpectArr.size(); expectIndex++) {
// JSONObject itemObj = mockExpectArr.getJSONObject(expectIndex);
// mockExpectJson = itemObj;
// }
// } else if (StringUtils.equalsIgnoreCase("Object", jsonValidator.getType().name())) {
// JSONObject mockExpectJsonItem = JSONObject.parseObject(jsonParams);
// mockExpectJson = mockExpectJsonItem;
// }
// } else {
// JSONArray jsonArray = mockExpectRequestObj.getJSONArray("variables");
// for (int i = 0; i < jsonArray.size(); i++) {
// JSONObject object = jsonArray.getJSONObject(i);
// String name = "";
// String value = "";
// if (object.containsKey("name")) {
// name = String.valueOf(object.get("name")).trim();
// }
// if (object.containsKey("value")) {
// value = String.valueOf(object.get("value")).trim();
// }
// if (StringUtils.isNotEmpty(name)) {
// mockExpectJson.put(name, value);
// }
// }
// }
// boolean isMatching = JsonStructUtils.checkJsonObjCompliance(mockExpectRequestObj, mockExpectJson);
// return isMatching;
}
private boolean isRequestMockExpectMatching(JSONObject mockExpectRequestObj, JSONObject reqJsonObj) {
boolean isJsonParam = mockExpectRequestObj.getBoolean("jsonParam");
JSONObject mockExpectJson = new JSONObject();
if (isJsonParam) {
String jsonParams = mockExpectRequestObj.getString("jsonData");
JSONValidator jsonValidator = JSONValidator.from(jsonParams);
if (StringUtils.equalsIgnoreCase("Array", jsonValidator.getType().name())) {
JSONArray mockExpectArr = JSONArray.parseArray(jsonParams);
for (int expectIndex = 0; expectIndex < mockExpectArr.size(); expectIndex++) {
JSONObject itemObj = mockExpectArr.getJSONObject(expectIndex);
mockExpectJson = itemObj;
}
} else if (StringUtils.equalsIgnoreCase("Object", jsonValidator.getType().name())) {
JSONObject mockExpectJsonItem = JSONObject.parseObject(jsonParams);
mockExpectJson = mockExpectJsonItem;
}
} else {
JSONArray jsonArray = mockExpectRequestObj.getJSONArray("variables");
for (int i = 0; i < jsonArray.size(); i++) {
JSONObject object = jsonArray.getJSONObject(i);
String name = "";
String value = "";
if (object.containsKey("name")) {
name = String.valueOf(object.get("name")).trim();
}
if (object.containsKey("value")) {
value = String.valueOf(object.get("value")).trim();
}
if (StringUtils.isNotEmpty(name)) {
mockExpectJson.put(name, value);
}
}
}
boolean isMatching = JsonStructUtils.checkJsonObjCompliance(reqJsonObj, mockExpectJson);
return isMatching;
}
private MockExpectConfigResponse getEmptyRequestMockExpectByParams(Map<String, String> requestHeaderMap, MockExpectConfigResponse model) {
JSONObject requestObj = model.getRequest();
if (requestObj.containsKey("params")) {
JSONObject paramsObj = requestObj.getJSONObject("params");
if (paramsObj.containsKey("headers")) {
JSONArray headArray = paramsObj.getJSONArray("headers");
boolean isHeadMatch = MockApiUtils.matchRequestHeader(headArray, requestHeaderMap);
if (!isHeadMatch) {
return null;
}
//判断rest为空
if (paramsObj.containsKey("rest")) {
JSONArray restArray = paramsObj.getJSONArray("rest");
for (int i = 0; i < restArray.size(); i++) {
JSONObject restObj = restArray.getJSONObject(i);
if (restObj.containsKey("enable") && restObj.containsKey("name") && restObj.containsKey("value")) {
boolean isEnable = restObj.getBoolean("enable");
if (isEnable) {
return null;
}
}
}
}
//判断arguments为空
if (paramsObj.containsKey("arguments")) {
JSONArray argumentsArray = paramsObj.getJSONArray("arguments");
for (int i = 0; i < argumentsArray.size(); i++) {
JSONObject argumentsObj = argumentsArray.getJSONObject(i);
if (argumentsObj.containsKey("enable") && argumentsObj.containsKey("name") && argumentsObj.containsKey("value")) {
boolean isEnable = argumentsObj.getBoolean("enable");
if (isEnable) {
return null;
}
}
}
}
//判断请求体为空
if (paramsObj.containsKey("body")) {
JSONObject bodyObj = paramsObj.getJSONObject("body");
if (bodyObj.containsKey("type")) {
String type = bodyObj.getString("type");
if (StringUtils.equalsIgnoreCase(type, "json")) {
if (bodyObj.containsKey("format") && StringUtils.equalsIgnoreCase(bodyObj.getString("format"), "json-schema") && bodyObj.containsKey("jsonSchema") && bodyObj.get("jsonSchema") != null) {
return null;
} else {
if (bodyObj.containsKey("raw")) {
String raw = bodyObj.getString("raw");
if (StringUtils.isNotEmpty(raw)) {
return null;
}
}
}
//Binary的先不处理
// }else if(StringUtils.equalsIgnoreCase(type,"binary")){
// if(bodyObj.containsKey("binary")){
// JSONArray binaryArray = bodyObj.getJSONArray("binary");
// for(int i = 0; i < binaryArray.size(); i ++){
// JSONObject binarObj = binaryArray.getJSONObject(i);
// if(binarObj.containsKey("enable") && binarObj.containsKey("description")){
// boolean isEnable = binarObj.getBoolean("enable");
// if(isEnable){
// return null;
// }
// }
// }
// }
} else if (StringUtils.equalsAnyIgnoreCase(type, "KeyValue", "Form Data", "WWW_FORM")) {
if (bodyObj.containsKey("kvs")) {
JSONArray kvsArray = bodyObj.getJSONArray("kvs");
for (int i = 0; i < kvsArray.size(); i++) {
JSONObject kvsObj = kvsArray.getJSONObject(i);
if (kvsObj.containsKey("enable") && kvsObj.containsKey("name") && kvsObj.containsKey("value")) {
boolean isEnable = kvsObj.getBoolean("enable");
if (isEnable) {
return null;
}
}
}
}
} else if (StringUtils.equalsAnyIgnoreCase(type, "XML", "Raw")) {
String raw = bodyObj.getString("raw");
if (StringUtils.isNotEmpty(raw)) {
return null;
}
}
}
}
return model;
} else {
return null;
}
} else {
return null;
}
}
private MockExpectConfigResponse getEmptyRequestMockExpect(MockExpectConfigResponse model) {
JSONObject requestObj = model.getRequest(); JSONObject requestObj = model.getRequest();
boolean isJsonParam = requestObj.getBoolean("jsonParam"); boolean isJsonParam = requestObj.getBoolean("jsonParam");
if (isJsonParam) { if (isJsonParam) {
@ -247,60 +522,10 @@ public class MockConfigService {
return model; return model;
} }
} }
} return null;
}
for (MockExpectConfigResponse model : mockExpectConfigList) {
try {
if (!model.isStatus()) {
continue;
}
JSONObject requestObj = model.getRequest();
boolean isJsonParam = requestObj.getBoolean("jsonParam");
JSONObject mockExpectJson = new JSONObject();
if (isJsonParam) {
String jsonParams = requestObj.getString("jsonData");
JSONValidator jsonValidator = JSONValidator.from(jsonParams);
if (StringUtils.equalsIgnoreCase("Array", jsonValidator.getType().name())) {
JSONArray mockExpectArr = JSONArray.parseArray(jsonParams);
for (int expectIndex = 0; expectIndex < mockExpectArr.size(); expectIndex++) {
JSONObject itemObj = mockExpectArr.getJSONObject(expectIndex);
mockExpectJson = itemObj;
}
} else if (StringUtils.equalsIgnoreCase("Object", jsonValidator.getType().name())) {
JSONObject mockExpectJsonItem = JSONObject.parseObject(jsonParams);
mockExpectJson = mockExpectJsonItem;
}
} else {
JSONArray jsonArray = requestObj.getJSONArray("variables");
for (int i = 0; i < jsonArray.size(); i++) {
JSONObject object = jsonArray.getJSONObject(i);
String name = "";
String value = "";
if (object.containsKey("name")) {
name = String.valueOf(object.get("name")).trim();
}
if (object.containsKey("value")) {
value = String.valueOf(object.get("value")).trim();
}
if (StringUtils.isNotEmpty(name)) {
mockExpectJson.put(name, value);
}
}
} }
boolean mathing = JsonStructUtils.checkJsonObjCompliance(reqJsonObj, mockExpectJson); public MockExpectConfigResponse findExpectConfigByArrayJson(Map<String, String> requestHeaderMap, List<MockExpectConfigResponse> mockExpectConfigList, JSONArray reqJsonArray) {
if (mathing) {
returnModel = model;
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return returnModel;
}
public MockExpectConfigResponse findExpectConfig(List<MockExpectConfigResponse> mockExpectConfigList, JSONArray reqJsonArray) {
MockExpectConfigResponse returnModel = null; MockExpectConfigResponse returnModel = null;
if (reqJsonArray == null || reqJsonArray.isEmpty()) { if (reqJsonArray == null || reqJsonArray.isEmpty()) {
@ -393,12 +618,48 @@ public class MockConfigService {
return returnModel; return returnModel;
} }
public String updateHttpServletResponse(MockExpectConfigResponse finalExpectConfig, HttpServletResponse response) { public String updateHttpServletResponse(MockExpectConfigResponse finalExpectConfig, String url, Map<String, String> headerMap, RequestMockParams requestMockParams, HttpServletResponse response) {
String returnStr = ""; String returnStr = "";
try { try {
//设置响应头和响应码 //设置响应头和响应码
JSONObject responseObj = finalExpectConfig.getResponse(); JSONObject responseObj = finalExpectConfig.getResponse();
String httpCode = responseObj.getString("httpCode"); String httpCode = responseObj.getString("httpCode");
if (StringUtils.isEmpty(httpCode)) {
httpCode = "500";
}
response.setStatus(Integer.parseInt(httpCode));
long sleepTime = 0;
if (responseObj.containsKey("responseResult")) {
JSONObject responseJsonObj = responseObj.getJSONObject("responseResult");
if (responseJsonObj.containsKey("headers")) {
JSONArray jsonArray = responseJsonObj.getJSONArray("headers");
for (int i = 0; i < jsonArray.size(); i++) {
JSONObject object = jsonArray.getJSONObject(i);
if (object.containsKey("name") && object.containsKey("enable") && object.containsKey("value")) {
boolean isEnable = object.getBoolean("enable");
if (isEnable) {
String name = String.valueOf(object.get("name")).trim();
String value = String.valueOf(object.get("value")).trim();
if (StringUtils.isNotEmpty(name)) {
response.setHeader(name, value);
}
}
}
}
}
if (responseJsonObj.containsKey("body")) {
returnStr = MockApiUtils.getResultByResponseResult(responseJsonObj.getJSONObject("body"), url, headerMap, requestMockParams);
}
if (responseJsonObj.containsKey("httpCode")) {
response.setStatus(Integer.parseInt(responseJsonObj.getString("httpCode")));
}
if (responseJsonObj.containsKey("delayed")) {
try {
sleepTime = Long.parseLong(String.valueOf(responseJsonObj.get("delayed")));
} catch (Exception e) {
}
}
} else {
JSONArray jsonArray = responseObj.getJSONArray("httpHeads"); JSONArray jsonArray = responseObj.getJSONArray("httpHeads");
for (int i = 0; i < jsonArray.size(); i++) { for (int i = 0; i < jsonArray.size(); i++) {
JSONObject object = jsonArray.getJSONObject(i); JSONObject object = jsonArray.getJSONObject(i);
@ -414,13 +675,16 @@ public class MockConfigService {
response.setHeader(name, value); response.setHeader(name, value);
} }
} }
response.setStatus(Integer.parseInt(httpCode));
returnStr = String.valueOf(responseObj.get("body")); returnStr = String.valueOf(responseObj.get("body"));
if (responseObj.containsKey("delayed")) { if (responseObj.containsKey("delayed")) {
try { try {
long sleepTime = Long.parseLong(String.valueOf(responseObj.get("delayed"))); sleepTime = Long.parseLong(String.valueOf(responseObj.get("delayed")));
} catch (Exception e) {
}
}
}
if (sleepTime > 0) {
try {
Thread.sleep(sleepTime); Thread.sleep(sleepTime);
} catch (Exception e) { } catch (Exception e) {
} }
@ -480,7 +744,7 @@ public class MockConfigService {
if (bodyObj.containsKey("jsonSchema") && bodyObj.getJSONObject("jsonSchema").containsKey("properties")) { if (bodyObj.containsKey("jsonSchema") && bodyObj.getJSONObject("jsonSchema").containsKey("properties")) {
String bodyRetunStr = bodyObj.getJSONObject("jsonSchema").getJSONObject("properties").toJSONString(); String bodyRetunStr = bodyObj.getJSONObject("jsonSchema").getJSONObject("properties").toJSONString();
JSONObject bodyReturnObj = JSONObject.parseObject(bodyRetunStr); JSONObject bodyReturnObj = JSONObject.parseObject(bodyRetunStr);
JSONObject returnObj = this.parseJsonSchema(bodyReturnObj); JSONObject returnObj = MockApiUtils.parseJsonSchema(bodyReturnObj);
returnStr = returnObj.toJSONString(); returnStr = returnObj.toJSONString();
} }
} else { } else {
@ -515,37 +779,38 @@ public class MockConfigService {
} }
} }
returnStr = JSONObject.toJSONString(paramMap); returnStr = JSONObject.toJSONString(paramMap);
} else if (StringUtils.equals(type, "BINARY")) { //Binary的先不处理
Map<String, String> paramMap = new LinkedHashMap<>(); // } else if (StringUtils.equals(type, "BINARY")) {
if (bodyObj.containsKey("binary")) { // Map<String, String> paramMap = new LinkedHashMap<>();
JSONArray kvsArr = bodyObj.getJSONArray("kvs"); // if (bodyObj.containsKey("binary")) {
for (int i = 0; i < kvsArr.size(); i++) { // JSONArray kvsArr = bodyObj.getJSONArray("kvs");
JSONObject kv = kvsArr.getJSONObject(i); // for (int i = 0; i < kvsArr.size(); i++) {
if (kv.containsKey("description") && kv.containsKey("files")) { // JSONObject kv = kvsArr.getJSONObject(i);
String name = kv.getString("description"); // if (kv.containsKey("description") && kv.containsKey("files")) {
JSONArray fileArr = kv.getJSONArray("files"); // String name = kv.getString("description");
String allValue = ""; // JSONArray fileArr = kv.getJSONArray("files");
for (int j = 0; j < fileArr.size(); j++) { // String allValue = "";
JSONObject fileObj = fileArr.getJSONObject(j); // for (int j = 0; j < fileArr.size(); j++) {
if (fileObj.containsKey("name")) { // JSONObject fileObj = fileArr.getJSONObject(j);
String values = fileObj.getString("name"); // if (fileObj.containsKey("name")) {
if (StringUtils.isEmpty(values)) { // String values = fileObj.getString("name");
values = ""; // if (StringUtils.isEmpty(values)) {
} else { // values = "";
try { // } else {
values = values.startsWith("@") ? ScriptEngineUtils.buildFunctionCallString(values) : values; // try {
} catch (Exception e) { // values = values.startsWith("@") ? ScriptEngineUtils.buildFunctionCallString(values) : values;
} // } catch (Exception e) {
} // }
// }
allValue += values + " ;"; //
} // allValue += values + " ;";
} // }
paramMap.put(name, allValue); // }
} // paramMap.put(name, allValue);
} // }
} // }
returnStr = JSONObject.toJSONString(paramMap); // }
// returnStr = JSONObject.toJSONString(paramMap);
} }
} }
} }
@ -563,78 +828,26 @@ public class MockConfigService {
return returnStr; return returnStr;
} }
private JSONObject parseJsonSchema(JSONObject bodyReturnObj) {
JSONObject returnObj = new JSONObject();
if (bodyReturnObj == null) {
return returnObj;
}
Set<String> keySet = bodyReturnObj.keySet();
for (String key : keySet) {
try {
JsonSchemaReturnObj obj = bodyReturnObj.getObject(key, JsonSchemaReturnObj.class);
if (StringUtils.equals("object", obj.getType())) {
JSONObject itemObj = this.parseJsonSchema(obj.getProperties());
if (!itemObj.isEmpty()) {
returnObj.put(key, itemObj);
}
} else if (StringUtils.equals("array", obj.getType())) {
if (obj.getItems() != null) {
JSONObject itemObj = obj.getItems();
if (itemObj.containsKey("type")) {
if (StringUtils.equals("object", itemObj.getString("type")) && itemObj.containsKey("properties")) {
JSONObject arrayObj = itemObj.getJSONObject("properties");
JSONObject parseObj = this.parseJsonSchema(arrayObj);
JSONArray array = new JSONArray();
array.add(parseObj);
returnObj.put(key, array);
} else if (StringUtils.equals("string", itemObj.getString("type")) && itemObj.containsKey("mock")) {
JsonSchemaReturnObj arrayObj = JSONObject.toJavaObject(itemObj, JsonSchemaReturnObj.class);
String value = this.getMockValues(arrayObj.getMockValue());
JSONArray array = new JSONArray();
array.add(value);
returnObj.put(key, array);
}
}
}
} else {
String values = obj.getMockValue();
if (StringUtils.isEmpty(values)) {
values = "";
} else {
try {
values = values.startsWith("@") ? ScriptEngineUtils.buildFunctionCallString(values) : values;
} catch (Exception e) {
}
}
returnObj.put(key, values);
}
} catch (Exception e) {
e.printStackTrace();
}
}
return returnObj;
}
private String getMockValues(String values) {
if (StringUtils.isEmpty(values)) {
values = "";
} else {
try {
values = values.startsWith("@") ? ScriptEngineUtils.buildFunctionCallString(values) : values;
} catch (Exception e) {
}
}
return values;
}
public MockExpectConfigWithBLOBs findMockExpectConfigById(String id) { public MockExpectConfigWithBLOBs findMockExpectConfigById(String id) {
return mockExpectConfigMapper.selectByPrimaryKey(id); return mockExpectConfigMapper.selectByPrimaryKey(id);
} }
public void deleteMockExpectConfig(String id) { public void deleteMockExpectConfig(String id) {
MockExpectConfigWithBLOBs mockBlobs = mockExpectConfigMapper.selectByPrimaryKey(id);
if (mockBlobs != null) {
this.deleteMockExpectFiles(mockBlobs);
mockExpectConfigMapper.deleteByPrimaryKey(id); mockExpectConfigMapper.deleteByPrimaryKey(id);
} }
}
private void deleteMockExpectFiles(MockExpectConfigWithBLOBs mockExpectConfigWithBLOBs) {
if (mockExpectConfigWithBLOBs != null && StringUtils.isNotEmpty(mockExpectConfigWithBLOBs.getRequest())) {
try {
FileUtils.deleteBodyFiles(mockExpectConfigWithBLOBs.getId());
} catch (Exception e) {
}
}
}
public void deleteMockConfigByApiId(String apiId) { public void deleteMockConfigByApiId(String apiId) {
MockConfigExample configExample = new MockConfigExample(); MockConfigExample configExample = new MockConfigExample();
@ -644,20 +857,31 @@ public class MockConfigService {
for (MockConfig mockConfig : mockConfigList) { for (MockConfig mockConfig : mockConfigList) {
example.clear(); example.clear();
example.createCriteria().andMockConfigIdEqualTo(mockConfig.getId()); example.createCriteria().andMockConfigIdEqualTo(mockConfig.getId());
List<MockExpectConfigWithBLOBs> deleteBolobs = mockExpectConfigMapper.selectByExampleWithBLOBs(example);
for (MockExpectConfigWithBLOBs model : deleteBolobs) {
this.deleteMockExpectFiles(model);
}
mockExpectConfigMapper.deleteByExample(example); mockExpectConfigMapper.deleteByExample(example);
} }
mockConfigMapper.deleteByExample(configExample); mockConfigMapper.deleteByExample(configExample);
} }
public JSONObject getGetParamMap(String urlParams, ApiDefinitionWithBLOBs api, HttpServletRequest request) { public RequestMockParams getGetParamMap(String urlParams, ApiDefinitionWithBLOBs api, HttpServletRequest request) {
JSONObject paramMap = this.getSendRestParamMapByIdAndUrl(api, urlParams); RequestMockParams requestMockParams = new RequestMockParams();
JSONObject urlParamsObject = this.getSendRestParamMapByIdAndUrl(api, urlParams);
JSONObject queryParamsObject = new JSONObject();
Enumeration<String> paramNameItor = request.getParameterNames(); Enumeration<String> paramNameItor = request.getParameterNames();
while (paramNameItor.hasMoreElements()) { while (paramNameItor.hasMoreElements()) {
String key = paramNameItor.nextElement(); String key = paramNameItor.nextElement();
String value = request.getParameter(key); String value = request.getParameter(key);
paramMap.put(key, value); queryParamsObject.put(key, value);
} }
return paramMap;
requestMockParams.setRestParamsObj(urlParamsObject);
requestMockParams.setQueryParamsObj(queryParamsObject);
return requestMockParams;
} }
public JSON getPostParamMap(HttpServletRequest request) { public JSON getPostParamMap(HttpServletRequest request) {
@ -699,13 +923,14 @@ public class MockConfigService {
} else { } else {
JSONObject object = new JSONObject(); JSONObject object = new JSONObject();
String bodyParam = this.readBody(request); String bodyParam = this.readBody(request);
if (!StringUtils.isEmpty(bodyParam)) { object.put("raw",bodyParam);
try { // if (!StringUtils.isEmpty(bodyParam)) {
object = JSONObject.parseObject(bodyParam); // try {
} catch (Exception e) { // object = JSONObject.parseObject(bodyParam);
e.printStackTrace(); // } catch (Exception e) {
} // object.put("raw",bodyParam);
} // }
// }
Enumeration<String> paramNameItor = request.getParameterNames(); Enumeration<String> paramNameItor = request.getParameterNames();
while (paramNameItor.hasMoreElements()) { while (paramNameItor.hasMoreElements()) {
@ -881,29 +1106,30 @@ public class MockConfigService {
} }
} }
} }
} else if (StringUtils.equals(type, "BINARY")) { //Binary的先不处理
if (bodyObj.containsKey("binary")) { // } else if (StringUtils.equals(type, "BINARY")) {
List<Map<String, String>> bodyParamList = new ArrayList<>(); // if (bodyObj.containsKey("binary")) {
JSONArray kvsArr = bodyObj.getJSONArray("binary"); // List<Map<String, String>> bodyParamList = new ArrayList<>();
// JSONArray kvsArr = bodyObj.getJSONArray("binary");
for (int i = 0; i < kvsArr.size(); i++) { //
JSONObject kv = kvsArr.getJSONObject(i); // for (int i = 0; i < kvsArr.size(); i++) {
if (kv.containsKey("description") && kv.containsKey("files")) { // JSONObject kv = kvsArr.getJSONObject(i);
String name = kv.getString("description"); // if (kv.containsKey("description") && kv.containsKey("files")) {
JSONArray fileArr = kv.getJSONArray("files"); // String name = kv.getString("description");
String value = ""; // JSONArray fileArr = kv.getJSONArray("files");
for (int j = 0; j < fileArr.size(); j++) { // String value = "";
JSONObject fileObj = fileArr.getJSONObject(j); // for (int j = 0; j < fileArr.size(); j++) {
if (fileObj.containsKey("name")) { // JSONObject fileObj = fileArr.getJSONObject(j);
value += fileObj.getString("name") + " ;"; // if (fileObj.containsKey("name")) {
} // value += fileObj.getString("name") + " ;";
} // }
if (!paramNameList.contains(name)) { // }
paramNameList.add(name); // if (!paramNameList.contains(name)) {
} // paramNameList.add(name);
} // }
} // }
} // }
// }
} }
} }
} catch (Exception e) { } catch (Exception e) {
@ -946,10 +1172,11 @@ public class MockConfigService {
return this.assemblyMockConfingResponse(configList); return this.assemblyMockConfingResponse(configList);
} }
public String checkReturnWithMockExpectByBodyParam(String method, Project project, HttpServletRequest public String checkReturnWithMockExpectByBodyParam(String method, Map<String, String> requestHeaderMap, Project project, HttpServletRequest
request, HttpServletResponse response) { request, HttpServletResponse response) {
String returnStr = ""; String returnStr = "";
boolean isMatch = false; boolean isMatch = false;
String url = request.getRequestURL().toString();
List<ApiDefinitionWithBLOBs> aualifiedApiList = new ArrayList<>(); List<ApiDefinitionWithBLOBs> aualifiedApiList = new ArrayList<>();
if (project != null) { if (project != null) {
String urlSuffix = this.getUrlSuffix(project.getSystemId(), request); String urlSuffix = this.getUrlSuffix(project.getSystemId(), request);
@ -960,33 +1187,40 @@ public class MockConfigService {
if (mockConfigData != null && mockConfigData.getMockExpectConfigList() != null) { if (mockConfigData != null && mockConfigData.getMockExpectConfigList() != null) {
JSON paramJson = this.getPostParamMap(request); JSON paramJson = this.getPostParamMap(request);
if (paramJson instanceof JSONObject) { if (paramJson instanceof JSONObject) {
JSONObject paramMap = (JSONObject) paramJson; JSONArray paramsArray = new JSONArray();
MockExpectConfigResponse finalExpectConfig = this.findExpectConfig(mockConfigData.getMockExpectConfigList(), paramMap); paramsArray.add(paramJson);
RequestMockParams mockParams = new RequestMockParams();
mockParams.setBodyParams(paramsArray);
MockExpectConfigResponse finalExpectConfig = this.findExpectConfig(requestHeaderMap, mockConfigData.getMockExpectConfigList(), mockParams);
if (finalExpectConfig != null) { if (finalExpectConfig != null) {
isMatch = true; isMatch = true;
returnStr = this.updateHttpServletResponse(finalExpectConfig, response); returnStr = this.updateHttpServletResponse(finalExpectConfig, url, requestHeaderMap, mockParams, response);
} }
} else if (paramJson instanceof JSONArray) { } else if (paramJson instanceof JSONArray) {
JSONArray paramArray = (JSONArray) paramJson; JSONArray paramArray = (JSONArray) paramJson;
MockExpectConfigResponse finalExpectConfig = this.findExpectConfig(mockConfigData.getMockExpectConfigList(), paramArray); RequestMockParams mockParams = new RequestMockParams();
mockParams.setBodyParams(paramArray);
MockExpectConfigResponse finalExpectConfig = this.findExpectConfig(requestHeaderMap, mockConfigData.getMockExpectConfigList(), mockParams);
if (finalExpectConfig != null) { if (finalExpectConfig != null) {
isMatch = true; isMatch = true;
returnStr = this.updateHttpServletResponse(finalExpectConfig, response); returnStr = this.updateHttpServletResponse(finalExpectConfig, url, requestHeaderMap, mockParams, response);
} }
} }
} }
} }
if (!isMatch) { if (!isMatch) {
returnStr = this.updateHttpServletResponse(aualifiedApiList, response); // returnStr = this.updateHttpServletResponse(aualifiedApiList, response);
response.setStatus(404);
} }
return returnStr; return returnStr;
} }
public String checkReturnWithMockExpectByUrlParam(String method, Project project, HttpServletRequest public String checkReturnWithMockExpectByUrlParam(String method, Map<String, String> requestHeaderMap, Project project, HttpServletRequest
request, HttpServletResponse response) { request, HttpServletResponse response) {
String returnStr = ""; String returnStr = "";
boolean isMatch = false; boolean isMatch = false;
String url = request.getRequestURI();
List<ApiDefinitionWithBLOBs> aualifiedApiList = new ArrayList<>(); List<ApiDefinitionWithBLOBs> aualifiedApiList = new ArrayList<>();
if (project != null) { if (project != null) {
String urlSuffix = this.getUrlSuffix(project.getSystemId(), request); String urlSuffix = this.getUrlSuffix(project.getSystemId(), request);
@ -1001,13 +1235,13 @@ public class MockConfigService {
*/ */
for (ApiDefinitionWithBLOBs api : aualifiedApiList) { for (ApiDefinitionWithBLOBs api : aualifiedApiList) {
JSONObject paramMap = this.getGetParamMap(urlSuffix, api, request); RequestMockParams paramMap = this.getGetParamMap(urlSuffix, api, request);
MockConfigResponse mockConfigData = this.findByApiId(api.getId()); MockConfigResponse mockConfigData = this.findByApiId(api.getId());
if (mockConfigData != null && mockConfigData.getMockExpectConfigList() != null) { if (mockConfigData != null && mockConfigData.getMockExpectConfigList() != null) {
MockExpectConfigResponse finalExpectConfig = this.findExpectConfig(mockConfigData.getMockExpectConfigList(), paramMap); MockExpectConfigResponse finalExpectConfig = this.findExpectConfig(requestHeaderMap, mockConfigData.getMockExpectConfigList(), paramMap);
if (finalExpectConfig != null) { if (finalExpectConfig != null) {
returnStr = this.updateHttpServletResponse(finalExpectConfig, response); returnStr = this.updateHttpServletResponse(finalExpectConfig, url, requestHeaderMap, paramMap, response);
isMatch = true; isMatch = true;
break; break;
} }
@ -1016,7 +1250,8 @@ public class MockConfigService {
} }
if (!isMatch) { if (!isMatch) {
returnStr = this.updateHttpServletResponse(aualifiedApiList, response); // returnStr = this.updateHttpServletResponse(aualifiedApiList, response);
response.setStatus(404);
} }
return returnStr; return returnStr;
} }

View File

@ -24,7 +24,13 @@ public class JsonStructUtils {
* @return * @return
*/ */
public static boolean checkJsonObjCompliance(JSONObject sourceObj, JSONObject matchObj) { public static boolean checkJsonObjCompliance(JSONObject sourceObj, JSONObject matchObj) {
if (sourceObj == null && matchObj == null) { if(sourceObj == null){
sourceObj = new JSONObject();
}
if(matchObj == null){
matchObj = new JSONObject();
}
if (sourceObj .isEmpty() && matchObj.isEmpty()) {
return true; return true;
} else if (sourceObj != null && matchObj != null) { } else if (sourceObj != null && matchObj != null) {
boolean lastMatchResultIsTrue = false; boolean lastMatchResultIsTrue = false;
@ -55,7 +61,7 @@ public class JsonStructUtils {
public static boolean checkJsonArrayCompliance(JSONArray sourceArray, JSONArray matchArray) { public static boolean checkJsonArrayCompliance(JSONArray sourceArray, JSONArray matchArray) {
if (sourceArray == null && matchArray == null) { if (sourceArray == null && matchArray == null) {
return true; return true;
} else if (sourceArray != null && matchArray != null && sourceArray.size() > matchArray.size()) { } else if (sourceArray != null && matchArray != null && sourceArray.size() >= matchArray.size()) {
try { try {
for (int i = 0; i < matchArray.size(); i++) { for (int i = 0; i < matchArray.size(); i++) {
Object obj = matchArray.get(i); Object obj = matchArray.get(i);

View File

@ -74,7 +74,8 @@
</div> </div>
<div v-if="showMock && (currentProtocol === 'HTTP')" class="ms-api-div"> <div v-if="showMock && (currentProtocol === 'HTTP')" class="ms-api-div">
<mock-config :base-mock-config-data="baseMockConfigData" type="http"/> <!-- <mock-config :base-mock-config-data="baseMockConfigData" type="http"/>-->
<mock-tab :base-mock-config-data="baseMockConfigData" type="http"/>
</div> </div>
<div v-if="showMock && (currentProtocol === 'TCP')" class="ms-api-div"> <div v-if="showMock && (currentProtocol === 'TCP')" class="ms-api-div">
<tcp-mock-config :base-mock-config-data="baseMockConfigData" type="tcp"/> <tcp-mock-config :base-mock-config-data="baseMockConfigData" type="tcp"/>
@ -104,7 +105,7 @@ import MsRunTestHttpPage from "./runtest/RunTestHTTPPage";
import MsRunTestTcpPage from "./runtest/RunTestTCPPage"; import MsRunTestTcpPage from "./runtest/RunTestTCPPage";
import MsRunTestSqlPage from "./runtest/RunTestSQLPage"; import MsRunTestSqlPage from "./runtest/RunTestSQLPage";
import MsRunTestDubboPage from "./runtest/RunTestDubboPage"; import MsRunTestDubboPage from "./runtest/RunTestDubboPage";
import MockConfig from "@/business/components/api/definition/components/mock/MockConfig"; import MockTab from "@/business/components/api/definition/components/mock/MockTab";
import TcpMockConfig from "@/business/components/api/definition/components/mock/TcpMockConfig"; import TcpMockConfig from "@/business/components/api/definition/components/mock/TcpMockConfig";
import ApiCaseSimpleList from "./list/ApiCaseSimpleList"; import ApiCaseSimpleList from "./list/ApiCaseSimpleList";
import MsApiCaseList from "./case/ApiCaseList"; import MsApiCaseList from "./case/ApiCaseList";
@ -120,7 +121,7 @@ export default {
MsRunTestTcpPage, MsRunTestTcpPage,
MsRunTestSqlPage, MsRunTestSqlPage,
MsRunTestDubboPage, MsRunTestDubboPage,
MockConfig, MockTab,
TcpMockConfig, TcpMockConfig,
ApiCaseSimpleList, ApiCaseSimpleList,
MsApiCaseList MsApiCaseList

View File

@ -128,6 +128,7 @@ export default {
propIsEnumerable: Object.prototype.propertyIsEnumerable propIsEnumerable: Object.prototype.propertyIsEnumerable
}; };
}, },
watch: { watch: {
'body.raw'() { 'body.raw'() {
if (this.body.format !== 'JSON-SCHEMA' && this.body.raw) { if (this.body.format !== 'JSON-SCHEMA' && this.body.raw) {
@ -141,7 +142,7 @@ export default {
this.body.jsonSchema = ""; this.body.jsonSchema = "";
} }
} }
} },
}, },
methods: { methods: {
isObj(x) { isObj(x) {

View File

@ -13,7 +13,7 @@
<i class="el-icon-plus"/> <i class="el-icon-plus"/>
</div> </div>
<div class="upload-item" slot="file" slot-scope="{file}"> <div class="upload-item" slot="file" slot-scope="{file}">
<span>{{file.file ? file.file.name : file.name}}</span> <span>{{file.file && file.file.name ? file.file.name : file.name}}</span>
<span class="el-upload-list__item-actions"> <span class="el-upload-list__item-actions">
<!--<span v-if="!disabled" class="el-upload-list__item-delete" @click="handleDownload(file)">--> <!--<span v-if="!disabled" class="el-upload-list__item-delete" @click="handleDownload(file)">-->
<!--<i class="el-icon-download"/>--> <!--<i class="el-icon-download"/>-->

View File

@ -0,0 +1,345 @@
<template>
<div>
<el-radio-group v-model="body.type" size="mini">
<el-radio :disabled="isReadOnly" :label="type.FORM_DATA" @change="modeChange">
{{ $t('api_test.definition.request.body_form_data') }}
</el-radio>
<el-radio :disabled="isReadOnly" :label="type.WWW_FORM" @change="modeChange">
{{ $t('api_test.definition.request.body_x_www_from_urlencoded') }}
</el-radio>
<el-radio :disabled="isReadOnly" :label="type.JSON" @change="modeChange">
{{ $t('api_test.definition.request.body_json') }}
</el-radio>
<el-radio :disabled="isReadOnly" :label="type.XML" @change="modeChange">
{{ $t('api_test.definition.request.body_xml') }}
</el-radio>
<el-radio :disabled="isReadOnly" :label="type.RAW" @change="modeChange">
{{ $t('api_test.definition.request.body_raw') }}
</el-radio>
</el-radio-group>
<div style="min-width: 1200px;" v-if="body.type == 'Form Data' || body.type == 'WWW_FORM'">
<el-row v-if="body.type == 'Form Data' || body.type == 'WWW_FORM'">
<el-link class="ms-el-link" @click="batchAdd"> {{ $t("commons.batch_add") }}</el-link>
</el-row>
<ms-api-variable
:with-mor-setting="true"
:is-read-only="isReadOnly"
:parameters="body.kvs"
:isShowEnable="isShowEnable"
type="body"/>
</div>
<div v-if="body.type == 'JSON'">
<div style="padding: 10px">
<el-switch active-text="JSON-SCHEMA" v-model="body.format" @change="formatChange" active-value="JSON-SCHEMA"/>
</div>
<ms-json-code-edit
v-if="body.format==='JSON-SCHEMA'"
:body="body"
ref="jsonCodeEdit"/>
<ms-code-edit
v-else-if="codeEditActive"
:read-only="isReadOnly"
:data.sync="body.raw"
:modes="modes"
:mode="'json'"
height="400px"
ref="codeEdit"/>
</div>
<div class="ms-body" v-if="body.type == 'XML'">
<ms-code-edit
:read-only="isReadOnly"
:data.sync="body.raw"
:modes="modes"
:mode="'text'"
ref="codeEdit"/>
</div>
<div class="ms-body" v-if="body.type == 'Raw'">
<ms-code-edit
:read-only="isReadOnly"
:data.sync="body.raw"
:modes="modes"
ref="codeEdit"/>
</div>
<batch-add-parameter @batchSave="batchSave" ref="batchAddParameter"/>
</div>
</template>
<script>
import MsApiKeyValue from "@/business/components/api/definition/components/ApiKeyValue";
import {BODY_TYPE, KeyValue} from "@/business/components/api/definition/model/ApiTestModel";
import MsCodeEdit from "@/business/components/common/components/MsCodeEdit";
import MsJsonCodeEdit from "@/business/components/common/json-schema/JsonSchemaEditor";
import MsDropdown from "@/business/components/common/components/MsDropdown";
import MsApiVariable from "@/business/components/api/definition/components/ApiVariable";
import MsApiFromUrlVariable from "@/business/components/api/definition/components/body/ApiFromUrlVariable";
import BatchAddParameter from "@/business/components/api/definition/components/basis/BatchAddParameter";
import Convert from "@/business/components/common/json-schema/convert/convert";
export default {
name: "MockApiBody",
components: {
MsApiVariable,
MsDropdown,
MsCodeEdit,
MsApiKeyValue,
MsApiFromUrlVariable,
MsJsonCodeEdit,
BatchAddParameter
},
props: {
body: {},
headers: Array,
isReadOnly: {
type: Boolean,
default: false
},
isShowEnable: {
type: Boolean,
default: true
}
},
data() {
return {
type: BODY_TYPE,
modes: ['text', 'json', 'xml', 'html'],
jsonSchema: "JSON",
codeEditActive: true,
hasOwnProperty: Object.prototype.hasOwnProperty,
propIsEnumerable: Object.prototype.propertyIsEnumerable
};
},
watch: {
'body.raw'() {
if (this.body.format !== 'JSON-SCHEMA' && this.body.raw) {
try {
const MsConvert = new Convert();
let data = MsConvert.format(JSON.parse(this.body.raw));
if (this.body.jsonSchema) {
this.body.jsonSchema = this.deepAssign(this.body.jsonSchema, data);
}
} catch (ex) {
this.body.jsonSchema = "";
}
}
},
},
methods: {
isObj(x) {
let type = typeof x;
return x !== null && (type === 'object' || type === 'function');
},
toObject(val) {
if (val === null || val === undefined) {
return;
}
return Object(val);
},
assignKey(to, from, key) {
let val = from[key];
if (val === undefined || val === null) {
return;
}
if (!this.hasOwnProperty.call(to, key) || !this.isObj(val)) {
to[key] = val;
} else {
to[key] = this.assign(Object(to[key]), from[key]);
}
},
assign(to, from) {
if (to === from) {
return to;
}
from = Object(from);
for (let key in from) {
if (this.hasOwnProperty.call(from, key)) {
this.assignKey(to, from, key);
}
}
if (Object.getOwnPropertySymbols) {
let symbols = Object.getOwnPropertySymbols(from);
for (let i = 0; i < symbols.length; i++) {
if (this.propIsEnumerable.call(from, symbols[i])) {
this.assignKey(to, from, symbols[i]);
}
}
}
return to;
},
deepAssign(target) {
target = this.toObject(target);
for (let s = 1; s < arguments.length; s++) {
this.assign(target, arguments[s]);
}
return target;
},
reloadCodeEdit() {
this.codeEditActive = false;
this.$nextTick(() => {
this.codeEditActive = true;
});
},
formatChange() {
const MsConvert = new Convert();
if (this.body.format === 'JSON-SCHEMA') {
if (this.body.raw && !this.body.jsonSchema) {
this.body.jsonSchema = MsConvert.format(JSON.parse(this.body.raw));
}
} else {
if (this.body.jsonSchema) {
MsConvert.schemaToJsonStr(this.body.jsonSchema, (result) => {
this.$set(this.body, 'raw', result);
this.reloadCodeEdit();
});
}
}
},
modeChange(mode) {
switch (this.body.type) {
case "JSON":
this.setContentType("application/json");
break;
case "XML":
this.setContentType("text/xml");
break;
case "WWW_FORM":
this.setContentType("application/x-www-form-urlencoded");
break;
// todo from data
// case "BINARY":
// this.setContentType("application/octet-stream");
// break;
default:
this.removeContentType();
break;
}
},
setContentType(value) {
let isType = false;
this.headers.forEach(item => {
if (item.name === "Content-Type") {
item.value = value;
isType = true;
}
})
if (!isType) {
this.headers.unshift(new KeyValue({name: "Content-Type", value: value}));
this.$emit('headersChange');
}
},
removeContentType() {
for (let index in this.headers) {
if (this.headers[index].name === "Content-Type") {
this.headers.splice(index, 1);
this.$emit('headersChange');
return;
}
}
},
batchAdd() {
this.$refs.batchAddParameter.open();
},
format(array, obj) {
if (array) {
let isAdd = true;
for (let i in array) {
let item = array[i];
if (item.name === obj.name) {
item.value = obj.value;
isAdd = false;
}
}
if (isAdd) {
this.body.kvs.unshift(obj);
}
}
},
batchSave(data) {
if (data) {
let params = data.split("\n");
let keyValues = [];
params.forEach(item => {
let line = [];
line[0] = item.substring(0,item.indexOf(":"));
line[1] = item.substring(item.indexOf(":")+1,item.length);
let required = false;
keyValues.unshift(new KeyValue({
name: line[0],
required: required,
value: line[1],
description: line[2],
type: "text",
valid: false,
file: false,
encode: true,
enable: true,
contentType: "text/plain"
}));
})
keyValues.forEach(item => {
this.format(this.body.kvs, item);
})
}
},
},
created() {
if (!this.body.type) {
this.body.type = BODY_TYPE.FORM_DATA;
}
if (this.body.kvs) {
this.body.kvs.forEach(param => {
if (!param.type) {
param.type = 'text';
}
});
}
}
}
</script>
<style scoped>
.textarea {
margin-top: 10px;
}
.ms-body {
padding: 15px 0;
height: 400px;
}
.el-dropdown {
margin-left: 20px;
line-height: 30px;
}
.ace_editor {
border-radius: 5px;
}
.el-radio-group {
margin: 10px 10px;
margin-top: 15px;
}
.ms-el-link {
float: right;
margin-right: 45px;
}
</style>

View File

@ -0,0 +1,396 @@
<template>
<div>
<el-radio-group v-model="body.type" size="mini">
<el-radio :disabled="isReadOnly" :label="type.JSON" @change="modeChange">
{{ $t('api_test.definition.request.body_json') }}
</el-radio>
<el-radio :disabled="isReadOnly" label="fromApi" @change="modeChange">
<!-- {{ 跟随API定义 }}-->
跟随API定义
</el-radio>
<el-radio :disabled="isReadOnly" :label="type.XML" @change="modeChange">
{{ $t('api_test.definition.request.body_xml') }}
</el-radio>
<el-radio :disabled="isReadOnly" :label="type.RAW" @change="modeChange">
{{ $t('api_test.definition.request.body_raw') }}
</el-radio>
<el-radio :disabled="isReadOnly" label="script" @change="modeChange">
{{ $t('api_test.automation.customize_script') }}
</el-radio>
</el-radio-group>
<div class="ms-body" v-if="body.type == 'JSON'">
<div style="padding: 10px">
<el-switch active-text="JSON-SCHEMA" v-model="body.format" @change="formatChange" active-value="JSON-SCHEMA"/>
</div>
<ms-json-code-edit
v-if="body.format==='JSON-SCHEMA'"
:body="body"
ref="jsonCodeEdit"/>
<ms-code-edit
v-else-if="codeEditActive && loadIsOver"
:read-only="isReadOnly"
:data.sync="body.raw"
:modes="modes"
:mode="'json'"
height="90%"
ref="codeEdit"/>
</div>
<div class="ms-body" v-if="body.type == 'fromApi'">
<ms-code-edit
:read-only="true"
:data.sync="body.apiRspRaw"
:modes="modes"
:mode="'text'"
v-if="loadIsOver"
height="90%"
ref="fromApiCodeEdit"/>
</div>
<div class="ms-body" v-if="body.type == 'XML'">
<el-input v-model="body.xmlHeader" size="small" style="width: 400px;margin-bottom: 5px"/>
<ms-code-edit
:read-only="isReadOnly"
:data.sync="body.xmlRaw"
:modes="modes"
:mode="'xml'"
v-if="loadIsOver"
height="90%"
ref="codeEdit"/>
</div>
<div class="ms-body" v-if="body.type == 'Raw'">
<ms-code-edit
:read-only="isReadOnly"
:data.sync="body.raw"
:modes="modes"
height="90%"
ref="codeEdit"/>
</div>
<div class="ms-body" v-if="body.type == 'script'">
<mock-api-script-editor v-if="loadIsOver"
:jsr223-processor="body.scriptObject"/>
</div>
<batch-add-parameter @batchSave="batchSave" ref="batchAddParameter"/>
</div>
</template>
<script>
import MsApiKeyValue from "@/business/components/api/definition/components/ApiKeyValue";
import {BODY_TYPE, KeyValue} from "@/business/components/api/definition/model/ApiTestModel";
import MsCodeEdit from "@/business/components/common/components/MsCodeEdit";
import MsJsonCodeEdit from "@/business/components/common/json-schema/JsonSchemaEditor";
import MsDropdown from "@/business/components/common/components/MsDropdown";
import MsApiVariable from "@/business/components/api/definition/components/ApiVariable";
import MsApiFromUrlVariable from "@/business/components/api/definition/components/body/ApiFromUrlVariable";
import BatchAddParameter from "@/business/components/api/definition/components/basis/BatchAddParameter";
import Convert from "@/business/components/common/json-schema/convert/convert";
import MockApiScriptEditor from "@/business/components/api/definition/components/mock/Components/MockApiScriptEditor";
export default {
name: "MockApiResponseBody",
components: {
MsApiVariable,
MsDropdown,
MsCodeEdit,
MsApiKeyValue,
MsApiFromUrlVariable,
MsJsonCodeEdit,
BatchAddParameter,
MockApiScriptEditor
},
props: {
apiId:String,
body: {},
headers: Array,
isReadOnly: {
type: Boolean,
default: false
},
isShowEnable: {
type: Boolean,
default: true
}
},
data() {
return {
loadIsOver: true,
type: BODY_TYPE,
modes: ['text', 'json', 'xml', 'html'],
jsonSchema: "JSON",
codeEditActive: true,
hasOwnProperty: Object.prototype.hasOwnProperty,
propIsEnumerable: Object.prototype.propertyIsEnumerable
};
},
watch: {
'body.raw'() {
if (this.body.format !== 'JSON-SCHEMA' && this.body.raw) {
try {
const MsConvert = new Convert();
let data = MsConvert.format(JSON.parse(this.body.raw));
if (this.body.jsonSchema) {
this.body.jsonSchema = this.deepAssign(this.body.jsonSchema, data);
}
} catch (ex) {
this.body.jsonSchema = "";
}
}
},
'body.xmlRaw'() {
if (!this.body.xmlRaw) {
this.body.xmlRaw = '';
}
},
'body.scriptObject'() {
if (!this.body.scriptObject) {
this.body.scriptObject = {};
}
},
'body.xmlHeader'() {
if (!this.body.xmlHeader) {
this.body.xmlHeader = 'version="1.0" encoding="UTF-8"';
}
},
},
methods: {
isObj(x) {
let type = typeof x;
return x !== null && (type === 'object' || type === 'function');
},
toObject(val) {
if (val === null || val === undefined) {
return;
}
return Object(val);
},
assignKey(to, from, key) {
let val = from[key];
if (val === undefined || val === null) {
return;
}
if (!this.hasOwnProperty.call(to, key) || !this.isObj(val)) {
to[key] = val;
} else {
to[key] = this.assign(Object(to[key]), from[key]);
}
},
assign(to, from) {
if (to === from) {
return to;
}
from = Object(from);
for (let key in from) {
if (this.hasOwnProperty.call(from, key)) {
this.assignKey(to, from, key);
}
}
if (Object.getOwnPropertySymbols) {
let symbols = Object.getOwnPropertySymbols(from);
for (let i = 0; i < symbols.length; i++) {
if (this.propIsEnumerable.call(from, symbols[i])) {
this.assignKey(to, from, symbols[i]);
}
}
}
return to;
},
deepAssign(target) {
target = this.toObject(target);
for (let s = 1; s < arguments.length; s++) {
this.assign(target, arguments[s]);
}
return target;
},
reloadCodeEdit() {
this.codeEditActive = false;
this.$nextTick(() => {
this.codeEditActive = true;
});
},
formatChange() {
const MsConvert = new Convert();
if (this.body.format === 'JSON-SCHEMA') {
if (this.body.raw && !this.body.jsonSchema) {
this.body.jsonSchema = MsConvert.format(JSON.parse(this.body.raw));
}
} else {
if (this.body.jsonSchema) {
MsConvert.schemaToJsonStr(this.body.jsonSchema, (result) => {
this.$set(this.body, 'raw', result);
this.reloadCodeEdit();
});
}
}
},
modeChange(mode) {
switch (this.body.type) {
case "JSON":
// this.setContentType("application/json");
this.refreshMsCodeEdit();
break;
case "XML":
// this.setContentType("text/xml");
this.refreshMsCodeEdit();
break;
case "fromApi":
this.selectApiResponse();
break;
default:
// this.removeContentType();
this.refreshMsCodeEdit();
break;
}
},
refreshMsCodeEdit(){
this.loadIsOver = false;
this.$nextTick(() => {
this.loadIsOver = true;
});
},
selectApiResponse(){
let selectUrl = "/mockConfig/getApiResponse/" + this.apiId;
this.$get(selectUrl, response => {
let apiResponse = response.data;
if(apiResponse && apiResponse.returnMsg){
this.body.apiRspRaw = apiResponse.returnMsg;
}
this.refreshMsCodeEdit();
});
},
setContentType(value) {
let isType = false;
this.headers.forEach(item => {
if (item.name === "Content-Type") {
item.value = value;
isType = true;
}
})
if (!isType) {
this.headers.unshift(new KeyValue({name: "Content-Type", value: value}));
this.$emit('headersChange');
}
},
removeContentType() {
for (let index in this.headers) {
if (this.headers[index].name === "Content-Type") {
this.headers.splice(index, 1);
this.$emit('headersChange');
return;
}
}
},
batchAdd() {
this.$refs.batchAddParameter.open();
},
format(array, obj) {
if (array) {
let isAdd = true;
for (let i in array) {
let item = array[i];
if (item.name === obj.name) {
item.value = obj.value;
isAdd = false;
}
}
if (isAdd) {
this.body.kvs.unshift(obj);
}
}
},
batchSave(data) {
if (data) {
let params = data.split("\n");
let keyValues = [];
params.forEach(item => {
let line = [];
line[0] = item.substring(0,item.indexOf(":"));
line[1] = item.substring(item.indexOf(":")+1,item.length);
let required = false;
keyValues.unshift(new KeyValue({
name: line[0],
required: required,
value: line[1],
description: line[2],
type: "text",
valid: false,
file: false,
encode: true,
enable: true,
contentType: "text/plain"
}));
})
keyValues.forEach(item => {
this.format(this.body.kvs, item);
})
}
},
},
created() {
if (!this.body.type) {
this.body.type = BODY_TYPE.FORM_DATA;
}
if (this.body.kvs) {
this.body.kvs.forEach(param => {
if (!param.type) {
param.type = 'text';
}
});
}
if (!this.body.xmlRaw) {
this.body.xmlRaw = '';
}
if (!this.body.scriptObject) {
this.body.scriptObject = {};
}
if (!this.body.xmlHeader) {
this.body.xmlHeader = 'version="1.0" encoding="UTF-8"';
}
}
}
</script>
<style scoped>
.textarea {
margin-top: 10px;
}
.ms-body {
padding: 15px 0;
height: 150px;
}
.el-dropdown {
margin-left: 20px;
line-height: 30px;
}
.ace_editor {
border-radius: 5px;
}
.el-radio-group {
margin: 10px 10px;
margin-top: 15px;
}
.ms-el-link {
float: right;
margin-right: 45px;
}
</style>

View File

@ -0,0 +1,210 @@
<template>
<div>
<el-row type="flex" :gutter="10">
<el-col :span="codeSpan" class="script-content">
<ms-code-edit v-if="isCodeEditAlive" :mode="codeEditModeMap[jsr223ProcessorData.scriptLanguage]"
:read-only="isReadOnly"
height="90%"
:data.sync="jsr223ProcessorData.script" theme="eclipse" :modes="['java','python']"
ref="codeEdit"/>
</el-col>
<div style="width: 14px;margin-right: 5px;">
<div style="height: 12px;width: 12px; line-height:12px;">
<i :class="showMenu ? 'el-icon-remove-outline' : 'el-icon-circle-plus-outline'"
class="show-menu"
@click="switchMenu"></i>
</div>
</div>
<el-col :span="menuSpan" class="script-index">
<ms-dropdown :default-command="jsr223ProcessorData.scriptLanguage" :commands="languages" style="margin-bottom: 5px;margin-left: 15px;"
@command="languageChange"/>
<mock-script-nav-menu ref="scriptNavMenu" :language="jsr223ProcessorData.scriptLanguage" :menus="codeTemplates"
@handleCode="handleCodeTemplate"/>
</el-col>
</el-row>
</div>
</template>
<script>
import MsCodeEdit from "@/business/components/api/definition/components/MsCodeEdit";
import MsDropdown from "@/business/components/common/components/MsDropdown";
import CustomFunctionRelate from "@/business/components/settings/project/function/CustomFunctionRelate";
import ApiFuncRelevance from "@/business/components/settings/project/function/ApiFuncRelevance";
import MockScriptNavMenu from "@/business/components/api/definition/components/mock/Components/MockScriptNavMenu";
export default {
name: "MockApiScriptEditor",
components: {MsDropdown, MsCodeEdit, CustomFunctionRelate, ApiFuncRelevance, MockScriptNavMenu},
data() {
return {
jsr223ProcessorData: {},
codeTemplates: [
{
title: "API"+this.$t('api_test.definition.document.request_info'),
children: [
{
title: this.$t('api_test.request.address'),
value: '\nreturnMsg.add(@address)\n',
},
{
title: "Header "+this.$t('api_test.definition.document.request_param'),
value: '\nreturnMsg.add(@header(${param}))\n',
},
{
title: this.$t('api_test.request.body')+this.$t('api_test.variable'),
value: '\nreturnMsg.add(@body(${param}))\n',
},
{
title: this.$t('api_test.request.body')+this.$t('api_test.variable')+" (Raw)",
value: '\nreturnMsg.add(@bodyRaw)\n',
},
{
title: "Query "+this.$t('api_test.definition.document.request_param'),
value: '\nreturnMsg.add(@query(${param}))\n',
},
{
title: "Rest "+this.$t('api_test.definition.document.request_param'),
value: '\nreturnMsg.add(@rest(${param}))\n',
},
]
},
{
title: this.$t('project.code_segment.code_segment'),
children: [
{
title: this.$t('project.code_segment.insert_segment'),
command: "custom_function",
}
]
},
],
isCodeEditAlive: true,
languages: [
'beanshell',"groovy"
// , "python", "nashornScript", "rhinoScript"
],
codeEditModeMap: {
beanshell: 'java',
python: 'python',
groovy: 'java',
nashornScript: 'javascript',
rhinoScript: 'javascript',
},
codeSpan: 20,
menuSpan: 4,
showMenu: true,
}
},
created() {
this.jsr223ProcessorData = this.jsr223Processor;
},
props: {
isReadOnly: {
type: Boolean,
default:
false
},
jsr223Processor: {
type: Object,
},
node: {},
},
watch: {
jsr223Processor() {
this.reload();
}
}
,
methods: {
addTemplate(template) {
if (!this.jsr223ProcessorData.script) {
this.jsr223ProcessorData.script = "";
}
this.jsr223ProcessorData.script += template.value;
if (this.jsr223ProcessorData.scriptLanguage === 'beanshell') {
this.jsr223ProcessorData.script += ';';
}
this.reload();
},
reload() {
this.isCodeEditAlive = false;
this.$nextTick(() => (this.isCodeEditAlive = true));
},
languageChange(language) {
this.jsr223ProcessorData.scriptLanguage = language;
this.$emit("languageChange");
},
addCustomFuncScript(script) {
this.jsr223ProcessorData.script = this.jsr223ProcessorData.script ?
this.jsr223ProcessorData.script + '\n\n' + script : script;
this.reload();
},
switchMenu() {
this.showMenu = !this.showMenu;
if (this.showMenu) {
this.codeSpan = 20;
this.menuSpan = 4;
} else {
this.codeSpan = 24;
this.menuSpan = 0;
}
},
handleCodeTemplate(code) {
if (!this.jsr223ProcessorData.script) {
this.jsr223ProcessorData.script = code;
} else {
this.jsr223ProcessorData.script = this.jsr223ProcessorData.script + '\n' + code;
}
this.reload();
},
}
}
</script>
<style scoped>
.ace_editor {
border-radius: 5px;
}
.script-content {
/*height: calc(100vh - 570px);*/
height: 185px;
min-height: 170px;
}
.script-index {
padding: 0 20px;
}
.template-title {
margin-bottom: 5px;
font-weight: bold;
font-size: 15px;
}
.document-url {
margin-top: 10px;
}
.instructions-icon {
margin-left: 5px;
}
.ms-dropdown {
margin-bottom: 20px;
}
.show-menu {
text-align:center;
font-weight: bold;
color:#935aa1;
font-size: 18px;
cursor: pointer;
}
.show-menu:hover {
color:#935aa1;
}
</style>

View File

@ -0,0 +1,228 @@
<template>
<div style="line-height: 20px;">
<div v-for="(menu, index) in menus" :key="index">
<span class="link-type">
<i class="icon el-icon-arrow-right" style="font-weight: bold; margin-right: 2px;"
@click="active(menu)" :class="{'is-active': menu.open}"></i>
<span @click="active(menu)" class="nav-menu-title nav-font">{{menu.title}}</span>
</span>
<el-collapse-transition>
<div v-if="menu.open">
<div v-for="(child, key) in menu.children" :key="key" class="func-div">
<el-link :disabled="child.disabled" @click="handleClick(child)" class="func-link nav-font">{{child.title}}</el-link>
</div>
</div>
</el-collapse-transition>
</div>
<custom-function-relate ref="customFunctionRelate" @addCustomFuncScript="handleCodeTemplate"/>
<!--接口列表-->
<api-func-relevance @save="apiSave" @close="apiClose" ref="apiFuncRelevance"/>
</div>
</template>
<script>
import ApiFuncRelevance from "@/business/components/settings/project/function/ApiFuncRelevance";
import CustomFunctionRelate from "@/business/components/settings/project/function/CustomFunctionRelate";
import {getCodeTemplate} from "@/business/components/settings/project/function/custom-function";
import {SCRIPT_MENU} from "@/business/components/settings/project/function/script-menu";
export default {
name: "MockScriptNavMenu",
components: {
ApiFuncRelevance,
CustomFunctionRelate
},
data() {
return {
value: true
}
},
props: {
language: {
type: String,
default() {
return "beanshell"
}
},
menus: {
type: Array,
default() {
return SCRIPT_MENU
}
}
},
methods: {
apiSave(data, env) {
// data; env:
let condition = env.config.httpConfig.conditions || [];
let protocol = "";
let host = "";
let domain = "";
let port = "";
if (condition && condition.length > 0) {
//
protocol = condition[0].protocol ? condition[0].protocol : "http";
host = condition[0].socket;
domain = condition[0].domain;
port = condition[0].port;
}
// todo
if (data.length > 5) {
this.$warning("最多可以选择5个接口");
return;
}
let code = "";
if (data.length > 0) {
for (let dt of data) {
// HTTPAPI
if (dt.protocol !== "HTTP") {
if (!dt.request) {
continue;
} else {
// HTTPCASE
if (dt.request) {
let req = JSON.parse(dt.request);
if (req.protocol !== "HTTP") {
continue;
}
}
}
}
let param = this._parseRequestObj(dt);
param['host'] = host;
param['domain'] = domain;
param['port'] = port;
param['protocol'] = protocol;
code += '\n' + getCodeTemplate(this.language, param);
}
}
this.handleCodeTemplate(code);
this.$refs.apiFuncRelevance.close();
},
handleCodeTemplate(code) {
this.$emit("handleCode", code);
},
_parseRequestObj(data) {
let requestHeaders = new Map();
let requestArguments = new Map();
let requestMethod = "";
let requestBody = "";
let requestPath = "";
let request = JSON.parse(data.request);
//
requestPath = request.path;
requestMethod = request.method;
let headers = request.headers;
if (headers && headers.length > 0) {
headers.forEach(header => {
if (header.name) {
requestHeaders.set(header.name, header.value);
}
})
}
let args = request.arguments;
if (args && args.length) {
args.forEach(arg => {
if (arg.name) {
requestArguments.set(arg.name, arg.value);
}
})
}
let body = request.body;
if (body.json) {
requestBody = body.raw;
}
return {requestPath, requestHeaders, requestMethod, requestBody, requestArguments}
},
apiClose() {
},
handleClick(obj) {
let code = "";
if (obj.command) {
code = this._handleCommand(obj.command);
if (!code) {
return;
}
} else {
// todo
if (this.language !== 'beanshell' && this.language !== 'groovy') {
if (obj.title === this.$t('api_test.request.processor.code_add_report_length') ||
obj.title === this.$t('api_test.request.processor.code_hide_report_length')) {
this.$warning("无对应的 "+ this.language +" 代码模版!");
return;
}
}
code = obj.value;
}
this.handleCodeTemplate(code);
},
_handleCommand(command) {
switch (command) {
case 'custom_function':
this.$refs.customFunctionRelate.open(this.language);
return "";
case 'api_definition':
this.$refs.apiFuncRelevance.open();
return "";
case 'new_api_request': {
// requestObj
let headers = new Map();
headers.set('Content-type', 'application/json');
return getCodeTemplate(this.language, {requestHeaders: headers});
}
default:
return "";
}
},
active(menu) {
if (!menu.open) {
this.$set(menu, "open", true);
} else {
this.$set(menu, "open", !menu.open);
}
}
}
}
</script>
<style scoped>
.template-title {
margin-bottom: 4px;
font-weight: bold;
font-size: 15px;
margin-left: 15px;
}
.func-link {
margin-left: 18px;
}
.func-div >>> .func-link {
color: #935aa1;
}
.func-div >>> .func-link:hover {
color: #935aa1;
}
.link-type {
font-weight: bold;
font-size: 14px;
}
.icon.is-active {
transform: rotate(90deg);
}
.nav-menu-title:hover {
cursor: pointer;
}
.nav-font {
font-size: 13px;
}
</style>

View File

@ -219,35 +219,7 @@ export default {
this.apiParams = response.data; this.apiParams = response.data;
}); });
}, },
copyExpect(row) {
let selectUrl = "/mockConfig/mockExpectConfig/" + row.id;
this.$get(selectUrl, response => {
let data = response.data;
this.showHeadTable = false;
this.mockExpectConfig = data;
this.mockExpectConfig.id = "";
this.mockExpectConfig.name = this.mockExpectConfig.name + "_copy";
if (this.mockExpectConfig.request == null) {
this.mockExpectConfig.request = {
jsonParam: false,
variables: [],
jsonData: "{}",
};
}
if (this.mockExpectConfig.response == null) {
this.mockExpectConfig.response = {
httpCode: "",
delayed: "",
httpHeads: [],
body: "",
};
}
this.$nextTick(function () {
this.showHeadTable = true;
this.saveMockExpectConfig();
});
});
},
removeExpect(row) { removeExpect(row) {
this.$confirm(this.$t('api_test.mock.delete_mock_expect'), this.$t('commons.prompt'), { this.$confirm(this.$t('api_test.mock.delete_mock_expect'), this.$t('commons.prompt'), {
confirmButtonText: this.$t('commons.confirm'), confirmButtonText: this.$t('commons.confirm'),
@ -332,40 +304,6 @@ export default {
} }
}); });
}, },
changeStatus(row) {
let mockParam = {};
mockParam.id = row.id;
mockParam.status = row.status;
this.$post('/mockConfig/updateMockExpectConfig', mockParam, response => {
});
},
clickRow(row, column, event) {
this.cleanMockExpectConfig();
let selectUrl = "/mockConfig/mockExpectConfig/" + row.id;
this.$get(selectUrl, response => {
let data = response.data;
this.showHeadTable = false;
this.mockExpectConfig = data;
if (this.mockExpectConfig.request == null) {
this.mockExpectConfig.request = {
jsonParam: false,
variables: [],
jsonData: "{}",
};
}
if (this.mockExpectConfig.response == null) {
this.mockExpectConfig.response = {
httpCode: "",
delayed: "",
httpHeads: [],
body: "",
};
}
this.$nextTick(function () {
this.showHeadTable = true;
});
});
}
} }
}; };
</script> </script>

View File

@ -0,0 +1,101 @@
<template>
<el-header style="width: 100% ;padding: 0px">
<el-card>
<el-row>
<el-col :span="1">
{{$t('commons.name')}}
</el-col>
<el-col :span="11">
<el-input class="ms-http-input" style="width: 80%" size="small" v-model="mockExpectConfig.name"/>
</el-col>
<el-col :span="1">
{{$t('commons.tag')}}
</el-col>
<el-col :span="11">
<ms-input-tag :currentScenario="mockExpectConfig" style="width: 80%;height: 100%;white-space: nowrap;overflow: hidden" v-if="showHeadTable" ref="tag"/>
</el-col>
</el-row>
</el-card>
</el-header>
</template>
<script>
import MsInputTag from "@/business/components/api/automation/scenario/MsInputTag";
export default {
name: "MockConfigHeader",
components: {MsInputTag},
data() {
return {
}
},
props: {
mockExpectConfig: Object,
showHeadTable:Boolean,
},
created() {
},
watch: {
},
methods: {
}
}
</script>
<style scoped>
.el-card-btn {
float: right;
top: 20px;
right: 0px;
padding: 0;
background: 0 0;
border: none;
outline: 0;
cursor: pointer;
font-size: 18px;
margin-left: 30px;
}
.variable-combine {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 10px;
}
.el-col {
height: 32px;
line-height: 32px;
}
.ms-api-header-select {
margin-left: 20px;
min-width: 100px;
}
.el-col {
height: 32px;
line-height: 32px;
}
.api-el-tag {
color: white;
}
.select-all {
margin-right: 10px;
}
.ms-col-name {
display: inline-block;
margin: 0 5px;
overflow-x: hidden;
padding-bottom: 0;
text-overflow: ellipsis;
vertical-align: middle;
white-space: nowrap;
width: 100px;
}
</style>

View File

@ -0,0 +1,343 @@
<template>
<ms-drawer :size="60" @close="close" :visible="showDrawer" direction="bottom">
<template v-slot:header>
<mock-config-header
:mock-expect-config="mockExpectConfig"
:show-head-table="showHeadTable"
/>
</template>
<el-container>
<el-main>
<!-- 期望详情 -->
<p class="tip">{{ $t('api_test.mock.request_condition') }}</p>
<el-form :model="mockExpectConfig" :rules="rule" ref="mockExpectForm" label-width="80px" label-position="right">
<div class="card">
<div class="base-info">
<el-row>
<mock-request-param
:isShowEnable="true"
:referenced="true"
:is-read-only="false"
:request="mockExpectConfig.request.params"/>
</el-row>
<el-row style="margin-top: 10px;">
<p class="tip">{{ $t('api_test.mock.rsp_param') }}</p>
</el-row>
<el-row>
<mock-response-param :api-id="apiId"
:response="mockExpectConfig.response.responseResult"/>
</el-row>
<el-row>
<div style="float: right;margin-right: 20px">
<el-button type="primary" size="small" @click="saveMockExpectConfig" title="ctrl + s">{{
$t('commons.save')
}}
</el-button>
</div>
</el-row>
</div>
</div>
</el-form>
</el-main>
</el-container>
</ms-drawer>
</template>
<script>
import MsDrawer from "@/business/components/common/components/MsDrawer";
import {REQUEST_HEADERS} from "@/common/js/constants";
import MockRowVariables from "@/business/components/api/definition/components/mock/MockRowVariables";
import MsCodeEdit from "@/business/components/common/components/MsCodeEdit";
import MockConfigHeader from "@/business/components/api/definition/components/mock/MockConfigHeader";
import MockRequestParam from "@/business/components/api/definition/components/mock/MockRequestParam";
import MockResponseParam from "@/business/components/api/definition/components/mock/MockResponseParam";
import {getUUID} from "@/common/js/utils";
export default {
name: 'MockEditDrawer',
components: {
MsDrawer,MockConfigHeader,MockRowVariables,MsCodeEdit,MockRequestParam,MockResponseParam
},
props: {
apiParams: Array,
apiId:String,
mockConfigId:String,
// mockConfigData: Object,
},
data() {
return {
showDrawer: false,
mockExpectConfig:{},
showHeadTable: true,
headerSuggestions: REQUEST_HEADERS,
baseMockExpectConfig: {
id: "",
name: "",
mockConfigId: "",
request: {
jsonParam: false,
variables: [],
jsonData: "{}",
params:{
headers:[],
arguments:[],
rest:[],
body:{
type: 'JSON',
binary:[]
}
}
},
response: {
httpCode: "",
delayed: "",
httpHeads: [],
body: "",
responseResult:{
headers:[],
arguments:[],
rest:[],
body:{
type: 'JSON',
binary:[]
}
}
},
},
rule: {
name: [
{required: true, message: this.$t('test_track.case.input_name'), trigger: 'blur'},
{max: 100, message: this.$t('test_track.length_less_than') + '100', trigger: 'blur'}
],
response: {
httpCode: [{required: true, message: this.$t('api_test.mock.rule.input_code'), trigger: 'blur'},],
delayed: [{required: true, message: this.$t('test_track.case.input_name'), trigger: 'blur'},],
},
},
};
},
watch: {
},
created() {
this.mockExpectConfig = JSON.parse(JSON.stringify(this.baseMockExpectConfig));
},
computed: {
},
methods: {
uuid: function () {
return (((1 + Math.random()) * 0x100000) | 0).toString(16).substring(1);
},
open(param){
this.mockExpectConfig = JSON.parse(JSON.stringify(this.baseMockExpectConfig));
if(param){
this.mockExpectConfig = param;
if(!this.mockExpectConfig.request.params){
let requestParamsObj = {
rest:[],
headers: [],
arguments: [],
body: {
type: "JSON",
raw: "",
kvs: [],
},
};
this.$set(this.mockExpectConfig.request,"params",requestParamsObj);
if(this.mockExpectConfig.request.jsonParam && this.mockExpectConfig.request.jsonData){
this.mockExpectConfig.request.params.body.type = "JSON";
this.mockExpectConfig.request.params.body.raw = this.mockExpectConfig.jsonData;
}else if(this.mockExpectConfig.request.variables){
this.mockExpectConfig.request.params.body.type = "Form Data";
let headerItem = {};
headerItem.enable = true;
this.mockExpectConfig.request.params.headers.push(headerItem);
this.mockExpectConfig.request.variables.forEach(item => {
this.mockExpectConfig.request.params.arguments.push({
description : "",
type : "text",
name : item.name,
value : item.value,
required : true,
contentType : "text/plain",
uuid : this.uuid(),
});
this.mockExpectConfig.request.params.body.kvs.push({
description : "",
type : "text",
name : item.name,
value : item.value,
required : true,
contentType : "text/plain",
uuid : this.uuid(),
});
});
}
}
if (!this.mockExpectConfig.response.responseResult) {
let responseResultObj = {
headers:[],
arguments:[],
rest:[],
httpCode: this.mockExpectConfig.response.httpCode,
delayed: this.mockExpectConfig.response.delayed,
body:{
type: "Raw",
raw: this.mockExpectConfig.response.body,
binary:[]
}
};
this.$set(this.mockExpectConfig.response,"responseResult",responseResultObj);
if(this.mockExpectConfig.response.httpHeads){
this.mockExpectConfig.response.httpHeads.forEach(item => {
this.mockExpectConfig.response.responseResult.headers.push({
enable:true,
name: item.name,
value: item.value,
});
});
}
}
}
this.showDrawer = true;
},
close(){
this.showDrawer = false;
},
saveMockExpectConfig() {
let mockConfigId = this.mockConfigId;
this.mockExpectConfig.mockConfigId = mockConfigId;
let formCheckResult = this.checkMockExpectForm("mockExpectForm", true);
},
cleanMockExpectConfig() {
this.showHeadTable = false;
this.mockExpectConfig = JSON.parse(JSON.stringify(this.baseMockExpectConfig));
this.$nextTick(function () {
this.showHeadTable = true;
});
},
updateMockExpectConfig() {
this.checkMockExpectForm("mockExpectForm");
},
uploadMockExpectConfig(clearForm) {
let url = "/mockConfig/updateMockExpectConfig";
let param = this.mockExpectConfig;
if(!param.request.params.id){
param.request.params.id = getUUID();
}
let obj = {
request: param.request.params,
response: param.response.responseResult
};
let bodyFiles = this.getBodyUploadFiles(obj);
this.$fileUpload(url, null, bodyFiles, param, response => {
let returnData = response.data;
this.mockExpectConfig.id = returnData.id;
this.$emit('refreshMockInfo',param.mockConfigId);
if (clearForm) {
this.cleanMockExpectConfig();
}
this.$message({
type: 'success',
message: this.$t('commons.save_success'),
});
this.close();
});
},
getBodyUploadFiles(data) {
let bodyUploadFiles = [];
data.bodyUploadIds = [];
let request = data.request;
let response = data.response;
if (request.body) {
if (request.body.kvs) {
request.body.kvs.forEach(param => {
if (param.files) {
param.files.forEach(item => {
if (item.file) {
let fileId = getUUID().substring(0, 8);
item.name = item.file.name;
item.id = fileId;
data.bodyUploadIds.push(fileId);
bodyUploadFiles.push(item.file);
}
});
}
});
}
if (request.body.binary) {
request.body.binary.forEach(param => {
if (param.files) {
param.files.forEach(item => {
if (item.file) {
let fileId = getUUID().substring(0, 8);
item.name = item.file.name;
item.id = fileId;
data.bodyUploadIds.push(fileId);
bodyUploadFiles.push(item.file);
}
});
}
});
}
}
if (response.body) {
if (response.body.kvs) {
response.body.kvs.forEach(param => {
if (param.files) {
param.files.forEach(item => {
if (item.file) {
let fileId = getUUID().substring(0, 8);
item.name = item.file.name;
item.id = fileId;
data.bodyUploadIds.push(fileId);
bodyUploadFiles.push(item.file);
}
});
}
});
}
if (response.body.binary) {
response.body.binary.forEach(param => {
if (param.files) {
param.files.forEach(item => {
if (item.file) {
let fileId = getUUID().substring(0, 8);
item.name = item.file.name;
item.id = fileId;
data.bodyUploadIds.push(fileId);
bodyUploadFiles.push(item.file);
}
});
}
});
}
}
return bodyUploadFiles;
},
checkMockExpectForm(formName, clearForm) {
this.$refs[formName].validate((valid) => {
if (valid) {
this.uploadMockExpectConfig(clearForm);
return true;
} else {
return false;
}
});
},
}
};
</script>
<style scoped>
.ms-drawer >>> .ms-drawer-body {
margin-top: 40px;
}
</style>

View File

@ -0,0 +1,390 @@
<template xmlns:v-slot="http://www.w3.org/1999/XSL/Transform">
<div>
<el-row>
<el-col :span="spanCount">
<!-- HTTP 请求参数 -->
<div style="border:1px #DCDFE6 solid; height: 100%;border-radius: 4px ;width: 100%" v-loading="isReloadData">
<el-tabs v-model="activeName" class="request-tabs">
<!-- 请求头-->
<el-tab-pane :label="$t('api_test.request.headers')" name="headers">
<el-tooltip class="item-tabs" effect="dark" :content="$t('api_test.request.headers')" placement="top-start" slot="label">
<span>{{ $t('api_test.request.headers') }}
<div class="el-step__icon is-text ms-api-col ms-header" v-if="request.headers.length>1">
<div class="el-step__icon-inner">{{ request.headers.length - 1 }}</div>
</div>
</span>
</el-tooltip>
<el-row>
<el-link class="ms-el-link" @click="batchAdd" style="color: #783887"> {{ $t("commons.batch_add") }}</el-link>
</el-row>
<ms-api-key-value :show-desc="true" :is-read-only="isReadOnly" :isShowEnable="isShowEnable" :suggestions="headerSuggestions" :items="request.headers" :need-mock="true"/>
</el-tab-pane>
<!--query 参数-->
<el-tab-pane :label="$t('api_test.definition.request.query_param')" name="parameters">
<el-tooltip class="item-tabs" effect="dark" :content="$t('api_test.definition.request.query_info')" placement="top-start" slot="label">
<span>{{ $t('api_test.definition.request.query_param') }}
<div class="el-step__icon is-text ms-api-col ms-header" v-if="request.arguments.length>1">
<div class="el-step__icon-inner">{{ request.arguments.length - 1 }}</div>
</div></span>
</el-tooltip>
<el-row>
<el-link class="ms-el-link" @click="batchAdd" style="color: #783887"> {{ $t("commons.batch_add") }}</el-link>
</el-row>
<ms-api-variable :with-mor-setting="true" :is-read-only="isReadOnly" :isShowEnable="isShowEnable" :parameters="request.arguments"/>
</el-tab-pane>
<!--REST 参数-->
<el-tab-pane :label="$t('api_test.definition.request.rest_param')" name="rest">
<el-tooltip class="item-tabs" effect="dark" :content="$t('api_test.definition.request.rest_info')" placement="top-start" slot="label">
<span>
{{ $t('api_test.definition.request.rest_param') }}
<div class="el-step__icon is-text ms-api-col ms-header" v-if="request.rest.length>1">
<div class="el-step__icon-inner">{{ request.rest.length - 1 }}</div>
</div>
</span>
</el-tooltip>
<el-row>
<el-link class="ms-el-link" @click="batchAdd" style="color: #783887"> {{ $t("commons.batch_add") }}</el-link>
</el-row>
<ms-api-variable :with-mor-setting="true" :is-read-only="isReadOnly" :isShowEnable="isShowEnable" :parameters="request.rest"/>
</el-tab-pane>
<!--请求体-->
<el-tab-pane v-if="isBodyShow" :label="$t('api_test.request.body')" name="body" style="overflow: auto">
<mock-api-body @headersChange="reloadBody" :is-read-only="isReadOnly" :isShowEnable="isShowEnable" :headers="request.headers" :body="request.body"/>
</el-tab-pane>
<el-tab-pane name="create" v-if="hasPermission('PROJECT_API_DEFINITION:READ+CREATE_API') && hasLicense() && definitionTest">
<template v-slot:label>
<el-button size="mini" type="primary" @click.stop @click="generate">{{ $t('commons.generate_test_data') }}</el-button>
</template>
</el-tab-pane>
</el-tabs>
</div>
</el-col>
</el-row>
<batch-add-parameter @batchSave="batchSave" ref="batchAddParameter"/>
</div>
</template>
<script>
import MsApiKeyValue from "@/business/components/api/definition/components/ApiKeyValue";
import MsApiAuthConfig from "@/business/components/api/definition/components/auth/ApiAuthConfig";
import ApiRequestMethodSelect from "@/business/components/api/definition/components/collapse/ApiRequestMethodSelect";
import {REQUEST_HEADERS} from "@/common/js/constants";
import MsApiVariable from "@/business/components/api/definition/components/ApiVariable";
import MsApiAssertions from "@/business/components/api/definition/components/assertion/ApiAssertions";
import MsApiExtract from "@/business/components/api/definition/components/extract/ApiExtract";
import {Body, KeyValue} from "@/business/components/api/definition/model/ApiTestModel";
import {hasLicense, getUUID} from "@/common/js/utils";
import BatchAddParameter from "@/business/components/api/definition/components/basis/BatchAddParameter";
import MsApiAdvancedConfig from "@/business/components/api/definition/components/request/http/ApiAdvancedConfig";
import MsJsr233Processor from "@/business/components/api/automation/scenario/component/Jsr233Processor";
import ApiDefinitionStepButton from "@/business/components/api/definition/components/request/components/ApiDefinitionStepButton";
import {hasPermission} from '@/common/js/utils';
import Convert from "@/business/components/common/json-schema/convert/convert";
import MockApiBody from "@/business/components/api/definition/components/mock/Components/MockApiBody";
export default {
name: "MockRequestParam",
components: {
ApiDefinitionStepButton,
MsJsr233Processor,
MsApiAdvancedConfig,
BatchAddParameter,
MsApiVariable,
ApiRequestMethodSelect,
MsApiExtract,
MsApiAuthConfig,
MockApiBody,
MsApiKeyValue,
MsApiAssertions
},
props: {
method: String,
request: {},
response: {},
definitionTest: {
type: Boolean,
default() {
return false;
}
},
showScript: {
type: Boolean,
default: true,
},
referenced: {
type: Boolean,
default: false,
},
isShowEnable: Boolean,
jsonPathList: Array,
isReadOnly: {
type: Boolean,
default: false
},
type: String,
},
data() {
let validateURL = (rule, value, callback) => {
try {
new URL(this.addProtocol(this.request.url));
} catch (e) {
callback(this.$t('api_test.request.url_invalid'));
}
};
return {
activeName: this.request.method === "POST" ? "body" : "parameters",
rules: {
name: [
{max: 300, message: this.$t('commons.input_limit', [1, 300]), trigger: 'blur'}
],
url: [
{max: 500, required: true, message: this.$t('commons.input_limit', [1, 500]), trigger: 'blur'},
{validator: validateURL, trigger: 'blur'}
],
path: [
{max: 500, message: this.$t('commons.input_limit', [0, 500]), trigger: 'blur'},
]
},
spanCount: 21,
headerSuggestions: REQUEST_HEADERS,
isReloadData: false,
isBodyShow: true,
dialogVisible: false,
hasOwnProperty: Object.prototype.hasOwnProperty,
propIsEnumerable: Object.prototype.propertyIsEnumerable
}
},
created() {
if (!this.referenced && this.showScript) {
this.spanCount = 21;
} else {
this.spanCount = 24;
}
this.init();
},
methods: {
hasPermission,
hasLicense,
generate() {
if (this.request.body && (this.request.body.jsonSchema || this.request.body.raw)) {
if (!this.request.body.jsonSchema) {
const MsConvert = new Convert();
this.request.body.jsonSchema = MsConvert.format(JSON.parse(this.request.body.raw));
}
this.$post('/api/test/data/generator', this.request.body.jsonSchema, response => {
if (response.data) {
if (this.request.body.format !== 'JSON-SCHEMA') {
this.request.body.raw = response.data;
} else {
const MsConvert = new Convert();
let data = MsConvert.format(JSON.parse(response.data));
this.request.body.jsonSchema = this.deepAssign(this.request.body.jsonSchema, data);
}
this.reloadBody();
}
});
}
},
remove(row) {
let index = this.request.hashTree.indexOf(row);
this.request.hashTree.splice(index, 1);
this.reload();
},
copyRow(row) {
let obj = JSON.parse(JSON.stringify(row));
obj.id = getUUID();
this.request.hashTree.push(obj);
this.reload();
},
reload() {
this.isReloadData = true
this.$nextTick(() => {
this.isReloadData = false
})
},
init() {
if (Object.prototype.toString.call(this.request).match(/\[object (\w+)\]/)[1].toLowerCase() !== 'object') {
this.request = JSON.parse(this.request);
}
if (!this.request.body) {
this.request.body = new Body();
}
if (!this.request.headers) {
this.request.headers = [];
}
if (!this.request.body.kvs) {
this.request.body.kvs = [];
}
if (!this.request.rest) {
this.request.rest = [];
}
if (!this.request.arguments) {
this.request.arguments = [];
}
},
reloadBody() {
// body
this.isBodyShow = false;
this.$nextTick(() => {
this.isBodyShow = true;
});
},
batchAdd() {
this.$refs.batchAddParameter.open();
},
format(array, obj) {
if (array) {
let isAdd = true;
for (let i in array) {
let item = array[i];
if (item.name === obj.name) {
item.value = obj.value;
isAdd = false;
}
}
if (isAdd) {
switch (this.activeName) {
case "parameters":
this.request.arguments.unshift(obj);
break;
case "rest":
this.request.rest.unshift(obj);
break;
case "headers":
this.request.headers.unshift(obj);
break;
default:
break;
}
}
}
},
batchSave(data) {
if (data) {
let params = data.split("\n");
let keyValues = [];
params.forEach(item => {
let line = item.split(/|:/);
let required = false;
keyValues.unshift(new KeyValue({
name: line[0],
required: required,
value: line[1],
description: line[2],
type: "text",
valid: false,
file: false,
encode: true,
enable: true,
contentType: "text/plain"
}));
})
keyValues.forEach(item => {
switch (this.activeName) {
case "parameters":
this.format(this.request.arguments, item);
break;
case "rest":
this.format(this.request.rest, item);
break;
case "headers":
this.format(this.request.headers, item);
break;
default:
break;
}
})
}
},
isObj(x) {
let type = typeof x;
return x !== null && (type === 'object' || type === 'function');
},
toObject(val) {
if (val === null || val === undefined) {
return;
}
return Object(val);
},
assignKey(to, from, key) {
let val = from[key];
if (val === undefined || val === null) {
return;
}
if (!this.hasOwnProperty.call(to, key) || !this.isObj(val)) {
to[key] = val;
} else {
to[key] = this.assign(Object(to[key]), from[key]);
}
},
assign(to, from) {
if (to === from) {
return to;
}
from = Object(from);
for (let key in from) {
if (this.hasOwnProperty.call(from, key)) {
this.assignKey(to, from, key);
}
}
if (Object.getOwnPropertySymbols) {
let symbols = Object.getOwnPropertySymbols(from);
for (let i = 0; i < symbols.length; i++) {
if (this.propIsEnumerable.call(from, symbols[i])) {
this.assignKey(to, from, symbols[i]);
}
}
}
return to;
},
deepAssign(target) {
target = this.toObject(target);
for (let s = 1; s < arguments.length; s++) {
this.assign(target, arguments[s]);
}
return target;
}
}
}
</script>
<style scoped>
.ms-query {
background: #783887;
color: white;
height: 18px;
border-radius: 42%;
}
.ms-header {
background: #783887;
color: white;
height: 18px;
border-radius: 42%;
}
.request-tabs {
margin: 20px;
min-height: 200px;
}
.ms-el-link {
float: right;
margin-right: 45px;
}
</style>

View File

@ -0,0 +1,216 @@
<template xmlns:v-slot="http://www.w3.org/1999/XSL/Transform">
<div class="text-container" style="border:1px #DCDFE6 solid; height: 100%;border-radius: 4px ;width: 100%">
<el-form :model="response" ref="response" label-width="100px">
<el-collapse-transition>
<el-tabs v-model="activeName" v-show="isActive" style="margin: 20px">
<el-tab-pane :label="$t('api_test.definition.request.response_header')" name="headers" class="pane">
<ms-api-key-value :isShowEnable="false" :suggestions="headerSuggestions" :items="response.headers"/>
</el-tab-pane>
<el-tab-pane :label="$t('api_test.definition.request.response_body')" name="body" class="pane">
<mock-api-response-body :isReadOnly="false" :isShowEnable="false" :api-id="apiId" :body="response.body" :headers="response.headers"/>
</el-tab-pane>
<el-tab-pane :label="$t('api_test.definition.request.status_code')" name="status_code" class="pane">
<el-row>
<el-col :span="2"/>
<el-col :span="20">
<el-input class="ms-http-input" size="small" v-model="response.httpCode"/>
</el-col>
<el-col :span="2"/>
</el-row>
</el-tab-pane>
<el-tab-pane label="响应延迟时间" name="delayed" class="pane">
<el-row>
<el-input-number v-model="response.delayed" :min="0">
<template slot="append">ms</template>
</el-input-number>
</el-row>
</el-tab-pane>
</el-tabs>
</el-collapse-transition>
</el-form>
</div>
</template>
<script>
import MockApiResponseBody from "@/business/components/api/definition/components/mock/Components/MockApiResponseBody";
import MsApiKeyValue from "@/business/components/api/definition/components/ApiKeyValue";
import MsApiAuthConfig from "@/business/components/api/definition/components/auth/ApiAuthConfig";
import ApiRequestMethodSelect from "@/business/components/api/definition/components/collapse/ApiRequestMethodSelect";
import MsApiVariable from "@/business/components/api/definition/components/ApiVariable";
import MsApiAssertions from "@/business/components/api/definition/components/assertion/ApiAssertions";
import MsApiExtract from "@/business/components/api/definition/components/extract/ApiExtract";
import BatchAddParameter from "@/business/components/api/definition/components/basis/BatchAddParameter";
import MsApiAdvancedConfig from "@/business/components/api/definition/components/request/http/ApiAdvancedConfig";
import MsJsr233Processor from "@/business/components/api/automation/scenario/component/Jsr233Processor";
import ApiDefinitionStepButton
from "@/business/components/api/definition/components/request/components/ApiDefinitionStepButton";
import {Body, BODY_FORMAT} from "@/business/components/api/definition/model/ApiTestModel";
import {REQUEST_HEADERS} from "@/common/js/constants";
export default {
name: "MockResponseParam",
components: {
ApiDefinitionStepButton,
MsJsr233Processor,
MsApiAdvancedConfig,
BatchAddParameter,
MsApiVariable,
ApiRequestMethodSelect,
MsApiExtract,
MsApiAuthConfig,
MockApiResponseBody,
MsApiKeyValue,
MsApiAssertions
},
props: {
response: {},
apiId:String,
},
data() {
return {
isActive: true,
activeName: "body",
modes: ['text', 'json', 'xml', 'html'],
sqlModes: ['text', 'table'],
mode: BODY_FORMAT.TEXT,
isMsCodeEditShow: true,
reqMessages: "",
headerSuggestions: REQUEST_HEADERS,
};
},
watch: {
response(){
this.setBodyType();
this.setReqMessage();
}
},
created() {
this.setBodyType();
this.setReqMessage();
},
methods: {
modeChange(mode) {
this.mode = mode;
},
sqlModeChange(mode) {
this.mode = mode;
},
setBodyType() {
if (!this.response || !this.response || !this.response.headers) {
return;
}
if (Object.prototype.toString.call(this.response).match(/\[object (\w+)\]/)[1].toLowerCase() !== 'object') {
this.response = JSON.parse(this.response);
}
if (!this.response.body) {
this.response.body = new Body();
}
if (!this.response.headers) {
this.response.headers = [];
}
if (!this.response.body.kvs) {
this.response.body.kvs = [];
}
if (!this.response.rest) {
this.response.rest = [];
}
if (!this.response.arguments) {
this.response.arguments = [];
}
if (this.response.headers.indexOf("Content-Type: application/json") > 0) {
this.mode = BODY_FORMAT.JSON;
this.$nextTick(() => {
if (this.$refs.modeDropdown) {
this.$refs.modeDropdown.handleCommand(BODY_FORMAT.JSON);
this.msCodeReload();
}
});
}
},
msCodeReload() {
this.isMsCodeEditShow = false;
this.$nextTick(() => {
this.isMsCodeEditShow = true;
});
},
setReqMessage() {
if (this.response) {
if (!this.response.url) {
this.response.url = "";
}
if (!this.response.headers) {
this.response.headers = "";
}
if (!this.response.cookies) {
this.response.cookies = "";
}
if (!this.response.body) {
this.response.body = "";
}
if (!this.response) {
this.response = {};
}
if (!this.response.vars) {
this.response.vars = "";
}
this.reqMessages = this.$t('api_test.request.address') + ":\n" + this.response.url + "\n" +
this.$t('api_test.scenario.headers') + ":\n" + this.response.headers + "\n" + "Cookies :\n" +
this.response.cookies + "\n" + "Body:" + "\n" + this.response.body;
}
},
},
mounted() {
this.setBodyType();
this.setReqMessage();
},
computed: {
responseResult() {
return this.response && this.response ? this.response : {};
}
}
};
</script>
<style scoped>
.text-container .icon {
padding: 5px;
}
.text-container .collapse {
cursor: pointer;
}
.text-container .collapse:hover {
opacity: 0.8;
}
.text-container .icon.is-active {
transform: rotate(90deg);
}
.text-container .pane {
/*background-color: #F5F5F5;*/
padding: 1px 0;
height: 250px;
overflow-y: auto;
}
.text-container .pane.cookie {
padding: 0;
}
/deep/ .el-tabs__nav-wrap::after {
height: 0px;
}
.ms-div {
margin-top: 20px;
}
pre {
margin: 0;
}
</style>

View File

@ -14,8 +14,6 @@
<el-autocomplete :disabled="isReadOnly" :maxlength="400" v-model="item.name" size="small" style="width: 100%" <el-autocomplete :disabled="isReadOnly" :maxlength="400" v-model="item.name" size="small" style="width: 100%"
:fetch-suggestions="querySearch" :fetch-suggestions="querySearch"
show-word-limit/> show-word-limit/>
<!-- <ms-api-variable-input :show-copy="showCopy" :show-variable="showVariable" :is-read-only="isReadOnly" v-model="item.name" size="small" maxlength="200" @change="change"-->
<!-- :placeholder="$t('api_test.variable_name')" show-word-limit/>-->
</el-col> </el-col>
<el-col> <el-col>
<el-input :disabled="isReadOnly" v-model="item.value" size="small" @change="change" <el-input :disabled="isReadOnly" v-model="item.value" size="small" @change="change"

View File

@ -0,0 +1,228 @@
<template>
<div>
<div>
<el-input :placeholder="$t('commons.search_by_name')" class="search-input" size="small"
:clearable="true"
v-model="tableSearch"/>
<el-button type="primary" style="float: right;margin-right: 10px" icon="el-icon-plus" size="small"
@click="addApiMock">{{ $t('commons.add') }}
</el-button>
<ms-table
v-loading="result.loading"
:data="mockConfigData.mockExpectConfigList.filter(data=>!tableSearch || data.name.toLowerCase().includes(tableSearch.toLowerCase()))"
:operators="operators"
:screen-height="screenHeight"
@row-click="clickRow"
row-key="id"
operator-width="80px"
ref="table"
>
<ms-table-column
prop="name"
:label="$t('api_test.mock.table.name')"
min-width="160px">
</ms-table-column>
<ms-table-column prop="tags" width="200px" :label="$t('api_test.mock.table.tag')">
<template v-slot:default="scope">
<ms-tag v-for="(itemName,index) in scope.row.tags" :key="index" type="success" effect="plain"
:show-tooltip="true" :content="itemName" style="margin-left: 0px; margin-right: 2px"/>
<span/>
</template>
</ms-table-column>
<ms-table-column
prop="createUserId"
:label="$t('api_test.mock.table.creator')"
min-width="160px"/>
<ms-table-column
sortable="updateTime"
min-width="160px"
:label="$t('api_test.definition.api_last_time')"
prop="updateTime">
<template v-slot:default="scope">
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
</template>
</ms-table-column>
<ms-table-column
prop="status"
min-width="50px"
:label="$t('api_test.mock.table.status')">
<template v-slot:default="scope">
<div>
<el-switch
v-model="scope.row.status"
class="captcha-img"
@change="changeStatus(scope.row)"
></el-switch>
</div>
</template>
</ms-table-column>
</ms-table>
</div>
<mock-edit-drawer :api-id="this.baseMockConfigData.mockConfig.apiId" @refreshMockInfo="refreshMockInfo" :mock-config-id="mockConfigData.mockConfig.id" ref="mockEditDrawer"/>
</div>
</template>
<script>
import {getCurrentProjectID, getUUID} from "@/common/js/utils";
import MockEditDrawer from "@/business/components/api/definition/components/mock/MockEditDrawer";
import MsTable from "@/business/components/common/components/table/MsTable";
import MsTableColumn from "@/business/components/common/components/table/MsTableColumn";
import MsTag from "@/business/components/common/components/MsTag";
export default {
name: 'MockTab',
components: {
MockEditDrawer,
MsTable,MsTableColumn,MsTag
},
props: {
baseMockConfigData: {}
},
data() {
return {
result: {},
visible: false,
mockConfigData: {},
tableSearch:"",
apiParams: [],
screenHeight:document.documentElement.clientHeight - 250,
operators: [
{
tip: this.$t('commons.edit'), icon: "el-icon-edit",
exec: this.clickRow,
},
{
tip: this.$t('commons.copy'), icon: "el-icon-copy-document",
exec: this.copyExpect,
},
{
tip: this.$t('commons.delete'), icon: "el-icon-delete", type: "danger",
exec: this.removeExpect,
permissions: ['PROJECT_TRACK_REVIEW:READ+RELEVANCE_OR_CANCEL']
}
],
};
},
watch: {
},
created() {
this.mockConfigData = this.baseMockConfigData;
this.searchApiParams(this.mockConfigData.mockConfig.apiId);
},
computed: {
projectId() {
return getCurrentProjectID();
},
},
methods: {
searchApiParams(apiId) {
let selectUrl = "/mockConfig/getApiParams/" + apiId;
this.$get(selectUrl, response => {
this.apiParams = response.data;
});
},
changeStatus(row) {
let mockParam = {};
mockParam.id = row.id;
mockParam.status = row.status;
this.$post('/mockConfig/updateMockExpectConfigStatus', mockParam, response => {
});
},
copyExpect(row) {
let selectUrl = "/mockConfig/mockExpectConfig/" + row.id;
this.$get(selectUrl, response => {
let data = response.data;
let mockExpectConfig = data;
mockExpectConfig.id = "";
mockExpectConfig.copyId = row.id;
mockExpectConfig.name = mockExpectConfig.name + "_copy";
if (mockExpectConfig.request == null) {
mockExpectConfig.request = {
jsonParam: false,
variables: [],
jsonData: "{}",
};
}
if (mockExpectConfig.response == null) {
mockExpectConfig.response = {
httpCode: "",
delayed: "",
httpHeads: [],
body: "",
};
}
this.$refs.mockEditDrawer.open(mockExpectConfig);
});
},
clickRow(row, column, event) {
let selectUrl = "/mockConfig/mockExpectConfig/" + row.id;
this.$get(selectUrl, response => {
let data = response.data;
let mockExpectConfig = data;
if (mockExpectConfig.request == null) {
mockExpectConfig.request = {
jsonParam: false,
variables: [],
jsonData: "{}",
};
}
if (mockExpectConfig.response == null) {
mockExpectConfig.response = {
httpCode: "",
delayed: "",
httpHeads: [],
body: "",
};
}
this.$refs.mockEditDrawer.open(mockExpectConfig);
});
},
addApiMock(){
this.$refs.mockEditDrawer.open();
},
removeExpect(row) {
this.$confirm(this.$t('api_test.mock.delete_mock_expect'), this.$t('commons.prompt'), {
confirmButtonText: this.$t('commons.confirm'),
cancelButtonText: this.$t('commons.cancel'),
type: 'warning'
}).then(() => {
let mockInfoId = row.mockConfigId;
let selectUrl = "/mockConfig/deleteMockExpectConfig/" + row.id;
this.$get(selectUrl, response => {
this.refreshMockInfo(mockInfoId);
this.$message({
type: 'success',
message: this.$t('commons.delete_success'),
});
});
}).catch(() => {
});
},
refreshMockInfo(mockConfigId) {
let mockParam = {};
mockParam.id = mockConfigId;
this.$post('/mockConfig/genMockConfig', mockParam, response => {
this.mockConfigData = response.data;
});
},
}
};
</script>
<style scoped>
.ms-drawer >>> .ms-drawer-body {
margin-top: 40px;
}
.search-input {
float: right;
width: 300px;
margin-right: 10px;
margin-bottom: 10px;
}
</style>

View File

@ -72,6 +72,8 @@ export default {
this.reload(); this.reload();
} }
}, },
created() {
},
mounted() { mounted() {
this.reload(); this.reload();
}, },

View File

@ -831,6 +831,7 @@ export default {
update_time: "Update time" update_time: "Update time"
}, },
expect_detail: "Expect", expect_detail: "Expect",
request_condition:"Request Condition",
base_info: "Base info", base_info: "Base info",
req_param: "Request params", req_param: "Request params",
rsp_param: "Response Params", rsp_param: "Response Params",

View File

@ -837,6 +837,7 @@ export default {
update_time: "更新时间" update_time: "更新时间"
}, },
expect_detail: "期望详情", expect_detail: "期望详情",
request_condition:"请求触发条件",
base_info: "基本信息", base_info: "基本信息",
req_param: "请求参数", req_param: "请求参数",
rsp_param: "响应内容", rsp_param: "响应内容",

View File

@ -837,6 +837,7 @@ export default {
update_time: "更新時間" update_time: "更新時間"
}, },
expect_detail: "期望詳情", expect_detail: "期望詳情",
request_condition:"請求觸發條件",
base_info: "基本信息", base_info: "基本信息",
req_param: "請求參數", req_param: "請求參數",
rsp_param: "響應內容", rsp_param: "響應內容",