1 parent
7362f22f98
commit
216354cef1
1 file changed
+79
@@ -15,6 +15,58 @@ import {
|
||||
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(
|
||||
page,
|
||||
{ maintenance = true, content = "help", message = maintenanceMessage } = {},
|
||||
@@ -28,6 +80,8 @@ async function layoutBoundary(
|
||||
);
|
||||
const reply = (data) =>
|
||||
route.fulfill({ json: { status: 200, msg: "", data } });
|
||||
if (content === "network" && Object.hasOwn(networkResponses, path))
|
||||
return reply(networkResponses[path]);
|
||||
if (path === "/common") {
|
||||
const response = await route.fetch();
|
||||
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