Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
MeterSphere
metersphere
提交
41f928aa
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,发现更多精彩内容 >>
提交
41f928aa
编写于
1月 13, 2021
作者:
F
fit2-zhao
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat(接口定义): 接口用例增加执行结果展示
上级
d24d7e51
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
242 addition
and
206 deletion
+242
-206
backend/src/main/java/io/metersphere/api/dto/definition/ApiTestCaseResult.java
.../io/metersphere/api/dto/definition/ApiTestCaseResult.java
+1
-0
frontend/src/business/components/api/definition/components/case/ApiCaseItem.vue
...components/api/definition/components/case/ApiCaseItem.vue
+241
-206
未找到文件。
backend/src/main/java/io/metersphere/api/dto/definition/ApiTestCaseResult.java
浏览文件 @
41f928aa
...
...
@@ -13,4 +13,5 @@ public class ApiTestCaseResult extends ApiTestCaseWithBLOBs {
private
String
execResult
;
private
Long
execTime
;
private
boolean
active
=
false
;
private
boolean
responseActive
=
false
;
}
frontend/src/business/components/api/definition/components/case/ApiCaseItem.vue
浏览文件 @
41f928aa
...
...
@@ -71,6 +71,17 @@
<ms-tcp-basis-parameters
:request=
"apiCase.request"
v-if=
"api.protocol==='TCP'"
/>
<ms-sql-basis-parameters
:request=
"apiCase.request"
v-if=
"api.protocol==='SQL'"
/>
<ms-dubbo-basis-parameters
:request=
"apiCase.request"
v-if=
"api.protocol==='DUBBO'"
/>
<!-- HTTP 请求返回数据 -->
<p
class=
"tip"
>
{{
$t
(
'
api_test.definition.request.res_param
'
)
}}
<i
class=
"icon el-icon-arrow-right"
:class=
"
{'is-responseActive': apiCase.responseActive}" @click="responseActive(apiCase)"/>
</p>
<el-collapse-transition>
<div
v-if=
"apiCase.responseActive"
>
<ms-request-result-tail
:response=
"responseData"
/>
</div>
</el-collapse-transition>
<!-- 保存操作 -->
<el-button
type=
"primary"
size=
"small"
style=
"margin: 20px; float: right"
@
click=
"saveTestCase(apiCase)"
v-tester
>
{{
$t
(
'
commons.save
'
)
}}
...
...
@@ -81,189 +92,195 @@
</
template
>
<
script
>
import
{
getCurrentProjectID
,
getUUID
}
from
"
../../../../../../common/js/utils
"
;
import
{
PRIORITY
,
RESULT_MAP
}
from
"
../../model/JsonData
"
;
import
MsTag
from
"
../../../../common/components/MsTag
"
;
import
MsTipButton
from
"
../../../../common/components/MsTipButton
"
;
import
MsApiRequestForm
from
"
../request/http/ApiRequestForm
"
;
import
ApiEnvironmentConfig
from
"
../environment/ApiEnvironmentConfig
"
;
import
MsApiAssertions
from
"
../assertion/ApiAssertions
"
;
import
MsSqlBasisParameters
from
"
../request/database/BasisParameters
"
;
import
MsTcpBasisParameters
from
"
../request/tcp/TcpBasisParameters
"
;
import
MsDubboBasisParameters
from
"
../request/dubbo/BasisParameters
"
;
import
MsApiExtendBtns
from
"
../reference/ApiExtendBtns
"
;
import
MsInputTag
from
"
@/business/components/api/automation/scenario/MsInputTag
"
;
import
{
getCurrentProjectID
,
getUUID
}
from
"
../../../../../../common/js/utils
"
;
import
{
PRIORITY
,
RESULT_MAP
}
from
"
../../model/JsonData
"
;
import
MsTag
from
"
../../../../common/components/MsTag
"
;
import
MsTipButton
from
"
../../../../common/components/MsTipButton
"
;
import
MsApiRequestForm
from
"
../request/http/ApiRequestForm
"
;
import
ApiEnvironmentConfig
from
"
../environment/ApiEnvironmentConfig
"
;
import
MsApiAssertions
from
"
../assertion/ApiAssertions
"
;
import
MsSqlBasisParameters
from
"
../request/database/BasisParameters
"
;
import
MsTcpBasisParameters
from
"
../request/tcp/TcpBasisParameters
"
;
import
MsDubboBasisParameters
from
"
../request/dubbo/BasisParameters
"
;
import
MsApiExtendBtns
from
"
../reference/ApiExtendBtns
"
;
import
MsInputTag
from
"
@/business/components/api/automation/scenario/MsInputTag
"
;
import
MsRequestResultTail
from
"
../response/RequestResultTail
"
;
export
default
{
name
:
"
ApiCaseItem
"
,
components
:
{
MsInputTag
,
MsTag
,
MsTipButton
,
MsApiRequestForm
,
ApiEnvironmentConfig
,
MsApiAssertions
,
MsSqlBasisParameters
,
MsTcpBasisParameters
,
MsDubboBasisParameters
,
MsApiExtendBtns
},
data
()
{
return
{
result
:
{},
grades
:
[],
isReadOnly
:
false
,
selectedEvent
:
Object
,
priorities
:
PRIORITY
,
runData
:
[],
reportId
:
""
,
checkedCases
:
new
Set
(),
visible
:
false
,
condition
:
{},
isShowInput
:
false
,
}
},
props
:
{
apiCase
:
{
type
:
Object
,
default
()
{
return
{}
}
},
environment
:
{},
index
:
{
type
:
Number
,
default
()
{
return
0
}
export
default
{
name
:
"
ApiCaseItem
"
,
components
:
{
MsInputTag
,
MsTag
,
MsTipButton
,
MsApiRequestForm
,
ApiEnvironmentConfig
,
MsApiAssertions
,
MsSqlBasisParameters
,
MsTcpBasisParameters
,
MsDubboBasisParameters
,
MsApiExtendBtns
,
MsRequestResultTail
},
api
:
{
type
:
Object
,
default
()
{
return
{}
data
()
{
return
{
result
:
{},
grades
:
[],
isReadOnly
:
false
,
selectedEvent
:
Object
,
priorities
:
PRIORITY
,
runData
:
[],
reportId
:
""
,
checkedCases
:
new
Set
(),
visible
:
false
,
condition
:
{},
responseData
:
{
type
:
'
HTTP
'
,
responseResult
:
{},
subRequestResults
:
[]},
isShowInput
:
false
,
}
},
isCaseEdit
:
Boolean
,
},
watch
:
{},
methods
:
{
deleteCase
(
index
,
row
)
{
this
.
$alert
(
this
.
$t
(
'
api_test.definition.request.delete_confirm
'
)
+
'
'
+
row
.
name
+
"
?
"
,
''
,
{
confirmButtonText
:
this
.
$t
(
'
commons.confirm
'
),
callback
:
(
action
)
=>
{
if
(
action
===
'
confirm
'
)
{
this
.
$get
(
'
/api/testcase/delete/
'
+
row
.
id
,
()
=>
{
this
.
$success
(
this
.
$t
(
'
commons.delete_success
'
));
this
.
$emit
(
'
refresh
'
);
});
}
props
:
{
apiCase
:
{
type
:
Object
,
default
()
{
return
{}
},
},
environment
:
{},
index
:
{
type
:
Number
,
default
()
{
return
0
}
});
},
singleRun
(
data
)
{
this
.
$emit
(
'
singleRun
'
,
data
);
},
copyCase
(
data
)
{
let
obj
=
{
name
:
"
copy_
"
+
data
.
name
,
priority
:
data
.
priority
,
active
:
true
,
request
:
data
.
request
};
this
.
$emit
(
'
copyCase
'
,
obj
);
},
api
:
{
type
:
Object
,
default
()
{
return
{}
}
},
isCaseEdit
:
Boolean
,
},
watch
:
{},
methods
:
{
deleteCase
(
index
,
row
)
{
this
.
$alert
(
this
.
$t
(
'
api_test.definition.request.delete_confirm
'
)
+
'
'
+
row
.
name
+
"
?
"
,
''
,
{
confirmButtonText
:
this
.
$t
(
'
commons.confirm
'
),
callback
:
(
action
)
=>
{
if
(
action
===
'
confirm
'
)
{
this
.
$get
(
'
/api/testcase/delete/
'
+
row
.
id
,
()
=>
{
this
.
$success
(
this
.
$t
(
'
commons.delete_success
'
));
this
.
$emit
(
'
refresh
'
);
});
}
}
});
selectTestCase
(
item
,
$event
)
{
if
(
!
item
.
id
||
!
this
.
loaded
)
{
return
;
}
if
(
$event
.
currentTarget
.
className
.
indexOf
(
'
is-selected
'
)
>
0
)
{
$event
.
currentTarget
.
className
=
"
el-card is-always-shadow
"
;
this
.
$emit
(
'
selectTestCase
'
,
null
);
}
else
{
if
(
this
.
selectedEvent
.
currentTarget
!=
undefined
)
{
this
.
selectedEvent
.
currentTarget
.
className
=
"
el-card is-always-shadow
"
;
},
getExecResult
()
{
// 执行结果信息
if
(
this
.
apiCase
)
{
let
url
=
"
/api/definition/report/getReport/
"
+
this
.
apiCase
.
id
;
this
.
$get
(
url
,
response
=>
{
if
(
response
.
data
)
{
let
data
=
JSON
.
parse
(
response
.
data
.
content
);
this
.
responseData
=
data
;
}
});
}
this
.
selectedEvent
.
currentTarget
=
$event
.
currentTarget
;
$event
.
currentTarget
.
className
=
"
el-card is-always-shadow is-selected
"
;
this
.
$emit
(
'
selectTestCase
'
,
item
);
}
},
singleRun
(
data
)
{
this
.
$emit
(
'
singleRun
'
,
data
);
},
copyCase
(
data
)
{
let
obj
=
{
name
:
"
copy_
"
+
data
.
name
,
priority
:
data
.
priority
,
active
:
true
,
request
:
data
.
request
};
this
.
$emit
(
'
copyCase
'
,
obj
);
},
},
changePriority
(
row
)
{
if
(
row
.
id
)
{
this
.
saveTestCase
(
row
);
}
},
saveTestCase
(
row
)
{
let
tmp
=
JSON
.
parse
(
JSON
.
stringify
(
row
));
this
.
isShowInput
=
false
;
if
(
this
.
validate
(
tmp
))
{
return
;
}
let
bodyFiles
=
this
.
getBodyUploadFiles
(
tmp
);
tmp
.
projectId
=
getCurrentProjectID
();
tmp
.
active
=
true
;
tmp
.
request
.
path
=
this
.
api
.
path
;
tmp
.
request
.
method
=
this
.
api
.
method
;
tmp
.
apiDefinitionId
=
tmp
.
apiDefinitionId
||
this
.
api
.
id
;
let
url
=
"
/api/testcase/create
"
;
if
(
tmp
.
id
)
{
url
=
"
/api/testcase/update
"
;
}
if
(
tmp
.
tags
instanceof
Array
)
{
tmp
.
tags
=
JSON
.
stringify
(
tmp
.
tags
);
}
this
.
$fileUpload
(
url
,
null
,
bodyFiles
,
tmp
,
(
response
)
=>
{
let
data
=
response
.
data
;
row
.
id
=
data
.
id
;
row
.
createTime
=
data
.
createTime
;
row
.
updateTime
=
data
.
updateTime
;
this
.
$success
(
this
.
$t
(
'
commons.save_success
'
));
});
},
showInput
(
row
)
{
// row.type = "create";
this
.
isShowInput
=
true
;
row
.
active
=
true
;
this
.
active
(
row
);
},
active
(
item
)
{
item
.
active
=
!
item
.
active
;
},
getResult
(
data
)
{
if
(
RESULT_MAP
.
get
(
data
))
{
return
RESULT_MAP
.
get
(
data
);
}
else
{
return
RESULT_MAP
.
get
(
"
default
"
);
}
},
validate
(
row
)
{
if
(
!
row
.
name
)
{
this
.
$warning
(
this
.
$t
(
'
api_test.input_name
'
));
return
true
;
}
},
showExecResult
(
data
)
{
this
.
$emit
(
'
showExecResult
'
,
data
);
},
getBodyUploadFiles
(
row
)
{
let
bodyUploadFiles
=
[];
row
.
bodyUploadIds
=
[];
let
request
=
row
.
request
;
if
(
request
.
body
&&
request
.
body
.
kvs
)
{
request
.
body
.
kvs
.
forEach
(
param
=>
{
if
(
param
.
files
)
{
param
.
files
.
forEach
(
item
=>
{
if
(
item
.
file
)
{
let
fileId
=
getUUID
().
substring
(
0
,
8
);
item
.
name
=
item
.
file
.
name
;
item
.
id
=
fileId
;
row
.
bodyUploadIds
.
push
(
fileId
);
bodyUploadFiles
.
push
(
item
.
file
);
}
});
selectTestCase
(
item
,
$event
)
{
if
(
!
item
.
id
||
!
this
.
loaded
)
{
return
;
}
if
(
$event
.
currentTarget
.
className
.
indexOf
(
'
is-selected
'
)
>
0
)
{
$event
.
currentTarget
.
className
=
"
el-card is-always-shadow
"
;
this
.
$emit
(
'
selectTestCase
'
,
null
);
}
else
{
if
(
this
.
selectedEvent
.
currentTarget
!=
undefined
)
{
this
.
selectedEvent
.
currentTarget
.
className
=
"
el-card is-always-shadow
"
;
}
this
.
selectedEvent
.
currentTarget
=
$event
.
currentTarget
;
$event
.
currentTarget
.
className
=
"
el-card is-always-shadow is-selected
"
;
this
.
$emit
(
'
selectTestCase
'
,
item
);
}
},
changePriority
(
row
)
{
if
(
row
.
id
)
{
this
.
saveTestCase
(
row
);
}
},
saveTestCase
(
row
)
{
let
tmp
=
JSON
.
parse
(
JSON
.
stringify
(
row
));
this
.
isShowInput
=
false
;
if
(
this
.
validate
(
tmp
))
{
return
;
}
let
bodyFiles
=
this
.
getBodyUploadFiles
(
tmp
);
tmp
.
projectId
=
getCurrentProjectID
();
tmp
.
active
=
true
;
tmp
.
request
.
path
=
this
.
api
.
path
;
tmp
.
request
.
method
=
this
.
api
.
method
;
tmp
.
apiDefinitionId
=
tmp
.
apiDefinitionId
||
this
.
api
.
id
;
let
url
=
"
/api/testcase/create
"
;
if
(
tmp
.
id
)
{
url
=
"
/api/testcase/update
"
;
}
if
(
tmp
.
tags
instanceof
Array
)
{
tmp
.
tags
=
JSON
.
stringify
(
tmp
.
tags
);
}
this
.
$fileUpload
(
url
,
null
,
bodyFiles
,
tmp
,
(
response
)
=>
{
let
data
=
response
.
data
;
row
.
id
=
data
.
id
;
row
.
createTime
=
data
.
createTime
;
row
.
updateTime
=
data
.
updateTime
;
this
.
$success
(
this
.
$t
(
'
commons.save_success
'
));
});
if
(
request
.
body
.
binary
)
{
request
.
body
.
binary
.
forEach
(
param
=>
{
},
showInput
(
row
)
{
// row.type = "create";
this
.
isShowInput
=
true
;
row
.
active
=
true
;
this
.
active
(
row
);
},
active
(
item
)
{
item
.
active
=
!
item
.
active
;
},
responseActive
(
item
)
{
item
.
responseActive
=
!
item
.
responseActive
;
if
(
item
.
responseActive
)
{
this
.
getExecResult
();
}
},
getResult
(
data
)
{
if
(
RESULT_MAP
.
get
(
data
))
{
return
RESULT_MAP
.
get
(
data
);
}
else
{
return
RESULT_MAP
.
get
(
"
default
"
);
}
},
validate
(
row
)
{
if
(
!
row
.
name
)
{
this
.
$warning
(
this
.
$t
(
'
api_test.input_name
'
));
return
true
;
}
},
showExecResult
(
data
)
{
this
.
$emit
(
'
showExecResult
'
,
data
);
},
getBodyUploadFiles
(
row
)
{
let
bodyUploadFiles
=
[];
row
.
bodyUploadIds
=
[];
let
request
=
row
.
request
;
if
(
request
.
body
&&
request
.
body
.
kvs
)
{
request
.
body
.
kvs
.
forEach
(
param
=>
{
if
(
param
.
files
)
{
param
.
files
.
forEach
(
item
=>
{
if
(
item
.
file
)
{
...
...
@@ -276,49 +293,67 @@ export default {
});
}
});
if
(
request
.
body
.
binary
)
{
request
.
body
.
binary
.
forEach
(
param
=>
{
if
(
param
.
files
)
{
param
.
files
.
forEach
(
item
=>
{
if
(
item
.
file
)
{
let
fileId
=
getUUID
().
substring
(
0
,
8
);
item
.
name
=
item
.
file
.
name
;
item
.
id
=
fileId
;
row
.
bodyUploadIds
.
push
(
fileId
);
bodyUploadFiles
.
push
(
item
.
file
);
}
});
}
});
}
}
}
return
bodyUploadFiles
;
}
,
return
bodyUploadFiles
;
},
}
}
}
</
script
>
<
style
scoped
>
.ms-api-select
{
margin-left
:
20px
;
width
:
80px
;
}
.ms-api-select
{
margin-left
:
20px
;
width
:
80px
;
}
.ms-api-header-select
{
margin-left
:
20px
;
min-width
:
100px
;
}
.ms-api-header-select
{
margin-left
:
20px
;
min-width
:
100px
;
}
.ms-api-label
{
color
:
#CCCCCC
;
}
.ms-api-label
{
color
:
#CCCCCC
;
}
.ms-api-col
{
background-color
:
#7C3985
;
border-color
:
#7C3985
;
margin-right
:
10px
;
color
:
white
;
}
.ms-api-col
{
background-color
:
#7C3985
;
border-color
:
#7C3985
;
margin-right
:
10px
;
color
:
white
;
}
.icon.is-active
{
transform
:
rotate
(
90deg
);
}
.icon.is-active
{
transform
:
rotate
(
90deg
);
}
.tip
{
padding
:
3px
5px
;
font-size
:
16px
;
border-radius
:
4px
;
border-left
:
4px
solid
#783887
;
margin
:
20px
0
;
}
.icon.is-responseActive
{
transform
:
rotate
(
90deg
);
}
.is-selected
{
background
:
#EFF7FF
;
}
.tip
{
padding
:
3px
5px
;
font-size
:
16px
;
border-radius
:
4px
;
border-left
:
4px
solid
#783887
;
margin
:
20px
0
;
}
.is-selected
{
background
:
#EFF7FF
;
}
</
style
>
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录