You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by sg...@apache.org on 2014/09/26 23:20:07 UTC

[08/13] git commit: CB-6481 Updated tests

CB-6481 Updated tests


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

Branch: refs/heads/master
Commit: eed41399786ae2ab93ff2b7a0cd3bae1f4ff721a
Parents: d8c586a
Author: daserge <da...@yandex.ru>
Authored: Tue Jul 22 15:14:53 2014 +0400
Committer: daserge <da...@yandex.ru>
Committed: Thu Sep 25 19:04:55 2014 +0400

----------------------------------------------------------------------
 cordova-lib/spec-cordova/HooksRunner.spec.js    | 613 +++++++++++++++++++
 cordova-lib/spec-cordova/build.spec.js          |   4 +-
 cordova-lib/spec-cordova/compile.spec.js        |   4 +-
 cordova-lib/spec-cordova/emulate.spec.js        |   4 +-
 .../plugins/com.plugin.withhooks/plugin.xml     |   7 +
 .../pluginOnePlatform_bat.xml                   |  19 +
 .../pluginOnePlatform_sh.xml                    |  19 +
 .../pluginOnlyNonPlatformScripts_bat.xml        |  14 +
 .../pluginOnlyNonPlatformScripts_sh.xml         |  14 +
 .../pluginTwoPlatforms_bat.xml                  |  24 +
 .../pluginTwoPlatforms_sh.xml                   |  24 +
 .../scripts/android/androidBeforeBuild.js       |   4 +
 .../scripts/android/androidBeforeInstall.js     |   4 +
 .../scripts/beforeBuild.bat                     |   2 +
 .../com.plugin.withhooks/scripts/beforeBuild.js |   4 +
 .../com.plugin.withhooks/scripts/beforeBuild.sh |   1 +
 .../scripts/beforeInstall.bat                   |   2 +
 .../scripts/beforeInstall.sh                    |   1 +
 .../scripts/beforeInstall01.js                  |   4 +
 .../scripts/beforeInstall2.js                   |   4 +
 .../scripts/beforeUninstall.js                  |   4 +
 .../scripts/windows/windowsBeforeBuild.js       |   4 +
 .../scripts/windows/windowsBeforeInstall.js     |   4 +
 .../fixtures/projWithHooks/.cordova/config.json |  22 +
 .../hooks/before_build/hookScriptDot03.js       |   4 +
 .../hooks/before_build/hookScriptDot1.js        |   4 +
 .../projWithHooks/.cordova/hooks/fail/fail.js   |   2 +
 .../hooks/before_build/hookScriptDot2.bat       |   2 +
 .../_bat/hooks/before_build/hookScript01.bat    |   2 +
 .../_bat/hooks/before_build/hookScript02.bat    |   2 +
 .../_bat/hooks/before_build/hookScript3.bat     |   2 +
 .../hooks/before_build/hookScriptDot2.sh        |   1 +
 .../_sh/hooks/before_build/hookScript01.sh      |   1 +
 .../_sh/hooks/before_build/hookScript02.sh      |   1 +
 .../_sh/hooks/before_build/hookScript3.sh       |   1 +
 .../fixtures/projWithHooks/config.xml           |  12 +
 .../projWithHooks/configOnePlatform_bat.xml     |  22 +
 .../projWithHooks/configOnePlatform_sh.xml      |  22 +
 .../configOnlyNonPlatformScripts_bat.xml        |  16 +
 .../configOnlyNonPlatformScripts_sh.xml         |  16 +
 .../projWithHooks/configTwoPlatforms_bat.xml    |  28 +
 .../projWithHooks/configTwoPlatforms_sh.xml     |  28 +
 .../hooks/before_build/hookScript10.js          |   4 +
 .../fixtures/projWithHooks/merges/.gitignore    |   0
 .../fixtures/projWithHooks/plugins/.gitignore   |   0
 .../scripts/android/appAndroidBeforeBuild.bat   |   2 +
 .../scripts/android/appAndroidBeforeBuild.js    |   4 +
 .../scripts/android/appAndroidBeforeBuild.sh    |   1 +
 .../android/appAndroidBeforePluginInstall.js    |   4 +
 .../projWithHooks/scripts/appBeforeBuild02.js   |   4 +
 .../projWithHooks/scripts/appBeforeBuild1.bat   |   2 +
 .../projWithHooks/scripts/appBeforeBuild1.sh    |   1 +
 .../scripts/appBeforePluginInstall.js           |   4 +
 .../projWithHooks/scripts/orderLogger.js        |  12 +
 .../scripts/windows/appWindowsBeforeBuild.bat   |   2 +
 .../scripts/windows/appWindowsBeforeBuild.js    |   4 +
 .../scripts/windows/appWindowsBeforeBuild.sh    |   1 +
 .../windows/appWindowsBeforePluginInstall.js    |   4 +
 .../fixtures/projWithHooks/www/config.xml       |  14 +
 .../fixtures/projWithHooks/www/css/index.css    | 115 ++++
 .../fixtures/projWithHooks/www/img/logo.png     | Bin 0 -> 21814 bytes
 .../fixtures/projWithHooks/www/index.html       |  43 ++
 .../fixtures/projWithHooks/www/js/index.js      |  49 ++
 .../fixtures/projWithHooks/www/spec.html        |  68 ++
 cordova-lib/spec-cordova/hooker.spec.js         | 261 --------
 cordova-lib/spec-cordova/lazy_load.spec.js      |   4 +-
 cordova-lib/spec-cordova/prepare.spec.js        |   4 +-
 cordova-lib/spec-cordova/run.spec.js            |   4 +-
 cordova-lib/spec-cordova/serve.spec.js          |   1 -
 69 files changed, 1310 insertions(+), 274 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/HooksRunner.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/HooksRunner.spec.js b/cordova-lib/spec-cordova/HooksRunner.spec.js
new file mode 100644
index 0000000..1e89808
--- /dev/null
+++ b/cordova-lib/spec-cordova/HooksRunner.spec.js
@@ -0,0 +1,613 @@
+/**
+ 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('../src/cordova/cordova'),
+    HooksRunner = require('../src/hooks/HooksRunner'),
+    shell  = require('shelljs'),
+    path   = require('path'),
+    fs     = require('fs'),
+    os     = require('os'),
+    Q      = require('q'),
+    child_process = require('child_process'),
+    helpers = require('./helpers'),
+    PluginInfo = require('../src/PluginInfo'),
+    superspawn = require('../src/cordova/superspawn'),
+    config = require('../src/cordova/config');
+
+var platform = os.platform();
+var tmpDir = helpers.tmpDir('hooks_test');
+var project = path.join(tmpDir, 'project');
+var dotCordova = path.join(project, '.cordova');
+var hooksDir = path.join(project, 'hooks');
+var hooksDirDot = path.join(project, '.cordova', 'hooks');
+var scriptsDir = path.join(project, 'scripts');
+var ext = platform.match(/(win32|win64)/)?'bat':'sh';
+var testPluginFixturePath = path.join(__dirname, 'fixtures', 'plugins', 'com.plugin.withhooks');
+
+var cordovaUtil = require('../src/cordova/util');
+
+
+// copy fixture
+shell.rm('-rf', project);
+shell.mkdir('-p', project);
+shell.cp('-R', path.join(__dirname, 'fixtures', 'projWithHooks', '*'), project);
+
+shell.mkdir('-p', dotCordova);
+shell.cp('-R', path.join(__dirname, 'fixtures', 'projWithHooks', '.cordova'), project);
+
+// copy sh/bat scripts
+if(ext === 'bat') {
+    shell.cp('-R', path.join(__dirname, 'fixtures', 'projWithHooks', '_bat', '*'), project);
+    shell.cp('-R', path.join(__dirname, 'fixtures', 'projWithHooks', '_bat', '.cordova'), project);
+} else {
+    shell.cp('-R', path.join(__dirname, 'fixtures', 'projWithHooks', '_sh', '*'), project);
+    shell.cp('-R', path.join(__dirname, 'fixtures', 'projWithHooks', '_sh', '.cordova'), project);
+}
+
+shell.chmod('-R', 'ug+x', hooksDir);
+shell.chmod('-R', 'ug+x', hooksDirDot);
+shell.chmod('-R', 'ug+x', scriptsDir);
+
+jasmine.getEnv().defaultTimeoutInterval = 3000;
+process.chdir(project);
+
+
+describe('HooksRunner', function() {
+    var hooksRunner;
+    var hookOptions;
+    var testPluginInstalledPath;
+    var projectRoot;
+    var fire;
+
+    it('should throw if provided directory is not a cordova project', function() {
+        expect(function() {
+            new HooksRunner(tmpDir);
+        }).toThrow();
+    });
+
+    it('should not throw if provided directory is a cordova project', function() {
+        expect(function () {
+            new HooksRunner(project);
+        }).not.toThrow();
+    });
+
+    it('should init test fixtures', function(done) {
+        hooksRunner = new HooksRunner(project);
+
+        // Now we load the config.json in the newly created project and edit the target platform's lib entry
+        // to point at the fixture version. This is necessary so that cordova.prepare can find cordova.js there.
+        var c = config.read(project);
+        c.lib[helpers.testPlatform].url = path.join(__dirname, 'fixtures', 'platforms', helpers.testPlatform + '-lib');
+        config.write(project, c);
+
+        // The config.json in the fixture project points at fake "local" paths.
+        // Since it's not a URL, the lazy-loader will just return the junk path.
+        spyOn(superspawn, 'spawn').andCallFake(function(cmd, args) {
+            if (cmd.match(/create\b/)) {
+                // This is a call to the bin/create script, so do the copy ourselves.
+                shell.cp('-R', path.join(__dirname, 'fixtures', 'platforms', 'android'), path.join(project, 'platforms'));
+            } else if(cmd.match(/version\b/)) {
+                return Q('3.3.0');
+            } else if(cmd.match(/update\b/)) {
+                fs.writeFileSync(path.join(project, 'platforms', helpers.testPlatform, 'updated'), 'I was updated!', 'utf-8');
+            }
+            return Q();
+        });
+
+
+        // Add the testing platform.
+        cordova.raw.platform('add', [helpers.testPlatform]).fail(function (err) {
+            expect(err).toBeUndefined();
+        }).then(function () {
+            // Add the testing plugin
+            projectRoot = cordovaUtil.isCordova();
+
+            var options = {
+                verbose: false,
+                platforms: [],
+                options: []
+            };
+
+            options = cordovaUtil.preProcessOptions(options);
+
+            hookOptions = { projectRoot: project, cordova: options };
+
+            cordova.raw.plugin('add', testPluginFixturePath).fail(function (err) {
+                expect(err).toBeUndefined();
+            }).then(function () {
+                testPluginInstalledPath = path.join(projectRoot, 'plugins', 'com.plugin.withhooks');
+                shell.chmod('-R', 'ug+x', path.join(testPluginInstalledPath, 'scripts'));
+                done();
+            });
+        });
+    });
+
+    describe('fire method', function() {
+        beforeEach(function() {
+            projectRoot = cordovaUtil.isCordova();
+
+            var options = {
+                verbose: false,
+                platforms: [],
+                options: []
+            };
+
+            options = cordovaUtil.preProcessOptions(options);
+            hookOptions = { projectRoot: project, cordova: options };
+
+            var hooksOrderFile = path.join(projectRoot, 'hooks_order.txt');
+            removeFileIfExists(hooksOrderFile);
+
+            fire = spyOn(HooksRunner.prototype, 'fire').andCallThrough();
+        });
+
+        // helper methods
+        function hooksOrderFileContents(hooksOrderFile) {
+            var order = fs.readFileSync(hooksOrderFile, 'ascii').replace(/\W/gm, ' ');
+
+            var orderArrOriginal = order.split(' ').slice(0);
+
+            function splitNumbers(mixedString) {
+                var re = /\w+/g, match, params = [];
+
+                while (match = re.exec(mixedString)) {
+                    params.push(match[0]);
+                }
+                return params;
+            }
+
+            return splitNumbers(orderArrOriginal).map(function(str) { return parseInt(str, 10); });
+        }
+
+        function hooksOrderFileIsOrdered(hooksOrderFile) {
+            var splitArrOriginal = hooksOrderFileContents(hooksOrderFile);
+            var splitArrSorted = splitArrOriginal.slice(0).sort(function(a, b) { return a - b; });
+
+            return JSON.stringify(splitArrOriginal) === JSON.stringify(splitArrSorted);
+        }
+
+        function backupAppConfig(projectRoot) {
+            shell.cp('-f', path.join(projectRoot, 'config.xml'), path.join(projectRoot, 'configOrig.xml'));
+        }
+
+        function restoreAppConfig(projectRoot) {
+            shell.cp('-f', path.join(projectRoot, 'configOrig.xml'), path.join(projectRoot, 'config.xml'));
+            shell.rm('-rf', path.join(projectRoot, 'configOrig.xml'));
+        }
+
+        function switchToOnlyNonPlatformScriptsAppConfig(projectRoot) {
+            backupAppConfig(projectRoot);
+            shell.cp('-f', path.join(projectRoot, 'configOnlyNonPlatformScripts_' + ext + '.xml'), path.join(projectRoot, 'config.xml'));
+        }
+
+        function switchToOnePlatformScriptsAppConfig(projectRoot) {
+            backupAppConfig(projectRoot);
+            shell.cp('-f', path.join(projectRoot, 'configOnePlatform_' + ext + '.xml'), path.join(projectRoot, 'config.xml'));
+        }
+
+        function switchToTwoPlatformsScriptsAppConfig(projectRoot) {
+            backupAppConfig(projectRoot);
+            shell.cp('-f', path.join(projectRoot, 'configTwoPlatforms_' + ext + '.xml'), path.join(projectRoot, 'config.xml'));
+        }
+
+        function backupPluginConfig() {
+            shell.cp('-f', path.join(testPluginInstalledPath, 'plugin.xml'), path.join(testPluginInstalledPath, 'pluginOrig.xml'));
+        }
+
+        function restorePluginConfig() {
+            shell.cp('-f', path.join(testPluginInstalledPath, 'pluginOrig.xml'), path.join(testPluginInstalledPath, 'plugin.xml'));
+            shell.rm('-rf', path.join(testPluginInstalledPath, 'pluginOrig.xml'));
+        }
+
+        function switchToOnlyNonPlatformScriptsPluginConfig(projectRoot) {
+            backupPluginConfig();
+            shell.cp('-f', path.join(testPluginInstalledPath, 'pluginOnlyNonPlatformScripts_' + ext + '.xml'), path.join(testPluginInstalledPath, 'plugin.xml'));
+        }
+
+        function switchToOnePlatformScriptsPluginConfig(projectRoot) {
+            backupPluginConfig();
+            shell.cp('-f', path.join(testPluginInstalledPath, 'pluginOnePlatform_' + ext + '.xml'), path.join(testPluginInstalledPath, 'plugin.xml'));
+        }
+
+        function switchToTwoPlatformsScriptsPluginConfig(projectRoot) {
+            backupPluginConfig();
+            shell.cp('-f', path.join(testPluginInstalledPath, 'pluginTwoPlatforms_' + ext + '.xml'), path.join(testPluginInstalledPath, 'plugin.xml'));
+        }
+
+        function removeFileIfExists(file) {
+            if (fs.existsSync(file)) {
+                fs.unlinkSync(file);
+            }
+        }
+
+        describe('application hooks', function() {
+            it('should execute hook scripts serially', function (done) {
+                var test_event = 'before_build';
+                var projectRoot = cordovaUtil.isCordova();
+                var hooksOrderFile = path.join(projectRoot, 'hooks_order.txt');
+
+                return hooksRunner.fire(test_event, hookOptions).then(function() {
+                    expect(hooksOrderFile).toExist();
+
+                    expect(hooksOrderFileIsOrdered(hooksOrderFile)).toBe(true);
+                }).fail(function (err) {
+                    expect(err).toBeUndefined();
+                }).then(function () {
+                    done();
+                });
+            });
+
+            it('should execute hook scripts serially from .cordova/hooks/hook_type and hooks/hook_type directories', function (done) {
+                var test_event = 'before_build';
+                var projectRoot = cordovaUtil.isCordova();
+                var hooksOrderFile = path.join(projectRoot, 'hooks_order.txt');
+
+                // using empty platforms list to test only hooks/ directories
+                hookOptions.cordova.platforms = [];
+
+                return hooksRunner.fire(test_event, hookOptions).then(function () {
+                    expect(hooksOrderFile).toExist();
+
+                    expect(hooksOrderFileIsOrdered(hooksOrderFile)).toBe(true);
+                }).fail(function (err) {
+                    expect(err).toBeUndefined();
+                }).then(function () {
+                    done();
+                });
+            });
+
+            it('should execute hook scripts serially from config.xml', function (done) {
+                var test_event = 'before_build';
+                var projectRoot = cordovaUtil.isCordova();
+                var hooksOrderFile = path.join(projectRoot, 'hooks_order.txt');
+
+                switchToOnlyNonPlatformScriptsAppConfig(projectRoot);
+
+                return hooksRunner.fire(test_event, hookOptions).then(function () {
+                    expect(hooksOrderFile).toExist();
+
+                    expect(hooksOrderFileIsOrdered(hooksOrderFile)).toBe(true);
+                }).fail(function (err) {
+                    expect(err).toBeUndefined();
+                }).then(function () {
+                    restoreAppConfig(projectRoot);
+                    done();
+                });
+            });
+
+            it('should execute hook scripts serially from config.xml including platform scripts', function (done) {
+                var test_event = 'before_build';
+                var projectRoot = cordovaUtil.isCordova();
+                var hooksOrderFile = path.join(projectRoot, 'hooks_order.txt');
+
+                switchToOnePlatformScriptsAppConfig(projectRoot);
+
+                return hooksRunner.fire(test_event, hookOptions).then(function () {
+                    expect(hooksOrderFile).toExist();
+
+                    expect(hooksOrderFileIsOrdered(hooksOrderFile)).toBe(true);
+                }).fail(function (err) {
+                    expect(err).toBeUndefined();
+                }).then(function () {
+                    restoreAppConfig(projectRoot);
+                    done();
+                });
+            });
+
+            it('should filter hook scripts from config.xml by platform', function (done) {
+                var test_event = 'before_build';
+                var projectRoot = cordovaUtil.isCordova();
+                var hooksOrderFile = path.join(projectRoot, 'hooks_order.txt');
+
+                switchToTwoPlatformsScriptsAppConfig(projectRoot);
+
+                hookOptions.cordova.platforms = ['android'];
+
+                return hooksRunner.fire(test_event, hookOptions).then(function () {
+                    expect(hooksOrderFile).toExist();
+
+                    expect(hooksOrderFileIsOrdered(hooksOrderFile)).toBe(true);
+
+                    var baseScriptResults = [1, 2, 3, 4, 5, 6, 7, 8, 9];
+                    var androidPlatformScriptsResults = [14, 15];
+
+                    expect(JSON.stringify(hooksOrderFileContents(hooksOrderFile)) ===
+                        JSON.stringify(baseScriptResults.slice(0).concat(androidPlatformScriptsResults))).toBe(true);
+                }).fail(function (err) {
+                    expect(err).toBeUndefined();
+                }).then(function () {
+                    restoreAppConfig(projectRoot);
+                    done();
+                });
+            });
+        });
+
+        describe('plugin hooks', function() {
+            it('should execute hook scripts serially from plugin.xml', function (done) {
+                var test_event = 'before_build';
+                var projectRoot = cordovaUtil.isCordova();
+                var hooksOrderFile = path.join(projectRoot, 'hooks_order.txt');
+
+                switchToOnlyNonPlatformScriptsPluginConfig();
+
+                return hooksRunner.fire(test_event, hookOptions).then(function () {
+                    expect(hooksOrderFile).toExist();
+
+                    expect(hooksOrderFileIsOrdered(hooksOrderFile)).toBe(true);
+                }).fail(function (err) {
+                    expect(err).toBeUndefined();
+                }).then(function () {
+                    restorePluginConfig(projectRoot);
+                    done();
+                });
+            });
+
+            it('should execute hook scripts serially from plugin.xml including platform scripts', function (done) {
+                var test_event = 'before_build';
+                var projectRoot = cordovaUtil.isCordova();
+                var hooksOrderFile = path.join(projectRoot, 'hooks_order.txt');
+
+                switchToOnePlatformScriptsPluginConfig();
+
+                return hooksRunner.fire(test_event, hookOptions).then(function () {
+                    expect(hooksOrderFile).toExist();
+
+                    expect(hooksOrderFileIsOrdered(hooksOrderFile)).toBe(true);
+                }).fail(function (err) {
+                    expect(err).toBeUndefined();
+                }).then(function () {
+                    restorePluginConfig(projectRoot);
+                    done();
+                });
+            });
+
+            it('should filter hook scripts from plugin.xml by platform', function (done) {
+                var test_event = 'before_build';
+                var projectRoot = cordovaUtil.isCordova();
+                var hooksOrderFile = path.join(projectRoot, 'hooks_order.txt');
+
+                switchToTwoPlatformsScriptsPluginConfig(projectRoot);
+
+                hookOptions.cordova.platforms = ['android'];
+
+                return hooksRunner.fire(test_event, hookOptions).then(function () {
+                    expect(hooksOrderFile).toExist();
+
+                    expect(hooksOrderFileIsOrdered(hooksOrderFile)).toBe(true);
+
+                    var baseScriptResults = [1, 2, 3, 4, 5, 6, 7, 21, 22];
+                    var androidPlatformScriptsResults = [26];
+
+                    expect(JSON.stringify(hooksOrderFileContents(hooksOrderFile)) ===
+                        JSON.stringify(baseScriptResults.slice(0).concat(androidPlatformScriptsResults))).toBe(true);
+                }).fail(function (err) {
+                    expect(err).toBeUndefined();
+                }).then(function () {
+                    restorePluginConfig(projectRoot);
+                    done();
+                });
+            });
+
+            it('should run before_plugin_uninstall, before_plugin_install, after_plugin_install hooks for a plugin being installed with correct opts.plugin context', function (done) {
+                var test_event = 'before_plugin_install';
+                var projectRoot = cordovaUtil.isCordova();
+
+                // remove plugin
+                cordova.raw.plugin('rm', 'com.plugin.withhooks').fail(function (err) {
+                    expect(err).toBeUndefined();
+                }).then(function () {
+                    cordova.raw.plugin('add', testPluginFixturePath).fail(function (err) {
+                        expect(err).toBeUndefined();
+                    }).then(function () {
+                        testPluginInstalledPath = path.join(projectRoot, 'plugins', 'com.plugin.withhooks');
+                        shell.chmod('-R', 'ug+x', path.join(testPluginInstalledPath, 'scripts'));
+
+                        var pluginInfo = new PluginInfo.PluginInfo(testPluginInstalledPath);
+
+                        var cordovaVersion = require('../package').version;
+
+                        var androidPluginOpts = {
+                            cordova: {
+                                platforms: [ 'android' ],
+                                plugins: ['com.plugin.withhooks'],
+                                version: cordovaVersion
+                            },
+                            plugin: {
+                                id: 'com.plugin.withhooks',
+                                pluginInfo: pluginInfo,
+                                platform: 'android',
+                                dir: testPluginInstalledPath
+                            },
+                            projectRoot: projectRoot
+                        };
+                        // Delete unique ids to allow comparing PluginInfo
+                        delete androidPluginOpts.plugin.pluginInfo._et;
+
+                        fire.calls.forEach(function(call) {
+                            if(call.args[1] && call.args[1].plugin) {
+                                // Delete unique ids to allow comparing PluginInfo
+                                delete call.args[1].plugin.pluginInfo._et;
+                            }
+
+                            if(call.args[0] == 'before_plugin_uninstall' || call.args[0] == 'before_plugin_install'
+                                || call.args[0] == 'after_plugin_install') {
+                                if(call.args[1] && call.args[1].plugin) {
+                                    if(call.args[1].plugin.platform == 'android') {
+                                        expect(JSON.stringify(androidPluginOpts)
+                                            === JSON.stringify(call.args[1])).toBe(true);
+                                    }
+                                }
+                            }
+                        });
+                    }).fail(function (err) {
+                        expect(err).toBeUndefined();
+                    }).fin(done);
+                });
+            });
+        });
+
+        describe('module-level hooks (event handlers)', function() {
+            var handler = jasmine.createSpy().andReturn(Q());
+            var test_event = 'before_build';
+
+            afterEach(function () {
+                cordova.removeAllListeners(test_event);
+                handler.reset();
+            });
+
+            it('should fire handlers using cordova.on', function(done) {
+                cordova.on(test_event, handler);
+                hooksRunner.fire(test_event, hookOptions).then(function () {
+                    expect(handler).toHaveBeenCalled();
+                }).fail(function (err) {
+                    expect(err).not.toBeDefined();
+                }).fin(done);
+            });
+
+            it('should pass the project root folder as parameter into the module-level handlers', function (done) {
+                cordova.on(test_event, handler);
+                hooksRunner.fire(test_event, hookOptions).then(function () {
+                    expect(handler).toHaveBeenCalledWith(hookOptions);
+                }).fail(function (err) {
+                    console.log(err);
+                    expect(err).not.toBeDefined();
+                }).fin(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);
+                hooksRunner.fire(test_event, hookOptions).then(function () {
+                    expect(handler).not.toHaveBeenCalled();
+                }).fail(function (err) {
+                    console.log(err);
+                    expect(err).toBeUndefined();
+                }).fin(done);
+            });
+
+            it('should execute event listeners serially', function(done) {
+                var h1_fired = false;
+                var h1 = function() {
+                    expect(h2_fired).toBe(false);
+                    // Delay 100 ms here to check that h2 is not executed until after
+                    // the promise returned by h1 is resolved.
+                    var q = Q.delay(100).then(function() {
+                        h1_fired = true;
+                    });
+                    return q;
+                };
+                var h2_fired = false;
+                var h2 = function() {
+                    h2_fired = true;
+                    expect(h1_fired).toBe(true);
+                    return Q();
+                };
+
+                cordova.on(test_event, h1);
+                cordova.on(test_event, h2);
+
+                return hooksRunner.fire(test_event, hookOptions).then(function() {
+                    expect(h1_fired).toBe(true);
+                    expect(h2_fired).toBe(true);
+                }).fail(function(err) {
+                    expect(err).toBeUndefined();
+                }).then(function() {
+                    cordova.removeAllListeners(test_event);
+                    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 () {
+                    h1_fired = true;
+                    expect(h2_fired).toBe(false);
+                    return Q();
+                };
+                var h2_fired = false;
+                var h2 = function () {
+                    h2_fired = true;
+                    expect(h1_fired).toBe(true);
+                    return Q();
+                };
+
+                cordova.on(test_event, h1);
+                cordova.on(test_event, h2);
+                hooksRunner.fire(test_event, hookOptions).then(function() {
+                    expect(h1_fired).toBe(true);
+                    expect(h2_fired).toBe(true);
+                    done();
+                });
+            });
+
+            it('should pass data object that fire calls into async handlers', function(done) {
+                var async = function (opts) {
+                    expect(opts).toEqual(hookOptions);
+                    return Q();
+                };
+                cordova.on(test_event, async);
+                hooksRunner.fire(test_event, hookOptions).then(function () {
+                    done();
+                });
+            });
+
+            it('should pass data object that fire calls into sync handlers', function(done) {
+                var async = function (opts) {
+                    expect(opts).toEqual(hookOptions);
+                };
+                cordova.on(test_event, async);
+                hooksRunner.fire(test_event, hookOptions).fin(done);
+            });
+
+            it('should error if any script exits with non-zero code', function(done) {
+                hooksRunner.fire('fail', hookOptions).then(function () {
+                    expect('the call').toBe('a failure');
+                }, function (err) {
+                    expect(err).toBeDefined();
+                }).fin(done);
+            });
+        });
+
+        it('should not error if the hook is unrecognized', function(done) {
+            hooksRunner.fire('CLEAN YOUR SHORTS GODDAMNIT LIKE A BIG BOY!', hookOptions).fail(function (err) {
+                expect('Call with unrecognized hook ').toBe('successful.\n' + err);
+            }).fin(done);
+        });
+    });
+});
+
+describe('cleanup', function() {
+// Cleanup. Must be the last spec. Is there a better place for final cleanup in Jasmine?
+    it('should not fail during cleanup', function () {
+        process.chdir(path.join(__dirname, '..'));  // Non e2e tests assume CWD is repo root.
+        if (ext == 'sh') {
+            shell.rm('-rf', tmpDir);
+        } else { // Windows:
+            // For some mysterious reason, both shell.rm and RMDIR /S /Q won't
+            // delete the dir on Windows, but they do remove the files leaving
+            // only folders. But the dir is removed just fine by
+            // shell.rm('-rf', tmpDir) at the top of this file with the next
+            // invocation of this test. The benefit of RMDIR /S /Q is that it
+            // doesn't print warnings like shell.rmdir() that look like this:
+            // rm: could not remove directory (code ENOTEMPTY): C:\Users\...
+            var cmd = 'RMDIR /S /Q ' + tmpDir;
+            child_process.exec(cmd);
+        }
+    });
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/build.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/build.spec.js b/cordova-lib/spec-cordova/build.spec.js
index 28127de..9528942 100644
--- a/cordova-lib/spec-cordova/build.spec.js
+++ b/cordova-lib/spec-cordova/build.spec.js
@@ -21,7 +21,7 @@ var cordova = require('../src/cordova/cordova'),
     shell = require('shelljs'),
     path = require('path'),
     fs = require('fs'),
-    hooker = require('../src/cordova/hooker'),
+    HooksRunner = require('../src/hooks/HooksRunner'),
     Q = require('q'),
     util = require('../src/cordova/util');
 
@@ -49,7 +49,7 @@ describe('build command', function() {
         is_cordova = spyOn(util, 'isCordova').andReturn(project_dir);
         cd_project_root = spyOn(util, 'cdProjectRoot').andReturn(project_dir);
         list_platforms = spyOn(util, 'listPlatforms').andReturn(supported_platforms);
-        fire = spyOn(hooker.prototype, 'fire').andReturn(Q());
+        fire = spyOn(HooksRunner.prototype, 'fire').andReturn(Q());
         prepare_spy = spyOn(cordova.raw, 'prepare').andReturn(Q());
         compile_spy = spyOn(cordova.raw, 'compile').andReturn(Q());
     });

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/compile.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/compile.spec.js b/cordova-lib/spec-cordova/compile.spec.js
index a1dadb3..f78d0c2 100644
--- a/cordova-lib/spec-cordova/compile.spec.js
+++ b/cordova-lib/spec-cordova/compile.spec.js
@@ -20,7 +20,7 @@ var cordova = require('../src/cordova/cordova'),
     platforms = require('../src/cordova/platforms'),
     path = require('path'),
     fs = require('fs'),
-    hooker = require('../src/cordova/hooker'),
+    HooksRunner = require('../src/hooks/HooksRunner'),
     superspawn = require('../src/cordova/superspawn'),
     util = require('../src/cordova/util'),
     Q = require('q'),
@@ -45,7 +45,7 @@ describe('compile command', function() {
         is_cordova = spyOn(util, 'isCordova').andReturn(project_dir);
         cd_project_root = spyOn(util, 'cdProjectRoot').andReturn(project_dir);
         list_platforms = spyOn(util, 'listPlatforms').andReturn(supported_platforms);
-        fire = spyOn(hooker.prototype, 'fire').andReturn(Q());
+        fire = spyOn(HooksRunner.prototype, 'fire').andReturn(Q());
         spyOn(superspawn, 'spawn').andCallFake(function() { return Q() });
     });
     describe('failure', function() {

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/emulate.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/emulate.spec.js b/cordova-lib/spec-cordova/emulate.spec.js
index 10f0d86..f770400 100644
--- a/cordova-lib/spec-cordova/emulate.spec.js
+++ b/cordova-lib/spec-cordova/emulate.spec.js
@@ -21,7 +21,7 @@ var cordova = require('../src/cordova/cordova'),
     superspawn = require('../src/cordova/superspawn'),
     path = require('path'),
     fs = require('fs'),
-    hooker = require('../src/cordova/hooker'),
+    HooksRunner = require('../src/hooks/HooksRunner'),
     Q = require('q'),
     util = require('../src/cordova/util'),
     os = require('os');
@@ -45,7 +45,7 @@ describe('emulate command', function() {
         is_cordova = spyOn(util, 'isCordova').andReturn(project_dir);
         cd_project_root = spyOn(util, 'cdProjectRoot').andReturn(project_dir);
         list_platforms = spyOn(util, 'listPlatforms').andReturn(supported_platforms);
-        fire = spyOn(hooker.prototype, 'fire').andReturn(Q());
+        fire = spyOn(HooksRunner.prototype, 'fire').andReturn(Q());
         prepare_spy = spyOn(cordova.raw, 'prepare').andReturn(Q());
         spyOn(superspawn, 'spawn').andCallFake(Q);
     });

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/plugin.xml
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/plugin.xml b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/plugin.xml
new file mode 100644
index 0000000..8e80560
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/plugin.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        id="com.plugin.withhooks"
+        version="0.0.1">
+    <name>Plugin with hooks</name>
+</plugin>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/pluginOnePlatform_bat.xml
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/pluginOnePlatform_bat.xml b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/pluginOnePlatform_bat.xml
new file mode 100644
index 0000000..e1d6a0c
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/pluginOnePlatform_bat.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        id="com.plugin.withhooks"
+        version="0.0.1">
+    <name>Plugin with hooks</name>
+
+    <hook type="before_plugin_install" src="scripts/beforeInstall01.js" />
+    <hook type="before_plugin_install" src="scripts/beforeInstall2.js" />
+    <hook type="before_plugin_install" src="scripts/beforeInstall.bat" />
+    <hook type="before_plugin_uninstall" src="scripts/beforeUninstall.js" />
+    <hook type="before_build" src="scripts/beforeBuild.js" />
+    <hook type="before_build" src="scripts/beforeBuild.bat" />
+
+    <platform name="android">
+        <hook type="before_plugin_install" src="scripts/android/androidBeforeInstall.js" />
+        <hook type="before_build" src="scripts/android/androidBeforeBuild.js" />
+    </platform>
+</plugin>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/pluginOnePlatform_sh.xml
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/pluginOnePlatform_sh.xml b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/pluginOnePlatform_sh.xml
new file mode 100644
index 0000000..fef675a
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/pluginOnePlatform_sh.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        id="com.plugin.withhooks"
+        version="0.0.1">
+    <name>Plugin with hooks</name>
+
+    <hook type="before_plugin_install" src="scripts/beforeInstall01.js" />
+    <hook type="before_plugin_install" src="scripts/beforeInstall2.js" />
+    <hook type="before_plugin_install" src="scripts/beforeInstall.sh" />
+    <hook type="before_plugin_uninstall" src="scripts/beforeUninstall.js" />
+    <hook type="before_build" src="scripts/beforeBuild.js" />
+    <hook type="before_build" src="scripts/beforeBuild.sh" />
+
+    <platform name="android">
+        <hook type="before_plugin_install" src="scripts/android/androidBeforeInstall.js" />
+        <hook type="before_build" src="scripts/android/androidBeforeBuild.js" />
+    </platform>
+</plugin>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/pluginOnlyNonPlatformScripts_bat.xml
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/pluginOnlyNonPlatformScripts_bat.xml b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/pluginOnlyNonPlatformScripts_bat.xml
new file mode 100644
index 0000000..fcbdb61
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/pluginOnlyNonPlatformScripts_bat.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        id="com.plugin.withhooks"
+        version="0.0.1">
+    <name>Plugin with hooks</name>
+
+    <hook type="before_plugin_install" src="scripts/beforeInstall01.js" />
+    <hook type="before_plugin_install" src="scripts/beforeInstall2.js" />
+    <hook type="before_plugin_install" src="scripts/beforeInstall.bat" />
+    <hook type="before_plugin_uninstall" src="scripts/beforeUninstall.js" />
+    <hook type="before_build" src="scripts/beforeBuild.js" />
+    <hook type="before_build" src="scripts/beforeBuild.bat" />
+</plugin>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/pluginOnlyNonPlatformScripts_sh.xml
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/pluginOnlyNonPlatformScripts_sh.xml b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/pluginOnlyNonPlatformScripts_sh.xml
new file mode 100644
index 0000000..7593ffe
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/pluginOnlyNonPlatformScripts_sh.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        id="com.plugin.withhooks"
+        version="0.0.1">
+    <name>Plugin with hooks</name>
+
+    <hook type="before_plugin_install" src="scripts/beforeInstall01.js" />
+    <hook type="before_plugin_install" src="scripts/beforeInstall2.js" />
+    <hook type="before_plugin_install" src="scripts/beforeInstall.sh" />
+    <hook type="before_plugin_uninstall" src="scripts/beforeUninstall.js" />
+    <hook type="before_build" src="scripts/beforeBuild.js" />
+    <hook type="before_build" src="scripts/beforeBuild.sh" />
+</plugin>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/pluginTwoPlatforms_bat.xml
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/pluginTwoPlatforms_bat.xml b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/pluginTwoPlatforms_bat.xml
new file mode 100644
index 0000000..8fd6d38
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/pluginTwoPlatforms_bat.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        id="com.plugin.withhooks"
+        version="0.0.1">
+    <name>Plugin with hooks</name>
+
+    <hook type="before_plugin_install" src="scripts/beforeInstall01.js" />
+    <hook type="before_plugin_install" src="scripts/beforeInstall2.js" />
+    <hook type="before_plugin_install" src="scripts/beforeInstall.bat" />
+    <hook type="before_plugin_uninstall" src="scripts/beforeUninstall.js" />
+    <hook type="before_build" src="scripts/beforeBuild.js" />
+    <hook type="before_build" src="scripts/beforeBuild.bat" />
+
+    <platform name="windows">
+        <hook type="before_plugin_install" src="scripts/windows/windowsBeforeInstall.js" />
+        <hook type="before_build" src="scripts/windows/windowsBeforeBuild.js" />
+    </platform>
+
+    <platform name="android">
+        <hook type="before_plugin_install" src="scripts/android/androidBeforeInstall.js" />
+        <hook type="before_build" src="scripts/android/androidBeforeBuild.js" />
+    </platform>
+</plugin>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/pluginTwoPlatforms_sh.xml
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/pluginTwoPlatforms_sh.xml b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/pluginTwoPlatforms_sh.xml
new file mode 100644
index 0000000..6a4e11d
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/pluginTwoPlatforms_sh.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        id="com.plugin.withhooks"
+        version="0.0.1">
+    <name>Plugin with hooks</name>
+
+    <hook type="before_plugin_install" src="scripts/beforeInstall01.js" />
+    <hook type="before_plugin_install" src="scripts/beforeInstall2.js" />
+    <hook type="before_plugin_install" src="scripts/beforeInstall.sh" />
+    <hook type="before_plugin_uninstall" src="scripts/beforeUninstall.js" />
+    <hook type="before_build" src="scripts/beforeBuild.js" />
+    <hook type="before_build" src="scripts/beforeBuild.sh" />
+
+    <platform name="windows">
+        <hook type="before_plugin_install" src="scripts/windows/windowsBeforeInstall.js" />
+        <hook type="before_build" src="scripts/windows/windowsBeforeBuild.js" />
+    </platform>
+
+    <platform name="android">
+        <hook type="before_plugin_install" src="scripts/android/androidBeforeInstall.js" />
+        <hook type="before_build" src="scripts/android/androidBeforeBuild.js" />
+    </platform>
+</plugin>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/android/androidBeforeBuild.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/android/androidBeforeBuild.js b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/android/androidBeforeBuild.js
new file mode 100644
index 0000000..4203c17
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/android/androidBeforeBuild.js
@@ -0,0 +1,4 @@
+module.exports = function(context) {
+    var orderLogger = require(require('path').join(context.opts.projectRoot, 'scripts', 'orderLogger'));
+    orderLogger.logOrder('26', context);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/android/androidBeforeInstall.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/android/androidBeforeInstall.js b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/android/androidBeforeInstall.js
new file mode 100644
index 0000000..96ac175
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/android/androidBeforeInstall.js
@@ -0,0 +1,4 @@
+module.exports = function(context) {
+    var orderLogger = require(require('path').join(context.opts.projectRoot, 'scripts', 'orderLogger'));
+    orderLogger.logOrder('25', context);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeBuild.bat
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeBuild.bat b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeBuild.bat
new file mode 100644
index 0000000..768a404
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeBuild.bat
@@ -0,0 +1,2 @@
+@echo off
+echo 22 >> hooks_order.txt
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeBuild.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeBuild.js b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeBuild.js
new file mode 100644
index 0000000..1f40574
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeBuild.js
@@ -0,0 +1,4 @@
+module.exports = function(context) {
+    var orderLogger = require(require('path').join(context.opts.projectRoot, 'scripts', 'orderLogger'));
+    orderLogger.logOrder('21', context);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeBuild.sh
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeBuild.sh b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeBuild.sh
new file mode 100644
index 0000000..5698c11
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeBuild.sh
@@ -0,0 +1 @@
+echo 22 >> hooks_order.txt
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeInstall.bat
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeInstall.bat b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeInstall.bat
new file mode 100644
index 0000000..7e6b0df
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeInstall.bat
@@ -0,0 +1,2 @@
+@echo off
+echo 19 >> hooks_order.txt
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeInstall.sh
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeInstall.sh b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeInstall.sh
new file mode 100644
index 0000000..2688501
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeInstall.sh
@@ -0,0 +1 @@
+echo 19 >> hooks_order.txt
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeInstall01.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeInstall01.js b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeInstall01.js
new file mode 100644
index 0000000..3d644b2
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeInstall01.js
@@ -0,0 +1,4 @@
+module.exports = function(context) {
+    var orderLogger = require(require('path').join(context.opts.projectRoot, 'scripts', 'orderLogger'));
+    orderLogger.logOrder('17', context);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeInstall2.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeInstall2.js b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeInstall2.js
new file mode 100644
index 0000000..b49f65c
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeInstall2.js
@@ -0,0 +1,4 @@
+module.exports = function(context) {
+    var orderLogger = require(require('path').join(context.opts.projectRoot, 'scripts', 'orderLogger'));
+    orderLogger.logOrder('18', context);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeUninstall.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeUninstall.js b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeUninstall.js
new file mode 100644
index 0000000..2b05f62
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/beforeUninstall.js
@@ -0,0 +1,4 @@
+module.exports = function(context) {
+    var orderLogger = require(require('path').join(context.opts.projectRoot, 'scripts', 'orderLogger'));
+    orderLogger.logOrder('20', context);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/windows/windowsBeforeBuild.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/windows/windowsBeforeBuild.js b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/windows/windowsBeforeBuild.js
new file mode 100644
index 0000000..7729968
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/windows/windowsBeforeBuild.js
@@ -0,0 +1,4 @@
+module.exports = function(context) {
+    var orderLogger = require(require('path').join(context.opts.projectRoot, 'scripts', 'orderLogger'));
+    orderLogger.logOrder('24', context);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/windows/windowsBeforeInstall.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/windows/windowsBeforeInstall.js b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/windows/windowsBeforeInstall.js
new file mode 100644
index 0000000..db4cbe0
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/plugins/com.plugin.withhooks/scripts/windows/windowsBeforeInstall.js
@@ -0,0 +1,4 @@
+module.exports = function(context) {
+    var orderLogger = require(require('path').join(context.opts.projectRoot, 'scripts', 'orderLogger'));
+    orderLogger.logOrder('23', context);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/.cordova/config.json
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/.cordova/config.json b/cordova-lib/spec-cordova/fixtures/projWithHooks/.cordova/config.json
new file mode 100644
index 0000000..4f52ca7
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/.cordova/config.json
@@ -0,0 +1,22 @@
+{
+  "id": "org.testing",
+  "name":"TestBase",
+  "lib": {
+    "android": {
+      "url": "/some/junk/path",
+      "version": "dev",
+      "id": "cordova-android-dev"
+    },
+    "ios": {
+      "url": "/some/junk/path",
+      "version": "dev",
+      "id": "cordova-ios-dev"
+    },
+    "wp8": {
+      "url": "/some/junk/path",
+      "version": "dev",
+      "id": "cordova-wp8-dev"
+    }
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/.cordova/hooks/before_build/hookScriptDot03.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/.cordova/hooks/before_build/hookScriptDot03.js b/cordova-lib/spec-cordova/fixtures/projWithHooks/.cordova/hooks/before_build/hookScriptDot03.js
new file mode 100644
index 0000000..5e69a7f
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/.cordova/hooks/before_build/hookScriptDot03.js
@@ -0,0 +1,4 @@
+#!/usr/bin/env node
+var path = require('path');
+var orderLogger = require(path.join(process.argv.slice(2)[0], 'scripts', 'orderLogger'));
+orderLogger.logOrder('01');
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/.cordova/hooks/before_build/hookScriptDot1.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/.cordova/hooks/before_build/hookScriptDot1.js b/cordova-lib/spec-cordova/fixtures/projWithHooks/.cordova/hooks/before_build/hookScriptDot1.js
new file mode 100644
index 0000000..2e8d8d5
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/.cordova/hooks/before_build/hookScriptDot1.js
@@ -0,0 +1,4 @@
+#!/usr/bin/env node
+var path = require('path');
+var orderLogger = require(path.join(process.argv.slice(2)[0], 'scripts', 'orderLogger'));
+orderLogger.logOrder('02');
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/.cordova/hooks/fail/fail.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/.cordova/hooks/fail/fail.js b/cordova-lib/spec-cordova/fixtures/projWithHooks/.cordova/hooks/fail/fail.js
new file mode 100644
index 0000000..d2d790b
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/.cordova/hooks/fail/fail.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+throw Error('test error');
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/_bat/.cordova/hooks/before_build/hookScriptDot2.bat
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/_bat/.cordova/hooks/before_build/hookScriptDot2.bat b/cordova-lib/spec-cordova/fixtures/projWithHooks/_bat/.cordova/hooks/before_build/hookScriptDot2.bat
new file mode 100644
index 0000000..0142765
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/_bat/.cordova/hooks/before_build/hookScriptDot2.bat
@@ -0,0 +1,2 @@
+@echo off
+echo 03 >> hooks_order.txt
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/_bat/hooks/before_build/hookScript01.bat
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/_bat/hooks/before_build/hookScript01.bat b/cordova-lib/spec-cordova/fixtures/projWithHooks/_bat/hooks/before_build/hookScript01.bat
new file mode 100644
index 0000000..a6711cf
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/_bat/hooks/before_build/hookScript01.bat
@@ -0,0 +1,2 @@
+@echo off
+echo 04 >> hooks_order.txt
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/_bat/hooks/before_build/hookScript02.bat
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/_bat/hooks/before_build/hookScript02.bat b/cordova-lib/spec-cordova/fixtures/projWithHooks/_bat/hooks/before_build/hookScript02.bat
new file mode 100644
index 0000000..1e824a4
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/_bat/hooks/before_build/hookScript02.bat
@@ -0,0 +1,2 @@
+@echo off
+echo 05 >> hooks_order.txt
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/_bat/hooks/before_build/hookScript3.bat
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/_bat/hooks/before_build/hookScript3.bat b/cordova-lib/spec-cordova/fixtures/projWithHooks/_bat/hooks/before_build/hookScript3.bat
new file mode 100644
index 0000000..f339213
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/_bat/hooks/before_build/hookScript3.bat
@@ -0,0 +1,2 @@
+@echo off
+echo 07 >> hooks_order.txt
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/_sh/.cordova/hooks/before_build/hookScriptDot2.sh
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/_sh/.cordova/hooks/before_build/hookScriptDot2.sh b/cordova-lib/spec-cordova/fixtures/projWithHooks/_sh/.cordova/hooks/before_build/hookScriptDot2.sh
new file mode 100644
index 0000000..7c0c654
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/_sh/.cordova/hooks/before_build/hookScriptDot2.sh
@@ -0,0 +1 @@
+echo 03 >> hooks_order.txt
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/_sh/hooks/before_build/hookScript01.sh
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/_sh/hooks/before_build/hookScript01.sh b/cordova-lib/spec-cordova/fixtures/projWithHooks/_sh/hooks/before_build/hookScript01.sh
new file mode 100644
index 0000000..ccc8c89
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/_sh/hooks/before_build/hookScript01.sh
@@ -0,0 +1 @@
+echo 04 >> hooks_order.txt
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/_sh/hooks/before_build/hookScript02.sh
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/_sh/hooks/before_build/hookScript02.sh b/cordova-lib/spec-cordova/fixtures/projWithHooks/_sh/hooks/before_build/hookScript02.sh
new file mode 100644
index 0000000..4926cd8
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/_sh/hooks/before_build/hookScript02.sh
@@ -0,0 +1 @@
+echo 05 >> hooks_order.txt
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/_sh/hooks/before_build/hookScript3.sh
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/_sh/hooks/before_build/hookScript3.sh b/cordova-lib/spec-cordova/fixtures/projWithHooks/_sh/hooks/before_build/hookScript3.sh
new file mode 100644
index 0000000..c52c84a
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/_sh/hooks/before_build/hookScript3.sh
@@ -0,0 +1 @@
+echo 07 >> hooks_order.txt
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/config.xml
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/config.xml b/cordova-lib/spec-cordova/fixtures/projWithHooks/config.xml
new file mode 100644
index 0000000..bc81273
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/config.xml
@@ -0,0 +1,12 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget id="io.cordova.hellocordova" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+    <name>HelloCordova</name>
+    <description>
+        A sample Apache Cordova application that responds to the deviceready event.
+    </description>
+    <author email="dev@cordova.apache.org" href="http://cordova.io">
+        Apache Cordova Team
+    </author>
+    <content src="index.html" />
+    <access origin="*" />
+</widget>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/configOnePlatform_bat.xml
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/configOnePlatform_bat.xml b/cordova-lib/spec-cordova/fixtures/projWithHooks/configOnePlatform_bat.xml
new file mode 100644
index 0000000..6f1a691
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/configOnePlatform_bat.xml
@@ -0,0 +1,22 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget id="io.cordova.hellocordova" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+    <name>HelloCordova</name>
+    <description>
+        A sample Apache Cordova application that responds to the deviceready event.
+    </description>
+    <author email="dev@cordova.apache.org" href="http://cordova.io">
+        Apache Cordova Team
+    </author>
+    <content src="index.html" />
+    <access origin="*" />
+
+    <hook type="before_build" src="scripts/appBeforeBuild1.bat" />
+    <hook type="before_build" src="scripts/appBeforeBuild02.js" />
+    <hook type="before_plugin_install" src="scripts/appBeforePluginInstall.js" />
+
+    <platform name="windows">
+        <hook type="before_build" src="scripts/windows/appWindowsBeforeBuild.bat" />
+        <hook type="before_build" src="scripts/windows/appWindowsBeforeBuild.js" />
+        <hook type="before_plugin_install" src="scripts/windows/appWindowsBeforePluginInstall.js" />
+    </platform>
+</widget>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/configOnePlatform_sh.xml
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/configOnePlatform_sh.xml b/cordova-lib/spec-cordova/fixtures/projWithHooks/configOnePlatform_sh.xml
new file mode 100644
index 0000000..bddcd25
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/configOnePlatform_sh.xml
@@ -0,0 +1,22 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget id="io.cordova.hellocordova" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+    <name>HelloCordova</name>
+    <description>
+        A sample Apache Cordova application that responds to the deviceready event.
+    </description>
+    <author email="dev@cordova.apache.org" href="http://cordova.io">
+        Apache Cordova Team
+    </author>
+    <content src="index.html" />
+    <access origin="*" />
+
+    <hook type="before_build" src="scripts/appBeforeBuild1.sh" />
+    <hook type="before_build" src="scripts/appBeforeBuild02.js" />
+    <hook type="before_plugin_install" src="scripts/appBeforePluginInstall.js" />
+
+    <platform name="windows">
+        <hook type="before_build" src="scripts/windows/appWindowsBeforeBuild.sh" />
+        <hook type="before_build" src="scripts/windows/appWindowsBeforeBuild.js" />
+        <hook type="before_plugin_install" src="scripts/windows/appWindowsBeforePluginInstall.js" />
+    </platform>
+</widget>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/configOnlyNonPlatformScripts_bat.xml
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/configOnlyNonPlatformScripts_bat.xml b/cordova-lib/spec-cordova/fixtures/projWithHooks/configOnlyNonPlatformScripts_bat.xml
new file mode 100644
index 0000000..8ad84f6
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/configOnlyNonPlatformScripts_bat.xml
@@ -0,0 +1,16 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget id="io.cordova.hellocordova" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+    <name>HelloCordova</name>
+    <description>
+        A sample Apache Cordova application that responds to the deviceready event.
+    </description>
+    <author email="dev@cordova.apache.org" href="http://cordova.io">
+        Apache Cordova Team
+    </author>
+    <content src="index.html" />
+    <access origin="*" />
+
+    <hook type="before_build" src="scripts/appBeforeBuild1.bat" />
+    <hook type="before_build" src="scripts/appBeforeBuild02.js" />
+    <hook type="before_plugin_install" src="scripts/appBeforePluginInstall.js" />
+</widget>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/configOnlyNonPlatformScripts_sh.xml
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/configOnlyNonPlatformScripts_sh.xml b/cordova-lib/spec-cordova/fixtures/projWithHooks/configOnlyNonPlatformScripts_sh.xml
new file mode 100644
index 0000000..8634f64
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/configOnlyNonPlatformScripts_sh.xml
@@ -0,0 +1,16 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget id="io.cordova.hellocordova" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+    <name>HelloCordova</name>
+    <description>
+        A sample Apache Cordova application that responds to the deviceready event.
+    </description>
+    <author email="dev@cordova.apache.org" href="http://cordova.io">
+        Apache Cordova Team
+    </author>
+    <content src="index.html" />
+    <access origin="*" />
+
+    <hook type="before_build" src="scripts/appBeforeBuild1.sh" />
+    <hook type="before_build" src="scripts/appBeforeBuild02.js" />
+    <hook type="before_plugin_install" src="scripts/appBeforePluginInstall.js" />
+</widget>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/configTwoPlatforms_bat.xml
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/configTwoPlatforms_bat.xml b/cordova-lib/spec-cordova/fixtures/projWithHooks/configTwoPlatforms_bat.xml
new file mode 100644
index 0000000..758ac70
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/configTwoPlatforms_bat.xml
@@ -0,0 +1,28 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget id="io.cordova.hellocordova" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+    <name>HelloCordova</name>
+    <description>
+        A sample Apache Cordova application that responds to the deviceready event.
+    </description>
+    <author email="dev@cordova.apache.org" href="http://cordova.io">
+        Apache Cordova Team
+    </author>
+    <content src="index.html" />
+    <access origin="*" />
+
+    <hook type="before_build" src="scripts/appBeforeBuild1.bat" />
+    <hook type="before_build" src="scripts/appBeforeBuild02.js" />
+    <hook type="before_plugin_install" src="scripts/appBeforePluginInstall.js" />
+
+    <platform name="windows">
+        <hook type="before_build" src="scripts/windows/appWindowsBeforeBuild.bat" />
+        <hook type="before_build" src="scripts/windows/appWindowsBeforeBuild.js" />
+        <hook type="before_plugin_install" src="scripts/windows/appWindowsBeforePluginInstall.js" />
+    </platform>
+
+    <platform name="android">
+        <hook type="before_build" src="scripts/android/appAndroidBeforeBuild.bat" />
+        <hook type="before_build" src="scripts/android/appAndroidBeforeBuild.js" />
+        <hook type="before_plugin_install" src="scripts/android/appAndroidBeforePluginInstall.js" />
+    </platform>
+</widget>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/configTwoPlatforms_sh.xml
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/configTwoPlatforms_sh.xml b/cordova-lib/spec-cordova/fixtures/projWithHooks/configTwoPlatforms_sh.xml
new file mode 100644
index 0000000..1175e6c
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/configTwoPlatforms_sh.xml
@@ -0,0 +1,28 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget id="io.cordova.hellocordova" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+    <name>HelloCordova</name>
+    <description>
+        A sample Apache Cordova application that responds to the deviceready event.
+    </description>
+    <author email="dev@cordova.apache.org" href="http://cordova.io">
+        Apache Cordova Team
+    </author>
+    <content src="index.html" />
+    <access origin="*" />
+
+    <hook type="before_build" src="scripts/appBeforeBuild1.sh" />
+    <hook type="before_build" src="scripts/appBeforeBuild02.js" />
+    <hook type="before_plugin_install" src="scripts/appBeforePluginInstall.js" />
+
+    <platform name="windows">
+        <hook type="before_build" src="scripts/windows/appWindowsBeforeBuild.sh" />
+        <hook type="before_build" src="scripts/windows/appWindowsBeforeBuild.js" />
+        <hook type="before_plugin_install" src="scripts/windows/appWindowsBeforePluginInstall.js" />
+    </platform>
+
+    <platform name="android">
+        <hook type="before_build" src="scripts/android/appAndroidBeforeBuild.sh" />
+        <hook type="before_build" src="scripts/android/appAndroidBeforeBuild.js" />
+        <hook type="before_plugin_install" src="scripts/android/appAndroidBeforePluginInstall.js" />
+    </platform>
+</widget>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/hooks/before_build/hookScript10.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/hooks/before_build/hookScript10.js b/cordova-lib/spec-cordova/fixtures/projWithHooks/hooks/before_build/hookScript10.js
new file mode 100644
index 0000000..bad1036
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/hooks/before_build/hookScript10.js
@@ -0,0 +1,4 @@
+#!/usr/bin/env node
+var path = require('path');
+var orderLogger = require(path.join(process.argv.slice(2)[0], 'scripts', 'orderLogger'));
+orderLogger.logOrder('06');
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/merges/.gitignore
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/merges/.gitignore b/cordova-lib/spec-cordova/fixtures/projWithHooks/merges/.gitignore
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/plugins/.gitignore
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/plugins/.gitignore b/cordova-lib/spec-cordova/fixtures/projWithHooks/plugins/.gitignore
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/android/appAndroidBeforeBuild.bat
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/android/appAndroidBeforeBuild.bat b/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/android/appAndroidBeforeBuild.bat
new file mode 100644
index 0000000..1893215
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/android/appAndroidBeforeBuild.bat
@@ -0,0 +1,2 @@
+@echo off
+echo 14 >> hooks_order.txt
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/android/appAndroidBeforeBuild.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/android/appAndroidBeforeBuild.js b/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/android/appAndroidBeforeBuild.js
new file mode 100644
index 0000000..b5e0971
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/android/appAndroidBeforeBuild.js
@@ -0,0 +1,4 @@
+module.exports = function(context) {
+    var orderLogger = require(require('path').join(context.opts.projectRoot, 'scripts', 'orderLogger'));
+    orderLogger.logOrder('15', context);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/android/appAndroidBeforeBuild.sh
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/android/appAndroidBeforeBuild.sh b/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/android/appAndroidBeforeBuild.sh
new file mode 100644
index 0000000..34f9b56
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/android/appAndroidBeforeBuild.sh
@@ -0,0 +1 @@
+echo 14 >> hooks_order.txt
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/android/appAndroidBeforePluginInstall.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/android/appAndroidBeforePluginInstall.js b/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/android/appAndroidBeforePluginInstall.js
new file mode 100644
index 0000000..608be4f
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/android/appAndroidBeforePluginInstall.js
@@ -0,0 +1,4 @@
+module.exports = function(context) {
+    var orderLogger = require(require('path').join(context.opts.projectRoot, 'scripts', 'orderLogger'));
+    orderLogger.logOrder('16', context);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/appBeforeBuild02.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/appBeforeBuild02.js b/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/appBeforeBuild02.js
new file mode 100644
index 0000000..e248272
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/appBeforeBuild02.js
@@ -0,0 +1,4 @@
+module.exports = function(context) {
+    var orderLogger = require(require('path').join(context.opts.projectRoot, 'scripts', 'orderLogger'));
+    orderLogger.logOrder('09', context);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/appBeforeBuild1.bat
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/appBeforeBuild1.bat b/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/appBeforeBuild1.bat
new file mode 100644
index 0000000..c3d28b8
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/appBeforeBuild1.bat
@@ -0,0 +1,2 @@
+@echo off
+echo 08 >> hooks_order.txt
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/appBeforeBuild1.sh
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/appBeforeBuild1.sh b/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/appBeforeBuild1.sh
new file mode 100644
index 0000000..03793d8
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/appBeforeBuild1.sh
@@ -0,0 +1 @@
+echo 08 >> hooks_order.txt
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/appBeforePluginInstall.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/appBeforePluginInstall.js b/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/appBeforePluginInstall.js
new file mode 100644
index 0000000..93e6701
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/appBeforePluginInstall.js
@@ -0,0 +1,4 @@
+module.exports = function(context) {
+    var orderLogger = require(require('path').join(context.opts.projectRoot, 'scripts', 'orderLogger'));
+    orderLogger.logOrder('10', context);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/orderLogger.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/orderLogger.js b/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/orderLogger.js
new file mode 100644
index 0000000..f50390a
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/orderLogger.js
@@ -0,0 +1,12 @@
+module.exports.logOrder = function logOrder(index, context) {
+    var indexWithEOL = index + require('os').EOL;
+    var path = require('path');
+    var fs = require('fs');
+
+    if(context) {
+        fs.appendFileSync(path.join(context.opts.projectRoot, 'hooks_order.txt'), indexWithEOL);
+    } else {
+
+        fs.appendFileSync('hooks_order.txt', indexWithEOL);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/windows/appWindowsBeforeBuild.bat
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/windows/appWindowsBeforeBuild.bat b/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/windows/appWindowsBeforeBuild.bat
new file mode 100644
index 0000000..1da7b9d
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/windows/appWindowsBeforeBuild.bat
@@ -0,0 +1,2 @@
+@echo off
+echo 11 >> hooks_order.txt
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/windows/appWindowsBeforeBuild.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/windows/appWindowsBeforeBuild.js b/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/windows/appWindowsBeforeBuild.js
new file mode 100644
index 0000000..01284f1
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/windows/appWindowsBeforeBuild.js
@@ -0,0 +1,4 @@
+module.exports = function(context) {
+    var orderLogger = require(require('path').join(context.opts.projectRoot, 'scripts', 'orderLogger'));
+    orderLogger.logOrder('12', context);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/windows/appWindowsBeforeBuild.sh
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/windows/appWindowsBeforeBuild.sh b/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/windows/appWindowsBeforeBuild.sh
new file mode 100644
index 0000000..d699b61
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/windows/appWindowsBeforeBuild.sh
@@ -0,0 +1 @@
+echo 11 >> hooks_order.txt
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/windows/appWindowsBeforePluginInstall.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/windows/appWindowsBeforePluginInstall.js b/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/windows/appWindowsBeforePluginInstall.js
new file mode 100644
index 0000000..1ad17e2
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/scripts/windows/appWindowsBeforePluginInstall.js
@@ -0,0 +1,4 @@
+module.exports = function(context) {
+    var orderLogger = require(require('path').join(context.opts.projectRoot, 'scripts', 'orderLogger'));
+    orderLogger.logOrder('13', context);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/eed41399/cordova-lib/spec-cordova/fixtures/projWithHooks/www/config.xml
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/fixtures/projWithHooks/www/config.xml b/cordova-lib/spec-cordova/fixtures/projWithHooks/www/config.xml
new file mode 100644
index 0000000..9e7b9e0
--- /dev/null
+++ b/cordova-lib/spec-cordova/fixtures/projWithHooks/www/config.xml
@@ -0,0 +1,14 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget id="org.testing" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+    <name>TestBase</name>
+    <description>
+        A sample Apache Cordova application that responds to the deviceready event.
+    </description>
+    <author email="dev@cordova.apache.org" href="http://cordova.io">
+        Apache Cordova Team
+    </author>
+    <content src="index.html" />
+    <access origin="*" />
+    <preference name="fullscreen" value="true" />
+    <preference name="webviewbounce" value="true" />
+</widget>