UNPKG

mobile-cli-lib

Version:
738 lines (737 loc) 80.9 kB
"use strict"; var __extends = (this && this.__extends) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; var devices_service_1 = require("../../../mobile/mobile-core/devices-service"); var yok_1 = require("../../../yok"); var Future = require("fibers/future"); var events_1 = require("events"); var chai_1 = require("chai"); var stubs_1 = require("../stubs"); var messages_1 = require("../../../messages/messages"); var constants = require("../../../constants"); var device_platforms_constants_1 = require("../../../mobile/device-platforms-constants"); var IOSDeviceDiscoveryStub = (function (_super) { __extends(IOSDeviceDiscoveryStub, _super); function IOSDeviceDiscoveryStub() { _super.apply(this, arguments); } IOSDeviceDiscoveryStub.prototype.startLookingForDevices = function () { return Future.fromResult(); }; IOSDeviceDiscoveryStub.prototype.checkForDevices = function () { return Future.fromResult(); }; return IOSDeviceDiscoveryStub; }(events_1.EventEmitter)); var AndroidDeviceDiscoveryStub = (function (_super) { __extends(AndroidDeviceDiscoveryStub, _super); function AndroidDeviceDiscoveryStub() { _super.apply(this, arguments); } AndroidDeviceDiscoveryStub.prototype.startLookingForDevices = function () { return Future.fromResult(); }; AndroidDeviceDiscoveryStub.prototype.checkForDevices = function () { return Future.fromResult(); }; return AndroidDeviceDiscoveryStub; }(events_1.EventEmitter)); var IOSSimulatorDiscoveryStub = (function (_super) { __extends(IOSSimulatorDiscoveryStub, _super); function IOSSimulatorDiscoveryStub() { _super.apply(this, arguments); } IOSSimulatorDiscoveryStub.prototype.startLookingForDevices = function () { return Future.fromResult(); }; IOSSimulatorDiscoveryStub.prototype.checkForDevices = function () { return Future.fromResult(); }; return IOSSimulatorDiscoveryStub; }(events_1.EventEmitter)); var androidDeviceDiscovery, iOSDeviceDiscovery, iOSSimulatorDiscovery, androidEmulatorDevice = { deviceInfo: { identifier: "androidEmulatorDevice", platform: "android" }, isEmulator: true }, iOSSimulator = { deviceInfo: { identifier: "ios-simulator-device", platform: "ios" }, applicationManager: { getInstalledApplications: function () { return Future.fromResult(["com.telerik.unitTest1", "com.telerik.unitTest2"]); }, canStartApplication: function () { return true; }, startApplication: function (packageName, framework) { return Future.fromResult(); }, tryStartApplication: function (packageName, framework) { return Future.fromResult(); }, reinstallApplication: function (packageName, packageFile) { return Future.fromResult(); }, isApplicationInstalled: function (packageName) { return Future.fromResult(_.includes(["com.telerik.unitTest1", "com.telerik.unitTest2"], packageName)); }, isLiveSyncSupported: function (appIdentifier) { return Future.fromResult(_.includes(["com.telerik.unitTest1", "com.telerik.unitTest2"], appIdentifier)); } }, deploy: function (packageFile, packageName) { return Future.fromResult(); }, isEmulator: true }; var AndroidEmulatorServices = (function () { function AndroidEmulatorServices() { this.isStartEmulatorCalled = false; } AndroidEmulatorServices.prototype.startEmulator = function () { this.isStartEmulatorCalled = true; androidDeviceDiscovery.emit("deviceFound", androidEmulatorDevice); return Future.fromResult(); }; return AndroidEmulatorServices; }()); var IOSEmulatorServices = (function () { function IOSEmulatorServices() { this.isStartEmulatorCalled = false; } IOSEmulatorServices.prototype.startEmulator = function () { if (!this.isStartEmulatorCalled) { this.isStartEmulatorCalled = true; iOSSimulatorDiscovery.emit("deviceFound", iOSSimulator); } return Future.fromResult(); }; return IOSEmulatorServices; }()); function createTestInjector() { var testInjector = new yok_1.Yok(); testInjector.register("logger", stubs_1.CommonLoggerStub); testInjector.register("errors", stubs_1.ErrorsStub); testInjector.register("iOSDeviceDiscovery", IOSDeviceDiscoveryStub); testInjector.register("iOSSimulatorDiscovery", IOSSimulatorDiscoveryStub); testInjector.register("androidDeviceDiscovery", AndroidDeviceDiscoveryStub); testInjector.register("staticConfig", { CLIENT_NAME: "unit-tests" }); testInjector.register("devicePlatformsConstants", device_platforms_constants_1.DevicePlatformsConstants); testInjector.register("androidEmulatorServices", AndroidEmulatorServices); testInjector.register("iOSEmulatorServices", IOSEmulatorServices); testInjector.register("messages", messages_1.Messages); testInjector.register("companionAppsService", {}); testInjector.register("processService", { attachToProcessExitSignals: function (context, callback) { } }); testInjector.register("mobileHelper", { platformNames: ["ios", "android"], validatePlatformName: function (platform) { return platform.toLowerCase(); }, getPlatformCapabilities: function (platform) { return { cableDeploy: true }; }, isiOSPlatform: function (platform) { return !!(platform && platform.toLowerCase() === "ios"); }, isAndroidPlatform: function (platform) { return !!(platform && platform.toLowerCase() === "android"); } }); testInjector.register("deviceLogProvider", { setLogLevel: function (logLevel, deviceIdentifier) { } }); testInjector.register("devicesService", devices_service_1.DevicesService); testInjector.register("hostInfo", { isDarwin: false }); testInjector.register("options", { emulator: false }); testInjector.register("androidProcessService", {}); return testInjector; } function mockIsAppInstalled(devices, expectedResult) { _.each(devices, function (device, index) { return device.applicationManager.isApplicationInstalled = function (packageName) { return Future.fromResult(expectedResult[index]); }; }); } function throwErrorFuture() { return (function () { throw new Error("error"); }).future()(); } var intervalId = 1; var nodeJsTimer = { ref: function () { }, unref: function () { return intervalId++; } }; var originalSetInterval = setInterval; function mockSetInterval(options) { global.setInterval = function (callback, ms) { var args = []; for (var _i = 2; _i < arguments.length; _i++) { args[_i - 2] = arguments[_i]; } if (options.shouldExecuteCallback) { callback(); } if (options.testCaseCallback) { options.testCaseCallback(); } return nodeJsTimer; }; } function resetDefaultSetInterval() { global.setInterval = originalSetInterval; } describe("devicesService", function () { var counter = 0, iOSDevice = { deviceInfo: { identifier: "ios-device", platform: "ios" }, applicationManager: { getInstalledApplications: function () { return Future.fromResult(["com.telerik.unitTest1", "com.telerik.unitTest2"]); }, canStartApplication: function () { return true; }, startApplication: function (packageName, framework) { return Future.fromResult(); }, tryStartApplication: function (packageName, framework) { return Future.fromResult(); }, reinstallApplication: function (packageName, packageFile) { return Future.fromResult(); }, isApplicationInstalled: function (packageName) { return Future.fromResult(_.includes(["com.telerik.unitTest1", "com.telerik.unitTest2"], packageName)); }, isLiveSyncSupported: function (appIdentifier) { return Future.fromResult(_.includes(["com.telerik.unitTest1", "com.telerik.unitTest2"], appIdentifier)); }, checkForApplicationUpdates: function () { return Future.fromResult(); }, getDebuggableApps: function () { return Future.fromResult(null); }, getDebuggableAppViews: function (appIdentifiers) { return Future.fromResult(null); } }, deploy: function (packageFile, packageName) { return Future.fromResult(); } }, androidDevice = { deviceInfo: { identifier: "android-device", platform: "android" }, applicationManager: { getInstalledApplications: function () { return Future.fromResult(["com.telerik.unitTest1", "com.telerik.unitTest2", "com.telerik.unitTest3"]); }, canStartApplication: function () { return true; }, startApplication: function (packageName, framework) { return Future.fromResult(); }, tryStartApplication: function (packageName, framework) { return Future.fromResult(); }, reinstallApplication: function (packageName, packageFile) { return Future.fromResult(); }, isApplicationInstalled: function (packageName) { return Future.fromResult(_.includes(["com.telerik.unitTest1", "com.telerik.unitTest2", "com.telerik.unitTest3"], packageName)); }, isLiveSyncSupported: function (appIdentifier) { return Future.fromResult(_.includes(["com.telerik.unitTest1", "com.telerik.unitTest2", "com.telerik.unitTest3"], appIdentifier)); }, checkForApplicationUpdates: function () { return Future.fromResult(); }, getDebuggableApps: function () { return Future.fromResult(null); }, getDebuggableAppViews: function (appIdentifiers) { return Future.fromResult(null); } }, deploy: function (packageFile, packageName) { return Future.fromResult(); } }, testInjector, devicesService, androidEmulatorServices, logger, assertAndroidEmulatorIsStarted = function () { chai_1.assert.isFalse(androidEmulatorServices.isStartEmulatorCalled); devicesService.execute(function () { counter++; return Future.fromResult(); }, function () { return true; }).wait(); chai_1.assert.deepEqual(counter, 1, "The action must be executed on only one device."); chai_1.assert.isTrue(androidEmulatorServices.isStartEmulatorCalled); androidDeviceDiscovery.emit("deviceLost", androidEmulatorDevice); androidEmulatorServices.isStartEmulatorCalled = false; }; beforeEach(function () { testInjector = createTestInjector(); devicesService = testInjector.resolve("devicesService"); iOSDeviceDiscovery = testInjector.resolve("iOSDeviceDiscovery"); iOSSimulatorDiscovery = testInjector.resolve("iOSSimulatorDiscovery"); androidDeviceDiscovery = testInjector.resolve("androidDeviceDiscovery"); androidEmulatorServices = testInjector.resolve("androidEmulatorServices"); logger = testInjector.resolve("logger"); counter = 0; }); it("attaches to events when a new DevicesService is instantiated", function () { iOSDeviceDiscovery.emit("deviceFound", iOSDevice); androidDeviceDiscovery.emit("deviceFound", androidDevice); var devices = devicesService.getDeviceInstances(); chai_1.assert.isTrue(devicesService.hasDevices, "After emitting two devices, hasDevices must be true"); chai_1.assert.deepEqual(devices[0], iOSDevice); chai_1.assert.deepEqual(devices[1], androidDevice); }); describe("hasDevices", function () { it("is true when device is found", function () { chai_1.assert.isFalse(devicesService.hasDevices, "Initially devicesService hasDevices must be false."); androidDeviceDiscovery.emit("deviceFound", androidDevice); chai_1.assert.isTrue(devicesService.hasDevices, "After emitting, hasDevices must be true"); }); it("is false when device is found and lost after that", function () { chai_1.assert.isFalse(devicesService.hasDevices, "Initially devicesService hasDevices must be false."); androidDeviceDiscovery.emit("deviceFound", androidDevice); androidDeviceDiscovery.emit("deviceLost", androidDevice); chai_1.assert.isFalse(devicesService.hasDevices, "After losing all devices, hasDevices must be false."); }); it("is true when two devices are found and one of them is lost after that", function () { chai_1.assert.isFalse(devicesService.hasDevices, "Initially devicesService hasDevices must be false."); androidDeviceDiscovery.emit("deviceFound", androidDevice); iOSDeviceDiscovery.emit("deviceFound", iOSDevice); androidDeviceDiscovery.emit("deviceLost", androidDevice); chai_1.assert.isTrue(devicesService.hasDevices, "After losing only one of two devices, hasDevices must be true."); }); }); describe("getDeviceInstances and getDevices", function () { it("returns one android device, when only one device is attached", function () { chai_1.assert.deepEqual(devicesService.getDeviceInstances(), [], "Initially getDevicesInstances must return empty array."); chai_1.assert.deepEqual(devicesService.getDevices(), [], "Initially getDevices must return empty array."); androidDeviceDiscovery.emit("deviceFound", androidDevice); chai_1.assert.deepEqual(devicesService.getDeviceInstances(), [androidDevice]); chai_1.assert.deepEqual(devicesService.getDevices(), [androidDevice.deviceInfo]); }); it("does not return any devices, when only one device is attached and it is removed after that", function () { chai_1.assert.deepEqual(devicesService.getDeviceInstances(), [], "Initially getDevicesInstances must return empty array."); chai_1.assert.deepEqual(devicesService.getDevices(), [], "Initially getDevices must return empty array."); androidDeviceDiscovery.emit("deviceFound", androidDevice); chai_1.assert.deepEqual(devicesService.getDeviceInstances(), [androidDevice]); chai_1.assert.deepEqual(devicesService.getDevices(), [androidDevice.deviceInfo]); androidDeviceDiscovery.emit("deviceLost", androidDevice); chai_1.assert.deepEqual(devicesService.getDeviceInstances(), [], "When all devices are lost, getDevicesInstances must return empty array."); chai_1.assert.deepEqual(devicesService.getDevices(), [], "When all devices are lost, getDevices must return empty array."); }); it("returns one android device, when two devices are attached and one of them is removed", function () { chai_1.assert.deepEqual(devicesService.getDeviceInstances(), [], "Initially getDevicesInstances must return empty array."); chai_1.assert.deepEqual(devicesService.getDevices(), [], "Initially getDevices must return empty array."); var tempDevice = { deviceInfo: { identifier: "temp-device" } }; androidDeviceDiscovery.emit("deviceFound", androidDevice); androidDeviceDiscovery.emit("deviceFound", tempDevice); chai_1.assert.deepEqual(devicesService.getDeviceInstances(), [androidDevice, tempDevice]); chai_1.assert.deepEqual(devicesService.getDevices(), [androidDevice.deviceInfo, tempDevice.deviceInfo]); androidDeviceDiscovery.emit("deviceLost", tempDevice); chai_1.assert.deepEqual(devicesService.getDeviceInstances(), [androidDevice]); chai_1.assert.deepEqual(devicesService.getDevices(), [androidDevice.deviceInfo]); }); }); describe("isAppInstalledOnDevices", function () { beforeEach(function () { androidDeviceDiscovery.emit("deviceFound", androidDevice); iOSDeviceDiscovery.emit("deviceFound", iOSDevice); }); it("returns true for each device on which the app is installed", function () { var deviceIdentifiers = [androidDevice.deviceInfo.identifier, iOSDevice.deviceInfo.identifier], appId = "com.telerik.unitTest1"; var results = devicesService.isAppInstalledOnDevices(deviceIdentifiers, appId, "cordova"); chai_1.assert.isTrue(results.length > 0); _.each(results, function (futurizedResult, index) { var realResult = futurizedResult.wait(); chai_1.assert.isTrue(realResult.isInstalled); chai_1.assert.deepEqual(realResult.appIdentifier, appId); chai_1.assert.deepEqual(realResult.deviceIdentifier, deviceIdentifiers[index]); chai_1.assert.deepEqual(realResult.isLiveSyncSupported, true); }); }); it("returns false for each device on which the app is not installed", function () { var results = devicesService.isAppInstalledOnDevices([androidDevice.deviceInfo.identifier, iOSDevice.deviceInfo.identifier], "com.telerik.unitTest3", "cordova"); chai_1.assert.isTrue(results.length > 0); Future.wait(results); chai_1.assert.deepEqual(results.map(function (r) { return r.get().isInstalled; }), [true, false]); }); it("throws error when invalid identifier is passed", function () { var results = devicesService.isAppInstalledOnDevices(["invalidDeviceId", iOSDevice.deviceInfo.identifier], "com.telerik.unitTest1", "cordova"); chai_1.assert.throws(function () { return Future.wait(results); }); _.each(results, function (futurizedResult) { var error = futurizedResult.error; if (error) { chai_1.assert.isTrue(error.message.indexOf("invalidDeviceId") !== -1, "The message must contain the id of the invalid device."); } else { chai_1.assert.isTrue(futurizedResult.get().isInstalled, "The app is installed on iOS Device, so we must return true."); } }); }); }); describe("initialize and other methods behavior after initialze work correctly", function () { var tempDevice = { deviceInfo: { identifier: "temp-device", platform: "android" }, applicationManager: { getInstalledApplications: function () { return Future.fromResult(["com.telerik.unitTest1", "com.telerik.unitTest2", "com.telerik.unitTest3"]); }, isApplicationInstalled: function (packageName) { return Future.fromResult(_.includes(["com.telerik.unitTest1", "com.telerik.unitTest2", "com.telerik.unitTest3"], packageName)); }, isLiveSyncSupported: function (appIdentifier) { return Future.fromResult(_.includes(["com.telerik.unitTest1", "com.telerik.unitTest2", "com.telerik.unitTest3"], appIdentifier)); } } }; describe("when initialize is called with platform and deviceId and device's platform is the same as passed one", function () { var assertAllMethodsResults = function (deviceId) { chai_1.assert.isFalse(devicesService.hasDevices, "Initially devicesService hasDevices must be false."); androidDeviceDiscovery.emit("deviceFound", androidDevice); devicesService.initialize({ platform: "android", deviceId: deviceId }).wait(); chai_1.assert.deepEqual(devicesService.platform, "android"); chai_1.assert.deepEqual(devicesService.deviceCount, 1); androidDeviceDiscovery.emit("deviceFound", tempDevice); chai_1.assert.isTrue(devicesService.hasDevices, "After emitting and initializing, hasDevices must be true"); chai_1.assert.deepEqual(devicesService.getDeviceInstances(), [androidDevice, tempDevice]); chai_1.assert.deepEqual(devicesService.getDevices(), [androidDevice.deviceInfo, tempDevice.deviceInfo]); chai_1.assert.deepEqual(devicesService.deviceCount, 1); devicesService.execute(function () { counter++; return Future.fromResult(); }).wait(); chai_1.assert.deepEqual(counter, 1, "The action must be executed on only one device."); counter = 0; devicesService.execute(function () { counter++; return Future.fromResult(); }, function () { return false; }).wait(); chai_1.assert.deepEqual(counter, 0, "The action must not be executed when canExecute returns false."); counter = 0; devicesService.execute(function () { counter++; return Future.fromResult(); }, function () { return true; }).wait(); chai_1.assert.deepEqual(counter, 1, "The action must be executed on only one device."); androidDeviceDiscovery.emit("deviceLost", androidDevice); androidDeviceDiscovery.emit("deviceLost", tempDevice); counter = 0; assertAndroidEmulatorIsStarted(); counter = 0; devicesService.execute(function () { counter++; return Future.fromResult(); }, function () { return true; }, { allowNoDevices: true }).wait(); chai_1.assert.deepEqual(counter, 0, "The action must not be executed when there are no devices."); chai_1.assert.isTrue(logger.output.indexOf(constants.ERROR_NO_DEVICES) !== -1); }; it("when deviceId is deviceIdentifier", function () { assertAllMethodsResults(androidDevice.deviceInfo.identifier); }); it("when deviceId is index", function () { assertAllMethodsResults("1"); }); it("fails when deviceId is invalid index (less than 0)", function () { chai_1.assert.throws(function () { return devicesService.initialize({ platform: "android", deviceId: "-1" }).wait(); }); }); it("fails when deviceId is invalid index (more than currently connected devices)", function () { chai_1.assert.throws(function () { return devicesService.initialize({ platform: "android", deviceId: "100" }).wait(); }); }); it("does not fail when iOSDeviceDiscovery startLookingForDevices fails", function () { iOSDeviceDiscovery.startLookingForDevices = function () { throw new Error("my error"); }; assertAllMethodsResults("1"); chai_1.assert.isTrue(logger.traceOutput.indexOf("my error") !== -1); }); it("does not fail when androidDeviceDiscovery startLookingForDevices fails", function () { androidDeviceDiscovery.startLookingForDevices = function () { throw new Error("my error"); }; iOSDeviceDiscovery.emit("deviceFound", iOSDevice); devicesService.initialize({ platform: "ios", deviceId: iOSDevice.deviceInfo.identifier }).wait(); chai_1.assert.isTrue(logger.traceOutput.indexOf("my error") !== -1); }); it("does not fail when iosSimulatorDiscovery startLookingForDevices fails", function () { var hostInfo = testInjector.resolve("hostInfo"); hostInfo.isDarwin = true; iOSSimulatorDiscovery.startLookingForDevices = function () { throw new Error("my error"); }; iOSDeviceDiscovery.emit("deviceFound", iOSDevice); devicesService.initialize({ platform: "ios", deviceId: iOSDevice.deviceInfo.identifier }).wait(); chai_1.assert.isTrue(logger.traceOutput.indexOf("my error") !== -1); }); }); it("when initialize is called with platform and deviceId and such device cannot be found", function () { chai_1.assert.isFalse(devicesService.hasDevices, "Initially devicesService hasDevices must be false."); chai_1.assert.throws(function () { return devicesService.initialize({ platform: "android", deviceId: androidDevice.deviceInfo.identifier }).wait(); }); }); it("when initialize is called with deviceId and invalid platform", function () { chai_1.assert.isFalse(devicesService.hasDevices, "Initially devicesService hasDevices must be false."); iOSDeviceDiscovery.emit("deviceFound", iOSDevice); androidDeviceDiscovery.emit("deviceFound", androidDevice); chai_1.assert.throws(function () { return devicesService.initialize({ platform: "invalidPlatform", deviceId: androidDevice.deviceInfo.identifier }).wait(); }); }); it("when initialize is called with platform and deviceId and device's platform is different", function () { chai_1.assert.isFalse(devicesService.hasDevices, "Initially devicesService hasDevices must be false."); iOSDeviceDiscovery.emit("deviceFound", iOSDevice); androidDeviceDiscovery.emit("deviceFound", androidDevice); chai_1.assert.throws(function () { return devicesService.initialize({ platform: "ios", deviceId: androidDevice.deviceInfo.identifier }).wait(); }); }); describe("when only deviceIdentifier is passed", function () { var assertAllMethodsResults = function (deviceId) { chai_1.assert.isFalse(devicesService.hasDevices, "Initially devicesService hasDevices must be false."); androidDeviceDiscovery.emit("deviceFound", androidDevice); devicesService.initialize({ deviceId: deviceId }).wait(); chai_1.assert.deepEqual(devicesService.platform, "android"); chai_1.assert.deepEqual(devicesService.deviceCount, 1); androidDeviceDiscovery.emit("deviceFound", tempDevice); iOSDeviceDiscovery.emit("deviceFound", iOSDevice); chai_1.assert.isTrue(devicesService.hasDevices, "After emitting and initializing, hasDevices must be true"); chai_1.assert.deepEqual(devicesService.getDeviceInstances(), [androidDevice, tempDevice, iOSDevice]); chai_1.assert.deepEqual(devicesService.getDevices(), [androidDevice.deviceInfo, tempDevice.deviceInfo, iOSDevice.deviceInfo]); chai_1.assert.deepEqual(devicesService.deviceCount, 1); counter = 0; devicesService.execute(function () { counter++; return Future.fromResult(); }).wait(); chai_1.assert.deepEqual(counter, 1, "The action must be executed on only one device."); counter = 0; devicesService.execute(function () { counter++; return Future.fromResult(); }, function () { return false; }).wait(); chai_1.assert.deepEqual(counter, 0, "The action must not be executed when canExecute returns false."); counter = 0; devicesService.execute(function () { counter++; return Future.fromResult(); }, function () { return true; }).wait(); chai_1.assert.deepEqual(counter, 1, "The action must be executed on only one device."); androidDeviceDiscovery.emit("deviceLost", androidDevice); androidDeviceDiscovery.emit("deviceLost", tempDevice); iOSDeviceDiscovery.emit("deviceLost", iOSDevice); counter = 0; assertAndroidEmulatorIsStarted(); counter = 0; devicesService.execute(function () { counter++; return Future.fromResult(); }, function () { return true; }, { allowNoDevices: true }).wait(); chai_1.assert.deepEqual(counter, 0, "The action must not be executed when there are no devices."); chai_1.assert.isTrue(logger.output.indexOf(constants.ERROR_NO_DEVICES) !== -1); }; it("when deviceId is deviceIdentifier", function () { assertAllMethodsResults(androidDevice.deviceInfo.identifier); }); it("when deviceId is index", function () { assertAllMethodsResults("1"); }); it("fails when deviceId is invalid index (less than 0)", function () { chai_1.assert.throws(function () { return devicesService.initialize({ deviceId: "-1" }).wait(); }); }); it("fails when deviceId is invalid index (more than currently connected devices)", function () { chai_1.assert.throws(function () { return devicesService.initialize({ deviceId: "100" }).wait(); }); }); it("does not fail when iOSDeviceDiscovery startLookingForDevices fails", function () { iOSDeviceDiscovery.startLookingForDevices = function () { throw new Error("my error"); }; assertAllMethodsResults("1"); chai_1.assert.isTrue(logger.traceOutput.indexOf("my error") !== -1); }); it("does not fail when androidDeviceDiscovery startLookingForDevices fails", function () { androidDeviceDiscovery.startLookingForDevices = function () { throw new Error("my error"); }; iOSDeviceDiscovery.emit("deviceFound", iOSDevice); devicesService.initialize({ deviceId: iOSDevice.deviceInfo.identifier }).wait(); chai_1.assert.isTrue(logger.traceOutput.indexOf("my error") !== -1); }); }); describe("when only platform is passed", function () { it("execute fails when platform is iOS on non-Darwin platform and there are no devices attached when --emulator is passed", function () { testInjector.resolve("hostInfo").isDarwin = false; devicesService.initialize({ platform: "ios" }).wait(); testInjector.resolve("options").emulator = true; chai_1.assert.throws(function () { return devicesService.execute(function () { counter++; return Future.fromResult(); }).wait(); }, "Cannot find connected devices. Reconnect any connected devices"); }); it("execute fails when platform is iOS on non-Darwin platform and there are no devices attached", function () { testInjector.resolve("hostInfo").isDarwin = false; devicesService.initialize({ platform: "ios" }).wait(); chai_1.assert.isFalse(devicesService.hasDevices, "MUST BE FALSE!!!"); chai_1.assert.throws(function () { return devicesService.execute(function () { counter++; return Future.fromResult(); }).wait(); }, "Cannot find connected devices. Reconnect any connected devices"); }); it("executes action only on iOS Simulator when iOS device is found and --emulator is passed", function () { testInjector.resolve("options").emulator = true; testInjector.resolve("hostInfo").isDarwin = true; iOSDeviceDiscovery.emit("deviceFound", iOSDevice); devicesService.initialize({ platform: "ios" }).wait(); var deviceIdentifier; counter = 0; devicesService.execute(function (d) { deviceIdentifier = d.deviceInfo.identifier; counter++; return Future.fromResult(); }).wait(); chai_1.assert.deepEqual(counter, 1, "The action must be executed on only one device. ASAAS"); chai_1.assert.deepEqual(deviceIdentifier, iOSSimulator.deviceInfo.identifier); counter = 0; devicesService.execute(function () { counter++; return Future.fromResult(); }, function () { return false; }).wait(); chai_1.assert.deepEqual(counter, 0, "The action must not be executed when canExecute returns false."); counter = 0; iOSDeviceDiscovery.emit("deviceLost", iOSDevice); deviceIdentifier = null; devicesService.execute(function (d) { deviceIdentifier = d.deviceInfo.identifier; counter++; return Future.fromResult(); }).wait(); chai_1.assert.deepEqual(counter, 1, "The action must be executed on only one device."); chai_1.assert.deepEqual(deviceIdentifier, iOSSimulator.deviceInfo.identifier); counter = 0; deviceIdentifier = null; devicesService.execute(function (d) { deviceIdentifier = d.deviceInfo.identifier; counter++; return Future.fromResult(); }, function () { return false; }).wait(); chai_1.assert.deepEqual(counter, 0, "The action must not be executed when canExecute returns false."); chai_1.assert.deepEqual(deviceIdentifier, null); }); it("all methods work as expected", function () { chai_1.assert.isFalse(devicesService.hasDevices, "Initially devicesService hasDevices must be false."); androidDeviceDiscovery.emit("deviceFound", androidDevice); devicesService.initialize({ platform: "android" }).wait(); chai_1.assert.deepEqual(devicesService.platform, "android"); chai_1.assert.deepEqual(devicesService.deviceCount, 1); androidDeviceDiscovery.emit("deviceFound", tempDevice); chai_1.assert.isTrue(devicesService.hasDevices, "After emitting and initializing, hasDevices must be true"); chai_1.assert.deepEqual(devicesService.getDeviceInstances(), [androidDevice, tempDevice]); chai_1.assert.deepEqual(devicesService.getDevices(), [androidDevice.deviceInfo, tempDevice.deviceInfo]); chai_1.assert.deepEqual(devicesService.deviceCount, 2); counter = 0; devicesService.execute(function () { counter++; return Future.fromResult(); }).wait(); chai_1.assert.deepEqual(counter, 2, "The action must be executed on two devices."); counter = 0; devicesService.execute(function () { counter++; return Future.fromResult(); }, function () { return false; }).wait(); chai_1.assert.deepEqual(counter, 0, "The action must not be executed when canExecute returns false."); counter = 0; devicesService.execute(function () { counter++; return Future.fromResult(); }, function () { return true; }).wait(); chai_1.assert.deepEqual(counter, 2, "The action must be executed on two devices."); androidDeviceDiscovery.emit("deviceLost", androidDevice); counter = 0; devicesService.execute(function () { counter++; return Future.fromResult(); }, function () { return true; }).wait(); chai_1.assert.deepEqual(counter, 1, "The action must be executed on only one device."); androidDeviceDiscovery.emit("deviceLost", tempDevice); counter = 0; assertAndroidEmulatorIsStarted(); counter = 0; devicesService.execute(function () { counter++; return Future.fromResult(); }, function () { return true; }, { allowNoDevices: true }).wait(); chai_1.assert.deepEqual(counter, 0, "The action must not be executed when there are no devices."); chai_1.assert.isTrue(logger.output.indexOf(constants.ERROR_NO_DEVICES) !== -1); chai_1.assert.isFalse(androidEmulatorServices.isStartEmulatorCalled); }); }); it("when only skipInferPlatform is passed (true)", function () { chai_1.assert.isFalse(devicesService.hasDevices, "Initially devicesService hasDevices must be false."); androidDeviceDiscovery.emit("deviceFound", androidDevice); iOSDeviceDiscovery.emit("deviceFound", iOSDevice); devicesService.initialize({ skipInferPlatform: true }).wait(); chai_1.assert.deepEqual(devicesService.platform, undefined); chai_1.assert.deepEqual(devicesService.deviceCount, 2); androidDeviceDiscovery.emit("deviceFound", tempDevice); chai_1.assert.isTrue(devicesService.hasDevices, "After emitting and initializing, hasDevices must be true"); chai_1.assert.deepEqual(devicesService.getDeviceInstances(), [androidDevice, iOSDevice, tempDevice]); chai_1.assert.deepEqual(devicesService.getDevices(), [androidDevice.deviceInfo, iOSDevice.deviceInfo, tempDevice.deviceInfo]); chai_1.assert.deepEqual(devicesService.deviceCount, 3); counter = 0; devicesService.execute(function () { counter++; return Future.fromResult(); }).wait(); chai_1.assert.deepEqual(counter, 3, "The action must be executed on two devices."); counter = 0; devicesService.execute(function () { counter++; return Future.fromResult(); }, function () { return false; }).wait(); chai_1.assert.deepEqual(counter, 0, "The action must not be executed when canExecute returns false."); counter = 0; devicesService.execute(function () { counter++; return Future.fromResult(); }, function () { return true; }).wait(); chai_1.assert.deepEqual(counter, 3, "The action must be executed on three devices."); androidDeviceDiscovery.emit("deviceLost", androidDevice); counter = 0; devicesService.execute(function () { counter++; return Future.fromResult(); }, function () { return true; }).wait(); chai_1.assert.deepEqual(counter, 2, "The action must be executed on two devices."); androidDeviceDiscovery.emit("deviceLost", tempDevice); iOSDeviceDiscovery.emit("deviceLost", iOSDevice); counter = 0; chai_1.assert.throws(function () { return devicesService.execute(function () { counter++; return Future.fromResult(); }, function () { return true; }).wait(); }); counter = 0; devicesService.execute(function () { counter++; return Future.fromResult(); }, function () { return true; }, { allowNoDevices: true }).wait(); chai_1.assert.deepEqual(counter, 0, "The action must not be executed when there are no devices."); chai_1.assert.isTrue(logger.output.indexOf(constants.ERROR_NO_DEVICES) !== -1); }); it("when parameters are not passed and devices with same platform are detected", function () { chai_1.assert.isFalse(devicesService.hasDevices, "Initially devicesService hasDevices must be false."); androidDeviceDiscovery.emit("deviceFound", androidDevice); devicesService.initialize().wait(); chai_1.assert.deepEqual(devicesService.platform, "android"); chai_1.assert.deepEqual(devicesService.deviceCount, 1); androidDeviceDiscovery.emit("deviceFound", tempDevice); chai_1.assert.isTrue(devicesService.hasDevices, "After emitting and initializing, hasDevices must be true"); chai_1.assert.deepEqual(devicesService.getDeviceInstances(), [androidDevice, tempDevice]); chai_1.assert.deepEqual(devicesService.getDevices(), [androidDevice.deviceInfo, tempDevice.deviceInfo]); chai_1.assert.deepEqual(devicesService.deviceCount, 2); counter = 0; devicesService.execute(function () { counter++; return Future.fromResult(); }).wait(); chai_1.assert.deepEqual(counter, 2, "The action must be executed on two devices."); counter = 0; devicesService.execute(function () { counter++; return Future.fromResult(); }, function () { return false; }).wait(); chai_1.assert.deepEqual(counter, 0, "The action must not be executed when canExecute returns false."); counter = 0; devicesService.execute(function () { counter++; return Future.fromResult(); }, function () { return true; }).wait(); chai_1.assert.deepEqual(counter, 2, "The action must be executed on two devices."); androidDeviceDiscovery.emit("deviceLost", androidDevice); counter = 0; devicesService.execute(function () { counter++; return Future.fromResult(); }, function () { return true; }).wait(); chai_1.assert.deepEqual(counter, 1, "The action must be executed on only one device."); androidDeviceDiscovery.emit("deviceLost", tempDevice); counter = 0; assertAndroidEmulatorIsStarted(); counter = 0; devicesService.execute(function () { counter++; return Future.fromResult(); }, function () { return true; }, { allowNoDevices: true }).wait(); chai_1.assert.deepEqual(counter, 0, "The action must not be executed when there are no devices."); chai_1.assert.isTrue(logger.output.indexOf(constants.ERROR_NO_DEVICES) !== -1); }); it("when parameters are not passed and devices with different platforms are detected initialize should throw", function () { chai_1.assert.isFalse(devicesService.hasDevices, "Initially devicesService hasDevices must be false."); androidDeviceDiscovery.emit("deviceFound", androidDevice); iOSDeviceDiscovery.emit("deviceFound", iOSDevice); chai_1.assert.throws(function () { return devicesService.initialize().wait(); }); }); it("when parameters are not passed and devices with invalid platforms are detected initialize should work with correct devices only", function () { chai_1.assert.isFalse(devicesService.hasDevices, "Initially devicesService hasDevices must be false."); androidDeviceDiscovery.emit("deviceFound", androidDevice); iOSDeviceDiscovery.emit("deviceFound", { deviceInfo: { identifier: "invalid-platform-device", platform: "invalid-platform" } }); devicesService.initialize().wait(); chai_1.assert.isTrue(logger.output.indexOf("is not supported") !== -1); }); it("when parameters are not passed and only devices with invalid platforms are detected, initialize should throw", function () { chai_1.assert.isFalse(devicesService.hasDevices, "Initially devicesService hasDevices must be false."); iOSDeviceDiscovery.emit("deviceFound", { deviceInfo: { identifier: "invalid-platform-device", platform: "invalid-platform" } }); chai_1.assert.throws(function () { return devicesService.initialize().wait(); }); chai_1.assert.isTrue(logger.output.indexOf("is not supported") !== -1); }); it("caches execution result and does not execute next time when called", function () { chai_1.assert.isFalse(devicesService.hasDevices, "Initially devicesService hasDevices must be false."); androidDeviceDiscovery.emit("deviceFound", androidDevice); devicesService.initialize({ platform: "android" }).wait(); chai_1.assert.deepEqual(devicesService.platform, "android"); chai_1.assert.deepEqual(devicesService.deviceCount, 1); devicesService.initialize({ platform: "ios" }).wait(); chai_1.assert.deepEqual(devicesService.platform, "android"); }); describe("when options.emulator is true on non-Darwin OS", function () { beforeEach(function () { var options = testInjector.resolve("options"); options.emulator = true; var hostInfo = testInjector.resolve("hostInfo"); hostInfo.isDarwin = false; }); it("throws when iOS platform is specified and iOS device identifier is passed", function () { iOSDeviceDiscovery.emit("deviceFound", iOSDevice); chai_1.assert.throws(function () { return devicesService.initialize({ platform: "ios", deviceId: iOSDevice.deviceInfo.identifier }).wait(); }, "You can use iOS simulator only on OS X."); }); it("throws when iOS device identifier is passed", function () { iOSDeviceDiscovery.emit("deviceFound", iOSDevice); chai_1.assert.throws(function () { return devicesService.initialize({ deviceId: iOSDevice.deviceInfo.identifier }).wait(); }, "You can use iOS simulator only on OS X."); }); it("throws when iOS platform is specified", function () { chai_1.assert.throws(function () { return devicesService.initialize({ platform: "ios" }).wait(); }, "You can use iOS simulator only on OS X."); }); it("throws when paramaters are not passed, but iOS device is detected", function () { iOSDeviceDiscovery.emit("deviceFound", iOSDevice); chai_1.assert.throws(function () { return devicesService.initialize().wait(); }, "You can use iOS simulator only on OS X."); }); it("does not throw when only skipInferPlatform is passed", function () { devicesService.initialize({ skipInferPlatform: true }).wait(); }); it("does not throw when Android platform is specified and Android device identifier is passed", function () { androidDeviceDiscovery.emit("deviceFound", androidDevice); devicesService.initialize({ platform: "android", deviceId: androidDevice.deviceInfo.identifier }).wait(); }); }); describe("does not fail on Darwin when trying to use iOS simulator", function () { beforeEach(function () { var options = testInjector.resolve("options"); options.emulator = true; var hostInfo = testInjector.resolve("hostInfo"); hostInfo.isDarwin = true; }); it("when iOS platform is specified and iOS device identifier is passed", function () { iOSDeviceDiscovery.emit("deviceFound", iOSDevice); devicesService.initialize({ platform: "ios", deviceId: iOSDevice.deviceInfo.identifier }).wait(); }); it("when iOS device identifier is passed", function () { iOSDeviceDiscovery.emit("deviceFound", iOSDevice); devicesService.initialize({ deviceId: iOSDevice.deviceInfo.identifier }).wait(); }); it("when iOS platform is specified", function () { devicesService.initialize({ platform: "ios" }).wait(); }); it("when paramaters are not passed, but iOS device is detected", function () { iOSDeviceDiscovery.emit("deviceFound", iOSDevice); devicesService.initialize().wait(); }); it("when only skipInferPlatform is passed", function () { devicesService.initialize({ skipInferPlatform: true }).wait(); }); it("when iOS platform is specified and iOS simulator device identifier is passed", function () { iOSDeviceDiscovery.emit("deviceFound", iOSSimulator); devicesService.initialize({ platform: "ios", deviceId: iOSSimulator.deviceInfo.identifier }).wait(); }); it("when iOS simulator identifier is passed", function () { iOSDeviceDiscovery.emit("deviceFound", iOSSimulator); devicesService.initialize({ deviceId: iOSSimulator.deviceInfo.identifier }).wait(); }); it("when paramaters are not passed, but iOS simulator is detected", function () { iOSDeviceDiscovery.emit("deviceFound", iOSSimulator); devicesService.initialize().wait(); }); }); }); describe("setLogLevel", function () { it("calls deviceLogProvider's setLogLevel with correct arguments", function () { var deviceLogProvider = testInjector.resolve("deviceLogProvider"); var actualLogLevel = null, actualDeviceIdentifier = null; deviceLogProvider.setLogLevel = function (logLevel, deviceIdentifier) { actualLogLevel = logLevel; actualDeviceIdentifier = deviceIdentifier; }; var expectedLogLevel = "expectedLogLevel", expectedDeviceId = "expcetedDeviceId"; devicesService.setLogLevel(expectedLogLevel, expectedDeviceId); chai_1.assert.deepEqual(actualLogLevel, expectedLogLevel); chai_1.assert.deepEqual(actualDeviceIdentifier, expectedDeviceId); devicesService.setLogLevel(expectedLogLevel); chai_1.assert.deepEqual(actualLogLevel, expectedLogLevel); chai_1.assert.deepEqual(actualDeviceIdentifier, undefined); }); }); describe("deployOnDevices", function () { beforeEach(function () { androidDeviceDiscovery.emit("deviceFound", androidDevice); iOSDeviceDiscovery.emit("deviceFound", iOSDevice); }); it("returns undefined for each device on which the app is installed", function () { var results = devicesService.deployOnDevices([androidDevice.deviceInfo.identifier, iOSDevice.deviceInfo.identifier], "path", "packageName", "cordova"); chai_1.assert.isTrue(results.length > 0); _.each(results, function (futurizedResult) { var realResult = futurizedResult.wait(); chai_1.assert.isTrue(realResult === undefined, "On success, undefined should be returned."); }); }); it("does not call startApplication when canStartApplication returns false", function () { iOSDevice.applicationManager.canStartApplication = function () { return false; }; iOSDevice.applicationManager.startApplication = function () {