Run core module E2E from checked-out sources

This commit is contained in:
pavlov346346-source 2026-09-07 18:09:50 +03:00
parent a1565bb1ef
commit c0409234df

View File

@ -1,7 +1,10 @@
import fs from 'node:fs';
import path from 'node:path';
import { test, expect } from '@playwright/test'; import { test, expect } from '@playwright/test';
async function loadModule(page,path,globalName){ async function loadModule(page,file,globalName){
await page.goto('/index.html', { waitUntil:'domcontentloaded' }); await page.goto('/index.html', { waitUntil:'domcontentloaded' });
await page.addScriptTag({url:path}); const content=fs.readFileSync(path.join(process.cwd(),'public','core',file),'utf8');
await page.addScriptTag({content});
expect(await page.evaluate(name=>Boolean(window[name]),globalName)).toBeTruthy(); expect(await page.evaluate(name=>Boolean(window[name]),globalName)).toBeTruthy();
} }
test('legacy localStorage payload cannot execute XSS', async ({ page }) => { test('legacy localStorage payload cannot execute XSS', async ({ page }) => {
@ -15,17 +18,17 @@ test('legacy localStorage payload cannot execute XSS', async ({ page }) => {
expect(pageErrors.filter(x=>!x.includes('supabase'))).toEqual([]); expect(pageErrors.filter(x=>!x.includes('supabase'))).toEqual([]);
}); });
test('safe insert helper handles foreign reference node', async ({ page }) => { test('safe insert helper handles foreign reference node', async ({ page }) => {
await loadModule(page,'/core/sun-safe.js','SunSafe'); await loadModule(page,'sun-safe.js','SunSafe');
const result=await page.evaluate(()=>{const a=document.createElement('div'),b=document.createElement('div'),n=document.createElement('span'),foreign=document.createElement('i');a.appendChild(foreign);document.body.append(a,b);try{window.SunSafe.insertBefore(b,n,foreign);return {ok:true,parent:n.parentNode===b}}catch(e){return {ok:false,error:String(e)}}}); const result=await page.evaluate(()=>{const a=document.createElement('div'),b=document.createElement('div'),n=document.createElement('span'),foreign=document.createElement('i');a.appendChild(foreign);document.body.append(a,b);try{window.SunSafe.insertBefore(b,n,foreign);return {ok:true,parent:n.parentNode===b}}catch(e){return {ok:false,error:String(e)}}});
expect(result).toEqual({ok:true,parent:true}); expect(result).toEqual({ok:true,parent:true});
}); });
test('shared PDF engine produces A4 PDF blob', async ({ page }) => { test('shared PDF engine produces A4 PDF blob', async ({ page }) => {
await loadModule(page,'/core/pdf-engine.js','SunPdfEngine'); await loadModule(page,'pdf-engine.js','SunPdfEngine');
const result=await page.evaluate(async()=>{const fake=new Uint8Array([255,216,255,217]);const blob=window.SunPdfEngine.fromJpegs([{width:1000,height:1414,bytes:fake}]);const head=new TextDecoder().decode(new Uint8Array(await blob.arrayBuffer()).slice(0,8));return {type:blob.type,size:blob.size,head,w:window.SunPdfEngine.PAGE_W,h:window.SunPdfEngine.PAGE_H}}); const result=await page.evaluate(async()=>{const fake=new Uint8Array([255,216,255,217]);const blob=window.SunPdfEngine.fromJpegs([{width:1000,height:1414,bytes:fake}]);const head=new TextDecoder().decode(new Uint8Array(await blob.arrayBuffer()).slice(0,8));return {type:blob.type,size:blob.size,head,w:window.SunPdfEngine.PAGE_W,h:window.SunPdfEngine.PAGE_H}});
expect(result.type).toBe('application/pdf'); expect(result.size).toBeGreaterThan(150); expect(result.head.startsWith('%PDF-1.4')).toBeTruthy(); expect(result.w/result.h).toBeCloseTo(1/Math.sqrt(2),3); expect(result.type).toBe('application/pdf'); expect(result.size).toBeGreaterThan(150); expect(result.head.startsWith('%PDF-1.4')).toBeTruthy(); expect(result.w/result.h).toBeCloseTo(1/Math.sqrt(2),3);
}); });
test('chat photo guard compresses a large camera image', async ({ page }) => { test('chat photo guard compresses a large camera image', async ({ page }) => {
await loadModule(page,'/core/performance.js','SunAttachmentGuard'); await loadModule(page,'performance.js','SunAttachmentGuard');
const result=await page.evaluate(async()=>{ const result=await page.evaluate(async()=>{
const c=document.createElement('canvas');c.width=3000;c.height=2200;const x=c.getContext('2d'); const c=document.createElement('canvas');c.width=3000;c.height=2200;const x=c.getContext('2d');
const g=x.createLinearGradient(0,0,c.width,c.height);g.addColorStop(0,'#172a3a');g.addColorStop(.5,'#d79a4a');g.addColorStop(1,'#f1e3ca');x.fillStyle=g;x.fillRect(0,0,c.width,c.height); const g=x.createLinearGradient(0,0,c.width,c.height);g.addColorStop(0,'#172a3a');g.addColorStop(.5,'#d79a4a');g.addColorStop(1,'#f1e3ca');x.fillStyle=g;x.fillRect(0,0,c.width,c.height);