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(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(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) })