first unit test

This commit is contained in:
Roman Volosovskyi 2016-05-29 21:14:34 +03:00
parent 043d28c44d
commit 1766b1af12
17 changed files with 145 additions and 98 deletions

5
.gitignore vendored
View File

@ -54,3 +54,8 @@ figwheel_server.log
# Lein # Lein
# #
.lein-failures .lein-failures
## Doo
#
out
doo-index.html

View File

@ -8,7 +8,7 @@
[reagent "0.5.1" :exclusions [cljsjs/react]] [reagent "0.5.1" :exclusions [cljsjs/react]]
[re-frame "0.6.0"] [re-frame "0.6.0"]
[prismatic/schema "1.0.4"] [prismatic/schema "1.0.4"]
^{:voom {:repo "git@github.com:status-im/status-lib.git" ^{:voom {:repo "git@github.com:status-im/status-lib.git"
:branch "master"}} :branch "master"}}
[status-im/protocol "0.1.1-20160525_083359-g53ab2c2"] [status-im/protocol "0.1.1-20160525_083359-g53ab2c2"]
[natal-shell "0.1.6"] [natal-shell "0.1.6"]
@ -20,11 +20,12 @@
["do" "clean" ["do" "clean"
["with-profile" "prod" "cljsbuild" "once" "ios"] ["with-profile" "prod" "cljsbuild" "once" "ios"]
["with-profile" "prod" "cljsbuild" "once" "android"]]} ["with-profile" "prod" "cljsbuild" "once" "android"]]}
:test-paths ["test/clj"]
:figwheel {:nrepl-port 7888} :figwheel {:nrepl-port 7888}
:profiles {:dev {:dependencies [[figwheel-sidecar "0.5.0-2"] :profiles {:dev {:dependencies [[figwheel-sidecar "0.5.0-2"]
[com.cemerick/piggieback "0.2.1"] [com.cemerick/piggieback "0.2.1"]
[io.appium/java-client "3.4.1"] [io.appium/java-client "3.4.1"]]
] :plugins [[lein-doo "0.1.6"]]
:source-paths ["src" "env/dev"] :source-paths ["src" "env/dev"]
:cljsbuild {:builds {:ios {:source-paths ["src" "env/dev"] :cljsbuild {:builds {:ios {:source-paths ["src" "env/dev"]
:figwheel true :figwheel true
@ -37,7 +38,13 @@
:compiler {:output-to "target/android/not-used.js" :compiler {:output-to "target/android/not-used.js"
:main "env.android.main" :main "env.android.main"
:output-dir "target/android" :output-dir "target/android"
:optimizations :none}}}} :optimizations :none}}
:test {:source-paths ["src" "test/cljs"]
:compiler
{:main status-im.test.runner
:output-to "target/test/test.js"
:optimizations :none
:target :nodejs}}}}
:repl-options {:nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]}} :repl-options {:nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]}}
:prod {:cljsbuild {:builds {:ios {:source-paths ["src" "env/prod"] :prod {:cljsbuild {:builds {:ios {:source-paths ["src" "env/prod"]
:compiler {:output-to "index.ios.js" :compiler {:output-to "index.ios.js"

View File

@ -60,5 +60,4 @@
(dispatch [:init-console-chat]) (dispatch [:init-console-chat])
(dispatch [:init-chat]) (dispatch [:init-chat])
(init-back-button-handler!) (init-back-button-handler!)
;(.registerComponent app-registry "StatusIm" #(r/reactify-component app-root)) (.registerComponent app-registry "StatusIm" #(r/reactify-component app-root)))
)

View File

@ -2,18 +2,16 @@
(:require [clojure.string :as s] (:require [clojure.string :as s]
[re-frame.core :refer [subscribe dispatch dispatch-sync]] [re-frame.core :refer [subscribe dispatch dispatch-sync]]
[reagent.core :as r] [reagent.core :as r]
[status-im.components.react :refer [android? [status-im.components.react :as re :refer [view
view text
text image
image navigator
navigator toolbar-android
toolbar-android drawer-layout-android
drawer-layout-android touchable-opacity]]
touchable-opacity]]
[status-im.resources :as res] [status-im.resources :as res]
[status-im.components.drawer.styles :as st] [status-im.components.drawer.styles :as st]
[status-im.i18n :refer [label]] [status-im.i18n :refer [label]]))
[status-im.components.react :refer [react]]))
(defonce drawer-atom (atom)) (defonce drawer-atom (atom))
@ -30,7 +28,7 @@
:style st/user-photo}]) :style st/user-photo}])
(defn menu-item [{:keys [name handler]}] (defn menu-item [{:keys [name handler]}]
[touchable-opacity {:style st/menu-item-touchable [touchable-opacity {:style st/menu-item-touchable
:onPress (fn [] :onPress (fn []
(close-drawer) (close-drawer)
(handler))} (handler))}
@ -41,40 +39,40 @@
(let [username (subscribe [:get :username])] (let [username (subscribe [:get :username])]
(fn [] (fn []
[view st/drawer-menu [view st/drawer-menu
[view st/user-photo-container [view st/user-photo-container
[user-photo {}]] [user-photo {}]]
[view st/name-container [view st/name-container
[text {:style st/name-text} [text {:style st/name-text}
@username]] @username]]
[view st/menu-items-container [view st/menu-items-container
[menu-item {:name (label :t/profile) [menu-item {:name (label :t/profile)
:handler #(dispatch [:navigate-to :my-profile])}] :handler #(dispatch [:navigate-to :my-profile])}]
[menu-item {:name (label :t/settings) [menu-item {:name (label :t/settings)
:handler (fn [] :handler (fn []
;; TODO not implemented ;; TODO not implemented
)}] )}]
[menu-item {:name (label :t/discovery) [menu-item {:name (label :t/discovery)
:handler #(dispatch [:navigate-to :discovery])}] :handler #(dispatch [:navigate-to :discovery])}]
[menu-item {:name (label :t/contacts) [menu-item {:name (label :t/contacts)
:handler #(dispatch [:show-contacts navigator])}] :handler #(dispatch [:show-contacts navigator])}]
[menu-item {:name (label :t/invite-friends) [menu-item {:name (label :t/invite-friends)
:handler (fn [] :handler (fn []
;; TODO not implemented ;; TODO not implemented
)}] )}]
[menu-item {:name (label :t/faq) [menu-item {:name (label :t/faq)
:handler (fn [])}]] :handler (fn [])}]]
[view st/switch-users-container [view st/switch-users-container
[touchable-opacity {:onPress (fn [] [touchable-opacity {:onPress (fn []
(close-drawer) (close-drawer)
;; TODO not implemented ;; TODO not implemented
)} )}
[text {:style st/switch-users-text} [text {:style st/switch-users-text}
(label :t/switch-users)]]]]))) (label :t/switch-users)]]]])))
(defn drawer-view [items] (defn drawer-view [items]
[drawer-layout-android {:drawerWidth 260 [drawer-layout-android {:drawerWidth 260
:drawerPosition react.DrawerLayoutAndroid.positions.Left :drawerPosition re/react.DrawerLayoutAndroild.positions.Left
:render-navigation-view #(r/as-element [drawer-menu]) :render-navigation-view #(r/as-element [drawer-menu])
:ref (fn [drawer] :ref (fn [drawer]
(reset! drawer-atom drawer))} (reset! drawer-atom drawer))}
items]) items])

View File

@ -1,29 +1,39 @@
(ns status-im.components.react (ns status-im.components.react
(:require [reagent.core :as r] (:require [reagent.core :as r]
[status-im.components.styles :as st])) [status-im.components.styles :as st]
[status-im.utils.utils :as u]))
(when (exists? js/window) (when (exists? js/window)
(set! js/window.React (js/require "react-native"))) (set! js/window.React (js/require "react-native")))
(def react (js/require "react-native")) (def react (u/require "react-native"))
(def app-registry (.-AppRegistry react)) (defn get-react-property [name]
(def navigator (r/adapt-react-class (.-Navigator react))) (aget react name))
(def text (r/adapt-react-class (.-Text react)))
(def view (r/adapt-react-class (.-View react))) (defn adapt-class [class]
(def image (r/adapt-react-class (.-Image react))) (when class (r/adapt-react-class class)))
(def touchable-highlight-class (r/adapt-react-class (.-TouchableHighlight react)))
(defn get-class [name]
(adapt-class (get-react-property name)))
(def app-registry (get-react-property "AppRegistry"))
(def navigator (get-class "Navigator"))
(def text (get-class "Text"))
(def view (get-class "View"))
(def image (get-class "Image"))
(def touchable-highlight-class (get-class "TouchableHighlight"))
(defn touchable-highlight [props content] (defn touchable-highlight [props content]
[touchable-highlight-class [touchable-highlight-class
(merge {:underlay-color :transparent} props) (merge {:underlay-color :transparent} props)
content]) content])
(def toolbar-android (r/adapt-react-class (.-ToolbarAndroid react))) (def toolbar-android (get-class "ToolbarAndroid"))
(def list-view-class (r/adapt-react-class (.-ListView react))) (def list-view-class (get-class "ListView"))
(defn list-view [props] (defn list-view [props]
[list-view-class (merge {:enableEmptySections true} props)]) [list-view-class (merge {:enableEmptySections true} props)])
(def scroll-view (r/adapt-react-class (.-ScrollView react))) (def scroll-view (get-class "ScrollView"))
(def touchable-without-feedback (r/adapt-react-class (.-TouchableWithoutFeedback react))) (def touchable-without-feedback (get-class "TouchableWithoutFeedback"))
(def text-input-class (r/adapt-react-class (.-TextInput react))) (def text-input-class (get-class "TextInput"))
(defn text-input [props text] (defn text-input [props text]
[text-input-class (merge [text-input-class (merge
{:underlineColorAndroid :transparent {:underlineColorAndroid :transparent
@ -31,11 +41,13 @@
:placeholder "Type"} :placeholder "Type"}
props) props)
text]) text])
(def drawer-layout-android (r/adapt-react-class (.-DrawerLayoutAndroid react))) (def drawer-layout-android (get-class "DrawerLayoutAndroid"))
(def touchable-opacity (r/adapt-react-class (.-TouchableOpacity react))) (def touchable-opacity (get-class "TouchableOpacity"))
(def modal (r/adapt-react-class (.-Modal react))) (def modal (get-class "Modal"))
(def picker (r/adapt-react-class (.-Picker react))) (def picker (get-class "Picker"))
(def picker-item (r/adapt-react-class (.-Item (.-Picker react)))) (def picker-item
(when-let [picker (get-react-property "Picker")]
(adapt-class (.-Item picker))))
(defn icon (defn icon
@ -44,20 +56,18 @@
[image {:source {:uri (keyword (str "icon_" (name n)))} [image {:source {:uri (keyword (str "icon_" (name n)))}
:style style}])) :style style}]))
;(def react-linear-gradient (.-default (js/require "react-native-linear-gradient"))) (def linear-gradient-class (u/require "react-native-linear-gradient"))
;(def linear-gradient (r/adapt-react-class react-linear-gradient))
(def linear-gradient-class (js/require "react-native-linear-gradient"))
(defn linear-gradient [props] (defn linear-gradient [props]
(r/creacteElement linear-gradient-class (r/create-element linear-gradient-class
(clj->js (merge {:inverted true} props)))) (clj->js (merge {:inverted true} props))))
(def platform (.. react -Platform -OS)) (def platform
(when-let [pl (.-Platform react)] (.-OS pl)))
(def android? (= platform "android")) (def android? (= platform "android"))
(defn list-item [component] (defn list-item [component]
(r/as-element component)) (r/as-element component))
(def dismiss-keyboard! (js/require "dismissKeyboard")) (def dismiss-keyboard! (u/require "dismissKeyboard"))

View File

@ -26,7 +26,7 @@
(register-handler :load-contacts load-contacts!) (register-handler :load-contacts load-contacts!)
;; TODO see https://github.com/rt2zz/react-native-contacts/issues/45 ;; TODO see https://github.com/rt2zz/react-native-contacts/issues/45
(def react-native-contacts (js/require "react-native-contacts")) (def react-native-contacts #_(js/require "react-native-contacts"))
(defn contact-name [contact] (defn contact-name [contact]
(->> contact (->> contact

View File

@ -35,15 +35,19 @@
;; -- Common -------------------------------------------------------------- ;; -- Common --------------------------------------------------------------
(defn set-el [db [_ k v]]
(assoc db k v))
(register-handler :set (register-handler :set
(debug debug
(fn [db [_ k v]] set-el)
(assoc db k v))))
(defn set-in [db [_ path v]]
(assoc-in db path v))
(register-handler :set-in (register-handler :set-in
(debug debug
(fn [db [_ path v]] set-in)
(assoc-in db path v))))
(register-handler :initialize-db (register-handler :initialize-db
(fn [_ _] (fn [_ _]

View File

@ -1,12 +1,15 @@
(ns status-im.i18n (ns status-im.i18n
(:require (:require
[status-im.translations.en :as en])) [status-im.translations.en :as en]
[status-im.utils.utils :as u]))
(def i18n (js/require "react-native-i18n")) (def i18n (u/require "react-native-i18n"))
(set! (.-fallbacks i18n) true) (set! (.-fallbacks i18n) true)
(set! (.-defaultSeparator i18n) "/") (set! (.-defaultSeparator i18n) "/")
(set! (.-translations i18n) (clj->js {:en en/translations})) (set! (.-translations i18n) (clj->js {:en en/translations}))
(defn label [path & options] (defn label [path & options]
(.t i18n (name path) (clj->js options))) (if (exists? i18n.t)
(.t i18n (name path) (clj->js options))
(name path)))

View File

@ -2,7 +2,8 @@
(:require [cljs.reader :refer [read-string]] (:require [cljs.reader :refer [read-string]]
[status-im.components.styles :refer [default-chat-color]] [status-im.components.styles :refer [default-chat-color]]
[status-im.utils.logging :as log] [status-im.utils.logging :as log]
[status-im.utils.types :refer [to-string]]) [status-im.utils.types :refer [to-string]]
[status-im.utils.utils :as u])
(:refer-clojure :exclude [exists?])) (:refer-clojure :exclude [exists?]))
(def opts {:schema [{:name :contacts (def opts {:schema [{:name :contacts
@ -68,9 +69,10 @@
:objectType "tag"} :objectType "tag"}
:last-updated "date"}}]}) :last-updated "date"}}]})
(def realm-class (js/require "realm")) (def realm-class (u/require "realm"))
(def realm (realm-class. (clj->js opts))) (def realm (when (cljs.core/exists? js/window)
(realm-class. (clj->js opts))))
(def schema-by-name (->> (:schema opts) (def schema-by-name (->> (:schema opts)
(mapv (fn [{:keys [name] :as schema}] (mapv (fn [{:keys [name] :as schema}]

View File

@ -1,9 +1,10 @@
(ns status-im.utils.crypt (ns status-im.utils.crypt
(:require [goog.crypt :refer [byteArrayToHex]] (:require [goog.crypt :refer [byteArrayToHex]]
[clojure.string :as s]) [clojure.string :as s]
[status-im.utils.utils :as u])
(:import goog.crypt.Sha256)) (:import goog.crypt.Sha256))
(def random-bytes (js/require "react-native-randombytes")) (def random-bytes (u/require "react-native-randombytes"))
(def sha-256 (Sha256.)) (def sha-256 (Sha256.))
@ -19,7 +20,7 @@
(byteArrayToHex (.digest sha-256))) (byteArrayToHex (.digest sha-256)))
(defn gen-random-bytes [length cb] (defn gen-random-bytes [length cb]
(.randomBytes random-bytes length (fn [& [err buf]] #_(.randomBytes random-bytes length (fn [& [err buf]]
(if err (if err
(cb {:error err}) (cb {:error err})
(cb {:buffer buf}))))) (cb {:buffer buf})))))

View File

@ -1,16 +1,17 @@
(ns status-im.utils.phone-number) (ns status-im.utils.phone-number
(:require [status-im.utils.utils :as u]))
(def i18n (js/require "react-native-i18n")) (def i18n (u/require "react-native-i18n"))
(def locale (.-locale i18n)) (def locale (or (.-locale i18n) "___en"))
(def country-code (subs locale 3 5)) (def country-code (subs locale 3 5))
(set! js/PhoneNumber (js/require "awesome-phonenumber")) (def awesome-phonenumber (u/require "awesome-phonenumber"))
;; todo check wrong numbers, .getNumber returns empty string ;; todo check wrong numbers, .getNumber returns empty string
(defn format-phone-number [number] (defn format-phone-number [number]
(str (.getNumber (js/PhoneNumber. number country-code "international")))) (str (.getNumber (awesome-phonenumber. number country-code "international"))))
(defn valid-mobile-number? [number] (defn valid-mobile-number? [number]
(when (string? number) (when (string? number)
(let [number-obj (js/PhoneNumber. number country-code "international")] (let [number-obj (awesome-phonenumber. number country-code "international")]
(and (.isValid number-obj) (and (.isValid number-obj)
(.isMobile number-obj))))) (.isMobile number-obj)))))

View File

@ -1,7 +1,8 @@
(ns status-im.utils.sms-listener (ns status-im.utils.sms-listener
(:require [status-im.components.react :refer [android?]])) (:require [status-im.components.react :refer [android?]]
[status-im.utils.utils :as u]))
(def sms-listener (.-default (js/require "react-native-android-sms-listener"))) (def sms-listener (.-default (u/require "react-native-android-sms-listener")))
;; Only android is supported! ;; Only android is supported!

View File

@ -5,6 +5,11 @@
[natal-shell.toast-android :as toast]) [natal-shell.toast-android :as toast])
(:require [status-im.constants :as const])) (:require [status-im.constants :as const]))
(defn require [module]
(if (exists? js/window)
(js/require module)
#js {}))
(defn log [obj] (defn log [obj]
(.log js/console obj)) (.log js/console obj))

View File

@ -0,0 +1,6 @@
(ns status-im.test.handlers
(:require [cljs.test :refer-macros [deftest is]]
[status-im.handlers :as h]))
(deftest test-set-val
(is (= {:key :val} (h/set-el {} [nil :key :val]))))

View File

@ -0,0 +1,5 @@
(ns status-im.test.runner
(:require [doo.runner :refer-macros [doo-tests]]
[status-im.test.handlers]))
(doo-tests 'status-im.test.handlers)