Files
MikrotikManager/tests/e2e/admin-tables.spec.ts
T

95 lines
5.9 KiB
TypeScript

import { test, expect, type Page } from "@playwright/test"
import { appUserReadSchema } from "../../packages/contracts/src/users"
import { certificatesStateSchema } from "../../packages/contracts/src/certificates"
import { certificateState, server } from "./fixtures/certificates"
import type { BackupItem } from "../../shared/api/backups"
const ids = Array.from({ length: 12 }, (_, i) => i + 1)
const users = ids.map(i => appUserReadSchema.parse({
id: String(i), name: `Пользователь ${i}`, login: `user-${i}`, email: `user${i}@example.test`,
role: "viewer", active: true, avatar: "U", lastSeen: null, sections: [], servers: [], bindings: [],
createdAt: "2026-09-14T00:00:00Z", updatedAt: "2026-09-14T00:00:00Z",
}))
const certificates = certificatesStateSchema.parse(certificateState(ids.map(i => ({
id: `1:*${i}`, rosId: `*${i}`, name: `cert-${i}`, serverId: "1", commonName: `host${i}.example.test`,
sans: [`alt${i}.example.test`], issuedBy: "Test CA", validFrom: "2026-09-01T00:00:00Z", validUntil: "2027-09-01T00:00:00Z",
rawValidFrom: "2026-09-01", rawValidUntil: "2027-09-01",
daysLeft: 300 + i, keySize: 2048, usage: ["server"], trusted: true, status: "valid",
}))))
const backups: BackupItem[] = ids.map(i => ({ id: String(i), serverId: 1, serverName: "Тестовый роутер",
filename: `backup-${i}.backup`, sizeBytes: i === 12 ? 1048576 : i * 1024, createdAt: "2026-09-14T00:00:00Z", kind: i > 6 ? "auto" : "manual", storage: "local" }))
async function setup(page: Page, url: string) {
await page.route("**/health", route => route.fulfill({ json: { ok: true } }))
await page.route("**/api/**", route => {
const path = new URL(route.request().url()).pathname
return route.fulfill({ json: path === "/api/users" ? { users }
: path === "/api/certificates/state" ? certificates : path === "/api/backups" ? backups
: path === "/api/certificates/acme-settings" ? { directoryUrl: "https://acme.example.test/directory", defaultZoneId: "", tokenConfigured: false }
: path === "/api/certificates/renew-settings" ? { enabled: false, intervalSec: 3600, renewBeforeDays: 30 }
: path === "/api/backups/schedule" ? { enabled: false, frequency: "daily", hour: 3, minute: 0, weekDay: 0, monthDay: 1, keepCount: 7, format: "backup", serverIds: [] }
: path === "/api/backups/storage" ? { provider: "local", s3Endpoint: "", s3Region: "", s3Bucket: "", s3Prefix: "", s3AccessKeyId: "", secretConfigured: false, s3ForcePathStyle: false, keepLocalCopy: true }
: path === "/api/auth/config" ? { required: false } : path === "/api/servers" ? [server] : {} })
})
await page.goto(url)
}
test("Пользователи: 12 строк, сортировка и раскрытие", async ({ page }) => {
await setup(page, "/users")
const rows = page.locator("tr[data-row-id]")
await expect(rows).toHaveCount(12)
await page.getByRole("table").getByRole("button", { name: "Пользователь", exact: true }).click()
await expect(rows.first()).toContainText("Пользователь 1")
await page.getByRole("table").getByRole("button", { name: "Пользователь", exact: true }).click()
await expect(rows.first()).toContainText("Пользователь 12")
await rows.first().click()
await expect(page.getByText("Разделы:", { exact: false }).last()).toBeVisible()
await rows.first().click()
await expect(rows).toHaveCount(12)
})
test("Сертификаты: 12 строк, сортировка и SAN в деталях", async ({ page }) => {
await setup(page, "/certificates")
const rows = page.locator("tr[data-row-id]")
await expect(rows).toHaveCount(12)
await page.getByRole("button", { name: "Сертификат", exact: true }).click()
await page.getByRole("button", { name: "Сертификат", exact: true }).click()
await expect(rows.first()).toContainText("cert-12")
await rows.first().click()
await expect(page.getByText("alt12.example.test", { exact: true })).toBeVisible()
await rows.first().click()
await expect(page.getByText("alt12.example.test", { exact: true })).toBeHidden()
})
test("Бэкапы: 12 строк, числовая сортировка и выбранный файл в подтверждении", async ({ page }) => {
await setup(page, "/backups")
const rows = page.locator("tr[data-row-id]")
await expect(rows).toHaveCount(12)
await page.getByRole("button", { name: "Размер", exact: true }).click()
await expect(rows.first()).toContainText("backup-12.backup")
await rows.first().getByRole("button", { name: "Удалить backup-12.backup", exact: true }).click()
await expect(page.getByRole("alertdialog")).toContainText("backup-12.backup")
await page.getByRole("button", { name: "Отмена", exact: true }).click()
await expect(rows).toHaveCount(12)
})
test("Бэкапы FilterQuery: тип, изменение значения и сброс", async ({ page }) => {
await setup(page, "/backups")
const rows = page.locator("tr[data-row-id]")
await expect(rows).toHaveCount(12)
await page.getByRole("button", { name: "Фильтры", exact: true }).click()
await page.getByRole("option", { name: "Тип", exact: true }).click()
await page.getByRole("option", { name: "равно", exact: true }).click()
await page.getByRole("option", { name: "авто", exact: true }).click()
await expect(rows).toHaveCount(6)
await expect(page.locator('tr[data-row-id="12"]')).toBeVisible()
await expect(page.locator('tr[data-row-id="1"]')).toHaveCount(0)
await page.getByRole("button", { name: "авто", exact: true }).click()
await page.getByRole("option", { name: "вручную", exact: true }).click()
await expect(rows).toHaveCount(6)
await expect(page.locator('tr[data-row-id="1"]')).toBeVisible()
await expect(page.locator('tr[data-row-id="12"]')).toHaveCount(0)
await page.getByRole("button", { name: "Очистить", exact: true }).click()
await expect(rows).toHaveCount(12)
})