import {test,expect} from "@playwright/test" import {container,server,state} from "./fixtures/containers" for(const [name,width] of [["desktop",1440],["mobile",390],["narrow",320]] as const)test("Контейнеры: клавиатура и адаптивность "+name,async({page})=>{ await page.setViewportSize({width,height:900}) const long={...container,name:"container-with-a-very-long-name-for-narrow-screens",image:"registry.example.test/project/long-container-image",comment:"Длинный комментарий для проверки переноса текста в карточке"} 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/auth/config"?{required:false}:new URL(r.request().url()).pathname==="/api/servers"?[{...server,name:"Очень длинное имя сервера контейнеров"}]:state([long])})) await page.goto("/containers");await expect(page.getByText(long.name,{exact:true})).toBeVisible();expect(await page.evaluate(()=>document.documentElement.scrollWidth<=window.innerWidth+1)).toBe(true) const search=page.getByRole("textbox",{name:"Поиск контейнеров"});await search.fill("нет-совпадений");await expect(page.getByText("Измените фильтр или поиск",{exact:true})).toBeVisible();await search.fill("") const stopped=page.getByRole("group",{name:"Статус контейнеров"}).getByRole("button",{name:"Остановлен",exact:true});await stopped.focus();await page.keyboard.press("Enter");await expect(stopped).toHaveAttribute("aria-pressed","true");const all=page.getByRole("group",{name:"Статус контейнеров"}).getByRole("button",{name:"Все",exact:true});await all.click();await expect(all).toHaveAttribute("aria-pressed","true") await page.screenshot({path:"docs/ux-ui/screens/containers-overview-"+name+".png",fullPage:true}) const menu=page.getByRole("button",{name:"Действия контейнера "+long.name});await menu.focus();await page.keyboard.press("Enter");await page.getByRole("menuitem",{name:"Снимок JSON",exact:true}).click();const dialog=page.getByRole("dialog");await expect(dialog).toContainText("конфигурация устройства и резервная копия");await expect.poll(async()=>{const bounds=await dialog.boundingBox();return !!bounds&&bounds.x>=0&&bounds.x+bounds.width<=width+1&&(width>=640||bounds.width>=width-2)}).toBe(true);expect(await dialog.evaluate(el=>el.scrollWidth<=el.clientWidth+1)).toBe(true) const download=page.waitForEvent("download");await dialog.getByRole("button",{name:"Файл",exact:true}).click();const file=await download;expect(file.suggestedFilename()).toMatch(/\.json$/);const stream=await file.createReadStream();const chunks:Buffer[]=[];for await(const chunk of stream!)chunks.push(Buffer.from(chunk));const json=JSON.parse(Buffer.concat(chunks).toString("utf8"));expect(json.container.name).toBe(long.name);expect(json.collectedAt).toBe("2026-10-01T00:00:00Z");expect(json.source).toBe("live");expect(JSON.stringify(json)).not.toContain("172.17.0.2") await page.screenshot({path:"docs/ux-ui/screens/containers-export-"+name+".png",fullPage:true});await dialog.getByRole("button",{name:"Закрыть",exact:true}).first().click();await expect(dialog).toHaveCount(0) }) test("Контейнеры: неизвестный статус не предлагает запуск",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/auth/config"?{required:false}:new URL(r.request().url()).pathname==="/api/servers"?[server]:state([{...container,status:"unknown"}])}));await page.goto("/containers");await page.getByRole("button",{name:"Действия контейнера "+container.name}).click();await expect(page.getByRole("menuitem",{name:"Запустить",exact:true})).toBeDisabled();await expect(page.getByRole("menuitem",{name:"Перезапустить",exact:true})).toBeDisabled() })