mirror of
https://github.com/MeshCore-Beacon/beacon-web.git
synced 2026-10-24 06:52:24 +00:00
109 lines
4.3 KiB
TypeScript
109 lines
4.3 KiB
TypeScript
import { describe, it, expect } from "vitest";
|
|
import {
|
|
stripPictographs,
|
|
nodeGlow,
|
|
idleDotTypes,
|
|
lightNode,
|
|
litFeatureCollection,
|
|
buildLiveNodeIndex,
|
|
withSelectedNode,
|
|
liveNeighborLines,
|
|
type LitEntry,
|
|
} from "../../../src/features/map/live-map";
|
|
|
|
describe("stripPictographs", () => {
|
|
it.each([
|
|
["💽 Back_Talk_Bouncer", "Back_Talk_Bouncer"],
|
|
["Valentine 🐶", "Valentine"],
|
|
["🇨🇦 Ottawa", "Ottawa"],
|
|
["👍🏽", ""],
|
|
["👨👩👧 Home Base", "Home Base"],
|
|
["Keycap 1️⃣", "Keycap 1"],
|
|
["Plain Name", "Plain Name"],
|
|
])("%s -> %s", (input, out) => expect(stripPictographs(input)).toBe(out));
|
|
});
|
|
|
|
describe("nodeGlow", () => {
|
|
it("is full at the crossing and fades linearly over 900 ms", () => {
|
|
expect(nodeGlow(1000, 1000)).toBe(1);
|
|
expect(nodeGlow(1000, 1450)).toBeCloseTo(0.5);
|
|
expect(nodeGlow(1000, 1900)).toBe(0);
|
|
expect(nodeGlow(1000, 5000)).toBe(0);
|
|
});
|
|
});
|
|
|
|
describe("idleDotTypes", () => {
|
|
it("shows repeaters and companions for All, otherwise only the filtered type", () => {
|
|
expect(idleDotTypes("")).toEqual(["repeater", "companion"]);
|
|
expect(idleDotTypes("repeater")).toEqual(["repeater"]);
|
|
expect(idleDotTypes("companion")).toEqual(["companion"]);
|
|
});
|
|
});
|
|
|
|
describe("litFeatureCollection", () => {
|
|
it("returns lit nodes with their glow and lit order, and drops faded ones", () => {
|
|
const lit = new Map<string, LitEntry>();
|
|
lightNode(lit, { id: "a", nodeTypeName: "repeater", label: "A", lng: 1, lat: 2, crossedAt: 0, seq: 1 });
|
|
lightNode(lit, { id: "b", nodeTypeName: "companion", label: "B", lng: 3, lat: 4, crossedAt: 600, seq: 2 });
|
|
const fc = litFeatureCollection(lit, 900);
|
|
expect(fc.features.map((f) => f.properties.id)).toEqual(["b"]);
|
|
expect(fc.features[0]!.properties).toMatchObject({ seq: 2, label: "B", nodeTypeName: "companion" });
|
|
expect(fc.features[0]!.properties.glow).toBeCloseTo(2 / 3);
|
|
expect(fc.features[0]!.geometry.coordinates).toEqual([3, 4]);
|
|
expect(lit.has("a")).toBe(false);
|
|
});
|
|
|
|
it("re-lighting a node gives it the new lit order", () => {
|
|
const lit = new Map<string, LitEntry>();
|
|
lightNode(lit, { id: "a", nodeTypeName: "repeater", label: "A", lng: 1, lat: 2, crossedAt: 0, seq: 1 });
|
|
lightNode(lit, { id: "a", nodeTypeName: "repeater", label: "A", lng: 1, lat: 2, crossedAt: 100, seq: 5 });
|
|
expect(litFeatureCollection(lit, 100).features[0]!.properties).toMatchObject({ seq: 5, glow: 1 });
|
|
});
|
|
});
|
|
|
|
describe("buildLiveNodeIndex", () => {
|
|
it("indexes every node by id with type and name", () => {
|
|
const fc = {
|
|
type: "FeatureCollection" as const,
|
|
features: [
|
|
{
|
|
type: "Feature" as const,
|
|
geometry: { type: "Point" as const, coordinates: [1, 2] },
|
|
properties: { id: "x", name: "X", nodeTypeName: "sensor", isObserver: false },
|
|
},
|
|
],
|
|
};
|
|
expect(buildLiveNodeIndex(fc).get("x")).toEqual({ nodeTypeName: "sensor", name: "X" });
|
|
});
|
|
});
|
|
|
|
describe("withSelectedNode", () => {
|
|
const feat = (id: string, nodeTypeName: string) => ({
|
|
type: "Feature" as const,
|
|
geometry: { type: "Point" as const, coordinates: [1, 2] },
|
|
properties: { id, name: id, nodeTypeName, isObserver: false },
|
|
});
|
|
const base = { type: "FeatureCollection" as const, features: [feat("r", "repeater"), feat("c", "companion")] };
|
|
const filtered = { type: "FeatureCollection" as const, features: [feat("r", "repeater")] };
|
|
|
|
it("adds the selected node back when the type filter hid it", () => {
|
|
expect(withSelectedNode(filtered, base, "c").features.map((f) => f.properties.id)).toEqual(["r", "c"]);
|
|
});
|
|
it("returns the filtered set unchanged when nothing needs adding", () => {
|
|
expect(withSelectedNode(filtered, base, "r")).toBe(filtered);
|
|
expect(withSelectedNode(filtered, base, null)).toBe(filtered);
|
|
expect(withSelectedNode(filtered, base, "gone")).toBe(filtered);
|
|
});
|
|
});
|
|
|
|
describe("liveNeighborLines", () => {
|
|
it("turns all-node lines into selected-node lines while Live is on", () => {
|
|
expect(liveNeighborLines("on", true)).toBe("selected");
|
|
expect(liveNeighborLines("selected", true)).toBe("selected");
|
|
expect(liveNeighborLines("off", true)).toBe("off");
|
|
});
|
|
it("leaves the setting alone when Live is off", () => {
|
|
expect(liveNeighborLines("on", false)).toBe("on");
|
|
});
|
|
});
|