1
0
This repository has been archived on 2026-08-25. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
tera/src/test/roadTraffic.test.ts
T

84 lines
2.9 KiB
TypeScript

/** Render-layer contract tests that do not require a WebGL context. */
import assert from "node:assert/strict";
import { describe, it } from "node:test";
import * as THREE from "three";
import type { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import CALIFORNIA_TRANSPORT from "../transport/california.ts";
import { createRoadTrafficLayer } from "../engine/roadTraffic.ts";
import type { World } from "../engine/world.ts";
function fixture() {
const world = {
project(lat: number, lng: number): [number, number] {
return [(lng + 121) * 20, -(lat - 36) * 20];
},
groundAt(): number {
return 0;
},
} as unknown as World;
const camera = new THREE.PerspectiveCamera(42, 16 / 9, 0.1, 2_000);
const controls = {
target: new THREE.Vector3(),
enabled: true,
} as unknown as OrbitControls;
const layer = createRoadTrafficLayer(world, camera, controls, {
pack: CALIFORNIA_TRANSPORT,
routeId: "la-sf-us-101",
count: 8,
seed: 115,
});
return { layer, camera, controls };
}
describe("road traffic render layer", () => {
it("draws one articulated hero and instanced background parts", () => {
const { layer } = fixture();
const hero = layer.group.getObjectByName("model-x-hero");
assert.ok(hero);
assert.equal(hero.scale.x, 0.18);
assert.ok(layer.group.children.some((child) => child instanceof THREE.InstancedMesh));
assert.equal(layer.hero()?.routeId, "la-sf-us-101");
assert.ok(Math.abs(hero.position.y - 0.155) < 1e-9);
layer.dispose();
});
it("switches routes and owns the orbit-control handoff while following", () => {
const { layer, camera, controls } = fixture();
layer.setRoute("la-sf-i-5");
assert.equal(layer.routeId(), "la-sf-i-5");
assert.equal(layer.hero()?.routeId, "la-sf-i-5");
layer.setFollowing(true);
assert.equal(layer.following(), true);
assert.equal(controls.enabled, false);
layer.tick(0.1);
assert.ok(camera.position.toArray().every(Number.isFinite));
assert.ok(controls.target.toArray().every(Number.isFinite));
layer.setCameraMode("driver");
assert.equal(layer.cameraMode(), "driver");
layer.tick(1 / 60);
assert.ok(camera.position.y > layer.group.getObjectByName("model-x-hero")!.position.y);
layer.setFollowing(false);
assert.equal(controls.enabled, true);
layer.dispose();
});
it("hands manual input to the deterministic hero and resumes assistance", () => {
const { layer } = fixture();
for (let index = 0; index < 20; index += 1) {
layer.setVehicleActions({ throttle: 1, steering: 0.8 });
layer.tick(1 / 30);
}
assert.equal(layer.hero().mode, "manual");
assert.ok(layer.hero().lateralOffsetM > 0);
layer.setVehicleActions({ modeRequest: "assisted" });
layer.tick(1 / 30);
assert.equal(layer.hero().mode, "assisted");
layer.dispose();
});
});