GithubHelp home page GithubHelp logo

cljs-react-test's Introduction

cljs-react-test

Installing

Clojars Project

(:require [cljs-react-test.simulate :as sim]
          [cljs-react-test.utils :as tu])

It is not trivial to get the dependecies right when adding libraries that depend on different versions of React (addons vs no addons). The following very explicit configuration should work:

(:dependencies [cljs-react-test "0.1.4-SNAPSHOT"]
               [cljsjs/react-with-addons "15.2.0-0"]
               [cljsjs/react-dom "15.2.0-0" :exclusions [cljsjs/react]])

Description

A thin wrapper around React.addons.TestUtils. It provides convenient access to their Simulate Events in ClojureScript in a more idiomatic way. All of React's Synthetic Events have their corresponding action in kebab-case, removing the "on":

Simulate.onChange(target, data)
(change target data)

Simulate.onDrop(target, data)
(drop target data)

All arguments can be passed as ClojureScript objects and they will be converted to JS objects via clj->js.

Note: Right now all functions take two arguments, even those that don't need the second one:

Simulate.onClick(target)
(click target) 		;; Will raise a warning
(click target nil)  ;; Correct Way

This will be corrected in the next version.

It also offers a couple of convenient fixture functions in the cljs-react-test.utils namespace such as new-container! and unmount!.

Testing Example:

This guide uses om which is deprecated in favor of om.next For an example using raw React, look at test/basic.cljs in this repository

We will be testing an Om component that takes a name as input and displays it. We start by requiring cljs-react-test.utils, cljs-react-test.simulate, and dommy.core, and our usual namespaces:

(ns cljs-react-test.basic
    (:require [cljs.test :refer-macros [deftest testing is are use-fixtures]]
              [cljs-react-test.utils :as tu]
              [cljs-react-test.simulate :as sim]
              [dommy.core :as dommy :refer-macros [sel1 sel]]
              [om.core :as om :include-macros true]
              [om.dom :as dom :include-macros true]))

We create a var where we will put a DOM object to act as container for our application and a fixture function that starts it, runs the tests, and then tears down React's rendering tree:

(def ^:dynamic c)

(use-fixtures :each (fn [test-fn]
                      (binding [c (tu/new-container!)]
                        (test-fn)
                        (tu/unmount! c))))

Note: this fixture will not work with asynchronous tests.

We write the simplest component we can think of:

(defn test-component [data owner]
  (om/component
   (dom/div nil
            (dom/p nil "Enter your name:")
            (dom/input
             #js {:onChange #(om/update! data :name (.. % -target -value))
                  :value (:name data)})
            (dom/p nil (str "Your name is: " (:name data))))))

And then we test it assuming there is a DOM Element at c:

(deftest name-component
  (testing "The initial state is displayed"
    (let [app-state (atom {:name "Arya"})
          _ (om/root test-component app-state {:target c})
          display-node (second (sel c [:p]))
          input-node (sel1 c [:input])]
      (is (re-find #"Arya" (.-innerHTML display-node)))
      (testing "and when there is new input, it changes the state"
        (sim/change input-node {:target {:value "Nymeria"}})
        (om.core/render-all)
        (is (= "Nymeria" (:name @app-state)))
        (is (re-find #"Nymeria" (.-innerHTML display-node)))))))

Notice the structure of test:

  1. Set up the initial state in app-state.
  2. Start the application with om/root into c.
  3. Test the initial rendering.
  4. Simulate events and then force a re-render with om/render-all.
  5. Test the changes both in the state and in the rendering tree.
  6. Go back to 4

Run the Tests

First download the repo:

git clone https://github.com/bensu/cljs-react-test
cd cljs-react-tests

And then run the tests with doo:

lein with-profile test doo slimer test

Or if you want to use PhantomJS:

lein with-profile test doo phantom test

Or use the alias defined in project.clj which uses SlimerJS:

lein test

I've had a better experience with SlimerJS than with PhantomJS.

We need to run the tests in a different profile since the library itself shouldn't depend on om but the tests do.

Contributions

Pull requests, issues, and feedback welcome.

License

Copyright © 2016 Sebastian Bensusan

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.

cljs-react-test's People

Contributors

bensu avatar johncowie avatar kamituel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

cljs-react-test's Issues

java.lang.Exception: No namespace: camel-snake-kebab.core

Every now and then I get the following error, nondeterministically:

java.lang.Exception: No namespace: camel-snake-kebab.core, compiling:(cljs_react_test/simulate.clj:1:1)

Perhaps something could be required in a better way? Otherwise what could it be going on?

Cheers - Victor

Trying to select (w/ Dommy) nested :option

Hi there, I am trying to utilize cljs-react-test and dommy to change a dropdown menu choice which in turns updates the atom. However, it seems I am not doing this correctly. Here is what I have for code and my tests.

------ Component --------- in (ns. component.dropdown)
(defn dropdown [] [:div [:select {:on-change #(swap! app-state assoc :bind (.. % -target -value))} [:option {:value "1"} "1"] [:option {:value "2"} "2"] [:option {:value "3"} "3"] [:option {:value "4"} "4"]]])

------In Test file ------------
`(def ^:dynamic c)

(use-fixtures :each (fn [test-fn]
(binding [c (tu/new-container!)]
(test-fn)
(tu/unmount! c))))

(deftest dropdown-selection-appstate-on-change
(let [_ (reagent/render [cd/dropdown app-state] c)
node (sel1 c [:select])
dropdown-selection (:bind @App-State)]
(is (= "0" (:bind @App-State)))
(sim/change node {:target {:option {:value "3"}}})
(is (= "3" (:bind @App-State)))))`

----------Test read out-----------
FAIL in (dropdown-selection-appstate-on-change) (:)
expected: (= "3" (:bind (clojure.core/deref app-state)))
actual: (not (= "3" nil))

TypeError: undefined is not an object (evaluating 'React.addons.TestUtils')

I am having some difficulty updating to the latest versions. I created a example project that demonstrates the issue.

Tests run as desired when using

[cljsjs/react-with-addons        "0.13.3-0"]
[cljs-react-test                 "0.1.3-SNAPSHOT"]

After updating dependencies to and making no other changes

[cljs-react-test                 "0.1.4-SNAPSHOT"]
[cljsjs/react-with-addons        "15.2.0-0"]
[cljsjs/react-dom                "15.2.0-0" :exclusions [cljsjs/react]]
[prismatic/dommy                 "1.1.0"]

The following error occurs

;; ======================================================================
;; Testing with Phantom:

TypeError: undefined is not an object (evaluating 'React.addons.TestUtils')

  phantomjs://code/phantom966794781240370468.js:81 in onError

Am I overlooking something?

Errors

Hi, i have installed slimerjs and tried to run your tests but a dependency is missing:
[org.omcljs/om "0.9.0"]
Also when i add the dependency i get this:

$ lein doo slimer test
Building ...
Analyzing jar:file:/Users/bago/.m2/repository/org/clojure/clojurescript/0.0-3308/clojurescript-0.0-3308.jar!/cljs/core.cljs
Compiling src/cljs_react_test/simulate.cljs
Compiling src/cljs_react_test/utils.cljs
Analyzing jar:file:/Users/bago/.m2/repository/prismatic/dommy/1.0.0/dommy-1.0.0.jar!/dommy/core.cljs
Analyzing jar:file:/Users/bago/.m2/repository/prismatic/dommy/1.0.0/dommy-1.0.0.jar!/dommy/utils.cljs
Analyzing jar:file:/Users/bago/.m2/repository/org/clojure/clojurescript/0.0-3308/clojurescript-0.0-3308.jar!/clojure/string.cljs
Compiling test/basic.cljs
Analyzing jar:file:/Users/bago/.m2/repository/org/omcljs/om/0.8.8/om-0.8.8.jar!/om/dom.cljs
Analyzing jar:file:/Users/bago/.m2/repository/org/clojure/clojurescript/0.0-3308/clojurescript-0.0-3308.jar!/cljs/test.cljs
Analyzing jar:file:/Users/bago/.m2/repository/org/clojure/core.async/0.1.346.0-17112a-alpha/core.async-0.1.346.0-17112a-alpha.jar!/cljs/core/async.cljs
Analyzing jar:file:/Users/bago/.m2/repository/org/clojure/core.async/0.1.346.0-17112a-alpha/core.async-0.1.346.0-17112a-alpha.jar!/cljs/core/async/impl/channels.cljs
Analyzing jar:file:/Users/bago/.m2/repository/org/clojure/core.async/0.1.346.0-17112a-alpha/core.async-0.1.346.0-17112a-alpha.jar!/cljs/core/async/impl/dispatch.cljs
Analyzing jar:file:/Users/bago/.m2/repository/org/clojure/core.async/0.1.346.0-17112a-alpha/core.async-0.1.346.0-17112a-alpha.jar!/cljs/core/async/impl/buffers.cljs
Analyzing jar:file:/Users/bago/.m2/repository/org/clojure/core.async/0.1.346.0-17112a-alpha/core.async-0.1.346.0-17112a-alpha.jar!/cljs/core/async/impl/protocols.cljs
Analyzing jar:file:/Users/bago/.m2/repository/org/clojure/core.async/0.1.346.0-17112a-alpha/core.async-0.1.346.0-17112a-alpha.jar!/cljs/core/async/impl/ioc_helpers.cljs
Analyzing jar:file:/Users/bago/.m2/repository/org/clojure/core.async/0.1.346.0-17112a-alpha/core.async-0.1.346.0-17112a-alpha.jar!/cljs/core/async/impl/timers.cljs
Analyzing jar:file:/Users/bago/.m2/repository/org/omcljs/om/0.8.8/om-0.8.8.jar!/om/core.cljs
Compiling test/test_runner.cljs
Analyzing jar:file:/Users/bago/.m2/repository/doo/doo/0.1.2-SNAPSHOT/doo-0.1.2-SNAPSHOT.jar!/doo/runner.cljs
Compiling /Users/bago/Documents/code/cljs-react-test/target/cljsbuild-compiler-0/cljs/test.cljs
Compiling /Users/bago/Documents/code/cljs-react-test/target/cljsbuild-compiler-0/clojure/string.cljs
Compiling /Users/bago/Documents/code/cljs-react-test/target/cljsbuild-compiler-0/om/dom.cljs
Compiling /Users/bago/Documents/code/cljs-react-test/target/cljsbuild-compiler-0/dommy/core.cljs
Compiling /Users/bago/Documents/code/cljs-react-test/target/cljsbuild-compiler-0/dommy/utils.cljs
Compiling /Users/bago/Documents/code/cljs-react-test/target/cljsbuild-compiler-0/doo/runner.cljs
Compiling /Users/bago/Documents/code/cljs-react-test/target/cljsbuild-compiler-0/om/core.cljs
Compiling /Users/bago/Documents/code/cljs-react-test/target/cljsbuild-compiler-0/cljs/core/async.cljs
Compiling /Users/bago/Documents/code/cljs-react-test/target/cljsbuild-compiler-0/cljs/core/async/impl/timers.cljs
Compiling /Users/bago/Documents/code/cljs-react-test/target/cljsbuild-compiler-0/cljs/core/async/impl/ioc_helpers.cljs
Compiling /Users/bago/Documents/code/cljs-react-test/target/cljsbuild-compiler-0/cljs/core/async/impl/protocols.cljs
Compiling /Users/bago/Documents/code/cljs-react-test/target/cljsbuild-compiler-0/cljs/core/async/impl/buffers.cljs
Compiling /Users/bago/Documents/code/cljs-react-test/target/cljsbuild-compiler-0/cljs/core/async/impl/dispatch.cljs
Compiling /Users/bago/Documents/code/cljs-react-test/target/cljsbuild-compiler-0/cljs/core/async/impl/channels.cljs
Compiling /Users/bago/Documents/code/cljs-react-test/target/cljsbuild-compiler-0/cljs/core.cljs
Applying optimizations :whitespace
Jul 14, 2015 6:30:47 PM com.google.javascript.jscomp.LoggerErrorManager println
SEVERE: ERROR - Duplicate extern input: file:/Users/bago/.m2/repository/cljsjs/react/0.12.2-5/react-0.12.2-5.jar!/cljsjs/common/react.ext.js

Jul 14, 2015 6:30:47 PM com.google.javascript.jscomp.LoggerErrorManager printSummary
WARNING: 1 error(s), 0 warning(s)
ERROR: JSC_DUPLICATE_EXTERN_INPUT. Duplicate extern input: file:/Users/bago/.m2/repository/cljsjs/react/0.12.2-5/react-0.12.2-5.jar!/cljsjs/common/react.ext.js at (unknown source) line (unknown line) : (unknown column)
... done. Elapsed 16.583571467 seconds

Watching paths: /Users/bago/Documents/code/cljs-react-test/src, /Users/bago/Documents/code/cljs-react-test/test

Duplicated external input: react.ext.js, any thought?
Thank you and great work!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.