src/poem-bars.test.lua
1-- Tests for poem-bars.lua. The bug these guard against: the bar width drifting
2-- (88 chars, doubled ╧╧) instead of a fixed 83 with two single junctions.
3-- Run: luajit src/poem-bars.test.lua
4package.path = "./src/?.lua;./libs/?.lua;" .. package.path
5local B = require("poem-bars")
6B.configure({ gray = "#868E96", blue = "#74C0FC" })
7
8local passed, failed = 0, 0
9local function check(name, cond)
10 if cond then passed = passed + 1 else failed = failed + 1; print(" FAIL: " .. name) end
11end
12
13-- Strip HTML tags, then count UTF-8 codepoints (box chars are 3 bytes each).
14local function visible(s)
15 local txt = s:gsub("<[^>]+>", "")
16 local _, n = txt:gsub("[^\128-\191]", "") -- count non-continuation bytes = codepoints
17 return n, txt
18end
19local function count(s, ch)
20 local _, n = s:gsub(ch, "")
21 return n
22end
23
24-- The width must hold at every progress level (the drift made it vary / overrun).
25for _, pct in ipairs({0, 1, 37, 50, 99, 100}) do
26 local bar = B.progress_dashes({ percentage = pct }, "blue", false, "bottom", true)
27 local n, txt = visible(bar.visual)
28 check("regular bottom bar is 83 wide @ " .. pct .. "%", n == 83)
29 -- Exactly two junctions (╧ when in progress, ┴ when not) -- never ╧╧ doubled.
30 local junctions = count(txt, "╧") + count(txt, "┴")
31 check("regular bottom bar has exactly 2 junctions @ " .. pct .. "%", junctions == 2)
32 check("regular bottom bar starts with left corner ╘ @ " .. pct .. "%", txt:sub(1, #"╘") == "╘")
33end
34
35-- Junctions must land at columns 10 and 70 (under the inner box walls).
36do
37 local bar = B.progress_dashes({ percentage = 0 }, "gray", false, "bottom", true)
38 local _, txt = visible(bar.visual)
39 -- Walk codepoints, record junction columns (0-indexed).
40 local col, cols = 0, {}
41 for cp in txt:gmatch("[\1-\127\194-\244][\128-\191]*") do
42 if cp == "╧" or cp == "┴" then cols[#cols + 1] = col end
43 col = col + 1
44 end
45 check("junctions at columns 10 and 70", cols[1] == 10 and cols[2] == 70)
46end
47
48-- Corner box top is 83 wide.
49do
50 local n = visible(B.corner_box_top(40, "#74C0FC"))
51 check("corner box top is 83 wide", n == 83)
52end
53
54-- Nav line is 83 wide WITH and WITHOUT the center chronological link.
55do
56 local sim = "<a href='x'>similar</a>"
57 local dif = "<a href='y'>different</a>"
58 local chrono = "<a href='z'>chronological</a>"
59 local n_with = visible(B.corner_box_nav_line(sim, dif, chrono, 40, "#74C0FC"))
60 local n_without = visible(B.corner_box_nav_line(sim, dif, nil, 40, "#74C0FC"))
61 check("nav line 83 wide with center link", n_with == 83)
62 check("nav line 83 wide without center link", n_without == 83)
63end
64
65-- Golden bottom bar is 84 wide (╚ + 82 interior + ┘) with two junctions.
66do
67 local bar = B.progress_dashes({ percentage = 50 }, "blue", true, "bottom", true)
68 local n, txt = visible(bar.visual)
69 check("golden bottom bar is 84 wide", n == 84)
70 -- Golden: left junction is double-up (╩/╨), right is single-up (╧/┴).
71 check("golden bottom bar has 2 junctions",
72 count(txt, "╩") + count(txt, "╨") + count(txt, "╧") + count(txt, "┴") == 2)
73 check("golden left junction is double-up", count(txt, "╩") + count(txt, "╨") == 1)
74end
75
76-- Golden nav builders are 84 wide (golden poems carry two outer ║ walls).
77do
78 local sim, dif = "<a href='x'>similar</a>", "<a href='y'>different</a>"
79 local chrono = "<a href='z'>chronological</a>"
80 check("golden separator is 84 wide", visible(B.golden_corner_box_separator("#74C0FC")) == 84)
81 check("golden nav line 84 with center", visible(B.golden_corner_box_nav_line(sim, dif, chrono, "#74C0FC")) == 84)
82 check("golden nav line 84 without center", visible(B.golden_corner_box_nav_line(sim, dif, nil, "#74C0FC")) == 84)
83end
84
85-- Fill frontier: the similar box's RIGHT edge (col 10) is single until the
86-- progress sweeps past it, then double. Left edge (frame) is always double.
87do
88 local sep_low = B.golden_corner_box_separator("#74C0FC", 4):gsub("<[^>]+>", "")
89 check("low progress: right corner single (┐, no ╗)",
90 sep_low:find("┐", 1, true) ~= nil and sep_low:find("╗", 1, true) == nil)
91 check("low progress: left corner still double (╠)", sep_low:find("╠", 1, true) ~= nil)
92 local sep_hi = B.golden_corner_box_separator("#74C0FC", 40):gsub("<[^>]+>", "")
93 check("high progress: right corner double (╗)", sep_hi:find("╗", 1, true) ~= nil)
94 local nav_low = B.golden_corner_box_nav_line("<a>similar</a>", "<a>different</a>", nil, "#74C0FC", 4):gsub("<[^>]+>", "")
95 check("low progress: nav right wall single (║ similar │)", nav_low:find("║ similar │", 1, true) ~= nil)
96end
97
98print(string.format("\npoem-bars: %d passed, %d failed", passed, failed))
99os.exit(failed == 0 and 0 or 1)
100