From 2f01336f903bd639b893297142b97489e969377b Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 23 Feb 2022 19:36:58 +0100 Subject: [PATCH] Set version to 8.0.446 --- CHANGELOG.md | 12 +++ build.clj | 2 +- deps.edn | 2 +- doc/user-guide.md | 30 +++--- src/promesa/core.cljc | 173 ++++++++++++++++++------------ src/promesa/impl.cljc | 77 +------------ test/promesa/tests/core_test.cljc | 136 +++++++++++++---------- 7 files changed, 210 insertions(+), 222 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01350f2..cc9d5d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog # + +## Version 8.0.446 + +Date: 2022-02-23 + +- Make `promise?` to check for IPromise protocol instead of concrete types. Now it should + more easy extend promise to other promise like types. +- Rename `promise.core/do!` macro to `promise.core/do` (backward compatible, previous + macro still in the codebase) +- Add promise aware `with-redefs` macro (thanks to @eccentric-j) + + ## Version 7.0.444 Date: 2022-02-22 diff --git a/build.clj b/build.clj index aae5c0a..982986b 100644 --- a/build.clj +++ b/build.clj @@ -5,7 +5,7 @@ [cljs.build.api :as api])) (def lib 'funcool/promesa) -(def version (format "7.0.%s" (b/git-count-revs nil))) +(def version (format "8.0.%s" (b/git-count-revs nil))) (def class-dir "target/classes") (def basis (b/create-basis {:project "deps.edn"})) (def jar-file (format "target/%s-%s.jar" (name lib) version)) diff --git a/deps.edn b/deps.edn index 287cfeb..ba113d4 100644 --- a/deps.edn +++ b/deps.edn @@ -29,7 +29,7 @@ :build {:extra-deps - {io.github.clojure/tools.build {:git/tag "v0.7.5" :git/sha "34727f7"}} + {io.github.clojure/tools.build {:git/tag "v0.7.7" :git/sha "1474ad6"}} :ns-default build} :outdated diff --git a/doc/user-guide.md b/doc/user-guide.md index b90c762..6f4101d 100644 --- a/doc/user-guide.md +++ b/doc/user-guide.md @@ -9,13 +9,13 @@ A promise library for Clojure and ClojureScript. Leiningen: ```clojure -[funcool/promesa "7.0.444"] +[funcool/promesa "8.0.446"] ``` deps.edn: ```clojure -funcool/promesa {:mvn/version "7.0.444"} +funcool/promesa {:mvn/version "8.0.446"} ``` On the JVM platform _promesa_ is built on top of *completable futures* @@ -104,30 +104,30 @@ if you want to execute it asynchronously, you can provide an executor: ;; => 1 ``` -Another way to create a promise is using the `do!` macro: +Another way to create a promise is using the `do` macro: ```clojure -(p/do! +(p/do (let [a (rand-int 10) b (rand-int 10)] (+ a b))) ``` -The `do!` macro works similarly to clojure's `do` block, so you can +The `do` macro works similarly to clojure's `do` block, so you can provide any expression, but only the last one will be returned. That expression can be a plain value or another promise. -If an exception is raised inside the `do!` block, it will return the +If an exception is raised inside the `do` block, it will return the rejected promise instead of re-raising the exception on the stack. -If the `do!` contains more than one expression, each expression will +If the `do` contains more than one expression, each expression will be treated as a promise expression and will be executed sequentially, each awaiting the resolution of the prior expression. -For example, this `do!` macro: +For example, this `do` macro: ```clojure -(p/do! (expr1) +(p/do (expr1) (expr2) (expr3)) ``` @@ -399,6 +399,12 @@ some computation inside the composed promise chain/pipeline raises an exception, the pipeline short-circuits and propagates the exception to the last promise in the chain. +The `catch` function adds a new handler to the promise chain that will +be called when any of the previous promises in the chain are rejected +or an exception is raised. The `catch` function also returns a promise +that will be resolved or rejected depending on what happens inside the +catch handler. + Let see an example: ```clojure @@ -407,12 +413,6 @@ Let see an example: (.log js/console error)))) ``` -The `catch` function adds a new handler to the promise chain that will -be called when any of the previous promises in the chain are rejected -or an exception is raised. The `catch` function also returns a promise -that will be resolved or rejected depending on what happens inside the -catch handler. - If you prefer `map`-like parameter ordering, the `err` function (and `error` alias) works in same way as `catch` but has parameters ordered like `map`: diff --git a/src/promesa/core.cljc b/src/promesa/core.cljc index 5618fe0..4122cc3 100644 --- a/src/promesa/core.cljc +++ b/src/promesa/core.cljc @@ -26,7 +26,7 @@ (:refer-clojure :exclude [delay spread promise await map mapcat run! future let loop recur - -> ->> as-> with-redefs]) + -> ->> as-> with-redefs do]) (:require [promesa.protocols :as pt] [clojure.core :as c] @@ -62,9 +62,16 @@ If an executor is provided, it will be used to resolve this promise." - ([v] (pt/-promise v)) + ([v] + (pt/-promise v)) ([v executor] - (pt/-map v identity executor))) + (pt/-map (pt/-promise v) identity executor))) + +(defn wrap + "A convenience alias for `promise` coercion function that only accepts + a single argument." + [v] + (pt/-promise v)) (defn create "Create a promise instance from a factory function. If an executor is @@ -92,11 +99,13 @@ (defn promise? "Return true if `v` is a promise instance." [v] - #?(:clj (instance? CompletionStage v) - :cljs (instance? impl/*default-promise* v))) + (satisfies? pt/IPromise v)) + + ;; #?(:clj (instance? CompletionStage v) + ;; :cljs (instance? impl/*default-promise* v))) (defn deferred? - "Return true if `v` is a promise instance (alias to `promise?`." + "Return true if `v` is a promise instance (alias to `promise?`)." [v] #?(:clj (instance? CompletionStage v) :cljs (instance? impl/*default-promise* v))) @@ -135,12 +144,6 @@ ;; Chaining -(defn wrap - [v] - (if (promise? v) - v - (pt/-promise v))) - (defn then "Chains a computation `f` (function) to be executed when the promise `p` is successfully resolved. @@ -151,15 +154,15 @@ If the function `f` returns a promise instance, it will be automatically unwrapped." ([p f] - (pt/-then p f)) + (pt/-then (pt/-promise p) f)) ([p f executor] - (pt/-then p f executor))) + (pt/-then (pt/-promise p) f executor))) (defn bind ([p f] - (pt/-bind p f)) + (pt/-bind (pt/-promise p) f)) ([p f executor] - (pt/-bind p f executor))) + (pt/-bind (pt/-promise p) f executor))) (defn then' "Chains a computation `f` (function) to be executed when the promise @@ -169,8 +172,10 @@ you also can provide a custom executor. Don't perform flatten on the result." - ([p f] (pt/-map p f)) - ([p f executor] (pt/-map p f executor))) + ([p f] + (pt/-map (pt/-promise p) f)) + ([p f executor] + (pt/-map (pt/-promise p) f executor))) (defn map "Chains a computation `f` (function) to be executed when the promise @@ -178,8 +183,10 @@ Unlike `then` this does not performs automatic promise flattening. This is designed to be used with `->>`." - ([f p] (pt/-map p f)) - ([executor f p] (pt/-map p f executor))) + ([f p] + (pt/-map (pt/-promise p) f)) + ([executor f p] + (pt/-map (pt/-promise p) f executor))) (defn mapcat "Chains a computation `f` (function) to be executed when the promise @@ -190,8 +197,10 @@ the same way as `map`. This is designed to be used with `->>`." - ([f p] (pt/-bind p f)) - ([executor f p] (pt/-bind p f executor))) + ([f p] + (pt/-bind (pt/-promise p) f)) + ([executor f p] + (pt/-bind (pt/-promise p) f executor))) (defn chain "Chain variable number of computations to be executed @@ -205,13 +214,15 @@ `chain` does not flattens the return value of each step (probably this is more performant than `chain`)." ([p f] (then' p f)) - ([p f & fs] (reduce pt/-map p (cons f fs)))) + ([p f & fs] (reduce pt/-map (pt/-promise p) (cons f fs)))) (defn handle "Executes `f` when the promise `p` is resolved or is rejected. Returns a promise resolved with the return value of `f` function." - ([p f] (pt/-handle p f)) - ([p f executor] (pt/-handle p f executor))) + ([p f] + (pt/-handle (pt/-promise p) f)) + ([p f executor] + (pt/-handle (pt/-promise p) f executor))) (defn finally "Attach a potentially side-effectful handler to promise that will be @@ -219,36 +230,42 @@ Returns the original promise and the return value of `f` function is ignored." - ([p f] (pt/-finally p f)) - ([p f executor] (pt/-finally p f executor))) + ([p f] + (pt/-finally (pt/-promise p) f)) + ([p f executor] + (pt/-finally (pt/-promise p) f executor))) (defn catch "Executes `f` when the promise `p` is rejected. Returns a promise resolved with the return value of `f` function handler." ([p f] - (pt/-thenErr p f)) + (pt/-thenErr (pt/-promise p) f)) ([p pred-or-type f] (c/let [accept? (if (ifn? pred-or-type) pred-or-type #(instance? pred-or-type %))] - (pt/-thenErr p (fn [e] - (if (accept? e) - (f e) - (impl/rejected e))))))) + (pt/-thenErr + (pt/-promise p) + (fn [e] + (if (accept? e) + (f e) + (impl/rejected e))))))) (defn catch' "Executes `f` when the promise `p` is rejected. Returns a promise resolved with the return value of `f` function handler." ([p f] - (pt/-mapErr p f)) + (pt/-mapErr (pt/-promise p) f)) ([p pred-or-type f] (c/let [accept? (if (ifn? pred-or-type) pred-or-type #(instance? pred-or-type %))] - (pt/-mapErr p (fn [e] - (if (accept? e) - (f e) - (throw e))))))) + (pt/-mapErr + (pt/-promise p) + (fn [e] + (if (accept? e) + (f e) + (impl/rejected e))))))) (defn error "Same as `catch` but with parameters inverted." @@ -298,12 +315,12 @@ (any promises ::default)) ([promises default] (c/let [state (atom {:resolved false - :counter (count promises) - :rejections []})] + :counter (count promises) + :rejections []})] (create (fn [resolve reject] (doseq [p promises] - (c/-> (promise p) + (c/-> (pt/-promise p) (then (fn [v] (when-not (:resolved @state) (swap! state (fn [state] @@ -407,34 +424,46 @@ to the last expression. Always awaiting the result of each expression." [& exprs] - `(pt/-bind nil (fn [_#] - ~(condp = (count exprs) - 0 `(pt/-promise nil) - 1 `(pt/-promise ~(first exprs)) - (reduce (fn [acc e] - `(pt/-bind ~e (fn [_#] ~acc))) - `(pt/-promise ~(last exprs)) - (reverse (butlast exprs))))))) + `(pt/-bind + (pt/-promise nil) + (fn [_#] + ~(condp = (count exprs) + 0 `(pt/-promise nil) + 1 `(pt/-promise ~(first exprs)) + (reduce (fn [acc e] + `(pt/-bind (pt/-promise ~e) (fn [_#] ~acc))) + `(pt/-promise ~(last exprs)) + (reverse (butlast exprs))))))) + + +(defmacro do + "An alias for do!" + [& exprs] + `(do! ~@exprs)) (defmacro let "A `let` alternative that always returns promise and waits for all the promises on the bindings." [bindings & body] - `(pt/-bind nil (fn [_#] - ~(c/->> (reverse (partition 2 bindings)) - (reduce (fn [acc [l r]] - `(pt/-bind ~r (fn [~l] ~acc))) - `(do! ~@body)))))) + `(pt/-bind + (pt/-promise nil) + (fn [_#] + ~(c/->> (reverse (partition 2 bindings)) + (reduce (fn [acc [l r]] + `(pt/-bind (pt/-promise ~r) (fn [~l] ~acc))) + `(do! ~@body)))))) (defmacro plet "A parallel let; executes all the bindings in parallel and when all bindings are resolved, executes the body." [bindings & body] - `(pt/-bind nil (fn [_#] - ~(c/let [bindings (partition 2 bindings)] - `(c/-> (all ~(mapv second bindings)) - (then (fn [[~@(mapv first bindings)]] - (do! ~@body)))))))) + `(pt/-bind + (pt/-promise nil) + (fn [_#] + ~(c/let [bindings (partition 2 bindings)] + `(c/-> (all ~(mapv second bindings)) + (then (fn [[~@(mapv first bindings)]] + (do! ~@body)))))))) (defmacro future "Analogous to `clojure.core/future` that returns a promise instance @@ -541,17 +570,19 @@ body and wait until they resolve or reject before restoring the bindings. Useful for mocking async APIs." [bindings & body] - (c/let [names (take-nth 2 bindings) - vals (take-nth 2 (drop 1 bindings)) - orig-val-syms (map (comp gensym #(str % "-orig-val__") name) names) - temp-val-syms (map (comp gensym #(str % "-temp-val__") name) names) - binds (map vector names temp-val-syms) - resets (reverse (map vector names orig-val-syms)) - bind-value (fn [[k v]] (list 'alter-var-root (list 'var k) (list 'constantly v)))] + (c/let [names (take-nth 2 bindings) + vals (take-nth 2 (drop 1 bindings)) + orig-val-syms (c/map (comp gensym #(str % "-orig-val__") name) names) + temp-val-syms (c/map (comp gensym #(str % "-temp-val__") name) names) + binds (c/map vector names temp-val-syms) + resets (reverse (c/map vector names orig-val-syms)) + bind-value (if (:ns &env) + (fn [[k v]] (list 'set! k v)) + (fn [[k v]] (list 'alter-var-root (list 'var k) (list 'constantly v))))] `(c/let [~@(interleave orig-val-syms names) - ~@(interleave temp-val-syms vals)] - ~@(map bind-value binds) - (c/-> (do! ~@body) - (finally - (fn [] - ~@(map bind-value resets))))))) + ~@(interleave temp-val-syms vals)] + ~@(c/map bind-value binds) + (c/-> (promesa.core/do! ~@body) + (promesa.core/finally + (fn [_# _#] + ~@(c/map bind-value resets))))))) diff --git a/src/promesa/impl.cljc b/src/promesa/impl.cljc index 3eec370..3bff19b 100644 --- a/src/promesa/impl.cljc +++ b/src/promesa/impl.cljc @@ -104,36 +104,6 @@ #?(:cljs (extend-promise! js/Promise)) -;; This code allows execute `then`, `map` and all the other promise -;; chaining functions on any object if the object is a thenable but -;; does not inherit from js/Promise, this code will automatically -;; coerce it to a js/Promise instance. - -#?(:cljs - (extend-type default - pt/IPromise - (-map - ([it f] (pt/-map (pt/-promise it) f)) - ([it f e] (pt/-map (pt/-promise it) f e))) - (-bind - ([it f] (pt/-bind (pt/-promise it) f)) - ([it f e] (pt/-bind (pt/-promise it) f e))) - (-then - ([it f] (pt/-then (pt/-promise it) f)) - ([it f e] (pt/-then (pt/-promise it) f e))) - (-mapErr - ([it f] (pt/-mapErr (pt/-promise it) f)) - ([it f e] (pt/-mapErr (pt/-promise it) f e))) - (-thenErr - ([it f] (pt/-thenErr (pt/-promise it) f)) - ([it f e] (pt/-thenErr (pt/-promise it) f e))) - (-handle - ([it f] (pt/-handle (pt/-promise it) f)) - ([it f e] (pt/-handle (pt/-promise it) f e))) - (-finally - ([it f] (pt/-finally (pt/-promise it) f)) - ([it f e] (pt/-finally (pt/-promise it) f e))))) - #?(:clj (def fw-identity (pu/->FunctionWrapper identity))) #?(:clj @@ -237,52 +207,7 @@ ^BiConsumer (pu/->BiConsumerWrapper f) ^Executor (exec/resolve-executor executor)))) - - Object - (-map - ([it f] (pt/-map (pt/-promise it) f)) - ([it f e] (pt/-map (pt/-promise it) f e))) - (-bind - ([it f] (pt/-bind (pt/-promise it) f)) - ([it f e] (pt/-bind (pt/-promise it) f e))) - (-then - ([it f] (pt/-then (pt/-promise it) f)) - ([it f e] (pt/-then (pt/-promise it) f e))) - (-handle - ([it f] (pt/-handle (pt/-promise it) f)) - ([it f e] (pt/-handle (pt/-promise it) f e))) - (-mapErr - ([it f] (pt/-mapErr (pt/-promise it) f)) - ([it f e] (pt/-mapErr (pt/-promise it) f e))) - (-thenErr - ([it f] (pt/-thenErr (pt/-promise it) f)) - ([it f e] (pt/-thenErr (pt/-promise it) f e))) - (-finally - ([it f] (pt/-finally (pt/-promise it) f)) - ([it f e] (pt/-finally (pt/-promise it) f e))) - - nil - (-map - ([it f] (pt/-map (pt/-promise it) f)) - ([it f e] (pt/-map (pt/-promise it) f e))) - (-bind - ([it f] (pt/-bind (pt/-promise it) f)) - ([it f e] (pt/-bind (pt/-promise it) f e))) - (-then - ([it f] (pt/-then (pt/-promise it) f)) - ([it f e] (pt/-then (pt/-promise it) f e))) - (-mapErr - ([it f] (pt/-mapErr (pt/-promise it) f)) - ([it f e] (pt/-mapErr (pt/-promise it) f e))) - (-thenErr - ([it f] (pt/-thenErr (pt/-promise it) f)) - ([it f e] (pt/-thenErr (pt/-promise it) f e))) - (-handle - ([it f] (pt/-handle (pt/-promise it) f)) - ([it f e] (pt/-handle (pt/-promise it) f e))) - (-finally - ([it f] (pt/-finally (pt/-promise it) f)) - ([it f e] (pt/-finally (pt/-promise it) f e))))) + )) #?(:clj (extend-type CompletableFuture diff --git a/test/promesa/tests/core_test.cljc b/test/promesa/tests/core_test.cljc index 0282c87..a980080 100644 --- a/test/promesa/tests/core_test.cljc +++ b/test/promesa/tests/core_test.cljc @@ -9,8 +9,23 @@ ;; --- Core Interface Tests -(t/deftest print-promise - (t/is (string? (pr-str (p/promise nil))))) +(t/deftest common-tests + (t/is (string? (pr-str (p/promise nil)))) + (t/is (false? (p/promise? {}))) + (t/is (false? (p/promise? nil))) + + #?(:cljs (t/is (false? (p/promise? #js {}))) + :clj (t/is (false? (p/promise? (Object.))))) + + (t/is (false? (p/promise? []))) + (t/is (false? (p/promise? #{}))) + + (t/is (true? (p/promise? (p/promise nil)))) + (t/is (true? (p/promise? (p/promise 1)))) + + (let [p (p/promise (ex-info "F" {}))] + (t/is (p/promise? p)) + (t/is (p/promise (p/catch p identity))))) (t/deftest promise-from-value #?(:cljs @@ -29,8 +44,8 @@ (t/async done (let [pr (p/deferred)] (p/then pr (fn [v] - (t/is (= v 1)) - (done))) + (t/is (= v 1)) + (done))) (p/resolve! pr 1))) :clj @@ -67,14 +82,14 @@ #?(:cljs (t/async done (let [p1 (p/create (fn [resolve reject] - (e/schedule! 50 #(resolve 1))))] + (e/schedule! 50 #(resolve 1))))] ;; (t/is (p/pending? p1)) (p/then p1 (fn [v] (t/is (= v 1)) (done))))) :clj (let [p1 (p/create (fn [resolve reject] - (e/schedule! 500 #(resolve 1))))] + (e/schedule! 500 #(resolve 1))))] (t/is (p/pending? p1)) (t/is (= @p1 1))))) @@ -107,9 +122,9 @@ #?(:cljs (t/async done - (p/do! (p/then p1 (fn [r] (t/is (= [:ok1 :ok2] r)))) - (p/then p2 (fn [r] (t/is (= :fail r)))) - (done))) + (p/do (p/then p1 (fn [r] (t/is (= [:ok1 :ok2] r)))) + (p/then p2 (fn [r] (t/is (= :fail r)))) + (done))) :clj (do (t/is (= [:ok1 :ok2] @p1)) @@ -128,9 +143,9 @@ (t/is (= :fail @p2))) :cljs (t/async done - (p/do! (p/then p1 (fn [r] (t/is (= r :ok)))) - (p/then p2 (fn [r] (t/is (= r :fail)))) - (done)))))) + (p/do (p/then p1 (fn [r] (t/is (= r :ok)))) + (p/then p2 (fn [r] (t/is (= r :fail)))) + (done)))))) (t/deftest compose-with-any (let [p1 (p/any [(promise-ko 100 :fail1) @@ -215,7 +230,7 @@ p3 (p/map inc p2) test #(p/then p3 (fn [res] (t/is (= res 4))))] - #?(:cljs (t/async done (p/do! (test) (done))) + #?(:cljs (t/async done (p/do (test) (done))) :clj @(test)))) (t/deftest chaining-using-then' @@ -223,7 +238,7 @@ p2 (p/then' p1 inc) p3 (p/then' p2 inc) test #(p/then p3 (fn [res] (t/is (= res 4))))] - #?(:cljs (t/async done (p/do! (test) (done))) + #?(:cljs (t/async done (p/do (test) (done))) :clj @(test)))) (t/deftest chaining-using-mapcat @@ -233,7 +248,7 @@ p3 (p/mapcat inc p2) test #(p/then p3 (fn [v] (t/is (= v 4))))] - #?(:cljs (t/async done (p/do! (test) (done))) + #?(:cljs (t/async done (p/do (test) (done))) :clj @(test)))) (t/deftest chaining-using-finally @@ -244,7 +259,7 @@ (t/is (= v 2)) (t/is (= @st 1))))] - #?(:cljs (t/async done (p/do! (test) (done))) + #?(:cljs (t/async done (p/do (test) (done))) :clj @(test)))) (t/deftest chaining-using-handle @@ -255,7 +270,7 @@ (t/is (= v :foobar)) (t/is (= @st 1))))] - #?(:cljs (t/async done (p/do! (test) (done))) + #?(:cljs (t/async done (p/do (test) (done))) :clj @(test)))) (t/deftest cancel-scheduled-task @@ -266,12 +281,12 @@ c2 (e/schedule! 100 #(vreset! value 2))] (p/cancel! c1) (e/schedule! 300 - (fn [] - (t/is (= @value 2)) - (t/is (realized? c2)) - (t/is (not (realized? c1))) - (t/is (p/cancelled? c1)) - (done))))) + (fn [] + (t/is (= @value 2)) + (t/is (realized? c2)) + (t/is (not (realized? c1))) + (t/is (p/cancelled? c1)) + (done))))) :clj (let [value (volatile! nil) c1 (e/schedule! 500 #(vreset! value 1)) @@ -303,13 +318,13 @@ (let [prm (-> (p/delay 200 :value) (p/timeout 300))] (p/then prm (fn [v] - (t/is (= v :value)) - (done))))) + (t/is (= v :value)) + (done))))) :clj (let [prm (-> (p/delay 200 :value) (p/timeout 500))] @(p/then prm (fn [v] - (t/is (= v :value))))))) + (t/is (= v :value))))))) (t/deftest chaining-using-chain #?(:cljs @@ -371,9 +386,9 @@ #?(:clj (t/deftest async-let (let [result (p/let [a (promise-ok 50 1) - b 2 - c 3 - d (promise-ok 100 4)] + b 2 + c 3 + d (promise-ok 100 4)] (+ a b c d))] (t/is (= @result 10))))) @@ -381,10 +396,10 @@ (t/deftest async-let (t/async done (let [result (p/let [a (promise-ok 50 1) - b 2 - c 3 - d (promise-ok 100 4) - e (.toString c)] + b 2 + c 3 + d (promise-ok 100 4) + e (.toString c)] (+ a b c d))] (p/then result (fn [result] (t/is (= result 10)) @@ -394,19 +409,19 @@ (t/deftest do-expression (let [err (ex-info "error" {}) - p1 (p/do! (throw err)) - p2 (p/do! (promise-ko 10 :ko)) - p3 (p/do! (promise-ok 10 :ok1) - (promise-ok 10 :ok2)) - - test #(p/do! - (-> (normalize-to-value p1) - (p/then (fn [res] (t/is (= res 'error))))) - (-> (normalize-to-value p2) - (p/then (fn [res] (t/is (= res :ko))))) - (-> (normalize-to-value p3) - (p/then (fn [res] (t/is (= res :ok2))))))] - #?(:cljs (t/async done (p/do! (test) (done))) + p1 (p/do (throw err)) + p2 (p/do (promise-ko 10 :ko)) + p3 (p/do (promise-ok 10 :ok1) + (promise-ok 10 :ok2)) + + test #(p/do + (-> (normalize-to-value p1) + (p/then (fn [res] (t/is (= res 'error))))) + (-> (normalize-to-value p2) + (p/then (fn [res] (t/is (= res :ko))))) + (-> (normalize-to-value p3) + (p/then (fn [res] (t/is (= res :ok2))))))] + #?(:cljs (t/async done (p/do (test) (done))) :clj @(test)))) (t/deftest run-helper @@ -414,13 +429,13 @@ p1 (run! f [10 20 30]) test #(->> (p/race [p1 (p/delay 100)]) (p/map (fn [res] (t/is (= res nil)))))] - #?(:cljs (t/async done (p/do! (test) (done))) + #?(:cljs (t/async done (p/do (test) (done))) :clj @(test)))) (t/deftest future-macro (let [p1 (p/future (+ 1 2 3)) test #(p/then p1 (fn [res] (t/is (= res 6))))] - #?(:cljs (t/async done (p/do! (test) (done))) + #?(:cljs (t/async done (p/do (test) (done))) :clj @(test)))) (t/deftest loop-and-recur @@ -430,7 +445,7 @@ (p/recur (p/delay 50 (inc a))))) test #(->> (p/race [p1 (p/delay 400 10)]) (p/map (fn [res] (t/is (= res 5)))))] - #?(:cljs (t/async done (p/do! (test) (done))) + #?(:cljs (t/async done (p/do (test) (done))) :clj @(test)))) ;; --- Threading tests @@ -441,13 +456,13 @@ (t/deftest thread-first-macro (let [p1 (p/-> (p/future (+ 1 2 3)) (* 2) future-inc) test #(p/then p1 (fn [res] (t/is (= res 13))))] - #?(:cljs (t/async done (p/do! (test) (done))) + #?(:cljs (t/async done (p/do (test) (done))) :clj @(test)))) (t/deftest thread-last-macro (let [p1 (p/->> (p/future [1 2 3]) (map inc)) test #(p/then p1 (fn [res] (t/is (= res [2 3 4]))))] - #?(:cljs (t/async done (p/do! (test) (done))) + #?(:cljs (t/async done (p/do (test) (done))) :clj @(test)))) (t/deftest thread-as-last-macro @@ -456,15 +471,20 @@ (/ <> 2) (future-inc <>)) test #(p/then p1 (fn [res] (t/is (= res 8))))] - #?(:cljs (t/async done (p/do! (test) (done))) + #?(:cljs (t/async done (p/do (test) (done))) :clj @(test)))) + +(defn test-fn + [] + (p/resolved "original")) + +(def test-var :original) + (t/deftest with-redefs-macro - (let [a-fn (fn [] (p/resolved "original")) - a-var :original - p1 (p/with-redefs [a-fn (fn [] (p/resolved "mocked")) - a-var :mocked] - (p/then (a-fn) #(vector % a-var))) + (let [p1 (p/with-redefs [test-fn (fn [] (p/resolved "mocked")) + test-var :mocked] + (p/then (test-fn) #(vector % test-var))) test #(p/then p1 (fn [res] (t/is (= res ["mocked" :mocked]))))] - #?(:cljs (t/async done (p/do! (test) (done))) + #?(:cljs (t/async done (p/do (test) (done))) :clj @(test))))