1 parent
7362f22f98
commit
216354cef1
1 file changed
+79
@@ -15,6 +15,58 @@ import {
|
|||||||
const maintenanceMessage =
|
const maintenanceMessage =
|
||||||
"系统正在升级维护,部分业务暂时不可用,请稍后再试。如有紧急问题请联系客服,我们正在尽快恢复服务。";
|
"系统正在升级维护,部分业务暂时不可用,请稍后再试。如有紧急问题请联系客服,我们正在尽快恢复服务。";
|
||||||
|
|
||||||
|
// 真实 KKY 实例在“网络与安全”中同时提供安全组和白名单入口,不绕过组件权限/加载条件。
|
||||||
|
const networkResponses = {
|
||||||
|
"/host/5": {
|
||||||
|
host: {
|
||||||
|
id: 5,
|
||||||
|
product_id: 123,
|
||||||
|
module: "kky_ecs",
|
||||||
|
name: "本地弹性云",
|
||||||
|
status: "Active",
|
||||||
|
billing_cycle: "monthly",
|
||||||
|
upgrade_allowed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"/kky_ecs/5": {
|
||||||
|
cpu: 2,
|
||||||
|
memory: 4,
|
||||||
|
bandwidth: 10,
|
||||||
|
protect: 0,
|
||||||
|
bill_method: 1,
|
||||||
|
ip: "192.0.2.5",
|
||||||
|
ips: ["192.0.2.5"],
|
||||||
|
intranet_ip: "10.0.0.5",
|
||||||
|
username: "root",
|
||||||
|
port: 22,
|
||||||
|
image: { name: "Ubuntu 24.04" },
|
||||||
|
security_group_id: 1,
|
||||||
|
security_group_name: "本地安全组",
|
||||||
|
},
|
||||||
|
"/kky_ecs/5/status": { status: "on", rescue: false },
|
||||||
|
"/kky_ecs/disk/5": { list: [] },
|
||||||
|
"/kky_ecs/monitor/5": {
|
||||||
|
sample_info: [],
|
||||||
|
cpu: [],
|
||||||
|
memory: [],
|
||||||
|
bandwidth: [],
|
||||||
|
disk: [],
|
||||||
|
},
|
||||||
|
"/kky_ecs/5/traffic": {
|
||||||
|
billing: { mode: "bandwidth", monthly_quota: 0, unit_price: "0.00" },
|
||||||
|
usage_status: "available",
|
||||||
|
quota_status: "not_applicable",
|
||||||
|
},
|
||||||
|
"/domain_whitelist/form": {
|
||||||
|
fields: [
|
||||||
|
{ name: "domains", title: "域名", type: "textarea", required: true },
|
||||||
|
],
|
||||||
|
ips: ["192.0.2.5"],
|
||||||
|
need_review: true,
|
||||||
|
},
|
||||||
|
"/domain_whitelist/record": { list: [], count: 0 },
|
||||||
|
};
|
||||||
|
|
||||||
async function layoutBoundary(
|
async function layoutBoundary(
|
||||||
page,
|
page,
|
||||||
{ maintenance = true, content = "help", message = maintenanceMessage } = {},
|
{ maintenance = true, content = "help", message = maintenanceMessage } = {},
|
||||||
@@ -28,6 +80,8 @@ async function layoutBoundary(
|
|||||||
);
|
);
|
||||||
const reply = (data) =>
|
const reply = (data) =>
|
||||||
route.fulfill({ json: { status: 200, msg: "", data } });
|
route.fulfill({ json: { status: 200, msg: "", data } });
|
||||||
|
if (content === "network" && Object.hasOwn(networkResponses, path))
|
||||||
|
return reply(networkResponses[path]);
|
||||||
if (path === "/common") {
|
if (path === "/common") {
|
||||||
const response = await route.fetch();
|
const response = await route.fetch();
|
||||||
const body = await response.json();
|
const body = await response.json();
|
||||||
@@ -400,3 +454,28 @@ for (const [path, name] of [
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test(
|
||||||
|
"instance network navigation has one keyboard stop per action",
|
||||||
|
{ timeout: 30000 },
|
||||||
|
(t) =>
|
||||||
|
scenario(t, {}, async (page) => {
|
||||||
|
await layoutBoundary(page, { maintenance: false, content: "network" });
|
||||||
|
await login(page, "/servers/server?id=5");
|
||||||
|
await page.getByRole("tab", { name: "网络与安全", exact: true }).click();
|
||||||
|
for (const name of ["前往安全组管理", "前往域名白名单"]) {
|
||||||
|
const link = page.getByRole("link", { name, exact: true });
|
||||||
|
await link.waitFor();
|
||||||
|
await link.focus();
|
||||||
|
await page.keyboard.press("Tab");
|
||||||
|
assert.equal(
|
||||||
|
await link.evaluate((element) =>
|
||||||
|
element.contains(document.activeElement),
|
||||||
|
),
|
||||||
|
false,
|
||||||
|
"Tab must leave each network navigation action after its first stop",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return { navigationActions: 2, singleKeyboardStop: true };
|
||||||
|
}),
|
||||||
|
);
|
||||||
Reference in new issue
Block a user