88 lines
6.5 KiB
JavaScript
88 lines
6.5 KiB
JavaScript
import { _electron as electron,expect } from '@playwright/test'
|
|
import { listPackage } from '@electron/asar'
|
|
import ExcelJS from 'exceljs'
|
|
import { PNG } from 'pngjs'
|
|
import fs from 'node:fs/promises'
|
|
import path from 'node:path'
|
|
import {PDFDocument} from 'pdf-lib'
|
|
const root=process.cwd(),version=JSON.parse(await fs.readFile('package.json','utf8')).version
|
|
await fs.mkdir(path.join(root,'.qa'),{recursive:true})
|
|
const qa=await fs.mkdtemp(path.join(root,'.qa','packaged-'+version+'-'))
|
|
const profile=path.join(qa,'profile'),sealFolder=path.join(qa,'seals'),output=path.join(qa,'output')
|
|
for(const folder of [profile,sealFolder,output])await fs.mkdir(folder,{recursive:true})
|
|
const image=new PNG({width:120,height:120})
|
|
for(let y=0;y<120;y++)for(let x=0;x<120;x++){
|
|
const i=(y*120+x)*4,d=Math.hypot(x-60,y-60)
|
|
image.data[i]=195;image.data[i+1]=30;image.data[i+2]=35;image.data[i+3]=d>45&&d<50?255:0
|
|
}
|
|
await fs.writeFile(path.join(sealFolder,'测试印章.png'),PNG.sync.write(image))
|
|
const book=new ExcelJS.Workbook(),sheet=book.addWorksheet('收据数据')
|
|
sheet.addRow(['收款日期','学校','年级','姓名','收费项目','金额'])
|
|
for(const [school,name,amount] of [['甲学校','张三',3500],['乙学校','赵六',2500],['甲学校','李四',3000],['甲学校','王五',2000]])sheet.addRow(['2026-10-19',school,'高一',name,'秋季学期服务费',amount])
|
|
const excelFile=path.join(qa,'收据测试数据.xlsx');await book.xlsx.writeFile(excelFile)
|
|
const archive=listPackage(path.join(root,'release','win-unpacked','resources','app.asar'))
|
|
expect(archive.some(file=>/[\\/](?:\.local-data|\.qa|\.vs|node_modules)(?:[\\/]|$)/.test(file))).toBe(false)
|
|
expect(archive.some(file=>/\.(?:sqlite|map)$/i.test(file))).toBe(false)
|
|
expect(archive.some(file=>/[\\/]brand-[^\\/]+\.png$/.test(file))).toBe(true)
|
|
const env={...process.env};delete env.ELECTRON_RUN_AS_NODE;delete env.ELECTRON_RENDERER_URL
|
|
let app
|
|
const errors=[]
|
|
try{
|
|
app=await electron.launch({executablePath:path.join(root,'release','win-unpacked','收据工坊.exe'),args:['--smoke-test','--user-data-dir='+profile],env,timeout:60000})
|
|
const page=await app.firstWindow();page.setDefaultTimeout(20000)
|
|
page.on('pageerror',error=>errors.push(error.message))
|
|
await expect(page.getByRole('heading',{name:'收据工作台',exact:true})).toBeVisible({timeout:30000})
|
|
await expect(page.getByText('把表格交给收据工坊')).toBeVisible({timeout:30000})
|
|
const boot=await page.evaluate(()=>window.receipts.bootstrap())
|
|
expect(boot.version).toBe(version)
|
|
expect(boot.dataDirectory).toBe(profile)
|
|
expect(boot.nextNumber).toBe('SJ00000001')
|
|
expect(boot.historyTotal).toBe(0);expect(boot.settings.historyPageSize).toBe(5)
|
|
await expect.poll(()=>page.locator('.brand-mark').evaluate(img=>img.complete&&img.naturalWidth===200)).toBe(true)
|
|
await page.getByRole('button',{name:'A4 打印排版',exact:true}).click()
|
|
await expect(page.frameLocator('iframe').locator('.receipt')).toHaveCount(2)
|
|
await page.getByLabel('打印每页张数').selectOption('1')
|
|
await expect(page.frameLocator('iframe').locator('.receipt')).toHaveCount(1)
|
|
await page.getByLabel('打印每页张数').selectOption('2')
|
|
await expect(page.frameLocator('iframe').locator('.receipt')).toHaveCount(2)
|
|
expect((await page.evaluate(()=>window.receipts.bootstrap())).nextNumber).toBe(boot.nextNumber)
|
|
await app.evaluate(({shell,dialog},file)=>{shell.openPath=async()=>'';dialog.showOpenDialog=async()=>({canceled:false,filePaths:[file]})},excelFile)
|
|
await page.evaluate(async({output,sealFolder})=>{const b=await window.receipts.bootstrap();await window.receipts.saveSettings({...b.settings,outputDirectory:output,sealDirectory:sealFolder,numberPrefix:'PACK'})},{output,sealFolder})
|
|
const seals=await page.evaluate(()=>window.receipts.listSeals());expect(seals.images).toHaveLength(1)
|
|
await page.evaluate(async sealId=>{const b=await window.receipts.bootstrap();await window.receipts.saveSettings({...b.settings,defaultSealId:sealId})},seals.images[0].id)
|
|
await page.reload()
|
|
await expect(page.getByRole('heading',{name:'收据工作台',exact:true})).toBeVisible()
|
|
await page.getByRole('button',{name:'导入 Excel',exact:true}).click()
|
|
await expect(page.getByText('已选择 4 条',{exact:true})).toBeVisible()
|
|
await expect(page.locator('.group-review')).toHaveJSProperty('open',false)
|
|
await page.getByRole('button',{name:'A4 打印排版',exact:true}).click()
|
|
await expect(page.frameLocator('iframe').locator('.receipt')).toHaveCount(2)
|
|
await expect(page.frameLocator('iframe').getByText('甲学校 高一 李四',{exact:true})).toBeVisible()
|
|
await page.getByLabel('单张 PNG',{exact:true}).check()
|
|
await page.getByRole('button',{name:/生成 4 张收据/}).click()
|
|
await expect.poll(async()=>page.evaluate(async()=> (await window.receipts.listBatches())[0]?.status),{timeout:120000,intervals:[500,1000]}).toBe('completed')
|
|
const batch=(await page.evaluate(()=>window.receipts.listBatches()))[0]
|
|
expect(batch.count).toBe(4);expect(batch.firstNumber).toBe('PACK00000001');expect(batch.lastNumber).toBe('PACK00000004')
|
|
const files=await fs.readdir(batch.outputDirectory,{recursive:true})
|
|
expect(files.filter(n=>n.endsWith('.png'))).toHaveLength(4)
|
|
expect(files.filter(n=>n.endsWith('.pdf'))).toHaveLength(6)
|
|
const png=await fs.readFile(path.join(batch.outputDirectory,files.find(n=>n.endsWith('.png'))))
|
|
expect(png.readUInt32BE(png.indexOf('pHYs')+4)).toBe(11811)
|
|
const pages={}
|
|
for(const [school,count] of [['甲学校',2],['乙学校',1]]){
|
|
const file=path.join(school,'高一','秋季学期服务费','A4打印版_每页2张.pdf')
|
|
expect(files).toContain(file)
|
|
const pdf=await PDFDocument.load(await fs.readFile(path.join(batch.outputDirectory,file)))
|
|
expect(pdf.getPageCount()).toBe(count);pages[school]=count
|
|
expect(Math.abs(pdf.getPage(0).getWidth()-595.28)).toBeLessThan(1)
|
|
}
|
|
await page.getByRole('button',{name:/生成记录/}).click()
|
|
await expect(page.locator('.history-table tbody tr')).toHaveCount(1)
|
|
expect((await page.evaluate(()=>window.receipts.bootstrap())).nextNumber).toBe('PACK00000005')
|
|
expect(errors).toEqual([])
|
|
const result={passed:true,version,packaged:true,cleanArchive:true,defaultGroupCollapsed:true,liveA4Preview:true,receipts:4,renderedPdf:true,renderedPng:true,printPages:pages,dpi:300,profile,errors}
|
|
await fs.writeFile(path.join(qa,'result.json'),JSON.stringify(result,null,2))
|
|
await fs.writeFile(path.join(root,'.qa','package-result.json'),JSON.stringify(result,null,2))
|
|
console.log('Packaged application verified: '+version+'. Artifacts: '+qa)
|
|
}finally{if(app)await app.close().catch(()=>{})}
|