feat(tests): Add comprehensive test coverage for terrain resizing logic

This commit is contained in:
2026-05-13 14:12:09 +02:00
parent f96cd18ecc
commit 2aae3dff27
2 changed files with 138 additions and 1 deletions

View File

@@ -160,6 +160,31 @@ describe("terrain grid resizing", () => {
expect(getTerrainHeightAtSample(resizedTerrain, 2, 2)).toBe(22); expect(getTerrainHeightAtSample(resizedTerrain, 2, 2)).toBe(22);
}); });
it("extends west and south when those cardinal resize directions are selected", () => {
const terrain = createTerrain({
id: "terrain-samples-extend-west-south",
position: { x: 10, y: 0, z: 20 },
sampleCountX: 3,
sampleCountZ: 3,
cellSize: 1,
heights: createIndexedHeights(3, 3)
});
const resizedTerrain = resizeTerrainGrid(terrain, {
sampleCountX: 5,
sampleCountZ: 5,
cellSize: terrain.cellSize,
resizeDirectionX: "west",
resizeDirectionZ: "south"
});
expect(resizedTerrain.position).toEqual({ x: 8, y: 0, z: 18 });
expect(getTerrainHeightAtSample(resizedTerrain, 2, 2)).toBe(0);
expect(getTerrainHeightAtSample(resizedTerrain, 4, 4)).toBe(22);
expect(getTerrainHeightAtSample(resizedTerrain, 0, 2)).toBe(0);
expect(getTerrainHeightAtSample(resizedTerrain, 2, 0)).toBe(0);
});
it("decreases Samples X/Z by cropping terrain instead of squashing existing data", () => { it("decreases Samples X/Z by cropping terrain instead of squashing existing data", () => {
const terrain = createTerrain({ const terrain = createTerrain({
id: "terrain-samples-crop", id: "terrain-samples-crop",
@@ -184,6 +209,33 @@ describe("terrain grid resizing", () => {
expect(getTerrainHeightAtSample(resizedTerrain, 2, 2)).toBe(22); expect(getTerrainHeightAtSample(resizedTerrain, 2, 2)).toBe(22);
}); });
it("crops west and south when those cardinal resize directions are selected", () => {
const terrain = createTerrain({
id: "terrain-samples-crop-west-south",
sampleCountX: 5,
sampleCountZ: 5,
cellSize: 1,
heights: createIndexedHeights(5, 5)
});
const resizedTerrain = resizeTerrainGrid(terrain, {
sampleCountX: 3,
sampleCountZ: 3,
cellSize: terrain.cellSize,
resizeDirectionX: "west",
resizeDirectionZ: "south"
});
expect(resizedTerrain.position).toEqual({
x: terrain.position.x + 2,
y: terrain.position.y,
z: terrain.position.z + 2
});
expect(getTerrainHeightAtSample(resizedTerrain, 0, 0)).toBe(22);
expect(getTerrainHeightAtSample(resizedTerrain, 1, 1)).toBe(33);
expect(getTerrainHeightAtSample(resizedTerrain, 2, 2)).toBe(44);
});
it("fills newly extended height samples from the nearest existing edge height", () => { it("fills newly extended height samples from the nearest existing edge height", () => {
const terrain = createTerrain({ const terrain = createTerrain({
id: "terrain-samples-edge-fill", id: "terrain-samples-edge-fill",
@@ -204,6 +256,37 @@ describe("terrain grid resizing", () => {
expect(getTerrainHeightAtSample(resizedTerrain, 4, 4)).toBe(22); expect(getTerrainHeightAtSample(resizedTerrain, 4, 4)).toBe(22);
}); });
it("preserves paint weights at the same world positions with west and south resizing", () => {
const terrain = createTerrain({
id: "terrain-samples-paint-west-south",
position: { x: 10, y: 0, z: 20 },
sampleCountX: 3,
sampleCountZ: 3,
cellSize: 1,
paintWeights: createIndexedPaintWeights(3, 3)
});
const resizedTerrain = resizeTerrainGrid(terrain, {
sampleCountX: 5,
sampleCountZ: 5,
cellSize: terrain.cellSize,
resizeDirectionX: "west",
resizeDirectionZ: "south"
});
const originalOffset = getTerrainPaintWeightSampleOffset(terrain, 1, 1);
const resizedOffset = getTerrainPaintWeightSampleOffset(resizedTerrain, 3, 3);
expect(resizedTerrain.paintWeights[resizedOffset]).toBeCloseTo(
terrain.paintWeights[originalOffset] ?? 0
);
expect(resizedTerrain.paintWeights[resizedOffset + 1]).toBeCloseTo(
terrain.paintWeights[originalOffset + 1] ?? 0
);
expect(resizedTerrain.paintWeights[resizedOffset + 2]).toBeCloseTo(
terrain.paintWeights[originalOffset + 2] ?? 0
);
});
it("keeps foliage masks and blocker masks valid after cell-size and sample-count edits", () => { it("keeps foliage masks and blocker masks valid after cell-size and sample-count edits", () => {
const foliageLayerId = "foliage-layer-resize-valid"; const foliageLayerId = "foliage-layer-resize-valid";
const terrain = createTerrain({ const terrain = createTerrain({
@@ -234,7 +317,9 @@ describe("terrain grid resizing", () => {
const extendedTerrain = resizeTerrainGrid(resolutionChangedTerrain, { const extendedTerrain = resizeTerrainGrid(resolutionChangedTerrain, {
sampleCountX: 6, sampleCountX: 6,
sampleCountZ: 4, sampleCountZ: 4,
cellSize: resolutionChangedTerrain.cellSize cellSize: resolutionChangedTerrain.cellSize,
resizeDirectionX: "west",
resizeDirectionZ: "south"
}); });
const resizedMask = getTerrainFoliageMask(extendedTerrain, foliageLayerId); const resizedMask = getTerrainFoliageMask(extendedTerrain, foliageLayerId);
@@ -284,6 +369,35 @@ describe("terrain grid resizing", () => {
expect(getTerrainFootprintDepth(resizedTerrain)).toBe(9); expect(getTerrainFootprintDepth(resizedTerrain)).toBe(9);
expect(resizedTerrain.position).toEqual(terrain.position); expect(resizedTerrain.position).toEqual(terrain.position);
}); });
it("uses cardinal directions for non-divisible footprint and cell-size edits", () => {
const terrain = createTerrain({
id: "terrain-cell-size-non-divisible-west-south",
sampleCountX: 9,
sampleCountZ: 9,
cellSize: 1,
heights: createIndexedHeights(9, 9)
});
const resizedTerrain = resizeTerrainGrid(terrain, {
sampleCountX: terrain.sampleCountX,
sampleCountZ: terrain.sampleCountZ,
cellSize: 3,
resizeDirectionX: "west",
resizeDirectionZ: "south"
});
expect(resizedTerrain.cellSize).toBe(3);
expect(resizedTerrain.sampleCountX).toBe(4);
expect(resizedTerrain.sampleCountZ).toBe(4);
expect(getTerrainFootprintWidth(resizedTerrain)).toBe(9);
expect(getTerrainFootprintDepth(resizedTerrain)).toBe(9);
expect(resizedTerrain.position).toEqual({
x: terrain.position.x - 1,
y: terrain.position.y,
z: terrain.position.z - 1
});
});
}); });
describe("terrain material layers", () => { describe("terrain material layers", () => {

View File

@@ -180,6 +180,29 @@ describe("Terrain foundation", () => {
expect(updatedTerrain?.cellSize).toBe(2); expect(updatedTerrain?.cellSize).toBe(2);
}); });
fireEvent.change(screen.getByTestId("terrain-grid-resize-direction-x"), {
target: { value: "west" }
});
fireEvent.change(screen.getByTestId("terrain-grid-resize-direction-z"), {
target: { value: "south" }
});
fireEvent.change(screen.getByTestId("terrain-grid-sample-count-x"), {
target: { value: "7" }
});
fireEvent.change(screen.getByTestId("terrain-grid-sample-count-z"), {
target: { value: "6" }
});
fireEvent.click(screen.getByTestId("terrain-grid-apply"));
await waitFor(() => {
const updatedTerrain = store.getState().document.terrains[createdTerrain.id];
expect(updatedTerrain?.sampleCountX).toBe(7);
expect(updatedTerrain?.sampleCountZ).toBe(6);
expect(updatedTerrain?.position.x).toBe(-8);
expect(updatedTerrain?.position.z).toBe(-6);
});
fireEvent.click(screen.getByTestId("terrain-collision-enabled")); fireEvent.click(screen.getByTestId("terrain-collision-enabled"));
await waitFor(() => { await waitFor(() => {