Files

49 lines
5.1 KiB
TypeScript

import {test,expect,type Page} from "@playwright/test"
import {mkdirSync} from "node:fs"
const host=(id:number)=>({serverId:id,serverName:"Роутер "+id,serverSite:"",serverCountry:"RU"})
async function setup(page:Page){
await page.route("**/health",r=>r.fulfill({json:{ok:true}}))
await page.route("**/api/**",r=>{const path=new URL(r.request().url()).pathname;return r.fulfill({json:path==="/api/servers"?[1,2].map(id=>({id,name:"Роутер "+id,host:"192.0.2."+id,enabled:true,status:null,country:"RU"})):path==="/api/ospf/catalog"?{interfaces:[1,2].map(id=>({...host(id),id:"i",instance:"default",area:"backbone",areaId:"0.0.0.0",interface:"ether"+id,cost:id===1?20:null,type:"ptp",disabled:false,inactive:false,priority:0,helloInterval:10,deadInterval:40,useBfd:true})),neighbors:[1,2].map(id=>({...host(id),id:"n",address:"192.0.2."+(3-id),routerId:"192.0.2."+(3-id),instance:"default",area:"backbone",areaId:"0.0.0.0",interface:"ether"+id,state:id===1?"Full":"Exchange",uptime:"1h",priority:0,stateChanges:0})),instances:[1,2].map(id=>({...host(id),id:"s",name:"default",routerId:"192.0.2."+id,version:2,disabled:false,inactive:false,redistribute:""})),bfdSessions:[1,2].map(id=>({...host(id),id:"b",localAddr:"192.0.2."+id,remoteAddr:"192.0.2."+(3-id),interface:"ether"+id,state:"Up",uptime:"1h",multihop:id===1?false:null,multiplier:id===1?0:null,txInterval:id===1?0:null,rxInterval:id===1?0:null,holdTime:id===1?0:null,packetsRx:id===1?0:null,packetsTx:id===1?0:null,stateChanges:id===1?0:null})),routes:[],failures:[]}:path==="/api/auth/config"?{required:false}:{}})})
}
for(const device of ["desktop","mobile"] as const)test("OSPF: layout/keyboard "+device,async({page})=>{
await page.setViewportSize(device==="desktop"?{width:1440,height:1000}:{width:390,height:844})
await page.emulateMedia({reducedMotion:"reduce"})
await page.clock.install({time:new Date("2026-09-30T05:00:00Z")})
await setup(page);await page.goto("/ospf?server=1")
await expect(page.getByText("ether1",{exact:true})).toBeVisible()
await expect(page.getByRole("textbox",{name:"Поиск в текущем разделе OSPF…"})).toBeVisible()
expect(await page.evaluate(()=>document.documentElement.scrollWidth<=innerWidth)).toBe(true)
const tabs=page.getByRole("button",{name:"BFD",exact:true}).locator("..")
expect(await tabs.evaluate(el=>el.getBoundingClientRect().right<=innerWidth)).toBe(true)
await page.addStyleTag({content:"nextjs-portal { display:none!important; }"});mkdirSync("docs/ux-ui/screens",{recursive:true})
await page.screenshot({path:"docs/ux-ui/screens/ospf-interfaces-"+device+".png",animations:"disabled"})
await page.getByRole("button",{name:"Соседи",exact:true}).focus();await page.keyboard.press("Enter")
const graph=page.getByRole("group",{name:"Топология OSPF"})
await expect(graph).toBeVisible()
await expect(graph.locator("animate,animateMotion")).toHaveCount(0)
await page.screenshot({path:"docs/ux-ui/screens/ospf-neighbors-"+device+".png",animations:"disabled"})
const open=page.locator("tr[data-row-id]").getByRole("button",{name:"Открыть узел Роутер 1",exact:true})
await open.focus();await page.keyboard.press("Enter")
const details=page.getByRole("region",{name:"Детали узла OSPF"});await expect(details).toBeVisible()
await details.scrollIntoViewIfNeeded()
expect(await details.evaluate(el=>el.getBoundingClientRect().right<=innerWidth)).toBe(true)
expect(await page.evaluate(()=>document.documentElement.scrollWidth<=innerWidth)).toBe(true)
await page.screenshot({path:"docs/ux-ui/screens/ospf-detail-"+device+".png",animations:"disabled"})
await details.getByRole("button",{name:"Закрыть",exact:true}).focus();await page.keyboard.press("Escape")
await expect(details).toHaveCount(0)
const node=graph.getByRole("button",{name:"Открыть узел Роутер 1",exact:true});await expect(node).toBeFocused()
await page.keyboard.press(" ");await expect(details).toBeVisible()
await page.keyboard.press("Escape");await expect(details).toHaveCount(0)
await page.getByRole("button",{name:"BFD",exact:true}).focus();await page.keyboard.press("Enter")
await expect(page.locator("tr[data-row-id]")).toHaveCount(1)
expect(await page.evaluate(()=>document.documentElement.scrollWidth<=innerWidth)).toBe(true)
await page.screenshot({path:"docs/ux-ui/screens/ospf-bfd-"+device+".png",animations:"disabled"})
})
test("OSPF: reduced motion и управление анимацией",async({page})=>{
await page.emulateMedia({reducedMotion:"reduce"});await setup(page);await page.goto("/ospf?tab=neighbors")
const graph=page.getByRole("group",{name:"Топология OSPF"}),toggle=page.getByRole("button",{name:"Анимация",exact:true})
await expect(toggle).toBeDisabled();await expect(toggle).toHaveAttribute("aria-pressed","false");await expect(graph.locator("animate,animateMotion")).toHaveCount(0)
await page.emulateMedia({reducedMotion:"no-preference"});await expect(toggle).toBeEnabled();await expect.poll(()=>graph.locator("animate,animateMotion").count()).toBeGreaterThan(0)
await toggle.click();await expect(toggle).toHaveAttribute("aria-pressed","false");await expect(graph.locator("animate,animateMotion")).toHaveCount(0)
})