feat(junction): Add command tests and serialization support for spline corridor junctions
This commit is contained in:
128
tests/domain/spline-corridor-junction.command.test.ts
Normal file
128
tests/domain/spline-corridor-junction.command.test.ts
Normal file
@@ -0,0 +1,128 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { createEditorStore } from "../../src/app/editor-store";
|
||||
import { createDeletePathCommand } from "../../src/commands/delete-path-command";
|
||||
import { createDeleteSplineCorridorJunctionCommand } from "../../src/commands/delete-spline-corridor-junction-command";
|
||||
import { createUpsertPathCommand } from "../../src/commands/upsert-path-command";
|
||||
import { createUpsertSplineCorridorJunctionCommand } from "../../src/commands/upsert-spline-corridor-junction-command";
|
||||
import { createScenePath } from "../../src/document/paths";
|
||||
import { createEmptySceneDocument } from "../../src/document/scene-document";
|
||||
import { createSplineCorridorJunction } from "../../src/document/spline-corridor-junctions";
|
||||
|
||||
describe("spline corridor junction commands", () => {
|
||||
it("creates, updates, deletes, undoes, and redoes junctions", () => {
|
||||
const store = createEditorStore({
|
||||
initialDocument: createEmptySceneDocument()
|
||||
});
|
||||
const pathA = createScenePath({ id: "path-junction-command-a" });
|
||||
const pathB = createScenePath({ id: "path-junction-command-b" });
|
||||
const junction = createSplineCorridorJunction({
|
||||
id: "junction-command",
|
||||
center: { x: 1, y: 0, z: 2 },
|
||||
radius: 2,
|
||||
connections: [
|
||||
{ pathId: pathA.id, progress: 0.5, clipDistance: 2 },
|
||||
{ pathId: pathB.id, progress: 0.25, clipDistance: 2 }
|
||||
]
|
||||
});
|
||||
|
||||
store.executeCommand(createUpsertPathCommand({ path: pathA }));
|
||||
store.executeCommand(createUpsertPathCommand({ path: pathB }));
|
||||
store.executeCommand(
|
||||
createUpsertSplineCorridorJunctionCommand({ junction })
|
||||
);
|
||||
|
||||
expect(
|
||||
store.getState().document.splineCorridorJunctions[junction.id]
|
||||
).toEqual(junction);
|
||||
|
||||
store.executeCommand(
|
||||
createUpsertSplineCorridorJunctionCommand({
|
||||
junction: createSplineCorridorJunction({
|
||||
...junction,
|
||||
radius: 3
|
||||
})
|
||||
})
|
||||
);
|
||||
|
||||
expect(
|
||||
store.getState().document.splineCorridorJunctions[junction.id]?.radius
|
||||
).toBe(3);
|
||||
|
||||
store.executeCommand(createDeleteSplineCorridorJunctionCommand(junction.id));
|
||||
expect(
|
||||
store.getState().document.splineCorridorJunctions[junction.id]
|
||||
).toBeUndefined();
|
||||
|
||||
expect(store.undo()).toBe(true);
|
||||
expect(
|
||||
store.getState().document.splineCorridorJunctions[junction.id]?.radius
|
||||
).toBe(3);
|
||||
|
||||
expect(store.undo()).toBe(true);
|
||||
expect(
|
||||
store.getState().document.splineCorridorJunctions[junction.id]?.radius
|
||||
).toBe(2);
|
||||
|
||||
expect(store.redo()).toBe(true);
|
||||
expect(
|
||||
store.getState().document.splineCorridorJunctions[junction.id]?.radius
|
||||
).toBe(3);
|
||||
});
|
||||
|
||||
it("removes invalid junction connections when deleting paths and restores them on undo", () => {
|
||||
const pathA = createScenePath({ id: "path-junction-delete-a" });
|
||||
const pathB = createScenePath({ id: "path-junction-delete-b" });
|
||||
const pathC = createScenePath({ id: "path-junction-delete-c" });
|
||||
const junction = createSplineCorridorJunction({
|
||||
id: "junction-delete",
|
||||
center: { x: 0, y: 0, z: 0 },
|
||||
connections: [
|
||||
{ pathId: pathA.id, progress: 0, clipDistance: 1.5 },
|
||||
{ pathId: pathB.id, progress: 0.5, clipDistance: 1.5 },
|
||||
{ pathId: pathC.id, progress: 1, clipDistance: 1.5 }
|
||||
]
|
||||
});
|
||||
const store = createEditorStore({
|
||||
initialDocument: {
|
||||
...createEmptySceneDocument(),
|
||||
paths: {
|
||||
[pathA.id]: pathA,
|
||||
[pathB.id]: pathB,
|
||||
[pathC.id]: pathC
|
||||
},
|
||||
splineCorridorJunctions: {
|
||||
[junction.id]: junction
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
store.executeCommand(createDeletePathCommand(pathA.id));
|
||||
|
||||
expect(
|
||||
store
|
||||
.getState()
|
||||
.document.splineCorridorJunctions[junction.id]?.connections.map(
|
||||
(connection) => connection.pathId
|
||||
)
|
||||
).toEqual([pathB.id, pathC.id]);
|
||||
|
||||
store.executeCommand(createDeletePathCommand(pathB.id));
|
||||
expect(
|
||||
store.getState().document.splineCorridorJunctions[junction.id]
|
||||
).toBeUndefined();
|
||||
|
||||
expect(store.undo()).toBe(true);
|
||||
expect(
|
||||
store.getState().document.splineCorridorJunctions[junction.id]
|
||||
?.connections
|
||||
).toHaveLength(2);
|
||||
|
||||
expect(store.undo()).toBe(true);
|
||||
expect(
|
||||
store.getState().document.splineCorridorJunctions[junction.id]
|
||||
?.connections
|
||||
).toHaveLength(3);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -68,6 +68,7 @@ import {
|
||||
SCENE_DOCUMENT_VERSION,
|
||||
SHADER_SKY_HORIZON_HEIGHT_SCENE_DOCUMENT_VERSION,
|
||||
SHADER_SKY_SCENE_DOCUMENT_VERSION,
|
||||
SPLINE_CORRIDOR_JUNCTIONS_SCENE_DOCUMENT_VERSION,
|
||||
SPLINE_CORRIDOR_COLLISION_SCENE_DOCUMENT_VERSION,
|
||||
SPLINE_REPEATERS_SCENE_DOCUMENT_VERSION,
|
||||
SPLINE_ROAD_EDGES_SCENE_DOCUMENT_VERSION,
|
||||
@@ -123,6 +124,7 @@ import {
|
||||
} from "../../src/serialization/scene-document-json";
|
||||
import { BUNDLED_FOLIAGE_PROTOTYPES } from "../../src/foliage/bundled-foliage-manifest";
|
||||
import { createFoliageLayer } from "../../src/foliage/foliage";
|
||||
import { createSplineCorridorJunction } from "../../src/document/spline-corridor-junctions";
|
||||
|
||||
describe("scene document JSON", () => {
|
||||
it("round-trips the current empty schema", () => {
|
||||
|
||||
Reference in New Issue
Block a user