fix(ui): сохранять контекст и блокировку рекурсивных маршрутов
This commit is contained in:
1 parent
52493debc2
commit
50fad3ac80
10 files changed
+223
-28
No files matched your search
@@ -0,0 +1,39 @@
|
||||
import {test,expect} from "@playwright/test"
|
||||
const headers={"access-control-allow-origin":"*","access-control-allow-methods":"GET,PUT,POST,OPTIONS","access-control-allow-headers":"Content-Type,Authorization"}
|
||||
const device={id:1,name:"Роутер 1",host:"192.0.2.1",country:"RU",enabled:true,status:null}
|
||||
const row=(name:string)=>({id:"one",dstAddress:"10.0.0.0/24",gateway:"192.0.2.1",distance:1,scope:30,targetScope:10,routingTable:"main",checkGateway:"ping",comment:name,disabled:false,country:""})
|
||||
for(const change of ["backend","mode"])for(const operation of ["read","write"])for(const fails of [false,true])test("Маршруты: поздний "+operation+" после смены "+change+"/"+fails,async({page})=>{
|
||||
let newReads=0
|
||||
await page.route("**/health",r=>r.fulfill({headers,json:{ok:true}}))
|
||||
await page.route("**/api/**",r=>{
|
||||
const u=new URL(r.request().url()),p=u.pathname;if(p==="/api/recursive-routes"&&u.port==="8101")newReads++
|
||||
return r.fulfill({headers,json:p==="/api/servers"?[device]:p==="/api/auth/config"?{required:false}:p==="/api/recursive-routes"?{serverId:1,routes:[row(u.port==="8101"?"Новый снимок":"Старый снимок")],live:true,stale:false}:p==="/api/recursive-routes/gateways"?{serverId:1,gateways:[]}:{} })
|
||||
})
|
||||
await page.goto("/settings");await page.getByRole("link",{name:/^Рекурсивные маршруты/}).click()
|
||||
await expect(page.locator("tr[data-row-id]")).toContainText("Старый снимок")
|
||||
let started=false,release!:()=>void;const gate=new Promise<void>(resolve=>{release=resolve})
|
||||
await page.route("**/api/recursive-routes*",async r=>{
|
||||
const u=new URL(r.request().url());if(u.port!=="8000"||u.pathname!=="/api/recursive-routes"||r.request().method()!==(operation==="read"?"GET":"PUT"))return r.fallback()
|
||||
started=true;await gate
|
||||
return r.fulfill(fails?{headers,status:503,json:{error:"Старая ошибка маршрутов"}}:{headers,json:operation==="read"?{serverId:1,routes:[],live:true,stale:false}:{ok:true,serverId:1,routes:r.request().postDataJSON().routes,pushedRoutes:r.request().postDataJSON().routes.length}})
|
||||
})
|
||||
if(operation==="read")await page.getByRole("button",{name:"Обновить",exact:true}).click()
|
||||
else{
|
||||
await page.getByRole("button",{name:"Добавить",exact:true}).click()
|
||||
const sheet=page.getByRole("dialog");await sheet.getByPlaceholder("8.8.8.8/32").fill("203.0.113.0/24");await sheet.getByPlaceholder("1.2.3.4%GW-NAME").fill("192.0.2.9")
|
||||
await sheet.getByRole("button",{name:"Добавить",exact:true}).click()
|
||||
}
|
||||
await expect.poll(()=>started).toBe(true);await page.goBack();await expect(page).toHaveURL(/settings/)
|
||||
if(change==="backend"){const input=page.getByPlaceholder("http://localhost:8000");await input.fill("http://localhost:8101");await input.press("Enter")}
|
||||
else await page.getByRole("button",{name:"Моковые",exact:true}).click()
|
||||
await page.getByRole("link",{name:/^Рекурсивные маршруты/}).click()
|
||||
if(change==="backend")await expect(page.locator("tr[data-row-id]")).toContainText("Новый снимок")
|
||||
else await expect(page.getByText("Раздел работает в режиме",{exact:false})).toBeVisible()
|
||||
const before=newReads,response=page.waitForResponse(r=>new URL(r.url()).port==="8000"&&new URL(r.url()).pathname==="/api/recursive-routes"&&r.request().method()===(operation==="read"?"GET":"PUT"))
|
||||
release();await(await response).finished()
|
||||
await page.evaluate(()=>new Promise<void>(resolve=>requestAnimationFrame(()=>requestAnimationFrame(()=>resolve()))))
|
||||
if(change==="backend")await expect(page.locator("tr[data-row-id]")).toContainText("Новый снимок")
|
||||
await expect(page.getByText("Старая ошибка маршрутов",{exact:false})).toHaveCount(0)
|
||||
await expect(page.locator("[data-sonner-toast]").filter({hasText:"Маршруты применены на роутер"})).toHaveCount(0)
|
||||
expect(newReads).toBe(before)
|
||||
})
|
||||
@@ -0,0 +1,59 @@
|
||||
import {test,expect,type Page} from "@playwright/test"
|
||||
const devices=[1,2].map(id=>({id,name:"Роутер "+id,host:"192.0.2."+id,country:"RU",enabled:true,status:null}))
|
||||
const row=(id:number)=>({id:"r"+id,dstAddress:"10.0."+id+".0/24",gateway:"192.0.2."+id,distance:1,scope:30,targetScope:10,routingTable:"main",checkGateway:"ping",comment:"Маршрут "+id,disabled:false,country:"RU"})
|
||||
async function setup(page:Page) {
|
||||
await page.route("**/health",r=>r.fulfill({json:{ok:true}}))
|
||||
await page.route("**/api/**",r=>{const u=new URL(r.request().url()),p=u.pathname,id=Number(u.searchParams.get("serverId"));return r.fulfill({json:p==="/api/servers"?devices:p==="/api/auth/config"?{required:false}:p==="/api/recursive-routes"?{serverId:id,routes:[row(id)],live:true,stale:false}:p==="/api/recursive-routes/gateways"?{serverId:id,gateways:[]}:{} })})
|
||||
}
|
||||
test("Маршруты: устройство, поиск и раскрытие переживают reload/history",async({page})=>{
|
||||
await setup(page);await page.goto("/recursive-routes?server=2&q=10.0.2&route=10.0.2.0%2F24&table=main&keep=x")
|
||||
await expect(page.getByRole("option").filter({hasText:"Роутер 2"})).toHaveAttribute("aria-selected","true")
|
||||
await expect(page.getByRole("textbox",{name:"Поиск маршрутов"})).toHaveValue("10.0.2")
|
||||
await expect(page.getByText("Endpoint 1",{exact:true})).toBeVisible()
|
||||
await page.reload();await expect(page.getByText("Endpoint 1",{exact:true})).toBeVisible()
|
||||
await page.getByRole("button",{name:"Сбросить поиск маршрутов"}).click()
|
||||
await expect(page).not.toHaveURL(/[?&]q=/)
|
||||
await page.getByRole("option").filter({hasText:"Роутер 1"}).click()
|
||||
await expect(page).toHaveURL(/server=1/);await expect(page).toHaveURL(/keep=x/)
|
||||
await expect(page.getByText("Endpoint 1",{exact:true})).toHaveCount(0)
|
||||
await page.goBack();await expect(page.getByText("Endpoint 1",{exact:true})).toBeVisible()
|
||||
await expect(page.locator("tr[data-row-id]")).toContainText("10.0.2.0/24")
|
||||
})
|
||||
for(const query of ["server=999","server=broken","server=1&server=2","q=a&q=b","route=10.0.1.0/24","table=main","route=a&route=b&table=main"])test("Маршруты: недоступный URL не расширяет срез "+query,async({page})=>{
|
||||
await setup(page);await page.goto("/recursive-routes?"+query+"&keep=x")
|
||||
const error=page.getByRole("alert").filter({hasText:"ссылк"})
|
||||
await expect(error).toBeVisible();await expect(page.locator("tr[data-row-id]")).toHaveCount(0)
|
||||
await expect(page.getByRole("button",{name:"Добавить",exact:true})).toBeDisabled()
|
||||
await error.getByRole("button",{name:"Сбросить контекст маршрутов"}).click()
|
||||
await expect(page).toHaveURL(/keep=x/);await expect(page.locator("tr[data-row-id]")).toHaveCount(1)
|
||||
})
|
||||
test("Маршруты: отсутствующая группа закрывается без сброса устройства и поиска",async({page})=>{
|
||||
await setup(page);await page.goto("/recursive-routes?server=2&q=10.0&route=10.0.9.0%2F24&table=main&keep=x")
|
||||
await page.getByRole("button",{name:"Закрыть маршрут",exact:true}).click()
|
||||
await expect(page).toHaveURL(/server=2/);await expect(page).toHaveURL(/q=10.0/);await expect(page).not.toHaveURL(/[?&]route=/)
|
||||
await expect(page.locator("tr[data-row-id]")).toContainText("10.0.2.0/24")
|
||||
})
|
||||
for(const fails of [false,true])test("Маршруты: history сохраняет lock до завершения записи "+fails,async({page})=>{
|
||||
await setup(page);let writes=0,reads=0;let release!:()=>void;const gate=new Promise<void>(resolve=>{release=resolve})
|
||||
await page.route("**/api/recursive-routes?**",r=>{reads++;const id=Number(new URL(r.request().url()).searchParams.get("serverId"));return r.fulfill({json:{serverId:id,routes:[row(id)],live:true,stale:false}})})
|
||||
await page.route("**/api/recursive-routes",async r=>{writes++;await gate;const next=r.request().postDataJSON().routes;return r.fulfill(fails?{status:503,json:{error:"Старая ошибка записи"}}:{json:{ok:true,serverId:1,routes:next,pushedRoutes:next.length}})})
|
||||
await page.goto("/recursive-routes?server=2")
|
||||
await page.getByRole("option").filter({hasText:"Роутер 1"}).click()
|
||||
await expect(page.getByRole("button",{name:"Добавить",exact:true})).toBeEnabled()
|
||||
await page.getByRole("button",{name:"Добавить",exact:true}).click()
|
||||
const sheet=page.getByRole("dialog")
|
||||
await sheet.getByPlaceholder("8.8.8.8/32").fill("203.0.113.0/24");await sheet.getByPlaceholder("1.2.3.4%GW-NAME").fill("192.0.2.9")
|
||||
await sheet.getByRole("button",{name:"Добавить",exact:true}).click();await expect.poll(()=>writes).toBe(1)
|
||||
await page.goBack();await expect(page).toHaveURL(/server=2/)
|
||||
await expect(page.getByRole("button",{name:"Добавить",exact:true})).toBeDisabled()
|
||||
await expect(page.getByRole("status").filter({hasText:"предыдущего контекста"})).toBeVisible()
|
||||
await page.goForward();await expect(page).toHaveURL(/server=1/)
|
||||
await expect(page.locator("tr[data-row-id]")).toHaveCount(1)
|
||||
await expect(page.getByRole("button",{name:"Добавить",exact:true})).toBeDisabled()
|
||||
const before=reads,response=page.waitForResponse(r=>r.request().method()==="PUT")
|
||||
release();await(await response).finished()
|
||||
await expect.poll(()=>reads).toBe(before+1);await expect(page.getByRole("button",{name:"Добавить",exact:true})).toBeEnabled()
|
||||
await expect(page.getByRole("dialog")).toHaveCount(0);await expect(page.getByText("Старая ошибка записи",{exact:false})).toHaveCount(0)
|
||||
await expect(page.locator("[data-sonner-toast]").filter({hasText:"Маршруты применены на роутер"})).toHaveCount(0)
|
||||
expect(writes).toBe(1)
|
||||
})
|
||||
Reference in new issue
Block a user