diff --git a/spec/plugman/install.spec.js b/spec/plugman/install.spec.js
index 7d9ca8880..cd5703449 100644
--- a/spec/plugman/install.spec.js
+++ b/spec/plugman/install.spec.js
@@ -27,6 +27,7 @@ var events = require('cordova-common').events;
var plugman = require('../../src/plugman/plugman');
var platforms = require('../../src/plugman/platforms/common');
var knownPlatforms = require('../../src/platforms/platforms');
+var cordovaUtil = require('../../src/cordova/util');
var common = require('../common');
var fs = require('fs');
var os = require('os');
@@ -287,15 +288,12 @@ describe('install', function () {
.fin(function () {
var plugmanVersion = require('../../package.json').version.replace(/-dev|-nightly.*$/, '');
var cordovaVersion = require('../../package.json').version.replace(/-dev|-nightly.*$/, '');
- expect(satisfies.calls.count()).toBe(4);
+ // var megaFun = require('../../package.json').version.replace(/-dev|-nightly.*$/, '');
+ expect(satisfies.calls.count()).toBe(2);
//
expect(satisfies.calls.argsFor(0)).toEqual([ cordovaVersion, '>=2.3.0', true ]);
//
expect(satisfies.calls.argsFor(1)).toEqual([ plugmanVersion, '>=0.10.0', true ]);
- //
- expect(satisfies.calls.argsFor(2)).toEqual([ null, '>=1.0.0', true ]);
- //
- expect(satisfies.calls.argsFor(3)).toEqual([ null, '>=3.0.0', true ]);
done();
});
}, TIMEOUT);
@@ -543,3 +541,67 @@ describe('end', function () {
shell.rm('-rf', temp_dir);
}, TIMEOUT);
});
+
+describe('unit tests for checkEngines', function () {
+ var fail;
+ var engine = [ { platform: 'android',
+ minVersion: '>=3.6.0',
+ currentVersion: '6.2.3' } ];
+ beforeEach(function () {
+ spyOn(semver, 'satisfies');
+ });
+
+ it('checkEngines should return true', function () {
+ spyOn(fs, 'existsSync').and.returnValue(false);
+ semver.satisfies.and.returnValue(true);
+ install.checkEngines(engine, 'pluginDir')
+ .then(function (res) {
+ expect(res).toBe(true);
+ }).fail(function err (errMsg) {
+ fail('fail handler unexpectedly invoked');
+ console.error(errMsg);
+ });
+ });
+
+ it('checkEngines should check cordovaDependencies', function () {
+ var pkgJson = { engines: { cordovaDependencies: { '9.0.0': [Object], '2.0.0': [Object] } } };
+ spyOn(fs, 'existsSync').and.returnValue(true);
+ spyOn(cordovaUtil, 'requireNoCache').and.returnValue(pkgJson);
+ semver.satisfies.and.callThrough();
+ install.checkEngines(engine, 'pluginDir')
+ .then(function (res) {
+ expect(res).toBe(true);
+ expect(semver.satisfies).toHaveBeenCalledWith('6.2.3', '>=3.6.0', true);
+ }).fail(function err (errMsg) {
+ fail('fail handler unexpectedly invoked');
+ console.error(errMsg);
+ });
+ });
+
+ it('checkEngines should check if plugin version is supported', function () {
+ spyOn(fs, 'existsSync').and.returnValue(true);
+ spyOn(cordovaUtil, 'requireNoCache').and.returnValue(true);
+ semver.satisfies.and.callThrough();
+ install.checkEngines(engine, 'pluginDir')
+ .then(function (res) {
+ expect(res).toBe(true);
+ expect(semver.satisfies).toHaveBeenCalledWith('6.2.3', '>=3.6.0', true);
+ }).fail(function err (errMsg) {
+ fail('fail handler unexpectedly invoked');
+ console.error(errMsg);
+ });
+ });
+
+ it('checkEngines should warn if plugin is not supported', function () {
+ spyOn(events, 'emit');
+ spyOn(Q, 'reject').and.callThrough();
+ semver.satisfies.and.returnValue(false);
+ install.checkEngines(engine, 'pluginDir')
+ .then(function (res) {
+ fail('success handler unexpectedly invoked');
+ }).fail(function err (errMsg) {
+ expect(errMsg).toBe('skip');
+ expect(events.emit).toHaveBeenCalledWith('warn', jasmine.stringMatching(/failed version requirement/));
+ });
+ });
+});
diff --git a/src/plugman/install.js b/src/plugman/install.js
index 51c6baf74..c54c0d331 100644
--- a/src/plugman/install.js
+++ b/src/plugman/install.js
@@ -100,33 +100,54 @@ function possiblyFetch (id, plugins_dir, options) {
return require('./plugman').fetch(id, plugins_dir, opts);
}
-function checkEngines (engines) {
+function checkEngines (engines, plugin_dir) {
+ var plugin_pkgJson_path = path.join(plugin_dir, 'package.json');
+ var plugin_pkgJson;
+
+ if (fs.existsSync(plugin_pkgJson_path)) {
+ plugin_pkgJson = cordovaUtil.requireNoCache(plugin_pkgJson_path);
+ }
for (var i = 0; i < engines.length; i++) {
var engine = engines[i];
-
- // This is a hack to allow plugins with tag to be installed with
- // engine with '-dev' or '-nightly' suffixes. It is required due to new semver range logic,
- // introduced in semver@3.x. For more details see https://github.com/npm/node-semver#prerelease-tags.
- //
- // This may lead to false-positive checks, when engine version with dropped
- // suffix is equal to one of range bounds, for example: 5.1.0-dev >= 5.1.0.
- // However this shouldn't be a problem, because this only should happen in dev workflow.
- engine.currentVersion = engine.currentVersion && engine.currentVersion.replace(/-dev|-nightly.*$/, '');
- if (semver.satisfies(engine.currentVersion, engine.minVersion, /* loose= */true) || engine.currentVersion === null) {
- continue; // engine ok!
- } else {
- var msg = 'Plugin doesn\'t support this project\'s ' + engine.name + ' version. ' +
- engine.name + ': ' + engine.currentVersion +
- ', failed version requirement: ' + engine.minVersion;
- events.emit('warn', msg);
- return Q.reject('skip');
+ if (engine && engine.currentVersion) {
+ if (plugin_pkgJson && plugin_pkgJson.engines && plugin_pkgJson.engines.cordovaDependencies) {
+ for (var key in plugin_pkgJson.engines.cordovaDependencies) {
+ if (plugin_pkgJson.engines.cordovaDependencies.hasOwnProperty(key)) {
+ if (((key < engine.currentVersion) || (key === engine.currentVersion)) && (plugin_pkgJson.engines.cordovaDependencies[key])) {
+ var plugin_pkgJson_min = plugin_pkgJson.engines.cordovaDependencies[key];
+ if (plugin_pkgJson_min[engine.name]) {
+ engine.minVersion = plugin_pkgJson_min[engine.name];
+ }
+ }
+ }
+ }
+ // This is a hack to allow plugins with tag to be installed with
+ // engine with '-dev' or '-nightly' suffixes. It is required due to new semver range logic,
+ // introduced in semver@3.x. For more details see https://github.com/npm/node-semver#prerelease-tags.
+ //
+ // This may lead to false-positive checks, when engine version with dropped
+ // suffix is equal to one of range bounds, for example: 5.1.0-dev >= 5.1.0.
+ // However this shouldn't be a problem, because this only should happen in dev workflow.
+ }
+ engine.currentVersion = engine.currentVersion && engine.currentVersion.replace(/-dev|-nightly.*$/, '');
+ if (semver.satisfies(engine.currentVersion, engine.minVersion, /* loose= */true) || engine.currentVersion === null) {
+ continue; // engine ok!
+ } else {
+ var msg = 'Plugin doesn\'t support this project\'s ' + engine.name + ' version. ' +
+ engine.name + ': ' + engine.currentVersion +
+ ', failed version requirement: ' + engine.minVersion;
+ events.emit('warn', msg);
+ return Q.reject('skip');
+ }
}
}
return Q(true);
}
+module.exports.checkEngines = checkEngines;
+
function cleanVersionOutput (version, name) {
var out = version.trim();
var rc_index = out.indexOf('rc');
@@ -310,7 +331,7 @@ function runInstall (actions, platform, project_dir, plugin_dir, plugins_dir, op
options.platformVersion = platformVersion;
return callEngineScripts(theEngines, path.resolve(plugins_dir, '..'));
}).then(function (engines) {
- return checkEngines(engines);
+ return module.exports.checkEngines(engines, plugin_dir);
}).then(function () {
filtered_variables = variableMerge.mergeVariables(plugin_dir, platform, options);
install.filtered_variables = filtered_variables;