mobile-cli-lib
Version:
common lib used by different CLI
359 lines (358 loc) • 21.7 kB
JavaScript
;
var decoratorsLib = require("../../decorators");
var yok_1 = require("../../yok");
var chai_1 = require("chai");
var Future = require("fibers/future");
var Promise = require("bluebird");
describe("decorators", function () {
var moduleName = "moduleName", propertyName = "propertyName", generatePublicApiFromExportedPromiseDecorator = function () {
chai_1.assert.deepEqual($injector.publicApi.__modules__[moduleName], undefined);
var promisifiedResult = decoratorsLib.exportedPromise(moduleName);
promisifiedResult({}, propertyName, {});
};
beforeEach(function () {
$injector = new yok_1.Yok();
});
after(function () {
$injector = new yok_1.Yok();
});
describe("exportedPromise", function () {
it("returns function", function () {
var result = decoratorsLib.exportedPromise("test");
chai_1.assert.equal(typeof (result), "function");
});
it("does not change original method", function () {
var promisifiedResult = decoratorsLib.exportedPromise(moduleName);
var expectedResult = { "originalObject": "originalValue" };
var actualResult = promisifiedResult({}, "myTest1", expectedResult);
chai_1.assert.deepEqual(actualResult, expectedResult);
});
it("adds method to public api", function () {
generatePublicApiFromExportedPromiseDecorator();
chai_1.assert.deepEqual(typeof ($injector.publicApi.__modules__[moduleName][propertyName]), "function");
});
it("returns Promise", function (done) {
var expectedResult = "result";
$injector.register(moduleName, { propertyName: function () { return expectedResult; } });
generatePublicApiFromExportedPromiseDecorator();
var promise = $injector.publicApi.__modules__[moduleName][propertyName]();
chai_1.assert.equal(typeof (promise.then), "function");
promise.then(function (val) {
chai_1.assert.deepEqual(val, expectedResult);
}).then(done).catch(done);
});
it("returns Promise, which is resolved to correct value (function without arguments)", function (done) {
var expectedResult = "result";
$injector.register(moduleName, { propertyName: function () { return expectedResult; } });
generatePublicApiFromExportedPromiseDecorator();
var promise = $injector.publicApi.__modules__[moduleName][propertyName]();
promise.then(function (val) {
chai_1.assert.deepEqual(val, expectedResult);
}).then(done).catch(done);
});
it("returns Promise, which is resolved to correct value (function with arguments)", function (done) {
var expectedArgs = ["result", "result1", "result2"];
$injector.register(moduleName, { propertyName: function (functionArgs) { return functionArgs; } });
generatePublicApiFromExportedPromiseDecorator();
var promise = $injector.publicApi.__modules__[moduleName][propertyName](expectedArgs);
promise.then(function (val) {
chai_1.assert.deepEqual(val, expectedArgs);
}).then(done).catch(done);
});
it("returns Promise, which is resolved to correct value (function returning IFuture without arguments)", function (done) {
var expectedResult = "result";
$injector.register(moduleName, { propertyName: function () { return Future.fromResult(expectedResult); } });
generatePublicApiFromExportedPromiseDecorator();
var promise = $injector.publicApi.__modules__[moduleName][propertyName]();
promise.then(function (val) {
chai_1.assert.deepEqual(val, expectedResult);
}).then(done).catch(done);
});
it("returns Promise, which is resolved to correct value (function returning IFuture with arguments)", function (done) {
var expectedArgs = ["result", "result1", "result2"];
$injector.register(moduleName, { propertyName: function (args) { return Future.fromResult(args); } });
generatePublicApiFromExportedPromiseDecorator();
var promise = $injector.publicApi.__modules__[moduleName][propertyName](expectedArgs);
promise.then(function (val) {
chai_1.assert.deepEqual(val, expectedArgs);
}).then(done).catch(done);
});
it("rejects Promise, which is resolved to correct error (function without arguments throws)", function (done) {
var expectedError = new Error("Test msg");
$injector.register(moduleName, { propertyName: function () { throw expectedError; } });
generatePublicApiFromExportedPromiseDecorator();
var promise = $injector.publicApi.__modules__[moduleName][propertyName]();
promise.then(function (result) {
throw new Error("Then method MUST not be called when promise is rejected!");
}, function (err) {
chai_1.assert.deepEqual(err, expectedError);
}).then(done).catch(done);
});
it("rejects Promise, which is resolved to correct error (function returning IFuture without arguments throws)", function (done) {
var expectedError = new Error("Test msg");
$injector.register(moduleName, { propertyName: function () { return (function () { throw expectedError; }).future()(); } });
generatePublicApiFromExportedPromiseDecorator();
var promise = $injector.publicApi.__modules__[moduleName][propertyName]();
promise.then(function (result) {
throw new Error("Then method MUST not be called when promise is rejected!");
}, function (err) {
chai_1.assert.deepEqual(err.message, expectedError.message);
}).then(done).catch(done);
});
it("returns Promises, which are resolved to correct value (function returning IFuture<T>[] without arguments)", function (done) {
var expectedResults = ["result1", "result2", "result3"];
$injector.register(moduleName, { propertyName: function () { return _.map(expectedResults, function (expectedResult) { return Future.fromResult(expectedResult); }); } });
generatePublicApiFromExportedPromiseDecorator();
var promises = $injector.publicApi.__modules__[moduleName][propertyName]();
Promise.all(promises)
.then(function (promiseResults) {
_.each(promiseResults, function (val, index) {
chai_1.assert.deepEqual(val, expectedResults[index]);
});
})
.then(done)
.catch(done);
});
it("rejects Promises, which are resolved to correct error (function returning IFuture<T>[] without arguments throws)", function (done) {
var expectedErrors = [new Error("result1"), new Error("result2"), new Error("result3")];
$injector.register(moduleName, { propertyName: function () { return _.map(expectedErrors, function (expectedError) { return (function () { throw expectedError; }).future()(); }); } });
generatePublicApiFromExportedPromiseDecorator();
new Promise(function (onFulfilled, onRejected) {
var promises = $injector.publicApi.__modules__[moduleName][propertyName]();
_.each(promises, function (promise, index) { return promise.then(function (result) {
onRejected(new Error("Then method MUST not be called when promise is rejected!. Result of promise is: " + result));
}, function (err) {
if (err.message !== expectedErrors[index].message) {
onRejected(new Error("Error message of rejected promise is not the expected one: expected: \"" + expectedErrors[index].message + "\", but was: \"" + err.message + "\"."));
}
if (index + 1 === expectedErrors.length) {
onFulfilled();
}
}); });
}).then(done).catch(done);
});
it("rejects only Promises which throw, resolves the others correctly (function returning IFuture<T>[] without arguments)", function (done) {
var expectedResults = ["result1", new Error("result2")];
$injector.register(moduleName, { propertyName: function () { return _.map(expectedResults, function (expectedResult) { return Future.fromResult(expectedResult); }); } });
generatePublicApiFromExportedPromiseDecorator();
new Promise(function (onFulfilled, onRejected) {
var promises = $injector.publicApi.__modules__[moduleName][propertyName]();
_.each(promises, function (promise, index) { return promise.then(function (val) {
chai_1.assert.deepEqual(val, expectedResults[index]);
if (index + 1 === expectedResults.length) {
onFulfilled();
}
}, function (err) {
chai_1.assert.deepEqual(err.message, expectedResults[index].message);
if (index + 1 === expectedResults.length) {
onFulfilled();
}
}); });
}).then(done).catch(done);
});
describe("postAction", function () {
var isPostActionExecuted = false;
var isActionExecuted = false;
var expectedResults;
var postAction = function () {
chai_1.assert.isTrue(isActionExecuted, "Post Action MUST be executed AFTER all actions are executed.");
isPostActionExecuted = true;
};
var getPromisesWithPostAction = function () {
var promisifiedResultFunction = decoratorsLib.exportedPromise(moduleName, postAction);
promisifiedResultFunction({}, propertyName, {});
return $injector.publicApi.__modules__[moduleName][propertyName]();
};
var assertResults = function (result) {
chai_1.assert.deepEqual(result, expectedResults);
chai_1.assert.isTrue(isPostActionExecuted, "Post action must be executed after all promises are resolved.");
chai_1.assert.isTrue(isActionExecuted, "All actions must be executed after the promise is resolved.");
};
beforeEach(function () {
isPostActionExecuted = false;
isActionExecuted = false;
});
it("executes postAction after all promises are resolved (function returning IFuture<T>)", function (done) {
expectedResults = "result";
$injector.register(moduleName, {
propertyName: function () {
return (function () {
chai_1.assert.isFalse(isPostActionExecuted, "Post action MUST NOT be called before all actions are executed.");
isActionExecuted = true;
return expectedResults;
}).future()();
}
});
getPromisesWithPostAction()
.then(assertResults)
.then(done)
.catch(done);
});
it("executes postAction after all promises are resolved (function returning IFuture<T>[])", function (done) {
expectedResults = ["result1", "result2", "result3"];
$injector.register(moduleName, {
propertyName: function () { return _.map(expectedResults, function (expectedResult, index) {
return (function () {
chai_1.assert.isFalse(isPostActionExecuted, "Post action MUST NOT be called before all actions are executed.");
isActionExecuted = (index + 1) === expectedResults.length;
return expectedResult;
}).future()();
}); }
});
Promise.all(getPromisesWithPostAction())
.then(assertResults)
.then(done)
.catch(done);
});
it("executes postAction after a promise is rejected (function returning IFuture<T> that throws)", function (done) {
expectedResults = "result";
var errorMessage = "This future throws";
$injector.register(moduleName, {
propertyName: function () {
return (function () {
chai_1.assert.isFalse(isPostActionExecuted, "Post action MUST NOT be called before all actions are executed.");
isActionExecuted = true;
throw new Error(errorMessage);
}).future()();
}
});
getPromisesWithPostAction()
.then(function (result) {
throw new Error("Then method MUST not be called when promise is rejected!");
}, function (err) {
chai_1.assert.deepEqual(err.message, errorMessage, "Error message of rejection should be the specified one.");
chai_1.assert.isTrue(isPostActionExecuted, "Post action must be executed after all promises are resolved.");
chai_1.assert.isTrue(isActionExecuted, "All actions must be executed after the promise is resolved.");
})
.then(done)
.catch(done);
});
it("executes postAction after all promises are rejected (function returning IFuture<T>[] that throws)", function (done) {
expectedResults = ["result1", "result2", "result3"];
var errorMessage = "This future throws.";
$injector.register(moduleName, {
propertyName: function () { return _.map(expectedResults, function (expectedResult, index) {
return (function () {
chai_1.assert.isFalse(isPostActionExecuted, "Post action MUST NOT be called before all actions are executed.");
isActionExecuted = (index + 1) === expectedResults.length;
throw new Error(errorMessage);
}).future()();
}); }
});
var caughtErrors = 0;
var mainPromise = new Promise(function (onFulfilled, onRejected) {
_.each(getPromisesWithPostAction(), function (promise) { return promise.then(function (result) {
throw new Error("Then method MUST not be called when promise is rejected!");
}, function (err) {
caughtErrors++;
chai_1.assert.deepEqual(err.message, errorMessage, "Error message of rejection should be the specified one.");
if (caughtErrors === expectedResults.length) {
onFulfilled();
}
}); });
});
mainPromise
.then(function (result) {
chai_1.assert.isTrue(isPostActionExecuted, "Post action must be executed after all promises are resolved.");
chai_1.assert.isTrue(isActionExecuted, "All actions must be executed after the promise is resolved.");
done();
})
.catch(done);
});
it("executes postAction after all some promises are rejected and others are resolved (function returning IFuture<T>[] where some of the future throw)", function (done) {
var calledActionsCount = 0;
expectedResults = ["result1", "result2", "result3", "result4"];
var errorMessage = "This future throws.";
$injector.register(moduleName, {
propertyName: function () { return _.map(expectedResults, function (expectedResult) {
return (function () {
chai_1.assert.isFalse(isPostActionExecuted, "Post action MUST NOT be called before all actions are executed.");
calledActionsCount++;
isActionExecuted = calledActionsCount === expectedResults.length;
if (calledActionsCount % 2 === 0) {
throw new Error(errorMessage);
}
else {
return expectedResult;
}
}).future()();
}); }
});
var caughtErrors = 0, resolvedPromises = 0;
var mainPromise = new Promise(function (onFulfilled, onRejected) {
_.each(getPromisesWithPostAction(), function (promise, index) { return promise.then(function (result) {
resolvedPromises++;
chai_1.assert.deepEqual(result, expectedResults[index]);
if ((caughtErrors + resolvedPromises) === expectedResults.length) {
onFulfilled();
}
}, function (err) {
caughtErrors++;
chai_1.assert.deepEqual(err.message, errorMessage, "Error message of rejection should be the specified one.");
if ((caughtErrors + resolvedPromises) === expectedResults.length) {
onFulfilled();
}
}); });
});
mainPromise
.then(function (result) {
chai_1.assert.isTrue(isPostActionExecuted, "Post action must be executed after all promises are resolved.");
chai_1.assert.isTrue(isActionExecuted, "All actions must be executed after the promise is resolved.");
done();
})
.catch(done);
});
});
});
describe("exported", function () {
var expectedResults = [
"string result",
1,
{ a: 1, b: "2" },
["string 1", "string2"],
true,
undefined,
null
];
var generatePublicApiFromExportedDecorator = function () {
chai_1.assert.deepEqual($injector.publicApi.__modules__[moduleName], undefined);
var resultFunction = decoratorsLib.exported(moduleName);
resultFunction({}, propertyName, {});
};
it("returns function", function () {
var result = decoratorsLib.exported("test");
chai_1.assert.equal(typeof (result), "function");
});
it("does not change original method", function () {
var exportedFunctionResult = decoratorsLib.exported(moduleName);
var expectedResult = { "originalObject": "originalValue" };
var actualResult = exportedFunctionResult({}, "myTest1", expectedResult);
chai_1.assert.deepEqual(actualResult, expectedResult);
});
_.each(expectedResults, function (expectedResult) {
it("returns correct result when function returns " + (_.isArray(expectedResult) ? "array" : typeof (expectedResult)), function () {
$injector.register(moduleName, { propertyName: function () { return expectedResult; } });
generatePublicApiFromExportedDecorator();
var actualResult = $injector.publicApi.__modules__[moduleName][propertyName]();
chai_1.assert.deepEqual(actualResult, expectedResult);
});
it("passes correct arguments to original function, when argument type is: " + (_.isArray(expectedResult) ? "array" : typeof (expectedResult)), function () {
$injector.register(moduleName, { propertyName: function (arg) { return arg; } });
generatePublicApiFromExportedDecorator();
var actualResult = $injector.publicApi.__modules__[moduleName][propertyName](expectedResult);
chai_1.assert.deepEqual(actualResult, expectedResult);
});
});
it("when function throws, raises the error only when the public API is called, not when decorator is applied", function () {
var errorMessage = "This is error message";
$injector.register(moduleName, { propertyName: function () { throw new Error(errorMessage); } });
generatePublicApiFromExportedDecorator();
chai_1.assert.throws(function () { return $injector.publicApi.__modules__[moduleName][propertyName](); }, errorMessage);
});
it("throws error when passed function returns IFuture", function () {
$injector.register(moduleName, { propertyName: function () { return Future.fromResult(expectedResults); } });
generatePublicApiFromExportedDecorator();
chai_1.assert.throws(function () { return $injector.publicApi.__modules__[moduleName][propertyName](); }, "Cannot use exported decorator with function returning IFuture<T>.");
});
});
});