quill/val Public Public: anyone can read this; nobody can change it.

forked from benjivers/val

workbenchthis machine
Files b02c1ef0dc92246d3da3567c343126686c5677c3
99 lines · 3.8 KB · ~1.1k tok Raw History
1
/**
2
 * The watching view: what a snapshot with no seat in it turns into on screen.
3
 */
4
5
import { describe, expect, test } from "bun:test";
6
import { drawWatching, watchLines, watching, wrap } from "../static/watch.js";
7
8
const spectator = (over: Record<string, unknown> = {}) => ({
9
  t: "s",
10
  spectator: true,
11
  why: "address",
12
  phase: "live",
13
  clock: 42.4,
14
  round: 7,
15
  score: { red: 3, blue: 3 },
16
  attackers: "red",
17
  result: null,
18
  events: ["red won the round"],
19
  feed: [],
20
  ...over,
21
});
22
23
const seated = () => ({ t: "s", phase: "live", me: { id: "p1", alive: true }, players: [] });
24
25
describe("telling a seat from a watcher", () => {
26
  test("a spectator snapshot is watching, a seat's is not", () => {
27
    expect(watching(spectator())).toBe(true);
28
    expect(watching(seated())).toBe(false);
29
  });
30
31
  test("a snapshot with no `me` is watching even if nobody flagged it", () => {
32
    expect(watching({ t: "s", phase: "live" })).toBe(true);
33
    expect(watching(null)).toBe(false);
34
    expect(watching(undefined)).toBe(false);
35
  });
36
});
37
38
describe("what the watching view says", () => {
39
  test("the score, the round and the clock, from the snapshot it was given", () => {
40
    const lines = watchLines(spectator());
41
    expect(lines.score).toBe("red 3 — 3 blue");
42
    expect(lines.clock).toBe("43s");
43
    expect(lines.phase).toBe("round 7 · live · red attacking");
44
  });
45
46
  test("a round that has just ended says who took it and why", () => {
47
    const lines = watchLines(spectator({ phase: "end", last: { round: 7, winner: "blue", why: "Time out" } }));
48
    expect(lines.phase).toBe("round 7 · round over — blue take it, time out · red attacking");
49
    // Once the next round is on, the phase line is the phase again.
50
    expect(watchLines(spectator({ phase: "buy", last: { round: 7, winner: "blue", why: "Time out" } })).phase).not.toContain("take it");
51
  });
52
53
  test("the reason is named: the seat is held at this address", () => {
54
    expect(watchLines(spectator()).why).toContain("address");
55
    expect(watchLines(spectator({ why: "cookie" })).why).toContain("cookie");
56
    // A snapshot that does not say still gets a sentence, not `undefined`.
57
    expect(watchLines(spectator({ why: undefined })).why).toContain("watching");
58
  });
59
60
  test("it never claims to know where anybody is", () => {
61
    const lines = watchLines(spectator());
62
    expect(lines.note).toContain("No map");
63
    expect(JSON.stringify(lines)).not.toMatch(/"x"|"y"/);
64
  });
65
66
  test("a half-built snapshot is drawn, not thrown on", () => {
67
    const lines = watchLines({ spectator: true });
68
    expect(lines.score).toBe("red 0 — 0 blue");
69
    expect(lines.clock).toBe("0s");
70
    expect(lines.phase).toContain("round 1");
71
  });
72
});
73
74
test("long sentences are broken to fit the canvas", () => {
75
  const ctx = { measureText: (text: string) => ({ width: text.length * 10 }) };
76
  const lines = wrap(ctx, "one two three four five six", 100);
77
  expect(lines.length).toBeGreaterThan(1);
78
  for (const line of lines) expect(line.length).toBeLessThanOrEqual(10);
79
  expect(lines.join(" ")).toBe("one two three four five six");
80
});
81
82
test("drawing it fills a flat panel and writes the score, and draws no world", () => {
83
  const ops: string[] = [];
84
  const ctx = new Proxy(
85
    { measureText: (text: string) => ({ width: text.length * 6 }) } as Record<string, unknown>,
86
    {
87
      get: (target, prop: string) =>
88
        prop in target
89
          ? target[prop]
90
          : (...args: unknown[]) => ops.push(`${prop}(${args.map(String).join(",")})`),
91
      set: () => true,
92
    },
93
  );
94
  drawWatching(ctx as never, spectator(), 900, 570);
95
  // One background rectangle and nothing else with an edge: no tiles, no bodies.
96
  expect(ops.filter((op) => op.startsWith("fillRect")).length).toBe(1);
97
  expect(ops.some((op) => op.startsWith("fillText(red 3 — 3 blue"))).toBe(true);
98
  expect(ops.some((op) => op.startsWith("fillText(watching"))).toBe(true);
99
});
↑↓ navigate ↵ open esc close
↑↓ navigate ↵ open esc close

Keyboard shortcuts