import { expect, test } from "@playwright/test"; type SymbolCase = { category: string; domain: "medium" | "pneumatic" | "signal" | "mechanical"; modelType: string; }; const symbolCases: SymbolCase[] = [ { category: "media", domain: "medium", modelType: "amesim_ideal_air_medium" }, { category: "media", domain: "medium", modelType: "amesim_helium_medium" }, { category: "storage", domain: "pneumatic", modelType: "amesim_pnch023" }, { category: "storage", domain: "pneumatic", modelType: "amesim_pnch012" }, { category: "flow", domain: "pneumatic", modelType: "amesim_pnor001" }, { category: "flow", domain: "pneumatic", modelType: "amesim_pnvo001_fixed" }, { category: "flow", domain: "pneumatic", modelType: "amesim_pnvo001" }, { category: "flow", domain: "pneumatic", modelType: "amesim_pnl00r" }, { category: "flow", domain: "pneumatic", modelType: "amesim_pnl0001" }, { category: "flow", domain: "pneumatic", modelType: "amesim_pnl0002" }, { category: "flow", domain: "pneumatic", modelType: "amesim_pnl0003" }, { category: "junctions", domain: "pneumatic", modelType: "amesim_pn3node2" }, { category: "junctions", domain: "pneumatic", modelType: "amesim_p4node2" }, { category: "boundary", domain: "pneumatic", modelType: "amesim_pnpl01" }, { category: "signals", domain: "signal", modelType: "amesim_step0" }, { category: "signals", domain: "signal", modelType: "amesim_ud00" }, { category: "mechanical", domain: "mechanical", modelType: "amesim_f000" }, { category: "mechanical", domain: "mechanical", modelType: "amesim_forc" }, { category: "mechanical", domain: "mechanical", modelType: "amesim_mecmas21" }, { category: "mechanical", domain: "mechanical", modelType: "amesim_lstp00a" }, { category: "mechanical", domain: "mechanical", modelType: "amesim_lmechn1" }, ]; const categoryLabels: Record = { boundary: "边界元件", flow: "流动元件", junctions: "连接元件", mechanical: "机械元件", media: "介质物性", signals: "信号元件", storage: "储能元件", }; test.beforeEach(async ({ page }) => { await page.addInitScript(() => { const preparedKey = "system-simulation-flow:component-symbols-prepared"; if (window.sessionStorage.getItem(preparedKey) !== "1") { window.localStorage.clear(); window.sessionStorage.clear(); window.sessionStorage.setItem(preparedKey, "1"); } window.location.hash = "#/modeling"; }); await page.route("**/api/components/catalog", async (route) => { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ schemaVersion: 1, libraries: [ { id: "amesim", label: "AMESim 组件库", version: "0.2.0", sourcePackage: "tests.e2e.amesim-symbols", temporary: true, order: 1, components: symbolCases.map((item, index) => ({ type: item.modelType, label: item.modelType, modelType: item.modelType, modelVersion: "0.1.0", symbol: item.modelType, order: index + 1, category: { id: item.category, label: categoryLabels[item.category], order: Object.keys(categoryLabels).indexOf(item.category) + 1, }, ports: [], parameters: [], })), }, ], }), }); }); }); test("全部已移植 AMESim 模型使用专属图标及正确领域配色", async ({ page }) => { await page.goto("/"); const palette = page.locator("aside.palette"); await expect(palette.locator('[data-component-symbol^="amesim_"]')).toHaveCount( symbolCases.length, ); await expect(palette.locator('[data-component-symbol="generic"]')).toHaveCount(0); for (const item of symbolCases) { const symbol = palette.locator(`[data-component-symbol="${item.modelType}"]`); await expect(symbol).toHaveCount(1); await expect(symbol.locator("svg")).toHaveAttribute("data-symbol-domain", item.domain); await expect(symbol).toHaveAttribute( "data-symbol-presentation", item.domain === "medium" ? "bare" : "framed", ); } }); test("旧工程保存的通用图标会按当前目录定义升级", async ({ page }) => { await page.goto("/"); await page.evaluate(() => { window.localStorage.setItem( "system-simulation-flow:autosave", JSON.stringify({ name: "legacy-symbol-project", nodes: [ { id: "amesim_pnl0001_1", type: "simulationComponent", position: { x: 200, y: 160 }, data: { label: "amesim_pnl0001_1", componentType: "amesim_pnl0001", modelType: "amesim_pnl0001", symbol: "pipe", ports: [], parameters: {}, parameterUnits: {}, rotation: 0, mirrored: false, }, }, ], edges: [], simulation: { t_start: 0, t_stop: 1, step: 0.1, max_step: 0.05, method: "BDF", }, }), ); }); await page.reload(); await page.getByRole("button", { name: "恢复", exact: true }).click(); const restoredNode = page.locator( '.flow-canvas .react-flow__node[data-id="amesim_pnl0001_1"]', ); await expect(restoredNode).toBeVisible(); await expect( restoredNode.locator('[data-component-symbol="amesim_pnl0001"]'), ).toBeVisible(); await expect(restoredNode.locator('[data-component-symbol="pipe"]')).toHaveCount(0); });