81 lines
6.5 KiB
JavaScript
81 lines
6.5 KiB
JavaScript
import { _electron as electron,expect } from '@playwright/test'
|
|
import electronPath from 'electron'
|
|
import ExcelJS from 'exceljs'
|
|
import { PNG } from 'pngjs'
|
|
import { PDFDocument } from 'pdf-lib'
|
|
import fs from 'node:fs/promises'
|
|
import path from 'node:path'
|
|
const root=process.cwd(),qa=path.join(root,'.qa','print-regression'),profile=path.join(qa,'profile'),output=path.join(qa,'output'),seals=path.join(qa,'seals')
|
|
if(!qa.startsWith(root+path.sep))throw Error('Invalid QA path')
|
|
await fs.rm(qa,{recursive:true,force:true})
|
|
await fs.mkdir(seals,{recursive:true});await fs.mkdir(output,{recursive:true})
|
|
const image=new PNG({width:256,height:256})
|
|
let seed=731
|
|
for(let i=0;i<image.data.length;i+=4){
|
|
seed=(Math.imul(seed,1664525)+1013904223)>>>0
|
|
image.data[i]=130+(seed&127);image.data[i+1]=(seed>>>8)&63;image.data[i+2]=(seed>>>16)&63;image.data[i+3]=100+(seed>>>24)%156
|
|
}
|
|
await fs.writeFile(path.join(seals,'批量打印测试章.png'),PNG.sync.write(image))
|
|
const book=new ExcelJS.Workbook(),sheet=book.addWorksheet('收据数据')
|
|
sheet.addRow(['收款日期','学校','年级','姓名','收费项目','金额','出纳','复核'])
|
|
for(let i=1;i<=41;i++)sheet.addRow(['2026-10-16','测试学校','高2028届','测试学生'+i,'测试收费项目',3500,'测试出纳','测试复核'])
|
|
const excelFile=path.join(qa,'批量测试.xlsx');await book.xlsx.writeFile(excelFile)
|
|
const env={...process.env};delete env.ELECTRON_RUN_AS_NODE;delete env.ELECTRON_RENDERER_URL
|
|
let desktop
|
|
try{
|
|
desktop=await electron.launch({executablePath:electronPath,args:['.','--test-mode','--user-data-dir='+profile],cwd:root,env,timeout:60000})
|
|
const page=await desktop.firstWindow();page.setDefaultTimeout(30000)
|
|
await expect(page.getByRole('heading',{name:'收据工作台',exact:true})).toBeVisible()
|
|
await expect.poll(()=>page.evaluate(async()=>!!(await window.receipts.bootstrap()).settings)).toBe(true)
|
|
await desktop.evaluate(({dialog,shell},p)=>{dialog.showOpenDialog=async()=>({canceled:false,filePaths:[p.excelFile]});shell.openPath=async()=>''},{excelFile})
|
|
await page.evaluate(async p=>{
|
|
const boot=await window.receipts.bootstrap()
|
|
await window.receipts.saveSettings({...boot.settings,outputDirectory:p.output,sealDirectory:p.seals,numberPrefix:'REG',exportPdf:false,exportPng:false,exportPrint:true})
|
|
},{output,seals})
|
|
const sealCharacters=await page.evaluate(async()=> (await window.receipts.listSeals()).images[0].dataUrl.length)
|
|
expect(sealCharacters*40).toBeGreaterThan(2*1024*1024)
|
|
const batchId=await page.evaluate(async()=>{
|
|
const draft=await window.receipts.importExcel(),seal=(await window.receipts.listSeals()).images[0]
|
|
window.printTestProgress=[]
|
|
window.receipts.onProgress(p=>window.printTestProgress.push({finished:p.finished,status:p.status,errorLength:p.errors.join('').length}))
|
|
return window.receipts.exportReceipts({draftId:draft.id,rowIndices:draft.rows.map(r=>r.index),sealId:seal.id,options:{pdf:false,png:false,print:true,receiptsPerPage:2,cutLine:true}})
|
|
})
|
|
await expect.poll(()=>page.evaluate(async()=> (await window.receipts.listBatches())[0]),{timeout:120000,intervals:[500,1000]}).toMatchObject({status:process.argv.includes('--expect-failure')?'failed':'completed'})
|
|
const summary=await page.evaluate(async()=> (await window.receipts.listBatches())[0])
|
|
if(process.argv.includes('--expect-failure')){
|
|
expect(summary.message).toContain('ERR_INVALID_URL')
|
|
console.log(JSON.stringify({reproduced:true,receiptCount:summary.count,messageCharacters:summary.message.length,imageCharactersInFirstChunk:sealCharacters*40}))
|
|
}else{
|
|
const files=await fs.readdir(summary.outputDirectory,{recursive:true})
|
|
const pdf=await PDFDocument.load(await fs.readFile(path.join(summary.outputDirectory,files.find(f=>f.endsWith('.pdf')))))
|
|
expect(pdf.getPageCount()).toBe(21);expect(Math.abs(pdf.getPage(0).getWidth()-595.28)).toBeLessThan(1)
|
|
const manifest=JSON.parse(await fs.readFile(path.join(summary.outputDirectory,'生成清单.json'),'utf8'))
|
|
expect(manifest.errors).toEqual([]);expect(manifest.receipts).toHaveLength(41)
|
|
expect((await page.evaluate(()=>window.receipts.bootstrap())).nextNumber).toBe('REG00000042')
|
|
const firstDirectory=summary.outputDirectory
|
|
await desktop.evaluate(({BrowserWindow})=>{
|
|
const original=BrowserWindow.prototype.loadURL
|
|
BrowserWindow.prototype.receiptTestLoadURL=original
|
|
BrowserWindow.prototype.loadURL=function(url,...args){
|
|
if(url.startsWith('receipt://print/'))return Promise.reject(new Error("ERR_INVALID_URL (-300) loading 'data:text/html;charset=utf-8,"+'sensitive'.repeat(300000)+"'"))
|
|
return original.call(this,url,...args)
|
|
}
|
|
})
|
|
await page.evaluate(async id=>window.receipts.exportReceipts({batchId:id,options:{pdf:false,png:false,print:true,receiptsPerPage:2,cutLine:true}}),batchId)
|
|
await expect.poll(()=>page.evaluate(async()=> (await window.receipts.listBatches())[0].status),{timeout:30000}).toBe('failed')
|
|
await expect(page.getByRole('alert')).toContainText('ERR_INVALID_URL')
|
|
expect((await page.getByRole('alert').innerText()).length).toBeLessThan(450)
|
|
await expect(page.getByRole('status')).toHaveCount(0)
|
|
const failed=(await page.evaluate(()=>window.receipts.listBatches()))[0]
|
|
expect(failed.message.length).toBeLessThan(450);expect(failed.message).not.toContain('sensitive')
|
|
await desktop.evaluate(({BrowserWindow})=>{BrowserWindow.prototype.loadURL=BrowserWindow.prototype.receiptTestLoadURL;delete BrowserWindow.prototype.receiptTestLoadURL})
|
|
await page.evaluate(async id=>window.receipts.exportReceipts({batchId:id,options:{pdf:true,png:true,print:true,receiptsPerPage:2,cutLine:true}}),batchId)
|
|
await expect.poll(()=>page.evaluate(async old=>{const b=(await window.receipts.listBatches())[0];return b.outputDirectory!==old&&b.status==='completed'},firstDirectory),{timeout:180000,intervals:[1000]}).toBe(true)
|
|
const retry=(await page.evaluate(()=>window.receipts.listBatches()))[0],retryFiles=await fs.readdir(retry.outputDirectory,{recursive:true})
|
|
expect(retryFiles.filter(f=>f.endsWith('.pdf'))).toHaveLength(42);expect(retryFiles.filter(f=>f.endsWith('.png'))).toHaveLength(41)
|
|
expect((await page.evaluate(()=>window.receipts.bootstrap())).nextNumber).toBe('REG00000042')
|
|
await fs.writeFile(path.join(qa,'result.json'),JSON.stringify({passed:true,receiptCount:41,printPages:pdf.getPageCount(),imageCharactersInFirstChunk:sealCharacters*40,retryPdfCount:42,retryPngCount:41,nextNumber:'REG00000042',shortErrorVerified:true,failureNoticeVerified:true,output:retry.outputDirectory},null,2))
|
|
console.log('Large stamp batch printing and original-number retry passed.')
|
|
}
|
|
}finally{if(desktop)await desktop.close().catch(()=>{})}
|