Skip to content

Commit 080ef4c

Browse files
committed
Add tests for root-served files and fix manifest content type
Go does not auto-detect application/manifest+json for .webmanifest files, so set the Content-Type header explicitly. Add table-driven tests covering status, content type, cache headers, and body for all root-served files (favicon, manifest, robots, service-worker).
1 parent 9ceaafd commit 080ef4c

2 files changed

Lines changed: 85 additions & 0 deletions

File tree

internal/ui/routes.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ func handleFavicon(mux *http.ServeMux, root fs.FS) {
6868

6969
func handleManifest(mux *http.ServeMux, root fs.FS) {
7070
mux.Handle("GET /manifest.webmanifest", cacheHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
71+
w.Header().Set("Content-Type", "application/manifest+json")
7172
http.ServeFileFS(w, r, root, "root/manifest.webmanifest")
7273
}), staticCacheMaxAge))
7374
}

internal/ui/routes_test.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package ui
2+
3+
import (
4+
"io/fs"
5+
"net/http"
6+
"net/http/httptest"
7+
"testing"
8+
"testing/fstest"
9+
)
10+
11+
func TestRootFiles(t *testing.T) {
12+
root := fstest.MapFS{
13+
"root/favicon.ico": &fstest.MapFile{Data: []byte("icon")},
14+
"root/manifest.webmanifest": &fstest.MapFile{Data: []byte(`{"name":"test"}`)},
15+
"root/robots.txt": &fstest.MapFile{Data: []byte("User-agent: *")},
16+
"root/service-worker.js": &fstest.MapFile{Data: []byte("// sw")},
17+
}
18+
19+
tests := []struct {
20+
name string
21+
path string
22+
handler func(*http.ServeMux, fs.FS)
23+
contentType string
24+
body string
25+
}{
26+
{
27+
name: "favicon",
28+
path: "/favicon.ico",
29+
handler: handleFavicon,
30+
contentType: "image/vnd.microsoft.icon",
31+
body: "icon",
32+
},
33+
{
34+
name: "manifest",
35+
path: "/manifest.webmanifest",
36+
handler: handleManifest,
37+
contentType: "application/manifest+json",
38+
body: `{"name":"test"}`,
39+
},
40+
{
41+
name: "robots",
42+
path: "/robots.txt",
43+
handler: handleRobots,
44+
contentType: "text/plain; charset=utf-8",
45+
body: "User-agent: *",
46+
},
47+
{
48+
name: "service-worker",
49+
path: "/service-worker.js",
50+
handler: handleServiceWorker,
51+
contentType: "text/javascript; charset=utf-8",
52+
body: "// sw",
53+
},
54+
}
55+
56+
for _, tt := range tests {
57+
t.Run(tt.name, func(t *testing.T) {
58+
mux := http.NewServeMux()
59+
tt.handler(mux, root)
60+
61+
req := httptest.NewRequest(http.MethodGet, tt.path, nil)
62+
rr := httptest.NewRecorder()
63+
mux.ServeHTTP(rr, req)
64+
65+
if rr.Code != http.StatusOK {
66+
t.Errorf("expected status 200, got %d", rr.Code)
67+
}
68+
69+
ct := rr.Header().Get("Content-Type")
70+
if ct != tt.contentType {
71+
t.Errorf("expected Content-Type %q, got %q", tt.contentType, ct)
72+
}
73+
74+
cc := rr.Header().Get("Cache-Control")
75+
if cc == "" {
76+
t.Error("expected Cache-Control header to be set")
77+
}
78+
79+
if body := rr.Body.String(); body != tt.body {
80+
t.Errorf("expected body %q, got %q", tt.body, body)
81+
}
82+
})
83+
}
84+
}

0 commit comments

Comments
 (0)