feat: integrate AMESim media models and editor UI

This commit is contained in:
ljz committed 2026-07-31 23:36:58 +08:00
1 parent 3e4f466114
commit e7177ab03e
181 files changed
+7042 -25270

No files matched your search

+202
View File
@@ -0,0 +1,202 @@
import { expect, test } from "@playwright/test";
import { prepareApp } from "./fixtures";
test.beforeEach(async ({ page }) => {
await prepareApp(page);
});
test("拖入介质定义后可供气动元件选择,删除定义会回退到内置空气", async ({
page,
}) => {
await page.goto("/");
const canvas = page.locator(".flow-canvas .react-flow__pane");
await page
.getByRole("button", { name: /空气介质定义/ })
.dragTo(canvas, { targetPosition: { x: 280, y: 220 } });
const mediumNode = page.locator(
'.flow-canvas .react-flow__node[data-id="amesim_ideal_air_medium_1"]',
);
await expect(mediumNode).toBeVisible();
await mediumNode.click();
await expect(page.getByLabel("介质定义索引(自动分配)")).toHaveValue("1");
const propertyModelSelect = page.getByLabel("物性计算模型");
await expect(propertyModelSelect).toHaveValue("0");
await expect(propertyModelSelect.locator('option[value="0"]')).toHaveText(
"理想气体",
);
await page
.getByRole("button", { name: /AMESim 气动测试元件/ })
.dragTo(canvas, { targetPosition: { x: 650, y: 360 } });
const pneumaticNode = page.locator(
'.flow-canvas .react-flow__node[data-id="amesim_pneumatic_test_1"]',
);
await expect(pneumaticNode).toBeVisible();
await pneumaticNode.click();
const mediumSelect = page.getByLabel("介质物性索引");
await expect(mediumSelect).toHaveValue("0");
await expect(mediumSelect.locator('option[value="0"]')).toHaveText("0");
await expect(mediumSelect.locator('option[value="1"]')).toHaveText("1");
await mediumSelect.selectOption("1");
await expect(mediumSelect).toHaveValue("1");
await mediumNode.click();
await page.getByRole("button", { name: "删除 (Delete)" }).click();
await expect(mediumNode).toHaveCount(0);
await pneumaticNode.click();
await expect(page.getByLabel("介质物性索引")).toHaveValue("0");
const consolePanel = page.getByRole("complementary", {
name: "仿真控制台",
exact: true,
});
await page.getByRole("button", { name: "展开仿真控制台" }).click();
await expect(consolePanel).toContainText(
"介质定义已删除,1 个介质物性引用已切回 0 — 空气(理想气体,内置默认)",
);
await page.getByRole("button", { name: "生成系统 XML" }).click();
const xmlBlock = consolePanel.getByLabel("生成的系统 XML");
await expect(xmlBlock).toContainText('mediumReferenceVersion="1"');
await expect(xmlBlock).toContainText('<Parameter name="gi" value="0"');
});
test("介质定义的物性计算模型会写入 XML", async ({ page }) => {
await page.goto("/");
const canvas = page.locator(".flow-canvas .react-flow__pane");
await page
.getByRole("button", { name: /空气介质定义/ })
.dragTo(canvas, { targetPosition: { x: 280, y: 220 } });
const mediumNode = page.locator(
'.flow-canvas .react-flow__node[data-id="amesim_ideal_air_medium_1"]',
);
await mediumNode.click();
await expect(page.getByLabel("物性计算模型")).toHaveValue("0");
await page.getByRole("button", { name: "生成系统 XML" }).click();
const consolePanel = page.getByRole("complementary", {
name: "仿真控制台",
exact: true,
});
await expect(consolePanel.getByLabel("生成的系统 XML")).toContainText(
'<Parameter name="property_model" value="0"',
);
});
test("氦气介质自动分配 gi,并以 Peng–Robinson 模型写入 XML", async ({
page,
}) => {
await page.goto("/");
const canvas = page.locator(".flow-canvas .react-flow__pane");
await page
.getByRole("button", { name: /空气介质定义/ })
.dragTo(canvas, { targetPosition: { x: 240, y: 180 } });
await page
.getByRole("button", { name: /氦气介质定义/ })
.dragTo(canvas, { targetPosition: { x: 520, y: 180 } });
const heliumNode = page.locator(
'.flow-canvas .react-flow__node[data-id="amesim_helium_medium_1"]',
);
await expect(heliumNode).toBeVisible();
await heliumNode.click();
await expect(page.getByLabel("介质定义索引(自动分配)")).toHaveValue("2");
const propertyModelSelect = page.getByLabel("物性计算模型");
await expect(propertyModelSelect).toHaveValue("0");
await expect(propertyModelSelect.locator('option[value="0"]')).toHaveText(
"Peng–Robinson",
);
await page
.getByRole("button", { name: /AMESim 气动测试元件/ })
.dragTo(canvas, { targetPosition: { x: 760, y: 360 } });
const pneumaticNode = page.locator(
'.flow-canvas .react-flow__node[data-id="amesim_pneumatic_test_1"]',
);
await expect(pneumaticNode).toBeVisible();
await pneumaticNode.click();
const mediumSelect = page.getByLabel("介质物性索引");
await expect(mediumSelect.locator("option")).toHaveText(["0", "1", "2"]);
await mediumSelect.selectOption("2");
await expect(mediumSelect).toHaveValue("2");
await page.getByRole("button", { name: "生成系统 XML" }).click();
const consolePanel = page.getByRole("complementary", {
name: "仿真控制台",
exact: true,
});
const xmlBlock = consolePanel.getByLabel("生成的系统 XML");
await expect(xmlBlock).toContainText('type="amesim_helium_medium"');
await expect(xmlBlock).toContainText('<Parameter name="gi" value="2"');
await expect(xmlBlock).toContainText(
'<Parameter name="property_model" value="0"',
);
const xml = await xmlBlock.textContent();
expect(xml).toMatch(
/<Component[^>]+type="amesim_helium_medium"[\s\S]*?<Parameter name="gi" value="2"[\s\S]*?<Parameter name="property_model" value="0"[\s\S]*?<\/Component>/,
);
expect(xml).toMatch(
/<Component[^>]+type="amesim_pneumatic_test"[\s\S]*?<Parameter name="gi" value="2"[\s\S]*?<\/Component>/,
);
});
test("导入工程中的未知物性计算模型会被检查出来", async ({ page }) => {
await page.goto("/");
const project = {
name: "invalid-property-model",
mediumReferenceVersion: 1,
nodes: [
{
id: "amesim_ideal_air_medium_1",
type: "simulationComponent",
position: { x: 280, y: 220 },
data: {
label: "空气介质_1",
componentType: "amesim_ideal_air_medium",
modelType: "amesim_ideal_air_medium",
ports: [],
parameters: { gi: 1, property_model: 99 },
parameterUnits: {},
rotation: 0,
mirrored: false,
},
},
],
edges: [],
simulation: {
t_start: 0,
t_stop: 1,
step: 0.1,
max_step: 0.05,
method: "RK45",
},
};
await page.locator('input[type="file"]').setInputFiles({
name: "invalid-property-model.json",
mimeType: "application/json",
buffer: Buffer.from(JSON.stringify(project)),
});
await page.getByRole("button", { name: "检查模型" }).click();
const consolePanel = page.getByRole("complementary", {
name: "仿真控制台",
exact: true,
});
await expect(consolePanel).toContainText(
"空气介质_1:物性计算模型不在支持的可选项中",
);
});