fix(ui): различать результат и отмену диагностики

This commit is contained in:
Denozordec committed 2026-10-01 04:07:08 +07:00
1 parent 8bda85129f
commit 6fa8e5bfd1
9 files changed
+132 -20

No files matched your search

+15
View File
@@ -0,0 +1,15 @@
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"}
for(const change of ["backend","mode"])for(const fails of [false,true])test("Диагностика: поздний запрос/"+change+"/"+fails,async({page})=>{
let started=false,completed=false,release!:()=>void;const gate=new Promise<void>(r=>release=r)
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;return r.fulfill({headers,json:p==="/api/auth/config"?{required:false}:p==="/api/servers"?[{id:1,name:u.port==="8101"?"Новый источник":"Прежний источник",host:"192.0.2.1",country:"RU",enabled:true,status:"online"}]:p.endsWith("/ros-src-address")?{ipv4:"192.0.2.1"}:p.endsWith("/probes/run")?{output:"НОВЫЙ РЕЗУЛЬТАТ"}:{tunnels:[]}})})
await page.goto("/probes");await expect(page.getByRole("button",{name:"Запустить",exact:true})).toBeEnabled()
await page.route("**/api/servers/1/probes/run",async r=>{if(new URL(r.request().url()).port!=="8000")return r.fallback();started=true;await gate;try{await r.fulfill(fails?{headers,status:503,json:{error:"СТАРАЯ ОШИБКА"}}:{headers,json:{output:"СТАРЫЙ РЕЗУЛЬТАТ"}})}catch{}finally{completed=true}})
await page.getByRole("button",{name:"Запустить",exact:true}).click();await expect.poll(()=>started).toBe(true);await page.getByRole("link",{name:/^Настройки/}).click()
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.goto("/probes");await expect(page.getByRole("button",{name:"Запустить",exact:true})).toBeEnabled();release();await expect.poll(()=>completed).toBe(true)
await page.getByRole("button",{name:"Запустить",exact:true}).click()
if(change==="backend")await expect(page.getByText("НОВЫЙ РЕЗУЛЬТАТ",{exact:true})).toBeVisible()
await expect(page.getByText("СТАРЫЙ РЕЗУЛЬТАТ",{exact:true})).toHaveCount(0);await expect(page.getByText("СТАРАЯ ОШИБКА",{exact:true})).toHaveCount(0)
})
+35
View File
@@ -0,0 +1,35 @@
import { test, expect, type Page } from "@playwright/test"
const devices=[{id:1,name:"Первый",host:"192.0.2.1",site:"Тест",country:"RU",asn:"AS64500",type:"vps",enabled:true,status:"online",latency:null}]
async function routes(page:Page){
await page.route("**/health",r=>r.fulfill({json:{ok:true}}))
await page.route("**/api/**",r=>{const p=new URL(r.request().url()).pathname;return r.fulfill({json:p==="/api/servers"?devices:p==="/api/auth/config"?{required:false}:p.endsWith("/ros-src-address")?{ipv4:"192.0.2.1"}:{tunnels:[]}})})
}
test.beforeEach(async({page})=>routes(page))
const run=(page:Page)=>page.getByRole("button",{name:"Запустить",exact:true})
for(const [name,data,status] of [["malformed",{},200],["legacy",{output:" error: RouterOS недоступен"},200],["API",{error:"Нет доступа к диагностике"},403]] as const)test("Диагностика: "+name+" сохраняет цель и допускает повтор",async({page})=>{
let fail=true;await page.route("**/api/servers/1/probes/run",r=>r.fulfill(fail?{json:data,status}:{json:{output:"PING подтверждён"}}))
await page.goto("/probes");await expect(run(page)).toBeEnabled();const target=page.getByRole("textbox",{name:"Цель диагностики"});await target.fill("198.51.100.9");await run(page).click()
await expect(page.getByText("ошибка",{exact:true})).toBeVisible();await expect(target).toHaveValue("198.51.100.9");await expect(run(page)).toBeEnabled()
fail=false;await run(page).click();await expect(page.getByText("PING подтверждён",{exact:true})).toBeVisible()
})
test("Диагностика: пустой output явно подтверждён",async({page})=>{
await page.route("**/api/servers/1/probes/run",r=>r.fulfill({json:{output:""}}));await page.goto("/probes");await run(page).click();await expect(page.getByText("Запрос выполнен: API вернул пустой вывод.",{exact:true})).toBeVisible()
})
test("Диагностика: повторный Enter, Стоп и поздний успех",async({page})=>{
let calls=0,release!:()=>void;const gate=new Promise<void>(r=>release=r)
await page.route("**/api/servers/1/probes/run",async r=>{calls++;await gate;await r.fulfill({json:{output:"ЗАПОЗДАЛЫЙ УСПЕХ"}}).catch(()=>{})})
await page.goto("/probes");const target=page.getByRole("textbox",{name:"Цель диагностики"});await target.press("Enter");await target.press("Enter");await expect.poll(()=>calls).toBe(1);await expect(run(page)).toBeDisabled()
await page.getByRole("button",{name:"Стоп",exact:true}).click();await expect(page.getByText("ожидание отменено",{exact:true})).toBeVisible();await expect(run(page)).toBeEnabled();release();await expect(page.getByText("ЗАПОЗДАЛЫЙ УСПЕХ",{exact:true})).toHaveCount(0)
await expect(page.getByText("Ожидание отменено. Остановка на устройстве не подтверждена.",{exact:true})).toBeVisible()
})
test("Диагностика: таймаут сохраняет ввод, без автоматического повтора",async({page})=>{
await page.clock.install();let calls=0,release!:()=>void;const gate=new Promise<void>(r=>release=r)
await page.route("**/api/servers/1/probes/run",async r=>{calls++;await gate;await r.fulfill({json:{output:"ПОЗДНО"}}).catch(()=>{})})
await page.goto("/probes");await run(page).click();await expect.poll(()=>calls).toBe(1);await page.clock.fastForward(60_100)
await expect(page.getByText(/Время ожидания истекло/)).toBeVisible();await expect(run(page)).toBeEnabled();await expect(page.getByRole("textbox",{name:"Цель диагностики"})).toHaveValue("8.8.8.8");expect(calls).toBe(1);release()
})
test("Диагностика: уход со страницы не переносит поздний вывод",async({page})=>{
let first=true,release!:()=>void;const gate=new Promise<void>(r=>release=r)
await page.route("**/api/servers/1/probes/run",async r=>{if(first){first=false;await gate;await r.fulfill({json:{output:"СТАРЫЙ ВЫВОД"}}).catch(()=>{})}else await r.fulfill({json:{output:"НОВЫЙ ВЫВОД"}})})
await page.goto("/probes");await run(page).click();await expect(run(page)).toBeDisabled();await page.goto("/terminal");release();await page.goto("/probes");await run(page).click();await expect(page.getByText("НОВЫЙ ВЫВОД",{exact:true})).toBeVisible();await expect(page.getByText("СТАРЫЙ ВЫВОД",{exact:true})).toHaveCount(0)
})