From 56d52b6fe6d2c740b07386d7d3b22ab5d2e02b4a Mon Sep 17 00:00:00 2001 From: Andrew Suzuki Date: Mon, 13 Jun 2016 14:23:47 -0400 Subject: [PATCH] finalize tests setup; 14 utils test; db test --- Makefile | 2 +- README.md | 2 +- project.clj | 4 +- src/cljs/ulysses/db.cljs | 11 ++ src/cljs/ulysses/lib/analytics.cljs | 2 +- src/cljs/ulysses/utils.cljs | 193 +++++++++++++++++++++++++--- test/cljs/ulysses/core_test.cljs | 7 +- test/cljs/ulysses/runner.cljs | 5 +- 8 files changed, 198 insertions(+), 28 deletions(-) diff --git a/Makefile b/Makefile index 3a60616..dd00da0 100644 --- a/Makefile +++ b/Makefile @@ -43,7 +43,7 @@ start: @$(MAKE) clean @$(MAKE) install @$(MAKE) sass-dev - @lein figwheel + @rlwrap lein figwheel test: lein doo phantom test once diff --git a/README.md b/README.md index 14b8426..2c1ab6f 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ stack: * css: [sass](http://sass-lang.com/) -* tests: [doo](https://github.com/bensu/doo) (runner) / [cljs.test](https://github.com/clojure/clojurescript/blob/master/src/main/cljs/cljs/test.cljs) +* tests: [doo](https://github.com/bensu/doo) (runner) / [cljs.test](https://github.com/clojure/clojurescript/wiki/Testing) * ci: [drone](https://github.com/drone/drone) [2] diff --git a/project.clj b/project.clj index 8552a38..6440e18 100644 --- a/project.clj +++ b/project.clj @@ -71,7 +71,7 @@ :output-to "resources/public/js/compiled/app.js" :optimizations :advanced :closure-defines {goog.DEBUG false} + :pretty-print false :libs ["src/js"] :foreign-libs [{:file "node_modules/autotrack/autotrack.js" - :provides ["autotrack"]}] - :pretty-print false}}]}}}) + :provides ["autotrack"]}]}}]}}}) diff --git a/src/cljs/ulysses/db.cljs b/src/cljs/ulysses/db.cljs index 21740d3..e90e894 100644 --- a/src/cljs/ulysses/db.cljs +++ b/src/cljs/ulysses/db.cljs @@ -1,4 +1,5 @@ (ns ulysses.db + (:require-macros [cljs.test :refer [deftest testing are is]]) (:require [ulysses.utils :refer [document-size window-size window-scroll-position]])) (def default-db @@ -103,3 +104,13 @@ "given a db, set the given keys to their original state" [db keys] (merge db (select-keys default-db keys))) + +;; ---------------------------------------------------------------------------- +;; tests +;; ---------------------------------------------------------------------------- + +(deftest test-refresh-keys + (testing "refresh-keys" + (are [keys db] (= default-db (refresh-keys db keys)) + [:active-page] (assoc default-db :active-page :builder) + [:page-current] (assoc default-db :page-current 2)))) diff --git a/src/cljs/ulysses/lib/analytics.cljs b/src/cljs/ulysses/lib/analytics.cljs index c55463b..c02e3bb 100644 --- a/src/cljs/ulysses/lib/analytics.cljs +++ b/src/cljs/ulysses/lib/analytics.cljs @@ -1,7 +1,7 @@ (ns ulysses.lib.analytics (:require [cljsjs.google-analytics] [ulysses.config :as config] - [autotrack])) + [autotrack])) ; so that goog compiler includes it (defn start [] (js/ga "create" config/google-analytics-code "auto") diff --git a/src/cljs/ulysses/utils.cljs b/src/cljs/ulysses/utils.cljs index 84be88e..05faa7f 100644 --- a/src/cljs/ulysses/utils.cljs +++ b/src/cljs/ulysses/utils.cljs @@ -1,14 +1,15 @@ (ns ulysses.utils - (:require-macros [cljs.core.async.macros :refer [go-loop]]) + (:require-macros [cljs.test :refer [deftest testing are is]] + [cljs.core.async.macros :refer [go-loop]]) (:require [clojure.string :as string] [clojure.walk :refer [keywordize-keys]] [clojure.set :refer [rename-keys]] [cljs.core.async :refer [chan put! k name (string/replace #"_" "-") keyword)) m)) (defn map-subels - "reagent util: apply f to each item in collection, - associating :key metadata (first tries :id of each el; - defaults to default-key-i where i is position in coll)" - [f coll] + "reagent util: make reagent element with component + for each value in coll, while associating :key metadata + (first try :id of each el; default to default-key-i + where i is key in coll)" + [component coll] (map-indexed (fn [i el] ^{:key (or (:id el) (str "default-key-" i))} - [f el]) + [component el]) coll)) (defn str->int "string or integer to integer; nil if not possible" [s] (if (integer? s) s - (when (and (string? s) (re-find #"^\d+$" s)) + (when (and (string? s) (re-find #"^[-+]?\d+$" s)) (js/parseInt s)))) (defn clj->json @@ -106,7 +115,7 @@ (defn find-by-id "find a map by :id within a seqable (of maps)" [id seqable] - (let [id-int (str->int id)] + (when-let [id-int (str->int id)] (some #(when (= (:id %) id-int) %) seqable))) @@ -202,6 +211,12 @@ (def debounce-standard (partial debounce config/request-debounce-time)) +(defn wop + "when obj is a javascript object, get property" + [obj prop-name] + (when (object? obj) + (aget obj prop-name))) + ;; ---------------------------------------------------------------------------- ;; classes ;; ---------------------------------------------------------------------------- @@ -272,15 +287,20 @@ (defn document-size "get the :width and :height of the current document" [] - (let [d js/document - body (or (.-body d) #js {}) - de (or (.-documentElement d) #js {})] - {:width (max - (.-scrollWidth body) (.-offsetWidth body) - (.-clientWidth de) (.-scrollWidth de) (.-offsetWidth de)) - :height (max - (.-scrollHeight body) (.-offsetHeight body) - (.-clientHeight de) (.-scrollHeight de) (.-offsetHeight de))})) + (or + (when-let [d js/document] + (let [body (wop d "body") + de (wop d "documentElement") + wb (partial wop body) + wde (partial wop de)] + (when (or body de) + {:width (max + (wb "scrollWidth") (wb "offsetWidth") + (wde "clientWidth") (wde "scrollWidth") (wde "offsetWidth")) + :height (max + (wb "scrollHeight") (wb "offsetHeight") + (wde "clientHeight") (wde "scrollHeight") (wde "offsetHeight"))}))) + {:width 0 :height 0})) (defn window-scroll-position "get the :y (scrollTop) and :x (scrollLeft) of the current window" @@ -416,7 +436,7 @@ (let [progress-id (when progress? (:next-progress-id db))] (when progress? (dispatch [:progress progress-id 1])) - (ajax.core/easy-ajax-request + (easy-ajax-request (string/join "/" (cons config/api-endpoint (map @@ -511,3 +531,136 @@ (defn scroll-to [y] (.scrollTo js/window 0 y)) + +;; ---------------------------------------------------------------------------- +;; tests +;; ---------------------------------------------------------------------------- + +(deftest test-noop + (is (nil? (noop))) + (is (nil? (noop 1))) + (is (nil? (noop 1 2)))) + +(deftest test-boolean? + (is (= true (boolean? true))) + (is (= true (boolean? false))) + (is (not (boolean? nil))) + (is (not (boolean? ""))) + (is (not (boolean? 0)))) + +; missing: ptr + +; missing: ptr-first + +(deftest test-metas-equal? + (is (metas-equal? [(with-meta {:a 1} {:key 1})] [(with-meta {:a 2} {:key 1})])) + (is (not (metas-equal? [(with-meta {:a 1} {:key 1})] [(with-meta {:a 2} {:key 2})])))) + +(deftest test-remap-and-variations + (let [from {:a 1 :b 2 :c 3}] + (testing "remap" + (is (= {:a 2 :b 4 :c 6} (remap (partial * 2) from)))) + (testing "remap-k" + (is (= {:a1 1 :b2 2 :c3 3} + (remap-k + (fn [k v] (keyword (str (name k) v))) + from)))) + (testing "remap-v" + (is (= {:a :a1 :b :b2 :c :c3} + (remap-v + (fn [k v] (keyword (str (name k) v))) + from)))))) + +(deftest test-hyphenate-keys + (is (= {:a-b 1 :c-d 2} (hyphenate-keys {:a_b 1 :c_d 2})))) + +(deftest test-map-subels + (testing "when values have ids" + (let [in [{:id 23 :value 3} {:id 95 :value 4}] + out (map-subels :div in) + expected (list (with-meta [:div (first in)] {:key 23}) + (with-meta [:div (second in)] {:key 95}))] + (is (= out expected)) + (is (metas-equal? out expected)))) + (testing "when values don't have ids" + (let [in [3 4] + out (map-subels :div in) + expected (list (with-meta [:div (first in)] {:key "default-key-0"}) + (with-meta [:div (second in)] {:key "default-key-1"}))] + (is (= out expected)) + (is (metas-equal? out expected)))) + (testing "when values have ids sometimes" + (let [in [{:id 23 :value 3} 4] + out (map-subels :div in) + expected (list (with-meta [:div (first in)] {:key 23}) + (with-meta [:div (second in)] {:key "default-key-1"}))] + (is (= out expected)) + (is (metas-equal? out expected))))) + +(deftest test-str->int + (testing "successful cases" + (is (= 0 (str->int "0"))) + (is (= -5 (str->int "-5"))) + (is (= 1 (str->int "1"))) + (is (= 20003018 (str->int "20003018"))) + (is (= 0 (str->int 0))) + (is (= -5 (str->int -5))) + (is (= 1 (str->int 1))) + (is (= 20003018 (str->int 20003018)))) + (testing "unsuccessful cases" + (is (nil? (str->int ""))) + (is (nil? (str->int "0.0"))) + (is (nil? (str->int "1.0"))) + (is (nil? (str->int "123.123"))) + (is (nil? (str->int "garbage"))) + (is (nil? (str->int "12moregarbage12"))) + (is (nil? (str->int 123.123))) + (is (nil? (str->int nil))))) + +(deftest test-clj->json + (is (= "null" (clj->json nil))) + (is (= "true" (clj->json true))) + (is (= "-3" (clj->json -3))) + (is (= "[1,2,3]" (clj->json [1 2 3]))) + (is (= "[\"one\",\"three\",\"two\"]" (clj->json (sorted-set :one :two :three))))) + +(deftest test-json->clj + (testing "basic values" + (is (= nil (json->clj "null"))) + (is (= true (json->clj "true"))) + (is (= -3 (json->clj "-3"))) + (is (= [1 2 3] (json->clj "[1,2,3]"))) + (is (= ["one" "two" "three"] (json->clj "[\"one\",\"two\",\"three\"]")))) + (testing "maps: no keywordizing" + (is (= {"a" 1 "b" 2} (json->clj "{\"a\": 1, \"b\": 2}")))) + (testing "maps: keywordizing" + (is (= {:a 1 :b 2} (json->clj "{\"a\": 1, \"b\": 2}" :keywords)))) + (testing "exception throwing" + (is (thrown? js/SyntaxError (json->clj "asdf"))) + (is (thrown? js/SyntaxError (json->clj "[1,2"))))) + +(deftest test-url-encode-component + (is (= "foo" (url-encode-component "foo"))) + (is (= "foo%20bar" (url-encode-component "foo bar"))) + (is (= "%3F%26%3F%26" (url-encode-component "?&?&")))) + +(deftest test-truncate-with-ellipsis + (testing "normal" + (is (= "foo..." (truncate-with-ellipsis "foo bar" 3)))) + (testing "custom ellipsis" + (is (= "foo[..]" (truncate-with-ellipsis "foo bar" 3 "[..]"))))) + +(deftest test-find-by-id + (let [ms [{:id 1} {:id 2} {:id 94}]] + (testing "found (type int)" + (is (= (first ms) (find-by-id 1 ms))) + (is (= (second ms) (find-by-id 2 ms))) + (is (= (last ms) (find-by-id 94 ms)))) + (testing "found (type int-string)" + (is (= (first ms) (find-by-id "1" ms))) + (is (= (second ms) (find-by-id "2" ms))) + (is (= (last ms) (find-by-id "94" ms)))) + (testing "not found" + (is (nil? (find-by-id 33 ms))) + (is (nil? (find-by-id "33" ms))) + (is (nil? (find-by-id "1.0" ms)))))) diff --git a/test/cljs/ulysses/core_test.cljs b/test/cljs/ulysses/core_test.cljs index 2051463..e7996a1 100644 --- a/test/cljs/ulysses/core_test.cljs +++ b/test/cljs/ulysses/core_test.cljs @@ -2,6 +2,11 @@ (:require [cljs.test :refer-macros [deftest testing is]] [ulysses.core :as core])) +;; NOTE +;; runner.cljs is currently set up to run tests in +;; all namespaces that match ulysses.*, which mostly +;; voids the need for this auxillary test directory + (deftest fake-test - (testing "fake description" + (testing "description" (is (= 2 2)))) diff --git a/test/cljs/ulysses/runner.cljs b/test/cljs/ulysses/runner.cljs index 8000357..24bc36b 100644 --- a/test/cljs/ulysses/runner.cljs +++ b/test/cljs/ulysses/runner.cljs @@ -1,5 +1,6 @@ (ns ulysses.runner - (:require [doo.runner :refer-macros [doo-tests]] + (:require [doo.runner :refer-macros [doo-tests doo-all-tests]] [ulysses.core-test])) -(doo-tests 'ulysses.core-test) +;; run all tests in all namespaces matching ulysses.* +(doo.runner/doo-all-tests #"ulysses.*")