Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
半栈学徒
incubator-echarts
提交
c7f9a4be
I
incubator-echarts
项目概览
半栈学徒
/
incubator-echarts
与 Fork 源项目一致
从无法访问的项目Fork
通知
5
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,发现更多精彩内容 >>
提交
c7f9a4be
编写于
4月 30, 2021
作者:
P
pissang
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
test(visual): add test runs manager
上级
2a9fd861
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
199 addition
and
23 deletion
+199
-23
test/runTest/cli.js
test/runTest/cli.js
+4
-0
test/runTest/client/client.css
test/runTest/client/client.css
+5
-0
test/runTest/client/client.js
test/runTest/client/client.js
+36
-0
test/runTest/client/index.html
test/runTest/client/index.html
+39
-1
test/runTest/server.js
test/runTest/server.js
+24
-12
test/runTest/store.js
test/runTest/store.js
+91
-10
未找到文件。
test/runTest/cli.js
浏览文件 @
c7f9a4be
...
...
@@ -327,6 +327,10 @@ async function runTests(pendingTests) {
let
runtimeCode
=
await
buildRuntimeCode
();
runtimeCode
=
`window.__TEST_PLAYBACK_SPEED__ =
${
program
.
speed
||
1
}
;\n
${
runtimeCode
}
`
;
process
.
on
(
'
exit
'
,
()
=>
{
browser
.
close
();
});
try
{
for
(
let
testOpt
of
pendingTests
)
{
console
.
log
(
`Running test:
${
testOpt
.
name
}
, renderer:
${
program
.
renderer
}
`
);
...
...
test/runTest/client/client.css
浏览文件 @
c7f9a4be
...
...
@@ -267,6 +267,11 @@ iframe {
overflow
:
overlay
;
}
#tests-runs-dialog
.el-dialog
{
width
:
90%
;
max-width
:
1400px
;
}
::-webkit-scrollbar
{
height
:
8px
;
...
...
test/runTest/client/client.js
浏览文件 @
c7f9a4be
...
...
@@ -109,6 +109,10 @@ const app = new Vue({
previewIframeSrc
:
''
,
previewTitle
:
''
,
// List of all runs.
showRunsDialog
:
false
,
testsRuns
:
[],
runConfig
:
Object
.
assign
({
sortBy
:
'
name
'
,
...
...
@@ -336,6 +340,34 @@ const app = new Vue({
}
}
});
},
showAllTestsRuns
()
{
this
.
showRunsDialog
=
true
;
socket
.
emit
(
'
getAllTestsRuns
'
);
},
switchTestsRun
(
runResult
)
{
},
genTestsRunReport
(
runResult
)
{
},
delTestsRun
(
runResult
)
{
app
.
$confirm
(
'
Are you sure to delete this run?
'
,
'
Warn
'
,
{
confirmButtonText
:
'
Yes
'
,
cancelButtonText
:
'
No
'
,
center
:
true
}).
then
(
value
=>
{
const
idx
=
this
.
testsRuns
.
indexOf
(
runResult
);
if
(
idx
>=
0
)
{
this
.
testsRuns
.
splice
(
idx
,
1
);
}
socket
.
emit
(
'
delTestsRun
'
,
{
id
:
runResult
.
id
});
}).
catch
(()
=>
{});
}
}
});
...
...
@@ -415,6 +447,10 @@ socket.on('abort', res => {
app
.
running
=
false
;
});
socket
.
on
(
'
getAllTestsRuns_return
'
,
res
=>
{
app
.
testsRuns
=
res
.
runs
;
});
function
updateUrl
(
notRefresh
)
{
const
searchUrl
=
assembleParams
({
test
:
app
.
currentTestName
,
...
...
test/runTest/client/index.html
浏览文件 @
c7f9a4be
...
...
@@ -37,6 +37,7 @@ under the License.
</div>
</el-header>
<el-container
style=
"min-height: 0"
>
<!-- https://juejin.im/post/5c642f2ff265da2de660ecfc -->
<!-------- Tests List ----------->
<el-aside
width=
"350px"
>
<div
class=
"nav-toolbar"
>
<el-row
class=
"filters"
:gutter=
"10"
:align=
"'middle'"
>
...
...
@@ -119,6 +120,16 @@ under the License.
</el-button-group>
</div>
<div
class=
"run-config-item"
>
<el-tooltip
content=
"Show All Tests Runs"
>
<i
style=
"font-size: 20px; cursor: pointer;"
class=
"el-icon-files"
@
click=
"showAllTestsRuns"
></i>
</el-tooltip>
</div>
<!-- <div class="run-config-item">
<el-checkbox v-model="runConfig.noHeadless">Replay</el-checkbox>
...
...
@@ -169,7 +180,7 @@ under the License.
</div>
</div>
<!-------- Single Test Reusult ----------->
<div
v-if=
"currentTest"
class=
"test-result"
>
<div
class=
"title"
>
<el-progress
...
...
@@ -268,6 +279,33 @@ under the License.
</div>
<iframe
:src=
"previewIframeSrc"
width=
"800"
height=
"600"
></iframe>
</el-dialog>
<!-------- All Tests Runs ----------->
<el-dialog
id=
"tests-runs-dialog"
:visible.sync=
"showRunsDialog"
title=
"All Tests Runs"
>
<el-table
:data=
"testsRuns"
>
<el-table-column
property=
"expectedVersion"
label=
"Expected"
></el-table-column>
<el-table-column
property=
"actualVersion"
label=
"Actual"
></el-table-column>
<el-table-column
property=
"renderer"
label=
"Renderer"
width=
"100"
></el-table-column>
<el-table-column
property=
"lastRunTime"
label=
"lastRunTime"
></el-table-column>
<el-table-column
property=
"total"
label=
"Total Tests"
width=
"100"
></el-table-column>
<el-table-column
property=
"finished"
label=
"Finished"
width=
"100"
></el-table-column>
<el-table-column
property=
"passed"
label=
"Passed"
width=
"100"
></el-table-column>
<el-table-column
fixed=
"right"
label=
""
width=
"160"
>
<template
slot-scope=
"scope"
>
<el-button
type=
"text"
@
click=
"switchTestsRun(scope.row)"
size=
"small"
>
View
</el-button>
<el-button
type=
"text"
@
click=
"genTestsRunReport(scope.row)"
size=
"small"
>
Report
</el-button>
<el-button
type=
"text"
@
click=
"delTestsRun(scope.row)"
size=
"small"
>
Delete
</el-button>
</template>
</el-table-column>
</el-table>
</el-dialog>
</el-main>
</el-container>
</el-container>
...
...
test/runTest/server.js
浏览文件 @
c7f9a4be
...
...
@@ -24,14 +24,22 @@ const path = require('path');
const
{
fork
}
=
require
(
'
child_process
'
);
const
semver
=
require
(
'
semver
'
);
const
{
port
,
origin
}
=
require
(
'
./config
'
);
const
{
getTestsList
,
updateTestsList
,
saveTestsList
,
mergeTestsResults
,
updateActionsMeta
,
getResultBaseDir
}
=
require
(
'
./store
'
);
const
{
getTestsList
,
updateTestsList
,
saveTestsList
,
mergeTestsResults
,
updateActionsMeta
,
getResultBaseDir
,
getRunHash
,
getAllTestsRuns
,
delTestsRun
}
=
require
(
'
./store
'
);
const
{
prepareEChartsLib
,
getActionsFullPath
}
=
require
(
'
./util
'
);
const
fse
=
require
(
'
fs-extra
'
);
const
fs
=
require
(
'
fs
'
);
const
open
=
require
(
'
open
'
);
const
TEST_HASH_SPLITTER
=
'
__
'
;
function
serve
()
{
const
server
=
http
.
createServer
((
request
,
response
)
=>
{
return
handler
(
request
,
response
,
{
...
...
@@ -199,13 +207,6 @@ function checkPuppeteer() {
}
}
function
getTestHash
(
params
)
{
return
[
params
.
expectedVersion
,
params
.
actualVersion
,
params
.
renderer
].
join
(
TEST_HASH_SPLITTER
);
}
async
function
start
()
{
if
(
!
checkPuppeteer
())
{
...
...
@@ -234,12 +235,12 @@ async function start() {
}
socket
.
on
(
'
setTestVersions
'
,
async
(
params
)
=>
{
if
(
_currentTestHash
!==
get
Test
Hash
(
params
))
{
if
(
_currentTestHash
!==
get
Run
Hash
(
params
))
{
abortTests
();
}
await
updateTestsList
(
_currentTestHash
=
get
Test
Hash
(
params
),
_currentTestHash
=
get
Run
Hash
(
params
),
!
running
// Set to unsettled if not running
);
...
...
@@ -249,6 +250,17 @@ async function start() {
});
});
socket
.
on
(
'
getAllTestsRuns
'
,
async
()
=>
{
socket
.
emit
(
'
getAllTestsRuns_return
'
,
{
runs
:
await
getAllTestsRuns
()
});
});
socket
.
on
(
'
delTestsRun
'
,
async
(
params
)
=>
{
delTestsRun
(
params
.
id
);
console
.
log
(
'
Deleted
'
,
params
.
id
);
});
socket
.
on
(
'
run
'
,
async
data
=>
{
let
startTime
=
Date
.
now
();
...
...
test/runTest/store.js
浏览文件 @
c7f9a4be
...
...
@@ -20,14 +20,18 @@
const
path
=
require
(
'
path
'
);
const
fse
=
require
(
'
fs-extra
'
);
const
fs
=
require
(
'
fs
'
);
const
glob
=
require
(
'
glob
'
);
const
glob
by
=
require
(
'
globby
'
);
const
{
testNameFromFile
}
=
require
(
'
./util
'
);
const
util
=
require
(
'
util
'
);
const
{
blacklist
,
SVGBlacklist
}
=
require
(
'
./blacklist
'
);
let
_tests
=
[];
let
_testsMap
=
{};
let
_testHash
=
''
;
let
_runHash
=
''
;
const
RESULT_FILE_NAME
=
'
__result__.json
'
;
const
RESULTS_ROOT_DIR
=
path
.
join
(
__dirname
,
'
tmp
'
,
'
result
'
);
const
TEST_HASH_SPLITTER
=
'
__
'
;
class
Test
{
constructor
(
fileUrl
)
{
...
...
@@ -59,14 +63,40 @@ class Test {
}
}
/**
* hash of each run is mainly for storing the results.
* It depends on two versions and rendering mode.
*/
function
getRunHash
(
params
)
{
return
[
params
.
expectedVersion
,
params
.
actualVersion
,
params
.
renderer
].
join
(
TEST_HASH_SPLITTER
);
}
/**
* Parse versions and rendering mode from run hash.
*/
function
parseRunHash
(
str
)
{
const
parts
=
str
.
split
(
TEST_HASH_SPLITTER
);
return
{
expectedVersion
:
parts
[
0
],
actualVersion
:
parts
[
1
],
renderer
:
parts
[
2
]
};
}
function
getResultBaseDir
()
{
return
path
.
join
(
__dirname
,
'
tmp
'
,
'
result
'
,
_test
Hash
);
return
path
.
join
(
RESULTS_ROOT_DIR
,
_run
Hash
);
}
module
.
exports
.
getResultBaseDir
=
getResultBaseDir
;
module
.
exports
.
getRunHash
=
getRunHash
;
function
getCacheFilePath
(
baseDir
)
{
return
path
.
join
(
getResultBaseDir
(),
'
__result__.json
'
);
;
function
getCacheFilePath
()
{
return
path
.
join
(
getResultBaseDir
(),
RESULT_FILE_NAME
)
;
}
module
.
exports
.
getTestsList
=
function
()
{
...
...
@@ -78,10 +108,10 @@ module.exports.getTestByFileUrl = function (url) {
};
module
.
exports
.
updateTestsList
=
async
function
(
test
Hash
,
run
Hash
,
setPendingTestToUnsettled
)
{
_
testHash
=
test
Hash
;
_
runHash
=
run
Hash
;
_tests
=
[];
_testsMap
=
{};
_testsExists
=
{};
...
...
@@ -105,7 +135,7 @@ module.exports.updateTestsList = async function (
catch
(
e
)
{
}
// Find if there is new html file
const
files
=
await
util
.
promisify
(
glob
)
(
'
**.html
'
,
{
cwd
:
path
.
resolve
(
__dirname
,
'
../
'
)
});
const
files
=
await
globby
(
'
**.html
'
,
{
cwd
:
path
.
resolve
(
__dirname
,
'
../
'
)
});
files
.
forEach
(
fileUrl
=>
{
if
(
blacklist
.
includes
(
fileUrl
))
{
return
;
...
...
@@ -169,4 +199,55 @@ module.exports.updateActionsMeta = function (testName, actions) {
fs
.
writeFileSync
(
metaPath
,
JSON
.
stringify
(
metaData
,
Object
.
keys
(
metaData
).
sort
((
a
,
b
)
=>
a
.
localeCompare
(
b
)),
2
),
'
utf-8
'
);
};
\ No newline at end of file
};
/**
* Get results of all runs
* @return [ { id, expectedVersion, actualVersion, renderer, lastRunTime, total, finished, passed } ]
*/
module
.
exports
.
getAllTestsRuns
=
async
function
()
{
const
dirs
=
await
globby
(
'
*
'
,
{
cwd
:
RESULTS_ROOT_DIR
,
onlyDirectories
:
true
});
return
dirs
.
map
((
dir
)
=>
{
const
params
=
parseRunHash
(
dir
);
const
resultJson
=
JSON
.
parse
(
fs
.
readFileSync
(
path
.
join
(
RESULTS_ROOT_DIR
,
dir
,
RESULT_FILE_NAME
),
'
utf-8
'
));
const
total
=
resultJson
.
length
;
let
lastRunTime
=
0
;
let
finishedCount
=
0
;
let
passedCount
=
0
;
resultJson
.
forEach
(
test
=>
{
lastRunTime
=
Math
.
max
(
test
.
lastRun
,
lastRunTime
);
if
(
test
.
status
===
'
finished
'
)
{
finishedCount
++
;
let
passed
=
true
;
test
.
results
.
forEach
(
result
=>
{
// Threshold?
if
(
result
.
diffRatio
>
0.0001
)
{
passed
=
false
;
}
});
if
(
passed
)
{
passedCount
++
;
}
}
});
params
.
lastRunTime
=
lastRunTime
>
0
?
new
Date
(
lastRunTime
).
toISOString
()
:
'
N/A
'
;
params
.
total
=
total
;
params
.
passed
=
passedCount
;
params
.
finished
=
finishedCount
;
params
.
id
=
dir
;
return
params
;
});
}
module
.
exports
.
delTestsRun
=
async
function
(
hash
)
{
fse
.
removeSync
(
path
.
join
(
RESULTS_ROOT_DIR
,
hash
));
}
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录