Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
MeterSphere
metersphere
提交
325b023c
M
metersphere
项目概览
MeterSphere
/
metersphere
上一次同步 大约 3 年
通知
25
Star
1
Fork
1
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
M
metersphere
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
325b023c
编写于
3月 29, 2020
作者:
C
chenjianxing
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
测试用例管理
上级
40473911
变更
16
隐藏空白更改
内联
并排
Showing
16 changed file
with
966 addition
and
332 deletion
+966
-332
backend/src/main/java/io/metersphere/base/domain/TestCase.java
...nd/src/main/java/io/metersphere/base/domain/TestCase.java
+10
-0
backend/src/main/java/io/metersphere/base/domain/TestCaseExample.java
...main/java/io/metersphere/base/domain/TestCaseExample.java
+70
-0
backend/src/main/java/io/metersphere/base/domain/TestCaseWithBLOBs.java
...in/java/io/metersphere/base/domain/TestCaseWithBLOBs.java
+5
-15
backend/src/main/java/io/metersphere/base/mapper/TestCaseMapper.xml
...c/main/java/io/metersphere/base/mapper/TestCaseMapper.xml
+41
-39
backend/src/main/java/io/metersphere/controller/TestCaseController.java
...in/java/io/metersphere/controller/TestCaseController.java
+62
-0
backend/src/main/java/io/metersphere/controller/request/testcase/QueryTestCaseRequest.java
...ere/controller/request/testcase/QueryTestCaseRequest.java
+18
-0
backend/src/main/java/io/metersphere/service/TestCaseService.java
...src/main/java/io/metersphere/service/TestCaseService.java
+63
-0
backend/src/main/resources/db/migration/V2__metersphere_ddl.sql
...d/src/main/resources/db/migration/V2__metersphere_ddl.sql
+123
-0
backend/src/main/resources/db/migration/V4__init_funcional.sql
...nd/src/main/resources/db/migration/V4__init_funcional.sql
+0
-38
backend/src/main/resources/db/migration/V5__init_track.sql
backend/src/main/resources/db/migration/V5__init_track.sql
+0
-76
frontend/src/business/components/common/head/HeaderUser.vue
frontend/src/business/components/common/head/HeaderUser.vue
+3
-1
frontend/src/business/components/track/case/TestCase.vue
frontend/src/business/components/track/case/TestCase.vue
+51
-146
frontend/src/business/components/track/case/components/NodeTree.vue
...rc/business/components/track/case/components/NodeTree.vue
+0
-17
frontend/src/business/components/track/case/components/TestCaseEdit.vue
...usiness/components/track/case/components/TestCaseEdit.vue
+312
-0
frontend/src/business/components/track/case/components/TestCaseList.vue
...usiness/components/track/case/components/TestCaseList.vue
+206
-0
frontend/src/common/constants.js
frontend/src/common/constants.js
+2
-0
未找到文件。
backend/src/main/java/io/metersphere/base/domain/TestCase.java
浏览文件 @
325b023c
...
...
@@ -13,6 +13,8 @@ public class TestCase implements Serializable {
private
String
type
;
private
String
maintainer
;
private
String
priority
;
private
String
method
;
...
...
@@ -65,6 +67,14 @@ public class TestCase implements Serializable {
this
.
type
=
type
==
null
?
null
:
type
.
trim
();
}
public
String
getMaintainer
()
{
return
maintainer
;
}
public
void
setMaintainer
(
String
maintainer
)
{
this
.
maintainer
=
maintainer
==
null
?
null
:
maintainer
.
trim
();
}
public
String
getPriority
()
{
return
priority
;
}
...
...
backend/src/main/java/io/metersphere/base/domain/TestCaseExample.java
浏览文件 @
325b023c
...
...
@@ -444,6 +444,76 @@ public class TestCaseExample {
return
(
Criteria
)
this
;
}
public
Criteria
andMaintainerIsNull
()
{
addCriterion
(
"maintainer is null"
);
return
(
Criteria
)
this
;
}
public
Criteria
andMaintainerIsNotNull
()
{
addCriterion
(
"maintainer is not null"
);
return
(
Criteria
)
this
;
}
public
Criteria
andMaintainerEqualTo
(
String
value
)
{
addCriterion
(
"maintainer ="
,
value
,
"maintainer"
);
return
(
Criteria
)
this
;
}
public
Criteria
andMaintainerNotEqualTo
(
String
value
)
{
addCriterion
(
"maintainer <>"
,
value
,
"maintainer"
);
return
(
Criteria
)
this
;
}
public
Criteria
andMaintainerGreaterThan
(
String
value
)
{
addCriterion
(
"maintainer >"
,
value
,
"maintainer"
);
return
(
Criteria
)
this
;
}
public
Criteria
andMaintainerGreaterThanOrEqualTo
(
String
value
)
{
addCriterion
(
"maintainer >="
,
value
,
"maintainer"
);
return
(
Criteria
)
this
;
}
public
Criteria
andMaintainerLessThan
(
String
value
)
{
addCriterion
(
"maintainer <"
,
value
,
"maintainer"
);
return
(
Criteria
)
this
;
}
public
Criteria
andMaintainerLessThanOrEqualTo
(
String
value
)
{
addCriterion
(
"maintainer <="
,
value
,
"maintainer"
);
return
(
Criteria
)
this
;
}
public
Criteria
andMaintainerLike
(
String
value
)
{
addCriterion
(
"maintainer like"
,
value
,
"maintainer"
);
return
(
Criteria
)
this
;
}
public
Criteria
andMaintainerNotLike
(
String
value
)
{
addCriterion
(
"maintainer not like"
,
value
,
"maintainer"
);
return
(
Criteria
)
this
;
}
public
Criteria
andMaintainerIn
(
List
<
String
>
values
)
{
addCriterion
(
"maintainer in"
,
values
,
"maintainer"
);
return
(
Criteria
)
this
;
}
public
Criteria
andMaintainerNotIn
(
List
<
String
>
values
)
{
addCriterion
(
"maintainer not in"
,
values
,
"maintainer"
);
return
(
Criteria
)
this
;
}
public
Criteria
andMaintainerBetween
(
String
value1
,
String
value2
)
{
addCriterion
(
"maintainer between"
,
value1
,
value2
,
"maintainer"
);
return
(
Criteria
)
this
;
}
public
Criteria
andMaintainerNotBetween
(
String
value1
,
String
value2
)
{
addCriterion
(
"maintainer not between"
,
value1
,
value2
,
"maintainer"
);
return
(
Criteria
)
this
;
}
public
Criteria
andPriorityIsNull
()
{
addCriterion
(
"priority is null"
);
return
(
Criteria
)
this
;
...
...
backend/src/main/java/io/metersphere/base/domain/TestCaseWithBLOBs.java
浏览文件 @
325b023c
...
...
@@ -3,20 +3,18 @@ package io.metersphere.base.domain;
import
java.io.Serializable
;
public
class
TestCaseWithBLOBs
extends
TestCase
implements
Serializable
{
private
String
detail
;
private
String
remark
;
private
String
steps
;
private
String
tags
;
private
static
final
long
serialVersionUID
=
1L
;
public
String
get
Detail
()
{
return
detail
;
public
String
get
Remark
()
{
return
remark
;
}
public
void
set
Detail
(
String
detail
)
{
this
.
detail
=
detail
==
null
?
null
:
detail
.
trim
();
public
void
set
Remark
(
String
remark
)
{
this
.
remark
=
remark
==
null
?
null
:
remark
.
trim
();
}
public
String
getSteps
()
{
...
...
@@ -26,12 +24,4 @@ public class TestCaseWithBLOBs extends TestCase implements Serializable {
public
void
setSteps
(
String
steps
)
{
this
.
steps
=
steps
==
null
?
null
:
steps
.
trim
();
}
public
String
getTags
()
{
return
tags
;
}
public
void
setTags
(
String
tags
)
{
this
.
tags
=
tags
==
null
?
null
:
tags
.
trim
();
}
}
\ No newline at end of file
backend/src/main/java/io/metersphere/base/mapper/TestCaseMapper.xml
浏览文件 @
325b023c
...
...
@@ -7,6 +7,7 @@
<result
column=
"project_id"
jdbcType=
"VARCHAR"
property=
"projectId"
/>
<result
column=
"name"
jdbcType=
"VARCHAR"
property=
"name"
/>
<result
column=
"type"
jdbcType=
"VARCHAR"
property=
"type"
/>
<result
column=
"maintainer"
jdbcType=
"VARCHAR"
property=
"maintainer"
/>
<result
column=
"priority"
jdbcType=
"VARCHAR"
property=
"priority"
/>
<result
column=
"method"
jdbcType=
"VARCHAR"
property=
"method"
/>
<result
column=
"prerequisite"
jdbcType=
"VARCHAR"
property=
"prerequisite"
/>
...
...
@@ -14,9 +15,8 @@
<result
column=
"update_time"
jdbcType=
"BIGINT"
property=
"updateTime"
/>
</resultMap>
<resultMap
extends=
"BaseResultMap"
id=
"ResultMapWithBLOBs"
type=
"io.metersphere.base.domain.TestCaseWithBLOBs"
>
<result
column=
"
detail"
jdbcType=
"LONGVARCHAR"
property=
"detail
"
/>
<result
column=
"
remark"
jdbcType=
"LONGVARCHAR"
property=
"remark
"
/>
<result
column=
"steps"
jdbcType=
"LONGVARCHAR"
property=
"steps"
/>
<result
column=
"tags"
jdbcType=
"LONGVARCHAR"
property=
"tags"
/>
</resultMap>
<sql
id=
"Example_Where_Clause"
>
<where>
...
...
@@ -77,11 +77,11 @@
</where>
</sql>
<sql
id=
"Base_Column_List"
>
id, node_id, project_id, name, type,
priority, method, prerequisite, create_tim
e,
update_time
id, node_id, project_id, name, type,
maintainer, priority, method, prerequisit
e,
create_time,
update_time
</sql>
<sql
id=
"Blob_Column_List"
>
detail, steps, tag
s
remark, step
s
</sql>
<select
id=
"selectByExampleWithBLOBs"
parameterType=
"io.metersphere.base.domain.TestCaseExample"
resultMap=
"ResultMapWithBLOBs"
>
select
...
...
@@ -133,15 +133,15 @@
</delete>
<insert
id=
"insert"
parameterType=
"io.metersphere.base.domain.TestCaseWithBLOBs"
>
insert into test_case (id, node_id, project_id,
name, type,
priority
,
method, prerequisite, create_tim
e,
update_time, detail, steps
,
tag
s)
name, type,
maintainer
,
priority, method, prerequisit
e,
create_time, update_time, remark
,
step
s)
values (#{id,jdbcType=VARCHAR}, #{nodeId,jdbcType=INTEGER}, #{projectId,jdbcType=VARCHAR},
#{name,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR}, #{
priority
,jdbcType=VARCHAR},
#{
method,jdbcType=VARCHAR}, #{prerequisite,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT
},
#{
updateTime,jdbcType=BIGINT}, #{detail,jdbcType=LONGVARCHAR}, #{steps
,jdbcType=LONGVARCHAR},
#{
tag
s,jdbcType=LONGVARCHAR})
#{name,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR}, #{
maintainer
,jdbcType=VARCHAR},
#{
priority,jdbcType=VARCHAR}, #{method,jdbcType=VARCHAR}, #{prerequisite,jdbcType=VARCHAR
},
#{
createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT}, #{remark
,jdbcType=LONGVARCHAR},
#{
step
s,jdbcType=LONGVARCHAR})
</insert>
<insert
id=
"insertSelective"
parameterType=
"io.metersphere.base.domain.TestCaseWithBLOBs"
>
insert into test_case
...
...
@@ -161,6 +161,9 @@
<if
test=
"type != null"
>
type,
</if>
<if
test=
"maintainer != null"
>
maintainer,
</if>
<if
test=
"priority != null"
>
priority,
</if>
...
...
@@ -176,15 +179,12 @@
<if
test=
"updateTime != null"
>
update_time,
</if>
<if
test=
"
detail
!= null"
>
detail
,
<if
test=
"
remark
!= null"
>
remark
,
</if>
<if
test=
"steps != null"
>
steps,
</if>
<if
test=
"tags != null"
>
tags,
</if>
</trim>
<trim
prefix=
"values ("
suffix=
")"
suffixOverrides=
","
>
<if
test=
"id != null"
>
...
...
@@ -202,6 +202,9 @@
<if
test=
"type != null"
>
#{type,jdbcType=VARCHAR},
</if>
<if
test=
"maintainer != null"
>
#{maintainer,jdbcType=VARCHAR},
</if>
<if
test=
"priority != null"
>
#{priority,jdbcType=VARCHAR},
</if>
...
...
@@ -217,15 +220,12 @@
<if
test=
"updateTime != null"
>
#{updateTime,jdbcType=BIGINT},
</if>
<if
test=
"
detail
!= null"
>
#{
detail
,jdbcType=LONGVARCHAR},
<if
test=
"
remark
!= null"
>
#{
remark
,jdbcType=LONGVARCHAR},
</if>
<if
test=
"steps != null"
>
#{steps,jdbcType=LONGVARCHAR},
</if>
<if
test=
"tags != null"
>
#{tags,jdbcType=LONGVARCHAR},
</if>
</trim>
</insert>
<select
id=
"countByExample"
parameterType=
"io.metersphere.base.domain.TestCaseExample"
resultType=
"java.lang.Long"
>
...
...
@@ -252,6 +252,9 @@
<if
test=
"record.type != null"
>
type = #{record.type,jdbcType=VARCHAR},
</if>
<if
test=
"record.maintainer != null"
>
maintainer = #{record.maintainer,jdbcType=VARCHAR},
</if>
<if
test=
"record.priority != null"
>
priority = #{record.priority,jdbcType=VARCHAR},
</if>
...
...
@@ -267,15 +270,12 @@
<if
test=
"record.updateTime != null"
>
update_time = #{record.updateTime,jdbcType=BIGINT},
</if>
<if
test=
"record.
detail
!= null"
>
detail = #{record.detail
,jdbcType=LONGVARCHAR},
<if
test=
"record.
remark
!= null"
>
remark = #{record.remark
,jdbcType=LONGVARCHAR},
</if>
<if
test=
"record.steps != null"
>
steps = #{record.steps,jdbcType=LONGVARCHAR},
</if>
<if
test=
"record.tags != null"
>
tags = #{record.tags,jdbcType=LONGVARCHAR},
</if>
</set>
<if
test=
"_parameter != null"
>
<include
refid=
"Update_By_Example_Where_Clause"
/>
...
...
@@ -288,14 +288,14 @@
project_id = #{record.projectId,jdbcType=VARCHAR},
name = #{record.name,jdbcType=VARCHAR},
type = #{record.type,jdbcType=VARCHAR},
maintainer = #{record.maintainer,jdbcType=VARCHAR},
priority = #{record.priority,jdbcType=VARCHAR},
method = #{record.method,jdbcType=VARCHAR},
prerequisite = #{record.prerequisite,jdbcType=VARCHAR},
create_time = #{record.createTime,jdbcType=BIGINT},
update_time = #{record.updateTime,jdbcType=BIGINT},
detail = #{record.detail,jdbcType=LONGVARCHAR},
steps = #{record.steps,jdbcType=LONGVARCHAR},
tags = #{record.tags,jdbcType=LONGVARCHAR}
remark = #{record.remark,jdbcType=LONGVARCHAR},
steps = #{record.steps,jdbcType=LONGVARCHAR}
<if
test=
"_parameter != null"
>
<include
refid=
"Update_By_Example_Where_Clause"
/>
</if>
...
...
@@ -307,6 +307,7 @@
project_id = #{record.projectId,jdbcType=VARCHAR},
name = #{record.name,jdbcType=VARCHAR},
type = #{record.type,jdbcType=VARCHAR},
maintainer = #{record.maintainer,jdbcType=VARCHAR},
priority = #{record.priority,jdbcType=VARCHAR},
method = #{record.method,jdbcType=VARCHAR},
prerequisite = #{record.prerequisite,jdbcType=VARCHAR},
...
...
@@ -331,6 +332,9 @@
<if
test=
"type != null"
>
type = #{type,jdbcType=VARCHAR},
</if>
<if
test=
"maintainer != null"
>
maintainer = #{maintainer,jdbcType=VARCHAR},
</if>
<if
test=
"priority != null"
>
priority = #{priority,jdbcType=VARCHAR},
</if>
...
...
@@ -346,15 +350,12 @@
<if
test=
"updateTime != null"
>
update_time = #{updateTime,jdbcType=BIGINT},
</if>
<if
test=
"
detail
!= null"
>
detail = #{detail
,jdbcType=LONGVARCHAR},
<if
test=
"
remark
!= null"
>
remark = #{remark
,jdbcType=LONGVARCHAR},
</if>
<if
test=
"steps != null"
>
steps = #{steps,jdbcType=LONGVARCHAR},
</if>
<if
test=
"tags != null"
>
tags = #{tags,jdbcType=LONGVARCHAR},
</if>
</set>
where id = #{id,jdbcType=VARCHAR}
</update>
...
...
@@ -364,14 +365,14 @@
project_id = #{projectId,jdbcType=VARCHAR},
name = #{name,jdbcType=VARCHAR},
type = #{type,jdbcType=VARCHAR},
maintainer = #{maintainer,jdbcType=VARCHAR},
priority = #{priority,jdbcType=VARCHAR},
method = #{method,jdbcType=VARCHAR},
prerequisite = #{prerequisite,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT},
update_time = #{updateTime,jdbcType=BIGINT},
detail = #{detail,jdbcType=LONGVARCHAR},
steps = #{steps,jdbcType=LONGVARCHAR},
tags = #{tags,jdbcType=LONGVARCHAR}
remark = #{remark,jdbcType=LONGVARCHAR},
steps = #{steps,jdbcType=LONGVARCHAR}
where id = #{id,jdbcType=VARCHAR}
</update>
<update
id=
"updateByPrimaryKey"
parameterType=
"io.metersphere.base.domain.TestCase"
>
...
...
@@ -380,6 +381,7 @@
project_id = #{projectId,jdbcType=VARCHAR},
name = #{name,jdbcType=VARCHAR},
type = #{type,jdbcType=VARCHAR},
maintainer = #{maintainer,jdbcType=VARCHAR},
priority = #{priority,jdbcType=VARCHAR},
method = #{method,jdbcType=VARCHAR},
prerequisite = #{prerequisite,jdbcType=VARCHAR},
...
...
backend/src/main/java/io/metersphere/controller/TestCaseController.java
0 → 100644
浏览文件 @
325b023c
package
io.metersphere.controller
;
import
com.github.pagehelper.Page
;
import
com.github.pagehelper.PageHelper
;
import
io.metersphere.base.domain.LoadTest
;
import
io.metersphere.base.domain.TestCase
;
import
io.metersphere.base.domain.TestCaseNode
;
import
io.metersphere.base.domain.TestCaseWithBLOBs
;
import
io.metersphere.commons.utils.PageUtils
;
import
io.metersphere.commons.utils.Pager
;
import
io.metersphere.controller.request.testcase.QueryTestCaseRequest
;
import
io.metersphere.controller.request.testplan.QueryTestPlanRequest
;
import
io.metersphere.dto.LoadTestDTO
;
import
io.metersphere.dto.TestCaseNodeDTO
;
import
io.metersphere.service.TestCaseNodeService
;
import
io.metersphere.service.TestCaseService
;
import
io.metersphere.user.SessionUtils
;
import
org.springframework.web.bind.annotation.*
;
import
javax.annotation.Resource
;
import
java.util.List
;
@RequestMapping
(
"/test/case"
)
@RestController
public
class
TestCaseController
{
@Resource
TestCaseService
testCaseService
;
@PostMapping
(
"/list/{goPage}/{pageSize}"
)
public
Pager
<
List
<
TestCaseWithBLOBs
>>
list
(
@PathVariable
int
goPage
,
@PathVariable
int
pageSize
,
@RequestBody
QueryTestCaseRequest
request
)
{
Page
<
Object
>
page
=
PageHelper
.
startPage
(
goPage
,
pageSize
,
true
);
return
PageUtils
.
setPageInfo
(
page
,
testCaseService
.
listTestCase
(
request
));
}
@PostMapping
(
"/list"
)
public
List
<
TestCase
>
getTestCaseByProjectId
(
@RequestBody
List
<
Integer
>
nodeIds
){
return
testCaseService
.
getTestCaseByNodeId
(
nodeIds
);
}
@PostMapping
(
"/get/{testCaseId}"
)
public
List
<
TestCaseWithBLOBs
>
getTestCase
(
@PathVariable
String
testCaseId
){
return
testCaseService
.
getTestCase
(
testCaseId
);
}
@PostMapping
(
"/add"
)
public
void
addTestCase
(
@RequestBody
TestCaseWithBLOBs
testCase
){
testCaseService
.
addTestCase
(
testCase
);
}
@PostMapping
(
"/edit"
)
public
void
editTestCase
(
@RequestBody
TestCaseWithBLOBs
testCase
){
testCaseService
.
editTestCase
(
testCase
);
}
@PostMapping
(
"/delete/{testCaseId}"
)
public
int
deleteTestCase
(
@PathVariable
String
testCaseId
){
return
testCaseService
.
deleteTestCase
(
testCaseId
);
}
}
backend/src/main/java/io/metersphere/controller/request/testcase/QueryTestCaseRequest.java
0 → 100644
浏览文件 @
325b023c
package
io.metersphere.controller.request.testcase
;
import
io.metersphere.base.domain.TestCase
;
import
java.util.List
;
public
class
QueryTestCaseRequest
extends
TestCase
{
List
<
Integer
>
nodeIds
;
public
List
<
Integer
>
getNodeIds
()
{
return
nodeIds
;
}
public
void
setNodeIds
(
List
<
Integer
>
nodeIds
)
{
this
.
nodeIds
=
nodeIds
;
}
}
backend/src/main/java/io/metersphere/service/TestCaseService.java
0 → 100644
浏览文件 @
325b023c
package
io.metersphere.service
;
import
io.metersphere.base.domain.*
;
import
io.metersphere.base.mapper.TestCaseMapper
;
import
io.metersphere.base.mapper.TestCaseNodeMapper
;
import
io.metersphere.commons.utils.BeanUtils
;
import
io.metersphere.controller.request.testcase.QueryTestCaseRequest
;
import
io.metersphere.dto.TestCaseNodeDTO
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
javax.annotation.Resource
;
import
java.util.*
;
@Service
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
class
TestCaseService
{
@Resource
TestCaseMapper
testCaseMapper
;
public
void
addTestCase
(
TestCaseWithBLOBs
testCase
)
{
testCase
.
setId
(
UUID
.
randomUUID
().
toString
());
testCase
.
setCreateTime
(
System
.
currentTimeMillis
());
testCase
.
setUpdateTime
(
System
.
currentTimeMillis
());
testCaseMapper
.
insert
(
testCase
);
}
public
List
<
TestCase
>
getTestCaseByNodeId
(
List
<
Integer
>
nodeIds
)
{
TestCaseExample
testCaseExample
=
new
TestCaseExample
();
testCaseExample
.
createCriteria
().
andNodeIdIn
(
nodeIds
);
return
testCaseMapper
.
selectByExample
(
testCaseExample
);
}
public
List
<
TestCaseWithBLOBs
>
getTestCase
(
String
testCaseId
)
{
TestCaseExample
testCaseExample
=
new
TestCaseExample
();
testCaseExample
.
createCriteria
().
andIdEqualTo
(
testCaseId
);
return
testCaseMapper
.
selectByExampleWithBLOBs
(
testCaseExample
);
}
public
int
editTestCase
(
TestCaseWithBLOBs
testCase
)
{
testCase
.
setUpdateTime
(
System
.
currentTimeMillis
());
return
testCaseMapper
.
updateByPrimaryKeySelective
(
testCase
);
}
public
int
deleteTestCase
(
String
testCaseId
)
{
return
testCaseMapper
.
deleteByPrimaryKey
(
testCaseId
);
}
public
List
<
TestCaseWithBLOBs
>
listTestCase
(
QueryTestCaseRequest
request
)
{
TestCaseExample
testCaseExample
=
new
TestCaseExample
();
TestCaseExample
.
Criteria
criteria
=
testCaseExample
.
createCriteria
();
if
(
StringUtils
.
isNotBlank
(
request
.
getName
())
){
criteria
.
andNameLike
(
"%"
+
request
.
getName
()
+
"%"
);
};
if
(
request
.
getNodeIds
()
!=
null
&&
request
.
getNodeIds
().
size
()
>
0
){
criteria
.
andNodeIdIn
(
request
.
getNodeIds
());
}
return
testCaseMapper
.
selectByExampleWithBLOBs
(
testCaseExample
);
}
}
backend/src/main/resources/db/migration/V2__metersphere_ddl.sql
浏览文件 @
325b023c
...
...
@@ -182,3 +182,126 @@ CREATE TABLE IF NOT EXISTS `workspace` (
DEFAULT
CHARSET
=
utf8mb4
COLLATE
=
utf8mb4_bin
;
-- funcional start
CREATE
TABLE
IF
NOT
EXISTS
`fuc_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'
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COLLATE
=
utf8mb4_bin
;
CREATE
TABLE
IF
NOT
EXISTS
`fuc_test_file`
(
`test_id`
varchar
(
64
)
DEFAULT
NULL
,
`file_id`
varchar
(
64
)
DEFAULT
NULL
,
UNIQUE
KEY
`load_test_file_unique_key`
(
`test_id`
,
`file_id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'功能测试和文件的关联表'
;
CREATE
TABLE
IF
NOT
EXISTS
`fuc_test_report`
(
`id`
varchar
(
50
)
NOT
NULL
COMMENT
'Test report ID'
,
`test_id`
varchar
(
50
)
NOT
NULL
COMMENT
'Test ID this test report belongs to'
,
`name`
varchar
(
64
)
NOT
NULL
COMMENT
'Test report name'
,
`description`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'Test report name'
,
`content`
longtext
,
`create_time`
bigint
(
13
)
NOT
NULL
COMMENT
'Create timestamp'
,
`update_time`
bigint
(
13
)
NOT
NULL
COMMENT
'Update timestamp'
,
`status`
varchar
(
64
)
NOT
NULL
COMMENT
'Status of this test run'
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COLLATE
=
utf8mb4_bin
;
-- funcional end
-- track start
CREATE
TABLE
IF
NOT
EXISTS
`test_plan`
(
`id`
varchar
(
50
)
NOT
NULL
COMMENT
'Test Plan ID'
,
`project_id`
varchar
(
50
)
NOT
NULL
COMMENT
'Project ID this plan belongs to'
,
`name`
varchar
(
64
)
NOT
NULL
COMMENT
'Plan name'
,
`description`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'Plan description'
,
`status`
varchar
(
20
)
NOT
NULL
COMMENT
'Plan status'
,
`test_case_match_rule`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'Test case match rule'
,
`executor_match_rule`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'Executor match rule)'
,
`tags`
text
COMMENT
'Test plan tags (JSON format)'
,
`create_time`
bigint
(
13
)
NOT
NULL
COMMENT
'Create timestamp'
,
`update_time`
bigint
(
13
)
NOT
NULL
COMMENT
'Update timestamp'
,
PRIMARY
KEY
(
`id`
),
FOREIGN
KEY
(
`project_id`
)
references
project
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COLLATE
=
utf8mb4_bin
;
CREATE
TABLE
IF
NOT
EXISTS
`test_case_node`
(
`id`
int
(
13
)
PRIMARY
KEY
AUTO_INCREMENT
COMMENT
'Test case node ID'
,
`project_id`
varchar
(
50
)
NOT
NULL
COMMENT
'Project ID this node belongs to'
,
`name`
varchar
(
64
)
NOT
NULL
COMMENT
'Node name'
,
`p_id`
int
(
13
)
DEFAULT
NULL
COMMENT
'Parent node ID'
,
`level`
int
(
10
)
DEFAULT
1
COMMENT
'Node level'
,
`create_time`
bigint
(
13
)
NOT
NULL
COMMENT
'Create timestamp'
,
`update_time`
bigint
(
13
)
NOT
NULL
COMMENT
'Update timestamp'
,
FOREIGN
KEY
(
`p_id`
)
references
test_case_node
(
`id`
)
ON
DELETE
CASCADE
,
FOREIGN
KEY
(
`project_id`
)
references
project
(
`id`
)
)
AUTO_INCREMENT
=
1
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COLLATE
=
utf8mb4_bin
;
CREATE
TABLE
IF
NOT
EXISTS
`test_case`
(
`id`
varchar
(
50
)
NOT
NULL
COMMENT
'Test case ID'
,
`node_id`
int
(
13
)
NOT
NULL
COMMENT
'Node ID this case belongs to'
,
`project_id`
varchar
(
50
)
NOT
NULL
COMMENT
'Project ID this test belongs to'
,
`name`
varchar
(
64
)
NOT
NULL
COMMENT
'Case name'
,
`type`
varchar
(
25
)
NOT
NULL
COMMENT
'Test case type'
,
`maintainer`
varchar
(
25
)
NOT
NULL
COMMENT
'Test case maintainer'
,
`priority`
varchar
(
50
)
NOT
NULL
COMMENT
'Test case priority'
,
`method`
varchar
(
15
)
NOT
NULL
COMMENT
'Test case method type'
,
`prerequisite`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'Test case prerequisite condition'
,
`remark`
text
DEFAULT
NULL
COMMENT
'Test case remark'
,
`steps`
text
DEFAULT
NULL
COMMENT
'Test case steps (JSON format)'
,
`create_time`
bigint
(
13
)
NOT
NULL
COMMENT
'Create timestamp'
,
`update_time`
bigint
(
13
)
NOT
NULL
COMMENT
'Update timestamp'
,
PRIMARY
KEY
(
`id`
),
FOREIGN
KEY
(
`project_id`
)
references
project
(
`id`
),
FOREIGN
KEY
(
`node_id`
)
references
test_case_node
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COLLATE
=
utf8mb4_bin
;
CREATE
TABLE
IF
NOT
EXISTS
`test_plan_test_case`
(
`id`
int
(
13
)
PRIMARY
KEY
AUTO_INCREMENT
COMMENT
'ID'
,
`plan_id`
varchar
(
50
)
NOT
NULL
COMMENT
'Plan ID relation to'
,
`case_id`
varchar
(
50
)
NOT
NULL
COMMENT
'Case ID relation to'
,
`executor`
varchar
(
64
)
NOT
NULL
COMMENT
'Test case executor'
,
`status`
varchar
(
15
)
NULL
COMMENT
'Test case status'
,
`results`
longtext
COMMENT
'Test case result'
,
`remark`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'Test case remark'
,
`create_time`
bigint
(
13
)
NOT
NULL
COMMENT
'Create timestamp'
,
`update_time`
bigint
(
13
)
NOT
NULL
COMMENT
'Update timestamp'
,
FOREIGN
KEY
(
`plan_id`
)
references
test_plan
(
`id`
),
FOREIGN
KEY
(
`case_id`
)
references
test_case
(
`id`
)
)
AUTO_INCREMENT
=
1
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COLLATE
=
utf8mb4_bin
;
-- track end
backend/src/main/resources/db/migration/V4__init_funcional.sql
已删除
100644 → 0
浏览文件 @
40473911
CREATE
TABLE
IF
NOT
EXISTS
`fuc_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'
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COLLATE
=
utf8mb4_bin
;
CREATE
TABLE
IF
NOT
EXISTS
`fuc_test_file`
(
`test_id`
varchar
(
64
)
DEFAULT
NULL
,
`file_id`
varchar
(
64
)
DEFAULT
NULL
,
UNIQUE
KEY
`load_test_file_unique_key`
(
`test_id`
,
`file_id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'功能测试和文件的关联表'
;
CREATE
TABLE
IF
NOT
EXISTS
`fuc_test_report`
(
`id`
varchar
(
50
)
NOT
NULL
COMMENT
'Test report ID'
,
`test_id`
varchar
(
50
)
NOT
NULL
COMMENT
'Test ID this test report belongs to'
,
`name`
varchar
(
64
)
NOT
NULL
COMMENT
'Test report name'
,
`description`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'Test report name'
,
`content`
longtext
,
`create_time`
bigint
(
13
)
NOT
NULL
COMMENT
'Create timestamp'
,
`update_time`
bigint
(
13
)
NOT
NULL
COMMENT
'Update timestamp'
,
`status`
varchar
(
64
)
NOT
NULL
COMMENT
'Status of this test run'
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COLLATE
=
utf8mb4_bin
;
backend/src/main/resources/db/migration/V5__init_track.sql
已删除
100644 → 0
浏览文件 @
40473911
CREATE
TABLE
IF
NOT
EXISTS
`test_plan`
(
`id`
varchar
(
50
)
NOT
NULL
COMMENT
'Test Plan ID'
,
`project_id`
varchar
(
50
)
NOT
NULL
COMMENT
'Project ID this plan belongs to'
,
`name`
varchar
(
64
)
NOT
NULL
COMMENT
'Plan name'
,
`description`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'Plan description'
,
`status`
varchar
(
20
)
NOT
NULL
COMMENT
'Plan status'
,
`test_case_match_rule`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'Test case match rule'
,
`executor_match_rule`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'Executor match rule)'
,
`tags`
text
COMMENT
'Test plan tags (JSON format)'
,
`create_time`
bigint
(
13
)
NOT
NULL
COMMENT
'Create timestamp'
,
`update_time`
bigint
(
13
)
NOT
NULL
COMMENT
'Update timestamp'
,
PRIMARY
KEY
(
`id`
),
FOREIGN
KEY
(
`project_id`
)
references
project
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COLLATE
=
utf8mb4_bin
;
CREATE
TABLE
IF
NOT
EXISTS
`test_case_node`
(
`id`
int
(
13
)
PRIMARY
KEY
AUTO_INCREMENT
COMMENT
'Test case node ID'
,
`project_id`
varchar
(
50
)
NOT
NULL
COMMENT
'Project ID this node belongs to'
,
`name`
varchar
(
64
)
NOT
NULL
COMMENT
'Node name'
,
`p_id`
int
(
13
)
DEFAULT
NULL
COMMENT
'Parent node ID'
,
`level`
int
(
10
)
DEFAULT
1
COMMENT
'Node level'
,
`create_time`
bigint
(
13
)
NOT
NULL
COMMENT
'Create timestamp'
,
`update_time`
bigint
(
13
)
NOT
NULL
COMMENT
'Update timestamp'
,
FOREIGN
KEY
(
`p_id`
)
references
test_case_node
(
`id`
)
ON
DELETE
CASCADE
,
FOREIGN
KEY
(
`project_id`
)
references
project
(
`id`
)
)
AUTO_INCREMENT
=
1
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COLLATE
=
utf8mb4_bin
;
CREATE
TABLE
IF
NOT
EXISTS
`test_case`
(
`id`
varchar
(
50
)
NOT
NULL
COMMENT
'Test case ID'
,
`node_id`
int
(
13
)
NOT
NULL
COMMENT
'Node ID this case belongs to'
,
`project_id`
varchar
(
50
)
NOT
NULL
COMMENT
'Project ID this test belongs to'
,
`name`
varchar
(
64
)
NOT
NULL
COMMENT
'Case name'
,
`type`
varchar
(
25
)
NOT
NULL
COMMENT
'Test case type'
,
`priority`
varchar
(
10
)
DEFAULT
NULL
COMMENT
'Test case priority'
,
`method`
varchar
(
15
)
NOT
NULL
COMMENT
'Test case method type'
,
`prerequisite`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'Test case prerequisite condition'
,
`detail`
text
COMMENT
'Load configuration (JSON format)'
,
`steps`
text
COMMENT
'Test case steps (JSON format)'
,
`tags`
text
COMMENT
'Test case tags (JSON format)'
,
`create_time`
bigint
(
13
)
NOT
NULL
COMMENT
'Create timestamp'
,
`update_time`
bigint
(
13
)
NOT
NULL
COMMENT
'Update timestamp'
,
PRIMARY
KEY
(
`id`
),
FOREIGN
KEY
(
`project_id`
)
references
project
(
`id`
),
FOREIGN
KEY
(
`node_id`
)
references
test_case_node
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COLLATE
=
utf8mb4_bin
;
CREATE
TABLE
IF
NOT
EXISTS
`test_plan_test_case`
(
`id`
int
(
13
)
PRIMARY
KEY
AUTO_INCREMENT
COMMENT
'ID'
,
`plan_id`
varchar
(
50
)
NOT
NULL
COMMENT
'Plan ID relation to'
,
`case_id`
varchar
(
50
)
NOT
NULL
COMMENT
'Case ID relation to'
,
`executor`
varchar
(
64
)
NOT
NULL
COMMENT
'Test case executor'
,
`status`
varchar
(
15
)
NULL
COMMENT
'Test case status'
,
`results`
longtext
COMMENT
'Test case result'
,
`remark`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'Test case remark'
,
`create_time`
bigint
(
13
)
NOT
NULL
COMMENT
'Create timestamp'
,
`update_time`
bigint
(
13
)
NOT
NULL
COMMENT
'Update timestamp'
,
FOREIGN
KEY
(
`plan_id`
)
references
test_plan
(
`id`
),
FOREIGN
KEY
(
`case_id`
)
references
test_case
(
`id`
)
)
AUTO_INCREMENT
=
1
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COLLATE
=
utf8mb4_bin
;
\ No newline at end of file
frontend/src/business/components/common/head/HeaderUser.vue
浏览文件 @
325b023c
...
...
@@ -42,7 +42,7 @@
</template>
<
script
>
import
{
ROLE_ORG_ADMIN
,
ROLE_TEST_MANAGER
,
ROLE_TEST_USER
,
ROLE_TEST_VIEWER
,
TokenKey
}
from
'
../../../../common/constants
'
;
import
{
ROLE_ORG_ADMIN
,
ROLE_TEST_MANAGER
,
ROLE_TEST_USER
,
ROLE_TEST_VIEWER
,
TokenKey
,
WORKSPACE_ID
}
from
'
../../../../common/constants
'
;
import
{
hasRoles
}
from
"
../../../../common/utils
"
;
export
default
{
...
...
@@ -113,6 +113,7 @@
let
workspace
=
data
.
filter
(
r
=>
r
.
id
===
this
.
currentUser
.
lastWorkspaceId
);
if
(
workspace
.
length
>
0
)
{
this
.
currentWorkspaceName
=
workspace
[
0
].
name
;
localStorage
.
setItem
(
WORKSPACE_ID
,
workspace
[
0
].
id
);
}
}
// this.workspaceIds = response.data.map(r = r.id);
...
...
@@ -138,6 +139,7 @@
}
this
.
$post
(
"
/user/switch/source/ws/
"
+
workspaceId
,
{},
response
=>
{
localStorage
.
setItem
(
TokenKey
,
JSON
.
stringify
(
response
.
data
));
localStorage
.
setItem
(
"
workspace_id
"
,
workspaceId
);
window
.
location
.
reload
();
})
}
...
...
frontend/src/business/components/track/case/TestCase.vue
浏览文件 @
325b023c
...
...
@@ -20,95 +20,35 @@
</el-submenu>
</el-menu>
<node-tree
class=
"node_tree"
:project-id=
"currentProject.id"
@
nodeSelectEvent=
"getCaseByNodeIds"
></node-tree>
@
nodeSelectEvent=
"getCaseByNodeIds"
ref=
"nodeTree"
></node-tree>
</el-aside>
<test-case-list
@
opentestCaseEditDialog=
"opentestCaseEditDialog"
@
testCaseEdit=
"opentestCaseEditDialog"
ref=
"testCaseList"
></test-case-list>
<el-main>
<el-card>
<div
slot=
"header"
>
<el-row
type=
"flex"
justify=
"space-between"
align=
"middle"
>
<span
class=
"title"
>
{{$t('commons.test')}}
</span>
<span
class=
"search"
>
<el-input
type=
"text"
size=
"small"
:placeholder=
"$t('load_test.search_by_name')"
prefix-icon=
"el-icon-search"
maxlength=
"60"
v-model=
"condition"
@
change=
"search"
clearable
/>
</span>
</el-row>
</div>
<el-table
:data=
"tableData"
class=
"test-content"
>
<el-table-column
prop=
"name"
:label=
"$t('commons.name')"
width=
"150"
show-overflow-tooltip
>
</el-table-column>
<el-table-column
prop=
"description"
:label=
"$t('commons.description')"
show-overflow-tooltip
>
</el-table-column>
<el-table-column
prop=
"projectName"
:label=
"$t('load_test.project_name')"
width=
"150"
show-overflow-tooltip
>
</el-table-column>
<el-table-column
width=
"250"
:label=
"$t('commons.create_time')"
>
<
template
slot-scope=
"scope"
>
<span>
{{
scope
.
row
.
createTime
|
timestampFormatDate
}}
</span>
</
template
>
</el-table-column>
<el-table-column
width=
"250"
:label=
"$t('commons.update_time')"
>
<
template
slot-scope=
"scope"
>
<span>
{{
scope
.
row
.
updateTime
|
timestampFormatDate
}}
</span>
</
template
>
</el-table-column>
<el-table-column
width=
"150"
:label=
"$t('commons.operating')"
>
<
template
slot-scope=
"scope"
>
<el-button
@
click=
"handleEdit(scope.row)"
type=
"primary"
icon=
"el-icon-edit"
size=
"mini"
circle
/>
<el-button
@
click=
"handleDelete(scope.row)"
type=
"danger"
icon=
"el-icon-delete"
size=
"mini"
circle
/>
</
template
>
</el-table-column>
</el-table>
<div>
<el-row>
<el-col
:span=
"22"
:offset=
"1"
>
<div
class=
"table-page"
>
<el-pagination
@
size-change=
"handleSizeChange"
@
current-change=
"handleCurrentChange"
:current-page.sync=
"currentPage"
:page-sizes=
"[5, 10, 20, 50, 100]"
:page-size=
"pageSize"
layout=
"total, sizes, prev, pager, next, jumper"
:total=
"total"
>
</el-pagination>
</div>
</el-col>
</el-row>
</div>
</el-card>
</el-main>
</el-container>
<test-case-edit
:project-id=
"currentProject.id"
@
refresh=
"getCaseByNodeIds"
ref=
"testCaseEditDialog"
></test-case-edit>
</div>
</template>
<
script
>
import
NodeTree
from
'
./components/NodeTree
'
;
import
TestCaseEdit
from
'
./components/TestCaseEdit
'
;
import
{
WORKSPACE_ID
}
from
'
../../../../common/constants
'
;
import
TestCaseList
from
"
./components/TestCaseList
"
;
export
default
{
name
:
"
TestCase
"
,
components
:
{
NodeTree
},
components
:
{
TestCaseList
,
NodeTree
,
TestCaseEdit
},
comments
:
{},
data
()
{
return
{
...
...
@@ -127,36 +67,15 @@
projects
:
[],
initProjects
:
[],
currentProject
:
null
,
}
},
watch
:
{
'
$route
'
(
to
)
{
this
.
projectId
=
to
.
params
.
projectId
;
this
.
initTableData
();
treeNodes
:
[]
}
},
created
:
function
()
{
this
.
projectId
=
this
.
$route
.
params
.
projectId
;
this
.
initTableData
();
this
.
getProjects
();
},
methods
:
{
initTableData
()
{
let
param
=
{
name
:
this
.
condition
,
};
if
(
this
.
projectId
!==
'
all
'
)
{
param
.
projectId
=
this
.
projectId
;
}
this
.
result
=
this
.
$post
(
this
.
buildPagePath
(
this
.
queryPath
),
param
,
response
=>
{
this
.
loadingRequire
.
testCase
=
false
;
let
data
=
response
.
data
;
this
.
total
=
data
.
itemCount
;
this
.
tableData
=
data
.
listObject
;
});
},
getProjects
()
{
this
.
$get
(
"
/project/listAll
"
,
(
response
)
=>
{
if
(
response
.
success
)
{
...
...
@@ -175,51 +94,6 @@
});
},
search
()
{
this
.
initTableData
();
},
buildPagePath
(
path
)
{
return
path
+
"
/
"
+
this
.
currentPage
+
"
/
"
+
this
.
pageSize
;
},
handleSizeChange
(
size
)
{
this
.
pageSize
=
size
;
this
.
initTableData
();
},
handleCurrentChange
(
current
)
{
this
.
currentPage
=
current
;
this
.
initTableData
();
},
handleSelectionChange
(
val
)
{
this
.
multipleSelection
=
val
;
},
handleEdit
(
testPlan
)
{
this
.
$router
.
push
({
path
:
'
/performance/plan/edit/
'
+
testPlan
.
id
,
})
},
handleDelete
(
testPlan
)
{
this
.
$alert
(
this
.
$t
(
'
load_test.delete_confirm
'
)
+
testPlan
.
name
+
"
?
"
,
''
,
{
confirmButtonText
:
this
.
$t
(
'
commons.confirm
'
),
callback
:
(
action
)
=>
{
if
(
action
===
'
confirm
'
)
{
this
.
_handleDelete
(
testPlan
);
}
}
});
},
_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
();
});
},
checkProject
()
{
if
(
this
.
currentProject
===
null
)
{
this
.
$alert
(
'
该工作空间下无项目,请先创建项目
'
,
'
创建项目
'
,
{
...
...
@@ -234,9 +108,36 @@
this
.
currentProject
=
project
;
},
getCaseByNodeIds
(
data
)
{
console
.
log
(
data
);
this
.
$refs
.
testCaseList
.
initTableData
(
data
);
},
opentestCaseEditDialog
(
data
)
{
this
.
setNodePathOption
(
this
.
$refs
.
nodeTree
.
treeNodes
);
this
.
setMaintainerOptions
();
this
.
$refs
.
testCaseEditDialog
.
opentestCaseEditDialog
(
data
);
},
setNodePathOption
(
nodes
)
{
let
moduleOptions
=
[];
nodes
.
forEach
(
node
=>
{
this
.
buildNodePath
(
node
,
{
path
:
''
},
moduleOptions
);
});
this
.
$refs
.
testCaseEditDialog
.
moduleOptions
=
moduleOptions
;
},
buildNodePath
(
node
,
option
,
moduleOptions
)
{
//递归构建节点路径
option
.
id
=
node
.
id
;
option
.
path
=
option
.
path
+
'
/
'
+
node
.
name
;
moduleOptions
.
push
(
option
);
if
(
node
.
children
){
for
(
let
i
=
0
;
i
<
node
.
children
.
length
;
i
++
){
this
.
buildNodePath
(
node
.
children
[
i
],
{
path
:
'
/
'
+
node
.
children
[
i
].
name
},
moduleOptions
);
}
}
},
setMaintainerOptions
()
{
let
workspaceId
=
localStorage
.
getItem
(
WORKSPACE_ID
);
this
.
$post
(
'
/user/ws/member/list/all
'
,
{
workspaceId
:
workspaceId
},
response
=>
{
this
.
$refs
.
testCaseEditDialog
.
maintainerOptions
=
response
.
data
;
});
}
}
}
...
...
@@ -271,7 +172,6 @@
}
.node_tree
{
/*box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04);*/
margin
:
10%
;
}
...
...
@@ -280,4 +180,9 @@
margin-left
:
20px
;
height
:
50px
;
}
.case_container
{
height
:
600px
;
}
</
style
>
frontend/src/business/components/track/case/components/NodeTree.vue
浏览文件 @
325b023c
...
...
@@ -80,13 +80,6 @@
},
form
:
{
name
:
''
,
region
:
''
,
date1
:
''
,
date2
:
''
,
delivery
:
false
,
type
:
[],
resource
:
''
,
desc
:
''
},
formLabelWidth
:
'
80px
'
,
dialogTableVisible
:
false
,
...
...
@@ -249,16 +242,6 @@
margin-top
:
15px
;
}
.node-dropdown
{
/*align-items: right;*/
/*margin-left: 50px;*/
/*color: darkgrey;*/
/*opacity:0.1;*/
/*filter:alpha(opacity=1); !* 针对 IE8 以及更早的版本 *!*/
}
.father
.child
{
display
:
none
;
}
...
...
frontend/src/business/components/track/case/components/TestCaseEdit.vue
0 → 100644
浏览文件 @
325b023c
<
template
>
<div>
<el-dialog
title=
"新建用例"
:visible.sync=
"dialogFormVisible"
width=
"65%"
>
<el-form
:model=
"form"
:rules=
"rules"
ref=
"caseFrom"
>
<el-row>
<el-col
:span=
"8"
:offset=
"1"
>
<el-form-item
placeholder=
"请输入内容"
label=
"用例名称"
:label-width=
"formLabelWidth"
prop=
"name"
>
<el-input
v-model=
"form.name"
></el-input>
</el-form-item>
</el-col>
<el-col
:span=
"11"
:offset=
"2"
>
<el-form-item
label=
"所属模块"
:label-width=
"formLabelWidth"
prop=
"module"
>
<el-select
v-model=
"form.module"
placeholder=
"请选择模块"
filterable
>
<el-option
v-for=
"item in moduleOptions"
:key=
"item.id"
:label=
"item.path"
:value=
"item.id"
>
</el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col
:span=
"10"
:offset=
"1"
>
<el-form-item
label=
"维护人"
:label-width=
"formLabelWidth"
prop=
"maintainer"
>
<el-select
v-model=
"form.maintainer"
placeholder=
"请选择维护人"
filterable
>
<el-option
v-for=
"item in maintainerOptions"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
>
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
label=
"优先级"
:label-width=
"formLabelWidth"
prop=
"priority"
>
<el-select
v-model=
"form.priority"
clearable
placeholder=
"请选择优先级"
>
<el-option
label=
"P0"
value=
"P0"
></el-option>
<el-option
label=
"P1"
value=
"P1"
></el-option>
<el-option
label=
"P2"
value=
"P2"
></el-option>
<el-option
label=
"P3"
value=
"P3"
></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col
:span=
"10"
:offset=
"1"
>
<el-form-item
label=
"用例类型"
:label-width=
"formLabelWidth"
prop=
"type"
>
<el-select
v-model=
"form.type"
placeholder=
"请选择用例类型"
>
<el-option
label=
"功能测试"
value=
"functional"
></el-option>
<el-option
label=
"性能测试"
value=
"performance"
></el-option>
<el-option
label=
"接口测试"
value=
"interface"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
label=
"测试方式"
:label-width=
"formLabelWidth"
prop=
"method"
>
<el-select
v-model=
"form.method"
placeholder=
"请选择测试方式"
>
<el-option
label=
"手动"
value=
"manual"
></el-option>
<el-option
label=
"自动"
value=
"auto"
></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row
style=
"margin-top: 15px;"
>
<el-col
:offset=
"2"
>
前置条件:
</el-col>
</el-row>
<el-row
type=
"flex"
justify=
"center"
style=
"margin-top: 10px;"
>
<el-col
:span=
"20"
>
<el-form-item>
<el-input
v-model=
"form.prerequisite"
type=
"textarea"
:autosize=
"
{ minRows: 2, maxRows: 4}"
:rows="2"
placeholder="请输入前置条件">
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row
style=
"margin-bottom: 10px"
>
<el-col
:offset=
"2"
>
执行步骤:
</el-col>
</el-row>
<el-row
type=
"flex"
justify=
"center"
>
<el-col
:span=
"20"
>
<el-table
:data=
"form.steps"
class=
"tb-edit"
border
:default-sort =
"
{prop: 'num', order: 'ascending'}"
highlight-current-row>
<el-table-column
label=
"编号"
prop=
"num"
min-width=
"15%"
></el-table-column>
<el-table-column
label=
"步骤描述"
prop=
"desc"
min-width=
"35%"
>
<template
slot-scope=
"scope"
>
<el-input
size=
"small"
v-model=
"scope.row.desc"
placeholder=
"请输入内容"
clearable
></el-input>
<span>
{{
scope
.
row
.
desc
}}
</span>
</
template
>
</el-table-column>
<el-table-column
label=
"预期结果"
prop=
"result"
min-width=
"35%"
>
<
template
slot-scope=
"scope"
>
<el-input
size=
"small"
v-model=
"scope.row.result"
placeholder=
"请输入内容"
clearable
></el-input>
<span>
{{
scope
.
row
.
result
}}
</span>
</
template
>
</el-table-column>
<el-table-column
label=
"操作"
min-width=
"15%"
>
<
template
slot-scope=
"scope"
>
<el-button
type=
"primary"
icon=
"el-icon-plus"
circle
size=
"mini"
@
click=
"handleAddStep(scope.$index, scope.row)"
></el-button>
<el-button
type=
"danger"
icon=
"el-icon-delete"
circle
size=
"mini"
@
click=
"handleDeleteStep(scope.$index, scope.row)"
:disabled=
"scope.$index == 0 ? true : false"
></el-button>
</
template
>
</el-table-column>
</el-table>
</el-col>
</el-row>
<el-row
style=
"margin-top: 15px;margin-bottom: 10px"
>
<el-col
:offset=
"2"
>
备注:
</el-col>
</el-row>
<el-row
type=
"flex"
justify=
"center"
>
<el-col
:span=
"20"
>
<el-form-item>
<el-input
v-model=
"form.remark"
:autosize=
"{ minRows: 2, maxRows: 4}"
type=
"textarea"
:rows=
"2"
placeholder=
"请输入内容"
></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div
slot=
"footer"
class=
"dialog-footer"
>
<el-button
@
click=
"dialogFormVisible = false"
>
取 消
</el-button>
<el-button
type=
"primary"
@
click=
"saveCase"
>
确 定
</el-button>
</div>
</el-dialog>
</div>
</template>
<
script
>
export
default
{
name
:
"
CreateCaseDialog
"
,
data
()
{
return
{
dialogFormVisible
:
false
,
form
:
{
name
:
''
,
module
:
''
,
maintainer
:
''
,
priority
:
''
,
type
:
''
,
method
:
''
,
prerequisite
:
''
,
steps
:
[{
num
:
1
,
desc
:
''
,
result
:
''
}],
remark
:
''
,
},
moduleOptions
:
[],
maintainerOptions
:
[],
rules
:{
name
:[{
required
:
true
,
message
:
'
请输入用例名称
'
,
trigger
:
'
blur
'
}],
module
:[{
required
:
true
,
message
:
'
请选择模块
'
,
trigger
:
'
change
'
}],
maintainer
:[{
required
:
true
,
message
:
'
请选择维护人
'
,
trigger
:
'
change
'
}],
priority
:[{
required
:
true
,
message
:
'
请选择优先级
'
,
trigger
:
'
change
'
}],
type
:[{
required
:
true
,
message
:
'
请选择用例类型
'
,
trigger
:
'
change
'
}],
method
:[{
required
:
true
,
message
:
'
请选择测试方式
'
,
trigger
:
'
change
'
}]
},
formLabelWidth
:
"
120px
"
,
operationType
:
''
};
},
props
:
{
projectId
:
null
},
methods
:
{
opentestCaseEditDialog
(
testCase
)
{
this
.
resetForm
();
this
.
operationType
=
'
add
'
;
if
(
testCase
){
//修改
this
.
operationType
=
'
edit
'
;
let
tmp
=
{};
Object
.
assign
(
tmp
,
testCase
);
tmp
.
steps
=
JSON
.
parse
(
testCase
.
steps
);
Object
.
assign
(
this
.
form
,
tmp
);
this
.
form
.
module
=
testCase
.
nodeId
;
}
this
.
dialogFormVisible
=
true
;
},
handleAddStep
(
index
,
data
)
{
let
step
=
{};
step
.
num
=
data
.
num
+
1
;
step
.
desc
=
null
;
step
.
result
=
null
;
this
.
form
.
steps
.
forEach
(
step
=>
{
if
(
step
.
num
>
data
.
num
){
step
.
num
++
;
}
});
this
.
form
.
steps
.
push
(
step
);
},
handleDeleteStep
(
index
,
data
)
{
this
.
form
.
steps
.
splice
(
index
,
1
);
this
.
form
.
steps
.
forEach
(
step
=>
{
if
(
step
.
num
>
data
.
num
){
step
.
num
--
;
}
});
},
saveCase
(){
this
.
$refs
[
'
caseFrom
'
].
validate
((
valid
)
=>
{
if
(
valid
)
{
let
param
=
{};
Object
.
assign
(
param
,
this
.
form
);
param
.
steps
=
JSON
.
stringify
(
this
.
form
.
steps
);
param
.
nodeId
=
this
.
form
.
module
;
param
.
projectId
=
this
.
projectId
;
this
.
$post
(
'
/test/case/
'
+
this
.
operationType
,
param
,
()
=>
{
this
.
$message
.
success
(
"
保存成功!
"
);
this
.
resetForm
();
this
.
dialogFormVisible
=
false
;
this
.
$emit
(
"
refresh
"
);
});
}
else
{
return
false
;
}
});
}
,
resetForm
()
{
if
(
this
.
$refs
[
'
caseFrom
'
])
{
this
.
$refs
[
'
caseFrom
'
].
resetFields
();
}
this
.
form
.
name
=
''
;
this
.
form
.
module
=
''
;
this
.
form
.
type
=
''
;
this
.
form
.
method
=
''
;
this
.
form
.
maintainer
=
''
;
this
.
form
.
priority
=
''
;
this
.
form
.
prerequisite
=
''
;
this
.
form
.
remark
=
''
;
this
.
form
.
steps
=
[{
num
:
1
,
desc
:
''
,
result
:
''
}];
}
}
}
</
script
>
<
style
scoped
>
.tb-edit
.el-input
{
display
:
none
;
color
:
black
;
}
.tb-edit
.current-row
.el-input
{
display
:
block
;
}
.tb-edit
.current-row
.el-input
+
span
{
display
:
none
;
}
</
style
>
frontend/src/business/components/track/case/components/TestCaseList.vue
0 → 100644
浏览文件 @
325b023c
<
template
>
<el-main>
<el-card>
<div
slot=
"header"
>
<el-row
type=
"flex"
justify=
"space-between"
align=
"middle"
>
<el-col
:span=
"5"
>
<span
class=
"title"
>
{{
$t
(
'
test_track.test_case
'
)
}}
</span>
</el-col>
<el-col
:span=
"1"
:offset=
"8"
>
<el-button
icon=
"el-icon-circle-plus-outline"
size=
"small"
round
@
click=
"opentestCaseEditDialog"
>
新建
</el-button>
</el-col>
<el-col
:span=
"1"
>
<el-button
icon=
"el-icon-refresh"
size=
"small"
round
@
click=
"initTableData(null)"
>
刷新
</el-button>
</el-col>
<el-col
:span=
"5"
>
<span
class=
"search"
>
<el-input
type=
"text"
size=
"small"
:placeholder=
"$t('load_test.search_by_name')"
prefix-icon=
"el-icon-search"
maxlength=
"60"
v-model=
"condition"
@
change=
"search"
clearable
/>
</span>
</el-col>
</el-row>
</div>
<el-table
:data=
"tableData"
class=
"test-content"
>
<el-table-column
prop=
"name"
:label=
"$t('commons.name')"
width=
"130"
show-overflow-tooltip
>
</el-table-column>
<el-table-column
prop=
"priority"
label=
"优先级"
width=
"130"
show-overflow-tooltip
>
</el-table-column>
<el-table-column
prop=
"type"
label=
"类型"
width=
"130"
show-overflow-tooltip
>
<template
slot-scope=
"scope"
>
<span
v-if=
"scope.row.type == 'functional'"
>
功能测试
</span>
<span
v-if=
"scope.row.type == 'performance'"
>
性能测试
</span>
<span
v-if=
"scope.row.type == 'interface'"
>
接口测试
</span>
</
template
>
</el-table-column>
<el-table-column
prop=
"method"
label=
"测试方式"
width=
"130"
show-overflow-tooltip
>
<
template
slot-scope=
"scope"
>
<span
v-if=
"scope.row.method == 'manual'"
>
手动
</span>
<span
v-if=
"scope.row.method == 'auto'"
>
自动
</span>
</
template
>
</el-table-column>
<el-table-column
prop=
"remark"
label=
"备注"
width=
"160"
show-overflow-tooltip
>
</el-table-column>
<el-table-column
width=
"160"
:label=
"$t('commons.create_time')"
>
<
template
slot-scope=
"scope"
>
<span>
{{
scope
.
row
.
createTime
|
timestampFormatDate
}}
</span>
</
template
>
</el-table-column>
<el-table-column
width=
"160"
:label=
"$t('commons.update_time')"
>
<
template
slot-scope=
"scope"
>
<span>
{{
scope
.
row
.
updateTime
|
timestampFormatDate
}}
</span>
</
template
>
</el-table-column>
<el-table-column
width=
"160"
:label=
"$t('commons.operating')"
>
<
template
slot-scope=
"scope"
>
<el-button
@
click=
"handleEdit(scope.row)"
type=
"primary"
icon=
"el-icon-edit"
size=
"mini"
circle
/>
<el-button
@
click=
"handleDelete(scope.row)"
type=
"danger"
icon=
"el-icon-delete"
size=
"mini"
circle
/>
</
template
>
</el-table-column>
</el-table>
<div>
<el-row>
<el-col
:span=
"22"
:offset=
"1"
>
<div
class=
"table-page"
>
<el-pagination
@
size-change=
"handleSizeChange"
@
current-change=
"handleCurrentChange"
:current-page.sync=
"currentPage"
:page-sizes=
"[5, 10, 20, 50, 100]"
:page-size=
"pageSize"
layout=
"total, sizes, prev, pager, next, jumper"
:total=
"total"
>
</el-pagination>
</div>
</el-col>
</el-row>
</div>
</el-card>
</el-main>
</template>
<
script
>
export
default
{
name
:
"
TestCaseList
"
,
data
()
{
return
{
result
:
{},
deletePath
:
"
/test/case/delete
"
,
condition
:
""
,
tableData
:
[],
multipleSelection
:
[],
currentPage
:
1
,
pageSize
:
5
,
total
:
0
,
loadingRequire
:
{
project
:
true
,
testCase
:
true
},
testId
:
null
,
}
},
created
:
function
()
{
this
.
projectId
=
this
.
$route
.
params
.
projectId
;
this
.
initTableData
(
null
);
},
methods
:
{
initTableData
(
nodeIds
)
{
let
param
=
{
name
:
this
.
condition
,
};
param
.
nodeIds
=
nodeIds
;
this
.
$post
(
this
.
buildPagePath
(
'
/test/case/list
'
),
param
,
response
=>
{
this
.
loadingRequire
.
testCase
=
false
;
let
data
=
response
.
data
;
this
.
total
=
data
.
itemCount
;
this
.
tableData
=
data
.
listObject
;
});
},
search
()
{
this
.
initTableData
(
null
);
},
buildPagePath
(
path
)
{
return
path
+
"
/
"
+
this
.
currentPage
+
"
/
"
+
this
.
pageSize
;
},
handleSizeChange
(
size
)
{
this
.
pageSize
=
size
;
this
.
initTableData
(
null
);
},
handleCurrentChange
(
current
)
{
this
.
currentPage
=
current
;
this
.
initTableData
(
null
);
},
handleSelectionChange
(
val
)
{
this
.
multipleSelection
=
val
;
},
handleEdit
(
testCase
)
{
this
.
$emit
(
'
testCaseEdit
'
,
testCase
);
},
handleDelete
(
testCase
)
{
this
.
$alert
(
this
.
$t
(
'
load_test.delete_confirm
'
)
+
testCase
.
name
+
"
?
"
,
''
,
{
confirmButtonText
:
this
.
$t
(
'
commons.confirm
'
),
callback
:
(
action
)
=>
{
if
(
action
===
'
confirm
'
)
{
this
.
_handleDelete
(
testCase
);
}
}
});
},
_handleDelete
(
testCase
)
{
let
testCaseId
=
testCase
.
id
this
.
$post
(
'
/test/case/delete/
'
+
testCaseId
,
{},
()
=>
{
this
.
initTableData
(
null
);
this
.
$message
({
message
:
this
.
$t
(
'
commons.delete_success
'
),
type
:
'
success
'
});
});
},
opentestCaseEditDialog
()
{
this
.
$emit
(
'
opentestCaseEditDialog
'
);
}
}
}
</
script
>
<
style
scoped
>
</
style
>
frontend/src/common/constants.js
浏览文件 @
325b023c
...
...
@@ -5,3 +5,5 @@ export const ROLE_ORG_ADMIN = 'org_admin';
export
const
ROLE_TEST_MANAGER
=
'
test_manager
'
;
export
const
ROLE_TEST_USER
=
'
test_user
'
;
export
const
ROLE_TEST_VIEWER
=
'
test_viewer
'
;
export
const
WORKSPACE_ID
=
'
workspace_id
'
;
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录