Spaces:
Paused
Paused
Download test/camera.test.js from Almaatla/SpaceCities: direct link, hf CLI and curl.
- Browser
- Download file 4.33 kB
-
https://huggingface.co/spaces/Almaatla/SpaceCities/resolve/main/test/camera.test.js
- Command line
-
hf download hf://spaces/Almaatla/SpaceCities/test/camera.test.js
-
curl -L -o camera.test.js https://huggingface.co/spaces/Almaatla/SpaceCities/resolve/main/test/camera.test.js
4.33 kB
| import { test } from "node:test"; | |
| import assert from "node:assert/strict"; | |
| import { | |
| createCamera, screenToWorld, worldToScreen, clampCamera, zoomAt, | |
| dragCamera, pinchZoomPan, MIN_ZOOM, MAX_ZOOM, | |
| } from "../camera.js"; | |
| const MAP = { width: 1600, height: 1000 }; | |
| const VW = 800, VH = 500; | |
| test("screenToWorld and worldToScreen are inverses", () => { | |
| const cam = { x: 700, y: 420, zoom: 1.4 }; | |
| const w = screenToWorld(cam, VW, VH, 123, 456); | |
| const s = worldToScreen(cam, VW, VH, w.x, w.y); | |
| assert.ok(Math.abs(s.x - 123) < 1e-9 && Math.abs(s.y - 456) < 1e-9, "round-trips back to the same screen point"); | |
| // The view centre maps to the camera's world focus. | |
| const c = screenToWorld(cam, VW, VH, VW / 2, VH / 2); | |
| assert.ok(Math.abs(c.x - cam.x) < 1e-9 && Math.abs(c.y - cam.y) < 1e-9); | |
| }); | |
| test("clampCamera keeps the view inside the map, and centres an axis smaller than the viewport", () => { | |
| const cam = { x: -500, y: 5000, zoom: 1 }; // way off both edges | |
| clampCamera(cam, MAP, VW, VH); | |
| assert.ok(cam.x >= VW / 2 && cam.x <= MAP.width - VW / 2, "x is pulled back inside the horizontal range"); | |
| assert.ok(cam.y >= VH / 2 && cam.y <= MAP.height - VH / 2, "y is pulled back inside the vertical range"); | |
| // Zoomed far out so the viewport is wider than the map -> that axis centres. | |
| const wide = { x: 10, y: 10, zoom: 0.1 }; | |
| clampCamera(wide, MAP, VW, VH); | |
| assert.equal(wide.x, MAP.width / 2, "an over-wide viewport centres x"); | |
| assert.equal(wide.y, MAP.height / 2, "an over-tall viewport centres y"); | |
| }); | |
| test("zoomAt keeps the world point under the cursor fixed and respects the zoom limits", () => { | |
| const cam = createCamera(MAP); | |
| const before = screenToWorld(cam, VW, VH, 600, 300); | |
| zoomAt(cam, MAP, VW, VH, 600, 300, 1.5); | |
| const after = screenToWorld(cam, VW, VH, 600, 300); | |
| assert.ok(Math.abs(before.x - after.x) < 1e-6 && Math.abs(before.y - after.y) < 1e-6, "the point under the cursor doesn't drift"); | |
| assert.ok(cam.zoom > 1, "it zoomed in"); | |
| for (let i = 0; i < 40; i++) zoomAt(cam, MAP, VW, VH, 400, 250, 2); | |
| assert.ok(cam.zoom <= MAX_ZOOM + 1e-9, "never past MAX_ZOOM"); | |
| for (let i = 0; i < 40; i++) zoomAt(cam, MAP, VW, VH, 400, 250, 0.5); | |
| assert.ok(cam.zoom >= Math.min(MIN_ZOOM, VW / MAP.width, VH / MAP.height) - 1e-9, "never below the fit-the-map minimum"); | |
| }); | |
| test("dragCamera moves the world opposite the finger, scaled by zoom, and clamps", () => { | |
| const cam = { x: 800, y: 500, zoom: 2 }; | |
| dragCamera(cam, MAP, VW, VH, 100, -40); // fingers drag right/up | |
| assert.equal(cam.x, 800 - 100 / 2, "content follows the finger: +dx screen -> -dx/zoom world"); | |
| assert.equal(cam.y, 500 - (-40) / 2); | |
| const edge = { x: MAP.width / 2, y: MAP.height / 2, zoom: 1 }; | |
| dragCamera(edge, MAP, VW, VH, 100000, 0); // shove hard past the edge | |
| assert.ok(edge.x <= MAP.width - VW / 2 + 1e-9, "a drag can't push the view off the map"); | |
| }); | |
| test("pinchZoomPan zooms by the spread ratio about the pinch midpoint", () => { | |
| const cam = { x: 800, y: 500, zoom: 1 }; | |
| // Both fingers straddle the exact view centre and spread 2x apart, midpoint | |
| // fixed -> pure zoom-in of ~2x, and the world point at the centre stays put. | |
| const centreWorldBefore = screenToWorld(cam, VW, VH, VW / 2, VH / 2); | |
| const prev = { ax: VW / 2 - 50, ay: VH / 2, bx: VW / 2 + 50, by: VH / 2 }; | |
| const cur = { ax: VW / 2 - 100, ay: VH / 2, bx: VW / 2 + 100, by: VH / 2 }; | |
| pinchZoomPan(cam, MAP, VW, VH, prev, cur); | |
| assert.ok(Math.abs(cam.zoom - 2) < 1e-6, "spread doubled -> zoom doubled"); | |
| const centreWorldAfter = screenToWorld(cam, VW, VH, VW / 2, VH / 2); | |
| assert.ok(Math.abs(centreWorldBefore.x - centreWorldAfter.x) < 1e-6 | |
| && Math.abs(centreWorldBefore.y - centreWorldAfter.y) < 1e-6, "the pinch midpoint's world point is anchored"); | |
| }); | |
| test("pinchZoomPan also pans when the two fingers translate together", () => { | |
| const cam = { x: 800, y: 500, zoom: 1 }; | |
| // Same spread (no zoom), both fingers slide +60px in x -> a pure pan. | |
| const prev = { ax: 300, ay: 250, bx: 400, by: 250 }; | |
| const cur = { ax: 360, ay: 250, bx: 460, by: 250 }; | |
| pinchZoomPan(cam, MAP, VW, VH, prev, cur); | |
| assert.ok(Math.abs(cam.zoom - 1) < 1e-9, "equal spread -> no zoom"); | |
| assert.equal(cam.x, 800 - 60 / 1, "the view pans opposite the shared finger movement"); | |
| }); | |