feat: integrate AMESim media models and editor UI
This commit is contained in:
1 parent
3e4f466114
commit
e7177ab03e
181 files changed
+7042
-25270
No files matched your search
@@ -0,0 +1,273 @@
|
||||
import { expect, test, type Locator } from "@playwright/test";
|
||||
import { prepareApp } from "./fixtures";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await prepareApp(page);
|
||||
await page.addInitScript(() => {
|
||||
window.localStorage.removeItem(
|
||||
"system-simulation-flow:palette-collapsed-sections",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
async function expectFixedIconCardSize(
|
||||
item: Locator,
|
||||
) {
|
||||
const itemBox = await item.boundingBox();
|
||||
const iconBox = await item.locator(".palette-icon").boundingBox();
|
||||
|
||||
expect(itemBox).not.toBeNull();
|
||||
expect(iconBox).not.toBeNull();
|
||||
expect(itemBox!.width).toBeGreaterThanOrEqual(75);
|
||||
expect(itemBox!.width).toBeLessThanOrEqual(77);
|
||||
expect(itemBox!.height).toBeGreaterThanOrEqual(81);
|
||||
expect(itemBox!.height).toBeLessThanOrEqual(83);
|
||||
expect(iconBox!.width).toBeGreaterThanOrEqual(47);
|
||||
expect(iconBox!.width).toBeLessThanOrEqual(49);
|
||||
expect(iconBox!.height).toBeGreaterThanOrEqual(47);
|
||||
expect(iconBox!.height).toBeLessThanOrEqual(49);
|
||||
}
|
||||
|
||||
test("组件库可切换详细与仅图标显示,并在刷新后保留选择", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
|
||||
const palette = page.locator("aside.palette");
|
||||
const detailedButton = page.getByRole("button", {
|
||||
name: "详细显示",
|
||||
exact: true,
|
||||
});
|
||||
const iconsButton = page.getByRole("button", {
|
||||
name: "仅图标显示",
|
||||
exact: true,
|
||||
});
|
||||
const airItem = palette.getByRole("button", {
|
||||
name: "空气介质定义",
|
||||
exact: true,
|
||||
});
|
||||
const heliumItem = palette.getByRole("button", {
|
||||
name: "氦气介质定义",
|
||||
exact: true,
|
||||
});
|
||||
|
||||
await expect(palette).toHaveAttribute("data-view-mode", "detailed");
|
||||
await expect(detailedButton).toHaveAttribute("aria-pressed", "true");
|
||||
await expect(iconsButton).toHaveAttribute("aria-pressed", "false");
|
||||
await expect(airItem.locator(".palette-item-copy")).toBeVisible();
|
||||
|
||||
const airSymbol = airItem.locator(
|
||||
'[data-component-symbol="amesim_ideal_air_medium"]',
|
||||
);
|
||||
const heliumSymbol = heliumItem.locator(
|
||||
'[data-component-symbol="amesim_helium_medium"]',
|
||||
);
|
||||
await expect(airSymbol.locator("svg")).toBeVisible();
|
||||
await expect(
|
||||
airSymbol.locator('[data-symbol-label="Air"]'),
|
||||
).toHaveText("Air");
|
||||
await expect(airSymbol.locator(".component-symbol-medium-svg path")).toHaveCount(0);
|
||||
await expect(heliumSymbol.locator("svg")).toBeVisible();
|
||||
await expect(
|
||||
heliumSymbol.locator('[data-symbol-label="He"]'),
|
||||
).toHaveText("He");
|
||||
await expect(heliumSymbol.locator(".component-symbol-medium-svg path")).toHaveCount(0);
|
||||
|
||||
const unknownSymbol = palette
|
||||
.getByRole("button", { name: "通用测试元件", exact: true })
|
||||
.locator('[data-component-symbol="generic"]');
|
||||
await expect(unknownSymbol.locator("svg")).toBeVisible();
|
||||
|
||||
await iconsButton.click();
|
||||
await expect(palette).toHaveAttribute("data-view-mode", "icons");
|
||||
await expect(detailedButton).toHaveAttribute("aria-pressed", "false");
|
||||
await expect(iconsButton).toHaveAttribute("aria-pressed", "true");
|
||||
await expect(airItem).toBeVisible();
|
||||
await expect(airItem.locator(".palette-item-name")).toBeVisible();
|
||||
await expect(airItem.locator(".palette-item-name")).toHaveText("空气介质定义");
|
||||
await expect(airItem.locator(".palette-item-meta")).toBeHidden();
|
||||
await expect(airItem).not.toHaveAttribute("title");
|
||||
|
||||
await page.reload();
|
||||
|
||||
await expect(palette).toHaveAttribute("data-view-mode", "icons");
|
||||
await expect(iconsButton).toHaveAttribute("aria-pressed", "true");
|
||||
await expect(airItem.locator(".palette-item-name")).toBeVisible();
|
||||
await expect(airItem.locator(".palette-item-meta")).toBeHidden();
|
||||
});
|
||||
|
||||
test("组件库和分类支持独立折叠并同步可访问状态", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
|
||||
const palette = page.locator("aside.palette");
|
||||
const libraryToggle = palette.getByRole("button", {
|
||||
name: "自动化测试组件库",
|
||||
exact: true,
|
||||
});
|
||||
const categoryToggle = palette.getByRole("button", {
|
||||
name: "介质物性",
|
||||
exact: true,
|
||||
});
|
||||
|
||||
await expect(libraryToggle).toHaveAttribute("aria-expanded", "true");
|
||||
const libraryContentId = await libraryToggle.getAttribute("aria-controls");
|
||||
expect(libraryContentId).toBeTruthy();
|
||||
await expect(page.locator(`[id="${libraryContentId}"]`)).toBeVisible();
|
||||
|
||||
await expect(categoryToggle).toHaveAttribute("aria-expanded", "true");
|
||||
const categoryItemsId = await categoryToggle.getAttribute("aria-controls");
|
||||
expect(categoryItemsId).toBeTruthy();
|
||||
await expect(page.locator(`[id="${categoryItemsId}"]`)).toBeVisible();
|
||||
await expect(
|
||||
palette.getByRole("button", { name: "空气介质定义", exact: true }),
|
||||
).toBeVisible();
|
||||
|
||||
await categoryToggle.click();
|
||||
await expect(categoryToggle).toHaveAttribute("aria-expanded", "false");
|
||||
await expect(page.locator(`[id="${categoryItemsId}"]`)).toHaveCount(0);
|
||||
await expect(
|
||||
palette.getByRole("button", { name: "空气介质定义", exact: true }),
|
||||
).toHaveCount(0);
|
||||
|
||||
await categoryToggle.click();
|
||||
await expect(categoryToggle).toHaveAttribute("aria-expanded", "true");
|
||||
await expect(page.locator(`[id="${categoryItemsId}"]`)).toBeVisible();
|
||||
|
||||
await libraryToggle.click();
|
||||
await expect(libraryToggle).toHaveAttribute("aria-expanded", "false");
|
||||
await expect(page.locator(`[id="${libraryContentId}"]`)).toHaveCount(0);
|
||||
await expect(
|
||||
palette.getByRole("button", { name: "介质物性", exact: true }),
|
||||
).toHaveCount(0);
|
||||
|
||||
await libraryToggle.click();
|
||||
await expect(libraryToggle).toHaveAttribute("aria-expanded", "true");
|
||||
await expect(page.locator(`[id="${libraryContentId}"]`)).toBeVisible();
|
||||
await expect(
|
||||
palette.getByRole("button", { name: "介质物性", exact: true }),
|
||||
).toHaveAttribute("aria-expanded", "true");
|
||||
});
|
||||
|
||||
test("仅图标模式名称截断且卡片尺寸不随侧栏和视口改变", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
await page
|
||||
.getByRole("button", { name: "仅图标显示", exact: true })
|
||||
.click();
|
||||
|
||||
const palette = page.locator("aside.palette");
|
||||
const longNameItem = palette.getByRole("button", {
|
||||
name: "AMESim 气动测试元件",
|
||||
exact: true,
|
||||
});
|
||||
const name = longNameItem.locator(".palette-item-name");
|
||||
const meta = longNameItem.locator(".palette-item-meta");
|
||||
|
||||
await expect(name).toBeVisible();
|
||||
await expect(name).toHaveText("AMESim 气动测试元件");
|
||||
await expect(meta).toBeHidden();
|
||||
await expect(longNameItem).not.toHaveAttribute("title");
|
||||
const truncation = await name.evaluate((element) => {
|
||||
const style = window.getComputedStyle(element);
|
||||
return {
|
||||
clipped: element.scrollWidth > element.clientWidth,
|
||||
overflow: style.overflow,
|
||||
textOverflow: style.textOverflow,
|
||||
whiteSpace: style.whiteSpace,
|
||||
};
|
||||
});
|
||||
expect(truncation).toEqual({
|
||||
clipped: true,
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
whiteSpace: "nowrap",
|
||||
});
|
||||
|
||||
await expectFixedIconCardSize(longNameItem);
|
||||
const initialPaletteBox = await palette.boundingBox();
|
||||
expect(initialPaletteBox).not.toBeNull();
|
||||
|
||||
const paletteSeparator = page.getByRole("separator", {
|
||||
name: "调整组件库宽度",
|
||||
});
|
||||
await paletteSeparator.focus();
|
||||
for (let index = 0; index < 5; index += 1) {
|
||||
await page.keyboard.press("ArrowRight");
|
||||
}
|
||||
await expect(paletteSeparator).toHaveAttribute("aria-valuenow", "330");
|
||||
const expandedPaletteBox = await palette.boundingBox();
|
||||
expect(expandedPaletteBox).not.toBeNull();
|
||||
expect(expandedPaletteBox!.width).toBeGreaterThan(initialPaletteBox!.width + 90);
|
||||
await expectFixedIconCardSize(longNameItem);
|
||||
|
||||
await page.setViewportSize({ width: 1000, height: 760 });
|
||||
await expect
|
||||
.poll(async () => Number(await paletteSeparator.getAttribute("aria-valuenow")))
|
||||
.toBeLessThan(330);
|
||||
await expectFixedIconCardSize(longNameItem);
|
||||
});
|
||||
|
||||
test("仅图标模式悬停后显示完整名称和图标预览并在移开后关闭", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
await page
|
||||
.getByRole("button", { name: "仅图标显示", exact: true })
|
||||
.click();
|
||||
|
||||
const item = page.locator("aside.palette").getByRole("button", {
|
||||
name: "AMESim 气动测试元件",
|
||||
exact: true,
|
||||
});
|
||||
const preview = page.locator("body > .palette-icon-preview[role='tooltip']");
|
||||
|
||||
await item.hover();
|
||||
await page.waitForTimeout(600);
|
||||
await expect(preview).toBeVisible();
|
||||
await expect(preview.locator(".palette-icon-preview-label")).toHaveText(
|
||||
"AMESim 气动测试元件",
|
||||
);
|
||||
await expect(
|
||||
preview.locator(
|
||||
'.palette-icon-preview-symbol [data-component-symbol="generic"] svg',
|
||||
),
|
||||
).toBeVisible();
|
||||
await expect(item).toHaveAttribute("aria-describedby", "palette-icon-preview");
|
||||
|
||||
await page.locator(".palette-panel-title").hover();
|
||||
await expect(preview).toHaveCount(0);
|
||||
await expect(item).not.toHaveAttribute("aria-describedby", "palette-icon-preview");
|
||||
});
|
||||
|
||||
test("仅图标模式仍可拖入氦气介质并在画布显示专用图标", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
|
||||
await page
|
||||
.getByRole("button", { name: "仅图标显示", exact: true })
|
||||
.click();
|
||||
|
||||
const palette = page.locator("aside.palette");
|
||||
const heliumItem = palette.getByRole("button", {
|
||||
name: "氦气介质定义",
|
||||
exact: true,
|
||||
});
|
||||
const canvas = page.locator(".flow-canvas .react-flow__pane");
|
||||
await heliumItem.dragTo(canvas, {
|
||||
targetPosition: { x: 420, y: 220 },
|
||||
});
|
||||
|
||||
const heliumNode = page.locator(
|
||||
'.flow-canvas .react-flow__node[data-id="amesim_helium_medium_1"]',
|
||||
);
|
||||
await expect(heliumNode).toBeVisible();
|
||||
await expect(
|
||||
heliumNode.locator(".sim-node.symbol-presentation-bare"),
|
||||
).toBeVisible();
|
||||
|
||||
const heliumCanvasSymbol = heliumNode.locator(
|
||||
'.node-symbol [data-component-symbol="amesim_helium_medium"]',
|
||||
);
|
||||
await expect(heliumCanvasSymbol).toHaveAttribute(
|
||||
"data-symbol-presentation",
|
||||
"bare",
|
||||
);
|
||||
await expect(heliumCanvasSymbol.locator("svg")).toBeVisible();
|
||||
await expect(
|
||||
heliumCanvasSymbol.locator('[data-symbol-label="He"]'),
|
||||
).toHaveText("He");
|
||||
});
|
||||
Reference in new issue
Block a user