AtlatestRepositorysigil-css
1
;;; Tests for (sigil css) - S-expression CSS DSL3
(import (sigil test))4
(import (sigil css))6
(test-group "css basic rules"7
(test "single property"8
(assert-equal9
(css->string (css ".card" (color "red")))10
".card {\n color: red;\n}\n\n"))12
(test "multiple properties"13
(assert-equal14
(css->string (css ".card" (color "red") (padding "1rem")))15
".card {\n color: red;\n padding: 1rem;\n}\n\n"))17
(test "empty rule (no properties)"18
(assert-equal19
(css->string (css ".empty"))20
""))22
(test "property with multiple values"23
(assert-equal24
(css->string (css ".box" (margin "1rem" "2rem")))25
".box {\n margin: 1rem 2rem;\n}\n\n")))27
(test-group "css nesting"28
(test "pseudo-class with &"29
(let ((result (css->string30
(css ".button"31
(color "white")32
(& ":hover"33
(background "blue"))))))34
;; Should have both .button and .button:hover rules35
(assert-true (string-contains? result ".button {"))36
(assert-true (string-contains? result ".button:hover {"))))38
(test "multiple nested rules"39
(let ((result (css->string40
(css ".link"41
(color "blue")42
(& ":hover" (color "red"))43
(& ":active" (color "purple"))))))44
(assert-true (string-contains? result ".link {"))45
(assert-true (string-contains? result ".link:hover {"))46
(assert-true (string-contains? result ".link:active {")))))48
(test-group "css-vars"49
(test "single variable"50
(let ((result (css->string (css-vars (--bg "#000")))))51
(assert-true (string-contains? result ":root {"))52
(assert-true (string-contains? result "--bg: #000"))))54
(test "multiple variables"55
(let ((result (css->string56
(css-vars57
(--bg "#0a0a0a")58
(--fg "#e0e0e0")59
(--accent "#f0c040")))))60
(assert-true (string-contains? result "--bg: #0a0a0a"))61
(assert-true (string-contains? result "--fg: #e0e0e0"))62
(assert-true (string-contains? result "--accent: #f0c040")))))64
(test-group "css-media"65
(test "simple media query"66
(let ((result (css->string67
(css-media "(max-width: 768px)"68
(css ".sidebar"69
(display "none"))))))70
(assert-true (string-contains? result "@media (max-width: 768px)"))71
(assert-true (string-contains? result ".sidebar {"))))73
(test "media query with multiple rules"74
(let ((result (css->string75
(css-media "(max-width: 768px)"76
(css ".sidebar" (visibility "hidden"))77
(css ".content" (width "100%"))))))78
(assert-true (string-contains? result ".sidebar {"))79
(assert-true (string-contains? result ".content {")))))81
(test-group "unit helpers"82
(test "px"83
(assert-equal (px 200) "200px"))85
(test "rem"86
(assert-equal (rem 1) "1rem"))88
(test "em"89
(assert-equal (em 0.5) "0.5em"))91
(test "%"92
(assert-equal (% 100) "100%"))94
(test "units in css rule"95
(let ((result (css->string96
(css ".box"97
(width (px 200))98
(padding (rem 1))))))99
(assert-true (string-contains? result "width: 200px"))100
(assert-true (string-contains? result "padding: 1rem")))))102
(test-group "color helpers"103
(test "rgb"104
(assert-equal (rgb 255 128 0) "rgb(255, 128, 0)"))106
(test "rgba"107
(assert-equal (rgba 255 128 0 0.5) "rgba(255, 128, 0, 0.5)"))109
(test "hsl"110
(assert-equal (hsl 180 50 50) "hsl(180, 50%, 50%)")))112
(test-group "theme support"113
(test "theme-ref reads from theme alist"114
(let ((theme '((bg . "#000") (fg . "#fff"))))115
(assert-equal (theme-ref theme 'bg) "#000")116
(assert-equal (theme-ref theme 'fg) "#fff")117
(assert-false (theme-ref theme 'nonexistent))))119
(test "theme-var generates var() reference"120
(assert-equal (theme-var 'fg) "var(--fg)")121
(assert-equal (theme-var 'background-color) "var(--background-color)"))123
(test "theme->css-vars generates :root"124
(let* ((theme '((bg . "#000") (fg . "#fff")))125
(result (css->string (theme->css-vars theme))))126
(assert-true (string-contains? result ":root {"))127
(assert-true (string-contains? result "--bg: #000"))128
(assert-true (string-contains? result "--fg: #fff"))))130
(test "theme-var in css rule"131
(let* ((val (theme-var 'fg))132
(result (css->string (css ".text" (color val)))))133
(assert-true (string-contains? result "color: var(--fg)")))))135
(test-group "css-combine"136
(test "combines multiple fragments"137
(let ((result (css->string138
(css-combine139
(css ".a" (color "red"))140
(css ".b" (color "blue"))))))141
(assert-true (string-contains? result ".a {"))142
(assert-true (string-contains? result ".b {")))))144
(test-group "important"145
(test "adds !important"146
(assert-equal (important "red") "red !important"))148
(test "important with number"149
(assert-equal (important 42) "42 !important")))151
(test-group "integration"152
(test "complete stylesheet"153
(let ((result (css->string154
(css-vars155
(--primary "#007bff")156
(--bg "#ffffff"))157
(css "body"158
(margin "0")159
(background "var(--bg)"))160
(css ".button"161
(padding (px 10) (px 20))162
(background "var(--primary)")163
(& ":hover"164
(opacity "0.9")))165
(css-media "(max-width: 600px)"166
(css ".button"167
(width "100%"))))))168
;; Check all parts are present169
(assert-true (string-contains? result ":root {"))170
(assert-true (string-contains? result "--primary: #007bff"))171
(assert-true (string-contains? result "body {"))172
(assert-true (string-contains? result ".button {"))173
(assert-true (string-contains? result ".button:hover {"))174
(assert-true (string-contains? result "@media (max-width: 600px)")))))176
(test-group "css-sel"177
(test "joins selectors with comma"178
(assert-equal (css-sel ".a" ".b") ".a, .b"))180
(test "single selector passes through"181
(assert-equal (css-sel ".a") ".a"))183
(test "three selectors"184
(assert-equal (css-sel ".a" ".b" ".c") ".a, .b, .c"))186
(test "compound selector in css rule"187
(let ((result (css->string188
(css (css-sel ".btn" "button[type=submit]")189
(padding "0.5rem")))))190
(assert-true (string-contains? result ".btn, button[type=submit] {"))))192
(test "compound selector with & nesting"193
(let ((result (css->string194
(css (css-sel ".btn" "button[type=submit]")195
(color "white")196
(& ":hover"197
(background "blue"))))))198
(assert-true (string-contains? result ".btn, button[type=submit] {"))199
(assert-true (string-contains? result ".btn:hover, button[type=submit]:hover {"))))201
(test "pseudo-element with &"202
(let ((result (css->string203
(css "dialog"204
(border "none")205
(& "::backdrop"206
(background "rgba(0,0,0,0.5)"))))))207
(assert-true (string-contains? result "dialog {"))208
(assert-true (string-contains? result "dialog::backdrop {"))))210
(test "attribute selector without quotes"211
(let ((result (css->string212
(css "input[type=text]"213
(padding "0.5rem")))))214
(assert-true (string-contains? result "input[type=text] {")))))216
;;; Helper for string-contains? if not available217
(define (string-contains? str substr)218
(let ((str-len (string-length str))219
(sub-len (string-length substr)))220
(let loop ((i 0))221
(cond222
((> (+ i sub-len) str-len) #f)223
((string=? (substring str i (+ i sub-len)) substr) #t)224
(else (loop (+ i 1)))))))226
(run-tests)