Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
MeterSphere
metersphere
提交
536a2d7d
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,发现更多精彩内容 >>
提交
536a2d7d
编写于
4月 21, 2020
作者:
C
Captain.B
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'origin/dev' into dev
上级
31fd266e
68c7c8f9
变更
14
隐藏空白更改
内联
并排
Showing
14 changed file
with
302 addition
and
250 deletion
+302
-250
backend/src/main/java/io/metersphere/controller/TestPlanTestCaseController.java
...io/metersphere/controller/TestPlanTestCaseController.java
+5
-0
backend/src/main/java/io/metersphere/report/GenerateReport.java
...d/src/main/java/io/metersphere/report/GenerateReport.java
+6
-6
backend/src/main/java/io/metersphere/service/ReportService.java
...d/src/main/java/io/metersphere/service/ReportService.java
+8
-8
frontend/src/business/components/api/test/ApiTestConfig.vue
frontend/src/business/components/api/test/ApiTestConfig.vue
+18
-7
frontend/src/business/components/api/test/components/ApiAssertionRegex.vue
...ness/components/api/test/components/ApiAssertionRegex.vue
+3
-3
frontend/src/business/components/api/test/components/ApiAssertionText.vue
...iness/components/api/test/components/ApiAssertionText.vue
+8
-8
frontend/src/business/components/api/test/components/ApiKeyValue.vue
...c/business/components/api/test/components/ApiKeyValue.vue
+26
-25
frontend/src/business/components/api/test/components/ApiRequestConfig.vue
...iness/components/api/test/components/ApiRequestConfig.vue
+1
-1
frontend/src/business/components/api/test/components/ApiRequestForm.vue
...usiness/components/api/test/components/ApiRequestForm.vue
+10
-10
frontend/src/business/components/api/test/components/ApiScenarioConfig.vue
...ness/components/api/test/components/ApiScenarioConfig.vue
+3
-4
frontend/src/business/components/api/test/components/ApiScenarioForm.vue
...siness/components/api/test/components/ApiScenarioForm.vue
+1
-1
frontend/src/business/components/track/plan/TestPlanView.vue
frontend/src/business/components/track/plan/TestPlanView.vue
+7
-9
frontend/src/business/components/track/plan/components/TestPlanTestCaseEdit.vue
...components/track/plan/components/TestPlanTestCaseEdit.vue
+186
-151
frontend/src/business/components/track/plan/components/TestPlanTestCaseList.vue
...components/track/plan/components/TestPlanTestCaseList.vue
+20
-17
未找到文件。
backend/src/main/java/io/metersphere/controller/TestPlanTestCaseController.java
浏览文件 @
536a2d7d
...
...
@@ -29,6 +29,11 @@ public class TestPlanTestCaseController {
return
PageUtils
.
setPageInfo
(
page
,
testPlanTestCaseService
.
getTestPlanCases
(
request
));
}
@PostMapping
(
"/list/all"
)
public
List
<
TestPlanCaseDTO
>
getTestPlanCases
(
@RequestBody
QueryTestPlanCaseRequest
request
){
return
testPlanTestCaseService
.
getTestPlanCases
(
request
);
}
@PostMapping
(
"/edit"
)
public
void
editTestCase
(
@RequestBody
TestPlanTestCase
testPlanTestCase
){
testPlanTestCaseService
.
editTestCase
(
testPlanTestCase
);
...
...
backend/src/main/java/io/metersphere/report/
JtlResolver
.java
→
backend/src/main/java/io/metersphere/report/
GenerateReport
.java
浏览文件 @
536a2d7d
...
...
@@ -24,7 +24,7 @@ import java.time.format.DateTimeFormatter;
import
java.util.*
;
import
java.util.stream.Collectors
;
public
class
JtlResolver
{
public
class
GenerateReport
{
private
static
final
Integer
ERRORS_TOP_SIZE
=
5
;
private
static
final
String
DATE_TIME_PATTERN
=
"yyyy/MM/dd HH:mm:ss"
;
...
...
@@ -186,7 +186,7 @@ public class JtlResolver {
}
}
Map
<
String
,
List
<
Metric
>>
jtlMap
=
falseList
.
stream
().
collect
(
Collectors
.
groupingBy
(
JtlResolver
:
:
getResponseCodeAndFailureMessage
));
Map
<
String
,
List
<
Metric
>>
jtlMap
=
falseList
.
stream
().
collect
(
Collectors
.
groupingBy
(
GenerateReport
:
:
getResponseCodeAndFailureMessage
));
for
(
Map
.
Entry
<
String
,
List
<
Metric
>>
next
:
jtlMap
.
entrySet
())
{
String
key
=
next
.
getKey
();
...
...
@@ -219,7 +219,7 @@ public class JtlResolver {
.
collect
(
Collectors
.
toList
());
Map
<
String
,
List
<
Metric
>>
collect
=
falseList
.
stream
()
.
collect
(
Collectors
.
groupingBy
(
JtlResolver
:
:
getResponseCodeAndFailureMessage
));
.
collect
(
Collectors
.
groupingBy
(
GenerateReport
:
:
getResponseCodeAndFailureMessage
));
for
(
Map
.
Entry
<
String
,
List
<
Metric
>>
next
:
collect
.
entrySet
())
{
String
key
=
next
.
getKey
();
...
...
@@ -270,9 +270,9 @@ public class JtlResolver {
TestOverview
testOverview
=
new
TestOverview
();
DecimalFormat
decimalFormat
=
new
DecimalFormat
(
"0.00"
);
List
<
Metric
>
totalLineList
=
JtlResolver
.
resolver
(
jtlString
);
List
<
Metric
>
totalLineList
=
GenerateReport
.
resolver
(
jtlString
);
// todo 修改测试概览的数值
List
<
Metric
>
totalLineList2
=
JtlResolver
.
resolver
(
jtlString
);
List
<
Metric
>
totalLineList2
=
GenerateReport
.
resolver
(
jtlString
);
// 时间戳转时间
for
(
Metric
metric
:
totalLineList2
)
{
metric
.
setTimestamp
(
stampToDate
(
DATE_TIME_PATTERN
,
metric
.
getTimestamp
()));
...
...
@@ -355,7 +355,7 @@ public class JtlResolver {
public
static
ReportTimeInfo
getReportTimeInfo
(
String
jtlString
)
{
ReportTimeInfo
reportTimeInfo
=
new
ReportTimeInfo
();
List
<
Metric
>
totalLineList
=
JtlResolver
.
resolver
(
jtlString
);
List
<
Metric
>
totalLineList
=
GenerateReport
.
resolver
(
jtlString
);
totalLineList
.
sort
(
Comparator
.
comparing
(
t0
->
Long
.
valueOf
(
t0
.
getTimestamp
())));
...
...
backend/src/main/java/io/metersphere/service/ReportService.java
浏览文件 @
536a2d7d
...
...
@@ -11,7 +11,7 @@ import io.metersphere.controller.request.ReportRequest;
import
io.metersphere.dto.ReportDTO
;
import
io.metersphere.engine.Engine
;
import
io.metersphere.engine.EngineFactory
;
import
io.metersphere.report.
JtlResolver
;
import
io.metersphere.report.
GenerateReport
;
import
io.metersphere.report.base.ChartsData
;
import
io.metersphere.report.base.Errors
;
import
io.metersphere.report.base.ReportTimeInfo
;
...
...
@@ -90,7 +90,7 @@ public class ReportService {
checkReportStatus
(
id
);
LoadTestReportWithBLOBs
loadTestReport
=
loadTestReportMapper
.
selectByPrimaryKey
(
id
);
String
content
=
loadTestReport
.
getContent
();
RequestStatisticsDTO
requestStatistics
=
JtlResolver
.
getRequestStatistics
(
content
);
RequestStatisticsDTO
requestStatistics
=
GenerateReport
.
getRequestStatistics
(
content
);
return
requestStatistics
;
}
...
...
@@ -98,7 +98,7 @@ public class ReportService {
checkReportStatus
(
id
);
LoadTestReportWithBLOBs
loadTestReport
=
loadTestReportMapper
.
selectByPrimaryKey
(
id
);
String
content
=
loadTestReport
.
getContent
();
List
<
Errors
>
errors
=
JtlResolver
.
getErrorsList
(
content
);
List
<
Errors
>
errors
=
GenerateReport
.
getErrorsList
(
content
);
return
errors
;
}
...
...
@@ -106,7 +106,7 @@ public class ReportService {
checkReportStatus
(
id
);
LoadTestReportWithBLOBs
loadTestReport
=
loadTestReportMapper
.
selectByPrimaryKey
(
id
);
String
content
=
loadTestReport
.
getContent
();
ErrorsTop5DTO
errors
=
JtlResolver
.
getErrorsTop5DTO
(
content
);
ErrorsTop5DTO
errors
=
GenerateReport
.
getErrorsTop5DTO
(
content
);
return
errors
;
}
...
...
@@ -114,7 +114,7 @@ public class ReportService {
checkReportStatus
(
id
);
LoadTestReportWithBLOBs
loadTestReport
=
loadTestReportMapper
.
selectByPrimaryKey
(
id
);
String
content
=
loadTestReport
.
getContent
();
TestOverview
testOverview
=
JtlResolver
.
getTestOverview
(
content
);
TestOverview
testOverview
=
GenerateReport
.
getTestOverview
(
content
);
return
testOverview
;
}
...
...
@@ -122,7 +122,7 @@ public class ReportService {
checkReportStatus
(
id
);
LoadTestReportWithBLOBs
loadTestReport
=
loadTestReportMapper
.
selectByPrimaryKey
(
id
);
String
content
=
loadTestReport
.
getContent
();
ReportTimeInfo
reportTimeInfo
=
JtlResolver
.
getReportTimeInfo
(
content
);
ReportTimeInfo
reportTimeInfo
=
GenerateReport
.
getReportTimeInfo
(
content
);
return
reportTimeInfo
;
}
...
...
@@ -130,7 +130,7 @@ public class ReportService {
checkReportStatus
(
id
);
LoadTestReportWithBLOBs
loadTestReport
=
loadTestReportMapper
.
selectByPrimaryKey
(
id
);
String
content
=
loadTestReport
.
getContent
();
List
<
ChartsData
>
chartsDataList
=
JtlResolver
.
getLoadChartData
(
content
);
List
<
ChartsData
>
chartsDataList
=
GenerateReport
.
getLoadChartData
(
content
);
return
chartsDataList
;
}
...
...
@@ -138,7 +138,7 @@ public class ReportService {
checkReportStatus
(
id
);
LoadTestReportWithBLOBs
loadTestReport
=
loadTestReportMapper
.
selectByPrimaryKey
(
id
);
String
content
=
loadTestReport
.
getContent
();
List
<
ChartsData
>
chartsDataList
=
JtlResolver
.
getResponseTimeChartData
(
content
);
List
<
ChartsData
>
chartsDataList
=
GenerateReport
.
getResponseTimeChartData
(
content
);
return
chartsDataList
;
}
...
...
frontend/src/business/components/api/test/ApiTestConfig.vue
浏览文件 @
536a2d7d
...
...
@@ -8,13 +8,13 @@
<el-input
class=
"test-name"
v-model=
"test.name"
maxlength=
"64"
:placeholder=
"$t('api_test.input_name')"
>
<el-select
class=
"test-project"
v-model=
"test.projectId"
slot=
"prepend"
:placeholder=
"$t('api_test.select_project')"
>
<el-option
v-for=
"
item in projects"
:key=
"item.id"
:label=
"item.name"
:value=
"item
.id"
/>
<el-option
v-for=
"
project in projects"
:key=
"project.id"
:label=
"project.name"
:value=
"project
.id"
/>
</el-select>
</el-input>
<el-button
type=
"primary"
plain
:disabled=
"isDisabled"
@
click=
"saveTest"
>
保存
</el-button>
</el-row>
</el-header>
<ms-api-scenario-config
:scenarios=
"test.scenario
_d
efinition"
/>
<ms-api-scenario-config
:scenarios=
"test.scenario
D
efinition"
/>
</el-container>
</el-card>
</div>
...
...
@@ -35,9 +35,10 @@
projects
:
[],
change
:
false
,
test
:
{
id
:
null
,
projectId
:
null
,
name
:
null
,
scenario
_d
efinition
:
[]
scenario
D
efinition
:
[]
}
}
},
...
...
@@ -53,11 +54,21 @@
methods
:
{
saveTest
:
function
()
{
this
.
change
=
false
;
this
.
$message
({
message
:
this
.
$t
(
'
commons.save_success
'
),
type
:
'
success
'
let
param
=
{
id
:
this
.
test
.
id
,
projectId
:
this
.
test
.
projectId
,
name
:
this
.
test
.
name
,
scenarioDefinition
:
JSON
.
stringify
(
this
.
test
.
scenarioDefinition
)
}
this
.
result
=
this
.
$post
(
"
/api/save
"
,
param
,
response
=>
{
this
.
test
.
id
=
response
.
data
;
this
.
$message
({
message
:
this
.
$t
(
'
commons.save_success
'
),
type
:
'
success
'
});
});
}
},
...
...
frontend/src/business/components/api/test/components/ApiAssertionRegex.vue
浏览文件 @
536a2d7d
...
...
@@ -4,9 +4,9 @@
<el-col
class=
"assertion-select"
>
<el-select
class=
"assertion-item"
v-model=
"regex.subject"
size=
"small"
:placeholder=
"$t('api_test.request.assertions.select_subject')"
>
<el-option
label=
"Http
-Code"
value=
"HTTP-CODE"
></el-option
>
<el-option
label=
"Header"
value=
"HEADER"
></el-option
>
<el-option
label=
"Body"
value=
"BODY"
></el-option
>
<el-option
label=
"Http
Code"
value=
"HTTP_CODE"
/
>
<el-option
label=
"Header"
value=
"HEADER"
/
>
<el-option
label=
"Body"
value=
"BODY"
/
>
</el-select>
</el-col>
<el-col>
...
...
frontend/src/business/components/api/test/components/ApiAssertionText.vue
浏览文件 @
536a2d7d
...
...
@@ -4,19 +4,19 @@
<el-col
class=
"assertion-select"
>
<el-select
class=
"assertion-item"
v-model=
"subject"
size=
"small"
:placeholder=
"$t('api_test.request.assertions.select_subject')"
>
<el-option
label=
"Http
-Code"
value=
"HTTP-CODE"
></el-option
>
<el-option
label=
"Header"
value=
"HEADER"
></el-option
>
<el-option
label=
"Body"
value=
"BODY"
></el-option
>
<el-option
label=
"Http
Code"
value=
"HTTP_CODE"
/
>
<el-option
label=
"Header"
value=
"HEADER"
/
>
<el-option
label=
"Body"
value=
"BODY"
/
>
</el-select>
</el-col>
<el-col
class=
"assertion-select"
>
<el-select
class=
"assertion-item"
v-model=
"condition"
size=
"small"
:placeholder=
"$t('api_test.request.assertions.select_contains')"
>
<el-option
:label=
"$t('api_test.request.assertions.contains')"
value=
"CONTAINS"
></el-option
>
<el-option
:label=
"$t('api_test.request.assertions.not_contains')"
value=
"NOT_CONTAINS"
></el-option
>
<el-option
:label=
"$t('api_test.request.assertions.equals')"
value=
"EQUALS"
></el-option
>
<el-option
:label=
"$t('api_test.request.assertions.start_with')"
value=
"START_WITH"
></el-option
>
<el-option
:label=
"$t('api_test.request.assertions.end_with')"
value=
"END_WITH"
></el-option
>
<el-option
:label=
"$t('api_test.request.assertions.contains')"
value=
"CONTAINS"
/
>
<el-option
:label=
"$t('api_test.request.assertions.not_contains')"
value=
"NOT_CONTAINS"
/
>
<el-option
:label=
"$t('api_test.request.assertions.equals')"
value=
"EQUALS"
/
>
<el-option
:label=
"$t('api_test.request.assertions.start_with')"
value=
"START_WITH"
/
>
<el-option
:label=
"$t('api_test.request.assertions.end_with')"
value=
"END_WITH"
/
>
</el-select>
</el-col>
<el-col>
...
...
frontend/src/business/components/api/test/components/ApiKeyValue.vue
浏览文件 @
536a2d7d
...
...
@@ -12,8 +12,21 @@
<el-input
v-model=
"item.value"
placeholder=
"Value"
size=
"small"
maxlength=
"100"
@
change=
"check"
/>
</el-col>
<el-col
class=
"kv-delete"
>
<el-button
size=
"mini"
class=
"el-icon-delete-solid"
circle
@
click=
"remove(index)"
:disabled=
"isDisable(index)"
/>
<el-button
size=
"mini"
class=
"el-icon-delete-solid"
circle
@
click=
"remove(index)"
/>
</el-col>
</el-row>
</div>
<div
class=
"kv-row"
>
<el-row
type=
"flex"
:gutter=
"20"
justify=
"space-between"
align=
"middle"
>
<el-col>
<el-input
v-model=
"kv.key"
placeholder=
"Key"
size=
"small"
maxlength=
"100"
@
change=
"add"
/>
</el-col>
<el-col>
<el-input
v-model=
"kv.value"
placeholder=
"Value"
size=
"small"
maxlength=
"100"
@
change=
"add"
/>
</el-col>
<el-col
class=
"kv-delete"
>
<el-button
size=
"mini"
class=
"el-icon-delete-solid"
circle
:disabled=
"true"
/>
</el-col>
</el-row>
</div>
...
...
@@ -31,45 +44,33 @@
items
:
Array
},
data
()
{
return
{
kv
:
new
KeyValue
()
}
},
methods
:
{
add
:
function
()
{
this
.
items
.
push
(
new
KeyValue
());
if
(
this
.
kv
.
key
||
this
.
kv
.
value
)
{
this
.
items
.
push
(
this
.
kv
);
this
.
kv
=
new
KeyValue
();
}
},
remove
:
function
(
index
)
{
this
.
items
.
splice
(
index
,
1
);
if
(
this
.
items
.
length
===
0
)
{
this
.
add
();
}
},
check
:
function
()
{
let
isNeedCreate
=
true
;
let
removeIndex
=
-
1
;
this
.
items
.
forEach
((
item
,
index
)
=>
{
if
(
!
item
.
key
&&
!
item
.
value
)
{
// 多余的空行
if
(
index
!==
this
.
items
.
length
-
1
)
{
removeIndex
=
index
;
}
// 没有空行,需要创建空行
isNeedCreate
=
false
;
removeIndex
=
index
;
}
});
if
(
isNeedCreate
)
{
this
.
add
();
}
if
(
removeIndex
!==
-
1
)
{
this
.
remove
(
removeIndex
);
}
// TODO 检查key重复
},
isDisable
:
function
(
index
)
{
return
this
.
items
.
length
-
1
===
index
;
}
},
created
()
{
if
(
this
.
items
.
length
===
0
)
{
this
.
add
();
}
}
}
...
...
frontend/src/business/components/api/test/components/ApiRequestConfig.vue
浏览文件 @
536a2d7d
...
...
@@ -11,7 +11,7 @@
</div>
<div
class=
"request-btn"
>
<el-dropdown
trigger=
"click"
@
command=
"handleCommand"
>
<span
class=
"el-dropdown-link el-icon-more"
></span
>
<span
class=
"el-dropdown-link el-icon-more"
/
>
<el-dropdown-menu
slot=
"dropdown"
>
<el-dropdown-item
:command=
"
{type: 'copy', index: index}">复制请求
</el-dropdown-item>
<el-dropdown-item
:command=
"
{type: 'delete', index: index}">删除请求
</el-dropdown-item>
...
...
frontend/src/business/components/api/test/components/ApiRequestForm.vue
浏览文件 @
536a2d7d
<
template
>
<el-form
:model=
"request"
:rules=
"rules"
ref=
"request"
label-width=
"100px"
>
<el-form-item
:label=
"$t('api_test.request.name')"
prop=
"name"
>
<el-input
v-model=
"request.name"
maxlength=
"100"
></el-input
>
<el-input
v-model=
"request.name"
maxlength=
"100"
/
>
</el-form-item>
<el-form-item
:label=
"$t('api_test.request.url')"
prop=
"url"
>
<el-input
v-model=
"request.url"
maxlength=
"100"
:placeholder=
"$t('api_test.request.url_description')"
>
<el-select
v-model=
"request.method"
slot=
"prepend"
class=
"request-method-select"
>
<el-option
label=
"GET"
value=
"GET"
></el-option
>
<el-option
label=
"POST"
value=
"POST"
></el-option
>
<el-option
label=
"PUT"
value=
"PUT"
></el-option
>
<el-option
label=
"PATCH"
value=
"PATCH"
></el-option
>
<el-option
label=
"DELETE"
value=
"DELETE"
></el-option
>
<el-option
label=
"OPTIONS"
value=
"OPTIONS"
></el-option
>
<el-option
label=
"HEAD"
value=
"HEAD"
></el-option
>
<el-option
label=
"CONNECT"
value=
"CONNECT"
></el-option
>
<el-option
label=
"GET"
value=
"GET"
/
>
<el-option
label=
"POST"
value=
"POST"
/
>
<el-option
label=
"PUT"
value=
"PUT"
/
>
<el-option
label=
"PATCH"
value=
"PATCH"
/
>
<el-option
label=
"DELETE"
value=
"DELETE"
/
>
<el-option
label=
"OPTIONS"
value=
"OPTIONS"
/
>
<el-option
label=
"HEAD"
value=
"HEAD"
/
>
<el-option
label=
"CONNECT"
value=
"CONNECT"
/
>
</el-select>
</el-input>
</el-form-item>
...
...
@@ -30,7 +30,7 @@
<ms-api-body
:body=
"request.body"
/>
</el-tab-pane>
<el-tab-pane
:label=
"$t('api_test.request.assertions.label')"
name=
"assertions"
>
<ms-api-assertions
:assertions=
"request.assertions"
></ms-api-assertions
>
<ms-api-assertions
:assertions=
"request.assertions"
/
>
</el-tab-pane>
<el-tab-pane
:label=
"$t('api_test.request.extract')"
name=
"extract"
v-if=
"false"
>
TODO
...
...
frontend/src/business/components/api/test/components/ApiScenarioConfig.vue
浏览文件 @
536a2d7d
...
...
@@ -18,14 +18,13 @@
</ms-api-collapse-item>
</ms-api-collapse>
</div>
<el-button
class=
"scenario-create"
type=
"primary"
size=
"mini"
icon=
"el-icon-plus"
plain
@
click=
"createScenario"
/>
<el-button
class=
"scenario-create"
type=
"primary"
size=
"mini"
icon=
"el-icon-plus"
plain
@
click=
"createScenario"
/>
</el-aside>
<el-main
class=
"scenario-main"
>
<div
class=
"scenario-form"
>
<ms-api-scenario-form
:scenario=
"selected"
v-if=
"isScenario"
></ms-api-scenario-form
>
<ms-api-request-form
:request=
"selected"
v-if=
"isRequest"
></ms-api-request-form
>
<ms-api-scenario-form
:scenario=
"selected"
v-if=
"isScenario"
/
>
<ms-api-request-form
:request=
"selected"
v-if=
"isRequest"
/
>
</div>
</el-main>
</el-container>
...
...
frontend/src/business/components/api/test/components/ApiScenarioForm.vue
浏览文件 @
536a2d7d
<
template
>
<el-form
:model=
"scenario"
:rules=
"rules"
ref=
"scenario"
label-width=
"100px"
>
<el-form-item
:label=
"$t('api_test.scenario.name')"
prop=
"name"
>
<el-input
v-model=
"scenario.name"
maxlength=
"100"
></el-input
>
<el-input
v-model=
"scenario.name"
maxlength=
"100"
/
>
</el-form-item>
<el-form-item
:label=
"$t('api_test.scenario.base_url')"
prop=
"url"
>
...
...
frontend/src/business/components/track/plan/TestPlanView.vue
浏览文件 @
536a2d7d
...
...
@@ -12,7 +12,7 @@
<plan-node-tree
class=
"node-tree"
:plan-id=
"planId"
@
nodeSelectEvent=
"
getPlanCases
"
@
nodeSelectEvent=
"
selectNodeIdsChange
"
ref=
"tree"
>
</plan-node-tree>
...
...
@@ -23,6 +23,7 @@
@
openTestCaseRelevanceDialog=
"openTestCaseRelevanceDialog"
@
refresh=
"refresh"
:plan-id=
"planId"
:select-node-ids=
"selectNodeIds"
ref=
"testCasePlanList"
></test-plan-test-case-list>
</el-main>
</el-container>
...
...
@@ -49,7 +50,8 @@
data
()
{
return
{
testPlans
:
[],
currentPlan
:
{}
currentPlan
:
{},
selectNodeIds
:
[]
}
},
computed
:
{
...
...
@@ -67,11 +69,11 @@
},
methods
:
{
refresh
()
{
this
.
getPlanCases
()
;
this
.
selectNodeIds
=
[]
;
this
.
$refs
.
tree
.
initTree
();
},
getPlanCases
(
nodeIds
)
{
this
.
$refs
.
testCasePlanList
.
initTableData
(
nodeIds
)
;
selectNodeIdsChange
(
nodeIds
)
{
this
.
selectNodeIds
=
nodeIds
;
},
openTestCaseRelevanceDialog
()
{
this
.
$refs
.
testCaseRelevance
.
openTestCaseRelevanceDialog
();
...
...
@@ -117,8 +119,4 @@
padding
:
15px
;
}
.main-content
{
/*background: white;*/
}
</
style
>
frontend/src/business/components/track/plan/components/TestPlanTestCaseEdit.vue
浏览文件 @
536a2d7d
<
template
>
<el-drawer
:before-close=
"handleClose"
:visible.sync=
"showDialog"
:with-header=
"false"
size=
"100%"
ref=
"drawer"
>
<template
v-slot:default=
"scope"
>
<el-header>
<el-row
type=
"flex"
class=
"head-bar"
>
<el-col
:span=
"12"
>
<el-button
plain
size=
"mini"
icon=
"el-icon-back"
@
click=
"cancel"
>
{{
$t
(
'
test_track.return
'
)
}}
</el-button>
</el-col>
<el-col
:span=
"12"
class=
"head-right"
>
<span
class=
"head-right-tip"
v-if=
"index + 1 == tableData.length"
>
{{
$t
(
'
test_track.plan_view.pre_case
'
)
}}
:
{{
tableData
?
tableData
[
index
-
1
].
name
:
''
}}
</span>
<span
class=
"head-right-tip"
v-if=
"index + 1
<
tableData.length
"
>
{{
$t
(
'
test_track.plan_view.next_case
'
)
}}
:
{{
tableData
?
tableData
[
index
+
1
].
name
:
''
}}
</span>
<el-button
plain
size=
"mini"
icon=
"el-icon-arrow-up"
:disabled=
"index + 1
<
=
1"
@
click=
"handlePre()"
/>
<span>
{{
index
+
1
}}
/
{{
tableData
.
length
}}
</span>
<el-button
plain
size=
"mini"
icon=
"el-icon-arrow-down"
:disabled=
"index + 1 >= tableData.length"
@
click=
"handleNext()"
/>
<el-divider
direction=
"vertical"
></el-divider>
<el-button
type=
"primary"
size=
"mini"
@
click=
"saveCase"
>
{{
$t
(
'
test_track.save
'
)
}}
</el-button>
</el-col>
</el-row>
<el-row
style=
"margin-top: 0px;"
>
<el-col>
<el-divider
content-position=
"left"
>
{{
testCase
.
name
}}
</el-divider>
</el-col>
</el-row>
</el-header>
<div
class=
"case_container"
>
<el-row
>
<el-col
:span=
"4"
:offset=
"1"
>
<span
class=
"cast_label"
>
{{
$t
(
'
test_track.case.priority
'
)
}}
:
</span>
<span
class=
"cast_item"
>
{{
testCase
.
priority
}}
</span>
</el-col>
<el-col
:span=
"5"
>
<span
class=
"cast_label"
>
{{
$t
(
'
test_track.case.case_type
'
)
}}
:
</span>
<span
class=
"cast_item"
v-if=
"testCase.type == 'functional'"
>
{{
$t
(
'
commons.functional
'
)
}}
</span>
<span
class=
"cast_item"
v-if=
"testCase.type == 'performance'"
>
{{
$t
(
'
commons.performance
'
)
}}
</span>
<span
class=
"cast_item"
v-if=
"testCase.type == 'api'"
>
{{
$t
(
'
commons.api
'
)
}}
</span>
</el-col>
<el-col
:span=
"13"
>
<test-plan-test-case-status-button
class=
"status-button"
@
statusChange=
"statusChange"
:status=
"testCase.status"
/>
</el-col>
</el-row>
<el-row>
<el-col
:span=
"4"
:offset=
"1"
>
<span
class=
"cast_label"
>
{{
$t
(
'
test_track.case.method
'
)
}}
:
</span>
<span
v-if=
"testCase.method == 'manual'"
>
{{
$t
(
'
test_track.case.manual
'
)
}}
</span>
<span
v-if=
"testCase.method == 'auto'"
>
{{
$t
(
'
test_track.case.auto
'
)
}}
</span>
</el-col>
<el-col
:span=
"5"
>
<span
class=
"cast_label"
>
{{
$t
(
'
test_track.case.module
'
)
}}
:
</span>
<span
class=
"cast_item"
>
{{
testCase
.
nodePath
}}
</span>
</el-col>
</el-row>
<el-row>
<el-col
:span=
"20"
:offset=
"1"
>
<div>
<span
class=
"cast_label"
>
{{
$t
(
'
test_track.case.steps
'
)
}}
:
</span>
</div>
<el-table
:data=
"testCase.steptResults"
class=
"tb-edit"
size=
"mini"
height=
"250px"
:border=
"true"
:default-sort =
"
{prop: 'num', order: 'ascending'}"
highlight-current-row>
<el-table-column
:label=
"$t('test_track.case.number')"
prop=
"num"
min-width=
"5%"
></el-table-column>
<el-table-column
:label=
"$t('test_track.case.step_desc')"
prop=
"desc"
min-width=
"29%"
>
<template
v-slot:default=
"scope"
>
<span>
{{
scope
.
row
.
desc
}}
</span>
</
template
>
</el-table-column>
<el-table-column
:label=
"$t('test_track.case.expected_results')"
prop=
"result"
min-width=
"28%"
>
<
template
v-slot:default=
"scope"
>
<span>
{{
scope
.
row
.
result
}}
</span>
</
template
>
</el-table-column>
<el-table-column
:label=
"$t('test_track.plan_view.actual_result')"
min-width=
"29%"
>
<
template
v-slot:default=
"scope"
>
<el-input
ref=
"drawer"
v-loading=
"result.loading"
>
<template
v-slot:default=
"scope"
>
<div
class=
"container"
>
<el-scrollbar>
<el-header>
<el-row
type=
"flex"
class=
"head-bar"
>
<el-col
:span=
"12"
>
<el-button
plain
size=
"mini"
icon=
"el-icon-back"
@
click=
"cancel"
>
{{
$t
(
'
test_track.return
'
)
}}
</el-button>
</el-col>
<el-col
:span=
"12"
class=
"head-right"
>
<span
class=
"head-right-tip"
v-if=
"index + 1 == testCases.length"
>
{{
$t
(
'
test_track.plan_view.pre_case
'
)
}}
:
{{
testCases
[
index
-
1
]
?
testCases
[
index
-
1
].
name
:
''
}}
</span>
<span
class=
"head-right-tip"
v-if=
"index + 1 != testCases.length"
>
{{
$t
(
'
test_track.plan_view.next_case
'
)
}}
:
{{
testCases
[
index
+
1
]
?
testCases
[
index
+
1
].
name
:
''
}}
</span>
<el-button
plain
size=
"mini"
icon=
"el-icon-arrow-up"
:disabled=
"index + 1
<
=
1"
@
click=
"handlePre()"
/>
<span>
{{
index
+
1
}}
/
{{
testCases
.
length
}}
</span>
<el-button
plain
size=
"mini"
icon=
"el-icon-arrow-down"
:disabled=
"index + 1 >= testCases.length"
@
click=
"handleNext()"
/>
<el-divider
direction=
"vertical"
></el-divider>
<el-button
type=
"primary"
size=
"mini"
@
click=
"saveCase"
>
{{
$t
(
'
test_track.save
'
)
}}
</el-button>
</el-col>
</el-row>
<el-row
style=
"margin-top: 0px;"
>
<el-col>
<el-divider
content-position=
"left"
>
{{
testCase
.
name
}}
</el-divider>
</el-col>
</el-row>
</el-header>
<div
class=
"case_container"
>
<el-row
>
<el-col
:span=
"4"
:offset=
"1"
>
<span
class=
"cast_label"
>
{{
$t
(
'
test_track.case.priority
'
)
}}
:
</span>
<span
class=
"cast_item"
>
{{
testCase
.
priority
}}
</span>
</el-col>
<el-col
:span=
"5"
>
<span
class=
"cast_label"
>
{{
$t
(
'
test_track.case.case_type
'
)
}}
:
</span>
<span
class=
"cast_item"
v-if=
"testCase.type == 'functional'"
>
{{
$t
(
'
commons.functional
'
)
}}
</span>
<span
class=
"cast_item"
v-if=
"testCase.type == 'performance'"
>
{{
$t
(
'
commons.performance
'
)
}}
</span>
<span
class=
"cast_item"
v-if=
"testCase.type == 'api'"
>
{{
$t
(
'
commons.api
'
)
}}
</span>
</el-col>
<el-col
:span=
"13"
>
<test-plan-test-case-status-button
class=
"status-button"
@
statusChange=
"statusChange"
:status=
"testCase.status"
/>
</el-col>
</el-row>
<el-row>
<el-col
:span=
"4"
:offset=
"1"
>
<span
class=
"cast_label"
>
{{
$t
(
'
test_track.case.method
'
)
}}
:
</span>
<span
v-if=
"testCase.method == 'manual'"
>
{{
$t
(
'
test_track.case.manual
'
)
}}
</span>
<span
v-if=
"testCase.method == 'auto'"
>
{{
$t
(
'
test_track.case.auto
'
)
}}
</span>
</el-col>
<el-col
:span=
"5"
>
<span
class=
"cast_label"
>
{{
$t
(
'
test_track.case.module
'
)
}}
:
</span>
<span
class=
"cast_item"
>
{{
testCase
.
nodePath
}}
</span>
</el-col>
</el-row>
<el-row>
<el-col
:span=
"20"
:offset=
"1"
>
<div>
<span
class=
"cast_label"
>
{{
$t
(
'
test_track.case.steps
'
)
}}
:
</span>
</div>
<el-table
:data=
"testCase.steptResults"
class=
"tb-edit"
size=
"mini"
type=
"textarea"
:rows=
"2"
v-model=
"scope.row.actualResult"
:placeholder=
"$t('commons.input_content')"
clearable
></el-input>
<span>
{{
scope
.
row
.
actualResult
}}
</span>
</
template
>
</el-table-column>
<el-table-column
:label=
"$t('test_track.plan_view.step_result')"
min-width=
"9%"
>
<
template
v-slot:default=
"scope"
>
<el-select
v-model=
"scope.row.executeResult"
size=
"mini"
>
<el-option
:label=
"$t('test_track.plan_view.pass')"
value=
"Pass"
style=
"color: #7ebf50;"
></el-option>
<el-option
:label=
"$t('test_track.plan_view.failure')"
value=
"Failure"
style=
"color: #e57471;"
></el-option>
<el-option
:label=
"$t('test_track.plan_view.blocking')"
value=
"Blocking"
style=
"color: #dda451;"
></el-option>
<el-option
:label=
"$t('test_track.plan_view.skip')"
value=
"Skip"
style=
"color: #919399;"
></el-option>
</el-select>
</
template
>
</el-table-column>
</el-table>
</el-col>
</el-row>
<el-row>
<el-col
:span=
"15"
:offset=
"1"
>
<div>
<span
class=
"cast_label"
>
{{$t('commons.remark')}}:
</span>
<span
v-if=
"testCase.remark == null || testCase.remark == ''"
style=
"color: darkgrey"
>
{{$t('commons.not_filled')}}
</span>
</div>
<div>
<el-input
:rows=
"3"
type=
"textarea"
v-if=
"testCase.remark"
disabled
v-model=
"testCase.remark"
></el-input>
:border=
"true"
:default-sort =
"
{prop: 'num', order: 'ascending'}"
highlight-current-row>
<el-table-column
:label=
"$t('test_track.case.number')"
prop=
"num"
min-width=
"5%"
></el-table-column>
<el-table-column
:label=
"$t('test_track.case.step_desc')"
prop=
"desc"
min-width=
"29%"
>
<template
v-slot:default=
"scope"
>
<span>
{{
scope
.
row
.
desc
}}
</span>
</
template
>
</el-table-column>
<el-table-column
:label=
"$t('test_track.case.expected_results')"
prop=
"result"
min-width=
"28%"
>
<
template
v-slot:default=
"scope"
>
<span>
{{
scope
.
row
.
result
}}
</span>
</
template
>
</el-table-column>
<el-table-column
:label=
"$t('test_track.plan_view.actual_result')"
min-width=
"29%"
>
<
template
v-slot:default=
"scope"
>
<el-input
size=
"mini"
type=
"textarea"
:rows=
"2"
v-model=
"scope.row.actualResult"
:placeholder=
"$t('commons.input_content')"
clearable
></el-input>
<span>
{{
scope
.
row
.
actualResult
}}
</span>
</
template
>
</el-table-column>
<el-table-column
:label=
"$t('test_track.plan_view.step_result')"
min-width=
"9%"
>
<
template
v-slot:default=
"scope"
>
<el-select
v-model=
"scope.row.executeResult"
size=
"mini"
>
<el-option
:label=
"$t('test_track.plan_view.pass')"
value=
"Pass"
style=
"color: #7ebf50;"
></el-option>
<el-option
:label=
"$t('test_track.plan_view.failure')"
value=
"Failure"
style=
"color: #e57471;"
></el-option>
<el-option
:label=
"$t('test_track.plan_view.blocking')"
value=
"Blocking"
style=
"color: #dda451;"
></el-option>
<el-option
:label=
"$t('test_track.plan_view.skip')"
value=
"Skip"
style=
"color: #919399;"
></el-option>
</el-select>
</
template
>
</el-table-column>
</el-table>
</el-col>
</el-row>
<el-row>
<el-col
:span=
"15"
:offset=
"1"
>
<div>
<span
class=
"cast_label"
>
{{$t('commons.remark')}}:
</span>
<span
v-if=
"testCase.remark == null || testCase.remark == ''"
style=
"color: darkgrey"
>
{{$t('commons.not_filled')}}
</span>
</div>
<div>
<el-input
:rows=
"3"
type=
"textarea"
v-if=
"testCase.remark"
disabled
v-model=
"testCase.remark"
></el-input>
</div>
</el-col>
</el-row>
</div>
</el-col>
</el-row>
</el-scrollbar>
</div>
</template>
</div>
</template>
</el-drawer>
</template>
<
script
>
...
...
@@ -163,17 +172,19 @@
components
:
{
TestPlanTestCaseStatusButton
},
data
()
{
return
{
result
:
{},
showDialog
:
false
,
testCase
:
{},
index
:
0
index
:
0
,
testCases
:
[]
};
},
props
:
{
tableData
:
{
type
:
Array
},
total
:
{
type
:
Number
},
searchParam
:
{
type
:
Object
}
},
methods
:
{
...
...
@@ -213,7 +224,7 @@
this
.
getTestCase
(
this
.
index
);
},
getTestCase
(
index
)
{
let
testCase
=
this
.
t
ableData
[
index
];
let
testCase
=
this
.
t
estCases
[
index
];
let
item
=
{};
Object
.
assign
(
item
,
testCase
);
item
.
results
=
JSON
.
parse
(
item
.
results
);
...
...
@@ -227,6 +238,22 @@
item
.
steptResults
.
push
(
item
.
steps
[
i
]);
}
this
.
testCase
=
item
;
},
openTestCaseEdit
(
testCase
)
{
this
.
showDialog
=
true
;
this
.
initData
(
testCase
);
},
initData
(
testCase
)
{
this
.
result
=
this
.
$post
(
'
/test/plan/case/list/all
'
,
this
.
searchParam
,
response
=>
{
this
.
testCases
=
response
.
data
;
for
(
let
i
=
0
;
i
<
this
.
testCases
.
length
;
i
++
)
{
if
(
this
.
testCases
[
i
].
id
===
testCase
.
id
)
{
this
.
index
=
i
;
this
.
getTestCase
(
i
);
}
}
});
}
}
}
...
...
@@ -265,12 +292,20 @@
float
:
right
;
}
.head-bar
{
margin-top
:
1%
;
}
.head-right-tip
{
color
:
darkgrey
;
}
.el-scrollbar
{
height
:
100%
;
}
.container
{
height
:
100vh
;
}
.case_container
>
.el-row
{
margin-top
:
1%
;
}
</
style
>
frontend/src/business/components/track/plan/components/TestPlanTestCaseList.vue
浏览文件 @
536a2d7d
...
...
@@ -35,11 +35,11 @@
<executor-edit
ref=
"executorEdit"
:select-ids=
"selectIds"
@
refresh=
"
initTableData
"
/>
@
refresh=
"
refresh
"
/>
<status-edit
ref=
"statusEdit"
:select-ids=
"selectIds"
@
refresh=
"
initTableData
"
/>
@
refresh=
"
refresh
"
/>
</div>
</
template
>
...
...
@@ -154,8 +154,8 @@
<test-plan-test-case-edit
ref=
"testPlanTestCaseEdit"
:
table-data=
"tableData
"
@
refresh=
"
initTableData
"
/>
:
search-param=
"condition
"
@
refresh=
"
refresh
"
/>
</el-card>
</div>
...
...
@@ -183,37 +183,44 @@
currentPage
:
1
,
pageSize
:
5
,
total
:
0
,
currentDataIndex
:
0
,
selectIds
:
new
Set
(),
selectIds
:
new
Set
()
}
},
props
:{
planId
:
{
type
:
String
},
selectNodeIds
:
{
type
:
Array
}
},
watch
:
{
planId
()
{
this
.
initTableData
();
},
selectNodeIds
()
{
this
.
refresh
();
}
},
created
:
function
()
{
this
.
initTableData
();
},
methods
:
{
initTableData
(
nodeIds
)
{
initTableData
()
{
if
(
this
.
planId
)
{
let
param
=
{};
Object
.
assign
(
param
,
this
.
condition
);
param
.
nodeIds
=
nodeIds
;
param
.
planId
=
this
.
planId
;
this
.
result
=
this
.
$post
(
this
.
buildPagePath
(
'
/test/plan/case/list
'
),
param
,
response
=>
{
this
.
condition
.
planId
=
this
.
planId
;
this
.
condition
.
nodeIds
=
this
.
selectNodeIds
;
this
.
result
=
this
.
$post
(
this
.
buildPagePath
(
'
/test/plan/case/list
'
),
this
.
condition
,
response
=>
{
let
data
=
response
.
data
;
this
.
total
=
data
.
itemCount
;
this
.
tableData
=
data
.
listObject
;
});
}
},
refresh
()
{
this
.
condition
=
{};
this
.
initTableData
();
},
search
()
{
this
.
initTableData
();
},
...
...
@@ -221,10 +228,7 @@
return
path
+
"
/
"
+
this
.
currentPage
+
"
/
"
+
this
.
pageSize
;
},
handleEdit
(
testCase
,
index
)
{
this
.
currentDataIndex
=
index
;
this
.
$refs
.
testPlanTestCaseEdit
.
index
=
index
;
this
.
$refs
.
testPlanTestCaseEdit
.
getTestCase
(
index
);
this
.
$refs
.
testPlanTestCaseEdit
.
showDialog
=
true
;
this
.
$refs
.
testPlanTestCaseEdit
.
openTestCaseEdit
(
testCase
);
},
handleDelete
(
testCase
)
{
this
.
$alert
(
this
.
$t
(
'
test_track.plan_view.confirm_cancel_relevance
'
)
+
'
'
+
testCase
.
name
+
"
?
"
,
''
,
{
...
...
@@ -239,7 +243,6 @@
_handleDelete
(
testCase
)
{
let
testCaseId
=
testCase
.
id
;
this
.
$post
(
'
/test/plan/case/delete/
'
+
testCaseId
,
{},
()
=>
{
this
.
initTableData
();
this
.
$emit
(
"
refresh
"
);
this
.
$message
({
message
:
this
.
$t
(
'
commons.delete_success
'
),
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录