Files
MikrotikManager/tests/e2e/system-database-context.spec.ts

28 lines
6.1 KiB
TypeScript

import {test,expect,type Page} from "@playwright/test"
const headers={"access-control-allow-origin":"*","access-control-allow-methods":"GET,POST,OPTIONS","access-control-allow-headers":"Content-Type,Authorization","access-control-expose-headers":"Content-Disposition,X-System-Database-Outcome"}
async function setup(page:Page){await page.route("**/health",r=>r.fulfill({headers,json:{status:"ok"}}));await page.route("**/api/**",r=>{const path=new URL(r.request().url()).pathname;return r.fulfill(path==="/api/auth/config"?{headers,json:{required:false}}:{headers,status:503,json:{error:"outside source fixture"}})});await page.goto("/settings");await expect(page.getByRole("button",{name:"Выбрать файл",exact:true})).toBeEnabled()}
async function source(page:Page,value:string){const input=page.getByRole("textbox",{name:"URL бекенда",exact:true});await input.fill(value);await input.press("Enter");await expect(input).toHaveValue(value);await expect(page.getByText("Доступен",{exact:true})).toBeVisible()}
for(const failed of [false,true])test("System DB source: ABA discards old backup outcome/"+failed,async({page})=>{
await setup(page);let started=false,completed=false,release!:()=>void,downloads=0;const gate=new Promise<void>(resolve=>release=resolve);page.on("download",()=>downloads++)
await page.route("http://localhost:8000/api/system/database/backup",async r=>{started=true;await gate;try{await r.fulfill(failed?{headers,status:503,json:{error:"OLD BACKUP FAILED"}}:{headers,body:Buffer.from("PGDMPfixture"),contentType:"application/octet-stream"})}catch{}finally{completed=true}})
try{await page.getByRole("region",{name:"Операции базы приложения"}).getByRole("button",{name:"Скачать",exact:true}).click();await expect.poll(()=>started).toBe(true);await source(page,"http://localhost:8101");await source(page,"http://localhost:8000");await expect(page.getByRole("button",{name:"Выбрать файл",exact:true})).toBeEnabled();release();await expect.poll(()=>completed).toBe(true);await expect(page.getByText("Бэкап базы приложения подготовлен к скачиванию",{exact:true})).toHaveCount(0);await expect(page.getByText("OLD BACKUP FAILED",{exact:true})).toHaveCount(0);expect(downloads).toBe(0)}finally{release()}
})
test("System DB source: unknown restore checkpoint belongs to its backend and survives ABA",async({page})=>{
await setup(page);let calls=0;await page.route("**/api/system/database/restore",r=>{calls++;return r.fulfill({headers,json:{ok:false}})})
await page.getByRole("button",{name:"Выбрать файл",exact:true}).click();await page.getByRole("dialog").locator('input[type="file"]').setInputFiles({name:"fixture.dump",mimeType:"application/octet-stream",buffer:Buffer.from("PGDMPfixture")});await page.getByRole("button",{name:"Продолжить",exact:true}).click();await page.getByRole("button",{name:"Восстановить",exact:true}).click();await expect(page.getByRole("button",{name:"Восстановить",exact:true})).toBeDisabled();await expect(page.getByRole("alert")).toContainText("не подтверждено");await page.getByRole("button",{name:"Отмена",exact:true}).click()
await source(page,"http://localhost:8101");await expect(page.getByRole("button",{name:"Выбрать файл",exact:true})).toBeEnabled();await source(page,"http://localhost:8000");await expect(page.getByRole("button",{name:"Выбрать файл",exact:true})).toBeDisabled();await expect(page.getByText(/Запрос мог выполниться на сервере/)).toBeVisible();expect(calls).toBe(1)
})
test("System DB source: switching to demo aborts pending backup publication",async({page})=>{
await setup(page);let started=false,completed=false,release!:()=>void;const gate=new Promise<void>(resolve=>release=resolve)
await page.route("**/api/system/database/backup",async r=>{started=true;await gate;try{await r.fulfill({headers,body:Buffer.from("PGDMPfixture"),contentType:"application/octet-stream"})}catch{}finally{completed=true}})
try{await page.getByRole("region",{name:"Операции базы приложения"}).getByRole("button",{name:"Скачать",exact:true}).click();await expect.poll(()=>started).toBe(true);await page.getByRole("button",{name:"Моковые",exact:true}).click();await expect(page.getByRole("button",{name:"Выбрать файл",exact:true})).toBeDisabled();release();await expect.poll(()=>completed).toBe(true);await expect(page.getByText("Бэкап базы приложения подготовлен к скачиванию",{exact:true})).toHaveCount(0)}finally{release()}
})
for(const failed of [false,true])test("System DB source: reload during restore retains checkpoint and ignores late receipt/"+failed,async({page})=>{
await setup(page);let started=false,completed=false,calls=0,release!:()=>void;const gate=new Promise<void>(resolve=>release=resolve)
await page.route("**/api/system/database/restore",async r=>{calls++;started=true;await gate;try{await r.fulfill(failed?{headers,status:503,json:{error:"OLD RESTORE FAILED"}}:{headers,json:{ok:true}})}catch{}finally{completed=true}})
try{
await page.getByRole("button",{name:"Выбрать файл",exact:true}).click();await page.getByRole("dialog").locator('input[type="file"]').setInputFiles({name:"fixture.dump",mimeType:"application/octet-stream",buffer:Buffer.from("PGDMPfixture")});await page.getByRole("button",{name:"Продолжить",exact:true}).click();await page.getByRole("button",{name:"Восстановить",exact:true}).click();await expect.poll(()=>started).toBe(true);await page.reload();await expect(page.getByRole("button",{name:"Выбрать файл",exact:true})).toBeDisabled();release();await expect.poll(()=>completed).toBe(true);await expect(page.getByText("База приложения восстановлена",{exact:true})).toHaveCount(0);await expect(page.getByText("OLD RESTORE FAILED",{exact:true})).toHaveCount(0);await expect(page.getByText(/Запрос мог выполниться на сервере/)).toBeVisible();expect(calls).toBe(1)
}finally{release()}
})