blob: b70b6eca6ff61f16ab7dfd5c4c2deaf7549d8085 [file] [log] [blame]
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
// ES6 Async Await tests -- verifies functionality of async/await
function echo(str) {
WScript.Echo(str);
}
var tests = [
{
name: "Async keyword with a lambda expressions",
body: function (index) {
var x = 12;
var y = 14;
var lambdaParenNoArg = async() => x < y;
var lambdaArgs = async(a, b, c) => a + b + c;
lambdaParenNoArg().then(result => {
echo(`Test #${index} - Success lambda expression with no argument called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error lambda expression with no argument called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch lambda expression with no argument called with err = ${err}`);
});
lambdaArgs(10, 20, 30).then(result => {
echo(`Test #${index} - Success lambda expression with several arguments called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error lambda expression with several arguments called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch lambda expression with several arguments called with err = ${err}`);
});
}
},
{
name: "Async keyword with a lambda expressions and local variable captured and shadowed",
body: function (index) {
var x = 12;
var lambdaSingleArgNoParen = async x => x;
var lambdaSingleArg = async(x) => x;
lambdaSingleArgNoParen(x).then(result => {
echo(`Test #${index} - Success lambda expression with single argument and no paren called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error lambda expression with single argument and no paren called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch lambda expression with single argument and no paren called with err = ${err}`);
});
lambdaSingleArg(x).then(result => {
echo(`Test #${index} - Success lambda expression with a single argument a called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error lambda expression with a single argument called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch lambda expression with a single argument called with err = ${err}`);
});
}
},
{
name: "Async function in a statement",
body: function (index) {
{
var namedNonAsyncMethod = function async(x, y) { return x + y; }
var unnamedAsyncMethod = async function (x, y) { return x + y; }
async function async(x, y) { return x - y; }
var result = namedNonAsyncMethod(10, 20);
echo(`Test #${index} - Success function #1 called with result = '${result}'`);
unnamedAsyncMethod(10, 20).then(result => {
echo(`Test #${index} - Success function #2 called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error function #2 called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch function #2 called with err = ${err}`);
});
async(10, 20).then(result => {
echo(`Test #${index} - Success function #3 called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error function #3 called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch function #3 called with err = ${err}`);
});
}
{
async function async() { return 12; }
async().then(result => {
echo(`Test #${index} - Success function #4 called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error function #4 called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch function #4 called with err = ${err}`);
});
}
{
function async() { return 12; }
var result = namedNonAsyncMethod(10, 20);
echo(`Test #${index} - Success function #5 called with result = '${result}'`);
}
}
},
{
name: "Async function in an object",
body: function (index) {
var object = {
async async() { return 12; }
};
var object2 = {
async() { return 12; }
};
var object3 = {
async "a"() { return 12; },
async 0() { return 12; },
async 3.14() { return 12; },
async else() { return 12; },
};
object.async().then(result => {
echo(`Test #${index} - Success function in a object #1 called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error function in a object #1 called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch function in a object #1 called with err = ${err}`);
});
var result = object2.async();
echo(`Test #${index} - Success function in a object #2 called with result = '${result}'`);
object3.a().then(result => {
echo(`Test #${index} - Success function in a object #3 called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error function in a object #3 called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch function in a object #3 called with err = ${err}`);
});
object3['0']().then(result => {
echo(`Test #${index} - Success function in a object #4 called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error function in a object #4 called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch function in a object #4 called with err = ${err}`);
});
object3['3.14']().then(result => {
echo(`Test #${index} - Success function in a object #5 called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error function in a object #5 called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch function in a object #5 called with err = ${err}`);
});
object3.else().then(result => {
echo(`Test #${index} - Success function in a object #6 called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error function in a object #6 called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch function in a object #6 called with err = ${err}`);
});
}
},
{
name: "Async classes",
body: function (index) {
class MyClass {
async asyncMethod(a) { return a; }
async async(a) { return a; }
async "a"() { return 12; }
async 0() { return 12; }
async 3.14() { return 12; }
async else() { return 12; }
static async staticAsyncMethod(a) { return a; }
}
class MySecondClass {
async(a) { return a; }
}
class MyThirdClass {
static async(a) { return a; }
}
var x = "foo";
class MyFourthClass {
async [x](a) { return a; }
}
var myClassInstance = new MyClass();
var mySecondClassInstance = new MySecondClass();
var myFourthClassInstance = new MyFourthClass();
myClassInstance.asyncMethod(10).then(result => {
echo(`Test #${index} - Success async in a class #1 called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error async in a class #1 called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch async in a class #1 called with err = ${err}`);
});
myClassInstance.async(10).then(result => {
echo(`Test #${index} - Success async in a class #2 called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error async in a class #2 called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch async in a class #2 called with err = ${err}`);
});
myClassInstance.a().then(result => {
echo(`Test #${index} - Success async in a class #3 called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error async in a class #3 called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch async in a class #3 called with err = ${err}`);
});
myClassInstance['0']().then(result => {
echo(`Test #${index} - Success async in a class #4 called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error async in a class #4 called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch async in a class #4 called with err = ${err}`);
});
myClassInstance['3.14']().then(result => {
echo(`Test #${index} - Success async in a class #5 called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error async in a class #5 called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch async in a class #5 called with err = ${err}`);
});
myClassInstance.else().then(result => {
echo(`Test #${index} - Success async in a class #6 called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error async in a class #6 called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch async in a class #6 called with err = ${err}`);
});
MyClass.staticAsyncMethod(10).then(result => {
echo(`Test #${index} - Success async in a class #7 called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error async in a class #7 called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch async in a class #7 called with err = ${err}`);
});
var result = mySecondClassInstance.async(10);
echo(`Test #${index} - Success async in a class #8 called with result = '${result}'`);
var result = MyThirdClass.async(10);
echo(`Test #${index} - Success async in a class #9 called with result = '${result}'`);
myFourthClassInstance.foo(10).then(result => {
echo(`Test #${index} - Success async in a class #10 called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error async in a class #10 called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch async in a class #10 called with err = ${err}`);
});
}
},
{
name: "Await in an async function",
body: function (index) {
async function asyncMethod(val, factor) {
val = val * factor;
if (val > 0)
val = await asyncMethod(val, -1);
return val;
}
function await(x) {
return x;
}
async function secondAsyncMethod(x) {
return await(x);
}
function rejectedPromiseMethod() {
return new Promise(function (resolve, reject) {
reject(Error('My Error'));
});
}
async function rejectAwaitMethod() {
return await rejectedPromiseMethod();
}
async function asyncThrowingMethod() {
throw 32;
}
async function throwAwaitMethod() {
return await asyncThrowingMethod();
}
asyncMethod(2, 2).then(result => {
echo(`Test #${index} - Success await in an async function #1 called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error await in an async function #1 called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch await in an async function #1 called with err = ${err}`);
});
secondAsyncMethod(2).then(result => {
echo(`Test #${index} - Success await in an async function #2 called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error await in an async function #2 called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch await in an async function #2 called with err = ${err}`);
});
rejectAwaitMethod(2).then(result => {
echo(`Test #${index} - Failed await in an async function doesn't catch a rejected Promise. Result = '${result}'`);
}, err => {
echo(`Test #${index} - Success await in an async function catch a rejected Promise in 'err'. Error = '${err}'`);
}).catch(err => {
echo(`Test #${index} - Success await in an async function catch a rejected Promise in 'catch'. Error = '${err}'`);
});
throwAwaitMethod(2).then(result => {
echo(`Test #${index} - Failed await in an async function doesn't catch an error. Result = '${result}'`);
}, err => {
echo(`Test #${index} - Success await in an async function catch an error in 'err'. Error = '${err}'`);
}).catch(err => {
echo(`Test #${index} - Success await in an async function catch an error in 'catch'. Error = '${err}'`);
});
}
},
{
name: "Await keyword with a lambda expressions",
body: function (index) {
{
async function asyncMethod(x, y, z) {
var lambdaExp = async(a, b, c) => a * b * c;
var lambdaResult = await lambdaExp(x, y, z);
return lambdaResult;
}
asyncMethod(5, 5, 5).then(result => {
echo(`Test #${index} - Success await keyword with a lambda expressions #1 called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error await keyword with a lambda expressions #1 called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch await keyword with a lambda expressions #1 called with err = ${err}`);
});
};
{
async function await(lambda, x, y, z) {
return await lambda(x, y, z);
}
await(async(a, b, c) => a + b + c, 10, 20, 30).then(result => {
echo(`Test #${index} - Success await keyword with a lambda expressions #1 called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error await keyword with a lambda expressions #1 called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch await keyword with a lambda expressions #1 called with err = ${err}`);
});
};
}
},
{
name: "Async function with default arguments's value",
body: function (index) {
{
function thrower() {
throw "expected error"
}
async function asyncMethod(argument = thrower()) {
return true;
}
async function secondAsyncMethod(argument = false) {
return true;
}
asyncMethod(true).then(result => {
echo(`Test #${index} - Success async function with default arguments's value overwritten #1 called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error async function with default arguments's value overwritten #1 called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch async function with default arguments's value overwritten #1 called with err = ${err}`);
});
asyncMethod().then(result => {
echo(`Test #${index} - Failed async function with default arguments's value has not been rejected as expected #2 called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Success async function with default arguments's value has been rejected as expected by 'err' #2 called with err = '${err}'`);
}).catch(err => {
echo(`Test #${index} - Success async function with default arguments's value has been rejected as expected by 'catch' #2 called with err = '${err}'`);
});
secondAsyncMethod().then(result => {
echo(`Test #${index} - Success async function with default arguments's value #3 called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error async function with default arguments's value #3 called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch async function with default arguments's value #3 called with err = ${err}`);
});
};
}
},
{
name: "Promise in an Async function",
body: function (index) {
{
async function asyncMethodResolved() {
let p = new Promise(function (resolve, reject) {
resolve("resolved");
});
return p.then(function (result) {
return result;
});
}
async function asyncMethodResolvedWithAwait() {
let p = new Promise(function (resolve, reject) {
resolve("resolved");
});
return await p;
}
async function asyncMethodRejected() {
let p = new Promise(function (resolve, reject) {
reject("rejected");
});
return p.then(function (result) {
return result;
});
}
asyncMethodResolved().then(result => {
echo(`Test #${index} - Success resolved promise in an async function #1 called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error resolved promise in an async function #1 called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch resolved promise in an async function #1 called with err = ${err}`);
});
asyncMethodResolvedWithAwait().then(result => {
echo(`Test #${index} - Success resolved promise in an async function #2 called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error resolved promise in an async function #2 called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch resolved promise in an async function #2 called with err = ${err}`);
});
asyncMethodRejected().then(result => {
echo(`Test #${index} - Failed promise in an async function has not been rejected as expected #3 called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Success promise in an async function has been rejected as expected by 'err' #3 called with err = '${err}'`);
}).catch(err => {
echo(`Test #${index} - Success promise in an async function has been rejected as expected by 'catch' #3 called with err = '${err}'`);
});
};
}
},
{
name: "%AsyncFunction% constructor creates async functions analogous to Function constructor",
body: function (index) {
var AsyncFunction = Object.getPrototypeOf(async function () { }).constructor;
var af = new AsyncFunction('return await Promise.resolve(0);');
af().then(result => {
echo(`Test #${index} - Success %AsyncFunction% created async function #1 called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error %AsyncFunction% created async function #1 called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch %AsyncFunction% created async function #1 called with err = ${err}`);
});
af = new AsyncFunction('a', 'b', 'c', 'a = await a; b = await b; c = await c; return a + b + c;');
af(Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)).then(result => {
echo(`Test #${index} - Success %AsyncFunction% created async function #2 called with result = '${result}'`);
}, err => {
echo(`Test #${index} - Error %AsyncFunction% created async function #2 called with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch %AsyncFunction% created async function #2 called with err = ${err}`);
});
}
},
{
name: "local variables with same names as formal parameters have proper redeclaration semantics (non-error cases, var and function)",
body: function (index) {
async function af1(x) { var y = x; var x = 'b'; return y + x; }
af1('a').then(result => {
if (result === 'ab') {
echo(`Test #${index} - Success inner var x overwrote formal parameter x only after the declaration statement`);
} else {
echo(`Test #${index} - Failure x appears to have an unexpected value x = '${result}'`);
}
}, err => {
echo(`Test #${index} - Error var redeclaration with err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch var redeclaration with err = ${err}`);
});
async function af2(x) { var xx = x(); function x() { return 'afx'; } return xx; }
af2(function () { return ''; }).then(result => {
if (result === 'afx') {
echo(`Test #${index} - Success inner function x() overwrote formal parameter x`);
} else {
echo(`Test #${index} - Failure x appears not assigned with inner function x(), x = '${result}'`);
}
}, err => {
echo(`Test #${index} - Error err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch err = ${err}`);
});
}
},
{
name: "this value in async functions behaves like it does in normal functions",
body: function (index) {
async function af() {
return this;
}
af.call(5).then(result => {
if (result == 5) {
echo(`Test #${index} - Success this value set to 5`);
} else {
echo(`Test #${index} - Failure this value is not 5, this = '${result}'`);
}
}, err => {
echo(`Test #${index} - Error err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch err = ${err}`);
});
var o = {
af: af,
b: "abc"
};
o.af().then(result => {
if (result.af === af && result.b === "abc") {
echo(`Test #${index} - Success this value set to { af: af, b: "abc" }`);
} else {
echo(`Test #${index} - Failure this value set to something else, this = '${result}'`);
}
}, err => {
echo(`Test #${index} - Error err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch err = ${err}`);
});
}
},
{
name: "arguments value in async functions behaves like it does in normal functions",
body: function (index) {
async function af() {
return arguments[0] + arguments[1];
}
af('a', 'b').then(result => {
if (result === 'ab') {
echo(`Test #${index} - Success result is 'ab' from arguments 'a' + 'b'`);
} else {
echo(`Test #${index} - Failure result is not 'ab', result = '${result}'`);
}
}, err => {
echo(`Test #${index} - Error err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch err = ${err}`);
});
}
},
{
name: "super value in async methods behaves like it does in normal methods",
body: function (index) {
class B {
af() {
return "base";
}
}
class C extends B {
async af() {
return super.af() + " derived";
}
}
var c = new C();
c.af().then(result => {
if (result === 'base derived') {
echo(`Test #${index} - Success result is 'base derived' from derived method call`);
} else {
echo(`Test #${index} - Failure result is not 'base derived', result = '${result}'`);
}
}, err => {
echo(`Test #${index} - Error err = ${err}`);
}).catch(err => {
echo(`Test #${index} - Catch err = ${err}`);
});
}
},
{
name:"Async function with formal captured in a lambda",
body: function (index) {
async function af(d = 1) {
return () => d;
}
af().then(result => {
if (result() === 1) {
print(`Test #${index} - Success lambda returns 1 when no arguments passed`);
} else {
print(`Test #${index} - Failure result is not 1, result = '${result()}'`);
}
}, err => {
print(`Test #${index} - Error err = ${err}`);
}).catch(err => {
print(`Test #${index} - Catch err = ${err}`);
});
}
},
{
name:"Async function with formal captured in a nested function",
body: function (index) {
async function af(d = 1) {
return function () { return d; };
}
af().then(result => {
if (result() === 1) {
print(`Test #${index} - Success nested function returns 1 when no arguments passed`);
} else {
print(`Test #${index} - Failure result is not 1, result = '${result()}'`);
}
}, err => {
print(`Test #${index} - Error err = ${err}`);
}).catch(err => {
print(`Test #${index} - Catch err = ${err}`);
});
}
},
{
name:"Async function with formal captured in eval",
body: function (index) {
async function af(d = 1) {
return eval("d");
}
af().then(result => {
if (result === 1) {
print(`Test #${index} - Success eval returns 1 when no arguments passed`);
} else {
print(`Test #${index} - Failure result is not 1, result = '${result}'`);
}
}, err => {
print(`Test #${index} - Error err = ${err}`);
}).catch(err => {
print(`Test #${index} - Catch err = ${err}`);
});
}
},
];
var index = 1;
function runTest(test) {
echo('Executing test #' + index + ' - ' + test.name);
try {
test.body(index);
} catch(e) {
echo('Caught exception: ' + e);
}
index++;
}
tests.forEach(runTest);
echo('\nCompletion Results:');