diff --git a/tests/production-ui-smoke.mjs b/tests/production-ui-smoke.mjs new file mode 100644 index 0000000..05de96d --- /dev/null +++ b/tests/production-ui-smoke.mjs @@ -0,0 +1,79 @@ +import assert from 'node:assert/strict'; +import fs from 'node:fs/promises'; +import {chromium,expect} from '@playwright/test'; + +// Fetch real production assets, but use a synthetic SDK session and workspace. +// All backend traffic is blocked: this verifies published UI, not server login, +// and never reads or modifies a customer account or database. +const base=new URL(process.env.TIMEWEB_BASE_URL||'https://app.caterium.ru'); +assert.equal(base.protocol,'https:'); +const output='production-ui-results'; +await fs.mkdir(output,{recursive:true}); +const browser=await chromium.launch(); +const results=[]; +try{ + for(const width of [1440,390]){ + const context=await browser.newContext({viewport:{width,height:900},serviceWorkers:'block'}); + try{ + await context.route('**/*',route=>{ + const request=route.request(),url=new URL(request.url()); + if(request.method()==='GET'&&url.origin===base.origin&&!url.pathname.startsWith('/api/'))return route.continue(); + return route.abort(); + }); + await context.addInitScript(()=>{ + const workspaceId='ui-smoke-workspace'; + const user={id:'ui-smoke-user',email:'ui-smoke@example.invalid',email_confirmed_at:'2026-01-01T00:00:00Z'}; + localStorage.setItem('sunCloudV2Config',JSON.stringify({workspaceId,localWorkspaceId:workspaceId,tenantStorageReady:true,autoSync:false})); + window.supabase={createClient:()=>({ + auth:{onAuthStateChange:()=>({data:{subscription:{unsubscribe(){}}}}),getSession:async()=>({data:{session:{user}},error:null}),getUser:async()=>({data:{user},error:null})}, + rpc:async name=>{ + if(name==='sun_my_workspaces')return new Promise(resolve=>{window.finishUiSmokeWorkspace=()=>resolve({data:[{id:workspaceId,name:'UI verification',role:'admin',is_active:true,permissions:{}}],error:null});}); + if(name==='sun_subscription_snapshot')return {data:{plan_id:'full',plan_name:'Full',status:'active',access_mode:'full',features:{}},error:null}; + if(name==='caterium_trial_demo_status')return {data:{canInstall:false,canUpgrade:false},error:null}; + if(name==='sun_is_platform_admin')return {data:false,error:null}; + return {data:null,error:null}; + }, + channel:()=>({on(){return this;},subscribe(){return this;}}),removeChannel(){} + })}; + }); + const page=await context.newPage(); + await page.goto(base.href,{waitUntil:'domcontentloaded',timeout:60000}); + const gate=page.locator('#sunCloudAuthGateV3'); + await expect(gate).toHaveAttribute('data-auth-state','loading',{timeout:20000}); + await expect(gate.locator('h2')).toHaveText('Загружаю рабочую базу'); + await expect(gate.locator('button:visible,input:visible,a:visible')).toHaveCount(0); + await expect(gate.locator('.sun-cloud-auth-error')).toBeHidden(); + await expect(page.locator('body > header')).toBeHidden(); + await page.screenshot({path:`${output}/loading-${width}.png`}); + await page.evaluate(()=>window.finishUiSmokeWorkspace()); + await expect(gate).toHaveCount(0,{timeout:20000}); + await expect(page.locator('body > header')).toBeVisible(); + const help=page.locator('#ctHelpNav'); + await expect(help).toHaveClass(/sun-nav-button/); + await help.scrollIntoViewIfNeeded(); + let icon=null; + if(width>900){ + await expect.poll(()=>help.evaluate(el=>getComputedStyle(el,'::before').maskImage||getComputedStyle(el,'::before').webkitMaskImage)).toContain('data:image/svg+xml'); + icon=await help.evaluate(el=>{ + const peer=document.querySelector('header nav .nav-settings'); + const size=node=>{const s=getComputedStyle(node,'::before');return {width:s.width,height:s.height,marginRight:s.marginRight,background:s.backgroundColor};}; + const s=getComputedStyle(el,'::before'); + return {help:size(el),peer:size(peer),mask:s.maskImage||s.webkitMaskImage}; + }); + assert.deepEqual(icon.help,icon.peer); + assert.match(decodeURIComponent(icon.mask),/]*r="9"/); + assert.match(decodeURIComponent(icon.mask),/M12 17h\.01/); + await page.locator('body > header').screenshot({path:`${output}/sidebar-${width}.png`}); + } + await help.click(); + await expect(page.locator('#ctHelpDialog')).toBeVisible(); + await expect(page.locator('#ctHelpTitle')).toHaveText('Помощь в Caterium'); + await expect.poll(()=>page.locator('#ctHelpResults details').count()).toBeGreaterThan(0); + await page.locator('#ctHelpClose').click(); + await expect(page.locator('#ctHelpDialog')).not.toBeVisible(); + results.push({width,quietLoading:true,automaticOpen:true,helpDialog:true,icon}); + console.log(`PASS published UI ${width}px: quiet loading, automatic open, Help dialog${icon?', native question-circle icon':''}`); + }finally{await context.close();} + } + await fs.writeFile(`${output}/result.json`,JSON.stringify({base:base.href,checkedAt:new Date().toISOString(),backend:'mocked and network-blocked',results},null,2)); +}finally{await browser.close();}