8
我已經開發了Om/React組件,但是我感覺真的很不舒服,不能用單元測試來推動我的開發。我試圖設置我的clojurescript項目來對這些組件運行單元測試,並且到目前爲止我已經能夠編寫單元測試並實例化組件。我所缺少的是能夠確保我的組件正確地對某些事件做出反應,例如onChange
,以便我可以模擬用戶輸入。如何正確(單元)測試Om/React組件?
這裏是我的測試代碼:
(defn simulate-click-event
"From https://github.com/levand/domina/blob/master/test/cljs/domina/test.cljs"
[el]
(let [document (.-document js/window)]
(cond
(.-click el) (.click el)
(.-createEvent document) (let [e (.createEvent document "MouseEvents")]
(.initMouseEvent e "click" true true
js/window 0 0 0 0 0
false false false false 0 nil)
(.dispatchEvent el e))
:default (throw "Unable to simulate click event"))))
(defn simulate-change-event
"From https://github.com/levand/domina/blob/master/test/cljs/domina/test.cljs"
[el]
(let [document (.-document js/window)]
(cond
(.-onChange el) (do (print "firing on change on " el) (.onChange el))
(.-createEvent document) (let [e (.createEvent document "HTMLEvents")]
(print "firing " e " on change on " (.-id el))
(.initEvent e "change" true true)
(.dispatchEvent el e))
:default (throw "Unable to simulate change event"))))
(def sink
"contains a channel that receives messages along with notification type"
(chan))
;; see http://yobriefca.se/blog/2014/06/04/publish-and-subscribe-with-core-dot-asyncs-pub-and-sub/
(def source
(pub sink #(:topic %)))
(defn change-field!
[id value]
(let [el (sel1 (keyword (str "#" id)))]
(dommy/set-value! el value)
(simulate-change-event el)
))
(deftest ^:async password-confirmation
(testing "do not submit if passwords are not equal"
(let [subscription (chan)]
(sub source :user-registration subscription)
(om/root
(partial u/registration-view source sink)
nil
{:target (sel1 :#view)})
(go
(let [m (<! subscription)]
(is (= :error (:state m)))
(done)
))
(change-field! "userRequestedEmail" "[email protected]")
(change-field! "userRequestedPassword" "secret")
(change-field! "confirmPassword" "nosecret")
(simulate-click-event (sel1 :#submitRegistration))
)))
此測試,但由於change-field!
功能實際上並沒有改變組件的狀態失敗。這裏是(部分)組件的代碼(原諒重複...):
(defn registration-view
"Registration form for users.
Submitting form triggers a request to server"
[source sink _ owner]
(reify
om/IInitState
(init-state [_]
{:userRequestedEmail ""
:userRequestedPassword ""
:confirmPassword ""}
)
om/IRenderState
(render-state
[this state]
(dom/fieldset
nil
(dom/legend nil "User Registration")
(dom/div #js { :className "pure-control-group" }
(dom/label #js { :for "userRequestedEmail" } "EMail")
(dom/input #js { :id "userRequestedEmail" :type "text" :placeholder "Enter an e-mail"
:value (:userRequestedEmail state)
:onChange #(om/set-state! owner :userRequestedEmail (.. % -target -value))}))
(dom/div #js { :className "pure-control-group" }
(dom/label #js { :for "userRequestedPassword" } "Password")
(dom/input #js { :id "userRequestedPassword" :type "password" :placeholder "Enter password"
:value (:userRequestedPassword state)
:onChange #(om/set-state! owner :userRequestedPassword (.. % -target -value))}))
(dom/div #js { :className "pure-control-group" }
(dom/label #js { :for "confirmPassword" } "")
(dom/input #js { :id "confirmPassword" :type "password" :placeholder "Confirm password"
:value (:confirmPassword state)
:onChange #(om/set-state! owner :confirmPassword (.. % -target -value))}))
(dom/button #js {:type "submit"
:id "submitRegistration"
:className "pure-button pure-button-primary"
:onClick #(submit-registration state sink)}
"Register")))))
我可以把痕跡,測試看到的是,組件的狀態不更新,當我觸發change
事件,雖然它被正確觸發。我懷疑這與Om/React的工作方式,包裝DOM組件有關,但不知道如何處理這個問題。
只是爲了確保:是(「記憶」甚至只有?)由OM在所有渲染你能確認你的DOM測試組件元素實際上是創建的,並且onChange處理程序已連接? – phtrivier 2014-10-06 16:20:08
是的。 'on click'事件被觸發,我可以看到消息通過core.async頻道:這就是'submit-registration'所做的,將xhrio調用的結果發送到'source'頻道,然後由'測試中的'(go ...)'循環。 – insitu 2014-10-06 17:42:01
@insitu也許不同的方法會有所幫助。我使用mochify測試反應組件,並在mochify的wiki頁面中添加了一個示例:https://github.com/mantoni/mochify.js/wiki/Testing-a-ReactJS-Component-with-Mochify – 2015-03-18 10:13:13