src/image-render-test.lua
1#!/usr/bin/env luajit
2-- image-render-test.lua
3--
4-- Regression test for URL-encoding of image filenames in the rendered HTML.
5--
6-- General description: an artist's PNG can be named anything -- including names
7-- with spaces and a literal "?" (e.g. a real file in ~/pictures/my-art that
8-- ends in "...TROUBLE-U-?-message-...png"). When such a name was dropped raw
9-- into an <img src="..."> the browser cut the path at the first space, or
10-- treated everything after the "?" as a query string, and drew a broken-image
11-- icon. This test pins the fix: format_image_entry() and text_image_link() must
12-- percent-encode the basename so the link reaches the real file on disk.
13--
14-- Runnable from any directory; it locates the source beside itself.
15
16-- {{{ locate the module beside this test, regardless of caller's cwd
17local DIR = arg[0]:match("^(.*)/[^/]+$") or "."
18package.path = DIR .. "/?.lua;" .. package.path
19local image_render = require("image-render")
20-- }}}
21
22local failures = 0
23
24-- {{{ local function check()
25local function check(label, condition)
26 if condition then
27 print(" ok - " .. label)
28 else
29 print(" FAIL - " .. label)
30 failures = failures + 1
31 end
32end
33-- }}}
34
35-- The actual offending filename pattern from the my-art catalog: spaces AND a
36-- question mark. If either survives un-encoded into an attribute the image 404s.
37local NASTY = "wawawwawawa ABC JK ? TROUBLE-U-?-message.png"
38-- A "looks like junk but is URL-safe" name -- all letters/digits. Must pass
39-- through UNCHANGED (we do not want gratuitous encoding of safe characters).
40local SAFE_JUNK = "hbidrtszezdsgvfty6.png"
41
42-- {{{ test: format_image_entry encodes the <img src>
43do
44 local poem = {
45 display_title = "test",
46 attachments = { { relative_path = NASTY, width = 100, height = 50 } },
47 }
48 local html = image_render.format_image_entry(poem)
49 local src = html:match('<img src="([^"]*)"')
50 check("format_image_entry emits an <img src>", src ~= nil)
51 check("space is percent-encoded (%20)", src:find("%%20") ~= nil)
52 check("question mark is percent-encoded (%3F)", src:find("%%3F") ~= nil)
53 check("no raw space survives in src", src:find(" ") == nil)
54 check("no raw '?' survives in src", src:find("%?") == nil)
55end
56-- }}}
57
58-- {{{ test: text_image_link encodes the <a href>
59do
60 local poem = { attachments = { { relative_path = NASTY } } }
61 local link = image_render.text_image_link(poem)
62 local href = link:match('<a href="([^"]*)"')
63 check("text_image_link emits an <a href>", href ~= nil)
64 check("href has no raw space", href:find(" ") == nil)
65 check("href has no raw '?'", href:find("%?") == nil)
66end
67-- }}}
68
69-- {{{ test: URL-safe junk filename is left untouched
70do
71 local poem = { attachments = { { relative_path = SAFE_JUNK } } }
72 local link = image_render.text_image_link(poem)
73 check("safe filename passes through unencoded",
74 link:find(SAFE_JUNK, 1, true) ~= nil)
75end
76-- }}}
77
78-- Namespacing (the collision fix): art images keep their source + subdirs so two
79-- files sharing a basename map to two different output/media/ paths; Mastodon
80-- hashes (not under input/images/) stay flat.
81local ROOT = "/mnt/mtwo/programming/ai-stuff/neocities-modernization"
82local ART_A = ROOT .. "/input/images/my-art/proposed-movement-design.png"
83local ART_B = ROOT .. "/input/images/my-art/game-design/proposed-movement-design.png"
84local MASTODON = ROOT .. "/input/media_attachments/files/112/500/670/original/ad3a0a69d3dcf172.png"
85
86local function src_of(path)
87 local html = image_render.format_image_entry(
88 { display_title = "t", attachments = { { relative_path = path, width = 1, height = 1 } } })
89 return html:match('<img src="([^"]*)"')
90end
91
92-- {{{ test: art keeps source + subdir; same-name files no longer collide
93do
94 local a, b = src_of(ART_A), src_of(ART_B)
95 check("art src keeps source prefix (my-art/)", a:find("my-art/proposed-movement-design.png", 1, true) ~= nil)
96 check("art src in subdir keeps the subdir (my-art/game-design/)",
97 b:find("my-art/game-design/proposed-movement-design.png", 1, true) ~= nil)
98 check("same basename, different subdir -> DIFFERENT src (collision fixed)", a ~= b)
99end
100-- }}}
101
102-- {{{ test: Mastodon hash stays flat (basename only, no nesting)
103do
104 local s = src_of(MASTODON)
105 check("mastodon src is the bare hash", s:find("ad3a0a69d3dcf172.png", 1, true) ~= nil)
106 check("mastodon src has no media_attachments nesting", s:find("media_attachments") == nil)
107 check("mastodon src has no files/ nesting", s:find("/files/") == nil)
108end
109-- }}}
110
111if failures == 0 then
112 print("ALL PASS")
113 os.exit(0)
114else
115 print(failures .. " FAILURE(S)")
116 os.exit(1)
117end
118