Files

15 lines
7.5 KiB
TypeScript

import {test,expect,type Page} from "@playwright/test"
import {evoSettings as initial,evoCatalog} from "./fixtures/evobgp"
const section=(p:Page)=>p.getByRole("region",{name:"Настройки EvoBGP",exact:true})
const base=(p:Page)=>p.getByRole("textbox",{name:"Базовый URL API",exact:true})
const key=(p:Page)=>p.getByLabel("API-ключ EvoBGP",{exact:true})
async function setup(page:Page){let settings={...initial};await page.route("**/health",r=>r.fulfill({json:{ok:true}}));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/evobgp/settings"){if(r.request().method()==="PUT"){const patch=r.request().postDataJSON();settings={baseUrl:patch.baseUrl??settings.baseUrl,enabled:patch.enabled??settings.enabled,secretConfigured:patch.apiKey!==undefined?!!patch.apiKey:settings.secretConfigured};return r.fulfill({json:{...settings,ok:true,savedFields:Object.keys(patch)}})}return r.fulfill({json:settings})}return r.fulfill(path==="/api/evobgp/catalog"?{json:evoCatalog}:path==="/api/evobgp/test"?{json:{ok:true}}:{status:503,json:{error:"outside fixture"}})});await page.goto("/settings");await page.getByRole("button",{name:"EvoBGP",exact:true}).click();await expect(base(page)).toHaveValue(initial.baseUrl)}
test("Evolution form: selective URL patch, canonical receipt and no duplicate success",async({page})=>{await setup(page);const patches:unknown[]=[];page.on("request",r=>{if(r.method()==="PUT")patches.push(r.postDataJSON())});await expect(section(page).getByRole("button",{name:"Сохранить",exact:true})).toBeDisabled();await base(page).fill(" new.evo.test/ ");await section(page).getByRole("button",{name:"Сохранить",exact:true}).click();await expect(base(page)).toHaveValue("https://new.evo.test");await expect(page.getByText("Настройки EvoBGP сохранены",{exact:true})).toHaveCount(1);await expect(section(page).getByRole("button",{name:"Сохранить",exact:true})).toBeDisabled();expect(patches).toEqual([{baseUrl:"https://new.evo.test"}])})
test("Evolution form: refresh preserves dirty URL, toggle and replacement key",async({page})=>{await setup(page);await base(page).fill("https://draft.evo.test");await key(page).fill("draft-secret");await page.getByRole("switch",{name:"Использовать каталог EvoBGP"}).click();await page.getByRole("button",{name:"Обновить настройки EvoBGP"}).click();await expect(page.getByText("Обновление настроек EvoBGP…",{exact:true})).toHaveCount(0);await expect(base(page)).toHaveValue("https://draft.evo.test");await expect(key(page)).toHaveValue("draft-secret");await expect(page.getByRole("switch",{name:"Использовать каталог EvoBGP"})).not.toBeChecked();await page.getByRole("button",{name:"Сохранить",exact:true}).click();await expect(page.getByText("Настройки EvoBGP сохранены",{exact:true})).toBeVisible();await expect(key(page)).toHaveValue("")})
test("Evolution form: invalid URL never writes and test never saves",async({page})=>{await setup(page);let writes=0;page.on("request",r=>{if(r.method()==="PUT")writes++});await base(page).fill("https://evo.test/v1");await page.getByRole("button",{name:"Сохранить",exact:true}).click();await expect(section(page).getByText(/Укажите HTTP\(S\) URL/)).toBeVisible();expect(writes).toBe(0);await base(page).fill("https://draft.evo.test");await page.getByRole("button",{name:"Проверить ключ",exact:true}).click();await expect(page.getByText("Соединение с EvoBGP установлено",{exact:true})).toBeVisible();expect(writes).toBe(0);await expect(page.getByRole("button",{name:"Сохранить",exact:true})).toBeEnabled()})
test("Evolution form: unknown save preserves drafts without retry",async({page})=>{await setup(page);let writes=0;await page.route("**/api/evobgp/settings",r=>{if(r.request().method()!=="PUT")return r.fallback();writes++;return r.fulfill({status:503,json:{error:"save unknown"}})});await key(page).fill("replacement");await page.getByRole("button",{name:"Сохранить",exact:true}).click();await expect(section(page).getByText(/save unknown.*Черновик сохранён/)).toBeVisible();await expect(key(page)).toHaveValue("replacement");await expect(page.getByText("Настройки EvoBGP сохранены",{exact:true})).toHaveCount(0);expect(writes).toBe(1)})
test("Evolution form: key clear requires confirmation and preserves other drafts",async({page})=>{await setup(page);const patches:unknown[]=[];page.on("request",r=>{if(r.method()==="PUT")patches.push(r.postDataJSON())});await base(page).fill("https://draft.evo.test");await key(page).fill("future-key");await page.getByRole("button",{name:"Удалить сохранённый ключ",exact:true}).click();expect(patches).toEqual([]);await page.getByRole("alertdialog").getByRole("button",{name:"Удалить ключ",exact:true}).click();await expect(page.getByRole("alertdialog")).toHaveCount(0);await expect(page.getByText("Удаление сохранённого ключа подтверждено",{exact:true})).toBeVisible();await expect(base(page)).toHaveValue("https://draft.evo.test");await expect(key(page)).toHaveValue("future-key");expect(patches).toEqual([{apiKey:null}]);await page.getByRole("button",{name:"Сохранить",exact:true}).click();await expect(page.getByText("Настройки EvoBGP сохранены",{exact:true})).toBeVisible();expect(patches[1]).toEqual({baseUrl:"https://draft.evo.test",apiKey:"future-key"})})
test("Evolution form: malformed clear retains confirmation and typed key",async({page})=>{await setup(page);await page.route("**/api/evobgp/settings",r=>r.request().method()==="PUT"?r.fulfill({json:{}}):r.fallback());await key(page).fill("future-key");await page.getByRole("button",{name:"Удалить сохранённый ключ",exact:true}).click();await page.getByRole("alertdialog").getByRole("button",{name:"Удалить ключ",exact:true}).click();await expect(page.getByRole("alertdialog").getByRole("alert")).toContainText("Подтверждения удаления нет");await page.getByRole("alertdialog").getByRole("button",{name:"Отмена",exact:true}).click();await expect(key(page)).toHaveValue("future-key");await expect(page.getByText("Ключ: сохранён",{exact:true})).toBeVisible()})
test("Evolution form: repeated save and other actions are locked during PUT",async({page})=>{await setup(page);let started=false,writes=0,release!:()=>void;const gate=new Promise<void>(r=>release=r);await page.route("**/api/evobgp/settings",async r=>{if(r.request().method()!=="PUT")return r.fallback();started=true;writes++;await gate;try{await r.fulfill({json:{...initial,baseUrl:"https://draft.evo.test",ok:true,savedFields:["baseUrl"]}})}catch{}});try{await base(page).fill("https://draft.evo.test");await page.getByRole("button",{name:"Сохранить",exact:true}).dblclick();await expect.poll(()=>started).toBe(true);await expect(page.getByRole("button",{name:"Сохранение…",exact:true})).toBeDisabled();await expect(page.getByRole("button",{name:"Проверить ключ",exact:true})).toBeDisabled();await expect(page.getByRole("button",{name:"Удалить сохранённый ключ",exact:true})).toBeDisabled();await expect(base(page)).toBeDisabled();expect(writes).toBe(1);release();await expect(page.getByText("Настройки EvoBGP сохранены",{exact:true})).toBeVisible()}finally{release()}})