/
githubmirror
/
echarts
Обзор
Документация
Войти
/
githubmirror
/
echarts
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
test/runTest/genReport.js
370 строк
10 KB
Ovilia
test(theme): fix test cases of v6
30 май 2025, 13:06
30 май 2025, 13:06
c448109
Код
Авторство
О чём код?
/* * 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. */ const fs = require('fs'); const path = require('path'); const util = require('util'); const { RESULT_FILE_NAME } = require('./store'); const readFileAsync = util.promisify(fs.readFile); function resolveImagePath(imageUrl) { if (!imageUrl) { return ''; } // The original image path is relative to the client. return imageUrl.replace(/\\/g, '/').replace(/\.\.\/tmp/g, './tmp'); } async function inlineImage(imageUrl) { if (!imageUrl) { return ''; } try { let fullPath = path.join(__dirname, resolveImagePath(imageUrl)); // let img = await jimp.read(fullPath); // img.quality(70); // return img.getBase64Async('image/jpeg'); let imgBuffer = await readFileAsync(fullPath); return 'data:image/webp;base64,' + imgBuffer.toString('base64'); } catch (e) { console.error(e); return ''; } } function shouldShowMarkAsExpected(test, expectedSource, expectedVersion) { if (expectedSource === 'release' && (expectedVersion !== test.expectedVersion) || !test.markedAsExpected ) { return false; } if (expectedSource !== 'release' && test.markedAsExpected.length > 0) { return true; } for (let i = 0; i < test.markedAsExpected.length; i++) { if (test.markedAsExpected[i].lastVersion === expectedVersion) { return true; } } return false; } function generateMarkDetails(test) { if (!test.markedAsExpected || test.markedAsExpected.length === 0) { return ''; } let markDetailsHtml = ` <div class="mark-details"> <h3>Marked As Expected Details</h3> <table> <tr> <th>Time</th> <th>Type</th> <th>Marked By</th> <th>Version</th> <th>Comment</th> <th>Link</th> </tr> `; test.markedAsExpected.forEach((mark) => { const timeStr = mark.markTime ? new Date(mark.markTime).toLocaleString() : '-'; markDetailsHtml += ` <tr> <td>${timeStr}</td> <td>${mark.type || '-'}</td> <td>${mark.markedBy || '-'}</td> <td>${mark.lastVersion || '-'}</td> <td>${mark.comment || '-'}</td> <td> ${mark.link ? `<a href="${mark.link}" target="_blank">${mark.link}</a>` : '-'} </td> </tr>`; }); markDetailsHtml += ` </table> </div>`; return markDetailsHtml; } async function genDetail(test) { let shotDetail = ''; let prevShotDesc = ''; let failed = 0; for (let shot of test.results) { if (shot.diffRatio < 0.001) { continue; } failed++; // Batch same description shot if (shot.desc !== prevShotDesc) { shotDetail += `\n#### ${shot.desc}`; prevShotDesc = shot.desc; } let [expectedUrl, actualUrl, diffUrl] = await Promise.all([ inlineImage(shot.expected), inlineImage(shot.actual), inlineImage(shot.diff) // resolveImagePath(shot.expected), // resolveImagePath(shot.actual), // resolveImagePath(shot.diff) ]); shotDetail += ` <div class="diff-container"> <figure class="diff-figure"> <img src="${expectedUrl}" /> <figcaption>Expected ${test.expectedVersion}</figcaption> </figure> <figure class="diff-figure"> <img src="${actualUrl}" /> <figcaption>Actual ${test.actualVersion}</figcaption> </figure> <figure class="diff-figure"> <img src="${diffUrl}" /> <figcaption>Diff(${shot.diffRatio && shot.diffRatio.toFixed(3)})</figcaption> </figure> </div> `; } return { content: shotDetail, failed, total: test.results.length }; } module.exports = async function(testDir) { let sections = []; let markedSections = []; let failedTest = 0; let markedTests = 0; const tests = JSON.parse(fs.readFileSync( path.join(testDir, RESULT_FILE_NAME), 'utf-8' )); // 从测试中提取expectedSource和expectedVersion信息 const expectedSource = tests.length > 0 ? tests[0].expectedSource || 'local' : 'local'; const expectedVersion = tests.length > 0 ? tests[0].expectedVersion || 'local' : 'local'; for (let test of tests) { let detail = await genDetail(test); if (detail.failed > 0) { // 检查是否被标记为预期的测试 if (shouldShowMarkAsExpected(test, expectedSource, expectedVersion)) { markedTests++; let title = `${markedTests}. ${test.name}`; let markContent = generateMarkDetails(test); let sectionText = ` <div class="section-divider"></div> <a id="marked-${test.name}"></a> <h2>${title}</h2> ${markContent} ${detail.content} `; markedSections.push({ content: sectionText, title, id: `marked-${test.name}` }); } else { failedTest++; let title = `${failedTest}. ${test.name} (Failed ${detail.failed} / ${detail.total})`; console.log(title); let sectionText = ` <div class="section-divider"></div> <a id="${test.name}"></a> <h2>${title}</h2> ${detail.content} `; sections.push({ content: sectionText, title, id: test.name }); } } } let htmlText = ` <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Visual Regression Test Report</title> <style> body { font-family: Arial, sans-serif; line-height: 1.6; margin: 0; padding: 0; } h1, h2, h3, h4 { margin-top: 20px; } .sidebar { position: fixed; top: 0; left: 0; width: 280px; height: 100%; background-color: #f8f8f8; padding: 20px; overflow-y: auto; box-shadow: 2px 0 5px rgba(0,0,0,0.1); } .main-content { margin-left: 320px; padding: 20px; } .section-divider { margin-top: 100px; height: 20px; border-top: 1px solid #aaa; } table { width: 100%; border-collapse: collapse; margin-top: 10px; } th, td { padding: 8px; text-align: left; border: 1px solid #ddd; } th { background-color: #f2f2f2; } tr:nth-child(even) { background-color: #f9f9f9; } .diff-container { margin-top: 10px; } .diff-figure { width: 30%; display: inline-block; margin: 0 10px; } .diff-figure img { width: 100%; } .mark-details { margin-top: 20px; } .nav-section { margin-top: 20px; } .nav-section h3 { margin-bottom: 10px; padding-bottom: 5px; border-bottom: 1px solid #ddd; } .nav-list { list-style-type: none; padding-left: 5px; } .nav-list li { margin-bottom: 8px; } .nav-list a { text-decoration: none; color: #333; } .nav-list a:hover { color: #0066cc; text-decoration: underline; } .summary { margin-bottom: 20px; } </style> </head> <body> <div class="sidebar"> <h2>Test Report</h2> <div class="summary"> <p>Total: ${tests.length}</p> <p>Failed: ${failedTest}</p> <p>Marked As Expected: ${markedTests}</p> </div> `; if (markedTests > 0) { htmlText += ` <div class="nav-section"> <h3>Marked As Expected Tests</h3> <ul class="nav-list"> ${markedSections.map(section => { return `<li><a href="#${section.id}">${section.title}</a></li>`; }).join('\n')} </ul> </div>`; } if (failedTest > 0) { htmlText += ` <div class="nav-section"> <h3>Failed Tests</h3> <ul class="nav-list"> ${sections.map(section => { return `<li><a href="#${section.id}">${section.title}</a></li>`; }).join('\n')} </ul> </div>`; } htmlText += ` </div> <div class="main-content"> <h1>Visual Regression Test Report</h1> `; htmlText += markedSections.map(section => section.content).join('\n\n'); htmlText += sections.map(section => section.content).join('\n\n'); htmlText += '\n</div>\n</body>\n</html>'; const file = path.join(testDir, 'report.html'); fs.writeFileSync(file, htmlText, 'utf-8'); return file; }