378 lines
21 KiB
HTML
Generated
378 lines
21 KiB
HTML
Generated
<!--
|
|
Licensed to the Apache Software Foundation (ASF) under one
|
|
or more contributor license agreements. See the NOTICE file
|
|
distributed with this work for additional information
|
|
regarding copyright ownership. The ASF licenses this file
|
|
to you under the Apache License, Version 2.0 (the
|
|
"License"); you may not use this file except in compliance
|
|
with the License. You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing,
|
|
software distributed under the License is distributed on an
|
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
KIND, either express or implied. See the License for the
|
|
specific language governing permissions and limitations
|
|
under the License.
|
|
-->
|
|
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|
<link rel="shortcut icon" href="asset/echarts-logo.png">
|
|
<title>Visual Regression Testing Tool</title>
|
|
</head>
|
|
<body>
|
|
<div id="app" style="display: none">
|
|
<el-container id="main">
|
|
<el-header class="header" height="50">
|
|
<div id="logo">
|
|
<img src="https://echarts.apache.org/zh/images/logo.png" />
|
|
<h1>Visual Regression Testing Tool</h1>
|
|
</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'">
|
|
<el-col :span="2">
|
|
<el-checkbox :indeterminate="isSelectAllIndeterminate" v-model="allSelected" @change="handleSelectAllChange"></el-checkbox>
|
|
</el-col>
|
|
<el-col :span="17">
|
|
<el-input v-model="searchString" size="mini" placeholder="Filter Tests"></el-input>
|
|
</el-col>
|
|
<el-col :span="2">
|
|
<el-button title="Sort By Failue Percentage" @click="toggleSort" size="mini" type="primary" icon="el-icon-sort">Sort</el-button>
|
|
</el-col>
|
|
</el-row>
|
|
</div>
|
|
<ul class="test-list">
|
|
<li v-for="(test, index) in tests"
|
|
:title="test.name"
|
|
:class="{active: currentTest && currentTest.name === test.name}"
|
|
@click="changeTest($event.target, test.name)"
|
|
>
|
|
<span @mouseup="handleSelect(index)" @mouseup.shift="handleShiftSelect(index)">
|
|
<el-checkbox v-model="test.selected"></el-checkbox>
|
|
</span>
|
|
<i class="el-icon-loading" v-if="test.status === 'pending' && running"></i>
|
|
|
|
<template v-if="test.status === 'finished'">
|
|
<el-tooltip
|
|
v-if="test.actualErrors && test.actualErrors.length > 0"
|
|
>
|
|
<div slot="content">{{test.actualErrors.length}} Errors</div>
|
|
<i class="el-icon-message-solid"
|
|
style="color: #F56C6C"
|
|
></i>
|
|
</el-tooltip>
|
|
<el-tooltip v-else>
|
|
<div slot="content">{{test.percentage}}% Passed</div>
|
|
<el-progress
|
|
type="circle"
|
|
:width="20"
|
|
:stroke-width="2"
|
|
:percentage="test.percentage"
|
|
:status="test.summary"
|
|
></el-progress>
|
|
</el-tooltip>
|
|
</template>
|
|
<el-tooltip
|
|
content="Not yet run"
|
|
v-else-if="!(test.status === 'pending' && running)"
|
|
>
|
|
<i class="el-icon-question"
|
|
style="color: #ccc;font-size: 20px;"
|
|
></i>
|
|
</el-tooltip>
|
|
<a :href="'#' + test.name" class="menu-link">
|
|
{{test.name}}
|
|
<i v-if="test.actions" class="el-icon-video-camera-solid"></i>
|
|
<span v-if="test.actions" style="font-size: 12px;color: #ccc;">({{test.actions}})</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</el-aside>
|
|
<el-main>
|
|
<div class="test-run-controls">
|
|
<div class="test-run-row">
|
|
<div class="run-config-item">
|
|
<el-tooltip content="Show Result of All Test Runnings">
|
|
<div style="cursor: pointer;" @click="showAllTestsRuns">
|
|
<i style="font-size:20px;vertical-align:middle;display:inline-block;" class="el-icon-files"></i>
|
|
<span style="vertical-align:middle;display:inline-block;">LIST OF RUNNING RESULTS</span>
|
|
</div>
|
|
</el-tooltip>
|
|
</div>
|
|
|
|
<div class="run-config-item">
|
|
<el-dropdown v-if="!running" split-button size="mini" title="Run"
|
|
@click="run('selected')"
|
|
@command="run"
|
|
>
|
|
<i class="el-icon-caret-right"></i> RUN ({{selectedTests.length}})
|
|
<el-dropdown-menu slot="dropdown" >
|
|
<el-dropdown-item command="unfinished">Run unfinished ({{unfinishedTests.length}})</el-dropdown-item>
|
|
<el-dropdown-item command="failed">Run failed ({{failedTests.length}})</el-dropdown-item>
|
|
<el-dropdown-item command="all">Run all ({{fullTests.length}})</el-dropdown-item>
|
|
</el-dropdown-menu>
|
|
</el-dropdown>
|
|
|
|
<el-button-group v-else>
|
|
<el-button size="mini" :loading="true">Stop</el-button>
|
|
<el-button title="Run" @click="stopTests" size="mini" icon="el-icon-close" style="padding-left: 3px;padding-right:3px;"></el-button>
|
|
</el-button-group>
|
|
|
|
<el-tooltip :content="'Finished ' + finishedPercentage + '%'">
|
|
<el-progress
|
|
type="circle"
|
|
:percentage="finishedPercentage"
|
|
:width="20"
|
|
:stroke-width="4"
|
|
:show-text="false"
|
|
></el-progress>
|
|
</el-tooltip>
|
|
</div>
|
|
</div>
|
|
<div class="test-run-row">
|
|
<div class="run-config-item">
|
|
<span class="label">
|
|
Expected
|
|
</span>
|
|
<el-select :disabled="running" size="mini" v-model="runConfig.expectedSource" style="width: 90px;">
|
|
<el-option value="release" label="Release"></el-option>
|
|
<el-option value="nightly" label="Nightly"></el-option>
|
|
<el-option value="PR" label="PR"></el-option>
|
|
<el-option value="local" label="Local"></el-option>
|
|
</el-select>
|
|
<el-select
|
|
v-if="runConfig.expectedSource !== 'local' && runConfig.expectedSource !== 'PR'"
|
|
:disabled="running"
|
|
size="mini"
|
|
v-model="runConfig.expectedVersion"
|
|
placeholder="Select Version"
|
|
:style="`width: ${runConfig.expectedSource === 'nightly' ? 160 : 80}px;`"
|
|
>
|
|
<el-option v-for="version in expectedVersionsList" :key="version" :label="version" :value="version"></el-option>
|
|
</el-select>
|
|
<el-input
|
|
v-if="runConfig.expectedSource === 'PR'"
|
|
:disabled="running"
|
|
size="mini"
|
|
v-model="runConfig.expectedVersion"
|
|
placeholder="#123"
|
|
style="width: 120px;"
|
|
></el-input>
|
|
<span class="label">
|
|
Actual
|
|
</span>
|
|
<el-select :disabled="running" size="mini" v-model="runConfig.actualSource" style="width: 90px;">
|
|
<el-option value="release" label="Release"></el-option>
|
|
<el-option value="nightly" label="Nightly"></el-option>
|
|
<el-option value="PR" label="PR"></el-option>
|
|
<el-option value="local" label="Local"></el-option>
|
|
</el-select>
|
|
<el-select
|
|
v-if="runConfig.actualSource !== 'local' && runConfig.actualSource !== 'PR'"
|
|
:disabled="running"
|
|
size="mini"
|
|
v-model="runConfig.actualVersion"
|
|
placeholder="Select Version"
|
|
:style="`width: ${runConfig.actualSource === 'nightly' ? 160 : 80}px;`"
|
|
>
|
|
<el-option v-for="version in actualVersionsList" :key="version" :label="version" :value="version"></el-option>
|
|
</el-select>
|
|
<el-input
|
|
v-if="runConfig.actualSource === 'PR'"
|
|
:disabled="running"
|
|
size="mini"
|
|
v-model="runConfig.actualVersion"
|
|
placeholder="#123"
|
|
style="width: 120px;"
|
|
></el-input>
|
|
</div>
|
|
<div class="run-config-item">
|
|
<span class="label">Renderer</span>
|
|
<el-select :disabled="running" size="mini" style="width: 100px;" v-model="runConfig.renderer" placeholder="Select Renderer">
|
|
<el-option key="canvas" label="canvas" value="canvas"></el-option>
|
|
<el-option key="svg" label="svg" value="svg"></el-option>
|
|
</el-select>
|
|
</div>
|
|
<div class="run-config-item">
|
|
<span class="label">Coarse Pointer</span>
|
|
<el-select :disabled="running" size="mini" style="width: 100px;" v-model="runConfig.useCoarsePointer" placeholder="auto">
|
|
<el-option key="auto" label="auto" value="auto"></el-option>
|
|
<el-option key="true" label="true" value="true"></el-option>
|
|
<el-option key="false" label="false" value="false"></el-option>
|
|
</el-select>
|
|
</div>
|
|
<div class="run-config-item">
|
|
<span class="label">Threads</span>
|
|
|
|
<el-select :disabled="running" size="mini" v-model="runConfig.threads" style="width: 58px">
|
|
<el-option v-for="t in [1, 2, 4, 6, 8]" :key="t" :label="t" :value="t"></el-option>
|
|
</el-select>
|
|
<!-- <el-slider style="width: 100px;" v-model="runConfig.threads" :step="1" :min="1" :max="8" show-stops></el-slider> -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-------- Single Test Reusult ----------->
|
|
<div v-if="currentTest" class="test-result">
|
|
<div class="title">
|
|
<el-progress
|
|
v-if="currentTest.status === 'finished'"
|
|
type="circle"
|
|
:width="30"
|
|
:stroke-width="4"
|
|
:percentage="currentTest.percentage"
|
|
:status="currentTest.summary"
|
|
style="margin-top: 5px;"
|
|
></el-progress>
|
|
<h3>{{currentTest.name}}</h3>
|
|
</div>
|
|
<div class="single-test-ops">
|
|
<el-button-group>
|
|
<el-button :loading="running" size="mini" @click="runSingleTest(currentTest.name)" type="primary" icon="el-icon-caret-right">Run Single</el-button>
|
|
<el-button :loading="running" size="mini" @click="runSingleTest(currentTest.name, true)">Replay</el-button>
|
|
</el-button-group>
|
|
<el-button size="mini" @click="open(currentTestUrl, '_blank')" icon="el-icon-link">Open Demo</el-button>
|
|
<el-button size="mini" @click="open(currentTestRecordUrl, '_blank')" icon="el-icon-video-camera">Record Interaction</el-button>
|
|
</div>
|
|
|
|
<div v-if="currentTest.results.length > 0">
|
|
<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)">
|
|
<i class="el-icon-s-operation"></i>{{result.desc || result.name}}
|
|
</h4>
|
|
<el-row :gutter="40" class="screenshots">
|
|
<el-col :span="8">
|
|
<el-card shadow="hover">
|
|
<div slot="header" class="clearfix">
|
|
<span>Expected - {{currentTest.expectedVersion || ''}}</span>
|
|
<i title="Preview" class="el-icon-view preview" @click="preview(currentTest, 'expected')"></i>
|
|
</div>
|
|
<el-image fit="cover" :src="result.expected" :preview-src-list="[result.expected]"></el-image>
|
|
</el-card>
|
|
</el-col>
|
|
|
|
<el-col :span="8">
|
|
<el-card shadow="hover">
|
|
<div slot="header" class="clearfix">
|
|
<span>Actual - {{currentTest.actualVersion || ''}}</span>
|
|
<i title="Preview" class="el-icon-view preview" @click="preview(currentTest, 'actual')"></i>
|
|
</div>
|
|
<el-image fit="cover" :src="result.actual" :preview-src-list="[result.actual]"></el-image>
|
|
</el-card>
|
|
</el-col>
|
|
|
|
<el-col :span="8">
|
|
<el-card shadow="hover">
|
|
<div slot="header" class="clearfix">
|
|
<span>Diff - {{result.diffRatio.toFixed(4)}}</span>
|
|
</div>
|
|
<el-image fit="cover" :src="result.diff" :preview-src-list="[result.diff]"></el-image>
|
|
</el-card>
|
|
</el-col>
|
|
</el-row>
|
|
</div>
|
|
</div>
|
|
<div v-else class="no-result">
|
|
No Result
|
|
</div>
|
|
|
|
<div class="test-errors" v-if="currentTest.expectedErrors.length > 0 || currentTest.actualErrors.length > 0">
|
|
<el-row :gutter="40">
|
|
<el-col :span="12">
|
|
<el-alert title="Expected Errors" type="error" show-icon></el-alert>
|
|
<div class="error-item" v-for="error in currentTest.expectedErrors">{{error}}</div>
|
|
</el-col>
|
|
<el-col :span="12">
|
|
<el-alert title="Actual Errors" type="error" show-icon> </el-alert>
|
|
<div class="error-item" v-for="error in currentTest.actualErrors">{{error}}</div>
|
|
</el-col>
|
|
</el-row>
|
|
</div>
|
|
|
|
<div class="test-logs" v-if="currentTest.expectedLogs.length > 0 || currentTest.actualLogs.length > 0">
|
|
<el-row :gutter="40">
|
|
<el-col :span="12">
|
|
<el-alert title="Expected Logs" type="info" show-icon> </el-alert>
|
|
<div class="log-item" v-for="log in currentTest.expectedLogs">{{log}}</div>
|
|
</el-col>
|
|
<el-col :span="12">
|
|
<el-alert title="Actual Logs" type="info" show-icon>
|
|
</el-alert>
|
|
<div class="log-item" v-for="log in currentTest.actualLogs">{{log}}</div>
|
|
</el-col>
|
|
</el-row>
|
|
</div>
|
|
</div>
|
|
|
|
<el-dialog
|
|
:visible.sync="showIframeDialog"
|
|
:center="true"
|
|
width="850px"
|
|
>
|
|
<div slot="title">
|
|
{{previewTitle}}
|
|
<a target="_blank" :href="'../../' + previewTitle"><i class="el-icon-link"></i>Open in New Window</a>
|
|
</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" v-loading="loadingTestsRuns">
|
|
<el-table-column property="expectedVersion" label="Expected" width="160"></el-table-column>
|
|
<el-table-column property="actualVersion" label="Actual" width="160"></el-table-column>
|
|
<el-table-column property="renderer" label="Renderer" width="100"></el-table-column>
|
|
<el-table-column property="lastRunTime" label="Last Run" width="160"></el-table-column>
|
|
<el-table-column property="diskSize" label="Disk Size" width="100"></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="Operations"
|
|
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>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
<script src="../node_modules/socket.io-client/dist/socket.io.js"></script>
|
|
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
|
|
|
|
<!-- Element UI -->
|
|
<link rel="stylesheet" href="https://unpkg.com/element-ui@2.15.1/lib/theme-chalk/index.css">
|
|
<script src="https://unpkg.com/element-ui@2.15.1/lib/index.js"></script>
|
|
|
|
<script src="client.js"></script>
|
|
|
|
<link rel="stylesheet" href="client.css">
|
|
|
|
</body>
|
|
</html>
|