(un)install specs. start of refactor
Project: http://git-wip-us.apache.org/repos/asf/cordova-plugman/repo Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugman/commit/c000040e Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugman/tree/c000040e Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugman/diff/c000040e Branch: refs/heads/master Commit: c000040e05a641423f38056a93d5cc45df343f83 Parents: 63400f3 Author: Fil Maj <[email protected]> Authored: Mon Apr 22 11:45:01 2013 -0700 Committer: Fil Maj <[email protected]> Committed: Mon Apr 22 11:45:01 2013 -0700 ---------------------------------------------------------------------- spec/prepare.spec.js | 7 -- spec/uninstall.spec.js | 85 +++++++++++++++++ src/platforms/android.js | 2 +- src/platforms/common.js | 5 + src/uninstall.js | 3 +- src/util/plugins.js | 157 ++++++++++++++++---------------- src/util/test-helpers.js | 26 ----- src/util/xml-helpers.js | 203 +++++++++++++++++++++-------------------- 8 files changed, 275 insertions(+), 213 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/c000040e/spec/common.spec.js ---------------------------------------------------------------------- diff --git a/spec/common.spec.js b/spec/common.spec.js new file mode 100644 index 0000000..e69de29 http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/c000040e/spec/platforms/android.spec.js ---------------------------------------------------------------------- diff --git a/spec/platforms/android.spec.js b/spec/platforms/android.spec.js new file mode 100644 index 0000000..e69de29 http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/c000040e/spec/platforms/blackberry.spec.js ---------------------------------------------------------------------- diff --git a/spec/platforms/blackberry.spec.js b/spec/platforms/blackberry.spec.js new file mode 100644 index 0000000..e69de29 http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/c000040e/spec/platforms/ios.spec.js ---------------------------------------------------------------------- diff --git a/spec/platforms/ios.spec.js b/spec/platforms/ios.spec.js new file mode 100644 index 0000000..e69de29 http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/c000040e/spec/prepare.spec.js ---------------------------------------------------------------------- diff --git a/spec/prepare.spec.js b/spec/prepare.spec.js index 494b8c5..8d03778 100644 --- a/spec/prepare.spec.js +++ b/spec/prepare.spec.js @@ -1,8 +1,4 @@ var prepare = require('../src/prepare'), - android = require('../src/platforms/android'), - ios = require('../src/platforms/ios'), - blackberry = require('../src/platforms/blackberry'), - plugman = require('../plugman'), fs = require('fs'), os = require('osenv'), path = require('path'), @@ -11,10 +7,7 @@ var prepare = require('../src/prepare'), childbrowser = path.join(__dirname, 'plugins', 'ChildBrowser'), dummyplugin = path.join(__dirname, 'plugins', 'DummyPlugin'), androidplugin = path.join(__dirname, 'plugins', 'AndroidJS'), - faultyplugin = path.join(__dirname, 'plugins', 'FaultyPlugin'), android_one_project = path.join(__dirname, 'projects', 'android_one', '*'); - blackberry_project = path.join(__dirname, 'projects', 'blackberry', '*'); - ios_project = path.join(__dirname, 'projects', 'ios-config-xml', '*'); plugins_dir = path.join(temp, 'cordova', 'plugins'); describe('prepare', function() { http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/c000040e/spec/uninstall.spec.js ---------------------------------------------------------------------- diff --git a/spec/uninstall.spec.js b/spec/uninstall.spec.js index e69de29..bf2f9d3 100644 --- a/spec/uninstall.spec.js +++ b/spec/uninstall.spec.js @@ -0,0 +1,85 @@ +var uninstall = require('../src/uninstall'), + install = require('../src/install'), + android = require('../src/platforms/android'), + ios = require('../src/platforms/ios'), + blackberry = require('../src/platforms/blackberry'), + plugman = require('../plugman'), + fs = require('fs'), + os = require('osenv'), + path = require('path'), + shell = require('shelljs'), + temp = path.join(os.tmpdir(), 'plugman'), + childbrowser = path.join(__dirname, 'plugins', 'ChildBrowser'), + dummyplugin = path.join(__dirname, 'plugins', 'DummyPlugin'), + variableplugin = path.join(__dirname, 'plugins', 'VariablePlugin'), + faultyplugin = path.join(__dirname, 'plugins', 'FaultyPlugin'), + android_one_project = path.join(__dirname, 'projects', 'android_one', '*'); + blackberry_project = path.join(__dirname, 'projects', 'blackberry', '*'); + ios_project = path.join(__dirname, 'projects', 'ios-config-xml', '*'); + plugins_dir = path.join(temp, 'cordova', 'plugins'); + +describe('uninstall', function() { + var copied_plugin_path = path.join(temp,'ChildBrowser'); + + beforeEach(function() { + shell.mkdir('-p', temp); + shell.mkdir('-p', plugins_dir); + }); + afterEach(function() { + shell.rm('-rf', temp); + }); + + describe('success', function() { + it('on an Android project should call into Android module\'s handleUninstall', function() { + // Set up android project w/ one plugin + shell.cp('-rf', android_one_project, temp); + shell.cp('-rf', dummyplugin, plugins_dir); + install('android', temp, 'DummyPlugin', plugins_dir, {}); + + var s = spyOn(android, 'handleUninstall'); + uninstall('android', temp, 'DummyPlugin', plugins_dir, {}); + expect(s).toHaveBeenCalled(); + }); + it('on a BlackBerry project should call into BlackBerry module\'s handleUninstall', function() { + // Set up blackberry project w/ one plugin + shell.cp('-rf', blackberry_project, temp); + shell.cp('-rf', dummyplugin, plugins_dir); + install('blackberry', temp, 'DummyPlugin', plugins_dir, {}); + + var s = spyOn(blackberry, 'handleUninstall'); + uninstall('blackberry', temp, 'DummyPlugin', plugins_dir, {}); + expect(s).toHaveBeenCalled(); + }); + it('on an iOS project should call into iOS module\'s handleUninstall', function() { + // Set up ios project w/ one plugin + shell.cp('-rf', ios_project, temp); + shell.cp('-rf', dummyplugin, plugins_dir); + install('ios', temp, 'DummyPlugin', plugins_dir, {}); + + var s = spyOn(ios, 'handleUninstall'); + uninstall('ios', temp, 'DummyPlugin', plugins_dir, {}); + expect(s).toHaveBeenCalled(); + }); + }); + + describe('failure', function() { + beforeEach(function() { + shell.cp('-rf', android_one_project, temp); + shell.cp('-rf', dummyplugin, plugins_dir); + install('android', temp, 'DummyPlugin', plugins_dir, {}); + }); + afterEach(function() { + shell.rm('-rf', temp); + }); + it('should throw if platform is unrecognized', function() { + expect(function() { + uninstall('atari', temp, 'SomePlugin', plugins_dir, {}); + }).toThrow('atari not supported.'); + }); + it('should throw if the plugin was not found', function() { + expect(function() { + uninstall('android', temp, 'SomePlugin', plugins_dir, {}); + }).toThrow('Plugin "SomePlugin" not found. Already uninstalled?'); + }); + }); +}); http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/c000040e/spec/util/plugins.spec.js ---------------------------------------------------------------------- diff --git a/spec/util/plugins.spec.js b/spec/util/plugins.spec.js new file mode 100644 index 0000000..e69de29 http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/c000040e/spec/util/xml-helpers.spec.js ---------------------------------------------------------------------- diff --git a/spec/util/xml-helpers.spec.js b/spec/util/xml-helpers.spec.js new file mode 100644 index 0000000..e69de29 http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/c000040e/src/platforms/android.js ---------------------------------------------------------------------- diff --git a/src/platforms/android.js b/src/platforms/android.js index f8dd640..90a828a 100644 --- a/src/platforms/android.js +++ b/src/platforms/android.js @@ -84,7 +84,7 @@ function handlePlugin(action, project_dir, plugin_dir, plugin_et, variables) { action = action.replace('force-', ''); } - root = et.Element("config-file"); + var root = et.Element("config-file"); root.attrib['parent'] = '.' plugin_et.findall('./access').forEach(function (tag) { root.append(tag); http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/c000040e/src/platforms/common.js ---------------------------------------------------------------------- diff --git a/src/platforms/common.js b/src/platforms/common.js new file mode 100644 index 0000000..24f3ea5 --- /dev/null +++ b/src/platforms/common.js @@ -0,0 +1,5 @@ + + +module.exports = { + +}; http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/c000040e/src/uninstall.js ---------------------------------------------------------------------- diff --git a/src/uninstall.js b/src/uninstall.js index 5befe83..2625c44 100644 --- a/src/uninstall.js +++ b/src/uninstall.js @@ -41,7 +41,7 @@ module.exports = function uninstallPlugin(platform, project_dir, name, plugins_d var plugin_xml_path = path.join(plugin_dir, 'plugin.xml'); if (!fs.existsSync(plugin_dir)) { - var err = new Error('Plugin ' + name + ' not found. Already uninstalled?'); + var err = new Error('Plugin "' + name + '" not found. Already uninstalled?'); if (callback) { callback(err); return; @@ -49,6 +49,7 @@ module.exports = function uninstallPlugin(platform, project_dir, name, plugins_d else throw err; } + // TODO: uninstall if plugin does not exist? this should not be here. if (!fs.existsSync(plugin_xml_path)) { // try querying the plugin database plugins.getPluginInfo(plugin_dir, http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/c000040e/src/util/plugins.js ---------------------------------------------------------------------- diff --git a/src/util/plugins.js b/src/util/plugins.js index 847f427..242cb1c 100644 --- a/src/util/plugins.js +++ b/src/util/plugins.js @@ -26,94 +26,97 @@ var http = require('http'), shell = require('shelljs'), remote = require(path.join(__dirname, '..', '..', 'config', 'remote')); -// Fetches plugin information from remote server -exports.getPluginInfo = function(plugin_name, callback) { - var responded = false; - http.get(remote.url + util.format(remote.query_path, plugin_name), function(res) { - var str = ''; - res.on('data', function (chunk) { - str += chunk; +module.exports = { + // Fetches plugin information from remote server + getPluginInfo:function(plugin_name, callback) { + var responded = false; + http.get(remote.url + util.format(remote.query_path, plugin_name), function(res) { + var str = ''; + res.on('data', function (chunk) { + str += chunk; + }); + res.on('end', function () { + responded = true; + var response, plugin_info; + if((response = JSON.parse(str)).rows.length == 1) { + plugin_info = response.rows[0].value; + callback(null, plugin_info); + } else { + callback("Could not find information on "+plugin_name+" plugin"); + } + }); + + }).on('error', function(e) { + callback(e); }); - res.on('end', function () { - responded = true; - var response, plugin_info; - if((response = JSON.parse(str)).rows.length == 1) { - plugin_info = response.rows[0].value; - callback(null, plugin_info); - } else { - callback("Could not find information on "+plugin_name+" plugin"); + + setTimeout(function() { + if (!responded) { + console.log('timed out'); + error('timed out') } + }, 3000); + }, + listAllPlugins:function(success, error) { + http.get(remote.url + remote.list_path, function(res) { + var str = ''; + res.on('data', function (chunk) { + str += chunk; + }); + res.on('end', function () { + var plugins = (JSON.parse(str)).rows; + success(plugins); + }); + + }).on('error', function(e) { + console.log("Got error: " + e.message); + error(e.message); }); + }, + clonePluginGitRepo:function(plugin_git_url, plugins_dir, callback) { + if(!shell.which('git')) { + var err = new Error('git command line is not installed'); + if (callback) callback(err); + else throw err; + } + // use osenv to get a temp directory in a portable way + var lastSlash = plugin_git_url.lastIndexOf('/'); + var basename = plugin_git_url.substring(lastSlash+1); + var dotGitIndex = basename.lastIndexOf('.git'); + if (dotGitIndex >= 0) { + basename = basename.substring(0, dotGitIndex); + } - }).on('error', function(e) { - callback(e); - }); + var plugin_dir = path.join(plugins_dir, basename); - setTimeout(function() { - if (!responded) { - console.log('timed out'); - error('timed out') + // trash it if it already exists (something went wrong before probably) + if(fs.existsSync(plugin_dir)) { + shell.rm('-rf', plugin_dir); } - }, 3000); -} -exports.listAllPlugins = function(success, error) { - http.get(remote.url + remote.list_path, function(res) { - var str = ''; - res.on('data', function (chunk) { - str += chunk; - }); - res.on('end', function () { - var plugins = (JSON.parse(str)).rows; - success(plugins); - }); - - }).on('error', function(e) { - console.log("Got error: " + e.message); - error(e.message); - }); -} - -exports.clonePluginGitRepo = function(plugin_git_url, plugins_dir, callback) { - if(!shell.which('git')) { - var err = new Error('git command line is not installed'); - if (callback) callback(err); - else throw err; - } - // use osenv to get a temp directory in a portable way - var lastSlash = plugin_git_url.lastIndexOf('/'); - var basename = plugin_git_url.substring(lastSlash+1); - var dotGitIndex = basename.lastIndexOf('.git'); - if (dotGitIndex >= 0) { - basename = basename.substring(0, dotGitIndex); + shell.exec('git clone ' + plugin_git_url + ' ' + plugin_dir + ' 2>&1 1>/dev/null', {silent: true, async:true}, function(code, output) { + if (code > 0) { + var err = new Error('failed to get the plugin via git from URL '+ plugin_git_url); + if (callback) callback(err) + else throw err; + } else { + if (callback) callback(null); + } + }); } + // TODO add method for archives and other formats + // extractArchive:function(plugin_dir) { + // } - var plugin_dir = path.join(plugins_dir, basename); + // TODO add method to publish plugin from cli + // publishPlugin:function(plugin_dir) { + // } - // trash it if it already exists (something went wrong before probably) - if(fs.existsSync(plugin_dir)) { - shell.rm('-rf', plugin_dir); - } + // TODO add method to unpublish plugin from cli + // unpublishPlugin:function(plugin_dir) { + // } +}; - shell.exec('git clone ' + plugin_git_url + ' ' + plugin_dir + ' 2>&1 1>/dev/null', {silent: true, async:true}, function(code, output) { - if (code > 0) { - var err = new Error('failed to get the plugin via git from URL '+ plugin_git_url); - if (callback) callback(err) - else throw err; - } else { - if (callback) callback(null); - } - }); -} -// TODO add method for archives and other formats -// exports.extractArchive = function(plugin_dir) { -// } -// TODO add method to publish plugin from cli -// exports.publishPlugin = function(plugin_dir) { -// } -// TODO add method to unpublish plugin from cli -// exports.unpublishPlugin = function(plugin_dir) { -// } http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/c000040e/src/util/test-helpers.js ---------------------------------------------------------------------- diff --git a/src/util/test-helpers.js b/src/util/test-helpers.js deleted file mode 100644 index d83f56a..0000000 --- a/src/util/test-helpers.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. -*/ - -exports.suppressOutput = function(f) { - var backupLog = console.log; - console.log = function() { } - f(); - console.log = backupLog; -}; - http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/c000040e/src/util/xml-helpers.js ---------------------------------------------------------------------- diff --git a/src/util/xml-helpers.js b/src/util/xml-helpers.js index 1197604..af38eee 100644 --- a/src/util/xml-helpers.js +++ b/src/util/xml-helpers.js @@ -25,125 +25,126 @@ var fs = require('fs') , path = require('path') , et = require('elementtree'); -exports.moveProjFile = function(origFile, projPath, callback) { - var src = path.resolve(projPath, origFile) - , dest = src.replace('.orig', ''); - - fs.createReadStream(src) - .pipe(fs.createWriteStream(dest)) - .on('close', callback); -} - -// compare two et.XML nodes, see if they match -// compares tagName, text, attributes and children (recursively) -exports.equalNodes = function(one, two) { - if (one.tag != two.tag) { - return false; - } else if (one.text.trim() != two.text.trim()) { - return false; - } else if (one._children.length != two._children.length) { - return false; - } - - var oneAttribKeys = Object.keys(one.attrib), - twoAttribKeys = Object.keys(two.attrib), - i = 0, attribName; - - if (oneAttribKeys.length != twoAttribKeys.length) { - return false; - } - - for (i; i < oneAttribKeys.length; i++) { - attribName = oneAttribKeys[i]; - - if (one.attrib[attribName] != two.attrib[attribName]) { +module.exports = { + moveProjFile: function(origFile, projPath, callback) { + var src = path.resolve(projPath, origFile) + , dest = src.replace('.orig', ''); + + fs.createReadStream(src) + .pipe(fs.createWriteStream(dest)) + .on('close', callback); + }, + + // compare two et.XML nodes, see if they match + // compares tagName, text, attributes and children (recursively) + equalNodes: function(one, two) { + if (one.tag != two.tag) { + return false; + } else if (one.text.trim() != two.text.trim()) { + return false; + } else if (one._children.length != two._children.length) { return false; } - } - for (i; i < one._children.length; i++) { - if (!exports.equalNodes(one._children[i], two._children[i])) { + var oneAttribKeys = Object.keys(one.attrib), + twoAttribKeys = Object.keys(two.attrib), + i = 0, attribName; + + if (oneAttribKeys.length != twoAttribKeys.length) { return false; } - } - return true; -} + for (i; i < oneAttribKeys.length; i++) { + attribName = oneAttribKeys[i]; -// adds node to doc at selector -exports.graftXML = function (doc, nodes, selector) { - var ROOT = /^\/([^\/]*)/ - , ABSOLUTE = /^\/([^\/]*)\/(.*)/ - , parent, tagName, subSelector; - - // handle absolute selector (which elementtree doesn't like) - if (ROOT.test(selector)) { - tagName = selector.match(ROOT)[1]; - if (tagName === doc._root.tag) { - parent = doc._root; - - // could be an absolute path, but not selecting the root - if (ABSOLUTE.test(selector)) { - subSelector = selector.match(ABSOLUTE)[2]; - parent = parent.find(subSelector) + if (one.attrib[attribName] != two.attrib[attribName]) { + return false; + } + } + + for (i; i < one._children.length; i++) { + if (!exports.equalNodes(one._children[i], two._children[i])) { + return false; } - } else { - return false; } - } else { - parent = doc.find(selector) - } - nodes.forEach(function (node) { - // check if child is unique first - if (uniqueChild(node, parent)) { - parent.append(node); + return true; + }, + + // adds node to doc at selector + graftXML: function (doc, nodes, selector) { + var ROOT = /^\/([^\/]*)/ + , ABSOLUTE = /^\/([^\/]*)\/(.*)/ + , parent, tagName, subSelector; + + // handle absolute selector (which elementtree doesn't like) + if (ROOT.test(selector)) { + tagName = selector.match(ROOT)[1]; + if (tagName === doc._root.tag) { + parent = doc._root; + + // could be an absolute path, but not selecting the root + if (ABSOLUTE.test(selector)) { + subSelector = selector.match(ABSOLUTE)[2]; + parent = parent.find(subSelector) + } + } else { + return false; + } + } else { + parent = doc.find(selector) } - }); - return true; -} + nodes.forEach(function (node) { + // check if child is unique first + if (uniqueChild(node, parent)) { + parent.append(node); + } + }); -// removes node from doc at selector -exports.pruneXML = function(doc, nodes, selector) { - var ROOT = /^\/([^\/]*)/ - , ABSOLUTE = /^\/([^\/]*)\/(.*)/ - , parent, tagName, subSelector; - - // handle absolute selector (which elementtree doesn't like) - if (ROOT.test(selector)) { - tagName = selector.match(ROOT)[1]; - if (tagName === doc._root.tag) { - parent = doc._root; - - // could be an absolute path, but not selecting the root - if (ABSOLUTE.test(selector)) { - subSelector = selector.match(ABSOLUTE)[2]; - parent = parent.find(subSelector) + return true; + }, + + // removes node from doc at selector + pruneXML: function(doc, nodes, selector) { + var ROOT = /^\/([^\/]*)/ + , ABSOLUTE = /^\/([^\/]*)\/(.*)/ + , parent, tagName, subSelector; + + // handle absolute selector (which elementtree doesn't like) + if (ROOT.test(selector)) { + tagName = selector.match(ROOT)[1]; + if (tagName === doc._root.tag) { + parent = doc._root; + + // could be an absolute path, but not selecting the root + if (ABSOLUTE.test(selector)) { + subSelector = selector.match(ABSOLUTE)[2]; + parent = parent.find(subSelector) + } + } else { + return false; } } else { - return false; + parent = doc.find(selector) } - } else { - parent = doc.find(selector) - } - nodes.forEach(function (node) { - var matchingKid = null; - if ((matchingKid = findChild(node, parent)) != null) { - // stupid elementtree takes an index argument it doesn't use - // and does not conform to the python lib - parent.remove(0, matchingKid); - } - }); - - return true; -} + nodes.forEach(function (node) { + var matchingKid = null; + if ((matchingKid = findChild(node, parent)) != null) { + // stupid elementtree takes an index argument it doesn't use + // and does not conform to the python lib + parent.remove(0, matchingKid); + } + }); -exports.parseElementtreeSync = function (filename) { - var contents = fs.readFileSync(filename, 'utf-8'); - return new et.ElementTree(et.XML(contents)); -} + return true; + }, + parseElementtreeSync: function (filename) { + var contents = fs.readFileSync(filename, 'utf-8'); + return new et.ElementTree(et.XML(contents)); + } +}; function findChild(node, parent) { var matchingKids = parent.findall(node.tag)
