chore(test): проверить смену источника оптимизатора
This commit is contained in:
1 parent
c82434c435
commit
d68c11e58a
5 files changed
+55
-2
No files matched your search
@@ -26,11 +26,17 @@
|
||||
| 7 | Серверы и мониторинг: детали, формы, URL-контекст, права | Завершён в границах локальной приёмки 2026-09-23; внешние ограничения ниже |
|
||||
| 8 | Трафик и статистика | Завершён 2026-09-28 в границах локальной приёмки; ограничения в блоке 8.13 |
|
||||
| 9 | VPN, Firewall и Filters | Завершён в границах локальной приёмки 2026-09-30; блоки 9.1–9.64, ограничения в 9.64 |
|
||||
| 10 | Маршрутизация, диагностика, карта и терминал | В работе: 10.1–10.36; URL устройства OSPF сохраняется, далее source/provenance |
|
||||
| 10 | Маршрутизация, диагностика, карта и терминал | В работе: 10.1–10.37; URL/source проверены, далее model provenance |
|
||||
| 11А | Пользователи, контейнеры, сертификаты и резервные копии | Не начат |
|
||||
| 11Б | Оповещения, сбор данных, интеграции, релизы и настройки | Не начат |
|
||||
| 12 | Итоговая доступность, адаптивность, производительность и регрессия | Не начат |
|
||||
|
||||
## Блок 10.37 — изоляция источника оптимизатора (2026-09-30)
|
||||
|
||||
- Отдельный config с локально изменяемым backend проверяет поздний preview/apply success и failure после смены backend либо live → mock через настройки. Новый экран сохраняет свой snapshot, старый receipt/error не показывается, старое применение не запускает reread нового backend.
|
||||
- 8 source E2E, TS/lint прошли; изменения только тестов/config, production frontend проверен в 10.36. HTTP interception, без реальных сетевых изменений.
|
||||
- Дальше: происхождение модельных метрик/fallback и их отображение; затем карта/терминал. Этап 10 не завершён. Оставшийся пятичасовой лимит на проверке — 2%.
|
||||
|
||||
## Блок 10.36 — URL устройства оптимизатора (2026-09-30)
|
||||
|
||||
- Параметр server восстанавливает OSPF устройство, select обновляет историю, другие параметры/fragment сохраняются. Suspense обеспечивает production render; URL меняет контекст без сброса локальной формы, источник по-прежнему изолирован key(mode, backendUrl).
|
||||
|
||||
@@ -196,3 +196,7 @@ Observed selector вместо default cost/disabled; неоднозначные
|
||||
## 10.36. URL устройства оптимизатора
|
||||
|
||||
server сохраняет выбор/reload/history без потери других параметров. Неизвестный/disabled/malformed explicit контекст не подменяется и не запускает preview/metadata; явный select восстанавливает работу. 22 E2E, 3 unit, TS/lint и production frontend прошли. Далее source/provenance; Home tabs URL пока вне блока.
|
||||
|
||||
## 10.37. Source isolation оптимизатора
|
||||
|
||||
8 E2E late preview/apply success/failure × backend/mode через настройки, новый снимок и отсутствие старых receipt/error/reread. TS/lint прошли. Production frontend из 10.36; реальные операции вне локальной приёмки. Далее model provenance и карта/терминал.
|
||||
@@ -2,7 +2,7 @@ import { defineConfig } from "@playwright/test"
|
||||
|
||||
export default defineConfig({
|
||||
testDir: "./tests/e2e",
|
||||
testIgnore: ["**/recursive-routes-context.spec.ts", "**/ospf-context.spec.ts", "**/bgp-context.spec.ts", "**/firewall-context.spec.ts", "**/filters-context.spec.ts", "**/ipsec-context.spec.ts", "**/gre-context.spec.ts", "**/vxlan-context.spec.ts"],
|
||||
testIgnore: ["**/route-optimizer-context.spec.ts", "**/recursive-routes-context.spec.ts", "**/ospf-context.spec.ts", "**/bgp-context.spec.ts", "**/firewall-context.spec.ts", "**/filters-context.spec.ts", "**/ipsec-context.spec.ts", "**/gre-context.spec.ts", "**/vxlan-context.spec.ts"],
|
||||
fullyParallel: false,
|
||||
workers: 1,
|
||||
retries: 0,
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import { defineConfig } from "@playwright/test"
|
||||
import base from "./playwright.config"
|
||||
const server=base.webServer
|
||||
if(!server||Array.isArray(server))throw new Error("Ожидается один локальный сервер")
|
||||
export default defineConfig({
|
||||
...base, use:{...base.use,baseURL:"http://127.0.0.1:3101"},testIgnore:[],testMatch:"route-optimizer-context.spec.ts",
|
||||
webServer:{...server,command:"node node_modules/next/dist/bin/next dev --hostname 127.0.0.1 --port 3101",url:"http://127.0.0.1:3101",env:{...server.env,NEXT_PUBLIC_BACKEND_URL:"local"}},
|
||||
})
|
||||
@@ -0,0 +1,35 @@
|
||||
import {test,expect} from "@playwright/test"
|
||||
const headers={"access-control-allow-origin":"*","access-control-allow-methods":"GET,POST,OPTIONS","access-control-allow-headers":"Content-Type,Authorization"}
|
||||
const item=(name:string)=>({id:"i",interface:name,currentCost:10,optimalCost:20,score:50,pingMs:10,dlMbps:100,ulMbps:50})
|
||||
for(const change of ["backend","mode"])for(const operation of ["preview","write"])for(const fails of [false,true])test("Оптимизатор: поздний "+operation+"/"+change+"/"+fails,async({page})=>{
|
||||
let newReads=0,started=false,release!:()=>void;const gate=new Promise<void>(resolve=>{release=resolve})
|
||||
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(u.port==="8101")newReads++
|
||||
const row=item(u.port==="8101"?"ether-new":"ether-old")
|
||||
return r.fulfill({headers,json:p==="/api/auth/config"?{required:false}:p==="/api/servers"?[{id:1,name:"Router",host:"192.0.2.1",country:"RU",type:"home-router",enabled:true,status:null}]:p==="/api/filters/rules"?{rulesets:[]}:p==="/api/uptime/speed-probes"?{probes:[]}:p==="/api/ospf/catalog"?{interfaces:[],instances:[],neighbors:[],bfdSessions:[],routes:[],failures:[]}:p.endsWith("/preview")?{serverId:1,serverName:"Router",pingWeight:60,interfacesTotal:1,changedCount:1,unchangedCount:0,interfaces:[row],changes:[row]}:{}})
|
||||
})
|
||||
await page.goto("/settings");await page.getByRole("link",{name:/^Оптимизатор маршрутов/}).click()
|
||||
const grid=page.getByRole("table").filter({hasText:"Speed (dl/ul)"})
|
||||
await expect(grid).toContainText("ether-old");await expect(page.getByText("0 iface · 0 area",{exact:true})).toBeVisible()
|
||||
const path=operation==="preview"?"/api/servers/1/ospf/optimize/preview":"/api/servers/1/ospf/optimize"
|
||||
await page.route("**/api/servers/**",async r=>{
|
||||
const u=new URL(r.request().url());if(u.port!=="8000"||u.pathname!==path)return r.fallback()
|
||||
started=true;await gate;const row=item("ether-late")
|
||||
return r.fulfill(fails?{headers,status:503,json:{error:"Старая ошибка оптимизатора"}}:{headers,json:operation==="preview"?{serverId:1,serverName:"Старый сервер",pingWeight:60,interfacesTotal:1,changedCount:1,unchangedCount:0,interfaces:[row],changes:[row]}:{serverId:1,serverName:"Старый сервер",pingWeight:60,optimizedCount:1,applied:[{interface:"ether-late",from:10,to:20}],interfaces:[row]}})
|
||||
})
|
||||
await page.getByRole("button",{name:operation==="preview"?"Обновить preview OSPF":"Оптимизировать OSPF",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(grid).toContainText("ether-new");await expect(page.getByText("0 iface · 0 area",{exact:true})).toBeVisible()}
|
||||
else await expect(page.getByText("Доступно только в режиме живых данных.",{exact:true})).toBeVisible()
|
||||
const before=newReads,response=page.waitForResponse(r=>new URL(r.url()).port==="8000"&&new URL(r.url()).pathname===path)
|
||||
release();await(await response).finished()
|
||||
await page.evaluate(()=>new Promise<void>(resolve=>requestAnimationFrame(()=>requestAnimationFrame(()=>resolve()))))
|
||||
if(change==="backend")await expect(grid).toContainText("ether-new")
|
||||
await expect(page.getByText("Старая ошибка оптимизатора",{exact:false})).toHaveCount(0)
|
||||
await expect(page.getByText("Старый сервер",{exact:false})).toHaveCount(0)
|
||||
expect(newReads).toBe(before)
|
||||
})
|
||||
Reference in new issue
Block a user