Files
preland/admin/tests/ui-target-login-race.cjs
T

23 lines
2.4 KiB
JavaScript

/* preland#26: late anonymous401 must preserve UI, notice and actual authenticated session. */
const {chromium}=require('playwright-core'),assert=require('node:assert/strict');
(async()=>{
const browser=await chromium.launch({executablePath:process.env.CHROMIUM_PATH||'/usr/bin/chromium',args:['--no-sandbox']});
const options={baseURL:process.env.ADMIN_URL||'http://admin'};const page=await browser.newPage(options);let original=[];
const login=async p=>{await p.goto('/');await p.getByLabel('Логин',{exact:true}).fill('admin');await p.getByLabel('Пароль',{exact:true}).fill('test-password');await p.getByRole('button',{name:'Войти',exact:true}).click();await p.locator('#workspace').waitFor({state:'visible'});};
try{
let release,ready,held=false;const gate=new Promise(r=>release=r),captured=new Promise(r=>ready=r);
await page.route('**/api/state',async route=>{if(held)return route.continue();held=true;const response=await route.fetch();assert.equal(response.status(),401);ready();await gate;await route.fulfill({response});});
const entered=login(page);await captured;await entered;
original=await page.locator('[data-overview-target]').evaluateAll(ns=>ns.map(n=>n.dataset.overviewTarget));const id=original[0];
await page.locator('[data-overview-target="'+id+'"] .domain-grip').press('ArrowRight');await page.waitForFunction(()=>document.querySelector('#notice').textContent==='Порядок доменов сохранён.');
release();await page.waitForTimeout(500);
assert.equal(await page.locator('#workspace').isVisible(),true,'late anonymous401 must not destroy successful login');
assert.equal(await page.locator('#notice').innerText(),'Порядок доменов сохранён.','late response must not replace successful mutation notice');
const current=await page.request.get('/api/state');assert.equal(current.status(),200,'late anonymous401 must not overwrite authenticated session cookie');
console.log('PASS late anonymous401 preserves workspace/success notice/authenticated session');
}finally{
if(original.length){const cleanup=await browser.newPage(options);await login(cleanup);const state=await cleanup.request.get('/api/state').then(r=>r.json());const response=await cleanup.request.post('/api/targets/order',{data:{ids:original},headers:{'X-CSRF-Token':state.csrf}});assert.ok(response.ok(),'cleanup restores order');}
await browser.close();
}
})().catch(e=>{console.error(e);process.exit(1)});