refactor(*): 平台架构 - 拆分后端领域模块与画布前端组件并补充测试

This commit is contained in:
ddcat666
2026-09-30 10:01:39 +08:00
parent e0a2697c60
commit 7f5d87ef1a
186 changed files with 33727 additions and 29905 deletions

View File

@@ -1,7 +1,19 @@
import { describe, expect, test } from "bun:test";
import { applyCanvasSelectionStrategy, canvasSelectionHitsBounds, createCanvasSelectionBounds, createCanvasSelectionSpatialIndexCache, offsetSelectedNodeBounds, resolveCanvasPointerIntent, resolveCanvasSelectionHitMode, resolveCanvasSelectionPreviewDelta, resolveCanvasSelectionStrategy, selectedNodesWorldBounds } from "@/lib/canvas/canvas-selection";
import {
applyCanvasSelectionStrategy,
canvasSelectionHitsBounds,
createCanvasSelectionBounds,
createCanvasSelectionSpatialIndexCache,
offsetSelectedNodeBounds,
resolveCanvasPointerIntent,
resolveCanvasSelectionHitMode,
resolveCanvasSelectionPreviewDelta,
resolveCanvasSelectionStrategy,
selectedNodesWorldBounds,
} from "@/lib/canvas/canvas-selection";
import { CanvasNodeType, type CanvasNodeData } from "@/types/canvas";
import { moduleGroupSource } from "./helpers/module-group-source";
describe("canvas selection semantics", () => {
test("maps modifiers to replace, add, toggle, and subtract strategies", () => {
@@ -78,7 +90,7 @@ describe("canvas selection semantics", () => {
});
test("uses region selection as the page default and commits selection outside pointer-move", async () => {
const projectSource = await Bun.file(new URL("../src/pages/canvas/project.tsx", import.meta.url)).text();
const projectSource = await Promise.resolve(moduleGroupSource("pages/canvas/project.tsx"));
const controllerSource = await Bun.file(new URL("../src/pages/canvas/use-canvas-selection-controller.ts", import.meta.url)).text();
const canvasSource = await Bun.file(new URL("../src/components/canvas/infinite-canvas.tsx", import.meta.url)).text();
const graphicsSource = await Bun.file(new URL("../src/components/canvas/canvas-leafer-graphics-layer.tsx", import.meta.url)).text();
@@ -91,22 +103,16 @@ describe("canvas selection semantics", () => {
expect(canvasSource).toContain('"canvas-cursor-select"');
expect(canvasSource).not.toContain('"cursor-crosshair"');
expect(graphicsSource).toContain('fill: "transparent"');
expect(graphicsSource).toContain('dashPattern: [4 / scale, 4 / scale]');
expect(graphicsSource).toContain("dashPattern: [4 / scale, 4 / scale]");
expect(globalStyles).toContain(".canvas-cursor-select");
expect(globalStyles).not.toContain("filter='drop-shadow");
});
test("offsets multi-select bounds with the live drag preview", () => {
const bounds = selectedNodesWorldBounds([
node("a", 100, 40),
node("b", 300, 80),
]);
const bounds = selectedNodesWorldBounds([node("a", 100, 40), node("b", 300, 80)]);
expect(bounds).toEqual({ left: 100, top: 40, width: 360, height: 130, count: 2 });
expect(offsetSelectedNodeBounds(bounds!, { x: 40, y: -20 })).toEqual({ left: 140, top: 20, width: 360, height: 130, count: 2 });
expect(selectedNodesWorldBounds([
node("a", 100, 40),
node("b", 300, 80),
], { x: 40, y: -20, nodeIds: new Set(["a", "b"]) })).toEqual({ left: 140, top: 20, width: 360, height: 130, count: 2 });
expect(selectedNodesWorldBounds([node("a", 100, 40), node("b", 300, 80)], { x: 40, y: -20, nodeIds: new Set(["a", "b"]) })).toEqual({ left: 140, top: 20, width: 360, height: 130, count: 2 });
});
});