Software / code / prosody
Comparison
spec/util_promise_spec.lua @ 9456:d54a0e129af8
util.promise: ES6-like API for promises
| author | Matthew Wild <mwild1@gmail.com> |
|---|---|
| date | Wed, 10 Oct 2018 17:45:19 +0100 |
| child | 9457:d01cff2f7a26 |
comparison
equal
deleted
inserted
replaced
| 9455:c62c983b8be3 | 9456:d54a0e129af8 |
|---|---|
| 1 local promise = require "util.promise"; | |
| 2 | |
| 3 describe("util.promise", function () | |
| 4 describe("new()", function () | |
| 5 it("returns a promise object", function () | |
| 6 assert(promise.new()); | |
| 7 end); | |
| 8 end); | |
| 9 it("notifies immediately for fulfilled promises", function () | |
| 10 local p = promise.new(function (resolve) | |
| 11 resolve("foo"); | |
| 12 end); | |
| 13 local cb = spy.new(function (v) | |
| 14 assert.equal("foo", v); | |
| 15 end); | |
| 16 p:next(cb); | |
| 17 assert.spy(cb).was_called(1); | |
| 18 end); | |
| 19 it("notifies on fulfilment of pending promises", function () | |
| 20 local r; | |
| 21 local p = promise.new(function (resolve) | |
| 22 r = resolve; | |
| 23 end); | |
| 24 local cb = spy.new(function (v) | |
| 25 assert.equal("foo", v); | |
| 26 end); | |
| 27 p:next(cb); | |
| 28 assert.spy(cb).was_called(0); | |
| 29 r("foo"); | |
| 30 assert.spy(cb).was_called(1); | |
| 31 end); | |
| 32 it("allows chaining :next() calls", function () | |
| 33 local r; | |
| 34 local result; | |
| 35 local p = promise.new(function (resolve) | |
| 36 r = resolve; | |
| 37 end); | |
| 38 local cb1 = spy.new(function (v) | |
| 39 assert.equal("foo", v); | |
| 40 return "bar"; | |
| 41 end); | |
| 42 local cb2 = spy.new(function (v) | |
| 43 assert.equal("bar", v); | |
| 44 result = v; | |
| 45 end); | |
| 46 p:next(cb1):next(cb2); | |
| 47 assert.spy(cb1).was_called(0); | |
| 48 assert.spy(cb2).was_called(0); | |
| 49 r("foo"); | |
| 50 assert.spy(cb1).was_called(1); | |
| 51 assert.spy(cb2).was_called(1); | |
| 52 assert.equal("bar", result); | |
| 53 end); | |
| 54 it("supports multiple :next() calls on the same promise", function () | |
| 55 local r; | |
| 56 local result; | |
| 57 local p = promise.new(function (resolve) | |
| 58 r = resolve; | |
| 59 end); | |
| 60 local cb1 = spy.new(function (v) | |
| 61 assert.equal("foo", v); | |
| 62 result = v; | |
| 63 end); | |
| 64 local cb2 = spy.new(function (v) | |
| 65 assert.equal("foo", v); | |
| 66 result = v; | |
| 67 end); | |
| 68 p:next(cb1); | |
| 69 p:next(cb2); | |
| 70 assert.spy(cb1).was_called(0); | |
| 71 assert.spy(cb2).was_called(0); | |
| 72 r("foo"); | |
| 73 assert.spy(cb1).was_called(1); | |
| 74 assert.spy(cb2).was_called(1); | |
| 75 assert.equal("foo", result); | |
| 76 end); | |
| 77 it("automatically rejects on error", function () | |
| 78 local r; | |
| 79 local p = promise.new(function (resolve) | |
| 80 r = resolve; | |
| 81 error("oh no"); | |
| 82 end); | |
| 83 local cb = spy.new(function () end); | |
| 84 local err_cb = spy.new(function (v) | |
| 85 assert.equal("oh no", v); | |
| 86 end); | |
| 87 p:next(cb, err_cb); | |
| 88 assert.spy(cb).was_called(0); | |
| 89 assert.spy(err_cb).was_called(1); | |
| 90 r("foo"); | |
| 91 assert.spy(cb).was_called(0); | |
| 92 assert.spy(err_cb).was_called(1); | |
| 93 end); | |
| 94 it("supports reject()", function () | |
| 95 local r, result; | |
| 96 local p = promise.new(function (resolve, reject) | |
| 97 r = reject; | |
| 98 end); | |
| 99 local cb = spy.new(function () end); | |
| 100 local err_cb = spy.new(function (v) | |
| 101 result = v; | |
| 102 assert.equal("oh doh", v); | |
| 103 end); | |
| 104 p:next(cb, err_cb); | |
| 105 assert.spy(cb).was_called(0); | |
| 106 assert.spy(err_cb).was_called(0); | |
| 107 r("oh doh"); | |
| 108 assert.spy(cb).was_called(0); | |
| 109 assert.spy(err_cb).was_called(1); | |
| 110 assert.equal("oh doh", result); | |
| 111 end); | |
| 112 it("supports chaining of rejected promises", function () | |
| 113 local r, result; | |
| 114 local p = promise.new(function (resolve, reject) | |
| 115 r = reject; | |
| 116 end); | |
| 117 local cb = spy.new(function () end); | |
| 118 local err_cb = spy.new(function (v) | |
| 119 result = v; | |
| 120 assert.equal("oh doh", v); | |
| 121 return "ok" | |
| 122 end); | |
| 123 local cb2 = spy.new(function (v) | |
| 124 result = v; | |
| 125 end); | |
| 126 local err_cb2 = spy.new(function (v) end); | |
| 127 p:next(cb, err_cb):next(cb2, err_cb2) | |
| 128 assert.spy(cb).was_called(0); | |
| 129 assert.spy(err_cb).was_called(0); | |
| 130 assert.spy(cb2).was_called(0); | |
| 131 assert.spy(err_cb2).was_called(0); | |
| 132 r("oh doh"); | |
| 133 assert.spy(cb).was_called(0); | |
| 134 assert.spy(err_cb).was_called(1); | |
| 135 assert.spy(cb2).was_called(1); | |
| 136 assert.spy(err_cb2).was_called(0); | |
| 137 assert.equal("ok", result); | |
| 138 end); | |
| 139 | |
| 140 describe("race()", function () | |
| 141 it("works with fulfilled promises", function () | |
| 142 local p1, p2 = promise.resolve("yep"), promise.resolve("nope"); | |
| 143 local p = promise.race({ p1, p2 }); | |
| 144 local result; | |
| 145 p:next(function (v) | |
| 146 result = v; | |
| 147 end); | |
| 148 assert.equal("yep", result); | |
| 149 end); | |
| 150 it("works with pending promises", function () | |
| 151 local r1, r2; | |
| 152 local p1, p2 = promise.new(function (resolve) r1 = resolve end), promise.new(function (resolve) r2 = resolve end); | |
| 153 local p = promise.race({ p1, p2 }); | |
| 154 | |
| 155 local result; | |
| 156 local cb = spy.new(function (v) | |
| 157 result = v; | |
| 158 end); | |
| 159 p:next(cb); | |
| 160 assert.spy(cb).was_called(0); | |
| 161 r2("yep"); | |
| 162 r1("nope"); | |
| 163 assert.spy(cb).was_called(1); | |
| 164 assert.equal("yep", result); | |
| 165 end); | |
| 166 end); | |
| 167 describe("all()", function () | |
| 168 it("works with fulfilled promises", function () | |
| 169 local p1, p2 = promise.resolve("yep"), promise.resolve("nope"); | |
| 170 local p = promise.all({ p1, p2 }); | |
| 171 local result; | |
| 172 p:next(function (v) | |
| 173 result = v; | |
| 174 end); | |
| 175 assert.same({ "yep", "nope" }, result); | |
| 176 end); | |
| 177 it("works with pending promises", function () | |
| 178 local r1, r2; | |
| 179 local p1, p2 = promise.new(function (resolve) r1 = resolve end), promise.new(function (resolve) r2 = resolve end); | |
| 180 local p = promise.all({ p1, p2 }); | |
| 181 | |
| 182 local result; | |
| 183 local cb = spy.new(function (v) | |
| 184 result = v; | |
| 185 end); | |
| 186 p:next(cb); | |
| 187 assert.spy(cb).was_called(0); | |
| 188 r2("yep"); | |
| 189 assert.spy(cb).was_called(0); | |
| 190 r1("nope"); | |
| 191 assert.spy(cb).was_called(1); | |
| 192 assert.same({ "nope", "yep" }, result); | |
| 193 end); | |
| 194 it("rejects if any promise rejects", function () | |
| 195 local r1, r2; | |
| 196 local p1 = promise.new(function (resolve, reject) r1 = reject end); | |
| 197 local p2 = promise.new(function (resolve, reject) r2 = reject end); | |
| 198 local p = promise.all({ p1, p2 }); | |
| 199 | |
| 200 local result; | |
| 201 local cb = spy.new(function (v) | |
| 202 result = v; | |
| 203 end); | |
| 204 local cb_err = spy.new(function (v) | |
| 205 result = v; | |
| 206 end); | |
| 207 p:next(cb, cb_err); | |
| 208 assert.spy(cb).was_called(0); | |
| 209 assert.spy(cb_err).was_called(0); | |
| 210 r2("fail"); | |
| 211 assert.spy(cb).was_called(0); | |
| 212 assert.spy(cb_err).was_called(1); | |
| 213 r1("nope"); | |
| 214 assert.spy(cb).was_called(0); | |
| 215 assert.spy(cb_err).was_called(1); | |
| 216 assert.equal("fail", result); | |
| 217 end); | |
| 218 end); | |
| 219 describe("catch()", function () | |
| 220 it("works", function () | |
| 221 local result; | |
| 222 local p = promise.new(function (resolve) | |
| 223 error({ foo = true }); | |
| 224 end); | |
| 225 local cb1 = spy.new(function (v) | |
| 226 result = v; | |
| 227 end); | |
| 228 assert.spy(cb1).was_called(0); | |
| 229 p:catch(cb1); | |
| 230 assert.spy(cb1).was_called(1); | |
| 231 assert.same({ foo = true }, result); | |
| 232 end); | |
| 233 end); | |
| 234 it("promises may be resolved by other promises", function () | |
| 235 local r1, r2; | |
| 236 local p1, p2 = promise.new(function (resolve) r1 = resolve end), promise.new(function (resolve) r2 = resolve end); | |
| 237 | |
| 238 local result; | |
| 239 local cb = spy.new(function (v) | |
| 240 result = v; | |
| 241 end); | |
| 242 p1:next(cb); | |
| 243 assert.spy(cb).was_called(0); | |
| 244 | |
| 245 r1(p2); | |
| 246 assert.spy(cb).was_called(0); | |
| 247 r2("yep"); | |
| 248 assert.spy(cb).was_called(1); | |
| 249 assert.equal("yep", result); | |
| 250 end); | |
| 251 describe("reject()", function () | |
| 252 it("returns a rejected promise", function () | |
| 253 local p = promise.reject("foo"); | |
| 254 local cb = spy.new(function (v) | |
| 255 result = v; | |
| 256 end); | |
| 257 p:next(cb); | |
| 258 assert.spy(cb).was_called(1); | |
| 259 assert.spy(cb).was_called_with("foo"); | |
| 260 end); | |
| 261 end); | |
| 262 end); |