forked from bots-garden/ori
| ✨ Workspace panel, selectors, previews, desktop app, sandbox template, resizable file tree, light/dark theme | 1 | package files_test |
| 2 | ||
| 3 | import ( | |
| 4 | "net/http" | |
| 5 | "os" | |
| 6 | "path/filepath" | |
| 7 | "testing" | |
| 8 | ||
| 9 | "rickub.com/bots-garden/ori/internal/files" | |
| 10 | ) | |
| 11 | ||
| 12 | var pngHeader = []byte{0x89, 'P', 'N', 'G', 0x0d, 0x0a, 0x1a, 0x0a, 0, 0, 0, 0} | |
| 13 | ||
| 14 | func TestRawStreamsBytesWithImageContentType(t *testing.T) { | |
| 15 | root, h := workspace(t) | |
| 16 | if err := os.WriteFile(filepath.Join(root, "logo.png"), pngHeader, 0o644); err != nil { | |
| 17 | t.Fatal(err) | |
| 18 | } | |
| 19 | ||
| 20 | rec := do(t, h, http.MethodGet, "/api/raw?path=logo.png", "") | |
| 21 | if rec.Code != http.StatusOK { | |
| 22 | t.Fatalf("GET raw = %d (%s)", rec.Code, rec.Body.String()) | |
| 23 | } | |
| 24 | if got := rec.Header().Get("Content-Type"); got != "image/png" { | |
| 25 | t.Errorf("Content-Type = %q, want image/png", got) | |
| 26 | } | |
| 27 | if got := rec.Body.Bytes(); string(got) != string(pngHeader) { | |
| 28 | t.Errorf("body = %v, want the exact file bytes", got) | |
| 29 | } | |
| 30 | if rec.Header().Get("Content-Length") != "12" { | |
| 31 | t.Errorf("Content-Length = %q, want 12", rec.Header().Get("Content-Length")) | |
| 32 | } | |
| 33 | } | |
| 34 | ||
| 35 | func TestRawAcceptsAbsolutePathsLikeTheOtherEndpoints(t *testing.T) { | |
| 36 | root, h := workspace(t) | |
| 37 | rec := do(t, h, http.MethodGet, "/api/raw?path="+filepath.Join(root, "README.md"), "") | |
| 38 | if rec.Code != http.StatusOK || rec.Body.String() != "# hello" { | |
| 39 | t.Errorf("absolute raw read = %d %q", rec.Code, rec.Body.String()) | |
| 40 | } | |
| 41 | if got := rec.Header().Get("Content-Type"); got != "text/markdown; charset=utf-8" { | |
| 42 | t.Errorf("Content-Type = %q, want the mime table's markdown type", got) | |
| 43 | } | |
| 44 | } | |
| 45 | ||
| 46 | func TestRawErrors(t *testing.T) { | |
| 47 | _, h := workspace(t) | |
| 48 | cases := []struct { | |
| 49 | target string | |
| 50 | want int | |
| 51 | }{ | |
| 52 | {"/api/raw", http.StatusBadRequest}, | |
| 53 | {"/api/raw?path=src", http.StatusBadRequest}, | |
| 54 | {"/api/raw?path=ghost.png", http.StatusNotFound}, | |
| 55 | } | |
| 56 | for _, tc := range cases { | |
| 57 | if rec := do(t, h, http.MethodGet, tc.target, ""); rec.Code != tc.want { | |
| 58 | t.Errorf("GET %s = %d, want %d", tc.target, rec.Code, tc.want) | |
| 59 | } | |
| 60 | } | |
| 61 | } | |
| 62 | ||
| 63 | func TestContentTypeFor(t *testing.T) { | |
| 64 | cases := []struct { | |
| 65 | path string | |
| 66 | head []byte | |
| 67 | want string | |
| 68 | }{ | |
| 69 | {"a.png", nil, "image/png"}, | |
| 70 | {"a.JPG", nil, "image/jpeg"}, | |
| 71 | {"a.jpeg", nil, "image/jpeg"}, | |
| 72 | {"a.gif", nil, "image/gif"}, | |
| 73 | {"a.webp", nil, "image/webp"}, | |
| 74 | {"a.svg", nil, "image/svg+xml"}, | |
| 75 | {"diagram.drawio.svg", nil, "image/svg+xml"}, | |
| 76 | {"a.bmp", nil, "image/bmp"}, | |
| 77 | {"a.ico", nil, "image/x-icon"}, | |
| 78 | {"a.avif", nil, "image/avif"}, | |
| 79 | {"a.json", nil, "application/json"}, | |
| 80 | {"noext", []byte("plain words"), "text/plain; charset=utf-8"}, | |
| 81 | } | |
| 82 | for _, tc := range cases { | |
| 83 | if got := files.ContentTypeFor(tc.path, tc.head); got != tc.want { | |
| 84 | t.Errorf("ContentTypeFor(%q) = %q, want %q", tc.path, got, tc.want) | |
| 85 | } | |
| 86 | } | |
| 87 | } |