Я разработал компоненты 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, но не уверен, как справиться с этим.
Просто чтобы убедиться: Ваш проверенный компонент, оказываемая ом на всех (даже только «в памяти»?) Можете ли вы подтвердить DOM элементы фактически созданы, а обработчик onChange прикреплен? – phtrivier
Да. Событие 'on click' запускается, я вижу сообщение, проходящее через канал core.async: это то, что делает' registration-registration', отправляет результат вызова xhrio на канал 'source', который затем принимается '(go ...)' цикл внутри теста. – insitu
@insitu Может быть, другой подход поможет. Я тестирую реагирующие компоненты с помощью mochify, и я добавил пример на страницу вики-страницы mochify: https://github.com/mantoni/mochify.js/wiki/Testing-a-ReactJS-Component-with-Mochify –