现有组件功能与Amesim组件比较对齐,补全功能;仿真服务启动环境检测,旧版json工程文件适配读取
This commit is contained in:
1 parent
b6c22a54f8
commit
6fc9afe41d
119 files changed
+260114
-351
No files matched your search
@@ -0,0 +1,127 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { expandSimulationConsole, prepareApp } from "./fixtures";
|
||||
|
||||
const report = {
|
||||
checkId: "backend-start-1", status: "running", stage: "compiling",
|
||||
message: "正在编译最小自检程序", durationMs: 100,
|
||||
compiler: "gcc", compilerVersion: "gcc test", sundialsRoot: "/native/sundials",
|
||||
error: null, failure: null,
|
||||
};
|
||||
|
||||
test("self-check progress does not block editing and completion is logged once", async ({ page }) => {
|
||||
await prepareApp(page);
|
||||
let completed = false;
|
||||
let requests = 0;
|
||||
await page.route("**/api/simulation/runtime-check", route => {
|
||||
requests++;
|
||||
return route.fulfill({ json: completed ? { ...report, status: "completed", stage: "complete",
|
||||
message: "仿真环境自检通过:最小程序预处理、编译、链接和运行均成功", durationMs: 1250 } : report });
|
||||
});
|
||||
await page.goto("/");
|
||||
await expandSimulationConsole(page);
|
||||
const panel = page.getByRole("complementary", { name: "仿真控制台", exact: true });
|
||||
await expect(panel).toContainText("正在检测仿真环境");
|
||||
const name = page.getByRole("textbox", { name: "工程", exact: true });
|
||||
await name.fill("检测期间仍可编辑");
|
||||
await expect(name).toHaveValue("检测期间仍可编辑");
|
||||
await expect.poll(() => requests).toBeGreaterThanOrEqual(3);
|
||||
await expect(panel.locator(".simulation-console-dock-entry-message").filter({ hasText: "正在检测仿真环境" })).toHaveCount(1);
|
||||
completed = true;
|
||||
await expect(panel).toContainText("仿真环境自检通过");
|
||||
await expect(panel).toContainText("1.25 秒");
|
||||
await page.evaluate(() => window.dispatchEvent(new Event("focus")));
|
||||
await expect(panel.locator(".simulation-console-dock-entry-message").filter({ hasText: "仿真环境自检通过" })).toHaveCount(1);
|
||||
});
|
||||
|
||||
test("link failure shows diagnostics and a backend restart reports recovery", async ({ page }) => {
|
||||
await prepareApp(page);
|
||||
let recovered = false;
|
||||
await page.route("**/api/simulation/runtime-check", route => route.fulfill({ json: recovered
|
||||
? { ...report, checkId: "backend-start-2", status: "completed", stage: "complete", message: "仿真环境自检通过" }
|
||||
: { ...report, status: "failed", stage: "linking", message: "仿真环境自检失败,编辑器仍可使用",
|
||||
error: "命令执行失败", failure: { command: ["gcc", "check.o", "-o", "model"], cwd: "/native/check",
|
||||
exitCode: 7, stderr: "cannot find library", stdout: "", errorType: "CalledProcessError" } } }));
|
||||
await page.goto("/");
|
||||
await expandSimulationConsole(page);
|
||||
const panel = page.getByRole("complementary", { name: "仿真控制台", exact: true });
|
||||
await expect(panel).toContainText("失败阶段:链接");
|
||||
await expect(panel).toContainText("退出码:7");
|
||||
await expect(panel).toContainText("cannot find library");
|
||||
await expect(panel).toContainText('"gcc" "check.o" "-o" "model"');
|
||||
await page.getByRole("textbox", { name: "工程", exact: true }).fill("失败后仍可编辑");
|
||||
recovered = true;
|
||||
await page.evaluate(() => window.dispatchEvent(new Event("focus")));
|
||||
await expect(panel).toContainText("仿真环境自检通过");
|
||||
});
|
||||
|
||||
test("backend unavailable at page load is retried without duplicate warnings", async ({ page }) => {
|
||||
await prepareApp(page);
|
||||
let available = false;
|
||||
await page.route("**/api/simulation/runtime-check", route => available
|
||||
? route.fulfill({ json: { ...report, status: "completed", message: "仿真环境自检通过" } })
|
||||
: route.fulfill({ status: 503 }));
|
||||
await page.goto("/");
|
||||
await expandSimulationConsole(page);
|
||||
const panel = page.getByRole("complementary", { name: "仿真控制台", exact: true });
|
||||
await expect(panel).toContainText("暂时无法获取仿真环境自检状态");
|
||||
available = true;
|
||||
await expect(panel).toContainText("仿真环境自检通过");
|
||||
});
|
||||
|
||||
for (const finalStatus of ["completed", "failed"] as const) {
|
||||
test(`automatic retries suppress diagnostics until ${finalStatus}`, async ({ page }) => {
|
||||
await prepareApp(page);
|
||||
let attempt = 1;
|
||||
let finished = false;
|
||||
const failure = { command: ["gcc", "check.c"], cwd: "/native/check", exitCode: 1,
|
||||
stderr: "CreateProcess: No such file or directory", stdout: "", errorType: "CalledProcessError" };
|
||||
await page.route("**/api/simulation/runtime-check", route => route.fulfill({ json: finished
|
||||
? { ...report, status: finalStatus, attempt: 6, stage: finalStatus === "failed" ? "preprocessing" : "complete",
|
||||
message: finalStatus === "failed" ? "本次启动自检未通过:首次检测及 5 轮重试均失败;编辑器仍可使用"
|
||||
: "本次启动自检通过,仿真环境可用(第 5 轮重试成功)",
|
||||
error: finalStatus === "failed" ? "命令执行失败" : null, failure: finalStatus === "failed" ? failure : null }
|
||||
: { ...report, status: "retrying", attempt, stage: "retry-wait", error: null, failure: null,
|
||||
message: `本轮检测未通过,正在准备第 ${attempt}/5 轮重试(间隔 0.5 秒);编辑器可正常使用` } }));
|
||||
await page.goto("/");
|
||||
await expandSimulationConsole(page);
|
||||
const panel = page.getByRole("complementary", { name: "仿真控制台", exact: true });
|
||||
await expect(panel).toContainText("第 1/5 轮重试");
|
||||
await expect(panel).not.toContainText("退出码");
|
||||
await expect(panel).not.toContainText("CreateProcess");
|
||||
await page.getByRole("textbox", { name: "工程", exact: true }).fill("重试时继续编辑");
|
||||
attempt = 2;
|
||||
await expect(panel).toContainText("第 2/5 轮重试");
|
||||
await expect(panel).not.toContainText("错误类型");
|
||||
finished = true;
|
||||
if (finalStatus === "completed") {
|
||||
await expect(panel).toContainText("仿真环境可用(第 5 轮重试成功)");
|
||||
await expect(panel).not.toContainText("CreateProcess");
|
||||
await expect(panel.locator(".simulation-console-dock-entry.error")).toHaveCount(0);
|
||||
} else {
|
||||
await expect(panel).toContainText("首次检测及 5 轮重试均失败");
|
||||
await expect(panel).toContainText("退出码:1");
|
||||
await expect(panel).toContainText("CreateProcess: No such file or directory");
|
||||
await expect(panel.locator(".simulation-console-dock-entry.error")).toHaveCount(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
test("finished startup report stops timed polling and is refreshed on focus", async ({ page }) => {
|
||||
await prepareApp(page);
|
||||
await page.clock.install();
|
||||
let requests = 0;
|
||||
await page.route("**/api/simulation/runtime-check", route => {
|
||||
requests++;
|
||||
return route.fulfill({ json: { ...report, status: "completed", stage: "complete",
|
||||
message: "本次启动自检通过,仿真环境可用" } });
|
||||
});
|
||||
await page.goto("/");
|
||||
await expandSimulationConsole(page);
|
||||
const panel = page.getByRole("complementary", { name: "仿真控制台", exact: true });
|
||||
await expect(panel).toContainText("本次启动自检通过");
|
||||
const completedRequests = requests;
|
||||
await page.clock.runFor(31000);
|
||||
expect(requests).toBe(completedRequests);
|
||||
await page.evaluate(() => window.dispatchEvent(new Event("focus")));
|
||||
await expect.poll(() => requests).toBe(completedRequests + 1);
|
||||
});
|
||||
Reference in new issue
Block a user