7 new suites: inline-edit (edit/save/cancel cycle), row-editing (form load + save), profile-editing (edit + put), tabs (content + OOB buttons), loading-indicator (sleep + content), bulk-operations (activate users), dedup-search. Total: 29 suites, 41 tests. All example handlers now have swap integration coverage. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
647 lines
20 KiB
Plaintext
647 lines
20 KiB
Plaintext
(define _mock-form (dict))
|
|
|
|
(define _mock-args (dict))
|
|
|
|
(define _mock-state (dict))
|
|
|
|
(define _mock-body "")
|
|
|
|
(define _mock-content-type "")
|
|
|
|
(define _mock-headers (dict))
|
|
|
|
(define _mock-now "12:00:00")
|
|
|
|
(define
|
|
reset-mocks!
|
|
(fn
|
|
()
|
|
(do
|
|
(set! _mock-form (dict))
|
|
(set! _mock-args (dict))
|
|
(set! _mock-state (dict))
|
|
(set! _mock-body "")
|
|
(set! _mock-content-type "")
|
|
(set! _mock-headers (dict)))))
|
|
|
|
(define
|
|
helper
|
|
(fn
|
|
(name a1 a2)
|
|
(cond
|
|
(= name "request-form")
|
|
(let
|
|
((key (or a1 "")) (default (if (nil? a2) "" a2)))
|
|
(let ((val (get _mock-form key))) (if (nil? val) default val)))
|
|
(= name "request-arg")
|
|
(let
|
|
((key (or a1 "")) (default a2))
|
|
(let ((val (get _mock-args key))) (if (nil? val) default val)))
|
|
(= name "state-get")
|
|
(let
|
|
((key (or a1 "")) (default a2))
|
|
(let ((val (get _mock-state key))) (if (nil? val) default val)))
|
|
(= name "state-set!")
|
|
(do (set! _mock-state (assoc _mock-state a1 a2)) nil)
|
|
(= name "now")
|
|
_mock-now
|
|
(= name "component-source")
|
|
(str "(defcomp " a1 " () (div))")
|
|
(= name "request-json")
|
|
_mock-body
|
|
(= name "request-content-type")
|
|
_mock-content-type
|
|
(= name "request-form-list")
|
|
(or (get _mock-form a1) (list))
|
|
(= name "request-args-all")
|
|
_mock-args
|
|
(= name "request-headers-all")
|
|
_mock-headers
|
|
(= name "request-form-all")
|
|
_mock-form
|
|
(= name "request-header")
|
|
(or (get _mock-headers a1) a2)
|
|
(= name "request-file-name")
|
|
(or (get _mock-form a1) "")
|
|
(= name "into")
|
|
(let
|
|
((coll (if (nil? a2) a1 a2)))
|
|
(if
|
|
(dict? coll)
|
|
(map (fn (key) (list key (get coll key))) (keys coll))
|
|
(if (nil? coll) (list) coll)))
|
|
:else nil)))
|
|
|
|
(define sleep (fn (ms) nil))
|
|
|
|
(define set-response-status (fn (code) nil))
|
|
|
|
(define json-encode (fn (val) (inspect val)))
|
|
|
|
(define random-int (fn (lo hi) lo))
|
|
|
|
(define
|
|
run-handler
|
|
(fn
|
|
(hdef)
|
|
(do
|
|
(let
|
|
((params (get hdef "params")) (closure (get hdef "closure")))
|
|
(when
|
|
(and params (not (empty? params)))
|
|
(for-each
|
|
(fn
|
|
(p)
|
|
(let
|
|
((val (get _mock-args p)))
|
|
(env-bind! closure p (or val nil))))
|
|
params)))
|
|
(let
|
|
((result (aser (get hdef "body") (get hdef "closure"))))
|
|
(if
|
|
(sx-expr? result)
|
|
(sx-expr-source result)
|
|
(if (string? result) result (str result)))))))
|
|
|
|
(defsuite
|
|
"swap:click-to-load"
|
|
(deftest
|
|
"innerHTML replaces target content"
|
|
(reset-mocks!)
|
|
(let
|
|
((page "(div :id \"click-result\" (p \"Click the button\"))")
|
|
(response (run-handler handler:ex-click)))
|
|
(let
|
|
((result (sx-swap page "innerHTML" "click-result" response)))
|
|
(do
|
|
(assert-true (contains? result "~examples/click-result"))
|
|
(assert-true (contains? result "12:00:00"))
|
|
(assert-false (contains? result "Click the button")))))))
|
|
|
|
(defsuite
|
|
"swap:form-submission"
|
|
(deftest
|
|
"innerHTML replaces with greeting"
|
|
(reset-mocks!)
|
|
(set! _mock-form {:name "Alice"})
|
|
(let
|
|
((page "(div :id \"form-result\" (p \"Submit the form\"))")
|
|
(response (run-handler handler:ex-form)))
|
|
(let
|
|
((result (sx-swap page "innerHTML" "form-result" response)))
|
|
(do
|
|
(assert-true (contains? result "Alice"))
|
|
(assert-false (contains? result "Submit the form")))))))
|
|
|
|
(defsuite
|
|
"swap:polling"
|
|
(deftest
|
|
"innerHTML shows counter after increment"
|
|
(reset-mocks!)
|
|
(let
|
|
((page "(div :id \"poll-result\" (p \"Waiting...\"))")
|
|
(response (run-handler handler:ex-poll)))
|
|
(let
|
|
((result (sx-swap page "innerHTML" "poll-result" response)))
|
|
(do
|
|
(assert-true (contains? result "1"))
|
|
(assert-false (contains? result "Waiting")))))))
|
|
|
|
(defsuite
|
|
"swap:oob-updates"
|
|
(deftest
|
|
"primary + OOB both update"
|
|
(reset-mocks!)
|
|
(let
|
|
((page "(div (div :id \"oob-box-a\" (p \"A old\")) (div :id \"oob-box-b\" (p \"B old\")))")
|
|
(response (run-handler handler:ex-oob)))
|
|
(let
|
|
((result (apply-response page response "innerHTML" "oob-box-a")))
|
|
(do
|
|
(assert-true (contains? result "Box A updated!"))
|
|
(assert-true (contains? result "Box B updated!"))
|
|
(assert-false (contains? result "A old"))
|
|
(assert-false (contains? result "B old")))))))
|
|
|
|
(defsuite
|
|
"swap:search"
|
|
(deftest
|
|
"innerHTML replaces search results"
|
|
(reset-mocks!)
|
|
(set! _mock-args {:q "Python"})
|
|
(let
|
|
((page "(div :id \"search-result\" (p \"Type to search\"))")
|
|
(response (run-handler handler:ex-search)))
|
|
(let
|
|
((result (sx-swap page "innerHTML" "search-result" response)))
|
|
(do
|
|
(assert-true (contains? result "Python"))
|
|
(assert-false (contains? result "Type to search")))))))
|
|
|
|
(defsuite
|
|
"swap:delete-row"
|
|
(deftest
|
|
"outerHTML removes element"
|
|
(let
|
|
((page "(table (tr :id \"row-1\" (td \"Item 1\")) (tr :id \"row-2\" (td \"Item 2\")))")
|
|
(response ""))
|
|
(let
|
|
((result (sx-swap page "outerHTML" "row-1" response)))
|
|
(do
|
|
(assert-false (contains? result "Item 1"))
|
|
(assert-true (contains? result "Item 2")))))))
|
|
|
|
(defsuite
|
|
"swap:beforeend"
|
|
(deftest
|
|
"appends new item to list"
|
|
(let
|
|
((page "(ul :id \"items\" (li \"first\"))") (response "(li \"second\")"))
|
|
(let
|
|
((result (sx-swap page "beforeend" "items" response)))
|
|
(do
|
|
(assert-true (contains? result "first"))
|
|
(assert-true (contains? result "second")))))))
|
|
|
|
(defsuite
|
|
"swap:infinite-scroll"
|
|
(deftest
|
|
"page 1 appends items to container"
|
|
(reset-mocks!)
|
|
(set! _mock-args {:page "1"})
|
|
(let
|
|
((page "(div :id \"scroll-items\" (div \"Item 0 — seed\"))")
|
|
(response (run-handler handler:ex-scroll)))
|
|
(let
|
|
((result (sx-swap page "beforeend" "scroll-items" response)))
|
|
(do
|
|
(assert-true (contains? result "Item 0"))
|
|
(assert-true (contains? result "Item 1"))
|
|
(assert-true (contains? result "page 1"))
|
|
(assert-true (contains? result "scroll-sentinel"))))))
|
|
(deftest
|
|
"page 2 appends more items"
|
|
(reset-mocks!)
|
|
(set! _mock-args {:page "2"})
|
|
(let
|
|
((page "(div :id \"scroll-items\" (div \"page 1 items\"))")
|
|
(response (run-handler handler:ex-scroll)))
|
|
(let
|
|
((result (sx-swap page "beforeend" "scroll-items" response)))
|
|
(do
|
|
(assert-true (contains? result "page 1 items"))
|
|
(assert-true (contains? result "Item 6"))
|
|
(assert-true (contains? result "page 2"))))))
|
|
(deftest
|
|
"last page has no sentinel"
|
|
(reset-mocks!)
|
|
(set! _mock-args {:page "6"})
|
|
(let
|
|
((page "(div :id \"scroll-items\")")
|
|
(response (run-handler handler:ex-scroll)))
|
|
(let
|
|
((result (sx-swap page "beforeend" "scroll-items" response)))
|
|
(do
|
|
(assert-true (contains? result "All items loaded"))
|
|
(assert-false (contains? result "scroll-sentinel")))))))
|
|
|
|
(defsuite
|
|
"swap:state-across-calls"
|
|
(deftest
|
|
"counter increments across handler calls"
|
|
(reset-mocks!)
|
|
(let
|
|
((r1 (run-handler handler:ex-poll)))
|
|
(let
|
|
((r2 (run-handler handler:ex-poll)))
|
|
(let
|
|
((page "(div :id \"counter\" (span \"0\"))")
|
|
(result (sx-swap page "innerHTML" "counter" r2)))
|
|
(assert-true (contains? result "2")))))))
|
|
|
|
(defsuite
|
|
"swap:dashboard"
|
|
(deftest
|
|
"innerHTML replaces with stats"
|
|
(reset-mocks!)
|
|
(let
|
|
((page "(div :id \"dash-content\" (p \"Loading...\"))")
|
|
(response (run-handler handler:ex-dashboard)))
|
|
(let
|
|
((result (sx-swap page "innerHTML" "dash-content" response)))
|
|
(do
|
|
(assert-true (contains? result "142"))
|
|
(assert-true (contains? result "Revenue"))
|
|
(assert-false (contains? result "Loading")))))))
|
|
|
|
(defsuite
|
|
"swap:lazy-load"
|
|
(deftest
|
|
"innerHTML replaces placeholder"
|
|
(reset-mocks!)
|
|
(let
|
|
((page "(div :id \"lazy-target\" (p \"Loading...\"))")
|
|
(response (run-handler handler:ex-lazy)))
|
|
(let
|
|
((result (sx-swap page "innerHTML" "lazy-target" response)))
|
|
(do
|
|
(assert-true (contains? result "~examples/lazy-result"))
|
|
(assert-true (contains? result "12:00:00"))
|
|
(assert-false (contains? result "Loading")))))))
|
|
|
|
(defsuite
|
|
"swap:dialog"
|
|
(deftest
|
|
"innerHTML opens modal"
|
|
(reset-mocks!)
|
|
(let
|
|
((page "(div :id \"dialog-target\")")
|
|
(response (run-handler handler:ex-dialog)))
|
|
(let
|
|
((result (sx-swap page "innerHTML" "dialog-target" response)))
|
|
(do
|
|
(assert-true (contains? result "~examples/dialog-modal"))
|
|
(assert-true (contains? result "Confirm Action"))))))
|
|
(deftest
|
|
"innerHTML closes modal"
|
|
(reset-mocks!)
|
|
(let
|
|
((page "(div :id \"dialog-target\" (~examples/dialog-modal))")
|
|
(response (run-handler handler:ex-dialog-close)))
|
|
(let
|
|
((result (sx-swap page "innerHTML" "dialog-target" response)))
|
|
(assert-false (contains? result "dialog-modal"))))))
|
|
|
|
(defsuite
|
|
"swap:keyboard"
|
|
(deftest
|
|
"dispatches action for known key"
|
|
(reset-mocks!)
|
|
(set! _mock-args {:key "s"})
|
|
(let
|
|
((page "(div :id \"kbd-result\" (p \"Press a key\"))")
|
|
(response (run-handler handler:ex-keyboard)))
|
|
(let
|
|
((result (sx-swap page "innerHTML" "kbd-result" response)))
|
|
(do
|
|
(assert-true (contains? result "Search panel activated"))
|
|
(assert-false (contains? result "Press a key"))))))
|
|
(deftest
|
|
"shows unknown for unmapped key"
|
|
(reset-mocks!)
|
|
(set! _mock-args {:key "z"})
|
|
(let
|
|
((page "(div :id \"kbd-result\")")
|
|
(response (run-handler handler:ex-keyboard)))
|
|
(let
|
|
((result (sx-swap page "innerHTML" "kbd-result" response)))
|
|
(assert-true (contains? result "Unknown key: z"))))))
|
|
|
|
(defsuite
|
|
"swap:validate"
|
|
(deftest
|
|
"empty email shows required"
|
|
(reset-mocks!)
|
|
(set! _mock-args {:email ""})
|
|
(let
|
|
((page "(div :id \"validate-result\")")
|
|
(response (run-handler handler:ex-validate)))
|
|
(let
|
|
((result (sx-swap page "innerHTML" "validate-result" response)))
|
|
(assert-true (contains? result "Email is required")))))
|
|
(deftest
|
|
"missing @ shows format error"
|
|
(reset-mocks!)
|
|
(set! _mock-args {:email "bad"})
|
|
(let
|
|
((page "(div :id \"validate-result\")")
|
|
(response (run-handler handler:ex-validate)))
|
|
(let
|
|
((result (sx-swap page "innerHTML" "validate-result" response)))
|
|
(assert-true (contains? result "Invalid email format")))))
|
|
(deftest
|
|
"valid email shows ok"
|
|
(reset-mocks!)
|
|
(set! _mock-args {:email "new@example.com"})
|
|
(let
|
|
((page "(div :id \"validate-result\")")
|
|
(response (run-handler handler:ex-validate)))
|
|
(let
|
|
((result (sx-swap page "innerHTML" "validate-result" response)))
|
|
(assert-true (contains? result "~examples/validation-ok"))))))
|
|
|
|
(defsuite
|
|
"swap:validate-submit"
|
|
(deftest
|
|
"valid email submits"
|
|
(reset-mocks!)
|
|
(set! _mock-form {:email "hi@example.com"})
|
|
(let
|
|
((page "(div :id \"validate-form-result\")")
|
|
(response (run-handler handler:ex-validate-submit)))
|
|
(let
|
|
((result (sx-swap page "innerHTML" "validate-form-result" response)))
|
|
(assert-true (contains? result "hi@example.com")))))
|
|
(deftest
|
|
"empty email rejects"
|
|
(reset-mocks!)
|
|
(set! _mock-form {:email ""})
|
|
(let
|
|
((page "(div :id \"validate-form-result\")")
|
|
(response (run-handler handler:ex-validate-submit)))
|
|
(let
|
|
((result (sx-swap page "innerHTML" "validate-form-result" response)))
|
|
(assert-true (contains? result "valid email"))))))
|
|
|
|
(defsuite
|
|
"swap:dependent-select"
|
|
(deftest
|
|
"returns options for category"
|
|
(reset-mocks!)
|
|
(set! _mock-args {:category "Languages"})
|
|
(let
|
|
((page "(select :id \"values-result\")")
|
|
(response (run-handler handler:ex-values)))
|
|
(let
|
|
((result (sx-swap page "innerHTML" "values-result" response)))
|
|
(do
|
|
(assert-true (contains? result "Python"))
|
|
(assert-true (contains? result "Rust"))))))
|
|
(deftest
|
|
"empty category returns no items"
|
|
(reset-mocks!)
|
|
(set! _mock-args {:category "Nonexistent"})
|
|
(let
|
|
((page "(select :id \"values-result\")")
|
|
(response (run-handler handler:ex-values)))
|
|
(let
|
|
((result (sx-swap page "innerHTML" "values-result" response)))
|
|
(assert-true (contains? result "No items"))))))
|
|
|
|
(defsuite
|
|
"swap:form-reset"
|
|
(deftest
|
|
"echoes submitted message"
|
|
(reset-mocks!)
|
|
(set! _mock-form {:message "Hello world"})
|
|
(let
|
|
((page "(div :id \"reset-result\")")
|
|
(response (run-handler handler:ex-reset-submit)))
|
|
(let
|
|
((result (sx-swap page "innerHTML" "reset-result" response)))
|
|
(assert-true (contains? result "Hello world"))))))
|
|
|
|
(defsuite
|
|
"swap:swap-modes-log"
|
|
(deftest
|
|
"beforeend appends log entry with OOB counter"
|
|
(reset-mocks!)
|
|
(set! _mock-args {:mode "beforeend"})
|
|
(let
|
|
((page "(div (div :id \"swap-log\") (span :id \"swap-counter\" \"Count: 0\"))")
|
|
(response (run-handler handler:ex-swap-log)))
|
|
(let
|
|
((result (apply-response page response "beforeend" "swap-log")))
|
|
(do
|
|
(assert-true (contains? result "beforeend"))
|
|
(assert-true (contains? result "Count: 1")))))))
|
|
|
|
(defsuite
|
|
"swap:json-echo"
|
|
(deftest
|
|
"echoes content type and body"
|
|
(reset-mocks!)
|
|
(set! _mock-body "{\"key\":\"val\"}")
|
|
(set! _mock-content-type "application/json")
|
|
(let
|
|
((page "(div :id \"json-result\")")
|
|
(response (run-handler handler:ex-json-echo)))
|
|
(let
|
|
((result (sx-swap page "innerHTML" "json-result" response)))
|
|
(do
|
|
(assert-true (contains? result "application/json"))
|
|
(assert-true (contains? result "~examples/json-result")))))))
|
|
|
|
(defsuite
|
|
"swap:retry"
|
|
(deftest
|
|
"first two calls return empty (503)"
|
|
(reset-mocks!)
|
|
(let
|
|
((r1 (run-handler handler:ex-flaky)))
|
|
(let
|
|
((r2 (run-handler handler:ex-flaky)))
|
|
(do (assert-equal r1 "") (assert-equal r2 "")))))
|
|
(deftest
|
|
"third call succeeds"
|
|
(reset-mocks!)
|
|
(let
|
|
((r1 (run-handler handler:ex-flaky)))
|
|
(let
|
|
((r2 (run-handler handler:ex-flaky)))
|
|
(let
|
|
((r3 (run-handler handler:ex-flaky)))
|
|
(let
|
|
((page "(div :id \"retry-result\" (p \"Retrying...\"))")
|
|
(result (sx-swap page "innerHTML" "retry-result" r3)))
|
|
(do
|
|
(assert-true (contains? result "~examples/retry-result"))
|
|
(assert-true (contains? result "Success"))
|
|
(assert-false (contains? result "Retrying")))))))))
|
|
|
|
(defsuite
|
|
"swap:animate"
|
|
(deftest
|
|
"returns color and timestamp"
|
|
(reset-mocks!)
|
|
(let
|
|
((page "(div :id \"anim-result\")")
|
|
(response (run-handler handler:ex-animate)))
|
|
(let
|
|
((result (sx-swap page "innerHTML" "anim-result" response)))
|
|
(do
|
|
(assert-true (contains? result "~anim-result"))
|
|
(assert-true (contains? result "12:00:00")))))))
|
|
|
|
(defsuite
|
|
"swap:inline-edit"
|
|
(deftest
|
|
"edit form loads current value"
|
|
(reset-mocks!)
|
|
(set! _mock-args {:value "Hello" :id "42"})
|
|
(let
|
|
((page "(div :id \"edit-target\" (span \"Hello\"))")
|
|
(response (run-handler handler:ex-edit-form)))
|
|
(let
|
|
((result (sx-swap page "innerHTML" "edit-target" response)))
|
|
(assert-true (contains? result "~examples/inline-edit-form")))))
|
|
(deftest
|
|
"save returns updated view"
|
|
(reset-mocks!)
|
|
(set! _mock-form {:value "Updated"})
|
|
(let
|
|
((page "(div :id \"edit-target\" (input))")
|
|
(response (run-handler handler:ex-edit-save)))
|
|
(let
|
|
((result (sx-swap page "innerHTML" "edit-target" response)))
|
|
(assert-true (contains? result "Updated")))))
|
|
(deftest
|
|
"cancel restores original"
|
|
(reset-mocks!)
|
|
(set! _mock-args {:value "Original" :id "42"})
|
|
(let
|
|
((page "(div :id \"edit-target\" (input))")
|
|
(response (run-handler handler:ex-edit-cancel)))
|
|
(let
|
|
((result (sx-swap page "innerHTML" "edit-target" response)))
|
|
(assert-true (contains? result "Original"))))))
|
|
|
|
(defsuite
|
|
"swap:row-editing"
|
|
(deftest
|
|
"form loads row data"
|
|
(reset-mocks!)
|
|
(set! _mock-args {:row-id "r1"})
|
|
(set! _mock-state {:ex-row-r1 {:stock "5" :id "r1" :price "$10" :name "Widget"}})
|
|
(let
|
|
((page "(tr :id \"row-r1\" (td \"Widget\"))")
|
|
(response (run-handler handler:ex-editrow-form)))
|
|
(let
|
|
((result (sx-swap page "outerHTML" "row-r1" response)))
|
|
(do
|
|
(assert-true (contains? result "~examples/edit-row-form"))
|
|
(assert-true (contains? result "Widget"))))))
|
|
(deftest
|
|
"save stores and returns view"
|
|
(reset-mocks!)
|
|
(set! _mock-form {:id "r1" :price "$20" :name "Gadget"})
|
|
(let
|
|
((page "(tr :id \"row-r1\" (input))")
|
|
(response (run-handler handler:ex-editrow-save)))
|
|
(let
|
|
((result (sx-swap page "outerHTML" "row-r1" response)))
|
|
(assert-true (contains? result "Gadget"))))))
|
|
|
|
(defsuite
|
|
"swap:profile-editing"
|
|
(deftest
|
|
"edit loads profile fields"
|
|
(reset-mocks!)
|
|
(set! _mock-state {:ex-profile {:email "ada@example.com" :role "Engineer" :name "Ada"}})
|
|
(let
|
|
((page "(div :id \"profile-target\" (p \"Ada\"))")
|
|
(response (run-handler handler:ex-pp-edit-all)))
|
|
(let
|
|
((result (sx-swap page "innerHTML" "profile-target" response)))
|
|
(assert-true (contains? result "~examples/pp-form-full")))))
|
|
(deftest
|
|
"put saves and returns view"
|
|
(reset-mocks!)
|
|
(set! _mock-form {:email "grace@example.com" :role "Captain" :name "Grace"})
|
|
(let
|
|
((page "(div :id \"profile-target\" (form))")
|
|
(response (run-handler handler:ex-pp-put)))
|
|
(let
|
|
((result (sx-swap page "innerHTML" "profile-target" response)))
|
|
(assert-true (contains? result "Grace"))))))
|
|
|
|
(defsuite
|
|
"swap:tabs"
|
|
(deftest
|
|
"returns tab content with OOB buttons"
|
|
(reset-mocks!)
|
|
(set! _mock-args {:tab "tab1"})
|
|
(let
|
|
((page "(div (div :id \"tab-content\" (p \"old\")) (div :id \"tab-buttons\" (button \"old\")))")
|
|
(response (run-handler handler:ex-tabs)))
|
|
(let
|
|
((result (apply-response page response "innerHTML" "tab-content")))
|
|
(do
|
|
(assert-true (contains? result "~examples/tab-btn"))
|
|
(assert-false (contains? result "\"old\"")))))))
|
|
|
|
(defsuite
|
|
"swap:loading-indicator"
|
|
(deftest
|
|
"slow handler returns content after mock sleep"
|
|
(reset-mocks!)
|
|
(let
|
|
((page "(div :id \"loading-result\" (p \"Loading...\"))")
|
|
(response (run-handler handler:ex-slow)))
|
|
(let
|
|
((result (sx-swap page "innerHTML" "loading-result" response)))
|
|
(do
|
|
(assert-true (contains? result "~examples/loading-result"))
|
|
(assert-true (contains? result "12:00:00"))
|
|
(assert-false (contains? result "Loading")))))))
|
|
|
|
(defsuite
|
|
"swap:bulk-operations"
|
|
(deftest
|
|
"activates selected users"
|
|
(reset-mocks!)
|
|
(set! _mock-args {:action "activate"})
|
|
(set! _mock-form {:ids (list "u1" "u2")})
|
|
(set! _mock-state {:ex-bulk-u2 {:status "inactive" :id "u2" :name "Bob"} :ex-bulk-u1 {:status "inactive" :id "u1" :name "Alice"}})
|
|
(let
|
|
((page "(tbody :id \"bulk-rows\" (tr \"old\"))")
|
|
(response (run-handler handler:ex-bulk)))
|
|
(let
|
|
((result (sx-swap page "innerHTML" "bulk-rows" response)))
|
|
(assert-true (contains? result "~examples/bulk-row"))))))
|
|
|
|
(defsuite
|
|
"swap:dedup-search"
|
|
(deftest
|
|
"returns search result"
|
|
(reset-mocks!)
|
|
(set! _mock-args {:q "test"})
|
|
(let
|
|
((page "(div :id \"search-result\" (p \"Searching...\"))")
|
|
(response (run-handler handler:ex-slow-search)))
|
|
(let
|
|
((result (sx-swap page "innerHTML" "search-result" response)))
|
|
(do
|
|
(assert-true (contains? result "~examples/sync-result"))
|
|
(assert-false (contains? result "Searching")))))))
|