Fork me on GitHub
#clojure-poland
<
2015-10-07
>
smogg07:10:02

uh, fajnie chociaż raz znaleźć polską aktywną grupę 😛

smogg07:10:35

Próbuję napisać test dla componenta w Reagencie, ktoś wie jak sprawdzić funkcję :on-click? Testy odpalamy z phantomjs, tam nie ma click() więc próbuję użyć jQuery, ale ten nie odpala :on-click'a w ogóle

zoldar07:10:55

nie jestem na bieżąco, ale powinieneś być w stanie wywołać (.onClick component)

zoldar07:10:26

zdarzenia w React są syntetyczne, nie są to typowe handlery w DOM

smogg07:10:04

Jasne, robię to w mniej wiecej w sposób pożyczony z samego reagenta: https://github.com/reagent-project/reagent/blob/master/test/reagenttest/testreagent.cljs Po wywołaniu with-mounted-component mam dostęp do obiektu DOM js i na tym wołam jQuery.trigger('click'). Ta sama funkcja jQuery działa oczywiście poprawnie w przeglądarce, a w phantomjs z jakiegoś powodu nic się nie dzieje

smogg07:10:45

Tak zeby było jasniej, jeden prosty test (klik on <tr> zaznacza checkbox'a gdzies w tym rzędzie:

(deftest service-component-test
  (when browser?
    (let [acme-service (->> acme-tenant :services rand-nth)
          get-first-row (fn [div] (.querySelector div "tr:nth-child(2)"))
          checkbox-checked? (fn [row] (.-checked (.querySelector row "td input")))
          service-component (p/service-component acme-service p/toggle-row)]
    (with-mounted-component service-component
      (fn [c div]
        (let [first-row (get-first-row div)]
          (testing "Unchecked checkbox"
            (is (not (checkbox-checked? first-row))))
          (.trigger (js/jQuery first-row) "click")
          (testing "Checked checkbox"
            (is (checkbox-checked? first-row)))))))))

smogg07:10:25

Nie mówię, że moje podejście do sprawy jest dobre oczyiście, ale już brakowalo mi pomysłów

zoldar07:10:47

bardziej jestem zdziwiony że trigger na click ci zadziałał... może czegoś nie wiem

smogg07:10:04

Czemu miałby nie działać?

zoldar07:10:01

bo tam nie prawdziwego event listenera. Jest jeden event listener który zbiera wszystkie zdarzenia od "korzenia" i na podstawie przekazanego identyfikatora komponentu podejmuje akcję

smogg07:10:51

no jasne, ale klikniecie jQuery odpala dokładnie to samo chyba co klikniecie myszką

smogg07:10:58

w sensie, wszystkie dane zostają nadal przekazane

smogg07:10:29

no ale sprawdzę dla pewności jeszcze raz, że napewno działa

smogg07:10:15

no działa bez problemu

zoldar07:10:17

heh, no to widocznie moja wiedza zardzewiała simple_smile sorry, może ktoś bardziej obeznany się wypowie w tej kwestii. może spróbuj na #C0620C0C8, kanał jest dosyć aktywny

smogg07:10:47

Będę próbował, dzięki!

zoldar07:10:53

dobra, już chyba wiem dlaczego to działa simple_smile , zdarzenia wywołane jQuery.trigger bąbelkują od 1.3 http://api.jquery.com/trigger/

jaen07:10:54

Był czas kiedy nie bubble'owały? TIL

zoldar07:10:30

"As of jQuery 1.3, .trigger()ed events bubble up the DOM tree"

jaen07:10:47

Tak, przeczytałem ten fragment, bardziej chodziło mi o to, że po prostu nie pamiętałem żeby tak nie było i mnie to trochę zdziwiło ; d

jaen07:10:00

Może za młody jestem po prostu xD

zoldar08:10:28

@smogg: sprawdzałeś czy querySelector zwraca coś w phantomie?

smogg08:10:20

Wydaje mi sie ze zwraca wszystko dobrze... Tutaj prosty przyklad:

(deftest click-test
  (when browser?
    (let [component (fn [] [:div {:class "someclass"
                            :on-click #(println "something")}])]
      (with-mounted-component (component)
        (fn [c div]
          (let [d (.querySelector div ".someclass")]
            ;; :on-click println never fires
            (.trigger (js/jQuery d) "click")))))))

smogg08:10:38

Natomiast to działa:

(deftest click-checkbox-test
  (when browser?
    (let [component (fn [] [:input {:type :checkbox 
                                    :class "someclass"
                                    :on-click #(println "something")}])]
      (with-mounted-component (component)
        (fn [c div]
          (let [d (.querySelector div "input")]
            ;; :on-click is fired
            (.trigger (js/jQuery d) "click")))))))

zoldar08:10:56

jesteś pewien, że w pierwszym przypadku nie dostajesz nulla?

smogg08:10:40

w sensie czy d jest puste?

smogg08:10:43

Nie, napewno nie

smogg08:10:11

wydaje mi sie, ze moze chodzic o niesynchroniczna funkcje

smogg08:10:33

moze po prostu chwila mija od wywolania trigger() do reakcji, a sprawdzam od razu

smogg08:10:05

tylko nie wiem jak poczekac... Nie wiem czy sie da jakos to zrobic moze z core.async?

smogg08:10:18

probowalem js setTimeout ale bez efektów

zoldar08:10:58

faktycznie, może tak być

zoldar09:10:55

osobiście postawiłbym na maksymalnie prosty handler który wywołuje jakąś zewnętrzną funkcję, którą można z ręki wyzwolić. wtedy w teście po odpaleniu funkcji, która modyfikuje stan renderujesz komponent i sprawdzasz

zoldar09:10:09

wtedy masz z bani zabawę z asynchronicznymi zdarzeniami. oczywiście nie zawsze się tak da

smogg09:10:40

no ta funkcja jest sprawdzana swoją drogą, ale tutaj potrzebuje potwierdzić, że DOM reaguje tak jak trzeba na click'a

smogg09:10:06

no i ogólnie ta wiedza wydaje mi się przydatna, więc chętnie się pomęczę z tym problemem jeszcze chwile

smogg09:10:15

jak się nie uda, to będę kombinował

jaen09:10:26

chociaż jednak może nie; bo chciałem powiedzieć, że println zwraca nil a to oznacza zatrzymanie propagacji, ale to i tak się powinno wypisać

smogg09:10:56

no na <input> działa bez problemu, więc...

jaen09:10:02

Ale nie używałem więc nie wiem na ile pomoże

smogg09:10:35

ok, sprawdzę, dzięki

jaen09:10:08

Może też Cię zainteresować to

jaen09:10:18

Oficjalne utilsy do testowania Reacta

jaen09:10:22

Mają symulację klikania np.

smogg09:10:03

o, to może być to!

smogg10:10:14

Ehh, nadal dupa nawet z TestUtils 😛

zoldar10:10:03

parafrazując, lepiej mieć stosunek z jeżem, niż zajmować się webdevem 😆