Files
workinf_Blender_Wasm/web/tests/e2e/user-manual-smoke.spec.ts
mes123456 b932db7642 feat(manual): add the illustrated Web Blender HTML user manual
A single-page 28-chapter manual generated from manual.json covers the
11 workspaces, all React editors, OPFS save/reopen, explicit local
downloads, import/export routes, preferences/keymap and the capability
matrix. It reuses verified course screenshots and adds 14 fresh
Chromium captures for shell, storage, area, camera, preferences, IO and
troubleshooting chapters.

Manual-driven fixes: Save As now states OPFS-only, GLTF import is
restored, quick toolbar honors its preference, startup workspace is
applied, Properties tabs jump to sections, Outliner fallback search
filters, and the editor-header ⋮ opens the area menu. Help and the
tutorial landing link the new manual; the PDF remains as an archive.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-11-13 11:58:40 +08:00

46 lines
2.5 KiB
TypeScript

import { expect, test } from "@playwright/test";
test.use({ viewport: { width: 1600, height: 900 } });
test("HTML manual has chapters, figures, working search and no overflow", async ({ page }) => {
test.setTimeout(240_000);
await page.goto("/manuals/index.html", { waitUntil: "load" });
await expect(page.locator(".manual-chapter")).toHaveCount(28);
await expect(page.locator(".manual-nav a[data-nav-id]")).toHaveCount(32);
await expect(page.getByLabel("搜索手册", { exact: true })).toBeVisible();
await expect(page.locator("figure img").first()).toBeVisible();
const firstImage = await page.locator("figure img").first().evaluate((element) => ({ complete: (element as HTMLImageElement).complete, width: (element as HTMLImageElement).naturalWidth }));
expect(firstImage.complete).toBe(true);
expect(firstImage.width).toBeGreaterThan(0);
await page.getByLabel("搜索手册", { exact: true }).fill("相机");
await expect(page.locator(".manual-search-status")).toContainText("匹配");
await expect.poll(async () => page.locator(".manual-nav a[data-nav-id][hidden]").count()).toBeGreaterThan(0);
await page.getByLabel("搜索手册", { exact: true }).fill("");
await expect(page.locator(".manual-search-status")).toHaveText("");
const overflow = await page.evaluate(() => document.documentElement.scrollWidth - window.innerWidth);
expect(overflow).toBeLessThanOrEqual(1);
});
test("manual is responsive and reachable from Help", async ({ page, context }) => {
test.setTimeout(240_000);
await page.setViewportSize({ width: 390, height: 844 });
await page.goto("/manuals/index.html", { waitUntil: "load" });
await expect(page.locator(".manual-menu-toggle")).toBeVisible();
expect(await page.evaluate(() => document.documentElement.scrollWidth - window.innerWidth)).toBeLessThanOrEqual(1);
await page.setViewportSize({ width: 1600, height: 900 });
await page.goto("/?ui=web", { waitUntil: "domcontentloaded" });
await page.locator("main.blender-app").waitFor({ timeout: 120_000 });
await page.getByRole("button", { name: "帮助", exact: true }).click();
const entry = page.getByRole("menuitem", { name: "使用手册(网页版)", exact: true });
await expect(entry).toBeVisible();
const popupPromise = context.waitForEvent("page", { timeout: 30_000 });
await entry.click();
const popup = await popupPromise;
await popup.waitForLoadState("domcontentloaded");
expect(new URL(popup.url()).pathname).toBe("/manuals/index.html");
await expect(popup.locator(".manual-chapter")).toHaveCount(28);
});