134 lines
5.8 KiB
TypeScript
134 lines
5.8 KiB
TypeScript
import { test, expect } from "./e2e-fixtures";
|
|
import { parse } from "yaml";
|
|
|
|
test("custom YAML nodes use compact forms, persist edits and integrate with subscription groups", async ({
|
|
page,
|
|
}) => {
|
|
const errors: string[] = [];
|
|
page.on("pageerror", (e) => errors.push(e.message));
|
|
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: "节点管理" }).click();
|
|
const create = page
|
|
.locator(".compact-create-panel details")
|
|
.filter({ has: page.getByRole("heading", { name: "新增自定义订阅节点" }) });
|
|
await create.locator(":scope > summary").click();
|
|
await create.getByLabel("Slug", { exact: true }).fill("custom-browser");
|
|
await create.getByLabel("显示名", { exact: true }).fill("香港自定义节点");
|
|
await create.getByRole("textbox", { name: "节点 YAML", exact: true }).fill("name: [invalid");
|
|
await create.getByRole("button", { name: "创建自定义节点" }).click();
|
|
await expect(create.getByRole("alert")).toContainText("YAML 格式错误");
|
|
await expect(create.getByRole("textbox", { name: "节点 YAML", exact: true })).toHaveValue(
|
|
"name: [invalid",
|
|
);
|
|
const source =
|
|
'# keep this comment\nproxies:\n - name: \'HK "AnyTLS": #1\'\n type: anytls\n server: hk.example.com\n port: 443\n password: "test-only:password"\n udp: true\n';
|
|
await create.getByRole("textbox", { name: "节点 YAML", exact: true }).fill(source);
|
|
await create.getByRole("button", { name: "创建自定义节点" }).click();
|
|
const row = page
|
|
.locator(".entity-table__item")
|
|
.filter({ hasText: "custom-browser" });
|
|
await expect(row).toBeVisible();
|
|
await expect(row).toContainText("不轮询");
|
|
await row.locator(":scope > summary").click();
|
|
await expect(row.getByRole("textbox", { name: "节点 YAML", exact: true })).toHaveValue(
|
|
source,
|
|
);
|
|
await expect(row.getByLabel("客户端地址", { exact: true })).toHaveCount(0);
|
|
const updated = source.replace('HK "AnyTLS": #1', 'HK "AnyTLS": #2');
|
|
await row.getByRole("textbox", { name: "节点 YAML", exact: true }).fill(updated);
|
|
await row.getByRole("button", { name: "保存自定义节点" }).click();
|
|
await expect(row.locator("p[role=status]")).toHaveText("已保存");
|
|
await page.reload();
|
|
await row.locator(":scope > summary").click();
|
|
await expect(
|
|
row.getByRole("textbox", { name: "节点 YAML", exact: true }),
|
|
).toHaveValue(updated);
|
|
await page.screenshot({
|
|
path: "test-results/custom-node-desktop.png",
|
|
fullPage: true,
|
|
});
|
|
const config = await page.request.get(
|
|
"/api/admin/nodes/custom-browser/config",
|
|
);
|
|
expect(config.status()).toBe(409);
|
|
const auth = await page.request.post("/api/hy2/nodes/custom-browser/auth", {
|
|
data: { auth: "test:test" },
|
|
});
|
|
expect(await auth.json()).toMatchObject({ ok: false });
|
|
|
|
await page.getByRole("link", { name: "订阅配置" }).click();
|
|
const main = page.locator(".proxy-group-card").first();
|
|
await expect(main.locator(".proxy-sort-item")).toContainText(
|
|
'HK "AnyTLS": #2',
|
|
);
|
|
const createGroup = page
|
|
.locator("details")
|
|
.filter({ has: page.locator("summary", { hasText: "新建分组" }) });
|
|
await createGroup.locator(":scope > summary").click();
|
|
await createGroup.getByLabel("新建分组名").fill("Custom Work");
|
|
await createGroup.getByRole("button", { name: /HK.*添加/ }).click();
|
|
await createGroup
|
|
.getByRole("button", { name: "新建分组", exact: true })
|
|
.click();
|
|
await expect(
|
|
page.locator("summary strong", { hasText: "Custom Work" }),
|
|
).toBeVisible();
|
|
const url = await page.locator(".copy-line code").first().textContent();
|
|
const response = await page.request.get(url!);
|
|
expect(response.status()).toBe(200);
|
|
const subscription = parse(await response.text());
|
|
const proxy = subscription.proxies.find(
|
|
(p: { type: string }) => p.type === "anytls",
|
|
);
|
|
expect(proxy).toMatchObject({
|
|
name: 'HK "AnyTLS": #2',
|
|
server: "hk.example.com",
|
|
password: "test-only:password",
|
|
udp: true,
|
|
});
|
|
expect(
|
|
subscription["proxy-groups"].find(
|
|
(g: { name: string }) => g.name === "Custom Work",
|
|
).proxies,
|
|
).toEqual([proxy.name]);
|
|
const group = page
|
|
.locator("details")
|
|
.filter({
|
|
has: page.locator("summary strong", { hasText: "Custom Work" }),
|
|
});
|
|
await group.locator(":scope > summary").click();
|
|
await group.getByRole("button", { name: "删除分组" }).click();
|
|
await page.getByRole("button", { name: "确认删除分组" }).click();
|
|
await expect(group).toHaveCount(0);
|
|
|
|
await page.getByRole("link", { name: "节点管理" }).click();
|
|
await page.getByRole("searchbox").fill("custom");
|
|
await expect(page.locator(".entity-table__item:visible")).toHaveCount(1);
|
|
await row.locator(":scope > summary").click();
|
|
await page.setViewportSize({ width: 390, height: 844 });
|
|
await expect
|
|
.poll(() =>
|
|
page.evaluate(() => document.documentElement.scrollWidth <= innerWidth),
|
|
)
|
|
.toBe(true);
|
|
await page.screenshot({
|
|
path: "test-results/custom-node-mobile.png",
|
|
fullPage: true,
|
|
});
|
|
await row.getByLabel("启用节点", { exact: true }).uncheck();
|
|
await row.getByRole("button", { name: "保存自定义节点" }).click();
|
|
await expect(row.locator("p[role=status]")).toHaveText("已保存");
|
|
const disabled = parse(await (await page.request.get(url!)).text());
|
|
expect(
|
|
disabled.proxies.some((p: { type: string }) => p.type === "anytls"),
|
|
).toBe(false);
|
|
await row.getByRole("button", { name: "删除节点" }).click();
|
|
await page.getByRole("button", { name: "确认删除节点" }).click();
|
|
await expect(row).toHaveCount(0);
|
|
expect(errors).toEqual([]);
|
|
});
|