1 local promise
= require
"util.promise";
3 describe("util.promise", function ()
4 --luacheck: ignore 212/resolve 212/reject
5 describe("new()", function ()
6 it("returns a promise object", function ()
10 it("notifies immediately for fulfilled promises", function ()
11 local p
= promise
.new(function (resolve
)
14 local cb
= spy
.new(function (v
)
15 assert.equal("foo", v
);
18 assert.spy(cb
).was_called(1);
20 it("notifies on fulfilment of pending promises", function ()
22 local p
= promise
.new(function (resolve
)
25 local cb
= spy
.new(function (v
)
26 assert.equal("foo", v
);
29 assert.spy(cb
).was_called(0);
31 assert.spy(cb
).was_called(1);
33 it("allows chaining :next() calls", function ()
36 local p
= promise
.new(function (resolve
)
39 local cb1
= spy
.new(function (v
)
40 assert.equal("foo", v
);
43 local cb2
= spy
.new(function (v
)
44 assert.equal("bar", v
);
47 p
:next(cb1
):next(cb2
);
48 assert.spy(cb1
).was_called(0);
49 assert.spy(cb2
).was_called(0);
51 assert.spy(cb1
).was_called(1);
52 assert.spy(cb2
).was_called(1);
53 assert.equal("bar", result
);
55 it("supports multiple :next() calls on the same promise", function ()
58 local p
= promise
.new(function (resolve
)
61 local cb1
= spy
.new(function (v
)
62 assert.equal("foo", v
);
65 local cb2
= spy
.new(function (v
)
66 assert.equal("foo", v
);
71 assert.spy(cb1
).was_called(0);
72 assert.spy(cb2
).was_called(0);
74 assert.spy(cb1
).was_called(1);
75 assert.spy(cb2
).was_called(1);
76 assert.equal("foo", result
);
78 it("automatically rejects on error", function ()
80 local p
= promise
.new(function (resolve
)
84 local cb
= spy
.new(function () end);
85 local err_cb
= spy
.new(function (v
)
86 assert.equal("oh no", v
);
89 assert.spy(cb
).was_called(0);
90 assert.spy(err_cb
).was_called(1);
92 assert.spy(cb
).was_called(0);
93 assert.spy(err_cb
).was_called(1);
95 it("supports reject()", function ()
97 local p
= promise
.new(function (resolve
, reject
)
100 local cb
= spy
.new(function () end);
101 local err_cb
= spy
.new(function (v
)
103 assert.equal("oh doh", v
);
106 assert.spy(cb
).was_called(0);
107 assert.spy(err_cb
).was_called(0);
109 assert.spy(cb
).was_called(0);
110 assert.spy(err_cb
).was_called(1);
111 assert.equal("oh doh", result
);
113 it("supports chaining of rejected promises", function ()
115 local p
= promise
.new(function (resolve
, reject
)
118 local cb
= spy
.new(function () end);
119 local err_cb
= spy
.new(function (v
)
121 assert.equal("oh doh", v
);
124 local cb2
= spy
.new(function (v
)
127 local err_cb2
= spy
.new(function () end);
128 p
:next(cb
, err_cb
):next(cb2
, err_cb2
)
129 assert.spy(cb
).was_called(0);
130 assert.spy(err_cb
).was_called(0);
131 assert.spy(cb2
).was_called(0);
132 assert.spy(err_cb2
).was_called(0);
134 assert.spy(cb
).was_called(0);
135 assert.spy(err_cb
).was_called(1);
136 assert.spy(cb2
).was_called(1);
137 assert.spy(err_cb2
).was_called(0);
138 assert.equal("ok", result
);
141 it("propagates errors down the chain, even when some handlers are not provided", function ()
143 local test_error
= {};
144 local p
= promise
.new(function (resolve
, reject
)
147 local cb
= spy
.new(function () end);
148 local err_cb
= spy
.new(function (e
) result
= e
end);
149 local p2
= p
:next(function () error(test_error
) end);
150 local p3
= p2
:next(cb
)
152 assert.spy(cb
).was_called(0);
153 assert.spy(err_cb
).was_called(0);
155 assert.spy(cb
).was_called(0);
156 assert.spy(err_cb
).was_called(1);
157 assert.spy(err_cb
).was_called_with("oh doh");
158 assert.equal("oh doh", result
);
161 it("propagates values down the chain, even when some handlers are not provided", function ()
163 local p
= promise
.new(function (resolve
, reject
)
166 local cb
= spy
.new(function () end);
167 local err_cb
= spy
.new(function () end);
168 local p2
= p
:next(function (v
) return v
; end);
169 local p3
= p2
:catch(err_cb
)
171 assert.spy(cb
).was_called(0);
172 assert.spy(err_cb
).was_called(0);
174 assert.spy(cb
).was_called(1);
175 assert.spy(cb
).was_called_with(1337);
176 assert.spy(err_cb
).was_called(0);
179 it("fulfilled promises do not call error handlers and do propagate value", function ()
180 local p
= promise
.resolve("foo");
181 local cb
= spy
.new(function () end);
182 local p2
= p
:catch(cb
);
183 assert.spy(cb
).was_called(0);
185 local cb2
= spy
.new(function () end);
187 assert.spy(cb2
).was_called(0);
190 it("rejected promises do not call fulfilled handlers and do propagate reason", function ()
191 local p
= promise
.reject("foo");
192 local cb
= spy
.new(function () end);
193 local p2
= p
:next(cb
);
194 assert.spy(cb
).was_called(0);
196 local cb2
= spy
.new(function () end);
197 local cb2_err
= spy
.new(function () end);
198 p2
:next(cb2
, cb2_err
);
199 assert.spy(cb2
).was_called(0);
200 assert.spy(cb2_err
).was_called(1);
201 assert.spy(cb2_err
).was_called_with("foo");
204 describe("allows callbacks to return", function ()
205 it("pending promises", function ()
207 local p
= promise
.resolve()
208 local cb
= spy
.new(function ()
209 return promise
.new(function (resolve
)
213 local cb2
= spy
.new(function () end);
214 p
:next(cb
):next(cb2
);
215 assert.spy(cb
).was_called(1);
216 assert.spy(cb2
).was_called(0);
218 assert.spy(cb
).was_called(1);
219 assert.spy(cb2
).was_called(1);
220 assert.spy(cb2
).was_called_with("hello");
223 it("resolved promises", function ()
224 local p
= promise
.resolve()
225 local cb
= spy
.new(function ()
226 return promise
.resolve("hello");
228 local cb2
= spy
.new(function () end);
229 p
:next(cb
):next(cb2
);
230 assert.spy(cb
).was_called(1);
231 assert.spy(cb2
).was_called(1);
232 assert.spy(cb2
).was_called_with("hello");
235 it("rejected promises", function ()
236 local p
= promise
.resolve()
237 local cb
= spy
.new(function ()
238 return promise
.reject("hello");
240 local cb2
= spy
.new(function ()
241 return promise
.reject("goodbye");
243 local cb3
= spy
.new(function () end);
244 p
:next(cb
):catch(cb2
):catch(cb3
);
245 assert.spy(cb
).was_called(1);
246 assert.spy(cb2
).was_called(1);
247 assert.spy(cb2
).was_called_with("hello");
248 assert.spy(cb3
).was_called(1);
249 assert.spy(cb3
).was_called_with("goodbye");
253 describe("race()", function ()
254 it("works with fulfilled promises", function ()
255 local p1
, p2
= promise
.resolve("yep"), promise
.resolve("nope");
256 local p
= promise
.race({ p1
, p2
});
261 assert.equal("yep", result
);
263 it("works with pending promises", function ()
265 local p1
, p2
= promise
.new(function (resolve
) r1
= resolve
end), promise
.new(function (resolve
) r2
= resolve
end);
266 local p
= promise
.race({ p1
, p2
});
269 local cb
= spy
.new(function (v
)
273 assert.spy(cb
).was_called(0);
276 assert.spy(cb
).was_called(1);
277 assert.equal("yep", result
);
280 describe("all()", function ()
281 it("works with fulfilled promises", function ()
282 local p1
, p2
= promise
.resolve("yep"), promise
.resolve("nope");
283 local p
= promise
.all({ p1
, p2
});
288 assert.same({ "yep", "nope" }, result
);
290 it("works with pending promises", function ()
292 local p1
, p2
= promise
.new(function (resolve
) r1
= resolve
end), promise
.new(function (resolve
) r2
= resolve
end);
293 local p
= promise
.all({ p1
, p2
});
296 local cb
= spy
.new(function (v
)
300 assert.spy(cb
).was_called(0);
302 assert.spy(cb
).was_called(0);
304 assert.spy(cb
).was_called(1);
305 assert.same({ "nope", "yep" }, result
);
307 it("rejects if any promise rejects", function ()
309 local p1
= promise
.new(function (resolve
, reject
) r1
= reject
end);
310 local p2
= promise
.new(function (resolve
, reject
) r2
= reject
end);
311 local p
= promise
.all({ p1
, p2
});
314 local cb
= spy
.new(function (v
)
317 local cb_err
= spy
.new(function (v
)
321 assert.spy(cb
).was_called(0);
322 assert.spy(cb_err
).was_called(0);
324 assert.spy(cb
).was_called(0);
325 assert.spy(cb_err
).was_called(1);
327 assert.spy(cb
).was_called(0);
328 assert.spy(cb_err
).was_called(1);
329 assert.equal("fail", result
);
332 describe("catch()", function ()
333 it("works", function ()
335 local p
= promise
.new(function (resolve
)
336 error({ foo
= true });
338 local cb1
= spy
.new(function (v
)
341 assert.spy(cb1
).was_called(0);
343 assert.spy(cb1
).was_called(1);
344 assert.same({ foo
= true }, result
);
347 it("promises may be resolved by other promises", function ()
349 local p1
, p2
= promise
.new(function (resolve
) r1
= resolve
end), promise
.new(function (resolve
) r2
= resolve
end);
352 local cb
= spy
.new(function (v
)
356 assert.spy(cb
).was_called(0);
359 assert.spy(cb
).was_called(0);
361 assert.spy(cb
).was_called(1);
362 assert.equal("yep", result
);
364 describe("reject()", function ()
365 it("returns a rejected promise", function ()
366 local p
= promise
.reject("foo");
367 local cb
= spy
.new(function () end);
369 assert.spy(cb
).was_called(1);
370 assert.spy(cb
).was_called_with("foo");
372 it("returns a rejected promise and does not call on_fulfilled", function ()
373 local p
= promise
.reject("foo");
374 local cb
= spy
.new(function () end);
376 assert.spy(cb
).was_called(0);
379 describe("finally()", function ()
380 local p
, p2
, resolve
, reject
, on_finally
;
381 before_each(function ()
382 p
= promise
.new(function (_resolve
, _reject
)
383 resolve
, reject
= _resolve
, _reject
;
385 on_finally
= spy
.new(function () end);
386 p2
= p
:finally(on_finally
);
388 it("runs when a promise is resolved", function ()
389 assert.spy(on_finally
).was_called(0);
391 assert.spy(on_finally
).was_called(1);
392 assert.spy(on_finally
).was_not_called_with("foo");
394 it("runs when a promise is rejected", function ()
395 assert.spy(on_finally
).was_called(0);
397 assert.spy(on_finally
).was_called(1);
398 assert.spy(on_finally
).was_not_called_with("foo");
400 it("returns a promise that fulfills with the original value", function ()
401 local cb2
= spy
.new(function () end);
403 assert.spy(on_finally
).was_called(0);
404 assert.spy(cb2
).was_called(0);
406 assert.spy(on_finally
).was_called(1);
407 assert.spy(cb2
).was_called(1);
408 assert.spy(on_finally
).was_not_called_with("foo");
409 assert.spy(cb2
).was_called_with("foo");
411 it("returns a promise that rejects with the original error", function ()
412 local on_finally_err
= spy
.new(function () end);
413 local on_finally_ok
= spy
.new(function () end);
414 p2
:catch(on_finally_err
);
415 p2
:next(on_finally_ok
);
416 assert.spy(on_finally
).was_called(0);
417 assert.spy(on_finally_err
).was_called(0);
419 assert.spy(on_finally
).was_called(1);
420 -- Since the original promise was rejected, the finally promise should also be
421 assert.spy(on_finally_ok
).was_called(0);
422 assert.spy(on_finally_err
).was_called(1);
423 assert.spy(on_finally
).was_not_called_with("foo");
424 assert.spy(on_finally_err
).was_called_with("foo");
426 it("returns a promise that rejects with an uncaught error inside on_finally", function ()
427 p
= promise
.new(function (_resolve
, _reject
)
428 resolve
, reject
= _resolve
, _reject
;
430 local test_error
= {};
431 on_finally
= spy
.new(function () error(test_error
) end);
432 p2
= p
:finally(on_finally
);
434 local on_finally_err
= spy
.new(function () end);
435 p2
:catch(on_finally_err
);
436 assert.spy(on_finally
).was_called(0);
437 assert.spy(on_finally_err
).was_called(0);
439 assert.spy(on_finally
).was_called(1);
440 assert.spy(on_finally_err
).was_called(1);
441 assert.spy(on_finally
).was_not_called_with("foo");
442 assert.spy(on_finally
).was_not_called_with(test_error
);
443 assert.spy(on_finally_err
).was_called_with(test_error
);
446 describe("try()", function ()
447 it("works with functions that return a promise", function ()
449 local p
= promise
.try(function ()
450 return promise
.new(function (_resolve
)
454 assert.is_function(resolve
);
455 local on_resolved
= spy
.new(function () end);
457 assert.spy(on_resolved
).was_not_called();
459 assert.spy(on_resolved
).was_called_with("foo");
462 it("works with functions that return a value", function ()
463 local p
= promise
.try(function ()
466 local on_resolved
= spy
.new(function () end);
468 assert.spy(on_resolved
).was_called_with("foo");
471 it("works with functions that return a promise that rejects", function ()
473 local p
= promise
.try(function ()
474 return promise
.new(function (_
, _reject
)
478 assert.is_function(reject
);
479 local on_rejected
= spy
.new(function () end);
480 p
:catch(on_rejected
);
481 assert.spy(on_rejected
).was_not_called();
483 assert.spy(on_rejected
).was_called_with("foo");
486 it("works with functions that throw errors", function ()
487 local test_error
= {};
488 local p
= promise
.try(function ()
491 local on_rejected
= spy
.new(function () end);
492 p
:catch(on_rejected
);
493 assert.spy(on_rejected
).was_called(1);
494 assert.spy(on_rejected
).was_called_with(test_error
);