| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768 |
- const assert = require('node:assert/strict');
- const fs = require('node:fs');
- const path = require('node:path');
- const http = require('node:http');
- const { chromium } = require('playwright');
- const root = path.resolve(__dirname, '..');
- let mode = 'issues';
- const records = ['人员证书', '项目信息'].map((template, index) => ({template, file:template+'.xlsx', sheet:'数据', row:7,
- fields:['编号'], message:'缺少主键字段:编号', action:'已跳过,未进入知识图谱',
- data:{编号:null, 名称:index ? '项目示例乙' : '证书示例甲', 备注:'<img src=x onerror=alert(1)>', 数量:0}}));
- const server = http.createServer((req, res) => {
- const url = new URL(req.url, 'http://localhost');
- if (url.pathname === '/api/data-quality') {
- res.setHeader('Content-Type','application/json; charset=utf-8');
- if (mode === 'error') { res.statusCode=503; res.end(JSON.stringify({detail:'报告暂不可用'})); return; }
- const payload = mode === 'zero' ? {data_version:'v2',total:0,datasets:{},records:[]} :
- {data_version:'v1',total:2,datasets:{人员证书:1,项目信息:1},records};
- if (!url.searchParams.has('details')) { const {records, ...summary}=payload; res.end(JSON.stringify(summary)); }
- else res.end(JSON.stringify(payload));
- return;
- }
- if (url.pathname.startsWith('/output/')) { res.setHeader('Content-Type','application/json'); res.end(JSON.stringify({nodes:[],relations:[],meta:{build_id:'v1'}})); return; }
- const file = path.join(root,'html',url.pathname === '/' ? 'knowledge_graph_3d.html' : url.pathname);
- if (!file.startsWith(path.join(root,'html')) || !fs.existsSync(file)) {res.statusCode=404; res.end();return;}
- res.setHeader('Content-Type',file.endsWith('.js') ? 'application/javascript; charset=utf-8' : file.endsWith('.css') ? 'text/css; charset=utf-8' : 'text/html; charset=utf-8');
- res.end(fs.readFileSync(file));
- });
- (async () => {
- await new Promise(resolve => server.listen(0,'127.0.0.1',resolve));
- const browser = await chromium.launch({headless:true, channel:'msedge'});
- try {
- const page = await browser.newPage({viewport:{width:1280,height:900}});
- const base = `http://127.0.0.1:${server.address().port}`;
- let dialogs=0; page.on('dialog', d => { dialogs++; d.dismiss(); });
- for (const entry of ['/index.html','/']) {
- mode='issues'; await page.goto(base+entry);
- const alert=page.locator('#dataQualityAlert');
- await alert.waitFor({state:'visible'}); assert.match(await alert.textContent(), /2/);
- await alert.click();
- await page.getByRole('button',{name:'项目信息.xlsx (1)',exact:true}).waitFor();
- assert.match(await page.locator('.dq-card h3').textContent(), /人员证书.xlsx.*第 7 行/);
- assert.equal(await page.locator('.dq-data dd').count(),4);
- assert.equal(await page.locator('.dq-data dd.dq-missing').textContent(),'(空)');
- assert.equal(await page.locator('.dq-data img').count(),0);
- await page.getByRole('button',{name:'项目信息.xlsx (1)',exact:true}).click();
- assert.match(await page.locator('.dq-card h3').textContent(),/项目信息.xlsx/);
- assert.match(await page.locator('.dq-card').textContent(),/项目示例乙/);
- fs.mkdirSync(path.join(root,'.runtime/qa'),{recursive:true});
- if(entry==='/') await page.screenshot({path:path.join(root,'.runtime/qa/data-quality-desktop.png')});
- await page.keyboard.press('Escape');
- assert.equal(await page.locator('#dataQualityDialog').evaluate(el=>el.open),false);
- }
- await page.setViewportSize({width:390,height:844}); await page.locator('#dataQualityAlert').click();
- await page.locator('.dq-card').waitFor();
- assert.ok(await page.locator('.dq-dialog').evaluate(el=>el.scrollWidth<=el.clientWidth));
- await page.screenshot({path:path.join(root,'.runtime/qa/data-quality-mobile.png')});
- mode='zero'; await page.evaluate(()=>window.dispatchEvent(new Event('focus')));
- await page.locator('#dataQualityAlert').waitFor({state:'hidden'});
- await page.getByText('当前版本没有缺少主键的记录。',{exact:true}).waitFor();
- await page.keyboard.press('Escape'); mode='error'; await page.evaluate(()=>window.dispatchEvent(new Event('focus')));
- await page.getByText('数据提醒暂不可用',{exact:true}).waitFor();
- await page.locator('#dataQualityAlert').click(); await page.getByRole('button',{name:'重新加载',exact:true}).waitFor();
- mode='issues'; await page.getByRole('button',{name:'重新加载',exact:true}).click(); await page.locator('.dq-card').waitFor();
- assert.equal(dialogs,0);
- console.log('PASS: both pages, file grouping, full fields, missing highlight, text escaping, Escape, mobile, zero/version refresh, error/retry');
- } finally { await browser.close(); await new Promise(resolve=>server.close(resolve)); }
- })().catch(error=>{console.error(error);process.exitCode=1;server.close();});
|