clone

an offline map explorer where each world, from a game map to a city's open data, ships as one .atlas file

feat/atlas-next-horizon
atlas / analysis / test / visual.test.ts
visual.test.ts 4.0K
1// The style tokens: pure, and the same numbers on both projections.23import assert from "node:assert/strict";4import test from "node:test";56import { cellPlan } from "../cellsystems/plan.ts";7import { geohashSystem } from "../cellsystems/geohash.ts";8import { gridCellVisual } from "../cellsystems/visual.ts";9import { gridTheme, palette } from "../cellsystems/tokens.ts";10import { square } from "./grounds.ts";1112const plan = cellPlan(square, geohashSystem, "m6");13const of = (hash: string) => {14 const cell = plan.find((candidate) => candidate.hash === hash);15 assert.ok(cell, `${hash} is not in this plan`);16 return cell;17};18const tokens = (hash: string, subgridVisible: boolean, labelled: boolean) =>19 gridCellVisual(square, geohashSystem, of(hash), { subgridVisible, labelled });2021test("the held cell draws as an outline while its subdivision is showing", () => {22 const scope = tokens("m6", true, true);23 assert.ok(scope);24 assert.equal(scope.bare, true);25 assert.equal(scope.line.color, gridTheme.lineWhite, "the chosen path draws white");26 assert.equal(scope.line.widthPx, gridTheme.widths.scopeBare);27 assert.equal(scope.fill, null, "a scope is not tiled");28 assert.equal(scope.label, null, "and it is not labelled either, while the subdivision reads");29});3031test("putting the subdivision away thickens the boundary and gives it back its label", () => {32 const put = tokens("m6", false, true);33 assert.ok(put);34 assert.equal(put.bare, false);35 assert.equal(put.line.widthPx, gridTheme.widths.scope);36 assert.deepEqual(put.label, {37 prefix: "m",38 final: "6",39 color: gridTheme.lineWhite,40 textAlpha: 1,41 chip: gridTheme.chip,42 sizePx: gridTheme.labelSizePx,43 });44});4546test("a child too small to label draws nothing at all", () => {47 assert.equal(tokens("m60", true, false), null, "no room for the label, no cell");48 assert.equal(tokens("m60", false, true), null, "subdivision put away, no cell");49 assert.equal(tokens("m60", false, false), null);50 const drawn = tokens("m60", true, true);51 assert.ok(drawn);52 assert.equal(drawn.line.opacity, gridTheme.childLineAlpha);53 assert.equal(drawn.fill?.opacity, gridTheme.childFillAlpha);54 assert.equal(drawn.line.color, palette[0], "child 0 wears the wheel's first accent");55});5657test("a neighbour dims with its distance, and the dimming has a floor", () => {58 const near = tokens("m0", true, true);59 const far = tokens("0", true, true);60 assert.ok(near && far);61 assert.equal(near.fill?.color, gridTheme.dimColor);62 assert.equal(near.fill?.opacity, gridTheme.dimBase + 1 * gridTheme.dimStep);63 assert.equal(far.fill?.opacity, gridTheme.dimBase + 2 * gridTheme.dimStep);64 assert.equal(near.line.opacity, gridTheme.neighborLineAlpha);65 assert.equal(near.label?.sizePx, gridTheme.neighborLabelSizePx);66 assert.equal(near.label?.chip, gridTheme.neighborChip);67 // The cap keeps a deep hierarchy from fading to black.68 const capped = gridCellVisual(square, geohashSystem,69 { ...of("0"), contextDistance: 40 }, { subgridVisible: true, labelled: true });70 assert.equal(capped?.fill?.opacity, gridTheme.dimCap);71});7273test("a leaf is filled in its own accent", () => {74 const leaf = cellPlan(square, geohashSystem, "m6s").at(-1);75 assert.ok(leaf);76 assert.equal(leaf.role, "leaf");77 const drawn = gridCellVisual(square, geohashSystem, leaf,78 { subgridVisible: true, labelled: true });79 assert.ok(drawn);80 assert.equal(drawn.bare, false, "there is no subdivision to be bare of");81 assert.equal(drawn.line.color, gridTheme.lineWhite);82 assert.equal(drawn.line.widthPx, gridTheme.widths.leaf);83 assert.equal(drawn.fill?.opacity, gridTheme.leafFillAlpha);84 assert.equal(drawn.fill?.color, palette[geohashSystem.on(square).colorKey("m6s")]);85});8687test("the tokens are values: nothing a renderer holds can change them", () => {88 const once = tokens("m0", true, true);89 const twice = tokens("m0", true, true);90 assert.deepEqual(twice, once);91 assert.notEqual(twice, once, "a fresh object each time, so a mutating renderer cannot leak");92});