This is an automated email from the ASF dual-hosted git repository.

shenyi pushed a commit to branch test-autorun
in repository https://gitbox.apache.org/repos/asf/incubator-echarts.git


The following commit(s) were added to refs/heads/test-autorun by this push:
     new ea440f6  test: Improve visual regression test UI
ea440f6 is described below

commit ea440f6b2584ad60e528f29627e5122d92ce6e7f
Author: pissang <bm2736...@gmail.com>
AuthorDate: Thu Aug 29 20:33:55 2019 +0800

    test: Improve visual regression test UI
---
 test/runTest/blacklist.js      |   4 +-
 test/runTest/cli.js            |  59 ++++++++++++++++-------
 test/runTest/client/client.css | 107 ++++++++++++++++++++++++++++++++++++++---
 test/runTest/client/client.js  | 102 +++++++++++++++++++++++++++++++++++----
 test/runTest/client/index.html |  62 +++++++++++++++++++-----
 5 files changed, 287 insertions(+), 47 deletions(-)

diff --git a/test/runTest/blacklist.js b/test/runTest/blacklist.js
index e059607..77cdd23 100644
--- a/test/runTest/blacklist.js
+++ b/test/runTest/blacklist.js
@@ -1,4 +1,4 @@
 module.exports = [
-'-cases.html',
-'geo-random-stream.html'
+    '-cases.html',
+    'geo-random-stream.html'
 ];
\ No newline at end of file
diff --git a/test/runTest/cli.js b/test/runTest/cli.js
index b560072..69d3188 100644
--- a/test/runTest/cli.js
+++ b/test/runTest/cli.js
@@ -140,7 +140,6 @@ async function takeScreenshot(page, elementQuery, fileUrl, 
desc, version) {
 }
 
 async function runTestPage(browser, fileUrl, version) {
-
     const {keepWait, waitTimeout} = createWaitTimeout(3200);
     const testResults = [];
     let screenshotPromises = [];
@@ -176,10 +175,16 @@ async function runTestPage(browser, fileUrl, version) {
 
     let pageFinishPromise = waitPageForFinish(page);
 
-    await page.goto(`${origin}/test/${fileUrl}`, {
-        waitUntil: 'networkidle2',
-        timeout: 10000
-    });
+    try {
+        await page.goto(`${origin}/test/${fileUrl}`, {
+            waitUntil: 'networkidle2',
+            timeout: 10000
+        });
+    }
+    catch(e) {
+        // TODO Timeout Error
+        console.error(e);
+    }
 
     // Do auto screenshot for every 1 second.
     let count = 1;
@@ -213,6 +218,7 @@ async function runTestPage(browser, fileUrl, version) {
 }
 
 async function runTest(browser, testOpt) {
+    testOpt.status === 'running';
     const fileUrl = testOpt.fileUrl;
     const expectedShots = await runTestPage(browser, fileUrl, '4.2.1');
     const actualShots = await runTestPage(browser, fileUrl);
@@ -238,6 +244,7 @@ async function runTest(browser, testOpt) {
             expected: getClientRelativePath(expected.screenshotPath),
             diff: getClientRelativePath(diffPath),
             name: actual.testName,
+            desc: actual.desc,
             diffRatio
         });
     });
@@ -292,21 +299,37 @@ async function start() {
 
     io.on('connect', socket => {
         broadcast({tests});
+        // TODO Stop previous?
+        socket.on('run', async testsNameList => {
+            console.log(testsNameList);
+
+            const pendingTests = tests.filter(testOpt => {
+                return testsNameList.includes(testOpt.name);
+            });
+
+            for (let testOpt of pendingTests) {
+                // Reset all tests results
+                testOpt.status = 'pending';
+                testOpt.results = [];
+            }
+
+            broadcast({tests});
+
+            try {
+                for (let testOpt of pendingTests) {
+                    await runTest(browser, testOpt);
+                    broadcast({tests});
+                    writeTestsToCache(tests);
+                }
+            }
+            catch(e) {
+                console.log(e);
+            }
+        });
     });
 
-    for (let testOpt of tests) {
-        if (testOpt.status === 'finished') {
-            continue;
-        }
-        console.log(`Running test ${testOpt.fileUrl}`)
-        await runTest(browser, testOpt);
-        broadcast({tests});
-        writeTestsToCache(tests);
-    }
 
+    // runTests(browser, tests, tests);
 }
 
-start().catch(e => {
-    console.log('Error during test');
-    console.log(e);
-})
\ No newline at end of file
+start()
\ No newline at end of file
diff --git a/test/runTest/client/client.css b/test/runTest/client/client.css
index 22ce528..62c1ca3 100644
--- a/test/runTest/client/client.css
+++ b/test/runTest/client/client.css
@@ -10,17 +10,112 @@
     font-family: "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans 
GB","Microsoft YaHei","微软雅黑",Arial,sans-serif;
 }
 
-.menu-link {
-    display: block;
+.header {
+    background-color: #293c55;
+    box-shadow: 0 0  20px rgba(0, 0, 0, 0.2);
+    position: relative;
+    z-index: 10;
+}
+
+.header h1 {
+    color: #fff;
+    line-height: 50px;
+    margin: 0;
+    font-weight: 200;
+    font-size: 20px;
+}
+
+#logo>* {
+    display: inline-block;
+    vertical-align: middle;
+}
+
+#logo img {
+    height: 30px;
+    margin-right: 20px;
+}
+
+.nav-toolbar {
+    padding: 10px 10px;
+    background: #162436;
+    box-shadow: inset 0 0 5px black;
+}
+.nav-toolbar .controls {
+    margin-top: 10px;
+}
+
+.test-list {
+    overflow-x: hidden;
+    background: #293c55;
+    margin: 0;
+    padding: 0;
+}
+.test-list li {
+    list-style: none;
+    padding-left: 10px;
+    cursor: pointer;
+    color: #f3f3f3;
+}
+.test-list li a.menu-link {
+    display: inline-block;
     text-decoration: none;
-    font-size: 18px;
+    font-size: 14px;
+    line-height: 40px;
+    color: #f3f3f3;
+    margin-left: 3px;
+    cursor: pointer;
 }
 
-.test-screenshots {
-    margin-top: 50px;
+.test-list li.active {
+    background: #e43c59;
+}
+.test-list li:hover {
+    background: #162436;
+}
+.test-list li>* {
+    vertical-align: middle;
+    display: inline-block
 }
 
-.test-screenshots img {
+.test-list .el-progress__text {
+    font-size: 12px!important;
+}
+
+.test-result {
+    margin-top: 80px;
+    padding: 0 20px;
+}
+
+.test-result img {
     /* height: 200px; */
     width: 100%;
+}
+.test-result h4 {
+    font-size: 30px;
+    font-weight: 200;
+    margin-left: -20px;
+}
+
+
+::-webkit-scrollbar {
+    height:8px;
+    width:8px;
+    transition:all 0.3s ease-in-out;
+    border-radius:2px;
+    background: transparent;
+}
+
+::-webkit-scrollbar-button {
+    display:none;
+}
+
+::-webkit-scrollbar-thumb {
+    width:8px;
+    min-height:15px;
+    background:rgba(50, 50, 50, 0.6) !important;
+    transition:all 0.3s ease-in-out;border-radius:2px;
+}
+
+::-webkit-scrollbar-thumb:hover {
+    background:rgba(0, 0, 0, 0.5) !important;
 }
\ No newline at end of file
diff --git a/test/runTest/client/client.js b/test/runTest/client/client.js
index 5bc96b6..716fdad 100644
--- a/test/runTest/client/client.js
+++ b/test/runTest/client/client.js
@@ -1,32 +1,114 @@
 const socket = io();
+
+function processTestsData(tests) {
+    tests.forEach(test => {
+        let passed = 0;
+        test.results.forEach(result => {
+            // Threshold?
+            if (result.diffRatio < 0.001) {
+                passed++;
+            }
+        });
+        test.percentage = passed === 0 ? 0 : Math.round(passed / 
test.results.length * 100);
+        if (test.percentage === 100) {
+            test.summary = 'success';
+        }
+        else if (test.percentage < 50) {
+            test.summary = 'exception';
+        }
+        else {
+            test.summary = 'warning'
+        }
+        test.selected = false;
+    });
+    return tests;
+}
+
 socket.on('connect', () => {
     console.log('Connected');
-
     const app = new Vue({
         el: '#app',
         data: {
-            tests: [],
-            selectedTestName: ''
+            fullTests: [],
+            currentTestName: '',
+            sortBy: 'name',
+            searchString: '',
+            running: false,
+
+            allSelected: false
         },
         computed: {
-            selectedTest() {
-                let selectedTest = this.tests.find(item => item.name === 
this.selectedTestName);
-                if (!selectedTest) {
-                    selectedTest = this.tests[0];
+            tests() {
+                let sortFunc = this.sortBy === 'name'
+                    ? (a, b) => a.name.localeCompare(b.name)
+                    : (a, b) => a.percentage - b.percentage;
+
+                if (!this.searchString) {
+                    return this.fullTests.sort(sortFunc);
+                }
+
+                return this.fullTests.filter(test => {
+                    return test.name.match(this.searchString);
+                }).sort(sortFunc);
+            },
+
+            currentTest() {
+                let currentTest = this.fullTests.find(item => item.name === 
this.currentTestName);
+                if (!currentTest) {
+                    currentTest = this.fullTests[0];
+                }
+                return currentTest;
+            },
+
+            isSelectAllIndeterminate() {
+                if (!this.tests.length) {
+                    return true;
+                }
+                return this.tests.some(test => {
+                    return test.selected !== this.tests[0].selected;
+                });
+            }
+        },
+        methods: {
+            goto(url) {
+                window.location.hash = '#' + url;
+            },
+            toggleSort() {
+                this.sortBy = this.sortBy === 'name' ? 'percentage' : 'name';
+            },
+            handleSelectAllChange(val) {
+                // Only select filtered tests.
+                this.tests.forEach(test => {
+                    test.selected = val;
+                });
+                this.isSelectAllIndeterminate = false;
+            },
+            runSelectedTests() {
+                this.running = true;
+                const tests = this.fullTests.filter(test => {
+                    return test.selected;
+                }).map(test => {
+                    return test.name
+                });
+                if (tests.length > 0) {
+                    socket.emit('run', tests);
                 }
-                return selectedTest;
+            },
+            stopTests() {
+                this.running = false;
+                socket.emit('stop');
             }
         }
     });
     app.$el.style.display = 'block';
 
     socket.on('broadcast', msg => {
-        app.tests = msg.tests;
+        app.fullTests = processTestsData(msg.tests);
     });
 
     function updateTestHash() {
         let testName = window.location.hash.slice(1);
-        app.selectedTestName = testName;
+        app.currentTestName = testName;
     }
 
     updateTestHash();
diff --git a/test/runTest/client/index.html b/test/runTest/client/index.html
index 8bfdf3b..e9797ec 100644
--- a/test/runTest/client/index.html
+++ b/test/runTest/client/index.html
@@ -8,22 +8,58 @@
 <body>
 <div id="app" style="display: none">
     <el-container id="main">
-        <el-header>
-            <h1>Visual Regression Test</h1>
+        <el-header class="header" height="50">
+            <div id="logo">
+                <img src="https://echarts.apache.org/zh/images/logo.png"; />
+                <h1>Visual Regression Test</h1>
+            </div>
         </el-header>
         <el-container style="min-height: 0"> <!-- 
https://juejin.im/post/5c642f2ff265da2de660ecfc -->
-            <el-aside width="250px">
-                <el-menu class="test-list">
-                    <el-menu-item v-for="test in tests">
+            <el-aside width="300px">
+                <div class="nav-toolbar">
+                    <el-input v-model="searchString" size="mini" 
placeholder="Filter Tests"></el-input>
+                    <div class="controls">
+                        <el-checkbox :indeterminate="isSelectAllIndeterminate" 
v-model="allSelected" @change="handleSelectAllChange"></el-checkbox>
+                        <el-button
+                            style="margin-left: 10px"
+                            title="Sort By Failue Percentage" 
@click="toggleSort" circle size="mini" type="primary" icon="el-icon-sort"
+                        ></el-button>
+                        <!-- <el-button-group>
+                            <el-button title="Select All" 
@click="selectAllTests" circle size="mini" type="primary" 
icon="el-icon-check"></el-button>
+                            <el-button title="Unselect All" 
@click="unselectAllTests" circle size="mini" type="primary" 
icon="el-icon-close"></el-button>
+                        </el-button-group> -->
+                        <el-button-group>
+                            <el-button title="Run Selected" 
@click="runSelectedTests" :loading="running" circle size="mini" type="primary" 
icon="el-icon-caret-right"></el-button>
+                            <el-button v-if="running" title="Run Selected" 
@click="stopTests" circle size="mini" type="primary" 
icon="el-icon-close"></el-button>
+                        </el-button-group>
+                    </div>
+                </div>
+                <ul class="test-list">
+                    <li v-for="test in tests"
+                        :title="test.name"
+                        :class="{active: currentTest && currentTest.name === 
test.name}"
+                        @click.self="goto(test.name)"
+                    >
+                        <el-checkbox v-model="test.selected"></el-checkbox>
+                        <i class="el-icon-loading" v-if="test.status === 
'pending' && running"></i>
+                        <el-progress
+                            v-if="test.status === 'finished'"
+                            type="circle"
+                            :width="20"
+                            :stroke-width="2"
+                            :percentage="test.percentage"
+                            :status="test.summary"
+                        ></el-progress>
                         <a :href="'#' + test.name" 
class="menu-link">{{test.name}}</a>
-                    </el-menu-item>
-                </el-menu>
+
+                    </li>
+                </ul>
             </el-aside>
             <el-main>
-                <div v-if="selectedTest">
-                    <div class="test-screenshots" v-for="result in 
selectedTest.results">
-                        <h4 class="md-title">{{result.name}}</h4>
-                        <el-row :gutter="20">
+                <div v-if="currentTest">
+                    <div class="test-result" v-for="result in 
currentTest.results">
+                        <h4>{{result.desc || result.name}}</h4>
+                        <el-row :gutter="40" class="screenshots">
                             <el-col :span="8">
                                 <el-card>
                                     <div slot="header" class="clearfix">
@@ -52,6 +88,10 @@
                             </el-col>
                         </el-row>
                     </div>
+
+                    <div class="test-result-nav">
+
+                    </div>
                 </div>
             </el-main>
         </el-container>


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@echarts.apache.org
For additional commands, e-mail: commits-h...@echarts.apache.org

Reply via email to