Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
MeterSphere
metersphere
提交
c6e384cd
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,发现更多精彩内容 >>
提交
c6e384cd
编写于
4月 02, 2020
作者:
C
chenjianxing
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
测试计划详情
上级
192b4fe4
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
507 addition
and
9 deletion
+507
-9
backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestCaseMapper.java
...ava/io/metersphere/base/mapper/ext/ExtTestCaseMapper.java
+14
-0
backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestCaseMapper.xml
...java/io/metersphere/base/mapper/ext/ExtTestCaseMapper.xml
+23
-0
backend/src/main/java/io/metersphere/controller/TestCaseController.java
...in/java/io/metersphere/controller/TestCaseController.java
+5
-0
backend/src/main/java/io/metersphere/controller/request/testcase/QueryTestCaseRequest.java
...ere/controller/request/testcase/QueryTestCaseRequest.java
+10
-0
backend/src/main/java/io/metersphere/service/TestCaseService.java
...src/main/java/io/metersphere/service/TestCaseService.java
+18
-0
frontend/src/business/components/track/case/TestCase.vue
frontend/src/business/components/track/case/TestCase.vue
+1
-3
frontend/src/business/components/track/plan/TestPlanView.vue
frontend/src/business/components/track/plan/TestPlanView.vue
+20
-2
frontend/src/business/components/track/plan/components/PlanNodeTree.vue
...usiness/components/track/plan/components/PlanNodeTree.vue
+0
-4
frontend/src/business/components/track/plan/components/TestCasePlanList.vue
...ess/components/track/plan/components/TestCasePlanList.vue
+215
-0
frontend/src/business/components/track/plan/components/TestCaseRelevance.vue
...ss/components/track/plan/components/TestCaseRelevance.vue
+201
-0
未找到文件。
backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestCaseMapper.java
0 → 100644
浏览文件 @
c6e384cd
package
io.metersphere.base.mapper.ext
;
import
io.metersphere.base.domain.TestCase
;
import
io.metersphere.controller.request.ReportRequest
;
import
io.metersphere.controller.request.testcase.QueryTestCaseRequest
;
import
io.metersphere.dto.ReportDTO
;
import
org.apache.ibatis.annotations.Param
;
import
java.util.List
;
public
interface
ExtTestCaseMapper
{
List
<
TestCase
>
getTestCaseNames
(
@Param
(
"request"
)
QueryTestCaseRequest
request
);
}
backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestCaseMapper.xml
0 → 100644
浏览文件 @
c6e384cd
<?xml version="1.0" encoding="UTF-8" ?>
<!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.ExtTestCaseMapper"
>
<select
id=
"getTestCaseNames"
resultType=
"io.metersphere.base.domain.TestCase"
>
select test_case.id, test_case.name
from test_case
<where>
<if
test=
"request.projectId != null"
>
AND test_case.project_id = #{request.projectId}
</if>
<if
test=
"request.nodeIds != null and request.nodeIds.size() > 0"
>
AND test_case.node_id IN
<foreach
collection=
"request.nodeIds"
open=
"("
close=
")"
separator=
","
item=
"nodeId"
>
#{nodeId}
</foreach>
</if>
</where>
ORDER BY test_case.update_time DESC
</select>
</mapper>
\ No newline at end of file
backend/src/main/java/io/metersphere/controller/TestCaseController.java
浏览文件 @
c6e384cd
...
...
@@ -38,6 +38,11 @@ public class TestCaseController {
return
testCaseService
.
getTestCaseByNodeId
(
nodeIds
);
}
@PostMapping
(
"/name/all"
)
public
List
<
TestCase
>
getTestCaseNames
(
@RequestBody
QueryTestCaseRequest
request
){
return
testCaseService
.
getTestCaseNames
(
request
);
}
@PostMapping
(
"/get/{testCaseId}"
)
public
List
<
TestCaseWithBLOBs
>
getTestCase
(
@PathVariable
String
testCaseId
){
return
testCaseService
.
getTestCase
(
testCaseId
);
...
...
backend/src/main/java/io/metersphere/controller/request/testcase/QueryTestCaseRequest.java
浏览文件 @
c6e384cd
...
...
@@ -8,6 +8,16 @@ public class QueryTestCaseRequest extends TestCase {
List
<
Integer
>
nodeIds
;
String
planId
;
public
String
getPlanId
()
{
return
planId
;
}
public
void
setPlanId
(
String
planId
)
{
this
.
planId
=
planId
;
}
public
List
<
Integer
>
getNodeIds
()
{
return
nodeIds
;
}
...
...
backend/src/main/java/io/metersphere/service/TestCaseService.java
浏览文件 @
c6e384cd
...
...
@@ -4,7 +4,10 @@ package io.metersphere.service;
import
io.metersphere.base.domain.TestCase
;
import
io.metersphere.base.domain.TestCaseExample
;
import
io.metersphere.base.domain.TestCaseWithBLOBs
;
import
io.metersphere.base.domain.TestPlan
;
import
io.metersphere.base.mapper.TestCaseMapper
;
import
io.metersphere.base.mapper.TestPlanMapper
;
import
io.metersphere.base.mapper.ext.ExtTestCaseMapper
;
import
io.metersphere.controller.request.testcase.QueryTestCaseRequest
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.stereotype.Service
;
...
...
@@ -21,6 +24,12 @@ public class TestCaseService {
@Resource
TestCaseMapper
testCaseMapper
;
@Resource
ExtTestCaseMapper
extTestCaseMapper
;
@Resource
TestPlanMapper
testPlanMapper
;
public
void
addTestCase
(
TestCaseWithBLOBs
testCase
)
{
testCase
.
setId
(
UUID
.
randomUUID
().
toString
());
testCase
.
setCreateTime
(
System
.
currentTimeMillis
());
...
...
@@ -63,4 +72,13 @@ public class TestCaseService {
}
return
testCaseMapper
.
selectByExampleWithBLOBs
(
testCaseExample
);
}
public
List
<
TestCase
>
getTestCaseNames
(
QueryTestCaseRequest
request
)
{
TestPlan
testPlan
=
testPlanMapper
.
selectByPrimaryKey
(
request
.
getPlanId
());
request
.
setProjectId
(
testPlan
.
getProjectId
());
return
extTestCaseMapper
.
getTestCaseNames
(
request
);
}
}
frontend/src/business/components/track/case/TestCase.vue
浏览文件 @
c6e384cd
...
...
@@ -5,7 +5,7 @@
<el-menu
:unique-opened=
"true"
mode=
"horizontal"
active-text-color=
"write"
class=
"project_menu"
>
<el-submenu
index=
"1"
popper-class=
"submenu"
v-permission=
"['test_user', 'test_viewer']"
>
<el-submenu
index=
"1"
popper-class=
"submenu"
>
<template
slot=
"title"
>
{{
currentProject
==
null
?
''
:
currentProject
.
name
}}
</
template
>
...
...
@@ -78,8 +78,6 @@
},
watch
:
{
'
$route
'
(
to
,
from
)
{
console
.
log
(
from
);
console
.
log
(
to
);
if
(
from
.
name
.
indexOf
(
"
Project
"
)
>
0
){
this
.
getProjects
();
}
...
...
frontend/src/business/components/track/plan/TestPlanView.vue
浏览文件 @
c6e384cd
...
...
@@ -7,11 +7,20 @@
:plan-id=
"planId"
class=
"node_tree"
@
nodeSelectEvent=
"get"
@
refresh=
"refresh"
ref=
"nodeTree"
></plan-node-tree>
</el-aside>
<el-main>
<test-case-plan-list
@
openTestCaseRelevanceDialog=
"openTestCaseRelevanceDialog"
ref=
"testCasePlanList"
></test-case-plan-list>
</el-main>
</el-container>
<test-case-relevance
@
refresh=
"getCaseByNodeIds"
ref=
"testCaseRelevance"
></test-case-relevance>
</div>
</
template
>
...
...
@@ -19,10 +28,12 @@
<
script
>
import
PlanNodeTree
from
"
./components/PlanNodeTree
"
;
import
TestCasePlanList
from
"
./components/TestCasePlanList
"
;
import
TestCaseRelevance
from
"
./components/TestCaseRelevance
"
;
export
default
{
name
:
"
TestPlanView
"
,
components
:
{
PlanNodeTree
},
components
:
{
PlanNodeTree
,
TestCasePlanList
,
TestCaseRelevance
},
data
()
{
return
{
currentProject
:
{}
...
...
@@ -39,6 +50,13 @@
},
get
()
{
},
openTestCaseRelevanceDialog
(
data
)
{
this
.
$refs
.
testCaseRelevance
.
dialogFormVisible
=
true
;
this
.
$refs
.
testCaseRelevance
.
getCaseNames
(
this
.
planId
);
},
getCaseByNodeIds
()
{
}
}
}
...
...
frontend/src/business/components/track/plan/components/PlanNodeTree.vue
浏览文件 @
c6e384cd
...
...
@@ -12,12 +12,10 @@
:expand-on-click-node=
"false"
draggable
ref=
"tree"
>
<span
class=
"custom-tree-node father"
slot-scope=
"
{node}" @click="selectNode(node)">
{{
node
.
label
}}
</span>
</el-tree>
</div>
...
...
@@ -56,8 +54,6 @@
}
},
created
()
{
console
.
log
(
"
created
"
);
console
.
log
(
this
.
planId
);
this
.
getNodeTree
();
},
methods
:
{
...
...
frontend/src/business/components/track/plan/components/TestCasePlanList.vue
0 → 100644
浏览文件 @
c6e384cd
<
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=
"$emit('openTestCaseRelevanceDialog')"
>
{{
$t
(
'
commons.create
'
)
}}
</el-button>
</el-col>
<el-col
:span=
"1"
>
<el-button
icon=
"el-icon-refresh"
size=
"small"
round
@
click=
"initTableData()"
>
{{
$t
(
'
commons.refresh
'
)
}}
</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=
"120"
show-overflow-tooltip
>
</el-table-column>
<el-table-column
prop=
"priority"
:label=
"$t('test_track.priority')"
width=
"120"
show-overflow-tooltip
>
</el-table-column>
<el-table-column
prop=
"type"
:label=
"$t('test_track.type')"
width=
"120"
show-overflow-tooltip
>
<template
slot-scope=
"scope"
>
<span
v-if=
"scope.row.type == 'functional'"
>
{{
$t
(
'
commons.functional
'
)
}}
</span>
<span
v-if=
"scope.row.type == 'performance'"
>
{{
$t
(
'
commons.performance
'
)
}}
</span>
<span
v-if=
"scope.row.type == 'interface'"
>
{{
$t
(
'
commons.interface
'
)
}}
</span>
</
template
>
</el-table-column>
<el-table-column
prop=
"method"
:label=
"$t('test_track.method')"
width=
"120"
show-overflow-tooltip
>
<
template
slot-scope=
"scope"
>
<span
v-if=
"scope.row.method == 'manual'"
>
{{
$t
(
'
test_track.manual
'
)
}}
</span>
<span
v-if=
"scope.row.method == 'auto'"
>
{{
$t
(
'
test_track.auto
'
)
}}
</span>
</
template
>
</el-table-column>
<el-table-column
prop=
"nodePath"
:label=
"$t('test_track.module')"
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=
"100"
: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
>
import
{
CURRENT_PROJECT
}
from
'
../../../../../common/constants
'
;
import
PlanNodeTree
from
'
./PlanNodeTree
'
;
export
default
{
name
:
"
TestCaseList
"
,
components
:
{
PlanNodeTree
},
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
.
initTableData
();
},
methods
:
{
initTableData
(
nodeIds
)
{
let
param
=
{
name
:
this
.
condition
,
};
param
.
nodeIds
=
nodeIds
;
if
(
localStorage
.
getItem
(
CURRENT_PROJECT
))
{
param
.
projectId
=
JSON
.
parse
(
localStorage
.
getItem
(
CURRENT_PROJECT
)).
id
;
}
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
();
},
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
(
testCase
)
{
this
.
$emit
(
'
testCaseRelevance
'
,
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
();
this
.
$message
({
message
:
this
.
$t
(
'
commons.delete_success
'
),
type
:
'
success
'
});
});
}
}
}
</
script
>
<
style
scoped
>
.table-page
{
padding-top
:
20px
;
margin-right
:
-9px
;
float
:
right
;
}
</
style
>
frontend/src/business/components/track/plan/components/TestCaseRelevance.vue
0 → 100644
浏览文件 @
c6e384cd
<
template
>
<div>
<el-dialog
:title=
"$t('test_track.create')"
:visible.sync=
"dialogFormVisible"
width=
"65%"
>
<el-container
style=
"min-height: 350px"
>
<el-aside
class=
"node_tree"
width=
"200px"
style=
"background-color: rgb(238, 241, 246)"
>
<plan-node-tree></plan-node-tree>
</el-aside>
<el-container>
<el-header
>
<el-checkbox
></el-checkbox>
</el-header>
<el-main
style=
"height: 100px;"
>
<el-scrollbar
style=
"height:100%"
>
<el-table
:data=
"testCases"
>
<el-table-column
prop=
"name"
style=
"width: 100%"
>
<template
slot=
"header"
>
<el-checkbox
v-model=
"checkAll"
></el-checkbox>
用例名称
</
template
>
<
template
slot-scope=
"scope"
>
<el-checkbox
v-model=
"scope.row.checked"
></el-checkbox>
{{
scope
.
row
.
name
}}
</
template
>
</el-table-column>
</el-table>
</el-scrollbar>
</el-main>
</el-container>
</el-container>
<div
slot=
"footer"
class=
"dialog-footer"
>
<el-button
@
click=
"dialogFormVisible = false"
>
{{$t('test_track.cancel')}}
</el-button>
<el-button
type=
"primary"
@
click=
"saveCase"
>
{{$t('test_track.confirm')}}
</el-button>
</div>
</el-dialog>
</div>
</template>
<
script
>
import
{
CURRENT_PROJECT
}
from
'
../../../../../common/constants
'
;
import
PlanNodeTree
from
'
./PlanNodeTree
'
;
export
default
{
name
:
"
TestCaseEdit
"
,
components
:
{
PlanNodeTree
},
data
()
{
return
{
dialogFormVisible
:
false
,
count
:
6
,
checkAll
:
false
,
testCases
:
[],
form
:
{
name
:
''
,
}
};
},
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
[
'
relevanceFrom
'
].
validate
((
valid
)
=>
{
if
(
valid
)
{
let
param
=
{};
Object
.
assign
(
param
,
this
.
form
);
param
.
steps
=
JSON
.
stringify
(
this
.
form
.
steps
);
param
.
nodeId
=
this
.
form
.
module
;
this
.
moduleOptions
.
forEach
(
item
=>
{
if
(
this
.
form
.
module
===
item
.
id
){
param
.
nodePath
=
item
.
path
;
}
});
if
(
localStorage
.
getItem
(
CURRENT_PROJECT
))
{
param
.
projectId
=
JSON
.
parse
(
localStorage
.
getItem
(
CURRENT_PROJECT
)).
id
;
}
this
.
$post
(
'
/test/case/
'
+
this
.
operationType
,
param
,
()
=>
{
this
.
$message
.
success
(
this
.
$t
(
'
commons.save_success
'
));
this
.
dialogFormVisible
=
false
;
this
.
$emit
(
"
refresh
"
);
});
}
else
{
return
false
;
}
});
}
,
resetForm
()
{
if
(
this
.
$refs
[
'
relevanceFrom
'
])
{
this
.
$refs
[
'
relevanceFrom
'
].
resetFields
();
}
},
load
()
{
this
.
count
+=
2
},
getCaseNames
(
planId
)
{
if
(
planId
){
let
param
=
{};
param
.
planId
=
planId
;
this
.
$post
(
'
/test/case/name/all
'
,
param
,
response
=>
{
this
.
testCases
=
response
.
data
;
this
.
testCases
.
forEach
(
item
=>
{
item
.
checked
=
false
;
});
});
}
}
}
}
</
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
;
}
.node_tree
{
/*border-radius: 1px;*/
/*padding-top: 5px ;*/
/*height: 100%;*/
/*box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04);*/
}
.el-header
{
background-color
:
darkgrey
;
color
:
#333
;
line-height
:
60px
;
height
:
1%
;
}
.el-aside
{
color
:
#333
;
}
</
style
>
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录