diff --git a/src/mount/core.cljc b/src/mount/core.cljc index 63250b9..d983c5f 100644 --- a/src/mount/core.cljc +++ b/src/mount/core.cljc @@ -191,15 +191,17 @@ (defn- state-to-sym [state] (->> state (drop 2) (apply str) symbol)) ;; magic 2 is removing "#'" in state name -(defn- was-removed? - "checks if a state was removed from a namespace" - [state] - (-> state state-to-sym resolve not)) +#?(:clj + (defn- was-removed? + "checks if a state was removed from a namespace" + [state] + (-> state state-to-sym resolve not))) -(defn cleanup-deleted [state] - (when (was-removed? state) - (cleanup-if-dirty state "(it was deleted)") - (swap! meta-state dissoc state))) +#?(:clj + (defn cleanup-deleted [state] + (when (was-removed? state) + (cleanup-if-dirty state "(it was deleted)") + (swap! meta-state dissoc state)))) (defn- bring [states fun order] (let [done (atom [])] @@ -228,11 +230,14 @@ (when origin (update-meta! [state] (merge-lifecycles sub origin))))) -(defn- substitute! [state with] +(defn- substitute! [state with mode] (let [lifecycle-fns #(select-keys % [:start :stop :suspend :resume :status]) origin (@meta-state state) - sub (@meta-state with)] - (update-meta! [with :sub?] true) + sub (if (= :value mode) + {:start (fn [] with) :status :stopped} + (@meta-state with))] + (when (= :state mode) + (update-meta! [with :sub?] true)) (update-meta! [state] (merge-lifecycles origin (lifecycle-fns origin) sub)))) (defn- unsub [state] @@ -268,7 +273,13 @@ (defn start-with [with] (doseq [[from to] with] (substitute! (var-to-str from) - (var-to-str to))) + to :value)) + (start)) + +(defn start-with-states [with] + (doseq [[from to] with] + (substitute! (var-to-str from) + (var-to-str to) :state)) (start)) (defn start-without [& states] diff --git a/test/core/mount/test.cljc b/test/core/mount/test.cljc index fa06e33..41158d2 100644 --- a/test/core/mount/test.cljc +++ b/test/core/mount/test.cljc @@ -12,6 +12,7 @@ mount.test.stop-except mount.test.start-without mount.test.start-with + mount.test.start-with-states mount.test.suspend-resume )) @@ -30,6 +31,7 @@ 'mount.test.stop-except 'mount.test.start-without 'mount.test.start-with + 'mount.test.start-with-states 'mount.test.suspend-resume )) diff --git a/test/core/mount/test/start_with.cljc b/test/core/mount/test/start_with.cljc index d8ef8b8..2e910d9 100644 --- a/test/core/mount/test/start_with.cljc +++ b/test/core/mount/test/start_with.cljc @@ -23,20 +23,14 @@ (deftest start-with (testing "should start with substitutes" - (let [_ (mount/start-with {#'tapp.websockets/system-a #'mount.test.start-with/test-conn - #'mount.test.helper/helper #'mount.test.start-with/test-nrepl})] + (let [_ (mount/start-with {#'tapp.websockets/system-a "system-a-sub" + #'mount.test.helper/helper "helper-sub"})] (is (map? (dval config))) - (is (vector? (dval helper))) - (is (= (dval system-a) 42)) + (is (= "helper-sub" (dval helper))) + (is (= "system-a-sub" (dval system-a))) (is (instance? datascript.db/DB @(dval log))) (mount/stop))) - (testing "should not start the substitute itself" - (let [_ (mount/start-with {#'tapp.websockets/system-a #'mount.test.start-with/test-conn})] - (is (instance? mount.core.NotStartedState (dval test-conn))) - (is (= 42 (dval system-a))) - (mount/stop))) - (testing "should start normally after start-with" (let [_ (mount/start)] (is (map? (dval config))) @@ -62,19 +56,13 @@ (deftest start-with (testing "should start with substitutes" - (let [_ (mount/start-with {#'tapp.nyse/conn #'mount.test.start-with/test-conn - #'tapp.example/nrepl #'mount.test.start-with/test-nrepl})] + (let [_ (mount/start-with {#'tapp.nyse/conn "conn-sub" + #'tapp.example/nrepl :nrepl-sub})] (is (map? (dval config))) - (is (vector? (dval nrepl))) - (is (= (dval conn) 42)) + (is (= :nrepl-sub (dval nrepl))) + (is (= "conn-sub" (dval conn))) (mount/stop))) - (testing "should not start the substitute itself" - (let [_ (mount/start-with {#'tapp.nyse/conn #'mount.test.start-with/test-conn})] - (is (instance? mount.core.NotStartedState (dval test-conn))) - (is (= (dval conn) 42)) - (mount/stop))) - (testing "should start normally after start-with" (let [_ (mount/start)] (is (map? (dval config))) diff --git a/test/core/mount/test/start_with_states.cljc b/test/core/mount/test/start_with_states.cljc new file mode 100644 index 0000000..62688f4 --- /dev/null +++ b/test/core/mount/test/start_with_states.cljc @@ -0,0 +1,95 @@ +(ns mount.test.start-with-states + (:require + #?@(:cljs [[cljs.test :as t :refer-macros [is are deftest testing use-fixtures]] + [mount.core :as mount :refer-macros [defstate]] + [tapp.websockets :refer [system-a]] + [tapp.conf :refer [config]] + [tapp.audit-log :refer [log]]] + :clj [[clojure.test :as t :refer [is are deftest testing use-fixtures]] + [mount.core :as mount :refer [defstate]] + [tapp.conf :refer [config]] + [tapp.nyse :refer [conn]] + [tapp.example :refer [nrepl]]]) + [mount.test.helper :refer [dval helper]])) + +#?(:clj (alter-meta! *ns* assoc ::load false)) + +(defstate test-conn :start 42 + :stop (constantly 0)) + +(defstate test-nrepl :start []) + +#?(:cljs + (deftest start-with-states + + (testing "should start with substitutes" + (let [_ (mount/start-with-states {#'tapp.websockets/system-a #'mount.test.start-with-states/test-conn + #'mount.test.helper/helper #'mount.test.start-with-states/test-nrepl})] + (is (map? (dval config))) + (is (vector? (dval helper))) + (is (= (dval system-a) 42)) + (is (instance? datascript.db/DB @(dval log))) + (mount/stop))) + + (testing "should not start the substitute itself" + (let [_ (mount/start-with-states {#'tapp.websockets/system-a #'mount.test.start-with-states/test-conn})] + (is (instance? mount.core.NotStartedState (dval test-conn))) + (is (= 42 (dval system-a))) + (mount/stop))) + + (testing "should start normally after start-with-states" + (let [_ (mount/start)] + (is (map? (dval config))) + (is (instance? datascript.db/DB @(dval log))) + (is (instance? js/WebSocket (dval system-a))) + (is (= 42 (dval test-conn))) + (is (vector? (dval test-nrepl))) + (is (= :started (dval helper))) + (mount/stop))) + + (testing "should start-without normally after start-with-states" + (let [_ (mount/start-without #'mount.test.start-with-states/test-conn + #'mount.test.start-with-states/test-nrepl)] + (is (map? (dval config))) + (is (instance? datascript.db/DB @(dval log))) + (is (instance? js/WebSocket (dval system-a))) + (is (= :started (dval helper))) + (is (instance? mount.core.NotStartedState (dval test-conn))) + (is (instance? mount.core.NotStartedState (dval test-nrepl))) + (mount/stop))))) + +#?(:clj + (deftest start-with-states + + (testing "should start with substitutes" + (let [_ (mount/start-with-states {#'tapp.nyse/conn #'mount.test.start-with-states/test-conn + #'tapp.example/nrepl #'mount.test.start-with-states/test-nrepl})] + (is (map? (dval config))) + (is (vector? (dval nrepl))) + (is (= (dval conn) 42)) + (mount/stop))) + + (testing "should not start the substitute itself" + (let [_ (mount/start-with-states {#'tapp.nyse/conn #'mount.test.start-with-states/test-conn})] + (is (instance? mount.core.NotStartedState (dval test-conn))) + (is (= (dval conn) 42)) + (mount/stop))) + + (testing "should start normally after start-with-states" + (let [_ (mount/start)] + (is (map? (dval config))) + (is (instance? clojure.tools.nrepl.server.Server (dval nrepl))) + (is (instance? datomic.peer.LocalConnection (dval conn))) + (is (= (dval test-conn) 42)) + (is (vector? (dval test-nrepl))) + (mount/stop))) + + (testing "should start-without normally after start-with-states" + (let [_ (mount/start-without #'mount.test.start-with-states/test-conn + #'mount.test.start-with-states/test-nrepl)] + (is (map? (dval config))) + (is (instance? clojure.tools.nrepl.server.Server (dval nrepl))) + (is (instance? datomic.peer.LocalConnection (dval conn))) + (is (instance? mount.core.NotStartedState (dval test-conn))) + (is (instance? mount.core.NotStartedState (dval test-nrepl))) + (mount/stop))))) diff --git a/test/core/mount/test/suspend_resume.cljc b/test/core/mount/test/suspend_resume.cljc index c3503ec..c5f5fda 100644 --- a/test/core/mount/test/suspend_resume.cljc +++ b/test/core/mount/test/suspend_resume.cljc @@ -79,12 +79,12 @@ (is (instance? mount.core.NotStartedState (dval web-server))))))) #?(:cljs - (deftest suspendable-start-with + (deftest suspendable-start-with-states (testing "when replacing a non suspendable state with a suspendable one, the later should be able to suspend/resume, the original should not be suspendable after resume and preserve its lifecycle fns after rollback/stop" - (let [_ (mount/start-with {#'tapp.websockets/system-a #'mount.test.suspend-resume/web-server}) + (let [_ (mount/start-with-states {#'tapp.websockets/system-a #'mount.test.suspend-resume/web-server}) _ (mount/suspend)] (is (= (dval system-a) :w-suspended)) (is (instance? mount.core.NotStartedState (dval web-server))) @@ -139,12 +139,12 @@ #?(:clj - (deftest suspendable-start-with + (deftest suspendable-start-with-states (testing "when replacing a non suspendable state with a suspendable one, the later should be able to suspend/resume, the original should not be suspendable after resume and preserve its lifecycle fns after rollback/stop" - (let [_ (mount/start-with {#'tapp.example/nrepl #'mount.test.suspend-resume/web-server}) + (let [_ (mount/start-with-states {#'tapp.example/nrepl #'mount.test.suspend-resume/web-server}) _ (mount/suspend)] (is (= (dval nrepl) :w-suspended)) (is (instance? mount.core.NotStartedState (dval web-server))) @@ -161,7 +161,7 @@ (testing "when replacing a suspendable state with a non suspendable one, the later should not be suspendable, the original should still be suspendable and preserve its lifecycle fns after the rollback/stop" - (let [_ (mount/start-with {#'mount.test.suspend-resume/web-server #'mount.test.suspend-resume/randomizer}) + (let [_ (mount/start-with-states {#'mount.test.suspend-resume/web-server #'mount.test.suspend-resume/randomizer}) _ (mount/suspend)] (is (integer? (dval web-server))) (is (instance? mount.core.NotStartedState (dval randomizer))) @@ -178,7 +178,7 @@ the original should still be suspended and preserve its lifecycle fns after the rollback/stop" (let [_ (mount/start) _ (mount/suspend) - _ (mount/start-with {#'mount.test.suspend-resume/web-server #'tapp.nyse/conn}) ;; TODO: good to WARN on started states during "start-with" + _ (mount/start-with-states {#'mount.test.suspend-resume/web-server #'tapp.nyse/conn}) ;; TODO: good to WARN on started states during "start-with-states" _ (mount/suspend)] (is (instance? datomic.peer.LocalConnection (dval conn))) (is (= (dval web-server) :w-suspended)) ;; since the "conn" does not have a resume method, so web-server was not started @@ -195,8 +195,8 @@ the original should still be suspended and preserve its lifecycle fns after the rollback/stop" (let [_ (mount/start) _ (mount/suspend) - _ (mount/start-with {#'mount.test.suspend-resume/web-server - #'mount.test.suspend-resume/q-listener})] ;; TODO: good to WARN on started states during "start-with" + _ (mount/start-with-states {#'mount.test.suspend-resume/web-server + #'mount.test.suspend-resume/q-listener})] ;; TODO: good to WARN on started states during "start-with-states" (is (= (dval q-listener) :q-suspended)) (is (= (dval web-server) :q-resumed)) (mount/suspend)