<!-- Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ --> <html> <head> <title>Test for Promise.all, Promise.race</title> <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> </head> <body> <p id="display"></p> <div id="content" style="display: none"> </div> <pre id="test"> <script type="application/javascript"><!-- function promiseUtilitiesDefined() { ok(Promise.all, "Promise.all must be defined when Promise is enabled."); ok(Promise.race, "Promise.race must be defined when Promise is enabled."); runTest(); } function promiseAllEmptyArray() { var p = Promise.all([]); ok(p instanceof Promise, "Return value of Promise.all should be a Promise."); p.then(function(values) { ok(Array.isArray(values), "Resolved value should be an array."); is(values.length, 0, "Resolved array length should match iterable's length."); runTest(); }, function() { ok(false, "Promise.all shouldn't fail when iterable has no rejected Promises."); runTest(); }); } function promiseAllArray() { var p = Promise.all([1, new Date(), Promise.resolve("firefox")]); ok(p instanceof Promise, "Return value of Promise.all should be a Promise."); p.then(function(values) { ok(Array.isArray(values), "Resolved value should be an array."); is(values.length, 3, "Resolved array length should match iterable's length."); is(values[0], 1, "Array values should match."); ok(values[1] instanceof Date, "Array values should match."); is(values[2], "firefox", "Array values should match."); runTest(); }, function() { ok(false, "Promise.all shouldn't fail when iterable has no rejected Promises."); runTest(); }); } function promiseAllIterable() { function* promiseGen() { var i = 3; while (--i) { yield Promise.resolve(i); } yield new Promise(function(resolve) { setTimeout(resolve, 10); }); } Promise.all(promiseGen()).then(function(values) { is(values.length, 3, "Resolved array length should match iterable's length."); is(values[0], 2, "Array values should match."); is(values[1], 1, "Array values should match."); is(values[2], undefined, "Array values should match."); runTest(); }, function(e) { ok(false, "Promise.all shouldn't fail when an iterable is passed."); runTest(); }); } function promiseAllWaitsForAllPromises() { var arr = [ new Promise(function(resolve) { setTimeout(resolve.bind(undefined, 1), 50); }), new Promise(function(resolve) { setTimeout(resolve.bind(undefined, 2), 10); }), new Promise(function(resolve) { setTimeout(resolve.bind(undefined, new Promise(function(resolve2) { resolve2(3); })), 10); }), new Promise(function(resolve) { setTimeout(resolve.bind(undefined, 4), 20); }) ]; var p = Promise.all(arr); p.then(function(values) { ok(Array.isArray(values), "Resolved value should be an array."); is(values.length, 4, "Resolved array length should match iterable's length."); is(values[0], 1, "Array values should match."); is(values[1], 2, "Array values should match."); is(values[2], 3, "Array values should match."); is(values[3], 4, "Array values should match."); runTest(); }, function() { ok(false, "Promise.all shouldn't fail when iterable has no rejected Promises."); runTest(); }); } function promiseAllRejectFails() { var arr = [ new Promise(function(resolve) { setTimeout(resolve.bind(undefined, 1), 50); }), new Promise(function(resolve, reject) { setTimeout(reject.bind(undefined, 2), 10); }), new Promise(function(resolve) { setTimeout(resolve.bind(undefined, 3), 10); }), new Promise(function(resolve) { setTimeout(resolve.bind(undefined, 4), 20); }) ]; var p = Promise.all(arr); p.then(function(values) { ok(false, "Promise.all shouldn't resolve when iterable has rejected Promises."); runTest(); }, function(e) { ok(true, "Promise.all should reject when iterable has rejected Promises."); is(e, 2, "Rejection value should match."); runTest(); }); } function promiseAllCastError() { var p = Promise.all([Promise.resolve(2), { then: function() { foo(); } }]); ok(p instanceof Promise, "Should cast to a Promise."); p.then(function(v) { ok(false, "promiseAllCastError: should've rejected."); runTest(); }, function(e) { ok(e instanceof ReferenceError, "promiseCastThenableError"); runTest(); }); } // Check that the resolved array is enumerable. function promiseAllEnumerable() { var p = Promise.all([1, new Date(), Promise.resolve("firefox")]); p.then(function(v) { var count = 0; for (key in v) { ++count; ok(v[key] === 1 || v[key] instanceof Date || v[key] === "firefox", "Enumerated properties don't match."); } is(count, 3, "Resolved array from Promise.all should be enumerable"); runTest(); }, function(e) { ok(false, "promiseAllEnumerable: should've resolved."); runTest(); }); } function promiseRaceEmpty() { var p = Promise.race([]); ok(p instanceof Promise, "Should return a Promise."); p.then(function() { ok(false, "Should not resolve"); }, function() { ok(false, "Should not reject"); }); // Per spec, An empty race never resolves or rejects. setTimeout(function() { ok(true); runTest(); }, 50); } function promiseRaceValuesArray() { var p = Promise.race([true, new Date(), 3]); ok(p instanceof Promise, "Should return a Promise."); p.then(function(winner) { is(winner, true, "First value should win."); runTest(); }, function(err) { ok(false, "Should not fail " + err + "."); runTest(); }); } function promiseRacePromiseArray() { function timeoutPromise(n) { return new Promise(function(resolve) { setTimeout(function() { resolve(n); }, n); }); } var arr = [ new Promise(function(resolve) { resolve("first"); }), Promise.resolve("second"), new Promise(function() {}), new Promise(function(resolve) { setTimeout(function() { setTimeout(function() { resolve("fourth"); }, 0); }, 0); }), ]; var p = Promise.race(arr); p.then(function(winner) { is(winner, "first", "First queued resolution should win the race."); runTest(); }); } function promiseRaceIterable() { function* participants() { yield new Promise(function(resolve) { setTimeout(resolve, 10, 10); }); yield new Promise(function(resolve) { setTimeout(resolve, 20, 20); }); } Promise.race(participants()).then(function(winner) { is(winner, 10, "Winner should be the one that finished earlier."); runTest(); }, function(e) { ok(false, "Promise.race shouldn't throw when an iterable is passed!"); runTest(); }); } function promiseRaceReject() { var p = Promise.race([ Promise.reject(new Error("Fail bad!")), new Promise(function(resolve) { setTimeout(resolve, 0); }) ]); p.then(function() { ok(false, "Should not resolve when winning Promise rejected."); runTest(); }, function(e) { ok(true, "Should be rejected"); ok(e instanceof Error, "Should reject with Error."); ok(e.message == "Fail bad!", "Message should match."); runTest(); }); } function promiseRaceThrow() { var p = Promise.race([ new Promise(function(resolve) { nonExistent(); }), new Promise(function(resolve) { setTimeout(resolve, 0); }) ]); p.then(function() { ok(false, "Should not resolve when winning Promise had an error."); runTest(); }, function(e) { ok(true, "Should be rejected"); ok(e instanceof ReferenceError, "Should reject with ReferenceError for function nonExistent()."); runTest(); }); } var tests = [ promiseUtilitiesDefined, promiseAllEmptyArray, promiseAllArray, promiseAllIterable, promiseAllWaitsForAllPromises, promiseAllRejectFails, promiseAllCastError, promiseAllEnumerable, promiseRaceEmpty, promiseRaceValuesArray, promiseRacePromiseArray, promiseRaceIterable, promiseRaceReject, promiseRaceThrow, ]; function runTest() { if (!tests.length) { SimpleTest.finish(); return; } var test = tests.shift(); test(); } SimpleTest.waitForExplicitFinish(); SimpleTest.requestFlakyTimeout("untriaged"); runTest(); // --> </script> </pre> </body> </html>