import { test, expect } from "./e2e-fixtures"; import { certificateFixture } from "./certificate-fixture"; import { readFileSync } from "node:fs"; import { parse } from "yaml"; test("upload wildcard certificate, download script and complete NAT node registration", async ({ page, request, }) => { const errors: string[] = []; page.on("pageerror", (e) => errors.push(e.message)); const fixture = certificateFixture(); await page.goto("/login"); await page.getByLabel("用户名", { exact: true }).fill("ui-review"); await page.getByLabel("密码", { exact: true }).fill("ui-review-local-2026"); await page.getByRole("button", { name: "登录", exact: true }).click(); await expect(page).toHaveURL(/dashboard/); await page.getByRole("link", { name: "证书与安装", exact: true }).click(); const upload = page.locator("details").filter({ has: page.getByRole("heading", { name: "上传证书", exact: true }), }); await upload.getByLabel("证书名称").fill("测试通配符证书"); await upload.getByLabel("CRT / 完整证书链").setInputFiles({ name: "test.crt", mimeType: "text/plain", buffer: Buffer.from(fixture.certificate), }); await upload.getByLabel("KEY / 私钥").setInputFiles({ name: "test.key", mimeType: "text/plain", buffer: Buffer.from("invalid"), }); await upload.getByRole("button", { name: "上传证书", exact: true }).click(); await expect(upload.getByRole("alert")).toContainText("无法解析"); await upload.getByLabel("KEY / 私钥").setInputFiles({ name: "test.key", mimeType: "text/plain", buffer: Buffer.from(fixture.privateKey), }); await upload.getByRole("button", { name: "上传证书", exact: true }).click(); await expect( page.getByText("测试通配符证书", { exact: true }).first(), ).toBeVisible(); await page.reload(); const create = page.locator("details").filter({ has: page.getByRole("heading", { name: "生成服务器安装脚本", exact: true, }), }); if ((await create.getAttribute("open")) === null) await create.locator("summary").click(); await create.getByLabel("节点名称", { exact: true }).fill("NAT 浏览器测试"); await create.getByLabel("节点 Slug", { exact: true }).fill("nat-browser"); await create .getByLabel("托管证书", { exact: true }) .selectOption({ label: "测试通配符证书" }); await create .getByRole("button", { name: "生成安装脚本", exact: true }) .click(); const row = page.locator(".provision-row").filter({ hasText: "nat-browser" }); await expect(row).toContainText("等待安装"); const downloadPath = await row .getByRole("link", { name: "下载 SH" }) .getAttribute("href"); expect((await request.get(downloadPath!, { maxRedirects: 0 })).status()).toBe( 307, ); const [download] = await Promise.all([ page.waitForEvent("download"), row.getByRole("link", { name: "下载 SH" }).click(), ]); const script = readFileSync((await download.path())!, "utf8"); expect(script).not.toContain("PRIVATE KEY"); expect(script).toContain("--domain"); const token = script.match(/^TOKEN='([a-f0-9]+)'$/m)![1]; const ports = { domain: "nat.p.xn--876a.net", hy2Port: 23456, statsPort: 23457, hy2ListenPort: 443, statsListenPort: 9999, }; expect( ( await request.post("/api/install", { data: { action: "prepare", ports } }) ).status(), ).toBe(400); expect( (await request.post("/api/install", { data: "x".repeat(5000) })).status(), ).toBe(413); const prepare = await request.post("/api/install", { headers: { Authorization: `Bearer ${token}` }, data: { action: "prepare", ports }, }); expect(prepare.status()).toBe(200); expect(prepare.headers()["cache-control"]).toBe("no-store"); const bundle = await prepare.json(); expect(bundle.privateKey).toBe(fixture.privateKey); const config = parse(bundle.config); expect(config.listen).toBe(":443"); expect(config.trafficStats.listen).toBe(":9999"); expect( ( await request.post("/api/install", { headers: { Authorization: `Bearer ${token}` }, data: { action: "complete" }, }) ).status(), ).toBe(200); await page.reload(); await expect(row).toContainText("已安装"); await expect(row.getByRole("link", { name: "下载 SH" })).toHaveCount(0); expect( ( await request.post("/api/install", { headers: { Authorization: `Bearer ${token}` }, data: { action: "prepare", ports }, }) ).status(), ).toBe(400); await page.screenshot({ path: "test-results/certificates-desktop.png", fullPage: true, }); await page.setViewportSize({ width: 390, height: 844 }); await page.screenshot({ path: "test-results/certificates-mobile.png", fullPage: true, }); expect( await page.evaluate( () => document.documentElement.scrollWidth <= innerWidth + 1, ), ).toBe(true); await page.getByRole("link", { name: "节点管理", exact: true }).click(); const node = page .locator(".entity-table__item") .filter({ hasText: "nat-browser" }); await expect(node).toContainText("nat.p.xn--876a.net"); await node.locator(":scope > summary").click(); await expect(node.getByLabel("对外端口", { exact: true })).toHaveValue( "23456", ); await expect(node.getByLabel("SNI", { exact: true })).toHaveValue( "nat.p.xn--876a.net", ); await expect(node.getByLabel("启用节点", { exact: true })).toBeChecked(); expect(errors).toEqual([]); });