oficina / estilo Public

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

Plain git — no account needed to clone.

Download

Download this file

1package brand
2
3import (
4 "bytes"
5 "encoding/json"
6 "net/http"
7 "net/http/httptest"
8 "os"
9 "testing"
10
11 "amadan.net/oficina/estilo.git/theme"
12)
13
14// The icons' colours and the apps' accents are one ring: icons.json must
15// carry exactly the hues theme/apps.go does, app for app.
16func TestIconHuesAreTheThemeRing(t *testing.T) {
17 raw, err := os.ReadFile("icons.json")
18 if err != nil {
19 t.Fatal(err)
20 }
21 var icons []struct {
22 ID string `json:"id"`
23 Hue *float64 `json:"hue"`
24 }
25 if err := json.Unmarshal(raw, &icons); err != nil {
26 t.Fatal(err)
27 }
28 seen := map[string]bool{}
29 for _, icon := range icons {
30 seen[icon.ID] = true
31 app, ok := theme.Lookup(icon.ID)
32 switch {
33 case !ok:
34 t.Errorf("icons.json has %q, which is not on the theme ring", icon.ID)
35 case icon.ID == "oficina":
36 if icon.Hue != nil {
37 t.Error("Oficina's mark is every hue, not one; its icons.json hue must be null")
38 }
39 case icon.Hue == nil || *icon.Hue != app.Hue:
40 t.Errorf("%s: icons.json hue %v, theme ring %v", icon.ID, icon.Hue, app.Hue)
41 }
42 if SVG(icon.ID) == nil {
43 t.Errorf("%s has no generated svg/", icon.ID)
44 }
45 }
46 for _, app := range theme.Apps() {
47 if !seen[app.Slug] {
48 t.Errorf("%s is on the theme ring but has no icon", app.Slug)
49 }
50 }
51}
52
53func TestEveryAppHasAnIcon(t *testing.T) {
54 for _, slug := range []string{"oficina", "docs", "sheets", "slides", "calendar", "calls", "memoria", "fichas", "mail", "files"} {
55 body := SVG(slug)
56 if !bytes.HasPrefix(bytes.TrimSpace(body), []byte("<svg")) {
57 t.Errorf("%s: not an svg", slug)
58 }
59 }
60 if !bytes.Equal(SVG("meet"), SVG("calls")) {
61 t.Error("meet, Calls' old name, does not give Calls' icon")
62 }
63 if SVG("../go.mod") != nil || SVG("") != nil || SVG("home") != nil {
64 t.Error("an unknown slug returned artwork")
65 }
66}
67
68func TestHandler(t *testing.T) {
69 h := Handler()
70 get := func(method, path string) *httptest.ResponseRecorder {
71 w := httptest.NewRecorder()
72 h.ServeHTTP(w, httptest.NewRequest(method, path, nil))
73 return w
74 }
75 w := get("GET", Path("docs"))
76 docs, _ := os.ReadFile("svg/docs.svg")
77 if w.Code != 200 || w.Header().Get("Content-Type") != "image/svg+xml" || w.Header().Get("X-Content-Type-Options") != "nosniff" || !bytes.Equal(w.Body.Bytes(), docs) {
78 t.Fatalf("GET docs: %d %q", w.Code, w.Header())
79 }
80 if w := get("HEAD", Path("sheets")); w.Code != 200 || w.Body.Len() != 0 {
81 t.Fatalf("HEAD: %d %d", w.Code, w.Body.Len())
82 }
83 for _, p := range []string{Prefix + "docs", Prefix + "nope.svg", Prefix + "../brand.css", "/elsewhere/docs.svg", Prefix} {
84 if w := get("GET", p); w.Code != http.StatusNotFound {
85 t.Errorf("%s: %d", p, w.Code)
86 }
87 }
88 if w := get("POST", Path("docs")); w.Code != http.StatusMethodNotAllowed {
89 t.Errorf("POST: %d", w.Code)
90 }
91}
92