Files
ytplayer/tests/admin-backups.spec.js
2026-10-14 02:06:33 +08:00

26 lines
1.8 KiB
JavaScript

const { test, expect } = require('@playwright/test');
test('backups lists integrity, previews diff, creates a snapshot and confirms restore', async ({ page }) => {
const calls = [];
await page.route('**/api/**', async route => {
const request = route.request(), url = new URL(request.url()); calls.push({ path: url.pathname, method: request.method() });
let body = { ok: true };
if (url.pathname === '/api/admin/me') body = { ok: true, enabled: true, admin: true };
if (url.pathname === '/api/admin/backups' && request.method() === 'GET') body = { ok: true, backups: [{ date: '2026-10-14', bytes: 1024, notes: 12, valid: true }] };
if (url.pathname === '/api/admin/backups/2026-10-14') body = { ok: true, diff: { changed: 2, added: 1, removed: 0, preview: [{ key: 'song:lyrics', change: 'changed' }] } };
if (url.pathname === '/api/admin/backups' && request.method() === 'POST') body = { ok: true, date: '2026-10-14', notes: 12 };
if (url.pathname.endsWith('/restore')) body = { ok: true, restored: 12, safetySnapshot: '/data/backups/snapshots/safety.json' };
await route.fulfill({ contentType: 'application/json', body: JSON.stringify(body) });
});
page.on('dialog', dialog => dialog.accept());
await page.goto('/admin.html#backups');
await expect(page.locator('#backupTable')).toContainText('Verified');
await expect(page.locator('#backupDiff')).toContainText('2 changed');
await expect(page.locator('a[href="/api/admin/backups/export/sqlite-dump"]')).toBeVisible();
await page.locator('#backupNow').click();
await expect(page.locator('#backupStatus')).toContainText('Saved 12 notes');
await page.locator('#backupRestore').click();
await expect.poll(() => calls.some(call => call.path.endsWith('/restore') && call.method === 'POST')).toBe(true);
await expect(page.locator('#backupStatus')).toContainText('Safety snapshot');
});