oficina / calendar Public

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

Plain git — no account needed to clone.

Download

Download this file

1package calendartest
2
3import (
4 "amadan.net/oficina/estilo.git/base"
5 estilobusy "amadan.net/oficina/estilo.git/busy"
6 "amadan.net/oficina/estilo.git/chrome"
7 "amadan.net/oficina/estilo.git/menu"
8 "amadan.net/oficina/estilo.git/sky"
9 "amadan.net/oficina/estilo.git/theme"
10 "bytes"
11 "os"
12 "path/filepath"
13 "testing"
14
15 "amadan.net/rastrillo/rastrillo/ui"
16)
17
18// vendoredTheme is the theme this app was scaffolded with. Change it
19// here when you swap static/theme.css for another of ui.ThemeNames().
20const vendoredTheme = "day"
21
22// vendoredIsMine names the vendored files this app has edited
23// DELIBERATELY. Add one here when you mean to diverge: this test stops
24// pinning it, and rastrillo doctor leaves it alone too. The file was
25// yours from the moment the scaffold wrote it — this is only where you
26// record that the edit was on purpose, so the next reader (and the next
27// upgrade) can tell it from drift.
28var vendoredIsMine = map[string]bool{
29 // rastrillo's shim as estilo carries it: without the old busy rule,
30 // which would fight busy.js. Pinned to estilo by TestBusyFilesAreEstilos.
31 "rastrillo.js": true,
32 // Calma with Calendar's accent, from estilo (estilo AGENTS.md,
33 // decisions table, row 8; this repo's ruling 2 is superseded). Pinned
34 // to estilo instead, by TestThemeIsEstilosForCalendar below.
35 "theme.css": true,
36 // Calendar's OWN calendar.js (bring the working day into view on
37 // load), not rastrillo's: from v0.26 rastrillo vendors a calendar.js
38 // of its own, the month-grid overlay for date fields, under the same
39 // name. Listed so doctor --fix never overwrites ours with it. Without
40 // rastrillo's overlay, datetime.js's button opens the browser's own
41 // picker, as it did on v0.23. Adopting the overlay means renaming
42 // ours first.
43 "calendar.js": true,
44 // estilo's busy.js, not rastrillo's: from fb806a2 rastrillo's copy
45 // learned to leave pow.js forms alone, and Calendar has no pow (auth
46 // runs ProofOff). Pinned to estilo by TestBusyFilesAreEstilos, like
47 // rastrillo.js; it follows estilo's when estilo takes the change.
48 "busy.js": true,
49 // rastrillo's console shell (from v0.27), which Calendar does not
50 // draw: its bar and page frame are estilo's chrome. Never vendored,
51 // so there is nothing here to pin.
52 "shell.css": true,
53 "shell.js": true,
54}
55
56// TestThemeIsEstilosForCalendar pins static/theme.css to the estilo this
57// app is built against. After an estilo upgrade, re-write it with
58// `go run ./scripts/writeestilo` — never by hand.
59func TestThemeIsEstilosForCalendar(t *testing.T) {
60 want, ok := theme.ForApp("calendar")
61 if !ok {
62 t.Fatal("estilo's theme ring has no calendar")
63 }
64 got, err := os.ReadFile(filepath.Join("..", "calendar", "static", "theme.css"))
65 if err != nil {
66 t.Fatal(err)
67 }
68 if !bytes.Equal(got, want) {
69 t.Error("static/theme.css differs from estilo's theme for calendar; run go run ./scripts/writeestilo")
70 }
71}
72
73// The scaffold delivered these files once; they are app-owned from
74// then on. This test pins each vendored copy byte-identical to the
75// library it came from: a reviewer runs the suite instead of reading
76// ~56KB of assets as app diff, and a framework upgrade that forgets
77// to re-copy is caught instead of drifting silently.
78//
79// The list is ui.VendoredAssets — the same function rastrillo new
80// wrote these files from and rastrillo doctor compares them against —
81// so a file added to the library's vendored set is pinned here without
82// this file changing.
83func TestVendoredAssetsMatchTheLibrary(t *testing.T) {
84 assets, ok := ui.VendoredAssets(vendoredTheme)
85 if !ok {
86 t.Fatalf("unknown theme %q", vendoredTheme)
87 }
88 for name, lib := range assets {
89 if vendoredIsMine[name] {
90 continue
91 }
92 vendored, err := os.ReadFile(filepath.Join("..", "calendar", "static", name))
93 if err != nil {
94 t.Errorf("read vendored %s: %v", name, err)
95 continue
96 }
97 if !bytes.Equal(vendored, lib) {
98 t.Errorf("static/%s differs from the library copy; re-copy it with rastrillo doctor --fix (or add it to vendoredIsMine if the edit was deliberate)", name)
99 }
100 }
101}
102
103// rastrillo's busy rule (Paul, 2026-09-29): a submit button's label gives
104// way to a spinner for at least 650ms, the button disables, and Back
105// resets it. static/ carries it as estilo does — the shim without the old
106// rule, busy.js and busy.css — pinned here to the estilo this app builds
107// against. After an estilo upgrade: go run ./scripts/writeestilo.
108func TestBusyFilesAreEstilos(t *testing.T) {
109 for name, want := range map[string][]byte{
110 "rastrillo.js": estilobusy.ShimJS(),
111 "busy.js": estilobusy.JS(),
112 "busy.css": estilobusy.CSS(),
113 } {
114 got, err := os.ReadFile(filepath.Join("..", "calendar", "static", name))
115 if err != nil {
116 t.Fatal(err)
117 }
118 if !bytes.Equal(got, want) {
119 t.Errorf("static/%s differs from estilo's; run go run ./scripts/writeestilo", name)
120 }
121 }
122}
123
124// The sign-in door's styles (Paul, 2026-09-29: every app's sign-in is a
125// version of the Oficina sign-in screen): estilo chrome's chrome.css,
126// which holds the [estilo-door] and [estilo-signin] rules, and the sky
127// behind it. Pinned to the estilo this app builds against. After an
128// estilo upgrade: go run ./scripts/writeestilo.
129func TestDoorFilesAreEstilos(t *testing.T) {
130 for name, want := range map[string][]byte{
131 "chrome.css": chrome.CSS(),
132 "sky.css": sky.CSS(),
133 } {
134 got, err := os.ReadFile(filepath.Join("..", "calendar", "static", name))
135 if err != nil {
136 t.Fatal(err)
137 }
138 if !bytes.Equal(got, want) {
139 t.Errorf("static/%s differs from estilo's; run go run ./scripts/writeestilo", name)
140 }
141 }
142}
143
144// The shared chrome's other files (estilo spec 2026-09-23 §1): base.css
145// (the link rule), menu.css (every floating panel) and chrome.js (Esc and
146// outside-click close). The layout links them in the spec's order after
147// theme.css. Pinned like the door's; after an estilo upgrade:
148// go run ./scripts/writeestilo.
149func TestSharedChromeFilesAreEstilos(t *testing.T) {
150 for name, want := range map[string][]byte{
151 "base.css": base.CSS(),
152 "menu.css": menu.CSS(),
153 "chrome.js": chrome.JS(),
154 } {
155 got, err := os.ReadFile(filepath.Join("..", "calendar", "static", name))
156 if err != nil {
157 t.Fatal(err)
158 }
159 if !bytes.Equal(got, want) {
160 t.Errorf("static/%s differs from estilo's; run go run ./scripts/writeestilo", name)
161 }
162 }
163}
164