fix(ui): проверять источник IPv4 для диагностики

This commit is contained in:
Denozordec committed 2026-10-01 08:36:31 +07:00
1 parent d0c715e93c
commit b60b7ac8e8
8 files changed
+81 -26

No files matched your search

+1 -1
View File
@@ -3,7 +3,7 @@ const headers={"access-control-allow-origin":"*","access-control-allow-methods":
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",type:"exit-node",country:"RU",enabled:true,status:"online"}]:p.endsWith("/ros-src-address")?{ipv4:"192.0.2.1"}:p.endsWith("/probes/run")?{output:"НОВЫЙ РЕЗУЛЬТАТ"}:{tunnels:[]}})})
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",type:"exit-node",country:"RU",enabled:true,status:"online"}]:p.endsWith("/ros-src-address")?{host:"192.0.2.1",ipv4:"192.0.2.1"}:p.endsWith("/probes/run")?{output:"НОВЫЙ РЕЗУЛЬТАТ"}:{tunnels:[]}})})
await page.goto("/probes?server=1");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()
+2 -2
View File
@@ -2,7 +2,7 @@ import { test, expect, type Page } from "@playwright/test"
const devices=[{id:1,name:"Первый",host:"192.0.2.1",site:"Тест",country:"RU",asn:"AS64500",type:"exit-node",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:[]}})})
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")?{host:"192.0.2.1",ipv4:"192.0.2.1"}:{tunnels:[]}})})
}
test.beforeEach(async({page})=>routes(page))
const run=(page:Page)=>page.getByRole("button",{name:"Запустить",exact:true})
@@ -94,7 +94,7 @@ test("Диагностика: DNS приложения, inline ошибка и
})
test("Диагностика: без выбора не запрашивает устройство",async({page})=>{
let requests=0;await page.route("**/api/servers/*/**",r=>{requests++;return r.fulfill({json:{ipv4:"192.0.2.1"}})})
let requests=0;await page.route("**/api/servers/*/**",r=>{requests++;return r.fulfill({json:{host:"192.0.2.1",ipv4:"192.0.2.1"}})})
await page.goto("/probes");await expect(page.getByRole("status").filter({hasText:"Выберите устройство для диагностики"})).toBeVisible();await expect(run(page)).toBeDisabled();expect(requests).toBe(0)
})
for(const query of ["server=1&server=2","server=bad%20id","server="])test("Диагностика: неверная ссылка не читает API "+query,async({page})=>{
+22
View File
@@ -0,0 +1,22 @@
import {test,expect} from "@playwright/test"
const devices=[{id:1,name:"Первый",host:"first.test",enabled:true,status:null,type:"exit-node"},{id:2,name:"Второй",host:"second.test",enabled:true,status:"online",type:"exit-node"}]
test.beforeEach(async({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/servers"?devices:new URL(r.request().url()).pathname==="/api/auth/config"?{required:false}:{tunnels:[]}}))})
for(const kind of ["API","bad-ip","wrong-host"])test("Источник preview: "+kind+" и повтор",async({page})=>{
let fail=true;await page.route("**/api/servers/1/ros-src-address",r=>r.fulfill(fail?(kind==="API"?{status:503,json:{error:"IPv4 отказ"}}:{json:{host:kind==="wrong-host"?"other.test":"first.test",ipv4:kind==="bad-ip"?"999.0.0.1":"192.0.2.1"}}):{json:{host:"first.test",ipv4:"192.0.2.1"}}))
await page.goto("/probes?server=1");await expect(page.getByRole("alert",{name:"Источник preview"})).toBeVisible();await expect(page.getByRole("button",{name:"Запустить",exact:true})).toBeEnabled()
fail=false;await page.getByRole("button",{name:"Повторить определение IPv4"}).click();await expect(page.getByRole("status").filter({hasText:"IPv4 для preview: 192.0.2.1"})).toBeVisible();await expect(page.getByRole("alert",{name:"Источник preview"})).toHaveCount(0)
})
test("Источник preview: null не является ошибкой или IP",async({page})=>{
await page.route("**/api/servers/1/ros-src-address",r=>r.fulfill({json:{host:"first.test",ipv4:null}}));await page.goto("/probes?server=1");await expect(page.getByRole("status").filter({hasText:"IPv4 для preview не определён"})).toBeVisible();await expect(page.getByRole("alert",{name:"Источник preview"})).toHaveCount(0);await expect(page.getByText(/src-address=\?/)).toBeVisible()
})
for(const fails of [false,true])test("Источник preview: поздний адрес прежнего устройства "+fails,async({page})=>{
let started=false,completed=false,release!:()=>void;const gate=new Promise<void>(r=>release=r)
await page.route("**/api/servers/1/ros-src-address",async r=>{started=true;await gate;try{await r.fulfill(fails?{status:503,json:{error:"СТАРАЯ ОШИБКА"}}:{json:{host:"first.test",ipv4:"192.0.2.1"}})}catch{}finally{completed=true}})
await page.route("**/api/servers/2/ros-src-address",r=>r.fulfill({json:{host:"second.test",ipv4:"192.0.2.2"}}))
await page.goto("/probes?server=1");await expect.poll(()=>started).toBe(true);await page.getByRole("option",{name:/Второй/}).click();await expect(page.getByRole("status").filter({hasText:"IPv4 для preview: 192.0.2.2"})).toBeVisible();release();await expect.poll(()=>completed).toBe(true)
await expect(page.getByText(/src-address=192.0.2.2/)).toBeVisible();await expect(page.getByText(/192.0.2.1|СТАРАЯ ОШИБКА/)).toHaveCount(0)
})
test("Источник preview: DNS не запрашивает RouterOS источник",async({page})=>{
let reads=0;await page.route("**/api/servers/*/ros-src-address",r=>{reads++;return r.fulfill({json:{host:"first.test",ipv4:null}})})
await page.goto("/probes");await page.getByRole("button",{name:"DNS",exact:true}).click();await page.getByRole("option",{name:/Первый/}).click();await expect(page.getByRole("textbox",{name:"Домен"})).toBeVisible();expect(reads).toBe(0)
})