13 lines
5.2 KiB
TypeScript
13 lines
5.2 KiB
TypeScript
import {test,expect,type Page} from "@playwright/test"
|
|
const probe={id:"probe-fixture",srcServerId:"1",dstServerId:"2",srcInterface:"",dstInterface:"",protocol:"tcp",direction:"both",durationSec:"10",enabled:true,lastRunAt:null,lastTxAvgMbps:0,lastRxAvgMbps:null,lastStatus:"done",lastError:null}
|
|
async function setup(page:Page){await page.route("**/health",r=>r.fulfill({json:{ok:true}}));await page.route("**/api/**",r=>r.fulfill({json:new URL(r.request().url()).pathname==="/api/auth/config"?{required:false}:new URL(r.request().url()).pathname==="/api/servers"?[{id:1,name:"Fixture server",host:"192.0.2.1",enabled:true,type:"exit-node",status:"online"}]:{tunnels:[]}}))}
|
|
async function open(page:Page){await page.goto("/probes?server=1");await page.getByRole("button",{name:"Расписание",exact:true}).click();return page.getByRole("region",{name:"Пробы скорости",exact:true})}
|
|
for(const malformed of [false,true])test("Probe schedule initial unknown and explicit retry/"+malformed,async({page})=>{await setup(page);let fail=true;await page.route("**/api/uptime/speed-probes",r=>r.fulfill(fail?(malformed?{json:{}}:{status:503,json:{error:"Schedule unavailable"}}):{json:{probes:[]}}));const panel=await open(page);await expect(panel.getByRole("alert")).toBeVisible();await expect(panel.getByText("Нет записей speed-test",{exact:true})).toHaveCount(0);fail=false;await panel.getByRole("button",{name:"Обновить пробы скорости"}).click();await expect(panel.getByText("Нет записей speed-test",{exact:true})).toBeVisible()})
|
|
test("Probe schedule refresh preserves confirmed rows and missing RX does not become zero",async({page})=>{await setup(page);let fail=false;await page.route("**/api/uptime/speed-probes",r=>r.fulfill(fail?{status:503,json:{error:"Schedule unavailable"}}:{json:{probes:[probe]}}));const panel=await open(page);await expect(panel.getByText(/TX: 0.0 .*RX: неизвестно/)).toBeVisible();fail=true;await panel.getByRole("button",{name:"Обновить пробы скорости"}).click();await expect(panel.getByRole("alert")).toContainText("Показан последний успешный список");await expect(panel.getByText(/RX: неизвестно/)).toBeVisible();await expect(panel.getByText(/Последние данные получены:/)).toBeVisible()})
|
|
test("Probe schedule timeout is retryable without automatic request",async({page})=>{await page.clock.install();await setup(page);let calls=0;await page.route("**/api/uptime/speed-probes",()=>{calls++});const panel=await open(page);await expect.poll(()=>calls).toBe(1);await page.clock.fastForward(30100);await expect(panel.getByRole("alert")).toContainText("Время ожидания");await expect(panel.getByRole("button",{name:"Обновить пробы скорости"})).toBeEnabled();expect(calls).toBe(1)})
|
|
test("Probe schedule respects its own uptime permission",async({page})=>{await setup(page);const claims={sub:"fixture",apps:["mm"],permissions:["mm:servers:read"],exp:Math.floor(Date.now()/1000)+3600};const token="e30."+Buffer.from(JSON.stringify(claims)).toString("base64url")+".fixture";await page.addInitScript(value=>localStorage.setItem("mmapp_token",value),token);await page.route("**/api/auth/config",r=>r.fulfill({json:{required:true}}));let calls=0;await page.route("**/api/uptime/speed-probes",r=>{calls++;return r.fulfill({json:{probes:[]}})});const panel=await open(page);await expect(panel.getByRole("alert")).toContainText("Нет права читать пробы скорости");expect(calls).toBe(0)})
|
|
|
|
for(const width of [320,1440])test("Probe schedule known rows fit/"+width,async({page})=>{await setup(page);await page.setViewportSize({width,height:900});await page.route("**/api/uptime/speed-probes",r=>r.fulfill({json:{probes:[{...probe,lastRunAt:"2026-10-03T00:00:00Z"}]}}));const panel=await open(page);await expect(panel.getByText(/RX: неизвестно/)).toBeVisible();await panel.scrollIntoViewIfNeeded();await expect(panel.getByRole("button",{name:"Обновить пробы скорости"})).toBeInViewport();expect(await page.evaluate(()=>document.documentElement.scrollWidth<=window.innerWidth)).toBe(true);await panel.screenshot({path:"docs/ux-ui/screens/probes-speed-schedule-"+width+".png"})})
|
|
|
|
test("Demo schedule clears a tunnel from another device and selects a valid one",async({page})=>{await setup(page);await page.addInitScript(()=>localStorage.setItem("routerlists:data-source","mock"));await page.goto("/probes?server=srv1");await page.getByRole("button",{name:"Расписание",exact:true}).click();await page.getByRole("button",{name:"Добавить правило",exact:true}).click();const server=page.getByRole("combobox",{name:"Устройство расписания"}),tunnel=page.getByRole("combobox",{name:"Туннель расписания"});await expect(tunnel).toHaveValue("gre1");await server.selectOption("srv2");await expect(tunnel).toHaveValue("");await expect(page.getByRole("button",{name:"Добавить",exact:true})).toBeDisabled();await server.selectOption("srv7");await expect(tunnel).toHaveValue("gre5");await expect(page.getByRole("button",{name:"Добавить",exact:true})).toBeEnabled()})
|