oficina / slides Public

Clone
git clone https://amadan.net/oficina/slides

Plain git — no account needed to clone.

Download

Download this file

1package render_test
2
3import (
4 "strings"
5 "testing"
6
7 "amadan.net/oficina/slides/internal/slides/deck"
8 "amadan.net/oficina/slides/internal/slides/render"
9)
10
11// Codex 7, reproduced then fixed: two columns blocks naming each other
12// used to vanish from the page with everything under them — every
13// member was "claimed", so nothing started the traversal. The ops
14// refuse the shape now, but a document can still hold it (two peers'
15// concurrent assignments merge into a cycle; a document written past
16// the ops), so the renderer appends whatever nothing reached at the
17// end, marked, rather than dropping it.
18func cyclicDeck(layout string) *deck.Deck {
19 blocks := []deck.Block{
20 {ID: "intro", Type: "text", Region: "body", Text: txt("Reached")},
21 {ID: "one", Type: "columns", Region: "body",
22 Props: map[string]any{"children": []any{"two", "kid"}}},
23 {ID: "two", Type: "columns", Region: "body",
24 Props: map[string]any{"children": []any{"one"}}},
25 {ID: "kid", Type: "text", Region: "body", Text: txt("Under the cycle")},
26 }
27 if layout == "canvas" {
28 for i := range blocks {
29 blocks[i].Region = ""
30 blocks[i].Box = box(0.1, 0.1+0.2*float64(i), 0.8, 0.15)
31 blocks[i].Z = i
32 }
33 }
34 return &deck.Deck{
35 Meta: deck.Meta{Theme: "paper"},
36 Slides: []deck.Slide{{ID: "s", Layout: layout, Template: "blank", Blocks: blocks}},
37 }
38}
39
40func TestBlocksNothingReachesRenderAtTheEndMarked(t *testing.T) {
41 for _, layout := range []string{"flow", "canvas"} {
42 t.Run(layout, func(t *testing.T) {
43 out, err := render.Slide(cyclicDeck(layout), 0, render.Desktop)
44 if err != nil {
45 t.Fatal(err)
46 }
47 s := string(out)
48 for _, id := range []string{"intro", "one", "two", "kid"} {
49 if n := strings.Count(s, `data-id="`+id+`"`); n != 1 {
50 t.Errorf("%s appears %d times, want 1:\n%s", id, n, s)
51 }
52 }
53 if !strings.Contains(s, "Under the cycle") {
54 t.Errorf("the text under the cycle is gone:\n%s", s)
55 }
56 // After the reached content, and marked: the cycle's first
57 // member is the root of the late pass, everything under it
58 // renders inside it, and every block nothing reached says
59 // so — the reached one does not.
60 if strings.Index(s, `data-id="intro"`) > strings.Index(s, `data-id="one"`) {
61 t.Errorf("the unreached blocks come before the reached one:\n%s", s)
62 }
63 if strings.Index(s, `data-id="one"`) > strings.Index(s, `data-id="two"`) ||
64 strings.Index(s, `data-id="two"`) > strings.Index(s, `data-id="kid"`) {
65 t.Errorf("the cycle does not render from its first member down:\n%s", s)
66 }
67 if got := strings.Count(s, `data-unreached="true"`); got != 3 {
68 t.Errorf("the three unreached blocks are marked; got %d marks:\n%s", got, s)
69 }
70 intro := s[strings.Index(s, `data-id="intro"`):]
71 intro = intro[:strings.Index(intro, ">")]
72 if strings.Contains(intro, "data-unreached") {
73 t.Errorf("the reached block is marked unreached: %s", intro)
74 }
75 if layout == "flow" && !strings.Contains(s, `data-region="unreached"`) {
76 t.Errorf("a flow slide wraps the late blocks in their own region:\n%s", s)
77 }
78 })
79 }
80}
81
82// A well-formed slide has nothing unreached, so nothing is marked and
83// no extra region appears — the fixture goldens hold that for every
84// template, and this says it in one line.
85func TestAWellFormedSlideHasNoUnreachedRegion(t *testing.T) {
86 out, err := render.Slide(fixture(), 2, render.Desktop)
87 if err != nil {
88 t.Fatal(err)
89 }
90 if strings.Contains(string(out), "unreached") {
91 t.Errorf("a well-formed two-column slide renders an unreached region:\n%s", out)
92 }
93}
94