Normalize size units and intrinsic sizing across Elisp and native layout. Add help, pointer, hover-style and keymap support with reusable interaction adapters. Keep content updates local, preserve scroll caches and hover borders, and avoid rebuilding retained plans and ownership metadata for stable geometry. Validation: make check and native-rust-tests passed; targeted native interaction and scroll publication regressions passed.
129 lines
6.1 KiB
EmacsLisp
129 lines
6.1 KiB
EmacsLisp
;;; ebox-size-tests.el --- Pure size expression contracts -*- lexical-binding: t; -*-
|
|
|
|
;;; Code:
|
|
|
|
(require 'ert)
|
|
(require 'ebox-size)
|
|
|
|
(ert-deftest ebox-size-explicit-units-resolve-against-their-reference ()
|
|
(let ((context '(:percent-base 300 :viewport-width 853 :viewport-height 701
|
|
:ch 8.5 :lh 19)))
|
|
(dolist (case '(((px 12.5) . 12.5) ((% 50) . 150.0)
|
|
((vw 33) . 281.49) ((vh 50) . 350.5)
|
|
((ch 80) . 680.0) ((lh 3) . 57)))
|
|
(should (ebox-size-value-p (car case)))
|
|
(should (< (abs (- (ebox-size-resolve (car case) context)
|
|
(cdr case)))
|
|
0.000001)))))
|
|
|
|
(ert-deftest ebox-size-fractions-survive-until-the-renderer ()
|
|
(should (= (ebox-size-resolve '(calc (- (vh 50) (lh 1)))
|
|
'(:viewport-height 931 :lh 19))
|
|
446.5))
|
|
(should (= (ebox-size-resolve '(calc (/ (px 3) 2)) nil) 1.5))
|
|
(should (= (ebox-size-resolve '(calc (* (/ 1 2) (lh 3))) '(:lh 19))
|
|
28.5)))
|
|
|
|
(ert-deftest ebox-size-math-preserves-dimensions-and-css-clamp-precedence ()
|
|
(let ((context '(:percent-base 300 :ch 8)))
|
|
(should (= (ebox-size-resolve '(min (% 100) (ch 80)) context) 300))
|
|
(should (= (ebox-size-resolve '(max (px 320) (% 50)) context) 320))
|
|
(should (= (ebox-size-resolve '(clamp (ch 20) (% 50) (ch 80)) context)
|
|
160))
|
|
;; CSS gives the minimum precedence when bounds are reversed.
|
|
(should (= (ebox-size-resolve '(clamp (px 80) (px 40) (px 20)) nil)
|
|
80))
|
|
(should (= (ebox-size-resolve '(calc (+ (px 10) (- (px 4)) (px -2)))
|
|
nil)
|
|
4))
|
|
(should (= (ebox-size-resolve '(calc (* (px 6) (min 2 3))) nil) 12))))
|
|
|
|
(ert-deftest ebox-size-missing-reference-defers-but-zero-resolves ()
|
|
(dolist (unit '(% vw vh ch lh))
|
|
(should-not (ebox-size-resolve (list unit 3) nil)))
|
|
(should-not (ebox-size-resolve '(min (px 20) (% 50)) nil))
|
|
(should-not (ebox-size-resolve '(calc (+ (vh 100) (px 1))) nil))
|
|
(should (= (ebox-size-resolve '(% 50) '(:percent-base 0)) 0))
|
|
(should (= (ebox-size-resolve '(calc (+ (vh 100) (px 1)))
|
|
'(:viewport-height 0))
|
|
1)))
|
|
|
|
(ert-deftest ebox-size-dependencies-are-recursive-distinct-and-stable ()
|
|
(let ((expression '(clamp (ch 20)
|
|
(calc (+ (% 30) (vw 4) (ch 2) (vh 1)))
|
|
(max (lh 8) (% 100)))))
|
|
(should (equal (ebox-size-dependencies expression)
|
|
'(ch percent viewport-width viewport-height lh)))
|
|
(should (equal (ebox-size-dependencies expression)
|
|
'(ch percent viewport-width viewport-height lh)))
|
|
(should-not (ebox-size-dependencies '(calc (+ (px 1) (px 2)))))))
|
|
|
|
(ert-deftest ebox-size-property-restrictions-apply-to-literals-and-dependencies ()
|
|
(should-not (ebox-size-value-p '(px -1)))
|
|
(should (ebox-size-value-p '(lh -1) t))
|
|
(should (ebox-size-value-p '(calc (- (px 1) (px 2)))))
|
|
(should (= (ebox-size-resolve '(calc (- (px 1) (px 2))) nil) -1))
|
|
(should (ebox-size-value-p '(% 50)))
|
|
(should-not (ebox-size-value-p '(% 50) t nil))
|
|
(should-not (ebox-size-value-p '(min (px 20) (calc (* 2 (% 10)))) t nil))
|
|
(should (ebox-size-value-p '(calc (- (vw 100) (px 1))) nil nil)))
|
|
|
|
(ert-deftest ebox-size-rejects-legacy-values-malformed-functions-and-unit-algebra ()
|
|
(dolist (value '(0 3 (240) "50%" auto viewport (viewport-height)
|
|
(fit-content (ch 80)) (em 2) (px) (px 1 2) (px "2")
|
|
(px . 2) (+ (px 1) (px 2))
|
|
(calc) (calc (px 1) (px 2)) (min) (max)
|
|
(clamp (px 1) (px 2)) (calc (+))
|
|
(calc (* (px 1) (px 2))) (calc (/ (px 1) (lh 2)))
|
|
(calc (+ (px 1) 1)) (min (px 1) 2)
|
|
(calc 2) (calc (/ 2 3))
|
|
(calc (/ (% 50) 0)) (calc (/ (px 1) (- 3 3)))
|
|
(calc (/ (px 1) 2 3))))
|
|
(should-not (ebox-size-value-p value t))
|
|
(should-error (ebox-size-resolve value nil) :type 'ebox-size-error)))
|
|
|
|
(ert-deftest ebox-size-rejects-nonfinite-input-context-and-overflow ()
|
|
(dolist (number (list 0.0e+NaN 1.0e+INF -1.0e+INF))
|
|
(should-not (ebox-size-value-p (list 'px number) t))
|
|
(should-error (ebox-size-resolve '(ch 1) (list :ch number))
|
|
:type 'ebox-size-error))
|
|
(should-error (ebox-size-resolve '(vh 1) '(:viewport-height -1))
|
|
:type 'ebox-size-error)
|
|
(should-not (ebox-size-value-p '(calc (* (px 1.0e+308) 10))))
|
|
(should-error (ebox-size-resolve '(ch 1.0e+308) '(:ch 100))
|
|
:type 'ebox-size-error))
|
|
|
|
(ert-deftest ebox-size-axis-contract-inspects-every-math-operand ()
|
|
"Property domains constrain every literal, even inside zero-valued math."
|
|
(dolist (case '((inline (px ch vw %) (lh vh))
|
|
(block (lh vh %) (px ch vw))
|
|
(stroke (px ch lh vw vh) (%))))
|
|
(dolist (unit (cadr case))
|
|
(should (ebox-size-value-for-axis-p (list unit 2) (car case))))
|
|
(dolist (unit (caddr case))
|
|
(let ((value (list unit 0)))
|
|
(dolist (expression
|
|
(list value (list 'min value value)
|
|
(list 'clamp value value value)
|
|
(list 'calc (list '* 0 value))
|
|
(list 'calc (list '- value value))))
|
|
(should (ebox-size-value-p expression))
|
|
(should-not (ebox-size-value-for-axis-p expression (car case)))
|
|
(should-error
|
|
(ebox-size-validate-for-axis expression :example (car case))
|
|
:type 'ebox-size-error))))))
|
|
|
|
(ert-deftest ebox-size-axis-errors-describe-property-and-allowed-units ()
|
|
"Malformed functions and unknown units give the same actionable context."
|
|
(dolist (value '((px 1) (rh 1) (calc (+ (lh 1) (px 0)))
|
|
(clamp (lh 1)) (lh -1) (lh "1")))
|
|
(let ((message
|
|
(condition-case condition
|
|
(progn (ebox-size-validate-for-axis value :height 'block) nil)
|
|
(ebox-size-error (error-message-string condition)))))
|
|
(should (string-match-p ":height" message))
|
|
(should (string-match-p "allowed units: (lh vh %)" message)))))
|
|
|
|
(provide 'ebox-size-tests)
|
|
;;; ebox-size-tests.el ends here
|