UNPKG

mobile-cli-lib

Version:
359 lines (358 loc) 21.7 kB
"use strict"; 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>."); }); }); });