feat(接口测试): 接口包含时脚本增加系统通知

--story=1012020 --user=王孝刚 接口脚本增加预警审核机制- v1,v2同步上
https://www.tapd.cn/55049933/s/1373989
This commit is contained in:
wxg0103 2023-05-22 17:01:34 +08:00 committed by fit2-zhao
parent 9b7de47b07
commit 6a006845a4
20 changed files with 442 additions and 34 deletions

View File

@ -16,6 +16,7 @@ import io.metersphere.api.dto.scenario.DatabaseConfig;
import io.metersphere.api.dto.scenario.KeyValue;
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
import io.metersphere.api.service.ApiTestEnvironmentService;
import io.metersphere.api.service.MsHashTreeService;
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs;
import io.metersphere.base.mapper.ApiScenarioMapper;
@ -59,6 +60,12 @@ public class ElementUtil {
private static final String POST = "POST";
private static final String ASSERTIONS = "ASSERTIONS";
private static final String BODY_FILE_DIR = FileUtils.BODY_FILE_DIR;
public final static List<String> scriptList = new ArrayList<String>() {{
this.add("JSR223Processor");
this.add("JSR223PreProcessor");
this.add("JSR223PostProcessor");
}};
public static final String JSR = "jsr223";
public static Arguments addArguments(ParameterConfig config, String projectId, String name) {
if (config.isEffective(projectId) && config.getConfig().get(projectId).getCommonConfig() != null
@ -822,4 +829,58 @@ public class ElementUtil {
}
}
}
public static List<String> scriptList(String request) {
List<String> list = new ArrayList<>();
if (StringUtils.isBlank(request)) {
return list;
}
JSONObject element = JSONObject.parseObject(request);
toList(element.getJSONArray(MsHashTreeService.HASH_TREE), scriptList, list);
return list;
}
private static void toList(JSONArray hashTree, List<String> scriptList, List<String> list) {
for (int i = 0; i < hashTree.size(); i++) {
JSONObject element = hashTree.getJSONObject(i);
if (element == null) {
continue;
}
if (scriptList.contains(element.getString(MsHashTreeService.TYPE))) {
JSONObject elementTarget = JSONObject.parseObject(element.toString());
if (elementTarget.containsKey(MsHashTreeService.HASH_TREE)) {
elementTarget.remove(MsHashTreeService.HASH_TREE);
}
elementTarget.remove(MsHashTreeService.ACTIVE);
elementTarget.remove(MsHashTreeService.INDEX);
list.add(elementTarget.toString());
}
JSONArray jsrArray = element.getJSONArray(JSR);
if (jsrArray != null) {
for (int j = 0; j < jsrArray.size(); j++) {
JSONObject jsr223 = jsrArray.getJSONObject(j);
if (jsr223 != null) {
list.add(jsr223.toString());
}
}
}
if (element.containsKey(MsHashTreeService.HASH_TREE)) {
JSONArray elementJSONArray = element.getJSONArray(MsHashTreeService.HASH_TREE);
toList(elementJSONArray, scriptList, list);
}
}
}
public static boolean isSend(List<String> org, List<String> target) {
if (org.size() != target.size() && target.size() > 0) {
return true;
}
List<String> diff = org.stream()
.filter(s -> !target.contains(s))
.collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(diff)) {
return true;
}
return false;
}
}

View File

@ -156,6 +156,8 @@ public class ApiAutomationService {
@Resource
private JMeterService jMeterService;
@Resource
private ApiTestCaseService apiTestCaseService;
private ThreadLocal<Long> currentScenarioOrder = new ThreadLocal<>();
public ApiScenarioDTO getDto(String id) {
@ -286,6 +288,16 @@ public class ApiAutomationService {
if (relationshipEdgeService != null) {
relationshipEdgeService.initRelationshipEdge(null, scenario);
}
apiTestCaseService.checkAndSendReviewMessage(
scenario.getId(),
scenario.getName(),
scenario.getProjectId(),
"场景用例通知",
NoticeConstants.TaskType.API_AUTOMATION_TASK,
null,
scenario.getScenarioDefinition(),
scenario.getPrincipal()
);
uploadFiles(request, bodyFiles, scenarioFiles);
return scenario;
@ -417,6 +429,16 @@ public class ApiAutomationService {
if (relationshipEdgeService != null) {
relationshipEdgeService.initRelationshipEdge(beforeScenario, scenario);
}
apiTestCaseService.checkAndSendReviewMessage(
scenario.getId(),
scenario.getName(),
scenario.getProjectId(),
"场景用例通知",
NoticeConstants.TaskType.API_AUTOMATION_TASK,
beforeScenario.getScenarioDefinition(),
scenario.getScenarioDefinition(),
scenario.getPrincipal()
);
checkAndSetLatestVersion(beforeScenario.getRefId());
return scenario;
}

View File

@ -18,10 +18,7 @@ import io.metersphere.api.dto.scenario.request.RequestType;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.*;
import io.metersphere.base.mapper.ext.*;
import io.metersphere.commons.constants.APITestStatus;
import io.metersphere.commons.constants.CommonConstants;
import io.metersphere.commons.constants.MsTestElementConstants;
import io.metersphere.commons.constants.TestPlanStatus;
import io.metersphere.commons.constants.*;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.*;
import io.metersphere.controller.request.OrderRequest;
@ -31,8 +28,11 @@ import io.metersphere.log.utils.ReflexObjectUtil;
import io.metersphere.log.vo.DetailColumn;
import io.metersphere.log.vo.OperatingLogDetails;
import io.metersphere.log.vo.api.DefinitionReference;
import io.metersphere.notice.service.NotificationService;
import io.metersphere.plugin.core.MsTestElement;
import io.metersphere.service.FileService;
import io.metersphere.service.ProjectApplicationService;
import io.metersphere.service.ProjectService;
import io.metersphere.service.UserService;
import io.metersphere.track.request.testcase.ApiCaseRelevanceRequest;
import io.metersphere.track.service.TestPlanApiCaseService;
@ -48,6 +48,7 @@ import org.apache.ibatis.session.SqlSessionFactory;
import org.aspectj.util.FileUtil;
import org.mybatis.spring.SqlSessionUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
@ -113,6 +114,13 @@ public class ApiTestCaseService {
private ObjectMapper mapper;
@Resource
private ExtApiDefinitionMapper extApiDefinitionMapper;
@Resource
private ProjectApplicationService projectApplicationService;
@Resource
private NotificationService notificationService;
@Lazy
@Resource
private ProjectService projectService;
private static final String BODY_FILE_DIR = FileUtils.BODY_FILE_DIR;
@ -390,6 +398,7 @@ public class ApiTestCaseService {
final ApiTestCaseWithBLOBs test = apiTestCaseMapper.selectByPrimaryKey(request.getId());
if (test != null) {
String requestOrg = test.getRequest();
test.setName(request.getName());
test.setCaseStatus(request.getCaseStatus());
if (StringUtils.isEmpty(request.getCaseStatus())) {
@ -411,6 +420,15 @@ public class ApiTestCaseService {
}
apiTestCaseMapper.updateByPrimaryKeySelective(test);
saveFollows(test.getId(), request.getFollows());
this.checkAndSendReviewMessage(test.getId(),
test.getName(),
test.getProjectId(),
"接口用例通知",
NoticeConstants.TaskType.API_DEFINITION_TASK,
requestOrg,
test.getRequest(),
test.getCreateUserId()
);
}
return test;
}
@ -469,6 +487,15 @@ public class ApiTestCaseService {
apiTestCaseMapper.insert(test);
saveFollows(test.getId(), request.getFollows());
}
this.checkAndSendReviewMessage(test.getId(),
test.getName(),
test.getProjectId(),
"接口用例通知",
NoticeConstants.TaskType.API_DEFINITION_TASK,
null,
test.getRequest(),
test.getCreateUserId()
);
return test;
}
@ -1180,4 +1207,52 @@ public class ApiTestCaseService {
return null;
}
//检查并发送脚本审核的通知
@Async
public void checkAndSendReviewMessage(
String id,
String name,
String projectId,
String title,
String resourceType,
String requestOrg,
String requestTarget,
String sendUser) {
try {
ProjectApplication scriptEnable = projectApplicationService
.getProjectApplication(projectId, ProjectApplicationType.API_REVIEW_TEST_SCRIPT.name());
if (BooleanUtils.toBoolean(scriptEnable.getTypeValue())) {
List<String> org = ElementUtil.scriptList(requestOrg);
List<String> target = ElementUtil.scriptList(requestTarget);
boolean isSend = ElementUtil.isSend(org, target);
if (isSend) {
ProjectApplication reviewer = projectApplicationService
.getProjectApplication(projectId, ProjectApplicationType.API_SCRIPT_REVIEWER.name());
if (StringUtils.isNotEmpty(reviewer.getTypeValue())) {
sendUser = reviewer.getTypeValue();
}
if (projectService.isProjectMember(projectId, sendUser)) {
Notification notification = new Notification();
notification.setTitle(title);
notification.setOperator(reviewer.getTypeValue());
notification.setOperation(NoticeConstants.Event.REVIEW);
notification.setResourceId(id);
notification.setResourceName(name);
notification.setResourceType(resourceType);
notification.setType(NotificationConstants.Type.SYSTEM_NOTICE.name());
notification.setStatus(NotificationConstants.Status.UNREAD.name());
notification.setCreateTime(System.currentTimeMillis());
notification.setReceiver(sendUser);
notificationService.sendAnnouncement(notification);
}
}
}
} catch (Exception e) {
LogUtil.error("发送通知失败", e);
}
}
}

View File

@ -7,11 +7,12 @@ import io.metersphere.api.dto.ApiMockEnvUpdateDTO;
import io.metersphere.api.dto.ApiTestEnvironmentDTO;
import io.metersphere.api.dto.mockconfig.MockConfigStaticData;
import io.metersphere.api.tcp.TCPPool;
import io.metersphere.base.domain.ApiTestEnvironmentExample;
import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs;
import io.metersphere.base.domain.Project;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.ApiTestEnvironmentMapper;
import io.metersphere.base.mapper.UserGroupMapper;
import io.metersphere.base.mapper.ext.ExtApiTestEnvironmentMapper;
import io.metersphere.commons.constants.NoticeConstants;
import io.metersphere.commons.constants.NotificationConstants;
import io.metersphere.commons.constants.ProjectApplicationType;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.*;
@ -23,16 +24,18 @@ import io.metersphere.log.utils.ReflexObjectUtil;
import io.metersphere.log.vo.DetailColumn;
import io.metersphere.log.vo.OperatingLogDetails;
import io.metersphere.log.vo.system.SystemReference;
import io.metersphere.service.EnvironmentGroupProjectService;
import io.metersphere.service.ProjectApplicationService;
import io.metersphere.service.ProjectService;
import io.metersphere.service.SystemParameterService;
import io.metersphere.notice.service.NotificationService;
import io.metersphere.service.*;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
@ -40,6 +43,7 @@ import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.stream.Collectors;
@Service
@Transactional(rollbackFor = Exception.class)
@ -55,6 +59,21 @@ public class ApiTestEnvironmentService {
private ProjectApplicationService projectApplicationService;
@Resource
private SqlSessionFactory sqlSessionFactory;
@Resource
private NotificationService notificationService;
@Lazy
@Resource
private ProjectService projectService;
@Resource
private UserGroupMapper userGroupMapper;
public static final String POST_STEP = "postStepProcessor";
public static final String PRE_STEP = "preStepProcessor";
public static final String POST = "postProcessor";
public static final String PRE = "preProcessor";
public static final String SCRIPT = "script";
public static final String JSR = "jsr223";
public static final String ASSERTIONS = "assertions";
public List<ApiTestEnvironmentWithBLOBs> list(String projectId) {
ApiTestEnvironmentExample example = new ApiTestEnvironmentExample();
@ -118,6 +137,14 @@ public class ApiTestEnvironmentService {
request.setCreateTime(System.currentTimeMillis());
request.setUpdateTime(System.currentTimeMillis());
apiTestEnvironmentMapper.insert(request);
checkAndSendReviewMessage(request.getId(),
request.getName(),
request.getProjectId(),
NoticeConstants.TaskType.ENV_TASK,
null,
request.getConfig(),
request.getCreateUser()
);
return request.getId();
}
@ -140,7 +167,35 @@ public class ApiTestEnvironmentService {
checkEnvironmentExist(apiTestEnvironment);
FileUtils.createFiles(apiTestEnvironment.getUploadIds(), sslFiles, FileUtils.BODY_FILE_DIR + "/ssl");
apiTestEnvironment.setUpdateTime(System.currentTimeMillis());
ApiTestEnvironmentWithBLOBs envOrg = apiTestEnvironmentMapper.selectByPrimaryKey(apiTestEnvironment.getId());
apiTestEnvironmentMapper.updateByPrimaryKeyWithBLOBs(apiTestEnvironment);
if (StringUtils.isBlank(apiTestEnvironment.getCreateUser())){
UserGroupExample userGroupExample = new UserGroupExample();
userGroupExample.createCriteria().andSourceIdEqualTo(apiTestEnvironment.getProjectId()).andGroupIdEqualTo("project_admin");
List<UserGroup> userGroups = userGroupMapper.selectByExample(userGroupExample);
if (CollectionUtils.isNotEmpty(userGroups)){
userGroups.forEach(userGroup -> {
checkAndSendReviewMessage(apiTestEnvironment.getId(),
apiTestEnvironment.getName(),
apiTestEnvironment.getProjectId(),
NoticeConstants.TaskType.ENV_TASK,
envOrg.getConfig(),
apiTestEnvironment.getConfig(),
userGroup.getUserId()
);
});
}
} else {
checkAndSendReviewMessage(apiTestEnvironment.getId(),
apiTestEnvironment.getName(),
apiTestEnvironment.getProjectId(),
NoticeConstants.TaskType.ENV_TASK,
envOrg.getConfig(),
apiTestEnvironment.getConfig(),
apiTestEnvironment.getCreateUser()
);
}
}
private void checkEnvironmentExist(ApiTestEnvironmentWithBLOBs environment) {
@ -606,4 +661,97 @@ public class ApiTestEnvironmentService {
}
return returnStr;
}
@Async
public void checkAndSendReviewMessage(
String id,
String name,
String projectId,
String resourceType,
String requestOrg,
String requestTarget,
String sendUser) {
try {
ProjectApplication scriptEnable = projectApplicationService
.getProjectApplication(projectId, ProjectApplicationType.API_REVIEW_TEST_SCRIPT.name());
if (BooleanUtils.toBoolean(scriptEnable.getTypeValue())) {
List<String> org = scriptList(requestOrg);
List<String> target = scriptList(requestTarget);
boolean isSend = isSend(org, target);
if (isSend) {
ProjectApplication reviewer = projectApplicationService
.getProjectApplication(projectId, ProjectApplicationType.API_SCRIPT_REVIEWER.name());
if (StringUtils.isNotBlank(reviewer.getTypeValue())) {
sendUser = reviewer.getTypeValue();
}
if (projectService.isProjectMember(projectId, sendUser)) {
Notification notification = new Notification();
notification.setTitle("环境设置");
notification.setOperator(reviewer.getTypeValue());
notification.setOperation(NoticeConstants.Event.REVIEW);
notification.setResourceId(id);
notification.setResourceName(name);
notification.setResourceType(resourceType);
notification.setType(NotificationConstants.Type.SYSTEM_NOTICE.name());
notification.setStatus(NotificationConstants.Status.UNREAD.name());
notification.setCreateTime(System.currentTimeMillis());
notification.setReceiver(sendUser);
notificationService.sendAnnouncement(notification);
}
}
}
} catch (Exception e) {
LogUtil.error("发送通知失败", e);
}
}
public static List<String> scriptList(String request) {
List<String> list = new ArrayList<>();
if (StringUtils.isNotBlank(request)){
JSONObject configObj = JSONObject.parseObject(request);
toList(list, configObj, POST_STEP, PRE_STEP);
toList(list, configObj, PRE, POST);
JSONObject object = configObj.getJSONObject(ASSERTIONS);
if (ObjectUtils.isNotEmpty(object)) {
JSONArray jsrArray = object.getJSONArray(JSR);
if (jsrArray != null) {
for (int j = 0; j < jsrArray.size(); j++) {
JSONObject jsr223 = jsrArray.getJSONObject(j);
if (jsr223 != null) {
list.add(jsr223.getString(SCRIPT));
}
}
}
}
}
return list;
}
private static void toList(List<String> list, JSONObject configObj, String pre, String post) {
JSONObject preProcessor = configObj.getJSONObject(pre);
if (ObjectUtils.isNotEmpty(preProcessor) && StringUtils.isNotBlank(preProcessor.getString(SCRIPT))) {
list.add(StringUtils.join(pre,preProcessor.getString(SCRIPT)));
}
JSONObject postProcessor = configObj.getJSONObject(post);
if (ObjectUtils.isNotEmpty(postProcessor) && StringUtils.isNotBlank(postProcessor.getString(SCRIPT))) {
list.add(StringUtils.join(post,postProcessor.getString(SCRIPT)));
}
}
public static boolean isSend(List<String> orgList, List<String> targetList) {
if (orgList.size() != targetList.size() && targetList.size() > 0) {
return true;
}
List<String> diff = orgList.stream()
.filter(s -> !targetList.contains(s))
.collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(diff)) {
return true;
}
return false;
}
}

View File

@ -70,7 +70,7 @@ public class MsHashTreeService {
private static final String FOLLOW_REDIRECTS = "followRedirects";
private static final String AUTO_REDIRECTS = "autoRedirects";
private static final String ALIAS = "alias";
private static final String INDEX = "index";
public static final String INDEX = "index";
public void setHashTree(JSONArray hashTree) {
// 将引用转成复制

View File

@ -21,6 +21,7 @@ public interface NoticeConstants {
String UI_DEFINITION_TASK = "UI_DEFINITION_TASK";
String UI_HOME_TASK = "UI_HOME_TASK";
String UI_REPORT_TASK = "UI_REPORT_TASK";
String ENV_TASK = "ENV_TASK";
}
interface Mode {

View File

@ -89,4 +89,13 @@ public enum ProjectApplicationType {
* 性能测试脚本评审人
*/
PERFORMANCE_SCRIPT_REVIEWER,
/**
* 接口测试是否评审脚本
*/
API_REVIEW_TEST_SCRIPT,
/**
* 接口测试脚本评审人
*/
API_SCRIPT_REVIEWER,
}

View File

@ -38,4 +38,7 @@ public class ProjectConfig {
//性能测试脚本审核人
private String performanceScriptReviewer;
private String apiScriptReviewer;
private Boolean apiReviewTestScript = false;
}

View File

@ -1191,7 +1191,7 @@ public class PerformanceTestService {
if (StringUtils.isNotEmpty(loadTestScriptReviewerConfig.getTypeValue())) {
sendUser = loadTestScriptReviewerConfig.getTypeValue();
}
if (projectService.isProjectMember(projectId, loadTestScriptReviewerConfig.getTypeValue())) {
if (projectService.isProjectMember(projectId, sendUser)) {
Notification notification = new Notification();
notification.setTitle("性能测试通知");
notification.setOperator(SessionUtils.getUserId());

View File

@ -218,7 +218,8 @@ public class ProjectApplicationService {
String value = conf.getTypeValue();
//性能测试审核人允许value值为空
if (!StringUtils.equals(type, ProjectApplicationType.PERFORMANCE_SCRIPT_REVIEWER.name())
if (!StringUtils.equals(type, ProjectApplicationType.API_SCRIPT_REVIEWER.name())
&& !StringUtils.equals(type, ProjectApplicationType.PERFORMANCE_SCRIPT_REVIEWER.name())
&& (StringUtils.isBlank(projectId) || StringUtils.isBlank(type) || StringUtils.isEmpty(value))) {
LogUtil.error("create or update project config error. project id or conf type or value is blank.");
return;

View File

@ -79,7 +79,9 @@
"html-webpack-inline-source-plugin": "0.0.10",
"less": "^3.9.0",
"less-loader": "^7.3.0",
"vue-template-compiler": "2.6.14"
"vue-template-compiler": "2.6.14",
"sass": "^1.43.4",
"sass-loader": "^10.1.1"
},
"eslintConfig": {
"root": true,

View File

@ -256,6 +256,7 @@ export default {
for (let i in arr) {
arr[i].disabled = disabled;
arr[i].projectId = this.calcProjectId(arr[i].projectId, id);
arr[i].notAddStep = true;
//
let typeArray = ["JDBCPostProcessor", "JDBCSampler", "JDBCPreProcessor"]
if (typeArray.indexOf(arr[i].type) !== -1) {

View File

@ -18,7 +18,7 @@
:value="item.id">
</el-option>
</el-select>
<el-button size="mini" @click="add" type="primary" v-if="tabType !== 'assertionsRule'">
<el-button size="mini" @click="add" type="primary" v-if="tabType !== 'assertionsRule'" :disabled="request.notAddStep">
{{ $t('api_test.request.assertions.add') }}
</el-button>
</p>

View File

@ -14,6 +14,15 @@ export function getResource(d) {
let resourceType = i18n.t('notice.resource.' + d.resourceType);
if (!d.operation.startsWith('EXECUTE_')) {
if (d.operation.startsWith('REVIEW') && d.resourceType === 'API_DEFINITION_TASK') {
resourceType = i18n.t('notice.api_case');
}
if (d.operation.startsWith('REVIEW') && d.resourceType === 'API_AUTOMATION_TASK') {
resourceType = i18n.t('notice.scenario_case');
}
if (d.operation.startsWith('REVIEW') && d.resourceType === 'ENV_TASK') {
resourceType = i18n.t('notice.env_task');
}
return resourceType;
}
switch (d.resourceType) {
@ -88,7 +97,9 @@ export function getUrl(d) {
case "API_DEFINITION_TASK" :
if (d.operation.startsWith('CASE_') || d.operation.startsWith('EXECUTE_')) {
url += "/api/definition?caseId=" + d.resourceId;
} else {
} else if (d.operation.startsWith('REVIEW')) {
url += "/api/definition?caseId=" + d.resourceId;
}else {
url += "/api/definition?resourceId=" + d.resourceId;
}
break;
@ -113,6 +124,9 @@ export function getUrl(d) {
case "TRACK_REPORT_TASK" :
url += "/track/testPlan/reportList";
break;
case"ENV_TASK" :
url += "/project/env?resourceId=" + d.resourceId;
break;
default:
break;
}

View File

@ -179,6 +179,20 @@ export default {
created() {
},
mounted() {
//
if (this.$route && this.$route.query && this.$route.query.resourceId) {
let id = this.$route.query.resourceId;
this.$get('/api/environment/get/' + id, response => {
if (response.data) {
this.editEnv(response.data);
} else {
this.$error(this.$t('environment.get_env_failed'));
}
});
}
},
activated() {
this.list();
},

View File

@ -36,13 +36,6 @@
:unit-options="applyUnitOptions"
@chooseChange="switchChange('TRACK_SHARE_REPORT_TIME', config.trackShareReportTime)"
:title="$t('report.report_sharing_link')"/>
<reviewer-config :name="$t('project.config.load_test_script_review')"
:popTitle="$t('project.config.load_test_script_review_detail')"
:reviewers="userInProject"
:config.sync="config"
@reviewerChange="switchChange('PERFORMANCE_SCRIPT_REVIEWER',config.performanceScriptReviewer)"
@chooseChange="switchChange('PERFORMANCE_REVIEW_LOAD_TEST_SCRIPT',config.performanceReviewLoadTestScript)"
/>
</el-row>
</el-tab-pane>
@ -107,6 +100,26 @@
@change="runModeChange($event, ['RESOURCE_POOL_ID', config.resourcePoolId])"></el-switch>
</template>
</app-manage-item>
<!-- 接口审核 -->
<reviewer-config
:name="$t('project.config.api_script_review')"
:popTitle="$t('project.config.api_script_review_tips')"
:reviewers="userInProject"
:reviewer.sync="config.apiScriptReviewer"
:reviewerSwitch.sync="config.apiReviewTestScript"
@reviewerChange="
switchChange(
'API_SCRIPT_REVIEWER',
config.apiScriptReviewer
)
"
@chooseChange="
switchChange(
'API_REVIEW_TEST_SCRIPT',
config.apiReviewTestScript
)
"
/>
</el-row>
</el-col>
@ -196,7 +209,7 @@
:reviewers="userInProject"
:reviewer.sync="config.performanceScriptReviewer"
:reviewerSwitch.sync="config.performanceReviewLoadTestScript"
:placeholder="$t('commons.creator')"
:placeholder="$t('commons.create_user')"
@reviewerChange="
switchChange(
'PERFORMANCE_SCRIPT_REVIEWER',
@ -291,6 +304,8 @@ export default {
shareReport: true,
performanceScriptReviewer: "",
performanceReviewLoadTestScript: false,
apiScriptReviewer: "",
apiReviewTestScript: false,
},
isPool: false
};
@ -390,6 +405,8 @@ export default {
if (!isExist) {
this.$set(this.config, "performanceScriptReviewer", null);
this.$set(this.config, "performanceReviewLoadTestScript", false);
this.$set(this.config, "apiScriptReviewer", null);
this.$set(this.config, "apiReviewTestScript", false);
}
});
},

View File

@ -34,8 +34,8 @@
<el-col :span="codeSpan">
<el-form-item>
<template v-slot>
<div style="position: relative;">
<el-tabs v-model="activeName">
<div style="position: relative;" :class="{'button-color': apiReviewTestScript}">
<el-tabs v-model="activeName" >
<el-tab-pane :label="$t('project.code_segment.segment')" name="code">
<ms-code-edit
v-if="isCodeEditAlive"
@ -163,9 +163,17 @@ export default {
response: {},
request: {},
debug: true,
console: this.$t('project.code_segment.no_result')
console: this.$t('project.code_segment.no_result'),
apiReviewTestScript: false
}
},
activated() {
this.$get('/project_application/get/' + getCurrentProjectID() + '/API_REVIEW_TEST_SCRIPT', res => {
if (res.data && res.data.typeValue) {
this.apiReviewTestScript = res.data.typeValue === 'true';
}
});
},
methods: {
open(data) {
this.activeName = "code";
@ -264,6 +272,10 @@ export default {
})
},
handleTest() {
if (this.apiReviewTestScript) {
this.$warning(this.$t('project.config.script_warning'));
return;
}
this.activeName = "result";
this.console = this.$t('project.code_segment.no_result');
this.reloadResult();
@ -300,7 +312,7 @@ export default {
}
</script>
<style scoped>
<style lang="scss" scoped>
.template-title {
margin-bottom: 5px;
font-weight: bold;
@ -343,4 +355,12 @@ export default {
color:#935aa1;
}
.button-color{
.el-button--primary{
color: #FFF !important;
background-color: rgb(188, 156, 195) !important;
border-color: rgb(188, 156, 195) !important;
}
}
</style>

View File

@ -851,6 +851,10 @@ export default {
contains_script_review: "has script stepreview it please",
load_test_script_review: "Performance test script review",
load_test_script_review_detail: "Performance test script file upload must specify user review",
api_script_review: "Interface script review",
api_script_review_tips: "User review must be specified when interface use cases include script steps",
reviewers: "Reviewers",
script_warning:"The script has enabled the review mechanism and cannot test the script on the current page",
}
},
member: {
@ -1510,7 +1514,8 @@ export default {
copy_warning: "Domain names whose enabling conditions are'none' do not support copying!",
path_warning: "The path cannot be empty",
project_warning: "project id cannot be empty",
module_warning: "The path cannot be empty"
module_warning: "The path cannot be empty",
get_env_failed: "Jump environment deleted!",
},
scenario: {
id: "Scenario ID",
@ -2901,6 +2906,8 @@ export default {
'EXECUTE_COMPLETED': ' Completed',
},
api_case: 'API Case',
scenario_case: "Scenario Case",
env_task: "Environment",
},
permission: {
project_error_report_library: {

View File

@ -855,6 +855,9 @@ export default {
load_test_script_review: "性能脚本审核",
load_test_script_review_detail: "上传性能测试脚本文件须指定用户审核",
contains_script_review: "包含脚本步骤,请审核",
api_script_review: "接口脚本审核",
api_script_review_tips: "接口用例包含脚本步骤时须指定用户审核",
script_warning:"脚本已启用审核机制,无法在当前页面测试脚本",
}
},
member: {
@ -1514,7 +1517,8 @@ export default {
copy_warning: "启用条件为 '无' 的域名不支持复制!",
path_warning: "路径不能为空",
project_warning: "项目不能为空",
module_warning: "模块不能为空"
module_warning: "模块不能为空",
get_env_failed: "跳转环境被删除!",
},
scenario: {
id: "场景ID",
@ -2905,7 +2909,9 @@ export default {
'EXECUTE_FAILED': '失败',
'EXECUTE_COMPLETED': '完成',
},
api_case: '接口用例'
api_case: '接口用例',
scenario_case: "场景用例",
env_task: "环境",
},
permission: {
project_error_report_library: {

View File

@ -855,6 +855,10 @@ export default {
contains_script_review: "包含脚本步骤,请审核",
load_test_script_review: "性能腳本審核",
load_test_script_review_detail: "上傳性能測試腳本文件須指定用戶審核",
api_script_review: "接口腳本審核",
api_script_review_tips: "接口用例包含腳本步驟時須指定用戶審核",
reviewers: "審核人",
script_warning:"腳本已啟用審核機制,無法在當前頁面測試腳本",
}
},
member: {
@ -1514,7 +1518,8 @@ export default {
copy_warning: "啟用條件為 '無' 的域名不支持複製!",
path_warning: "路徑不能為空",
project_warning: "項目不能為空",
module_warning: "模塊不能為空"
module_warning: "模塊不能為空",
get_env_failed: "跳轉環境被删除!",
},
scenario: {
id: "場景ID",
@ -2901,7 +2906,9 @@ export default {
'EXECUTE_FAILED': '失敗',
'EXECUTE_COMPLETED': '完成',
},
api_case: '接口用例'
api_case: '接口用例',
scenario_case: "場景用例",
env_task: "環境",
},
permission: {
project_error_report_library: {