From 45cdb35158ac44a24f0ac3f8ae2b180ad2e6d00f Mon Sep 17 00:00:00 2001 From: Victor Giers Date: Wed, 13 May 2026 20:07:08 +0200 Subject: [PATCH] feat(tests): Add tests for reattaching and reprojecting spline corridor junctions --- .../domain/spline-corridor-junctions.test.ts | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/tests/domain/spline-corridor-junctions.test.ts b/tests/domain/spline-corridor-junctions.test.ts index 0ca175a6..730d690f 100644 --- a/tests/domain/spline-corridor-junctions.test.ts +++ b/tests/domain/spline-corridor-junctions.test.ts @@ -5,6 +5,7 @@ import { createSplineCorridorJunction } from "../../src/document/spline-corridor import { createSplineCorridorJunctionFromCandidate, detectSplineCorridorJunctionCandidates, + reattachSplineCorridorJunctionsToPaths, resolveSplineCorridorJunctionClipIntervals } from "../../src/spline-corridor/spline-corridor-junctions"; @@ -224,4 +225,98 @@ describe("spline corridor junctions", () => { }) ]); }); + + it("reattaches persisted junctions to moved crossing paths", () => { + const pathA = createRoadPath("path-reattach-a", [ + { x: 0, z: 0 }, + { x: 10, z: 0 } + ]); + const pathB = createRoadPath("path-reattach-b", [ + { x: 5, z: -5 }, + { x: 5, z: 5 } + ]); + const movedPathA = createRoadPath("path-reattach-a", [ + { x: 0, z: 2 }, + { x: 10, z: 2 } + ]); + const junction = createSplineCorridorJunction({ + id: "junction-reattach", + center: { x: 5, y: 0, z: 0 }, + connections: [ + { id: "connection-a", pathId: pathA.id, progress: 0.5, clipDistance: 2 }, + { id: "connection-b", pathId: pathB.id, progress: 0.5, clipDistance: 2 } + ] + }); + + const nextJunctions = reattachSplineCorridorJunctionsToPaths({ + paths: [movedPathA, pathB], + junctions: { + [junction.id]: junction + }, + changedPathIds: [pathA.id] + }); + const nextJunction = nextJunctions[junction.id]; + const movedPathConnection = nextJunction?.connections.find( + (connection) => connection.pathId === movedPathA.id + ); + const stationaryPathConnection = nextJunction?.connections.find( + (connection) => connection.pathId === pathB.id + ); + + expect(nextJunction?.center).toMatchObject({ + x: expect.closeTo(5, 5), + y: expect.closeTo(0, 5), + z: expect.closeTo(2, 5) + }); + expect(movedPathConnection?.id).toBe("connection-a"); + expect(movedPathConnection?.progress).toBeCloseTo(0.5); + expect(stationaryPathConnection?.id).toBe("connection-b"); + expect(stationaryPathConnection?.progress).toBeCloseTo(0.7); + expect(stationaryPathConnection?.clipDistance).toBe(2); + }); + + it("reprojects persisted junction connections when no new crossing candidate exists", () => { + const pathA = createRoadPath("path-reattach-fallback-a", [ + { x: 0, z: 0 }, + { x: 10, z: 0 } + ]); + const pathB = createRoadPath("path-reattach-fallback-b", [ + { x: 5, z: -5 }, + { x: 5, z: 5 } + ]); + const movedPathA = createRoadPath("path-reattach-fallback-a", [ + { x: 0, z: 8 }, + { x: 10, z: 8 } + ]); + const junction = createSplineCorridorJunction({ + id: "junction-reattach-fallback", + center: { x: 5, y: 0, z: 0 }, + connections: [ + { pathId: pathA.id, progress: 0.5, clipDistance: 2 }, + { pathId: pathB.id, progress: 0.5, clipDistance: 2 } + ] + }); + + const nextJunction = reattachSplineCorridorJunctionsToPaths({ + paths: [movedPathA, pathB], + junctions: { + [junction.id]: junction + }, + changedPathIds: [pathA.id] + })[junction.id]; + + expect(nextJunction?.center).toMatchObject({ + x: expect.closeTo(5, 5), + y: expect.closeTo(0, 5), + z: expect.closeTo(4, 5) + }); + expect( + nextJunction?.connections.find((connection) => connection.pathId === pathA.id) + ?.progress + ).toBeCloseTo(0.5); + expect( + nextJunction?.connections.find((connection) => connection.pathId === pathB.id) + ?.progress + ).toBeCloseTo(0.5); + }); });