Merge branch 'master' into StudioProjectCompat

This will have to be linted
This commit is contained in:
Joe Bowser 2017-06-26 10:29:31 -07:00
commit e456175a81
42 changed files with 3130 additions and 3262 deletions

10
.eslintrc.yml Normal file
View File

@ -0,0 +1,10 @@
root: true
extends: semistandard
rules:
indent:
- error
- 4
camelcase: off
padded-blocks: off
operator-linebreak: off
no-throw-literal: off

View File

@ -15,7 +15,7 @@ android:
- tools
- tools
script:
- npm run jshint
- npm run eslint
- npm run cover
- npm run test-build
after_script:

View File

@ -19,12 +19,12 @@
under the License.
*/
var shell = require('shelljs'),
Q = require('q'),
path = require('path'),
fs = require('fs'),
check_reqs = require('./../templates/cordova/lib/check_reqs'),
ROOT = path.join(__dirname, '..', '..');
var shell = require('shelljs');
var Q = require('q');
var path = require('path');
var fs = require('fs');
var check_reqs = require('./../templates/cordova/lib/check_reqs');
var ROOT = path.join(__dirname, '..', '..');
var MIN_SDK_VERSION = 19;
@ -62,9 +62,9 @@ function copyJsAndLibrary(projectPath, shared, projectName, isLegacy) {
// We need these files to build cordova.js if using browserify method.
shell.cp('-rf', path.join(ROOT, 'cordova-js-src'), path.join(projectPath, 'platform_www'));
// Don't fail if there are no old jars, because there hasn't been cordova JARs for years!
// Don't fail if there are no old jars.
setShellFatal(false, function () {
shell.ls(path.join(app_path, 'libs', 'cordova-*.jar')).forEach(function(oldJar) {
shell.ls(path.join(projectPath, 'libs', 'cordova-*.jar')).forEach(function (oldJar) {
console.log('Deleting ' + oldJar);
shell.rm('-f', oldJar);
});
@ -116,9 +116,8 @@ function writeProjectProperties(projectPath, target_api) {
var subProjects = extractSubProjectPaths(data);
subProjects = subProjects.filter(function (p) {
return !(/^CordovaLib$/m.exec(p) ||
/[\\\/]cordova-android[\\\/]framework$/m.exec(p) ||
/^(\.\.[\\\/])+framework$/m.exec(p)
);
/[\\/]cordova-android[\\/]framework$/m.exec(p) ||
/^(\.\.[\\/])+framework$/m.exec(p));
});
subProjects.unshift('CordovaLib');
data = data.replace(/^\s*android\.library\.reference\.\d+=.*\n/mg, '');
@ -326,7 +325,7 @@ exports.create = function(project_path, config, options, events) {
function generateDoneMessage (type, link) {
var pkg = require('../../package');
var msg = 'Android project ' + (type == 'update' ? 'updated ' : 'created ') + 'with ' + pkg.name + '@' + pkg.version;
var msg = 'Android project ' + (type === 'update' ? 'updated ' : 'created ') + 'with ' + pkg.name + '@' + pkg.version;
if (link) {
msg += ' and has a linked CordovaLib';
}
@ -372,7 +371,6 @@ exports.update = function(projectPath, options, events) {
}).thenResolve(projectPath);
};
// For testing
exports.validatePackageName = validatePackageName;
exports.validateProjectName = validateProjectName;

View File

@ -29,7 +29,6 @@ var selfEvents = require('cordova-common').events;
var PLATFORM = 'android';
function setupEvents (externalEventEmitter) {
if (externalEventEmitter) {
// This will make the platform internal events visible outside
@ -43,7 +42,6 @@ function setupEvents(externalEventEmitter) {
return selfEvents;
}
/**
* Class, that acts as abstraction over particular platform. Encapsulates the
* platform's properties and methods.
@ -117,14 +115,11 @@ Api.createPlatform = function (destination, config, options, events) {
events = setupEvents(events);
var result;
try {
result = require('../../lib/create')
.create(destination, config, options, events)
.then(function (destination) {
result = require('../../lib/create').create(destination, config, options, events).then(function (destination) {
var PlatformApi = require(path.resolve(destination, 'cordova/Api'));
return new PlatformApi(PLATFORM, destination, events);
});
}
catch (e) {
} catch (e) {
events.emit('error', 'createPlatform is not callable from the android project API.');
throw (e);
}
@ -151,14 +146,11 @@ Api.updatePlatform = function (destination, options, events) {
events = setupEvents(events);
var result;
try {
result = require('../../lib/create')
.update(destination, options, events)
.then(function (destination) {
result = require('../../lib/create').update(destination, options, events).then(function (destination) {
var PlatformApi = require(path.resolve(destination, 'cordova/Api'));
return new PlatformApi('android', destination, events);
});
}
catch (e) {
} catch (e) {
events.emit('error', 'updatePlatform is not callable from the android project API, you will need to do this manually.');
throw (e);
}
@ -235,12 +227,10 @@ Api.prototype.addPlugin = function (plugin, installOptions) {
installOptions.android_studio = true;
}
return Q()
.then(function () {
return Q().then(function () {
// CB-11964: Do a clean when installing the plugin code to get around
// the Gradle bug introduced by the Android Gradle Plugin Version 2.2
// TODO: Delete when the next version of Android Gradle plugin comes out
// Since clean doesn't just clean the build, it also wipes out www, we need
// to pass additional options.
@ -253,14 +243,10 @@ Api.prototype.addPlugin = function (plugin, installOptions) {
if (!AndroidStudio.isAndroidStudioProject(self.root) && !project.isClean()) {
return self.clean(opts);
}
})
.then(function () {
return PluginManager.get(self.platform, self.locations, project)
.addPlugin(plugin, installOptions);
})
.then(function () {
}).then(function () {
return PluginManager.get(self.platform, self.locations, project).addPlugin(plugin, installOptions);
}).then(function () {
if (plugin.getFrameworks(this.platform).length === 0) return;
selfEvents.emit('verbose', 'Updating build files since android plugin contained <framework>');
//This should pick the correct builder, not just get gradle
require('./lib/builders/builders').getBuilder(this.builder).prepBuildFiles();
@ -351,11 +337,9 @@ Api.prototype.build = function (buildOptions) {
var self = this;
if(this.android_studio)
buildOptions.studio = true;
return require('./lib/check_reqs').run()
.then(function () {
return require('./lib/check_reqs').run() .then(function () {
return require('./lib/build').run.call(self, buildOptions);
})
.then(function (buildResults) {
}).then(function (buildResults) {
// Cast build result to array of build artifacts
return buildResults.apkPaths.map(function (apkPath) {
return {
@ -382,8 +366,7 @@ Api.prototype.build = function (buildOptions) {
*/
Api.prototype.run = function (runOptions) {
var self = this;
return require('./lib/check_reqs').run()
.then(function () {
return require('./lib/check_reqs').run().then(function () {
return require('./lib/run').run.call(self, runOptions);
});
};
@ -397,17 +380,13 @@ Api.prototype.run = function(runOptions) {
*/
Api.prototype.clean = function (cleanOptions) {
var self = this;
return require('./lib/check_reqs').run()
.then(function () {
return require('./lib/check_reqs').run().then(function () {
return require('./lib/build').runClean.call(self, cleanOptions);
})
.then(function () {
}).then(function () {
return require('./lib/prepare').clean.call(self, cleanOptions);
});
};
/**
* Performs a requirements check for current platform. Each platform defines its
* own set of requirements, which should be resolved before platform can be

View File

@ -44,8 +44,7 @@ function isEmulator(line) {
* devices/emulators
*/
Adb.devices = function (opts) {
return spawn('adb', ['devices'], {cwd: os.tmpdir()})
.then(function(output) {
return spawn('adb', ['devices'], {cwd: os.tmpdir()}).then(function (output) {
return output.split('\n').filter(function (line) {
// Filter out either real devices or emulators, depending on options
return (line && opts && opts.emulators) ? isEmulator(line) : isDevice(line);
@ -59,8 +58,7 @@ Adb.install = function (target, packagePath, opts) {
events.emit('verbose', 'Installing apk ' + packagePath + ' on target ' + target + '...');
var args = ['-s', target, 'install'];
if (opts && opts.replace) args.push('-r');
return spawn('adb', args.concat(packagePath), {cwd: os.tmpdir()})
.then(function(output) {
return spawn('adb', args.concat(packagePath), {cwd: os.tmpdir()}).then(function (output) {
// 'adb install' seems to always returns no error, even if installation fails
// so we catching output to detect installation failure
if (output.match(/Failure/)) {
@ -86,8 +84,7 @@ Adb.shell = function (target, shellCommand) {
events.emit('verbose', 'Running adb shell command "' + shellCommand + '" on target ' + target + '...');
var args = ['-s', target, 'shell'];
shellCommand = shellCommand.split(/\s+/);
return spawn('adb', args.concat(shellCommand), {cwd: os.tmpdir()})
.catch(function (output) {
return spawn('adb', args.concat(shellCommand), {cwd: os.tmpdir()}).catch(function (output) {
return Q.reject(new CordovaError('Failed to execute shell command "' +
shellCommand + '"" on device: ' + output));
});
@ -95,8 +92,7 @@ Adb.shell = function (target, shellCommand) {
Adb.start = function (target, activityName) {
events.emit('verbose', 'Starting application "' + activityName + '" on target ' + target + '...');
return Adb.shell(target, 'am start -W -a android.intent.action.MAIN -n' + activityName)
.catch(function (output) {
return Adb.shell(target, 'am start -W -a android.intent.action.MAIN -n' + activityName).catch(function (output) {
return Q.reject(new CordovaError('Failed to start application "' +
activityName + '"" on device: ' + output));
});

View File

@ -102,8 +102,7 @@ AndroidManifest.prototype.getActivity = function() {
};
};
['minSdkVersion', 'maxSdkVersion', 'targetSdkVersion']
.forEach(function(sdkPrefName) {
['minSdkVersion', 'maxSdkVersion', 'targetSdkVersion'].forEach(function (sdkPrefName) {
// Copy variable reference to avoid closure issues
var prefName = sdkPrefName;

View File

@ -28,8 +28,7 @@ var projectFileCache = {};
function addToPropertyList (projectProperties, key, value) {
var i = 1;
while (projectProperties.get(key + '.' + i))
i++;
while (projectProperties.get(key + '.' + i)) { i++; }
projectProperties.set(key + '.' + i, value);
projectProperties.dirty = true;
@ -54,7 +53,7 @@ function removeFromPropertyList(projectProperties, key, value) {
function getRelativeLibraryPath (parentDir, subDir) {
var libraryPath = path.relative(parentDir, subDir);
return (path.sep == '\\') ? libraryPath.replace(/\\/g, '/') : libraryPath;
return (path.sep === '\\') ? libraryPath.replace(/\\/g, '/') : libraryPath;
}
function AndroidProject (projectDir) {

View File

@ -17,8 +17,8 @@
under the License.
*/
var Q = require('q'),
superspawn = require('cordova-common').superspawn;
var Q = require('q');
var superspawn = require('cordova-common').superspawn;
var suffix_number_regex = /(\d+)$/;
// Used for sorting Android targets, example strings to sort:
@ -44,8 +44,7 @@ function sort_by_largest_numerical_suffix(a, b) {
}
module.exports.print_newest_available_sdk_target = function () {
return module.exports.list_targets()
.then(function(targets) {
return module.exports.list_targets().then(function (targets) {
targets.sort(sort_by_largest_numerical_suffix);
console.log(targets[0]);
});
@ -78,26 +77,22 @@ function parse_targets(output) {
}
module.exports.list_targets_with_android = function () {
return superspawn.spawn('android', ['list', 'target'])
.then(parse_targets);
return superspawn.spawn('android', ['list', 'target']).then(parse_targets);
};
module.exports.list_targets_with_avdmanager = function () {
return superspawn.spawn('avdmanager', ['list', 'target'])
.then(parse_targets);
return superspawn.spawn('avdmanager', ['list', 'target']).then(parse_targets);
};
module.exports.list_targets = function () {
return module.exports.list_targets_with_avdmanager()
.catch(function(err) {
return module.exports.list_targets_with_avdmanager().catch(function (err) {
// If there's an error, like avdmanager could not be found, we can try
// as a last resort, to run `android`, in case this is a super old
// SDK installation.
if (err && (err.code == 'ENOENT' || (err.stderr && err.stderr.match(/not recognized/)))) {
if (err && (err.code === 'ENOENT' || (err.stderr && err.stderr.match(/not recognized/)))) {
return module.exports.list_targets_with_android();
} else throw err;
})
.then(function(targets) {
}).then(function (targets) {
if (targets.length === 0) {
return Q.reject(new Error('No android targets (SDKs) installed!'));
}

View File

@ -19,10 +19,10 @@
under the License.
*/
var Q = require('q'),
path = require('path'),
fs = require('fs'),
nopt = require('nopt');
var Q = require('q');
var path = require('path');
var fs = require('fs');
var nopt = require('nopt');
var Adb = require('./Adb');
@ -64,11 +64,9 @@ function parseOpts(options, resolvedTarget, projectRoot) {
if (options.nobuild) ret.buildMethod = 'none';
if (options.argv.versionCode)
ret.extraArgs.push('-PcdvVersionCode=' + options.argv.versionCode);
if (options.argv.versionCode) { ret.extraArgs.push('-PcdvVersionCode=' + options.argv.versionCode); }
if (options.argv.minSdkVersion)
ret.extraArgs.push('-PcdvMinSdkVersion=' + options.argv.minSdkVersion);
if (options.argv.minSdkVersion) { ret.extraArgs.push('-PcdvMinSdkVersion=' + options.argv.minSdkVersion); }
if (options.argv.gradleArg) {
ret.extraArgs = ret.extraArgs.concat(options.argv.gradleArg);
@ -76,12 +74,10 @@ function parseOpts(options, resolvedTarget, projectRoot) {
var packageArgs = {};
if (options.argv.keystore)
packageArgs.keystore = path.relative(projectRoot, path.resolve(options.argv.keystore));
if (options.argv.keystore) { packageArgs.keystore = path.relative(projectRoot, path.resolve(options.argv.keystore)); }
['alias', 'storePassword', 'password', 'keystoreType'].forEach(function (flagName) {
if (options.argv[flagName])
packageArgs[flagName] = options.argv[flagName];
if (options.argv[flagName]) { packageArgs[flagName] = options.argv[flagName]; }
});
var buildConfig = options.buildConfig;
@ -132,8 +128,7 @@ function parseOpts(options, resolvedTarget, projectRoot) {
module.exports.runClean = function (options) {
var opts = parseOpts(options, null, this.root);
var builder = builders.getBuilder(opts.buildMethod);
return builder.prepEnv(opts)
.then(function() {
return builder.prepEnv(opts).then(function () {
return builder.clean(opts);
});
};
@ -154,14 +149,12 @@ module.exports.run = function(options, optResolvedTarget) {
var opts = parseOpts(options, optResolvedTarget, this.root);
console.log(opts.buildMethod);
var builder = builders.getBuilder(opts.buildMethod);
return builder.prepEnv(opts)
.then(function() {
return builder.prepEnv(opts).then(function () {
if (opts.prepEnv) {
events.emit('verbose', 'Build file successfully prepared.');
return;
}
return builder.build(opts)
.then(function() {
return builder.build(opts).then(function () {
var apkPaths = builder.findOutputApks(opts.buildType, opts.arch);
events.emit('log', 'Built the following apk(s): \n\t' + apkPaths.join('\n\t'));
return {
@ -179,31 +172,24 @@ module.exports.run = function(options, optResolvedTarget) {
*/
module.exports.detectArchitecture = function (target) {
function helper () {
return Adb.shell(target, 'cat /proc/cpuinfo')
.then(function(output) {
return Adb.shell(target, 'cat /proc/cpuinfo').then(function (output) {
return /intel/i.exec(output) ? 'x86' : 'arm';
});
}
// It sometimes happens (at least on OS X), that this command will hang forever.
// To fix it, either unplug & replug device, or restart adb server.
return helper()
.timeout(1000, new CordovaError('Device communication timed out. Try unplugging & replugging the device.'))
.then(null, function(err) {
return helper().timeout(1000, new CordovaError('Device communication timed out. Try unplugging & replugging the device.')).then(null, function (err) {
if (/timed out/.exec('' + err)) {
// adb kill-server doesn't seem to do the trick.
// Could probably find a x-platform version of killall, but I'm not actually
// sure that this scenario even happens on non-OSX machines.
events.emit('verbose', 'adb timed out while detecting device/emulator architecture. Killing adb and trying again.');
return spawn('killall', ['adb'])
.then(function() {
return helper()
.then(null, function() {
return spawn('killall', ['adb']).then(function () {
return helper().then(null, function () {
// The double kill is sadly often necessary, at least on mac.
events.emit('warn', 'adb timed out a second time while detecting device/emulator architecture. Killing adb and trying again.');
return spawn('killall', ['adb'])
.then(function() {
return helper()
.then(null, function() {
return spawn('killall', ['adb']).then(function () {
return helper().then(null, function () {
return Q.reject(new CordovaError('adb timed out a third time while detecting device/emulator architecture. Try unplugging & replugging the device.'));
});
});
@ -220,7 +206,7 @@ module.exports.detectArchitecture = function(target) {
module.exports.findBestApkForArchitecture = function (buildResults, arch) {
var paths = buildResults.apkPaths.filter(function (p) {
var apkName = path.basename(p);
if (buildResults.buildType == 'debug') {
if (buildResults.buildType === 'debug') {
return /-debug/.exec(apkName);
}
return !/-debug/.exec(apkName);

View File

@ -16,6 +16,8 @@
specific language governing permissions and limitations
under the License.
*/
/* eslint no-self-assign: 0 */
/* eslint no-unused-vars: 0 */
var Q = require('q');
var fs = require('fs');
@ -46,13 +48,11 @@ GenericBuilder.prototype.clean = function() {
GenericBuilder.prototype.findOutputApks = function (build_type, arch) {
var self = this;
return Object.keys(this.binDirs)
.reduce(function (result, builderName) {
return Object.keys(this.binDirs) .reduce(function (result, builderName) {
console.log('builderName:'+ builderName);
var binDir = self.binDirs[builderName];
return result.concat(findOutputApksHelper(binDir, build_type, builderName === 'ant' ? null : arch));
}, [])
.sort(apkSorter);
}, []).sort(apkSorter);
};
module.exports = GenericBuilder;
@ -74,8 +74,7 @@ function findOutputApksHelper(dir, build_type, arch) {
var shellSilent = shell.config.silent;
shell.config.silent = true;
var ret = shell.ls(path.join(dir, '*.apk'))
.filter(function(candidate) {
var ret = shell.ls(path.join(dir, '*.apk')).filter(function (candidate) {
var apkName = path.basename(candidate);
// Need to choose between release and debug .apk.
if (build_type === 'debug') {
@ -85,8 +84,7 @@ function findOutputApksHelper(dir, build_type, arch) {
return /-release/.exec(apkName) && !/-unaligned/.exec(apkName);
}
return true;
})
.sort(apkSorter);
}).sort(apkSorter);
shellSilent = shellSilent;
@ -98,13 +96,13 @@ function findOutputApksHelper(dir, build_type, arch) {
// And show only arch-specific ones (or non-arch-specific)
ret = ret.filter(function (p) {
/* jshint -W018 */
return !!/-x86|-arm/.exec(path.basename(p)) == archSpecific;
return !!/-x86|-arm/.exec(path.basename(p)) === archSpecific;
/* jshint +W018 */
});
if (archSpecific && ret.length > 1 && arch) {
ret = ret.filter(function (p) {
return path.basename(p).indexOf('-' + arch) != -1;
return path.basename(p).indexOf('-' + arch) !== -1;
});
}

View File

@ -43,9 +43,9 @@ function GradleBuilder (projectRoot) {
util.inherits(GradleBuilder, GenericBuilder);
GradleBuilder.prototype.getArgs = function (cmd, opts) {
if (cmd == 'release') {
if (cmd === 'release') {
cmd = 'cdvBuildRelease';
} else if (cmd == 'debug') {
} else if (cmd === 'debug') {
cmd = 'cdvBuildDebug';
}
var args = [cmd, '-b', path.join(this.root, 'build.gradle')];
@ -150,8 +150,7 @@ GradleBuilder.prototype.prepBuildFiles = function() {
var realDir = p.replace(/[/\\]/g, ':');
var libName = realDir.replace(name + '-', '');
var str = 'include ":' + libName + '"\n';
if(realDir.indexOf(name+'-')!==-1)
str+='project(":'+libName+'").projectDir = new File("'+p+'")\n';
if (realDir.indexOf(name + '-') !== -1) { str += 'project(":' + libName + '").projectDir = new File("' + p + '")\n'; }
return str;
});
@ -173,8 +172,7 @@ GradleBuilder.prototype.prepBuildFiles = function() {
var projectGradleFile = fs.readFileSync(gradlePath, 'utf-8');
if(projectGradleFile.indexOf('CordovaLib') != -1) {
depsList += '{\n exclude module:("CordovaLib")\n }\n';
}
else {
} else {
depsList += '\n';
}
};
@ -194,7 +192,6 @@ GradleBuilder.prototype.prepBuildFiles = function() {
[/^\/?extras\/android\/support\/(.*)$/, 'com.android.support:support-$1:+'],
[/^\/?google\/google_play_services\/libproject\/google-play-services_lib\/?$/, 'com.google.android.gms:play-services:+']
];
propertiesObj.systemLibs.forEach(function (p) {
var mavenRef;
// It's already in gradle form if it has two ':'s
@ -228,8 +225,7 @@ GradleBuilder.prototype.prepBuildFiles = function() {
GradleBuilder.prototype.prepEnv = function (opts) {
var self = this;
return check_reqs.check_gradle()
.then(function(gradlePath) {
return check_reqs.check_gradle().then(function (gradlePath) {
return self.runGradleWrapper(gradlePath);
}).then(function () {
return self.prepBuildFiles();
@ -276,10 +272,9 @@ GradleBuilder.prototype.prepEnv = function(opts) {
*/
GradleBuilder.prototype.build = function (opts) {
var wrapper = path.join(this.root, 'gradlew');
var args = this.getArgs(opts.buildType == 'debug' ? 'debug' : 'release', opts);
var args = this.getArgs(opts.buildType === 'debug' ? 'debug' : 'release', opts);
return superspawn.spawn(wrapper, args, {stdio: 'pipe'})
.progress(function (stdio){
return superspawn.spawn(wrapper, args, {stdio: 'pipe'}).progress(function (stdio) {
if (stdio.stderr) {
/*
* Workaround for the issue with Java printing some unwanted information to
@ -314,8 +309,7 @@ GradleBuilder.prototype.clean = function(opts) {
var args = builder.getArgs('clean', opts);
return Q().then(function () {
return superspawn.spawn(wrapper, args, {stdio: 'inherit'});
})
.then(function () {
}).then(function () {
shell.rm('-rf', path.join(builder.root, 'out'));
['debug', 'release'].forEach(function (config) {

View File

@ -35,8 +35,7 @@ var knownBuilders = {
* @return {Builder} A builder instance for specified build type.
*/
module.exports.getBuilder = function (builderType, projectRoot) {
if (!knownBuilders[builderType])
throw new CordovaError('Builder ' + builderType + ' is not supported.');
if (!knownBuilders[builderType]) { throw new CordovaError('Builder ' + builderType + ' is not supported.'); }
try {
var Builder = require('./' + knownBuilders[builderType]);

View File

@ -21,14 +21,14 @@
/* jshint sub:true */
var shelljs = require('shelljs'),
child_process = require('child_process'),
Q = require('q'),
path = require('path'),
fs = require('fs'),
os = require('os'),
REPO_ROOT = path.join(__dirname, '..', '..', '..', '..'),
PROJECT_ROOT = path.join(__dirname, '..', '..');
var shelljs = require('shelljs');
var child_process = require('child_process');
var Q = require('q');
var path = require('path');
var fs = require('fs');
var os = require('os');
var REPO_ROOT = path.join(__dirname, '..', '..', '..', '..');
var PROJECT_ROOT = path.join(__dirname, '..', '..');
var CordovaError = require('cordova-common').CordovaError;
var superspawn = require('cordova-common').superspawn;
var android_sdk = require('./android_sdk');
@ -53,11 +53,11 @@ function tryCommand(cmd, errMsg, catchStderr) {
}
module.exports.isWindows = function () {
return (os.platform() == 'win32');
return (os.platform() === 'win32');
};
module.exports.isDarwin = function () {
return (os.platform() == 'darwin');
return (os.platform() === 'darwin');
};
// Get valid target from framework/project.properties if run from this repo
@ -84,12 +84,13 @@ module.exports.get_target = function() {
// Returns a promise. Called only by build and clean commands.
module.exports.check_ant = function () {
return superspawn.spawn('ant', ['-version'])
.then(function(output) {
return superspawn.spawn('ant', ['-version']).then(function (output) {
// Parse Ant version from command output
return /version ((?:\d+\.)+(?:\d+))/i.exec(output)[1];
}).catch(function (err) {
if (err) {
throw new CordovaError('Failed to run `ant -version`. Make sure you have `ant` on your $PATH.');
}
});
};
@ -108,6 +109,12 @@ module.exports.get_gradle_wrapper = function() {
} else { ++i; }
}
} else if (module.exports.isWindows()) {
var result = child_process.spawnSync(path.join(__dirname, 'getASPath.bat'));
// console.log('result.stdout =' + result.stdout.toString());
// console.log('result.stderr =' + result.stderr.toString());
if (result.stderr.toString().length > 0) {
var androidPath = path.join(process.env['ProgramFiles'], 'Android') + '/';
if (fs.existsSync(androidPath)) {
program_dir = fs.readdirSync(androidPath);
@ -118,11 +125,17 @@ module.exports.get_gradle_wrapper = function() {
} else { ++i; }
}
}
} else {
// console.log('got android studio path from registry');
// remove the (os independent) new line char at the end of stdout
// add gradle to match the above.
androidStudioPath = path.join(result.stdout.toString().split('\r\n')[0], 'gradle');
}
}
if (androidStudioPath !== null && fs.existsSync(androidStudioPath)) {
var dirs = fs.readdirSync(androidStudioPath);
if(dirs[0].split('-')[0] == 'gradle') {
if (dirs[0].split('-')[0] === 'gradle') {
return path.join(androidStudioPath, dirs[0], 'bin', 'gradle');
}
} else {
@ -135,17 +148,17 @@ module.exports.get_gradle_wrapper = function() {
module.exports.check_gradle = function () {
var sdkDir = process.env['ANDROID_HOME'];
var d = Q.defer();
if (!sdkDir)
if (!sdkDir) {
return Q.reject(new CordovaError('Could not find gradle wrapper within Android SDK. Could not find Android SDK directory.\n' +
'Might need to install Android SDK or set up \'ANDROID_HOME\' env variable.'));
}
var gradlePath = module.exports.get_gradle_wrapper();
if (gradlePath.length !== 0)
d.resolve(gradlePath);
else
if (gradlePath.length !== 0) { d.resolve(gradlePath); } else {
d.reject(new CordovaError('Could not find an installed version of Gradle either in Android Studio,\n' +
'or on your system to install the gradle wrapper. Please include gradle \n' +
'in your path, or install Android Studio'));
}
return d.promise;
};
@ -165,11 +178,12 @@ module.exports.check_java = function() {
var find_java = '/usr/libexec/java_home';
var default_java_error_msg = 'Failed to find \'JAVA_HOME\' environment variable. Try setting setting it manually.';
if (fs.existsSync(find_java)) {
return superspawn.spawn(find_java)
.then(function(stdout) {
return superspawn.spawn(find_java).then(function (stdout) {
process.env['JAVA_HOME'] = stdout.trim();
}).catch(function (err) {
if (err) {
throw new CordovaError(default_java_error_msg);
}
});
} else {
// See if we can derive it from javac's location.
@ -209,8 +223,7 @@ module.exports.check_java = function() {
}
// We use tryCommand with catchStderr = true, because
// javac writes version info to stderr instead of stdout
return tryCommand('javac -version', msg, true)
.then(function (output) {
return tryCommand('javac -version', msg, true).then(function (output) {
// Let's check for at least Java 8, and keep it future proof so we can support Java 10
var match = /javac ((?:1\.)(?:[8-9]\.)(?:\d+))|((?:1\.)(?:[1-9]\d+\.)(?:\d+))/i.exec(output);
return match && match[1];
@ -265,7 +278,7 @@ module.exports.check_android = function() {
if (androidCmdPath) {
parentDir = path.dirname(androidCmdPath);
grandParentDir = path.dirname(parentDir);
if (path.basename(parentDir) == 'tools' || fs.existsSync(path.join(grandParentDir, 'tools', 'android'))) {
if (path.basename(parentDir) === 'tools' || fs.existsSync(path.join(grandParentDir, 'tools', 'android'))) {
maybeSetAndroidHome(grandParentDir);
} else {
throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting setting it manually.\n' +
@ -276,7 +289,7 @@ module.exports.check_android = function() {
if (adbInPath) {
parentDir = path.dirname(adbInPath);
grandParentDir = path.dirname(parentDir);
if (path.basename(parentDir) == 'platform-tools') {
if (path.basename(parentDir) === 'platform-tools') {
maybeSetAndroidHome(grandParentDir);
} else {
throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting setting it manually.\n' +
@ -287,7 +300,7 @@ module.exports.check_android = function() {
if (avdmanagerInPath) {
parentDir = path.dirname(avdmanagerInPath);
grandParentDir = path.dirname(parentDir);
if (path.basename(parentDir) == 'bin' && path.basename(grandParentDir) == 'tools') {
if (path.basename(parentDir) === 'bin' && path.basename(grandParentDir) === 'tools') {
maybeSetAndroidHome(path.dirname(grandParentDir));
} else {
throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting setting it manually.\n' +
@ -337,8 +350,7 @@ module.exports.check_android_target = function(originalError) {
// Google Inc.:Google APIs:20
// Google Inc.:Glass Development Kit Preview:20
var desired_api_level = module.exports.get_target();
return android_sdk.list_targets()
.then(function(targets) {
return android_sdk.list_targets().then(function (targets) {
if (targets.indexOf(desired_api_level) >= 0) {
return targets;
}
@ -358,8 +370,7 @@ module.exports.check_android_target = function(originalError) {
// Returns a promise.
module.exports.run = function () {
return Q.all([this.check_java(), this.check_android()])
.then(function(values) {
return Q.all([this.check_java(), this.check_android()]).then(function (values) {
console.log('ANDROID_HOME=' + process.env['ANDROID_HOME']);
console.log('JAVA_HOME=' + process.env['JAVA_HOME']);
@ -373,7 +384,6 @@ module.exports.run = function() {
});
};
/**
* Object thar represents one of requirements for current platform.
* @param {String} id The unique identifier for this requirements.
@ -387,7 +397,7 @@ var Requirement = function (id, name, version, installed) {
this.name = name;
this.installed = installed || false;
this.metadata = {
version: version,
version: version
};
};
@ -417,15 +427,13 @@ module.exports.check_all = function() {
return checkFns.reduce(function (promise, checkFn, idx) {
// Update each requirement with results
var requirement = requirements[idx];
return promise.then(checkFn)
.then(function (version) {
return promise.then(checkFn).then(function (version) {
requirement.installed = true;
requirement.metadata.version = version;
}, function (err) {
requirement.metadata.reason = err instanceof Error ? err.message : err;
});
}, Q())
.then(function () {
}, Q()).then(function () {
// When chain is completed, return requirements array to upstream API
return requirements;
});

View File

@ -19,8 +19,8 @@
under the License.
*/
var Q = require('q'),
build = require('./build');
var Q = require('q');
var build = require('./build');
var path = require('path');
var Adb = require('./Adb');
var AndroidManifest = require('./AndroidManifest');
@ -33,14 +33,12 @@ var events = require('cordova-common').events;
* @param lookHarder When true, try restarting adb if no devices are found.
*/
module.exports.list = function (lookHarder) {
return Adb.devices()
.then(function(list) {
return Adb.devices().then(function (list) {
if (list.length === 0 && lookHarder) {
// adb kill-server doesn't seem to do the trick.
// Could probably find a x-platform version of killall, but I'm not actually
// sure that this scenario even happens on non-OSX machines.
return spawn('killall', ['adb'])
.then(function() {
return spawn('killall', ['adb']).then(function () {
events.emit('verbose', 'Restarting adb to see if more devices are detected.');
return Adb.devices();
}, function () {
@ -53,8 +51,7 @@ module.exports.list = function(lookHarder) {
};
module.exports.resolveTarget = function (target) {
return this.list(true)
.then(function(device_list) {
return this.list(true).then(function (device_list) {
if (!device_list || !device_list.length) {
return Q.reject(new CordovaError('Failed to deploy to device, no devices found.'));
}
@ -65,8 +62,7 @@ module.exports.resolveTarget = function(target) {
return Q.reject('ERROR: Unable to find target \'' + target + '\'.');
}
return build.detectArchitecture(target)
.then(function(arch) {
return build.detectArchitecture(target).then(function (arch) {
return { target: target, arch: arch, isEmulator: false };
});
});
@ -79,7 +75,7 @@ module.exports.resolveTarget = function(target) {
*/
module.exports.install = function (target, buildResults) {
return Q().then(function () {
if (target && typeof target == 'object') {
if (target && typeof target === 'object') {
return target;
}
return module.exports.resolveTarget(target);
@ -91,24 +87,20 @@ module.exports.install = function(target, buildResults) {
events.emit('log', 'Using apk: ' + apk_path);
events.emit('log', 'Package name: ' + pkgName);
return Adb.install(resolvedTarget.target, apk_path, {replace: true})
.catch(function (error) {
return Adb.install(resolvedTarget.target, apk_path, {replace: true}).catch(function (error) {
// CB-9557 CB-10157 only uninstall and reinstall app if the one that
// is already installed on device was signed w/different certificate
if (!/INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES/.test(error.toString()))
throw error;
if (!/INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES/.test(error.toString())) { throw error; }
events.emit('warn', 'Uninstalling app from device and reinstalling it again because the ' +
'installed app already signed with different key');
// This promise is always resolved, even if 'adb uninstall' fails to uninstall app
// or the app doesn't installed at all, so no error catching needed.
return Adb.uninstall(resolvedTarget.target, pkgName)
.then(function() {
return Adb.uninstall(resolvedTarget.target, pkgName).then(function () {
return Adb.install(resolvedTarget.target, apk_path, {replace: true});
});
})
.then(function() {
}).then(function () {
// unlock screen
return Adb.shell(resolvedTarget.target, 'input keyevent 82');
}).then(function () {

View File

@ -55,8 +55,7 @@ function forgivingWhichSync(cmd) {
}
module.exports.list_images_using_avdmanager = function () {
return superspawn.spawn('avdmanager', ['list', 'avd'])
.then(function(output) {
return superspawn.spawn('avdmanager', ['list', 'avd']).then(function (output) {
var response = output.split('\n');
var emulator_list = [];
for (var i = 1; i < response.length; i++) {
@ -116,8 +115,7 @@ module.exports.list_images_using_avdmanager = function () {
};
module.exports.list_images_using_android = function () {
return superspawn.spawn('android', ['list', 'avd'])
.then(function(output) {
return superspawn.spawn('android', ['list', 'avd']).then(function (output) {
var response = output.split('\n');
var emulator_list = [];
for (var i = 1; i < response.length; i++) {
@ -188,8 +186,7 @@ module.exports.list_images = function() {
* Returns a promise.
*/
module.exports.best_image = function () {
return this.list_images()
.then(function(images) {
return this.list_images().then(function (images) {
// Just return undefined if there is no images
if (images.length === 0) return;
@ -200,7 +197,7 @@ module.exports.best_image = function() {
var target = images[i].target;
if (target) {
var num = target.split('(API level ')[1].replace(')', '');
if (num == project_target) {
if (num === project_target) {
return images[i];
} else if (project_target - num < closest && project_target > num) {
closest = project_target - num;
@ -220,8 +217,7 @@ module.exports.list_started = function() {
// Returns a promise.
// TODO: we should remove this, there's a more robust method under android_sdk.js
module.exports.list_targets = function () {
return superspawn.spawn('android', ['list', 'targets'], {cwd: os.tmpdir()})
.then(function(output) {
return superspawn.spawn('android', ['list', 'targets'], {cwd: os.tmpdir()}).then(function (output) {
var target_out = output.split('\n');
var targets = [];
for (var i = target_out.length; i >= 0; i--) {
@ -240,8 +236,7 @@ module.exports.list_targets = function() {
module.exports.get_available_port = function () {
var self = this;
return self.list_started()
.then(function (emulators) {
return self.list_started().then(function (emulators) {
for (var p = 5584; p >= 5554; p -= 2) {
if (emulators.indexOf('emulator-' + p) === -1) {
events.emit('verbose', 'Found available port: ' + p);
@ -268,8 +263,7 @@ module.exports.start = function(emulator_ID, boot_timeout) {
return Q().then(function () {
if (emulator_ID) return Q(emulator_ID);
return self.best_image()
.then(function(best) {
return self.best_image().then(function (best) {
if (best && best.name) {
events.emit('warn', 'No emulator specified, defaulting to ' + best.name);
return best.name;
@ -282,8 +276,7 @@ module.exports.start = function(emulator_ID, boot_timeout) {
'HINT: For a faster emulator, use an Intel System Image and install the HAXM device driver\n'));
});
}).then(function (emulatorId) {
return self.get_available_port()
.then(function (port) {
return self.get_available_port().then(function (port) {
// Figure out the directory the emulator binary runs in, and set the cwd to that directory.
// Workaround for https://code.google.com/p/android/issues/detail?id=235461
var emulator_dir = path.dirname(shelljs.which('emulator'));
@ -298,18 +291,15 @@ module.exports.start = function(emulator_ID, boot_timeout) {
return self.wait_for_emulator(port);
});
}).then(function (emulatorId) {
if (!emulatorId)
return Q.reject(new CordovaError('Failed to start emulator'));
if (!emulatorId) { return Q.reject(new CordovaError('Failed to start emulator')); }
// wait for emulator to boot up
process.stdout.write('Waiting for emulator to boot (this may take a while)...');
return self.wait_for_boot(emulatorId, boot_timeout)
.then(function(success) {
return self.wait_for_boot(emulatorId, boot_timeout).then(function (success) {
if (success) {
events.emit('log', 'BOOT COMPLETE');
// unlock screen
return Adb.shell(emulatorId, 'input keyevent 82')
.then(function() {
return Adb.shell(emulatorId, 'input keyevent 82').then(function () {
// return the new emulator id for the started emulators
return emulatorId;
});
@ -329,16 +319,15 @@ module.exports.wait_for_emulator = function(port) {
var self = this;
return Q().then(function () {
var emulator_id = 'emulator-' + port;
return Adb.shell(emulator_id, 'getprop dev.bootcomplete')
.then(function (output) {
return Adb.shell(emulator_id, 'getprop dev.bootcomplete').then(function (output) {
if (output.indexOf('1') >= 0) {
return emulator_id;
}
return self.wait_for_emulator(port);
}, function (error) {
if (error && error.message &&
(error.message.indexOf('not found') > -1) ||
error.message.indexOf('device offline') > -1) {
if ((error && error.message &&
(error.message.indexOf('not found') > -1)) ||
(error.message.indexOf('device offline') > -1)) {
// emulator not yet started, continue waiting
return self.wait_for_emulator(port);
} else {
@ -356,8 +345,7 @@ module.exports.wait_for_emulator = function(port) {
*/
module.exports.wait_for_boot = function (emulator_id, time_remaining) {
var self = this;
return Adb.shell(emulator_id, 'ps')
.then(function(output) {
return Adb.shell(emulator_id, 'ps').then(function (output) {
if (output.match(/android\.process\.acore/)) {
return true;
} else if (time_remaining === 0) {
@ -382,8 +370,7 @@ module.exports.wait_for_boot = function(emulator_id, time_remaining) {
module.exports.create_image = function (name, target) {
console.log('Creating new avd named ' + name);
if (target) {
return superspawn.spawn('android', ['create', 'avd', '--name', name, '--target', target])
.then(null, function(error) {
return superspawn.spawn('android', ['create', 'avd', '--name', name, '--target', target]).then(null, function (error) {
console.error('ERROR : Failed to create emulator image : ');
console.error(' Do you have the latest android targets including ' + target + '?');
console.error(error);
@ -391,8 +378,7 @@ module.exports.create_image = function(name, target) {
} else {
console.log('WARNING : Project target not found, creating avd with a different target but the project may fail to install.');
// TODO: there's a more robust method for finding targets in android_sdk.js
return superspawn.spawn('android', ['create', 'avd', '--name', name, '--target', this.list_targets()[0]])
.then(function() {
return superspawn.spawn('android', ['create', 'avd', '--name', name, '--target', this.list_targets()[0]]).then(function () {
// TODO: This seems like another error case, even though it always happens.
console.error('ERROR : Unable to create an avd emulator, no targets found.');
console.error('Ensure you have targets available by running the "android" command');
@ -405,8 +391,7 @@ module.exports.create_image = function(name, target) {
};
module.exports.resolveTarget = function (target) {
return this.list_started()
.then(function(emulator_list) {
return this.list_started().then(function (emulator_list) {
if (emulator_list.length < 1) {
return Q.reject('No running Android emulators found, please start an emulator before deploying your project.');
}
@ -417,8 +402,7 @@ module.exports.resolveTarget = function(target) {
return Q.reject('Unable to find target \'' + target + '\'. Failed to deploy to emulator.');
}
return build.detectArchitecture(target)
.then(function(arch) {
return build.detectArchitecture(target).then(function (arch) {
return {target: target, arch: arch, isEmulator: true};
});
});
@ -438,7 +422,7 @@ module.exports.install = function(givenTarget, buildResults) {
// resolve the target emulator
return Q().then(function () {
if (givenTarget && typeof givenTarget == 'object') {
if (givenTarget && typeof givenTarget === 'object') {
return givenTarget;
} else {
return module.exports.resolveTarget(givenTarget);
@ -452,8 +436,7 @@ module.exports.install = function(givenTarget, buildResults) {
}).then(function () {
// This promise is always resolved, even if 'adb uninstall' fails to uninstall app
// or the app doesn't installed at all, so no error catching needed.
return Q.when()
.then(function() {
return Q.when().then(function () {
var apk_path = build.findBestApkForArchitecture(buildResults, target.arch);
var execOptions = {
@ -494,27 +477,23 @@ module.exports.install = function(givenTarget, buildResults) {
}
function installPromise () {
return adbInstallWithOptions(target.target, apk_path, execOptions)
.catch(function (error) {
return adbInstallWithOptions(target.target, apk_path, execOptions).catch(function (error) {
// CB-9557 CB-10157 only uninstall and reinstall app if the one that
// is already installed on device was signed w/different certificate
if (!/INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES/.test(error.toString()))
throw error;
if (!/INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES/.test(error.toString())) { throw error; }
events.emit('warn', 'Uninstalling app from device and reinstalling it because the ' +
'currently installed app was signed with different key');
// This promise is always resolved, even if 'adb uninstall' fails to uninstall app
// or the app doesn't installed at all, so no error catching needed.
return Adb.uninstall(target.target, pkgName)
.then(function() {
return Adb.uninstall(target.target, pkgName).then(function () {
return adbInstallWithOptions(target.target, apk_path, execOptions);
});
});
}
return retry.retryPromise(NUM_INSTALL_RETRIES, installPromise)
.then(function (output) {
return retry.retryPromise(NUM_INSTALL_RETRIES, installPromise).then(function (output) {
events.emit('log', 'INSTALL SUCCESS');
});
});

View File

@ -0,0 +1,3 @@
@ECHO OFF
for /f "tokens=2*" %%a in ('REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Android Studio" /v Path') do set "ASPath=%%~b"
ECHO %ASPath%

View File

@ -19,11 +19,11 @@
under the License.
*/
var path = require('path'),
os = require('os'),
Q = require('q'),
child_process = require('child_process'),
ROOT = path.join(__dirname, '..', '..');
var path = require('path');
var os = require('os');
var Q = require('q');
var child_process = require('child_process');
var ROOT = path.join(__dirname, '..', '..');
/*
* Starts running logcat in the shell.

View File

@ -95,9 +95,9 @@ var handlers = {
subDir = src;
}
if (obj.type == 'gradleReference') {
if (obj.type === 'gradleReference') {
project.addGradleReference(parentDir, subDir);
} else if (obj.type == 'sys') {
} else if (obj.type === 'sys') {
project.addSystemLibrary(parentDir, subDir);
} else {
project.addSubProject(parentDir, subDir);
@ -125,9 +125,9 @@ var handlers = {
subDir = src;
}
if (obj.type == 'gradleReference') {
if (obj.type === 'gradleReference') {
project.removeGradleReference(parentDir, subDir);
} else if (obj.type == 'sys') {
} else if (obj.type === 'sys') {
project.removeSystemLibrary(parentDir, subDir);
} else {
project.removeSubProject(parentDir, subDir);
@ -221,14 +221,12 @@ function copyFile (plugin_dir, src, project_dir, dest, link) {
// check that src path is inside plugin directory
var real_path = fs.realpathSync(src);
var real_plugin_path = fs.realpathSync(plugin_dir);
if (real_path.indexOf(real_plugin_path) !== 0)
throw new CordovaError('File "' + src + '" is located outside the plugin directory "' + plugin_dir + '"');
if (real_path.indexOf(real_plugin_path) !== 0) { throw new CordovaError('File "' + src + '" is located outside the plugin directory "' + plugin_dir + '"'); }
dest = path.resolve(project_dir, dest);
// check that dest path is located in project directory
if (dest.indexOf(project_dir) !== 0)
throw new CordovaError('Destination "' + dest + '" for source file "' + src + '" is located outside the project');
if (dest.indexOf(project_dir) !== 0) { throw new CordovaError('Destination "' + dest + '" for source file "' + src + '" is located outside the project'); }
shell.mkdir('-p', path.dirname(dest));
if (link) {
@ -244,8 +242,7 @@ function copyFile (plugin_dir, src, project_dir, dest, link) {
// Same as copy file but throws error if target exists
function copyNewFile (plugin_dir, src, project_dir, dest, link) {
var target_path = path.resolve(project_dir, dest);
if (fs.existsSync(target_path))
throw new CordovaError('"' + target_path + '" already exists!');
if (fs.existsSync(target_path)) { throw new CordovaError('"' + target_path + '" already exists!'); }
copyFile(plugin_dir, src, project_dir, dest, !!link);
}
@ -260,8 +257,7 @@ function symlinkFileOrDirTree(src, dest) {
fs.readdirSync(src).forEach(function (entry) {
symlinkFileOrDirTree(path.join(src, entry), path.join(dest, entry));
});
}
else {
} else {
fs.symlinkSync(path.relative(fs.realpathSync(path.dirname(dest)), src), dest);
}
}

View File

@ -16,6 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
/* eslint no-useless-escape: 0 */
var Q = require('q');
var fs = require('fs');
@ -40,17 +41,14 @@ module.exports.prepare = function (cordovaProject, options) {
this._config = updateConfigFilesFrom(cordovaProject.projectConfig, munger, this.locations);
// Update own www dir with project's www assets and plugins' assets and js-files
return Q.when(updateWww(cordovaProject, this.locations))
.then(function () {
return Q.when(updateWww(cordovaProject, this.locations)).then(function () {
// update project according to config.xml changes.
return updateProjectAccordingTo(self._config, self.locations);
})
.then(function () {
}).then(function () {
updateIcons(cordovaProject, path.relative(cordovaProject.root, self.locations.res));
updateSplashes(cordovaProject, path.relative(cordovaProject.root, self.locations.res));
updateFileResources(cordovaProject, path.relative(cordovaProject.root, self.locations.root));
})
.then(function () {
}).then(function () {
events.emit('verbose', 'Prepared android project successfully');
});
};
@ -272,7 +270,7 @@ function updateSplashes(cordovaProject, platformResourcesDir) {
if (!resource.density) {
return;
}
if (resource.density == 'mdpi') {
if (resource.density === 'mdpi') {
hadMdpi = true;
}
var targetPath = getImageResourcePath(
@ -397,15 +395,13 @@ function cleanIcons(projectRoot, projectConfig, platformResourcesDir) {
*/
function mapImageResources (rootDir, subDir, type, resourceName) {
var pathMap = {};
shell.ls(path.join(rootDir, subDir, type + '-*'))
.forEach(function (drawableFolder) {
shell.ls(path.join(rootDir, subDir, type + '-*')).forEach(function (drawableFolder) {
var imagePath = path.join(subDir, path.basename(drawableFolder), resourceName);
pathMap[imagePath] = null;
});
return pathMap;
}
function updateFileResources (cordovaProject, platformDir) {
var files = cordovaProject.projectConfig.getFileResources('android');
@ -426,7 +422,6 @@ function updateFileResources(cordovaProject, platformDir) {
resourceMap, { rootDir: cordovaProject.root }, logFileOp);
}
function cleanFileResources (projectRoot, projectConfig, platformDir) {
var files = projectConfig.getFileResources('android', true);
if (files.length > 0) {
@ -439,7 +434,8 @@ function cleanFileResources(projectRoot, projectConfig, platformDir) {
});
FileUpdater.updatePaths(
resourceMap, { rootDir: projectRoot, all: true}, logFileOp);
resourceMap, {
rootDir: projectRoot, all: true}, logFileOp);
}
}

View File

@ -21,12 +21,12 @@
/* jshint loopfunc:true */
var path = require('path'),
build = require('./build'),
emulator = require('./emulator'),
device = require('./device'),
Q = require('q'),
events = require('cordova-common').events;
var path = require('path');
var build = require('./build');
var emulator = require('./emulator');
var device = require('./device');
var Q = require('q');
var events = require('cordova-common').events;
function getInstallTarget (runOptions) {
var install_target;
@ -56,12 +56,10 @@ function getInstallTarget(runOptions) {
var self = this;
var install_target = getInstallTarget(runOptions);
return Q()
.then(function() {
return Q().then(function () {
if (!install_target) {
// no target given, deploy to device if available, otherwise use the emulator.
return device.list()
.then(function(device_list) {
return device.list().then(function (device_list) {
if (device_list.length > 0) {
events.emit('warn', 'No target specified, deploying to device \'' + device_list[0] + '\'.');
install_target = device_list[0];
@ -72,35 +70,30 @@ function getInstallTarget(runOptions) {
});
}
}).then(function () {
if (install_target == '--device') {
if (install_target === '--device') {
return device.resolveTarget(null);
} else if (install_target == '--emulator') {
} else if (install_target === '--emulator') {
// Give preference to any already started emulators. Else, start one.
return emulator.list_started()
.then(function(started) {
return emulator.list_started().then(function (started) {
return started && started.length > 0 ? started[0] : emulator.start();
}).then(function (emulatorId) {
return emulator.resolveTarget(emulatorId);
});
}
// They specified a specific device/emulator ID.
return device.list()
.then(function(devices) {
return device.list().then(function (devices) {
if (devices.indexOf(install_target) > -1) {
return device.resolveTarget(install_target);
}
return emulator.list_started()
.then(function(started_emulators) {
return emulator.list_started().then(function (started_emulators) {
if (started_emulators.indexOf(install_target) > -1) {
return emulator.resolveTarget(install_target);
}
return emulator.list_images()
.then(function(avds) {
return emulator.list_images().then(function (avds) {
// if target emulator isn't started, then start it.
for (var avd in avds) {
if (avds[avd].name == install_target) {
return emulator.start(install_target)
.then(function(emulatorId) {
if (avds[avd].name === install_target) {
return emulator.start(install_target).then(function (emulatorId) {
return emulator.resolveTarget(emulatorId);
});
}
@ -114,11 +107,9 @@ function getInstallTarget(runOptions) {
// build results (according to platformApi spec) so they are in different
// format than emulator.install expects.
// TODO: Update emulator/device.install to handle this change
return build.run.call(self, runOptions, resolvedTarget)
.then(function(buildResults) {
return build.run.call(self, runOptions, resolvedTarget).then(function (buildResults) {
if (resolvedTarget.isEmulator) {
return emulator.wait_for_boot(resolvedTarget.target)
.then(function () {
return emulator.wait_for_boot(resolvedTarget.target).then(function () {
return emulator.install(resolvedTarget, buildResults);
});
}

File diff suppressed because it is too large Load Diff

View File

@ -19,10 +19,10 @@
"apache"
],
"scripts": {
"test": "npm run jshint && jasmine",
"test": "npm run eslint && jasmine",
"cover": "istanbul cover --root bin/templates/cordova --print detail jasmine",
"test-build": "jasmine --captureExceptions --color spec/e2e/*.spec.js",
"jshint": "jshint bin && jshint spec"
"eslint": "eslint bin && eslint spec"
},
"author": "Apache Software Foundation",
"license": "Apache-2.0",
@ -43,9 +43,15 @@
"shelljs"
],
"devDependencies": {
"eslint": "^3.19.0",
"eslint-config-semistandard": "^11.0.0",
"eslint-config-standard": "^10.2.1",
"eslint-plugin-import": "^2.3.0",
"eslint-plugin-node": "^5.0.0",
"eslint-plugin-promise": "^3.5.0",
"eslint-plugin-standard": "^3.0.1",
"istanbul": "^0.4.2",
"jasmine": "^2.5.2",
"jshint": "^2.6.0",
"promise-matchers": "~0",
"rewire": "^2.1.3"
},

2
spec/.eslintrc.yml Normal file
View File

@ -0,0 +1,2 @@
env:
jasmine: true

View File

@ -32,7 +32,6 @@ function createAndBuild(projectname, projectid, done) {
});
}
describe('create', function () {
it('Test#001 : create project with ascii name, no spaces', function (done) {

View File

@ -17,11 +17,11 @@
under the License.
*/
var PluginInfoProvider = require('cordova-common').PluginInfoProvider,
shell = require('shelljs'),
cp = require('child_process'),
path = require('path'),
util = require('util');
var PluginInfoProvider = require('cordova-common').PluginInfoProvider;
var shell = require('shelljs');
var cp = require('child_process');
var path = require('path');
var util = require('util');
var cordova_bin = path.join(__dirname, '../../../bin');

View File

@ -17,8 +17,8 @@
under the License.
*/
var path = require('path'),
actions = require('./helpers/projectActions.js');
var path = require('path');
var actions = require('./helpers/projectActions.js');
var PLUGIN_ADD_TIMEOUT = 90000;

View File

@ -17,16 +17,16 @@
under the License.
*/
var actions = require('./helpers/projectActions.js'),
shell = require('shelljs'),
fs = require('fs'),
util = require('util'),
platformOld = { version: '4.0.0', path: 'cordova-android-old' },
platformEdge = { version: getCurrentVersion(), path: '.' };
var actions = require('./helpers/projectActions.js');
var shell = require('shelljs');
var fs = require('fs');
var util = require('util');
var platformOld = { version: '4.0.0', path: 'cordova-android-old' };
var platformEdge = { version: getCurrentVersion(), path: '.' };
var DOWNLOAD_TIMEOUT = 2 * 60 * 1000,
UPDATE_TIMEOUT = 90 * 1000,
PLATFORM_GIT_URL = 'https://github.com/apache/cordova-android';
var DOWNLOAD_TIMEOUT = 2 * 60 * 1000;
var UPDATE_TIMEOUT = 90 * 1000;
var PLATFORM_GIT_URL = 'https://github.com/apache/cordova-android';
function getCurrentVersion () {
return fs.readFileSync('VERSION').toString().trim();

View File

@ -1 +0,0 @@
./org.test.plugins.dummyplugin/www/dummyplugin.js

View File

@ -2,7 +2,6 @@
var path = require('path');
var AndroidStudio = require('../../bin/templates/cordova/lib/AndroidStudio');
describe('AndroidStudio module', function () {
it('should return true for Android Studio project', function () {
var root = path.join(__dirname, '../fixtures/android_studio_project/');

View File

@ -17,8 +17,6 @@
under the License.
*/
/* jshint node:true */
var Q = require('q');
var os = require('os');
var path = require('path');
@ -59,9 +57,7 @@ describe('addPlugin method', function () {
});
it('Test#001 : should call gradleBuilder.prepBuildFiles for every plugin with frameworks', function (done) {
api.addPlugin(new PluginInfo(path.join(FIXTURES, 'cordova-plugin-fake')))
.catch(fail)
.fin(function () {
api.addPlugin(new PluginInfo(path.join(FIXTURES, 'cordova-plugin-fake'))).catch(fail).fin(function () {
expect(fail).not.toHaveBeenCalled();
expect(gradleBuilder.prepBuildFiles).toHaveBeenCalled();
done();
@ -69,9 +65,7 @@ describe('addPlugin method', function () {
});
it('Test#002 : shouldn\'t trigger gradleBuilder.prepBuildFiles for plugins without android frameworks', function (done) {
api.addPlugin(new PluginInfo(path.join(FIXTURES, 'cordova-plugin-fake-ios-frameworks')))
.catch(fail)
.fin(function () {
api.addPlugin(new PluginInfo(path.join(FIXTURES, 'cordova-plugin-fake-ios-frameworks'))).catch(fail).fin(function () {
expect(fail).not.toHaveBeenCalled();
expect(gradleBuilder.prepBuildFiles).not.toHaveBeenCalled();
done();

View File

@ -16,41 +16,37 @@
specific language governing permissions and limitations
under the License.
*/
/* jshint laxcomma:true */
var android_sdk = require("../../bin/templates/cordova/lib/android_sdk");
var superspawn = require("cordova-common").superspawn;
var fs = require("fs");
var path = require("path");
var Q = require("q");
var android_sdk = require('../../bin/templates/cordova/lib/android_sdk');
var superspawn = require('cordova-common').superspawn;
var fs = require('fs');
var path = require('path');
var Q = require('q');
describe("android_sdk", function () {
describe("list_targets_with_android", function() {
it("should invoke `android` with the `list target` command and _not_ the `list targets` command, as the plural form is not supported in some Android SDK Tools versions", function() {
describe('android_sdk', function () {
describe('list_targets_with_android', function () {
it('should invoke `android` with the `list target` command and _not_ the `list targets` command, as the plural form is not supported in some Android SDK Tools versions', function () {
var deferred = Q.defer();
spyOn(superspawn, "spawn").and.returnValue(deferred.promise);
spyOn(superspawn, 'spawn').and.returnValue(deferred.promise);
android_sdk.list_targets_with_android();
expect(superspawn.spawn).toHaveBeenCalledWith("android", ["list", "target"]);
expect(superspawn.spawn).toHaveBeenCalledWith('android', ['list', 'target']);
});
it("should parse and return results from `android list targets` command", function(done) {
it('should parse and return results from `android list targets` command', function (done) {
var deferred = Q.defer();
spyOn(superspawn, "spawn").and.returnValue(deferred.promise);
deferred.resolve(fs.readFileSync(path.join("spec", "fixtures", "sdk25.2-android_list_targets.txt"), "utf-8"));
return android_sdk.list_targets_with_android()
.then(function(list) {
[ "Google Inc.:Google APIs:23",
"Google Inc.:Google APIs:22",
"Google Inc.:Google APIs:21",
"android-25",
"android-24",
"android-N",
"android-23",
"android-MNC",
"android-22",
"android-21",
"android-20" ].forEach(function(target) {
expect(list).toContain(target);
});
spyOn(superspawn, 'spawn').and.returnValue(deferred.promise);
deferred.resolve(fs.readFileSync(path.join('spec', 'fixtures', 'sdk25.2-android_list_targets.txt'), 'utf-8'));
return android_sdk.list_targets_with_android().then(function (list) {
[ 'Google Inc.:Google APIs:23',
'Google Inc.:Google APIs:22',
'Google Inc.:Google APIs:21',
'android-25',
'android-24',
'android-N',
'android-23',
'android-MNC',
'android-22',
'android-21',
'android-20' ].forEach(function (target) { expect(list).toContain(target); });
}).fail(function (err) {
console.log(err);
expect(err).toBeUndefined();
@ -59,14 +55,13 @@ describe("android_sdk", function () {
});
});
});
describe("list_targets_with_avdmanager", function() {
it("should parse and return results from `avdmanager list target` command", function(done) {
describe('list_targets_with_avdmanager', function () {
it('should parse and return results from `avdmanager list target` command', function (done) {
var deferred = Q.defer();
spyOn(superspawn, "spawn").and.returnValue(deferred.promise);
deferred.resolve(fs.readFileSync(path.join("spec", "fixtures", "sdk25.3-avdmanager_list_target.txt"), "utf-8"));
return android_sdk.list_targets_with_avdmanager()
.then(function(list) {
expect(list).toContain("android-25");
spyOn(superspawn, 'spawn').and.returnValue(deferred.promise);
deferred.resolve(fs.readFileSync(path.join('spec', 'fixtures', 'sdk25.3-avdmanager_list_target.txt'), 'utf-8'));
return android_sdk.list_targets_with_avdmanager().then(function (list) {
expect(list).toContain('android-25');
}).fail(function (err) {
console.log(err);
expect(err).toBeUndefined();
@ -75,56 +70,53 @@ describe("android_sdk", function () {
});
});
});
describe("list_targets", function() {
it("should parse Android SDK installed target information with `avdmanager` command first", function() {
describe('list_targets', function () {
it('should parse Android SDK installed target information with `avdmanager` command first', function () {
var deferred = Q.defer();
var avdmanager_spy = spyOn(android_sdk, "list_targets_with_avdmanager").and.returnValue(deferred.promise);
var avdmanager_spy = spyOn(android_sdk, 'list_targets_with_avdmanager').and.returnValue(deferred.promise);
android_sdk.list_targets();
expect(avdmanager_spy).toHaveBeenCalled();
});
it("should parse Android SDK installed target information with `android` command if list_targets_with_avdmanager fails with ENOENT", function(done) {
it('should parse Android SDK installed target information with `android` command if list_targets_with_avdmanager fails with ENOENT', function (done) {
var deferred = Q.defer();
spyOn(android_sdk, "list_targets_with_avdmanager").and.returnValue(deferred.promise);
spyOn(android_sdk, 'list_targets_with_avdmanager').and.returnValue(deferred.promise);
deferred.reject({
code: "ENOENT"
code: 'ENOENT'
});
var twoferred = Q.defer();
twoferred.resolve(["target1"]);
var avdmanager_spy = spyOn(android_sdk, "list_targets_with_android").and.returnValue(twoferred.promise);
return android_sdk.list_targets()
.then(function(targets) {
twoferred.resolve(['target1']);
var avdmanager_spy = spyOn(android_sdk, 'list_targets_with_android').and.returnValue(twoferred.promise);
return android_sdk.list_targets().then(function (targets) {
expect(avdmanager_spy).toHaveBeenCalled();
expect(targets[0]).toEqual("target1");
expect(targets[0]).toEqual('target1');
done();
});
});
it("should parse Android SDK installed target information with `android` command if list_targets_with_avdmanager fails with not-recognized error (Windows)", function(done) {
it('should parse Android SDK installed target information with `android` command if list_targets_with_avdmanager fails with not-recognized error (Windows)', function (done) {
var deferred = Q.defer();
spyOn(android_sdk, "list_targets_with_avdmanager").and.returnValue(deferred.promise);
spyOn(android_sdk, 'list_targets_with_avdmanager').and.returnValue(deferred.promise);
deferred.reject({
code: 1,
stderr: "'avdmanager' is not recognized as an internal or external commmand,\r\noperable program or batch file.\r\n"
});
var twoferred = Q.defer();
twoferred.resolve(["target1"]);
var avdmanager_spy = spyOn(android_sdk, "list_targets_with_android").and.returnValue(twoferred.promise);
return android_sdk.list_targets()
.then(function(targets) {
twoferred.resolve(['target1']);
var avdmanager_spy = spyOn(android_sdk, 'list_targets_with_android').and.returnValue(twoferred.promise);
return android_sdk.list_targets().then(function (targets) {
expect(avdmanager_spy).toHaveBeenCalled();
expect(targets[0]).toEqual("target1");
expect(targets[0]).toEqual('target1');
done();
});
});
it("should throw an error if no Android targets were found.", function(done) {
it('should throw an error if no Android targets were found.', function (done) {
var deferred = Q.defer();
spyOn(android_sdk, "list_targets_with_avdmanager").and.returnValue(deferred.promise);
spyOn(android_sdk, 'list_targets_with_avdmanager').and.returnValue(deferred.promise);
deferred.resolve([]);
return android_sdk.list_targets()
.then(function(targets) {
return android_sdk.list_targets().then(function (targets) {
done.fail();
}).catch(function (err) {
expect(err).toBeDefined();
expect(err.message).toContain("No android targets (SDKs) installed!");
expect(err.message).toContain('No android targets (SDKs) installed!');
done();
});
});

View File

@ -1,4 +1,5 @@
var gradle_builder = require('../../../bin/templates/cordova/lib/builders/GradleBuilder.js');
var Gradle_builder = require('../../../bin/templates/cordova/lib/builders/GradleBuilder.js');
var fs = require('fs');
var superspawn = require('cordova-common').superspawn;
var builder;
@ -6,7 +7,7 @@ var builder;
describe('Gradle Builder', function () {
beforeEach(function () {
spyOn(fs, 'existsSync').and.returnValue(true);
builder = new gradle_builder('/root');
builder = new Gradle_builder('/root');
spyOn(superspawn, 'spawn');
});

View File

@ -16,16 +16,15 @@
specific language governing permissions and limitations
under the License.
*/
/* jshint laxcomma:true */
var check_reqs = require("../../bin/templates/cordova/lib/check_reqs");
var android_sdk = require("../../bin/templates/cordova/lib/android_sdk");
var shelljs = require("shelljs");
var fs = require("fs");
var path = require("path");
var Q = require("q");
var check_reqs = require('../../bin/templates/cordova/lib/check_reqs');
var android_sdk = require('../../bin/templates/cordova/lib/android_sdk');
var shelljs = require('shelljs');
var fs = require('fs');
var path = require('path');
var Q = require('q');
describe("check_reqs", function () {
describe('check_reqs', function () {
var original_env;
beforeAll(function () {
original_env = Object.create(process.env);
@ -35,23 +34,22 @@ describe("check_reqs", function () {
process.env[k] = original_env[k];
});
});
describe("check_android", function() {
describe("set ANDROID_HOME if not set", function() {
describe('check_android', function () {
describe('set ANDROID_HOME if not set', function () {
beforeEach(function () {
delete process.env.ANDROID_HOME;
});
describe("even if no Android binaries are on the PATH", function() {
describe('even if no Android binaries are on the PATH', function () {
beforeEach(function () {
spyOn(shelljs, "which").and.returnValue(null);
spyOn(fs, "existsSync").and.returnValue(true);
spyOn(shelljs, 'which').and.returnValue(null);
spyOn(fs, 'existsSync').and.returnValue(true);
});
it("it should set ANDROID_HOME on Windows", function(done) {
spyOn(check_reqs, "isWindows").and.returnValue(true);
process.env.LOCALAPPDATA = "windows-local-app-data";
process.env.ProgramFiles = "windows-program-files";
return check_reqs.check_android()
.then(function() {
expect(process.env.ANDROID_HOME).toContain("windows-local-app-data");
it('it should set ANDROID_HOME on Windows', function (done) {
spyOn(check_reqs, 'isWindows').and.returnValue(true);
process.env.LOCALAPPDATA = 'windows-local-app-data';
process.env.ProgramFiles = 'windows-program-files';
return check_reqs.check_android().then(function () {
expect(process.env.ANDROID_HOME).toContain('windows-local-app-data');
}).fail(function (err) {
expect(err).toBeUndefined();
console.log(err);
@ -61,13 +59,12 @@ describe("check_reqs", function () {
done();
});
});
it("it should set ANDROID_HOME on Darwin", function(done) {
spyOn(check_reqs, "isWindows").and.returnValue(false);
spyOn(check_reqs, "isDarwin").and.returnValue(true);
process.env.HOME = "home is where the heart is";
return check_reqs.check_android()
.then(function() {
expect(process.env.ANDROID_HOME).toContain("home is where the heart is");
it('it should set ANDROID_HOME on Darwin', function (done) {
spyOn(check_reqs, 'isWindows').and.returnValue(false);
spyOn(check_reqs, 'isDarwin').and.returnValue(true);
process.env.HOME = 'home is where the heart is';
return check_reqs.check_android().then(function () {
expect(process.env.ANDROID_HOME).toContain('home is where the heart is');
}).fail(function (err) {
expect(err).toBeUndefined();
console.log(err);
@ -77,134 +74,127 @@ describe("check_reqs", function () {
});
});
});
describe("if some Android tooling exists on the PATH", function() {
describe('if some Android tooling exists on the PATH', function () {
beforeEach(function () {
spyOn(fs, "realpathSync").and.callFake(function(path) {
spyOn(fs, 'realpathSync').and.callFake(function (path) {
return path;
});
});
it("should set ANDROID_HOME based on `android` command if command exists in a SDK-like directory structure", function(done) {
spyOn(fs, "existsSync").and.returnValue(true);
spyOn(shelljs, "which").and.callFake(function(cmd) {
if (cmd == "android") {
return "/android/sdk/tools/android";
it('should set ANDROID_HOME based on `android` command if command exists in a SDK-like directory structure', function (done) {
spyOn(fs, 'existsSync').and.returnValue(true);
spyOn(shelljs, 'which').and.callFake(function (cmd) {
if (cmd === 'android') {
return '/android/sdk/tools/android';
} else {
return null;
}
});
return check_reqs.check_android()
.then(function() {
expect(process.env.ANDROID_HOME).toEqual("/android/sdk");
return check_reqs.check_android().then(function () {
expect(process.env.ANDROID_HOME).toEqual('/android/sdk');
done();
}).fail(function (err) {
expect(err).toBeUndefined();
console.log(err);
});
});
it("should error out if `android` command exists in a non-SDK-like directory structure", function(done) {
spyOn(shelljs, "which").and.callFake(function(cmd) {
if (cmd == "android") {
return "/just/some/random/path/android";
it('should error out if `android` command exists in a non-SDK-like directory structure', function (done) {
spyOn(shelljs, 'which').and.callFake(function (cmd) {
if (cmd === 'android') {
return '/just/some/random/path/android';
} else {
return null;
}
});
return check_reqs.check_android()
.then(function() {
return check_reqs.check_android().then(function () {
done.fail();
}).fail(function (err) {
expect(err).toBeDefined();
expect(err.message).toContain("update your PATH to include valid path");
expect(err.message).toContain('update your PATH to include valid path');
done();
});
});
it("should set ANDROID_HOME based on `adb` command if command exists in a SDK-like directory structure", function(done) {
spyOn(fs, "existsSync").and.returnValue(true);
spyOn(shelljs, "which").and.callFake(function(cmd) {
if (cmd == "adb") {
return "/android/sdk/platform-tools/adb";
it('should set ANDROID_HOME based on `adb` command if command exists in a SDK-like directory structure', function (done) {
spyOn(fs, 'existsSync').and.returnValue(true);
spyOn(shelljs, 'which').and.callFake(function (cmd) {
if (cmd === 'adb') {
return '/android/sdk/platform-tools/adb';
} else {
return null;
}
});
return check_reqs.check_android()
.then(function() {
expect(process.env.ANDROID_HOME).toEqual("/android/sdk");
return check_reqs.check_android().then(function () {
expect(process.env.ANDROID_HOME).toEqual('/android/sdk');
done();
}).fail(function (err) {
expect(err).toBeUndefined();
console.log(err);
});
});
it("should error out if `adb` command exists in a non-SDK-like directory structure", function(done) {
spyOn(shelljs, "which").and.callFake(function(cmd) {
if (cmd == "adb") {
return "/just/some/random/path/adb";
it('should error out if `adb` command exists in a non-SDK-like directory structure', function (done) {
spyOn(shelljs, 'which').and.callFake(function (cmd) {
if (cmd === 'adb') {
return '/just/some/random/path/adb';
} else {
return null;
}
});
return check_reqs.check_android()
.then(function() {
return check_reqs.check_android().then(function () {
done.fail();
}).fail(function (err) {
expect(err).toBeDefined();
expect(err.message).toContain("update your PATH to include valid path");
expect(err.message).toContain('update your PATH to include valid path');
done();
});
});
it("should set ANDROID_HOME based on `avdmanager` command if command exists in a SDK-like directory structure", function(done) {
spyOn(fs, "existsSync").and.returnValue(true);
spyOn(shelljs, "which").and.callFake(function(cmd) {
if (cmd == "avdmanager") {
return "/android/sdk/tools/bin/avdmanager";
it('should set ANDROID_HOME based on `avdmanager` command if command exists in a SDK-like directory structure', function (done) {
spyOn(fs, 'existsSync').and.returnValue(true);
spyOn(shelljs, 'which').and.callFake(function (cmd) {
if (cmd === 'avdmanager') {
return '/android/sdk/tools/bin/avdmanager';
} else {
return null;
}
});
return check_reqs.check_android()
.then(function() {
expect(process.env.ANDROID_HOME).toEqual("/android/sdk");
return check_reqs.check_android().then(function () {
expect(process.env.ANDROID_HOME).toEqual('/android/sdk');
done();
}).fail(function (err) {
expect(err).toBeUndefined();
console.log(err);
});
});
it("should error out if `avdmanager` command exists in a non-SDK-like directory structure", function(done) {
spyOn(shelljs, "which").and.callFake(function(cmd) {
if (cmd == "avdmanager") {
return "/just/some/random/path/avdmanager";
it('should error out if `avdmanager` command exists in a non-SDK-like directory structure', function (done) {
spyOn(shelljs, 'which').and.callFake(function (cmd) {
if (cmd === 'avdmanager') {
return '/just/some/random/path/avdmanager';
} else {
return null;
}
});
return check_reqs.check_android()
.then(function() {
return check_reqs.check_android().then(function () {
done.fail();
}).fail(function (err) {
expect(err).toBeDefined();
expect(err.message).toContain("update your PATH to include valid path");
expect(err.message).toContain('update your PATH to include valid path');
done();
});
});
});
});
describe("set PATH for various Android binaries if not available", function() {
describe('set PATH for various Android binaries if not available', function () {
beforeEach(function () {
spyOn(shelljs, "which").and.returnValue(null);
process.env.ANDROID_HOME = "let the children play";
spyOn(fs, "existsSync").and.returnValue(true);
spyOn(shelljs, 'which').and.returnValue(null);
process.env.ANDROID_HOME = 'let the children play';
spyOn(fs, 'existsSync').and.returnValue(true);
});
afterEach(function () {
delete process.env.ANDROID_HOME;
});
it("should add tools/bin,tools,platform-tools to PATH if `avdmanager`,`android`,`adb` is not found", function(done) {
return check_reqs.check_android()
.then(function() {
expect(process.env.PATH).toContain("let the children play" + path.sep + "tools");
expect(process.env.PATH).toContain("let the children play" + path.sep + "platform-tools");
expect(process.env.PATH).toContain("let the children play" + path.sep + "tools" + path.sep + "bin");
it('should add tools/bin,tools,platform-tools to PATH if `avdmanager`,`android`,`adb` is not found', function (done) {
return check_reqs.check_android().then(function () {
expect(process.env.PATH).toContain('let the children play' + path.sep + 'tools');
expect(process.env.PATH).toContain('let the children play' + path.sep + 'platform-tools');
expect(process.env.PATH).toContain('let the children play' + path.sep + 'tools' + path.sep + 'bin');
done();
}).fail(function (err) {
expect(err).toBeUndefined();
@ -213,37 +203,35 @@ describe("check_reqs", function () {
});
});
});
describe("get_target", function() {
it("should retrieve target from framework project.properties file", function() {
describe('get_target', function () {
it('should retrieve target from framework project.properties file', function () {
var target = check_reqs.get_target();
expect(target).toBeDefined();
expect(target).toContain("android-");
expect(target).toContain('android-');
});
});
describe("check_android_target", function() {
it("should should return full list of supported targets if there is a match to ideal api level", function(done) {
describe('check_android_target', function () {
it('should should return full list of supported targets if there is a match to ideal api level', function (done) {
var deferred = Q.defer();
spyOn(android_sdk, "list_targets").and.returnValue(deferred.promise);
var fake_targets = ["you are my fire", "my one desire"];
spyOn(android_sdk, 'list_targets').and.returnValue(deferred.promise);
var fake_targets = ['you are my fire', 'my one desire'];
deferred.resolve(fake_targets);
spyOn(check_reqs, "get_target").and.returnValue("you are my fire");
return check_reqs.check_android_target()
.then(function(targets) {
spyOn(check_reqs, 'get_target').and.returnValue('you are my fire');
return check_reqs.check_android_target().then(function (targets) {
expect(targets).toBeDefined();
expect(targets).toEqual(fake_targets);
done();
});
});
it("should error out if there is no match between ideal api level and installed targets", function(done) {
it('should error out if there is no match between ideal api level and installed targets', function (done) {
var deferred = Q.defer();
spyOn(android_sdk, "list_targets").and.returnValue(deferred.promise);
var fake_targets = ["you are my fire", "my one desire"];
spyOn(android_sdk, 'list_targets').and.returnValue(deferred.promise);
var fake_targets = ['you are my fire', 'my one desire'];
deferred.resolve(fake_targets);
spyOn(check_reqs, "get_target").and.returnValue("and i knowwwwwwwwwwww");
return check_reqs.check_android_target()
.catch(function(err) {
spyOn(check_reqs, 'get_target').and.returnValue('and i knowwwwwwwwwwww');
return check_reqs.check_android_target().catch(function (err) {
expect(err).toBeDefined();
expect(err.message).toContain("Please install Android target");
expect(err.message).toContain('Please install Android target');
done();
});
});

View File

@ -16,39 +16,37 @@
specific language governing permissions and limitations
under the License.
*/
/* jshint laxcomma:true */
var create = require("../../bin/lib/create");
var create = require('../../bin/lib/create');
describe("create", function () {
describe("validatePackageName", function() {
describe('create', function () {
describe('validatePackageName', function () {
var valid = [
"org.apache.mobilespec"
, "com.example"
, "com.floors42.package"
, "ball8.ball8.ball8ball"
'org.apache.mobilespec',
'com.example',
'com.floors42.package',
'ball8.ball8.ball8ball'
];
var invalid = [
""
, "com.class.is.bad"
, "0com.example.mobilespec"
, "c-m.e@a!p%e.mobilespec"
, "notenoughdots"
, ".starts.with.a.dot"
, "ends.with.a.dot."
, "_underscore.anything"
, "underscore._something"
, "_underscore._all._the._things"
, "8.ball"
, "8ball.ball"
, "ball8.8ball"
, "ball8.com.8ball"
'',
'com.class.is.bad',
'0com.example.mobilespec',
'c-m.e@a!p%e.mobilespec',
'notenoughdots',
'.starts.with.a.dot',
'ends.with.a.dot.',
'_underscore.anything',
'underscore._something',
'_underscore._all._the._things',
'8.ball',
'8ball.ball',
'ball8.8ball',
'ball8.com.8ball'
];
valid.forEach(function (package_name) {
it("Test#001 : should accept " + package_name, function(done) {
return create.validatePackageName(package_name)
.then(function() {
it('Test#001 : should accept ' + package_name, function (done) {
return create.validatePackageName(package_name).then(function () {
// resolved
done();
}).fail(function (err) {
@ -58,9 +56,8 @@ describe("create", function () {
});
invalid.forEach(function (package_name) {
it("Test#002 : should reject " + package_name, function(done) {
return create.validatePackageName(package_name)
.then(function() {
it('Test#002 : should reject ' + package_name, function (done) {
return create.validatePackageName(package_name).then(function () {
// shouldn't be here
expect(true).toBe(false);
}).fail(function (err) {
@ -70,23 +67,22 @@ describe("create", function () {
});
});
});
describe("validateProjectName", function() {
describe('validateProjectName', function () {
var valid = [
"mobilespec"
, "package_name"
, "PackageName"
, "CordovaLib"
'mobilespec',
'package_name',
'PackageName',
'CordovaLib'
];
var invalid = [
""
, "0startswithdigit"
, "CordovaActivity"
'',
'0startswithdigit',
'CordovaActivity'
];
valid.forEach(function (project_name) {
it("Test#003 : should accept " + project_name, function(done) {
return create.validateProjectName(project_name)
.then(function() {
it('Test#003 : should accept ' + project_name, function (done) {
return create.validateProjectName(project_name).then(function () {
// resolved
done();
}).fail(function (err) {
@ -96,9 +92,8 @@ describe("create", function () {
});
invalid.forEach(function (project_name) {
it("Test#004 : should reject " + project_name, function(done) {
return create.validateProjectName(project_name)
.then(function() {
it('Test#004 : should reject ' + project_name, function (done) {
return create.validateProjectName(project_name).then(function () {
// shouldn't be here
expect(true).toBe(false);
}).fail(function (err) {
@ -109,4 +104,3 @@ describe("create", function () {
});
});
});

View File

@ -16,26 +16,26 @@
specific language governing permissions and limitations
under the License.
*/
var emu = require("../../bin/templates/cordova/lib/emulator");
var superspawn = require("cordova-common").superspawn;
var Q = require("q");
var fs = require("fs");
var path = require("path");
var shelljs = require("shelljs");
describe("emulator", function () {
describe("list_images_using_avdmanager", function() {
it("should properly parse details of SDK Tools 25.3.1 `avdmanager` output", function(done) {
var emu = require('../../bin/templates/cordova/lib/emulator');
var superspawn = require('cordova-common').superspawn;
var Q = require('q');
var fs = require('fs');
var path = require('path');
var shelljs = require('shelljs');
describe('emulator', function () {
describe('list_images_using_avdmanager', function () {
it('should properly parse details of SDK Tools 25.3.1 `avdmanager` output', function (done) {
var deferred = Q.defer();
spyOn(superspawn, "spawn").and.returnValue(deferred.promise);
deferred.resolve(fs.readFileSync(path.join("spec", "fixtures", "sdk25.3-avdmanager_list_avd.txt"), "utf-8"));
return emu.list_images_using_avdmanager()
.then(function(list) {
spyOn(superspawn, 'spawn').and.returnValue(deferred.promise);
deferred.resolve(fs.readFileSync(path.join('spec', 'fixtures', 'sdk25.3-avdmanager_list_avd.txt'), 'utf-8'));
return emu.list_images_using_avdmanager().then(function (list) {
expect(list).toBeDefined();
expect(list[0].name).toEqual("nexus5-5.1");
expect(list[0].target).toEqual("Android 5.1 (API level 22)");
expect(list[1].device).toEqual("pixel (Google)");
expect(list[2].abi).toEqual("default/x86_64");
expect(list[0].name).toEqual('nexus5-5.1');
expect(list[0].target).toEqual('Android 5.1 (API level 22)');
expect(list[1].device).toEqual('pixel (Google)');
expect(list[2].abi).toEqual('default/x86_64');
}).fail(function (err) {
expect(err).toBeUndefined();
}).fin(function () {
@ -43,26 +43,25 @@ describe("emulator", function () {
});
});
});
describe("list_images_using_android", function() {
it("should invoke `android` with the `list avd` command and _not_ the `list avds` command, as the plural form is not supported in some Android SDK Tools versions", function() {
describe('list_images_using_android', function () {
it('should invoke `android` with the `list avd` command and _not_ the `list avds` command, as the plural form is not supported in some Android SDK Tools versions', function () {
var deferred = Q.defer();
spyOn(superspawn, "spawn").and.returnValue(deferred.promise);
spyOn(superspawn, 'spawn').and.returnValue(deferred.promise);
emu.list_images_using_android();
expect(superspawn.spawn).toHaveBeenCalledWith("android", ["list", "avd"]);
expect(superspawn.spawn).toHaveBeenCalledWith('android', ['list', 'avd']);
});
it("should properly parse details of SDK Tools pre-25.3.1 `android list avd` output", function(done) {
it('should properly parse details of SDK Tools pre-25.3.1 `android list avd` output', function (done) {
var deferred = Q.defer();
spyOn(superspawn, "spawn").and.returnValue(deferred.promise);
deferred.resolve(fs.readFileSync(path.join("spec", "fixtures", "sdk25.2-android_list_avd.txt"), "utf-8"));
return emu.list_images_using_android()
.then(function(list) {
spyOn(superspawn, 'spawn').and.returnValue(deferred.promise);
deferred.resolve(fs.readFileSync(path.join('spec', 'fixtures', 'sdk25.2-android_list_avd.txt'), 'utf-8'));
return emu.list_images_using_android().then(function (list) {
expect(list).toBeDefined();
expect(list[0].name).toEqual("QWR");
expect(list[0].device).toEqual("Nexus 5 (Google)");
expect(list[0].path).toEqual("/Users/shazron/.android/avd/QWR.avd");
expect(list[0].target).toEqual("Android 7.1.1 (API level 25)");
expect(list[0].abi).toEqual("google_apis/x86_64");
expect(list[0].skin).toEqual("1080x1920");
expect(list[0].name).toEqual('QWR');
expect(list[0].device).toEqual('Nexus 5 (Google)');
expect(list[0].path).toEqual('/Users/shazron/.android/avd/QWR.avd');
expect(list[0].target).toEqual('Android 7.1.1 (API level 25)');
expect(list[0].abi).toEqual('google_apis/x86_64');
expect(list[0].skin).toEqual('1080x1920');
}).fail(function (err) {
expect(err).toBeUndefined();
}).fin(function () {
@ -70,42 +69,41 @@ describe("emulator", function () {
});
});
});
describe("list_images", function() {
describe('list_images', function () {
beforeEach(function () {
spyOn(fs, "realpathSync").and.callFake(function(cmd) {
spyOn(fs, 'realpathSync').and.callFake(function (cmd) {
return cmd;
});
});
it("should try to parse AVD information using `avdmanager` first", function() {
spyOn(shelljs, "which").and.callFake(function(cmd) {
if (cmd == "avdmanager") {
it('should try to parse AVD information using `avdmanager` first', function () {
spyOn(shelljs, 'which').and.callFake(function (cmd) {
if (cmd === 'avdmanager') {
return true;
} else {
return false;
}
});
var avdmanager_spy = spyOn(emu, "list_images_using_avdmanager").and.returnValue({catch:function(){}});
var avdmanager_spy = spyOn(emu, 'list_images_using_avdmanager').and.returnValue({catch: function () {}});
emu.list_images();
expect(avdmanager_spy).toHaveBeenCalled();
});
it("should delegate to `android` if `avdmanager` cant be found and `android` can", function() {
spyOn(shelljs, "which").and.callFake(function(cmd) {
if (cmd == "avdmanager") {
it('should delegate to `android` if `avdmanager` cant be found and `android` can', function () {
spyOn(shelljs, 'which').and.callFake(function (cmd) {
if (cmd === 'avdmanager') {
return false;
} else {
return true;
}
});
var android_spy = spyOn(emu, "list_images_using_android");
var android_spy = spyOn(emu, 'list_images_using_android');
emu.list_images();
expect(android_spy).toHaveBeenCalled();
});
it("should throw an error if neither `avdmanager` nor `android` are able to be found", function(done) {
spyOn(shelljs, "which").and.returnValue(false);
return emu.list_images()
.catch(function(err) {
it('should throw an error if neither `avdmanager` nor `android` are able to be found', function (done) {
spyOn(shelljs, 'which').and.returnValue(false);
return emu.list_images().catch(function (err) {
expect(err).toBeDefined();
expect(err.message).toContain("Could not find either `android` or `avdmanager`");
expect(err.message).toContain('Could not find either `android` or `avdmanager`');
done();
});
});

View File

@ -48,8 +48,8 @@ describe('common platform handler', function() {
shell.mkdir('-p', project_dir);
fs.writeFileSync(non_plugin_file, 'contents', 'utf-8');
var outside_file = '../non_plugin_file';
expect(function(){copyFile(test_dir, outside_file, project_dir, dest);}).
toThrow(new Error('File "' + path.resolve(test_dir, outside_file) + '" is located outside the plugin directory "' + test_dir + '"'));
expect(function () { copyFile(test_dir, outside_file, project_dir, dest); })
.toThrow(new Error('File "' + path.resolve(test_dir, outside_file) + '" is located outside the plugin directory "' + test_dir + '"'));
shell.rm('-rf', test_dir);
});
@ -75,16 +75,16 @@ describe('common platform handler', function() {
return;
}
expect(function(){copyFile(test_dir, symlink_file, project_dir, dest);}).
toThrow(new Error('File "' + path.resolve(test_dir, symlink_file) + '" is located outside the plugin directory "' + test_dir + '"'));
expect(function () { copyFile(test_dir, symlink_file, project_dir, dest); })
.toThrow(new Error('File "' + path.resolve(test_dir, symlink_file) + '" is located outside the plugin directory "' + test_dir + '"'));
shell.rm('-rf', project_dir);
});
it('Test#005 : should throw if dest is outside the project directory', function () {
shell.mkdir('-p', java_dir);
fs.writeFileSync(java_file, 'contents', 'utf-8');
expect(function(){copyFile(test_dir, java_file, project_dir, non_plugin_file);}).
toThrow(new Error('Destination "' + path.resolve(project_dir, non_plugin_file) + '" for source file "' + path.resolve(test_dir, java_file) + '" is located outside the project'));
expect(function () { copyFile(test_dir, java_file, project_dir, non_plugin_file); })
.toThrow(new Error('Destination "' + path.resolve(project_dir, non_plugin_file) + '" for source file "' + path.resolve(test_dir, java_file) + '" is located outside the project'));
shell.rm('-rf', project_dir);
});
@ -121,8 +121,8 @@ describe('common platform handler', function() {
describe('copyNewFile', function () {
it('Test#008 : should throw if target path exists', function () {
shell.mkdir('-p', dest);
expect(function(){copyNewFile(test_dir, src, project_dir, dest);}).
toThrow(new Error('"' + dest + '" already exists!'));
expect(function () { copyNewFile(test_dir, src, project_dir, dest); })
.toThrow(new Error('"' + dest + '" already exists!'));
shell.rm('-rf', dest);
});
});

View File

@ -34,9 +34,9 @@ var PluginInfo = require('cordova-common').PluginInfo;
var AndroidProject = require('../../../bin/templates/cordova/lib/AndroidProject');
var dummyPluginInfo = new PluginInfo(dummyplugin);
var valid_source = dummyPluginInfo.getSourceFiles('android'),
valid_resources = dummyPluginInfo.getResourceFiles('android'),
valid_libs = dummyPluginInfo.getLibFiles('android');
var valid_source = dummyPluginInfo.getSourceFiles('android');
var valid_resources = dummyPluginInfo.getResourceFiles('android');
var valid_libs = dummyPluginInfo.getLibFiles('android');
var faultyPluginInfo = new PluginInfo(faultyplugin);
var invalid_source = faultyPluginInfo.getSourceFiles('android');
@ -198,7 +198,8 @@ describe('android project handler', function() {
describe('of <asset> elements', function () {
var asset = {src: 'www/dummyPlugin.js', target: 'foo/dummy.js'};
var wwwDest, platformWwwDest;
var wwwDest; /* eslint no-unused-vars: "off" */
var platformWwwDest; /* eslint no-unused-vars: "off" */
beforeEach(function () {
wwwDest = path.resolve(dummyProject.www, asset.target);
@ -321,10 +322,10 @@ describe('android project handler', function() {
});
});
describe('of <js-module> elements', function () {
var jsModule = {src: 'www/dummyPlugin.js'};
var wwwDest, platformWwwDest;
var wwwDest;
var platformWwwDest;
beforeEach(function () {
wwwDest = path.resolve(dummyProject.www, 'plugins', dummyPluginInfo.id, jsModule.src);

View File

@ -17,21 +17,21 @@
under the License.
*/
var rewire = require("rewire");
var run = rewire("../../bin/templates/cordova/lib/run");
var getInstallTarget = run.__get__("getInstallTarget");
var rewire = require('rewire');
var run = rewire('../../bin/templates/cordova/lib/run');
var getInstallTarget = run.__get__('getInstallTarget');
describe("run", function () {
describe("getInstallTarget", function() {
var targetOpts = { target: "emu" };
describe('run', function () {
describe('getInstallTarget', function () {
var targetOpts = { target: 'emu' };
var deviceOpts = { device: true };
var emulatorOpts = { emulator: true };
var emptyOpts = {};
it("Test#001 : should select correct target based on the run opts", function() {
expect(getInstallTarget(targetOpts)).toBe("emu");
expect(getInstallTarget(deviceOpts)).toBe("--device");
expect(getInstallTarget(emulatorOpts)).toBe("--emulator");
it('Test#001 : should select correct target based on the run opts', function () {
expect(getInstallTarget(targetOpts)).toBe('emu');
expect(getInstallTarget(deviceOpts)).toBe('--device');
expect(getInstallTarget(emulatorOpts)).toBe('--emulator');
expect(getInstallTarget(emptyOpts)).toBeUndefined();
});
});