Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
x649585723
incubator-echarts
提交
2973d0c9
I
incubator-echarts
项目概览
x649585723
/
incubator-echarts
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
I
incubator-echarts
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
2973d0c9
编写于
9月 07, 2019
作者:
P
pissang
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
test: improve ui of recording screenshots.
上级
e3d8d628
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
129 addition
and
41 deletion
+129
-41
test/runTest/Timeline.js
test/runTest/Timeline.js
+20
-4
test/runTest/cli.js
test/runTest/cli.js
+22
-22
test/runTest/client/client.css
test/runTest/client/client.css
+5
-1
test/runTest/client/index.html
test/runTest/client/index.html
+8
-5
test/runTest/recorder/index.html
test/runTest/recorder/index.html
+11
-5
test/runTest/recorder/recorder.css
test/runTest/recorder/recorder.css
+24
-1
test/runTest/recorder/recorder.js
test/runTest/recorder/recorder.js
+30
-2
test/runTest/util.js
test/runTest/util.js
+9
-1
未找到文件。
test/runTest/Timeline.js
浏览文件 @
2973d0c9
const
{
waitTime
}
=
require
(
'
./util
'
);
module
.
exports
=
class
Timeline
{
constructor
(
page
)
{
...
...
@@ -17,7 +19,7 @@ module.exports = class Timeline {
}
async
runAction
(
action
,
playbackSpeed
)
{
async
runAction
(
action
,
takeScreenshot
,
playbackSpeed
)
{
this
.
stop
();
playbackSpeed
=
playbackSpeed
||
1
;
...
...
@@ -45,7 +47,7 @@ module.exports = class Timeline {
self
.
_elapsedTime
+=
dTime
*
playbackSpeed
;
self
.
_current
=
current
;
await
self
.
_update
();
await
self
.
_update
(
takeScreenshot
);
if
(
self
.
_currentOpIndex
>=
self
.
_ops
.
length
)
{
// Finished
resolve
();
...
...
@@ -66,7 +68,7 @@ module.exports = class Timeline {
}
}
async
_update
()
{
async
_update
(
takeScreenshot
)
{
let
op
=
this
.
_ops
[
this
.
_currentOpIndex
];
if
(
op
.
time
>
this
.
_elapsedTime
)
{
...
...
@@ -85,11 +87,25 @@ module.exports = class Timeline {
await
page
.
mouse
.
up
();
break
;
case
'
mousemove
'
:
page
.
mouse
.
move
(
op
.
x
,
op
.
y
);
await
page
.
mouse
.
move
(
op
.
x
,
op
.
y
);
break
;
case
'
screenshot
'
:
await
takeScreenshot
();
break
;
}
this
.
_currentOpIndex
++
;
// If next op is an auto screenshot
let
nextOp
=
this
.
_ops
[
this
.
_currentOpIndex
];
console
.
log
(
nextOp
.
type
);
if
(
nextOp
&&
nextOp
.
type
===
'
screenshot-auto
'
)
{
// TODO Configuration time
await
waitTime
(
300
);
console
.
log
(
Date
.
now
());
await
takeScreenshot
();
console
.
log
(
Date
.
now
());
this
.
_currentOpIndex
++
;
}
}
};
\ No newline at end of file
test/runTest/cli.js
浏览文件 @
2973d0c9
...
...
@@ -5,7 +5,7 @@ const fs = require('fs');
const
path
=
require
(
'
path
'
);
const
program
=
require
(
'
commander
'
);
const
compareScreenshot
=
require
(
'
./compareScreenshot
'
);
const
{
testNameFromFile
,
fileNameFromTest
,
getVersionDir
,
buildRuntimeCode
}
=
require
(
'
./util
'
);
const
{
testNameFromFile
,
fileNameFromTest
,
getVersionDir
,
buildRuntimeCode
,
waitTime
}
=
require
(
'
./util
'
);
const
{
origin
}
=
require
(
'
./config
'
);
const
Timeline
=
require
(
'
./Timeline
'
);
...
...
@@ -48,19 +48,14 @@ function replaceEChartsVersion(interceptedRequest, version) {
}
}
function
waitTime
(
time
)
{
return
new
Promise
(
resolve
=>
{
setTimeout
(()
=>
{
resolve
();
},
time
);
});
}
async
function
takeScreenshot
(
page
,
fullPage
,
fileUrl
,
desc
,
version
)
{
async
function
takeScreenshot
(
page
,
fullPage
,
fileUrl
,
desc
,
version
,
minor
)
{
let
screenshotName
=
testNameFromFile
(
fileUrl
);
if
(
desc
)
{
screenshotName
+=
'
-
'
+
slugify
(
desc
,
{
replacement
:
'
-
'
,
lower
:
true
});
}
if
(
minor
)
{
screenshotName
+=
'
-
'
+
minor
;
}
let
screenshotPrefix
=
version
?
'
expected
'
:
'
actual
'
;
fse
.
ensureDirSync
(
path
.
join
(
__dirname
,
getScreenshotDir
()));
let
screenshotPath
=
path
.
join
(
__dirname
,
`
${
getScreenshotDir
()}
/
${
screenshotName
}
-
${
screenshotPrefix
}
.png`
);
...
...
@@ -91,14 +86,23 @@ async function runActions(page, testOpt, version, screenshots) {
window
.
scrollTo
(
x
,
y
);
},
action
.
scrollX
,
action
.
scrollY
);
await
timeline
.
runAction
(
action
,
playbackSpeed
);
// Wait for animation finished
// TODO Configuration.
await
waitTime
(
action
.
wait
==
null
?
200
:
action
.
wait
);
let
count
=
0
;
async
function
_innerTakeScreenshot
()
{
const
desc
=
action
.
desc
||
action
.
name
;
const
{
screenshotName
,
screenshotPath
}
=
await
takeScreenshot
(
page
,
false
,
testOpt
.
fileUrl
,
desc
,
version
,
count
++
);
screenshots
.
push
({
screenshotName
,
desc
,
screenshotPath
});
}
await
timeline
.
runAction
(
action
,
_innerTakeScreenshot
,
playbackSpeed
);
const
desc
=
action
.
desc
||
action
.
name
;
const
{
screenshotName
,
screenshotPath
}
=
await
takeScreenshot
(
page
,
false
,
testOpt
.
fileUrl
,
desc
,
version
);
screenshots
.
push
({
screenshotName
,
desc
,
screenshotPath
});
if
(
count
===
0
)
{
// TODO Configuration time
await
waitTime
(
300
);
await
_innerTakeScreenshot
();
}
// const desc = action.desc || action.name;
// const {screenshotName, screenshotPath} = await takeScreenshot(page, false, testOpt.fileUrl, desc, version);
// screenshots.push({screenshotName, desc, screenshotPath});
}
timeline
.
stop
();
}
...
...
@@ -132,18 +136,14 @@ async function runTestPage(browser, testOpt, version, runtimeCode) {
console
.
error
(
e
);
}
await
waitTime
(
500
);
// Wait for animation or something else.
// Final shot.
let
desc
=
'
Full Shot
'
;
const
{
screenshotName
,
screenshotPath
}
=
await
takeScreenshot
(
page
,
true
,
fileUrl
,
desc
,
version
);
screenshots
.
push
({
screenshotName
,
desc
,
screenshotPath
});
await
runActions
(
page
,
testOpt
,
version
,
screenshots
);
if
(
!
screenshots
.
length
)
{
waitTime
(
500
);
// Wait for animation or something else.
}
await
page
.
close
();
return
{
...
...
test/runTest/client/client.css
浏览文件 @
2973d0c9
...
...
@@ -108,10 +108,14 @@
}
.test-screenshots
{
margin-top
:
8
0px
;
margin-top
:
2
0px
;
padding
:
0
20px
;
}
.test-screenshots
h4
{
margin-top
:
60px
;
}
.test-screenshots
img
{
/* height: 200px; */
width
:
100%
;
...
...
test/runTest/client/index.html
浏览文件 @
2973d0c9
...
...
@@ -69,11 +69,14 @@
<a
target=
"_blank"
:href=
"currentTestRecordUrl"
><i
class=
"el-icon-video-camera"
></i>
Record Interaction
</a>
</div>
<div
class=
"test-screenshots"
v-for=
"result in currentTest.results"
>
<h4>
{{result.desc || result.name}}
</h4>
<div
class=
"test-screenshots"
v-for=
"(result, idx) in currentTest.results"
>
<!-- Not display title if it's same with previous -->
<h4
v-if=
"result.desc !== (currentTest.results[idx - 1] && currentTest.results[idx - 1].desc)"
>
{{result.desc || result.name}}
</h4>
<el-row
:gutter=
"40"
class=
"screenshots"
>
<el-col
:span=
"8"
>
<el-card>
<el-card
shadow=
"hover"
>
<div
slot=
"header"
class=
"clearfix"
>
<span>
Expected
</span>
</div>
...
...
@@ -82,7 +85,7 @@
</el-col>
<el-col
:span=
"8"
>
<el-card>
<el-card
shadow=
"hover"
>
<div
slot=
"header"
class=
"clearfix"
>
<span>
Actual
</span>
</div>
...
...
@@ -91,7 +94,7 @@
</el-col>
<el-col
:span=
"8"
>
<el-card>
<el-card
shadow=
"hover"
>
<div
slot=
"header"
class=
"clearfix"
>
<span>
Diff({{result.diffRatio.toFixed(4)}})
</span>
</div>
...
...
test/runTest/recorder/index.html
浏览文件 @
2973d0c9
...
...
@@ -8,7 +8,7 @@
<body>
<div
id=
"app"
style=
"display: none"
>
<iframe
:src=
"url"
></iframe>
<div
id=
"recording-status"
v-if=
"currentAction"
>
<div
id=
"recording-status"
>
<el-button
:icon=
"recordingAction ? 'el-icon-video-camera' : 'el-icon-video-camera'"
class=
"recording-button"
circle
:type=
"recordingAction ? 'danger' : 'info'"
...
...
@@ -20,25 +20,31 @@
<el-card
class=
"box-card"
>
<div
slot=
"header"
class=
"clearfix"
>
<span>
Actions
</span>
<div
style=
"float:right
"
>
<div
class=
"toolbar
"
>
<el-button
type=
"primary"
size=
"mini"
icon=
"el-icon-caret-right"
circle
@
click=
"run"
></el-button>
<el-button
type=
"primary"
size=
"mini"
icon=
"el-icon-circle-plus"
@
click=
"newAction"
>
New
</el-button>
<el-popover
title=
"Configuration"
class=
"configuration"
>
<div
class=
"config-item"
>
<el-checkbox
v-model=
"config.screenshotAfterMouseUp"
>
Auto screenshot after mouse up
</el-checkbox>
</div>
<i
slot=
"reference"
class=
"el-icon-setting"
></i>
</el-popover>
</div>
</div>
<div
v-for=
"action in actions"
:class=
"{'action-item': true, 'active': action.name === currentAction.name}"
@
click.self=
"select(action.name)"
>
{{action.name}}
<div
style=
"float:right"
class=
"operations"
>
<el-popover>
<div
style=
"text-align: center"
>
{ scrollX: {{action.scrollX}}, scrollY: {{action.scrollY}} }
</div>
<div
v-for=
"op in action.ops"
style=
"text-align: center"
>
{{op}}
</div>
<!-- <el-button slot="reference" size="mini">OP ({{action.ops.length}})</el-button> -->
<div
slot=
"reference"
>
<span>
Data ({{action.ops.length}})
</span>
<i
slot=
"reference"
class=
"el-icon-caret-bottom"
></i>
</div>
</el-popover>
<i
slot=
"reference"
class=
"el-icon-delete"
@
click=
"doDelete(action.name)"
></i>
<i
class=
"el-icon-delete"
@
click=
"doDelete(action.name)"
></i>
<i
class=
"el-icon-refresh-left"
@
click=
"clearOps(action.name)"
></i>
</div>
</div>
</el-card>
...
...
test/runTest/recorder/recorder.css
浏览文件 @
2973d0c9
...
...
@@ -104,6 +104,25 @@ iframe {
width
:
300px
;
}
#actions
.toolbar
{
float
:
right
;
margin-top
:
-5px
;
}
#actions
.toolbar
>*
{
display
:
inline-block
;
vertical-align
:
middle
;
}
#actions
.toolbar
i
.el-icon-setting
{
font-size
:
20px
;
cursor
:
pointer
;
margin-left
:
10px
;
}
#actions
.toolbar
.config-item
{
margin
:
5px
0
;
}
#actions
.action-item
{
line-height
:
40px
;
padding
:
0
20px
;
...
...
@@ -111,7 +130,7 @@ iframe {
cursor
:
pointer
;
}
\
#actions
.action-item
:hover
{
background
:
#eee
;
}
...
...
@@ -129,6 +148,10 @@ iframe {
display
:
inline-block
;
vertical-align
:
middle
;
}
#actions
.action-item
.operations
i
{
margin-left
:
5px
;
font-size
:
18px
;
}
#actions
.action-item
.operations
.el-icon-delete
{
color
:
#F56C6C
;
...
...
test/runTest/recorder/recorder.js
浏览文件 @
2973d0c9
...
...
@@ -10,6 +10,9 @@ const app = new Vue({
currentAction
:
null
,
recordingAction
:
null
,
config
:
{
screenshotAfterMouseUp
:
true
},
drawerVisible
:
true
},
...
...
@@ -50,6 +53,20 @@ const app = new Vue({
}).
catch
(
e
=>
{});
},
clearOps
(
actionName
)
{
app
.
$confirm
(
'
Aure you sure?
'
,
'
Clear this action
'
,
{
confirmButtonText
:
'
Yes
'
,
cancelButtonText
:
'
No
'
,
type
:
'
warning
'
}).
then
(()
=>
{
this
.
deletePopoverVisible
=
false
;
let
action
=
this
.
actions
.
find
(
action
=>
action
.
name
===
actionName
);
if
(
action
)
{
action
.
ops
=
[];
}
}).
catch
(
e
=>
{});
},
run
()
{
socket
.
emit
(
'
runSingle
'
,
{
testName
:
app
.
currentTestName
...
...
@@ -71,10 +88,14 @@ function saveData() {
function
keyboardRecordingHandler
(
e
)
{
if
(
e
.
key
.
toLowerCase
()
===
'
r
'
&&
e
.
shiftKey
)
{
if
(
!
app
.
recordingAction
)
{
// Create a new action if currentAction has ops.
if
(
!
app
.
currentAction
||
app
.
currentAction
.
ops
.
length
>
0
)
{
app
.
newAction
();
}
app
.
recordingAction
=
app
.
currentAction
;
if
(
app
.
recordingAction
)
{
let
$iframe
=
document
.
body
.
querySelector
(
'
iframe
'
);
app
.
recordingAction
.
ops
=
[];
app
.
recordingAction
.
scrollY
=
$iframe
.
contentWindow
.
scrollY
;
app
.
recordingAction
.
scrollX
=
$iframe
.
contentWindow
.
scrollX
;
app
.
recordingAction
.
timestamp
=
Date
.
now
();
...
...
@@ -93,12 +114,19 @@ function recordIframeEvents(iframe, app) {
function
addMouseOp
(
type
,
e
)
{
if
(
app
.
recordingAction
)
{
let
time
=
Date
.
now
()
-
app
.
recordingAction
.
timestamp
;
app
.
recordingAction
.
ops
.
push
({
type
,
time
:
Date
.
now
()
-
app
.
recordingAction
.
timestamp
,
time
:
time
,
x
:
e
.
clientX
,
y
:
e
.
clientY
});
if
(
type
===
'
mouseup
'
&&
app
.
config
.
screenshotAfterMouseUp
)
{
app
.
recordingAction
.
ops
.
push
({
time
:
time
+
1
,
// TODO, Add delay time?
type
:
'
screenshot-auto
'
});
}
app
.
$notify
.
info
({
title
:
type
,
message
:
`(x:
${
e
.
clientX
}
, y:
${
e
.
clientY
}
)`
,
...
...
test/runTest/util.js
浏览文件 @
2973d0c9
...
...
@@ -70,4 +70,12 @@ module.exports.buildRuntimeCode = async function () {
// seedrandom use crypto as external module. Set it to null to avoid not defined error.
// TODO
return
'
window.crypto = null
\n
'
+
output
.
code
;
};
\ No newline at end of file
};
module
.
exports
.
waitTime
=
function
(
time
)
{
return
new
Promise
(
resolve
=>
{
setTimeout
(()
=>
{
resolve
();
},
time
);
});
}
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录