Merge branch 'dev' of https://github.com/fit2cloudrd/metersphere-server into dev
This commit is contained in:
commit
78a325b75b
|
@ -57,6 +57,11 @@
|
|||
<artifactId>spring-boot-starter-jetty</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mybatis.spring.boot</groupId>
|
||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
package io.metersphere.api.controller;
|
||||
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import io.metersphere.api.dto.APITestResult;
|
||||
import io.metersphere.api.dto.DeleteAPITestRequest;
|
||||
import io.metersphere.api.dto.QueryAPITestRequest;
|
||||
import io.metersphere.api.dto.SaveAPITestRequest;
|
||||
import io.metersphere.api.service.ApiTestService;
|
||||
import io.metersphere.base.domain.ApiTestWithBLOBs;
|
||||
import io.metersphere.commons.constants.RoleConstants;
|
||||
import io.metersphere.commons.utils.PageUtils;
|
||||
import io.metersphere.commons.utils.Pager;
|
||||
import io.metersphere.service.FileService;
|
||||
import io.metersphere.user.SessionUtils;
|
||||
import org.apache.shiro.authz.annotation.Logical;
|
||||
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@RestController
|
||||
@RequestMapping(value = "/api")
|
||||
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER, RoleConstants.TEST_VIEWER}, logical = Logical.OR)
|
||||
public class APITestController {
|
||||
@Resource
|
||||
private ApiTestService apiTestService;
|
||||
@Resource
|
||||
private FileService fileService;
|
||||
|
||||
@GetMapping("recent/{count}")
|
||||
public List<APITestResult> recentTest(@PathVariable int count) {
|
||||
String currentWorkspaceId = SessionUtils.getCurrentWorkspaceId();
|
||||
QueryAPITestRequest request = new QueryAPITestRequest();
|
||||
request.setWorkspaceId(currentWorkspaceId);
|
||||
PageHelper.startPage(1, count, true);
|
||||
return apiTestService.recentTest(request);
|
||||
}
|
||||
|
||||
@PostMapping("/list/{goPage}/{pageSize}")
|
||||
public Pager<List<APITestResult>> list(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryAPITestRequest request) {
|
||||
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
|
||||
request.setWorkspaceId(SessionUtils.getCurrentWorkspaceId());
|
||||
return PageUtils.setPageInfo(page, apiTestService.list(request));
|
||||
}
|
||||
|
||||
@PostMapping(value = "/save")
|
||||
public String save(@RequestBody SaveAPITestRequest request) {
|
||||
return apiTestService.save(request);
|
||||
}
|
||||
|
||||
@GetMapping("/get/{testId}")
|
||||
public ApiTestWithBLOBs get(@PathVariable String testId) {
|
||||
return apiTestService.get(testId);
|
||||
}
|
||||
|
||||
@PostMapping("/delete")
|
||||
public void delete(@RequestBody DeleteAPITestRequest request) {
|
||||
apiTestService.delete(request);
|
||||
}
|
||||
//
|
||||
// @PostMapping("/run")
|
||||
// public void run(@RequestBody RunTestPlanRequest request) {
|
||||
// apiTestService.run(request);
|
||||
// }
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package io.metersphere.api.dto;
|
||||
|
||||
import io.metersphere.base.domain.ApiTestWithBLOBs;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
public class APITestResult extends ApiTestWithBLOBs {
|
||||
|
||||
private String projectName;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package io.metersphere.api.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
public class DeleteAPITestRequest {
|
||||
|
||||
private String id;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package io.metersphere.api.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class QueryAPITestRequest {
|
||||
|
||||
private String id;
|
||||
private String projectId;
|
||||
private String name;
|
||||
private String workspaceId;
|
||||
private boolean recent = false;
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package io.metersphere.api.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
public class SaveAPITestRequest {
|
||||
|
||||
private String id;
|
||||
|
||||
private String projectId;
|
||||
|
||||
private String name;
|
||||
|
||||
private String scenarioDefinition;
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
package io.metersphere.api.service;
|
||||
|
||||
import io.metersphere.api.dto.APITestResult;
|
||||
import io.metersphere.api.dto.DeleteAPITestRequest;
|
||||
import io.metersphere.api.dto.QueryAPITestRequest;
|
||||
import io.metersphere.api.dto.SaveAPITestRequest;
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.mapper.*;
|
||||
import io.metersphere.base.mapper.ext.ExtApiTestMapper;
|
||||
import io.metersphere.commons.constants.APITestStatus;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.i18n.Translator;
|
||||
import io.metersphere.service.FileService;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class ApiTestService {
|
||||
|
||||
@Resource
|
||||
private ApiTestMapper apiTestMapper;
|
||||
@Resource
|
||||
private ExtApiTestMapper extApiTestMapper;
|
||||
@Resource
|
||||
private ProjectMapper projectMapper;
|
||||
@Resource
|
||||
private FileMetadataMapper fileMetadataMapper;
|
||||
@Resource
|
||||
private FileContentMapper fileContentMapper;
|
||||
@Resource
|
||||
private ApiTestFileMapper apiTestFileMapper;
|
||||
@Resource
|
||||
private FileService fileService;
|
||||
|
||||
public List<APITestResult> list(QueryAPITestRequest request) {
|
||||
return extApiTestMapper.list(request);
|
||||
}
|
||||
|
||||
public List<APITestResult> recentTest(QueryAPITestRequest request) {
|
||||
request.setRecent(true);
|
||||
return extApiTestMapper.list(request);
|
||||
}
|
||||
|
||||
public String save(SaveAPITestRequest request) {
|
||||
final ApiTestWithBLOBs test;
|
||||
if (StringUtils.isNotBlank(request.getId())) {
|
||||
test = updateTest(request);
|
||||
} else {
|
||||
test = createTest(request);
|
||||
}
|
||||
return test.getId();
|
||||
}
|
||||
|
||||
public ApiTestWithBLOBs get(String id) {
|
||||
return apiTestMapper.selectByPrimaryKey(id);
|
||||
}
|
||||
|
||||
public void delete(DeleteAPITestRequest request) {
|
||||
apiTestMapper.deleteByPrimaryKey(request.getId());
|
||||
}
|
||||
|
||||
private ApiTestWithBLOBs updateTest(SaveAPITestRequest request) {
|
||||
final ApiTestWithBLOBs test = new ApiTestWithBLOBs();
|
||||
test.setId(request.getId());
|
||||
test.setName(request.getName());
|
||||
test.setProjectId(request.getProjectId());
|
||||
test.setScenarioDefinition(request.getScenarioDefinition());
|
||||
test.setUpdateTime(System.currentTimeMillis());
|
||||
test.setStatus(APITestStatus.Saved.name());
|
||||
apiTestMapper.updateByPrimaryKeySelective(test);
|
||||
return test;
|
||||
}
|
||||
|
||||
private ApiTestWithBLOBs createTest(SaveAPITestRequest request) {
|
||||
ApiTestExample example = new ApiTestExample();
|
||||
example.createCriteria().andNameEqualTo(request.getName()).andProjectIdEqualTo(request.getProjectId());
|
||||
if (apiTestMapper.countByExample(example) > 0) {
|
||||
MSException.throwException(Translator.get("load_test_already_exists"));
|
||||
}
|
||||
|
||||
final ApiTestWithBLOBs test = new ApiTestWithBLOBs();
|
||||
test.setId(UUID.randomUUID().toString());
|
||||
test.setName(request.getName());
|
||||
test.setProjectId(request.getProjectId());
|
||||
test.setScenarioDefinition(request.getScenarioDefinition());
|
||||
test.setCreateTime(System.currentTimeMillis());
|
||||
test.setUpdateTime(System.currentTimeMillis());
|
||||
test.setStatus(APITestStatus.Saved.name());
|
||||
apiTestMapper.insert(test);
|
||||
return test;
|
||||
}
|
||||
|
||||
}
|
|
@ -11,6 +11,8 @@ public class ApiTest implements Serializable {
|
|||
|
||||
private String description;
|
||||
|
||||
private String status;
|
||||
|
||||
private Long createTime;
|
||||
|
||||
private Long updateTime;
|
||||
|
@ -49,6 +51,14 @@ public class ApiTest implements Serializable {
|
|||
this.description = description == null ? null : description.trim();
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status == null ? null : status.trim();
|
||||
}
|
||||
|
||||
public Long getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
|
|
@ -384,6 +384,76 @@ public class ApiTestExample {
|
|||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andStatusIsNull() {
|
||||
addCriterion("status is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andStatusIsNotNull() {
|
||||
addCriterion("status is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andStatusEqualTo(String value) {
|
||||
addCriterion("status =", value, "status");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andStatusNotEqualTo(String value) {
|
||||
addCriterion("status <>", value, "status");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andStatusGreaterThan(String value) {
|
||||
addCriterion("status >", value, "status");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andStatusGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("status >=", value, "status");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andStatusLessThan(String value) {
|
||||
addCriterion("status <", value, "status");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andStatusLessThanOrEqualTo(String value) {
|
||||
addCriterion("status <=", value, "status");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andStatusLike(String value) {
|
||||
addCriterion("status like", value, "status");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andStatusNotLike(String value) {
|
||||
addCriterion("status not like", value, "status");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andStatusIn(List<String> values) {
|
||||
addCriterion("status in", values, "status");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andStatusNotIn(List<String> values) {
|
||||
addCriterion("status not in", values, "status");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andStatusBetween(String value1, String value2) {
|
||||
addCriterion("status between", value1, value2, "status");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andStatusNotBetween(String value1, String value2) {
|
||||
addCriterion("status not between", value1, value2, "status");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCreateTimeIsNull() {
|
||||
addCriterion("create_time is null");
|
||||
return (Criteria) this;
|
||||
|
|
|
@ -3,18 +3,18 @@ package io.metersphere.base.domain;
|
|||
import java.io.Serializable;
|
||||
|
||||
public class ApiTestWithBLOBs extends ApiTest implements Serializable {
|
||||
private String runtimeConfiguration;
|
||||
private String scenarioDefinition;
|
||||
|
||||
private String schedule;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public String getRuntimeConfiguration() {
|
||||
return runtimeConfiguration;
|
||||
public String getScenarioDefinition() {
|
||||
return scenarioDefinition;
|
||||
}
|
||||
|
||||
public void setRuntimeConfiguration(String runtimeConfiguration) {
|
||||
this.runtimeConfiguration = runtimeConfiguration == null ? null : runtimeConfiguration.trim();
|
||||
public void setScenarioDefinition(String scenarioDefinition) {
|
||||
this.scenarioDefinition = scenarioDefinition == null ? null : scenarioDefinition.trim();
|
||||
}
|
||||
|
||||
public String getSchedule() {
|
||||
|
|
|
@ -6,11 +6,12 @@
|
|||
<result column="project_id" jdbcType="VARCHAR" property="projectId" />
|
||||
<result column="name" jdbcType="VARCHAR" property="name" />
|
||||
<result column="description" jdbcType="VARCHAR" property="description" />
|
||||
<result column="status" jdbcType="VARCHAR" property="status" />
|
||||
<result column="create_time" jdbcType="BIGINT" property="createTime" />
|
||||
<result column="update_time" jdbcType="BIGINT" property="updateTime" />
|
||||
</resultMap>
|
||||
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.ApiTestWithBLOBs">
|
||||
<result column="runtime_configuration" jdbcType="LONGVARCHAR" property="runtimeConfiguration" />
|
||||
<result column="scenario_definition" jdbcType="LONGVARCHAR" property="scenarioDefinition" />
|
||||
<result column="schedule" jdbcType="LONGVARCHAR" property="schedule" />
|
||||
</resultMap>
|
||||
<sql id="Example_Where_Clause">
|
||||
|
@ -72,10 +73,10 @@
|
|||
</where>
|
||||
</sql>
|
||||
<sql id="Base_Column_List">
|
||||
id, project_id, name, description, create_time, update_time
|
||||
id, project_id, name, description, status, create_time, update_time
|
||||
</sql>
|
||||
<sql id="Blob_Column_List">
|
||||
runtime_configuration, schedule
|
||||
scenario_definition, schedule
|
||||
</sql>
|
||||
<select id="selectByExampleWithBLOBs" parameterType="io.metersphere.base.domain.ApiTestExample" resultMap="ResultMapWithBLOBs">
|
||||
select
|
||||
|
@ -127,11 +128,13 @@
|
|||
</delete>
|
||||
<insert id="insert" parameterType="io.metersphere.base.domain.ApiTestWithBLOBs">
|
||||
insert into api_test (id, project_id, name,
|
||||
description, create_time, update_time,
|
||||
runtime_configuration, schedule)
|
||||
description, status, create_time,
|
||||
update_time, scenario_definition, schedule
|
||||
)
|
||||
values (#{id,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR},
|
||||
#{description,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
|
||||
#{runtimeConfiguration,jdbcType=LONGVARCHAR}, #{schedule,jdbcType=LONGVARCHAR})
|
||||
#{description,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT},
|
||||
#{updateTime,jdbcType=BIGINT}, #{scenarioDefinition,jdbcType=LONGVARCHAR}, #{schedule,jdbcType=LONGVARCHAR}
|
||||
)
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="io.metersphere.base.domain.ApiTestWithBLOBs">
|
||||
insert into api_test
|
||||
|
@ -148,14 +151,17 @@
|
|||
<if test="description != null">
|
||||
description,
|
||||
</if>
|
||||
<if test="status != null">
|
||||
status,
|
||||
</if>
|
||||
<if test="createTime != null">
|
||||
create_time,
|
||||
</if>
|
||||
<if test="updateTime != null">
|
||||
update_time,
|
||||
</if>
|
||||
<if test="runtimeConfiguration != null">
|
||||
runtime_configuration,
|
||||
<if test="scenarioDefinition != null">
|
||||
scenario_definition,
|
||||
</if>
|
||||
<if test="schedule != null">
|
||||
schedule,
|
||||
|
@ -174,14 +180,17 @@
|
|||
<if test="description != null">
|
||||
#{description,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="status != null">
|
||||
#{status,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="createTime != null">
|
||||
#{createTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="updateTime != null">
|
||||
#{updateTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="runtimeConfiguration != null">
|
||||
#{runtimeConfiguration,jdbcType=LONGVARCHAR},
|
||||
<if test="scenarioDefinition != null">
|
||||
#{scenarioDefinition,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
<if test="schedule != null">
|
||||
#{schedule,jdbcType=LONGVARCHAR},
|
||||
|
@ -209,14 +218,17 @@
|
|||
<if test="record.description != null">
|
||||
description = #{record.description,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.status != null">
|
||||
status = #{record.status,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.createTime != null">
|
||||
create_time = #{record.createTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="record.updateTime != null">
|
||||
update_time = #{record.updateTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="record.runtimeConfiguration != null">
|
||||
runtime_configuration = #{record.runtimeConfiguration,jdbcType=LONGVARCHAR},
|
||||
<if test="record.scenarioDefinition != null">
|
||||
scenario_definition = #{record.scenarioDefinition,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
<if test="record.schedule != null">
|
||||
schedule = #{record.schedule,jdbcType=LONGVARCHAR},
|
||||
|
@ -232,9 +244,10 @@
|
|||
project_id = #{record.projectId,jdbcType=VARCHAR},
|
||||
name = #{record.name,jdbcType=VARCHAR},
|
||||
description = #{record.description,jdbcType=VARCHAR},
|
||||
status = #{record.status,jdbcType=VARCHAR},
|
||||
create_time = #{record.createTime,jdbcType=BIGINT},
|
||||
update_time = #{record.updateTime,jdbcType=BIGINT},
|
||||
runtime_configuration = #{record.runtimeConfiguration,jdbcType=LONGVARCHAR},
|
||||
scenario_definition = #{record.scenarioDefinition,jdbcType=LONGVARCHAR},
|
||||
schedule = #{record.schedule,jdbcType=LONGVARCHAR}
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
|
@ -246,6 +259,7 @@
|
|||
project_id = #{record.projectId,jdbcType=VARCHAR},
|
||||
name = #{record.name,jdbcType=VARCHAR},
|
||||
description = #{record.description,jdbcType=VARCHAR},
|
||||
status = #{record.status,jdbcType=VARCHAR},
|
||||
create_time = #{record.createTime,jdbcType=BIGINT},
|
||||
update_time = #{record.updateTime,jdbcType=BIGINT}
|
||||
<if test="_parameter != null">
|
||||
|
@ -264,14 +278,17 @@
|
|||
<if test="description != null">
|
||||
description = #{description,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="status != null">
|
||||
status = #{status,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="createTime != null">
|
||||
create_time = #{createTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="updateTime != null">
|
||||
update_time = #{updateTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="runtimeConfiguration != null">
|
||||
runtime_configuration = #{runtimeConfiguration,jdbcType=LONGVARCHAR},
|
||||
<if test="scenarioDefinition != null">
|
||||
scenario_definition = #{scenarioDefinition,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
<if test="schedule != null">
|
||||
schedule = #{schedule,jdbcType=LONGVARCHAR},
|
||||
|
@ -284,9 +301,10 @@
|
|||
set project_id = #{projectId,jdbcType=VARCHAR},
|
||||
name = #{name,jdbcType=VARCHAR},
|
||||
description = #{description,jdbcType=VARCHAR},
|
||||
status = #{status,jdbcType=VARCHAR},
|
||||
create_time = #{createTime,jdbcType=BIGINT},
|
||||
update_time = #{updateTime,jdbcType=BIGINT},
|
||||
runtime_configuration = #{runtimeConfiguration,jdbcType=LONGVARCHAR},
|
||||
scenario_definition = #{scenarioDefinition,jdbcType=LONGVARCHAR},
|
||||
schedule = #{schedule,jdbcType=LONGVARCHAR}
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
|
@ -295,6 +313,7 @@
|
|||
set project_id = #{projectId,jdbcType=VARCHAR},
|
||||
name = #{name,jdbcType=VARCHAR},
|
||||
description = #{description,jdbcType=VARCHAR},
|
||||
status = #{status,jdbcType=VARCHAR},
|
||||
create_time = #{createTime,jdbcType=BIGINT},
|
||||
update_time = #{updateTime,jdbcType=BIGINT}
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package io.metersphere.base.mapper.ext;
|
||||
|
||||
import io.metersphere.controller.request.testplan.QueryTestPlanRequest;
|
||||
import io.metersphere.dto.ApiTestDTO;
|
||||
import io.metersphere.api.dto.APITestResult;
|
||||
import io.metersphere.api.dto.QueryAPITestRequest;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ExtApiTestMapper {
|
||||
List<ApiTestDTO> list(@Param("request") QueryTestPlanRequest params);
|
||||
List<APITestResult> list(@Param("request") QueryAPITestRequest request);
|
||||
}
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||
<mapper namespace="io.metersphere.base.mapper.ext.ExtApiTestMapper">
|
||||
|
||||
<resultMap id="BaseResultMap" type="io.metersphere.dto.ApiTestDTO"
|
||||
<resultMap id="BaseResultMap" type="io.metersphere.api.dto.APITestResult"
|
||||
extends="io.metersphere.base.mapper.ApiTestMapper.BaseResultMap">
|
||||
<result column="project_name" property="projectName"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="list" resultMap="BaseResultMap" parameterType="io.metersphere.controller.request.testplan.QueryTestPlanRequest">
|
||||
<select id="list" resultMap="BaseResultMap" parameterType="io.metersphere.api.dto.APITestResult">
|
||||
select api_test.*, project.name as project_name
|
||||
from api_test
|
||||
left join project on api_test.project_id = project.id
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
package io.metersphere.commons.constants;
|
||||
|
||||
public enum APITestStatus {
|
||||
Saved, Starting, Running, Completed, Error
|
||||
}
|
|
@ -1,99 +0,0 @@
|
|||
package io.metersphere.controller;
|
||||
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import io.metersphere.base.domain.FileMetadata;
|
||||
import io.metersphere.commons.constants.RoleConstants;
|
||||
import io.metersphere.commons.utils.PageUtils;
|
||||
import io.metersphere.commons.utils.Pager;
|
||||
import io.metersphere.controller.request.testplan.*;
|
||||
import io.metersphere.dto.ApiTestDTO;
|
||||
import io.metersphere.service.FileService;
|
||||
import io.metersphere.service.ApiTestService;
|
||||
import io.metersphere.user.SessionUtils;
|
||||
import org.apache.shiro.authz.annotation.Logical;
|
||||
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping(value = "/api")
|
||||
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER, RoleConstants.TEST_VIEWER}, logical = Logical.OR)
|
||||
public class ApiTestController {
|
||||
@Resource
|
||||
private ApiTestService apiTestService;
|
||||
@Resource
|
||||
private FileService fileService;
|
||||
|
||||
@GetMapping("recent/{count}")
|
||||
public List<ApiTestDTO> recentTestPlans(@PathVariable int count) {
|
||||
String currentWorkspaceId = SessionUtils.getCurrentWorkspaceId();
|
||||
QueryTestPlanRequest request = new QueryTestPlanRequest();
|
||||
request.setWorkspaceId(currentWorkspaceId);
|
||||
PageHelper.startPage(1, count, true);
|
||||
return apiTestService.recentTestPlans(request);
|
||||
}
|
||||
|
||||
@PostMapping("/list/{goPage}/{pageSize}")
|
||||
public Pager<List<ApiTestDTO>> list(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryTestPlanRequest request) {
|
||||
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
|
||||
request.setWorkspaceId(SessionUtils.getCurrentWorkspaceId());
|
||||
return PageUtils.setPageInfo(page, apiTestService.list(request));
|
||||
}
|
||||
|
||||
@PostMapping(value = "/save", consumes = {"multipart/form-data"})
|
||||
public String save(
|
||||
@RequestPart("request") SaveTestPlanRequest request,
|
||||
@RequestPart(value = "file") MultipartFile file
|
||||
) {
|
||||
return apiTestService.save(request, file);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/edit", consumes = {"multipart/form-data"})
|
||||
public String edit(
|
||||
@RequestPart("request") EditTestPlanRequest request,
|
||||
@RequestPart(value = "file", required = false) MultipartFile file
|
||||
) {
|
||||
return apiTestService.edit(request, file);
|
||||
}
|
||||
|
||||
@GetMapping("/get/{testId}")
|
||||
public ApiTestDTO get(@PathVariable String testId) {
|
||||
return apiTestService.get(testId);
|
||||
}
|
||||
|
||||
@GetMapping("/get-runtime-config/{testId}")
|
||||
public String getAdvancedConfiguration(@PathVariable String testId) {
|
||||
return apiTestService.getRuntimeConfiguration(testId);
|
||||
}
|
||||
|
||||
@PostMapping("/delete")
|
||||
public void delete(@RequestBody DeleteTestPlanRequest request) {
|
||||
apiTestService.delete(request);
|
||||
}
|
||||
|
||||
@PostMapping("/run")
|
||||
public void run(@RequestBody RunTestPlanRequest request) {
|
||||
apiTestService.run(request);
|
||||
}
|
||||
|
||||
@GetMapping("/file/metadata/{testId}")
|
||||
public FileMetadata getFileMetadata(@PathVariable String testId) {
|
||||
return fileService.getApiFileMetadataByTestId(testId);
|
||||
}
|
||||
|
||||
@PostMapping("/file/download")
|
||||
public ResponseEntity<byte[]> downloadJmx(@RequestBody FileOperationRequest fileOperationRequest) {
|
||||
byte[] bytes = fileService.loadFileAsBytes(fileOperationRequest.getId());
|
||||
return ResponseEntity.ok()
|
||||
.contentType(MediaType.parseMediaType("application/octet-stream"))
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileOperationRequest.getName() + "\"")
|
||||
.body(bytes);
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@ import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
|
|||
/**
|
||||
* 统一处理返回结果集
|
||||
*/
|
||||
@RestControllerAdvice(value = {"io.metersphere.controller"})
|
||||
@RestControllerAdvice(value = {"io.metersphere.controller", "io.metersphere.api.controller"})
|
||||
public class ResultResponseBodyAdvice implements ResponseBodyAdvice<Object> {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
package io.metersphere.dto;
|
||||
|
||||
import io.metersphere.base.domain.LoadTest;
|
||||
|
||||
public class ApiTestDTO extends LoadTest {
|
||||
private String projectName;
|
||||
|
||||
public String getProjectName() {
|
||||
return projectName;
|
||||
}
|
||||
|
||||
public void setProjectName(String projectName) {
|
||||
this.projectName = projectName;
|
||||
}
|
||||
}
|
|
@ -5,7 +5,6 @@ import com.opencsv.bean.CsvToBeanBuilder;
|
|||
import com.opencsv.bean.HeaderColumnNameMappingStrategy;
|
||||
import io.metersphere.report.base.*;
|
||||
import io.metersphere.report.parse.ResultDataParse;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.jmeter.report.processor.ErrorsSummaryConsumer;
|
||||
import org.apache.jmeter.report.processor.StatisticsSummaryConsumer;
|
||||
import org.apache.jmeter.report.processor.Top5ErrorsBySamplerConsumer;
|
||||
|
@ -14,6 +13,7 @@ import org.apache.jmeter.report.processor.graph.impl.HitsPerSecondGraphConsumer;
|
|||
import org.apache.jmeter.report.processor.graph.impl.ResponseTimeOverTimeGraphConsumer;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.DecimalFormat;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
|
@ -21,12 +21,9 @@ import java.time.LocalDateTime;
|
|||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class GenerateReport {
|
||||
|
||||
private static final String DATE_TIME_PATTERN = "yyyy/MM/dd HH:mm:ss";
|
||||
|
||||
private static List<Metric> resolver(String jtlString) {
|
||||
HeaderColumnNameMappingStrategy<Metric> ms = new HeaderColumnNameMappingStrategy<>();
|
||||
ms.setType(Metric.class);
|
||||
|
@ -60,71 +57,38 @@ public class GenerateReport {
|
|||
}
|
||||
|
||||
public static TestOverview getTestOverview(String jtlString) {
|
||||
TestOverview testOverview = new TestOverview();
|
||||
DecimalFormat decimalFormat = new DecimalFormat("0.00");
|
||||
|
||||
List<Metric> totalLineList = GenerateReport.resolver(jtlString);
|
||||
// todo 修改测试概览的数值
|
||||
List<Metric> totalLineList2 = GenerateReport.resolver(jtlString);
|
||||
// 时间戳转时间
|
||||
for (Metric metric : totalLineList2) {
|
||||
metric.setTimestamp(stampToDate(DATE_TIME_PATTERN, metric.getTimestamp()));
|
||||
}
|
||||
Map<String, Object> activeDataMap = ResultDataParse.getGraphDataMap(jtlString, new ActiveThreadsGraphConsumer());
|
||||
List<ChartsData> usersList = ResultDataParse.graphMapParsing(activeDataMap, "users");
|
||||
Optional<ChartsData> max = usersList.stream().max(Comparator.comparing(ChartsData::getyAxis));
|
||||
int maxUser = max.get().getyAxis().setScale(0, BigDecimal.ROUND_UP).intValue();
|
||||
|
||||
Map<String, List<Metric>> collect2 = Objects.requireNonNull(totalLineList2).stream().collect(Collectors.groupingBy(Metric::getTimestamp));
|
||||
List<Map.Entry<String, List<Metric>>> entries = new ArrayList<>(collect2.entrySet());
|
||||
int maxUsers = 0;
|
||||
for (Map.Entry<String, List<Metric>> entry : entries) {
|
||||
List<Metric> metrics = entry.getValue();
|
||||
Map<String, List<Metric>> metricsMap = metrics.stream().collect(Collectors.groupingBy(Metric::getThreadName));
|
||||
if (metricsMap.size() > maxUsers) {
|
||||
maxUsers = metricsMap.size();
|
||||
}
|
||||
}
|
||||
Map<String, Object> hitsDataMap = ResultDataParse.getGraphDataMap(jtlString, new HitsPerSecondGraphConsumer());
|
||||
List<ChartsData> hitsList = ResultDataParse.graphMapParsing(hitsDataMap, "hits");
|
||||
double hits = hitsList.stream().map(ChartsData::getyAxis)
|
||||
.mapToDouble(BigDecimal::doubleValue)
|
||||
.average().orElse(0);
|
||||
|
||||
Map<String, List<Metric>> collect = totalLineList.stream().collect(Collectors.groupingBy(Metric::getTimestamp));
|
||||
Iterator<Map.Entry<String, List<Metric>>> iterator = collect.entrySet().iterator();
|
||||
Map<String, Object> errorDataMap = ResultDataParse.getSummryDataMap(jtlString, new StatisticsSummaryConsumer());
|
||||
List<Statistics> statisticsList = ResultDataParse.summaryMapParsing(errorDataMap, Statistics.class);
|
||||
Optional<Double> error = statisticsList.stream().map(item -> Double.parseDouble(item.getError())).reduce(Double::sum);
|
||||
|
||||
int totalElapsed = 0;
|
||||
float totalBytes = 0f;
|
||||
Map<String, Object> responseDataMap = ResultDataParse.getGraphDataMap(jtlString, new ResponseTimeOverTimeGraphConsumer());
|
||||
List<ChartsData> responseDataList = ResultDataParse.graphMapParsing(responseDataMap, "response");
|
||||
double responseTime = responseDataList.stream().map(ChartsData::getyAxis)
|
||||
.mapToDouble(BigDecimal::doubleValue)
|
||||
.average().orElse(0);
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<String, List<Metric>> entry = iterator.next();
|
||||
List<Metric> metricList = entry.getValue();
|
||||
|
||||
for (Metric metric : metricList) {
|
||||
String elapsed = metric.getElapsed();
|
||||
totalElapsed += Integer.parseInt(elapsed);
|
||||
String bytes = metric.getBytes();
|
||||
totalBytes += Float.parseFloat(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
totalLineList.sort(Comparator.comparing(t0 -> Long.valueOf(t0.getTimestamp())));
|
||||
|
||||
testOverview.setMaxUsers(String.valueOf(maxUsers));
|
||||
|
||||
List<Metric> list90 = totalLineList.subList(0, totalLineList.size() * 9 / 10);
|
||||
long sum = list90.stream().mapToLong(metric -> Long.parseLong(metric.getElapsed())).sum();
|
||||
double avg90 = (double) sum / 1000 / list90.size();
|
||||
testOverview.setResponseTime90(decimalFormat.format(avg90));
|
||||
|
||||
long timesStampStart = Long.parseLong(totalLineList.get(0).getTimestamp());
|
||||
long timesStampEnd = Long.parseLong(totalLineList.get(totalLineList.size() - 1).getTimestamp());
|
||||
long time = timesStampEnd - timesStampStart + Long.parseLong(totalLineList.get(totalLineList.size() - 1).getElapsed());
|
||||
double avgThroughput = (double) totalLineList.size() / (time * 1.0 / 1000);
|
||||
testOverview.setAvgThroughput(decimalFormat.format(avgThroughput));
|
||||
|
||||
List<Metric> falseList = totalLineList.stream().filter(metric -> StringUtils.equals("false", metric.getSuccess())).collect(Collectors.toList());
|
||||
double errors = falseList.size() * 1.0 / totalLineList.size() * 100;
|
||||
testOverview.setErrors(decimalFormat.format(errors));
|
||||
|
||||
double avg = totalElapsed * 1.0 / totalLineList.size() / 1000;
|
||||
testOverview.setAvgResponseTime(decimalFormat.format(avg));
|
||||
|
||||
double bandwidth = totalBytes * 1.0 / time;
|
||||
testOverview.setAvgBandwidth(decimalFormat.format(bandwidth));
|
||||
TestOverview testOverview = new TestOverview();
|
||||
testOverview.setMaxUsers(String.valueOf(maxUser));
|
||||
testOverview.setAvgThroughput(decimalFormat.format(hits));
|
||||
testOverview.setErrors(decimalFormat.format(error.get()));
|
||||
testOverview.setAvgResponseTime(decimalFormat.format(responseTime / 1000));
|
||||
|
||||
// todo
|
||||
testOverview.setResponseTime90("0");
|
||||
testOverview.setAvgBandwidth("0");
|
||||
return testOverview;
|
||||
}
|
||||
|
||||
|
@ -168,10 +132,4 @@ public class GenerateReport {
|
|||
return reportTimeInfo;
|
||||
}
|
||||
|
||||
private static String stampToDate(String pattern, String timeStamp) {
|
||||
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
|
||||
LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(Long.parseLong(timeStamp)), ZoneId.systemDefault());
|
||||
return localDateTime.format(dateTimeFormatter);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,194 +0,0 @@
|
|||
package io.metersphere.service;
|
||||
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.mapper.*;
|
||||
import io.metersphere.base.mapper.ext.ExtApiTestMapper;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.controller.request.testplan.*;
|
||||
import io.metersphere.dto.ApiTestDTO;
|
||||
import io.metersphere.i18n.Translator;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class ApiTestService {
|
||||
@Resource
|
||||
private ApiTestMapper ApiTestMapper;
|
||||
@Resource
|
||||
private ExtApiTestMapper extApiTestMapper;
|
||||
@Resource
|
||||
private ProjectMapper projectMapper;
|
||||
@Resource
|
||||
private FileMetadataMapper fileMetadataMapper;
|
||||
@Resource
|
||||
private FileContentMapper fileContentMapper;
|
||||
@Resource
|
||||
private ApiTestFileMapper ApiTestFileMapper;
|
||||
@Resource
|
||||
private FileService fileService;
|
||||
|
||||
public List<ApiTestDTO> list(QueryTestPlanRequest request) {
|
||||
return extApiTestMapper.list(request);
|
||||
}
|
||||
|
||||
public void delete(DeleteTestPlanRequest request) {
|
||||
ApiTestMapper.deleteByPrimaryKey(request.getId());
|
||||
|
||||
fileService.deleteFileByTestId(request.getId());
|
||||
}
|
||||
|
||||
public String save(SaveTestPlanRequest request, MultipartFile file) {
|
||||
if (file == null) {
|
||||
throw new IllegalArgumentException("文件不能为空!");
|
||||
}
|
||||
|
||||
final FileMetadata fileMetadata = saveFile(file);
|
||||
|
||||
final ApiTestWithBLOBs ApiTest = saveApiTest(request);
|
||||
|
||||
ApiTestFile ApiTestFile = new ApiTestFile();
|
||||
ApiTestFile.setTestId(ApiTest.getId());
|
||||
ApiTestFile.setFileId(fileMetadata.getId());
|
||||
ApiTestFileMapper.insert(ApiTestFile);
|
||||
|
||||
return ApiTest.getId();
|
||||
}
|
||||
|
||||
private ApiTestWithBLOBs saveApiTest(SaveTestPlanRequest request) {
|
||||
|
||||
ApiTestExample example = new ApiTestExample();
|
||||
example.createCriteria().andNameEqualTo(request.getName()).andProjectIdEqualTo(request.getProjectId());
|
||||
if (ApiTestMapper.countByExample(example) > 0) {
|
||||
MSException.throwException(Translator.get("function_test_already_exists"));
|
||||
}
|
||||
|
||||
final ApiTestWithBLOBs ApiTes = new ApiTestWithBLOBs();
|
||||
ApiTes.setId(UUID.randomUUID().toString());
|
||||
ApiTes.setName(request.getName());
|
||||
ApiTes.setProjectId(request.getProjectId());
|
||||
ApiTes.setCreateTime(System.currentTimeMillis());
|
||||
ApiTes.setUpdateTime(System.currentTimeMillis());
|
||||
ApiTes.setDescription("todo");
|
||||
ApiTes.setRuntimeConfiguration(request.getRuntimeConfiguration());
|
||||
ApiTestMapper.insert(ApiTes);
|
||||
return ApiTes;
|
||||
}
|
||||
|
||||
private FileMetadata saveFile(MultipartFile file) {
|
||||
final FileMetadata fileMetadata = new FileMetadata();
|
||||
fileMetadata.setId(UUID.randomUUID().toString());
|
||||
fileMetadata.setName(file.getOriginalFilename());
|
||||
fileMetadata.setSize(file.getSize());
|
||||
fileMetadata.setCreateTime(System.currentTimeMillis());
|
||||
fileMetadata.setUpdateTime(System.currentTimeMillis());
|
||||
fileMetadata.setType("jmx");
|
||||
fileMetadataMapper.insert(fileMetadata);
|
||||
|
||||
FileContent fileContent = new FileContent();
|
||||
fileContent.setFileId(fileMetadata.getId());
|
||||
try {
|
||||
fileContent.setFile(file.getBytes());
|
||||
} catch (IOException e) {
|
||||
MSException.throwException(e);
|
||||
}
|
||||
fileContentMapper.insert(fileContent);
|
||||
|
||||
return fileMetadata;
|
||||
}
|
||||
|
||||
public String edit(EditTestPlanRequest request, MultipartFile file) {
|
||||
// 新选择了一个文件,删除原来的文件
|
||||
if (file != null) {
|
||||
fileService.deleteFileByTestId(request.getId());
|
||||
final FileMetadata fileMetadata = saveFile(file);
|
||||
ApiTestFile ApiTestFile = new ApiTestFile();
|
||||
ApiTestFile.setTestId(request.getId());
|
||||
ApiTestFile.setFileId(fileMetadata.getId());
|
||||
ApiTestFileMapper.insert(ApiTestFile);
|
||||
}
|
||||
|
||||
final ApiTestWithBLOBs ApiTest = ApiTestMapper.selectByPrimaryKey(request.getId());
|
||||
if (ApiTest == null) {
|
||||
MSException.throwException("无法编辑测试,未找到测试:" + request.getId());
|
||||
} else {
|
||||
ApiTest.setName(request.getName());
|
||||
ApiTest.setProjectId(request.getProjectId());
|
||||
ApiTest.setUpdateTime(System.currentTimeMillis());
|
||||
ApiTest.setDescription("todo");
|
||||
ApiTest.setRuntimeConfiguration(request.getRuntimeConfiguration());
|
||||
ApiTestMapper.updateByPrimaryKeySelective(ApiTest);
|
||||
}
|
||||
|
||||
return request.getId();
|
||||
}
|
||||
|
||||
public void run(RunTestPlanRequest request) {
|
||||
final ApiTestWithBLOBs ApiTest = ApiTestMapper.selectByPrimaryKey(request.getId());
|
||||
// if (ApiTest == null) {
|
||||
// MSException.throwException("无法运行测试,未找到测试:" + request.getId());
|
||||
// }
|
||||
//
|
||||
// final List<FileMetadata> fileMetadataList = fileService.getFileMetadataByTestId(request.getId());
|
||||
// if (fileMetadataList == null) {
|
||||
// MSException.throwException("无法运行测试,无法获取测试文件元信息,测试ID:" + request.getId());
|
||||
// }
|
||||
//
|
||||
// final FileContent fileContent = fileService.getFileContent(fileMetadata.getId());
|
||||
// if (fileContent == null) {
|
||||
// MSException.throwException("无法运行测试,无法获取测试文件内容,测试ID:" + request.getId());
|
||||
// }
|
||||
//
|
||||
// System.out.println("开始运行:" + ApiTest.getName());
|
||||
// final Engine engine = EngineFactory.createEngine(fileMetadata.getType());
|
||||
// if (engine == null) {
|
||||
// MSException.throwException(String.format("无法运行测试,未识别测试文件类型,测试ID:%s,文件类型:%s",
|
||||
// request.getId(),
|
||||
// fileMetadata.getType()));
|
||||
// }
|
||||
//
|
||||
// boolean init = true;
|
||||
// try {
|
||||
//// init = engine.init(EngineFactory.createContext(ApiTest, fileMetadata, fileContent));
|
||||
// } catch (Exception e) {
|
||||
// MSException.throwException(e);
|
||||
// }
|
||||
// if (!init) {
|
||||
// MSException.throwException(String.format("无法运行测试,初始化运行环境失败,测试ID:%s", request.getId()));
|
||||
// }
|
||||
//
|
||||
//// engine.start();
|
||||
|
||||
/// todo:通过调用stop方法能够停止正在运行的engine,但是如果部署了多个backend实例,页面发送的停止请求如何定位到具体的engine
|
||||
}
|
||||
|
||||
public List<ApiTestDTO> recentTestPlans(QueryTestPlanRequest request) {
|
||||
// 查询最近的测试计划
|
||||
request.setRecent(true);
|
||||
return extApiTestMapper.list(request);
|
||||
}
|
||||
|
||||
public ApiTestDTO get(String testId) {
|
||||
QueryTestPlanRequest request = new QueryTestPlanRequest();
|
||||
request.setId(testId);
|
||||
List<ApiTestDTO> testDTOS = extApiTestMapper.list(request);
|
||||
if (!CollectionUtils.isEmpty(testDTOS)) {
|
||||
return testDTOS.get(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getRuntimeConfiguration(String testId) {
|
||||
ApiTestWithBLOBs ApiTestWithBLOBs = ApiTestMapper.selectByPrimaryKey(testId);
|
||||
return Optional.ofNullable(ApiTestWithBLOBs).orElse(new ApiTestWithBLOBs()).getRuntimeConfiguration();
|
||||
}
|
||||
|
||||
}
|
|
@ -194,19 +194,17 @@ CREATE TABLE IF NOT EXISTS `workspace` (
|
|||
-- api start
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `api_test` (
|
||||
`id` varchar(50) NOT NULL COMMENT 'Test ID',
|
||||
`project_id` varchar(50) NOT NULL COMMENT 'Project ID this test belongs to',
|
||||
`name` varchar(64) NOT NULL COMMENT 'Test name',
|
||||
`description` varchar(255) DEFAULT NULL COMMENT 'Test description',
|
||||
`runtime_configuration` longtext COMMENT 'Load configuration (JSON format)',
|
||||
`schedule` longtext COMMENT 'Test schedule (cron list)',
|
||||
`create_time` bigint(13) NOT NULL COMMENT 'Create timestamp',
|
||||
`update_time` bigint(13) NOT NULL COMMENT 'Update timestamp',
|
||||
`id` varchar(50) COLLATE utf8mb4_bin NOT NULL COMMENT 'Test ID',
|
||||
`project_id` varchar(50) COLLATE utf8mb4_bin NOT NULL COMMENT 'Project ID this test belongs to',
|
||||
`name` varchar(64) COLLATE utf8mb4_bin NOT NULL COMMENT 'Test name',
|
||||
`description` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL COMMENT 'Test description',
|
||||
`scenario_definition` longtext COLLATE utf8mb4_bin COMMENT 'Scenario definition (JSON format)',
|
||||
`schedule` longtext COLLATE utf8mb4_bin COMMENT 'Test schedule (cron list)',
|
||||
`status` varchar(64) COLLATE utf8mb4_bin DEFAULT NULL,
|
||||
`create_time` bigint(13) NOT NULL COMMENT 'Create timestamp',
|
||||
`update_time` bigint(13) NOT NULL COMMENT 'Update timestamp',
|
||||
PRIMARY KEY (`id`)
|
||||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_bin;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `api_test_file` (
|
||||
`test_id` varchar(64) DEFAULT NULL,
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<template>
|
||||
|
||||
<div id="menu-bar" v-if="isRouterAlive">
|
||||
<div id="menu-bar">
|
||||
<el-row type="flex">
|
||||
<el-col :span="8">
|
||||
<el-menu class="header-menu" :unique-opened="true" mode="horizontal" router :default-active='$route.path'>
|
||||
|
@ -22,10 +21,10 @@
|
|||
<template v-slot:title>{{$t('commons.test')}}</template>
|
||||
<ms-recent-list :options="testRecent"/>
|
||||
<el-divider/>
|
||||
<ms-show-all :index="'/api/test/all'"/>
|
||||
<ms-show-all :index="'/api/test/list/all'"/>
|
||||
<ms-create-button :index="'/api/test/create'" :title="$t('load_test.create')"/>
|
||||
<el-menu-item :index="testCaseProjectPath" class="blank_item"></el-menu-item>
|
||||
<el-menu-item :index="testEditPath" class="blank_item"></el-menu-item>
|
||||
<!-- <el-menu-item :index="testCaseProjectPath" class="blank_item"></el-menu-item>-->
|
||||
<!-- <el-menu-item :index="testEditPath" class="blank_item"></el-menu-item>-->
|
||||
</el-submenu>
|
||||
|
||||
<el-submenu v-if="isCurrentWorkspaceUser"
|
||||
|
@ -34,7 +33,7 @@
|
|||
<ms-recent-list :options="reportRecent"/>
|
||||
<el-divider/>
|
||||
<ms-show-all :index="'/api/report/all'"/>
|
||||
<el-menu-item :index="reportViewPath" class="blank_item"></el-menu-item>
|
||||
<!-- <el-menu-item :index="reportViewPath" class="blank_item"></el-menu-item>-->
|
||||
</el-submenu>
|
||||
</el-menu>
|
||||
</el-col>
|
||||
|
@ -63,10 +62,10 @@
|
|||
data() {
|
||||
return {
|
||||
isCurrentWorkspaceUser: false,
|
||||
testCaseProjectPath: '',
|
||||
testEditPath: '',
|
||||
reportViewPath: '',
|
||||
isRouterAlive: true,
|
||||
// testCaseProjectPath: '',
|
||||
// testEditPath: '',
|
||||
// reportViewPath: '',
|
||||
// isRouterAlive: true,
|
||||
projectRecent: {
|
||||
title: this.$t('project.recent'),
|
||||
url: "/project/recent/5",
|
||||
|
@ -82,6 +81,9 @@
|
|||
url: "/api/recent/5",
|
||||
index: function (item) {
|
||||
return '/api/test/edit/' + item.id;
|
||||
},
|
||||
router: function (item) {
|
||||
return {path: '/api/test/edit', query: {id: item.id}}
|
||||
}
|
||||
},
|
||||
reportRecent: {
|
||||
|
@ -93,35 +95,35 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$route'(to, from) {
|
||||
let path = to.path;
|
||||
//激活菜单栏
|
||||
if (path.indexOf("/api/test/") >= 0) {
|
||||
this.testCaseProjectPath = '/api/test/' + this.$route.params.projectId;
|
||||
this.reload();
|
||||
}
|
||||
if (path.indexOf("/api/test/edit/") >= 0) {
|
||||
this.testEditPath = '/api/test/edit/' + this.$route.params.testId;
|
||||
this.reload();
|
||||
}
|
||||
if (path.indexOf("/api/report/view/") >= 0) {
|
||||
this.reportViewPath = '/api/report/view/' + this.$route.params.reportId;
|
||||
this.reload();
|
||||
}
|
||||
}
|
||||
},
|
||||
// watch: {
|
||||
// '$route'(to, from) {
|
||||
// let path = to.path;
|
||||
// //激活菜单栏
|
||||
// if (path.indexOf("/api/test/") >= 0) {
|
||||
// this.testCaseProjectPath = '/api/test/' + this.$route.params.projectId;
|
||||
// this.reload();
|
||||
// }
|
||||
// if (path.indexOf("/api/test/edit/") >= 0) {
|
||||
// this.testEditPath = '/api/test/edit/' + this.$route.params.testId;
|
||||
// this.reload();
|
||||
// }
|
||||
// if (path.indexOf("/api/report/view/") >= 0) {
|
||||
// this.reportViewPath = '/api/report/view/' + this.$route.params.reportId;
|
||||
// this.reload();
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
mounted() {
|
||||
this.isCurrentWorkspaceUser = checkoutCurrentWorkspace();
|
||||
},
|
||||
methods: {
|
||||
reload() {
|
||||
this.isRouterAlive = false;
|
||||
this.$nextTick(function () {
|
||||
this.isRouterAlive = true;
|
||||
})
|
||||
}
|
||||
}
|
||||
// methods: {
|
||||
// reload() {
|
||||
// this.isRouterAlive = false;
|
||||
// this.$nextTick(function () {
|
||||
// this.isRouterAlive = true;
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
</script>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<el-button type="primary" plain :disabled="isDisabled" @click="saveTest">保存</el-button>
|
||||
</el-row>
|
||||
</el-header>
|
||||
<ms-api-scenario-config :scenarios="test.scenarioDefinition"/>
|
||||
<ms-api-scenario-config :scenarios="test.scenarioDefinition" ref="config"/>
|
||||
</el-container>
|
||||
</el-card>
|
||||
</div>
|
||||
|
@ -23,26 +23,34 @@
|
|||
|
||||
<script>
|
||||
import MsApiScenarioConfig from "./components/ApiScenarioConfig";
|
||||
import {Test} from "./model/ScenarioModel"
|
||||
|
||||
export default {
|
||||
name: "MsApiTestConfig",
|
||||
|
||||
components: {MsApiScenarioConfig},
|
||||
|
||||
props: ["id"],
|
||||
|
||||
data() {
|
||||
return {
|
||||
result: {},
|
||||
projects: [],
|
||||
change: false,
|
||||
test: {
|
||||
id: null,
|
||||
projectId: null,
|
||||
name: null,
|
||||
scenarioDefinition: []
|
||||
}
|
||||
test: new Test()
|
||||
}
|
||||
},
|
||||
|
||||
beforeRouteUpdate(to, from, next) {
|
||||
if (to.params.type === "edit") {
|
||||
this.getTest(to.query.id);
|
||||
} else {
|
||||
this.test = new Test();
|
||||
this.$refs.config.reset();
|
||||
}
|
||||
next();
|
||||
},
|
||||
|
||||
watch: {
|
||||
test: {
|
||||
handler: function () {
|
||||
|
@ -53,6 +61,19 @@
|
|||
},
|
||||
|
||||
methods: {
|
||||
getTest: function (id) {
|
||||
this.result = this.$get("/api/get/" + id, response => {
|
||||
let item = response.data;
|
||||
|
||||
this.test.reset({
|
||||
id: item.id,
|
||||
projectId: item.projectId,
|
||||
name: item.name,
|
||||
scenarioDefinition: JSON.parse(item.scenarioDefinition),
|
||||
});
|
||||
this.$refs.config.reset();
|
||||
});
|
||||
},
|
||||
saveTest: function () {
|
||||
this.change = false;
|
||||
|
||||
|
@ -83,6 +104,9 @@
|
|||
this.result = this.$get("/project/listAll", response => {
|
||||
this.projects = response.data;
|
||||
})
|
||||
if (this.id) {
|
||||
this.getTest(this.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -71,7 +71,6 @@
|
|||
data() {
|
||||
return {
|
||||
result: {},
|
||||
deletePath: "/api/delete",
|
||||
condition: "",
|
||||
projectId: null,
|
||||
tableData: [],
|
||||
|
@ -83,16 +82,18 @@
|
|||
testId: null,
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$route'(to) {
|
||||
this.projectId = to.params.projectId;
|
||||
this.search();
|
||||
}
|
||||
|
||||
beforeRouteUpdate(to, from, next) {
|
||||
this.projectId = to.params.projectId;
|
||||
this.search();
|
||||
next();
|
||||
},
|
||||
|
||||
created: function () {
|
||||
this.projectId = this.$route.params.projectId;
|
||||
this.search();
|
||||
},
|
||||
|
||||
methods: {
|
||||
search() {
|
||||
let param = {
|
||||
|
@ -113,34 +114,27 @@
|
|||
handleSelectionChange(val) {
|
||||
this.multipleSelection = val;
|
||||
},
|
||||
handleEdit(testPlan) {
|
||||
handleEdit(test) {
|
||||
this.$router.push({
|
||||
path: '/api/test/edit/' + testPlan.id,
|
||||
path: '/api/test/edit?id=' + test.id,
|
||||
})
|
||||
},
|
||||
handleDelete(testPlan) {
|
||||
this.$alert(this.$t('load_test.delete_confirm') + testPlan.name + "?", '', {
|
||||
handleDelete(test) {
|
||||
this.$alert(this.$t('load_test.delete_confirm') + test.name + "?", '', {
|
||||
confirmButtonText: this.$t('commons.confirm'),
|
||||
callback: (action) => {
|
||||
if (action === 'confirm') {
|
||||
this._handleDelete(testPlan);
|
||||
this.result = this.$post("/api/delete", {id: test.id}, () => {
|
||||
this.$message({
|
||||
message: this.$t('commons.delete_success'),
|
||||
type: 'success'
|
||||
});
|
||||
this.initTableData();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
_handleDelete(testPlan) {
|
||||
let data = {
|
||||
id: testPlan.id
|
||||
};
|
||||
|
||||
this.result = this.$post(this.deletePath, data, () => {
|
||||
this.$message({
|
||||
message: this.$t('commons.delete_success'),
|
||||
type: 'success'
|
||||
});
|
||||
this.initTableData();
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -149,6 +143,4 @@
|
|||
.test-content {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
|
|
@ -41,14 +41,7 @@
|
|||
options: ASSERTION_TYPE,
|
||||
type: "",
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
createRegex: function () {
|
||||
return new Regex();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="assertion-item-editing response-time" v-if="assertions.responseTime.isValid()">
|
||||
<div class="assertion-item-editing response-time" v-if="isShow">
|
||||
<div>
|
||||
{{$t("api_test.request.assertions.response_time")}}
|
||||
</div>
|
||||
|
@ -31,6 +31,13 @@
|
|||
|
||||
props: {
|
||||
assertions: Assertions
|
||||
},
|
||||
|
||||
computed: {
|
||||
isShow() {
|
||||
let rt = this.assertions.responseTime;
|
||||
return rt.responseInTime !== null && rt.responseInTime > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -80,10 +80,7 @@
|
|||
},
|
||||
|
||||
created() {
|
||||
if (this.requests.length === 0) {
|
||||
this.createRequest();
|
||||
this.select(this.requests[0]);
|
||||
}
|
||||
this.select(this.requests[0]);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -43,12 +43,13 @@
|
|||
import MsApiKeyValue from "./ApiKeyValue";
|
||||
import MsApiBody from "./ApiBody";
|
||||
import MsApiAssertions from "./ApiAssertions";
|
||||
import {Request} from "../model/ScenarioModel";
|
||||
|
||||
export default {
|
||||
name: "MsApiRequestForm",
|
||||
components: {MsApiAssertions, MsApiBody, MsApiKeyValue},
|
||||
props: {
|
||||
request: Object
|
||||
request: Request
|
||||
},
|
||||
|
||||
data() {
|
||||
|
|
|
@ -6,7 +6,12 @@
|
|||
<ms-api-collapse-item v-for="(scenario, index) in scenarios" :key="index"
|
||||
:title="scenario.name" :name="index">
|
||||
<template slot="title">
|
||||
<div class="scenario-name">{{scenario.name}}</div>
|
||||
<div class="scenario-name">
|
||||
{{scenario.name}}
|
||||
<span id="hint" v-if="!scenario.name">
|
||||
{{$t('api_test.scenario.config')}}
|
||||
</span>
|
||||
</div>
|
||||
<el-dropdown trigger="click" @command="handleCommand">
|
||||
<span class="el-dropdown-link el-icon-more scenario-btn"/>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
|
@ -57,14 +62,13 @@
|
|||
data() {
|
||||
return {
|
||||
activeName: 0,
|
||||
selected: Object
|
||||
selected: [Scenario, Request]
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
createScenario: function () {
|
||||
let scenario = new Scenario({name: "Scenario"});
|
||||
this.scenarios.push(scenario);
|
||||
this.scenarios.push(new Scenario());
|
||||
},
|
||||
deleteScenario: function (index) {
|
||||
this.scenarios.splice(index, 1);
|
||||
|
@ -85,6 +89,12 @@
|
|||
},
|
||||
select: function (obj) {
|
||||
this.selected = obj;
|
||||
},
|
||||
reset: function () {
|
||||
this.$nextTick(function () {
|
||||
this.activeName = 0;
|
||||
this.select(this.scenarios[0]);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -98,10 +108,7 @@
|
|||
},
|
||||
|
||||
created() {
|
||||
if (this.scenarios.length === 0) {
|
||||
this.createScenario();
|
||||
this.select(this.scenarios[0]);
|
||||
}
|
||||
this.select(this.scenarios[0]);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -131,6 +138,10 @@
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.scenario-name > #hint {
|
||||
color: #8a8b8d;
|
||||
}
|
||||
|
||||
.scenario-btn {
|
||||
text-align: center;
|
||||
padding: 13px;
|
||||
|
|
|
@ -21,12 +21,13 @@
|
|||
|
||||
<script>
|
||||
import MsApiKeyValue from "./ApiKeyValue";
|
||||
import {Scenario} from "../model/ScenarioModel";
|
||||
|
||||
export default {
|
||||
name: "MsApiScenarioForm",
|
||||
components: {MsApiKeyValue},
|
||||
props: {
|
||||
scenario: Object
|
||||
scenario: Scenario
|
||||
},
|
||||
|
||||
data() {
|
||||
|
|
|
@ -1,9 +1,23 @@
|
|||
import {generateId} from "element-ui/src/utils/util";
|
||||
|
||||
const assign = function (obj, options) {
|
||||
for (let name in options) {
|
||||
if (options.hasOwnProperty(name)) {
|
||||
obj[name] = options[name];
|
||||
if (options) {
|
||||
for (let name in options) {
|
||||
if (options.hasOwnProperty(name)) {
|
||||
if (!(obj[name] instanceof Array)) {
|
||||
obj[name] = options[name];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const assigns = function (target, source, type) {
|
||||
if (target instanceof Array && source instanceof Array) {
|
||||
if (source && source.length > 0) {
|
||||
source.forEach((options) => {
|
||||
target.push(new type(options));
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,8 +33,32 @@ export const ASSERTION_TYPE = {
|
|||
RESPONSE_TIME: "RESPONSE_TIME"
|
||||
}
|
||||
|
||||
export class Test {
|
||||
constructor(options) {
|
||||
this.reset(options);
|
||||
}
|
||||
|
||||
reset(options) {
|
||||
options = this.getDefaultOptions(options);
|
||||
this.id = null;
|
||||
this.name = null;
|
||||
this.projectId = null;
|
||||
this.scenarioDefinition = [];
|
||||
|
||||
assign(this, options);
|
||||
assigns(this.scenarioDefinition, options.scenarioDefinition, Scenario);
|
||||
}
|
||||
|
||||
getDefaultOptions(options) {
|
||||
options = options || {};
|
||||
options.scenarioDefinition = options.scenarioDefinition || [new Scenario()];
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
||||
export class Scenario {
|
||||
constructor(options) {
|
||||
options = this.getDefaultOptions(options);
|
||||
this.name = null;
|
||||
this.url = null;
|
||||
this.variables = [];
|
||||
|
@ -28,32 +66,55 @@ export class Scenario {
|
|||
this.requests = [];
|
||||
|
||||
assign(this, options);
|
||||
assigns(this.variables, options.variables, KeyValue);
|
||||
assigns(this.headers, options.headers, KeyValue);
|
||||
assigns(this.requests, options.requests, Request);
|
||||
}
|
||||
|
||||
getDefaultOptions(options) {
|
||||
options = options || {};
|
||||
options.requests = options.requests || [new Request()];
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
||||
export class Request {
|
||||
constructor(options) {
|
||||
options = this.getDefaultOptions(options);
|
||||
this.randomId = generateId();
|
||||
this.name = null;
|
||||
this.url = null;
|
||||
this.method = null;
|
||||
this.parameters = [];
|
||||
this.headers = [];
|
||||
this.body = new Body();
|
||||
this.assertions = new Assertions();
|
||||
this.body = null;
|
||||
this.assertions = null;
|
||||
this.extract = [];
|
||||
|
||||
assign(this, options);
|
||||
assigns(this.parameters, options.parameters, KeyValue);
|
||||
assigns(this.headers, options.headers, KeyValue);
|
||||
// TODO assigns extract
|
||||
}
|
||||
|
||||
getDefaultOptions(options) {
|
||||
options = options || {};
|
||||
options.method = "GET";
|
||||
options.body = new Body(options.body);
|
||||
options.assertions = new Assertions(options.assertions);
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
||||
export class Body {
|
||||
constructor(options) {
|
||||
options = options || {};
|
||||
this.type = null;
|
||||
this.text = null;
|
||||
this.kvs = [];
|
||||
|
||||
assign(this, options);
|
||||
assigns(this.kvs, options.kvs, KeyValue);
|
||||
}
|
||||
|
||||
isKV() {
|
||||
|
@ -63,6 +124,7 @@ export class Body {
|
|||
|
||||
export class KeyValue {
|
||||
constructor(options) {
|
||||
options = options || {};
|
||||
this.key = null;
|
||||
this.value = null;
|
||||
|
||||
|
@ -72,11 +134,20 @@ export class KeyValue {
|
|||
|
||||
export class Assertions {
|
||||
constructor(options) {
|
||||
options = this.getDefaultOptions(options);
|
||||
this.text = [];
|
||||
this.regex = [];
|
||||
this.responseTime = new ResponseTime();
|
||||
this.responseTime = null;
|
||||
|
||||
assign(this, options);
|
||||
assigns(this.text, options.text, KeyValue);
|
||||
assigns(this.regex, options.regex, KeyValue);
|
||||
}
|
||||
|
||||
getDefaultOptions(options) {
|
||||
options = options || {};
|
||||
options.responseTime = new ResponseTime(options.responseTime);
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,6 +159,7 @@ class AssertionType {
|
|||
|
||||
export class Text extends AssertionType {
|
||||
constructor(options) {
|
||||
options = options || {};
|
||||
super(ASSERTION_TYPE.TEXT);
|
||||
this.subject = null;
|
||||
this.condition = null;
|
||||
|
@ -99,6 +171,7 @@ export class Text extends AssertionType {
|
|||
|
||||
export class Regex extends AssertionType {
|
||||
constructor(options) {
|
||||
options = options || {};
|
||||
super(ASSERTION_TYPE.REGEX);
|
||||
this.subject = null;
|
||||
this.expression = null;
|
||||
|
@ -110,14 +183,11 @@ export class Regex extends AssertionType {
|
|||
|
||||
export class ResponseTime extends AssertionType {
|
||||
constructor(options) {
|
||||
options = options || {};
|
||||
super(ASSERTION_TYPE.RESPONSE_TIME);
|
||||
this.responseInTime = null;
|
||||
|
||||
assign(this, options);
|
||||
}
|
||||
|
||||
isValid() {
|
||||
return this.responseInTime !== null && this.responseInTime > 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
name: "MsCreateTest",
|
||||
props: {
|
||||
show: Boolean,
|
||||
to: String,
|
||||
to: [String, Object],
|
||||
title: {
|
||||
type: String,
|
||||
default: function () {
|
||||
|
|
|
@ -95,25 +95,14 @@ const router = new VueRouter({
|
|||
component: ApiTestHome,
|
||||
},
|
||||
{
|
||||
path: 'test/create',
|
||||
name: "createAPITest",
|
||||
path: "test/:type",
|
||||
name: "ApiTestConfig",
|
||||
component: ApiTestConfig,
|
||||
props: (route) => ({id: route.query.id})
|
||||
},
|
||||
{
|
||||
path: "test/edit/:testId",
|
||||
name: "editAPITest",
|
||||
component: ApiTestConfig,
|
||||
props: {
|
||||
content: (route) => {
|
||||
return {
|
||||
...route.params
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
path: "test/:projectId",
|
||||
name: "fucPlan",
|
||||
path: "test/list/:projectId",
|
||||
name: "ApiTestList",
|
||||
component: ApiTestList
|
||||
},
|
||||
{
|
||||
|
|
|
@ -174,6 +174,7 @@ export default {
|
|||
input_name: "请输入测试名称",
|
||||
select_project: "请选择项目",
|
||||
scenario: {
|
||||
config: "场景配置",
|
||||
input_name: "请输入场景名称",
|
||||
name: "场景名称",
|
||||
base_url: "基础URL",
|
||||
|
|
Loading…
Reference in New Issue