Merge branch 'master' of https://github.com/metersphere/metersphere
This commit is contained in:
commit
d11f0363c5
|
@ -497,6 +497,15 @@
|
|||
<outputDirectory>src/main/resources/jmeter/lib/ext</outputDirectory>
|
||||
<destFileName>ApacheJMeter_functions.jar</destFileName>
|
||||
</artifactItem>
|
||||
<artifactItem>
|
||||
<groupId>org.python</groupId>
|
||||
<artifactId>jython-standalone</artifactId>
|
||||
<version>2.7.0</version>
|
||||
<type>jar</type>
|
||||
<overWrite>true</overWrite>
|
||||
<outputDirectory>src/main/resources/jmeter/lib/ext</outputDirectory>
|
||||
<destFileName>jython-standalone.jar</destFileName>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
<outputDirectory>${project.build.directory}/wars</outputDirectory>
|
||||
<overWriteReleases>false</overWriteReleases>
|
||||
|
|
|
@ -16,6 +16,7 @@ public class Scenario {
|
|||
private List<KeyValue> headers;
|
||||
private List<Request> requests;
|
||||
private DubboConfig dubboConfig;
|
||||
private TCPConfig tcpConfig;
|
||||
private List<DatabaseConfig> databaseConfigs;
|
||||
private Boolean enable;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package io.metersphere.api.dto.scenario;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class TCPConfig {
|
||||
private String classname;
|
||||
private String server;
|
||||
private Integer port;
|
||||
private Integer ctimeout;
|
||||
private Integer timeout;
|
||||
private Boolean reUseConnection;
|
||||
private Boolean nodelay;
|
||||
private Boolean closeConnection;
|
||||
private String soLinger;
|
||||
private String eolByte;
|
||||
private String username;
|
||||
private String password;
|
||||
}
|
|
@ -11,7 +11,7 @@ import org.apache.jmeter.save.SaveService;
|
|||
import org.apache.jmeter.util.JMeterUtils;
|
||||
import org.apache.jmeter.visualizers.backend.BackendListener;
|
||||
import org.apache.jorphan.collections.HashTree;
|
||||
import org.python.core.Options;
|
||||
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
|
@ -34,10 +34,6 @@ public class JMeterService {
|
|||
JMeterUtils.setJMeterHome(JMETER_HOME);
|
||||
JMeterUtils.setLocale(LocaleContextHolder.getLocale());
|
||||
|
||||
|
||||
//解决无法加载 PyScriptEngineFactory
|
||||
Options.importSite = false;
|
||||
|
||||
try {
|
||||
Object scriptWrapper = SaveService.loadElement(is);
|
||||
HashTree testPlan = getHashTree(scriptWrapper);
|
||||
|
@ -51,7 +47,7 @@ public class JMeterService {
|
|||
}
|
||||
}
|
||||
|
||||
private String getJmeterHome() {
|
||||
public String getJmeterHome() {
|
||||
String home = getClass().getResource("/").getPath() + "jmeter";
|
||||
try {
|
||||
File file = new File(home);
|
||||
|
|
|
@ -173,6 +173,12 @@
|
|||
#{value}
|
||||
</foreach>
|
||||
</when>
|
||||
<when test="key=='executor'">
|
||||
and test_plan_test_case.executor in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</when>
|
||||
<otherwise>
|
||||
and test_plan_test_case.status in
|
||||
<foreach collection="values" item="value" separator="," open="(" close=")">
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package io.metersphere.listener;
|
||||
|
||||
import io.metersphere.api.jmeter.JMeterService;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.service.ScheduleService;
|
||||
import org.python.core.Options;
|
||||
import org.python.util.PythonInterpreter;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
@ -12,12 +16,16 @@ public class AppStartListener implements ApplicationListener<ApplicationReadyEve
|
|||
|
||||
@Resource
|
||||
private ScheduleService scheduleService;
|
||||
@Resource
|
||||
private JMeterService jMeterService;
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
|
||||
|
||||
System.out.println("================= 应用启动 =================");
|
||||
|
||||
initPythonEnv();
|
||||
|
||||
try {
|
||||
Thread.sleep(3 * 60 * 1000);
|
||||
} catch (InterruptedException e) {
|
||||
|
@ -25,6 +33,24 @@ public class AppStartListener implements ApplicationListener<ApplicationReadyEve
|
|||
}
|
||||
|
||||
scheduleService.startEnableSchedules();
|
||||
}
|
||||
|
||||
/**
|
||||
* 解决接口测试-无法导入内置python包
|
||||
*/
|
||||
private void initPythonEnv() {
|
||||
//解决无法加载 PyScriptEngineFactory
|
||||
Options.importSite = false;
|
||||
try {
|
||||
PythonInterpreter interp = new PythonInterpreter();
|
||||
String path = jMeterService.getJmeterHome();
|
||||
System.out.println("sys.path: " + path);
|
||||
path += "/lib/ext/jython-standalone.jar/Lib";
|
||||
interp.exec("import sys");
|
||||
interp.exec("sys.path.append(\"" + path + "\")");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
LogUtil.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<el-input :disabled="isReadOnly" class="test-name" v-model="test.name" maxlength="60"
|
||||
:placeholder="$t('api_test.input_name')"
|
||||
show-word-limit>
|
||||
<el-select :disabled="isReadOnly" class="test-project" v-model="test.projectId" slot="prepend"
|
||||
<el-select filterable class="test-project" v-model="test.projectId" slot="prepend"
|
||||
:placeholder="$t('api_test.select_project')">
|
||||
<el-option v-for="project in projects" :key="project.id" :label="project.name" :value="project.id"/>
|
||||
</el-select>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<el-dialog :close-on-click-modal="false" :title="$t('api_test.environment.environment_config')"
|
||||
:visible.sync="visible" class="environment-dialog"
|
||||
:visible.sync="visible" class="environment-dialog" width="60%"
|
||||
@close="close" append-to-body ref="environmentConfig">
|
||||
<el-container v-loading="result.loading">
|
||||
<ms-aside-item :enable-aside-hidden="false" :title="$t('api_test.environment.environment_list')"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="variable-input">
|
||||
<el-input :disabled="isReadOnly" :value="value" v-bind="$attrs" :size="size" @change="change" @input="input"/>
|
||||
<el-input class="el-input__inner_pd" :disabled="isReadOnly" :value="value" v-bind="$attrs" :size="size" @change="change" @input="input"/>
|
||||
<div :class="{'hidden': !showVariable}" class="variable-combine" v-if="value">
|
||||
<div class="variable">{{variable}}</div>
|
||||
<el-tooltip :content="$t('api_test.copied')" manual v-model="visible" placement="top" :visible-arrow="false">
|
||||
|
@ -70,6 +70,9 @@
|
|||
.variable-input {
|
||||
position: relative;
|
||||
}
|
||||
.el-input__inner_pd >>> .el-input__inner {
|
||||
padding-right: 135px;
|
||||
}
|
||||
|
||||
.variable-combine {
|
||||
color: #7F7F7F;
|
||||
|
|
|
@ -1052,10 +1052,21 @@ class JMXTCPRequest {
|
|||
obj.set(scenario.environment.config.tcpConfig, true);
|
||||
return obj;
|
||||
}
|
||||
obj.set(scenario.tcpConfig, true);
|
||||
|
||||
this.copy(this, scenario.tcpConfig);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
copy(target, source) {
|
||||
for (let key in source) {
|
||||
if (source.hasOwnProperty(key)) {
|
||||
if (source[key] !== undefined && !target[key]) {
|
||||
target[key] = source[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class JMeterTestPlan extends Element {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
maxlength="30" show-word-limit
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<el-select :disabled="isReadOnly" v-model="testPlan.projectId"
|
||||
<el-select filterable v-model="testPlan.projectId"
|
||||
:placeholder="$t('load_test.select_project')">
|
||||
<el-option
|
||||
v-for="item in projects"
|
||||
|
|
|
@ -101,7 +101,7 @@
|
|||
<el-form :model="memberForm" ref="form" :rules="orgMemberRule" label-position="right" label-width="100px"
|
||||
size="small">
|
||||
<el-form-item :label="$t('commons.member')" prop="userIds">
|
||||
<el-select v-model="memberForm.userIds" multiple :placeholder="$t('member.please_choose_member')"
|
||||
<el-select filterable v-model="memberForm.userIds" multiple :placeholder="$t('member.please_choose_member')"
|
||||
class="select-width">
|
||||
<el-option
|
||||
v-for="item in memberForm.userList"
|
||||
|
@ -114,7 +114,7 @@
|
|||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('commons.role')" prop="roleIds">
|
||||
<el-select v-model="memberForm.roleIds" multiple :placeholder="$t('role.please_choose_role')"
|
||||
<el-select filterable v-model="memberForm.roleIds" multiple :placeholder="$t('role.please_choose_role')"
|
||||
class="select-width">
|
||||
<el-option
|
||||
v-for="item in memberForm.roles"
|
||||
|
@ -151,7 +151,7 @@
|
|||
</el-form-item>
|
||||
<el-form-item :label="$t('commons.role')" prop="roleIds"
|
||||
:rules="{required: true, message: $t('role.please_choose_role'), trigger: 'change'}">
|
||||
<el-select v-model="memberForm.roleIds" multiple :placeholder="$t('role.please_choose_role')"
|
||||
<el-select filterable v-model="memberForm.roleIds" multiple :placeholder="$t('role.please_choose_role')"
|
||||
class="select-width">
|
||||
<el-option
|
||||
v-for="item in memberForm.allroles"
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
<el-input type="textarea" v-model="form.description"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('workspace.organization_name')" prop="organizationId">
|
||||
<el-select v-model="form.organizationId" :placeholder="$t('organization.select_organization')"
|
||||
<el-select filterable v-model="form.organizationId" :placeholder="$t('organization.select_organization')"
|
||||
class="select-width">
|
||||
<el-option
|
||||
v-for="item in form.orgList"
|
||||
|
@ -65,7 +65,7 @@
|
|||
<el-input type="textarea" v-model="form.description"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('workspace.organization_name')" prop="organizationId">
|
||||
<el-select v-model="form.organizationId" :placeholder="$t('organization.select_organization')"
|
||||
<el-select filterable v-model="form.organizationId" :placeholder="$t('organization.select_organization')"
|
||||
class="select-width">
|
||||
<el-option
|
||||
v-for="item in form.orgList1"
|
||||
|
@ -117,7 +117,7 @@
|
|||
<el-form :model="memberForm" ref="form" :rules="wsMemberRule" label-position="right" label-width="100px"
|
||||
size="small">
|
||||
<el-form-item :label="$t('commons.member')" prop="userIds">
|
||||
<el-select v-model="memberForm.userIds" multiple :placeholder="$t('member.please_choose_member')"
|
||||
<el-select filterable v-model="memberForm.userIds" multiple :placeholder="$t('member.please_choose_member')"
|
||||
class="select-width">
|
||||
<el-option
|
||||
v-for="item in memberForm.userList"
|
||||
|
@ -130,7 +130,7 @@
|
|||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('commons.role')" prop="roleIds">
|
||||
<el-select v-model="memberForm.roleIds" multiple :placeholder="$t('role.please_choose_role')"
|
||||
<el-select filterable v-model="memberForm.roleIds" multiple :placeholder="$t('role.please_choose_role')"
|
||||
class="select-width">
|
||||
<el-option
|
||||
v-for="item in memberForm.roles"
|
||||
|
@ -166,7 +166,7 @@
|
|||
<el-input v-model="memberForm.phone" autocomplete="off" :disabled="true"/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('commons.role')" prop="roleIds" :rules="{required: true, message: $t('role.please_choose_role'), trigger: 'change'}">
|
||||
<el-select v-model="memberForm.roleIds" multiple :placeholder="$t('role.please_choose_role')"
|
||||
<el-select filterable v-model="memberForm.roleIds" multiple :placeholder="$t('role.please_choose_role')"
|
||||
class="select-width">
|
||||
<el-option
|
||||
v-for="item in memberForm.allroles"
|
||||
|
|
|
@ -74,7 +74,7 @@
|
|||
:prop="'roles.' + index + '.id'"
|
||||
:rules="{required: true, message: $t('role.please_choose_role'), trigger: 'change'}"
|
||||
>
|
||||
<el-select v-model="role.id" :placeholder="$t('role.please_choose_role')">
|
||||
<el-select filterable v-model="role.id" :placeholder="$t('role.please_choose_role')">
|
||||
<el-option
|
||||
v-for="item in activeRole(role)"
|
||||
:key="item.id"
|
||||
|
@ -93,7 +93,7 @@
|
|||
:prop="'roles.' + index + '.ids'"
|
||||
:rules="{required: true, message: $t('organization.select_organization'), trigger: 'change'}"
|
||||
>
|
||||
<el-select v-model="role.ids" :placeholder="$t('organization.select_organization')" multiple>
|
||||
<el-select filterable v-model="role.ids" :placeholder="$t('organization.select_organization')" multiple>
|
||||
<el-option
|
||||
v-for="item in form.orgList"
|
||||
:key="item.id"
|
||||
|
@ -108,7 +108,7 @@
|
|||
:prop="'roles.' + index + '.ids'"
|
||||
:rules="{required: true, message: $t('workspace.select'), trigger: 'change'}"
|
||||
>
|
||||
<el-select v-model="role.ids" :placeholder="$t('workspace.select')" multiple>
|
||||
<el-select filterable v-model="role.ids" :placeholder="$t('workspace.select')" multiple>
|
||||
<el-option
|
||||
v-for="item in form.wsList"
|
||||
:key="item.id"
|
||||
|
@ -123,7 +123,7 @@
|
|||
:prop="'roles.' + index + '.ids'"
|
||||
:rules="{required: true, message: $t('workspace.select'), trigger: 'change'}"
|
||||
>
|
||||
<el-select v-model="role.ids" :placeholder="$t('workspace.select')" multiple>
|
||||
<el-select filterable v-model="role.ids" :placeholder="$t('workspace.select')" multiple>
|
||||
<el-option
|
||||
v-for="item in form.wsList"
|
||||
:key="item.id"
|
||||
|
@ -138,7 +138,7 @@
|
|||
:prop="'roles.' + index + '.ids'"
|
||||
:rules="{required: true, message: $t('workspace.select'), trigger: 'change'}"
|
||||
>
|
||||
<el-select v-model="role.ids" :placeholder="$t('workspace.select')" multiple>
|
||||
<el-select filterable v-model="role.ids" :placeholder="$t('workspace.select')" multiple>
|
||||
<el-option
|
||||
v-for="item in form.wsList"
|
||||
:key="item.id"
|
||||
|
@ -187,7 +187,7 @@
|
|||
:prop="'roles.' + index + '.id'"
|
||||
:rules="{required: true, message: $t('role.please_choose_role'), trigger: 'change'}"
|
||||
>
|
||||
<el-select v-model="role.id" :placeholder="$t('role.please_choose_role')" :disabled="!!role.id">
|
||||
<el-select filterable v-model="role.id" :placeholder="$t('role.please_choose_role')" :disabled="!!role.id">
|
||||
<el-option
|
||||
v-for="item in activeRole(role)"
|
||||
:key="item.id"
|
||||
|
@ -204,7 +204,7 @@
|
|||
:prop="'roles.' + index + '.ids'"
|
||||
:rules="{required: true, message: $t('organization.select_organization'), trigger: 'change'}"
|
||||
>
|
||||
<el-select v-model="role.ids" :placeholder="$t('organization.select_organization')" multiple>
|
||||
<el-select filterable v-model="role.ids" :placeholder="$t('organization.select_organization')" multiple>
|
||||
<el-option
|
||||
v-for="item in form.orgList"
|
||||
:key="item.id"
|
||||
|
@ -219,7 +219,7 @@
|
|||
:prop="'roles.' + index + '.ids'"
|
||||
:rules="{required: true, message: $t('workspace.select'), trigger: 'change'}"
|
||||
>
|
||||
<el-select v-model="role.ids" :placeholder="$t('workspace.select')" multiple>
|
||||
<el-select filterable v-model="role.ids" :placeholder="$t('workspace.select')" multiple>
|
||||
<el-option
|
||||
v-for="item in form.wsList"
|
||||
:key="item.id"
|
||||
|
@ -234,7 +234,7 @@
|
|||
:prop="'roles.' + index + '.ids'"
|
||||
:rules="{required: true, message: $t('workspace.select'), trigger: 'change'}"
|
||||
>
|
||||
<el-select v-model="role.ids" :placeholder="$t('workspace.select')" multiple>
|
||||
<el-select filterable v-model="role.ids" :placeholder="$t('workspace.select')" multiple>
|
||||
<el-option
|
||||
v-for="item in form.wsList"
|
||||
:key="item.id"
|
||||
|
@ -249,7 +249,7 @@
|
|||
:prop="'roles.' + index + '.ids'"
|
||||
:rules="{required: true, message: $t('workspace.select'), trigger: 'change'}"
|
||||
>
|
||||
<el-select v-model="role.ids" :placeholder="$t('workspace.select')" multiple>
|
||||
<el-select filterable v-model="role.ids" :placeholder="$t('workspace.select')" multiple>
|
||||
<el-option
|
||||
v-for="item in form.wsList"
|
||||
:key="item.id"
|
||||
|
|
|
@ -0,0 +1,203 @@
|
|||
<template>
|
||||
<el-form :model="form" ref="caseFrom" v-loading="result.loading">
|
||||
|
||||
<el-row>
|
||||
<el-col :span="8" :offset="1">
|
||||
<el-form-item
|
||||
:placeholder="$t('test_track.case.input_name')"
|
||||
:label="$t('test_track.case.name')"
|
||||
:label-width="formLabelWidth"
|
||||
prop="name">
|
||||
<el-input class="case-name" :disabled="readOnly" v-model="testCase.name"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="11" :offset="2">
|
||||
<el-form-item :label="$t('test_track.case.module')" :label-width="formLabelWidth" prop="module">
|
||||
<el-input class="case-name" :disabled="readOnly" v-model="testCase.nodePath"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="10" :offset="1">
|
||||
<el-form-item :label="$t('test_track.case.maintainer')" :label-width="formLabelWidth" prop="maintainer">
|
||||
<el-select :disabled="readOnly" v-model="testCase.maintainer"
|
||||
:placeholder="$t('test_track.case.input_maintainer')" filterable>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item :label="$t('test_track.case.priority')" :label-width="formLabelWidth" prop="priority">
|
||||
<el-select :disabled="readOnly" v-model="testCase.priority" clearable
|
||||
:placeholder="$t('test_track.case.input_priority')">
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="10" :offset="1">
|
||||
<el-form-item :label="$t('test_track.case.type')" :label-width="formLabelWidth" prop="type">
|
||||
<el-select :disabled="readOnly" v-model="testCase.type"
|
||||
:placeholder="$t('test_track.case.input_type')">
|
||||
<el-option :label="$t('commons.functional')" value="functional"></el-option>
|
||||
<el-option :label="$t('commons.performance')" value="performance"></el-option>
|
||||
<el-option :label="$t('commons.api')" value="api"></el-option>
|
||||
</el-select>
|
||||
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item :label="$t('test_track.case.method')" :label-width="formLabelWidth" prop="method">
|
||||
<el-select :disabled="readOnly" v-model="testCase.method" :placeholder="$t('test_track.case.input_method')">
|
||||
<el-option :label="$t('test_track.case.auto')" value="auto"></el-option>
|
||||
<el-option :label="$t('test_track.case.manual')" value="manual"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row v-if="testCase.method && testCase.method == 'auto'">
|
||||
<el-col :span="9" :offset="1">
|
||||
<el-form-item :label="$t('test_track.case.relate_test')" :label-width="formLabelWidth" prop="testId">
|
||||
<el-select filterable :disabled="readOnly" v-model="testCase.testId"
|
||||
:placeholder="$t('test_track.case.input_type')">
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="9" :offset="1" v-if="testCase.testId=='other'">
|
||||
<el-form-item :label="$t('test_track.case.test_name')" :label-width="formLabelWidth" prop="testId">
|
||||
<el-input v-model="testCase.otherTestName" :placeholder="$t('test_track.case.input_test_case')"
|
||||
:disabled="readOnly"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row style="margin-top: 15px;">
|
||||
<el-col :offset="2">{{ $t('test_track.case.prerequisite') }}:</el-col>
|
||||
</el-row>
|
||||
<el-row type="flex" justify="center" style="margin-top: 10px;">
|
||||
<el-col :span="20">
|
||||
<el-form-item prop="prerequisite">
|
||||
<el-input :disabled="readOnly" v-model="testCase.prerequisite"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 4}"
|
||||
:rows="2"
|
||||
:placeholder="$t('test_track.case.input_prerequisite')"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row v-if="testCase.method && testCase.method != 'auto'" style="margin-bottom: 10px">
|
||||
<el-col :offset="2">{{ $t('test_track.case.steps') }}:</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row v-if="testCase.method && testCase.method != 'auto'" type="flex" justify="center">
|
||||
<el-col :span="20">
|
||||
<el-table
|
||||
v-if="isStepTableAlive"
|
||||
:data="JSON.parse(testCase.steps)"
|
||||
class="tb-edit"
|
||||
border
|
||||
size="mini"
|
||||
:default-sort="{prop: 'num', order: 'ascending'}"
|
||||
highlight-current-row>
|
||||
<el-table-column :label="$t('test_track.case.number')" prop="num" min-width="15%"></el-table-column>
|
||||
<el-table-column :label="$t('test_track.case.step_desc')" prop="desc" min-width="35%">
|
||||
<template v-slot:default="scope">
|
||||
<el-input
|
||||
class="table-edit-input"
|
||||
size="mini"
|
||||
:disabled="readOnly"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 1, maxRows: 6}"
|
||||
:rows="2"
|
||||
v-model="scope.row.desc"
|
||||
:placeholder="$t('commons.input_content')"
|
||||
clearable/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('test_track.case.expected_results')" prop="result" min-width="35%">
|
||||
<template v-slot:default="scope">
|
||||
<el-input
|
||||
class="table-edit-input"
|
||||
size="mini"
|
||||
:disabled="readOnly"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 1, maxRows: 6}"
|
||||
:rows="2"
|
||||
v-model="scope.row.result"
|
||||
:placeholder="$t('commons.input_content')"
|
||||
clearable/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row style="margin-top: 15px;margin-bottom: 10px">
|
||||
<el-col :offset="2">{{ $t('commons.remark') }}:</el-col>
|
||||
</el-row>
|
||||
<el-row type="flex" justify="center">
|
||||
<el-col :span="20">
|
||||
<el-form-item prop="remark">
|
||||
<el-input v-model="testCase.remark"
|
||||
:autosize="{ minRows: 2, maxRows: 4}"
|
||||
type="textarea"
|
||||
:disabled="readOnly"
|
||||
:rows="2"
|
||||
:placeholder="$t('commons.input_content')"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: "TestCaseDetail",
|
||||
data() {
|
||||
return {
|
||||
result: {},
|
||||
dialogFormVisible: false,
|
||||
readOnly: true,
|
||||
form: {
|
||||
name: '',
|
||||
module: '',
|
||||
maintainer: '',
|
||||
priority: '',
|
||||
type: '',
|
||||
method: '',
|
||||
prerequisite: '',
|
||||
testId: '',
|
||||
otherTestName: '',
|
||||
steps: [{
|
||||
num: 1,
|
||||
desc: '',
|
||||
result: ''
|
||||
}],
|
||||
remark: '',
|
||||
},
|
||||
workspaceId: '',
|
||||
formLabelWidth: "120px",
|
||||
|
||||
isStepTableAlive: true,
|
||||
methodOptions: [
|
||||
{value: 'auto', label: this.$t('test_track.case.auto')},
|
||||
{value: 'manual', label: this.$t('test_track.case.manual')}
|
||||
]
|
||||
};
|
||||
},
|
||||
props: {
|
||||
testCase: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -56,9 +56,18 @@
|
|||
show-overflow-tooltip
|
||||
>
|
||||
<template v-slot:default="scope">
|
||||
<div @mouseover="showDetail(scope.row)">
|
||||
<!--<div @mouseover="showDetail(scope.row)">
|
||||
<p>{{ scope.row.name }}</p>
|
||||
</div>
|
||||
</div>-->
|
||||
<el-popover
|
||||
placement="right-end"
|
||||
:title="$t('test_track.case.view_case')"
|
||||
width="60%"
|
||||
trigger="hover"
|
||||
>
|
||||
<test-case-detail :test-case="scope.row"/>
|
||||
<p slot="reference">{{ scope.row.name }}</p>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
|
@ -164,7 +173,7 @@
|
|||
import {WORKSPACE_ID} from "../../../../../common/js/constants";
|
||||
import {LIST_CHANGE, TrackEvent} from "@/business/components/common/head/ListEvent";
|
||||
import StatusTableItem from "@/business/components/track/common/tableItems/planview/StatusTableItem";
|
||||
|
||||
import TestCaseDetail from "./TestCaseDetail";
|
||||
export default {
|
||||
name: "TestCaseList",
|
||||
components: {
|
||||
|
@ -182,7 +191,8 @@
|
|||
MsTableHeader,
|
||||
ShowMoreBtn,
|
||||
BatchEdit,
|
||||
StatusTableItem
|
||||
StatusTableItem,
|
||||
TestCaseDetail
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
|
|
@ -1,53 +1,56 @@
|
|||
<template>
|
||||
<el-menu :unique-opened="true" mode="horizontal" active-text-color="write"
|
||||
class="project_menu">
|
||||
<el-submenu index="1" popper-class="submenu">
|
||||
<template v-slot:title>
|
||||
<span class="menu-title">{{'[' + title + ']'}}</span>
|
||||
<span> {{currentData == null ? '' : currentData.name}} </span>
|
||||
</template>
|
||||
<template v-slot:default>
|
||||
<div style="height:400px;">
|
||||
<el-scrollbar style="height:100%">
|
||||
<label v-for="(item,index) in data" :key="index">
|
||||
<el-menu-item @click="changeData(item)">
|
||||
{{item.name}}
|
||||
<i class="el-icon-check" v-if="currentData && item.id === currentData.id"></i>
|
||||
</el-menu-item>
|
||||
</label>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</template>
|
||||
</el-submenu>
|
||||
</el-menu>
|
||||
<div>
|
||||
<span class="menu-title">{{'[' + title + ']'}}</span>
|
||||
<el-select filterable slot="prepend" v-model="value" @change="changeData" class="project_menu"
|
||||
size="small">
|
||||
<el-option v-for="(item,index) in data" :key="index" :label="item.name" :value="index"/>
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "SelectMenu",
|
||||
props: {
|
||||
data: {
|
||||
type: Array
|
||||
},
|
||||
currentData: {
|
||||
type: Object
|
||||
},
|
||||
title: {
|
||||
type: String
|
||||
}
|
||||
export default {
|
||||
name: "SelectMenu",
|
||||
props: {
|
||||
data: {
|
||||
type: Array
|
||||
},
|
||||
methods: {
|
||||
changeData(data) {
|
||||
this.$emit("dataChange", data);
|
||||
currentData: {
|
||||
type: Object
|
||||
},
|
||||
title: {
|
||||
type: String
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
value: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
currentData(data) {
|
||||
if (data != undefined && data != null) {
|
||||
this.value = data.name;
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changeData(index) {
|
||||
this.$emit("dataChange", this.data[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.project_menu {
|
||||
width: 214px;
|
||||
}
|
||||
|
||||
.menu-title {
|
||||
color: darkgrey;
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -180,6 +180,7 @@
|
|||
:disabled="isReadOnly"
|
||||
v-model="scope.row.executeResult"
|
||||
@change="stepResultChange()"
|
||||
filterable
|
||||
size="mini">
|
||||
<el-option :label="$t('test_track.plan_view.pass')" value="Pass"
|
||||
style="color: #7ebf50;"></el-option>
|
||||
|
@ -227,6 +228,7 @@
|
|||
{{ $t('test_track.issue.please_choose_current_owner') }}
|
||||
<el-select v-model="testCase.tapdUsers"
|
||||
multiple
|
||||
filterable
|
||||
style="width: 20%"
|
||||
:placeholder="$t('test_track.issue.please_choose_current_owner')"
|
||||
collapse-tags>
|
||||
|
|
|
@ -122,13 +122,13 @@
|
|||
>
|
||||
<ckeditor :editor="editor" disabled :config="editorConfig"
|
||||
v-model="scope.row.description"/>
|
||||
<el-button slot="reference" type="text">{{$t('test_track.issue.preview')}}</el-button>
|
||||
<el-button slot="reference" type="text">{{ $t('test_track.issue.preview') }}</el-button>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="platform" :label="$t('test_track.issue.platform')"/>
|
||||
</el-table>
|
||||
<el-button slot="reference" type="text">{{scope.row.issuesSize}}</el-button>
|
||||
<el-button slot="reference" type="text">{{ scope.row.issuesSize }}</el-button>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
@ -136,6 +136,8 @@
|
|||
|
||||
<el-table-column
|
||||
prop="executorName"
|
||||
:filters="executorFilters"
|
||||
column-key="executor"
|
||||
:label="$t('test_track.plan_view.executor')">
|
||||
</el-table-column>
|
||||
|
||||
|
@ -152,18 +154,18 @@
|
|||
</span>
|
||||
<el-dropdown-menu slot="dropdown" chang>
|
||||
<el-dropdown-item :disabled="!isTestManagerOrTestUser" :command="{id: scope.row.id, status: 'Pass'}">
|
||||
{{$t('test_track.plan_view.pass')}}
|
||||
{{ $t('test_track.plan_view.pass') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :disabled="!isTestManagerOrTestUser"
|
||||
:command="{id: scope.row.id, status: 'Failure'}">
|
||||
{{$t('test_track.plan_view.failure')}}
|
||||
{{ $t('test_track.plan_view.failure') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :disabled="!isTestManagerOrTestUser"
|
||||
:command="{id: scope.row.id, status: 'Blocking'}">
|
||||
{{$t('test_track.plan_view.blocking')}}
|
||||
{{ $t('test_track.plan_view.blocking') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :disabled="!isTestManagerOrTestUser" :command="{id: scope.row.id, status: 'Skip'}">
|
||||
{{$t('test_track.plan_view.skip')}}
|
||||
{{ $t('test_track.plan_view.skip') }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
|
@ -210,386 +212,392 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import ExecutorEdit from './ExecutorEdit';
|
||||
import StatusEdit from './StatusEdit';
|
||||
import TestPlanTestCaseEdit from "./TestPlanTestCaseEdit";
|
||||
import MsTipButton from '../../../../common/components/MsTipButton';
|
||||
import MsTablePagination from '../../../../common/pagination/TablePagination';
|
||||
import MsTableHeader from '../../../../common/components/MsTableHeader';
|
||||
import MsTableButton from '../../../../common/components/MsTableButton';
|
||||
import NodeBreadcrumb from '../../../common/NodeBreadcrumb';
|
||||
import ExecutorEdit from './ExecutorEdit';
|
||||
import StatusEdit from './StatusEdit';
|
||||
import TestPlanTestCaseEdit from "./TestPlanTestCaseEdit";
|
||||
import MsTipButton from '../../../../common/components/MsTipButton';
|
||||
import MsTablePagination from '../../../../common/pagination/TablePagination';
|
||||
import MsTableHeader from '../../../../common/components/MsTableHeader';
|
||||
import MsTableButton from '../../../../common/components/MsTableButton';
|
||||
import NodeBreadcrumb from '../../../common/NodeBreadcrumb';
|
||||
|
||||
import {ROLE_TEST_MANAGER, ROLE_TEST_USER, TokenKey, WORKSPACE_ID} from '../../../../../../common/js/constants';
|
||||
import {_filter, _sort, checkoutTestManagerOrTestUser, hasRoles} from '../../../../../../common/js/utils';
|
||||
import PriorityTableItem from "../../../common/tableItems/planview/PriorityTableItem";
|
||||
import StatusTableItem from "../../../common/tableItems/planview/StatusTableItem";
|
||||
import TypeTableItem from "../../../common/tableItems/planview/TypeTableItem";
|
||||
import MethodTableItem from "../../../common/tableItems/planview/MethodTableItem";
|
||||
import MsTableOperator from "../../../../common/components/MsTableOperator";
|
||||
import MsTableOperatorButton from "../../../../common/components/MsTableOperatorButton";
|
||||
import TestReportTemplateList from "./TestReportTemplateList";
|
||||
import TestCaseReportView from "./report/TestCaseReportView";
|
||||
import {TEST_CASE_CONFIGS} from "../../../../common/components/search/search-components";
|
||||
import ShowMoreBtn from "../../../case/components/ShowMoreBtn";
|
||||
import BatchEdit from "../../../case/components/BatchEdit";
|
||||
import ClassicEditor from "@ckeditor/ckeditor5-build-classic";
|
||||
import {hub} from "@/business/components/track/plan/event-bus";
|
||||
import {ROLE_TEST_MANAGER, ROLE_TEST_USER, TokenKey, WORKSPACE_ID} from "@/common/js/constants";
|
||||
import {_filter, _sort, checkoutTestManagerOrTestUser, hasRoles} from "@/common/js/utils";
|
||||
import PriorityTableItem from "../../../common/tableItems/planview/PriorityTableItem";
|
||||
import StatusTableItem from "../../../common/tableItems/planview/StatusTableItem";
|
||||
import TypeTableItem from "../../../common/tableItems/planview/TypeTableItem";
|
||||
import MethodTableItem from "../../../common/tableItems/planview/MethodTableItem";
|
||||
import MsTableOperator from "../../../../common/components/MsTableOperator";
|
||||
import MsTableOperatorButton from "../../../../common/components/MsTableOperatorButton";
|
||||
import TestReportTemplateList from "./TestReportTemplateList";
|
||||
import TestCaseReportView from "./report/TestCaseReportView";
|
||||
import {TEST_CASE_CONFIGS} from "../../../../common/components/search/search-components";
|
||||
import ShowMoreBtn from "../../../case/components/ShowMoreBtn";
|
||||
import BatchEdit from "../../../case/components/BatchEdit";
|
||||
import ClassicEditor from "@ckeditor/ckeditor5-build-classic";
|
||||
import {hub} from "@/business/components/track/plan/event-bus";
|
||||
|
||||
export default {
|
||||
name: "TestPlanTestCaseList",
|
||||
components: {
|
||||
TestCaseReportView,
|
||||
TestReportTemplateList,
|
||||
MsTableOperatorButton,
|
||||
MsTableOperator,
|
||||
MethodTableItem,
|
||||
TypeTableItem,
|
||||
StatusTableItem,
|
||||
PriorityTableItem, StatusEdit, ExecutorEdit, MsTipButton, MsTablePagination,
|
||||
TestPlanTestCaseEdit, MsTableHeader, NodeBreadcrumb, MsTableButton, ShowMoreBtn,
|
||||
BatchEdit
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
result: {},
|
||||
deletePath: "/test/case/delete",
|
||||
condition: {
|
||||
components: TEST_CASE_CONFIGS
|
||||
},
|
||||
showMyTestCase: false,
|
||||
tableData: [],
|
||||
currentPage: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
selectRows: new Set(),
|
||||
testPlan: {},
|
||||
isReadOnly: false,
|
||||
isTestManagerOrTestUser: false,
|
||||
priorityFilters: [
|
||||
{text: 'P0', value: 'P0'},
|
||||
{text: 'P1', value: 'P1'},
|
||||
{text: 'P2', value: 'P2'},
|
||||
{text: 'P3', value: 'P3'}
|
||||
],
|
||||
methodFilters: [
|
||||
{text: this.$t('test_track.case.manual'), value: 'manual'},
|
||||
{text: this.$t('test_track.case.auto'), value: 'auto'}
|
||||
],
|
||||
typeFilters: [
|
||||
{text: this.$t('commons.functional'), value: 'functional'},
|
||||
{text: this.$t('commons.performance'), value: 'performance'},
|
||||
{text: this.$t('commons.api'), value: 'api'}
|
||||
],
|
||||
statusFilters: [
|
||||
{text: this.$t('test_track.plan.plan_status_prepare'), value: 'Prepare'},
|
||||
{text: this.$t('test_track.plan_view.pass'), value: 'Pass'},
|
||||
{text: this.$t('test_track.plan_view.failure'), value: 'Failure'},
|
||||
{text: this.$t('test_track.plan_view.blocking'), value: 'Blocking'},
|
||||
{text: this.$t('test_track.plan_view.skip'), value: 'Skip'},
|
||||
{text: this.$t('test_track.plan.plan_status_running'), value: 'Underway'},
|
||||
],
|
||||
showMore: false,
|
||||
buttons: [
|
||||
{
|
||||
name: this.$t('test_track.case.batch_edit_case'), handleClick: this.handleBatchEdit
|
||||
},
|
||||
{
|
||||
name: this.$t('test_track.case.batch_unlink'), handleClick: this.handleDeleteBatch
|
||||
}
|
||||
],
|
||||
typeArr: [
|
||||
{id: 'status', name: this.$t('test_track.plan_view.execute_result')},
|
||||
{id: 'executor', name: this.$t('test_track.plan_view.executor')},
|
||||
],
|
||||
valueArr: {
|
||||
executor: [],
|
||||
status: [
|
||||
{name: this.$t('test_track.plan_view.pass'), id: 'Pass'},
|
||||
{name: this.$t('test_track.plan_view.failure'), id: 'Failure'},
|
||||
{name: this.$t('test_track.plan_view.blocking'), id: 'Blocking'},
|
||||
{name: this.$t('test_track.plan_view.skip'), id: 'Skip'}
|
||||
]
|
||||
},
|
||||
editor: ClassicEditor,
|
||||
editorConfig: {
|
||||
// 'increaseIndent','decreaseIndent'
|
||||
toolbar: [],
|
||||
},
|
||||
}
|
||||
},
|
||||
props: {
|
||||
planId: {
|
||||
type: String
|
||||
export default {
|
||||
name: "TestPlanTestCaseList",
|
||||
components: {
|
||||
TestCaseReportView,
|
||||
TestReportTemplateList,
|
||||
MsTableOperatorButton,
|
||||
MsTableOperator,
|
||||
MethodTableItem,
|
||||
TypeTableItem,
|
||||
StatusTableItem,
|
||||
PriorityTableItem, StatusEdit, ExecutorEdit, MsTipButton, MsTablePagination,
|
||||
TestPlanTestCaseEdit, MsTableHeader, NodeBreadcrumb, MsTableButton, ShowMoreBtn,
|
||||
BatchEdit
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
result: {},
|
||||
deletePath: "/test/case/delete",
|
||||
condition: {
|
||||
components: TEST_CASE_CONFIGS
|
||||
},
|
||||
selectNodeIds: {
|
||||
type: Array
|
||||
showMyTestCase: false,
|
||||
tableData: [],
|
||||
currentPage: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
selectRows: new Set(),
|
||||
testPlan: {},
|
||||
isReadOnly: false,
|
||||
isTestManagerOrTestUser: false,
|
||||
priorityFilters: [
|
||||
{text: 'P0', value: 'P0'},
|
||||
{text: 'P1', value: 'P1'},
|
||||
{text: 'P2', value: 'P2'},
|
||||
{text: 'P3', value: 'P3'}
|
||||
],
|
||||
methodFilters: [
|
||||
{text: this.$t('test_track.case.manual'), value: 'manual'},
|
||||
{text: this.$t('test_track.case.auto'), value: 'auto'}
|
||||
],
|
||||
typeFilters: [
|
||||
{text: this.$t('commons.functional'), value: 'functional'},
|
||||
{text: this.$t('commons.performance'), value: 'performance'},
|
||||
{text: this.$t('commons.api'), value: 'api'}
|
||||
],
|
||||
statusFilters: [
|
||||
{text: this.$t('test_track.plan.plan_status_prepare'), value: 'Prepare'},
|
||||
{text: this.$t('test_track.plan_view.pass'), value: 'Pass'},
|
||||
{text: this.$t('test_track.plan_view.failure'), value: 'Failure'},
|
||||
{text: this.$t('test_track.plan_view.blocking'), value: 'Blocking'},
|
||||
{text: this.$t('test_track.plan_view.skip'), value: 'Skip'},
|
||||
{text: this.$t('test_track.plan.plan_status_running'), value: 'Underway'},
|
||||
],
|
||||
executorFilters: [],
|
||||
showMore: false,
|
||||
buttons: [
|
||||
{
|
||||
name: this.$t('test_track.case.batch_edit_case'), handleClick: this.handleBatchEdit
|
||||
},
|
||||
{
|
||||
name: this.$t('test_track.case.batch_unlink'), handleClick: this.handleDeleteBatch
|
||||
}
|
||||
],
|
||||
typeArr: [
|
||||
{id: 'status', name: this.$t('test_track.plan_view.execute_result')},
|
||||
{id: 'executor', name: this.$t('test_track.plan_view.executor')},
|
||||
],
|
||||
valueArr: {
|
||||
executor: [],
|
||||
status: [
|
||||
{name: this.$t('test_track.plan_view.pass'), id: 'Pass'},
|
||||
{name: this.$t('test_track.plan_view.failure'), id: 'Failure'},
|
||||
{name: this.$t('test_track.plan_view.blocking'), id: 'Blocking'},
|
||||
{name: this.$t('test_track.plan_view.skip'), id: 'Skip'}
|
||||
]
|
||||
},
|
||||
selectParentNodes: {
|
||||
type: Array
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
planId() {
|
||||
this.refreshTableAndPlan();
|
||||
editor: ClassicEditor,
|
||||
editorConfig: {
|
||||
// 'increaseIndent','decreaseIndent'
|
||||
toolbar: [],
|
||||
},
|
||||
selectNodeIds() {
|
||||
this.search();
|
||||
}
|
||||
}
|
||||
},
|
||||
props: {
|
||||
planId: {
|
||||
type: String
|
||||
},
|
||||
mounted() {
|
||||
hub.$on("openFailureTestCase", row => {
|
||||
this.isReadOnly = true;
|
||||
this.condition.status = 'Failure';
|
||||
this.$refs.testPlanTestCaseEdit.openTestCaseEdit(row);
|
||||
});
|
||||
selectNodeIds: {
|
||||
type: Array
|
||||
},
|
||||
selectParentNodes: {
|
||||
type: Array
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
planId() {
|
||||
this.refreshTableAndPlan();
|
||||
this.isTestManagerOrTestUser = checkoutTestManagerOrTestUser();
|
||||
},
|
||||
beforeDestroy() {
|
||||
hub.$off("openFailureTestCase");
|
||||
},
|
||||
methods: {
|
||||
initTableData() {
|
||||
if (this.planId) {
|
||||
// param.planId = this.planId;
|
||||
this.condition.planId = this.planId;
|
||||
}
|
||||
if (this.selectNodeIds && this.selectNodeIds.length > 0) {
|
||||
// param.nodeIds = this.selectNodeIds;
|
||||
this.condition.nodeIds = this.selectNodeIds;
|
||||
}
|
||||
if (this.planId) {
|
||||
this.result = this.$post(this.buildPagePath('/test/plan/case/list'), this.condition, response => {
|
||||
let data = response.data;
|
||||
this.total = data.itemCount;
|
||||
this.tableData = data.listObject;
|
||||
for (let i = 0; i < this.tableData.length; i++) {
|
||||
if (this.tableData[i]) {
|
||||
this.$set(this.tableData[i], "issuesSize", 0);
|
||||
this.$get("/issues/get/" + this.tableData[i].caseId, response => {
|
||||
let issues = response.data;
|
||||
if (this.tableData[i]) {
|
||||
this.$set(this.tableData[i], "issuesSize", issues.length);
|
||||
this.$set(this.tableData[i], "issuesContent", issues);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
this.selectRows.clear();
|
||||
});
|
||||
}
|
||||
},
|
||||
showDetail(row, event, column) {
|
||||
this.isReadOnly = true;
|
||||
this.$refs.testPlanTestCaseEdit.openTestCaseEdit(row);
|
||||
},
|
||||
refresh() {
|
||||
this.condition = {components: TEST_CASE_CONFIGS};
|
||||
this.selectRows.clear();
|
||||
this.$emit('refresh');
|
||||
},
|
||||
refreshTableAndPlan() {
|
||||
this.getTestPlanById();
|
||||
this.initTableData();
|
||||
},
|
||||
refreshTestPlanRecent() {
|
||||
if (hasRoles(ROLE_TEST_USER, ROLE_TEST_MANAGER)) {
|
||||
let param = {};
|
||||
param.id = this.planId;
|
||||
param.updateTime = Date.now();
|
||||
this.$post('/test/plan/edit', param);
|
||||
}
|
||||
},
|
||||
search() {
|
||||
this.initTableData();
|
||||
},
|
||||
buildPagePath(path) {
|
||||
return path + "/" + this.currentPage + "/" + this.pageSize;
|
||||
},
|
||||
handleEdit(testCase, index) {
|
||||
this.isReadOnly = false;
|
||||
if (!checkoutTestManagerOrTestUser()) {
|
||||
this.isReadOnly = true;
|
||||
}
|
||||
this.$refs.testPlanTestCaseEdit.openTestCaseEdit(testCase);
|
||||
},
|
||||
handleDelete(testCase) {
|
||||
this.$alert(this.$t('test_track.plan_view.confirm_cancel_relevance') + ' ' + testCase.name + " ?", '', {
|
||||
confirmButtonText: this.$t('commons.confirm'),
|
||||
callback: (action) => {
|
||||
if (action === 'confirm') {
|
||||
this._handleDelete(testCase);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
handleDeleteBatch() {
|
||||
if (this.tableData.length < 1) {
|
||||
this.$warning(this.$t('test_track.plan_view.no_case_relevance'));
|
||||
return;
|
||||
}
|
||||
this.$alert(this.$t('test_track.plan_view.confirm_cancel_relevance') + " ?", '', {
|
||||
confirmButtonText: this.$t('commons.confirm'),
|
||||
callback: (action) => {
|
||||
if (action === 'confirm') {
|
||||
if (this.selectRows.size > 0) {
|
||||
let ids = Array.from(this.selectRows).map(row => row.id);
|
||||
this._handleBatchDelete(ids);
|
||||
} else {
|
||||
if (this.planId) {
|
||||
this.condition.planId = this.planId;
|
||||
}
|
||||
if (this.selectNodeIds && this.selectNodeIds.length > 0) {
|
||||
this.condition.nodeIds = this.selectNodeIds;
|
||||
}
|
||||
// 根据条件查询计划下所有的关联用例
|
||||
this.$post('/test/plan/case/list/all', this.condition, res => {
|
||||
let data = res.data;
|
||||
let ids = data.map(d => d.id);
|
||||
this._handleBatchDelete(ids);
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
_handleBatchDelete(ids) {
|
||||
this.result = this.$post('/test/plan/case/batch/delete', {ids:ids}, () => {
|
||||
this.selectRows.clear();
|
||||
this.$emit("refresh");
|
||||
this.$success(this.$t('test_track.cancel_relevance_success'));
|
||||
});
|
||||
},
|
||||
_handleDelete(testCase) {
|
||||
let testCaseId = testCase.id;
|
||||
this.result = this.$post('/test/plan/case/delete/' + testCaseId, {}, () => {
|
||||
this.$emit("refresh");
|
||||
this.$success(this.$t('test_track.cancel_relevance_success'));
|
||||
});
|
||||
},
|
||||
handleSelectAll(selection) {
|
||||
if (selection.length > 0) {
|
||||
this.tableData.forEach(item => {
|
||||
this.$set(item, "showMore", true);
|
||||
this.selectRows.add(item);
|
||||
});
|
||||
} else {
|
||||
this.selectRows.clear();
|
||||
this.tableData.forEach(row => {
|
||||
this.$set(row, "showMore", false);
|
||||
})
|
||||
}
|
||||
},
|
||||
handleSelectionChange(selection, row) {
|
||||
if (this.selectRows.has(row)) {
|
||||
this.$set(row, "showMore", false);
|
||||
this.selectRows.delete(row);
|
||||
} else {
|
||||
this.$set(row, "showMore", true);
|
||||
this.selectRows.add(row);
|
||||
}
|
||||
},
|
||||
handleBatch(type) {
|
||||
if (this.selectRows.size < 1) {
|
||||
this.$warning(this.$t('test_track.plan_view.select_manipulate'));
|
||||
return;
|
||||
}
|
||||
if (type === 'executor') {
|
||||
this.$refs.executorEdit.openExecutorEdit();
|
||||
} else if (type === 'status') {
|
||||
this.$refs.statusEdit.openStatusEdit();
|
||||
} else if (type === 'delete') {
|
||||
this.handleDeleteBatch();
|
||||
}
|
||||
},
|
||||
searchMyTestCase() {
|
||||
this.showMyTestCase = !this.showMyTestCase;
|
||||
if (this.showMyTestCase) {
|
||||
let user = JSON.parse(localStorage.getItem(TokenKey));
|
||||
this.condition.executor = user.id;
|
||||
} else {
|
||||
this.condition.executor = null;
|
||||
}
|
||||
this.initTableData();
|
||||
},
|
||||
openTestReport() {
|
||||
this.$refs.testReportTemplateList.open(this.planId);
|
||||
},
|
||||
statusChange(param) {
|
||||
this.$post('/test/plan/case/edit', param, () => {
|
||||
selectNodeIds() {
|
||||
this.search();
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
hub.$on("openFailureTestCase", row => {
|
||||
this.isReadOnly = true;
|
||||
this.condition.status = 'Failure';
|
||||
this.$refs.testPlanTestCaseEdit.openTestCaseEdit(row);
|
||||
});
|
||||
this.refreshTableAndPlan();
|
||||
this.isTestManagerOrTestUser = checkoutTestManagerOrTestUser();
|
||||
this.result = this.$get('user/list', response => {
|
||||
this.executorFilters = response.data.map(u => {
|
||||
return {text: u.name, value: u.id}
|
||||
});
|
||||
});
|
||||
},
|
||||
beforeDestroy() {
|
||||
hub.$off("openFailureTestCase");
|
||||
},
|
||||
methods: {
|
||||
initTableData() {
|
||||
if (this.planId) {
|
||||
// param.planId = this.planId;
|
||||
this.condition.planId = this.planId;
|
||||
}
|
||||
if (this.selectNodeIds && this.selectNodeIds.length > 0) {
|
||||
// param.nodeIds = this.selectNodeIds;
|
||||
this.condition.nodeIds = this.selectNodeIds;
|
||||
}
|
||||
if (this.planId) {
|
||||
this.result = this.$post(this.buildPagePath('/test/plan/case/list'), this.condition, response => {
|
||||
let data = response.data;
|
||||
this.total = data.itemCount;
|
||||
this.tableData = data.listObject;
|
||||
for (let i = 0; i < this.tableData.length; i++) {
|
||||
if (this.tableData[i].id == param.id) {
|
||||
this.tableData[i].status = param.status;
|
||||
break;
|
||||
if (this.tableData[i]) {
|
||||
this.$set(this.tableData[i], "issuesSize", 0);
|
||||
this.$get("/issues/get/" + this.tableData[i].caseId, response => {
|
||||
let issues = response.data;
|
||||
if (this.tableData[i]) {
|
||||
this.$set(this.tableData[i], "issuesSize", issues.length);
|
||||
this.$set(this.tableData[i], "issuesContent", issues);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
getTestPlanById() {
|
||||
if (this.planId) {
|
||||
this.$post('/test/plan/get/' + this.planId, {}, response => {
|
||||
this.testPlan = response.data;
|
||||
this.refreshTestPlanRecent();
|
||||
});
|
||||
}
|
||||
},
|
||||
openReport(planId, id) {
|
||||
this.getTestPlanById();
|
||||
if (!id) {
|
||||
id = this.testPlan.reportId;
|
||||
}
|
||||
if (!planId) {
|
||||
planId = this.planId;
|
||||
}
|
||||
this.$refs.testCaseReportView.open(planId, id);
|
||||
},
|
||||
filter(filters) {
|
||||
_filter(filters, this.condition);
|
||||
this.initTableData();
|
||||
},
|
||||
sort(column) {
|
||||
// 每次只对一个字段排序
|
||||
if (this.condition.orders) {
|
||||
this.condition.orders = [];
|
||||
}
|
||||
_sort(column, this.condition);
|
||||
this.initTableData();
|
||||
},
|
||||
batchEdit(form) {
|
||||
let param = {};
|
||||
param[form.type] = form.value;
|
||||
param.ids = Array.from(this.selectRows).map(row => row.id);
|
||||
this.$post('/test/plan/case/batch/edit', param, () => {
|
||||
this.selectRows.clear();
|
||||
this.status = '';
|
||||
this.$post('/test/plan/edit/status/' + this.planId);
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
this.$emit('refresh');
|
||||
});
|
||||
},
|
||||
handleBatchEdit() {
|
||||
this.getMaintainerOptions();
|
||||
this.$refs.batchEdit.open();
|
||||
},
|
||||
getMaintainerOptions() {
|
||||
let workspaceId = localStorage.getItem(WORKSPACE_ID);
|
||||
this.$post('/user/ws/member/tester/list', {workspaceId: workspaceId}, response => {
|
||||
this.valueArr.executor = response.data;
|
||||
});
|
||||
}
|
||||
},
|
||||
showDetail(row, event, column) {
|
||||
this.isReadOnly = true;
|
||||
this.$refs.testPlanTestCaseEdit.openTestCaseEdit(row);
|
||||
},
|
||||
refresh() {
|
||||
this.condition = {components: TEST_CASE_CONFIGS};
|
||||
this.selectRows.clear();
|
||||
this.$emit('refresh');
|
||||
},
|
||||
refreshTableAndPlan() {
|
||||
this.getTestPlanById();
|
||||
this.initTableData();
|
||||
},
|
||||
refreshTestPlanRecent() {
|
||||
if (hasRoles(ROLE_TEST_USER, ROLE_TEST_MANAGER)) {
|
||||
let param = {};
|
||||
param.id = this.planId;
|
||||
param.updateTime = Date.now();
|
||||
this.$post('/test/plan/edit', param);
|
||||
}
|
||||
},
|
||||
search() {
|
||||
this.initTableData();
|
||||
},
|
||||
buildPagePath(path) {
|
||||
return path + "/" + this.currentPage + "/" + this.pageSize;
|
||||
},
|
||||
handleEdit(testCase, index) {
|
||||
this.isReadOnly = false;
|
||||
if (!checkoutTestManagerOrTestUser()) {
|
||||
this.isReadOnly = true;
|
||||
}
|
||||
this.$refs.testPlanTestCaseEdit.openTestCaseEdit(testCase);
|
||||
},
|
||||
handleDelete(testCase) {
|
||||
this.$alert(this.$t('test_track.plan_view.confirm_cancel_relevance') + ' ' + testCase.name + " ?", '', {
|
||||
confirmButtonText: this.$t('commons.confirm'),
|
||||
callback: (action) => {
|
||||
if (action === 'confirm') {
|
||||
this._handleDelete(testCase);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
handleDeleteBatch() {
|
||||
if (this.tableData.length < 1) {
|
||||
this.$warning(this.$t('test_track.plan_view.no_case_relevance'));
|
||||
return;
|
||||
}
|
||||
this.$alert(this.$t('test_track.plan_view.confirm_cancel_relevance') + " ?", '', {
|
||||
confirmButtonText: this.$t('commons.confirm'),
|
||||
callback: (action) => {
|
||||
if (action === 'confirm') {
|
||||
if (this.selectRows.size > 0) {
|
||||
let ids = Array.from(this.selectRows).map(row => row.id);
|
||||
this._handleBatchDelete(ids);
|
||||
} else {
|
||||
if (this.planId) {
|
||||
this.condition.planId = this.planId;
|
||||
}
|
||||
if (this.selectNodeIds && this.selectNodeIds.length > 0) {
|
||||
this.condition.nodeIds = this.selectNodeIds;
|
||||
}
|
||||
// 根据条件查询计划下所有的关联用例
|
||||
this.$post('/test/plan/case/list/all', this.condition, res => {
|
||||
let data = res.data;
|
||||
let ids = data.map(d => d.id);
|
||||
this._handleBatchDelete(ids);
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
_handleBatchDelete(ids) {
|
||||
this.result = this.$post('/test/plan/case/batch/delete', {ids: ids}, () => {
|
||||
this.selectRows.clear();
|
||||
this.$emit("refresh");
|
||||
this.$success(this.$t('test_track.cancel_relevance_success'));
|
||||
});
|
||||
},
|
||||
_handleDelete(testCase) {
|
||||
let testCaseId = testCase.id;
|
||||
this.result = this.$post('/test/plan/case/delete/' + testCaseId, {}, () => {
|
||||
this.$emit("refresh");
|
||||
this.$success(this.$t('test_track.cancel_relevance_success'));
|
||||
});
|
||||
},
|
||||
handleSelectAll(selection) {
|
||||
if (selection.length > 0) {
|
||||
this.tableData.forEach(item => {
|
||||
this.$set(item, "showMore", true);
|
||||
this.selectRows.add(item);
|
||||
});
|
||||
} else {
|
||||
this.selectRows.clear();
|
||||
this.tableData.forEach(row => {
|
||||
this.$set(row, "showMore", false);
|
||||
})
|
||||
}
|
||||
},
|
||||
handleSelectionChange(selection, row) {
|
||||
if (this.selectRows.has(row)) {
|
||||
this.$set(row, "showMore", false);
|
||||
this.selectRows.delete(row);
|
||||
} else {
|
||||
this.$set(row, "showMore", true);
|
||||
this.selectRows.add(row);
|
||||
}
|
||||
},
|
||||
handleBatch(type) {
|
||||
if (this.selectRows.size < 1) {
|
||||
this.$warning(this.$t('test_track.plan_view.select_manipulate'));
|
||||
return;
|
||||
}
|
||||
if (type === 'executor') {
|
||||
this.$refs.executorEdit.openExecutorEdit();
|
||||
} else if (type === 'status') {
|
||||
this.$refs.statusEdit.openStatusEdit();
|
||||
} else if (type === 'delete') {
|
||||
this.handleDeleteBatch();
|
||||
}
|
||||
},
|
||||
searchMyTestCase() {
|
||||
this.showMyTestCase = !this.showMyTestCase;
|
||||
if (this.showMyTestCase) {
|
||||
let user = JSON.parse(localStorage.getItem(TokenKey));
|
||||
this.condition.executor = user.id;
|
||||
} else {
|
||||
this.condition.executor = null;
|
||||
}
|
||||
this.initTableData();
|
||||
},
|
||||
openTestReport() {
|
||||
this.$refs.testReportTemplateList.open(this.planId);
|
||||
},
|
||||
statusChange(param) {
|
||||
this.$post('/test/plan/case/edit', param, () => {
|
||||
for (let i = 0; i < this.tableData.length; i++) {
|
||||
if (this.tableData[i].id == param.id) {
|
||||
this.tableData[i].status = param.status;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
getTestPlanById() {
|
||||
if (this.planId) {
|
||||
this.$post('/test/plan/get/' + this.planId, {}, response => {
|
||||
this.testPlan = response.data;
|
||||
this.refreshTestPlanRecent();
|
||||
});
|
||||
}
|
||||
},
|
||||
openReport(planId, id) {
|
||||
this.getTestPlanById();
|
||||
if (!id) {
|
||||
id = this.testPlan.reportId;
|
||||
}
|
||||
if (!planId) {
|
||||
planId = this.planId;
|
||||
}
|
||||
this.$refs.testCaseReportView.open(planId, id);
|
||||
},
|
||||
filter(filters) {
|
||||
_filter(filters, this.condition);
|
||||
this.initTableData();
|
||||
},
|
||||
sort(column) {
|
||||
// 每次只对一个字段排序
|
||||
if (this.condition.orders) {
|
||||
this.condition.orders = [];
|
||||
}
|
||||
_sort(column, this.condition);
|
||||
this.initTableData();
|
||||
},
|
||||
batchEdit(form) {
|
||||
let param = {};
|
||||
param[form.type] = form.value;
|
||||
param.ids = Array.from(this.selectRows).map(row => row.id);
|
||||
this.$post('/test/plan/case/batch/edit', param, () => {
|
||||
this.selectRows.clear();
|
||||
this.status = '';
|
||||
this.$post('/test/plan/edit/status/' + this.planId);
|
||||
this.$success(this.$t('commons.save_success'));
|
||||
this.$emit('refresh');
|
||||
});
|
||||
},
|
||||
handleBatchEdit() {
|
||||
this.getMaintainerOptions();
|
||||
this.$refs.batchEdit.open();
|
||||
},
|
||||
getMaintainerOptions() {
|
||||
let workspaceId = localStorage.getItem(WORKSPACE_ID);
|
||||
this.$post('/user/ws/member/tester/list', {workspaceId: workspaceId}, response => {
|
||||
this.valueArr.executor = response.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.search {
|
||||
margin-left: 10px;
|
||||
width: 240px;
|
||||
}
|
||||
.search {
|
||||
margin-left: 10px;
|
||||
width: 240px;
|
||||
}
|
||||
|
||||
.test-case-status, .el-table {
|
||||
cursor: pointer;
|
||||
}
|
||||
.test-case-status, .el-table {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -61,7 +61,7 @@ export default {
|
|||
window.console.error(error.response || error.message);
|
||||
if (error.response && error.response.data) {
|
||||
if (error.response.headers["authentication-status"] !== "invalid") {
|
||||
Message.error({message: error.response.data.message, showClose: true});
|
||||
Message.error({message: error.response.data.message || error.response.data, showClose: true});
|
||||
}
|
||||
} else {
|
||||
Message.error({message: error.message, showClose: true});
|
||||
|
|
Loading…
Reference in New Issue