refactor(接口测试): 脚本下载优化处理

This commit is contained in:
fit2-zhao 2021-12-17 15:38:31 +08:00 committed by fit2-zhao
parent 5f700a5b44
commit cac0150c9d
10 changed files with 208 additions and 321 deletions

View File

@ -51,7 +51,7 @@ public class ApiJmeterFileController {
byte[] bytes = apiJmeterFileService.downloadJmeterFiles(runMode, testId, reportId);
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType("application/octet-stream"))
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + testId + ".zip\"")
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + reportId + "_" + testId + ".zip\"")
.body(bytes);
}

View File

@ -1,132 +0,0 @@
package io.metersphere.api.dto.definition.request.assertions.document;
import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import io.metersphere.vo.Condition;
import io.metersphere.vo.ElementCondition;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.oro.text.regex.Pattern;
import java.text.DecimalFormat;
import java.util.List;
import java.util.Map;
public class DocumentUtils {
public static boolean documentChecked(Object subj, String condition, ThreadLocal<DecimalFormat> decimalFormatter) {
if (StringUtils.isNotEmpty(condition)) {
ElementCondition elementCondition = JSON.parseObject(condition, ElementCondition.class);
boolean isTrue = true;
if (CollectionUtils.isNotEmpty(elementCondition.getConditions())) {
for (Condition item : elementCondition.getConditions()) {
String expectedValue = item.getValue() != null ? item.getValue().toString() : "";
String resValue = objectToString(subj, decimalFormatter);
switch (item.getKey()) {
case "value_eq":
isTrue = StringUtils.equals(resValue, expectedValue);
break;
case "value_not_eq":
isTrue = !StringUtils.equals(resValue, expectedValue);
break;
case "value_in":
isTrue = StringUtils.contains(resValue, expectedValue);
break;
case "length_eq":
isTrue = getLength(subj, decimalFormatter) == numberOf(item.getValue());
break;
case "length_not_eq":
isTrue = getLength(subj, decimalFormatter) != numberOf(item.getValue());
break;
case "length_gt":
isTrue = getLength(subj, decimalFormatter) > numberOf(item.getValue());
break;
case "length_lt":
isTrue = getLength(subj, decimalFormatter) < numberOf(item.getValue());
break;
case "regular":
Pattern pattern = JMeterUtils.getPatternCache().getPattern(expectedValue);
isTrue = JMeterUtils.getMatcher().matches(resValue, pattern);
break;
}
if (!isTrue) {
break;
}
}
}
return isTrue;
}
return true;
}
public static String objectToString(Object subj, ThreadLocal<DecimalFormat> decimalFormatter) {
String str;
if (subj == null) {
str = "null";
} else if (subj instanceof Map) {
str = new Gson().toJson(subj);
} else if (!(subj instanceof Double) && !(subj instanceof Float)) {
str = subj.toString();
} else {
str = ((DecimalFormat) decimalFormatter.get()).format(subj);
}
return str;
}
private static int getLength(Object value) {
if (value != null) {
if (value instanceof List) {
return ((List) value).size();
}
return value.toString().length();
}
return 0;
}
private static int getLength(Object value, ThreadLocal<DecimalFormat> decimalFormatter) {
if (value != null) {
if (value instanceof Map) {
return ((Map) value).size();
} else if (value instanceof List) {
return ((List) value).size();
} else if (!(value instanceof Double) && !(value instanceof Float)) {
return value.toString().length();
} else {
return ((DecimalFormat) decimalFormatter.get()).format(value).length();
}
}
return 0;
}
private static long numberOf(Object value) {
if (value != null) {
try {
return Long.parseLong(value.toString());
} catch (Exception e) {
return 0;
}
}
return 0;
}
public static String documentMsg(Object resValue, String condition) {
String msg = "";
if (StringUtils.isNotEmpty(condition)) {
ElementCondition elementCondition = JSON.parseObject(condition, ElementCondition.class);
if (CollectionUtils.isNotEmpty(elementCondition.getConditions())) {
for (Condition item : elementCondition.getConditions()) {
if (StringUtils.equalsAny(item.getKey(), "value_eq", "value_not_eq", "value_in")) {
msg = resValue != null ? resValue.toString() : "";
} else if (StringUtils.equalsAny(item.getKey(), "length_eq", "length_not_eq", "length_gt", "length_lt")) {
msg = "长度是:" + getLength(resValue) + "";
} else {
msg = resValue != null ? resValue.toString() : "";
}
}
}
}
return msg;
}
}

View File

@ -150,6 +150,17 @@ public class ExecThreadPoolExecutor {
return workerQueue.stream().filter(task -> StringUtils.equals(((ExecTask) task).getRequest().getReportId(), reportId)).count() > 0;
}
public boolean checkPlanReport(String planReportId) {
// 检查缓冲区
Queue<JmeterRunRequestDTO> bufferQueue = msRejectedExecutionHandler.getBufferQueue();
if (CollectionUtils.isNotEmpty(bufferQueue)) {
return bufferQueue.stream().filter(task -> StringUtils.equals(task.getTestPlanReportId(), planReportId)).count() > 0;
}
// 检查等待队列
BlockingQueue workerQueue = threadPool.getQueue();
return workerQueue.stream().filter(task -> StringUtils.equals(((ExecTask) task).getRequest().getTestPlanReportId(), planReportId)).count() > 0;
}
public String getWorkerQueue() {
StringBuffer buffer = new StringBuffer();
BlockingQueue workerQueue = threadPool.getQueue();

View File

@ -1,6 +1,7 @@
package io.metersphere.api.exec.schedule;
import io.metersphere.api.cache.TestPlanReportExecuteCatch;
import io.metersphere.api.exec.queue.ExecThreadPoolExecutor;
import io.metersphere.api.jmeter.MessageCache;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.track.service.TestPlanReportService;
@ -27,7 +28,9 @@ public class TestPlanReportListenerScheduled {
private void listener(String planReportId) {
LoggerUtil.info("检查测试计划执行报告:【" + planReportId + "");
if (TestPlanReportExecuteCatch.getTestPlanExecuteInfo(planReportId) != null) {
if (!CommonBeanFactory.getBean(ExecThreadPoolExecutor.class).checkPlanReport(planReportId)) {
CommonBeanFactory.getBean(TestPlanReportService.class).countReport(planReportId);
}
} else {
MessageCache.jobReportCache.remove(planReportId);
LoggerUtil.info("测试计划执行报告:【" + planReportId + "】执行完成,剩余队列:" + MessageCache.jobReportCache.size());

View File

@ -3,7 +3,7 @@ package io.metersphere.api.jmeter;
import com.alibaba.fastjson.JSON;
import io.metersphere.api.service.ApiScenarioReportService;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.utils.LoggerUtil;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@ -29,10 +29,10 @@ public class FixedTask {
if (MessageCache.concurrencyCounter != null && MessageCache.concurrencyCounter.size() > 0) {
for (String key : MessageCache.concurrencyCounter.keySet()) {
ReportCounter counter = MessageCache.concurrencyCounter.get(key);
LogUtil.info("集成报告:【" + key + "】总执行场景:【" + counter.getTestIds().size() + "】已经执行完成场景:【" + counter.getCompletedIds().size() + "");
LoggerUtil.info("集成报告:【" + key + "】总执行场景:【" + counter.getTestIds().size() + "】已经执行完成场景:【" + counter.getCompletedIds().size() + "");
List<String> filterList = counter.getTestIds().stream().filter(t -> !counter.getCompletedIds().contains(t)).collect(Collectors.toList());
LogUtil.debug("剩余要执行的报告" + JSON.toJSONString(filterList));
LoggerUtil.debug("剩余要执行的报告" + JSON.toJSONString(filterList));
// 合并
if (counter.getCompletedIds().size() >= counter.getTestIds().size()) {
scenarioReportService.margeReport(key);
@ -51,14 +51,14 @@ public class FixedTask {
// 资源池中已经没有执行的请求了
int runningCount = scenarioReportService.get(key, counter);
if (runningCount == 0) {
LogUtil.error("发生未知异常,进行资源合并,请检查资源池是否正常运行");
LoggerUtil.error("发生未知异常,进行资源合并,请检查资源池是否正常运行");
scenarioReportService.margeReport(key);
guardTask.remove(key);
MessageCache.concurrencyCounter.remove(key);
}
}
} catch (Exception ex) {
LogUtil.error(ex.getMessage());
LoggerUtil.error(ex.getMessage());
}
}
}

View File

@ -195,6 +195,7 @@ public class ApiDefinitionExecResultService {
Map<String, String> caseReportMap = new HashMap<>();
boolean isFirst = true;
int countExpectProcessResultCount = 0;
if (CollectionUtils.isNotEmpty(requestResults)) {
for (RequestResult resultItem : requestResults) {
if (!StringUtils.startsWithAny(resultItem.getName(), "PRE_PROCESSOR_ENV_", "POST_PROCESSOR_ENV_")) {
countExpectProcessResultCount++;
@ -227,6 +228,7 @@ public class ApiDefinitionExecResultService {
SerialBlockingQueueUtil.offer(dto, SerialBlockingQueueUtil.END_SIGN);
}
}
}
updateTestCaseStates(dto.getTestId());
testPlanLog.info("TestPlanReportId[" + dto.getTestPlanReportId() + "] APICASE OVER. API CASE STATUS:" + JSONObject.toJSONString(apiIdResultMap));
TestPlanReportExecuteCatch.updateApiTestPlanExecuteInfo(dto.getTestPlanReportId(), apiIdResultMap, null, null);

View File

@ -98,7 +98,7 @@ public class ApiJmeterFileService {
}
hashTree = GenerateHashTreeUtil.generateHashTree(scenario, reportId, planEnvMap);
}
return zipFilesToByteArray(remoteTestId, hashTree);
return zipFilesToByteArray((reportId + "_" + remoteTestId), hashTree);
}
public byte[] downloadJmeterJar() {

View File

@ -39,6 +39,12 @@
v-on:requestResult="requestResult"
/>
</el-tab-pane>
<el-tab-pane name="console">
<template slot="label">
<span class="console">{{ $t('api_test.definition.request.console') }}</span>
</template>
<pre>{{ content.console }}</pre>
</el-tab-pane>
</el-tabs>
</div>
<ms-api-report-export

View File

@ -23,65 +23,65 @@ export function STEP() {
['CustomizeReq', getDefaultSamplerMenu()],
['MaxSamplerProxy', getDefaultSamplerMenu()],
['GenericController', getAll()],
['AllSamplerProxy', ["HTTPSamplerProxy", "DubboSampler", "JDBCSampler", "TCPSampler", "Sampler", "AbstractSampler","JSR223Processor"]],
['DEFINITION', ["HTTPSamplerProxy", "DubboSampler", "JDBCSampler", "TCPSampler"]],
['AllCanExecType', ["HTTPSamplerProxy", "DubboSampler", "JDBCSampler", "TCPSampler", "JSR223Processor", "AbstractSampler"]]]);
['AllSamplerProxy', ['HTTPSamplerProxy', 'DubboSampler', 'JDBCSampler', 'TCPSampler', 'Sampler', 'AbstractSampler', 'JSR223Processor']],
['DEFINITION', ['HTTPSamplerProxy', 'DubboSampler', 'JDBCSampler', 'TCPSampler']],
['AllCanExecType', ['HTTPSamplerProxy', 'DubboSampler', 'JDBCSampler', 'TCPSampler', 'JSR223Processor', 'AbstractSampler']]]);
return map
}
export const ELEMENT_TYPE = {
scenario: "scenario",
HTTPSamplerProxy: "HTTPSamplerProxy",
OT_IMPORT: "OT_IMPORT",
IfController: "IfController",
TransactionController: "TransactionController",
ConstantTimer: "ConstantTimer",
JSR223Processor: "JSR223Processor",
JSR223PreProcessor: "JSR223PreProcessor",
JSR223PostProcessor: "JSR223PostProcessor",
JDBCPostProcessor: "JDBCPostProcessor",
JDBCPreProcessor: "JDBCPreProcessor",
Assertions: "Assertions",
Extract: "Extract",
CustomizeReq: "CustomizeReq",
LoopController: "LoopController",
Plugin: "Plugin"
scenario: 'scenario',
HTTPSamplerProxy: 'HTTPSamplerProxy',
OT_IMPORT: 'OT_IMPORT',
IfController: 'IfController',
TransactionController: 'TransactionController',
ConstantTimer: 'ConstantTimer',
JSR223Processor: 'JSR223Processor',
JSR223PreProcessor: 'JSR223PreProcessor',
JSR223PostProcessor: 'JSR223PostProcessor',
JDBCPostProcessor: 'JDBCPostProcessor',
JDBCPreProcessor: 'JDBCPreProcessor',
Assertions: 'Assertions',
Extract: 'Extract',
CustomizeReq: 'CustomizeReq',
LoopController: 'LoopController',
Plugin: 'Plugin'
}
export const TYPE_TO_C = new Map([
['scenario', "io.metersphere.api.dto.definition.request.MsScenario"],
['HTTPSamplerProxy', "io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy"],
['DubboSampler', "io.metersphere.api.dto.definition.request.sampler.MsDubboSampler"],
['JDBCSampler', "io.metersphere.api.dto.definition.request.sampler.MsJDBCSampler"],
['TCPSampler', "io.metersphere.api.dto.definition.request.sampler.MsTCPSampler"],
['IfController', "io.metersphere.api.dto.definition.request.controller.MsIfController"],
['TransactionController', "io.metersphere.api.dto.definition.request.controller.MsTransactionController"],
['LoopController', "io.metersphere.api.dto.definition.request.controller.MsLoopController"],
['ConstantTimer', "io.metersphere.api.dto.definition.request.timer.MsConstantTimer"],
['JSR223Processor', "io.metersphere.api.dto.definition.request.processors.MsJSR223Processor"],
['JSR223PreProcessor', "io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor"],
['JSR223PostProcessor', "io.metersphere.api.dto.definition.request.processors.post.MsJSR223PostProcessor"],
['JDBCPreProcessor', "io.metersphere.api.dto.definition.request.processors.pre.MsJDBCPreProcessor"],
['JDBCPostProcessor', "io.metersphere.api.dto.definition.request.processors.post.MsJDBCPostProcessor"],
['Assertions', "io.metersphere.api.dto.definition.request.assertions.MsAssertions"],
['Extract', "io.metersphere.api.dto.definition.request.extract.MsExtract"],
['JmeterElement', "io.metersphere.api.dto.definition.request.unknown.MsJmeterElement"],
['TestPlan', "io.metersphere.api.dto.definition.request.MsTestPlan"],
['ThreadGroup', "io.metersphere.api.dto.definition.request.MsThreadGroup"],
['DNSCacheManager', "io.metersphere.api.dto.definition.request.dns.MsDNSCacheManager"],
['DebugSampler', "io.metersphere.api.dto.definition.request.sampler.MsDebugSampler"],
['AuthManager', "io.metersphere.api.dto.definition.request.auth.MsAuthManager"]
['scenario', 'io.metersphere.api.dto.definition.request.MsScenario'],
['HTTPSamplerProxy', 'io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy'],
['DubboSampler', 'io.metersphere.api.dto.definition.request.sampler.MsDubboSampler'],
['JDBCSampler', 'io.metersphere.api.dto.definition.request.sampler.MsJDBCSampler'],
['TCPSampler', 'io.metersphere.api.dto.definition.request.sampler.MsTCPSampler'],
['IfController', 'io.metersphere.api.dto.definition.request.controller.MsIfController'],
['TransactionController', 'io.metersphere.api.dto.definition.request.controller.MsTransactionController'],
['LoopController', 'io.metersphere.api.dto.definition.request.controller.MsLoopController'],
['ConstantTimer', 'io.metersphere.api.dto.definition.request.timer.MsConstantTimer'],
['JSR223Processor', 'io.metersphere.api.dto.definition.request.processors.MsJSR223Processor'],
['JSR223PreProcessor', 'io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor'],
['JSR223PostProcessor', 'io.metersphere.api.dto.definition.request.processors.post.MsJSR223PostProcessor'],
['JDBCPreProcessor', 'io.metersphere.api.dto.definition.request.processors.pre.MsJDBCPreProcessor'],
['JDBCPostProcessor', 'io.metersphere.api.dto.definition.request.processors.post.MsJDBCPostProcessor'],
['Assertions', 'io.metersphere.api.dto.definition.request.assertions.MsAssertions'],
['Extract', 'io.metersphere.api.dto.definition.request.extract.MsExtract'],
['JmeterElement', 'io.metersphere.api.dto.definition.request.unknown.MsJmeterElement'],
['TestPlan', 'io.metersphere.api.dto.definition.request.MsTestPlan'],
['ThreadGroup', 'io.metersphere.api.dto.definition.request.MsThreadGroup'],
['DNSCacheManager', 'io.metersphere.api.dto.definition.request.dns.MsDNSCacheManager'],
['DebugSampler', 'io.metersphere.api.dto.definition.request.sampler.MsDebugSampler'],
['AuthManager', 'io.metersphere.api.dto.definition.request.auth.MsAuthManager']
])
export const PLUGIN_ELEMENTS = new Map([
['menu_post_processors', ['HtmlExtractor', 'JMESPathExtractor', 'JSONPostProcessor', 'RegexExtractor', 'BoundaryExtractor', 'JSR223PostProcessor', 'Separator', 'JDBCPostProcessor', 'XPath2Extractor', 'XPathExtractor', 'ResultAction', 'DebugPostProcessor', 'BeanShellPostProcessor']],
['menu_assertions', ["Assertions", "Extract", 'Assertion', 'JSONPathAssertion', 'SizeAssertion', 'JSR223Assertion', 'XPath2Assertion', 'Separator', 'HTMLAssertion', 'JMESPathAssertion', 'MD5HexAssertion', 'SMIMEAssertion', 'XMLSchemaAssertion', 'XMLAssertion', 'XPathAssertion', 'DurationAssertion', 'CompareAssertion', 'BeanShellAssertion']],
['menu_assertions', ['Assertions', 'Extract', 'Assertion', 'JSONPathAssertion', 'SizeAssertion', 'JSR223Assertion', 'XPath2Assertion', 'Separator', 'HTMLAssertion', 'JMESPathAssertion', 'MD5HexAssertion', 'SMIMEAssertion', 'XMLSchemaAssertion', 'XMLAssertion', 'XPathAssertion', 'DurationAssertion', 'CompareAssertion', 'BeanShellAssertion']],
['menu_listener', ['AbstractVisualizer', 'AbstractListener', 'ViewResultsFullVisualizer', 'SummaryReport', 'StatVisualizer', 'BackendListener', 'Separator', 'JSR223Listener', 'ResultSaver', 'RespTimeGraphVisualizer', 'GraphVisualizer', 'AssertionVisualizer', 'ComparisonVisualizer', 'StatGraphVisualizer', 'Summariser', 'TableVisualizer', 'SimpleDataWriter', 'MailerVisualizer', 'BeanShellListener']],
['menu_pre_processors', ['AbstractPostProcessor', 'JSR223PreProcessor', 'UserParameters', 'Separator', 'AnchorModifier', 'URLRewritingModifier', 'JDBCPreProcessor', 'SampleTimeout', 'RegExUserParameters', 'BeanShellPreProcessor']],
['menu_logic_controller', ['GenericController', "IfController", "LoopController", 'IfControllerPanel', 'TransactionController', 'LoopControlPanel', 'WhileController', 'Separator', 'ForeachControlPanel', 'IncludeController', 'RunTime', 'CriticalSectionController', 'InterleaveControl', 'OnceOnlyController', 'RecordController', 'LogicController', 'RandomControl', 'RandomOrderController', 'ThroughputController', 'SwitchController', 'ModuleController']],
['menu_logic_controller', ['GenericController', 'scenario', 'IfController', 'LoopController', 'IfControllerPanel', 'TransactionController', 'LoopControlPanel', 'WhileController', 'Separator', 'ForeachControlPanel', 'IncludeController', 'RunTime', 'CriticalSectionController', 'InterleaveControl', 'OnceOnlyController', 'RecordController', 'LogicController', 'RandomControl', 'RandomOrderController', 'ThroughputController', 'SwitchController', 'ModuleController']],
['menu_fragments', ['TestFragmentController']],
['menu_non_test_elements', ['ProxyControl', 'HttpMirrorControl', 'GenerateTree', 'PropertyControl']],
['menu_generative_controller', ["HTTPSamplerProxy", "JSR223Processor", "DubboSampler", "JDBCSampler", "TCPSampler", "Sampler", 'AbstractSampler', 'CustomizeReq', 'HttpTestSample', 'TestAction', 'DebugSampler', 'JSR223Sampler', 'Separator', 'AjpSampler', 'AccessLogSampler', 'BeanShellSampler', 'BoltSampler', 'FtpTestSampler', 'GraphQLHTTPSampler', 'JDBCSampler', 'JMSPublisher', 'JMSSampler', 'JMSSubscriber', 'JUnitTestSampler', 'JavaTestSampler', 'LdapExtTestSampler', 'LdapTestSampler', 'SystemSampler', 'SmtpSampler', 'TCPSampler', 'MailReaderSampler']],
['menu_generative_controller', ['HTTPSamplerProxy', 'JSR223Processor', 'DubboSampler', 'JDBCSampler', 'TCPSampler', 'Sampler', 'AbstractSampler', 'CustomizeReq', 'HttpTestSample', 'TestAction', 'DebugSampler', 'JSR223Sampler', 'Separator', 'AjpSampler', 'AccessLogSampler', 'BeanShellSampler', 'BoltSampler', 'FtpTestSampler', 'GraphQLHTTPSampler', 'JDBCSampler', 'JMSPublisher', 'JMSSampler', 'JMSSubscriber', 'JUnitTestSampler', 'JavaTestSampler', 'LdapExtTestSampler', 'LdapTestSampler', 'SystemSampler', 'SmtpSampler', 'TCPSampler', 'MailReaderSampler']],
['menu_threads', ['SetupThreadGroup', 'PostThreadGroup', 'ThreadGroup']],
['menu_timer', ['ConstantTimer', 'UniformRandomTimer', 'PreciseThroughputTimer', 'ConstantThroughputTimer', 'Separator', 'JSR223Timer', 'SyncTimer', 'PoissonRandomTimer', 'GaussianRandomTimer', 'BeanShellTimer']],
['menu_config_element', ['CSVDataSet', 'HeaderPanel', 'CookiePanel', 'CacheManager', 'HttpDefaults', 'Separator', 'BoltConnectionElement', 'DNSCachePanel', 'FtpConfig', 'AuthPanel', 'DataSourceElement', 'JavaConfig', 'LdapExtConfig', 'LdapConfig', 'TCPConfig', 'KeystoreConfig', 'ArgumentsPanel', 'LoginConfig', 'SimpleConfig', 'CounterConfig', 'RandomVariableConfig']],
@ -102,7 +102,7 @@ export function init() {
let allArray = [];
allArray = allArray.concat(PLUGIN_ELEMENTS.get('menu_generative_controller'));
allArray = allArray.concat(PLUGIN_ELEMENTS.get('menu_logic_controller'));
allArray = allArray.concat(["scenario", "ConstantTimer", "JSR223Processor"]);
allArray = allArray.concat(['scenario', 'ConstantTimer', 'JSR223Processor']);
return allArray;
}

View File

@ -2,27 +2,23 @@
<el-header style="width: 100% ;padding: 0px">
<el-card>
<el-row>
<el-col :span="api.protocol==='HTTP'? 7:9">
<el-tooltip :content="api.name">
<span class="ms-col-name"> {{api.name}}</span>
</el-tooltip>
</el-col>
<el-col :span="api.protocol==='HTTP'? 6:8">
<el-col :span="1">
<el-tag size="mini" :style="{'background-color': getColor(true, api.method), border: getColor(true, api.method)}" class="api-el-tag">
{{ api.method }}
</el-tag>
</el-col>
<el-col :span="api.protocol==='HTTP'? 4:0">
<el-col :span="9">
<div class="variable-combine"> {{ api.name }}</div>
</el-col>
<el-col :span="9">
<div class="variable-combine" style="margin-left: 10px">{{ api.path === null ? " " : api.path }}</div>
</el-col>
<el-col :span="5">
<div>
<ms-environment-select
:project-id="projectId"
:is-read-only="isReadOnly"
:useEnvironment='useEnvironment'
@setEnvironment="setEnvironment" ref="environmentSelect"/>
</div>
</el-col>
</el-row>
</el-card>
@ -35,6 +31,7 @@
import MsTag from "../../../../common/components/MsTag";
import MsEnvironmentSelect from "./MsEnvironmentSelect";
import {API_METHOD_COLOUR} from "../../model/JsonData";
export default {
name: "ApiCaseHeader",
components: {MsEnvironmentSelect, MsTag, ApiEnvironmentConfig},