fix(ui): учитывать права и состояние устройства при откате истории
This commit is contained in:
1 parent
5ce20e8892
commit
c8f9c83f45
17 files changed
+388
-16
No files matched your search
@@ -0,0 +1,30 @@
|
||||
import {test,expect,type Page} from '@playwright/test'
|
||||
const sections=['wireguard','ipsec','gre','firewall','filters','recursive-routes'] as const
|
||||
function token(writer:boolean){return [Buffer.from('{}').toString('base64url'),Buffer.from(JSON.stringify({sub:'own207',apps:['mm'],permissions:['mm:dashboard:read','mm:servers:read','mm:network:read','mm:filters:read',...(writer?['mm:network:write','mm:filters:write']:[])],exp:Math.floor(Date.now()/1000)+600})).toString('base64url'),'fixture'].join('.')}
|
||||
async function setup(page:Page,section:string,writer:boolean,enabled=true){let writes=0
|
||||
await page.addInitScript(t=>localStorage.setItem('mmapp_token',t),token(writer))
|
||||
await page.route('**/health',r=>r.fulfill({json:{ok:true}}))
|
||||
await page.route('**/api/**',r=>{const path=new URL(r.request().url()).pathname;if(r.request().method()!=='GET'){writes++;return r.fulfill({status:403,json:{error:'Unexpected mutation in read-only history fixture'}})}
|
||||
const json=path.endsWith('/revisions')?{revisions:[{id:'own207-revision',serverId:'1',section,source:'apply',fingerprint:'fixture',createdAt:'2026-10-13T00:00:00Z',note:null,itemCount:1}]}:
|
||||
path==='/api/auth/config'?{required:true,portal_url:'http://portal.own.invalid'}:
|
||||
path==='/api/servers'?[{id:1,name:'Own207 router',host:'192.0.2.207',type:'exit-node',enabled,country:'RU',site:'OWN',asn:'',status:'online',latency:1}]:
|
||||
path==='/api/wireguard'?{interfaces:[]}:
|
||||
path==='/api/ipsec'?{servers:[],clients:[]}:
|
||||
path==='/api/gre/tunnels'||path==='/api/filters/gre-tunnels'?{tunnels:[]}:
|
||||
path==='/api/firewall/all'?{rules:[],addressLists:[]}:
|
||||
path==='/api/filters/rules'?{rulesets:[{serverId:'1',rules:[]}],greTunnels:[],live:true}:
|
||||
path==='/api/recursive-routes/catalog'?{serverId:1,routes:[],live:true,stale:false}:
|
||||
path==='/api/recursive-routes/gateways/catalog'?{serverId:1,gateways:[]}:
|
||||
path==='/api/evobgp/settings'?{enabled:false,baseUrl:'',secretConfigured:false}:{}
|
||||
return r.fulfill({json})})
|
||||
await page.goto('/'+section+'?server=1');return ()=>writes
|
||||
}
|
||||
for(const width of [1440,320])for(const section of sections)test(`История207 reader не может откатить ${section} ${width}`,async({page})=>{
|
||||
await page.setViewportSize({width,height:1000});const writes=await setup(page,section,false)
|
||||
const history=page.getByRole('button',{name:'История',exact:true});await expect(history).toBeEnabled();await history.click();const sheet=page.getByRole('dialog');const restore=sheet.getByRole('button',{name:'Откатить',exact:true});await expect(restore).toBeDisabled();await expect(sheet.getByRole('status')).toContainText('Откат недоступен');await restore.evaluate(b=>(b as HTMLButtonElement).click());expect(writes()).toBe(0);expect(await page.evaluate(()=>document.documentElement.scrollWidth<=innerWidth+1)).toBe(true)
|
||||
})
|
||||
for(const section of sections){test(`История207 writer сохраняет подтверждение ${section}`,async({page})=>{
|
||||
const writes=await setup(page,section,true);const history=page.getByRole('button',{name:'История',exact:true});await expect(history).toBeEnabled();await history.click();const restore=page.getByRole('dialog').getByRole('button',{name:'Откатить',exact:true});await expect(restore).toBeEnabled();await restore.click();await expect(page.getByRole('alertdialog')).toBeVisible();await page.getByRole('alertdialog').getByRole('button',{name:'Отмена',exact:true}).click();expect(writes()).toBe(0)
|
||||
});test(`История207 выключенный сервер блокирует откат ${section}`,async({page})=>{
|
||||
const writes=await setup(page,section,true,false);const history=page.getByRole('button',{name:'История',exact:true});await expect(history).toBeVisible();if(await history.isEnabled()){await history.click();await expect(page.getByRole('dialog').getByRole('button',{name:'Откатить',exact:true})).toBeDisabled()}expect(writes()).toBe(0)
|
||||
})}
|
||||
Reference in new issue
Block a user