You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

317 lines
12 KiB

(ns formulare.core-test
(:require [clojure.test :refer :all]
[formulare.core :refer :all]
[clojure.string :refer [starts-with?]]
[clojure.spec.alpha :as spec]))
(deftest test-form-data
(testing "no from-req is given"
(let [def {:fields {:name {:label ""
:required false
:spec :a}}}]
(is (= {:name "a"}
(form-data def {:params {:name "a"}})))
(is (= {:name nil}
(form-data def {:params {}})))))
(testing "from-req is called"
(let [def {:fields {:name {:label ""
:required false
:spec :a
:from-req #(str "foo" %)}}}]
(is (= {:name "foo"}
(form-data def {:params {}})))
(is (= {:name "fooa"}
(form-data def {:params {:name "a"}})))))
(testing "from-req is given in one field, not in another"
(let [def {:fields {:foo {:label ""
:spec number?
:from-req bigint}
:bar {:label ""
:spec string?}}}]
(is (= {:foo 5
:bar "a"}
(form-data def {:params {:foo "5"
:bar "a"}})))))
(testing "type conversion"
(let [def {:fields {:foo {:label ""
:required false
:spec :a
:from-req bigint}}}]
(is (= {:foo 5}
(form-data def {:params {:foo 5}}))))))
(deftest test-valid?
(testing "required-key does not change validity of the form"
(let [def {:fields {:name {:label ""
:spec nil?
:required true}}}]
(is (= true (valid? def {:params {:name nil}}))))
(let [def {:fields {:name {:label ""
:spec nil?
:required false}}}]
(is (= true (valid? def {:params {:name nil}})))))
(testing "unconverted values are passed to spec"
(let [def {:fields {:foo {:label ""
:spec string?
:from-req bigint}
:bar {:label ""
:spec string?}}}]
(is (= true (valid? def {:params {:foo "5"
:bar "a"}}))))))
(deftest test-render-widgets
(testing "form-hash is rendered"
(let [def {:fields {}}]
(is (= (list [:input {:type "hidden"
:name "__form-hash"
:id "__form-hash"
:value (form-hash def {})}])
(rest (render-widgets def {} {}))))))
(testing "anti-forgery-field is rendered"
(let [def {:fields {}}]
(is (starts-with? (first (render-widgets def {} {}))
(str "<input id=\"__anti-forgery-token\""
" name=\"__anti-forgery-token\""
" type=\"hidden\"")))))
(testing "input is rendered correctly"
(let [def {:fields {:foo-id {:label "foo-label"
:widget :input}}}]
(is (= (list nil
[:label {:for "foo-id"} "foo-label"]
[:input {:id "foo-id"
:name "foo-id"
:required false
:type "text"
:value nil}])
(first
(nthrest
(render-widgets def {} {})
2)))))
(let [def {:fields {:foo-id {:label "foo-label"
:required true
:widget :input}}}]
(is (= (list nil
[:label {:for "foo-id"} "foo-label"]
[:input {:id "foo-id"
:name "foo-id"
:required true
:type "text"
:value nil}])
(first
(nthrest
(render-widgets def {} {})
2)))))
(testing "input is default"
(let [def {:fields {:foo-id {:label "foo-label"
:required true}}}]
(is (= (list nil
[:label {:for "foo-id"} "foo-label"]
[:input {:id "foo-id"
:name "foo-id"
:required true
:type "text"
:value nil}])
(first
(nthrest
(render-widgets def {} {})
2)))))))
(testing "checkbox is rendered correctly"
(let [def {:fields {:foo-id {:label "foo-label"
:widget :checkbox}}}]
(is (= (list nil
[:label {:for "foo-id"} "foo-label"]
[:input {:id "foo-id"
:name "foo-id"
:checked false
:type "checkbox"
:value nil}])
(first
(nthrest
(render-widgets def {} {})
2)))))
(let [def {:fields {:foo-id {:label "foo-label"
:required true
:widget :checkbox}}}]
(is (= (list nil
[:label {:for "foo-id"} "foo-label"]
[:input {:id "foo-id"
:name "foo-id"
:checked false
:type "checkbox"
:value nil}])
(first
(nthrest
(render-widgets def {} {})
2))))))
(testing "textarea is rendered correctly"
(let [def {:fields {:foo-id {:label "foo-label"
:widget :textarea}}}]
(is (= (list nil
[:label {:for "foo-id"} "foo-label"]
[:textarea {:id "foo-id"
:name "foo-id"
:required false}
""])
(first
(nthrest
(render-widgets def {} {})
2)))))
(let [def {:fields {:foo-id {:label "foo-label"
:required true
:widget :textarea}}}]
(is (= (list nil
[:label {:for "foo-id"} "foo-label"]
[:textarea {:id "foo-id"
:name "foo-id"
:required true}
""])
(first
(nthrest
(render-widgets def {} {})
2))))))
(testing "select is rendered correctly"
(let [def {:fields {:foo-id {:label "foo-label"
:widget :select
:options [["value1" "key1"]
["value2" "key2"]]}}}]
(is (= (list nil
[:label {:for "foo-id"} "foo-label"]
[:select {:id "foo-id"
:name "foo-id"}
(list
[:option {:value "key1" :selected false} "value1"]
[:option {:value "key2" :selected false} "value2"])])
(first
(nthrest
(render-widgets def {} {})
2))))))
(testing "hidden is rendered correctly"
(let [def {:fields {:foo-id {:label "foo-label"
:widget :hidden}}}]
(is (= (list nil
nil
[:input {:id "foo-id"
:type "hidden"
:name "foo-id"
:value nil}])
(first
(nthrest
(render-widgets def {} {})
2)))))
(let [def {:fields {:foo-id {:label "foo-label"
:widget :hidden}}}]
(is (= (list nil
nil
[:input {:id "foo-id"
:type "hidden"
:name "foo-id"
:value "4711"}])
(first
(nthrest
(render-widgets def {:foo-id "4711"} {})
2))))))
(testing "mselect is rendered correctly"
(let [def {:fields {:foo-id {:label "foo-label"
:widget :mselect
:options [["value1" "key1"]
["value2" "key2"]]}}}]
(is (= (list nil
[:label {:for "foo-id"} "foo-label"]
[:select {:id "foo-id"
:name "foo-id"
:size 5
:multiple "multiple"}
(list
[:option {:value "key1" :selected false} "value1"]
[:option {:value "key2" :selected false} "value2"])])
(first
(nthrest
(render-widgets def {} {})
2))))))
(testing "input-widget uses :attr"
(let [def {:fields {:foor-id {:attrs {:autofocus true}}}}
rendered-input (-> (render-widgets def {} {})
(nthrest 2)
first
(nthrest 2)
first)
input-attrs (second rendered-input)]
(contains? input-attrs :autofocus)
(is (= true (:autofocus input-attrs)))))
(testing "render-anti-forgery-field"
(testing "default is true"
(let [def {:fields {:foo-id {}}}
rendered-input (-> (render-widgets def {} {})
first)]
(is (string? rendered-input))
(is (starts-with? rendered-input "<input id=\"__anti-forgery-token"))
(is (clojure.string/includes? rendered-input
"name=\"__anti-forgery-token\""))))))
(deftest to-form-is-used
(testing "data passed to fo-form is taken from values"
(let [def {:fields {:foo {:label ""
:to-form (partial str "4711")}}}]
(is (= (list nil
[:label {:for "foo"} ""]
[:input {:id "foo"
:name "foo"
:value "4711abc"
:required false
:type "text"}])
(first
(nthrest
(render-widgets def {:foo "abc"} {})
2)))))
(let [def {:fields {:foo {:label ""
:to-form (partial str "4711")}}}]
(is (= (list nil
[:label {:for "foo"} ""]
[:input {:id "foo"
:name "foo"
:value "4711abc"
:required false
:type "text"}])
(first
(nthrest
(render-widgets def {:foo "abc"} {:params {:foo "def"}})
2)))))))
(deftest form-specs-is-applied
(testing "valid spec"
(let [def {:fields {}
:form-specs [(fn [req] true)]}]
(is (= [:input {:type "hidden"
:name "__form-hash"
:id "__form-hash"
:value (form-hash def {})}]
(second
(render-widgets
def
{}
{:params {:__form-hash (form-hash def {})}}))))))
(testing "invalid spec"
(let [def {:fields {}
:form-specs [(fn [req] false)]}]
(is (= [:section.flash--error
[:h2.flash__heading--error "Warning"]
[:p "The form must comply to " (name :clojure.spec.alpha/unknown)]]
(first
(render-widgets
def
{}
{:params {:__form-hash (form-hash def {})}})))))))
(deftest html-contents-are-escaped
(testing "mselect"
(let [def {:fields {:foo {:widget :mselect
:options [["<>" "key1"]]}}}]
(is (= [:option {:value "key1" :selected false} "&lt;&gt;"]
(-> (render-widgets def {} {})
(nthrest 2)
first
(nth 2)
(nth 2)
first))))))