mirror of
https://github.com/zhigang1992/react-native-code-push.git
synced 2026-06-09 20:25:15 +08:00
392 lines
17 KiB
JavaScript
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;
|