Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
MeterSphere
metersphere
提交
b8488309
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,发现更多精彩内容 >>
提交
b8488309
编写于
12月 07, 2020
作者:
F
fit2-zhao
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat(接口自动化): 完成场景批量执行,基础报告生成
上级
1aab595a
变更
34
隐藏空白更改
内联
并排
Showing
34 changed file
with
1171 addition
and
253 deletion
+1171
-253
backend/src/main/java/io/metersphere/api/controller/APIScenarioReportController.java
...tersphere/api/controller/APIScenarioReportController.java
+45
-6
backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java
...o/metersphere/api/controller/ApiAutomationController.java
+12
-5
backend/src/main/java/io/metersphere/api/dto/automation/APIScenarioReportResult.java
...tersphere/api/dto/automation/APIScenarioReportResult.java
+18
-0
backend/src/main/java/io/metersphere/api/dto/automation/RunScenarioRequest.java
...io/metersphere/api/dto/automation/RunScenarioRequest.java
+19
-0
backend/src/main/java/io/metersphere/api/dto/automation/SaveApiScenarioRequest.java
...etersphere/api/dto/automation/SaveApiScenarioRequest.java
+4
-0
backend/src/main/java/io/metersphere/api/dto/definition/request/MsScenario.java
...io/metersphere/api/dto/definition/request/MsScenario.java
+19
-8
backend/src/main/java/io/metersphere/api/dto/definition/request/MsTestElement.java
...metersphere/api/dto/definition/request/MsTestElement.java
+1
-1
backend/src/main/java/io/metersphere/api/dto/definition/request/MsThreadGroup.java
...metersphere/api/dto/definition/request/MsThreadGroup.java
+1
-0
backend/src/main/java/io/metersphere/api/jmeter/APIBackendListenerClient.java
...a/io/metersphere/api/jmeter/APIBackendListenerClient.java
+1
-1
backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java
...java/io/metersphere/api/service/ApiAutomationService.java
+77
-19
backend/src/main/java/io/metersphere/api/service/ApiScenarioReportService.java
.../io/metersphere/api/service/ApiScenarioReportService.java
+116
-1
backend/src/main/java/io/metersphere/base/domain/ApiScenarioReport.java
...in/java/io/metersphere/base/domain/ApiScenarioReport.java
+3
-2
backend/src/main/java/io/metersphere/base/domain/ApiScenarioReportDetail.java
...a/io/metersphere/base/domain/ApiScenarioReportDetail.java
+1
-1
backend/src/main/java/io/metersphere/base/domain/ApiScenarioReportDetailExample.java
...tersphere/base/domain/ApiScenarioReportDetailExample.java
+28
-28
backend/src/main/java/io/metersphere/base/domain/ApiScenarioReportExample.java
.../io/metersphere/base/domain/ApiScenarioReportExample.java
+28
-28
backend/src/main/java/io/metersphere/base/mapper/ApiScenarioReportDetailMapper.xml
...metersphere/base/mapper/ApiScenarioReportDetailMapper.xml
+16
-16
backend/src/main/java/io/metersphere/base/mapper/ApiScenarioReportMapper.xml
...va/io/metersphere/base/mapper/ApiScenarioReportMapper.xml
+14
-14
backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioReportMapper.java
...tersphere/base/mapper/ext/ExtApiScenarioReportMapper.java
+15
-0
backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioReportMapper.xml
...etersphere/base/mapper/ext/ExtApiScenarioReportMapper.xml
+169
-0
backend/src/main/resources/generatorConfig.xml
backend/src/main/resources/generatorConfig.xml
+2
-4
frontend/src/business/components/api/automation/report/ApiReportDetail.vue
...ness/components/api/automation/report/ApiReportDetail.vue
+31
-6
frontend/src/business/components/api/automation/report/ApiReportList.vue
...siness/components/api/automation/report/ApiReportList.vue
+228
-0
frontend/src/business/components/api/automation/report/ApiReportViewHeader.vue
.../components/api/automation/report/ApiReportViewHeader.vue
+11
-4
frontend/src/business/components/api/automation/report/components/ScenarioResult.vue
...nents/api/automation/report/components/ScenarioResult.vue
+18
-4
frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue
...ss/components/api/automation/scenario/ApiScenarioList.vue
+92
-59
frontend/src/business/components/api/automation/scenario/DebugRun.vue
.../business/components/api/automation/scenario/DebugRun.vue
+106
-0
frontend/src/business/components/api/automation/scenario/EditApiScenario.vue
...ss/components/api/automation/scenario/EditApiScenario.vue
+62
-7
frontend/src/business/components/api/definition/components/jmeter/components/test-plan/index.js
...efinition/components/jmeter/components/test-plan/index.js
+0
-5
frontend/src/business/components/api/definition/components/jmeter/components/thread-group/index.js
...nition/components/jmeter/components/thread-group/index.js
+0
-14
frontend/src/business/components/api/head/ApiHeaderMenus.vue
frontend/src/business/components/api/head/ApiHeaderMenus.vue
+4
-0
frontend/src/business/components/api/router.js
frontend/src/business/components/api/router.js
+5
-0
frontend/src/i18n/en-US.js
frontend/src/i18n/en-US.js
+11
-9
frontend/src/i18n/zh-CN.js
frontend/src/i18n/zh-CN.js
+11
-9
frontend/src/i18n/zh-TW.js
frontend/src/i18n/zh-TW.js
+3
-2
未找到文件。
backend/src/main/java/io/metersphere/api/controller/APIScenarioReportController.java
浏览文件 @
b8488309
package
io.metersphere.api.controller
;
import
com.github.pagehelper.Page
;
import
com.github.pagehelper.PageHelper
;
import
io.metersphere.api.dto.APIReportResult
;
import
io.metersphere.api.dto.DeleteAPIReportRequest
;
import
io.metersphere.api.dto.QueryAPIReportRequest
;
import
io.metersphere.api.dto.automation.APIScenarioReportResult
;
import
io.metersphere.api.service.ApiScenarioReportService
;
import
io.metersphere.commons.constants.RoleConstants
;
import
io.metersphere.commons.utils.PageUtils
;
import
io.metersphere.commons.utils.Pager
;
import
io.metersphere.commons.utils.SessionUtils
;
import
org.apache.shiro.authz.annotation.Logical
;
import
org.apache.shiro.authz.annotation.RequiresRoles
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
org.springframework.web.bind.annotation.*
;
import
javax.annotation.Resource
;
import
java.util.List
;
@RestController
@RequestMapping
(
value
=
"/api/scenario/report"
)
...
...
@@ -20,8 +26,41 @@ public class APIScenarioReportController {
@Resource
private
ApiScenarioReportService
apiReportService
;
@GetMapping
(
"/get/{reportId}"
)
public
APIReportResult
get
(
@PathVariable
String
reportId
)
{
@GetMapping
(
"/get/{reportId}/{infoDb}"
)
public
APIReportResult
get
(
@PathVariable
String
reportId
,
@PathVariable
Boolean
infoDb
)
{
if
(
infoDb
){
return
apiReportService
.
get
(
reportId
);
}
return
apiReportService
.
getCacheResult
(
reportId
);
}
@PostMapping
(
"/list/{goPage}/{pageSize}"
)
public
Pager
<
List
<
APIScenarioReportResult
>>
list
(
@PathVariable
int
goPage
,
@PathVariable
int
pageSize
,
@RequestBody
QueryAPIReportRequest
request
)
{
Page
<
Object
>
page
=
PageHelper
.
startPage
(
goPage
,
pageSize
,
true
);
request
.
setWorkspaceId
(
SessionUtils
.
getCurrentWorkspaceId
());
return
PageUtils
.
setPageInfo
(
page
,
apiReportService
.
list
(
request
));
}
@PostMapping
(
"/add"
)
@RequiresRoles
(
value
=
{
RoleConstants
.
TEST_USER
,
RoleConstants
.
TEST_MANAGER
},
logical
=
Logical
.
OR
)
public
String
add
(
@RequestBody
APIScenarioReportResult
node
)
{
return
apiReportService
.
add
(
node
);
}
@PostMapping
(
"/update"
)
@RequiresRoles
(
value
=
{
RoleConstants
.
TEST_USER
,
RoleConstants
.
TEST_MANAGER
},
logical
=
Logical
.
OR
)
public
String
update
(
@RequestBody
APIScenarioReportResult
node
)
{
return
apiReportService
.
update
(
node
);
}
@PostMapping
(
"/delete"
)
public
void
delete
(
@RequestBody
DeleteAPIReportRequest
request
)
{
apiReportService
.
delete
(
request
);
}
@PostMapping
(
"/batch/delete"
)
public
void
deleteAPIReportBatch
(
@RequestBody
DeleteAPIReportRequest
reportRequest
)
{
apiReportService
.
deleteAPIReportBatch
(
reportRequest
);
}
}
backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java
浏览文件 @
b8488309
...
...
@@ -4,6 +4,7 @@ import com.github.pagehelper.Page;
import
com.github.pagehelper.PageHelper
;
import
io.metersphere.api.dto.automation.ApiScenarioDTO
;
import
io.metersphere.api.dto.automation.ApiScenarioRequest
;
import
io.metersphere.api.dto.automation.RunScenarioRequest
;
import
io.metersphere.api.dto.automation.SaveApiScenarioRequest
;
import
io.metersphere.api.dto.definition.RunDefinitionRequest
;
import
io.metersphere.api.service.ApiAutomationService
;
...
...
@@ -36,13 +37,13 @@ public class ApiAutomationController {
}
@PostMapping
(
value
=
"/create"
)
public
void
create
(
@Request
Body
SaveApiScenarioRequest
request
)
{
apiAutomationService
.
create
(
request
);
public
void
create
(
@Request
Part
(
"request"
)
SaveApiScenarioRequest
request
,
@RequestPart
(
value
=
"files"
)
List
<
MultipartFile
>
bodyFiles
)
{
apiAutomationService
.
create
(
request
,
bodyFiles
);
}
@PostMapping
(
value
=
"/update"
)
public
void
update
(
@Request
Body
SaveApiScenarioRequest
request
)
{
apiAutomationService
.
update
(
request
);
public
void
update
(
@Request
Part
(
"request"
)
SaveApiScenarioRequest
request
,
@RequestPart
(
value
=
"files"
)
List
<
MultipartFile
>
bodyFiles
)
{
apiAutomationService
.
update
(
request
,
bodyFiles
);
}
@GetMapping
(
"/delete/{id}"
)
...
...
@@ -70,9 +71,15 @@ public class ApiAutomationController {
return
apiAutomationService
.
getApiScenarios
(
ids
);
}
@PostMapping
(
value
=
"/run"
)
@PostMapping
(
value
=
"/run
/debug
"
)
public
void
runDebug
(
@RequestPart
(
"request"
)
RunDefinitionRequest
request
,
@RequestPart
(
value
=
"files"
)
List
<
MultipartFile
>
bodyFiles
)
{
apiAutomationService
.
run
(
request
,
bodyFiles
);
}
@PostMapping
(
value
=
"/run"
)
public
void
run
(
@RequestBody
RunScenarioRequest
request
)
{
apiAutomationService
.
run
(
request
);
}
}
backend/src/main/java/io/metersphere/api/dto/automation/APIScenarioReportResult.java
0 → 100644
浏览文件 @
b8488309
package
io.metersphere.api.dto.automation
;
import
io.metersphere.base.domain.ApiScenarioReport
;
import
lombok.Getter
;
import
lombok.Setter
;
@Setter
@Getter
public
class
APIScenarioReportResult
extends
ApiScenarioReport
{
private
String
testName
;
private
String
projectName
;
private
String
userName
;
private
String
content
;
}
backend/src/main/java/io/metersphere/api/dto/automation/RunScenarioRequest.java
0 → 100644
浏览文件 @
b8488309
package
io.metersphere.api.dto.automation
;
import
lombok.Getter
;
import
lombok.Setter
;
import
java.util.List
;
@Setter
@Getter
public
class
RunScenarioRequest
{
private
String
id
;
private
String
reportId
;
private
String
environmentId
;
private
List
<
String
>
scenarioIds
;
}
backend/src/main/java/io/metersphere/api/dto/automation/SaveApiScenarioRequest.java
浏览文件 @
b8488309
...
...
@@ -3,6 +3,8 @@ package io.metersphere.api.dto.automation;
import
lombok.Getter
;
import
lombok.Setter
;
import
java.util.List
;
@Setter
@Getter
public
class
SaveApiScenarioRequest
{
...
...
@@ -35,4 +37,6 @@ public class SaveApiScenarioRequest {
private
String
description
;
private
String
scenarioDefinition
;
List
<
String
>
bodyUploadIds
;
}
backend/src/main/java/io/metersphere/api/dto/definition/request/MsScenario.java
浏览文件 @
b8488309
...
...
@@ -4,6 +4,9 @@ import com.alibaba.fastjson.JSON;
import
com.alibaba.fastjson.JSONObject
;
import
com.alibaba.fastjson.annotation.JSONField
;
import
com.alibaba.fastjson.annotation.JSONType
;
import
com.fasterxml.jackson.core.type.TypeReference
;
import
com.fasterxml.jackson.databind.DeserializationFeature
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
io.metersphere.api.dto.scenario.environment.EnvironmentConfig
;
import
io.metersphere.api.service.ApiAutomationService
;
import
io.metersphere.api.service.ApiTestEnvironmentService
;
...
...
@@ -15,6 +18,7 @@ import lombok.EqualsAndHashCode;
import
org.apache.commons.collections.CollectionUtils
;
import
org.apache.jorphan.collections.HashTree
;
import
java.util.LinkedList
;
import
java.util.List
;
@Data
...
...
@@ -41,14 +45,21 @@ public class MsScenario extends MsTestElement {
if
(
this
.
getReferenced
()
!=
null
&&
this
.
getReferenced
().
equals
(
"Deleted"
))
{
return
;
}
else
if
(
this
.
getReferenced
()
!=
null
&&
this
.
getReferenced
().
equals
(
"REF"
))
{
ApiAutomationService
apiAutomationService
=
CommonBeanFactory
.
getBean
(
ApiAutomationService
.
class
);
ApiScenario
scenario
=
apiAutomationService
.
getApiScenario
(
this
.
getId
());
JSONObject
element
=
JSON
.
parseObject
(
scenario
.
getScenarioDefinition
());
List
<
MsTestElement
>
dataArr
=
JSON
.
parseArray
(
element
.
getString
(
"hashTree"
),
MsTestElement
.
class
);
if
(
hashTree
==
null
)
{
hashTree
=
dataArr
;
}
else
{
hashTree
.
addAll
(
dataArr
);
try
{
ApiAutomationService
apiAutomationService
=
CommonBeanFactory
.
getBean
(
ApiAutomationService
.
class
);
ObjectMapper
mapper
=
new
ObjectMapper
();
mapper
.
configure
(
DeserializationFeature
.
FAIL_ON_UNKNOWN_PROPERTIES
,
false
);
ApiScenario
scenario
=
apiAutomationService
.
getApiScenario
(
this
.
getId
());
JSONObject
element
=
JSON
.
parseObject
(
scenario
.
getScenarioDefinition
());
LinkedList
<
MsTestElement
>
elements
=
mapper
.
readValue
(
element
.
getString
(
"hashTree"
),
new
TypeReference
<
LinkedList
<
MsTestElement
>>()
{
});
if
(
hashTree
==
null
)
{
hashTree
=
elements
;
}
else
{
hashTree
.
addAll
(
elements
);
}
}
catch
(
Exception
ex
)
{
ex
.
printStackTrace
();
}
}
if
(
CollectionUtils
.
isNotEmpty
(
hashTree
))
{
...
...
backend/src/main/java/io/metersphere/api/dto/definition/request/MsTestElement.java
浏览文件 @
b8488309
...
...
@@ -51,7 +51,7 @@ import java.util.List;
MsJSR223PreProcessor
.
class
,
MsTestPlan
.
class
,
MsThreadGroup
.
class
,
AuthManager
.
class
,
MsAssertions
.
class
,
MsExtract
.
class
,
MsTCPSampler
.
class
,
MsDubboSampler
.
class
,
MsJDBCSampler
.
class
,
MsConstantTimer
.
class
,
MsIfController
.
class
,
MsScenario
.
class
},
typeKey
=
"type"
)
@Data
public
abstract
class
MsTestElement
{
public
class
MsTestElement
{
private
String
type
;
@JSONField
(
ordinal
=
1
)
private
String
id
;
...
...
backend/src/main/java/io/metersphere/api/dto/definition/request/MsThreadGroup.java
浏览文件 @
b8488309
...
...
@@ -50,4 +50,5 @@ public class MsThreadGroup extends MsTestElement {
threadGroup
.
setSamplerController
(
loopController
);
return
threadGroup
;
}
}
backend/src/main/java/io/metersphere/api/jmeter/APIBackendListenerClient.java
浏览文件 @
b8488309
...
...
@@ -169,7 +169,7 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
}
}
else
if
(
StringUtils
.
equals
(
this
.
runMode
,
ApiRunMode
.
SCENARIO
.
name
()))
{
// 执行报告不需要存储,由用户确认后在存储
testResult
.
setTestId
(
debugRepor
tId
);
testResult
.
setTestId
(
tes
tId
);
apiScenarioReportService
.
complete
(
testResult
);
}
else
{
apiTestService
.
changeStatus
(
testId
,
APITestStatus
.
Completed
);
...
...
backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java
浏览文件 @
b8488309
...
...
@@ -2,13 +2,16 @@ package io.metersphere.api.service;
import
com.alibaba.fastjson.JSON
;
import
com.alibaba.fastjson.JSONObject
;
import
com.fasterxml.jackson.core.type.TypeReference
;
import
com.fasterxml.jackson.databind.DeserializationFeature
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.google.gson.Gson
;
import
io.metersphere.api.dto.APIReportResult
;
import
io.metersphere.api.dto.automation.ApiScenarioDTO
;
import
io.metersphere.api.dto.automation.ApiScenarioRequest
;
import
io.metersphere.api.dto.automation.SaveApiScenarioRequest
;
import
io.metersphere.api.dto.automation.ScenarioStatus
;
import
io.metersphere.api.dto.automation.*
;
import
io.metersphere.api.dto.definition.RunDefinitionRequest
;
import
io.metersphere.api.dto.definition.request.MsTestElement
;
import
io.metersphere.api.dto.definition.request.MsTestPlan
;
import
io.metersphere.api.dto.definition.request.MsThreadGroup
;
import
io.metersphere.api.dto.scenario.environment.EnvironmentConfig
;
import
io.metersphere.api.jmeter.JMeterService
;
import
io.metersphere.base.domain.*
;
...
...
@@ -24,6 +27,7 @@ import io.metersphere.i18n.Translator;
import
org.apache.commons.collections.CollectionUtils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.apache.jorphan.collections.HashTree
;
import
org.apache.jorphan.collections.ListedHashTree
;
import
org.aspectj.util.FileUtil
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
...
...
@@ -32,9 +36,9 @@ import org.springframework.web.multipart.MultipartFile;
import
javax.annotation.Resource
;
import
java.io.*
;
import
java.util.ArrayList
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.UUID
;
import
java.util.stream.Collectors
;
@Service
...
...
@@ -83,8 +87,9 @@ public class ApiAutomationService {
apiScenarioMapper
.
deleteByExample
(
example
);
}
public
void
create
(
SaveApiScenarioRequest
request
)
{
public
void
create
(
SaveApiScenarioRequest
request
,
List
<
MultipartFile
>
bodyFiles
)
{
checkNameExist
(
request
);
final
ApiScenario
scenario
=
new
ApiScenario
();
scenario
.
setId
(
request
.
getId
());
scenario
.
setName
(
request
.
getName
());
...
...
@@ -111,10 +116,16 @@ public class ApiAutomationService {
}
scenario
.
setDescription
(
request
.
getDescription
());
apiScenarioMapper
.
insert
(
scenario
);
List
<
String
>
bodyUploadIds
=
new
ArrayList
<>(
request
.
getBodyUploadIds
());
createBodyFiles
(
bodyUploadIds
,
bodyFiles
);
}
public
void
update
(
SaveApiScenarioRequest
request
)
{
public
void
update
(
SaveApiScenarioRequest
request
,
List
<
MultipartFile
>
bodyFiles
)
{
checkNameExist
(
request
);
List
<
String
>
bodyUploadIds
=
new
ArrayList
<>(
request
.
getBodyUploadIds
());
createBodyFiles
(
bodyUploadIds
,
bodyFiles
);
final
ApiScenario
scenario
=
new
ApiScenario
();
scenario
.
setId
(
request
.
getId
());
scenario
.
setName
(
request
.
getName
());
...
...
@@ -176,7 +187,7 @@ public class ApiAutomationService {
}
private
void
createBodyFiles
(
List
<
String
>
bodyUploadIds
,
List
<
MultipartFile
>
bodyFiles
)
{
if
(!
bodyUploadIds
.
isEmpty
())
{
if
(!
bodyUploadIds
.
isEmpty
()
&&
!
bodyFiles
.
isEmpty
()
)
{
File
testDir
=
new
File
(
BODY_FILE_DIR
);
if
(!
testDir
.
exists
())
{
testDir
.
mkdirs
();
...
...
@@ -208,6 +219,63 @@ public class ApiAutomationService {
}
}
private
void
createAPIReportResult
(
String
id
)
{
APIReportResult
report
=
new
APIReportResult
();
report
.
setId
(
id
);
report
.
setTestId
(
id
);
report
.
setName
(
""
);
report
.
setTriggerMode
(
null
);
report
.
setCreateTime
(
System
.
currentTimeMillis
());
report
.
setUpdateTime
(
System
.
currentTimeMillis
());
report
.
setStatus
(
APITestStatus
.
Running
.
name
());
report
.
setUserId
(
SessionUtils
.
getUserId
());
apiReportService
.
addResult
(
report
);
}
/**
* 场景测试执行
*
* @param request
* @return
*/
public
String
run
(
RunScenarioRequest
request
)
{
List
<
ApiScenario
>
apiScenarios
=
extApiScenarioMapper
.
selectIds
(
request
.
getScenarioIds
());
MsTestPlan
testPlan
=
new
MsTestPlan
();
testPlan
.
setHashTree
(
new
LinkedList
<>());
HashTree
jmeterTestPlanHashTree
=
new
ListedHashTree
();
EnvironmentConfig
config
=
null
;
for
(
ApiScenario
item
:
apiScenarios
)
{
MsThreadGroup
group
=
new
MsThreadGroup
();
group
.
setLabel
(
item
.
getName
());
group
.
setName
(
item
.
getName
());
try
{
ObjectMapper
mapper
=
new
ObjectMapper
();
mapper
.
configure
(
DeserializationFeature
.
FAIL_ON_UNKNOWN_PROPERTIES
,
false
);
JSONObject
element
=
JSON
.
parseObject
(
item
.
getScenarioDefinition
());
String
environmentId
=
element
.
getString
(
"environmentId"
);
if
(
environmentId
!=
null
)
{
ApiTestEnvironmentWithBLOBs
environment
=
environmentService
.
get
(
environmentId
);
config
=
JSONObject
.
parseObject
(
environment
.
getConfig
(),
EnvironmentConfig
.
class
);
}
LinkedList
<
MsTestElement
>
elements
=
mapper
.
readValue
(
element
.
getString
(
"hashTree"
),
new
TypeReference
<
LinkedList
<
MsTestElement
>>()
{
});
group
.
setHashTree
(
elements
);
testPlan
.
getHashTree
().
add
(
group
);
}
catch
(
Exception
ex
)
{
ex
.
printStackTrace
();
}
}
testPlan
.
toHashTree
(
jmeterTestPlanHashTree
,
testPlan
.
getHashTree
(),
config
);
// 调用执行方法
jMeterService
.
runDefinition
(
request
.
getId
(),
jmeterTestPlanHashTree
,
request
.
getReportId
(),
ApiRunMode
.
SCENARIO
.
name
());
createAPIReportResult
(
request
.
getId
());
return
request
.
getId
();
}
/**
* 场景测试执行
*
...
...
@@ -228,17 +296,7 @@ public class ApiAutomationService {
// 调用执行方法
jMeterService
.
runDefinition
(
request
.
getId
(),
hashTree
,
request
.
getReportId
(),
ApiRunMode
.
SCENARIO
.
name
());
APIReportResult
report
=
new
APIReportResult
();
report
.
setId
(
UUID
.
randomUUID
().
toString
());
report
.
setTestId
(
request
.
getReportId
());
report
.
setName
(
"RUN"
);
report
.
setTriggerMode
(
null
);
report
.
setCreateTime
(
System
.
currentTimeMillis
());
report
.
setUpdateTime
(
System
.
currentTimeMillis
());
report
.
setStatus
(
APITestStatus
.
Running
.
name
());
report
.
setUserId
(
SessionUtils
.
getUserId
());
apiReportService
.
addResult
(
report
);
createAPIReportResult
(
request
.
getId
());
return
request
.
getId
();
}
}
backend/src/main/java/io/metersphere/api/service/ApiScenarioReportService.java
浏览文件 @
b8488309
...
...
@@ -2,23 +2,39 @@ package io.metersphere.api.service;
import
com.alibaba.fastjson.JSONObject
;
import
io.metersphere.api.dto.APIReportResult
;
import
io.metersphere.api.dto.DeleteAPIReportRequest
;
import
io.metersphere.api.dto.QueryAPIReportRequest
;
import
io.metersphere.api.dto.automation.APIScenarioReportResult
;
import
io.metersphere.api.jmeter.TestResult
;
import
io.metersphere.base.domain.ApiTestReportDetail
;
import
io.metersphere.base.domain.*
;
import
io.metersphere.base.mapper.ApiScenarioReportDetailMapper
;
import
io.metersphere.base.mapper.ApiScenarioReportMapper
;
import
io.metersphere.base.mapper.ext.ExtApiScenarioReportMapper
;
import
io.metersphere.commons.constants.APITestStatus
;
import
io.metersphere.commons.exception.MSException
;
import
io.metersphere.commons.utils.ServiceUtils
;
import
io.metersphere.i18n.Translator
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
sun.security.util.Cache
;
import
javax.annotation.Resource
;
import
java.nio.charset.StandardCharsets
;
import
java.util.List
;
import
java.util.UUID
;
@Service
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
class
ApiScenarioReportService
{
private
static
Cache
cache
=
Cache
.
newHardMemoryCache
(
0
,
3600
*
24
);
@Resource
private
ExtApiScenarioReportMapper
extApiScenarioReportMapper
;
@Resource
private
ApiScenarioReportMapper
apiScenarioReportMapper
;
@Resource
private
ApiScenarioReportDetailMapper
apiScenarioReportDetailMapper
;
public
void
complete
(
TestResult
result
)
{
Object
obj
=
cache
.
get
(
result
.
getTestId
());
...
...
@@ -64,4 +80,103 @@ public class ApiScenarioReportService {
}
return
null
;
}
public
APIReportResult
get
(
String
reportId
)
{
APIReportResult
reportResult
=
extApiScenarioReportMapper
.
get
(
reportId
);
ApiScenarioReportDetail
detail
=
apiScenarioReportDetailMapper
.
selectByPrimaryKey
(
reportId
);
if
(
detail
!=
null
)
{
reportResult
.
setContent
(
new
String
(
detail
.
getContent
(),
StandardCharsets
.
UTF_8
));
}
return
reportResult
;
}
public
List
<
APIScenarioReportResult
>
list
(
QueryAPIReportRequest
request
)
{
request
.
setOrders
(
ServiceUtils
.
getDefaultOrder
(
request
.
getOrders
()));
return
extApiScenarioReportMapper
.
list
(
request
);
}
private
void
checkNameExist
(
APIScenarioReportResult
request
)
{
ApiScenarioReportExample
example
=
new
ApiScenarioReportExample
();
example
.
createCriteria
().
andNameEqualTo
(
request
.
getName
()).
andProjectIdEqualTo
(
request
.
getProjectId
()).
andIdNotEqualTo
(
request
.
getId
());
if
(
apiScenarioReportMapper
.
countByExample
(
example
)
>
0
)
{
MSException
.
throwException
(
Translator
.
get
(
"load_test_already_exists"
));
}
}
public
ApiScenarioReport
createReport
(
APIScenarioReportResult
test
)
{
checkNameExist
(
test
);
ApiScenarioReport
report
=
new
ApiScenarioReport
();
report
.
setId
(
UUID
.
randomUUID
().
toString
());
report
.
setProjectId
(
test
.
getProjectId
());
report
.
setName
(
test
.
getName
());
report
.
setTriggerMode
(
test
.
getTriggerMode
());
report
.
setDescription
(
test
.
getDescription
());
report
.
setCreateTime
(
System
.
currentTimeMillis
());
report
.
setUpdateTime
(
System
.
currentTimeMillis
());
report
.
setStatus
(
test
.
getStatus
());
report
.
setUserId
(
test
.
getUserId
());
apiScenarioReportMapper
.
insert
(
report
);
return
report
;
}
public
ApiScenarioReport
updateReport
(
APIScenarioReportResult
test
)
{
checkNameExist
(
test
);
ApiScenarioReport
report
=
new
ApiScenarioReport
();
report
.
setId
(
test
.
getId
());
report
.
setProjectId
(
test
.
getProjectId
());
report
.
setName
(
test
.
getName
());
report
.
setTriggerMode
(
test
.
getTriggerMode
());
report
.
setDescription
(
test
.
getDescription
());
report
.
setCreateTime
(
System
.
currentTimeMillis
());
report
.
setUpdateTime
(
System
.
currentTimeMillis
());
report
.
setStatus
(
test
.
getStatus
());
report
.
setUserId
(
test
.
getUserId
());
apiScenarioReportMapper
.
updateByPrimaryKey
(
report
);
return
report
;
}
public
String
add
(
APIScenarioReportResult
test
)
{
ApiScenarioReport
report
=
createReport
(
test
);
ApiScenarioReportDetail
detail
=
new
ApiScenarioReportDetail
();
detail
.
setContent
(
test
.
getContent
().
getBytes
(
StandardCharsets
.
UTF_8
));
detail
.
setReportId
(
report
.
getId
());
detail
.
setProjectId
(
test
.
getProjectId
());
apiScenarioReportDetailMapper
.
insert
(
detail
);
return
report
.
getId
();
}
public
String
update
(
APIScenarioReportResult
test
)
{
ApiScenarioReport
report
=
updateReport
(
test
);
ApiScenarioReportDetail
detail
=
apiScenarioReportDetailMapper
.
selectByPrimaryKey
(
test
.
getId
());
if
(
detail
==
null
)
{
detail
=
new
ApiScenarioReportDetail
();
detail
.
setContent
(
test
.
getContent
().
getBytes
(
StandardCharsets
.
UTF_8
));
detail
.
setReportId
(
report
.
getId
());
detail
.
setProjectId
(
test
.
getProjectId
());
apiScenarioReportDetailMapper
.
insert
(
detail
);
}
else
{
detail
.
setContent
(
test
.
getContent
().
getBytes
(
StandardCharsets
.
UTF_8
));
detail
.
setReportId
(
report
.
getId
());
detail
.
setProjectId
(
test
.
getProjectId
());
apiScenarioReportDetailMapper
.
updateByPrimaryKey
(
detail
);
}
return
report
.
getId
();
}
public
void
delete
(
DeleteAPIReportRequest
request
)
{
apiScenarioReportDetailMapper
.
deleteByPrimaryKey
(
request
.
getId
());
apiScenarioReportMapper
.
deleteByPrimaryKey
(
request
.
getId
());
}
public
void
deleteAPIReportBatch
(
DeleteAPIReportRequest
reportRequest
)
{
ApiScenarioReportDetailExample
detailExample
=
new
ApiScenarioReportDetailExample
();
detailExample
.
createCriteria
().
andReportIdIn
(
reportRequest
.
getIds
());
apiScenarioReportDetailMapper
.
deleteByExample
(
detailExample
);
ApiScenarioReportExample
apiTestReportExample
=
new
ApiScenarioReportExample
();
apiTestReportExample
.
createCriteria
().
andIdIn
(
reportRequest
.
getIds
());
apiScenarioReportMapper
.
deleteByExample
(
apiTestReportExample
);
}
}
backend/src/main/java/io/metersphere/base/domain/ApiScenarioReport.java
浏览文件 @
b8488309
package
io.metersphere.base.domain
;
import
java.io.Serializable
;
import
lombok.Data
;
import
java.io.Serializable
;
@Data
public
class
ApiScenarioReport
implements
Serializable
{
private
String
id
;
private
String
scenario
Id
;
private
String
project
Id
;
private
String
name
;
...
...
backend/src/main/java/io/metersphere/base/domain/ApiScenarioReportDetail.java
浏览文件 @
b8488309
...
...
@@ -7,7 +7,7 @@ import lombok.Data;
public
class
ApiScenarioReportDetail
implements
Serializable
{
private
String
reportId
;
private
String
scenario
Id
;
private
String
project
Id
;
private
byte
[]
content
;
...
...
backend/src/main/java/io/metersphere/base/domain/ApiScenarioReportDetailExample.java
浏览文件 @
b8488309
...
...
@@ -174,73 +174,73 @@ public class ApiScenarioReportDetailExample {
return
(
Criteria
)
this
;
}
public
Criteria
and
Scenario
IdIsNull
()
{
addCriterion
(
"
scenario
_id is null"
);
public
Criteria
and
Project
IdIsNull
()
{
addCriterion
(
"
project
_id is null"
);
return
(
Criteria
)
this
;
}
public
Criteria
and
Scenario
IdIsNotNull
()
{
addCriterion
(
"
scenario
_id is not null"
);
public
Criteria
and
Project
IdIsNotNull
()
{
addCriterion
(
"
project
_id is not null"
);
return
(
Criteria
)
this
;
}
public
Criteria
and
Scenario
IdEqualTo
(
String
value
)
{
addCriterion
(
"
scenario_id ="
,
value
,
"scenario
Id"
);
public
Criteria
and
Project
IdEqualTo
(
String
value
)
{
addCriterion
(
"
project_id ="
,
value
,
"project
Id"
);
return
(
Criteria
)
this
;
}
public
Criteria
and
Scenario
IdNotEqualTo
(
String
value
)
{
addCriterion
(
"
scenario_id <>"
,
value
,
"scenario
Id"
);
public
Criteria
and
Project
IdNotEqualTo
(
String
value
)
{
addCriterion
(
"
project_id <>"
,
value
,
"project
Id"
);
return
(
Criteria
)
this
;
}
public
Criteria
and
Scenario
IdGreaterThan
(
String
value
)
{
addCriterion
(
"
scenario_id >"
,
value
,
"scenario
Id"
);
public
Criteria
and
Project
IdGreaterThan
(
String
value
)
{
addCriterion
(
"
project_id >"
,
value
,
"project
Id"
);
return
(
Criteria
)
this
;
}
public
Criteria
and
Scenario
IdGreaterThanOrEqualTo
(
String
value
)
{
addCriterion
(
"
scenario_id >="
,
value
,
"scenario
Id"
);
public
Criteria
and
Project
IdGreaterThanOrEqualTo
(
String
value
)
{
addCriterion
(
"
project_id >="
,
value
,
"project
Id"
);
return
(
Criteria
)
this
;
}
public
Criteria
and
Scenario
IdLessThan
(
String
value
)
{
addCriterion
(
"
scenario_id <"
,
value
,
"scenario
Id"
);
public
Criteria
and
Project
IdLessThan
(
String
value
)
{
addCriterion
(
"
project_id <"
,
value
,
"project
Id"
);
return
(
Criteria
)
this
;
}
public
Criteria
and
Scenario
IdLessThanOrEqualTo
(
String
value
)
{
addCriterion
(
"
scenario_id <="
,
value
,
"scenario
Id"
);
public
Criteria
and
Project
IdLessThanOrEqualTo
(
String
value
)
{
addCriterion
(
"
project_id <="
,
value
,
"project
Id"
);
return
(
Criteria
)
this
;
}
public
Criteria
and
Scenario
IdLike
(
String
value
)
{
addCriterion
(
"
scenario_id like"
,
value
,
"scenario
Id"
);
public
Criteria
and
Project
IdLike
(
String
value
)
{
addCriterion
(
"
project_id like"
,
value
,
"project
Id"
);
return
(
Criteria
)
this
;
}
public
Criteria
and
Scenario
IdNotLike
(
String
value
)
{
addCriterion
(
"
scenario_id not like"
,
value
,
"scenario
Id"
);
public
Criteria
and
Project
IdNotLike
(
String
value
)
{
addCriterion
(
"
project_id not like"
,
value
,
"project
Id"
);
return
(
Criteria
)
this
;
}
public
Criteria
and
Scenario
IdIn
(
List
<
String
>
values
)
{
addCriterion
(
"
scenario_id in"
,
values
,
"scenario
Id"
);
public
Criteria
and
Project
IdIn
(
List
<
String
>
values
)
{
addCriterion
(
"
project_id in"
,
values
,
"project
Id"
);
return
(
Criteria
)
this
;
}
public
Criteria
and
Scenario
IdNotIn
(
List
<
String
>
values
)
{
addCriterion
(
"
scenario_id not in"
,
values
,
"scenario
Id"
);
public
Criteria
and
Project
IdNotIn
(
List
<
String
>
values
)
{
addCriterion
(
"
project_id not in"
,
values
,
"project
Id"
);
return
(
Criteria
)
this
;
}
public
Criteria
and
Scenario
IdBetween
(
String
value1
,
String
value2
)
{
addCriterion
(
"
scenario_id between"
,
value1
,
value2
,
"scenario
Id"
);
public
Criteria
and
Project
IdBetween
(
String
value1
,
String
value2
)
{
addCriterion
(
"
project_id between"
,
value1
,
value2
,
"project
Id"
);
return
(
Criteria
)
this
;
}
public
Criteria
and
Scenario
IdNotBetween
(
String
value1
,
String
value2
)
{
addCriterion
(
"
scenario_id not between"
,
value1
,
value2
,
"scenario
Id"
);
public
Criteria
and
Project
IdNotBetween
(
String
value1
,
String
value2
)
{
addCriterion
(
"
project_id not between"
,
value1
,
value2
,
"project
Id"
);
return
(
Criteria
)
this
;
}
}
...
...
backend/src/main/java/io/metersphere/base/domain/ApiScenarioReportExample.java
浏览文件 @
b8488309
...
...
@@ -174,73 +174,73 @@ public class ApiScenarioReportExample {
return
(
Criteria
)
this
;
}
public
Criteria
and
Scenario
IdIsNull
()
{
addCriterion
(
"
scenario
_id is null"
);
public
Criteria
and
Project
IdIsNull
()
{
addCriterion
(
"
project
_id is null"
);
return
(
Criteria
)
this
;
}
public
Criteria
and
Scenario
IdIsNotNull
()
{
addCriterion
(
"
scenario
_id is not null"
);
public
Criteria
and
Project
IdIsNotNull
()
{
addCriterion
(
"
project
_id is not null"
);
return
(
Criteria
)
this
;
}
public
Criteria
and
Scenario
IdEqualTo
(
String
value
)
{
addCriterion
(
"
scenario_id ="
,
value
,
"scenario
Id"
);
public
Criteria
and
Project
IdEqualTo
(
String
value
)
{
addCriterion
(
"
project_id ="
,
value
,
"project
Id"
);
return
(
Criteria
)
this
;
}
public
Criteria
and
Scenario
IdNotEqualTo
(
String
value
)
{
addCriterion
(
"
scenario_id <>"
,
value
,
"scenario
Id"
);
public
Criteria
and
Project
IdNotEqualTo
(
String
value
)
{
addCriterion
(
"
project_id <>"
,
value
,
"project
Id"
);
return
(
Criteria
)
this
;
}
public
Criteria
and
Scenario
IdGreaterThan
(
String
value
)
{
addCriterion
(
"
scenario_id >"
,
value
,
"scenario
Id"
);
public
Criteria
and
Project
IdGreaterThan
(
String
value
)
{
addCriterion
(
"
project_id >"
,
value
,
"project
Id"
);
return
(
Criteria
)
this
;
}
public
Criteria
and
Scenario
IdGreaterThanOrEqualTo
(
String
value
)
{
addCriterion
(
"
scenario_id >="
,
value
,
"scenario
Id"
);
public
Criteria
and
Project
IdGreaterThanOrEqualTo
(
String
value
)
{
addCriterion
(
"
project_id >="
,
value
,
"project
Id"
);
return
(
Criteria
)
this
;
}
public
Criteria
and
Scenario
IdLessThan
(
String
value
)
{
addCriterion
(
"
scenario_id <"
,
value
,
"scenario
Id"
);
public
Criteria
and
Project
IdLessThan
(
String
value
)
{
addCriterion
(
"
project_id <"
,
value
,
"project
Id"
);
return
(
Criteria
)
this
;
}
public
Criteria
and
Scenario
IdLessThanOrEqualTo
(
String
value
)
{
addCriterion
(
"
scenario_id <="
,
value
,
"scenario
Id"
);
public
Criteria
and
Project
IdLessThanOrEqualTo
(
String
value
)
{
addCriterion
(
"
project_id <="
,
value
,
"project
Id"
);
return
(
Criteria
)
this
;
}
public
Criteria
and
Scenario
IdLike
(
String
value
)
{
addCriterion
(
"
scenario_id like"
,
value
,
"scenario
Id"
);
public
Criteria
and
Project
IdLike
(
String
value
)
{
addCriterion
(
"
project_id like"
,
value
,
"project
Id"
);
return
(
Criteria
)
this
;
}
public
Criteria
and
Scenario
IdNotLike
(
String
value
)
{
addCriterion
(
"
scenario_id not like"
,
value
,
"scenario
Id"
);
public
Criteria
and
Project
IdNotLike
(
String
value
)
{
addCriterion
(
"
project_id not like"
,
value
,
"project
Id"
);
return
(
Criteria
)
this
;
}
public
Criteria
and
Scenario
IdIn
(
List
<
String
>
values
)
{
addCriterion
(
"
scenario_id in"
,
values
,
"scenario
Id"
);
public
Criteria
and
Project
IdIn
(
List
<
String
>
values
)
{
addCriterion
(
"
project_id in"
,
values
,
"project
Id"
);
return
(
Criteria
)
this
;
}
public
Criteria
and
Scenario
IdNotIn
(
List
<
String
>
values
)
{
addCriterion
(
"
scenario_id not in"
,
values
,
"scenario
Id"
);
public
Criteria
and
Project
IdNotIn
(
List
<
String
>
values
)
{
addCriterion
(
"
project_id not in"
,
values
,
"project
Id"
);
return
(
Criteria
)
this
;
}
public
Criteria
and
Scenario
IdBetween
(
String
value1
,
String
value2
)
{
addCriterion
(
"
scenario_id between"
,
value1
,
value2
,
"scenario
Id"
);
public
Criteria
and
Project
IdBetween
(
String
value1
,
String
value2
)
{
addCriterion
(
"
project_id between"
,
value1
,
value2
,
"project
Id"
);
return
(
Criteria
)
this
;
}
public
Criteria
and
Scenario
IdNotBetween
(
String
value1
,
String
value2
)
{
addCriterion
(
"
scenario_id not between"
,
value1
,
value2
,
"scenario
Id"
);
public
Criteria
and
Project
IdNotBetween
(
String
value1
,
String
value2
)
{
addCriterion
(
"
project_id not between"
,
value1
,
value2
,
"project
Id"
);
return
(
Criteria
)
this
;
}
...
...
backend/src/main/java/io/metersphere/base/mapper/ApiScenarioReportDetailMapper.xml
浏览文件 @
b8488309
...
...
@@ -3,7 +3,7 @@
<mapper
namespace=
"io.metersphere.base.mapper.ApiScenarioReportDetailMapper"
>
<resultMap
id=
"BaseResultMap"
type=
"io.metersphere.base.domain.ApiScenarioReportDetail"
>
<id
column=
"report_id"
jdbcType=
"VARCHAR"
property=
"reportId"
/>
<result
column=
"
scenario_id"
jdbcType=
"VARCHAR"
property=
"scenario
Id"
/>
<result
column=
"
project_id"
jdbcType=
"VARCHAR"
property=
"project
Id"
/>
</resultMap>
<resultMap
extends=
"BaseResultMap"
id=
"ResultMapWithBLOBs"
type=
"io.metersphere.base.domain.ApiScenarioReportDetail"
>
<result
column=
"content"
jdbcType=
"LONGVARBINARY"
property=
"content"
/>
...
...
@@ -67,7 +67,7 @@
</where>
</sql>
<sql
id=
"Base_Column_List"
>
report_id,
scenario
_id
report_id,
project
_id
</sql>
<sql
id=
"Blob_Column_List"
>
content
...
...
@@ -121,9 +121,9 @@
</if>
</delete>
<insert
id=
"insert"
parameterType=
"io.metersphere.base.domain.ApiScenarioReportDetail"
>
insert into api_scenario_report_detail (report_id,
scenario
_id, content
insert into api_scenario_report_detail (report_id,
project
_id, content
)
values (#{reportId,jdbcType=VARCHAR}, #{
scenario
Id,jdbcType=VARCHAR}, #{content,jdbcType=LONGVARBINARY}
values (#{reportId,jdbcType=VARCHAR}, #{
project
Id,jdbcType=VARCHAR}, #{content,jdbcType=LONGVARBINARY}
)
</insert>
<insert
id=
"insertSelective"
parameterType=
"io.metersphere.base.domain.ApiScenarioReportDetail"
>
...
...
@@ -132,8 +132,8 @@
<if
test=
"reportId != null"
>
report_id,
</if>
<if
test=
"
scenario
Id != null"
>
scenario
_id,
<if
test=
"
project
Id != null"
>
project
_id,
</if>
<if
test=
"content != null"
>
content,
...
...
@@ -143,8 +143,8 @@
<if
test=
"reportId != null"
>
#{reportId,jdbcType=VARCHAR},
</if>
<if
test=
"
scenario
Id != null"
>
#{
scenario
Id,jdbcType=VARCHAR},
<if
test=
"
project
Id != null"
>
#{
project
Id,jdbcType=VARCHAR},
</if>
<if
test=
"content != null"
>
#{content,jdbcType=LONGVARBINARY},
...
...
@@ -163,8 +163,8 @@
<if
test=
"record.reportId != null"
>
report_id = #{record.reportId,jdbcType=VARCHAR},
</if>
<if
test=
"record.
scenario
Id != null"
>
scenario_id = #{record.scenario
Id,jdbcType=VARCHAR},
<if
test=
"record.
project
Id != null"
>
project_id = #{record.project
Id,jdbcType=VARCHAR},
</if>
<if
test=
"record.content != null"
>
content = #{record.content,jdbcType=LONGVARBINARY},
...
...
@@ -177,7 +177,7 @@
<update
id=
"updateByExampleWithBLOBs"
parameterType=
"map"
>
update api_scenario_report_detail
set report_id = #{record.reportId,jdbcType=VARCHAR},
scenario_id = #{record.scenario
Id,jdbcType=VARCHAR},
project_id = #{record.project
Id,jdbcType=VARCHAR},
content = #{record.content,jdbcType=LONGVARBINARY}
<if
test=
"_parameter != null"
>
<include
refid=
"Update_By_Example_Where_Clause"
/>
...
...
@@ -186,7 +186,7 @@
<update
id=
"updateByExample"
parameterType=
"map"
>
update api_scenario_report_detail
set report_id = #{record.reportId,jdbcType=VARCHAR},
scenario_id = #{record.scenario
Id,jdbcType=VARCHAR}
project_id = #{record.project
Id,jdbcType=VARCHAR}
<if
test=
"_parameter != null"
>
<include
refid=
"Update_By_Example_Where_Clause"
/>
</if>
...
...
@@ -194,8 +194,8 @@
<update
id=
"updateByPrimaryKeySelective"
parameterType=
"io.metersphere.base.domain.ApiScenarioReportDetail"
>
update api_scenario_report_detail
<set>
<if
test=
"
scenario
Id != null"
>
scenario_id = #{scenario
Id,jdbcType=VARCHAR},
<if
test=
"
project
Id != null"
>
project_id = #{project
Id,jdbcType=VARCHAR},
</if>
<if
test=
"content != null"
>
content = #{content,jdbcType=LONGVARBINARY},
...
...
@@ -205,13 +205,13 @@
</update>
<update
id=
"updateByPrimaryKeyWithBLOBs"
parameterType=
"io.metersphere.base.domain.ApiScenarioReportDetail"
>
update api_scenario_report_detail
set
scenario_id = #{scenario
Id,jdbcType=VARCHAR},
set
project_id = #{project
Id,jdbcType=VARCHAR},
content = #{content,jdbcType=LONGVARBINARY}
where report_id = #{reportId,jdbcType=VARCHAR}
</update>
<update
id=
"updateByPrimaryKey"
parameterType=
"io.metersphere.base.domain.ApiScenarioReportDetail"
>
update api_scenario_report_detail
set
scenario_id = #{scenario
Id,jdbcType=VARCHAR}
set
project_id = #{project
Id,jdbcType=VARCHAR}
where report_id = #{reportId,jdbcType=VARCHAR}
</update>
</mapper>
\ No newline at end of file
backend/src/main/java/io/metersphere/base/mapper/ApiScenarioReportMapper.xml
浏览文件 @
b8488309
...
...
@@ -3,7 +3,7 @@
<mapper
namespace=
"io.metersphere.base.mapper.ApiScenarioReportMapper"
>
<resultMap
id=
"BaseResultMap"
type=
"io.metersphere.base.domain.ApiScenarioReport"
>
<id
column=
"id"
jdbcType=
"VARCHAR"
property=
"id"
/>
<result
column=
"
scenario_id"
jdbcType=
"VARCHAR"
property=
"scenario
Id"
/>
<result
column=
"
project_id"
jdbcType=
"VARCHAR"
property=
"project
Id"
/>
<result
column=
"name"
jdbcType=
"VARCHAR"
property=
"name"
/>
<result
column=
"description"
jdbcType=
"VARCHAR"
property=
"description"
/>
<result
column=
"create_time"
jdbcType=
"BIGINT"
property=
"createTime"
/>
...
...
@@ -71,7 +71,7 @@
</where>
</sql>
<sql
id=
"Base_Column_List"
>
id,
scenario
_id, `name`, description, create_time, update_time, `status`, user_id,
id,
project
_id, `name`, description, create_time, update_time, `status`, user_id,
trigger_mode
</sql>
<select
id=
"selectByExample"
parameterType=
"io.metersphere.base.domain.ApiScenarioReportExample"
resultMap=
"BaseResultMap"
>
...
...
@@ -105,11 +105,11 @@
</if>
</delete>
<insert
id=
"insert"
parameterType=
"io.metersphere.base.domain.ApiScenarioReport"
>
insert into api_scenario_report (id,
scenario
_id, `name`,
insert into api_scenario_report (id,
project
_id, `name`,
description, create_time, update_time,
`status`, user_id, trigger_mode
)
values (#{id,jdbcType=VARCHAR}, #{
scenario
Id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR},
values (#{id,jdbcType=VARCHAR}, #{
project
Id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR},
#{description,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
#{status,jdbcType=VARCHAR}, #{userId,jdbcType=VARCHAR}, #{triggerMode,jdbcType=VARCHAR}
)
...
...
@@ -120,8 +120,8 @@
<if
test=
"id != null"
>
id,
</if>
<if
test=
"
scenario
Id != null"
>
scenario
_id,
<if
test=
"
project
Id != null"
>
project
_id,
</if>
<if
test=
"name != null"
>
`name`,
...
...
@@ -149,8 +149,8 @@
<if
test=
"id != null"
>
#{id,jdbcType=VARCHAR},
</if>
<if
test=
"
scenario
Id != null"
>
#{
scenario
Id,jdbcType=VARCHAR},
<if
test=
"
project
Id != null"
>
#{
project
Id,jdbcType=VARCHAR},
</if>
<if
test=
"name != null"
>
#{name,jdbcType=VARCHAR},
...
...
@@ -187,8 +187,8 @@
<if
test=
"record.id != null"
>
id = #{record.id,jdbcType=VARCHAR},
</if>
<if
test=
"record.
scenario
Id != null"
>
scenario_id = #{record.scenario
Id,jdbcType=VARCHAR},
<if
test=
"record.
project
Id != null"
>
project_id = #{record.project
Id,jdbcType=VARCHAR},
</if>
<if
test=
"record.name != null"
>
`name` = #{record.name,jdbcType=VARCHAR},
...
...
@@ -219,7 +219,7 @@
<update
id=
"updateByExample"
parameterType=
"map"
>
update api_scenario_report
set id = #{record.id,jdbcType=VARCHAR},
scenario_id = #{record.scenario
Id,jdbcType=VARCHAR},
project_id = #{record.project
Id,jdbcType=VARCHAR},
`name` = #{record.name,jdbcType=VARCHAR},
description = #{record.description,jdbcType=VARCHAR},
create_time = #{record.createTime,jdbcType=BIGINT},
...
...
@@ -234,8 +234,8 @@
<update
id=
"updateByPrimaryKeySelective"
parameterType=
"io.metersphere.base.domain.ApiScenarioReport"
>
update api_scenario_report
<set>
<if
test=
"
scenario
Id != null"
>
scenario_id = #{scenario
Id,jdbcType=VARCHAR},
<if
test=
"
project
Id != null"
>
project_id = #{project
Id,jdbcType=VARCHAR},
</if>
<if
test=
"name != null"
>
`name` = #{name,jdbcType=VARCHAR},
...
...
@@ -263,7 +263,7 @@
</update>
<update
id=
"updateByPrimaryKey"
parameterType=
"io.metersphere.base.domain.ApiScenarioReport"
>
update api_scenario_report
set
scenario_id = #{scenario
Id,jdbcType=VARCHAR},
set
project_id = #{project
Id,jdbcType=VARCHAR},
`name` = #{name,jdbcType=VARCHAR},
description = #{description,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT},
...
...
backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioReportMapper.java
0 → 100644
浏览文件 @
b8488309
package
io.metersphere.base.mapper.ext
;
import
io.metersphere.api.dto.APIReportResult
;
import
io.metersphere.api.dto.QueryAPIReportRequest
;
import
io.metersphere.api.dto.automation.APIScenarioReportResult
;
import
org.apache.ibatis.annotations.Param
;
import
java.util.List
;
public
interface
ExtApiScenarioReportMapper
{
List
<
APIScenarioReportResult
>
list
(
@Param
(
"request"
)
QueryAPIReportRequest
request
);
APIReportResult
get
(
@Param
(
"reportId"
)
String
reportId
);
}
\ No newline at end of file
backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioReportMapper.xml
0 → 100644
浏览文件 @
b8488309
<?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.ExtApiScenarioReportMapper"
>
<resultMap
id=
"BaseResultMap"
type=
"io.metersphere.api.dto.automation.APIScenarioReportResult"
extends=
"io.metersphere.base.mapper.ApiScenarioReportMapper.BaseResultMap"
>
<result
column=
"test_name"
property=
"testName"
/>
<result
column=
"project_name"
property=
"projectName"
/>
<result
column=
"user_name"
property=
"userName"
/>
</resultMap>
<sql
id=
"condition"
>
<choose>
<when
test=
'${object}.operator == "like"'
>
like CONCAT('%', #{${object}.value},'%')
</when>
<when
test=
'${object}.operator == "not like"'
>
not like CONCAT('%', #{${object}.value},'%')
</when>
<when
test=
'${object}.operator == "in"'
>
in
<foreach
collection=
"${object}.value"
item=
"v"
separator=
","
open=
"("
close=
")"
>
#{v}
</foreach>
</when>
<when
test=
'${object}.operator == "not in"'
>
not in
<foreach
collection=
"${object}.value"
item=
"v"
separator=
","
open=
"("
close=
")"
>
#{v}
</foreach>
</when>
<when
test=
'${object}.operator == "between"'
>
between #{${object}.value[0]} and #{${object}.value[1]}
</when>
<when
test=
'${object}.operator == "gt"'
>
>
#{${object}.value}
</when>
<when
test=
'${object}.operator == "lt"'
>
<
#{${object}.value}
</when>
<when
test=
'${object}.operator == "ge"'
>
>
= #{${object}.value}
</when>
<when
test=
'${object}.operator == "le"'
>
<
= #{${object}.value}
</when>
<when
test=
'${object}.operator == "current user"'
>
= '${@io.metersphere.commons.utils.SessionUtils@getUserId()}'
</when>
<otherwise>
= #{${object}.value}
</otherwise>
</choose>
</sql>
<sql
id=
"combine"
>
<if
test=
'${condition}.name != null and (${name} == null or ${name} == "")'
>
and r.name
<include
refid=
"condition"
>
<property
name=
"object"
value=
"${condition}.name"
/>
</include>
</if>
<if
test=
"${condition}.testName != null"
>
and t.name
<include
refid=
"condition"
>
<property
name=
"object"
value=
"${condition}.testName"
/>
</include>
</if>
<if
test=
"${condition}.projectName != null"
>
and project.name
<include
refid=
"condition"
>
<property
name=
"object"
value=
"${condition}.projectName"
/>
</include>
</if>
<if
test=
"${condition}.createTime != null"
>
and r.create_time
<include
refid=
"condition"
>
<property
name=
"object"
value=
"${condition}.createTime"
/>
</include>
</if>
<if
test=
"${condition}.status != null"
>
and r.status
<include
refid=
"condition"
>
<property
name=
"object"
value=
"${condition}.status"
/>
</include>
</if>
<if
test=
"${condition}.triggerMode != null"
>
and r.trigger_mode
<include
refid=
"condition"
>
<property
name=
"object"
value=
"${condition}.triggerMode"
/>
</include>
</if>
<if
test=
"${condition}.creator != null"
>
and r.user_id
<include
refid=
"condition"
>
<property
name=
"object"
value=
"${condition}.creator"
/>
</include>
</if>
</sql>
<select
id=
"list"
resultMap=
"BaseResultMap"
>
SELECT r.name AS test_name,
r.name, r.description, r.id, r.project_id, r.create_time, r.update_time, r.status, r.trigger_mode,
project.name AS project_name, user.name AS user_name
FROM api_scenario_report r
LEFT JOIN project ON project.id = r.project_id
LEFT JOIN user ON user.id = r.user_id
<where>
<if
test=
"request.combine != null"
>
<include
refid=
"combine"
>
<property
name=
"condition"
value=
"request.combine"
/>
<property
name=
"name"
value=
"request.name"
/>
</include>
</if>
<if
test=
"request.name != null"
>
and r.name like CONCAT('%', #{request.name},'%')
</if>
<if
test=
"request.userId != null"
>
AND r.user_id = #{request.userId,jdbcType=VARCHAR}
</if>
<if
test=
"request.projectId != null"
>
AND project.id = #{request.projectId}
</if>
<if
test=
"request.workspaceId != null"
>
AND project.workspace_id = #{request.workspaceId,jdbcType=VARCHAR}
</if>
<if
test=
"request.filters != null and request.filters.size() > 0"
>
<foreach
collection=
"request.filters.entrySet()"
index=
"key"
item=
"values"
>
<if
test=
"values != null and values.size() > 0"
>
<choose>
<when
test=
"key=='status'"
>
and r.status in
<foreach
collection=
"values"
item=
"value"
separator=
","
open=
"("
close=
")"
>
#{value}
</foreach>
</when>
<otherwise>
and r.trigger_mode in
<foreach
collection=
"values"
item=
"value"
separator=
","
open=
"("
close=
")"
>
#{value}
</foreach>
</otherwise>
</choose>
</if>
</foreach>
</if>
AND r.status != 'Debug'
</where>
<if
test=
"request.orders != null and request.orders.size() > 0"
>
order by
<foreach
collection=
"request.orders"
separator=
","
item=
"order"
>
r.${order.name} ${order.type}
</foreach>
</if>
</select>
<select
id=
"get"
resultType=
"io.metersphere.api.dto.APIReportResult"
>
SELECT r.*,r.id As testId, r.name AS test_name, project.name AS project_name, user.name AS user_name
FROM api_scenario_report r
LEFT JOIN project ON project.id = r.project_id
LEFT JOIN user ON user.id = r.user_id
<where>
r.id = #{reportId}
</where>
ORDER BY r.update_time DESC
</select>
</mapper>
\ No newline at end of file
backend/src/main/resources/generatorConfig.xml
浏览文件 @
b8488309
...
...
@@ -64,10 +64,8 @@
<!--要生成的数据库表 -->
<table
tableName=
"schedule"
/>
<table
tableName=
"notice"
/>
<table
tableName=
"message_task"
/>
<table
tableName=
"test_plan"
/>
<table
tableName=
"api_scenario_report"
/>
<table
tableName=
"api_scenario_report_detail"
/>
</context>
</generatorConfiguration>
\ No newline at end of file
frontend/src/business/components/api/automation/report/ApiReportDetail.vue
浏览文件 @
b8488309
...
...
@@ -4,12 +4,12 @@
<el-card>
<section
class=
"report-container"
v-if=
"this.report.testId"
>
<ms-api-report-view-header
:report=
"report"
@
reportExport=
"handleExport"
/>
<ms-api-report-view-header
:report=
"report"
@
reportExport=
"handleExport"
@
reportSave=
"handleSave"
/>
<main
v-if=
"this.isNotRunning"
>
<ms-metric-chart
:content=
"content"
:totalTime=
"totalTime"
/>
<div
@
click=
"active"
>
<ms-scenario-results
:scenarios=
"content.scenarios"
v-on:requestResult=
"requestResult"
/>
<div>
<ms-scenario-results
:scenarios=
"content.scenarios"
v-on:requestResult=
"requestResult"
/>
</div>
<el-collapse-transition>
<div
v-show=
"isActive"
style=
"width: 99%"
>
...
...
@@ -64,10 +64,14 @@
requestType
:
undefined
,
}
},
props
:
[
'
reportId
'
],
activated
()
{
this
.
isRequestResult
=
false
;
},
props
:
{
reportId
:
String
,
currentProjectId
:
String
,
infoDb
:
Boolean
,
},
watch
:
{
reportId
()
{
this
.
getReport
();
...
...
@@ -91,7 +95,7 @@
getReport
()
{
this
.
init
();
if
(
this
.
reportId
)
{
let
url
=
"
/api/scenario/report/get/
"
+
this
.
reportId
;
let
url
=
"
/api/scenario/report/get/
"
+
this
.
reportId
+
"
/
"
+
this
.
infoDb
;
this
.
$get
(
url
,
response
=>
{
this
.
report
=
response
.
data
||
{};
if
(
response
.
data
)
{
...
...
@@ -99,7 +103,6 @@
try
{
this
.
content
=
JSON
.
parse
(
this
.
report
.
content
);
}
catch
(
e
)
{
// console.log(this.report.content)
throw
e
;
}
this
.
getFails
();
...
...
@@ -136,6 +139,7 @@
}
},
requestResult
(
requestResult
)
{
this
.
active
();
this
.
isRequestResult
=
false
;
this
.
requestType
=
undefined
;
if
(
requestResult
.
request
.
body
.
indexOf
(
'
[Callable Statement]
'
)
>
-
1
)
{
...
...
@@ -155,6 +159,27 @@
reset
();
});
},
handleSave
()
{
if
(
!
this
.
report
.
name
)
{
this
.
$warning
(
this
.
$t
(
'
api_test.automation.report_name_info
'
));
return
;
}
if
(
!
this
.
currentProjectId
)
{
this
.
$warning
(
this
.
$t
(
'
api_test.select_project
'
));
return
;
}
this
.
loading
=
true
;
this
.
report
.
projectId
=
this
.
currentProjectId
;
let
url
=
"
/api/scenario/report/add
"
;
if
(
this
.
infoDb
===
true
)
{
url
=
"
/api/scenario/report/update
"
;
}
this
.
result
=
this
.
$post
(
url
,
this
.
report
,
response
=>
{
this
.
$success
(
this
.
$t
(
'
commons.save_success
'
));
this
.
loading
=
false
;
this
.
$emit
(
'
refresh
'
);
});
},
exportReportReset
()
{
this
.
$router
.
go
(
0
);
}
...
...
frontend/src/business/components/api/automation/report/ApiReportList.vue
0 → 100644
浏览文件 @
b8488309
<
template
>
<ms-container>
<ms-main-container>
<el-card
class=
"table-card"
v-loading=
"result.loading"
>
<template
v-slot:header
>
<ms-table-header
:is-tester-permission=
"true"
:condition.sync=
"condition"
@
search=
"search"
:title=
"$t('api_report.title')"
:show-create=
"false"
/>
</
template
>
<el-table
border
:data=
"tableData"
class=
"adjust-table table-content"
@
sort-change=
"sort"
@
select-all=
"handleSelectAll"
@
select=
"handleSelect"
@
filter-change=
"filter"
@
row-click=
"handleView"
>
<el-table-column
type=
"selection"
/>
<el-table-column
width=
"40"
:resizable=
"false"
align=
"center"
>
<
template
v-slot:default=
"scope"
>
<show-more-btn
:is-show=
"scope.row.showMore"
:buttons=
"buttons"
:size=
"selectRows.size"
/>
</
template
>
</el-table-column>
<el-table-column
:label=
"$t('commons.name')"
width=
"200"
show-overflow-tooltip
prop=
"name"
>
</el-table-column>
<!--
<el-table-column prop="testName" :label="$t('api_report.test_name')" width="200" show-overflow-tooltip/>
-->
<el-table-column
prop=
"projectName"
:label=
"$t('load_test.project_name')"
width=
"150"
show-overflow-tooltip
/>
<el-table-column
prop=
"userName"
:label=
"$t('api_test.creator')"
width=
"150"
show-overflow-tooltip
/>
<el-table-column
prop=
"createTime"
width=
"250"
:label=
"$t('commons.create_time')"
sortable
>
<
template
v-slot:default=
"scope"
>
<span>
{{
scope
.
row
.
createTime
|
timestampFormatDate
}}
</span>
</
template
>
</el-table-column>
<el-table-column
prop=
"triggerMode"
width=
"150"
:label=
"$t('commons.trigger_mode.name')"
column-key=
"triggerMode"
:filters=
"triggerFilters"
>
<
template
v-slot:default=
"scope"
>
<report-trigger-mode-item
:trigger-mode=
"scope.row.triggerMode"
/>
</
template
>
</el-table-column>
<el-table-column
prop=
"status"
:label=
"$t('commons.status')"
column-key=
"status"
:filters=
"statusFilters"
>
<
template
v-slot:default=
"{row}"
>
<ms-api-report-status
:row=
"row"
/>
</
template
>
</el-table-column>
<el-table-column
width=
"150"
:label=
"$t('commons.operating')"
>
<
template
v-slot:default=
"scope"
>
<ms-table-operator-button
:tip=
"$t('api_report.detail')"
icon=
"el-icon-s-data"
@
exec=
"handleView(scope.row)"
type=
"primary"
/>
<ms-table-operator-button
:is-tester-permission=
"true"
:tip=
"$t('api_report.delete')"
icon=
"el-icon-delete"
@
exec=
"handleDelete(scope.row)"
type=
"danger"
/>
</
template
>
</el-table-column>
</el-table>
<ms-table-pagination
:change=
"search"
:current-page.sync=
"currentPage"
:page-size.sync=
"pageSize"
:total=
"total"
/>
</el-card>
</ms-main-container>
<el-drawer
:visible.sync=
"debugVisible"
:destroy-on-close=
"true"
direction=
"ltr"
:withHeader=
"false"
:title=
"$t('test_track.plan_view.test_result')"
:modal=
"false"
size=
"90%"
>
<ms-api-report-detail
:report-id=
"reportId"
:currentProjectId=
"currentProjectId"
:info-db=
"true"
@
refresh=
"search"
/>
</el-drawer>
</ms-container>
</template>
<
script
>
import
MsTablePagination
from
"
../../../common/pagination/TablePagination
"
;
import
MsTableHeader
from
"
../../../common/components/MsTableHeader
"
;
import
MsContainer
from
"
../../../common/components/MsContainer
"
;
import
MsMainContainer
from
"
../../../common/components/MsMainContainer
"
;
import
MsApiReportStatus
from
"
./ApiReportStatus
"
;
import
{
_filter
,
_sort
}
from
"
@/common/js/utils
"
;
import
MsTableOperatorButton
from
"
../../../common/components/MsTableOperatorButton
"
;
import
ReportTriggerModeItem
from
"
../../../common/tableItem/ReportTriggerModeItem
"
;
import
{
REPORT_CONFIGS
}
from
"
../../../common/components/search/search-components
"
;
import
{
ApiEvent
,
LIST_CHANGE
}
from
"
@/business/components/common/head/ListEvent
"
;
import
ShowMoreBtn
from
"
../../../track/case/components/ShowMoreBtn
"
;
import
MsApiReportDetail
from
"
./ApiReportDetail
"
;
export
default
{
components
:
{
ReportTriggerModeItem
,
MsTableOperatorButton
,
MsApiReportStatus
,
MsMainContainer
,
MsContainer
,
MsTableHeader
,
MsTablePagination
,
ShowMoreBtn
,
MsApiReportDetail
},
data
()
{
return
{
result
:
{},
reportId
:
""
,
debugVisible
:
false
,
condition
:
{
components
:
REPORT_CONFIGS
},
tableData
:
[],
multipleSelection
:
[],
currentPage
:
1
,
pageSize
:
5
,
total
:
0
,
loading
:
false
,
currentProjectId
:
""
,
statusFilters
:
[
{
text
:
'
Saved
'
,
value
:
'
Saved
'
},
{
text
:
'
Starting
'
,
value
:
'
Starting
'
},
{
text
:
'
Running
'
,
value
:
'
Running
'
},
{
text
:
'
Reporting
'
,
value
:
'
Reporting
'
},
{
text
:
'
Completed
'
,
value
:
'
Completed
'
},
{
text
:
'
Error
'
,
value
:
'
Error
'
},
{
text
:
'
Success
'
,
value
:
'
Success
'
},
],
triggerFilters
:
[
{
text
:
this
.
$t
(
'
commons.trigger_mode.manual
'
),
value
:
'
MANUAL
'
},
{
text
:
this
.
$t
(
'
commons.trigger_mode.schedule
'
),
value
:
'
SCHEDULE
'
},
{
text
:
this
.
$t
(
'
commons.trigger_mode.api
'
),
value
:
'
API
'
}
],
buttons
:
[
{
name
:
this
.
$t
(
'
api_report.batch_delete
'
),
handleClick
:
this
.
handleBatchDelete
}
],
selectRows
:
new
Set
(),
}
},
watch
:
{
'
$route
'
:
'
init
'
,
},
methods
:
{
search
()
{
if
(
this
.
testId
!==
'
all
'
)
{
this
.
condition
.
testId
=
this
.
testId
;
}
let
url
=
"
/api/scenario/report/list/
"
+
this
.
currentPage
+
"
/
"
+
this
.
pageSize
;
this
.
result
=
this
.
$post
(
url
,
this
.
condition
,
response
=>
{
let
data
=
response
.
data
;
this
.
total
=
data
.
itemCount
;
this
.
tableData
=
data
.
listObject
;
this
.
selectRows
.
clear
();
});
},
handleSelectionChange
(
val
)
{
this
.
multipleSelection
=
val
;
},
handleView
(
report
)
{
this
.
reportId
=
report
.
id
;
this
.
currentProjectId
=
report
.
projectId
;
this
.
debugVisible
=
true
;
},
handleDelete
(
report
)
{
this
.
$alert
(
this
.
$t
(
'
api_report.delete_confirm
'
)
+
report
.
name
+
"
?
"
,
''
,
{
confirmButtonText
:
this
.
$t
(
'
commons.confirm
'
),
callback
:
(
action
)
=>
{
if
(
action
===
'
confirm
'
)
{
this
.
result
=
this
.
$post
(
"
/api/scenario/report/delete
"
,
{
id
:
report
.
id
},
()
=>
{
this
.
$success
(
this
.
$t
(
'
commons.delete_success
'
));
this
.
search
();
// 发送广播,刷新 head 上的最新列表
ApiEvent
.
$emit
(
LIST_CHANGE
);
});
}
}
});
},
init
()
{
this
.
testId
=
this
.
$route
.
params
.
testId
;
this
.
search
();
},
sort
(
column
)
{
_sort
(
column
,
this
.
condition
);
this
.
init
();
},
filter
(
filters
)
{
_filter
(
filters
,
this
.
condition
);
this
.
init
();
},
handleSelect
(
selection
,
row
)
{
if
(
this
.
selectRows
.
has
(
row
))
{
this
.
$set
(
row
,
"
showMore
"
,
false
);
this
.
selectRows
.
delete
(
row
);
}
else
{
this
.
$set
(
row
,
"
showMore
"
,
true
);
this
.
selectRows
.
add
(
row
);
}
},
handleSelectAll
(
selection
)
{
if
(
selection
.
length
>
0
)
{
this
.
tableData
.
forEach
(
item
=>
{
this
.
$set
(
item
,
"
showMore
"
,
true
);
this
.
selectRows
.
add
(
item
);
});
}
else
{
this
.
selectRows
.
clear
();
this
.
tableData
.
forEach
(
row
=>
{
this
.
$set
(
row
,
"
showMore
"
,
false
);
})
}
},
handleBatchDelete
()
{
this
.
$alert
(
this
.
$t
(
'
api_report.delete_batch_confirm
'
)
+
"
?
"
,
''
,
{
confirmButtonText
:
this
.
$t
(
'
commons.confirm
'
),
callback
:
(
action
)
=>
{
if
(
action
===
'
confirm
'
)
{
let
ids
=
Array
.
from
(
this
.
selectRows
).
map
(
row
=>
row
.
id
);
this
.
$post
(
'
/api/scenario/report/batch/delete
'
,
{
ids
:
ids
},
()
=>
{
this
.
selectRows
.
clear
();
this
.
$success
(
this
.
$t
(
'
commons.delete_success
'
));
this
.
search
();
// 发送广播,刷新 head 上的最新列表
ApiEvent
.
$emit
(
LIST_CHANGE
);
});
}
}
});
}
},
created
()
{
this
.
init
();
}
}
</
script
>
<
style
scoped
>
.table-content
{
width
:
100%
;
}
</
style
>
frontend/src/business/components/api/automation/report/ApiReportViewHeader.vue
浏览文件 @
b8488309
...
...
@@ -2,13 +2,17 @@
<header
class=
"report-header"
>
<el-row>
<el-col>
<span>
{{
report
.
projectName
===
null
||
report
.
projectName
===
''
?
"
场景执行报告
"
:
report
.
projectName
}}
/
</span>
<router-link
:to=
"path"
>
{{
report
.
testName
}}
</router-link>
<span><el-input
size=
"mini"
style=
"width: 200px"
v-model=
"report.name"
/>
</span>
<span
class=
"time"
>
{{
report
.
createTime
|
timestampFormatDate
}}
</span>
<el-button
:disabled=
"isReadOnly"
class=
"export-button"
plain
type=
"primary"
size=
"mini"
@
click=
"handleExport(report.name)"
style=
"margin-left: 120
0px"
>
<el-button
:disabled=
"isReadOnly"
class=
"export-button"
plain
type=
"primary"
size=
"mini"
@
click=
"handleExport(report.name)"
style=
"margin-right: 1
0px"
>
{{
$t
(
'
test_track.plan_view.export_report
'
)
}}
</el-button>
<el-button
:disabled=
"isReadOnly"
class=
"export-button"
plain
type=
"primary"
size=
"mini"
@
click=
"handleSave(report.name)"
style=
"margin-right: 10px"
>
{{
$t
(
'
commons.save
'
)
}}
</el-button>
</el-col>
</el-row>
</header>
...
...
@@ -38,6 +42,9 @@
methods
:
{
handleExport
(
name
)
{
this
.
$emit
(
'
reportExport
'
,
name
);
},
handleSave
(
name
)
{
this
.
$emit
(
'
reportSave
'
,
name
);
}
}
}
...
...
frontend/src/business/components/api/automation/report/components/ScenarioResult.vue
浏览文件 @
b8488309
<
template
>
<div
class=
"scenario-result"
>
<div
v-for=
"(request, index) in scenario.requestResults"
:key=
"index"
>
<ms-request-result
:key=
"index"
:request=
"request"
:indexNumber=
"index"
v-on:requestResult=
"requestResult"
:scenarioName=
"scenario.name"
/>
<div
@
click=
"active"
>
<el-row
:gutter=
"10"
type=
"flex"
align=
"middle"
class=
"info"
>
<el-col
:span=
"16"
>
<i
class=
"icon el-icon-arrow-right"
:class=
"
{'is-active': isActive}"/>
{{
scenario
.
name
}}
</el-col>
</el-row>
</div>
<el-collapse-transition>
<div
v-show=
"isActive"
>
<div
v-for=
"(request, index) in scenario.requestResults"
:key=
"index"
>
<ms-request-result
:key=
"index"
:request=
"request"
:indexNumber=
"index"
v-on:requestResult=
"requestResult"
:scenarioName=
"scenario.name"
/>
</div>
</div>
</el-collapse-transition>
</div>
</
template
>
...
...
frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue
浏览文件 @
b8488309
<
template
>
<el-card
class=
"table-card"
v-loading=
"result.loading"
>
<template
v-slot:header
>
<ms-table-header
:condition.sync=
"condition"
@
search=
"search"
title=
""
:show-create=
"false"
/>
</
template
>
<div>
<el-card
class=
"table-card"
v-loading=
"result.loading"
>
<template
v-slot:header
>
<ms-table-header
:condition.sync=
"condition"
@
search=
"search"
title=
""
:show-create=
"false"
/>
</
template
>
<el-table
ref=
"scenarioTable"
border
:data=
"tableData"
class=
"adjust-table"
@
select-all=
"select"
@
select=
"select"
>
<el-table-column
type=
"selection"
/>
<el-table-column
width=
"40"
:resizable=
"false"
align=
"center"
>
<
template
v-slot:default=
"{row}"
>
<show-more-btn
:is-show=
"isSelect(row)"
:buttons=
"buttons"
:size=
"selection.length"
/>
</
template
>
</el-table-column>
<el-table-column
prop=
"name"
:label=
"$t('api_test.automation.scenario_name')"
show-overflow-tooltip
/>
<el-table-column
prop=
"level"
:label=
"$t('api_test.automation.case_level')"
show-overflow-tooltip
>
<
template
v-slot:default=
"scope"
>
<ms-tag
v-if=
"scope.row.level == 'P0'"
type=
"info"
effect=
"plain"
content=
"P0"
/>
<ms-tag
v-if=
"scope.row.level == 'P1'"
type=
"warning"
effect=
"plain"
content=
"P1"
/>
<ms-tag
v-if=
"scope.row.level == 'P2'"
type=
"success"
effect=
"plain"
content=
"P2"
/>
<ms-tag
v-if=
"scope.row.level == 'P3'"
type=
"danger"
effect=
"plain"
content=
"P3"
/>
</
template
>
<el-table
ref=
"scenarioTable"
border
:data=
"tableData"
class=
"adjust-table"
@
select-all=
"select"
@
select=
"select"
>
<el-table-column
type=
"selection"
/>
<el-table-column
width=
"40"
:resizable=
"false"
align=
"center"
>
<
template
v-slot:default=
"{row}"
>
<show-more-btn
:is-show=
"isSelect(row)"
:buttons=
"buttons"
:size=
"selection.length"
/>
</
template
>
</el-table-column>
<el-table-column
prop=
"name"
:label=
"$t('api_test.automation.scenario_name')"
show-overflow-tooltip
/>
<el-table-column
prop=
"level"
:label=
"$t('api_test.automation.case_level')"
show-overflow-tooltip
>
<
template
v-slot:default=
"scope"
>
<ms-tag
v-if=
"scope.row.level == 'P0'"
type=
"info"
effect=
"plain"
content=
"P0"
/>
<ms-tag
v-if=
"scope.row.level == 'P1'"
type=
"warning"
effect=
"plain"
content=
"P1"
/>
<ms-tag
v-if=
"scope.row.level == 'P2'"
type=
"success"
effect=
"plain"
content=
"P2"
/>
<ms-tag
v-if=
"scope.row.level == 'P3'"
type=
"danger"
effect=
"plain"
content=
"P3"
/>
</
template
>
</el-table-column>
<el-table-column
prop=
"tagName"
:label=
"$t('api_test.automation.tag')"
show-overflow-tooltip
>
<
template
v-slot:default=
"scope"
>
<ms-tag
type=
"success"
effect=
"plain"
v-if=
"scope.row.tagName!=undefined"
:content=
"scope.row.tagName"
/>
</
template
>
</el-table-column>
<el-table-column
prop=
"userId"
:label=
"$t('api_test.automation.creator')"
show-overflow-tooltip
/>
<el-table-column
prop=
"updateTime"
:label=
"$t('api_test.automation.update_time')"
width=
"180"
>
<
template
v-slot:default=
"scope"
>
<span>
{{
scope
.
row
.
updateTime
|
timestampFormatDate
}}
</span>
</
template
>
</el-table-column>
<el-table-column
prop=
"stepTotal"
:label=
"$t('api_test.automation.step')"
show-overflow-tooltip
/>
<el-table-column
prop=
"status"
:label=
"$t('api_test.automation.last_result')"
>
<
template
v-slot:default=
"{row}"
>
<el-link
type=
"success"
v-if=
"row.status === 'Success'"
>
{{
$t
(
'
api_test.automation.success
'
)
}}
</el-link>
<el-link
type=
"danger"
v-if=
"row.status === 'Fail'"
>
{{
$t
(
'
api_test.automation.fail
'
)
}}
</el-link>
<el-link
type=
"warning"
v-if=
"row.status === 'Trash'"
>
{{
$t
(
'
api_test.automation.trash
'
)
}}
</el-link>
</
template
>
</el-table-column>
<el-table-column
prop=
"passingRate"
:label=
"$t('api_test.automation.passing_rate')"
show-overflow-tooltip
/>
<el-table-column
:label=
"$t('commons.operating')"
width=
"180"
>
<
template
v-slot:default=
"{row}"
>
<el-button
type=
"text"
@
click=
"edit(row)"
>
{{
$t
(
'
api_test.automation.edit
'
)
}}
</el-button>
<el-button
type=
"text"
@
click=
"execute(row)"
>
{{
$t
(
'
api_test.automation.execute
'
)
}}
</el-button>
<el-button
type=
"text"
@
click=
"copy(row)"
>
{{
$t
(
'
api_test.automation.copy
'
)
}}
</el-button>
<el-button
type=
"text"
@
click=
"remove(row)"
>
{{
$t
(
'
api_test.automation.remove
'
)
}}
</el-button>
</
template
>
</el-table-column>
</el-table>
<ms-table-pagination
:change=
"search"
:current-page.sync=
"currentPage"
:page-size.sync=
"pageSize"
:total=
"total"
/>
</el-card>
</el-table-column>
<el-table-column
prop=
"tagName"
:label=
"$t('api_test.automation.tag')"
show-overflow-tooltip
>
<
template
v-slot:default=
"scope"
>
<ms-tag
type=
"success"
effect=
"plain"
v-if=
"scope.row.tagName!=undefined"
:content=
"scope.row.tagName"
/>
</
template
>
</el-table-column>
<el-table-column
prop=
"userId"
:label=
"$t('api_test.automation.creator')"
show-overflow-tooltip
/>
<el-table-column
prop=
"updateTime"
:label=
"$t('api_test.automation.update_time')"
width=
"180"
>
<
template
v-slot:default=
"scope"
>
<span>
{{
scope
.
row
.
updateTime
|
timestampFormatDate
}}
</span>
</
template
>
</el-table-column>
<el-table-column
prop=
"stepTotal"
:label=
"$t('api_test.automation.step')"
show-overflow-tooltip
/>
<el-table-column
prop=
"status"
:label=
"$t('api_test.automation.last_result')"
>
<
template
v-slot:default=
"{row}"
>
<el-link
type=
"success"
v-if=
"row.status === 'Success'"
>
{{
$t
(
'
api_test.automation.success
'
)
}}
</el-link>
<el-link
type=
"danger"
v-if=
"row.status === 'Fail'"
>
{{
$t
(
'
api_test.automation.fail
'
)
}}
</el-link>
<el-link
type=
"warning"
v-if=
"row.status === 'Trash'"
>
{{
$t
(
'
api_test.automation.trash
'
)
}}
</el-link>
</
template
>
</el-table-column>
<el-table-column
prop=
"passingRate"
:label=
"$t('api_test.automation.passing_rate')"
show-overflow-tooltip
/>
<el-table-column
:label=
"$t('commons.operating')"
width=
"180"
>
<
template
v-slot:default=
"{row}"
>
<el-button
type=
"text"
@
click=
"edit(row)"
>
{{
$t
(
'
api_test.automation.edit
'
)
}}
</el-button>
<el-button
type=
"text"
@
click=
"execute(row)"
>
{{
$t
(
'
api_test.automation.execute
'
)
}}
</el-button>
<el-button
type=
"text"
@
click=
"copy(row)"
>
{{
$t
(
'
api_test.automation.copy
'
)
}}
</el-button>
<el-button
type=
"text"
@
click=
"remove(row)"
>
{{
$t
(
'
api_test.automation.remove
'
)
}}
</el-button>
</
template
>
</el-table-column>
</el-table>
<ms-table-pagination
:change=
"search"
:current-page.sync=
"currentPage"
:page-size.sync=
"pageSize"
:total=
"total"
/>
<div>
<!-- 调试结果 -->
<el-drawer
:visible.sync=
"runVisible"
:destroy-on-close=
"true"
direction=
"ltr"
:withHeader=
"false"
:title=
"$t('test_track.plan_view.test_result')"
:modal=
"false"
size=
"90%"
>
<ms-api-report-detail
:report-id=
"reportId"
:currentProjectId=
"currentProject!=undefined ? currentProject.id:''"
/>
</el-drawer>
</div>
</el-card>
</div>
</template>
<
script
>
...
...
@@ -65,10 +75,11 @@
import
ShowMoreBtn
from
"
@/business/components/track/case/components/ShowMoreBtn
"
;
import
MsTag
from
"
../../../common/components/MsTag
"
;
import
{
getUUID
}
from
"
@/common/js/utils
"
;
import
MsApiReportDetail
from
"
../report/ApiReportDetail
"
;
export
default
{
name
:
"
MsApiScenarioList
"
,
components
:
{
ShowMoreBtn
,
MsTablePagination
,
MsTableHeader
,
MsTag
},
components
:
{
ShowMoreBtn
,
MsTablePagination
,
MsTableHeader
,
MsTag
,
MsApiReportDetail
},
props
:
{
currentProject
:
Object
,
currentModule
:
Object
,
...
...
@@ -83,6 +94,9 @@
currentPage
:
1
,
pageSize
:
10
,
total
:
0
,
reportId
:
""
,
runVisible
:
false
,
runData
:
[],
buttons
:
[
{
name
:
this
.
$t
(
'
api_test.automation.batch_add_plan
'
),
handleClick
:
this
.
handleBatchAddCase
...
...
@@ -140,7 +154,16 @@
},
handleBatchExecute
()
{
let
url
=
"
/api/automation/run
"
;
let
run
=
{};
let
scenarioIds
=
this
.
selection
;
run
.
id
=
getUUID
();
run
.
scenarioIds
=
scenarioIds
;
this
.
result
=
this
.
$post
(
url
,
run
,
response
=>
{
let
data
=
response
.
data
;
this
.
runVisible
=
true
;
this
.
reportId
=
run
.
id
;
});
},
selectAllChange
()
{
this
.
handleCommand
(
"
table
"
);
...
...
@@ -156,7 +179,17 @@
this
.
$emit
(
'
edit
'
,
row
);
},
execute
(
row
)
{
let
url
=
"
/api/automation/run
"
;
let
run
=
{};
let
scenarioIds
=
[];
scenarioIds
.
push
(
row
.
id
);
run
.
id
=
getUUID
();
run
.
scenarioIds
=
scenarioIds
;
this
.
result
=
this
.
$post
(
url
,
run
,
response
=>
{
let
data
=
response
.
data
;
this
.
runVisible
=
true
;
this
.
reportId
=
run
.
id
;
});
},
copy
(
row
)
{
row
.
id
=
getUUID
();
...
...
frontend/src/business/components/api/automation/scenario/Run.vue
→
frontend/src/business/components/api/automation/scenario/
Debug
Run.vue
浏览文件 @
b8488309
...
...
@@ -3,17 +3,16 @@
</
template
>
<
script
>
import
{
getUUID
}
from
"
@/common/js/utils
"
;
import
ThreadGroup
from
"
../../definition/components/jmeter/components/thread-group
"
;
import
TestPlan
from
"
../../definition/components/jmeter/components/test-plan
"
;
import
{
createComponent
}
from
"
../../definition/components/jmeter/components
"
;
export
default
{
name
:
'
MsRun
'
,
name
:
'
Ms
Debug
Run
'
,
components
:
{},
props
:
{
environment
:
String
,
debug
:
Boolean
,
reportId
:
String
,
runData
:
Array
,
runData
:
Object
,
},
data
()
{
return
{
...
...
@@ -31,82 +30,71 @@
}
},
methods
:
{
getResult
()
{
if
(
this
.
runId
)
{
let
url
=
""
;
if
(
this
.
debug
)
{
url
=
"
/api/definition/report/get/
"
+
this
.
runId
+
"
/
"
+
"
debug
"
;
}
else
{
url
=
"
/api/definition/report/get/
"
+
this
.
runId
+
"
/
"
+
"
run
"
;
}
this
.
$get
(
url
,
response
=>
{
if
(
response
.
data
)
{
let
data
=
JSON
.
parse
(
response
.
data
.
content
);
this
.
$emit
(
'
runRefresh
'
,
data
);
}
else
{
if
(
this
.
reqNumber
<
60
)
{
this
.
reqNumber
++
;
setTimeout
(
this
.
getResult
,
2000
);
}
else
{
this
.
$error
(
"
获取报告超时
"
);
this
.
$emit
(
'
runRefresh
'
,
{});
}
setFiles
(
item
,
bodyUploadFiles
,
obj
)
{
if
(
item
.
body
)
{
item
.
body
.
kvs
.
forEach
(
param
=>
{
if
(
param
.
files
)
{
param
.
files
.
forEach
(
item
=>
{
if
(
item
.
file
)
{
if
(
!
item
.
id
)
{
let
fileId
=
getUUID
().
substring
(
0
,
12
);
item
.
name
=
item
.
file
.
name
;
item
.
id
=
fileId
;
}
obj
.
bodyUploadIds
.
push
(
item
.
id
);
bodyUploadFiles
.
push
(
item
.
file
);
}
});
}
});
item
.
body
.
binary
.
forEach
(
param
=>
{
if
(
param
.
files
)
{
param
.
files
.
forEach
(
item
=>
{
if
(
item
.
file
)
{
if
(
!
item
.
id
)
{
let
fileId
=
getUUID
().
substring
(
0
,
12
);
item
.
name
=
item
.
file
.
name
;
item
.
id
=
fileId
;
}
obj
.
bodyUploadIds
.
push
(
item
.
id
);
bodyUploadFiles
.
push
(
item
.
file
);
}
});
}
});
}
},
recursiveFile
(
arr
,
bodyUploadFiles
,
obj
)
{
arr
.
forEach
(
item
=>
{
this
.
setFiles
(
item
,
bodyUploadFiles
,
obj
);
if
(
item
.
hashTree
!=
undefined
&&
item
.
hashTree
.
length
>
0
)
{
this
.
recursiveFile
(
item
.
hashTree
,
bodyUploadFiles
,
obj
);
}
});
},
getBodyUploadFiles
(
obj
)
{
let
bodyUploadFiles
=
[];
obj
.
bodyUploadIds
=
[];
this
.
runData
.
forEach
(
request
=>
{
if
(
request
.
body
)
{
request
.
body
.
kvs
.
forEach
(
param
=>
{
if
(
param
.
files
)
{
param
.
files
.
forEach
(
item
=>
{
if
(
item
.
file
)
{
if
(
!
item
.
id
)
{
let
fileId
=
getUUID
().
substring
(
0
,
12
);
item
.
name
=
item
.
file
.
name
;
item
.
id
=
fileId
;
}
obj
.
bodyUploadIds
.
push
(
item
.
id
);
bodyUploadFiles
.
push
(
item
.
file
);
}
});
}
});
request
.
body
.
binary
.
forEach
(
param
=>
{
if
(
param
.
files
)
{
param
.
files
.
forEach
(
item
=>
{
if
(
item
.
file
)
{
if
(
!
item
.
id
)
{
let
fileId
=
getUUID
().
substring
(
0
,
12
);
item
.
name
=
item
.
file
.
name
;
item
.
id
=
fileId
;
}
obj
.
bodyUploadIds
.
push
(
item
.
id
);
bodyUploadFiles
.
push
(
item
.
file
);
}
});
}
});
let
request
=
this
.
runData
;
request
.
hashTree
.
forEach
(
item
=>
{
this
.
setFiles
(
item
,
bodyUploadFiles
,
obj
);
if
(
item
.
hashTree
!=
undefined
&&
item
.
hashTree
.
length
>
0
)
{
this
.
recursiveFile
(
item
.
hashTree
,
bodyUploadFiles
,
obj
);
}
})
;
})
return
bodyUploadFiles
;
},
run
()
{
let
testPlan
=
new
TestPlan
();
this
.
runData
.
forEach
(
item
=>
{
let
threadGroup
=
new
ThreadGroup
();
threadGroup
.
hashTree
=
[];
threadGroup
.
name
=
item
.
name
;
threadGroup
.
hashTree
.
push
(
item
);
testPlan
.
hashTree
.
push
(
threadGroup
);
})
console
.
log
(
"
====
"
,
testPlan
)
let
testPlan
=
createComponent
(
'
TestPlan
'
);
let
threadGroup
=
createComponent
(
'
ThreadGroup
'
);
threadGroup
.
hashTree
=
[];
threadGroup
.
name
=
this
.
runData
.
name
;
threadGroup
.
hashTree
.
push
(
this
.
runData
);
testPlan
.
hashTree
.
push
(
threadGroup
);
let
reqObj
=
{
id
:
this
.
reportId
,
reportId
:
this
.
reportId
,
environmentId
:
this
.
environment
,
testElement
:
testPlan
};
let
bodyFiles
=
this
.
getBodyUploadFiles
(
reqObj
);
let
url
=
"
/api/automation/run
"
;
console
.
log
(
bodyFiles
)
let
url
=
"
/api/automation/run/debug
"
;
this
.
$fileUpload
(
url
,
null
,
bodyFiles
,
reqObj
,
response
=>
{
this
.
runId
=
response
.
data
;
this
.
$emit
(
'
runRefresh
'
,
{});
...
...
frontend/src/business/components/api/automation/scenario/EditApiScenario.vue
浏览文件 @
b8488309
...
...
@@ -261,7 +261,7 @@
@
runRefresh=
"runRefresh"
ref=
"runTest"
/>
<!-- 调试结果 -->
<el-drawer
:visible.sync=
"debugVisible"
:destroy-on-close=
"true"
direction=
"ltr"
:withHeader=
"false"
:title=
"$t('test_track.plan_view.test_result')"
:modal=
"false"
size=
"90%"
>
<ms-api-report-detail
:report-id=
"reportId"
/>
<ms-api-report-detail
:report-id=
"reportId"
:currentProjectId=
"currentProject.id"
/>
</el-drawer>
</div>
</el-card>
...
...
@@ -284,7 +284,7 @@
import
{
getUUID
}
from
"
@/common/js/utils
"
;
import
ApiEnvironmentConfig
from
"
../../definition/components/environment/ApiEnvironmentConfig
"
;
import
MsAddTag
from
"
./AddTag
"
;
import
MsRun
from
"
./Run
"
;
import
MsRun
from
"
./
Debug
Run
"
;
import
MsImportApiScenario
from
"
./ImportApiScenario
"
;
import
MsApiScenarioComponent
from
"
./ApiScenarioComponent
"
;
import
MsApiReportDetail
from
"
../report/ApiReportDetail
"
;
...
...
@@ -333,7 +333,7 @@
expandedNode
:
[],
scenarioDefinition
:
[],
path
:
"
/api/automation/create
"
,
debugData
:
[]
,
debugData
:
{}
,
reportId
:
""
,
}
},
...
...
@@ -539,9 +539,7 @@
this
.
$error
(
this
.
$t
(
'
api_test.environment.select_environment
'
));
return
;
}
let
scenario
=
{
id
:
this
.
currentScenario
.
id
,
name
:
this
.
currentScenario
.
name
,
type
:
"
scenario
"
,
referenced
:
'
Created
'
,
environmentId
:
this
.
currentEnvironmentId
,
hashTree
:
this
.
scenarioDefinition
};
this
.
debugData
=
[];
this
.
debugData
.
push
(
scenario
);
this
.
debugData
=
{
id
:
this
.
currentScenario
.
id
,
name
:
this
.
currentScenario
.
name
,
type
:
"
scenario
"
,
referenced
:
'
Created
'
,
environmentId
:
this
.
currentEnvironmentId
,
hashTree
:
this
.
scenarioDefinition
};
this
.
reportId
=
getUUID
().
substring
(
0
,
8
);
},
getEnvironments
()
{
...
...
@@ -592,11 +590,68 @@
});
return
path
[
0
].
path
;
},
setFiles
(
item
,
bodyUploadFiles
,
obj
)
{
if
(
item
.
body
)
{
item
.
body
.
kvs
.
forEach
(
param
=>
{
if
(
param
.
files
)
{
param
.
files
.
forEach
(
item
=>
{
if
(
item
.
file
)
{
if
(
!
item
.
id
)
{
let
fileId
=
getUUID
().
substring
(
0
,
12
);
item
.
name
=
item
.
file
.
name
;
item
.
id
=
fileId
;
}
obj
.
bodyUploadIds
.
push
(
item
.
id
);
bodyUploadFiles
.
push
(
item
.
file
);
}
});
}
});
item
.
body
.
binary
.
forEach
(
param
=>
{
if
(
param
.
files
)
{
param
.
files
.
forEach
(
item
=>
{
if
(
item
.
file
)
{
if
(
!
item
.
id
)
{
let
fileId
=
getUUID
().
substring
(
0
,
12
);
item
.
name
=
item
.
file
.
name
;
item
.
id
=
fileId
;
}
obj
.
bodyUploadIds
.
push
(
item
.
id
);
bodyUploadFiles
.
push
(
item
.
file
);
}
});
}
});
}
},
recursiveFile
(
arr
,
bodyUploadFiles
,
obj
)
{
arr
.
forEach
(
item
=>
{
this
.
setFiles
(
item
,
bodyUploadFiles
,
obj
);
if
(
item
.
hashTree
!=
undefined
&&
item
.
hashTree
.
length
>
0
)
{
this
.
recursiveFile
(
item
.
hashTree
,
bodyUploadFiles
,
obj
);
}
});
},
getBodyUploadFiles
(
obj
)
{
let
bodyUploadFiles
=
[];
obj
.
bodyUploadIds
=
[];
this
.
scenarioDefinition
.
forEach
(
item
=>
{
this
.
setFiles
(
item
,
bodyUploadFiles
,
obj
);
if
(
item
.
hashTree
!=
undefined
&&
item
.
hashTree
.
length
>
0
)
{
this
.
recursiveFile
(
item
.
hashTree
,
bodyUploadFiles
,
obj
);
}
})
return
bodyUploadFiles
;
},
editScenario
()
{
this
.
$refs
[
'
currentScenario
'
].
validate
((
valid
)
=>
{
if
(
valid
)
{
this
.
setParameter
();
this
.
result
=
this
.
$post
(
this
.
path
,
this
.
currentScenario
,
()
=>
{
let
bodyFiles
=
this
.
getBodyUploadFiles
(
this
.
currentScenario
);
console
.
log
(
bodyFiles
)
console
.
log
(
this
.
currentScenario
.
bodyUploadIds
)
this
.
$fileUpload
(
this
.
path
,
null
,
bodyFiles
,
this
.
currentScenario
,
()
=>
{
this
.
$success
(
this
.
$t
(
'
commons.save_success
'
));
this
.
path
=
"
/api/automation/update
"
;
this
.
currentScenario
.
tagId
=
JSON
.
parse
(
this
.
currentScenario
.
tagId
);
...
...
frontend/src/business/components/api/definition/components/jmeter/components/test-plan/index.js
浏览文件 @
b8488309
...
...
@@ -12,12 +12,7 @@ export const TYPE = "TestPlan";
export
default
class
TestPlan
extends
HashTreeElement
{
constructor
(
options
=
DEFAULT_OPTIONS
)
{
super
(
options
);
this
.
$type
=
TYPE
;
this
.
type
=
TYPE
;
this
.
functionalMode
=
this
.
initBoolProp
(
'
TestPlan.functional_mode
'
,
false
);
this
.
serializeThreadGroups
=
this
.
initBoolProp
(
'
TestPlan.serialize_threadgroups
'
,
false
);
this
.
tearDownOnShutdown
=
this
.
initBoolProp
(
'
TestPlan.tearDown_on_shutdown
'
,
true
);
this
.
userDefineClasspath
=
this
.
initStringProp
(
'
TestPlan.user_define_classpath
'
);
this
.
hashTree
=
[];
this
.
userDefinedVariables
=
[];
...
...
frontend/src/business/components/api/definition/components/jmeter/components/thread-group/index.js
浏览文件 @
b8488309
...
...
@@ -11,21 +11,7 @@ export const TYPE = "ThreadGroup";
export
default
class
ThreadGroup
extends
HashTreeElement
{
constructor
(
options
=
DEFAULT_OPTIONS
)
{
super
(
options
);
this
.
$type
=
TYPE
;
this
.
type
=
TYPE
;
this
.
onSampleError
=
this
.
initStringProp
(
'
ThreadGroup.on_sample_error
'
,
'
continue
'
);
this
.
numThreads
=
this
.
initStringProp
(
'
ThreadGroup.num_threads
'
,
1
);
this
.
rampTime
=
this
.
initStringProp
(
'
ThreadGroup.ramp_time
'
,
1
);
let
loopController
=
this
.
initElementProp
(
'
ThreadGroup.main_controller
'
,
'
LoopController
'
);
this
.
continueForever
=
loopController
.
initBoolProp
(
'
LoopController.continue_forever
'
,
false
);
this
.
loops
=
loopController
.
initStringProp
(
'
LoopController.loops
'
,
1
);
this
.
sameUserOnNextIteration
=
this
.
initBoolProp
(
'
ThreadGroup.same_user_on_next_iteration
'
,
true
);
this
.
delayedStart
=
this
.
initBoolProp
(
'
ThreadGroup.delayedStart
'
);
this
.
scheduler
=
this
.
initBoolProp
(
'
ThreadGroup.scheduler
'
,
false
);
this
.
delay
=
this
.
initStringProp
(
'
ThreadGroup.delay
'
);
this
.
duration
=
this
.
initStringProp
(
'
ThreadGroup.duration
'
);
}
}
...
...
frontend/src/business/components/api/head/ApiHeaderMenus.vue
浏览文件 @
b8488309
...
...
@@ -15,6 +15,10 @@
{{
$t
(
"
i18n.automation
"
)
}}
</el-menu-item>
<el-menu-item
:index=
"'/api/automation/report'"
>
{{
$t
(
"
i18n.report
"
)
}}
</el-menu-item>
<el-submenu
:class=
"
{'deactivation':!isProjectActivation}" v-permission="['test_manager','test_user','test_viewer']" index="3">
<template
v-slot:title
>
{{
$t
(
'
commons.project
'
)
}}
</
template
>
<ms-recent-list
ref=
"projectRecent"
:options=
"projectRecent"
/>
...
...
frontend/src/business/components/api/router.js
浏览文件 @
b8488309
...
...
@@ -48,6 +48,11 @@ export default {
path
:
"
automation
"
,
name
:
"
ApiAutomation
"
,
component
:
()
=>
import
(
'
@/business/components/api/automation/ApiAutomation
'
),
},
{
path
:
"
automation/report
"
,
name
:
"
ApiReportList
"
,
component
:
()
=>
import
(
'
@/business/components/api/automation/report/ApiReportList
'
),
}
]
}
frontend/src/i18n/en-US.js
浏览文件 @
b8488309
...
...
@@ -163,7 +163,7 @@ export default {
current_user
:
"
Current user
"
}
},
monitor
:
"
monitor
"
monitor
:
"
monitor
"
},
license
:
{
title
:
'
Authorization management
'
,
...
...
@@ -543,6 +543,7 @@ export default {
customize_script
:
"
Custom script
"
,
customize_req
:
"
Custom request
"
,
reference_info
:
"
Please select interface or use case
"
,
report_name_info
:
'
Please enter the registration name
'
,
},
environment
:
{
name
:
"
Environment Name
"
,
...
...
@@ -779,14 +780,14 @@ export default {
not_exist
:
"
Test report does not exist
"
,
},
api_monitor
:
{
to
:
"
to
"
,
start_time
:
"
Start Time
"
,
end_time
:
"
End Time
"
,
today
:
"
Today
"
,
this_week
:
"
This Week
"
,
this_mouth
:
"
This Mouth
"
,
please_search
:
"
Please Search
"
,
date
:
"
Date
"
to
:
"
to
"
,
start_time
:
"
Start Time
"
,
end_time
:
"
End Time
"
,
today
:
"
Today
"
,
this_week
:
"
This Week
"
,
this_mouth
:
"
This Mouth
"
,
please_search
:
"
Please Search
"
,
date
:
"
Date
"
},
test_track
:
{
test_track
:
"
Track
"
,
...
...
@@ -1096,6 +1097,7 @@ export default {
home
:
'
Home
'
,
definition
:
'
Api Definition
'
,
automation
:
'
Api Automation
'
,
report
:
'
Test report
'
,
},
ldap
:
{
url
:
'
LDAP URL
'
,
...
...
frontend/src/i18n/zh-CN.js
浏览文件 @
b8488309
...
...
@@ -570,7 +570,8 @@ export default {
follow_people
:
"
关注人
"
,
select_table
:
"
选择可见数据
"
,
select_all
:
"
选择全部数据
"
}
},
report_name_info
:
'
请输入报名名称
'
,
},
environment
:
{
name
:
"
环境名称
"
,
...
...
@@ -809,14 +810,14 @@ export default {
not_exist
:
"
测试报告不存在
"
,
},
api_monitor
:
{
to
:
"
至
"
,
start_time
:
"
开始日期
"
,
end_time
:
"
结束日期
"
,
today
:
"
今日
"
,
this_week
:
"
本周
"
,
this_mouth
:
"
本月
"
,
please_search
:
"
请搜索
"
,
date
:
"
日期
"
to
:
"
至
"
,
start_time
:
"
开始日期
"
,
end_time
:
"
结束日期
"
,
today
:
"
今日
"
,
this_week
:
"
本周
"
,
this_mouth
:
"
本月
"
,
please_search
:
"
请搜索
"
,
date
:
"
日期
"
},
test_track
:
{
test_track
:
"
测试跟踪
"
,
...
...
@@ -1125,6 +1126,7 @@ export default {
home
:
'
首页
'
,
definition
:
'
接口定义
'
,
automation
:
'
接口自动化
'
,
report
:
'
测试报告
'
,
},
ldap
:
{
url
:
'
LDAP地址
'
,
...
...
frontend/src/i18n/zh-TW.js
浏览文件 @
b8488309
...
...
@@ -543,8 +543,8 @@ export default {
scenario_import
:
"
場景導入
"
,
customize_script
:
"
自定義腳本
"
,
customize_req
:
"
自定義請求
"
,
reference_info
:
"
請選擇接口或用例
"
reference_info
:
"
請選擇接口或用例
"
,
report_name_info
:
'
请输入报名名称
'
,
},
environment
:
{
name
:
"
環境名稱
"
,
...
...
@@ -1098,6 +1098,7 @@ export default {
home
:
'
首頁
'
,
definition
:
'
接口定義
'
,
automation
:
'
接口自動化
'
,
report
:
'
測試報告
'
,
},
ldap
:
{
url
:
'
LDAP地址
'
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录