internal/server/server_test.go (view raw)
1package server
2
3import (
4 "context"
5 "io"
6 "net/http"
7 "net/http/httptest"
8 "strconv"
9 "strings"
10 "testing"
11
12 "codeberg.org/maxwelljensen/weimar/internal/auth"
13 "codeberg.org/maxwelljensen/weimar/internal/db"
14)
15
16func TestHandleOGPreview_ServesAllRequiredTags(t *testing.T) {
17 database, err := db.Open(":memory:")
18 if err != nil {
19 t.Fatalf("open db: %v", err)
20 }
21 t.Cleanup(func() { database.Close() })
22 if err := database.Migrate(context.Background()); err != nil {
23 t.Fatalf("migrate: %v", err)
24 }
25
26 // Create a user and an image directly.
27 auth.Register(context.Background(), database, "testuser", "password123", false)
28 img, err := database.CreateImage(context.Background(), &db.Image{
29 Filename: "photo.jpg",
30 StoragePath: "ab/cd/ef/abcdef.jpg",
31 UploadedBy: 1,
32 FileSize: 204800,
33 Width: 1920,
34 Height: 1080,
35 MimeType: "image/jpeg",
36 })
37 if err != nil {
38 t.Fatalf("create image: %v", err)
39 }
40
41 // Construct a minimal Server with just the fields needed by handleOGPreview.
42 s := &Server{
43 db: database,
44 // spaH is only called on error (missing image); we never hit it in this test.
45 spaH: func(w http.ResponseWriter, r *http.Request) {},
46 }
47
48 idStr := strconv.FormatInt(img.ID, 10)
49 req := httptest.NewRequest("GET", "/image/"+idStr, nil)
50 req.SetPathValue("id", idStr)
51 w := httptest.NewRecorder()
52
53 s.handleOGPreview(w, req)
54
55 resp := w.Result()
56 body, _ := io.ReadAll(resp.Body)
57 resp.Body.Close()
58 html := string(body)
59
60 if resp.StatusCode != 200 {
61 t.Fatalf("status = %d, want 200; body:\n%s", resp.StatusCode, html)
62 }
63
64 ct := resp.Header.Get("Content-Type")
65 if !strings.HasPrefix(ct, "text/html") {
66 t.Fatalf("Content-Type = %q, want text/html", ct)
67 }
68
69 // Verify all required OG tags are present by content.
70 required := []string{
71 `og:title`,
72 `og:description`,
73 `og:url`,
74 `og:image`,
75 `og:image:secure_url`,
76 `og:type`,
77 `og:locale`,
78 `twitter:card`,
79 `twitter:image`,
80 }
81 for _, tag := range required {
82 if !strings.Contains(html, tag) {
83 t.Errorf("missing meta tag: %s", tag)
84 }
85 }
86
87 // Verify specific values.
88 if !strings.Contains(html, "photo.jpg") {
89 t.Errorf("expected filename in OG title, got:\n%s", html)
90 }
91 if !strings.Contains(html, "testuser") {
92 t.Errorf("expected uploader in description, got:\n%s", html)
93 }
94 if !strings.Contains(html, "1920") {
95 t.Errorf("expected width in OG image:width, got:\n%s", html)
96 }
97 if strings.Contains(html, "&") || strings.Contains(html, "<") {
98 t.Errorf("HTML appears double-escaped:\n%s", html)
99 }
100 // Should NOT contain the SPA title placeholder.
101 if strings.Contains(html, "weimar") && !strings.Contains(html, "og:site_name") {
102 t.Errorf("response appears to be SPA fallback, not OG page:\n%s", html)
103 }
104}