import {test,expect} from '@playwright/test'; const gateSelector='#sunCloudAuthGateV3'; async function startWorkspaceLookup(page,{withoutDecoration=false}={}){ await page.route('https://**',route=>route.abort()); if(withoutDecoration)await page.route('**/core/login-signature-v1776.js*',route=>route.abort()); await page.addInitScript(()=>{ localStorage.setItem('sunCloudV2Config',JSON.stringify({workspaceId:'startup-company',localWorkspaceId:'startup-company',tenantStorageReady:true,autoSync:false})); const recovered=sessionStorage.getItem('testWorkspaceRecovered')==='1'; window.workspaceLookupCount=0; window.supabase={createClient:()=>({ auth:{onAuthStateChange:()=>({data:{subscription:{unsubscribe(){}}}}),getSession:()=>recovered?Promise.resolve({data:{session:{user:{id:'startup-user',email:'test@example.invalid'}}},error:null}):new Promise(resolve=>{window.finishSessionRestore=resolve}),getUser:async()=>({data:{user:null}})}, rpc:async name=>{ if(name==='sun_my_workspaces'){ window.workspaceLookupCount++; if(recovered)return {data:[{id:'startup-company',name:'Test company',role:'admin',is_active:true}],error:null}; return new Promise(resolve=>{window.finishWorkspaceLookup=resolve}); } return {data:null,error:null}; }, channel:()=>({on(){return this},subscribe(){return this}}),removeChannel:()=>{} })}; }); await page.goto('/index.html',{waitUntil:'domcontentloaded'}); await page.waitForFunction(()=>Boolean(window.finishSessionRestore)); await page.evaluate(()=>finishSessionRestore({data:{session:{user:{id:'startup-user',email:'test@example.invalid'}}},error:null})); await page.waitForFunction(()=>window.workspaceLookupCount===1); await expect(page.locator(gateSelector)).toHaveAttribute('data-auth-state','loading'); } async function expectQuietLoading(page){ const gate=page.locator(gateSelector); 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-actions')).toBeHidden(); await expect(gate.locator('.sun-cloud-auth-error')).toBeHidden(); await expect(gate.locator('.hint:visible')).toHaveCount(0); await expect(page.locator('body > header')).toBeHidden(); expect(await gate.locator('.sun-cloud-auth-brand').evaluate(el=>getComputedStyle(el,'::after').animationName)).toBe('caterium-workspace-loading'); } async function resolveWorkspace(page){ await page.evaluate(()=>finishWorkspaceLookup({data:[{id:'startup-company',name:'Test company',role:'admin',is_active:true}],error:null})); await expect(page.locator(gateSelector)).toHaveCount(0); await expect(page.locator('body > header')).toBeVisible(); } for(const withoutDecoration of [false,true]){ test(`workspace loading has no recovery controls and opens automatically (decoration blocked: ${withoutDecoration})`,async({page})=>{ await startWorkspaceLookup(page,{withoutDecoration}); await expectQuietLoading(page); await page.emulateMedia({reducedMotion:'reduce'}); expect(await page.locator(`${gateSelector} .sun-cloud-auth-brand`).evaluate(el=>getComputedStyle(el,'::after').animationName)).toBe('none'); await resolveWorkspace(page); }); } test('failed workspace lookup retains recovery controls and retry returns to quiet loading',async({page})=>{ await startWorkspaceLookup(page); await expectQuietLoading(page); await page.evaluate(()=>finishWorkspaceLookup({data:null,error:{message:'Workspace lookup failed',code:'TEST_NETWORK'}})); const gate=page.locator(gateSelector); await expect(gate).toHaveAttribute('data-auth-state','error'); await expect(page.locator('#sunGateRetryWorkspaceV3')).toBeVisible(); await expect(page.locator('#sunGateSignOutV3')).toBeVisible(); await expect(page.locator('#sunGateErrorV3')).toBeVisible(); // Error markup intentionally has no .sun-cloud-auth-brand loading wrapper. expect(await gate.evaluate(el=>[...el.querySelectorAll('*')].some(node=>getComputedStyle(node,'::after').animationName==='caterium-workspace-loading'))).toBe(false); await page.locator('#sunGateRetryWorkspaceV3').click(); await page.waitForFunction(()=>window.workspaceLookupCount===2); await expect(gate).toHaveAttribute('data-auth-state','loading'); await expectQuietLoading(page); // A successful recovery deliberately reloads the document. Restore the mock // session/workspace on that new document rather than pausing it a second time. const reloaded=page.waitForEvent('framenavigated',frame=>frame===page.mainFrame()); await page.evaluate(()=>{ sessionStorage.setItem('testWorkspaceRecovered','1'); finishWorkspaceLookup({data:[{id:'startup-company',name:'Test company',role:'admin',is_active:true}],error:null}); }); await reloaded; await expect(page.locator(gateSelector)).toHaveCount(0); await expect(page.locator('body > header')).toBeVisible(); });