93 lines
7.5 KiB
JavaScript
93 lines
7.5 KiB
JavaScript
import {test,expect} from '@playwright/test';
|
||
|
||
async function boot(page){
|
||
await page.route('https://**',r=>r.abort());
|
||
await page.goto('/index.html',{waitUntil:'domcontentloaded'});
|
||
await page.waitForFunction(()=>Boolean(window.sunClientOfferDebugPdfPages&&window.SunOfferTemplate));
|
||
}
|
||
const base={brandName:'Компания Лист',brandCity:'Казань',client:'Анна и Михаил',event:'Ужин для друзей',date:'2026-10-24',guests:20,foodGrams:8000,pricing:{base:24000,manual:2000,promo:0,discount:2000,itemsTotal:22000,delivery:1000,total:23000},items:[{id:'fixture',name:'Брускетта с печёными овощами, творожным сыром и зеленью',categoryId:0,categoryName:'Боксы',qty:2,unitPrice:12000,sum:24000,weight:'1200 г',composition:['Томаты, баклажаны, перец, сливочный сыр и зелень'],photoData:''}]};
|
||
function validLayout(pages){
|
||
return pages.flatMap((p,index)=>p.__proposalLayout.filter(b=>b.x<35||b.x+b.w>965||b.y<0||b.y+b.h>1400).map(b=>({page:index+1,...b})));
|
||
}
|
||
|
||
test('all 21 selections render their actual distinct covers and local Cyrillic fonts',async({page})=>{
|
||
test.setTimeout(90000);await boot(page);
|
||
const result=await page.evaluate(async s=>{
|
||
const out=[];
|
||
for(const id of CateriumProposalPDF.IDS){
|
||
const pages=await sunClientOfferDebugPdfPages({...s,offerTemplateId:id});
|
||
const text=pages.flatMap(p=>p.__proposalLayout).map(x=>x.text).join('\n');
|
||
out.push({id,cover:pages[0].dataset.sunProposalTemplate,width:pages[0].width,pages:pages.length,text,pixel:pages[0].toDataURL('image/jpeg',.1)});
|
||
pages.forEach(c=>{c.width=0;c.height=0});
|
||
}
|
||
return {out,fonts:[...document.fonts].filter(f=>f.family.includes('Caterium')).map(f=>f.status),choices:SunOfferTemplate.list().map(t=>t.id)};
|
||
},base);
|
||
expect(result.out).toHaveLength(21);expect(result.choices).toHaveLength(21);
|
||
expect(result.fonts).toEqual(['loaded','loaded','loaded']);
|
||
expect(new Set(result.out.map(r=>r.pixel)).size).toBe(21);
|
||
for(const row of result.out){expect(row.cover).toBe(row.id);expect(row.width).toBe(2400);expect(row.text.replaceAll('\n',' ')).toContain(base.items[0].name);expect(row.text).toContain('23');expect(row.text).not.toMatch(/Солнце|SUN \/ CATERING/)}
|
||
});
|
||
|
||
test('flow preserves long Cyrillic names and compositions across pages without text collisions',async({page})=>{
|
||
test.setTimeout(90000);await boot(page);
|
||
const results=await page.evaluate(async({s,validator})=>{
|
||
const valid=eval('('+validator+')'),out=[];
|
||
const long='Очень длинное название блюда с запечённым баклажаном и сливочным сыром ';
|
||
const composition='НачалоСостава '+('Томаты и печёный перец, сливочный сыр; '.repeat(130))+' КонецСостава';
|
||
const sample={...s,event:long.repeat(3),client:long.repeat(2),items:[{...s.items[0],name:long.repeat(4),composition:[composition]}]};
|
||
for(const id of ['light','editorial-grid','neon-menu','premium-emerald']){
|
||
const pages=await sunClientOfferDebugPdfPages({...sample,offerTemplateId:id});
|
||
const layout=pages.flatMap(p=>p.__proposalLayout),text=layout.map(b=>b.text).join(' ').replace(/\s+/g,' ');
|
||
const collisions=[];
|
||
pages.slice(1).forEach((p,index)=>{const list=p.__proposalLayout;for(let i=0;i<list.length;i++)for(let j=i+1;j<list.length;j++){const a=list[i],b=list[j];if(Math.min(a.x+a.w,b.x+b.w)-Math.max(a.x,b.x)>2&&Math.min(a.y+a.h,b.y+b.h)-Math.max(a.y,b.y)>2)collisions.push({page:index+2,a:a.role,b:b.role})}});
|
||
out.push({id,bounds:valid(pages),collisions,text});pages.forEach(c=>{c.width=0;c.height=0});
|
||
}return out;
|
||
},{s:base,validator:validLayout.toString()});
|
||
for(const r of results){expect(r.bounds).toEqual([]);expect(r.collisions).toEqual([]);expect(r.text).toContain('НачалоСостава');expect(r.text).toContain('КонецСостава');expect(r.text).not.toContain('…')}
|
||
});
|
||
|
||
test('offer settings hide personal data and optional blocks; custom gallery reaches the PDF',async({page})=>{
|
||
await boot(page);
|
||
const result=await page.evaluate(async s=>{
|
||
const c=document.createElement('canvas');c.width=40;c.height=40;const ctx=c.getContext('2d');ctx.fillStyle='#891552';ctx.fillRect(0,0,40,40);const gallery=c.toDataURL();
|
||
window.SunOfferWorkspaceV1769={galleryFor:()=>[gallery]};
|
||
window.SunClientOfferSettings={get:()=>({showClientName:false,showDate:false,showGuests:false,showGallery:true,showBoxCount:false,showPriceBreakdown:false,showAmountPerGuest:false,showControl:false,showExtras:false,showFooterNote:false,texts:{menuTitle:'Специальное меню'}})};
|
||
const draws=[],draw=CanvasRenderingContext2D.prototype.drawImage;CanvasRenderingContext2D.prototype.drawImage=function(image,...a){draws.push(image.src);return draw.call(this,image,...a)};
|
||
try{
|
||
const pages=await sunClientOfferDebugPdfPages({...s,offerTemplateId:'light',orderId:'local-fixture'}),text=pages.flatMap(p=>p.__proposalLayout).map(b=>b.text).join(' ');
|
||
return {text,gallery:draws.includes(gallery),bounds:pages.flatMap(p=>p.__proposalLayout.filter(b=>b.y+b.h>1400))};
|
||
}finally{CanvasRenderingContext2D.prototype.drawImage=draw}
|
||
},base);
|
||
expect(result.text).toContain('Специальное меню');expect(result.text).not.toContain(base.client);expect(result.text).not.toContain('октября');expect(result.text).not.toContain('Скидка');expect(result.text).not.toContain('гостей');expect(result.gallery).toBe(true);expect(result.bounds).toEqual([]);
|
||
});
|
||
|
||
test('per-order picker retains the classic, modern and additional collections together',async({page})=>{
|
||
await boot(page);
|
||
await page.evaluate(()=>{
|
||
const grid=document.createElement('div');grid.className='sun-v1764-offer-template-grid';
|
||
for(const id of CateriumProposalPDF.IDS){const b=document.createElement('button');b.dataset.v1764OfferTemplate=id;grid.appendChild(b)}document.body.appendChild(grid);
|
||
});
|
||
await expect(page.locator('.sun-v1764-offer-template-grid button')).toHaveCount(21);
|
||
await expect(page.locator('.sun-v1767-group-label')).toHaveCount(3);
|
||
});
|
||
|
||
test('an actual offer downloads the same A4 pages shown in its preview',async({page})=>{
|
||
test.setTimeout(60000);await boot(page);
|
||
await page.evaluate(async s=>{
|
||
boxes=[{id:'pdf-local',name:s.items[0].name,price:12000,category:0,weight:'1200 г',composition:s.items[0].composition,photo:''}];
|
||
orders=[{id:'pdf-local-order',event:s.event,contact:s.client,date:s.date,time:'18:00',guestsCount:20,lines:[{id:'pdf-local',qty:2}],total:24000,status:'Новый',clientOfferTemplateId:'event-ticket'}];
|
||
await window.sunOpenClientOffer('pdf-local-order');
|
||
},base);
|
||
await expect(page.locator('#sunClientOfferPreview canvas').first()).toHaveAttribute('data-sun-proposal-template','event-ticket');
|
||
const pageCount=await page.locator('#sunClientOfferPreview canvas').count();
|
||
const downloadPromise=page.waitForEvent('download');
|
||
await page.evaluate(()=>window.sunClientOfferDownload());
|
||
const download=await downloadPromise,stream=await download.createReadStream(),chunks=[];
|
||
for await(const chunk of stream)chunks.push(chunk);
|
||
const body=Buffer.concat(chunks).toString('latin1');
|
||
expect(body.startsWith('%PDF-1.4')).toBe(true);
|
||
expect((body.match(/\/Type \/Page\b/g)||[]).length).toBe(pageCount);
|
||
expect((body.match(/\/MediaBox \[0 0 595\.28 841\.89\]/g)||[]).length).toBe(pageCount);
|
||
expect(body).toContain('/Width 2400');
|
||
});
|