Files
react-native-code-push/code-push-plugin-testing-framework/script/platform.js
2016-06-15 16:55:09 -07:00

392 lines
17 KiB
JavaScript

"use strict";
var Q = require("q");
var testUtil_1 = require("./testUtil");
//////////////////////////////////////////////////////////////////////////////////////////
// PLATFORMS
/**
* Android implementations of IPlatform.
*/
var Android = (function () {
function Android(emulatorManager) {
this.emulatorManager = emulatorManager;
}
/**
* Gets the platform name. (e.g. "android" for the Android platform).
*/
Android.prototype.getName = function () {
return "android";
};
/**
* The command line flag used to determine whether or not this platform should run.
* Runs when the flag is present, doesn't run otherwise.
*/
Android.prototype.getCommandLineFlagName = function () {
return "--android";
};
/**
* Gets the server url used for testing.
*/
Android.prototype.getServerUrl = function () {
if (!this.serverUrl)
this.serverUrl = testUtil_1.TestUtil.readMochaCommandLineOption(Android.ANDROID_SERVER_URL_OPTION_NAME, Android.DEFAULT_ANDROID_SERVER_URL);
return this.serverUrl;
};
/**
* Gets an IEmulatorManager that is used to control the emulator during the tests.
*/
Android.prototype.getEmulatorManager = function () {
return this.emulatorManager;
};
/**
* Gets the default deployment key.
*/
Android.prototype.getDefaultDeploymentKey = function () {
return "mock-android-deployment-key";
};
Android.ANDROID_SERVER_URL_OPTION_NAME = "--androidserver";
Android.DEFAULT_ANDROID_SERVER_URL = "http://10.0.2.2:3001";
return Android;
}());
exports.Android = Android;
/**
* IOS implementation of IPlatform.
*/
var IOS = (function () {
function IOS(emulatorManager) {
this.emulatorManager = emulatorManager;
}
/**
* Gets the platform name. (e.g. "android" for the Android platform).
*/
IOS.prototype.getName = function () {
return "ios";
};
/**
* The command line flag used to determine whether or not this platform should run.
* Runs when the flag is present, doesn't run otherwise.
*/
IOS.prototype.getCommandLineFlagName = function () {
return "--ios";
};
/**
* Gets the server url used for testing.
*/
IOS.prototype.getServerUrl = function () {
if (!this.serverUrl)
this.serverUrl = testUtil_1.TestUtil.readMochaCommandLineOption(IOS.IOS_SERVER_URL_OPTION_NAME, IOS.DEFAULT_IOS_SERVER_URL);
return this.serverUrl;
};
/**
* Gets an IEmulatorManager that is used to control the emulator during the tests.
*/
IOS.prototype.getEmulatorManager = function () {
return this.emulatorManager;
};
/**
* Gets the default deployment key.
*/
IOS.prototype.getDefaultDeploymentKey = function () {
return "mock-ios-deployment-key";
};
IOS.IOS_SERVER_URL_OPTION_NAME = "--iosserver";
IOS.DEFAULT_IOS_SERVER_URL = "http://127.0.0.1:3000";
return IOS;
}());
exports.IOS = IOS;
//////////////////////////////////////////////////////////////////////////////////////////
// EMULATOR MANAGERS
// bootEmulatorInternal constants
var emulatorMaxReadyAttempts = 5;
var emulatorReadyCheckDelayMs = 30 * 1000;
/**
* Helper function for EmulatorManager implementations to use to boot an emulator with a given platformName and check, start, and kill methods.
*/
function bootEmulatorInternal(platformName, restartEmulators, targetEmulator, checkEmulator, startEmulator, killEmulator) {
var deferred = Q.defer();
console.log("Setting up " + platformName + " emulator.");
function onEmulatorReady() {
console.log(platformName + " emulator is ready!");
deferred.resolve(undefined);
return deferred.promise;
}
// Called to check if the emulator for the platform is initialized.
function checkEmulatorReady() {
var checkDeferred = Q.defer();
console.log("Checking if " + platformName + " emulator is ready yet...");
// Dummy command that succeeds if emulator is ready and fails otherwise.
checkEmulator()
.then(function () {
checkDeferred.resolve(undefined);
}, function (error) {
console.log(platformName + " emulator is not ready yet!");
checkDeferred.reject(error);
});
return checkDeferred.promise;
}
var emulatorReadyAttempts = 0;
// Loops checks to see if the emulator is ready and eventually fails after surpassing emulatorMaxReadyAttempts.
function checkEmulatorReadyLooper() {
var looperDeferred = Q.defer();
emulatorReadyAttempts++;
if (emulatorReadyAttempts > emulatorMaxReadyAttempts) {
console.log(platformName + " emulator is not ready after " + emulatorMaxReadyAttempts + " attempts, abort.");
deferred.reject(platformName + " emulator failed to boot.");
looperDeferred.resolve(undefined);
}
setTimeout(function () {
checkEmulatorReady()
.then(function () {
looperDeferred.resolve(undefined);
onEmulatorReady();
}, function () {
return checkEmulatorReadyLooper().then(function () { looperDeferred.resolve(undefined); }, function () { looperDeferred.reject(undefined); });
});
}, emulatorReadyCheckDelayMs);
return looperDeferred.promise;
}
// Starts and loops the emulator.
function startEmulatorAndLoop() {
console.log("Booting " + platformName + " emulator named " + targetEmulator + ".");
startEmulator(targetEmulator).catch(function (error) { console.log(error); deferred.reject(error); });
return checkEmulatorReadyLooper();
}
var promise;
if (restartEmulators) {
console.log("Killing " + platformName + " emulator.");
promise = killEmulator().catch(function () { return null; }).then(startEmulatorAndLoop);
}
else {
promise = checkEmulatorReady().then(onEmulatorReady, startEmulatorAndLoop);
}
return deferred.promise;
}
var AndroidEmulatorManager = (function () {
function AndroidEmulatorManager() {
}
/**
* Returns the target emulator, which is specified through the command line.
*/
AndroidEmulatorManager.prototype.getTargetEmulator = function () {
if (this.targetEmulator)
return Q(this.targetEmulator);
else {
this.targetEmulator = testUtil_1.TestUtil.readMochaCommandLineOption(AndroidEmulatorManager.ANDROID_EMULATOR_OPTION_NAME, AndroidEmulatorManager.DEFAULT_ANDROID_EMULATOR);
console.log("Using Android emulator named " + this.targetEmulator);
return Q(this.targetEmulator);
}
};
/**
* Boots the target emulator.
*/
AndroidEmulatorManager.prototype.bootEmulator = function (restartEmulators) {
function checkAndroidEmulator() {
// A command that does nothing but only succeeds if the emulator is running.
// List all of the packages on the device.
return testUtil_1.TestUtil.getProcessOutput("adb shell pm list packages", { noLogCommand: true, noLogStdOut: true, noLogStdErr: true }).then(function () { return null; });
}
function startAndroidEmulator(androidEmulatorName) {
return testUtil_1.TestUtil.getProcessOutput("emulator @" + androidEmulatorName).then(function () { return null; });
}
function killAndroidEmulator() {
return testUtil_1.TestUtil.getProcessOutput("adb emu kill").then(function () { return null; });
}
return this.getTargetEmulator()
.then(function (targetEmulator) {
return bootEmulatorInternal("Android", restartEmulators, targetEmulator, checkAndroidEmulator, startAndroidEmulator, killAndroidEmulator);
});
};
/**
* Launches an already installed application by app id.
*/
AndroidEmulatorManager.prototype.launchInstalledApplication = function (appId) {
return testUtil_1.TestUtil.getProcessOutput("adb shell monkey -p " + appId + " -c android.intent.category.LAUNCHER 1").then(function () { return null; });
};
/**
* Ends a running application given its app id.
*/
AndroidEmulatorManager.prototype.endRunningApplication = function (appId) {
return testUtil_1.TestUtil.getProcessOutput("adb shell am force-stop " + appId).then(function () { return null; });
};
/**
* Restarts an already installed application by app id.
*/
AndroidEmulatorManager.prototype.restartApplication = function (appId) {
var _this = this;
return this.endRunningApplication(appId)
.then(function () {
// Wait for a second before restarting.
return Q.delay(1000);
})
.then(function () {
return _this.launchInstalledApplication(appId);
});
};
/**
* Navigates away from the current app, waits for a delay (defaults to 1 second), then navigates to the specified app.
*/
AndroidEmulatorManager.prototype.resumeApplication = function (appId, delayBeforeResumingMs) {
var _this = this;
if (delayBeforeResumingMs === void 0) { delayBeforeResumingMs = 1000; }
// Open a default Android app (for example, settings).
return this.launchInstalledApplication("com.android.settings")
.then(function () {
console.log("Waiting for " + delayBeforeResumingMs + "ms before resuming the test application.");
return Q.delay(delayBeforeResumingMs);
})
.then(function () {
// Reopen the app.
return _this.launchInstalledApplication(appId);
});
};
/**
* Prepares the emulator for a test.
*/
AndroidEmulatorManager.prototype.prepareEmulatorForTest = function (appId) {
return this.endRunningApplication(appId)
.then(function () { return testUtil_1.TestUtil.getProcessOutput("adb shell pm clear " + appId); }).then(function () { return null; });
};
/**
* Uninstalls the app from the emulator.
*/
AndroidEmulatorManager.prototype.uninstallApplication = function (appId) {
return testUtil_1.TestUtil.getProcessOutput("adb uninstall " + appId).then(function () { return null; });
};
AndroidEmulatorManager.ANDROID_EMULATOR_OPTION_NAME = "--androidemu";
AndroidEmulatorManager.DEFAULT_ANDROID_EMULATOR = "emulator";
return AndroidEmulatorManager;
}());
exports.AndroidEmulatorManager = AndroidEmulatorManager;
var IOSEmulatorManager = (function () {
function IOSEmulatorManager() {
}
/**
* Returns the target emulator, which is specified through the command line.
*/
IOSEmulatorManager.prototype.getTargetEmulator = function () {
var _this = this;
if (this.targetEmulator)
return Q(this.targetEmulator);
else {
var deferred = Q.defer();
var targetIOSEmulator = testUtil_1.TestUtil.readMochaCommandLineOption(IOSEmulatorManager.IOS_EMULATOR_OPTION_NAME);
if (!targetIOSEmulator) {
// If no iOS simulator is specified, get the most recent iOS simulator to run tests on.
testUtil_1.TestUtil.getProcessOutput("xcrun simctl list", { noLogCommand: true, noLogStdOut: true, noLogStdErr: true })
.then(function (listOfDevicesWithDevicePairs) {
var listOfDevices = listOfDevicesWithDevicePairs.slice(listOfDevicesWithDevicePairs.indexOf("-- iOS"), listOfDevicesWithDevicePairs.indexOf("-- tvOS"));
var phoneDevice = /iPhone (\S* )*(\(([0-9A-Z-]*)\))/g;
var match = listOfDevices.match(phoneDevice);
deferred.resolve(match[match.length - 1]);
}, function (error) {
deferred.reject(error);
});
}
else {
// Use the simulator specified on the command line.
deferred.resolve(targetIOSEmulator);
}
return deferred.promise
.then(function (targetEmulator) {
_this.targetEmulator = targetEmulator;
console.log("Using iOS simulator named " + _this.targetEmulator);
return _this.targetEmulator;
});
}
};
/**
* Boots the target emulator.
*/
IOSEmulatorManager.prototype.bootEmulator = function (restartEmulators) {
function checkIOSEmulator() {
// A command that does nothing but only succeeds if the emulator is running.
// Get the environment variable with the name "asdf" (return null, not an error, if not initialized).
return testUtil_1.TestUtil.getProcessOutput("xcrun simctl getenv booted asdf", { noLogCommand: true, noLogStdOut: true, noLogStdErr: true }).then(function () { return null; });
}
function startIOSEmulator(iOSEmulatorName) {
return testUtil_1.TestUtil.getProcessOutput("xcrun instruments -w \"" + iOSEmulatorName + "\"", { noLogStdErr: true })
.catch(function (error) { return undefined; /* Always fails because we do not specify a template, which is not necessary to just start the emulator */ }).then(function () { return null; });
}
function killIOSEmulator() {
return testUtil_1.TestUtil.getProcessOutput("killall Simulator").then(function () { return null; });
}
return this.getTargetEmulator()
.then(function (targetEmulator) {
return bootEmulatorInternal("iOS", restartEmulators, targetEmulator, checkIOSEmulator, startIOSEmulator, killIOSEmulator);
});
};
/**
* Launches an already installed application by app id.
*/
IOSEmulatorManager.prototype.launchInstalledApplication = function (appId) {
return testUtil_1.TestUtil.getProcessOutput("xcrun simctl launch booted " + appId, undefined).then(function () { return null; });
};
/**
* Ends a running application given its app id.
*/
IOSEmulatorManager.prototype.endRunningApplication = function (appId) {
return testUtil_1.TestUtil.getProcessOutput("xcrun simctl spawn booted launchctl list", { noLogCommand: true, noLogStdOut: true, noLogStdErr: true })
.then(function (processListOutput) {
// Find the app's process.
var regex = new RegExp("(\\S+" + appId + "\\S+)");
var execResult = regex.exec(processListOutput);
if (execResult) {
return execResult[0];
}
else {
return Q.reject("Could not get the running application label.");
}
})
.then(function (applicationLabel) {
// Kill the app if we found the process.
return testUtil_1.TestUtil.getProcessOutput("xcrun simctl spawn booted launchctl stop " + applicationLabel, undefined).then(function () { return null; });
}, function (error) {
// We couldn't find the app's process so it must not be running.
return Q.resolve(error);
});
};
/**
* Restarts an already installed application by app id.
*/
IOSEmulatorManager.prototype.restartApplication = function (appId) {
var _this = this;
return this.endRunningApplication(appId)
.then(function () {
// Wait for a second before restarting.
return Q.delay(1000);
})
.then(function () { return _this.launchInstalledApplication(appId); });
};
/**
* Navigates away from the current app, waits for a delay (defaults to 1 second), then navigates to the specified app.
*/
IOSEmulatorManager.prototype.resumeApplication = function (appId, delayBeforeResumingMs) {
var _this = this;
if (delayBeforeResumingMs === void 0) { delayBeforeResumingMs = 1000; }
// Open a default iOS app (for example, camera).
return this.launchInstalledApplication("com.apple.camera")
.then(function () {
console.log("Waiting for " + delayBeforeResumingMs + "ms before resuming the test application.");
return Q.delay(delayBeforeResumingMs);
})
.then(function () {
// Reopen the app.
return _this.launchInstalledApplication(appId);
});
};
/**
* Prepares the emulator for a test.
*/
IOSEmulatorManager.prototype.prepareEmulatorForTest = function (appId) {
return this.endRunningApplication(appId);
};
/**
* Uninstalls the app from the emulator.
*/
IOSEmulatorManager.prototype.uninstallApplication = function (appId) {
return testUtil_1.TestUtil.getProcessOutput("xcrun simctl uninstall booted " + appId).then(function () { return null; });
};
IOSEmulatorManager.IOS_EMULATOR_OPTION_NAME = "--iosemu";
return IOSEmulatorManager;
}());
exports.IOSEmulatorManager = IOSEmulatorManager;