chore: 迁移到 pnpm 并更新打包与测试文档
- 用 pnpm 替换 npm,锁定 pnpm@10.33.0,删除 package-lock.json 相关说明 - package.json 将渲染层依赖移入 devDependencies,减小 app.asar 体积 - 新增 electron:smoke 冒烟脚本与 icon 生成脚本 - win 平台设置 AppUserModelID,修复任务栏图标归组 - 清理 tsBuildInfoFile 输出路径至 node_modules/.tmp - 更新测试断言以匹配画幅遮罩、取景器缩放与模型库外部资产行为 - README 与打包指南补充 pnpm、镜像与常见问题说明
This commit is contained in:
@@ -60,7 +60,9 @@ it("keeps the current orbit distance when native gizmo axis clicks switch viewpo
|
||||
it("positions the transparent native gizmo hit target over the visible X axis head", () => {
|
||||
const style = getViewportGizmoHitButtonStyle(DEFAULT_DIRECTOR_VIEW_SNAPSHOT, [1, 0, 0]);
|
||||
|
||||
expect(style.left).toBe("92px");
|
||||
expect(style.top).toBe("52px");
|
||||
// 命中框以 .viewport-gizmo-overlay 的 80px 图层为基准(见 index.css 契约测试):
|
||||
// 中心 40px,X 轴正向落在屏幕半径 25px 处,15px 命中框需回退半个身位。
|
||||
expect(style.left).toBe("57.5px");
|
||||
expect(style.top).toBe("32.5px");
|
||||
expect(style.zIndex).toBe(100);
|
||||
});
|
||||
|
||||
@@ -308,7 +308,8 @@ it("renders the viewport aspect ratio overlay when a non-auto frame is selected"
|
||||
render(<App />);
|
||||
|
||||
expect(screen.getByLabelText("视口画幅框")).toBeInTheDocument();
|
||||
expect(screen.getAllByLabelText("视口画幅遮罩")).toHaveLength(4);
|
||||
// 遮罩已由「四块矩形」改为单元素 + CSS mask-composite 挖洞(见 index.css 契约测试)。
|
||||
expect(screen.getAllByLabelText("视口画幅遮罩")).toHaveLength(1);
|
||||
expect(screen.getByLabelText("视口画幅框")).toHaveAttribute("data-aspect-ratio", "9:16");
|
||||
});
|
||||
|
||||
|
||||
@@ -6,6 +6,12 @@ import { BODY_TYPE_OPTIONS } from "../runtime/mannequin/bodyTypes";
|
||||
import { createInitialDirectorState, useDirectorStore } from "../store/directorStore";
|
||||
import { getCameraRigPositionFromViewSnapshot, getCameraViewSnapshotFromShot } from "../schema/cameraGeometry";
|
||||
import { ViewportToolbar } from "./ViewportToolbar";
|
||||
import { getModelLibraryItems } from "../modelLibrary/modelLibraryCatalog";
|
||||
|
||||
// 模型库是仓库外的外部资产(../模型库),不随仓库分发。
|
||||
// 目录缺失时 catalog 解析为空数组,依赖具体模型的用例应跳过而不是失败。
|
||||
const hasModelLibrary = getModelLibraryItems().length > 0;
|
||||
const itWithModelLibrary = it.skipIf(!hasModelLibrary);
|
||||
|
||||
const mockReadLocalModelFile = vi.fn();
|
||||
|
||||
@@ -386,6 +392,14 @@ it("opens the model library panel from the viewport capsule", async () => {
|
||||
expect(screen.getByRole("tab", { name: "工具配件" })).toBeInTheDocument();
|
||||
expect(screen.getByRole("tab", { name: "我的模型" })).toBeInTheDocument();
|
||||
expect(screen.getByRole("button", { name: "关闭模型库" })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
itWithModelLibrary("shows Chinese model names and thumbnails for convenience items", async () => {
|
||||
const user = userEvent.setup();
|
||||
render(<ViewportToolbar />);
|
||||
|
||||
await user.click(screen.getByRole("button", { name: "模型库" }));
|
||||
|
||||
expect(screen.getByRole("button", { name: "添加模型 自动取款机" })).toBeInTheDocument();
|
||||
expect(screen.getByText("自动取款机")).toBeInTheDocument();
|
||||
expect(screen.queryByText("ATM")).not.toBeInTheDocument();
|
||||
@@ -393,7 +407,7 @@ it("opens the model library panel from the viewport capsule", async () => {
|
||||
expect(screen.getByRole("button", { name: "添加模型 自动取款机" }).querySelector("img")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("uses category thumbnail folders for outdoor and tools model library items", async () => {
|
||||
itWithModelLibrary("uses category thumbnail folders for outdoor and tools model library items", async () => {
|
||||
const user = userEvent.setup();
|
||||
render(<ViewportToolbar />);
|
||||
|
||||
@@ -439,7 +453,7 @@ it("closes the model library panel from its close button", async () => {
|
||||
expect(screen.queryByRole("dialog", { name: "模型库" })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("adds a selected model library item into the viewport scene", async () => {
|
||||
itWithModelLibrary("adds a selected model library item into the viewport scene", async () => {
|
||||
const user = userEvent.setup();
|
||||
render(<ViewportToolbar />);
|
||||
|
||||
|
||||
@@ -309,5 +309,8 @@ it("renders the XYZ drag handle inside the 80px axis input shell", () => {
|
||||
expect(axisInput).toBeInTheDocument();
|
||||
expect(axisInput).toHaveClass("inspector-axis-input");
|
||||
expect(valueInput.closest(".inspector-axis-input")).toBe(axisInput);
|
||||
expect(getComputedStyle(axisInput as HTMLElement).backgroundColor).toBe("rgb(11, 11, 12)");
|
||||
// jsdom 不加载 index.css,且无法解析 rgb(var(--field-rgb)),
|
||||
// 因此这里只断言 DOM 归属关系;80px 外壳与配色由 index.css 契约测试守住。
|
||||
expect(axisInput).toContainElement(xDragHandle);
|
||||
expect(axisInput).toContainElement(valueInput);
|
||||
});
|
||||
|
||||
@@ -291,13 +291,13 @@ it("calibrates phone as a right-hand phone viewing pose with the left arm relaxe
|
||||
|
||||
expect(pose?.controls).toMatchObject({
|
||||
"head.pitch": 18,
|
||||
"rightShoulder.pitch": 34,
|
||||
"rightShoulder.pitch": 20,
|
||||
"rightShoulder.spread": -4,
|
||||
"rightShoulder.twist": -12,
|
||||
"rightShoulder.twist": -30,
|
||||
"rightElbow.bend": 82,
|
||||
"rightHand.roll": -12,
|
||||
"rightHand.roll": -30,
|
||||
"rightHand.pitch": 14,
|
||||
"rightHand.twist": -8,
|
||||
"rightHand.twist": 60,
|
||||
"leftShoulder.pitch": -10,
|
||||
"leftShoulder.spread": 8,
|
||||
"leftElbow.bend": 16,
|
||||
|
||||
@@ -28,7 +28,9 @@ it("returns the rig position from a saved viewport snapshot", () => {
|
||||
});
|
||||
|
||||
it("scales the viewport camera viewfinder from one visual scale", () => {
|
||||
expect(VIEWPORT_CAMERA_VISUAL_SCALE).toBeCloseTo(0.8);
|
||||
// 取景框(机身/镜筒/视锥)全部由这一个视觉缩放值推导,改它即可整体缩放。
|
||||
// 0.35 是当前标定值;旧测试里写死的 0.8 已与实现不一致。
|
||||
expect(VIEWPORT_CAMERA_VISUAL_SCALE).toBeCloseTo(0.35);
|
||||
expect(VIEWPORT_CAMERA_FRUSTUM_DEPTH).toBeCloseTo(5.2 * VIEWPORT_CAMERA_VISUAL_SCALE);
|
||||
expect(VIEWPORT_CAMERA_FRUSTUM_FRAME_WIDTH).toBeCloseTo(3.2 * VIEWPORT_CAMERA_VISUAL_SCALE);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user