Files
rose-ash/spec/tests/test-text-layout.sx
giles 854ed9c027 Hyperscript conformance: 372→373 — hide/show strategy, generator toEqual
Parser: hide/show handle `with opacity/visibility/display` strategy,
target detection for then-less chaining (add/remove/set/put as boundary).
Generator: inline run().toEqual([...]) pattern for eval-only tests.
Compiler: hide/show emit correct CSS property per strategy.

373/831 (45%)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 11:42:28 +00:00

177 lines
5.5 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
;; ==========================================================================
;; test-text-layout.sx — Tests for Pretext (DOM-free text layout)
;; ==========================================================================
;; All tests use fixed widths — no IO, pure arithmetic verification.
;; --------------------------------------------------------------------------
;; Line breaking
;; --------------------------------------------------------------------------
(defsuite
"line-badness"
(deftest
"exact fit has zero badness"
(assert-equal 0 (line-badness 100 100)))
(deftest
"underfull line has positive badness"
(assert (> (line-badness 50 100) 0)))
(deftest
"overfull line has large badness"
(assert (> (line-badness 110 100) 10000))))
(defsuite
"compute-demerits"
(deftest
"zero badness and penalty gives 1"
(assert-equal 1 (compute-demerits 0 0)))
(deftest
"badness contributes quadratically"
(assert-equal 121 (compute-demerits 10 0)))
(deftest
"penalty adds independently"
(assert-equal 26 (compute-demerits 0 5))))
(defsuite
"sum-widths"
(deftest
"single word"
(assert-equal 10 (sum-widths (list 10 20 30) 5 0 1)))
(deftest
"two words with space"
(assert-equal 35 (sum-widths (list 10 20 30) 5 0 2)))
(deftest
"three words with spaces"
(assert-equal 70 (sum-widths (list 10 20 30) 5 0 3)))
(deftest
"subset range"
(assert-equal 55 (sum-widths (list 10 20 30) 5 1 3))))
(defsuite
"break-lines"
(deftest "empty input" (assert-equal (list) (break-lines (list) 5 100)))
(deftest
"all words fit on one line"
(let
((result (break-lines (list 10 20 30) 5 100)))
(assert-equal 1 (len result))
(assert-equal (list 0 3) (first result))))
(deftest
"forced two-line break"
(let
((result (break-lines (list 40 40) 5 50)))
(assert-equal 2 (len result))
(assert-equal (list 0 1) (first result))
(assert-equal (list 1 2) (nth result 1))))
(deftest
"three lines from five words"
(let
((result (break-lines (list 30 30 30 30 30) 5 70)))
(assert-equal 3 (len result))))
(deftest
"single word per line when words are wide"
(let
((result (break-lines (list 80 80 80) 5 90)))
(assert-equal 3 (len result)))))
;; --------------------------------------------------------------------------
;; Positioning
;; --------------------------------------------------------------------------
(defsuite
"position-line"
(deftest
"single word at origin"
(let
((result (position-line (list "hello") (list 50) 5 0 0)))
(assert-equal 1 (len result))
(assert-equal 0 (get (first result) :x))
(assert-equal 0 (get (first result) :y))
(assert-equal "hello" (get (first result) :word))))
(deftest
"two words spaced apart"
(let
((result (position-line (list "hi" "there") (list 20 40) 5 0 10)))
(assert-equal 2 (len result))
(assert-equal 0 (get (first result) :x))
(assert-equal 25 (get (nth result 1) :x))
(assert-equal 10 (get (nth result 1) :y))))
(deftest
"custom x offset"
(let
((result (position-line (list "word") (list 30) 5 10 0)))
(assert-equal 10 (get (first result) :x)))))
(defsuite
"position-lines"
(deftest
"two lines stacked vertically"
(let
((result (position-lines (list "a" "b" "c" "d") (list 10 10 10 10) (list (list 0 2) (list 2 4)) 5 20 0 0)))
(assert-equal 2 (len result))
(assert-equal 0 (get (first (first result)) :y))
(assert-equal 20 (get (first (nth result 1)) :y)))))
;; --------------------------------------------------------------------------
;; Hyphenation
;; --------------------------------------------------------------------------
(defsuite
"hyphenation-trie"
(deftest
"build trie from patterns"
(let
((trie (make-hyphenation-trie (list "hy1p" "he2n"))))
(assert (dict? trie))
(assert (has-key? trie :children))))
(deftest
"trie has expected structure"
(let
((trie (make-hyphenation-trie (list "ab1c"))))
(assert (has-key? (get trie :children) "a")))))
(defsuite
"hyphenate-word"
(deftest
"word with no patterns returns single syllable"
(let
((trie (make-hyphenation-trie (list))))
(assert-equal (list "xyz") (hyphenate-word trie "xyz"))))
(deftest
"simple hyphenation"
(let
((trie (make-hyphenation-trie (list "hy1phen"))))
(let
((syllables (hyphenate-word trie "hyphen")))
(assert (>= (len syllables) 1))))))
;; --------------------------------------------------------------------------
;; Integration: break + position
;; --------------------------------------------------------------------------
(defsuite
"layout-integration"
(deftest
"break and position round-trip"
(let
((widths (list 30 30 30 30))
(words (list "one" "two" "three" "four"))
(space-width 5)
(max-width 70)
(line-height 20))
(let
((ranges (break-lines widths space-width max-width)))
(let
((positioned (position-lines words widths ranges space-width line-height 0 0)))
(assert (> (len positioned) 0))
(assert-equal 0 (get (first (first positioned)) :x))
(assert-equal 0 (get (first (first positioned)) :y))))))
(deftest
"total height is lines × line-height"
(let
((widths (list 80 80 80))
(space-width 5)
(max-width 90)
(line-height 20))
(let
((ranges (break-lines widths space-width max-width)))
(assert-equal 3 (len ranges))))))