import {test,expect,type Page} from "@playwright/test" import {emptyAlerts,emptyOutbox} from "./fixtures/alerts" import type {AlertTargetIssue} from "@mmapp/contracts/alerts" async function setup(page:Page,reply:()=>unknown){ await page.route("**/health",r=>r.fulfill({json:{status:"ok"}})) await page.route("**/api/**",r=>{const path=new URL(r.request().url()).pathname if(path==="/api/auth/config")return r.fulfill({json:{required:false}}) if(path==="/api/alerts")return r.fulfill({json:reply()}) if(path==="/api/alerts/outbox")return r.fulfill({json:emptyOutbox}) if(path==="/api/servers"||path==="/api/bgp/sessions")return r.fulfill({json:[]}) if(path==="/api/filters/gre-tunnels")return r.fulfill({json:{tunnels:[]}}) return r.fulfill({status:503,json:{error:"outside diagnostic fixture"}}) }) await page.goto("/alerts") } for(const width of[1440,320])test(`Alerts targets: ambiguity is explained and grouped at ${width}`,async({page})=>{ await page.setViewportSize({width,height:1000}) const issues:AlertTargetIssue[]=[{kind:"server",target:"CHR",reason:"ambiguous"},{kind:"traffic",target:"CHR",reason:"ambiguous"}] let current=issues await setup(page,()=>({...emptyAlerts,meta:{...emptyAlerts.meta,targetIssues:current}})) const warning=page.getByRole("status",{name:"Проблемы целей оповещений"}) await expect(warning).toBeVisible();await expect(warning.getByText("CHR",{exact:true})).toHaveCount(1) await expect(warning).toContainText("Несколько включённых объектов") await expect(warning).toContainText("обновите цели существующих правил") await expect(warning.getByRole("link",{name:"Проверить серверы"})).toHaveAttribute("href","/servers") expect(await page.evaluate(()=>document.documentElement.scrollWidth<=innerWidth)).toBe(true) current=[];await page.getByRole("button",{name:"Обновить",exact:true}).click();await expect(warning).toHaveCount(0) }) test("Alerts targets: disabled source and probe explain the next action",async({page})=>{ await setup(page,()=>({...emptyAlerts,meta:{...emptyAlerts.meta,targetIssues:[{kind:"traffic",target:"router",reason:"disabled-source"},{kind:"probe",target:"probe → target",reason:"disabled-object"}]}})) const warning=page.getByRole("status",{name:"Проблемы целей оповещений"}) await expect(warning).toContainText("Сбор данных этого типа выключен") await expect(warning).toContainText("Объект или его сервер выключен") await expect(warning.getByRole("link",{name:"Проверить сбор данных"})).toHaveAttribute("href","/data-collection") await expect(warning.getByRole("link",{name:"Проверить пробы"})).toHaveAttribute("href","/uptime") }) test("Alerts targets: older valid API does not invent diagnostics",async({page})=>{ await setup(page,()=>emptyAlerts) await expect(page.getByText("Всего: 0",{exact:true})).toBeVisible() await expect(page.getByRole("status",{name:"Проблемы целей оповещений"})).toHaveCount(0) }) test("Alerts targets: many long labels remain compact and keyboard accessible on phone",async({page})=>{ await page.setViewportSize({width:320,height:1000}) const targets=Array.from({length:6},(_,index)=>`target-${index}-${"x".repeat(180)}`) await setup(page,()=>({...emptyAlerts,meta:{...emptyAlerts.meta,targetIssues:targets.map(target=>({kind:"server",target,reason:"ambiguous"}))}})) const warning=page.getByRole("status",{name:"Проблемы целей оповещений"}) await expect(warning.getByText(targets[0],{exact:true})).toBeHidden() const summary=warning.locator("summary");await summary.focus();await page.keyboard.press("Enter") await expect(warning.getByText(targets[0],{exact:true})).toBeVisible() expect(await page.evaluate(()=>document.documentElement.scrollWidth<=innerWidth)).toBe(true) await page.keyboard.press("Enter");await expect(warning.getByText(targets[0],{exact:true})).toBeHidden() })