2014-10-06 2 views
8

Om/React 구성 요소를 개발했지만 단위 테스트로 개발을 추진할 수 없다는 것이 정말 불편합니다. 구성 요소에 대한 단위 테스트를 실행하기 위해 클로저 스크립트 프로젝트를 설정하려고 시도했으며, 지금까지 단위 테스트를 작성하고 구성 요소를 인스턴스화 할 수있는 시점에 도달했습니다. 내가 누락 된 부분은 구성 요소가 일부 이벤트에 올바르게 반응하는지 확인하는 기능입니다. 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 구성 요소를 감싸는 방식과 관련이 있다고 생각하지만이 문제를 어떻게 다룰 지 확신하지 못합니다.

+0

그냥 확인하기 : 내가 변경 이벤트를 테스트하는 모카를 사용하여 이런 일을하고 있어요 하는 (? '메모리'도 전용) 모두에서 톰에 의해 렌더링 당신이 DOM을 확인 할 수 있습니다 테스트 구성 요소입니다 요소가 실제로 생성되고 onChange 핸들러가 첨부됩니까? – phtrivier

+0

예. 'on click' 이벤트가 발생하면 core.async 채널을 통해 전달되는 메시지를 볼 수 있습니다 :'submit-registration'은 xhrio 호출의 결과를'source' 채널에 보냅니다. '(go ...) '테스트 루프를 반복합니다. – insitu

+0

@insitu 어쩌면 다른 접근 방식이 도움이 될 것입니다. mochify를 사용하여 반응하는 요소를 테스트하고 mochify의 wiki 페이지에 예제를 추가했습니다. https://github.com/mantoni/mochify.js/wiki/Testing-a-ReactJS-Component-with-Michify –

답변

1

반응 라이브러리의 ReactTestUtils를 사용하여 구성 요소의 이벤트를 조롱 할 수 있습니다.

var comp = ReactTestUtils.renderIntoDocument(<Component />); 
var changingElement = ReactTestUtils.findRenderedDOMComponentWithClass(comp, 'el-class'); 
it ('calls myChangeMethod on change', function() { 
    ReactTestUtils.Simulate.change(changingElement); 
    assert(comp.myChangeEventMethod.called, true); 
} 
관련 문제