You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by fi...@apache.org on 2013/06/12 23:49:19 UTC

[1/3] updating part of the config_parser specs

Updated Branches:
  refs/heads/lazy bd3cec50b -> 0c2ffe441


http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/spec/cordova-cli/run.spec.js
----------------------------------------------------------------------
diff --git a/spec/cordova-cli/run.spec.js b/spec/cordova-cli/run.spec.js
deleted file mode 100644
index 7e505ef..0000000
--- a/spec/cordova-cli/run.spec.js
+++ /dev/null
@@ -1,141 +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.
-*/
-var cordova = require('../../cordova'),
-    et = require('elementtree'),
-    shell = require('shelljs'),
-    path = require('path'),
-    fs = require('fs'),
-    config_parser = require('../../src/config_parser'),
-    android_parser = require('../../src/metadata/android_parser'),
-    hooker = require('../../src/hooker'),
-    fixtures = path.join(__dirname, '..', 'fixtures'),
-    hooks = path.join(fixtures, 'hooks'),
-    tempDir = path.join(__dirname, '..', '..', 'temp'),
-    cordova_project = path.join(fixtures, 'projects', 'cordova');
-
-var cwd = process.cwd();
-
-describe('run command', function() {
-    beforeEach(function() {
-        shell.rm('-rf', tempDir);
-        cordova.create(tempDir);
-    });
-
-    describe('failure', function() {
-        afterEach(function() {
-            process.chdir(cwd);
-        });
-        it('should not run inside a Cordova-based project with no added platforms', function() {
-            process.chdir(tempDir);
-            expect(function() {
-                cordova.run();
-            }).toThrow();
-        });
-        it('should not run outside of a Cordova-based project', function() {
-            shell.mkdir('-p', tempDir);
-            process.chdir(tempDir);
-
-            expect(function() {
-                cordova.run();
-            }).toThrow();
-        });
-    });
-    
-    describe('success', function() {
-        beforeEach(function() {
-            shell.cp('-Rf', path.join(cordova_project, 'platforms', 'android'), path.join(tempDir, 'platforms'));
-            process.chdir(tempDir);
-        });
-        afterEach(function() {
-            process.chdir(cwd);
-        });
-        it('should invoke prepare', function() {
-            var spy = spyOn(cordova, 'prepare');
-            spyOn(shell, 'exec');
-            cordova.run();
-            expect(spy).toHaveBeenCalled();
-        });
-        it('should shell out to underlying `run` platform-level scripts', function(done) {
-            spyOn(cordova, 'prepare').andCallFake(function(platforms, callback) {
-                callback(false);
-            });
-            var spy = spyOn(shell, 'exec').andCallFake(function(cmd, options, cb) {
-                cb(0, 'yep');
-            });
-            cordova.run('android', function() {
-                 expect(spy.mostRecentCall.args[0]).toMatch(/cordova.run" --device$/gi);
-                 done();
-            });
-        });
-    });
-
-
-    describe('hooks', function() {
-        var s;
-        beforeEach(function() {
-            s = spyOn(hooker.prototype, 'fire').andCallFake(function(hook, opts, cb) {
-                if (cb) cb();
-                else opts();
-            });
-        });
-
-        describe('when platforms are added', function() {
-            beforeEach(function() {
-                shell.cp('-Rf', path.join(cordova_project, 'platforms', 'android'), path.join(tempDir, 'platforms'));
-                process.chdir(tempDir);
-            });
-            afterEach(function() {
-                process.chdir(cwd);
-            });
-
-            it('should fire before hooks through the hooker module', function() {
-
-                spyOn(shell, 'exec');
-                cordova.run();
-                expect(hooker.prototype.fire).toHaveBeenCalledWith('before_run', {platforms:['android']}, jasmine.any(Function));
-            });
-            it('should fire after hooks through the hooker module', function(done) {
-                spyOn(shell, 'exec').andCallFake(function(cmd, options, callback) {
-                    callback(0, 'fucking eh');
-                });
-                cordova.run('android', function() {
-                     expect(hooker.prototype.fire).toHaveBeenCalledWith('after_run', {platforms:['android']}, jasmine.any(Function));
-                     done();
-                });
-            });
-        });
-
-        describe('with no platforms added', function() {
-            beforeEach(function() {
-                process.chdir(tempDir);
-            });
-            afterEach(function() {
-                process.chdir(cwd);
-            });
-            it('should not fire the hooker', function() {
-                spyOn(shell, 'exec');
-                expect(function() {
-                    cordova.run();
-                }).toThrow();
-                expect(s).not.toHaveBeenCalledWith('before_run');
-                expect(s).not.toHaveBeenCalledWith('after_run');
-            });
-        });
-    });
-});

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/spec/cordova-cli/serve.spec.js
----------------------------------------------------------------------
diff --git a/spec/cordova-cli/serve.spec.js b/spec/cordova-cli/serve.spec.js
deleted file mode 100644
index 0139da8..0000000
--- a/spec/cordova-cli/serve.spec.js
+++ /dev/null
@@ -1,134 +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.
-*/
-var cordova = require('../../cordova'),
-    path = require('path'),
-    shell = require('shelljs'),
-    request = require('request'),
-    fs = require('fs'),
-    util = require('../../src/util'),
-    hooker = require('../../src/hooker'),
-    tempDir = path.join(__dirname, '..', '..', 'temp'),
-    http = require('http'),
-    android_parser = require('../../src/metadata/android_parser'),
-    ios_parser = require('../../src/metadata/ios_parser'),
-    blackberry_parser = require('../../src/metadata/blackberry_parser'),
-    wp7_parser        = require('../../src/metadata/wp7_parser'),
-    wp8_parser        = require('../../src/metadata/wp8_parser');
-
-var cwd = process.cwd();
-
-xdescribe('serve command', function() {
-    beforeEach(function() {
-        // Make a temp directory
-        shell.rm('-rf', tempDir);
-        shell.mkdir('-p', tempDir);
-    });
-    it('should not run outside of a Cordova-based project', function() {
-        this.after(function() {
-            process.chdir(cwd);
-        });
-
-        process.chdir(tempDir);
-
-        expect(function() {
-            cordova.serve('android');
-        }).toThrow();
-    });
-
-
-    describe('`serve`', function() {
-        var payloads = {
-            android: 'This is the Android test file.',
-            ios: 'This is the iOS test file.'
-        };
-
-        beforeEach(function() {
-            cordova.create(tempDir);
-            process.chdir(tempDir);
-            cordova.platform('add', 'android');
-            cordova.platform('add', 'ios');
-
-            // Write testing HTML files into the directory.
-            fs.writeFileSync(path.join(tempDir, 'platforms', 'android', 'assets', 'www', 'test.html'), payloads.android);
-            fs.writeFileSync(path.join(tempDir, 'platforms', 'ios', 'www', 'test.html'), payloads.ios);
-        });
-
-        afterEach(function() {
-            process.chdir(cwd);
-        });
-
-        function test_serve(platform, path, expectedContents, port) {
-            return function() {
-                var ret;
-                runs(function() {
-                    ret = port ? cordova.serve(platform, port) : cordova.serve(platform);
-                });
-
-                waitsFor(function() {
-                    return ret.server;
-                }, 'the server should start', 1000);
-
-                var done, errorCB;
-                runs(function() {
-                    expect(ret.server).toBeDefined();
-                    errorCB = jasmine.createSpy();
-                    http.get({
-                        host: 'localhost',
-                        port: port || 8000,
-                        path: path
-                    }).on('response', function(res) {
-                        var response = '';
-                        res.on('data', function(data) {
-                            response += data;
-                        });
-                        res.on('end', function() {
-                            expect(res.statusCode).toEqual(200);
-                            expect(response).toEqual(expectedContents);
-                            done = true;
-                        });
-                    }).on('error', errorCB);
-                });
-
-                waitsFor(function() {
-                    return done;
-                }, 'the HTTP request should complete', 1000);
-
-                runs(function() {
-                    expect(done).toBeTruthy();
-                    expect(errorCB).not.toHaveBeenCalled();
-
-                    ret.server.close();
-                });
-            };
-        };
-
-        it('should serve from top-level www if the file exists there', function() {
-            var payload = 'This is test file.';
-            fs.writeFileSync(path.join(util.projectWww(tempDir), 'test.html'), payload);
-            test_serve('android', '/test.html', payload)();
-        });
-
-        it('should fall back to assets/www on Android', test_serve('android', '/test.html', payloads.android));
-        it('should fall back to www on iOS', test_serve('ios', '/test.html', payloads.ios));
-
-        it('should honour a custom port setting', test_serve('android', '/test.html', payloads.android, 9001));
-    });
-});
-

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/spec/cordova-cli/util.spec.js
----------------------------------------------------------------------
diff --git a/spec/cordova-cli/util.spec.js b/spec/cordova-cli/util.spec.js
deleted file mode 100644
index a57d551..0000000
--- a/spec/cordova-cli/util.spec.js
+++ /dev/null
@@ -1,13 +0,0 @@
-var cordova = require('../../cordova'),
-    shell = require('shelljs'),
-    path = require('path'),
-    fs = require('fs'),
-    cordova_util = require('../../src/util'),
-    fixtures = path.join(__dirname, '..', 'fixtures');
-
-var cwd = process.cwd();
-
-describe('util module', function() {
-    describe('isCordova method', function() {
-    });
-});

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/spec/create.spec.js
----------------------------------------------------------------------
diff --git a/spec/create.spec.js b/spec/create.spec.js
new file mode 100644
index 0000000..4fa4e23
--- /dev/null
+++ b/spec/create.spec.js
@@ -0,0 +1,127 @@
+var cordova = require('../cordova'),
+    path    = require('path'),
+    shell   = require('shelljs'),
+    fs      = require('fs'),
+    util    = require('../src/util'),
+    config    = require('../src/config'),
+    lazy_load = require('../src/lazy_load'),
+    tempDir = path.join(__dirname, '..', 'temp');
+
+describe('create command', function () {
+    var mkdir, cp, config_spy, load_cordova, load_custom, exists, config_read, parser, package, name;
+    beforeEach(function() {
+        shell.rm('-rf', tempDir);
+        mkdir = spyOn(shell, 'mkdir');
+        cp = spyOn(shell, 'cp');
+        config_spy = spyOn(cordova, 'config');
+        config_read = spyOn(config, 'read').andReturn({});
+        exists = spyOn(fs, 'existsSync').andReturn(true);
+        load_cordova = spyOn(lazy_load, 'cordova').andCallFake(function(platform, cb) {
+            cb();
+        });
+        load_custom = spyOn(lazy_load, 'custom').andCallFake(function(url, id, platform, version, cb) {
+            cb();
+        });
+        package = jasmine.createSpy('config.packageName');
+        name = jasmine.createSpy('config.name');
+        parser = spyOn(util, 'config_parser').andReturn({
+            packageName:package,
+            name:name
+        });
+    });
+
+    describe('failure', function() {
+        it('should return a help message if incorrect number of parameters is used', function() {
+            expect(cordova.create()).toMatch(/synopsis/gi);
+        });
+    });
+
+    describe('success', function() {
+        it('should create a default project if only directory is specified', function(done) {
+            cordova.create(tempDir, function() {
+                expect(mkdir).toHaveBeenCalledWith('-p', path.join(tempDir, '.cordova'));
+                expect(package).toHaveBeenCalledWith('io.cordova.hellocordova');
+                expect(name).toHaveBeenCalledWith('HelloCordova');
+                done();
+            });
+        });
+        it('should create a default project if only directory and id is specified', function(done) {
+            cordova.create(tempDir, 'ca.filmaj.canucks', function() {
+                expect(mkdir).toHaveBeenCalledWith('-p', path.join(tempDir, '.cordova'));
+                expect(package).toHaveBeenCalledWith('ca.filmaj.canucks');
+                expect(name).toHaveBeenCalledWith('HelloCordova');
+                done();
+            });
+        });
+        it('should create a project in specified directory with specified name and id', function(done) {
+            cordova.create(tempDir, 'ca.filmaj.canucks', 'IHateTheBruins', function() {
+                expect(mkdir).toHaveBeenCalledWith('-p', path.join(tempDir, '.cordova'));
+                expect(package).toHaveBeenCalledWith('ca.filmaj.canucks');
+                expect(name).toHaveBeenCalledWith('IHateTheBruins');
+                done();
+            });
+        });
+        it('should create top-level directory structure appropriate for a cordova-cli project', function(done) {
+            cordova.create(tempDir, function() {
+                expect(mkdir).toHaveBeenCalledWith('-p', path.join(tempDir, 'platforms'));
+                expect(mkdir).toHaveBeenCalledWith('-p', path.join(tempDir, 'merges'));
+                expect(mkdir).toHaveBeenCalledWith('-p', path.join(tempDir, 'plugins'));
+                expect(mkdir).toHaveBeenCalledWith('-p', path.join(tempDir, 'www'));
+                done();
+            });
+        });
+        it('should create appropriate directories for hooks', function(done) {
+            var hooks_dir = path.join(tempDir, '.cordova', 'hooks');
+            cordova.create(tempDir, function() {
+                expect(mkdir).toHaveBeenCalledWith('-p', hooks_dir);
+                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'after_build')));
+                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'after_compile')));
+                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'after_docs')));
+                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'after_emulate')));
+                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'after_platform_add')));
+                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'after_platform_rm')));
+                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'after_platform_ls')));
+                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'after_plugin_add')));
+                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'after_plugin_ls')));
+                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'after_plugin_rm')));
+                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'after_prepare')));
+                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'after_run')));
+                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'before_build')));
+                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'before_compile')));
+                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'before_docs')));
+                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'before_emulate')));
+                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'before_platform_add')));
+                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'before_platform_rm')));
+                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'before_platform_ls')));
+                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'before_plugin_add')));
+                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'before_plugin_ls')));
+                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'before_plugin_rm')));
+                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'before_prepare')));
+                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'before_run')));
+                done();
+            });
+        });
+        it('should by default use cordova-app-hello-world as www assets', function(done) {
+            cordova.create(tempDir, function() {
+                expect(load_cordova).toHaveBeenCalledWith('www', jasmine.any(Function));
+                done();
+            });
+        });
+        it('should try to lazy load custom www location if specified', function(done) {
+            var fake_config = {
+                lib:{
+                    www:{
+                        id:'supercordova',
+                        uri:'/supacordoba',
+                        version:'1337'
+                    }
+                }
+            };
+            config_read.andReturn(fake_config);
+            cordova.create(tempDir, function() {
+                expect(load_custom).toHaveBeenCalledWith(fake_config.lib.www.uri, fake_config.lib.www.id, 'www', fake_config.lib.www.version, jasmine.any(Function));
+                done();
+            });
+        });
+    });
+});

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/spec/emulate.spec.js
----------------------------------------------------------------------
diff --git a/spec/emulate.spec.js b/spec/emulate.spec.js
new file mode 100644
index 0000000..4f8e14b
--- /dev/null
+++ b/spec/emulate.spec.js
@@ -0,0 +1,125 @@
+/**
+    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.
+*/
+var cordova = require('../../cordova'),
+    et = require('elementtree'),
+    shell = require('shelljs'),
+    path = require('path'),
+    fs = require('fs'),
+    hooker = require('../../src/hooker'),
+    tempDir = path.join(__dirname, '..', '..', 'temp');
+
+var cwd = process.cwd();
+
+describe('emulate command', function() {
+    beforeEach(function() {
+        shell.rm('-rf', tempDir);
+        cordova.create(tempDir);
+    });
+
+    describe('failure', function() {
+        afterEach(function() {
+            process.chdir(cwd);
+        });
+        it('should not run inside a Cordova-based project with no added platforms', function() {
+            process.chdir(tempDir);
+            expect(function() {
+                cordova.emulate();
+            }).toThrow();
+        });
+        it('should not run outside of a Cordova-based project', function() {
+            shell.mkdir('-p', tempDir);
+            process.chdir(tempDir);
+
+            expect(function() {
+                cordova.emulate();
+            }).toThrow();
+        });
+    });
+
+    describe('success', function() {
+        beforeEach(function() {
+            process.chdir(tempDir);
+            spyOn(cordova, 'prepare').andCallFake(function(ps, cb) {
+                cb();
+            });
+        });
+        afterEach(function() {
+            process.chdir(cwd);
+        });
+        it('should run inside a Cordova-based project with at least one added platform', function(done) {
+            var s = spyOn(shell, 'exec').andCallFake(function(cmd, opts, cb) {
+                cb(0, 'yokay');
+            });
+            cordova.emulate(['android', 'beer'], function(err) {
+                expect(s).toHaveBeenCalled();
+                expect(s.mostRecentCall.args[0]).toMatch(/cordova.run" --emulator$/gi);
+                done();
+            });
+        });
+    });
+
+    describe('hooks', function() {
+        var hook_spy;
+        var shell_spy;
+        var prepare_spy;
+        beforeEach(function() {
+            hook_spy = spyOn(hooker.prototype, 'fire').andCallFake(function(hook, opts, cb) {
+                if (cb) cb();
+                else opts();
+            });
+            prepare_spy = spyOn(cordova, 'prepare').andCallFake(function(ps, cb) {
+                cb();
+            });
+            shell_spy = spyOn(shell, 'exec').andCallFake(function(cmd, opts, cb) {
+                cb(0, 'yup'); // fake out shell so system thinks every shell-out is successful
+            });
+            process.chdir(tempDir);
+        });
+        afterEach(function() {
+            hook_spy.reset();
+            prepare_spy.reset();
+            shell_spy.reset();
+            process.chdir(cwd);
+        });
+
+        describe('when platforms are added', function() {
+            it('should fire before hooks through the hooker module', function(done) {
+                cordova.emulate(['android', 'ios'], function(err) {
+                    expect(hook_spy).toHaveBeenCalledWith('before_emulate', {platforms:['android', 'ios']}, jasmine.any(Function));
+                    done();
+                });
+            });
+            it('should fire after hooks through the hooker module', function(done) {
+                cordova.emulate('android', function() {
+                     expect(hook_spy).toHaveBeenCalledWith('after_emulate', {platforms:['android']}, jasmine.any(Function));
+                     done();
+                });
+            });
+        });
+
+        describe('with no platforms added', function() {
+            it('should not fire the hooker', function() {
+                expect(function() {
+                    cordova.emulate();
+                }).toThrow();
+                expect(hook_spy).not.toHaveBeenCalled();
+            });
+        });
+    });
+});

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/spec/helper.js
----------------------------------------------------------------------
diff --git a/spec/helper.js b/spec/helper.js
new file mode 100644
index 0000000..351e6e4
--- /dev/null
+++ b/spec/helper.js
@@ -0,0 +1,19 @@
+/**
+    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.
+*/
+jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/spec/hooker.spec.js
----------------------------------------------------------------------
diff --git a/spec/hooker.spec.js b/spec/hooker.spec.js
new file mode 100644
index 0000000..6b0129a
--- /dev/null
+++ b/spec/hooker.spec.js
@@ -0,0 +1,202 @@
+ /**
+    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.
+*/
+var hooker = require('../../src/hooker'),
+    shell  = require('shelljs'),
+    path   = require('path'),
+    fs     = require('fs'),
+    os     = require('os'),
+    tempDir= path.join(__dirname, '..', '..', 'temp'),
+    hooks  = path.join(__dirname, '..', 'fixtures', 'hooks'),
+    cordova= require('../../cordova');
+
+var platform = os.platform();
+var cwd = process.cwd();
+
+describe('hooker', function() {
+    it('should throw if provided directory is not a cordova project', function() {
+        shell.rm('-rf', tempDir);
+        shell.mkdir('-p', tempDir); 
+        this.after(function() {
+            shell.rm('-rf', tempDir);
+        });
+
+        expect(function() {
+            var h = new hooker(tempDir);
+        }).toThrow();
+    });
+    it('should not throw if provided directory is a cordova project', function() {
+        cordova.create(tempDir);
+        this.after(function() {
+            shell.rm('-rf', tempDir);
+        });
+
+        expect(function() {
+            var h = new hooker(tempDir);
+        }).not.toThrow();
+    });
+
+    describe('fire method', function() {
+        var h;
+
+        beforeEach(function() {
+            cordova.create(tempDir);
+            h = new hooker(tempDir);
+        });
+        afterEach(function() {
+            shell.rm('-rf', tempDir);
+        });
+
+        describe('failure', function() {
+            it('should not error if the hook is unrecognized', function(done) {
+                h.fire('CLEAN YOUR SHORTS GODDAMNIT LIKE A BIG BOY!', function(err){
+                    expect(err).not.toBeDefined();
+                    done();
+                });
+            });
+            it('should error if any script exits with non-zero code', function(done) {
+                var script;
+                if (platform.match(/(win32|win64)/)) {
+                    script = path.join(tempDir, '.cordova', 'hooks', 'before_build', 'fail.bat');
+                    shell.cp(path.join(hooks, 'fail', 'fail.bat'), script);
+                } else {
+                    script = path.join(tempDir, '.cordova', 'hooks', 'before_build', 'fail.sh');
+                    shell.cp(path.join(hooks, 'fail', 'fail.sh'), script);
+                }
+                fs.chmodSync(script, '754');
+                h.fire('before_build', function(err){
+                    expect(err).toBeDefined();
+                    done();
+                });
+            });
+        });
+
+        describe('success', function() {
+            it('should execute all scripts in order and fire callback', function(done) {
+                var hook = path.join(tempDir, '.cordova', 'hooks', 'before_build');
+                if (platform.match(/(win32|win64)/)) {
+                    shell.cp(path.join(hooks, 'test', '0.bat'), hook);
+                    shell.cp(path.join(hooks, 'test', '1.bat'), hook);
+                } else {
+                    shell.cp(path.join(hooks, 'test', '0.sh'), hook);
+                    shell.cp(path.join(hooks, 'test', '1.sh'), hook);
+                }
+                fs.readdirSync(hook).forEach(function(script) {
+                    fs.chmodSync(path.join(hook, script), '754');
+                });
+                var returnValue;
+                var s = spyOn(shell, 'exec').andCallFake(function(cmd, opts, cb) {
+                    cb(0, '');
+                });
+                h.fire('before_build', function(err) {
+                    expect(err).not.toBeDefined();
+                    if (platform.match(/(win32|win64)/)) {
+                        expect(s.calls[0].args[0]).toMatch(/0.bat/);
+                        expect(s.calls[1].args[0]).toMatch(/1.bat/);
+                    } else {
+                        expect(s.calls[0].args[0]).toMatch(/0.sh/);
+                        expect(s.calls[1].args[0]).toMatch(/1.sh/);
+                    }
+                    done();
+                });
+            });
+            it('should pass the project root folder as parameter into the project-level hooks', function(done) {
+                var hook = path.join(tempDir, '.cordova', 'hooks', 'before_build');
+                if (platform.match(/(win32|win64)/)) {
+                    shell.cp(path.join(hooks, 'test', '0.bat'), hook);
+                } else {
+                    shell.cp(path.join(hooks, 'test', '0.sh'), hook);
+                }
+                fs.readdirSync(hook).forEach(function(script) {
+                    fs.chmodSync(path.join(hook, script), '754');
+                });
+                var s = spyOn(shell, 'exec').andCallFake(function(cmd, opts, cb) {
+                    cb(0, '');
+                });
+                h.fire('before_build', function(err) {
+                    expect(err).not.toBeDefined();
+                    var param_str;
+                    if (platform.match(/(win32|win64)/)) {
+                        param_str = '0.bat "'+tempDir+'"';
+                    } else { 
+                        param_str = '0.sh "'+tempDir+'"'; 
+                    }
+                    expect(s.calls[0].args[0].indexOf(param_str)).not.toEqual(-1);
+                    done();
+                });
+            });
+            describe('module-level hooks', function() {
+                var handler = jasmine.createSpy();
+                var test_event = 'before_build';
+                afterEach(function() {
+                    cordova.off(test_event, handler);
+                    handler.reset();
+                });
+
+                it('should fire handlers using cordova.on', function(done) {
+                    cordova.on(test_event, handler);
+                    h.fire(test_event, function(err) {
+                        expect(handler).toHaveBeenCalled();
+                        expect(err).not.toBeDefined();
+                        done();
+                    });
+                });
+                it('should pass the project root folder as parameter into the module-level handlers', function(done) {
+                    cordova.on(test_event, handler);
+                    h.fire(test_event, function(err) {
+                        expect(handler).toHaveBeenCalledWith({root:tempDir});
+                        expect(err).not.toBeDefined();
+                        done();
+                    });
+                });
+                it('should be able to stop listening to events using cordova.off', function(done) {
+                    cordova.on(test_event, handler);
+                    cordova.off(test_event, handler);
+                    h.fire(test_event, function(err) {
+                        expect(handler).not.toHaveBeenCalled();
+                        done();
+                    });
+                });
+                it('should allow for hook to opt into asynchronous execution and block further hooks from firing using the done callback', function(done) {
+                    var h1_fired = false;
+                    var h1 = function(root, cb) {
+                        h1_fired = true;
+                        setTimeout(cb, 100);
+                    };
+                    var h2_fired = false;
+                    var h2 = function() {
+                        h2_fired = true;
+                    };
+                    runs(function() {
+                        cordova.on(test_event, h1);
+                        cordova.on(test_event, h2);
+                        h.fire(test_event, function(err) {
+                            done();
+                        });
+                        expect(h1_fired).toBe(true);
+                        expect(h2_fired).toBe(false);
+                    });
+                    waits(100);
+                    runs(function() {
+                        expect(h2_fired).toBe(true);
+                    });
+                });
+            });
+        });
+    });
+});

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/spec/platform.spec.js
----------------------------------------------------------------------
diff --git a/spec/platform.spec.js b/spec/platform.spec.js
new file mode 100644
index 0000000..fed1f3b
--- /dev/null
+++ b/spec/platform.spec.js
@@ -0,0 +1,284 @@
+/**
+    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.
+*/
+var cordova = require('../../cordova'),
+    path = require('path'),
+    shell = require('shelljs'),
+    fs = require('fs'),
+    util = require('../../src/util'),
+    hooker = require('../../src/hooker'),
+    platform = require('../../src/platform'),
+    platforms = require('../../platforms'),
+    tempDir = path.join(__dirname, '..', '..', 'temp');
+    android_parser = require('../../src/metadata/android_parser');
+
+var cwd = process.cwd();
+
+describe('platform command', function() {
+    beforeEach(function() {
+        // Make a temp directory
+        shell.rm('-rf', tempDir);
+        shell.mkdir('-p', tempDir);
+    });
+    it('should run inside a Cordova-based project', function() {
+        this.after(function() {
+            process.chdir(cwd);
+        });
+
+        cordova.create(tempDir);
+
+        process.chdir(tempDir);
+
+        expect(function() {
+            cordova.platform();
+        }).not.toThrow();
+    });
+    it('should not run outside of a Cordova-based project', function() {
+        this.after(function() {
+            process.chdir(cwd);
+        });
+
+        process.chdir(tempDir);
+
+        expect(function() {
+            cordova.platform();
+        }).toThrow();
+    });
+
+    describe('`ls`', function() { 
+        beforeEach(function() {
+            cordova.create(tempDir);
+            process.chdir(tempDir);
+        });
+
+        afterEach(function() {
+            process.chdir(cwd);
+            cordova.removeAllListeners('results'); // clean up event listener
+        });
+
+        it('should list out no platforms for a fresh project', function(done) {
+            shell.rm('-rf', path.join(tempDir, 'platforms', '*'));
+            cordova.on('results', function(res) {
+                expect(res).toEqual('No platforms added. Use `cordova platform add <platform>`.');
+                done();
+            });
+            cordova.platform('list');
+        });
+
+        it('should list out added platforms in a project', function(done) {
+            var platforms = path.join(tempDir, 'platforms');
+            shell.mkdir(path.join(platforms, 'android'));
+            shell.mkdir(path.join(platforms, 'ios'));
+            
+            cordova.on('results', function(res) {
+                expect(res.length).toEqual(2);
+                done();
+            });
+            cordova.platform('list');
+        });
+    });
+
+    describe('`add`', function() {
+        beforeEach(function() {
+            cordova.create(tempDir);
+            process.chdir(tempDir);
+        });
+
+        afterEach(function() {
+            process.chdir(cwd);
+        });
+
+        it('should handle multiple platforms and shell out to specified platform\'s bin/create', function() {
+            spyOn(platform, 'supports').andCallFake(function(target, callback) {
+                    callback(null);
+            });
+            var sh = spyOn(shell, 'exec');
+            cordova.platform('add', ['foo', 'bar']);
+            var foo_create = path.join('foo', 'bin', 'create');
+            var bar_create = path.join('bar', 'bin', 'create');
+            expect(sh.argsForCall[0][0]).toContain(foo_create);
+            expect(sh.argsForCall[1][0]).toContain(bar_create);
+        });
+    });
+
+    describe('`remove`',function() {
+        beforeEach(function() {
+            cordova.create(tempDir);
+            process.chdir(tempDir);
+        });
+
+        afterEach(function() {
+            process.chdir(cwd);
+            cordova.removeAllListeners('results');
+        });
+
+        it('should remove a supported and added platform', function(done) {
+            shell.mkdir(path.join(tempDir, 'platforms', 'android'));
+            shell.mkdir(path.join(tempDir, 'platforms', 'ios'));
+            cordova.platform('remove', 'android', function() {
+                cordova.on('results', function(res) {
+                    expect(res.length).toEqual(1);
+                    done();
+                });
+                cordova.platform('list');
+            });
+        });
+
+        it('should be able to remove multiple platforms', function(done) {
+            shell.mkdir(path.join(tempDir, 'platforms', 'android'));
+            shell.mkdir(path.join(tempDir, 'platforms', 'blackberry'));
+            shell.mkdir(path.join(tempDir, 'platforms', 'ios'));
+            cordova.platform('remove', ['android','blackberry'], function() {
+                cordova.on('results', function(res) {
+                    expect(res.length).toEqual(1);
+                    done();
+                });
+                cordova.platform('list');
+            });
+        });
+    });
+
+    describe('hooks', function() {
+        var s;
+        beforeEach(function() {
+            cordova.create(tempDir);
+            process.chdir(tempDir);
+            s = spyOn(hooker.prototype, 'fire').andCallFake(function(hook, opts, cb) {
+                if (cb) cb();
+                else opts();
+            });
+        });
+        afterEach(function() {
+            process.chdir(cwd);
+            shell.rm('-rf', tempDir);
+        });
+
+        describe('list (ls) hooks', function() {
+            it('should fire before hooks through the hooker module', function() {
+                cordova.platform();
+                expect(s).toHaveBeenCalledWith('before_platform_ls', jasmine.any(Function));
+            });
+            it('should fire after hooks through the hooker module', function() {
+                cordova.platform();
+                expect(s).toHaveBeenCalledWith('after_platform_ls', jasmine.any(Function));
+            });
+        });
+        describe('remove (rm) hooks', function() {
+            it('should fire before hooks through the hooker module', function() {
+                cordova.platform('rm', 'android');
+                expect(s).toHaveBeenCalledWith('before_platform_rm', {platforms:['android']}, jasmine.any(Function));
+            });
+            it('should fire after hooks through the hooker module', function() {
+                cordova.platform('rm', 'android');
+                expect(s).toHaveBeenCalledWith('after_platform_rm', {platforms:['android']}, jasmine.any(Function));
+            });
+        });
+        describe('add hooks', function() {
+            var sh, cr;
+            beforeEach(function() {
+                sh = spyOn(shell, 'exec').andCallFake(function(cmd, opts, cb) {
+                    var a_path = path.join(tempDir, 'platforms','android'); 
+                    shell.mkdir('-p',a_path); 
+                    fs.writeFileSync(path.join(a_path, 'AndroidManifest.xml'), 'hi', 'utf-8');
+                    cb(0, 'mkay');
+                });
+                cr = spyOn(android_parser.prototype, 'update_project').andCallFake(function(cfg, cb) {
+                    cb();
+                });
+                spyOn(platform, 'supports').andCallFake(function (t, cb) {
+                    cb();
+                });
+            });
+            it('should fire before and after hooks through the hooker module', function() {
+                cordova.platform('add', 'android');
+                expect(s).toHaveBeenCalledWith('before_platform_add', {platforms:['android']}, jasmine.any(Function));
+                expect(s).toHaveBeenCalledWith('after_platform_add', {platforms:['android']}, jasmine.any(Function));
+            });
+        });
+    });
+});
+
+describe('platform.supports(name, callback)', function() {
+    var androidParser = require('../../src/metadata/android_parser');
+
+    beforeEach(function() {
+        spyOn(androidParser, 'check_requirements');
+    });
+
+    it('should require a platform name', function() {
+        expect(function() {
+            cordova.platform.supports(undefined, function(e){});
+        }).toThrow();
+    });
+
+    it('should require a callback function', function() {
+        expect(function() {
+            cordova.platform.supports('android', undefined);
+        }).toThrow();
+    });
+
+    describe('when platform is unknown', function() {
+        it('should trigger callback with false', function(done) {
+            cordova.platform.supports('windows-3.1', function(e) {
+                expect(e).toEqual(jasmine.any(Error));
+                done();
+            });
+        });
+    });
+
+    describe('when platform is supported', function() {
+        beforeEach(function() {
+            androidParser.check_requirements.andCallFake(function(callback) {
+                callback(null);
+            });
+        });
+
+        it('should trigger callback without error', function(done) {
+            cordova.platform.supports('android', function(e) {
+                expect(e).toBeNull();
+                done();
+            });
+        });
+    });
+
+    describe('when platform is unsupported', function() {
+        beforeEach(function() {
+            androidParser.check_requirements.andCallFake(function(callback) {
+                callback(new Error('could not find the android sdk'));
+            });
+        });
+
+        it('should trigger callback with error', function(done) {
+            cordova.platform.supports('android', function(e) {
+                expect(e).toEqual(jasmine.any(Error));
+                done();
+            });
+        });
+    });
+});
+
+describe('platform parsers', function() {
+    it('should be exposed on the platform module', function() {
+        for (var platform in platforms) {
+            expect(cordova.platform[platform]).toBeDefined();
+            for (var prop in platforms[platform]) {
+                expect(cordova.platform[platform][prop]).toBeDefined();
+            }
+        }
+    });
+});

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/spec/plugin.spec.js
----------------------------------------------------------------------
diff --git a/spec/plugin.spec.js b/spec/plugin.spec.js
new file mode 100644
index 0000000..d042841
--- /dev/null
+++ b/spec/plugin.spec.js
@@ -0,0 +1,146 @@
+/**
+    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.
+*/
+var cordova = require('../../cordova'),
+    path = require('path'),
+    shell = require('shelljs'),
+    fs = require('fs'),
+    hooker = require('../../src/hooker'),
+    tempDir = path.join(__dirname, '..', '..', 'temp'),
+    fixturesDir = path.join(__dirname, '..', 'fixtures'),
+    testPlugin = path.join(fixturesDir, 'plugins', 'test'),
+    cordova_project = path.join(fixturesDir, 'projects', 'cordova'),
+    androidPlugin = path.join(fixturesDir, 'plugins', 'android');
+
+var cwd = process.cwd();
+
+describe('plugin command', function() {
+    beforeEach(function() {
+        // Make a temp directory
+        shell.rm('-rf', tempDir);
+        shell.mkdir('-p', tempDir);
+    });
+
+    it('should run inside a Cordova-based project', function() {
+        this.after(function() {
+            process.chdir(cwd);
+        });
+
+        cordova.create(tempDir);
+
+        process.chdir(tempDir);
+
+        expect(function() {
+            cordova.plugin();
+        }).not.toThrow();
+    });
+    it('should not run outside of a Cordova-based project', function() {
+        this.after(function() {
+            process.chdir(cwd);
+        });
+
+        process.chdir(tempDir);
+
+        expect(function() {
+            cordova.plugin();
+        }).toThrow();
+    });
+
+    describe('edge cases', function() {
+       beforeEach(function() {
+           cordova.create(tempDir);
+           process.chdir(tempDir);
+       });
+
+       afterEach(function() {
+           process.chdir(cwd);
+           cordova.removeAllListeners('results');
+       });
+
+       it('should not fail when the plugins directory is missing', function() {
+           fs.rmdirSync('plugins');
+
+           expect(function() {
+               cordova.plugin();
+           }).not.toThrow();
+       });
+
+       it('should ignore files, like .gitignore, in the plugins directory', function(done) {
+           var someFile = path.join(tempDir, 'plugins', '.gitignore');
+           fs.writeFileSync(someFile, 'not a plugin');
+           cordova.on('results', function(res) {
+               expect(res).toEqual('No plugins added. Use `cordova plugin add <plugin>`.');
+               done();
+           });
+
+           cordova.plugin('list');
+       });
+    });
+
+    describe('`ls`', function() {
+        beforeEach(function() {
+            cordova.create(tempDir);
+            process.chdir(tempDir);
+        });
+
+        afterEach(function() {
+            process.chdir(cwd);
+            cordova.removeAllListeners('results');
+        });
+
+        it('should list out no plugins for a fresh project', function(done) {
+            cordova.on('results', function(res) {
+                expect(res).toEqual('No plugins added. Use `cordova plugin add <plugin>`.');
+                done();
+            });
+            cordova.plugin('list');
+        });
+        it('should list out any added plugins in a project', function(done) {
+            var random_plug = 'randomplug';
+            shell.mkdir('-p', path.join(tempDir, 'plugins', random_plug));
+            cordova.on('results', function(res) {
+                expect(res).toEqual([random_plug]);
+                done();
+            });
+            cordova.plugin('list');
+        });
+    });
+
+    describe('`add`', function() {
+        beforeEach(function() {
+            cordova.create(tempDir);
+            process.chdir(tempDir);
+        });
+
+        afterEach(function() {
+            process.chdir(cwd);
+        });
+        describe('failure', function() {
+            it('should throw if plugin does not have a plugin.xml', function() {
+                process.chdir(cordova_project);
+                this.after(function() {
+                    process.chdir(cwd);
+                });
+                expect(function() {
+                    cordova.plugin('add', fixturesDir);
+                }).toThrow();
+            });
+        });
+    });
+});
+

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/spec/plugin_parser.spec.js
----------------------------------------------------------------------
diff --git a/spec/plugin_parser.spec.js b/spec/plugin_parser.spec.js
new file mode 100644
index 0000000..15b5993
--- /dev/null
+++ b/spec/plugin_parser.spec.js
@@ -0,0 +1,42 @@
+
+/**
+    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.
+*/
+var cordova = require('../../cordova'),
+    path = require('path'),
+    fs = require('fs'),
+    plugin_parser = require('../../src/plugin_parser'),
+    et = require('elementtree'),
+    xml = path.join(__dirname, '..', 'fixtures', 'plugins', 'test', 'plugin.xml');
+
+describe('plugin.xml parser', function () {
+    it('should read a proper plugin.xml file', function() {
+        var cfg;
+        expect(function () {
+            cfg = new plugin_parser(xml);
+        }).not.toThrow();
+        expect(cfg).toBeDefined();
+        expect(cfg.doc).toBeDefined();
+    });
+    it('should be able to figure out which platforms the plugin supports', function() {
+        var cfg = new plugin_parser(xml);
+        expect(cfg.platforms.length).toBe(1);
+        expect(cfg.platforms.indexOf('ios') > -1).toBe(true);
+    });
+});
+

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/spec/prepare.spec.js
----------------------------------------------------------------------
diff --git a/spec/prepare.spec.js b/spec/prepare.spec.js
new file mode 100644
index 0000000..d7c7d28
--- /dev/null
+++ b/spec/prepare.spec.js
@@ -0,0 +1,153 @@
+/**
+    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.
+*/
+var cordova = require('../../cordova'),
+    et = require('elementtree'),
+    shell = require('shelljs'),
+    plugman = require('plugman'),
+    path = require('path'),
+    fs = require('fs'),
+    config_parser = require('../../src/config_parser'),
+    android_parser = require('../../src/metadata/android_parser'),
+    hooker = require('../../src/hooker'),
+    fixtures = path.join(__dirname, '..', 'fixtures'),
+    test_plugin = path.join(fixtures, 'plugins', 'android'),
+    hooks = path.join(fixtures, 'hooks'),
+    tempDir = path.join(__dirname, '..', '..', 'temp'),
+    cordova_project = path.join(fixtures, 'projects', 'cordova');
+
+var cwd = process.cwd();
+
+describe('prepare command', function() {
+    beforeEach(function() {
+        shell.rm('-rf', tempDir);
+        cordova.create(tempDir);
+    });
+
+    it('should not run inside a Cordova-based project with no added platforms', function() {
+        this.after(function() {
+            process.chdir(cwd);
+        });
+
+        process.chdir(tempDir);
+        expect(function() {
+            cordova.prepare();
+        }).toThrow();
+    });
+    
+    it('should run inside a Cordova-based project with at least one added platform', function(done) {
+        process.chdir(tempDir);
+        var android_path = path.join(tempDir, 'platforms', 'android');
+        shell.mkdir(android_path);
+        fs.writeFileSync(path.join(android_path, 'AndroidManifest.xml'), 'hi', 'utf-8');
+        spyOn(plugman, 'prepare');
+        cordova.prepare(['android'], function(err) {
+            done();
+        });
+    });
+    it('should not run outside of a Cordova-based project', function() {
+        this.after(function() {
+            process.chdir(cwd);
+        });
+
+        shell.mkdir('-p', tempDir);
+        process.chdir(tempDir);
+
+        expect(function() {
+            cordova.prepare();
+        }).toThrow();
+    });
+
+    describe('plugman integration', function() {
+        beforeEach(function() {
+            shell.cp('-Rf', path.join(cordova_project, 'platforms', 'android'), path.join(tempDir, 'platforms'));
+            process.chdir(tempDir);
+        });
+        afterEach(function() {
+            process.chdir(cwd);
+        });
+
+        it('should invoke plugman.prepare after update_project', function() {
+            var a_parser_spy = spyOn(android_parser.prototype, 'update_project');
+            var prep_spy = spyOn(plugman, 'prepare');
+            cordova.prepare();
+            a_parser_spy.mostRecentCall.args[1](); // fake out android_parser
+            var android_path = path.join(tempDir, 'platforms', 'android');
+            var plugins_dir = path.join(tempDir, 'plugins');
+            expect(prep_spy).toHaveBeenCalledWith(android_path, 'android', plugins_dir);
+        });
+        it('should invoke add_plugin_changes for any added plugins to verify configuration changes for plugins are in place', function() {
+            var platform_path  = path.join(tempDir, 'platforms', 'android');
+            var plugins_dir = path.join(tempDir, 'plugins');
+            plugman.install('android', platform_path, test_plugin, plugins_dir, {});
+            var a_parser_spy = spyOn(android_parser.prototype, 'update_project');
+            var prep_spy = spyOn(plugman, 'prepare');
+            var plugin_changes_spy = spyOn(plugman.config_changes, 'add_plugin_changes');
+            cordova.prepare();
+            a_parser_spy.mostRecentCall.args[1](); // fake out android_parser
+            expect(plugin_changes_spy).toHaveBeenCalledWith('android', platform_path, plugins_dir, 'ca.filmaj.AndroidPlugin', {PACKAGE_NAME:"org.apache.cordova.cordovaExample"}, true, false); 
+        });
+    });
+
+    describe('hooks', function() {
+        var s;
+        beforeEach(function() {
+            s = spyOn(hooker.prototype, 'fire').andReturn(true);
+        });
+
+        describe('when platforms are added', function() {
+            beforeEach(function() {
+                shell.cp('-rf', path.join(cordova_project, 'platforms', 'android'), path.join(tempDir, 'platforms'));
+                process.chdir(tempDir);
+            });
+            afterEach(function() {
+                shell.rm('-rf', path.join(tempDir, 'platforms', 'android'));
+                process.chdir(cwd);
+            });
+
+            it('should fire before hooks through the hooker module', function() {
+                cordova.prepare();
+                expect(s).toHaveBeenCalledWith('before_prepare', jasmine.any(Function));
+            });
+            it('should fire after hooks through the hooker module', function() {
+                spyOn(shell, 'exec');
+                cordova.prepare('android', function() {
+                     expect(hooker.prototype.fire).toHaveBeenCalledWith('after_prepare');
+                });
+            });
+        });
+
+        describe('with no platforms added', function() {
+            beforeEach(function() {
+                shell.rm('-rf', tempDir);
+                cordova.create(tempDir);
+                process.chdir(tempDir);
+            });
+            afterEach(function() {
+                process.chdir(cwd);
+            });
+            it('should not fire the hooker', function() {
+                expect(function() {
+                    cordova.prepare();
+                }).toThrow();
+                expect(s).not.toHaveBeenCalledWith('before_prepare');
+                expect(s).not.toHaveBeenCalledWith('after_prepare');
+            });
+        });
+    });
+});

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/spec/run.spec.js
----------------------------------------------------------------------
diff --git a/spec/run.spec.js b/spec/run.spec.js
new file mode 100644
index 0000000..7e505ef
--- /dev/null
+++ b/spec/run.spec.js
@@ -0,0 +1,141 @@
+/**
+    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.
+*/
+var cordova = require('../../cordova'),
+    et = require('elementtree'),
+    shell = require('shelljs'),
+    path = require('path'),
+    fs = require('fs'),
+    config_parser = require('../../src/config_parser'),
+    android_parser = require('../../src/metadata/android_parser'),
+    hooker = require('../../src/hooker'),
+    fixtures = path.join(__dirname, '..', 'fixtures'),
+    hooks = path.join(fixtures, 'hooks'),
+    tempDir = path.join(__dirname, '..', '..', 'temp'),
+    cordova_project = path.join(fixtures, 'projects', 'cordova');
+
+var cwd = process.cwd();
+
+describe('run command', function() {
+    beforeEach(function() {
+        shell.rm('-rf', tempDir);
+        cordova.create(tempDir);
+    });
+
+    describe('failure', function() {
+        afterEach(function() {
+            process.chdir(cwd);
+        });
+        it('should not run inside a Cordova-based project with no added platforms', function() {
+            process.chdir(tempDir);
+            expect(function() {
+                cordova.run();
+            }).toThrow();
+        });
+        it('should not run outside of a Cordova-based project', function() {
+            shell.mkdir('-p', tempDir);
+            process.chdir(tempDir);
+
+            expect(function() {
+                cordova.run();
+            }).toThrow();
+        });
+    });
+    
+    describe('success', function() {
+        beforeEach(function() {
+            shell.cp('-Rf', path.join(cordova_project, 'platforms', 'android'), path.join(tempDir, 'platforms'));
+            process.chdir(tempDir);
+        });
+        afterEach(function() {
+            process.chdir(cwd);
+        });
+        it('should invoke prepare', function() {
+            var spy = spyOn(cordova, 'prepare');
+            spyOn(shell, 'exec');
+            cordova.run();
+            expect(spy).toHaveBeenCalled();
+        });
+        it('should shell out to underlying `run` platform-level scripts', function(done) {
+            spyOn(cordova, 'prepare').andCallFake(function(platforms, callback) {
+                callback(false);
+            });
+            var spy = spyOn(shell, 'exec').andCallFake(function(cmd, options, cb) {
+                cb(0, 'yep');
+            });
+            cordova.run('android', function() {
+                 expect(spy.mostRecentCall.args[0]).toMatch(/cordova.run" --device$/gi);
+                 done();
+            });
+        });
+    });
+
+
+    describe('hooks', function() {
+        var s;
+        beforeEach(function() {
+            s = spyOn(hooker.prototype, 'fire').andCallFake(function(hook, opts, cb) {
+                if (cb) cb();
+                else opts();
+            });
+        });
+
+        describe('when platforms are added', function() {
+            beforeEach(function() {
+                shell.cp('-Rf', path.join(cordova_project, 'platforms', 'android'), path.join(tempDir, 'platforms'));
+                process.chdir(tempDir);
+            });
+            afterEach(function() {
+                process.chdir(cwd);
+            });
+
+            it('should fire before hooks through the hooker module', function() {
+
+                spyOn(shell, 'exec');
+                cordova.run();
+                expect(hooker.prototype.fire).toHaveBeenCalledWith('before_run', {platforms:['android']}, jasmine.any(Function));
+            });
+            it('should fire after hooks through the hooker module', function(done) {
+                spyOn(shell, 'exec').andCallFake(function(cmd, options, callback) {
+                    callback(0, 'fucking eh');
+                });
+                cordova.run('android', function() {
+                     expect(hooker.prototype.fire).toHaveBeenCalledWith('after_run', {platforms:['android']}, jasmine.any(Function));
+                     done();
+                });
+            });
+        });
+
+        describe('with no platforms added', function() {
+            beforeEach(function() {
+                process.chdir(tempDir);
+            });
+            afterEach(function() {
+                process.chdir(cwd);
+            });
+            it('should not fire the hooker', function() {
+                spyOn(shell, 'exec');
+                expect(function() {
+                    cordova.run();
+                }).toThrow();
+                expect(s).not.toHaveBeenCalledWith('before_run');
+                expect(s).not.toHaveBeenCalledWith('after_run');
+            });
+        });
+    });
+});

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/spec/serve.spec.js
----------------------------------------------------------------------
diff --git a/spec/serve.spec.js b/spec/serve.spec.js
new file mode 100644
index 0000000..0139da8
--- /dev/null
+++ b/spec/serve.spec.js
@@ -0,0 +1,134 @@
+
+/**
+    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.
+*/
+var cordova = require('../../cordova'),
+    path = require('path'),
+    shell = require('shelljs'),
+    request = require('request'),
+    fs = require('fs'),
+    util = require('../../src/util'),
+    hooker = require('../../src/hooker'),
+    tempDir = path.join(__dirname, '..', '..', 'temp'),
+    http = require('http'),
+    android_parser = require('../../src/metadata/android_parser'),
+    ios_parser = require('../../src/metadata/ios_parser'),
+    blackberry_parser = require('../../src/metadata/blackberry_parser'),
+    wp7_parser        = require('../../src/metadata/wp7_parser'),
+    wp8_parser        = require('../../src/metadata/wp8_parser');
+
+var cwd = process.cwd();
+
+xdescribe('serve command', function() {
+    beforeEach(function() {
+        // Make a temp directory
+        shell.rm('-rf', tempDir);
+        shell.mkdir('-p', tempDir);
+    });
+    it('should not run outside of a Cordova-based project', function() {
+        this.after(function() {
+            process.chdir(cwd);
+        });
+
+        process.chdir(tempDir);
+
+        expect(function() {
+            cordova.serve('android');
+        }).toThrow();
+    });
+
+
+    describe('`serve`', function() {
+        var payloads = {
+            android: 'This is the Android test file.',
+            ios: 'This is the iOS test file.'
+        };
+
+        beforeEach(function() {
+            cordova.create(tempDir);
+            process.chdir(tempDir);
+            cordova.platform('add', 'android');
+            cordova.platform('add', 'ios');
+
+            // Write testing HTML files into the directory.
+            fs.writeFileSync(path.join(tempDir, 'platforms', 'android', 'assets', 'www', 'test.html'), payloads.android);
+            fs.writeFileSync(path.join(tempDir, 'platforms', 'ios', 'www', 'test.html'), payloads.ios);
+        });
+
+        afterEach(function() {
+            process.chdir(cwd);
+        });
+
+        function test_serve(platform, path, expectedContents, port) {
+            return function() {
+                var ret;
+                runs(function() {
+                    ret = port ? cordova.serve(platform, port) : cordova.serve(platform);
+                });
+
+                waitsFor(function() {
+                    return ret.server;
+                }, 'the server should start', 1000);
+
+                var done, errorCB;
+                runs(function() {
+                    expect(ret.server).toBeDefined();
+                    errorCB = jasmine.createSpy();
+                    http.get({
+                        host: 'localhost',
+                        port: port || 8000,
+                        path: path
+                    }).on('response', function(res) {
+                        var response = '';
+                        res.on('data', function(data) {
+                            response += data;
+                        });
+                        res.on('end', function() {
+                            expect(res.statusCode).toEqual(200);
+                            expect(response).toEqual(expectedContents);
+                            done = true;
+                        });
+                    }).on('error', errorCB);
+                });
+
+                waitsFor(function() {
+                    return done;
+                }, 'the HTTP request should complete', 1000);
+
+                runs(function() {
+                    expect(done).toBeTruthy();
+                    expect(errorCB).not.toHaveBeenCalled();
+
+                    ret.server.close();
+                });
+            };
+        };
+
+        it('should serve from top-level www if the file exists there', function() {
+            var payload = 'This is test file.';
+            fs.writeFileSync(path.join(util.projectWww(tempDir), 'test.html'), payload);
+            test_serve('android', '/test.html', payload)();
+        });
+
+        it('should fall back to assets/www on Android', test_serve('android', '/test.html', payloads.android));
+        it('should fall back to www on iOS', test_serve('ios', '/test.html', payloads.ios));
+
+        it('should honour a custom port setting', test_serve('android', '/test.html', payloads.android, 9001));
+    });
+});
+

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/spec/util.spec.js
----------------------------------------------------------------------
diff --git a/spec/util.spec.js b/spec/util.spec.js
new file mode 100644
index 0000000..a57d551
--- /dev/null
+++ b/spec/util.spec.js
@@ -0,0 +1,13 @@
+var cordova = require('../../cordova'),
+    shell = require('shelljs'),
+    path = require('path'),
+    fs = require('fs'),
+    cordova_util = require('../../src/util'),
+    fixtures = path.join(__dirname, '..', 'fixtures');
+
+var cwd = process.cwd();
+
+describe('util module', function() {
+    describe('isCordova method', function() {
+    });
+});

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/src/config_parser.js
----------------------------------------------------------------------
diff --git a/src/config_parser.js b/src/config_parser.js
index 082b7f2..33a1c38 100644
--- a/src/config_parser.js
+++ b/src/config_parser.js
@@ -1,4 +1,3 @@
-
 /**
     Licensed to the Apache Software Foundation (ASF) under one
     or more contributor license agreements.  See the NOTICE file


[3/3] git commit: fixing platform add with new lazy load

Posted by fi...@apache.org.
fixing platform add with new lazy load


Project: http://git-wip-us.apache.org/repos/asf/cordova-cli/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-cli/commit/0c2ffe44
Tree: http://git-wip-us.apache.org/repos/asf/cordova-cli/tree/0c2ffe44
Diff: http://git-wip-us.apache.org/repos/asf/cordova-cli/diff/0c2ffe44

Branch: refs/heads/lazy
Commit: 0c2ffe4412d18db9aa06436c5c349020513b6be6
Parents: 1569274
Author: Fil Maj <ma...@gmail.com>
Authored: Wed Jun 12 14:49:13 2013 -0700
Committer: Fil Maj <ma...@gmail.com>
Committed: Wed Jun 12 14:49:13 2013 -0700

----------------------------------------------------------------------
 platforms.js                      |   2 +-
 src/metadata/android_parser.js    |   4 +-
 src/metadata/blackberry_parser.js |   8 +-
 src/metadata/ios_parser.js        |   2 +-
 src/metadata/wp7_parser.js        |   4 +-
 src/metadata/wp8_parser.js        |   4 +-
 src/platform.js                   | 169 ++++++++++++++++++---------------
 7 files changed, 107 insertions(+), 86 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/0c2ffe44/platforms.js
----------------------------------------------------------------------
diff --git a/platforms.js b/platforms.js
index 7d894b4..0096fcb 100644
--- a/platforms.js
+++ b/platforms.js
@@ -24,7 +24,7 @@ module.exports = {
     }, 
     'android' : {
         parser : require('./src/metadata/android_parser'),
-        url    : 'https://git-wip-us.apache.org/repos/asf?p=cordova-ios.git'
+        url    : 'https://git-wip-us.apache.org/repos/asf?p=cordova-android.git'
     }, 
     'wp7' : {
         parser : require('./src/metadata/wp7_parser'),

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/0c2ffe44/src/metadata/android_parser.js
----------------------------------------------------------------------
diff --git a/src/metadata/android_parser.js b/src/metadata/android_parser.js
index dce21e2..c109b1a 100644
--- a/src/metadata/android_parser.js
+++ b/src/metadata/android_parser.js
@@ -51,7 +51,7 @@ module.exports.check_requirements = function(callback) {
             if (output.indexOf('android-17') == -1) {
                 callback('Please install Android target 17 (the Android 4.2 SDK). Make sure you have the latest Android tools installed as well. Run `android` from your command-line to install/update any missing SDKs or tools.');
             } else {
-                var cmd = 'android update project -p ' + path.join(util.libDirectory, 'cordova-android-' + util.cordovaTag, 'framework') + ' -t android-17';
+                var cmd = 'android update project -p ' + path.join(util.libDirectory, 'android', 'cordova', util.cordovaTag, 'framework') + ' -t android-17';
                 events.emit('log', 'Running "' + cmd + '" (output to follow)...');
                 shell.exec(cmd, {silent:true, async:true}, function(code, output) {
                     events.emit('log', output);
@@ -160,7 +160,7 @@ module.exports.prototype = {
         shell.cp('-rf', www, platformWww);
 
         // write out android lib's cordova.js
-        var jsPath = path.join(util.libDirectory, 'cordova-android-' + util.cordovaTag, 'framework', 'assets', 'www', 'cordova.js');
+        var jsPath = path.join(util.libDirectory, 'android', 'cordova', util.cordovaTag, 'framework', 'assets', 'www', 'cordova.js');
         fs.writeFileSync(path.join(this.www_dir(), 'cordova.js'), fs.readFileSync(jsPath, 'utf-8'), 'utf-8');
 
     },

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/0c2ffe44/src/metadata/blackberry_parser.js
----------------------------------------------------------------------
diff --git a/src/metadata/blackberry_parser.js b/src/metadata/blackberry_parser.js
index 853ae03..a9b03c5 100644
--- a/src/metadata/blackberry_parser.js
+++ b/src/metadata/blackberry_parser.js
@@ -120,18 +120,18 @@ module.exports.prototype = {
         shell.cp('-rf', www, this.path);
 
         // add cordova.js
-        shell.cp('-f', path.join(util.libDirectory, 'cordova-blackberry-' + util.cordovaTag, 'javascript', 'cordova.blackberry10.js'), path.join(this.www_dir(), 'cordova.js'));
+        shell.cp('-f', path.join(util.libDirectory, 'blackberry', 'cordova', util.cordovaTag, 'javascript', 'cordova.blackberry10.js'), path.join(this.www_dir(), 'cordova.js'));
 
         // add webworks ext directories
-        shell.cp('-rf', path.join(util.libDirectory, 'cordova-blackberry-' + util.cordovaTag, 'framework', 'ext*'), this.www_dir());
+        shell.cp('-rf', path.join(util.libDirectory,  'blackberry', 'cordova', util.cordovaTag, 'framework', 'ext*'), this.www_dir());
 
         // add config.xml
         // @TODO should use project www/config.xml but it must use BBWP elements
-        shell.cp('-f', path.join(util.libDirectory, 'cordova-blackberry-' + util.cordovaTag, 'bin', 'templates', 'project', 'www', 'config.xml'), this.www_dir());
+        shell.cp('-f', path.join(util.libDirectory, 'blackberry', 'cordova', util.cordovaTag, 'bin', 'templates', 'project', 'www', 'config.xml'), this.www_dir());
 
         // add res/
         // @TODO remove this when config.xml is generalized
-        shell.cp('-rf', path.join(util.libDirectory, 'cordova-blackberry-' + util.cordovaTag, 'bin', 'templates', 'project', 'www', 'res'), this.www_dir());
+        shell.cp('-rf', path.join(util.libDirectory, 'blackberry', 'cordova', util.cordovaTag, 'bin', 'templates', 'project', 'www', 'res'), this.www_dir());
     },
 
     // update the overrides folder into the www folder

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/0c2ffe44/src/metadata/ios_parser.js
----------------------------------------------------------------------
diff --git a/src/metadata/ios_parser.js b/src/metadata/ios_parser.js
index 7570930..99e5a5e 100644
--- a/src/metadata/ios_parser.js
+++ b/src/metadata/ios_parser.js
@@ -177,7 +177,7 @@ module.exports.prototype = {
         shell.cp('-rf', www, this.path);
 
         // write out proper cordova.js
-        shell.cp('-f', path.join(util.libDirectory, 'cordova-ios-' + util.cordovaTag, 'CordovaLib', 'cordova.js'), path.join(project_www, 'cordova.js'));
+        shell.cp('-f', path.join(util.libDirectory, 'ios', 'cordova', util.cordovaTag, 'CordovaLib', 'cordova.js'), path.join(project_www, 'cordova.js'));
 
     },
 

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/0c2ffe44/src/metadata/wp7_parser.js
----------------------------------------------------------------------
diff --git a/src/metadata/wp7_parser.js b/src/metadata/wp7_parser.js
index 0ec0983..420231b 100644
--- a/src/metadata/wp7_parser.js
+++ b/src/metadata/wp7_parser.js
@@ -42,7 +42,7 @@ module.exports = function wp7_parser(project) {
 module.exports.check_requirements = function(callback) {
     // TODO: requires the libraries to be available.
     events.emit('log', 'Checking WP7 requirements...');
-    var command = '"' + path.join(util.libDirectory, 'cordova-wp7-' + util.cordovaTag, 'bin', 'check_reqs') + '"';
+    var command = '"' + path.join(util.libDirectory, 'wp7', 'cordova', util.cordovaTag, 'bin', 'check_reqs') + '"';
     events.emit('log', 'Running "' + command + '" (output to follow)');
     shell.exec(command, {silent:true, async:true}, function(code, output) {
         events.emit('log', output);
@@ -145,7 +145,7 @@ module.exports.prototype = {
         shell.cp('-rf', project_www, this.wp7_proj_dir);
 
         // copy over wp7 lib's cordova.js
-        var cordovajs_path = path.join(util.libDirectory, 'cordova-wp7-' + util.cordovaTag, 'templates', 'standalone', 'www', 'cordova.js');
+        var cordovajs_path = path.join(util.libDirectory, 'wp7', 'cordova', util.cordovaTag, 'templates', 'standalone', 'www', 'cordova.js');
         fs.writeFileSync(path.join(this.www_dir(), 'cordova.js'), fs.readFileSync(cordovajs_path, 'utf-8'), 'utf-8');
     },
 

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/0c2ffe44/src/metadata/wp8_parser.js
----------------------------------------------------------------------
diff --git a/src/metadata/wp8_parser.js b/src/metadata/wp8_parser.js
index 080b3ac..1a3f723 100644
--- a/src/metadata/wp8_parser.js
+++ b/src/metadata/wp8_parser.js
@@ -42,7 +42,7 @@ module.exports = function wp8_parser(project) {
 module.exports.check_requirements = function(callback) {
     events.emit('log', 'Checking WP8 requirements...');
     // TODO: requires the libraries to be available.
-    var command = '"' + path.join(util.libDirectory, 'cordova-wp8-' + util.cordovaTag, 'bin', 'check_reqs') + '"';
+    var command = '"' + path.join(util.libDirectory, 'wp8', 'cordova', util.cordovaTag, 'bin', 'check_reqs') + '"';
     events.emit('log', 'Running "' + command + '" (output to follow)');
     shell.exec(command, {silent:true, async:true}, function(code, output) {
         events.emit('log', output);
@@ -145,7 +145,7 @@ module.exports.prototype = {
         shell.cp('-rf', project_www, this.wp8_proj_dir);
 
         // copy over wp8 lib's cordova.js
-        var cordovajs_path = path.join(util.libDirectory, 'cordova-wp8-' + util.cordovaTag, 'templates', 'standalone', 'www', 'cordova.js');
+        var cordovajs_path = path.join(util.libDirectory, 'wp8', 'cordova', util.cordovaTag, 'templates', 'standalone', 'www', 'cordova.js');
         fs.writeFileSync(path.join(this.www_dir(), 'cordova.js'), fs.readFileSync(cordovajs_path, 'utf-8'), 'utf-8');
     },
 

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/0c2ffe44/src/platform.js
----------------------------------------------------------------------
diff --git a/src/platform.js b/src/platform.js
index f0537de..58be9af 100644
--- a/src/platform.js
+++ b/src/platform.js
@@ -17,6 +17,7 @@
     under the License.
 */
 var config_parser     = require('./config_parser'),
+    config            = require('./config'),
     cordova_util      = require('./util'),
     util              = require('util'),
     fs                = require('fs'),
@@ -41,13 +42,17 @@ module.exports = function platform(command, targets, callback) {
 
     var hooks = new hooker(projectRoot);
 
-    var createOverrides = function(target) {
-        shell.mkdir('-p', path.join(cordova_util.appDir(projectRoot), 'merges', target));
-    };
 
     if (arguments.length === 0) command = 'ls';
     if (targets) {
         if (!(targets instanceof Array)) targets = [targets];
+        targets.forEach(function(t) {
+            if (!(t in platforms)) {
+                var err = new Error('Platform "' + t + '" not recognized as core cordova platform.');
+                if (callback) return callback(err);
+                else throw err;
+            }
+        });
     }
 
     var xml = cordova_util.projectConfig(projectRoot);
@@ -86,77 +91,36 @@ module.exports = function platform(command, targets, callback) {
                     }
                 });
             });
-            var add_callback = n(targets.length, function() {
-                hooks.fire('before_platform_add', opts, function(err) {
-                    if (err) {
-                        if (callback) callback(err);
-                        else throw err;
-                    } else {
-                        targets.forEach(function(target) {
-                            var output = path.join(projectRoot, 'platforms', target);
-
-                            // Check if output directory already exists.
-                            if (fs.existsSync(output)) {
-                                var err = new Error('Platform "' + target + '" already exists at "' + output + '"');
-                                if (callback) callback(err);
-                                else throw err;
-                            } else {
-                                // Make sure we have minimum requirements to work with specified platform
-                                events.emit('log', 'Checking if platform "' + target + '" passes minimum requirements...');
-                                module.exports.supports(target, function(err) {
-                                    if (err) {
-                                        if (callback) callback(err);
-                                        else throw err;
-                                    } else {
-                                        // Create a platform app using the ./bin/create scripts that exist in each repo.
-                                        // Run platform's create script
-                                        var bin = path.join(cordova_util.libDirectory, 'cordova-' + target + '-' + cordova_util.cordovaTag, 'bin', 'create');
-                                        var args = (target=='ios') ? '--arc' : '';
-                                        var pkg = cfg.packageName().replace(/[^\w.]/g,'_');
-                                        var name = cfg.name().replace(/\W/g,'_');
-                                        var command = util.format('"%s" %s "%s" "%s" "%s"', bin, args, output, pkg, name);
-                                        events.emit('log', 'Running bin/create for platform "' + target + '" with command: "' + command + '" (output to follow)');
-
-                                        shell.exec(command, {silent:true,async:true}, function(code, create_output) {
-                                            events.emit('log', create_output);
-                                            if (code > 0) {
-                                                var err = new Error('An error occured during creation of ' + target + ' sub-project. ' + create_output);
-                                                if (callback) callback(err);
-                                                else throw err;
-                                            } else {
-                                                var parser = new platforms[target].parser(output);
-                                                events.emit('log', 'Updating ' + target + ' project from config.xml...');
-                                                parser.update_project(cfg, function() {
-                                                    createOverrides(target);
-                                                    end(); //platform add is done by now.
-                                                    // Install all currently installed plugins into this new platform.
-                                                    var pluginsDir = path.join(projectRoot, 'plugins');
-                                                    var plugins = fs.readdirSync(pluginsDir);
-                                                    plugins && plugins.forEach(function(plugin) {
-                                                        if (fs.statSync(path.join(projectRoot, 'plugins', plugin)).isDirectory()) {
-                                                            events.emit('log', 'Installing plugin "' + plugin + '" following successful platform add of ' + target);
-                                                            plugman.install(target, output, path.basename(plugin), pluginsDir, { www_dir: parser.staging_dir() });
-                                                        }
-                                                    });
-                                                });
-                                            }
-                                        });
-                                    }
-                                });
-                            }
-                        });
-                    }
-                });
-            });
-            targets.forEach(function(t) {
-                lazy_load(t, function(err) {
-                    if (err) {
-                        if (callback) callback(err);
-                        else throw err;
-                    } else {
-                        add_callback();
-                    }
-                });
+            var config_json = config.read(projectRoot);
+            hooks.fire('before_platform_add', opts, function(err) {
+                if (err) {
+                    if (callback) callback(err);
+                    else throw err;
+                } else {
+                    targets.forEach(function(t) {
+                        if (config_json.lib && config_json.lib[t]) {
+                            events.emit('log', 'Using custom cordova platform library for "' + t + '".');
+                            lazy_load.custom(config_json.lib[t].uri, config_json.lib[t].id, t, config_json.lib[t].version, function(err) {
+                                if (err) {
+                                    if (callback) callback(err);
+                                    else throw err;
+                                } else {
+                                    call_into_create(t, projectRoot, true /* is_custom */, cfg, config_json.lib[t].id, config_json.lib[t].version, callback, end);
+                                }
+                            });
+                        } else {
+                            events.emit('log', 'Using stock cordova platform library for "' + t + '".');
+                            lazy_load.cordova(t, function(err) {
+                                if (err) {
+                                    if (callback) callback(err);
+                                    else throw err;
+                                } else {
+                                    call_into_create(t, projectRoot, false /* is_custom */, cfg, 'cordova', cordova_util.cordovaTag, callback, end);
+                                }
+                            });
+                        }
+                    });
+                }
             });
             break;
         case 'rm':
@@ -233,3 +197,60 @@ module.exports.supports = function(name, callback) {
 for (var p in platforms) {
     module.exports[p] = platforms[p];
 }
+function createOverrides(projectRoot, target) {
+    shell.mkdir('-p', path.join(cordova_util.appDir(projectRoot), 'merges', target));
+};
+
+function call_into_create(target, projectRoot, is_custom, cfg, id, version, callback, end) {
+    var output = path.join(projectRoot, 'platforms', target);
+
+    // Check if output directory already exists.
+    if (fs.existsSync(output)) {
+        var err = new Error('Platform "' + target + '" already exists at "' + output + '"');
+        if (callback) callback(err);
+        else throw err;
+    } else {
+        // Make sure we have minimum requirements to work with specified platform
+        events.emit('log', 'Checking if platform "' + target + '" passes minimum requirements...');
+        module.exports.supports(target, function(err) {
+            if (err) {
+                if (callback) callback(err);
+                else throw err;
+            } else {
+                // Create a platform app using the ./bin/create scripts that exist in each repo.
+                // Run platform's create script
+                var bin = path.join(cordova_util.libDirectory, target, id, version, 'bin', 'create');
+                var args = (target=='ios') ? '--arc' : '';
+                var pkg = cfg.packageName().replace(/[^\w.]/g,'_');
+                var name = cfg.name().replace(/\W/g,'_');
+                var command = util.format('"%s" %s "%s" "%s" "%s"', bin, args, output, pkg, name);
+                events.emit('log', 'Running bin/create for platform "' + target + '" with command: "' + command + '" (output to follow)');
+
+                shell.exec(command, {silent:true,async:true}, function(code, create_output) {
+                    events.emit('log', create_output);
+                    if (code > 0) {
+                        var err = new Error('An error occured during creation of ' + target + ' sub-project. ' + create_output);
+                        if (callback) callback(err);
+                        else throw err;
+                    } else {
+                        var parser = new platforms[target].parser(output);
+                        events.emit('log', 'Updating ' + target + ' project from config.xml...');
+                        parser.update_project(cfg, function() {
+                            createOverrides(projectRoot, target);
+                            end(); //platform add is done by now.
+                            // Install all currently installed plugins into this new platform.
+                            var pluginsDir = path.join(projectRoot, 'plugins');
+                            var plugins = fs.readdirSync(pluginsDir);
+                            plugins && plugins.forEach(function(plugin) {
+                                if (fs.statSync(path.join(projectRoot, 'plugins', plugin)).isDirectory()) {
+                                    events.emit('log', 'Installing plugin "' + plugin + '" following successful platform add of ' + target);
+                                    plugman.install(target, output, path.basename(plugin), pluginsDir, { www_dir: parser.staging_dir() });
+                                }
+                            });
+                        });
+                    }
+                });
+            }
+        });
+    }
+}


[2/3] git commit: updating part of the config_parser specs

Posted by fi...@apache.org.
updating part of the config_parser specs


Project: http://git-wip-us.apache.org/repos/asf/cordova-cli/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-cli/commit/1569274e
Tree: http://git-wip-us.apache.org/repos/asf/cordova-cli/tree/1569274e
Diff: http://git-wip-us.apache.org/repos/asf/cordova-cli/diff/1569274e

Branch: refs/heads/lazy
Commit: 1569274ef5172321ae26cc7e73ae4fdc81413022
Parents: bd3cec5
Author: Fil Maj <ma...@gmail.com>
Authored: Wed Jun 12 11:54:46 2013 -0700
Committer: Fil Maj <ma...@gmail.com>
Committed: Wed Jun 12 11:54:46 2013 -0700

----------------------------------------------------------------------
 spec/build.spec.js                     | 126 ++++++++++++
 spec/compile.spec.js                   | 116 ++++++++++++
 spec/config_parser.spec.js             | 186 ++++++++++++++++++
 spec/cordova-cli/build.spec.js         | 126 ------------
 spec/cordova-cli/compile.spec.js       | 116 ------------
 spec/cordova-cli/config_parser.spec.js | 188 ------------------
 spec/cordova-cli/create.spec.js        | 127 -------------
 spec/cordova-cli/emulate.spec.js       | 125 ------------
 spec/cordova-cli/helper.js             |  19 --
 spec/cordova-cli/hooker.spec.js        | 202 --------------------
 spec/cordova-cli/platform.spec.js      | 284 ----------------------------
 spec/cordova-cli/plugin.spec.js        | 146 --------------
 spec/cordova-cli/plugin_parser.spec.js |  42 ----
 spec/cordova-cli/prepare.spec.js       | 153 ---------------
 spec/cordova-cli/run.spec.js           | 141 --------------
 spec/cordova-cli/serve.spec.js         | 134 -------------
 spec/cordova-cli/util.spec.js          |  13 --
 spec/create.spec.js                    | 127 +++++++++++++
 spec/emulate.spec.js                   | 125 ++++++++++++
 spec/helper.js                         |  19 ++
 spec/hooker.spec.js                    | 202 ++++++++++++++++++++
 spec/platform.spec.js                  | 284 ++++++++++++++++++++++++++++
 spec/plugin.spec.js                    | 146 ++++++++++++++
 spec/plugin_parser.spec.js             |  42 ++++
 spec/prepare.spec.js                   | 153 +++++++++++++++
 spec/run.spec.js                       | 141 ++++++++++++++
 spec/serve.spec.js                     | 134 +++++++++++++
 spec/util.spec.js                      |  13 ++
 src/config_parser.js                   |   1 -
 29 files changed, 1814 insertions(+), 1817 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/spec/build.spec.js
----------------------------------------------------------------------
diff --git a/spec/build.spec.js b/spec/build.spec.js
new file mode 100644
index 0000000..7b30414
--- /dev/null
+++ b/spec/build.spec.js
@@ -0,0 +1,126 @@
+/**
+    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.
+*/
+var cordova = require('../../cordova'),
+    shell = require('shelljs'),
+    path = require('path'),
+    fs = require('fs'),
+    events = require('../../src/events'),
+    hooker = require('../../src/hooker'),
+    tempDir = path.join(__dirname, '..', '..', 'temp');
+
+var cwd = process.cwd();
+
+describe('build command', function() {
+    beforeEach(function() {
+        shell.rm('-rf', tempDir);
+        shell.mkdir('-p', tempDir);
+    });
+
+    describe('failure', function() {
+        afterEach(function() {
+            process.chdir(cwd);
+            spyOn(shell, 'exec');
+        });
+        it('should not run inside a Cordova-based project with no added platforms', function() {
+            cordova.create(tempDir);
+            process.chdir(tempDir);
+            expect(function() {
+                cordova.build();
+            }).toThrow();
+        });
+        it('should not run outside of a Cordova-based project', function() {
+            shell.mkdir('-p', tempDir);
+            process.chdir(tempDir);
+            expect(function() {
+                cordova.build();
+            }).toThrow();
+        });
+    });
+
+    describe('success', function() {
+        beforeEach(function() {
+            cordova.create(tempDir);
+            process.chdir(tempDir);
+        });
+        afterEach(function() {
+            process.chdir(cwd);
+        });
+        it('should run inside a Cordova-based project with at least one added platform and call both prepare and compile', function(done) {
+            var prepare_spy = spyOn(cordova, 'prepare').andCallFake(function(platforms, cb) {
+                cb();
+            });
+            var compile_spy = spyOn(cordova, 'compile').andCallFake(function(platforms, cb) {
+                cb();
+            });
+
+            cordova.build(['android','ios'], function(err) {
+                expect(prepare_spy).toHaveBeenCalledWith(['android', 'ios'], jasmine.any(Function));
+                expect(compile_spy).toHaveBeenCalledWith(['android', 'ios'], jasmine.any(Function));
+                done();
+            });
+        });
+    });
+
+    describe('hooks', function() {
+        var hook_spy;
+        var prepare_spy;
+        var compile_spy;
+        beforeEach(function() {
+            hook_spy = spyOn(hooker.prototype, 'fire').andCallFake(function(hook, opts, cb) {
+                cb();
+            });
+            prepare_spy = spyOn(cordova, 'prepare').andCallFake(function(platforms, cb) {
+                cb(); 
+            });
+            compile_spy = spyOn(cordova, 'compile').andCallFake(function(platforms, cb) {
+                cb(); 
+            });
+            cordova.create(tempDir);
+            process.chdir(tempDir);
+        });
+        afterEach(function() {
+            hook_spy.reset();
+            prepare_spy.reset();
+            compile_spy.reset();
+            process.chdir(cwd);
+        });
+
+        describe('when platforms are added', function() {
+            it('should fire before hooks through the hooker module', function() {
+                cordova.build(['android', 'ios']);
+                expect(hook_spy).toHaveBeenCalledWith('before_build', {platforms:['android', 'ios']}, jasmine.any(Function));
+            });
+            it('should fire after hooks through the hooker module', function(done) {
+                cordova.build('android', function() {
+                     expect(hook_spy).toHaveBeenCalledWith('after_build', {platforms:['android']}, jasmine.any(Function));
+                     done();
+                });
+            });
+        });
+
+        describe('with no platforms added', function() {
+            it('should not fire the hooker', function() {
+                expect(function() {
+                    cordova.build();
+                }).toThrow();
+                expect(hook_spy).not.toHaveBeenCalled();
+            });
+        });
+    });
+});

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/spec/compile.spec.js
----------------------------------------------------------------------
diff --git a/spec/compile.spec.js b/spec/compile.spec.js
new file mode 100644
index 0000000..b79d889
--- /dev/null
+++ b/spec/compile.spec.js
@@ -0,0 +1,116 @@
+/**
+    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.
+*/
+var cordova = require('../../cordova'),
+    shell = require('shelljs'),
+    path = require('path'),
+    fs = require('fs'),
+    events = require('../../src/events'),
+    hooker = require('../../src/hooker'),
+    tempDir = path.join(__dirname, '..', '..', 'temp');
+
+var cwd = process.cwd();
+
+describe('compile command', function() {
+    beforeEach(function() {
+        shell.rm('-rf', tempDir);
+        shell.mkdir('-p', tempDir);
+    });
+
+    describe('failure', function() {
+        afterEach(function() {
+            process.chdir(cwd);
+        });
+        it('should not run inside a Cordova-based project with no added platforms', function() {
+            cordova.create(tempDir);
+            process.chdir(tempDir);
+            expect(function() {
+                cordova.compile();
+            }).toThrow();
+        });
+        it('should not run outside of a Cordova-based project', function() {
+            shell.mkdir('-p', tempDir);
+            process.chdir(tempDir);
+            expect(function() {
+                cordova.compile();
+            }).toThrow();
+        });
+    });
+
+    describe('success', function() {
+        beforeEach(function() {
+            cordova.create(tempDir);
+            process.chdir(tempDir);
+        });
+        afterEach(function() {
+            process.chdir(cwd);
+        });
+        it('should run inside a Cordova-based project with at least one added platform and shell out to a build command', function(done) {
+            var sh_spy = spyOn(shell, 'exec').andCallFake(function(cmd, opts, cb) {
+                cb(0, 'mhmm');
+            });
+            cordova.compile(['android', 'ios'], function(err) {
+                expect(sh_spy).toHaveBeenCalled();
+                expect(sh_spy.mostRecentCall.args[0]).toMatch(/cordova.build"$/gi);
+                done();
+            });
+        });
+    });
+
+    describe('hooks', function() {
+        var hook_spy;
+        var shell_spy;
+        beforeEach(function() {
+            hook_spy = spyOn(hooker.prototype, 'fire').andCallFake(function(hook, opts, cb) {
+                cb();
+            });
+            shell_spy = spyOn(shell, 'exec').andCallFake(function(cmd, opts, cb) {
+                cb(0, 'yup'); // fake out shell so system thinks every shell-out is successful
+            });
+            cordova.create(tempDir);
+            process.chdir(tempDir);
+        });
+        afterEach(function() {
+            hook_spy.reset();
+            shell_spy.reset();
+            process.chdir(cwd);
+        });
+
+        describe('when platforms are added', function() {
+            it('should fire before hooks through the hooker module', function() {
+                cordova.compile(['android', 'ios']);
+                expect(hook_spy).toHaveBeenCalledWith('before_compile', {platforms:['android', 'ios']}, jasmine.any(Function));
+            });
+            it('should fire after hooks through the hooker module', function(done) {
+                cordova.compile('android', function() {
+                     expect(hook_spy).toHaveBeenCalledWith('after_compile', {platforms:['android']}, jasmine.any(Function));
+                     done();
+                });
+            });
+        });
+
+        describe('with no platforms added', function() {
+            it('should not fire the hooker', function() {
+                expect(function() {
+                    cordova.compile();
+                }).toThrow();
+                expect(hook_spy).not.toHaveBeenCalled();
+            });
+        });
+    });
+});

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/spec/config_parser.spec.js
----------------------------------------------------------------------
diff --git a/spec/config_parser.spec.js b/spec/config_parser.spec.js
new file mode 100644
index 0000000..058d56b
--- /dev/null
+++ b/spec/config_parser.spec.js
@@ -0,0 +1,186 @@
+/**
+    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.
+*/
+var path = require('path'),
+    fs = require('fs'),
+    shell = require('shelljs'),
+    config_parser = require('../src/config_parser'),
+    et = require('elementtree'),
+    xml = path.join(__dirname, '..', 'templates', 'config.xml'),
+    util = require('../src/util');
+
+var xml_contents = fs.readFileSync(xml, 'utf-8');
+
+describe('config.xml parser', function () {
+    var readFile, update;
+    beforeEach(function() {
+        readFile = spyOn(fs, 'readFileSync').andReturn(xml_contents);
+        update = spyOn(config_parser.prototype, 'update');
+    });
+
+    it('should create an instance based on an xml file', function() {
+        var cfg;
+        expect(function () {
+            cfg = new config_parser(xml);
+        }).not.toThrow();
+        expect(cfg).toBeDefined();
+        expect(cfg.doc).toBeDefined();
+    });
+
+    describe('package name / id', function() {
+        var cfg;
+
+        beforeEach(function() {
+            cfg = new config_parser(xml);
+        });
+
+        it('should get the (default) packagename', function() {
+            expect(cfg.packageName()).toEqual('io.cordova.hellocordova');
+        });
+        it('should allow setting the packagename', function() {
+            cfg.packageName('this.is.bat.country');
+            expect(cfg.packageName()).toEqual('this.is.bat.country');
+        });
+        it('should write to disk after setting the packagename', function() {
+            cfg.packageName('this.is.bat.country');
+            expect(update).toHaveBeenCalled();
+        });
+    });
+
+    describe('version', function() {
+        var cfg;
+
+        beforeEach(function() {
+            cfg = new config_parser(xml);
+        });
+
+        it('should get the version', function() {
+            expect(cfg.version()).toEqual('0.0.1');
+        });
+        it('should allow setting the version', function() {
+            cfg.version('2.0.1');
+            expect(cfg.version()).toEqual('2.0.1');
+        });
+        it('should write to disk after setting the version', function() {
+            cfg.version('2.0.1');
+            expect(update).toHaveBeenCalled();
+        });
+    });
+
+    describe('app name', function() {
+        var cfg;
+
+        beforeEach(function() {
+            cfg = new config_parser(xml);
+        });
+
+        it('should get the (default) app name', function() {
+            expect(cfg.name()).toEqual('Hello Cordova');
+        });
+        it('should allow setting the app name', function() {
+            cfg.name('this.is.bat.country');
+            expect(cfg.name()).toEqual('this.is.bat.country');
+        });
+        it('should write to disk after setting the name', function() {
+            cfg.name('one toke over the line');
+            expect(update).toHaveBeenCalled();
+        });
+    });
+
+    describe('access elements (whitelist)', function() {
+        var cfg;
+
+        beforeEach(function() {
+            cfg = new config_parser(xml);
+        });
+
+        describe('getter', function() {
+            it('should get the (default) access element', function() {
+                expect(cfg.access.get()[0]).toEqual('*');
+            });
+            it('should return an array of all access origin uris via access()', function() {
+                expect(cfg.access.get() instanceof Array).toBe(true);
+            });
+        });
+        describe('setters', function() {
+            it('should allow removing a uri from the access list', function() {
+                cfg.access.remove('*');
+                expect(cfg.access.get().length).toEqual(0);
+            });
+            it('should write to disk after removing a uri', function() {
+                cfg.access.remove('*');
+                expect(update).toHaveBeenCalled();
+            });
+            it('should allow adding a new uri to the access list', function() {
+                cfg.access.add('http://canucks.com');
+                expect(cfg.access.get().length).toEqual(2);
+                expect(cfg.access.get().indexOf('http://canucks.com') > -1).toBe(true);
+            });
+            it('should write to disk after adding a uri', function() {
+                cfg.access.add('http://cordova.io');
+                expect(update).toHaveBeenCalled();
+            });
+            it('should allow removing all access elements when no parameter is specified', function() {
+                cfg.access.add('http://cordova.io');
+                cfg.access.remove();
+                expect(cfg.access.get().length).toEqual(0);
+            });
+        });
+    });
+
+    describe('preference elements', function() {
+        var cfg;
+
+        beforeEach(function() {
+            cfg = new config_parser(xml);
+        });
+
+        describe('getter', function() {
+            it('should get all preference elements', function() {
+                expect(cfg.preference.get()[0].name).toEqual('phonegap-version');
+                expect(cfg.preference.get()[0].value).toEqual('1.9.0');
+            });
+            it('should return an array of all preference name/value pairs', function() {
+                expect(cfg.preference.get() instanceof Array).toBe(true);
+            });
+        });
+        describe('setters', function() {
+            it('should allow removing a preference by name', function() {
+                cfg.preference.remove('phonegap-version');
+                expect(cfg.preference.get().length).toEqual(3);
+            });
+            it('should write to disk after removing a preference', function() {
+                cfg.preference.remove('phonegap-version');
+                expect(fs.readFileSync(xml, 'utf-8')).not.toMatch(/<preference\sname="phonegap-version"/);
+            });
+            it('should allow adding a new preference', function() {
+                cfg.preference.add({name:'UIWebViewBounce',value:'false'});
+                expect(cfg.preference.get().length).toEqual(5);
+                expect(cfg.preference.get()[4].value).toEqual('false');
+            });
+            it('should write to disk after adding a preference', function() {
+                cfg.preference.add({name:'UIWebViewBounce',value:'false'});
+                expect(fs.readFileSync(xml, 'utf-8')).toMatch(/<preference name="UIWebViewBounce" value="false"/);
+            });
+            it('should allow removing all preference elements when no parameter is specified', function() {
+                cfg.preference.remove();
+                expect(fs.readFileSync(xml, 'utf-8')).not.toMatch(/<preference.*\/>/);
+            });
+        });
+    });
+});

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/spec/cordova-cli/build.spec.js
----------------------------------------------------------------------
diff --git a/spec/cordova-cli/build.spec.js b/spec/cordova-cli/build.spec.js
deleted file mode 100644
index 7b30414..0000000
--- a/spec/cordova-cli/build.spec.js
+++ /dev/null
@@ -1,126 +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.
-*/
-var cordova = require('../../cordova'),
-    shell = require('shelljs'),
-    path = require('path'),
-    fs = require('fs'),
-    events = require('../../src/events'),
-    hooker = require('../../src/hooker'),
-    tempDir = path.join(__dirname, '..', '..', 'temp');
-
-var cwd = process.cwd();
-
-describe('build command', function() {
-    beforeEach(function() {
-        shell.rm('-rf', tempDir);
-        shell.mkdir('-p', tempDir);
-    });
-
-    describe('failure', function() {
-        afterEach(function() {
-            process.chdir(cwd);
-            spyOn(shell, 'exec');
-        });
-        it('should not run inside a Cordova-based project with no added platforms', function() {
-            cordova.create(tempDir);
-            process.chdir(tempDir);
-            expect(function() {
-                cordova.build();
-            }).toThrow();
-        });
-        it('should not run outside of a Cordova-based project', function() {
-            shell.mkdir('-p', tempDir);
-            process.chdir(tempDir);
-            expect(function() {
-                cordova.build();
-            }).toThrow();
-        });
-    });
-
-    describe('success', function() {
-        beforeEach(function() {
-            cordova.create(tempDir);
-            process.chdir(tempDir);
-        });
-        afterEach(function() {
-            process.chdir(cwd);
-        });
-        it('should run inside a Cordova-based project with at least one added platform and call both prepare and compile', function(done) {
-            var prepare_spy = spyOn(cordova, 'prepare').andCallFake(function(platforms, cb) {
-                cb();
-            });
-            var compile_spy = spyOn(cordova, 'compile').andCallFake(function(platforms, cb) {
-                cb();
-            });
-
-            cordova.build(['android','ios'], function(err) {
-                expect(prepare_spy).toHaveBeenCalledWith(['android', 'ios'], jasmine.any(Function));
-                expect(compile_spy).toHaveBeenCalledWith(['android', 'ios'], jasmine.any(Function));
-                done();
-            });
-        });
-    });
-
-    describe('hooks', function() {
-        var hook_spy;
-        var prepare_spy;
-        var compile_spy;
-        beforeEach(function() {
-            hook_spy = spyOn(hooker.prototype, 'fire').andCallFake(function(hook, opts, cb) {
-                cb();
-            });
-            prepare_spy = spyOn(cordova, 'prepare').andCallFake(function(platforms, cb) {
-                cb(); 
-            });
-            compile_spy = spyOn(cordova, 'compile').andCallFake(function(platforms, cb) {
-                cb(); 
-            });
-            cordova.create(tempDir);
-            process.chdir(tempDir);
-        });
-        afterEach(function() {
-            hook_spy.reset();
-            prepare_spy.reset();
-            compile_spy.reset();
-            process.chdir(cwd);
-        });
-
-        describe('when platforms are added', function() {
-            it('should fire before hooks through the hooker module', function() {
-                cordova.build(['android', 'ios']);
-                expect(hook_spy).toHaveBeenCalledWith('before_build', {platforms:['android', 'ios']}, jasmine.any(Function));
-            });
-            it('should fire after hooks through the hooker module', function(done) {
-                cordova.build('android', function() {
-                     expect(hook_spy).toHaveBeenCalledWith('after_build', {platforms:['android']}, jasmine.any(Function));
-                     done();
-                });
-            });
-        });
-
-        describe('with no platforms added', function() {
-            it('should not fire the hooker', function() {
-                expect(function() {
-                    cordova.build();
-                }).toThrow();
-                expect(hook_spy).not.toHaveBeenCalled();
-            });
-        });
-    });
-});

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/spec/cordova-cli/compile.spec.js
----------------------------------------------------------------------
diff --git a/spec/cordova-cli/compile.spec.js b/spec/cordova-cli/compile.spec.js
deleted file mode 100644
index b79d889..0000000
--- a/spec/cordova-cli/compile.spec.js
+++ /dev/null
@@ -1,116 +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.
-*/
-var cordova = require('../../cordova'),
-    shell = require('shelljs'),
-    path = require('path'),
-    fs = require('fs'),
-    events = require('../../src/events'),
-    hooker = require('../../src/hooker'),
-    tempDir = path.join(__dirname, '..', '..', 'temp');
-
-var cwd = process.cwd();
-
-describe('compile command', function() {
-    beforeEach(function() {
-        shell.rm('-rf', tempDir);
-        shell.mkdir('-p', tempDir);
-    });
-
-    describe('failure', function() {
-        afterEach(function() {
-            process.chdir(cwd);
-        });
-        it('should not run inside a Cordova-based project with no added platforms', function() {
-            cordova.create(tempDir);
-            process.chdir(tempDir);
-            expect(function() {
-                cordova.compile();
-            }).toThrow();
-        });
-        it('should not run outside of a Cordova-based project', function() {
-            shell.mkdir('-p', tempDir);
-            process.chdir(tempDir);
-            expect(function() {
-                cordova.compile();
-            }).toThrow();
-        });
-    });
-
-    describe('success', function() {
-        beforeEach(function() {
-            cordova.create(tempDir);
-            process.chdir(tempDir);
-        });
-        afterEach(function() {
-            process.chdir(cwd);
-        });
-        it('should run inside a Cordova-based project with at least one added platform and shell out to a build command', function(done) {
-            var sh_spy = spyOn(shell, 'exec').andCallFake(function(cmd, opts, cb) {
-                cb(0, 'mhmm');
-            });
-            cordova.compile(['android', 'ios'], function(err) {
-                expect(sh_spy).toHaveBeenCalled();
-                expect(sh_spy.mostRecentCall.args[0]).toMatch(/cordova.build"$/gi);
-                done();
-            });
-        });
-    });
-
-    describe('hooks', function() {
-        var hook_spy;
-        var shell_spy;
-        beforeEach(function() {
-            hook_spy = spyOn(hooker.prototype, 'fire').andCallFake(function(hook, opts, cb) {
-                cb();
-            });
-            shell_spy = spyOn(shell, 'exec').andCallFake(function(cmd, opts, cb) {
-                cb(0, 'yup'); // fake out shell so system thinks every shell-out is successful
-            });
-            cordova.create(tempDir);
-            process.chdir(tempDir);
-        });
-        afterEach(function() {
-            hook_spy.reset();
-            shell_spy.reset();
-            process.chdir(cwd);
-        });
-
-        describe('when platforms are added', function() {
-            it('should fire before hooks through the hooker module', function() {
-                cordova.compile(['android', 'ios']);
-                expect(hook_spy).toHaveBeenCalledWith('before_compile', {platforms:['android', 'ios']}, jasmine.any(Function));
-            });
-            it('should fire after hooks through the hooker module', function(done) {
-                cordova.compile('android', function() {
-                     expect(hook_spy).toHaveBeenCalledWith('after_compile', {platforms:['android']}, jasmine.any(Function));
-                     done();
-                });
-            });
-        });
-
-        describe('with no platforms added', function() {
-            it('should not fire the hooker', function() {
-                expect(function() {
-                    cordova.compile();
-                }).toThrow();
-                expect(hook_spy).not.toHaveBeenCalled();
-            });
-        });
-    });
-});

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/spec/cordova-cli/config_parser.spec.js
----------------------------------------------------------------------
diff --git a/spec/cordova-cli/config_parser.spec.js b/spec/cordova-cli/config_parser.spec.js
deleted file mode 100644
index 303b3d6..0000000
--- a/spec/cordova-cli/config_parser.spec.js
+++ /dev/null
@@ -1,188 +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.
-*/
-var cordova = require('../../cordova'),
-    path = require('path'),
-    fs = require('fs'),
-    shell = require('shelljs'),
-    config_parser = require('../../src/config_parser'),
-    tempDir = path.join(__dirname, '..', '..', 'temp'),
-    et = require('elementtree'),
-    util = require('../../src/util'),
-    xml = util.projectConfig(tempDir);
-
-
-describe('config.xml parser', function () {
-    beforeEach(function() {
-        shell.rm('-rf', tempDir);
-        cordova.create(tempDir);
-    });
-
-    it('should create an instance based on an xml file', function() {
-        var cfg;
-        expect(function () {
-            cfg = new config_parser(xml);
-        }).not.toThrow();
-        expect(cfg).toBeDefined();
-        expect(cfg.doc).toBeDefined();
-    });
-
-    describe('package name / id', function() {
-        var cfg;
-
-        beforeEach(function() {
-            cfg = new config_parser(xml);
-        });
-
-        it('should get the (default) packagename', function() {
-            expect(cfg.packageName()).toEqual('io.cordova.hellocordova');
-        });
-        it('should allow setting the packagename', function() {
-            cfg.packageName('this.is.bat.country');
-            expect(cfg.packageName()).toEqual('this.is.bat.country');
-        });
-        it('should write to disk after setting the packagename', function() {
-            cfg.packageName('this.is.bat.country');
-            expect(fs.readFileSync(xml, 'utf-8')).toMatch(/id="this\.is\.bat\.country"/);
-        });
-    });
-
-    describe('version', function() {
-        var cfg;
-
-        beforeEach(function() {
-            cfg = new config_parser(xml);
-        });
-
-        it('should get the version', function() {
-            expect(cfg.version()).toEqual('2.0.0');
-        });
-        it('should allow setting the version', function() {
-            cfg.version('2.0.1');
-            expect(cfg.version()).toEqual('2.0.1');
-        });
-        it('should write to disk after setting the version', function() {
-            cfg.version('2.0.1');
-            expect(fs.readFileSync(xml, 'utf-8')).toMatch(/version="2.0.1"/);
-        });
-    });
-
-    describe('app name', function() {
-        var cfg;
-
-        beforeEach(function() {
-            cfg = new config_parser(xml);
-        });
-
-        it('should get the (default) app name', function() {
-            expect(cfg.name()).toEqual('HelloCordova');
-        });
-        it('should allow setting the app name', function() {
-            cfg.name('this.is.bat.country');
-            expect(cfg.name()).toEqual('this.is.bat.country');
-        });
-        it('should write to disk after setting the name', function() {
-            cfg.name('one toke over the line');
-            expect(fs.readFileSync(xml, 'utf-8')).toMatch(/<name>one toke over the line<\/name>/);
-        });
-    });
-
-    describe('access elements (whitelist)', function() {
-        var cfg;
-
-        beforeEach(function() {
-            cfg = new config_parser(xml);
-        });
-
-        describe('getter', function() {
-            it('should get the (default) access element', function() {
-                expect(cfg.access.get()[0]).toEqual('*');
-            });
-            it('should return an array of all access origin uris via access()', function() {
-                expect(cfg.access.get() instanceof Array).toBe(true);
-            });
-        });
-        describe('setters', function() {
-            it('should allow removing a uri from the access list', function() {
-                cfg.access.remove('*');
-                expect(cfg.access.get().length).toEqual(0);
-            });
-            it('should write to disk after removing a uri', function() {
-                cfg.access.remove('*');
-                expect(fs.readFileSync(xml, 'utf-8')).not.toMatch(/<access.*\/>/);
-            });
-            it('should allow adding a new uri to the access list', function() {
-                cfg.access.add('http://canucks.com');
-                expect(cfg.access.get().length).toEqual(2);
-                expect(cfg.access.get().indexOf('http://canucks.com') > -1).toBe(true);
-            });
-            it('should write to disk after adding a uri', function() {
-                cfg.access.add('http://cordova.io');
-                expect(fs.readFileSync(xml, 'utf-8')).toMatch(/<access origin="http:\/\/cordova\.io/);
-            });
-            it('should allow removing all access elements when no parameter is specified', function() {
-                cfg.access.add('http://cordova.io');
-                cfg.access.remove();
-
-                expect(fs.readFileSync(xml, 'utf-8')).not.toMatch(/<access.*\/>/);
-            });
-        });
-    });
-
-    describe('preference elements', function() {
-        var cfg;
-
-        beforeEach(function() {
-            cfg = new config_parser(xml);
-        });
-
-        describe('getter', function() {
-            it('should get all preference elements', function() {
-                expect(cfg.preference.get()[0].name).toEqual('phonegap-version');
-                expect(cfg.preference.get()[0].value).toEqual('1.9.0');
-            });
-            it('should return an array of all preference name/value pairs', function() {
-                expect(cfg.preference.get() instanceof Array).toBe(true);
-            });
-        });
-        describe('setters', function() {
-            it('should allow removing a preference by name', function() {
-                cfg.preference.remove('phonegap-version');
-                expect(cfg.preference.get().length).toEqual(3);
-            });
-            it('should write to disk after removing a preference', function() {
-                cfg.preference.remove('phonegap-version');
-                expect(fs.readFileSync(xml, 'utf-8')).not.toMatch(/<preference\sname="phonegap-version"/);
-            });
-            it('should allow adding a new preference', function() {
-                cfg.preference.add({name:'UIWebViewBounce',value:'false'});
-                expect(cfg.preference.get().length).toEqual(5);
-                expect(cfg.preference.get()[4].value).toEqual('false');
-            });
-            it('should write to disk after adding a preference', function() {
-                cfg.preference.add({name:'UIWebViewBounce',value:'false'});
-                expect(fs.readFileSync(xml, 'utf-8')).toMatch(/<preference name="UIWebViewBounce" value="false"/);
-            });
-            it('should allow removing all preference elements when no parameter is specified', function() {
-                cfg.preference.remove();
-                expect(fs.readFileSync(xml, 'utf-8')).not.toMatch(/<preference.*\/>/);
-            });
-        });
-    });
-});

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/spec/cordova-cli/create.spec.js
----------------------------------------------------------------------
diff --git a/spec/cordova-cli/create.spec.js b/spec/cordova-cli/create.spec.js
deleted file mode 100644
index c8f6969..0000000
--- a/spec/cordova-cli/create.spec.js
+++ /dev/null
@@ -1,127 +0,0 @@
-var cordova = require('../../cordova'),
-    path    = require('path'),
-    shell   = require('shelljs'),
-    fs      = require('fs'),
-    util    = require('../../src/util'),
-    config    = require('../../src/config'),
-    lazy_load = require('../../src/lazy_load'),
-    tempDir = path.join(__dirname, '..', '..', 'temp');
-
-describe('create command', function () {
-    var mkdir, cp, config_spy, load_cordova, load_custom, exists, config_read, parser, package, name;
-    beforeEach(function() {
-        shell.rm('-rf', tempDir);
-        mkdir = spyOn(shell, 'mkdir');
-        cp = spyOn(shell, 'cp');
-        config_spy = spyOn(cordova, 'config');
-        config_read = spyOn(config, 'read').andReturn({});
-        exists = spyOn(fs, 'existsSync').andReturn(true);
-        load_cordova = spyOn(lazy_load, 'cordova').andCallFake(function(platform, cb) {
-            cb();
-        });
-        load_custom = spyOn(lazy_load, 'custom').andCallFake(function(url, id, platform, version, cb) {
-            cb();
-        });
-        package = jasmine.createSpy('config.packageName');
-        name = jasmine.createSpy('config.name');
-        parser = spyOn(util, 'config_parser').andReturn({
-            packageName:package,
-            name:name
-        });
-    });
-
-    describe('failure', function() {
-        it('should return a help message if incorrect number of parameters is used', function() {
-            expect(cordova.create()).toMatch(/synopsis/gi);
-        });
-    });
-
-    describe('success', function() {
-        it('should create a default project if only directory is specified', function(done) {
-            cordova.create(tempDir, function() {
-                expect(mkdir).toHaveBeenCalledWith('-p', path.join(tempDir, '.cordova'));
-                expect(package).toHaveBeenCalledWith('io.cordova.hellocordova');
-                expect(name).toHaveBeenCalledWith('HelloCordova');
-                done();
-            });
-        });
-        it('should create a default project if only directory and id is specified', function(done) {
-            cordova.create(tempDir, 'ca.filmaj.canucks', function() {
-                expect(mkdir).toHaveBeenCalledWith('-p', path.join(tempDir, '.cordova'));
-                expect(package).toHaveBeenCalledWith('ca.filmaj.canucks');
-                expect(name).toHaveBeenCalledWith('HelloCordova');
-                done();
-            });
-        });
-        it('should create a project in specified directory with specified name and id', function(done) {
-            cordova.create(tempDir, 'ca.filmaj.canucks', 'IHateTheBruins', function() {
-                expect(mkdir).toHaveBeenCalledWith('-p', path.join(tempDir, '.cordova'));
-                expect(package).toHaveBeenCalledWith('ca.filmaj.canucks');
-                expect(name).toHaveBeenCalledWith('IHateTheBruins');
-                done();
-            });
-        });
-        it('should create top-level directory structure appropriate for a cordova-cli project', function(done) {
-            cordova.create(tempDir, function() {
-                expect(mkdir).toHaveBeenCalledWith('-p', path.join(tempDir, 'platforms'));
-                expect(mkdir).toHaveBeenCalledWith('-p', path.join(tempDir, 'merges'));
-                expect(mkdir).toHaveBeenCalledWith('-p', path.join(tempDir, 'plugins'));
-                expect(mkdir).toHaveBeenCalledWith('-p', path.join(tempDir, 'www'));
-                done();
-            });
-        });
-        it('should create appropriate directories for hooks', function(done) {
-            var hooks_dir = path.join(tempDir, '.cordova', 'hooks');
-            cordova.create(tempDir, function() {
-                expect(mkdir).toHaveBeenCalledWith('-p', hooks_dir);
-                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'after_build')));
-                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'after_compile')));
-                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'after_docs')));
-                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'after_emulate')));
-                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'after_platform_add')));
-                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'after_platform_rm')));
-                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'after_platform_ls')));
-                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'after_plugin_add')));
-                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'after_plugin_ls')));
-                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'after_plugin_rm')));
-                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'after_prepare')));
-                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'after_run')));
-                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'before_build')));
-                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'before_compile')));
-                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'before_docs')));
-                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'before_emulate')));
-                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'before_platform_add')));
-                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'before_platform_rm')));
-                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'before_platform_ls')));
-                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'before_plugin_add')));
-                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'before_plugin_ls')));
-                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'before_plugin_rm')));
-                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'before_prepare')));
-                expect(mkdir).toHaveBeenCalledWith( (path.join(hooks_dir, 'before_run')));
-                done();
-            });
-        });
-        it('should by default use cordova-app-hello-world as www assets', function(done) {
-            cordova.create(tempDir, function() {
-                expect(load_cordova).toHaveBeenCalledWith('www', jasmine.any(Function));
-                done();
-            });
-        });
-        it('should try to lazy load custom www location if specified', function(done) {
-            var fake_config = {
-                lib:{
-                    www:{
-                        id:'supercordova',
-                        uri:'/supacordoba',
-                        version:'1337'
-                    }
-                }
-            };
-            config_read.andReturn(fake_config);
-            cordova.create(tempDir, function() {
-                expect(load_custom).toHaveBeenCalledWith(fake_config.lib.www.uri, fake_config.lib.www.id, 'www', fake_config.lib.www.version, jasmine.any(Function));
-                done();
-            });
-        });
-    });
-});

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/spec/cordova-cli/emulate.spec.js
----------------------------------------------------------------------
diff --git a/spec/cordova-cli/emulate.spec.js b/spec/cordova-cli/emulate.spec.js
deleted file mode 100644
index 4f8e14b..0000000
--- a/spec/cordova-cli/emulate.spec.js
+++ /dev/null
@@ -1,125 +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.
-*/
-var cordova = require('../../cordova'),
-    et = require('elementtree'),
-    shell = require('shelljs'),
-    path = require('path'),
-    fs = require('fs'),
-    hooker = require('../../src/hooker'),
-    tempDir = path.join(__dirname, '..', '..', 'temp');
-
-var cwd = process.cwd();
-
-describe('emulate command', function() {
-    beforeEach(function() {
-        shell.rm('-rf', tempDir);
-        cordova.create(tempDir);
-    });
-
-    describe('failure', function() {
-        afterEach(function() {
-            process.chdir(cwd);
-        });
-        it('should not run inside a Cordova-based project with no added platforms', function() {
-            process.chdir(tempDir);
-            expect(function() {
-                cordova.emulate();
-            }).toThrow();
-        });
-        it('should not run outside of a Cordova-based project', function() {
-            shell.mkdir('-p', tempDir);
-            process.chdir(tempDir);
-
-            expect(function() {
-                cordova.emulate();
-            }).toThrow();
-        });
-    });
-
-    describe('success', function() {
-        beforeEach(function() {
-            process.chdir(tempDir);
-            spyOn(cordova, 'prepare').andCallFake(function(ps, cb) {
-                cb();
-            });
-        });
-        afterEach(function() {
-            process.chdir(cwd);
-        });
-        it('should run inside a Cordova-based project with at least one added platform', function(done) {
-            var s = spyOn(shell, 'exec').andCallFake(function(cmd, opts, cb) {
-                cb(0, 'yokay');
-            });
-            cordova.emulate(['android', 'beer'], function(err) {
-                expect(s).toHaveBeenCalled();
-                expect(s.mostRecentCall.args[0]).toMatch(/cordova.run" --emulator$/gi);
-                done();
-            });
-        });
-    });
-
-    describe('hooks', function() {
-        var hook_spy;
-        var shell_spy;
-        var prepare_spy;
-        beforeEach(function() {
-            hook_spy = spyOn(hooker.prototype, 'fire').andCallFake(function(hook, opts, cb) {
-                if (cb) cb();
-                else opts();
-            });
-            prepare_spy = spyOn(cordova, 'prepare').andCallFake(function(ps, cb) {
-                cb();
-            });
-            shell_spy = spyOn(shell, 'exec').andCallFake(function(cmd, opts, cb) {
-                cb(0, 'yup'); // fake out shell so system thinks every shell-out is successful
-            });
-            process.chdir(tempDir);
-        });
-        afterEach(function() {
-            hook_spy.reset();
-            prepare_spy.reset();
-            shell_spy.reset();
-            process.chdir(cwd);
-        });
-
-        describe('when platforms are added', function() {
-            it('should fire before hooks through the hooker module', function(done) {
-                cordova.emulate(['android', 'ios'], function(err) {
-                    expect(hook_spy).toHaveBeenCalledWith('before_emulate', {platforms:['android', 'ios']}, jasmine.any(Function));
-                    done();
-                });
-            });
-            it('should fire after hooks through the hooker module', function(done) {
-                cordova.emulate('android', function() {
-                     expect(hook_spy).toHaveBeenCalledWith('after_emulate', {platforms:['android']}, jasmine.any(Function));
-                     done();
-                });
-            });
-        });
-
-        describe('with no platforms added', function() {
-            it('should not fire the hooker', function() {
-                expect(function() {
-                    cordova.emulate();
-                }).toThrow();
-                expect(hook_spy).not.toHaveBeenCalled();
-            });
-        });
-    });
-});

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/spec/cordova-cli/helper.js
----------------------------------------------------------------------
diff --git a/spec/cordova-cli/helper.js b/spec/cordova-cli/helper.js
deleted file mode 100644
index 351e6e4..0000000
--- a/spec/cordova-cli/helper.js
+++ /dev/null
@@ -1,19 +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.
-*/
-jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/spec/cordova-cli/hooker.spec.js
----------------------------------------------------------------------
diff --git a/spec/cordova-cli/hooker.spec.js b/spec/cordova-cli/hooker.spec.js
deleted file mode 100644
index 6b0129a..0000000
--- a/spec/cordova-cli/hooker.spec.js
+++ /dev/null
@@ -1,202 +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.
-*/
-var hooker = require('../../src/hooker'),
-    shell  = require('shelljs'),
-    path   = require('path'),
-    fs     = require('fs'),
-    os     = require('os'),
-    tempDir= path.join(__dirname, '..', '..', 'temp'),
-    hooks  = path.join(__dirname, '..', 'fixtures', 'hooks'),
-    cordova= require('../../cordova');
-
-var platform = os.platform();
-var cwd = process.cwd();
-
-describe('hooker', function() {
-    it('should throw if provided directory is not a cordova project', function() {
-        shell.rm('-rf', tempDir);
-        shell.mkdir('-p', tempDir); 
-        this.after(function() {
-            shell.rm('-rf', tempDir);
-        });
-
-        expect(function() {
-            var h = new hooker(tempDir);
-        }).toThrow();
-    });
-    it('should not throw if provided directory is a cordova project', function() {
-        cordova.create(tempDir);
-        this.after(function() {
-            shell.rm('-rf', tempDir);
-        });
-
-        expect(function() {
-            var h = new hooker(tempDir);
-        }).not.toThrow();
-    });
-
-    describe('fire method', function() {
-        var h;
-
-        beforeEach(function() {
-            cordova.create(tempDir);
-            h = new hooker(tempDir);
-        });
-        afterEach(function() {
-            shell.rm('-rf', tempDir);
-        });
-
-        describe('failure', function() {
-            it('should not error if the hook is unrecognized', function(done) {
-                h.fire('CLEAN YOUR SHORTS GODDAMNIT LIKE A BIG BOY!', function(err){
-                    expect(err).not.toBeDefined();
-                    done();
-                });
-            });
-            it('should error if any script exits with non-zero code', function(done) {
-                var script;
-                if (platform.match(/(win32|win64)/)) {
-                    script = path.join(tempDir, '.cordova', 'hooks', 'before_build', 'fail.bat');
-                    shell.cp(path.join(hooks, 'fail', 'fail.bat'), script);
-                } else {
-                    script = path.join(tempDir, '.cordova', 'hooks', 'before_build', 'fail.sh');
-                    shell.cp(path.join(hooks, 'fail', 'fail.sh'), script);
-                }
-                fs.chmodSync(script, '754');
-                h.fire('before_build', function(err){
-                    expect(err).toBeDefined();
-                    done();
-                });
-            });
-        });
-
-        describe('success', function() {
-            it('should execute all scripts in order and fire callback', function(done) {
-                var hook = path.join(tempDir, '.cordova', 'hooks', 'before_build');
-                if (platform.match(/(win32|win64)/)) {
-                    shell.cp(path.join(hooks, 'test', '0.bat'), hook);
-                    shell.cp(path.join(hooks, 'test', '1.bat'), hook);
-                } else {
-                    shell.cp(path.join(hooks, 'test', '0.sh'), hook);
-                    shell.cp(path.join(hooks, 'test', '1.sh'), hook);
-                }
-                fs.readdirSync(hook).forEach(function(script) {
-                    fs.chmodSync(path.join(hook, script), '754');
-                });
-                var returnValue;
-                var s = spyOn(shell, 'exec').andCallFake(function(cmd, opts, cb) {
-                    cb(0, '');
-                });
-                h.fire('before_build', function(err) {
-                    expect(err).not.toBeDefined();
-                    if (platform.match(/(win32|win64)/)) {
-                        expect(s.calls[0].args[0]).toMatch(/0.bat/);
-                        expect(s.calls[1].args[0]).toMatch(/1.bat/);
-                    } else {
-                        expect(s.calls[0].args[0]).toMatch(/0.sh/);
-                        expect(s.calls[1].args[0]).toMatch(/1.sh/);
-                    }
-                    done();
-                });
-            });
-            it('should pass the project root folder as parameter into the project-level hooks', function(done) {
-                var hook = path.join(tempDir, '.cordova', 'hooks', 'before_build');
-                if (platform.match(/(win32|win64)/)) {
-                    shell.cp(path.join(hooks, 'test', '0.bat'), hook);
-                } else {
-                    shell.cp(path.join(hooks, 'test', '0.sh'), hook);
-                }
-                fs.readdirSync(hook).forEach(function(script) {
-                    fs.chmodSync(path.join(hook, script), '754');
-                });
-                var s = spyOn(shell, 'exec').andCallFake(function(cmd, opts, cb) {
-                    cb(0, '');
-                });
-                h.fire('before_build', function(err) {
-                    expect(err).not.toBeDefined();
-                    var param_str;
-                    if (platform.match(/(win32|win64)/)) {
-                        param_str = '0.bat "'+tempDir+'"';
-                    } else { 
-                        param_str = '0.sh "'+tempDir+'"'; 
-                    }
-                    expect(s.calls[0].args[0].indexOf(param_str)).not.toEqual(-1);
-                    done();
-                });
-            });
-            describe('module-level hooks', function() {
-                var handler = jasmine.createSpy();
-                var test_event = 'before_build';
-                afterEach(function() {
-                    cordova.off(test_event, handler);
-                    handler.reset();
-                });
-
-                it('should fire handlers using cordova.on', function(done) {
-                    cordova.on(test_event, handler);
-                    h.fire(test_event, function(err) {
-                        expect(handler).toHaveBeenCalled();
-                        expect(err).not.toBeDefined();
-                        done();
-                    });
-                });
-                it('should pass the project root folder as parameter into the module-level handlers', function(done) {
-                    cordova.on(test_event, handler);
-                    h.fire(test_event, function(err) {
-                        expect(handler).toHaveBeenCalledWith({root:tempDir});
-                        expect(err).not.toBeDefined();
-                        done();
-                    });
-                });
-                it('should be able to stop listening to events using cordova.off', function(done) {
-                    cordova.on(test_event, handler);
-                    cordova.off(test_event, handler);
-                    h.fire(test_event, function(err) {
-                        expect(handler).not.toHaveBeenCalled();
-                        done();
-                    });
-                });
-                it('should allow for hook to opt into asynchronous execution and block further hooks from firing using the done callback', function(done) {
-                    var h1_fired = false;
-                    var h1 = function(root, cb) {
-                        h1_fired = true;
-                        setTimeout(cb, 100);
-                    };
-                    var h2_fired = false;
-                    var h2 = function() {
-                        h2_fired = true;
-                    };
-                    runs(function() {
-                        cordova.on(test_event, h1);
-                        cordova.on(test_event, h2);
-                        h.fire(test_event, function(err) {
-                            done();
-                        });
-                        expect(h1_fired).toBe(true);
-                        expect(h2_fired).toBe(false);
-                    });
-                    waits(100);
-                    runs(function() {
-                        expect(h2_fired).toBe(true);
-                    });
-                });
-            });
-        });
-    });
-});

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/spec/cordova-cli/platform.spec.js
----------------------------------------------------------------------
diff --git a/spec/cordova-cli/platform.spec.js b/spec/cordova-cli/platform.spec.js
deleted file mode 100644
index fed1f3b..0000000
--- a/spec/cordova-cli/platform.spec.js
+++ /dev/null
@@ -1,284 +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.
-*/
-var cordova = require('../../cordova'),
-    path = require('path'),
-    shell = require('shelljs'),
-    fs = require('fs'),
-    util = require('../../src/util'),
-    hooker = require('../../src/hooker'),
-    platform = require('../../src/platform'),
-    platforms = require('../../platforms'),
-    tempDir = path.join(__dirname, '..', '..', 'temp');
-    android_parser = require('../../src/metadata/android_parser');
-
-var cwd = process.cwd();
-
-describe('platform command', function() {
-    beforeEach(function() {
-        // Make a temp directory
-        shell.rm('-rf', tempDir);
-        shell.mkdir('-p', tempDir);
-    });
-    it('should run inside a Cordova-based project', function() {
-        this.after(function() {
-            process.chdir(cwd);
-        });
-
-        cordova.create(tempDir);
-
-        process.chdir(tempDir);
-
-        expect(function() {
-            cordova.platform();
-        }).not.toThrow();
-    });
-    it('should not run outside of a Cordova-based project', function() {
-        this.after(function() {
-            process.chdir(cwd);
-        });
-
-        process.chdir(tempDir);
-
-        expect(function() {
-            cordova.platform();
-        }).toThrow();
-    });
-
-    describe('`ls`', function() { 
-        beforeEach(function() {
-            cordova.create(tempDir);
-            process.chdir(tempDir);
-        });
-
-        afterEach(function() {
-            process.chdir(cwd);
-            cordova.removeAllListeners('results'); // clean up event listener
-        });
-
-        it('should list out no platforms for a fresh project', function(done) {
-            shell.rm('-rf', path.join(tempDir, 'platforms', '*'));
-            cordova.on('results', function(res) {
-                expect(res).toEqual('No platforms added. Use `cordova platform add <platform>`.');
-                done();
-            });
-            cordova.platform('list');
-        });
-
-        it('should list out added platforms in a project', function(done) {
-            var platforms = path.join(tempDir, 'platforms');
-            shell.mkdir(path.join(platforms, 'android'));
-            shell.mkdir(path.join(platforms, 'ios'));
-            
-            cordova.on('results', function(res) {
-                expect(res.length).toEqual(2);
-                done();
-            });
-            cordova.platform('list');
-        });
-    });
-
-    describe('`add`', function() {
-        beforeEach(function() {
-            cordova.create(tempDir);
-            process.chdir(tempDir);
-        });
-
-        afterEach(function() {
-            process.chdir(cwd);
-        });
-
-        it('should handle multiple platforms and shell out to specified platform\'s bin/create', function() {
-            spyOn(platform, 'supports').andCallFake(function(target, callback) {
-                    callback(null);
-            });
-            var sh = spyOn(shell, 'exec');
-            cordova.platform('add', ['foo', 'bar']);
-            var foo_create = path.join('foo', 'bin', 'create');
-            var bar_create = path.join('bar', 'bin', 'create');
-            expect(sh.argsForCall[0][0]).toContain(foo_create);
-            expect(sh.argsForCall[1][0]).toContain(bar_create);
-        });
-    });
-
-    describe('`remove`',function() {
-        beforeEach(function() {
-            cordova.create(tempDir);
-            process.chdir(tempDir);
-        });
-
-        afterEach(function() {
-            process.chdir(cwd);
-            cordova.removeAllListeners('results');
-        });
-
-        it('should remove a supported and added platform', function(done) {
-            shell.mkdir(path.join(tempDir, 'platforms', 'android'));
-            shell.mkdir(path.join(tempDir, 'platforms', 'ios'));
-            cordova.platform('remove', 'android', function() {
-                cordova.on('results', function(res) {
-                    expect(res.length).toEqual(1);
-                    done();
-                });
-                cordova.platform('list');
-            });
-        });
-
-        it('should be able to remove multiple platforms', function(done) {
-            shell.mkdir(path.join(tempDir, 'platforms', 'android'));
-            shell.mkdir(path.join(tempDir, 'platforms', 'blackberry'));
-            shell.mkdir(path.join(tempDir, 'platforms', 'ios'));
-            cordova.platform('remove', ['android','blackberry'], function() {
-                cordova.on('results', function(res) {
-                    expect(res.length).toEqual(1);
-                    done();
-                });
-                cordova.platform('list');
-            });
-        });
-    });
-
-    describe('hooks', function() {
-        var s;
-        beforeEach(function() {
-            cordova.create(tempDir);
-            process.chdir(tempDir);
-            s = spyOn(hooker.prototype, 'fire').andCallFake(function(hook, opts, cb) {
-                if (cb) cb();
-                else opts();
-            });
-        });
-        afterEach(function() {
-            process.chdir(cwd);
-            shell.rm('-rf', tempDir);
-        });
-
-        describe('list (ls) hooks', function() {
-            it('should fire before hooks through the hooker module', function() {
-                cordova.platform();
-                expect(s).toHaveBeenCalledWith('before_platform_ls', jasmine.any(Function));
-            });
-            it('should fire after hooks through the hooker module', function() {
-                cordova.platform();
-                expect(s).toHaveBeenCalledWith('after_platform_ls', jasmine.any(Function));
-            });
-        });
-        describe('remove (rm) hooks', function() {
-            it('should fire before hooks through the hooker module', function() {
-                cordova.platform('rm', 'android');
-                expect(s).toHaveBeenCalledWith('before_platform_rm', {platforms:['android']}, jasmine.any(Function));
-            });
-            it('should fire after hooks through the hooker module', function() {
-                cordova.platform('rm', 'android');
-                expect(s).toHaveBeenCalledWith('after_platform_rm', {platforms:['android']}, jasmine.any(Function));
-            });
-        });
-        describe('add hooks', function() {
-            var sh, cr;
-            beforeEach(function() {
-                sh = spyOn(shell, 'exec').andCallFake(function(cmd, opts, cb) {
-                    var a_path = path.join(tempDir, 'platforms','android'); 
-                    shell.mkdir('-p',a_path); 
-                    fs.writeFileSync(path.join(a_path, 'AndroidManifest.xml'), 'hi', 'utf-8');
-                    cb(0, 'mkay');
-                });
-                cr = spyOn(android_parser.prototype, 'update_project').andCallFake(function(cfg, cb) {
-                    cb();
-                });
-                spyOn(platform, 'supports').andCallFake(function (t, cb) {
-                    cb();
-                });
-            });
-            it('should fire before and after hooks through the hooker module', function() {
-                cordova.platform('add', 'android');
-                expect(s).toHaveBeenCalledWith('before_platform_add', {platforms:['android']}, jasmine.any(Function));
-                expect(s).toHaveBeenCalledWith('after_platform_add', {platforms:['android']}, jasmine.any(Function));
-            });
-        });
-    });
-});
-
-describe('platform.supports(name, callback)', function() {
-    var androidParser = require('../../src/metadata/android_parser');
-
-    beforeEach(function() {
-        spyOn(androidParser, 'check_requirements');
-    });
-
-    it('should require a platform name', function() {
-        expect(function() {
-            cordova.platform.supports(undefined, function(e){});
-        }).toThrow();
-    });
-
-    it('should require a callback function', function() {
-        expect(function() {
-            cordova.platform.supports('android', undefined);
-        }).toThrow();
-    });
-
-    describe('when platform is unknown', function() {
-        it('should trigger callback with false', function(done) {
-            cordova.platform.supports('windows-3.1', function(e) {
-                expect(e).toEqual(jasmine.any(Error));
-                done();
-            });
-        });
-    });
-
-    describe('when platform is supported', function() {
-        beforeEach(function() {
-            androidParser.check_requirements.andCallFake(function(callback) {
-                callback(null);
-            });
-        });
-
-        it('should trigger callback without error', function(done) {
-            cordova.platform.supports('android', function(e) {
-                expect(e).toBeNull();
-                done();
-            });
-        });
-    });
-
-    describe('when platform is unsupported', function() {
-        beforeEach(function() {
-            androidParser.check_requirements.andCallFake(function(callback) {
-                callback(new Error('could not find the android sdk'));
-            });
-        });
-
-        it('should trigger callback with error', function(done) {
-            cordova.platform.supports('android', function(e) {
-                expect(e).toEqual(jasmine.any(Error));
-                done();
-            });
-        });
-    });
-});
-
-describe('platform parsers', function() {
-    it('should be exposed on the platform module', function() {
-        for (var platform in platforms) {
-            expect(cordova.platform[platform]).toBeDefined();
-            for (var prop in platforms[platform]) {
-                expect(cordova.platform[platform][prop]).toBeDefined();
-            }
-        }
-    });
-});

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/spec/cordova-cli/plugin.spec.js
----------------------------------------------------------------------
diff --git a/spec/cordova-cli/plugin.spec.js b/spec/cordova-cli/plugin.spec.js
deleted file mode 100644
index d042841..0000000
--- a/spec/cordova-cli/plugin.spec.js
+++ /dev/null
@@ -1,146 +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.
-*/
-var cordova = require('../../cordova'),
-    path = require('path'),
-    shell = require('shelljs'),
-    fs = require('fs'),
-    hooker = require('../../src/hooker'),
-    tempDir = path.join(__dirname, '..', '..', 'temp'),
-    fixturesDir = path.join(__dirname, '..', 'fixtures'),
-    testPlugin = path.join(fixturesDir, 'plugins', 'test'),
-    cordova_project = path.join(fixturesDir, 'projects', 'cordova'),
-    androidPlugin = path.join(fixturesDir, 'plugins', 'android');
-
-var cwd = process.cwd();
-
-describe('plugin command', function() {
-    beforeEach(function() {
-        // Make a temp directory
-        shell.rm('-rf', tempDir);
-        shell.mkdir('-p', tempDir);
-    });
-
-    it('should run inside a Cordova-based project', function() {
-        this.after(function() {
-            process.chdir(cwd);
-        });
-
-        cordova.create(tempDir);
-
-        process.chdir(tempDir);
-
-        expect(function() {
-            cordova.plugin();
-        }).not.toThrow();
-    });
-    it('should not run outside of a Cordova-based project', function() {
-        this.after(function() {
-            process.chdir(cwd);
-        });
-
-        process.chdir(tempDir);
-
-        expect(function() {
-            cordova.plugin();
-        }).toThrow();
-    });
-
-    describe('edge cases', function() {
-       beforeEach(function() {
-           cordova.create(tempDir);
-           process.chdir(tempDir);
-       });
-
-       afterEach(function() {
-           process.chdir(cwd);
-           cordova.removeAllListeners('results');
-       });
-
-       it('should not fail when the plugins directory is missing', function() {
-           fs.rmdirSync('plugins');
-
-           expect(function() {
-               cordova.plugin();
-           }).not.toThrow();
-       });
-
-       it('should ignore files, like .gitignore, in the plugins directory', function(done) {
-           var someFile = path.join(tempDir, 'plugins', '.gitignore');
-           fs.writeFileSync(someFile, 'not a plugin');
-           cordova.on('results', function(res) {
-               expect(res).toEqual('No plugins added. Use `cordova plugin add <plugin>`.');
-               done();
-           });
-
-           cordova.plugin('list');
-       });
-    });
-
-    describe('`ls`', function() {
-        beforeEach(function() {
-            cordova.create(tempDir);
-            process.chdir(tempDir);
-        });
-
-        afterEach(function() {
-            process.chdir(cwd);
-            cordova.removeAllListeners('results');
-        });
-
-        it('should list out no plugins for a fresh project', function(done) {
-            cordova.on('results', function(res) {
-                expect(res).toEqual('No plugins added. Use `cordova plugin add <plugin>`.');
-                done();
-            });
-            cordova.plugin('list');
-        });
-        it('should list out any added plugins in a project', function(done) {
-            var random_plug = 'randomplug';
-            shell.mkdir('-p', path.join(tempDir, 'plugins', random_plug));
-            cordova.on('results', function(res) {
-                expect(res).toEqual([random_plug]);
-                done();
-            });
-            cordova.plugin('list');
-        });
-    });
-
-    describe('`add`', function() {
-        beforeEach(function() {
-            cordova.create(tempDir);
-            process.chdir(tempDir);
-        });
-
-        afterEach(function() {
-            process.chdir(cwd);
-        });
-        describe('failure', function() {
-            it('should throw if plugin does not have a plugin.xml', function() {
-                process.chdir(cordova_project);
-                this.after(function() {
-                    process.chdir(cwd);
-                });
-                expect(function() {
-                    cordova.plugin('add', fixturesDir);
-                }).toThrow();
-            });
-        });
-    });
-});
-

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/spec/cordova-cli/plugin_parser.spec.js
----------------------------------------------------------------------
diff --git a/spec/cordova-cli/plugin_parser.spec.js b/spec/cordova-cli/plugin_parser.spec.js
deleted file mode 100644
index 15b5993..0000000
--- a/spec/cordova-cli/plugin_parser.spec.js
+++ /dev/null
@@ -1,42 +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.
-*/
-var cordova = require('../../cordova'),
-    path = require('path'),
-    fs = require('fs'),
-    plugin_parser = require('../../src/plugin_parser'),
-    et = require('elementtree'),
-    xml = path.join(__dirname, '..', 'fixtures', 'plugins', 'test', 'plugin.xml');
-
-describe('plugin.xml parser', function () {
-    it('should read a proper plugin.xml file', function() {
-        var cfg;
-        expect(function () {
-            cfg = new plugin_parser(xml);
-        }).not.toThrow();
-        expect(cfg).toBeDefined();
-        expect(cfg.doc).toBeDefined();
-    });
-    it('should be able to figure out which platforms the plugin supports', function() {
-        var cfg = new plugin_parser(xml);
-        expect(cfg.platforms.length).toBe(1);
-        expect(cfg.platforms.indexOf('ios') > -1).toBe(true);
-    });
-});
-

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1569274e/spec/cordova-cli/prepare.spec.js
----------------------------------------------------------------------
diff --git a/spec/cordova-cli/prepare.spec.js b/spec/cordova-cli/prepare.spec.js
deleted file mode 100644
index d7c7d28..0000000
--- a/spec/cordova-cli/prepare.spec.js
+++ /dev/null
@@ -1,153 +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.
-*/
-var cordova = require('../../cordova'),
-    et = require('elementtree'),
-    shell = require('shelljs'),
-    plugman = require('plugman'),
-    path = require('path'),
-    fs = require('fs'),
-    config_parser = require('../../src/config_parser'),
-    android_parser = require('../../src/metadata/android_parser'),
-    hooker = require('../../src/hooker'),
-    fixtures = path.join(__dirname, '..', 'fixtures'),
-    test_plugin = path.join(fixtures, 'plugins', 'android'),
-    hooks = path.join(fixtures, 'hooks'),
-    tempDir = path.join(__dirname, '..', '..', 'temp'),
-    cordova_project = path.join(fixtures, 'projects', 'cordova');
-
-var cwd = process.cwd();
-
-describe('prepare command', function() {
-    beforeEach(function() {
-        shell.rm('-rf', tempDir);
-        cordova.create(tempDir);
-    });
-
-    it('should not run inside a Cordova-based project with no added platforms', function() {
-        this.after(function() {
-            process.chdir(cwd);
-        });
-
-        process.chdir(tempDir);
-        expect(function() {
-            cordova.prepare();
-        }).toThrow();
-    });
-    
-    it('should run inside a Cordova-based project with at least one added platform', function(done) {
-        process.chdir(tempDir);
-        var android_path = path.join(tempDir, 'platforms', 'android');
-        shell.mkdir(android_path);
-        fs.writeFileSync(path.join(android_path, 'AndroidManifest.xml'), 'hi', 'utf-8');
-        spyOn(plugman, 'prepare');
-        cordova.prepare(['android'], function(err) {
-            done();
-        });
-    });
-    it('should not run outside of a Cordova-based project', function() {
-        this.after(function() {
-            process.chdir(cwd);
-        });
-
-        shell.mkdir('-p', tempDir);
-        process.chdir(tempDir);
-
-        expect(function() {
-            cordova.prepare();
-        }).toThrow();
-    });
-
-    describe('plugman integration', function() {
-        beforeEach(function() {
-            shell.cp('-Rf', path.join(cordova_project, 'platforms', 'android'), path.join(tempDir, 'platforms'));
-            process.chdir(tempDir);
-        });
-        afterEach(function() {
-            process.chdir(cwd);
-        });
-
-        it('should invoke plugman.prepare after update_project', function() {
-            var a_parser_spy = spyOn(android_parser.prototype, 'update_project');
-            var prep_spy = spyOn(plugman, 'prepare');
-            cordova.prepare();
-            a_parser_spy.mostRecentCall.args[1](); // fake out android_parser
-            var android_path = path.join(tempDir, 'platforms', 'android');
-            var plugins_dir = path.join(tempDir, 'plugins');
-            expect(prep_spy).toHaveBeenCalledWith(android_path, 'android', plugins_dir);
-        });
-        it('should invoke add_plugin_changes for any added plugins to verify configuration changes for plugins are in place', function() {
-            var platform_path  = path.join(tempDir, 'platforms', 'android');
-            var plugins_dir = path.join(tempDir, 'plugins');
-            plugman.install('android', platform_path, test_plugin, plugins_dir, {});
-            var a_parser_spy = spyOn(android_parser.prototype, 'update_project');
-            var prep_spy = spyOn(plugman, 'prepare');
-            var plugin_changes_spy = spyOn(plugman.config_changes, 'add_plugin_changes');
-            cordova.prepare();
-            a_parser_spy.mostRecentCall.args[1](); // fake out android_parser
-            expect(plugin_changes_spy).toHaveBeenCalledWith('android', platform_path, plugins_dir, 'ca.filmaj.AndroidPlugin', {PACKAGE_NAME:"org.apache.cordova.cordovaExample"}, true, false); 
-        });
-    });
-
-    describe('hooks', function() {
-        var s;
-        beforeEach(function() {
-            s = spyOn(hooker.prototype, 'fire').andReturn(true);
-        });
-
-        describe('when platforms are added', function() {
-            beforeEach(function() {
-                shell.cp('-rf', path.join(cordova_project, 'platforms', 'android'), path.join(tempDir, 'platforms'));
-                process.chdir(tempDir);
-            });
-            afterEach(function() {
-                shell.rm('-rf', path.join(tempDir, 'platforms', 'android'));
-                process.chdir(cwd);
-            });
-
-            it('should fire before hooks through the hooker module', function() {
-                cordova.prepare();
-                expect(s).toHaveBeenCalledWith('before_prepare', jasmine.any(Function));
-            });
-            it('should fire after hooks through the hooker module', function() {
-                spyOn(shell, 'exec');
-                cordova.prepare('android', function() {
-                     expect(hooker.prototype.fire).toHaveBeenCalledWith('after_prepare');
-                });
-            });
-        });
-
-        describe('with no platforms added', function() {
-            beforeEach(function() {
-                shell.rm('-rf', tempDir);
-                cordova.create(tempDir);
-                process.chdir(tempDir);
-            });
-            afterEach(function() {
-                process.chdir(cwd);
-            });
-            it('should not fire the hooker', function() {
-                expect(function() {
-                    cordova.prepare();
-                }).toThrow();
-                expect(s).not.toHaveBeenCalledWith('before_prepare');
-                expect(s).not.toHaveBeenCalledWith('after_prepare');
-            });
-        });
-    });
-});