You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by an...@apache.org on 2016/03/11 08:24:37 UTC

[1/6] ios commit: CB-10769 Copy raw pluginHandler tests from cordova-lib

Repository: cordova-ios
Updated Branches:
  refs/heads/master 70e16ef6e -> 000a61e60


http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/ios_parser.spec.js
----------------------------------------------------------------------
diff --git a/tests/spec/unit/ios_parser.spec.js b/tests/spec/unit/ios_parser.spec.js
new file mode 100644
index 0000000..736d48a
--- /dev/null
+++ b/tests/spec/unit/ios_parser.spec.js
@@ -0,0 +1,500 @@
+/**
+ 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 iosParser = require('../../src/cordova/metadata/ios_parser'),
+    util = require('../../src/cordova/util'),
+    path = require('path'),
+    shell = require('shelljs'),
+    plist = require('plist'),
+    xcode = require('xcode'),
+    fs = require('fs'),
+    Q = require('q'),
+    config = require('../../src/cordova/config'),
+    Parser = require('../../src/cordova/metadata/parser'),
+    ConfigParser = require('cordova-common').ConfigParser;
+
+var iosProjectFixture = path.join(__dirname, '../fixtures/projects/ios');
+var proj = path.join(__dirname, 'some/path');
+var ios_proj = path.join(proj, 'platforms/ios');
+
+shell.config.silent = true;
+
+// Create a real config object before mocking out everything.
+var cfg = new ConfigParser(path.join(__dirname, '..', 'test-config.xml'));
+var cfg2 = new ConfigParser(path.join(__dirname, '..', 'test-config-2.xml'));
+
+describe('ios project parser', function () {
+    var custom;
+    beforeEach(function() {
+        custom = spyOn(config, 'has_custom_path').andReturn(false);
+        shell.mkdir('-p', ios_proj);
+        shell.cp('-rf', iosProjectFixture + '/*', ios_proj);
+    });
+
+    afterEach(function () {
+        shell.rm('-rf', path.join(__dirname, 'some'));
+    });
+
+    function wrapper(p, done, post) {
+        p.then(post, function(err) {
+            expect(err.stack).toBeUndefined();
+        }).fin(done);
+    }
+
+    function errorWrapper(p, done, post) {
+        p.then(function() {
+            expect('this call').toBe('fail');
+        }, post).fin(done);
+    }
+
+    describe('constructions', function() {
+        it('should throw if provided directory does not contain an xcodeproj file', function() {
+            expect(function() {
+                new iosParser(proj);
+            }).toThrow();
+        });
+        it('should create an instance with path, pbxproj, xcodeproj, originalName and cordovaproj properties', function() {
+            expect(function() {
+                var p = new iosParser(ios_proj);
+                expect(p.path).toEqual(ios_proj);
+                expect(p.pbxproj).toEqual(path.join(ios_proj, 'test.xcodeproj', 'project.pbxproj'));
+                expect(p.xcodeproj).toEqual(path.join(ios_proj, 'test.xcodeproj'));
+            }).not.toThrow();
+        });
+        it('should be an instance of Parser', function() {
+            expect(new iosParser(ios_proj) instanceof Parser).toBe(true);
+        });
+        it('should call super with the correct arguments', function() {
+            var call = spyOn(Parser, 'call');
+            var p = new iosParser(ios_proj);
+            expect(call).toHaveBeenCalledWith(p, 'ios', ios_proj);
+        });
+    });
+
+    describe('instance', function() {
+        var p, is_cordova, getOrientation;
+        beforeEach(function() {
+            p = new iosParser(ios_proj);
+            is_cordova = spyOn(util, 'isCordova').andReturn(proj);
+            getOrientation = spyOn(p.helper, 'getOrientation');
+        });
+
+        describe('update_from_config method', function() {
+            var mv;
+            var plist_parse, plist_build, xc;
+            var update_name;
+            var xcOrig = xcode.project;
+            beforeEach(function() {
+                mv = spyOn(shell, 'mv');
+                plist_parse = spyOn(plist, 'parse').andReturn({
+                });
+                plist_build = spyOn(plist, 'build').andReturn('');
+                xc = spyOn(xcode, 'project')
+                .andCallFake(function (pbxproj) {
+                    var xc = new xcOrig(pbxproj);
+                    update_name = spyOn(xc, 'updateProductName').andCallThrough();
+                    return xc;
+                });
+                cfg.name = function() { return 'testname'; };
+                cfg.packageName = function() { return 'testpkg'; };
+                cfg.version = function() { return 'one point oh'; };
+            });
+
+            it('should update the app name in pbxproj by calling xcode.updateProductName, and move the ios native files to match the new name', function(done) {
+                var test_path = path.join(proj, 'platforms', 'ios', 'test');
+                var testname_path = path.join(proj, 'platforms', 'ios', 'testname');
+                wrapper(p.update_from_config(cfg), done, function() {
+                    expect(update_name).toHaveBeenCalledWith('testname');
+                    expect(mv).toHaveBeenCalledWith(path.join(test_path, 'test-Info.plist'), path.join(test_path, 'testname-Info.plist'));
+                    expect(mv).toHaveBeenCalledWith(path.join(test_path, 'test-Prefix.pch'), path.join(test_path, 'testname-Prefix.pch'));
+                    expect(mv).toHaveBeenCalledWith(test_path + '.xcodeproj', testname_path + '.xcodeproj');
+                    expect(mv).toHaveBeenCalledWith(test_path, testname_path);
+                });
+            });
+            it('should write out the app id to info plist as CFBundleIdentifier', function(done) {
+                cfg.ios_CFBundleIdentifier = function() { return null; };
+                wrapper(p.update_from_config(cfg), done, function() {
+                    expect(plist_build.mostRecentCall.args[0].CFBundleIdentifier).toEqual('testpkg');
+                });
+            });
+            it('should write out the app id to info plist as CFBundleIdentifier with ios-CFBundleIdentifier', function(done) {
+                cfg.ios_CFBundleIdentifier = function() { return 'testpkg_ios'; };
+                wrapper(p.update_from_config(cfg), done, function() {
+                    expect(plist_build.mostRecentCall.args[0].CFBundleIdentifier).toEqual('testpkg_ios');
+                });
+            });
+            it('should write out the app version to info plist as CFBundleVersion', function(done) {
+                wrapper(p.update_from_config(cfg), done, function() {
+                    expect(plist_build.mostRecentCall.args[0].CFBundleShortVersionString).toEqual('one point oh');
+                });
+            });
+            it('should write out the orientation preference value', function(done) {
+                getOrientation.andCallThrough();
+                wrapper(p.update_from_config(cfg), done, function() {
+                    expect(plist_build.mostRecentCall.args[0].UISupportedInterfaceOrientations).toEqual([ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown' ]);
+                    expect(plist_build.mostRecentCall.args[0]['UISupportedInterfaceOrientations~ipad']).toEqual([ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown' ]);
+                    expect(plist_build.mostRecentCall.args[0].UIInterfaceOrientation).toEqual([ 'UIInterfaceOrientationPortrait' ]);
+                });
+            });
+            it('should handle no orientation', function(done) {
+                getOrientation.andReturn('');
+                wrapper(p.update_from_config(cfg), done, function() {
+                    expect(plist_build.mostRecentCall.args[0].UISupportedInterfaceOrientations).toBeUndefined();
+                    expect(plist_build.mostRecentCall.args[0]['UISupportedInterfaceOrientations~ipad']).toBeUndefined();
+                    expect(plist_build.mostRecentCall.args[0].UIInterfaceOrientation).toBeUndefined();
+                });
+            });
+            it('should handle default orientation', function(done) {
+                getOrientation.andReturn(p.helper.ORIENTATION_DEFAULT);
+                wrapper(p.update_from_config(cfg), done, function() {
+                    expect(plist_build.mostRecentCall.args[0].UISupportedInterfaceOrientations).toBeUndefined();
+                    expect(plist_build.mostRecentCall.args[0]['UISupportedInterfaceOrientations~ipad']).toBeUndefined();
+                    expect(plist_build.mostRecentCall.args[0].UIInterfaceOrientation).toBeUndefined();
+                });
+            });
+            it('should handle portrait orientation', function(done) {
+                getOrientation.andReturn(p.helper.ORIENTATION_PORTRAIT);
+                wrapper(p.update_from_config(cfg), done, function() {
+                    expect(plist_build.mostRecentCall.args[0].UISupportedInterfaceOrientations).toEqual([ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown' ]);
+                    expect(plist_build.mostRecentCall.args[0].UIInterfaceOrientation).toEqual([ 'UIInterfaceOrientationPortrait' ]);
+                });
+            });
+            it('should handle landscape orientation', function(done) {
+                getOrientation.andReturn(p.helper.ORIENTATION_LANDSCAPE);
+                wrapper(p.update_from_config(cfg), done, function() {
+                    expect(plist_build.mostRecentCall.args[0].UISupportedInterfaceOrientations).toEqual([ 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight' ]);
+                    expect(plist_build.mostRecentCall.args[0].UIInterfaceOrientation).toEqual([ 'UIInterfaceOrientationLandscapeLeft' ]);
+                });
+            });
+            it('should handle all orientation on ios', function(done) {
+                getOrientation.andReturn(p.helper.ORIENTATION_ALL);
+                wrapper(p.update_from_config(cfg2), done, function() {
+                    expect(plist_build.mostRecentCall.args[0].UISupportedInterfaceOrientations).toEqual([ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown', 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight' ]);
+                    expect(plist_build.mostRecentCall.args[0].UIInterfaceOrientation).toEqual([ 'UIInterfaceOrientationPortrait' ]);
+                });
+            });
+            it('should handle custom orientation', function(done) {
+                getOrientation.andReturn('some-custom-orientation');
+                wrapper(p.update_from_config(cfg), done, function() {
+                    expect(plist_build.mostRecentCall.args[0].UISupportedInterfaceOrientations).toBeUndefined();
+                    expect(plist_build.mostRecentCall.args[0].UIInterfaceOrientation).toEqual([ 'some-custom-orientation' ]);
+                });
+            });
+            ///// App Transport Security Tests /////////////////////////////
+            it('<access> - should handle wildcard', function(done) {
+                wrapper(p.update_from_config(cfg), done, function() {
+                    var ats = plist_build.mostRecentCall.args[0].NSAppTransportSecurity;
+                    expect(ats.NSAllowsArbitraryLoads).toEqual(true);
+                });
+            });
+            it('<access> - https, subdomain wildcard', function(done) {
+                wrapper(p.update_from_config(cfg), done, function() {
+                    var ats = plist_build.mostRecentCall.args[0].NSAppTransportSecurity;
+                    var exceptionDomains = ats.NSExceptionDomains;
+                    var d;
+                    
+                    expect(exceptionDomains).toBeTruthy();
+                    
+                    d = exceptionDomains['server01.com'];
+                    expect(d).toBeTruthy();
+                    expect(d.NSIncludesSubdomains).toEqual(true);
+                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(null);
+                    expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
+                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
+                    
+                    d = exceptionDomains['server02.com'];
+                    expect(d).toBeTruthy();
+                    expect(d.NSIncludesSubdomains).toEqual(true);
+                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(null);
+                    expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
+                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
+
+                    d = exceptionDomains['server03.com'];
+                    expect(d).toBeTruthy();
+                    expect(d.NSIncludesSubdomains).toEqual(true);
+                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(null);
+                    expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
+                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
+                    
+                    d = exceptionDomains['server04.com'];
+                    expect(d).toBeTruthy();
+                    expect(d.NSIncludesSubdomains).toEqual(true);
+                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(null);
+                    expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
+                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
+                });
+            });
+            it('<access> - http, no wildcard', function(done) {
+                wrapper(p.update_from_config(cfg), done, function() {
+                    var ats = plist_build.mostRecentCall.args[0].NSAppTransportSecurity;
+                    var exceptionDomains = ats.NSExceptionDomains;
+                    var d;
+                    
+                    expect(exceptionDomains).toBeTruthy();
+                    
+                    d = exceptionDomains['server05.com'];
+                    expect(d).toBeTruthy();
+                    expect(d.NSIncludesSubdomains).toEqual(null);
+                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
+                    expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
+                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
+
+                    d = exceptionDomains['server06.com'];
+                    expect(d).toBeTruthy();
+                    expect(d.NSIncludesSubdomains).toEqual(null);
+                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
+                    expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
+                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
+
+                    d = exceptionDomains['server07.com'];
+                    expect(d).toBeTruthy();
+                    expect(d.NSIncludesSubdomains).toEqual(null);
+                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
+                    expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
+                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
+
+                    d = exceptionDomains['server08.com'];
+                    expect(d).toBeTruthy();
+                    expect(d.NSIncludesSubdomains).toEqual(null);
+                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
+                    expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
+                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
+                });
+            });
+            it('<access> - https, no wildcard', function(done) {
+                wrapper(p.update_from_config(cfg), done, function() {
+                    var ats = plist_build.mostRecentCall.args[0].NSAppTransportSecurity;
+                    var exceptionDomains = ats.NSExceptionDomains;
+                    var d;
+                    
+                    expect(exceptionDomains).toBeTruthy();
+                    
+                    d = exceptionDomains['server09.com'];
+                    expect(d).toBeTruthy();
+                    expect(d.NSIncludesSubdomains).toEqual(null);
+                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(null);
+                    expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
+                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
+
+                    d = exceptionDomains['server10.com'];
+                    expect(d).toBeTruthy();
+                    expect(d.NSIncludesSubdomains).toEqual(null);
+                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(null);
+                    expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
+                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
+
+                    d = exceptionDomains['server11.com'];
+                    expect(d).toBeTruthy();
+                    expect(d.NSIncludesSubdomains).toEqual(null);
+                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(null);
+                    expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
+                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
+
+                    d = exceptionDomains['server12.com'];
+                    expect(d).toBeTruthy();
+                    expect(d.NSIncludesSubdomains).toEqual(null);
+                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(null);
+                    expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
+                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
+                });
+            });
+            //////////////////////////////////////////////////
+            it('<access>, <allow-navigation> - http and https, no clobber', function(done) {
+                wrapper(p.update_from_config(cfg2), done, function() {
+                    var ats = plist_build.mostRecentCall.args[0].NSAppTransportSecurity;
+                    var exceptionDomains = ats.NSExceptionDomains;
+                    var d;
+                    
+                    expect(exceptionDomains).toBeTruthy();
+                    
+                    d = exceptionDomains['apache.org'];
+                    expect(d).toBeTruthy();
+                    expect(d.NSIncludesSubdomains).toEqual(true);
+                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
+                    expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
+                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
+                });
+            });
+            //////////////////////////////////////////////////
+            it('<allow-navigation> - wildcard scheme, wildcard subdomain', function(done) {
+                wrapper(p.update_from_config(cfg), done, function() {
+                    var ats = plist_build.mostRecentCall.args[0].NSAppTransportSecurity;
+                    var exceptionDomains = ats.NSExceptionDomains;
+                    var d;
+                    
+                    expect(exceptionDomains).toBeTruthy();
+                    
+                    d = exceptionDomains['server33.com'];
+                    expect(d).toBeTruthy();
+                    expect(d.NSIncludesSubdomains).toEqual(true);
+                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
+                    expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
+                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
+
+                    d = exceptionDomains['server34.com'];
+                    expect(d).toBeTruthy();
+                    expect(d.NSIncludesSubdomains).toEqual(true);
+                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
+                    expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
+                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
+
+                    d = exceptionDomains['server35.com'];
+                    expect(d).toBeTruthy();
+                    expect(d.NSIncludesSubdomains).toEqual(true);
+                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
+                    expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
+                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
+
+                    d = exceptionDomains['server36.com'];
+                    expect(d).toBeTruthy();
+                    expect(d.NSIncludesSubdomains).toEqual(true);
+                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
+                    expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
+                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
+                });
+            });
+            it('<allow-navigation> - wildcard scheme, no subdomain', function(done) {
+                wrapper(p.update_from_config(cfg), done, function() {
+                    var ats = plist_build.mostRecentCall.args[0].NSAppTransportSecurity;
+                    var exceptionDomains = ats.NSExceptionDomains;
+                    var d;
+                    
+                    expect(exceptionDomains).toBeTruthy();
+                    
+                    d = exceptionDomains['server37.com'];
+                    expect(d).toBeTruthy();
+                    expect(d.NSIncludesSubdomains).toEqual(null);
+                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
+                    expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
+                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
+
+                    d = exceptionDomains['server38.com'];
+                    expect(d).toBeTruthy();
+                    expect(d.NSIncludesSubdomains).toEqual(null);
+                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
+                    expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
+                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
+
+                    d = exceptionDomains['server39.com'];
+                    expect(d).toBeTruthy();
+                    expect(d.NSIncludesSubdomains).toEqual(null);
+                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
+                    expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
+                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
+
+                    d = exceptionDomains['server40.com'];
+                    expect(d).toBeTruthy();
+                    expect(d.NSIncludesSubdomains).toEqual(null);
+                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
+                    expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
+                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
+                });
+            });
+            it('<allow-navigation> - should ignore wildcards like data:*, https:*, https://*', function(done) {
+                wrapper(p.update_from_config(cfg), done, function() {
+                    var ats = plist_build.mostRecentCall.args[0].NSAppTransportSecurity;
+                    var exceptionDomains = ats.NSExceptionDomains;
+                    expect(exceptionDomains['']).toBeUndefined();
+                    expect(exceptionDomains['null']).toBeUndefined();
+                    expect(exceptionDomains['undefined']).toBeUndefined();
+                });
+            });
+        });
+        describe('www_dir method', function() {
+            it('should return /www', function() {
+                expect(p.www_dir()).toEqual(path.join(ios_proj, 'www'));
+            });
+        });
+        describe('config_xml method', function() {
+            it('should return the location of the config.xml', function() {
+                expect(p.config_xml()).toEqual(path.join(ios_proj, 'test', 'config.xml'));
+            });
+        });
+        describe('update_www method', function() {
+            var cp, rm;
+
+            beforeEach(function () {
+                rm = spyOn(shell, 'rm').andCallThrough();
+                cp = spyOn(shell, 'cp').andCallThrough();
+            });
+
+            it('should rm project-level www and cp in platform agnostic www', function() {
+                p.update_www(path.join('lib','dir'));
+                expect(rm).toHaveBeenCalled();
+                expect(cp).toHaveBeenCalled();
+            });
+        });
+        describe('update_overrides method', function() {
+            var exists, rm, cp;
+            beforeEach(function() {
+                exists = spyOn(fs, 'existsSync').andCallThrough();
+                rm = spyOn(shell, 'rm').andCallThrough();
+                cp = spyOn(shell, 'cp').andCallThrough();
+            });
+            it('should do nothing if merges directory does not exist', function() {
+                cp.reset();
+                exists.andReturn(false);
+                p.update_overrides();
+                expect(cp).not.toHaveBeenCalled();
+            });
+            it('should copy merges path into www', function() {
+                cp.andCallFake(function(){});
+                cp.reset();
+                exists.andReturn(true);
+                p.update_overrides();
+                expect(cp).toHaveBeenCalled();
+            });
+        });
+        describe('update_project method', function() {
+            var config, www, overrides, svn;
+            beforeEach(function() {
+                config = spyOn(p, 'update_from_config').andReturn(Q());
+                www = spyOn(p, 'update_www');
+                overrides = spyOn(p, 'update_overrides');
+                svn = spyOn(util, 'deleteSvnFolders');
+            });
+            it('should call update_from_config', function(done) {
+                wrapper(p.update_project(), done, function() {
+                    expect(config).toHaveBeenCalled();
+                });
+            });
+            it('should throw if update_from_config errors', function(done) {
+                var e = new Error('uh oh!');
+                config.andReturn(Q.reject(e));
+                errorWrapper(p.update_project({}), done, function(err) {
+                    expect(err).toEqual(e);
+                });
+            });
+            it('should not call update_www', function(done) {
+                wrapper(p.update_project({}), done, function() {
+                    expect(www).not().toHaveBeenCalled();
+                });
+            });
+            it('should call update_overrides', function(done) {
+                wrapper(p.update_project(), done, function() {
+                    expect(overrides).toHaveBeenCalled();
+                });
+            });
+            it('should call deleteSvnFolders', function(done) {
+                wrapper(p.update_project(), done, function() {
+                    expect(svn).toHaveBeenCalled();
+                });
+            });
+        });
+    });
+});


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org


[5/6] ios commit: CB-10769 Update specs according to actual implementation

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/000a61e6/tests/spec/unit/ios_parser.spec.js
----------------------------------------------------------------------
diff --git a/tests/spec/unit/ios_parser.spec.js b/tests/spec/unit/ios_parser.spec.js
deleted file mode 100644
index 736d48a..0000000
--- a/tests/spec/unit/ios_parser.spec.js
+++ /dev/null
@@ -1,500 +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 iosParser = require('../../src/cordova/metadata/ios_parser'),
-    util = require('../../src/cordova/util'),
-    path = require('path'),
-    shell = require('shelljs'),
-    plist = require('plist'),
-    xcode = require('xcode'),
-    fs = require('fs'),
-    Q = require('q'),
-    config = require('../../src/cordova/config'),
-    Parser = require('../../src/cordova/metadata/parser'),
-    ConfigParser = require('cordova-common').ConfigParser;
-
-var iosProjectFixture = path.join(__dirname, '../fixtures/projects/ios');
-var proj = path.join(__dirname, 'some/path');
-var ios_proj = path.join(proj, 'platforms/ios');
-
-shell.config.silent = true;
-
-// Create a real config object before mocking out everything.
-var cfg = new ConfigParser(path.join(__dirname, '..', 'test-config.xml'));
-var cfg2 = new ConfigParser(path.join(__dirname, '..', 'test-config-2.xml'));
-
-describe('ios project parser', function () {
-    var custom;
-    beforeEach(function() {
-        custom = spyOn(config, 'has_custom_path').andReturn(false);
-        shell.mkdir('-p', ios_proj);
-        shell.cp('-rf', iosProjectFixture + '/*', ios_proj);
-    });
-
-    afterEach(function () {
-        shell.rm('-rf', path.join(__dirname, 'some'));
-    });
-
-    function wrapper(p, done, post) {
-        p.then(post, function(err) {
-            expect(err.stack).toBeUndefined();
-        }).fin(done);
-    }
-
-    function errorWrapper(p, done, post) {
-        p.then(function() {
-            expect('this call').toBe('fail');
-        }, post).fin(done);
-    }
-
-    describe('constructions', function() {
-        it('should throw if provided directory does not contain an xcodeproj file', function() {
-            expect(function() {
-                new iosParser(proj);
-            }).toThrow();
-        });
-        it('should create an instance with path, pbxproj, xcodeproj, originalName and cordovaproj properties', function() {
-            expect(function() {
-                var p = new iosParser(ios_proj);
-                expect(p.path).toEqual(ios_proj);
-                expect(p.pbxproj).toEqual(path.join(ios_proj, 'test.xcodeproj', 'project.pbxproj'));
-                expect(p.xcodeproj).toEqual(path.join(ios_proj, 'test.xcodeproj'));
-            }).not.toThrow();
-        });
-        it('should be an instance of Parser', function() {
-            expect(new iosParser(ios_proj) instanceof Parser).toBe(true);
-        });
-        it('should call super with the correct arguments', function() {
-            var call = spyOn(Parser, 'call');
-            var p = new iosParser(ios_proj);
-            expect(call).toHaveBeenCalledWith(p, 'ios', ios_proj);
-        });
-    });
-
-    describe('instance', function() {
-        var p, is_cordova, getOrientation;
-        beforeEach(function() {
-            p = new iosParser(ios_proj);
-            is_cordova = spyOn(util, 'isCordova').andReturn(proj);
-            getOrientation = spyOn(p.helper, 'getOrientation');
-        });
-
-        describe('update_from_config method', function() {
-            var mv;
-            var plist_parse, plist_build, xc;
-            var update_name;
-            var xcOrig = xcode.project;
-            beforeEach(function() {
-                mv = spyOn(shell, 'mv');
-                plist_parse = spyOn(plist, 'parse').andReturn({
-                });
-                plist_build = spyOn(plist, 'build').andReturn('');
-                xc = spyOn(xcode, 'project')
-                .andCallFake(function (pbxproj) {
-                    var xc = new xcOrig(pbxproj);
-                    update_name = spyOn(xc, 'updateProductName').andCallThrough();
-                    return xc;
-                });
-                cfg.name = function() { return 'testname'; };
-                cfg.packageName = function() { return 'testpkg'; };
-                cfg.version = function() { return 'one point oh'; };
-            });
-
-            it('should update the app name in pbxproj by calling xcode.updateProductName, and move the ios native files to match the new name', function(done) {
-                var test_path = path.join(proj, 'platforms', 'ios', 'test');
-                var testname_path = path.join(proj, 'platforms', 'ios', 'testname');
-                wrapper(p.update_from_config(cfg), done, function() {
-                    expect(update_name).toHaveBeenCalledWith('testname');
-                    expect(mv).toHaveBeenCalledWith(path.join(test_path, 'test-Info.plist'), path.join(test_path, 'testname-Info.plist'));
-                    expect(mv).toHaveBeenCalledWith(path.join(test_path, 'test-Prefix.pch'), path.join(test_path, 'testname-Prefix.pch'));
-                    expect(mv).toHaveBeenCalledWith(test_path + '.xcodeproj', testname_path + '.xcodeproj');
-                    expect(mv).toHaveBeenCalledWith(test_path, testname_path);
-                });
-            });
-            it('should write out the app id to info plist as CFBundleIdentifier', function(done) {
-                cfg.ios_CFBundleIdentifier = function() { return null; };
-                wrapper(p.update_from_config(cfg), done, function() {
-                    expect(plist_build.mostRecentCall.args[0].CFBundleIdentifier).toEqual('testpkg');
-                });
-            });
-            it('should write out the app id to info plist as CFBundleIdentifier with ios-CFBundleIdentifier', function(done) {
-                cfg.ios_CFBundleIdentifier = function() { return 'testpkg_ios'; };
-                wrapper(p.update_from_config(cfg), done, function() {
-                    expect(plist_build.mostRecentCall.args[0].CFBundleIdentifier).toEqual('testpkg_ios');
-                });
-            });
-            it('should write out the app version to info plist as CFBundleVersion', function(done) {
-                wrapper(p.update_from_config(cfg), done, function() {
-                    expect(plist_build.mostRecentCall.args[0].CFBundleShortVersionString).toEqual('one point oh');
-                });
-            });
-            it('should write out the orientation preference value', function(done) {
-                getOrientation.andCallThrough();
-                wrapper(p.update_from_config(cfg), done, function() {
-                    expect(plist_build.mostRecentCall.args[0].UISupportedInterfaceOrientations).toEqual([ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown' ]);
-                    expect(plist_build.mostRecentCall.args[0]['UISupportedInterfaceOrientations~ipad']).toEqual([ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown' ]);
-                    expect(plist_build.mostRecentCall.args[0].UIInterfaceOrientation).toEqual([ 'UIInterfaceOrientationPortrait' ]);
-                });
-            });
-            it('should handle no orientation', function(done) {
-                getOrientation.andReturn('');
-                wrapper(p.update_from_config(cfg), done, function() {
-                    expect(plist_build.mostRecentCall.args[0].UISupportedInterfaceOrientations).toBeUndefined();
-                    expect(plist_build.mostRecentCall.args[0]['UISupportedInterfaceOrientations~ipad']).toBeUndefined();
-                    expect(plist_build.mostRecentCall.args[0].UIInterfaceOrientation).toBeUndefined();
-                });
-            });
-            it('should handle default orientation', function(done) {
-                getOrientation.andReturn(p.helper.ORIENTATION_DEFAULT);
-                wrapper(p.update_from_config(cfg), done, function() {
-                    expect(plist_build.mostRecentCall.args[0].UISupportedInterfaceOrientations).toBeUndefined();
-                    expect(plist_build.mostRecentCall.args[0]['UISupportedInterfaceOrientations~ipad']).toBeUndefined();
-                    expect(plist_build.mostRecentCall.args[0].UIInterfaceOrientation).toBeUndefined();
-                });
-            });
-            it('should handle portrait orientation', function(done) {
-                getOrientation.andReturn(p.helper.ORIENTATION_PORTRAIT);
-                wrapper(p.update_from_config(cfg), done, function() {
-                    expect(plist_build.mostRecentCall.args[0].UISupportedInterfaceOrientations).toEqual([ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown' ]);
-                    expect(plist_build.mostRecentCall.args[0].UIInterfaceOrientation).toEqual([ 'UIInterfaceOrientationPortrait' ]);
-                });
-            });
-            it('should handle landscape orientation', function(done) {
-                getOrientation.andReturn(p.helper.ORIENTATION_LANDSCAPE);
-                wrapper(p.update_from_config(cfg), done, function() {
-                    expect(plist_build.mostRecentCall.args[0].UISupportedInterfaceOrientations).toEqual([ 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight' ]);
-                    expect(plist_build.mostRecentCall.args[0].UIInterfaceOrientation).toEqual([ 'UIInterfaceOrientationLandscapeLeft' ]);
-                });
-            });
-            it('should handle all orientation on ios', function(done) {
-                getOrientation.andReturn(p.helper.ORIENTATION_ALL);
-                wrapper(p.update_from_config(cfg2), done, function() {
-                    expect(plist_build.mostRecentCall.args[0].UISupportedInterfaceOrientations).toEqual([ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown', 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight' ]);
-                    expect(plist_build.mostRecentCall.args[0].UIInterfaceOrientation).toEqual([ 'UIInterfaceOrientationPortrait' ]);
-                });
-            });
-            it('should handle custom orientation', function(done) {
-                getOrientation.andReturn('some-custom-orientation');
-                wrapper(p.update_from_config(cfg), done, function() {
-                    expect(plist_build.mostRecentCall.args[0].UISupportedInterfaceOrientations).toBeUndefined();
-                    expect(plist_build.mostRecentCall.args[0].UIInterfaceOrientation).toEqual([ 'some-custom-orientation' ]);
-                });
-            });
-            ///// App Transport Security Tests /////////////////////////////
-            it('<access> - should handle wildcard', function(done) {
-                wrapper(p.update_from_config(cfg), done, function() {
-                    var ats = plist_build.mostRecentCall.args[0].NSAppTransportSecurity;
-                    expect(ats.NSAllowsArbitraryLoads).toEqual(true);
-                });
-            });
-            it('<access> - https, subdomain wildcard', function(done) {
-                wrapper(p.update_from_config(cfg), done, function() {
-                    var ats = plist_build.mostRecentCall.args[0].NSAppTransportSecurity;
-                    var exceptionDomains = ats.NSExceptionDomains;
-                    var d;
-                    
-                    expect(exceptionDomains).toBeTruthy();
-                    
-                    d = exceptionDomains['server01.com'];
-                    expect(d).toBeTruthy();
-                    expect(d.NSIncludesSubdomains).toEqual(true);
-                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(null);
-                    expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
-                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
-                    
-                    d = exceptionDomains['server02.com'];
-                    expect(d).toBeTruthy();
-                    expect(d.NSIncludesSubdomains).toEqual(true);
-                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(null);
-                    expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
-                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
-
-                    d = exceptionDomains['server03.com'];
-                    expect(d).toBeTruthy();
-                    expect(d.NSIncludesSubdomains).toEqual(true);
-                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(null);
-                    expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
-                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
-                    
-                    d = exceptionDomains['server04.com'];
-                    expect(d).toBeTruthy();
-                    expect(d.NSIncludesSubdomains).toEqual(true);
-                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(null);
-                    expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
-                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
-                });
-            });
-            it('<access> - http, no wildcard', function(done) {
-                wrapper(p.update_from_config(cfg), done, function() {
-                    var ats = plist_build.mostRecentCall.args[0].NSAppTransportSecurity;
-                    var exceptionDomains = ats.NSExceptionDomains;
-                    var d;
-                    
-                    expect(exceptionDomains).toBeTruthy();
-                    
-                    d = exceptionDomains['server05.com'];
-                    expect(d).toBeTruthy();
-                    expect(d.NSIncludesSubdomains).toEqual(null);
-                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
-                    expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
-                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
-
-                    d = exceptionDomains['server06.com'];
-                    expect(d).toBeTruthy();
-                    expect(d.NSIncludesSubdomains).toEqual(null);
-                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
-                    expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
-                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
-
-                    d = exceptionDomains['server07.com'];
-                    expect(d).toBeTruthy();
-                    expect(d.NSIncludesSubdomains).toEqual(null);
-                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
-                    expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
-                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
-
-                    d = exceptionDomains['server08.com'];
-                    expect(d).toBeTruthy();
-                    expect(d.NSIncludesSubdomains).toEqual(null);
-                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
-                    expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
-                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
-                });
-            });
-            it('<access> - https, no wildcard', function(done) {
-                wrapper(p.update_from_config(cfg), done, function() {
-                    var ats = plist_build.mostRecentCall.args[0].NSAppTransportSecurity;
-                    var exceptionDomains = ats.NSExceptionDomains;
-                    var d;
-                    
-                    expect(exceptionDomains).toBeTruthy();
-                    
-                    d = exceptionDomains['server09.com'];
-                    expect(d).toBeTruthy();
-                    expect(d.NSIncludesSubdomains).toEqual(null);
-                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(null);
-                    expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
-                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
-
-                    d = exceptionDomains['server10.com'];
-                    expect(d).toBeTruthy();
-                    expect(d.NSIncludesSubdomains).toEqual(null);
-                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(null);
-                    expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
-                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
-
-                    d = exceptionDomains['server11.com'];
-                    expect(d).toBeTruthy();
-                    expect(d.NSIncludesSubdomains).toEqual(null);
-                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(null);
-                    expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
-                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
-
-                    d = exceptionDomains['server12.com'];
-                    expect(d).toBeTruthy();
-                    expect(d.NSIncludesSubdomains).toEqual(null);
-                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(null);
-                    expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
-                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
-                });
-            });
-            //////////////////////////////////////////////////
-            it('<access>, <allow-navigation> - http and https, no clobber', function(done) {
-                wrapper(p.update_from_config(cfg2), done, function() {
-                    var ats = plist_build.mostRecentCall.args[0].NSAppTransportSecurity;
-                    var exceptionDomains = ats.NSExceptionDomains;
-                    var d;
-                    
-                    expect(exceptionDomains).toBeTruthy();
-                    
-                    d = exceptionDomains['apache.org'];
-                    expect(d).toBeTruthy();
-                    expect(d.NSIncludesSubdomains).toEqual(true);
-                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
-                    expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
-                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
-                });
-            });
-            //////////////////////////////////////////////////
-            it('<allow-navigation> - wildcard scheme, wildcard subdomain', function(done) {
-                wrapper(p.update_from_config(cfg), done, function() {
-                    var ats = plist_build.mostRecentCall.args[0].NSAppTransportSecurity;
-                    var exceptionDomains = ats.NSExceptionDomains;
-                    var d;
-                    
-                    expect(exceptionDomains).toBeTruthy();
-                    
-                    d = exceptionDomains['server33.com'];
-                    expect(d).toBeTruthy();
-                    expect(d.NSIncludesSubdomains).toEqual(true);
-                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
-                    expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
-                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
-
-                    d = exceptionDomains['server34.com'];
-                    expect(d).toBeTruthy();
-                    expect(d.NSIncludesSubdomains).toEqual(true);
-                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
-                    expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
-                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
-
-                    d = exceptionDomains['server35.com'];
-                    expect(d).toBeTruthy();
-                    expect(d.NSIncludesSubdomains).toEqual(true);
-                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
-                    expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
-                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
-
-                    d = exceptionDomains['server36.com'];
-                    expect(d).toBeTruthy();
-                    expect(d.NSIncludesSubdomains).toEqual(true);
-                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
-                    expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
-                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
-                });
-            });
-            it('<allow-navigation> - wildcard scheme, no subdomain', function(done) {
-                wrapper(p.update_from_config(cfg), done, function() {
-                    var ats = plist_build.mostRecentCall.args[0].NSAppTransportSecurity;
-                    var exceptionDomains = ats.NSExceptionDomains;
-                    var d;
-                    
-                    expect(exceptionDomains).toBeTruthy();
-                    
-                    d = exceptionDomains['server37.com'];
-                    expect(d).toBeTruthy();
-                    expect(d.NSIncludesSubdomains).toEqual(null);
-                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
-                    expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
-                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
-
-                    d = exceptionDomains['server38.com'];
-                    expect(d).toBeTruthy();
-                    expect(d.NSIncludesSubdomains).toEqual(null);
-                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
-                    expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
-                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
-
-                    d = exceptionDomains['server39.com'];
-                    expect(d).toBeTruthy();
-                    expect(d.NSIncludesSubdomains).toEqual(null);
-                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
-                    expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
-                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
-
-                    d = exceptionDomains['server40.com'];
-                    expect(d).toBeTruthy();
-                    expect(d.NSIncludesSubdomains).toEqual(null);
-                    expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
-                    expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
-                    expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
-                });
-            });
-            it('<allow-navigation> - should ignore wildcards like data:*, https:*, https://*', function(done) {
-                wrapper(p.update_from_config(cfg), done, function() {
-                    var ats = plist_build.mostRecentCall.args[0].NSAppTransportSecurity;
-                    var exceptionDomains = ats.NSExceptionDomains;
-                    expect(exceptionDomains['']).toBeUndefined();
-                    expect(exceptionDomains['null']).toBeUndefined();
-                    expect(exceptionDomains['undefined']).toBeUndefined();
-                });
-            });
-        });
-        describe('www_dir method', function() {
-            it('should return /www', function() {
-                expect(p.www_dir()).toEqual(path.join(ios_proj, 'www'));
-            });
-        });
-        describe('config_xml method', function() {
-            it('should return the location of the config.xml', function() {
-                expect(p.config_xml()).toEqual(path.join(ios_proj, 'test', 'config.xml'));
-            });
-        });
-        describe('update_www method', function() {
-            var cp, rm;
-
-            beforeEach(function () {
-                rm = spyOn(shell, 'rm').andCallThrough();
-                cp = spyOn(shell, 'cp').andCallThrough();
-            });
-
-            it('should rm project-level www and cp in platform agnostic www', function() {
-                p.update_www(path.join('lib','dir'));
-                expect(rm).toHaveBeenCalled();
-                expect(cp).toHaveBeenCalled();
-            });
-        });
-        describe('update_overrides method', function() {
-            var exists, rm, cp;
-            beforeEach(function() {
-                exists = spyOn(fs, 'existsSync').andCallThrough();
-                rm = spyOn(shell, 'rm').andCallThrough();
-                cp = spyOn(shell, 'cp').andCallThrough();
-            });
-            it('should do nothing if merges directory does not exist', function() {
-                cp.reset();
-                exists.andReturn(false);
-                p.update_overrides();
-                expect(cp).not.toHaveBeenCalled();
-            });
-            it('should copy merges path into www', function() {
-                cp.andCallFake(function(){});
-                cp.reset();
-                exists.andReturn(true);
-                p.update_overrides();
-                expect(cp).toHaveBeenCalled();
-            });
-        });
-        describe('update_project method', function() {
-            var config, www, overrides, svn;
-            beforeEach(function() {
-                config = spyOn(p, 'update_from_config').andReturn(Q());
-                www = spyOn(p, 'update_www');
-                overrides = spyOn(p, 'update_overrides');
-                svn = spyOn(util, 'deleteSvnFolders');
-            });
-            it('should call update_from_config', function(done) {
-                wrapper(p.update_project(), done, function() {
-                    expect(config).toHaveBeenCalled();
-                });
-            });
-            it('should throw if update_from_config errors', function(done) {
-                var e = new Error('uh oh!');
-                config.andReturn(Q.reject(e));
-                errorWrapper(p.update_project({}), done, function(err) {
-                    expect(err).toEqual(e);
-                });
-            });
-            it('should not call update_www', function(done) {
-                wrapper(p.update_project({}), done, function() {
-                    expect(www).not().toHaveBeenCalled();
-                });
-            });
-            it('should call update_overrides', function(done) {
-                wrapper(p.update_project(), done, function() {
-                    expect(overrides).toHaveBeenCalled();
-                });
-            });
-            it('should call deleteSvnFolders', function(done) {
-                wrapper(p.update_project(), done, function() {
-                    expect(svn).toHaveBeenCalled();
-                });
-            });
-        });
-    });
-});

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/000a61e6/tests/spec/unit/prepare.spec.js
----------------------------------------------------------------------
diff --git a/tests/spec/unit/prepare.spec.js b/tests/spec/unit/prepare.spec.js
new file mode 100644
index 0000000..be8bb12
--- /dev/null
+++ b/tests/spec/unit/prepare.spec.js
@@ -0,0 +1,417 @@
+/**
+ 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 os = require('os');
+var path = require('path');
+var shell = require('shelljs');
+var plist = require('plist');
+var xcode = require('xcode');
+var rewire = require('rewire');
+var Api = require('../../../bin/templates/scripts/cordova/Api');
+var prepare = rewire('../../../bin/templates/scripts/cordova/lib/prepare');
+
+var FIXTURES = path.join(__dirname, 'fixtures');
+
+var iosProjectFixture = path.join(FIXTURES, 'ios-config-xml');
+var iosProject = path.join(os.tmpdir(), 'prepare');
+var iosPlatform = path.join(iosProject, 'platforms/ios');
+
+shell.config.silent = true;
+
+var ConfigParser = require('cordova-common').ConfigParser;
+// Create a real config object before mocking out everything.
+var cfg = new ConfigParser(path.join(FIXTURES, 'test-config.xml'));
+var cfg2 = new ConfigParser(path.join(FIXTURES, 'test-config-2.xml'));
+
+
+function wrapper(p, done, post) {
+    p.then(post, function(err) {
+        expect(err.stack).toBeUndefined();
+    }).fin(done);
+}
+
+describe('prepare', function () {
+    var p;
+    beforeEach(function() {
+        shell.mkdir('-p', iosPlatform);
+        shell.cp('-rf', iosProjectFixture + '/*', iosPlatform);
+        p = new Api('ios', iosPlatform);
+    });
+
+    afterEach(function () {
+        shell.rm('-rf', path.join(__dirname, 'some'));
+    });
+
+    describe('updateProject method', function() {
+        var mv;
+        var update_name;
+        var xcOrig = xcode.project;
+
+        var updateProject = prepare.__get__('updateProject');
+
+        beforeEach(function() {
+            mv = spyOn(shell, 'mv');
+            spyOn(plist, 'parse').andReturn({});
+            spyOn(plist, 'build').andReturn('');
+            spyOn(xcode, 'project').andCallFake(function (pbxproj) {
+                var xc = new xcOrig(pbxproj);
+                update_name = spyOn(xc, 'updateProductName').andCallThrough();
+                return xc;
+            });
+            cfg.name = function() { return 'SampleApp'; };
+            cfg2.name = function() { return 'SampleApp'; };
+            cfg.packageName = function() { return 'testpkg'; };
+            cfg.version = function() { return 'one point oh'; };
+
+            spyOn(cfg, 'getPreference');
+        });
+
+        it('should update the app name in pbxproj by calling xcode.updateProductName, and move the ios native files to match the new name', function(done) {
+            var test_path = path.join(iosProject, 'platforms/ios/test');
+            var testname_path = path.join(iosProject, 'platforms/ios/testname');
+            wrapper(updateProject(cfg, p.locations), done, function() {
+                expect(update_name).toHaveBeenCalledWith('testname');
+                expect(mv).toHaveBeenCalledWith(path.join(test_path, 'test-Info.plist'), path.join(test_path, 'testname-Info.plist'));
+                expect(mv).toHaveBeenCalledWith(path.join(test_path, 'test-Prefix.pch'), path.join(test_path, 'testname-Prefix.pch'));
+                expect(mv).toHaveBeenCalledWith(test_path + '.xcodeproj', testname_path + '.xcodeproj');
+                expect(mv).toHaveBeenCalledWith(test_path, testname_path);
+            });
+        });
+        it('should write out the app id to info plist as CFBundleIdentifier', function(done) {
+            cfg.ios_CFBundleIdentifier = function() { return null; };
+            wrapper(updateProject(cfg, p.locations), done, function() {
+                expect(plist.build.mostRecentCall.args[0].CFBundleIdentifier).toEqual('testpkg');
+            });
+        });
+        it('should write out the app id to info plist as CFBundleIdentifier with ios-CFBundleIdentifier', function(done) {
+            cfg.ios_CFBundleIdentifier = function() { return 'testpkg_ios'; };
+            wrapper(updateProject(cfg, p.locations), done, function() {
+                expect(plist.build.mostRecentCall.args[0].CFBundleIdentifier).toEqual('testpkg_ios');
+            });
+        });
+        it('should write out the app version to info plist as CFBundleVersion', function(done) {
+            wrapper(updateProject(cfg, p.locations), done, function() {
+                expect(plist.build.mostRecentCall.args[0].CFBundleShortVersionString).toEqual('one point oh');
+            });
+        });
+        it('should write out the orientation preference value', function(done) {
+            cfg.getPreference.andCallThrough();
+            wrapper(updateProject(cfg, p.locations), done, function() {
+                expect(plist.build.mostRecentCall.args[0].UISupportedInterfaceOrientations).toEqual([ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown' ]);
+                expect(plist.build.mostRecentCall.args[0]['UISupportedInterfaceOrientations~ipad']).toEqual([ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown' ]);
+                expect(plist.build.mostRecentCall.args[0].UIInterfaceOrientation).toEqual([ 'UIInterfaceOrientationPortrait' ]);
+            });
+        });
+        it('should handle no orientation', function(done) {
+            cfg.getPreference.andReturn('');
+            wrapper(updateProject(cfg, p.locations), done, function() {
+                expect(plist.build.mostRecentCall.args[0].UISupportedInterfaceOrientations).toBeUndefined();
+                expect(plist.build.mostRecentCall.args[0]['UISupportedInterfaceOrientations~ipad']).toBeUndefined();
+                expect(plist.build.mostRecentCall.args[0].UIInterfaceOrientation).toBeUndefined();
+            });
+        });
+        it('should handle default orientation', function(done) {
+            cfg.getPreference.andReturn('default');
+            wrapper(updateProject(cfg, p.locations), done, function() {
+                expect(plist.build.mostRecentCall.args[0].UISupportedInterfaceOrientations).toBeUndefined();
+                expect(plist.build.mostRecentCall.args[0]['UISupportedInterfaceOrientations~ipad']).toBeUndefined();
+                expect(plist.build.mostRecentCall.args[0].UIInterfaceOrientation).toBeUndefined();
+            });
+        });
+        it('should handle portrait orientation', function(done) {
+            cfg.getPreference.andReturn('portrait');
+            wrapper(updateProject(cfg, p.locations), done, function() {
+                expect(plist.build.mostRecentCall.args[0].UISupportedInterfaceOrientations).toEqual([ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown' ]);
+                expect(plist.build.mostRecentCall.args[0].UIInterfaceOrientation).toEqual([ 'UIInterfaceOrientationPortrait' ]);
+            });
+        });
+        it('should handle landscape orientation', function(done) {
+            cfg.getPreference.andReturn('landscape');
+            wrapper(updateProject(cfg, p.locations), done, function() {
+                expect(plist.build.mostRecentCall.args[0].UISupportedInterfaceOrientations).toEqual([ 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight' ]);
+                expect(plist.build.mostRecentCall.args[0].UIInterfaceOrientation).toEqual([ 'UIInterfaceOrientationLandscapeLeft' ]);
+            });
+        });
+        it('should handle all orientation on ios', function(done) {
+            cfg.getPreference.andReturn('all');
+            wrapper(updateProject(cfg, p.locations), done, function() {
+                expect(plist.build.mostRecentCall.args[0].UISupportedInterfaceOrientations).toEqual([ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown', 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight' ]);
+                expect(plist.build.mostRecentCall.args[0].UIInterfaceOrientation).toEqual([ 'UIInterfaceOrientationPortrait' ]);
+            });
+        });
+        it('should handle custom orientation', function(done) {
+            cfg.getPreference.andReturn('some-custom-orientation');
+            wrapper(updateProject(cfg, p.locations), done, function() {
+                expect(plist.build.mostRecentCall.args[0].UISupportedInterfaceOrientations).toBeUndefined();
+                expect(plist.build.mostRecentCall.args[0].UIInterfaceOrientation).toBeUndefined();
+            });
+        });
+        ///// App Transport Security Tests /////////////////////////////
+        it('<access> - should handle wildcard', function(done) {
+            wrapper(updateProject(cfg, p.locations), done, function() {
+                var ats = plist.build.mostRecentCall.args[0].NSAppTransportSecurity;
+                expect(ats.NSAllowsArbitraryLoads).toEqual(true);
+            });
+        });
+        it('<access> - https, subdomain wildcard', function(done) {
+            wrapper(updateProject(cfg, p.locations), done, function() {
+                var ats = plist.build.mostRecentCall.args[0].NSAppTransportSecurity;
+                var exceptionDomains = ats.NSExceptionDomains;
+                var d;
+
+                expect(exceptionDomains).toBeTruthy();
+
+                d = exceptionDomains['server01.com'];
+                expect(d).toBeTruthy();
+                expect(d.NSIncludesSubdomains).toEqual(true);
+                expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(null);
+                expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
+                expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
+
+                d = exceptionDomains['server02.com'];
+                expect(d).toBeTruthy();
+                expect(d.NSIncludesSubdomains).toEqual(true);
+                expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(null);
+                expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
+                expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
+
+                d = exceptionDomains['server03.com'];
+                expect(d).toBeTruthy();
+                expect(d.NSIncludesSubdomains).toEqual(true);
+                expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(null);
+                expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
+                expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
+
+                d = exceptionDomains['server04.com'];
+                expect(d).toBeTruthy();
+                expect(d.NSIncludesSubdomains).toEqual(true);
+                expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(null);
+                expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
+                expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
+            });
+        });
+        it('<access> - http, no wildcard', function(done) {
+            wrapper(updateProject(cfg, p.locations), done, function() {
+                var ats = plist.build.mostRecentCall.args[0].NSAppTransportSecurity;
+                var exceptionDomains = ats.NSExceptionDomains;
+                var d;
+
+                expect(exceptionDomains).toBeTruthy();
+
+                d = exceptionDomains['server05.com'];
+                expect(d).toBeTruthy();
+                expect(d.NSIncludesSubdomains).toEqual(null);
+                expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
+                expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
+                expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
+
+                d = exceptionDomains['server06.com'];
+                expect(d).toBeTruthy();
+                expect(d.NSIncludesSubdomains).toEqual(null);
+                expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
+                expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
+                expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
+
+                d = exceptionDomains['server07.com'];
+                expect(d).toBeTruthy();
+                expect(d.NSIncludesSubdomains).toEqual(null);
+                expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
+                expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
+                expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
+
+                d = exceptionDomains['server08.com'];
+                expect(d).toBeTruthy();
+                expect(d.NSIncludesSubdomains).toEqual(null);
+                expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
+                expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
+                expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
+            });
+        });
+        it('<access> - https, no wildcard', function(done) {
+            wrapper(updateProject(cfg, p.locations), done, function() {
+                var ats = plist.build.mostRecentCall.args[0].NSAppTransportSecurity;
+                var exceptionDomains = ats.NSExceptionDomains;
+                var d;
+
+                expect(exceptionDomains).toBeTruthy();
+
+                d = exceptionDomains['server09.com'];
+                expect(d).toBeTruthy();
+                expect(d.NSIncludesSubdomains).toEqual(null);
+                expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(null);
+                expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
+                expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
+
+                d = exceptionDomains['server10.com'];
+                expect(d).toBeTruthy();
+                expect(d.NSIncludesSubdomains).toEqual(null);
+                expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(null);
+                expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
+                expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
+
+                d = exceptionDomains['server11.com'];
+                expect(d).toBeTruthy();
+                expect(d.NSIncludesSubdomains).toEqual(null);
+                expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(null);
+                expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
+                expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
+
+                d = exceptionDomains['server12.com'];
+                expect(d).toBeTruthy();
+                expect(d.NSIncludesSubdomains).toEqual(null);
+                expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(null);
+                expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
+                expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
+            });
+        });
+        //////////////////////////////////////////////////
+        it('<access>, <allow-navigation> - http and https, no clobber', function(done) {
+            wrapper(updateProject(cfg2, p.locations), done, function() {
+                var ats = plist.build.mostRecentCall.args[0].NSAppTransportSecurity;
+                var exceptionDomains = ats.NSExceptionDomains;
+                var d;
+
+                expect(exceptionDomains).toBeTruthy();
+
+                d = exceptionDomains['apache.org'];
+                expect(d).toBeTruthy();
+                expect(d.NSIncludesSubdomains).toEqual(true);
+                expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
+                expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
+                expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
+            });
+        });
+        //////////////////////////////////////////////////
+        it('<allow-navigation> - wildcard scheme, wildcard subdomain', function(done) {
+            wrapper(updateProject(cfg, p.locations), done, function() {
+                var ats = plist.build.mostRecentCall.args[0].NSAppTransportSecurity;
+                var exceptionDomains = ats.NSExceptionDomains;
+                var d;
+
+                expect(exceptionDomains).toBeTruthy();
+
+                d = exceptionDomains['server33.com'];
+                expect(d).toBeTruthy();
+                expect(d.NSIncludesSubdomains).toEqual(true);
+                expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
+                expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
+                expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
+
+                d = exceptionDomains['server34.com'];
+                expect(d).toBeTruthy();
+                expect(d.NSIncludesSubdomains).toEqual(true);
+                expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
+                expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
+                expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
+
+                d = exceptionDomains['server35.com'];
+                expect(d).toBeTruthy();
+                expect(d.NSIncludesSubdomains).toEqual(true);
+                expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
+                expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
+                expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
+
+                d = exceptionDomains['server36.com'];
+                expect(d).toBeTruthy();
+                expect(d.NSIncludesSubdomains).toEqual(true);
+                expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
+                expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
+                expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
+            });
+        });
+        it('<allow-navigation> - wildcard scheme, no subdomain', function(done) {
+            wrapper(updateProject(cfg, p.locations), done, function() {
+                var ats = plist.build.mostRecentCall.args[0].NSAppTransportSecurity;
+                var exceptionDomains = ats.NSExceptionDomains;
+                var d;
+
+                expect(exceptionDomains).toBeTruthy();
+
+                d = exceptionDomains['server37.com'];
+                expect(d).toBeTruthy();
+                expect(d.NSIncludesSubdomains).toEqual(null);
+                expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
+                expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
+                expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
+
+                d = exceptionDomains['server38.com'];
+                expect(d).toBeTruthy();
+                expect(d.NSIncludesSubdomains).toEqual(null);
+                expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
+                expect(d.NSExceptionMinimumTLSVersion).toEqual(null);
+                expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
+
+                d = exceptionDomains['server39.com'];
+                expect(d).toBeTruthy();
+                expect(d.NSIncludesSubdomains).toEqual(null);
+                expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
+                expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
+                expect(d.NSExceptionRequiresForwardSecrecy).toEqual(null);
+
+                d = exceptionDomains['server40.com'];
+                expect(d).toBeTruthy();
+                expect(d.NSIncludesSubdomains).toEqual(null);
+                expect(d.NSExceptionAllowsInsecureHTTPLoads).toEqual(true);
+                expect(d.NSExceptionMinimumTLSVersion).toEqual('TLSv1.1');
+                expect(d.NSExceptionRequiresForwardSecrecy).toEqual(false);
+            });
+        });
+        it('<allow-navigation> - should ignore wildcards like data:*, https:*, https://*', function(done) {
+            wrapper(updateProject(cfg, p.locations), done, function() {
+                var ats = plist.build.mostRecentCall.args[0].NSAppTransportSecurity;
+                var exceptionDomains = ats.NSExceptionDomains;
+                expect(exceptionDomains['']).toBeUndefined();
+                expect(exceptionDomains['null']).toBeUndefined();
+                expect(exceptionDomains['undefined']).toBeUndefined();
+            });
+        });
+    });
+
+    describe('updateWww method', function() {
+        var rm, cp;
+        var updateWww = prepare.__get__('updateWww');
+
+        beforeEach(function () {
+            rm = spyOn(shell, 'rm');
+            cp = spyOn(shell, 'cp');
+        });
+
+        var project = {
+            root: iosProject,
+            locations: { www: path.join(iosProject, 'www') }
+        };
+
+        it('should rm project-level www and cp in platform agnostic www', function() {
+            updateWww(project, p.locations);
+            expect(rm).toHaveBeenCalled();
+            expect(cp).toHaveBeenCalled();
+        });
+        it('should do nothing if merges directory does not exist', function() {
+            var merges_path = path.join(project.root, 'merges/ios');
+            updateWww(project, p.locations);
+            expect(cp).not.toHaveBeenCalledWith('-rf', merges_path, p.locations.www);
+        });
+        it('should copy merges path into www', function() {
+            var merges_path = path.join(project.root, 'merges/ios');
+            shell.mkdir('-p', merges_path);
+            updateWww(project, p.locations);
+            expect(cp).toHaveBeenCalledWith('-rf', path.join(merges_path, '*'), p.locations.www);
+        });
+    });
+});

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/000a61e6/tests/spec/unit/projectFile.spec.js
----------------------------------------------------------------------
diff --git a/tests/spec/unit/projectFile.spec.js b/tests/spec/unit/projectFile.spec.js
new file mode 100644
index 0000000..aca8fd9
--- /dev/null
+++ b/tests/spec/unit/projectFile.spec.js
@@ -0,0 +1,83 @@
+/**
+    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 os = require('os');
+var path = require('path');
+var shell = require('shelljs');
+var projectFile = require('../../../bin/templates/scripts/cordova/lib/projectFile');
+
+var iosProject = path.join(os.tmpdir(), 'plugman/projectFile');
+var iosProjectFixture = path.join(__dirname, 'fixtures/ios-config-xml/*');
+
+var locations = {
+    root: iosProject,
+    pbxproj: path.join(iosProject, 'SampleApp.xcodeproj/project.pbxproj')
+};
+
+describe('projectFile', function() {
+    beforeEach(function() {
+        shell.cp('-rf', iosProjectFixture, iosProject);
+    });
+
+    afterEach(function() {
+        shell.rm('-rf', iosProject);
+    });
+
+    describe('parse method', function () {
+        it('should throw if project is not an xcode project', function() {
+            shell.rm('-rf', path.join(iosProject, 'SampleApp', 'SampleApp.xcodeproj'));
+            expect(function() { projectFile.parse(); }).toThrow();
+        });
+        it('should throw if project does not contain an appropriate config.xml file', function() {
+            shell.rm(path.join(iosProject, 'SampleApp', 'config.xml'));
+            expect(function() { projectFile.parse(locations); })
+                .toThrow('could not find -Info.plist file, or config.xml file.');
+        });
+        it('should throw if project does not contain an appropriate -Info.plist file', function() {
+            shell.rm(path.join(iosProject, 'SampleApp', 'SampleApp-Info.plist'));
+            expect(function () { projectFile.parse(locations); })
+                .toThrow('could not find -Info.plist file, or config.xml file.');
+        });
+        it('should return right directory when multiple .plist files are present', function() {
+            //Create a folder named A with config.xml and .plist files in it
+            var pathToFolderA = path.join(iosProject, 'A');
+            shell.mkdir(pathToFolderA);
+            shell.cp('-rf', path.join(iosProject, 'SampleApp/*'), pathToFolderA);
+
+            var parsedProjectFile = projectFile.parse(locations);
+            var pluginsDir = parsedProjectFile.plugins_dir,
+                resourcesDir = parsedProjectFile.resources_dir,
+                xcodePath = parsedProjectFile.xcode_path;
+
+            var pluginsDirParent = path.dirname(pluginsDir),
+                resourcesDirParent = path.dirname(resourcesDir),
+                sampleAppDir = path.join(iosProject, 'SampleApp');
+
+            expect(pluginsDirParent).toEqual(sampleAppDir);
+            expect(resourcesDirParent).toEqual(sampleAppDir);
+            expect(xcodePath).toEqual(sampleAppDir);
+        });
+    });
+
+    describe('other methods', function () {
+        it('getPackageName method should return the CFBundleIdentifier from the project\'s Info.plist file', function() {
+            expect(projectFile.parse(locations).getPackageName()).toEqual('com.example.friendstring');
+        });
+    });
+});


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org


[3/6] ios commit: CB-10769 Copy raw pluginHandler tests from cordova-lib

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/ios-config-xml/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/ios-config-xml/CordovaLib/CordovaLib.xcodeproj/project.pbxproj b/tests/spec/unit/fixtures/ios-config-xml/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..5d0d461
--- /dev/null
+++ b/tests/spec/unit/fixtures/ios-config-xml/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
@@ -0,0 +1,636 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		1F2BECC013F9785B00A93BF6 /* CDVBattery.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F2BECBE13F9785B00A93BF6 /* CDVBattery.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		1F2BECC113F9785B00A93BF6 /* CDVBattery.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F2BECBF13F9785B00A93BF6 /* CDVBattery.m */; };
+		1F3C04CE12BC247D004F9E10 /* CDVContact.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F3C04CC12BC247D004F9E10 /* CDVContact.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		1F3C04CF12BC247D004F9E10 /* CDVContact.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F3C04CD12BC247D004F9E10 /* CDVContact.m */; };
+		1F584B9B1385A28A00ED25E8 /* CDVCapture.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F584B991385A28900ED25E8 /* CDVCapture.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		1F584B9C1385A28A00ED25E8 /* CDVCapture.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F584B9A1385A28900ED25E8 /* CDVCapture.m */; };
+		1F92F4A01314023E0046367C /* CDVPluginResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F92F49E1314023E0046367C /* CDVPluginResult.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		1F92F4A11314023E0046367C /* CDVPluginResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F92F49F1314023E0046367C /* CDVPluginResult.m */; };
+		301F2F2A14F3C9CA003FE9FC /* CDV.h in Headers */ = {isa = PBXBuildFile; fileRef = 301F2F2914F3C9CA003FE9FC /* CDV.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		302965BC13A94E9D007046C5 /* CDVDebug.h in Headers */ = {isa = PBXBuildFile; fileRef = 302965BB13A94E9D007046C5 /* CDVDebug.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3034979C1513D56A0090E688 /* CDVLocalStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = 3034979A1513D56A0090E688 /* CDVLocalStorage.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3034979E1513D56A0090E688 /* CDVLocalStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 3034979B1513D56A0090E688 /* CDVLocalStorage.m */; };
+		30392E4E14F4FCAB00B9E0B8 /* CDVAvailability.h in Headers */ = {isa = PBXBuildFile; fileRef = 30392E4D14F4FCAB00B9E0B8 /* CDVAvailability.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3062D120151D0EDB000D9128 /* UIDevice+Extensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 3062D11E151D0EDB000D9128 /* UIDevice+Extensions.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3062D122151D0EDB000D9128 /* UIDevice+Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 3062D11F151D0EDB000D9128 /* UIDevice+Extensions.m */; };
+		307A8F9E1385A2EC00E43782 /* CDVConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 307A8F9C1385A2EC00E43782 /* CDVConnection.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		307A8F9F1385A2EC00E43782 /* CDVConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 307A8F9D1385A2EC00E43782 /* CDVConnection.m */; };
+		30A90B9114588697006178D3 /* JSONKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 30A90B8F14588697006178D3 /* JSONKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		30A90B9314588697006178D3 /* JSONKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 30A90B9014588697006178D3 /* JSONKit.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
+		30B39EBE13D0268B0009682A /* CDVSplashScreen.h in Headers */ = {isa = PBXBuildFile; fileRef = 30B39EBC13D0268B0009682A /* CDVSplashScreen.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		30B39EBF13D0268B0009682A /* CDVSplashScreen.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B39EBD13D0268B0009682A /* CDVSplashScreen.m */; };
+		30C5F1DF15AF9E950052A00D /* CDVDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = 30C5F1DD15AF9E950052A00D /* CDVDevice.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		30C5F1E015AF9E950052A00D /* CDVDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = 30C5F1DE15AF9E950052A00D /* CDVDevice.m */; };
+		30C684801406CB38004C1A8E /* CDVWhitelist.h in Headers */ = {isa = PBXBuildFile; fileRef = 30C6847E1406CB38004C1A8E /* CDVWhitelist.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		30C684821406CB38004C1A8E /* CDVWhitelist.m in Sources */ = {isa = PBXBuildFile; fileRef = 30C6847F1406CB38004C1A8E /* CDVWhitelist.m */; };
+		30C684941407044B004C1A8E /* CDVURLProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 30C684921407044A004C1A8E /* CDVURLProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		30C684961407044B004C1A8E /* CDVURLProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 30C684931407044A004C1A8E /* CDVURLProtocol.m */; };
+		30E33AF213A7E24B00594D64 /* CDVPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 30E33AF013A7E24B00594D64 /* CDVPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		30E33AF313A7E24B00594D64 /* CDVPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 30E33AF113A7E24B00594D64 /* CDVPlugin.m */; };
+		30E563CF13E217EC00C949AA /* NSMutableArray+QueueAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 30E563CD13E217EC00C949AA /* NSMutableArray+QueueAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		30E563D013E217EC00C949AA /* NSMutableArray+QueueAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 30E563CE13E217EC00C949AA /* NSMutableArray+QueueAdditions.m */; };
+		30F5EBAB14CA26E700987760 /* CDVCommandDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 30F5EBA914CA26E700987760 /* CDVCommandDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3E76876D156A90EE00EB6FA3 /* CDVLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E76876B156A90EE00EB6FA3 /* CDVLogger.m */; };
+		3E76876F156A90EE00EB6FA3 /* CDVLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 3E76876C156A90EE00EB6FA3 /* CDVLogger.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8852C43A14B65FD800F0E735 /* CDVViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 8852C43614B65FD800F0E735 /* CDVViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8852C43C14B65FD800F0E735 /* CDVViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8852C43714B65FD800F0E735 /* CDVViewController.m */; };
+		8852C43F14B65FD800F0E735 /* CDVCordovaView.h in Headers */ = {isa = PBXBuildFile; fileRef = 8852C43814B65FD800F0E735 /* CDVCordovaView.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8852C44114B65FD800F0E735 /* CDVCordovaView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8852C43914B65FD800F0E735 /* CDVCordovaView.m */; };
+		8887FD661090FBE7009987E8 /* CDVCamera.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD261090FBE7009987E8 /* CDVCamera.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8887FD671090FBE7009987E8 /* CDVCamera.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD271090FBE7009987E8 /* CDVCamera.m */; };
+		8887FD681090FBE7009987E8 /* NSDictionary+Extensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD281090FBE7009987E8 /* NSDictionary+Extensions.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8887FD691090FBE7009987E8 /* NSDictionary+Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD291090FBE7009987E8 /* NSDictionary+Extensions.m */; };
+		8887FD6A1090FBE7009987E8 /* CDVContacts.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD2A1090FBE7009987E8 /* CDVContacts.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8887FD6B1090FBE7009987E8 /* CDVContacts.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD2B1090FBE7009987E8 /* CDVContacts.m */; };
+		8887FD6C1090FBE7009987E8 /* CDVDebugConsole.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD2C1090FBE7009987E8 /* CDVDebugConsole.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8887FD6D1090FBE7009987E8 /* CDVDebugConsole.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD2D1090FBE7009987E8 /* CDVDebugConsole.m */; };
+		8887FD701090FBE7009987E8 /* CDVFile.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD301090FBE7009987E8 /* CDVFile.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8887FD711090FBE7009987E8 /* CDVFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD311090FBE7009987E8 /* CDVFile.m */; };
+		8887FD741090FBE7009987E8 /* CDVInvokedUrlCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD341090FBE7009987E8 /* CDVInvokedUrlCommand.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8887FD751090FBE7009987E8 /* CDVInvokedUrlCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD351090FBE7009987E8 /* CDVInvokedUrlCommand.m */; };
+		8887FD851090FBE7009987E8 /* CDVLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD461090FBE7009987E8 /* CDVLocation.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8887FD861090FBE7009987E8 /* CDVLocation.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD471090FBE7009987E8 /* CDVLocation.m */; };
+		8887FD8D1090FBE7009987E8 /* CDVNotification.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD4E1090FBE7009987E8 /* CDVNotification.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8887FD8E1090FBE7009987E8 /* CDVNotification.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD4F1090FBE7009987E8 /* CDVNotification.m */; };
+		8887FD8F1090FBE7009987E8 /* NSData+Base64.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD501090FBE7009987E8 /* NSData+Base64.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8887FD901090FBE7009987E8 /* NSData+Base64.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD511090FBE7009987E8 /* NSData+Base64.m */; };
+		8887FD9D1090FBE7009987E8 /* CDVReachability.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD5E1090FBE7009987E8 /* CDVReachability.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8887FD9E1090FBE7009987E8 /* CDVReachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD5F1090FBE7009987E8 /* CDVReachability.m */; };
+		8887FD9F1090FBE7009987E8 /* CDVSound.h in Headers */ = {isa = PBXBuildFile; fileRef = 8887FD601090FBE7009987E8 /* CDVSound.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8887FDA01090FBE7009987E8 /* CDVSound.m in Sources */ = {isa = PBXBuildFile; fileRef = 8887FD611090FBE7009987E8 /* CDVSound.m */; };
+		88BA573D109BB46F00FB5E78 /* CDVAccelerometer.h in Headers */ = {isa = PBXBuildFile; fileRef = 88BA573B109BB46F00FB5E78 /* CDVAccelerometer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		88BA573E109BB46F00FB5E78 /* CDVAccelerometer.m in Sources */ = {isa = PBXBuildFile; fileRef = 88BA573C109BB46F00FB5E78 /* CDVAccelerometer.m */; };
+		9D76CF3C1625A4C50008A0F6 /* CDVGlobalization.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D76CF3A1625A4C50008A0F6 /* CDVGlobalization.h */; };
+		9D76CF3D1625A4C50008A0F6 /* CDVGlobalization.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D76CF3B1625A4C50008A0F6 /* CDVGlobalization.m */; };
+		C937A4561337599E002C4C79 /* CDVFileTransfer.h in Headers */ = {isa = PBXBuildFile; fileRef = C937A4541337599E002C4C79 /* CDVFileTransfer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		C937A4571337599E002C4C79 /* CDVFileTransfer.m in Sources */ = {isa = PBXBuildFile; fileRef = C937A4551337599E002C4C79 /* CDVFileTransfer.m */; };
+		EB3B3547161CB44D003DBE7D /* CDVCommandQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = EB3B3545161CB44D003DBE7D /* CDVCommandQueue.h */; };
+		EB3B3548161CB44D003DBE7D /* CDVCommandQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = EB3B3546161CB44D003DBE7D /* CDVCommandQueue.m */; };
+		EB3B357C161F2A45003DBE7D /* CDVCommandDelegateImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = EB3B357A161F2A44003DBE7D /* CDVCommandDelegateImpl.h */; };
+		EB3B357D161F2A45003DBE7D /* CDVCommandDelegateImpl.m in Sources */ = {isa = PBXBuildFile; fileRef = EB3B357B161F2A45003DBE7D /* CDVCommandDelegateImpl.m */; };
+		EB80C2AC15DEA63D004D9E7B /* CDVEcho.h in Headers */ = {isa = PBXBuildFile; fileRef = EB80C2AA15DEA63D004D9E7B /* CDVEcho.h */; };
+		EB80C2AD15DEA63D004D9E7B /* CDVEcho.m in Sources */ = {isa = PBXBuildFile; fileRef = EB80C2AB15DEA63D004D9E7B /* CDVEcho.m */; };
+		EBA3557315ABD38C00F4DE24 /* NSArray+Comparisons.h in Headers */ = {isa = PBXBuildFile; fileRef = EBA3557115ABD38C00F4DE24 /* NSArray+Comparisons.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		EBA3557515ABD38C00F4DE24 /* NSArray+Comparisons.m in Sources */ = {isa = PBXBuildFile; fileRef = EBA3557215ABD38C00F4DE24 /* NSArray+Comparisons.m */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		1F2BECBE13F9785B00A93BF6 /* CDVBattery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVBattery.h; path = Classes/CDVBattery.h; sourceTree = "<group>"; };
+		1F2BECBF13F9785B00A93BF6 /* CDVBattery.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVBattery.m; path = Classes/CDVBattery.m; sourceTree = "<group>"; };
+		1F3C04CC12BC247D004F9E10 /* CDVContact.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVContact.h; path = Classes/CDVContact.h; sourceTree = "<group>"; };
+		1F3C04CD12BC247D004F9E10 /* CDVContact.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVContact.m; path = Classes/CDVContact.m; sourceTree = "<group>"; };
+		1F584B991385A28900ED25E8 /* CDVCapture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVCapture.h; path = Classes/CDVCapture.h; sourceTree = "<group>"; };
+		1F584B9A1385A28900ED25E8 /* CDVCapture.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVCapture.m; path = Classes/CDVCapture.m; sourceTree = "<group>"; };
+		1F92F49E1314023E0046367C /* CDVPluginResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVPluginResult.h; path = Classes/CDVPluginResult.h; sourceTree = "<group>"; };
+		1F92F49F1314023E0046367C /* CDVPluginResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVPluginResult.m; path = Classes/CDVPluginResult.m; sourceTree = "<group>"; };
+		301F2F2914F3C9CA003FE9FC /* CDV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDV.h; path = Classes/CDV.h; sourceTree = "<group>"; };
+		302965BB13A94E9D007046C5 /* CDVDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVDebug.h; path = Classes/CDVDebug.h; sourceTree = "<group>"; };
+		30325A0B136B343700982B63 /* VERSION */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = VERSION; sourceTree = "<group>"; };
+		3034979A1513D56A0090E688 /* CDVLocalStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVLocalStorage.h; path = Classes/CDVLocalStorage.h; sourceTree = "<group>"; };
+		3034979B1513D56A0090E688 /* CDVLocalStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVLocalStorage.m; path = Classes/CDVLocalStorage.m; sourceTree = "<group>"; };
+		30392E4D14F4FCAB00B9E0B8 /* CDVAvailability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVAvailability.h; path = Classes/CDVAvailability.h; sourceTree = "<group>"; };
+		3062D11E151D0EDB000D9128 /* UIDevice+Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIDevice+Extensions.h"; path = "Classes/UIDevice+Extensions.h"; sourceTree = "<group>"; };
+		3062D11F151D0EDB000D9128 /* UIDevice+Extensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIDevice+Extensions.m"; path = "Classes/UIDevice+Extensions.m"; sourceTree = "<group>"; };
+		307A8F9C1385A2EC00E43782 /* CDVConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVConnection.h; path = Classes/CDVConnection.h; sourceTree = "<group>"; };
+		307A8F9D1385A2EC00E43782 /* CDVConnection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVConnection.m; path = Classes/CDVConnection.m; sourceTree = "<group>"; };
+		30A90B8F14588697006178D3 /* JSONKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSONKit.h; sourceTree = "<group>"; };
+		30A90B9014588697006178D3 /* JSONKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSONKit.m; sourceTree = "<group>"; };
+		30B39EBC13D0268B0009682A /* CDVSplashScreen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVSplashScreen.h; path = Classes/CDVSplashScreen.h; sourceTree = "<group>"; };
+		30B39EBD13D0268B0009682A /* CDVSplashScreen.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVSplashScreen.m; path = Classes/CDVSplashScreen.m; sourceTree = "<group>"; };
+		30C5F1DD15AF9E950052A00D /* CDVDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVDevice.h; path = Classes/CDVDevice.h; sourceTree = "<group>"; };
+		30C5F1DE15AF9E950052A00D /* CDVDevice.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVDevice.m; path = Classes/CDVDevice.m; sourceTree = "<group>"; };
+		30C6847E1406CB38004C1A8E /* CDVWhitelist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVWhitelist.h; path = Classes/CDVWhitelist.h; sourceTree = "<group>"; };
+		30C6847F1406CB38004C1A8E /* CDVWhitelist.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVWhitelist.m; path = Classes/CDVWhitelist.m; sourceTree = "<group>"; };
+		30C684921407044A004C1A8E /* CDVURLProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVURLProtocol.h; path = Classes/CDVURLProtocol.h; sourceTree = "<group>"; };
+		30C684931407044A004C1A8E /* CDVURLProtocol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVURLProtocol.m; path = Classes/CDVURLProtocol.m; sourceTree = "<group>"; };
+		30E33AF013A7E24B00594D64 /* CDVPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVPlugin.h; path = Classes/CDVPlugin.h; sourceTree = "<group>"; };
+		30E33AF113A7E24B00594D64 /* CDVPlugin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVPlugin.m; path = Classes/CDVPlugin.m; sourceTree = "<group>"; };
+		30E563CD13E217EC00C949AA /* NSMutableArray+QueueAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSMutableArray+QueueAdditions.h"; path = "Classes/NSMutableArray+QueueAdditions.h"; sourceTree = "<group>"; };
+		30E563CE13E217EC00C949AA /* NSMutableArray+QueueAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSMutableArray+QueueAdditions.m"; path = "Classes/NSMutableArray+QueueAdditions.m"; sourceTree = "<group>"; };
+		30F5EBA914CA26E700987760 /* CDVCommandDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVCommandDelegate.h; path = Classes/CDVCommandDelegate.h; sourceTree = "<group>"; };
+		3E76876B156A90EE00EB6FA3 /* CDVLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVLogger.m; path = Classes/CDVLogger.m; sourceTree = "<group>"; };
+		3E76876C156A90EE00EB6FA3 /* CDVLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVLogger.h; path = Classes/CDVLogger.h; sourceTree = "<group>"; };
+		686357AA141002F100DF4CF2 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+		686357AC141002F100DF4CF2 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+		686357AE141002F100DF4CF2 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+		686357CC14100AAD00DF4CF2 /* AddressBookUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBookUI.framework; path = System/Library/Frameworks/AddressBookUI.framework; sourceTree = SDKROOT; };
+		686357CE14100ADA00DF4CF2 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
+		686357CF14100ADB00DF4CF2 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
+		686357D014100ADE00DF4CF2 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; };
+		686357D214100AE700DF4CF2 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };
+		686357D414100AF200DF4CF2 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
+		686357DC14100B1600DF4CF2 /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; };
+		68A32D7114102E1C006B237C /* libCordova.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libCordova.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		68A32D7414103017006B237C /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; };
+		8852C43614B65FD800F0E735 /* CDVViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVViewController.h; path = Classes/CDVViewController.h; sourceTree = "<group>"; };
+		8852C43714B65FD800F0E735 /* CDVViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVViewController.m; path = Classes/CDVViewController.m; sourceTree = "<group>"; };
+		8852C43814B65FD800F0E735 /* CDVCordovaView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVCordovaView.h; path = Classes/CDVCordovaView.h; sourceTree = "<group>"; };
+		8852C43914B65FD800F0E735 /* CDVCordovaView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVCordovaView.m; path = Classes/CDVCordovaView.m; sourceTree = "<group>"; };
+		8887FD261090FBE7009987E8 /* CDVCamera.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVCamera.h; path = Classes/CDVCamera.h; sourceTree = "<group>"; };
+		8887FD271090FBE7009987E8 /* CDVCamera.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVCamera.m; path = Classes/CDVCamera.m; sourceTree = "<group>"; };
+		8887FD281090FBE7009987E8 /* NSDictionary+Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSDictionary+Extensions.h"; path = "Classes/NSDictionary+Extensions.h"; sourceTree = "<group>"; };
+		8887FD291090FBE7009987E8 /* NSDictionary+Extensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSDictionary+Extensions.m"; path = "Classes/NSDictionary+Extensions.m"; sourceTree = "<group>"; };
+		8887FD2A1090FBE7009987E8 /* CDVContacts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVContacts.h; path = Classes/CDVContacts.h; sourceTree = "<group>"; };
+		8887FD2B1090FBE7009987E8 /* CDVContacts.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVContacts.m; path = Classes/CDVContacts.m; sourceTree = "<group>"; };
+		8887FD2C1090FBE7009987E8 /* CDVDebugConsole.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVDebugConsole.h; path = Classes/CDVDebugConsole.h; sourceTree = "<group>"; };
+		8887FD2D1090FBE7009987E8 /* CDVDebugConsole.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVDebugConsole.m; path = Classes/CDVDebugConsole.m; sourceTree = "<group>"; };
+		8887FD301090FBE7009987E8 /* CDVFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVFile.h; path = Classes/CDVFile.h; sourceTree = "<group>"; };
+		8887FD311090FBE7009987E8 /* CDVFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVFile.m; path = Classes/CDVFile.m; sourceTree = "<group>"; };
+		8887FD341090FBE7009987E8 /* CDVInvokedUrlCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVInvokedUrlCommand.h; path = Classes/CDVInvokedUrlCommand.h; sourceTree = "<group>"; };
+		8887FD351090FBE7009987E8 /* CDVInvokedUrlCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVInvokedUrlCommand.m; path = Classes/CDVInvokedUrlCommand.m; sourceTree = "<group>"; };
+		8887FD461090FBE7009987E8 /* CDVLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVLocation.h; path = Classes/CDVLocation.h; sourceTree = "<group>"; };
+		8887FD471090FBE7009987E8 /* CDVLocation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVLocation.m; path = Classes/CDVLocation.m; sourceTree = "<group>"; };
+		8887FD4E1090FBE7009987E8 /* CDVNotification.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVNotification.h; path = Classes/CDVNotification.h; sourceTree = "<group>"; };
+		8887FD4F1090FBE7009987E8 /* CDVNotification.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVNotification.m; path = Classes/CDVNotification.m; sourceTree = "<group>"; };
+		8887FD501090FBE7009987E8 /* NSData+Base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSData+Base64.h"; path = "Classes/NSData+Base64.h"; sourceTree = "<group>"; };
+		8887FD511090FBE7009987E8 /* NSData+Base64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSData+Base64.m"; path = "Classes/NSData+Base64.m"; sourceTree = "<group>"; };
+		8887FD5E1090FBE7009987E8 /* CDVReachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVReachability.h; path = Classes/CDVReachability.h; sourceTree = "<group>"; };
+		8887FD5F1090FBE7009987E8 /* CDVReachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVReachability.m; path = Classes/CDVReachability.m; sourceTree = "<group>"; };
+		8887FD601090FBE7009987E8 /* CDVSound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVSound.h; path = Classes/CDVSound.h; sourceTree = "<group>"; };
+		8887FD611090FBE7009987E8 /* CDVSound.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVSound.m; path = Classes/CDVSound.m; sourceTree = "<group>"; };
+		88BA573B109BB46F00FB5E78 /* CDVAccelerometer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVAccelerometer.h; path = Classes/CDVAccelerometer.h; sourceTree = "<group>"; };
+		88BA573C109BB46F00FB5E78 /* CDVAccelerometer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVAccelerometer.m; path = Classes/CDVAccelerometer.m; sourceTree = "<group>"; };
+		9D76CF3A1625A4C50008A0F6 /* CDVGlobalization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVGlobalization.h; path = Classes/CDVGlobalization.h; sourceTree = "<group>"; };
+		9D76CF3B1625A4C50008A0F6 /* CDVGlobalization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVGlobalization.m; path = Classes/CDVGlobalization.m; sourceTree = "<group>"; };
+		AA747D9E0F9514B9006C5449 /* CordovaLib_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CordovaLib_Prefix.pch; sourceTree = SOURCE_ROOT; };
+		C937A4541337599E002C4C79 /* CDVFileTransfer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVFileTransfer.h; path = Classes/CDVFileTransfer.h; sourceTree = "<group>"; };
+		C937A4551337599E002C4C79 /* CDVFileTransfer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVFileTransfer.m; path = Classes/CDVFileTransfer.m; sourceTree = "<group>"; };
+		EB3B3545161CB44D003DBE7D /* CDVCommandQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVCommandQueue.h; path = Classes/CDVCommandQueue.h; sourceTree = "<group>"; };
+		EB3B3546161CB44D003DBE7D /* CDVCommandQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVCommandQueue.m; path = Classes/CDVCommandQueue.m; sourceTree = "<group>"; };
+		EB3B357A161F2A44003DBE7D /* CDVCommandDelegateImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVCommandDelegateImpl.h; path = Classes/CDVCommandDelegateImpl.h; sourceTree = "<group>"; };
+		EB3B357B161F2A45003DBE7D /* CDVCommandDelegateImpl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVCommandDelegateImpl.m; path = Classes/CDVCommandDelegateImpl.m; sourceTree = "<group>"; };
+		EB80C2AA15DEA63D004D9E7B /* CDVEcho.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVEcho.h; path = Classes/CDVEcho.h; sourceTree = "<group>"; };
+		EB80C2AB15DEA63D004D9E7B /* CDVEcho.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVEcho.m; path = Classes/CDVEcho.m; sourceTree = "<group>"; };
+		EBA3557115ABD38C00F4DE24 /* NSArray+Comparisons.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSArray+Comparisons.h"; path = "Classes/NSArray+Comparisons.h"; sourceTree = "<group>"; };
+		EBA3557215ABD38C00F4DE24 /* NSArray+Comparisons.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSArray+Comparisons.m"; path = "Classes/NSArray+Comparisons.m"; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		D2AAC07C0554694100DB518D /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		034768DFFF38A50411DB9C8B /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				68A32D7114102E1C006B237C /* libCordova.a */,
+			);
+			name = Products;
+			sourceTree = CORDOVALIB;
+		};
+		0867D691FE84028FC02AAC07 /* CordovaLib */ = {
+			isa = PBXGroup;
+			children = (
+				8887FD101090FB43009987E8 /* Classes */,
+				32C88DFF0371C24200C91783 /* Other Sources */,
+				0867D69AFE84028FC02AAC07 /* Frameworks */,
+				034768DFFF38A50411DB9C8B /* Products */,
+				30325A0B136B343700982B63 /* VERSION */,
+			);
+			name = CordovaLib;
+			sourceTree = "<group>";
+		};
+		0867D69AFE84028FC02AAC07 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				68A32D7414103017006B237C /* AddressBook.framework */,
+				686357DC14100B1600DF4CF2 /* CoreMedia.framework */,
+				686357CE14100ADA00DF4CF2 /* AudioToolbox.framework */,
+				686357CF14100ADB00DF4CF2 /* AVFoundation.framework */,
+				686357D014100ADE00DF4CF2 /* CoreLocation.framework */,
+				686357D214100AE700DF4CF2 /* MobileCoreServices.framework */,
+				686357D414100AF200DF4CF2 /* SystemConfiguration.framework */,
+				686357CC14100AAD00DF4CF2 /* AddressBookUI.framework */,
+				686357AA141002F100DF4CF2 /* UIKit.framework */,
+				686357AC141002F100DF4CF2 /* Foundation.framework */,
+				686357AE141002F100DF4CF2 /* CoreGraphics.framework */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		3054098714B77FF3009841CA /* Cleaver */ = {
+			isa = PBXGroup;
+			children = (
+				8852C43614B65FD800F0E735 /* CDVViewController.h */,
+				8852C43714B65FD800F0E735 /* CDVViewController.m */,
+				8852C43814B65FD800F0E735 /* CDVCordovaView.h */,
+				8852C43914B65FD800F0E735 /* CDVCordovaView.m */,
+				EB3B3545161CB44D003DBE7D /* CDVCommandQueue.h */,
+				EB3B3546161CB44D003DBE7D /* CDVCommandQueue.m */,
+			);
+			name = Cleaver;
+			sourceTree = "<group>";
+		};
+		32C88DFF0371C24200C91783 /* Other Sources */ = {
+			isa = PBXGroup;
+			children = (
+				AA747D9E0F9514B9006C5449 /* CordovaLib_Prefix.pch */,
+			);
+			name = "Other Sources";
+			sourceTree = "<group>";
+		};
+		888700D710922F56009987E8 /* Commands */ = {
+			isa = PBXGroup;
+			children = (
+				30C5F1DD15AF9E950052A00D /* CDVDevice.h */,
+				30C5F1DE15AF9E950052A00D /* CDVDevice.m */,
+				301F2F2914F3C9CA003FE9FC /* CDV.h */,
+				3034979A1513D56A0090E688 /* CDVLocalStorage.h */,
+				3034979B1513D56A0090E688 /* CDVLocalStorage.m */,
+				30392E4D14F4FCAB00B9E0B8 /* CDVAvailability.h */,
+				30F5EBA914CA26E700987760 /* CDVCommandDelegate.h */,
+				EB3B357A161F2A44003DBE7D /* CDVCommandDelegateImpl.h */,
+				EB3B357B161F2A45003DBE7D /* CDVCommandDelegateImpl.m */,
+				30C684921407044A004C1A8E /* CDVURLProtocol.h */,
+				30C684931407044A004C1A8E /* CDVURLProtocol.m */,
+				30C6847E1406CB38004C1A8E /* CDVWhitelist.h */,
+				30C6847F1406CB38004C1A8E /* CDVWhitelist.m */,
+				1F2BECBE13F9785B00A93BF6 /* CDVBattery.h */,
+				1F2BECBF13F9785B00A93BF6 /* CDVBattery.m */,
+				30B39EBC13D0268B0009682A /* CDVSplashScreen.h */,
+				30B39EBD13D0268B0009682A /* CDVSplashScreen.m */,
+				30E33AF013A7E24B00594D64 /* CDVPlugin.h */,
+				30E33AF113A7E24B00594D64 /* CDVPlugin.m */,
+				307A8F9C1385A2EC00E43782 /* CDVConnection.h */,
+				307A8F9D1385A2EC00E43782 /* CDVConnection.m */,
+				1F92F49E1314023E0046367C /* CDVPluginResult.h */,
+				1F92F49F1314023E0046367C /* CDVPluginResult.m */,
+				88BA573B109BB46F00FB5E78 /* CDVAccelerometer.h */,
+				88BA573C109BB46F00FB5E78 /* CDVAccelerometer.m */,
+				8887FD261090FBE7009987E8 /* CDVCamera.h */,
+				8887FD271090FBE7009987E8 /* CDVCamera.m */,
+				1F584B991385A28900ED25E8 /* CDVCapture.h */,
+				1F584B9A1385A28900ED25E8 /* CDVCapture.m */,
+				1F3C04CC12BC247D004F9E10 /* CDVContact.h */,
+				1F3C04CD12BC247D004F9E10 /* CDVContact.m */,
+				8887FD2A1090FBE7009987E8 /* CDVContacts.h */,
+				8887FD2B1090FBE7009987E8 /* CDVContacts.m */,
+				8887FD2C1090FBE7009987E8 /* CDVDebugConsole.h */,
+				8887FD2D1090FBE7009987E8 /* CDVDebugConsole.m */,
+				EB80C2AA15DEA63D004D9E7B /* CDVEcho.h */,
+				EB80C2AB15DEA63D004D9E7B /* CDVEcho.m */,
+				8887FD301090FBE7009987E8 /* CDVFile.h */,
+				8887FD311090FBE7009987E8 /* CDVFile.m */,
+				8887FD341090FBE7009987E8 /* CDVInvokedUrlCommand.h */,
+				8887FD351090FBE7009987E8 /* CDVInvokedUrlCommand.m */,
+				C937A4541337599E002C4C79 /* CDVFileTransfer.h */,
+				C937A4551337599E002C4C79 /* CDVFileTransfer.m */,
+				8887FD461090FBE7009987E8 /* CDVLocation.h */,
+				8887FD471090FBE7009987E8 /* CDVLocation.m */,
+				8887FD4E1090FBE7009987E8 /* CDVNotification.h */,
+				8887FD4F1090FBE7009987E8 /* CDVNotification.m */,
+				8887FD5E1090FBE7009987E8 /* CDVReachability.h */,
+				8887FD5F1090FBE7009987E8 /* CDVReachability.m */,
+				8887FD601090FBE7009987E8 /* CDVSound.h */,
+				8887FD611090FBE7009987E8 /* CDVSound.m */,
+				3E76876B156A90EE00EB6FA3 /* CDVLogger.m */,
+				3E76876C156A90EE00EB6FA3 /* CDVLogger.h */,
+				9D76CF3A1625A4C50008A0F6 /* CDVGlobalization.h */,
+				9D76CF3B1625A4C50008A0F6 /* CDVGlobalization.m */,
+			);
+			name = Commands;
+			sourceTree = "<group>";
+		};
+		888700D910923009009987E8 /* Util */ = {
+			isa = PBXGroup;
+			children = (
+				3062D11E151D0EDB000D9128 /* UIDevice+Extensions.h */,
+				3062D11F151D0EDB000D9128 /* UIDevice+Extensions.m */,
+				EBA3557115ABD38C00F4DE24 /* NSArray+Comparisons.h */,
+				EBA3557215ABD38C00F4DE24 /* NSArray+Comparisons.m */,
+				8887FD281090FBE7009987E8 /* NSDictionary+Extensions.h */,
+				8887FD291090FBE7009987E8 /* NSDictionary+Extensions.m */,
+				302965BB13A94E9D007046C5 /* CDVDebug.h */,
+				30E563CD13E217EC00C949AA /* NSMutableArray+QueueAdditions.h */,
+				30E563CE13E217EC00C949AA /* NSMutableArray+QueueAdditions.m */,
+				8887FD501090FBE7009987E8 /* NSData+Base64.h */,
+				8887FD511090FBE7009987E8 /* NSData+Base64.m */,
+			);
+			name = Util;
+			sourceTree = "<group>";
+		};
+		8887FD101090FB43009987E8 /* Classes */ = {
+			isa = PBXGroup;
+			children = (
+				3054098714B77FF3009841CA /* Cleaver */,
+				888700D710922F56009987E8 /* Commands */,
+				8887FD361090FBE7009987E8 /* JSON */,
+				888700D910923009009987E8 /* Util */,
+			);
+			name = Classes;
+			sourceTree = "<group>";
+		};
+		8887FD361090FBE7009987E8 /* JSON */ = {
+			isa = PBXGroup;
+			children = (
+				30A90B8F14588697006178D3 /* JSONKit.h */,
+				30A90B9014588697006178D3 /* JSONKit.m */,
+			);
+			name = JSON;
+			path = Classes/JSON;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+		D2AAC07A0554694100DB518D /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				8887FD661090FBE7009987E8 /* CDVCamera.h in Headers */,
+				8887FD681090FBE7009987E8 /* NSDictionary+Extensions.h in Headers */,
+				8887FD6A1090FBE7009987E8 /* CDVContacts.h in Headers */,
+				8887FD6C1090FBE7009987E8 /* CDVDebugConsole.h in Headers */,
+				8887FD701090FBE7009987E8 /* CDVFile.h in Headers */,
+				8887FD741090FBE7009987E8 /* CDVInvokedUrlCommand.h in Headers */,
+				8887FD851090FBE7009987E8 /* CDVLocation.h in Headers */,
+				8887FD8D1090FBE7009987E8 /* CDVNotification.h in Headers */,
+				8887FD8F1090FBE7009987E8 /* NSData+Base64.h in Headers */,
+				8887FD9D1090FBE7009987E8 /* CDVReachability.h in Headers */,
+				8887FD9F1090FBE7009987E8 /* CDVSound.h in Headers */,
+				88BA573D109BB46F00FB5E78 /* CDVAccelerometer.h in Headers */,
+				1F3C04CE12BC247D004F9E10 /* CDVContact.h in Headers */,
+				1F92F4A01314023E0046367C /* CDVPluginResult.h in Headers */,
+				C937A4561337599E002C4C79 /* CDVFileTransfer.h in Headers */,
+				307A8F9E1385A2EC00E43782 /* CDVConnection.h in Headers */,
+				1F584B9B1385A28A00ED25E8 /* CDVCapture.h in Headers */,
+				30E33AF213A7E24B00594D64 /* CDVPlugin.h in Headers */,
+				302965BC13A94E9D007046C5 /* CDVDebug.h in Headers */,
+				30B39EBE13D0268B0009682A /* CDVSplashScreen.h in Headers */,
+				30E563CF13E217EC00C949AA /* NSMutableArray+QueueAdditions.h in Headers */,
+				1F2BECC013F9785B00A93BF6 /* CDVBattery.h in Headers */,
+				30C684801406CB38004C1A8E /* CDVWhitelist.h in Headers */,
+				30C684941407044B004C1A8E /* CDVURLProtocol.h in Headers */,
+				30A90B9114588697006178D3 /* JSONKit.h in Headers */,
+				8852C43A14B65FD800F0E735 /* CDVViewController.h in Headers */,
+				8852C43F14B65FD800F0E735 /* CDVCordovaView.h in Headers */,
+				30F5EBAB14CA26E700987760 /* CDVCommandDelegate.h in Headers */,
+				301F2F2A14F3C9CA003FE9FC /* CDV.h in Headers */,
+				30392E4E14F4FCAB00B9E0B8 /* CDVAvailability.h in Headers */,
+				3034979C1513D56A0090E688 /* CDVLocalStorage.h in Headers */,
+				3062D120151D0EDB000D9128 /* UIDevice+Extensions.h in Headers */,
+				3E76876F156A90EE00EB6FA3 /* CDVLogger.h in Headers */,
+				EBA3557315ABD38C00F4DE24 /* NSArray+Comparisons.h in Headers */,
+				30C5F1DF15AF9E950052A00D /* CDVDevice.h in Headers */,
+				EB80C2AC15DEA63D004D9E7B /* CDVEcho.h in Headers */,
+				EB3B3547161CB44D003DBE7D /* CDVCommandQueue.h in Headers */,
+				EB3B357C161F2A45003DBE7D /* CDVCommandDelegateImpl.h in Headers */,
+				9D76CF3C1625A4C50008A0F6 /* CDVGlobalization.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+		D2AAC07D0554694100DB518D /* CordovaLib */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 1DEB921E08733DC00010E9CD /* Build configuration list for PBXNativeTarget "CordovaLib" */;
+			buildPhases = (
+				D2AAC07A0554694100DB518D /* Headers */,
+				D2AAC07B0554694100DB518D /* Sources */,
+				D2AAC07C0554694100DB518D /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = CordovaLib;
+			productName = CordovaLib;
+			productReference = 68A32D7114102E1C006B237C /* libCordova.a */;
+			productType = "com.apple.product-type.library.static";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		0867D690FE84028FC02AAC07 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 0430;
+			};
+			buildConfigurationList = 1DEB922208733DC00010E9CD /* Build configuration list for PBXProject "CordovaLib" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 1;
+			knownRegions = (
+				English,
+				Japanese,
+				French,
+				German,
+				en,
+			);
+			mainGroup = 0867D691FE84028FC02AAC07 /* CordovaLib */;
+			productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				D2AAC07D0554694100DB518D /* CordovaLib */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+		D2AAC07B0554694100DB518D /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				8887FD671090FBE7009987E8 /* CDVCamera.m in Sources */,
+				8887FD691090FBE7009987E8 /* NSDictionary+Extensions.m in Sources */,
+				8887FD6B1090FBE7009987E8 /* CDVContacts.m in Sources */,
+				8887FD6D1090FBE7009987E8 /* CDVDebugConsole.m in Sources */,
+				8887FD711090FBE7009987E8 /* CDVFile.m in Sources */,
+				8887FD751090FBE7009987E8 /* CDVInvokedUrlCommand.m in Sources */,
+				8887FD861090FBE7009987E8 /* CDVLocation.m in Sources */,
+				8887FD8E1090FBE7009987E8 /* CDVNotification.m in Sources */,
+				8887FD901090FBE7009987E8 /* NSData+Base64.m in Sources */,
+				8887FD9E1090FBE7009987E8 /* CDVReachability.m in Sources */,
+				8887FDA01090FBE7009987E8 /* CDVSound.m in Sources */,
+				88BA573E109BB46F00FB5E78 /* CDVAccelerometer.m in Sources */,
+				1F3C04CF12BC247D004F9E10 /* CDVContact.m in Sources */,
+				1F92F4A11314023E0046367C /* CDVPluginResult.m in Sources */,
+				C937A4571337599E002C4C79 /* CDVFileTransfer.m in Sources */,
+				307A8F9F1385A2EC00E43782 /* CDVConnection.m in Sources */,
+				1F584B9C1385A28A00ED25E8 /* CDVCapture.m in Sources */,
+				30E33AF313A7E24B00594D64 /* CDVPlugin.m in Sources */,
+				30B39EBF13D0268B0009682A /* CDVSplashScreen.m in Sources */,
+				30E563D013E217EC00C949AA /* NSMutableArray+QueueAdditions.m in Sources */,
+				1F2BECC113F9785B00A93BF6 /* CDVBattery.m in Sources */,
+				30C684821406CB38004C1A8E /* CDVWhitelist.m in Sources */,
+				30C684961407044B004C1A8E /* CDVURLProtocol.m in Sources */,
+				30A90B9314588697006178D3 /* JSONKit.m in Sources */,
+				8852C43C14B65FD800F0E735 /* CDVViewController.m in Sources */,
+				8852C44114B65FD800F0E735 /* CDVCordovaView.m in Sources */,
+				3034979E1513D56A0090E688 /* CDVLocalStorage.m in Sources */,
+				3062D122151D0EDB000D9128 /* UIDevice+Extensions.m in Sources */,
+				3E76876D156A90EE00EB6FA3 /* CDVLogger.m in Sources */,
+				EBA3557515ABD38C00F4DE24 /* NSArray+Comparisons.m in Sources */,
+				30C5F1E015AF9E950052A00D /* CDVDevice.m in Sources */,
+				EB80C2AD15DEA63D004D9E7B /* CDVEcho.m in Sources */,
+				EB3B3548161CB44D003DBE7D /* CDVCommandQueue.m in Sources */,
+				EB3B357D161F2A45003DBE7D /* CDVCommandDelegateImpl.m in Sources */,
+				9D76CF3D1625A4C50008A0F6 /* CDVGlobalization.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+		1DEB921F08733DC00010E9CD /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				"ARCHS[sdk=iphoneos*]" = (
+					armv6,
+					armv7,
+				);
+				"ARCHS[sdk=iphoneos6.*]" = (
+					armv7,
+					armv7s,
+				);
+				"ARCHS[sdk=iphonesimulator*]" = i386;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				COPY_PHASE_STRIP = NO;
+				DSTROOT = "/tmp/$(PROJECT_NAME).dst";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_MODEL_TUNING = G5;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = CordovaLib_Prefix.pch;
+				GCC_PREPROCESSOR_DEFINITIONS = "";
+				GCC_THUMB_SUPPORT = NO;
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				INSTALL_PATH = /usr/local/lib;
+				IPHONEOS_DEPLOYMENT_TARGET = 4.2;
+				PRODUCT_NAME = Cordova;
+				PUBLIC_HEADERS_FOLDER_PATH = include/Cordova;
+				SKIP_INSTALL = YES;
+			};
+			name = Debug;
+		};
+		1DEB922008733DC00010E9CD /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				"ARCHS[sdk=iphoneos*]" = (
+					armv6,
+					armv7,
+				);
+				"ARCHS[sdk=iphoneos6.*]" = (
+					armv7,
+					armv7s,
+				);
+				"ARCHS[sdk=iphonesimulator*]" = i386;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				DSTROOT = "/tmp/$(PROJECT_NAME).dst";
+				GCC_MODEL_TUNING = G5;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = CordovaLib_Prefix.pch;
+				GCC_PREPROCESSOR_DEFINITIONS = "";
+				GCC_THUMB_SUPPORT = NO;
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				INSTALL_PATH = /usr/local/lib;
+				IPHONEOS_DEPLOYMENT_TARGET = 4.2;
+				PRODUCT_NAME = Cordova;
+				PUBLIC_HEADERS_FOLDER_PATH = include/Cordova;
+				SKIP_INSTALL = YES;
+			};
+			name = Release;
+		};
+		1DEB922308733DC00010E9CD /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				"ARCHS[sdk=iphoneos*]" = (
+					armv6,
+					armv7,
+				);
+				"ARCHS[sdk=iphoneos6.*]" = (
+					armv7,
+					armv7s,
+				);
+				"ARCHS[sdk=iphonesimulator*]" = i386;
+				GCC_C_LANGUAGE_STANDARD = c99;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = "";
+				GCC_THUMB_SUPPORT = NO;
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 4.2;
+				ONLY_ACTIVE_ARCH = NO;
+				OTHER_CFLAGS = "-DDEBUG";
+				PUBLIC_HEADERS_FOLDER_PATH = include/Cordova;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				USER_HEADER_SEARCH_PATHS = "";
+				VALID_ARCHS = "i386 armv6 armv7 armv7s";
+			};
+			name = Debug;
+		};
+		1DEB922408733DC00010E9CD /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				"ARCHS[sdk=iphoneos*]" = (
+					armv6,
+					armv7,
+				);
+				"ARCHS[sdk=iphoneos6.*]" = (
+					armv7,
+					armv7s,
+				);
+				"ARCHS[sdk=iphonesimulator*]" = i386;
+				GCC_C_LANGUAGE_STANDARD = c99;
+				GCC_PREPROCESSOR_DEFINITIONS = "";
+				GCC_THUMB_SUPPORT = NO;
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 4.2;
+				ONLY_ACTIVE_ARCH = NO;
+				PUBLIC_HEADERS_FOLDER_PATH = include/Cordova;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				VALID_ARCHS = "i386 armv6 armv7 armv7s";
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		1DEB921E08733DC00010E9CD /* Build configuration list for PBXNativeTarget "CordovaLib" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				1DEB921F08733DC00010E9CD /* Debug */,
+				1DEB922008733DC00010E9CD /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		1DEB922208733DC00010E9CD /* Build configuration list for PBXProject "CordovaLib" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				1DEB922308733DC00010E9CD /* Debug */,
+				1DEB922408733DC00010E9CD /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 0867D690FE84028FC02AAC07 /* Project object */;
+}

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/ios-config-xml/CordovaLib/VERSION
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/ios-config-xml/CordovaLib/VERSION b/tests/spec/unit/fixtures/ios-config-xml/CordovaLib/VERSION
new file mode 100644
index 0000000..1545d96
--- /dev/null
+++ b/tests/spec/unit/fixtures/ios-config-xml/CordovaLib/VERSION
@@ -0,0 +1 @@
+3.5.0

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/ios-config-xml/SampleApp.xcodeproj/project.orig.pbxproj
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp.xcodeproj/project.orig.pbxproj b/tests/spec/unit/fixtures/ios-config-xml/SampleApp.xcodeproj/project.orig.pbxproj
new file mode 100644
index 0000000..a4d87f9
--- /dev/null
+++ b/tests/spec/unit/fixtures/ios-config-xml/SampleApp.xcodeproj/project.orig.pbxproj
@@ -0,0 +1,498 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		571A464014DB0A1B007FEAC7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A463F14DB0A1B007FEAC7 /* Foundation.framework */; };
+		571A464214DB0A1B007FEAC7 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464114DB0A1B007FEAC7 /* UIKit.framework */; };
+		571A464414DB0A1B007FEAC7 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464314DB0A1B007FEAC7 /* CoreGraphics.framework */; };
+		571A464614DB0A1B007FEAC7 /* AddressBook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464514DB0A1B007FEAC7 /* AddressBook.framework */; };
+		571A464814DB0A1B007FEAC7 /* AddressBookUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464714DB0A1B007FEAC7 /* AddressBookUI.framework */; };
+		571A464A14DB0A1B007FEAC7 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464914DB0A1B007FEAC7 /* AudioToolbox.framework */; };
+		571A464C14DB0A1B007FEAC7 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464B14DB0A1B007FEAC7 /* AVFoundation.framework */; };
+		571A464E14DB0A1B007FEAC7 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464D14DB0A1B007FEAC7 /* CoreLocation.framework */; };
+		571A465014DB0A1B007FEAC7 /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464F14DB0A1B007FEAC7 /* MediaPlayer.framework */; };
+		571A465214DB0A1B007FEAC7 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A465114DB0A1B007FEAC7 /* QuartzCore.framework */; };
+		571A465414DB0A1B007FEAC7 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A465314DB0A1B007FEAC7 /* SystemConfiguration.framework */; };
+		571A465614DB0A1B007FEAC7 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A465514DB0A1B007FEAC7 /* MobileCoreServices.framework */; };
+		571A465814DB0A1B007FEAC7 /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A465714DB0A1B007FEAC7 /* CoreMedia.framework */; };
+		571A465E14DB0A1B007FEAC7 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 571A465C14DB0A1B007FEAC7 /* InfoPlist.strings */; };
+		571A466014DB0A1B007FEAC7 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 571A465F14DB0A1B007FEAC7 /* main.m */; };
+		571A466314DB0A1B007FEAC7 /* PhoneGap.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A466214DB0A1B007FEAC7 /* PhoneGap.framework */; };
+		571A466814DB0A1B007FEAC7 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 571A466614DB0A1B007FEAC7 /* Localizable.strings */; };
+		571A466C14DB0A1B007FEAC7 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 571A466A14DB0A1B007FEAC7 /* Localizable.strings */; };
+		571A466F14DB0A1B007FEAC7 /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 571A466E14DB0A1B007FEAC7 /* icon.png */; };
+		571A467114DB0A1B007FEAC7 /* icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 571A467014DB0A1B007FEAC7 /* icon@2x.png */; };
+		571A467314DB0A1B007FEAC7 /* icon-72.png in Resources */ = {isa = PBXBuildFile; fileRef = 571A467214DB0A1B007FEAC7 /* icon-72.png */; };
+		571A467614DB0A1B007FEAC7 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 571A467514DB0A1B007FEAC7 /* Default.png */; };
+		571A467814DB0A1B007FEAC7 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 571A467714DB0A1B007FEAC7 /* Default@2x.png */; };
+		571A467A14DB0A1B007FEAC7 /* Capture.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 571A467914DB0A1B007FEAC7 /* Capture.bundle */; };
+		571A467C14DB0A1B007FEAC7 /* PhoneGap.plist in Resources */ = {isa = PBXBuildFile; fileRef = 571A467B14DB0A1B007FEAC7 /* PhoneGap.plist */; };
+		571A468014DB0A1B007FEAC7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 571A467F14DB0A1B007FEAC7 /* AppDelegate.m */; };
+		571A468314DB0A1B007FEAC7 /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 571A468214DB0A1B007FEAC7 /* MainViewController.m */; };
+		571A468514DB0A1B007FEAC7 /* MainViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 571A468414DB0A1B007FEAC7 /* MainViewController.xib */; };
+		577FC36614DB0B620082BA7B /* www in Resources */ = {isa = PBXBuildFile; fileRef = 577FC36514DB0B620082BA7B /* www */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		571A463B14DB0A1B007FEAC7 /* ChildApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ChildApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		571A463F14DB0A1B007FEAC7 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+		571A464114DB0A1B007FEAC7 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+		571A464314DB0A1B007FEAC7 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+		571A464514DB0A1B007FEAC7 /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; };
+		571A464714DB0A1B007FEAC7 /* AddressBookUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBookUI.framework; path = System/Library/Frameworks/AddressBookUI.framework; sourceTree = SDKROOT; };
+		571A464914DB0A1B007FEAC7 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
+		571A464B14DB0A1B007FEAC7 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
+		571A464D14DB0A1B007FEAC7 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; };
+		571A464F14DB0A1B007FEAC7 /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; };
+		571A465114DB0A1B007FEAC7 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
+		571A465314DB0A1B007FEAC7 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
+		571A465514DB0A1B007FEAC7 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };
+		571A465714DB0A1B007FEAC7 /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; };
+		571A465B14DB0A1B007FEAC7 /* ChildApp-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ChildApp-Info.plist"; sourceTree = "<group>"; };
+		571A465D14DB0A1B007FEAC7 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+		571A465F14DB0A1B007FEAC7 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+		571A466114DB0A1B007FEAC7 /* ChildApp-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ChildApp-Prefix.pch"; sourceTree = "<group>"; };
+		571A466214DB0A1B007FEAC7 /* PhoneGap.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PhoneGap.framework; path = /Users/Shared/PhoneGap/Frameworks/PhoneGap.framework; sourceTree = "<absolute>"; };
+		571A466714DB0A1B007FEAC7 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = Resources/en.lproj/Localizable.strings; sourceTree = "<group>"; };
+		571A466B14DB0A1B007FEAC7 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = Resources/es.lproj/Localizable.strings; sourceTree = "<group>"; };
+		571A466E14DB0A1B007FEAC7 /* icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = icon.png; path = Resources/icons/icon.png; sourceTree = "<group>"; };
+		571A467014DB0A1B007FEAC7 /* icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "icon@2x.png"; path = "Resources/icons/icon@2x.png"; sourceTree = "<group>"; };
+		571A467214DB0A1B007FEAC7 /* icon-72.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "icon-72.png"; path = "Resources/icons/icon-72.png"; sourceTree = "<group>"; };
+		571A467514DB0A1B007FEAC7 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Default.png; path = Resources/splash/Default.png; sourceTree = "<group>"; };
+		571A467714DB0A1B007FEAC7 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default@2x.png"; path = "Resources/splash/Default@2x.png"; sourceTree = "<group>"; };
+		571A467914DB0A1B007FEAC7 /* Capture.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = Capture.bundle; path = Resources/Capture.bundle; sourceTree = "<group>"; };
+		571A467B14DB0A1B007FEAC7 /* PhoneGap.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = PhoneGap.plist; sourceTree = "<group>"; };
+		571A467E14DB0A1B007FEAC7 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Classes/AppDelegate.h; sourceTree = "<group>"; };
+		571A467F14DB0A1B007FEAC7 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = Classes/AppDelegate.m; sourceTree = "<group>"; };
+		571A468114DB0A1B007FEAC7 /* MainViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MainViewController.h; path = Classes/MainViewController.h; sourceTree = "<group>"; };
+		571A468214DB0A1B007FEAC7 /* MainViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = MainViewController.m; path = Classes/MainViewController.m; sourceTree = "<group>"; };
+		571A468414DB0A1B007FEAC7 /* MainViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = MainViewController.xib; path = Classes/MainViewController.xib; sourceTree = "<group>"; };
+		571A468714DB0A1B007FEAC7 /* README */ = {isa = PBXFileReference; lastKnownFileType = text; name = README; path = Plugins/README; sourceTree = "<group>"; };
+		577FC36514DB0B620082BA7B /* www */ = {isa = PBXFileReference; lastKnownFileType = folder; path = www; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		571A463514DB0A1B007FEAC7 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				571A464014DB0A1B007FEAC7 /* Foundation.framework in Frameworks */,
+				571A464214DB0A1B007FEAC7 /* UIKit.framework in Frameworks */,
+				571A464414DB0A1B007FEAC7 /* CoreGraphics.framework in Frameworks */,
+				571A464614DB0A1B007FEAC7 /* AddressBook.framework in Frameworks */,
+				571A464814DB0A1B007FEAC7 /* AddressBookUI.framework in Frameworks */,
+				571A464A14DB0A1B007FEAC7 /* AudioToolbox.framework in Frameworks */,
+				571A464C14DB0A1B007FEAC7 /* AVFoundation.framework in Frameworks */,
+				571A464E14DB0A1B007FEAC7 /* CoreLocation.framework in Frameworks */,
+				571A465014DB0A1B007FEAC7 /* MediaPlayer.framework in Frameworks */,
+				571A465214DB0A1B007FEAC7 /* QuartzCore.framework in Frameworks */,
+				571A465414DB0A1B007FEAC7 /* SystemConfiguration.framework in Frameworks */,
+				571A465614DB0A1B007FEAC7 /* MobileCoreServices.framework in Frameworks */,
+				571A465814DB0A1B007FEAC7 /* CoreMedia.framework in Frameworks */,
+				571A466314DB0A1B007FEAC7 /* PhoneGap.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		571A463814DB0A1B007FEAC7 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		571A462D14DB0A1A007FEAC7 = {
+			isa = PBXGroup;
+			children = (
+				577FC36514DB0B620082BA7B /* www */,
+				571A465914DB0A1B007FEAC7 /* ChildApp */,
+				571A463E14DB0A1B007FEAC7 /* Frameworks */,
+				571A463C14DB0A1B007FEAC7 /* Products */,
+			);
+			sourceTree = "<group>";
+		};
+		571A463C14DB0A1B007FEAC7 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				571A463B14DB0A1B007FEAC7 /* ChildApp.app */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		571A463E14DB0A1B007FEAC7 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				571A463F14DB0A1B007FEAC7 /* Foundation.framework */,
+				571A464114DB0A1B007FEAC7 /* UIKit.framework */,
+				571A464314DB0A1B007FEAC7 /* CoreGraphics.framework */,
+				571A464514DB0A1B007FEAC7 /* AddressBook.framework */,
+				571A464714DB0A1B007FEAC7 /* AddressBookUI.framework */,
+				571A464914DB0A1B007FEAC7 /* AudioToolbox.framework */,
+				571A464B14DB0A1B007FEAC7 /* AVFoundation.framework */,
+				571A464D14DB0A1B007FEAC7 /* CoreLocation.framework */,
+				571A464F14DB0A1B007FEAC7 /* MediaPlayer.framework */,
+				571A465114DB0A1B007FEAC7 /* QuartzCore.framework */,
+				571A465314DB0A1B007FEAC7 /* SystemConfiguration.framework */,
+				571A465514DB0A1B007FEAC7 /* MobileCoreServices.framework */,
+				571A465714DB0A1B007FEAC7 /* CoreMedia.framework */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		571A465914DB0A1B007FEAC7 /* ChildApp */ = {
+			isa = PBXGroup;
+			children = (
+				571A466214DB0A1B007FEAC7 /* PhoneGap.framework */,
+				571A466414DB0A1B007FEAC7 /* Resources */,
+				571A467D14DB0A1B007FEAC7 /* Classes */,
+				571A468614DB0A1B007FEAC7 /* Plugins */,
+				571A465A14DB0A1B007FEAC7 /* Supporting Files */,
+			);
+			path = ChildApp;
+			sourceTree = "<group>";
+		};
+		571A465A14DB0A1B007FEAC7 /* Supporting Files */ = {
+			isa = PBXGroup;
+			children = (
+				571A465B14DB0A1B007FEAC7 /* ChildApp-Info.plist */,
+				571A465C14DB0A1B007FEAC7 /* InfoPlist.strings */,
+				571A465F14DB0A1B007FEAC7 /* main.m */,
+				571A466114DB0A1B007FEAC7 /* ChildApp-Prefix.pch */,
+				571A467B14DB0A1B007FEAC7 /* PhoneGap.plist */,
+				571A468414DB0A1B007FEAC7 /* MainViewController.xib */,
+			);
+			name = "Supporting Files";
+			sourceTree = "<group>";
+		};
+		571A466414DB0A1B007FEAC7 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				571A467914DB0A1B007FEAC7 /* Capture.bundle */,
+				571A466514DB0A1B007FEAC7 /* en.lproj */,
+				571A466914DB0A1B007FEAC7 /* es.lproj */,
+				571A466D14DB0A1B007FEAC7 /* icons */,
+				571A467414DB0A1B007FEAC7 /* splash */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		571A466514DB0A1B007FEAC7 /* en.lproj */ = {
+			isa = PBXGroup;
+			children = (
+				571A466614DB0A1B007FEAC7 /* Localizable.strings */,
+			);
+			name = en.lproj;
+			sourceTree = "<group>";
+		};
+		571A466914DB0A1B007FEAC7 /* es.lproj */ = {
+			isa = PBXGroup;
+			children = (
+				571A466A14DB0A1B007FEAC7 /* Localizable.strings */,
+			);
+			name = es.lproj;
+			sourceTree = "<group>";
+		};
+		571A466D14DB0A1B007FEAC7 /* icons */ = {
+			isa = PBXGroup;
+			children = (
+				571A466E14DB0A1B007FEAC7 /* icon.png */,
+				571A467014DB0A1B007FEAC7 /* icon@2x.png */,
+				571A467214DB0A1B007FEAC7 /* icon-72.png */,
+			);
+			name = icons;
+			sourceTree = "<group>";
+		};
+		571A467414DB0A1B007FEAC7 /* splash */ = {
+			isa = PBXGroup;
+			children = (
+				571A467514DB0A1B007FEAC7 /* Default.png */,
+				571A467714DB0A1B007FEAC7 /* Default@2x.png */,
+			);
+			name = splash;
+			sourceTree = "<group>";
+		};
+		571A467D14DB0A1B007FEAC7 /* Classes */ = {
+			isa = PBXGroup;
+			children = (
+				571A467E14DB0A1B007FEAC7 /* AppDelegate.h */,
+				571A467F14DB0A1B007FEAC7 /* AppDelegate.m */,
+				571A468114DB0A1B007FEAC7 /* MainViewController.h */,
+				571A468214DB0A1B007FEAC7 /* MainViewController.m */,
+			);
+			name = Classes;
+			sourceTree = "<group>";
+		};
+		571A468614DB0A1B007FEAC7 /* Plugins */ = {
+			isa = PBXGroup;
+			children = (
+				571A468714DB0A1B007FEAC7 /* README */,
+			);
+			name = Plugins;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		571A463A14DB0A1B007FEAC7 /* ChildApp */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 571A468A14DB0A1B007FEAC7 /* Build configuration list for PBXNativeTarget "ChildApp" */;
+			buildPhases = (
+				571A463414DB0A1B007FEAC7 /* Sources */,
+				571A463514DB0A1B007FEAC7 /* Frameworks */,
+				571A463614DB0A1B007FEAC7 /* Resources */,
+				571A463714DB0A1B007FEAC7 /* Sources */,
+				571A463814DB0A1B007FEAC7 /* Frameworks */,
+				571A463914DB0A1B007FEAC7 /* ShellScript */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = ChildApp;
+			productName = ChildApp;
+			productReference = 571A463B14DB0A1B007FEAC7 /* ChildApp.app */;
+			productType = "com.apple.product-type.application";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		571A462F14DB0A1A007FEAC7 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 0420;
+			};
+			buildConfigurationList = 571A463214DB0A1A007FEAC7 /* Build configuration list for PBXProject "ChildApp" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+				es,
+			);
+			mainGroup = 571A462D14DB0A1A007FEAC7;
+			productRefGroup = 571A463C14DB0A1B007FEAC7 /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				571A463A14DB0A1B007FEAC7 /* ChildApp */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		571A463614DB0A1B007FEAC7 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				571A465E14DB0A1B007FEAC7 /* InfoPlist.strings in Resources */,
+				571A466814DB0A1B007FEAC7 /* Localizable.strings in Resources */,
+				571A466C14DB0A1B007FEAC7 /* Localizable.strings in Resources */,
+				571A466F14DB0A1B007FEAC7 /* icon.png in Resources */,
+				571A467114DB0A1B007FEAC7 /* icon@2x.png in Resources */,
+				571A467314DB0A1B007FEAC7 /* icon-72.png in Resources */,
+				571A467614DB0A1B007FEAC7 /* Default.png in Resources */,
+				571A467814DB0A1B007FEAC7 /* Default@2x.png in Resources */,
+				571A467A14DB0A1B007FEAC7 /* Capture.bundle in Resources */,
+				571A467C14DB0A1B007FEAC7 /* PhoneGap.plist in Resources */,
+				571A468514DB0A1B007FEAC7 /* MainViewController.xib in Resources */,
+				577FC36614DB0B620082BA7B /* www in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		571A463914DB0A1B007FEAC7 /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/bash;
+			shellScript = "\n\t\t\t\t\t\t\t\tif [ ! -d \"$PROJECT_DIR/www\" ] ; then\n\t\t\t\t\t\t\t\t\tcp -R /Users/Shared/PhoneGap/Frameworks/PhoneGap.framework/www \"$PROJECT_DIR\"\n\t\t\t\t\t\t\t\tfi\n\t\t\t\t\t\t\t\t# detect www folder reference in project, if missing, print warning\n\t\t\t\t\t\t\t\tgrep \"{isa = PBXFileReference; lastKnownFileType = folder; path = www; sourceTree = \\\"<group>\\\"; };\" \"$PROJECT_DIR/$PROJECT_NAME.xcodeproj/project.pbxproj\"\n\t\t\t\t\t\t\t\trc=$? \n\t\t\t\t\t\t\t\tif [ $rc != 0 ] ; then\n\t\t\t\t\t\t\t\techo -e \"warning: Missing - Add $PROJECT_DIR/www as a folder reference in your project. Just drag and drop the folder into your project, into the Project Navigator of Xcode 4. Make sure you select the second radio-button: 'Create folder references for any added folders' (which will create a blue folder)\" 1>&2\n\t\t\t\t\t\t\t\tfi\t\t\t\t\t\t\t";
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		571A463414DB0A1B007FEAC7 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				571A466014DB0A1B007FEAC7 /* main.m in Sources */,
+				571A468014DB0A1B007FEAC7 /* AppDelegate.m in Sources */,
+				571A468314DB0A1B007FEAC7 /* MainViewController.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		571A463714DB0A1B007FEAC7 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+		571A465C14DB0A1B007FEAC7 /* InfoPlist.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				571A465D14DB0A1B007FEAC7 /* en */,
+			);
+			name = InfoPlist.strings;
+			sourceTree = "<group>";
+		};
+		571A466614DB0A1B007FEAC7 /* Localizable.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				571A466714DB0A1B007FEAC7 /* en */,
+			);
+			name = Localizable.strings;
+			sourceTree = "<group>";
+		};
+		571A466A14DB0A1B007FEAC7 /* Localizable.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				571A466B14DB0A1B007FEAC7 /* es */,
+			);
+			name = Localizable.strings;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+		571A468814DB0A1B007FEAC7 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				CLANG_ENABLE_OBJC_ARC = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = NO;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+				GCC_VERSION = com.apple.compilers.llvmgcc42;
+				GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 3.0;
+				SDKROOT = iphoneos;
+			};
+			name = Debug;
+		};
+		571A468914DB0A1B007FEAC7 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				CLANG_ENABLE_OBJC_ARC = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_VERSION = com.apple.compilers.llvmgcc42;
+				GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 3.0;
+				SDKROOT = iphoneos;
+				VALIDATE_PRODUCT = YES;
+			};
+			name = Release;
+		};
+		571A468B14DB0A1B007FEAC7 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = YES;
+				COPY_PHASE_STRIP = NO;
+				FRAMEWORK_SEARCH_PATHS = /Users/Shared/PhoneGap/Frameworks;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = "ChildApp/ChildApp-Prefix.pch";
+				GCC_PREPROCESSOR_DEFINITIONS = "PHONEGAP_FRAMEWORK=YES";
+				INFOPLIST_FILE = "ChildApp/ChildApp-Info.plist";
+				OTHER_LDFLAGS = (
+					"-weak_framework",
+					UIKit,
+					"-weak_framework",
+					AVFoundation,
+					"-weak_framework",
+					CoreMedia,
+					"-weak_library",
+					/usr/lib/libSystem.B.dylib,
+				);
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = app;
+			};
+			name = Debug;
+		};
+		571A468C14DB0A1B007FEAC7 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = YES;
+				COPY_PHASE_STRIP = YES;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				FRAMEWORK_SEARCH_PATHS = /Users/Shared/PhoneGap/Frameworks;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = "ChildApp/ChildApp-Prefix.pch";
+				GCC_PREPROCESSOR_DEFINITIONS = "PHONEGAP_FRAMEWORK=YES";
+				INFOPLIST_FILE = "ChildApp/ChildApp-Info.plist";
+				OTHER_LDFLAGS = (
+					"-weak_framework",
+					UIKit,
+					"-weak_framework",
+					AVFoundation,
+					"-weak_framework",
+					CoreMedia,
+					"-weak_library",
+					/usr/lib/libSystem.B.dylib,
+				);
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TARGETED_DEVICE_FAMILY = "1,2";
+				VALIDATE_PRODUCT = YES;
+				WRAPPER_EXTENSION = app;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		571A463214DB0A1A007FEAC7 /* Build configuration list for PBXProject "ChildApp" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				571A468814DB0A1B007FEAC7 /* Debug */,
+				571A468914DB0A1B007FEAC7 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		571A468A14DB0A1B007FEAC7 /* Build configuration list for PBXNativeTarget "ChildApp" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				571A468B14DB0A1B007FEAC7 /* Debug */,
+				571A468C14DB0A1B007FEAC7 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 571A462F14DB0A1A007FEAC7 /* Project object */;
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org


[2/6] ios commit: CB-10769 Copy raw pluginHandler tests from cordova-lib

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/ios-config-xml/SampleApp.xcodeproj/project.pbxproj
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp.xcodeproj/project.pbxproj b/tests/spec/unit/fixtures/ios-config-xml/SampleApp.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..5630416
--- /dev/null
+++ b/tests/spec/unit/fixtures/ios-config-xml/SampleApp.xcodeproj/project.pbxproj
@@ -0,0 +1,496 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		571A464014DB0A1B007FEAC7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A463F14DB0A1B007FEAC7 /* Foundation.framework */; };
+		571A464214DB0A1B007FEAC7 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464114DB0A1B007FEAC7 /* UIKit.framework */; };
+		571A464414DB0A1B007FEAC7 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464314DB0A1B007FEAC7 /* CoreGraphics.framework */; };
+		571A464614DB0A1B007FEAC7 /* AddressBook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464514DB0A1B007FEAC7 /* AddressBook.framework */; };
+		571A464814DB0A1B007FEAC7 /* AddressBookUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464714DB0A1B007FEAC7 /* AddressBookUI.framework */; };
+		571A464A14DB0A1B007FEAC7 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464914DB0A1B007FEAC7 /* AudioToolbox.framework */; };
+		571A464C14DB0A1B007FEAC7 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464B14DB0A1B007FEAC7 /* AVFoundation.framework */; };
+		571A464E14DB0A1B007FEAC7 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464D14DB0A1B007FEAC7 /* CoreLocation.framework */; };
+		571A465014DB0A1B007FEAC7 /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A464F14DB0A1B007FEAC7 /* MediaPlayer.framework */; };
+		571A465214DB0A1B007FEAC7 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A465114DB0A1B007FEAC7 /* QuartzCore.framework */; };
+		571A465414DB0A1B007FEAC7 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A465314DB0A1B007FEAC7 /* SystemConfiguration.framework */; };
+		571A465614DB0A1B007FEAC7 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A465514DB0A1B007FEAC7 /* MobileCoreServices.framework */; };
+		571A465814DB0A1B007FEAC7 /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A465714DB0A1B007FEAC7 /* CoreMedia.framework */; };
+		571A465E14DB0A1B007FEAC7 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 571A465C14DB0A1B007FEAC7 /* InfoPlist.strings */; };
+		571A466014DB0A1B007FEAC7 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 571A465F14DB0A1B007FEAC7 /* main.m */; };
+		571A466314DB0A1B007FEAC7 /* PhoneGap.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 571A466214DB0A1B007FEAC7 /* PhoneGap.framework */; };
+		571A466814DB0A1B007FEAC7 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 571A466614DB0A1B007FEAC7 /* Localizable.strings */; };
+		571A466C14DB0A1B007FEAC7 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 571A466A14DB0A1B007FEAC7 /* Localizable.strings */; };
+		571A466F14DB0A1B007FEAC7 /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 571A466E14DB0A1B007FEAC7 /* icon.png */; };
+		571A467114DB0A1B007FEAC7 /* icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 571A467014DB0A1B007FEAC7 /* icon@2x.png */; };
+		571A467314DB0A1B007FEAC7 /* icon-72.png in Resources */ = {isa = PBXBuildFile; fileRef = 571A467214DB0A1B007FEAC7 /* icon-72.png */; };
+		571A467614DB0A1B007FEAC7 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 571A467514DB0A1B007FEAC7 /* Default.png */; };
+		571A467814DB0A1B007FEAC7 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 571A467714DB0A1B007FEAC7 /* Default@2x.png */; };
+		571A467A14DB0A1B007FEAC7 /* Capture.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 571A467914DB0A1B007FEAC7 /* Capture.bundle */; };
+		571A467C14DB0A1B007FEAC7 /* PhoneGap.plist in Resources */ = {isa = PBXBuildFile; fileRef = 571A467B14DB0A1B007FEAC7 /* PhoneGap.plist */; };
+		571A468014DB0A1B007FEAC7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 571A467F14DB0A1B007FEAC7 /* AppDelegate.m */; };
+		571A468314DB0A1B007FEAC7 /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 571A468214DB0A1B007FEAC7 /* MainViewController.m */; };
+		571A468514DB0A1B007FEAC7 /* MainViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 571A468414DB0A1B007FEAC7 /* MainViewController.xib */; };
+		577FC36614DB0B620082BA7B /* www in Resources */ = {isa = PBXBuildFile; fileRef = 577FC36514DB0B620082BA7B /* www */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		571A463B14DB0A1B007FEAC7 /* SampleApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SampleApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		571A463F14DB0A1B007FEAC7 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+		571A464114DB0A1B007FEAC7 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+		571A464314DB0A1B007FEAC7 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+		571A464514DB0A1B007FEAC7 /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; };
+		571A464714DB0A1B007FEAC7 /* AddressBookUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBookUI.framework; path = System/Library/Frameworks/AddressBookUI.framework; sourceTree = SDKROOT; };
+		571A464914DB0A1B007FEAC7 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
+		571A464B14DB0A1B007FEAC7 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
+		571A464D14DB0A1B007FEAC7 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; };
+		571A464F14DB0A1B007FEAC7 /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; };
+		571A465114DB0A1B007FEAC7 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
+		571A465314DB0A1B007FEAC7 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
+		571A465514DB0A1B007FEAC7 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };
+		571A465714DB0A1B007FEAC7 /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; };
+		571A465B14DB0A1B007FEAC7 /* SampleApp-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SampleApp-Info.plist"; sourceTree = "<group>"; };
+		571A465D14DB0A1B007FEAC7 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+		571A465F14DB0A1B007FEAC7 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+		571A466114DB0A1B007FEAC7 /* SampleApp-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SampleApp-Prefix.pch"; sourceTree = "<group>"; };
+		571A466214DB0A1B007FEAC7 /* PhoneGap.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PhoneGap.framework; path = /Users/Shared/PhoneGap/Frameworks/PhoneGap.framework; sourceTree = "<absolute>"; };
+		571A466714DB0A1B007FEAC7 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = Resources/en.lproj/Localizable.strings; sourceTree = "<group>"; };
+		571A466B14DB0A1B007FEAC7 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = Resources/es.lproj/Localizable.strings; sourceTree = "<group>"; };
+		571A466E14DB0A1B007FEAC7 /* icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = icon.png; path = Resources/icons/icon.png; sourceTree = "<group>"; };
+		571A467014DB0A1B007FEAC7 /* icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "icon@2x.png"; path = "Resources/icons/icon@2x.png"; sourceTree = "<group>"; };
+		571A467214DB0A1B007FEAC7 /* icon-72.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "icon-72.png"; path = "Resources/icons/icon-72.png"; sourceTree = "<group>"; };
+		571A467514DB0A1B007FEAC7 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Default.png; path = Resources/splash/Default.png; sourceTree = "<group>"; };
+		571A467714DB0A1B007FEAC7 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default@2x.png"; path = "Resources/splash/Default@2x.png"; sourceTree = "<group>"; };
+		571A467914DB0A1B007FEAC7 /* Capture.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = Capture.bundle; path = Resources/Capture.bundle; sourceTree = "<group>"; };
+		571A467B14DB0A1B007FEAC7 /* PhoneGap.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = PhoneGap.plist; sourceTree = "<group>"; };
+		571A467E14DB0A1B007FEAC7 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Classes/AppDelegate.h; sourceTree = "<group>"; };
+		571A467F14DB0A1B007FEAC7 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = Classes/AppDelegate.m; sourceTree = "<group>"; };
+		571A468114DB0A1B007FEAC7 /* MainViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MainViewController.h; path = Classes/MainViewController.h; sourceTree = "<group>"; };
+		571A468214DB0A1B007FEAC7 /* MainViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = MainViewController.m; path = Classes/MainViewController.m; sourceTree = "<group>"; };
+		571A468414DB0A1B007FEAC7 /* MainViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = MainViewController.xib; path = Classes/MainViewController.xib; sourceTree = "<group>"; };
+		571A468714DB0A1B007FEAC7 /* README */ = {isa = PBXFileReference; lastKnownFileType = text; name = README; path = Plugins/README; sourceTree = "<group>"; };
+		577FC36514DB0B620082BA7B /* www */ = {isa = PBXFileReference; lastKnownFileType = folder; path = www; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		571A463514DB0A1B007FEAC7 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				571A464014DB0A1B007FEAC7 /* Foundation.framework in Frameworks */,
+				571A464214DB0A1B007FEAC7 /* UIKit.framework in Frameworks */,
+				571A464414DB0A1B007FEAC7 /* CoreGraphics.framework in Frameworks */,
+				571A464614DB0A1B007FEAC7 /* AddressBook.framework in Frameworks */,
+				571A464814DB0A1B007FEAC7 /* AddressBookUI.framework in Frameworks */,
+				571A464A14DB0A1B007FEAC7 /* AudioToolbox.framework in Frameworks */,
+				571A464C14DB0A1B007FEAC7 /* AVFoundation.framework in Frameworks */,
+				571A464E14DB0A1B007FEAC7 /* CoreLocation.framework in Frameworks */,
+				571A465014DB0A1B007FEAC7 /* MediaPlayer.framework in Frameworks */,
+				571A465214DB0A1B007FEAC7 /* QuartzCore.framework in Frameworks */,
+				571A465414DB0A1B007FEAC7 /* SystemConfiguration.framework in Frameworks */,
+				571A465614DB0A1B007FEAC7 /* MobileCoreServices.framework in Frameworks */,
+				571A465814DB0A1B007FEAC7 /* CoreMedia.framework in Frameworks */,
+				571A466314DB0A1B007FEAC7 /* PhoneGap.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		571A463814DB0A1B007FEAC7 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		571A462D14DB0A1A007FEAC7 = {
+			isa = PBXGroup;
+			children = (
+				577FC36514DB0B620082BA7B /* www */,
+				571A465914DB0A1B007FEAC7 /* SampleApp */,
+				571A463E14DB0A1B007FEAC7 /* Frameworks */,
+				571A463C14DB0A1B007FEAC7 /* Products */,
+			);
+			sourceTree = "<group>";
+		};
+		571A463C14DB0A1B007FEAC7 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				571A463B14DB0A1B007FEAC7 /* SampleApp.app */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		571A463E14DB0A1B007FEAC7 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				571A463F14DB0A1B007FEAC7 /* Foundation.framework */,
+				571A464114DB0A1B007FEAC7 /* UIKit.framework */,
+				571A464314DB0A1B007FEAC7 /* CoreGraphics.framework */,
+				571A464514DB0A1B007FEAC7 /* AddressBook.framework */,
+				571A464714DB0A1B007FEAC7 /* AddressBookUI.framework */,
+				571A464914DB0A1B007FEAC7 /* AudioToolbox.framework */,
+				571A464B14DB0A1B007FEAC7 /* AVFoundation.framework */,
+				571A464D14DB0A1B007FEAC7 /* CoreLocation.framework */,
+				571A464F14DB0A1B007FEAC7 /* MediaPlayer.framework */,
+				571A465114DB0A1B007FEAC7 /* QuartzCore.framework */,
+				571A465314DB0A1B007FEAC7 /* SystemConfiguration.framework */,
+				571A465514DB0A1B007FEAC7 /* MobileCoreServices.framework */,
+				571A465714DB0A1B007FEAC7 /* CoreMedia.framework */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		571A465914DB0A1B007FEAC7 /* SampleApp */ = {
+			isa = PBXGroup;
+			children = (
+				571A466214DB0A1B007FEAC7 /* PhoneGap.framework */,
+				571A466414DB0A1B007FEAC7 /* Resources */,
+				571A467D14DB0A1B007FEAC7 /* Classes */,
+				571A468614DB0A1B007FEAC7 /* Plugins */,
+				571A465A14DB0A1B007FEAC7 /* Supporting Files */,
+			);
+			path = SampleApp;
+			sourceTree = "<group>";
+		};
+		571A465A14DB0A1B007FEAC7 /* Supporting Files */ = {
+			isa = PBXGroup;
+			children = (
+				571A465B14DB0A1B007FEAC7 /* SampleApp-Info.plist */,
+				571A465C14DB0A1B007FEAC7 /* InfoPlist.strings */,
+				571A465F14DB0A1B007FEAC7 /* main.m */,
+				571A466114DB0A1B007FEAC7 /* SampleApp-Prefix.pch */,
+				571A467B14DB0A1B007FEAC7 /* PhoneGap.plist */,
+				571A468414DB0A1B007FEAC7 /* MainViewController.xib */,
+			);
+			name = "Supporting Files";
+			sourceTree = "<group>";
+		};
+		571A466414DB0A1B007FEAC7 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				571A467914DB0A1B007FEAC7 /* Capture.bundle */,
+				571A466514DB0A1B007FEAC7 /* en.lproj */,
+				571A466914DB0A1B007FEAC7 /* es.lproj */,
+				571A466D14DB0A1B007FEAC7 /* icons */,
+				571A467414DB0A1B007FEAC7 /* splash */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		571A466514DB0A1B007FEAC7 /* en.lproj */ = {
+			isa = PBXGroup;
+			children = (
+				571A466614DB0A1B007FEAC7 /* Localizable.strings */,
+			);
+			name = en.lproj;
+			sourceTree = "<group>";
+		};
+		571A466914DB0A1B007FEAC7 /* es.lproj */ = {
+			isa = PBXGroup;
+			children = (
+				571A466A14DB0A1B007FEAC7 /* Localizable.strings */,
+			);
+			name = es.lproj;
+			sourceTree = "<group>";
+		};
+		571A466D14DB0A1B007FEAC7 /* icons */ = {
+			isa = PBXGroup;
+			children = (
+				571A466E14DB0A1B007FEAC7 /* icon.png */,
+				571A467014DB0A1B007FEAC7 /* icon@2x.png */,
+				571A467214DB0A1B007FEAC7 /* icon-72.png */,
+			);
+			name = icons;
+			sourceTree = "<group>";
+		};
+		571A467414DB0A1B007FEAC7 /* splash */ = {
+			isa = PBXGroup;
+			children = (
+				571A467514DB0A1B007FEAC7 /* Default.png */,
+				571A467714DB0A1B007FEAC7 /* Default@2x.png */,
+			);
+			name = splash;
+			sourceTree = "<group>";
+		};
+		571A467D14DB0A1B007FEAC7 /* Classes */ = {
+			isa = PBXGroup;
+			children = (
+				571A467E14DB0A1B007FEAC7 /* AppDelegate.h */,
+				571A467F14DB0A1B007FEAC7 /* AppDelegate.m */,
+				571A468114DB0A1B007FEAC7 /* MainViewController.h */,
+				571A468214DB0A1B007FEAC7 /* MainViewController.m */,
+			);
+			name = Classes;
+			sourceTree = "<group>";
+		};
+		571A468614DB0A1B007FEAC7 /* Plugins */ = {
+			isa = PBXGroup;
+			children = (
+				571A468714DB0A1B007FEAC7 /* README */,
+			);
+			name = Plugins;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		571A463A14DB0A1B007FEAC7 /* SampleApp */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 571A468A14DB0A1B007FEAC7 /* Build configuration list for PBXNativeTarget "SampleApp" */;
+			buildPhases = (
+				571A463414DB0A1B007FEAC7 /* Sources */,
+				571A463514DB0A1B007FEAC7 /* Frameworks */,
+				571A463614DB0A1B007FEAC7 /* Resources */,
+				571A463714DB0A1B007FEAC7 /* Sources */,
+				571A463814DB0A1B007FEAC7 /* Frameworks */,
+				571A463914DB0A1B007FEAC7 /* ShellScript */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = SampleApp;
+			productName = SampleApp;
+			productReference = 571A463B14DB0A1B007FEAC7 /* SampleApp.app */;
+			productType = "com.apple.product-type.application";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		571A462F14DB0A1A007FEAC7 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 0420;
+			};
+			buildConfigurationList = 571A463214DB0A1A007FEAC7 /* Build configuration list for PBXProject "SampleApp" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+				es,
+			);
+			mainGroup = 571A462D14DB0A1A007FEAC7;
+			productRefGroup = 571A463C14DB0A1B007FEAC7 /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				571A463A14DB0A1B007FEAC7 /* SampleApp */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		571A463614DB0A1B007FEAC7 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				571A465E14DB0A1B007FEAC7 /* InfoPlist.strings in Resources */,
+				571A466814DB0A1B007FEAC7 /* Localizable.strings in Resources */,
+				571A466C14DB0A1B007FEAC7 /* Localizable.strings in Resources */,
+				571A466F14DB0A1B007FEAC7 /* icon.png in Resources */,
+				571A467114DB0A1B007FEAC7 /* icon@2x.png in Resources */,
+				571A467314DB0A1B007FEAC7 /* icon-72.png in Resources */,
+				571A467614DB0A1B007FEAC7 /* Default.png in Resources */,
+				571A467814DB0A1B007FEAC7 /* Default@2x.png in Resources */,
+				571A467A14DB0A1B007FEAC7 /* Capture.bundle in Resources */,
+				571A467C14DB0A1B007FEAC7 /* PhoneGap.plist in Resources */,
+				571A468514DB0A1B007FEAC7 /* MainViewController.xib in Resources */,
+				577FC36614DB0B620082BA7B /* www in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		571A463914DB0A1B007FEAC7 /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/bash;
+			shellScript = "\n\t\t\t\t\t\t\t\tif [ ! -d \"$PROJECT_DIR/www\" ] ; then\n\t\t\t\t\t\t\t\t\tcp -R /Users/Shared/PhoneGap/Frameworks/PhoneGap.framework/www \"$PROJECT_DIR\"\n\t\t\t\t\t\t\t\tfi\n\t\t\t\t\t\t\t\t# detect www folder reference in project, if missing, print warning\n\t\t\t\t\t\t\t\tgrep \"{isa = PBXFileReference; lastKnownFileType = folder; path = www; sourceTree = \\\"<group>\\\"; };\" \"$PROJECT_DIR/$PROJECT_NAME.xcodeproj/project.pbxproj\"\n\t\t\t\t\t\t\t\trc=$? \n\t\t\t\t\t\t\t\tif [ $rc != 0 ] ; then\n\t\t\t\t\t\t\t\techo -e \"warning: Missing - Add $PROJECT_DIR/www as a folder reference in your project. Just drag and drop the folder into your project, into the Project Navigator of Xcode 4. Make sure you select the second radio-button: 'Create folder references for any added folders' (which will create a blue folder)\" 1>&2\n\t\t\t\t\t\t\t\tfi\t\t\t\t\t\t\t";
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		571A463414DB0A1B007FEAC7 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				571A466014DB0A1B007FEAC7 /* main.m in Sources */,
+				571A468014DB0A1B007FEAC7 /* AppDelegate.m in Sources */,
+				571A468314DB0A1B007FEAC7 /* MainViewController.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		571A463714DB0A1B007FEAC7 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+		571A465C14DB0A1B007FEAC7 /* InfoPlist.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				571A465D14DB0A1B007FEAC7 /* en */,
+			);
+			name = InfoPlist.strings;
+			sourceTree = "<group>";
+		};
+		571A466614DB0A1B007FEAC7 /* Localizable.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				571A466714DB0A1B007FEAC7 /* en */,
+			);
+			name = Localizable.strings;
+			sourceTree = "<group>";
+		};
+		571A466A14DB0A1B007FEAC7 /* Localizable.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				571A466B14DB0A1B007FEAC7 /* es */,
+			);
+			name = Localizable.strings;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+		571A468814DB0A1B007FEAC7 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				CLANG_ENABLE_OBJC_ARC = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = NO;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+				GCC_VERSION = com.apple.compilers.llvmgcc42;
+				GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 3.0;
+				SDKROOT = iphoneos;
+			};
+			name = Debug;
+		};
+		571A468914DB0A1B007FEAC7 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				CLANG_ENABLE_OBJC_ARC = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_VERSION = com.apple.compilers.llvmgcc42;
+				GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 3.0;
+				SDKROOT = iphoneos;
+				VALIDATE_PRODUCT = YES;
+			};
+			name = Release;
+		};
+		571A468B14DB0A1B007FEAC7 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = YES;
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = "SampleApp/SampleApp-Prefix.pch";
+				GCC_PREPROCESSOR_DEFINITIONS = "PHONEGAP_FRAMEWORK=YES";
+				INFOPLIST_FILE = "SampleApp/SampleApp-Info.plist";
+				OTHER_LDFLAGS = (
+					"-weak_framework",
+					UIKit,
+					"-weak_framework",
+					AVFoundation,
+					"-weak_framework",
+					CoreMedia,
+					"-weak_library",
+					/usr/lib/libSystem.B.dylib,
+				);
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = app;
+			};
+			name = Debug;
+		};
+		571A468C14DB0A1B007FEAC7 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = YES;
+				COPY_PHASE_STRIP = YES;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = "SampleApp/SampleApp-Prefix.pch";
+				GCC_PREPROCESSOR_DEFINITIONS = "PHONEGAP_FRAMEWORK=YES";
+				INFOPLIST_FILE = "SampleApp/SampleApp-Info.plist";
+				OTHER_LDFLAGS = (
+					"-weak_framework",
+					UIKit,
+					"-weak_framework",
+					AVFoundation,
+					"-weak_framework",
+					CoreMedia,
+					"-weak_library",
+					/usr/lib/libSystem.B.dylib,
+				);
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TARGETED_DEVICE_FAMILY = "1,2";
+				VALIDATE_PRODUCT = YES;
+				WRAPPER_EXTENSION = app;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		571A463214DB0A1A007FEAC7 /* Build configuration list for PBXProject "SampleApp" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				571A468814DB0A1B007FEAC7 /* Debug */,
+				571A468914DB0A1B007FEAC7 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		571A468A14DB0A1B007FEAC7 /* Build configuration list for PBXNativeTarget "SampleApp" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				571A468B14DB0A1B007FEAC7 /* Debug */,
+				571A468C14DB0A1B007FEAC7 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 571A462F14DB0A1A007FEAC7 /* Project object */;
+}

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/ios-config-xml/SampleApp/SampleApp-Info.plist
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/SampleApp-Info.plist b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/SampleApp-Info.plist
new file mode 100644
index 0000000..5afd655
--- /dev/null
+++ b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/SampleApp-Info.plist
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<!--
+#
+# 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.
+#
+-->
+<plist version="1.0">
+<dict>
+	<key>CFBundleIcons</key>
+	<dict>
+		<key>CFBundlePrimaryIcon</key>
+		<dict>
+			<key>CFBundleIconFiles</key>
+			<array>
+                <string>icon.png</string>
+                <string>icon@2x.png</string>
+                <string>icon-72.png</string>
+                <string>icon-72@2x.png</string>
+			</array>
+			<key>UIPrerenderedIcon</key>
+			<false/>
+		</dict>
+	</dict>
+	<key>UISupportedInterfaceOrientations~ipad</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationPortraitUpsideDown</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+	</array>
+	<key>UISupportedInterfaceOrientations</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+	</array>
+	<key>CFValidSchemas</key>
+	<array>
+		<string>schema-a</string>
+		<dict>
+			<key>SchemaName</key>
+			<string>schema-c</string>
+		</dict>
+	</array>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleDisplayName</key>
+	<string>${PRODUCT_NAME}</string>
+	<key>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleIconFile</key>
+	<string>icon.png</string>
+	<key>CFBundleIdentifier</key>
+	<string>com.example.friendstring</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>${PRODUCT_NAME}</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1.0</string>
+	<key>LSRequiresIPhoneOS</key>
+	<true/>
+	<key>NSMainNibFile</key>
+	<string></string>
+	<key>NSMainNibFile~ipad</key>
+	<string></string>
+</dict>
+</plist>

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/ios-config-xml/SampleApp/config.xml
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/config.xml b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/config.xml
new file mode 100644
index 0000000..f0a823b
--- /dev/null
+++ b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/config.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+#
+# 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.
+#
+-->
+<widget>
+    <preference name="KeyboardDisplayRequiresUserAction" value="true" />
+    <preference name="SuppressesIncrementalRendering" value="false" />
+    <preference name="UIWebViewBounce" value="true" />
+    <preference name="TopActivityIndicator" value="gray" />
+    <preference name="EnableLocation" value="false" />
+    <preference name="EnableViewportScale" value="false" />
+    <preference name="AutoHideSplashScreen" value="true" />
+    <preference name="ShowSplashScreenSpinner" value="true" />
+    <preference name="MediaPlaybackRequiresUserAction" value="false" />
+    <preference name="AllowInlineMediaPlayback" value="false" />
+    <preference name="OpenAllWhitelistURLsInWebView" value="false" />
+    <preference name="BackupWebStorage" value="cloud" />
+
+    <plugins>
+        <plugin name="Device" value="CDVDevice" />
+        <plugin name="Logger" value="CDVLogger" />
+        <plugin name="Compass" value="CDVLocation" />
+        <plugin name="Accelerometer" value="CDVAccelerometer" />
+        <plugin name="Camera" value="CDVCamera" />
+        <plugin name="NetworkStatus" value="CDVConnection" />
+        <plugin name="org.apache.cordova.core.contacts" value="CDVContacts" />
+        <plugin name="Debug Console" value="CDVDebugConsole" />
+        <plugin name="Echo" value="CDVEcho" />
+        <plugin name="File" value="CDVFile" />
+        <plugin name="FileTransfer" value="CDVFileTransfer" />
+        <plugin name="Geolocation" value="CDVLocation" />
+        <plugin name="Notification" value="CDVNotification" />
+        <plugin name="Media" value="CDVSound" />
+        <plugin name="Capture" value="CDVCapture" />
+        <plugin name="SplashScreen" value="CDVSplashScreen" />
+        <plugin name="Battery" value="CDVBattery" />
+        <plugin name="Globalization" value="CDVGlobalization" />
+        <plugin name="InAppBrowser" value="CDVInAppBrowser" />
+    </plugins>
+
+    <access origin="*" />
+</widget>

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/ios-config-xml/www/.gitkeep
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/ios-config-xml/www/.gitkeep b/tests/spec/unit/fixtures/ios-config-xml/www/.gitkeep
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/plugin.xml
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/plugin.xml b/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/plugin.xml
new file mode 100644
index 0000000..6db8426
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/plugin.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright 2013 Anis Kadri
+
+ Licensed 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.
+
+-->
+
+<plugin xmlns="http://cordova.apache.org/ns/plugins/1.0"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    id="org.test.plugins.dummyplugin"
+    version="0.6.0">
+
+    <!-- new requirement: NO SPACES -->
+    <name>dummyplugin</name>
+    <!-- These are going to be required by plugman-registry -->
+    <description>my description</description>
+    <author>Jackson Badman</author>
+    <keywords>dummy,plugin</keywords>
+    <license>BSD</license>
+    <!-- end plugman-registry requirements -->
+
+    <asset src="www/dummyplugin.js" target="dummyplugin.js" />
+    <asset src="www/dummyplugin" target="dummyplugin" />
+
+    <config-file target="config.xml" parent="/*">
+        <access origin="build.phonegap.com" />
+        <access origin="s3.amazonaws.com" />
+    </config-file>
+
+    <!-- ios -->
+    <platform name="ios">
+        <!-- CDV 2.5+ -->
+        <config-file target="config.xml" parent="/widget/plugins">
+            <plugin name="org.test.plugins.dummyplugin"
+                value="DummyPluginCommand"/>
+        </config-file>
+
+        <resource-file src="src/ios/DummyPlugin.bundle" />
+
+        <header-file src="src/ios/DummyPluginCommand.h" />
+        <source-file src="src/ios/DummyPluginCommand.m"/>
+
+        <source-file src="src/ios/SourceWithFramework.m" framework="true" />
+
+        <header-file src="src/ios/TargetDirTest.h" target-dir="targetDir" />
+        <source-file src="src/ios/TargetDirTest.m" target-dir="targetDir" />
+
+        <!-- framework for testing (not actual dependency of org.test.plugins.dummyplugin -->
+        <framework src="src/ios/libsqlite3.dylib" />
+        <framework src="src/ios/libsqlite3.dylib" weak="true" />
+        <framework src="src/ios/Custom.framework" custom="true" />
+    </platform>
+</plugin>

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/Custom.framework/someFheader.h
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/Custom.framework/someFheader.h b/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/Custom.framework/someFheader.h
new file mode 100644
index 0000000..fc09fe4
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/Custom.framework/someFheader.h
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/src/ios/Custom.framework/someFheader.h

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/Custom.framework/somebinlib
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/Custom.framework/somebinlib b/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/Custom.framework/somebinlib
new file mode 100644
index 0000000..9e93c21
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/Custom.framework/somebinlib
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/src/ios/Custom.framework/somebinlib

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/DummyPlugin.bundle
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/DummyPlugin.bundle b/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/DummyPlugin.bundle
new file mode 100644
index 0000000..70cd334
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/DummyPlugin.bundle
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/src/ios/DummyPlugin.bundle

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/DummyPluginCommand.h
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/DummyPluginCommand.h b/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/DummyPluginCommand.h
new file mode 100644
index 0000000..2d8fb01
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/DummyPluginCommand.h
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/src/ios/DummyPluginCommand.h

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/DummyPluginCommand.m
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/DummyPluginCommand.m b/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/DummyPluginCommand.m
new file mode 100644
index 0000000..51cd929
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/DummyPluginCommand.m
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/src/ios/DummyPluginCommand.m

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/SourceWithFramework.m
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/SourceWithFramework.m b/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/SourceWithFramework.m
new file mode 100644
index 0000000..de7b1d7
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/SourceWithFramework.m
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/src/ios/SourceWithFramework.m

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/TargetDirTest.h
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/TargetDirTest.h b/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/TargetDirTest.h
new file mode 100644
index 0000000..a83006f
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/TargetDirTest.h
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/src/ios/TargetDirTest.h

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/TargetDirTest.m
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/TargetDirTest.m b/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/TargetDirTest.m
new file mode 100644
index 0000000..95f2620
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/TargetDirTest.m
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/src/ios/TargetDirTest.m

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/libsqlite3.dylib
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/libsqlite3.dylib b/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/libsqlite3.dylib
new file mode 100644
index 0000000..fd3be07
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/src/ios/libsqlite3.dylib
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/src/ios/libsqlite3.dylib

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/www/dummyplugin.js
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/www/dummyplugin.js b/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/www/dummyplugin.js
new file mode 100644
index 0000000..631d6da
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/www/dummyplugin.js
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/www/dummyplugin.js

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/www/dummyplugin/image.jpg
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/www/dummyplugin/image.jpg b/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/www/dummyplugin/image.jpg
new file mode 100644
index 0000000..219c78a
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.dummyplugin/www/dummyplugin/image.jpg
@@ -0,0 +1 @@
+./org.test.plugins.dummyplugin/www/dummyplugin/image.jpg

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.faultyplugin/plugin.xml
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.faultyplugin/plugin.xml b/tests/spec/unit/fixtures/org.test.plugins.faultyplugin/plugin.xml
new file mode 100644
index 0000000..6e8a4d7
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.faultyplugin/plugin.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright 2013 Anis Kadri
+
+ Licensed 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.
+
+-->
+
+<plugin xmlns="http://cordova.apache.org/ns/plugins/1.0"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    id="org.test.plugins.faultyplugin"
+    version="0.6.0">
+
+    <name>Faulty Plugin</name>
+
+    <access origin="build.phonegap.com" />
+    <access origin="s3.amazonaws.com" />
+    <!-- file doesn't exist -->
+
+    <config-file target="config.xml" parent="/widget">
+        <asset src="www/main.js" target="faultyplugin/main.js" />
+        <asset src="www/index.js" target="faultyplugin/index.js" />
+    </config-file>
+
+    <!-- ios -->
+    <platform name="ios">
+        <!-- /cordova/plugins no longer exists, it is now /widget/plugins -->
+        <!-- this should fail to install on ios -->
+        <config-file target="config.xml" parent="/cordova/plugins">
+            <plugin name="org.test.plugins.faultyplugin"
+                value="org.test.plugins.faultyplugin"/>
+        </config-file>
+
+        <header-file src="src/ios/org.test.plugins.faultyplugin.h" />
+        <source-file src="src/ios/org.test.plugins.faultyplugin.m" />
+        <!-- these files don't exist -->
+        <header-file src="src/ios/FaultyPluginCommand.h" />
+        <source-file src="src/ios/FaultyPluginCommand.m" />
+        <resource-file src="src/ios/IDontExist.bundle" />
+        <framework src="src/ios/Nopers.lib" />
+        <framework src="src/ios/NonExistantCustomFramework.framework" custom="true" />
+    </platform>
+</plugin>

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.faultyplugin/src/ios/FaultyPlugin.h
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.faultyplugin/src/ios/FaultyPlugin.h b/tests/spec/unit/fixtures/org.test.plugins.faultyplugin/src/ios/FaultyPlugin.h
new file mode 100644
index 0000000..bf9cf91
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.faultyplugin/src/ios/FaultyPlugin.h
@@ -0,0 +1 @@
+./org.test.plugins.faultyplugin/src/ios/org.test.plugins.faultyplugin.h

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.faultyplugin/src/ios/FaultyPlugin.m
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.faultyplugin/src/ios/FaultyPlugin.m b/tests/spec/unit/fixtures/org.test.plugins.faultyplugin/src/ios/FaultyPlugin.m
new file mode 100644
index 0000000..a8971cd
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.faultyplugin/src/ios/FaultyPlugin.m
@@ -0,0 +1 @@
+./org.test.plugins.faultyplugin/src/ios/org.test.plugins.faultyplugin.m

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/plugin.xml
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/plugin.xml b/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/plugin.xml
new file mode 100644
index 0000000..0f3cfac
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/plugin.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright 2013 Anis Kadri
+
+ Licensed 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.
+
+-->
+
+<plugin xmlns="http://cordova.apache.org/ns/plugins/1.0"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    id="org.test.plugins.weblessplugin"
+    version="0.6.0">
+
+    <name>Webless Plugin</name>
+
+    <config-file target="config.xml" parent="/*">
+        <access origin="build.phonegap.com" />
+        <access origin="s3.amazonaws.com" />
+    </config-file>
+
+    <!-- ios -->
+    <platform name="ios">
+        <!-- CDV 2.4 had a /cordova/plugins instead of /widget/plugins so ignored! -->
+        <!-- CDV 2.5+ -->
+        <config-file target="config.xml" parent="/widget/plugins">
+            <plugin name="org.test.plugins.weblessplugin"
+                value="WeblessPluginCommand"/>
+        </config-file>
+
+        <resource-file src="src/ios/WeblessPlugin.bundle" />
+        <resource-file src="src/ios/WeblessPluginViewController.xib" />
+
+        <header-file src="src/ios/WeblessPluginCommand.h" />
+        <header-file src="src/ios/WeblessPluginViewController.h" />
+
+        <source-file src="src/ios/WeblessPluginCommand.m" />
+        <source-file src="src/ios/WeblessPluginViewController.m" />
+
+        <!-- framework for testing (not actual dependency of org.test.plugins.weblessplugin -->
+        <framework src="libsqlite3.dylib" />
+    </platform>
+</plugin>

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/arrow_left.png
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/arrow_left.png b/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/arrow_left.png
new file mode 100644
index 0000000..28daba3
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/arrow_left.png
@@ -0,0 +1 @@
+./org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/arrow_left.png

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/arrow_left@2x.png
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/arrow_left@2x.png b/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/arrow_left@2x.png
new file mode 100644
index 0000000..7da870b
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/arrow_left@2x.png
@@ -0,0 +1 @@
+./org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/arrow_left@2x.png

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/arrow_right.png
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/arrow_right.png b/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/arrow_right.png
new file mode 100644
index 0000000..31ae8e3
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/arrow_right.png
@@ -0,0 +1 @@
+./org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/arrow_right.png

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/arrow_right@2x.png
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/arrow_right@2x.png b/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/arrow_right@2x.png
new file mode 100644
index 0000000..8e11f04
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/arrow_right@2x.png
@@ -0,0 +1 @@
+./org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/arrow_right@2x.png

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/but_refresh.png
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/but_refresh.png b/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/but_refresh.png
new file mode 100644
index 0000000..15947aa
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/but_refresh.png
@@ -0,0 +1 @@
+./org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/but_refresh.png

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/but_refresh@2x.png
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/but_refresh@2x.png b/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/but_refresh@2x.png
new file mode 100644
index 0000000..f6cb35b
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/but_refresh@2x.png
@@ -0,0 +1 @@
+./org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/but_refresh@2x.png

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/compass.png
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/compass.png b/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/compass.png
new file mode 100644
index 0000000..4386959
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/compass.png
@@ -0,0 +1 @@
+./org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/compass.png

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/compass@2x.png
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/compass@2x.png b/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/compass@2x.png
new file mode 100644
index 0000000..73148c6
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/compass@2x.png
@@ -0,0 +1 @@
+./org.test.plugins.weblessplugin/src/ios/WeblessPlugin.bundle/compass@2x.png

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPluginCommand.h
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPluginCommand.h b/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPluginCommand.h
new file mode 100644
index 0000000..57cbdb9
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPluginCommand.h
@@ -0,0 +1 @@
+./org.test.plugins.weblessplugin/src/ios/WeblessPluginCommand.h

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPluginCommand.m
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPluginCommand.m b/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPluginCommand.m
new file mode 100644
index 0000000..097f7f8
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPluginCommand.m
@@ -0,0 +1 @@
+./org.test.plugins.weblessplugin/src/ios/WeblessPluginCommand.m

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPluginViewController.h
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPluginViewController.h b/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPluginViewController.h
new file mode 100644
index 0000000..f052697
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPluginViewController.h
@@ -0,0 +1 @@
+./org.test.plugins.weblessplugin/src/ios/WeblessPluginViewController.h

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPluginViewController.m
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPluginViewController.m b/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPluginViewController.m
new file mode 100644
index 0000000..bbaf3af
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPluginViewController.m
@@ -0,0 +1 @@
+./org.test.plugins.weblessplugin/src/ios/WeblessPluginViewController.m

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPluginViewController.xib
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPluginViewController.xib b/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPluginViewController.xib
new file mode 100644
index 0000000..97e3629
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.weblessplugin/src/ios/WeblessPluginViewController.xib
@@ -0,0 +1 @@
+./org.test.plugins.weblessplugin/src/ios/WeblessPluginViewController.xib

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/test-config-2.xml
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/test-config-2.xml b/tests/spec/unit/fixtures/test-config-2.xml
new file mode 100644
index 0000000..c756d4e
--- /dev/null
+++ b/tests/spec/unit/fixtures/test-config-2.xml
@@ -0,0 +1,22 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget android-packageName="io.cordova.hellocordova.android" id="io.cordova.hellocordova" ios-CFBundleIdentifier="io.cordova.hellocordova.ios" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+    <name>Hello Cordova</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" />
+
+    <platform name="ios">
+        <preference name="orientation" value="all" />
+    </platform>
+
+    <access origin="http://*.apache.org" />
+    <access origin="https://*.apache.org" />
+
+    <allow-navigation href="http://*.apache.org" />
+    <allow-navigation href="https://*.apache.org" />
+     
+</widget>

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/fixtures/test-config.xml
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/test-config.xml b/tests/spec/unit/fixtures/test-config.xml
new file mode 100644
index 0000000..7b4e571
--- /dev/null
+++ b/tests/spec/unit/fixtures/test-config.xml
@@ -0,0 +1,109 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget id="io.cordova.hellocordova" ios-CFBundleIdentifier="io.cordova.hellocordova.ios" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+    <name>Hello Cordova</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> tests
+
+        Test wildcard allow all. Note in ATS you can open up all, and have restrictions for certain domains.
+        This is to allow for example, an in-app-browser (*) but your own server communications must be https, for example.
+     -->
+    <access origin="*" />
+    <!-- https, with subdomain wildcard, with attribute differences -->
+    <access origin="https://*.server01.com" /> <!-- equivalent to the next line -->
+    <access origin="https://*.server01.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="true" />
+    <access origin="https://*.server02.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="false" />
+    <access origin="https://*.server03.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="true" />
+    <access origin="https://*.server04.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="false" />
+    <!-- http, no subdomain wildcard, with attribute differences -->
+    <access origin="http://server05.com" /> <!-- equivalent to the next line -->
+    <access origin="http://server05.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="true" />
+    <access origin="http://server06.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="false" />
+    <access origin="http://server07.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="true" />
+    <access origin="http://server08.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="false" />
+    <!-- https, no subdomain wildcard, with attribute differences -->
+    <access origin="https://server09.com" /> <!-- equivalent to the next line -->
+    <access origin="https://server09.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="true" />
+    <access origin="https://server10.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="false" />
+    <access origin="https://server11.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="true" />
+    <access origin="https://server12.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="false" />
+
+    <!--
+        <allow-navigation> tests
+
+        Test wildcard allow all. Note in ATS you can open up all, and have restrictions for certain domains.
+        This is to allow for example, an in-app-browser (*) but your own server communications must be https, for example.
+     -->
+    <allow-navigation href="*" />
+    <!-- https, with subdomain wildcard, attribute differences -->
+    <allow-navigation href="https://*.server21.com" /> <!-- equivalent to the next line -->
+    <allow-navigation href="https://*.server21.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="true" />
+    <allow-navigation href="https://*.server22.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="false" />
+    <allow-navigation href="https://*.server23.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="true" />
+    <allow-navigation href="https://*.server24.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="false" />
+    <!-- http, no subdomain, with attribute differences -->
+    <allow-navigation href="http://server25.com" /> <!-- equivalent to the next line -->
+    <allow-navigation href="http://server25.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="true" />
+    <allow-navigation href="http://server26.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="false" />
+    <allow-navigation href="http://server27.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="true" />
+    <allow-navigation href="http://server28.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="false" />
+    <!-- https, no subdomain, with attribute differences -->
+    <allow-navigation href="https://server29.com" /> <!-- equivalent to the next line -->
+    <allow-navigation href="https://server29.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="true" />
+    <allow-navigation href="https://server30.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="false" />
+    <allow-navigation href="https://server31.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="true" />
+    <allow-navigation href="https://server32.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="false" />
+    <!-- wildcard scheme, with subdomain wildcard, with attribute differences -->
+    <allow-navigation href="*://*.server33.com" /> <!-- equivalent to the next line -->
+    <allow-navigation href="*://*.server33.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="true" />
+    <allow-navigation href="*://*.server34.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="false" />
+    <allow-navigation href="*://*.server35.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="true" />
+    <allow-navigation href="*://*.server36.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="false" />
+    <!-- wildcard scheme, no subdomain, with attribute differences -->
+    <allow-navigation href="*://server37.com" /> <!-- equivalent to the next line -->
+    <allow-navigation href="*://server37.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="true" />
+    <allow-navigation href="*://server38.com" minimum-tls-version="TLSv1.2" requires-forward-secrecy="false" />
+    <allow-navigation href="*://server39.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="true" />
+    <allow-navigation href="*://server40.com" minimum-tls-version="TLSv1.1" requires-forward-secrecy="false" />
+
+    <!-- https://issues.apache.org/jira/browse/CB-9758 Mobilespec crashes adding plugins on OS X -->
+    <allow-navigation href="data:*" />
+    <allow-navigation href="http:*" />
+    <allow-navigation href="https:*" />
+    <allow-navigation href="http://*" />
+    <allow-navigation href="https://*" />
+
+    <preference name="fullscreen" value="true" />
+    <preference name="webviewbounce" value="true" />
+    <preference name="orientation" value="portrait" />
+    <icon id="icon" src="icon.png" />
+    <icon height="255" id="logo" src="logo.png" width="255" />
+    <plugin name="org.apache.cordova.pluginwithvars">
+        <variable name="var" value="varvalue" />
+    </plugin>
+    <plugin name="org.apache.cordova.pluginwithurl" src="http://cordova.apache.org/pluginwithurl" />
+    <plugin name="org.apache.cordova.pluginwithversion" version="1.1.1" />
+    <plugin name="org.apache.cordova.pluginwithurlandversion" src="http://cordova.apache.org/pluginwithurlandversion" version="1.1.1" />
+    <plugin name="org.apache.cordova.justaplugin" />
+    <feature name="Legacy plugin entry with version">
+        <param name="id" value="org.apache.cordova.legacyfeatureversion" />
+        <param name="version" value="1.2.3" />
+        <param name="aVar" value="aValue" />
+    </feature>
+    <feature name="Legacy plugin entry with url">
+        <param name="id" value="org.apache.cordova.legacyfeatureurl" />
+        <param name="url" value="http://cordova.apache.org/legacyfeatureurl" />
+    </feature>
+    <feature name="Legacy plugin entry with version and url">
+        <param name="id" value="org.apache.cordova.legacyfeatureversionandurl" />
+        <param name="version" value="1.2.3" />
+        <param name="url" value="http://cordova.apache.org/legacyfeatureversionandurl" />
+    </feature>
+</widget>


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org


[4/6] ios commit: CB-10769 Copy raw pluginHandler tests from cordova-lib

Posted by an...@apache.org.
CB-10769 Copy raw pluginHandler tests from cordova-lib

Update tests structure and npm tasks
Copying related fixtures from cordova-lib


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

Branch: refs/heads/master
Commit: c0db5e4ecfb4e2afa31fdb277620cc4ebcf7d7f3
Parents: 70e16ef
Author: Vladimir Kotikov <v-...@microsoft.com>
Authored: Thu Mar 3 17:06:19 2016 +0300
Committer: Vladimir Kotikov <v-...@microsoft.com>
Committed: Fri Mar 11 10:12:15 2016 +0300

----------------------------------------------------------------------
 .gitignore                                      |   1 +
 .jshintignore                                   |   1 +
 package.json                                    |   7 +-
 tests/spec/unit/Plugman/common.spec.js          | 195 ++++++
 tests/spec/unit/Plugman/ios.spec.js             | 447 +++++++++++++
 .../CordovaLib.xcodeproj/project.pbxproj        | 636 +++++++++++++++++++
 .../fixtures/ios-config-xml/CordovaLib/VERSION  |   1 +
 .../SampleApp.xcodeproj/project.orig.pbxproj    | 498 +++++++++++++++
 .../SampleApp.xcodeproj/project.pbxproj         | 496 +++++++++++++++
 .../SampleApp/SampleApp-Info.plist              |  86 +++
 .../ios-config-xml/SampleApp/config.xml         |  59 ++
 .../unit/fixtures/ios-config-xml/www/.gitkeep   |   0
 .../org.test.plugins.dummyplugin/plugin.xml     |  66 ++
 .../src/ios/Custom.framework/someFheader.h      |   1 +
 .../src/ios/Custom.framework/somebinlib         |   1 +
 .../src/ios/DummyPlugin.bundle                  |   1 +
 .../src/ios/DummyPluginCommand.h                |   1 +
 .../src/ios/DummyPluginCommand.m                |   1 +
 .../src/ios/SourceWithFramework.m               |   1 +
 .../src/ios/TargetDirTest.h                     |   1 +
 .../src/ios/TargetDirTest.m                     |   1 +
 .../src/ios/libsqlite3.dylib                    |   1 +
 .../www/dummyplugin.js                          |   1 +
 .../www/dummyplugin/image.jpg                   |   1 +
 .../org.test.plugins.faultyplugin/plugin.xml    |  55 ++
 .../src/ios/FaultyPlugin.h                      |   1 +
 .../src/ios/FaultyPlugin.m                      |   1 +
 .../org.test.plugins.weblessplugin/plugin.xml   |  54 ++
 .../src/ios/WeblessPlugin.bundle/arrow_left.png |   1 +
 .../ios/WeblessPlugin.bundle/arrow_left@2x.png  |   1 +
 .../ios/WeblessPlugin.bundle/arrow_right.png    |   1 +
 .../ios/WeblessPlugin.bundle/arrow_right@2x.png |   1 +
 .../ios/WeblessPlugin.bundle/but_refresh.png    |   1 +
 .../ios/WeblessPlugin.bundle/but_refresh@2x.png |   1 +
 .../src/ios/WeblessPlugin.bundle/compass.png    |   1 +
 .../src/ios/WeblessPlugin.bundle/compass@2x.png |   1 +
 .../src/ios/WeblessPluginCommand.h              |   1 +
 .../src/ios/WeblessPluginCommand.m              |   1 +
 .../src/ios/WeblessPluginViewController.h       |   1 +
 .../src/ios/WeblessPluginViewController.m       |   1 +
 .../src/ios/WeblessPluginViewController.xib     |   1 +
 tests/spec/unit/fixtures/test-config-2.xml      |  22 +
 tests/spec/unit/fixtures/test-config.xml        | 109 ++++
 tests/spec/unit/ios_parser.spec.js              | 500 +++++++++++++++
 44 files changed, 3256 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index aff5891..2744ab7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,4 @@ tmp
 xcuserdata
 console.log
 node_modules/
+npm-debug.log
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/.jshintignore
----------------------------------------------------------------------
diff --git a/.jshintignore b/.jshintignore
index e87aa4b..1ec4bc1 100644
--- a/.jshintignore
+++ b/.jshintignore
@@ -1,2 +1,3 @@
 bin/node_modules/*
 bin/templates/project/*
+tests/spec/unit/fixtures/*
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/package.json
----------------------------------------------------------------------
diff --git a/package.json b/package.json
index 447a38e..5f05f17 100644
--- a/package.json
+++ b/package.json
@@ -15,10 +15,10 @@
     "cordova:platform"
   ],
   "scripts": {
-    "test": "npm run jshint && npm run jasmine",
-    "jasmine": "npm run objc-tests && npm run jasmine-tests",
+    "test": "npm run jshint && npm run e2e-tests && npm run objc-tests && npm run unit-tests",
+    "e2e-tests": "jasmine-node --captureExceptions --color tests/spec/create.spec.js",
     "objc-tests": "jasmine-node --captureExceptions --color tests/spec/cordovalib.spec.js",
-    "jasmine-tests": "jasmine-node --captureExceptions --color tests/spec/create.spec.js",
+    "unit-tests": "jasmine-node --captureExceptions --color tests/spec/unit",
     "jshint": "node node_modules/jshint/bin/jshint bin && node node_modules/jshint/bin/jshint tests"
   },
   "author": "Apache Software Foundation",
@@ -29,6 +29,7 @@
     "tmp": "^0.0.26",
     "jasmine-node": "~1",
     "coffee-script": "^1.7.1",
+    "rewire": "^2.5.1",
     "nodeunit": "^0.8.7"
   },
   "dependencies": {

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/Plugman/common.spec.js
----------------------------------------------------------------------
diff --git a/tests/spec/unit/Plugman/common.spec.js b/tests/spec/unit/Plugman/common.spec.js
new file mode 100644
index 0000000..f591193
--- /dev/null
+++ b/tests/spec/unit/Plugman/common.spec.js
@@ -0,0 +1,195 @@
+/*
+ *
+ *
+ * Licensed 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.
+ *
+*/
+
+/* jshint laxcomma:true */
+
+var common = require('../../src/plugman/platforms/common')
+  , path = require('path')
+  , fs = require('fs')
+  , osenv = require('os')
+  , shell = require('shelljs')
+  , test_dir = path.join(osenv.tmpdir(), 'test_plugman')
+  , project_dir = path.join(test_dir, 'project')
+  , src = path.join(project_dir, 'src')
+  , dest = path.join(project_dir, 'dest')
+  , java_dir = path.join(src, 'one', 'two', 'three')
+  , java_file = path.join(java_dir, 'test.java')
+  , symlink_file = path.join(java_dir, 'symlink')
+  , non_plugin_file = path.join(osenv.tmpdir(), 'non_plugin_file');
+
+describe('common platform handler', function() {
+    describe('resolveSrcPath', function() {
+        it('should not throw if path exists', function(){
+            shell.mkdir('-p', test_dir);
+            var target = path.join(test_dir, 'somefile');
+            fs.writeFileSync(target, '80085', 'utf-8');
+            expect(function(){common.resolveSrcPath(test_dir, 'somefile');}).not.toThrow();
+            shell.rm('-rf', test_dir);
+        });
+    });
+
+    describe('resolveTargetPath', function() {
+        it('should throw if path exists', function(){
+            shell.mkdir('-p', test_dir);
+            expect(function(){common.resolveTargetPath(test_dir);}).toThrow();
+            shell.rm('-rf', test_dir);
+        });
+
+        it('should not throw if path cannot be resolved', function(){
+            expect(function(){common.resolveTargetPath(test_dir, 'somefile');}).not.toThrow();
+        });
+    });
+
+    describe('copyFile', function() {
+        it('should throw if source path not found', function(){
+            expect(function(){common.copyFile(test_dir, src, project_dir, dest);}).
+                toThrow(new Error('"' + src + '" not found!'));
+        });
+
+        it('should throw if src not in plugin directory', function(){
+            shell.mkdir('-p', project_dir);
+            fs.writeFileSync(non_plugin_file, 'contents', 'utf-8');
+            expect(function(){common.copyFile(test_dir, '../non_plugin_file', project_dir, dest);}).
+                toThrow(new Error('"' + non_plugin_file + '" not located within plugin!'));
+            shell.rm('-rf', test_dir);
+        });
+
+        it('should allow symlink src, if inside plugin', function(){
+            shell.mkdir('-p', java_dir);
+            fs.writeFileSync(java_file, 'contents', 'utf-8');
+
+            // This will fail on windows if not admin - ignore the error in that case.
+            if (ignoreEPERMonWin32(java_file, symlink_file)) {
+                return;
+            }
+
+            common.copyFile(test_dir, symlink_file, project_dir, dest);
+            shell.rm('-rf', project_dir);
+        });
+
+        it('should throw if symlink is linked to a file outside the plugin', function(){
+            shell.mkdir('-p', java_dir);
+            fs.writeFileSync(non_plugin_file, 'contents', 'utf-8');
+
+            // This will fail on windows if not admin - ignore the error in that case.
+            if (ignoreEPERMonWin32(non_plugin_file, symlink_file)) {
+                return;
+            }
+
+            expect(function(){common.copyFile(test_dir, symlink_file, project_dir, dest);}).
+                toThrow(new Error('"' + symlink_file + '" not located within plugin!'));
+            shell.rm('-rf', project_dir);
+        });
+
+        it('should throw if dest is outside the project directory', function(){
+            shell.mkdir('-p', java_dir);
+            fs.writeFileSync(java_file, 'contents', 'utf-8');
+            expect(function(){common.copyFile(test_dir, java_file, project_dir, non_plugin_file);}).
+                toThrow(new Error('"' + non_plugin_file + '" not located within project!'));
+            shell.rm('-rf', project_dir);
+        });
+
+        it('should call mkdir -p on target path', function(){
+            shell.mkdir('-p', java_dir);
+            fs.writeFileSync(java_file, 'contents', 'utf-8');
+
+            var s = spyOn(shell, 'mkdir').andCallThrough();
+            var resolvedDest = common.resolveTargetPath(project_dir, dest);
+
+            common.copyFile(test_dir, java_file, project_dir, dest);
+
+            expect(s).toHaveBeenCalled();
+            expect(s).toHaveBeenCalledWith('-p', path.dirname(resolvedDest));
+            shell.rm('-rf', project_dir);
+        });
+
+        it('should call cp source/dest paths', function(){
+            shell.mkdir('-p', java_dir);
+            fs.writeFileSync(java_file, 'contents', 'utf-8');
+
+            var s = spyOn(shell, 'cp').andCallThrough();
+            var resolvedDest = common.resolveTargetPath(project_dir, dest);
+
+            common.copyFile(test_dir, java_file, project_dir, dest);
+
+            expect(s).toHaveBeenCalled();
+            expect(s).toHaveBeenCalledWith('-f', java_file, resolvedDest);
+
+            shell.rm('-rf', project_dir);
+        });
+
+    });
+
+    describe('copyNewFile', function () {
+        it('should throw if target path exists', function(){
+            shell.mkdir('-p', dest);
+            expect(function(){common.copyNewFile(test_dir, src, project_dir, dest);}).
+                toThrow(new Error('"' + dest + '" already exists!'));
+            shell.rm('-rf', dest);
+        });
+
+    });
+
+    describe('deleteJava', function() {
+        it('should call fs.unlinkSync on the provided paths', function(){
+            shell.mkdir('-p', java_dir);
+            fs.writeFileSync(java_file, 'contents', 'utf-8');
+
+            var s = spyOn(fs, 'unlinkSync').andCallThrough();
+            common.deleteJava(project_dir, java_file);
+            expect(s).toHaveBeenCalled();
+            expect(s).toHaveBeenCalledWith(path.resolve(project_dir, java_file));
+
+            shell.rm('-rf', java_dir);
+        });
+
+        it('should delete empty directories after removing source code in a java src path hierarchy', function(){
+            shell.mkdir('-p', java_dir);
+            fs.writeFileSync(java_file, 'contents', 'utf-8');
+
+            common.deleteJava(project_dir, java_file);
+            expect(fs.existsSync(java_file)).not.toBe(true);
+            expect(fs.existsSync(java_dir)).not.toBe(true);
+            expect(fs.existsSync(path.join(src,'one'))).not.toBe(true);
+
+            shell.rm('-rf', java_dir);
+        });
+
+        it('should never delete the top-level src directory, even if all plugins added were removed', function(){
+            shell.mkdir('-p', java_dir);
+            fs.writeFileSync(java_file, 'contents', 'utf-8');
+
+            common.deleteJava(project_dir, java_file);
+            expect(fs.existsSync(src)).toBe(true);
+
+            shell.rm('-rf', java_dir);
+        });
+    });
+});
+
+function ignoreEPERMonWin32(symlink_src, symlink_dest) {
+    try {
+        fs.symlinkSync(symlink_src, symlink_dest);
+    } catch (e) {
+        if (process.platform === 'win32' && e.message.indexOf('Error: EPERM, operation not permitted' > -1)) {
+            return true;
+        }
+        throw e;
+    }
+    return false;
+}

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/c0db5e4e/tests/spec/unit/Plugman/ios.spec.js
----------------------------------------------------------------------
diff --git a/tests/spec/unit/Plugman/ios.spec.js b/tests/spec/unit/Plugman/ios.spec.js
new file mode 100644
index 0000000..7c245bd
--- /dev/null
+++ b/tests/spec/unit/Plugman/ios.spec.js
@@ -0,0 +1,447 @@
+/**
+    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.
+*/
+
+/* jshint sub:true */
+
+var ios = require('../../src/plugman/platforms/ios'),
+    install = require('../../src/plugman/install'),
+    path = require('path'),
+    fs = require('fs'),
+    shell = require('shelljs'),
+    os = require('os'),
+    temp = path.join(os.tmpdir(), 'plugman'),
+    plugins_dir = path.join(temp, 'cordova', 'plugins'),
+    ios_config_xml_project = path.join(__dirname, '..', 'projects', 'ios-config-xml', '*'),
+    ios_project = path.join(ios_config_xml_project, '..'),
+    faultyplugin = path.join(__dirname, '..', 'plugins', 'org.test.plugins.faultyplugin'),
+    dummyplugin = path.join(__dirname, '..', 'plugins', 'org.test.plugins.dummyplugin'),
+    weblessplugin = path.join(__dirname, '..', 'plugins', 'org.test.plugins.weblessplugin'),
+    done = false;
+
+var PluginInfo = require('cordova-common').PluginInfo;
+
+var dummyPluginInfo = new PluginInfo(dummyplugin);
+var dummy_id = dummyPluginInfo.id;
+var valid_source = dummyPluginInfo.getSourceFiles('ios'),
+    valid_headers = dummyPluginInfo.getHeaderFiles('ios'),
+    valid_resources = dummyPluginInfo.getResourceFiles('ios'),
+    valid_custom_frameworks = dummyPluginInfo.getFrameworks('ios').filter(function(f) { return f.custom; });
+
+var faultyPluginInfo = new PluginInfo(faultyplugin);
+var faulty_id = faultyPluginInfo.id;
+
+var invalid_source = faultyPluginInfo.getSourceFiles('ios');
+var invalid_headers = faultyPluginInfo.getHeaderFiles('ios');
+var invalid_resources = faultyPluginInfo.getResourceFiles('ios');
+var invalid_custom_frameworks = faultyPluginInfo.getFrameworks('ios').filter(function(f) { return f.custom; });
+
+shell.mkdir('-p', temp);
+shell.cp('-rf', ios_config_xml_project, temp);
+var proj_files = ios.parseProjectFile(temp);
+shell.rm('-rf', temp);
+ios.purgeProjectFileCache(temp);
+
+function copyArray(arr) {
+    return Array.prototype.slice.call(arr, 0);
+}
+
+function installPromise(f) {
+    f.then(function(res) { done = true; }, function(err) { done = err; });
+}
+
+function slashJoin() {
+    // In some places we need to use forward slash instead of path.join().
+    // See CB-7311.
+    return Array.prototype.join.call(arguments, '/');
+}
+
+describe('ios project handler', function() {
+    beforeEach(function() {
+        shell.mkdir('-p', temp);
+        shell.mkdir('-p', plugins_dir);
+    });
+    afterEach(function() {
+        shell.rm('-rf', temp);
+        ios.purgeProjectFileCache(temp);
+    });
+
+    describe('www_dir method', function() {
+        it('should return cordova-ios project www location using www_dir', function() {
+            expect(ios.www_dir(path.sep)).toEqual(path.sep + 'www');
+        });
+    });
+
+    describe('package_name method', function() {
+        it('should return the CFBundleIdentifier from the project\'s Info.plist file', function() {
+            expect(ios.package_name(ios_project)).toEqual('com.example.friendstring');
+        });
+    });
+
+    describe('parseProjectFile method', function () {
+        it('should throw if project is not an xcode project', function() {
+            expect(function() {
+                ios.parseProjectFile(temp);
+            }).toThrow('does not appear to be an xcode project (no xcode project file)');
+        });
+        it('should throw if project does not contain an appropriate config.xml file', function() {
+            shell.cp('-rf', ios_config_xml_project, temp);
+            shell.rm(path.join(temp, 'SampleApp', 'config.xml'));
+
+            expect(function() {
+                ios.parseProjectFile(temp);
+            }).toThrow('could not find -Info.plist file, or config.xml file.');
+        });
+        it('should throw if project does not contain an appropriate -Info.plist file', function() {
+            shell.cp('-rf', ios_config_xml_project, temp);
+            shell.rm(path.join(temp, 'SampleApp', 'SampleApp-Info.plist'));
+
+            expect(function () {
+                ios.parseProjectFile(temp);
+            }).toThrow('could not find -Info.plist file, or config.xml file.');
+        });
+        it('should return right directory when multiple .plist files are present', function() {
+            shell.cp('-rf', ios_config_xml_project, temp);
+            //Create a folder named A with config.xml and .plist files in it
+            var pathToFolderA = path.join(temp, 'A');
+            shell.mkdir(pathToFolderA);
+            shell.cp('-rf', path.join(temp, 'SampleApp/*'), pathToFolderA);
+
+            var parsedProjectFile = ios.parseProjectFile(temp);
+            var pluginsDir = parsedProjectFile.plugins_dir,
+                resourcesDir = parsedProjectFile.resources_dir,
+                xcodePath = parsedProjectFile.xcode_path;
+
+            var pluginsDirParent = path.dirname(pluginsDir),
+                resourcesDirParent = path.dirname(resourcesDir),
+                sampleAppDir = path.join(temp, 'SampleApp');
+
+            expect(pluginsDirParent).toEqual(sampleAppDir);
+            expect(resourcesDirParent).toEqual(sampleAppDir);
+            expect(xcodePath).toEqual(sampleAppDir);
+        });
+    });
+
+    describe('installation', function() {
+        beforeEach(function() {
+            shell.cp('-rf', ios_config_xml_project, temp);
+            done = false;
+        });
+
+        describe('of <source-file> elements', function() {
+            it('should throw if source-file src cannot be found', function() {
+                var source = copyArray(invalid_source);
+                expect(function() {
+                    ios['source-file'].install(source[1], faultyplugin, temp, faulty_id, null, proj_files);
+                }).toThrow();
+            });
+            it('should throw if source-file target already exists', function() {
+                var source = copyArray(valid_source);
+                var target = path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'DummyPluginCommand.m');
+                shell.mkdir('-p', path.dirname(target));
+                fs.writeFileSync(target, 'some bs', 'utf-8');
+                expect(function() {
+                    ios['source-file'].install(source[0], dummyplugin, temp, dummy_id, null, proj_files);
+                }).toThrow();
+            });
+            it('should call into xcodeproj\'s addSourceFile appropriately when element has no target-dir', function() {
+                var source = copyArray(valid_source).filter(function(s) { return s.targetDir === undefined; });
+                var spy = spyOn(proj_files.xcode, 'addSourceFile');
+                ios['source-file'].install(source[0], dummyplugin, temp, dummy_id, null, proj_files);
+                expect(spy).toHaveBeenCalledWith(slashJoin('Plugins', dummy_id, 'DummyPluginCommand.m'), {});
+            });
+            it('should call into xcodeproj\'s addSourceFile appropriately when element has a target-dir', function() {
+                var source = copyArray(valid_source).filter(function(s) { return s.targetDir !== undefined; });
+                var spy = spyOn(proj_files.xcode, 'addSourceFile');
+                ios['source-file'].install(source[0], dummyplugin, temp, dummy_id, null, proj_files);
+                expect(spy).toHaveBeenCalledWith(slashJoin('Plugins', dummy_id, 'targetDir', 'TargetDirTest.m'), {});
+            });
+            it('should cp the file to the right target location when element has no target-dir', function() {
+                var source = copyArray(valid_source).filter(function(s) { return s.targetDir === undefined; });
+                var spy = spyOn(shell, 'cp');
+                ios['source-file'].install(source[0], dummyplugin, temp, dummy_id, null, proj_files);
+                expect(spy).toHaveBeenCalledWith('-f', path.join(dummyplugin, 'src', 'ios', 'DummyPluginCommand.m'), path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'DummyPluginCommand.m'));
+            });
+            it('should cp the file to the right target location when element has a target-dir', function() {
+                var source = copyArray(valid_source).filter(function(s) { return s.targetDir !== undefined; });
+                var spy = spyOn(shell, 'cp');
+                ios['source-file'].install(source[0], dummyplugin, temp, dummy_id, null, proj_files);
+                expect(spy).toHaveBeenCalledWith('-f', path.join(dummyplugin, 'src', 'ios', 'TargetDirTest.m'), path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'targetDir', 'TargetDirTest.m'));
+            });
+            it('should call into xcodeproj\'s addFramework appropriately when element has framework=true set', function() {
+                var source = copyArray(valid_source).filter(function(s) { return s.framework; });
+                spyOn(proj_files.xcode, 'addSourceFile');
+                var spy = spyOn(proj_files.xcode, 'addFramework');
+                ios['source-file'].install(source[0], dummyplugin, temp, dummy_id, null, proj_files);
+                expect(spy).toHaveBeenCalledWith(path.join('SampleApp', 'Plugins', dummy_id, 'SourceWithFramework.m'), {weak:false});
+            });
+        });
+
+        describe('of <header-file> elements', function() {
+            it('should throw if header-file src cannot be found', function() {
+                var headers = copyArray(invalid_headers);
+                expect(function() {
+                    ios['header-file'].install(headers[1], faultyplugin, temp, faulty_id, null, proj_files);
+                }).toThrow();
+            });
+            it('should throw if header-file target already exists', function() {
+                var headers = copyArray(valid_headers);
+                var target = path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'DummyPluginCommand.h');
+                shell.mkdir('-p', path.dirname(target));
+                fs.writeFileSync(target, 'some bs', 'utf-8');
+                expect(function() {
+                    ios['header-file'].install(headers[0], dummyplugin, temp, dummy_id, null, proj_files);
+                }).toThrow();
+            });
+            it('should call into xcodeproj\'s addHeaderFile appropriately when element has no target-dir', function() {
+                var headers = copyArray(valid_headers).filter(function(s) { return s.targetDir === undefined; });
+                var spy = spyOn(proj_files.xcode, 'addHeaderFile');
+                ios['header-file'].install(headers[0], dummyplugin, temp, dummy_id,  null, proj_files);
+                expect(spy).toHaveBeenCalledWith(slashJoin('Plugins', dummy_id, 'DummyPluginCommand.h'));
+            });
+            it('should call into xcodeproj\'s addHeaderFile appropriately when element a target-dir', function() {
+                var headers = copyArray(valid_headers).filter(function(s) { return s.targetDir !== undefined; });
+                var spy = spyOn(proj_files.xcode, 'addHeaderFile');
+                ios['header-file'].install(headers[0], dummyplugin, temp, dummy_id, null, proj_files);
+                expect(spy).toHaveBeenCalledWith(slashJoin('Plugins', dummy_id, 'targetDir', 'TargetDirTest.h'));
+            });
+            it('should cp the file to the right target location when element has no target-dir', function() {
+                var headers = copyArray(valid_headers).filter(function(s) { return s.targetDir === undefined; });
+                var spy = spyOn(shell, 'cp');
+                ios['header-file'].install(headers[0], dummyplugin, temp, dummy_id, null, proj_files);
+                expect(spy).toHaveBeenCalledWith('-f', path.join(dummyplugin, 'src', 'ios', 'DummyPluginCommand.h'), path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'DummyPluginCommand.h'));
+            });
+            it('should cp the file to the right target location when element has a target-dir', function() {
+                var headers = copyArray(valid_headers).filter(function(s) { return s.targetDir !== undefined; });
+                var spy = spyOn(shell, 'cp');
+                ios['header-file'].install(headers[0], dummyplugin, temp, dummy_id, null, proj_files);
+                expect(spy).toHaveBeenCalledWith('-f', path.join(dummyplugin, 'src', 'ios', 'TargetDirTest.h'), path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'targetDir', 'TargetDirTest.h'));
+            });
+        });
+
+        describe('of <resource-file> elements', function() {
+            it('should throw if resource-file src cannot be found', function() {
+                var resources = copyArray(invalid_resources);
+                expect(function() {
+                    ios['resource-file'].install(resources[0], faultyplugin, temp, 'pluginid', null, proj_files);
+                }).toThrow('cannot find "' + path.resolve(faultyplugin, 'src/ios/IDontExist.bundle') + '" ios <resource-file>');
+            });
+            it('should throw if resource-file target already exists', function() {
+                var resources = copyArray(valid_resources);
+                var target = path.join(temp, 'SampleApp', 'Resources', 'DummyPlugin.bundle');
+                shell.mkdir('-p', path.dirname(target));
+                fs.writeFileSync(target, 'some bs', 'utf-8');
+                expect(function() {
+                    ios['resource-file'].install(resources[0], dummyplugin, temp, 'pluginid',null, proj_files);
+                }).toThrow('target destination "' + target + '" already exists');
+            });
+            it('should call into xcodeproj\'s addResourceFile', function() {
+                var resources = copyArray(valid_resources);
+                var spy = spyOn(proj_files.xcode, 'addResourceFile');
+                ios['resource-file'].install(resources[0], dummyplugin, temp, 'pluginid', null, proj_files);
+                expect(spy).toHaveBeenCalledWith(path.join('Resources', 'DummyPlugin.bundle'));
+            });
+            it('should cp the file to the right target location', function() {
+                var resources = copyArray(valid_resources);
+                var spy = spyOn(shell, 'cp');
+                ios['resource-file'].install(resources[0], dummyplugin, temp, 'pluginid', null, proj_files);
+                expect(spy).toHaveBeenCalledWith('-R', path.join(dummyplugin, 'src', 'ios', 'DummyPlugin.bundle'), path.join(temp, 'SampleApp', 'Resources'));
+            });
+        });
+        describe('of <framework> elements', function() {
+
+            it('should call into xcodeproj\'s addFramework', function() {
+                var frameworks = copyArray(valid_custom_frameworks);
+                var spy = spyOn(proj_files.xcode, 'addFramework');
+                ios['framework'].install(frameworks[0], dummyplugin, temp, dummy_id, null, proj_files);
+                expect(spy).toHaveBeenCalledWith(path.normalize('SampleApp/Plugins/org.test.plugins.dummyplugin/Custom.framework'), {customFramework:true});
+            });
+
+            // TODO: Add more tests to cover the cases:
+            // * framework with weak attribute
+            // * framework that shouldn't be added/removed
+
+            describe('with custom="true" attribute', function () {
+                it('should throw if framework src cannot be found', function() {
+                    var frameworks = copyArray(invalid_custom_frameworks);
+                    expect(function() {
+                        ios['framework'].install(frameworks[0], faultyplugin, temp, dummy_id, null, proj_files);
+                    }).toThrow('cannot find "' + path.resolve(faultyplugin, 'src/ios/NonExistantCustomFramework.framework') + '" ios <framework>');
+                });
+                it('should throw if framework target already exists', function() {
+                    var frameworks = copyArray(valid_custom_frameworks);
+                    var target = path.join(temp, 'SampleApp/Plugins/org.test.plugins.dummyplugin/Custom.framework');
+                    shell.mkdir('-p', target);
+                    expect(function() {
+                        ios['framework'].install(frameworks[0], dummyplugin, temp, dummy_id, null, proj_files);
+                    }).toThrow('target destination "' + target + '" already exists');
+                });
+                it('should cp the file to the right target location', function() {
+                    var frameworks = copyArray(valid_custom_frameworks);
+                    var spy = spyOn(shell, 'cp');
+                    ios['framework'].install(frameworks[0], dummyplugin, temp, dummy_id, null, proj_files);
+                    expect(spy).toHaveBeenCalledWith('-R', path.join(dummyplugin, 'src', 'ios', 'Custom.framework'),
+                                                     path.join(temp, 'SampleApp/Plugins/org.test.plugins.dummyplugin'));
+                });
+            });
+        });
+        it('of two plugins should apply xcode file changes from both', function(){
+            runs(function() {
+                installPromise(
+                    install('ios', temp, dummyplugin)
+                    .then(function () { install('ios', temp, weblessplugin); })
+                );
+            });
+            waitsFor(function() { return done; }, 'install promise never resolved', 200);
+            runs(function() {
+                var xcode = ios.parseProjectFile(temp).xcode;
+                // from org.test.plugins.dummyplugin
+                expect(xcode.hasFile(slashJoin('Resources', 'DummyPlugin.bundle'))).toBe(true);
+                expect(xcode.hasFile(slashJoin('Plugins','org.test.plugins.dummyplugin', 'DummyPluginCommand.h'))).toBe(true);
+                expect(xcode.hasFile(slashJoin('Plugins','org.test.plugins.dummyplugin', 'DummyPluginCommand.m'))).toBe(true);
+                expect(xcode.hasFile(slashJoin('Plugins','org.test.plugins.dummyplugin','targetDir','TargetDirTest.h'))).toBe(true);
+                expect(xcode.hasFile(slashJoin('Plugins','org.test.plugins.dummyplugin','targetDir','TargetDirTest.m'))).toBe(true);
+                expect(xcode.hasFile('usr/lib/src/ios/libsqlite3.dylib')).toBe(true);
+                expect(xcode.hasFile(slashJoin('SampleApp','Plugins','org.test.plugins.dummyplugin','Custom.framework'))).toBe(true);
+                // from org.test.plugins.weblessplugin
+                expect(xcode.hasFile(slashJoin('Resources', 'WeblessPluginViewController.xib'))).toBe(true);
+                expect(xcode.hasFile(slashJoin('Plugins','org.test.plugins.weblessplugin','WeblessPluginCommand.h'))).toBe(true);
+                expect(xcode.hasFile(slashJoin('Plugins','org.test.plugins.weblessplugin','WeblessPluginCommand.m'))).toBe(true);
+                expect(xcode.hasFile('usr/lib/libsqlite3.dylib')).toBe(true);
+            });
+        });
+    });
+
+    describe('uninstallation', function() {
+        describe('of <source-file> elements', function() {
+            it('should call into xcodeproj\'s removeSourceFile appropriately when element has no target-dir', function(){
+                var source = copyArray(valid_source).filter(function(s) { return s.targetDir === undefined; });
+                shell.cp('-rf', ios_config_xml_project, temp);
+                var spy = spyOn(proj_files.xcode, 'removeSourceFile');
+                ios['source-file'].uninstall(source[0], temp, dummy_id, null, proj_files);
+                expect(spy).toHaveBeenCalledWith(slashJoin('Plugins', dummy_id, 'DummyPluginCommand.m'));
+            });
+            it('should call into xcodeproj\'s removeSourceFile appropriately when element a target-dir', function(){
+                var source = copyArray(valid_source).filter(function(s) { return s.targetDir !== undefined; });
+                shell.cp('-rf', ios_config_xml_project, temp);
+                var spy = spyOn(proj_files.xcode, 'removeSourceFile');
+                ios['source-file'].uninstall(source[0], temp, dummy_id, null, proj_files);
+                expect(spy).toHaveBeenCalledWith(slashJoin('Plugins', dummy_id, 'targetDir', 'TargetDirTest.m'));
+            });
+            it('should rm the file from the right target location when element has no target-dir', function(){
+                var source = copyArray(valid_source).filter(function(s) { return s.targetDir === undefined; });
+                shell.cp('-rf', ios_config_xml_project, temp);
+
+                var spy = spyOn(shell, 'rm');
+                ios['source-file'].uninstall(source[0], temp, dummy_id, null, proj_files);
+                expect(spy).toHaveBeenCalledWith('-rf', path.join(temp, 'SampleApp', 'Plugins', dummy_id));
+            });
+            it('should rm the file from the right target location when element has a target-dir', function(){
+                var source = copyArray(valid_source).filter(function(s) { return s.targetDir !== undefined; });
+                shell.cp('-rf', ios_config_xml_project, temp);
+                var spy = spyOn(shell, 'rm');
+
+                ios['source-file'].uninstall(source[0], temp, dummy_id, null, proj_files);
+                expect(spy).toHaveBeenCalledWith('-rf', path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'targetDir'));
+            });
+            it('should call into xcodeproj\'s removeFramework appropriately when element framework=true set', function(){
+                var source = copyArray(valid_source).filter(function(s) { return s.framework; });
+                shell.cp('-rf', ios_config_xml_project, temp);
+                var spy = spyOn(proj_files.xcode, 'removeFramework');
+
+                ios['source-file'].uninstall(source[0], temp, dummy_id, null, proj_files);
+                expect(spy).toHaveBeenCalledWith(path.join('SampleApp', 'Plugins', dummy_id, 'SourceWithFramework.m'));
+            });
+        });
+
+        describe('of <header-file> elements', function() {
+            beforeEach(function() {
+                shell.cp('-rf', ios_config_xml_project, temp);
+            });
+            it('should call into xcodeproj\'s removeHeaderFile appropriately when element has no target-dir', function(){
+                var headers = copyArray(valid_headers).filter(function(s) { return s.targetDir === undefined; });
+                var spy = spyOn(proj_files.xcode, 'removeHeaderFile');
+
+                ios['header-file'].uninstall(headers[0], temp, dummy_id, null, proj_files);
+                expect(spy).toHaveBeenCalledWith(slashJoin('Plugins', dummy_id, 'DummyPluginCommand.h'));
+            });
+            it('should call into xcodeproj\'s removeHeaderFile appropriately when element a target-dir', function(){
+                var headers = copyArray(valid_headers).filter(function(s) { return s.targetDir !== undefined; });
+
+                var spy = spyOn(proj_files.xcode, 'removeHeaderFile');
+
+                ios['header-file'].uninstall(headers[0], temp, dummy_id, null, proj_files);
+                expect(spy).toHaveBeenCalledWith(slashJoin('Plugins', dummy_id, 'targetDir', 'TargetDirTest.h'));
+            });
+            it('should rm the file from the right target location', function(){
+                var headers = copyArray(valid_headers).filter(function(s) { return s.targetDir !== undefined; });
+                var spy = spyOn(shell, 'rm');
+
+                ios['header-file'].uninstall(headers[0], temp, dummy_id, null, proj_files);
+                expect(spy).toHaveBeenCalledWith('-rf', path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'targetDir'));
+            });
+        });
+
+        describe('of <resource-file> elements', function() {
+            beforeEach(function() {
+                shell.cp('-rf', ios_config_xml_project, temp);
+            });
+            it('should call into xcodeproj\'s removeResourceFile', function(){
+                var resources = copyArray(valid_resources);
+                var spy = spyOn(proj_files.xcode, 'removeResourceFile');
+
+                ios['resource-file'].uninstall(resources[0], temp, 'pluginid', null, proj_files);
+                expect(spy).toHaveBeenCalledWith(path.join('Resources', 'DummyPlugin.bundle'));
+            });
+            it('should rm the file from the right target location', function(){
+                var resources = copyArray(valid_resources);
+                var spy = spyOn(shell, 'rm');
+
+                ios['resource-file'].uninstall(resources[0], temp, 'pluginid', null, proj_files);
+                expect(spy).toHaveBeenCalledWith('-rf', path.join(temp, 'SampleApp', 'Resources', 'DummyPlugin.bundle'));
+            });
+        });
+        describe('of <framework> elements', function() {
+            beforeEach(function() {
+                shell.cp('-rf', ios_config_xml_project, temp);
+            });
+
+            it('should call into xcodeproj\'s removeFramework', function(){
+                var frameworks = copyArray(valid_custom_frameworks);
+                var spy = spyOn(proj_files.xcode, 'removeFramework');
+
+                ios['framework'].uninstall(frameworks[0], temp, dummy_id, null, proj_files);
+                expect(spy).toHaveBeenCalledWith(path.join(temp, 'SampleApp/Plugins/org.test.plugins.dummyplugin/Custom.framework'), {customFramework:true});
+            });
+
+            // TODO: Add more tests to cover the cases:
+            // * framework with weak attribute
+            // * framework that shouldn't be added/removed
+
+            describe('with custom="true" attribute', function () {
+                it('should rm the file from the right target location', function(){
+                    var frameworks = copyArray(valid_custom_frameworks);
+                    var spy = spyOn(shell, 'rm');
+
+                    ios['framework'].uninstall(frameworks[0], temp, dummy_id, null, proj_files);
+                    expect(spy).toHaveBeenCalledWith('-rf', path.join(temp, 'SampleApp/Plugins/org.test.plugins.dummyplugin/Custom.framework'));
+                });
+            });
+        });
+    });
+});


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org


[6/6] ios commit: CB-10769 Update specs according to actual implementation

Posted by an...@apache.org.
CB-10769 Update specs according to actual implementation

This closes #200


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

Branch: refs/heads/master
Commit: 000a61e602f3bddd641316a8fda985d87ad10b62
Parents: c0db5e4
Author: Vladimir Kotikov <v-...@microsoft.com>
Authored: Wed Mar 2 16:44:09 2016 +0300
Committer: Vladimir Kotikov <v-...@microsoft.com>
Committed: Fri Mar 11 10:23:00 2016 +0300

----------------------------------------------------------------------
 .gitignore                                    |   2 +-
 .jshintignore                                 |   2 +-
 tests/spec/unit/Api.spec.js                   |  42 ++
 tests/spec/unit/Plugman/common.spec.js        | 135 +++---
 tests/spec/unit/Plugman/ios.spec.js           | 447 ------------------
 tests/spec/unit/Plugman/pluginHandler.spec.js | 408 +++++++++++++++++
 tests/spec/unit/ios_parser.spec.js            | 500 ---------------------
 tests/spec/unit/prepare.spec.js               | 417 +++++++++++++++++
 tests/spec/unit/projectFile.spec.js           |  83 ++++
 9 files changed, 1012 insertions(+), 1024 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/000a61e6/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index 2744ab7..d1aeeeb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,4 +7,4 @@ tmp
 xcuserdata
 console.log
 node_modules/
-npm-debug.log
\ No newline at end of file
+npm-debug.log

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/000a61e6/.jshintignore
----------------------------------------------------------------------
diff --git a/.jshintignore b/.jshintignore
index 1ec4bc1..281391b 100644
--- a/.jshintignore
+++ b/.jshintignore
@@ -1,3 +1,3 @@
 bin/node_modules/*
 bin/templates/project/*
-tests/spec/unit/fixtures/*
\ No newline at end of file
+tests/spec/unit/fixtures/*

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/000a61e6/tests/spec/unit/Api.spec.js
----------------------------------------------------------------------
diff --git a/tests/spec/unit/Api.spec.js b/tests/spec/unit/Api.spec.js
new file mode 100644
index 0000000..9c25f59
--- /dev/null
+++ b/tests/spec/unit/Api.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 path = require('path');
+var Api = require('../../../bin/templates/scripts/cordova/Api');
+var FIXTURES = path.join(__dirname, 'fixtures');
+var iosProjectFixture = path.join(FIXTURES, 'ios-config-xml');
+
+describe('Platform Api', function () {
+
+    describe('constructor', function() {
+        it('should throw if provided directory does not contain an xcodeproj file', function() {
+            expect(function() { new Api('ios', path.join(FIXTURES, '..')); }).toThrow();
+        });
+        it('should create an instance with path, pbxproj, xcodeproj, originalName and cordovaproj properties', function() {
+            expect(function() {
+                var p = new Api('ios',iosProjectFixture);
+                expect(p.locations.root).toEqual(iosProjectFixture);
+                expect(p.locations.pbxproj).toEqual(path.join(iosProjectFixture, 'SampleApp.xcodeproj', 'project.pbxproj'));
+                expect(p.locations.xcodeProjDir).toEqual(path.join(iosProjectFixture, 'SampleApp.xcodeproj'));
+                expect(p.locations.www).toEqual(path.join(iosProjectFixture, 'www'));
+                expect(p.locations.configXml).toEqual(path.join(iosProjectFixture, 'SampleApp', 'config.xml'));
+            }).not.toThrow();
+        });
+    });
+});

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/000a61e6/tests/spec/unit/Plugman/common.spec.js
----------------------------------------------------------------------
diff --git a/tests/spec/unit/Plugman/common.spec.js b/tests/spec/unit/Plugman/common.spec.js
index f591193..89451e5 100644
--- a/tests/spec/unit/Plugman/common.spec.js
+++ b/tests/spec/unit/Plugman/common.spec.js
@@ -16,74 +16,59 @@
  *
 */
 
-/* jshint laxcomma:true */
-
-var common = require('../../src/plugman/platforms/common')
-  , path = require('path')
-  , fs = require('fs')
-  , osenv = require('os')
-  , shell = require('shelljs')
-  , test_dir = path.join(osenv.tmpdir(), 'test_plugman')
-  , project_dir = path.join(test_dir, 'project')
-  , src = path.join(project_dir, 'src')
-  , dest = path.join(project_dir, 'dest')
-  , java_dir = path.join(src, 'one', 'two', 'three')
-  , java_file = path.join(java_dir, 'test.java')
-  , symlink_file = path.join(java_dir, 'symlink')
-  , non_plugin_file = path.join(osenv.tmpdir(), 'non_plugin_file');
-
-describe('common platform handler', function() {
-    describe('resolveSrcPath', function() {
-        it('should not throw if path exists', function(){
-            shell.mkdir('-p', test_dir);
-            var target = path.join(test_dir, 'somefile');
-            fs.writeFileSync(target, '80085', 'utf-8');
-            expect(function(){common.resolveSrcPath(test_dir, 'somefile');}).not.toThrow();
-            shell.rm('-rf', test_dir);
-        });
-    });
+var fs = require('fs');
+var path = require('path');
+var osenv = require('os');
+var shell = require('shelljs');
+var rewire = require('rewire');
 
-    describe('resolveTargetPath', function() {
-        it('should throw if path exists', function(){
-            shell.mkdir('-p', test_dir);
-            expect(function(){common.resolveTargetPath(test_dir);}).toThrow();
-            shell.rm('-rf', test_dir);
-        });
+var common = rewire('../../../../bin/templates/scripts/cordova/lib/plugman/pluginHandlers');
 
-        it('should not throw if path cannot be resolved', function(){
-            expect(function(){common.resolveTargetPath(test_dir, 'somefile');}).not.toThrow();
-        });
-    });
+var test_dir = path.join(osenv.tmpdir(), 'test_plugman');
+var project_dir = path.join(test_dir, 'project');
+var src = path.join(project_dir, 'src');
+var dest = path.join(project_dir, 'dest');
+var srcDirTree = path.join(src, 'one', 'two', 'three');
+var srcFile = path.join(srcDirTree, 'test.java');
+var symlink_file = path.join(srcDirTree, 'symlink');
+var non_plugin_file = path.join(osenv.tmpdir(), 'non_plugin_file');
+
+var copyFile = common.__get__('copyFile');
+var copyNewFile = common.__get__('copyNewFile');
+var removeFileAndParents = common.__get__('removeFileAndParents');
+
+describe('common handler routines', function() {
 
     describe('copyFile', function() {
         it('should throw if source path not found', function(){
-            expect(function(){common.copyFile(test_dir, src, project_dir, dest);}).
+            shell.rm('-rf', test_dir);
+            expect(function(){copyFile(test_dir, src, project_dir, dest);}).
                 toThrow(new Error('"' + src + '" not found!'));
         });
 
         it('should throw if src not in plugin directory', function(){
             shell.mkdir('-p', project_dir);
             fs.writeFileSync(non_plugin_file, 'contents', 'utf-8');
-            expect(function(){common.copyFile(test_dir, '../non_plugin_file', project_dir, dest);}).
+            expect(function(){copyFile(test_dir, '../non_plugin_file', project_dir, dest);}).
                 toThrow(new Error('"' + non_plugin_file + '" not located within plugin!'));
             shell.rm('-rf', test_dir);
         });
 
         it('should allow symlink src, if inside plugin', function(){
-            shell.mkdir('-p', java_dir);
-            fs.writeFileSync(java_file, 'contents', 'utf-8');
+            shell.mkdir('-p', srcDirTree);
+            fs.writeFileSync(srcFile, 'contents', 'utf-8');
 
             // This will fail on windows if not admin - ignore the error in that case.
-            if (ignoreEPERMonWin32(java_file, symlink_file)) {
+            if (ignoreEPERMonWin32(srcFile, symlink_file)) {
                 return;
             }
 
-            common.copyFile(test_dir, symlink_file, project_dir, dest);
+            copyFile(test_dir, symlink_file, project_dir, dest);
             shell.rm('-rf', project_dir);
         });
 
         it('should throw if symlink is linked to a file outside the plugin', function(){
-            shell.mkdir('-p', java_dir);
+            shell.mkdir('-p', srcDirTree);
             fs.writeFileSync(non_plugin_file, 'contents', 'utf-8');
 
             // This will fail on windows if not admin - ignore the error in that case.
@@ -91,27 +76,27 @@ describe('common platform handler', function() {
                 return;
             }
 
-            expect(function(){common.copyFile(test_dir, symlink_file, project_dir, dest);}).
+            expect(function(){copyFile(test_dir, symlink_file, project_dir, dest);}).
                 toThrow(new Error('"' + symlink_file + '" not located within plugin!'));
             shell.rm('-rf', project_dir);
         });
 
         it('should throw if dest is outside the project directory', function(){
-            shell.mkdir('-p', java_dir);
-            fs.writeFileSync(java_file, 'contents', 'utf-8');
-            expect(function(){common.copyFile(test_dir, java_file, project_dir, non_plugin_file);}).
+            shell.mkdir('-p', srcDirTree);
+            fs.writeFileSync(srcFile, 'contents', 'utf-8');
+            expect(function(){copyFile(test_dir, srcFile, project_dir, non_plugin_file);}).
                 toThrow(new Error('"' + non_plugin_file + '" not located within project!'));
             shell.rm('-rf', project_dir);
         });
 
         it('should call mkdir -p on target path', function(){
-            shell.mkdir('-p', java_dir);
-            fs.writeFileSync(java_file, 'contents', 'utf-8');
+            shell.mkdir('-p', srcDirTree);
+            fs.writeFileSync(srcFile, 'contents', 'utf-8');
 
             var s = spyOn(shell, 'mkdir').andCallThrough();
-            var resolvedDest = common.resolveTargetPath(project_dir, dest);
+            var resolvedDest = path.resolve(project_dir, dest);
 
-            common.copyFile(test_dir, java_file, project_dir, dest);
+            copyFile(test_dir, srcFile, project_dir, dest);
 
             expect(s).toHaveBeenCalled();
             expect(s).toHaveBeenCalledWith('-p', path.dirname(resolvedDest));
@@ -119,16 +104,16 @@ describe('common platform handler', function() {
         });
 
         it('should call cp source/dest paths', function(){
-            shell.mkdir('-p', java_dir);
-            fs.writeFileSync(java_file, 'contents', 'utf-8');
+            shell.mkdir('-p', srcDirTree);
+            fs.writeFileSync(srcFile, 'contents', 'utf-8');
 
             var s = spyOn(shell, 'cp').andCallThrough();
-            var resolvedDest = common.resolveTargetPath(project_dir, dest);
+            var resolvedDest = path.resolve(project_dir, dest);
 
-            common.copyFile(test_dir, java_file, project_dir, dest);
+            copyFile(test_dir, srcFile, project_dir, dest);
 
             expect(s).toHaveBeenCalled();
-            expect(s).toHaveBeenCalledWith('-f', java_file, resolvedDest);
+            expect(s).toHaveBeenCalledWith('-f', srcFile, resolvedDest);
 
             shell.rm('-rf', project_dir);
         });
@@ -138,7 +123,7 @@ describe('common platform handler', function() {
     describe('copyNewFile', function () {
         it('should throw if target path exists', function(){
             shell.mkdir('-p', dest);
-            expect(function(){common.copyNewFile(test_dir, src, project_dir, dest);}).
+            expect(function(){copyNewFile(test_dir, src, project_dir, dest);}).
                 toThrow(new Error('"' + dest + '" already exists!'));
             shell.rm('-rf', dest);
         });
@@ -147,37 +132,37 @@ describe('common platform handler', function() {
 
     describe('deleteJava', function() {
         it('should call fs.unlinkSync on the provided paths', function(){
-            shell.mkdir('-p', java_dir);
-            fs.writeFileSync(java_file, 'contents', 'utf-8');
+            shell.mkdir('-p', srcDirTree);
+            fs.writeFileSync(srcFile, 'contents', 'utf-8');
 
             var s = spyOn(fs, 'unlinkSync').andCallThrough();
-            common.deleteJava(project_dir, java_file);
+            removeFileAndParents(project_dir, srcFile);
             expect(s).toHaveBeenCalled();
-            expect(s).toHaveBeenCalledWith(path.resolve(project_dir, java_file));
+            expect(s).toHaveBeenCalledWith(path.resolve(project_dir, srcFile));
 
-            shell.rm('-rf', java_dir);
+            shell.rm('-rf', srcDirTree);
         });
 
-        it('should delete empty directories after removing source code in a java src path hierarchy', function(){
-            shell.mkdir('-p', java_dir);
-            fs.writeFileSync(java_file, 'contents', 'utf-8');
+        it('should delete empty directories after removing source code in path hierarchy', function(){
+            shell.mkdir('-p', srcDirTree);
+            fs.writeFileSync(srcFile, 'contents', 'utf-8');
 
-            common.deleteJava(project_dir, java_file);
-            expect(fs.existsSync(java_file)).not.toBe(true);
-            expect(fs.existsSync(java_dir)).not.toBe(true);
+            removeFileAndParents(project_dir, srcFile);
+            expect(fs.existsSync(srcFile)).not.toBe(true);
+            expect(fs.existsSync(srcDirTree)).not.toBe(true);
             expect(fs.existsSync(path.join(src,'one'))).not.toBe(true);
 
-            shell.rm('-rf', java_dir);
+            shell.rm('-rf', srcDirTree);
         });
 
-        it('should never delete the top-level src directory, even if all plugins added were removed', function(){
-            shell.mkdir('-p', java_dir);
-            fs.writeFileSync(java_file, 'contents', 'utf-8');
+        it('should delete the top-level src directory if all plugins added were removed', function(){
+            shell.mkdir('-p', srcDirTree);
+            fs.writeFileSync(srcFile, 'contents', 'utf-8');
 
-            common.deleteJava(project_dir, java_file);
-            expect(fs.existsSync(src)).toBe(true);
+            removeFileAndParents(project_dir, srcFile);
+            expect(fs.existsSync(src)).toBe(false);
 
-            shell.rm('-rf', java_dir);
+            shell.rm('-rf', srcDirTree);
         });
     });
 });

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/000a61e6/tests/spec/unit/Plugman/ios.spec.js
----------------------------------------------------------------------
diff --git a/tests/spec/unit/Plugman/ios.spec.js b/tests/spec/unit/Plugman/ios.spec.js
deleted file mode 100644
index 7c245bd..0000000
--- a/tests/spec/unit/Plugman/ios.spec.js
+++ /dev/null
@@ -1,447 +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.
-*/
-
-/* jshint sub:true */
-
-var ios = require('../../src/plugman/platforms/ios'),
-    install = require('../../src/plugman/install'),
-    path = require('path'),
-    fs = require('fs'),
-    shell = require('shelljs'),
-    os = require('os'),
-    temp = path.join(os.tmpdir(), 'plugman'),
-    plugins_dir = path.join(temp, 'cordova', 'plugins'),
-    ios_config_xml_project = path.join(__dirname, '..', 'projects', 'ios-config-xml', '*'),
-    ios_project = path.join(ios_config_xml_project, '..'),
-    faultyplugin = path.join(__dirname, '..', 'plugins', 'org.test.plugins.faultyplugin'),
-    dummyplugin = path.join(__dirname, '..', 'plugins', 'org.test.plugins.dummyplugin'),
-    weblessplugin = path.join(__dirname, '..', 'plugins', 'org.test.plugins.weblessplugin'),
-    done = false;
-
-var PluginInfo = require('cordova-common').PluginInfo;
-
-var dummyPluginInfo = new PluginInfo(dummyplugin);
-var dummy_id = dummyPluginInfo.id;
-var valid_source = dummyPluginInfo.getSourceFiles('ios'),
-    valid_headers = dummyPluginInfo.getHeaderFiles('ios'),
-    valid_resources = dummyPluginInfo.getResourceFiles('ios'),
-    valid_custom_frameworks = dummyPluginInfo.getFrameworks('ios').filter(function(f) { return f.custom; });
-
-var faultyPluginInfo = new PluginInfo(faultyplugin);
-var faulty_id = faultyPluginInfo.id;
-
-var invalid_source = faultyPluginInfo.getSourceFiles('ios');
-var invalid_headers = faultyPluginInfo.getHeaderFiles('ios');
-var invalid_resources = faultyPluginInfo.getResourceFiles('ios');
-var invalid_custom_frameworks = faultyPluginInfo.getFrameworks('ios').filter(function(f) { return f.custom; });
-
-shell.mkdir('-p', temp);
-shell.cp('-rf', ios_config_xml_project, temp);
-var proj_files = ios.parseProjectFile(temp);
-shell.rm('-rf', temp);
-ios.purgeProjectFileCache(temp);
-
-function copyArray(arr) {
-    return Array.prototype.slice.call(arr, 0);
-}
-
-function installPromise(f) {
-    f.then(function(res) { done = true; }, function(err) { done = err; });
-}
-
-function slashJoin() {
-    // In some places we need to use forward slash instead of path.join().
-    // See CB-7311.
-    return Array.prototype.join.call(arguments, '/');
-}
-
-describe('ios project handler', function() {
-    beforeEach(function() {
-        shell.mkdir('-p', temp);
-        shell.mkdir('-p', plugins_dir);
-    });
-    afterEach(function() {
-        shell.rm('-rf', temp);
-        ios.purgeProjectFileCache(temp);
-    });
-
-    describe('www_dir method', function() {
-        it('should return cordova-ios project www location using www_dir', function() {
-            expect(ios.www_dir(path.sep)).toEqual(path.sep + 'www');
-        });
-    });
-
-    describe('package_name method', function() {
-        it('should return the CFBundleIdentifier from the project\'s Info.plist file', function() {
-            expect(ios.package_name(ios_project)).toEqual('com.example.friendstring');
-        });
-    });
-
-    describe('parseProjectFile method', function () {
-        it('should throw if project is not an xcode project', function() {
-            expect(function() {
-                ios.parseProjectFile(temp);
-            }).toThrow('does not appear to be an xcode project (no xcode project file)');
-        });
-        it('should throw if project does not contain an appropriate config.xml file', function() {
-            shell.cp('-rf', ios_config_xml_project, temp);
-            shell.rm(path.join(temp, 'SampleApp', 'config.xml'));
-
-            expect(function() {
-                ios.parseProjectFile(temp);
-            }).toThrow('could not find -Info.plist file, or config.xml file.');
-        });
-        it('should throw if project does not contain an appropriate -Info.plist file', function() {
-            shell.cp('-rf', ios_config_xml_project, temp);
-            shell.rm(path.join(temp, 'SampleApp', 'SampleApp-Info.plist'));
-
-            expect(function () {
-                ios.parseProjectFile(temp);
-            }).toThrow('could not find -Info.plist file, or config.xml file.');
-        });
-        it('should return right directory when multiple .plist files are present', function() {
-            shell.cp('-rf', ios_config_xml_project, temp);
-            //Create a folder named A with config.xml and .plist files in it
-            var pathToFolderA = path.join(temp, 'A');
-            shell.mkdir(pathToFolderA);
-            shell.cp('-rf', path.join(temp, 'SampleApp/*'), pathToFolderA);
-
-            var parsedProjectFile = ios.parseProjectFile(temp);
-            var pluginsDir = parsedProjectFile.plugins_dir,
-                resourcesDir = parsedProjectFile.resources_dir,
-                xcodePath = parsedProjectFile.xcode_path;
-
-            var pluginsDirParent = path.dirname(pluginsDir),
-                resourcesDirParent = path.dirname(resourcesDir),
-                sampleAppDir = path.join(temp, 'SampleApp');
-
-            expect(pluginsDirParent).toEqual(sampleAppDir);
-            expect(resourcesDirParent).toEqual(sampleAppDir);
-            expect(xcodePath).toEqual(sampleAppDir);
-        });
-    });
-
-    describe('installation', function() {
-        beforeEach(function() {
-            shell.cp('-rf', ios_config_xml_project, temp);
-            done = false;
-        });
-
-        describe('of <source-file> elements', function() {
-            it('should throw if source-file src cannot be found', function() {
-                var source = copyArray(invalid_source);
-                expect(function() {
-                    ios['source-file'].install(source[1], faultyplugin, temp, faulty_id, null, proj_files);
-                }).toThrow();
-            });
-            it('should throw if source-file target already exists', function() {
-                var source = copyArray(valid_source);
-                var target = path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'DummyPluginCommand.m');
-                shell.mkdir('-p', path.dirname(target));
-                fs.writeFileSync(target, 'some bs', 'utf-8');
-                expect(function() {
-                    ios['source-file'].install(source[0], dummyplugin, temp, dummy_id, null, proj_files);
-                }).toThrow();
-            });
-            it('should call into xcodeproj\'s addSourceFile appropriately when element has no target-dir', function() {
-                var source = copyArray(valid_source).filter(function(s) { return s.targetDir === undefined; });
-                var spy = spyOn(proj_files.xcode, 'addSourceFile');
-                ios['source-file'].install(source[0], dummyplugin, temp, dummy_id, null, proj_files);
-                expect(spy).toHaveBeenCalledWith(slashJoin('Plugins', dummy_id, 'DummyPluginCommand.m'), {});
-            });
-            it('should call into xcodeproj\'s addSourceFile appropriately when element has a target-dir', function() {
-                var source = copyArray(valid_source).filter(function(s) { return s.targetDir !== undefined; });
-                var spy = spyOn(proj_files.xcode, 'addSourceFile');
-                ios['source-file'].install(source[0], dummyplugin, temp, dummy_id, null, proj_files);
-                expect(spy).toHaveBeenCalledWith(slashJoin('Plugins', dummy_id, 'targetDir', 'TargetDirTest.m'), {});
-            });
-            it('should cp the file to the right target location when element has no target-dir', function() {
-                var source = copyArray(valid_source).filter(function(s) { return s.targetDir === undefined; });
-                var spy = spyOn(shell, 'cp');
-                ios['source-file'].install(source[0], dummyplugin, temp, dummy_id, null, proj_files);
-                expect(spy).toHaveBeenCalledWith('-f', path.join(dummyplugin, 'src', 'ios', 'DummyPluginCommand.m'), path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'DummyPluginCommand.m'));
-            });
-            it('should cp the file to the right target location when element has a target-dir', function() {
-                var source = copyArray(valid_source).filter(function(s) { return s.targetDir !== undefined; });
-                var spy = spyOn(shell, 'cp');
-                ios['source-file'].install(source[0], dummyplugin, temp, dummy_id, null, proj_files);
-                expect(spy).toHaveBeenCalledWith('-f', path.join(dummyplugin, 'src', 'ios', 'TargetDirTest.m'), path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'targetDir', 'TargetDirTest.m'));
-            });
-            it('should call into xcodeproj\'s addFramework appropriately when element has framework=true set', function() {
-                var source = copyArray(valid_source).filter(function(s) { return s.framework; });
-                spyOn(proj_files.xcode, 'addSourceFile');
-                var spy = spyOn(proj_files.xcode, 'addFramework');
-                ios['source-file'].install(source[0], dummyplugin, temp, dummy_id, null, proj_files);
-                expect(spy).toHaveBeenCalledWith(path.join('SampleApp', 'Plugins', dummy_id, 'SourceWithFramework.m'), {weak:false});
-            });
-        });
-
-        describe('of <header-file> elements', function() {
-            it('should throw if header-file src cannot be found', function() {
-                var headers = copyArray(invalid_headers);
-                expect(function() {
-                    ios['header-file'].install(headers[1], faultyplugin, temp, faulty_id, null, proj_files);
-                }).toThrow();
-            });
-            it('should throw if header-file target already exists', function() {
-                var headers = copyArray(valid_headers);
-                var target = path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'DummyPluginCommand.h');
-                shell.mkdir('-p', path.dirname(target));
-                fs.writeFileSync(target, 'some bs', 'utf-8');
-                expect(function() {
-                    ios['header-file'].install(headers[0], dummyplugin, temp, dummy_id, null, proj_files);
-                }).toThrow();
-            });
-            it('should call into xcodeproj\'s addHeaderFile appropriately when element has no target-dir', function() {
-                var headers = copyArray(valid_headers).filter(function(s) { return s.targetDir === undefined; });
-                var spy = spyOn(proj_files.xcode, 'addHeaderFile');
-                ios['header-file'].install(headers[0], dummyplugin, temp, dummy_id,  null, proj_files);
-                expect(spy).toHaveBeenCalledWith(slashJoin('Plugins', dummy_id, 'DummyPluginCommand.h'));
-            });
-            it('should call into xcodeproj\'s addHeaderFile appropriately when element a target-dir', function() {
-                var headers = copyArray(valid_headers).filter(function(s) { return s.targetDir !== undefined; });
-                var spy = spyOn(proj_files.xcode, 'addHeaderFile');
-                ios['header-file'].install(headers[0], dummyplugin, temp, dummy_id, null, proj_files);
-                expect(spy).toHaveBeenCalledWith(slashJoin('Plugins', dummy_id, 'targetDir', 'TargetDirTest.h'));
-            });
-            it('should cp the file to the right target location when element has no target-dir', function() {
-                var headers = copyArray(valid_headers).filter(function(s) { return s.targetDir === undefined; });
-                var spy = spyOn(shell, 'cp');
-                ios['header-file'].install(headers[0], dummyplugin, temp, dummy_id, null, proj_files);
-                expect(spy).toHaveBeenCalledWith('-f', path.join(dummyplugin, 'src', 'ios', 'DummyPluginCommand.h'), path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'DummyPluginCommand.h'));
-            });
-            it('should cp the file to the right target location when element has a target-dir', function() {
-                var headers = copyArray(valid_headers).filter(function(s) { return s.targetDir !== undefined; });
-                var spy = spyOn(shell, 'cp');
-                ios['header-file'].install(headers[0], dummyplugin, temp, dummy_id, null, proj_files);
-                expect(spy).toHaveBeenCalledWith('-f', path.join(dummyplugin, 'src', 'ios', 'TargetDirTest.h'), path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'targetDir', 'TargetDirTest.h'));
-            });
-        });
-
-        describe('of <resource-file> elements', function() {
-            it('should throw if resource-file src cannot be found', function() {
-                var resources = copyArray(invalid_resources);
-                expect(function() {
-                    ios['resource-file'].install(resources[0], faultyplugin, temp, 'pluginid', null, proj_files);
-                }).toThrow('cannot find "' + path.resolve(faultyplugin, 'src/ios/IDontExist.bundle') + '" ios <resource-file>');
-            });
-            it('should throw if resource-file target already exists', function() {
-                var resources = copyArray(valid_resources);
-                var target = path.join(temp, 'SampleApp', 'Resources', 'DummyPlugin.bundle');
-                shell.mkdir('-p', path.dirname(target));
-                fs.writeFileSync(target, 'some bs', 'utf-8');
-                expect(function() {
-                    ios['resource-file'].install(resources[0], dummyplugin, temp, 'pluginid',null, proj_files);
-                }).toThrow('target destination "' + target + '" already exists');
-            });
-            it('should call into xcodeproj\'s addResourceFile', function() {
-                var resources = copyArray(valid_resources);
-                var spy = spyOn(proj_files.xcode, 'addResourceFile');
-                ios['resource-file'].install(resources[0], dummyplugin, temp, 'pluginid', null, proj_files);
-                expect(spy).toHaveBeenCalledWith(path.join('Resources', 'DummyPlugin.bundle'));
-            });
-            it('should cp the file to the right target location', function() {
-                var resources = copyArray(valid_resources);
-                var spy = spyOn(shell, 'cp');
-                ios['resource-file'].install(resources[0], dummyplugin, temp, 'pluginid', null, proj_files);
-                expect(spy).toHaveBeenCalledWith('-R', path.join(dummyplugin, 'src', 'ios', 'DummyPlugin.bundle'), path.join(temp, 'SampleApp', 'Resources'));
-            });
-        });
-        describe('of <framework> elements', function() {
-
-            it('should call into xcodeproj\'s addFramework', function() {
-                var frameworks = copyArray(valid_custom_frameworks);
-                var spy = spyOn(proj_files.xcode, 'addFramework');
-                ios['framework'].install(frameworks[0], dummyplugin, temp, dummy_id, null, proj_files);
-                expect(spy).toHaveBeenCalledWith(path.normalize('SampleApp/Plugins/org.test.plugins.dummyplugin/Custom.framework'), {customFramework:true});
-            });
-
-            // TODO: Add more tests to cover the cases:
-            // * framework with weak attribute
-            // * framework that shouldn't be added/removed
-
-            describe('with custom="true" attribute', function () {
-                it('should throw if framework src cannot be found', function() {
-                    var frameworks = copyArray(invalid_custom_frameworks);
-                    expect(function() {
-                        ios['framework'].install(frameworks[0], faultyplugin, temp, dummy_id, null, proj_files);
-                    }).toThrow('cannot find "' + path.resolve(faultyplugin, 'src/ios/NonExistantCustomFramework.framework') + '" ios <framework>');
-                });
-                it('should throw if framework target already exists', function() {
-                    var frameworks = copyArray(valid_custom_frameworks);
-                    var target = path.join(temp, 'SampleApp/Plugins/org.test.plugins.dummyplugin/Custom.framework');
-                    shell.mkdir('-p', target);
-                    expect(function() {
-                        ios['framework'].install(frameworks[0], dummyplugin, temp, dummy_id, null, proj_files);
-                    }).toThrow('target destination "' + target + '" already exists');
-                });
-                it('should cp the file to the right target location', function() {
-                    var frameworks = copyArray(valid_custom_frameworks);
-                    var spy = spyOn(shell, 'cp');
-                    ios['framework'].install(frameworks[0], dummyplugin, temp, dummy_id, null, proj_files);
-                    expect(spy).toHaveBeenCalledWith('-R', path.join(dummyplugin, 'src', 'ios', 'Custom.framework'),
-                                                     path.join(temp, 'SampleApp/Plugins/org.test.plugins.dummyplugin'));
-                });
-            });
-        });
-        it('of two plugins should apply xcode file changes from both', function(){
-            runs(function() {
-                installPromise(
-                    install('ios', temp, dummyplugin)
-                    .then(function () { install('ios', temp, weblessplugin); })
-                );
-            });
-            waitsFor(function() { return done; }, 'install promise never resolved', 200);
-            runs(function() {
-                var xcode = ios.parseProjectFile(temp).xcode;
-                // from org.test.plugins.dummyplugin
-                expect(xcode.hasFile(slashJoin('Resources', 'DummyPlugin.bundle'))).toBe(true);
-                expect(xcode.hasFile(slashJoin('Plugins','org.test.plugins.dummyplugin', 'DummyPluginCommand.h'))).toBe(true);
-                expect(xcode.hasFile(slashJoin('Plugins','org.test.plugins.dummyplugin', 'DummyPluginCommand.m'))).toBe(true);
-                expect(xcode.hasFile(slashJoin('Plugins','org.test.plugins.dummyplugin','targetDir','TargetDirTest.h'))).toBe(true);
-                expect(xcode.hasFile(slashJoin('Plugins','org.test.plugins.dummyplugin','targetDir','TargetDirTest.m'))).toBe(true);
-                expect(xcode.hasFile('usr/lib/src/ios/libsqlite3.dylib')).toBe(true);
-                expect(xcode.hasFile(slashJoin('SampleApp','Plugins','org.test.plugins.dummyplugin','Custom.framework'))).toBe(true);
-                // from org.test.plugins.weblessplugin
-                expect(xcode.hasFile(slashJoin('Resources', 'WeblessPluginViewController.xib'))).toBe(true);
-                expect(xcode.hasFile(slashJoin('Plugins','org.test.plugins.weblessplugin','WeblessPluginCommand.h'))).toBe(true);
-                expect(xcode.hasFile(slashJoin('Plugins','org.test.plugins.weblessplugin','WeblessPluginCommand.m'))).toBe(true);
-                expect(xcode.hasFile('usr/lib/libsqlite3.dylib')).toBe(true);
-            });
-        });
-    });
-
-    describe('uninstallation', function() {
-        describe('of <source-file> elements', function() {
-            it('should call into xcodeproj\'s removeSourceFile appropriately when element has no target-dir', function(){
-                var source = copyArray(valid_source).filter(function(s) { return s.targetDir === undefined; });
-                shell.cp('-rf', ios_config_xml_project, temp);
-                var spy = spyOn(proj_files.xcode, 'removeSourceFile');
-                ios['source-file'].uninstall(source[0], temp, dummy_id, null, proj_files);
-                expect(spy).toHaveBeenCalledWith(slashJoin('Plugins', dummy_id, 'DummyPluginCommand.m'));
-            });
-            it('should call into xcodeproj\'s removeSourceFile appropriately when element a target-dir', function(){
-                var source = copyArray(valid_source).filter(function(s) { return s.targetDir !== undefined; });
-                shell.cp('-rf', ios_config_xml_project, temp);
-                var spy = spyOn(proj_files.xcode, 'removeSourceFile');
-                ios['source-file'].uninstall(source[0], temp, dummy_id, null, proj_files);
-                expect(spy).toHaveBeenCalledWith(slashJoin('Plugins', dummy_id, 'targetDir', 'TargetDirTest.m'));
-            });
-            it('should rm the file from the right target location when element has no target-dir', function(){
-                var source = copyArray(valid_source).filter(function(s) { return s.targetDir === undefined; });
-                shell.cp('-rf', ios_config_xml_project, temp);
-
-                var spy = spyOn(shell, 'rm');
-                ios['source-file'].uninstall(source[0], temp, dummy_id, null, proj_files);
-                expect(spy).toHaveBeenCalledWith('-rf', path.join(temp, 'SampleApp', 'Plugins', dummy_id));
-            });
-            it('should rm the file from the right target location when element has a target-dir', function(){
-                var source = copyArray(valid_source).filter(function(s) { return s.targetDir !== undefined; });
-                shell.cp('-rf', ios_config_xml_project, temp);
-                var spy = spyOn(shell, 'rm');
-
-                ios['source-file'].uninstall(source[0], temp, dummy_id, null, proj_files);
-                expect(spy).toHaveBeenCalledWith('-rf', path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'targetDir'));
-            });
-            it('should call into xcodeproj\'s removeFramework appropriately when element framework=true set', function(){
-                var source = copyArray(valid_source).filter(function(s) { return s.framework; });
-                shell.cp('-rf', ios_config_xml_project, temp);
-                var spy = spyOn(proj_files.xcode, 'removeFramework');
-
-                ios['source-file'].uninstall(source[0], temp, dummy_id, null, proj_files);
-                expect(spy).toHaveBeenCalledWith(path.join('SampleApp', 'Plugins', dummy_id, 'SourceWithFramework.m'));
-            });
-        });
-
-        describe('of <header-file> elements', function() {
-            beforeEach(function() {
-                shell.cp('-rf', ios_config_xml_project, temp);
-            });
-            it('should call into xcodeproj\'s removeHeaderFile appropriately when element has no target-dir', function(){
-                var headers = copyArray(valid_headers).filter(function(s) { return s.targetDir === undefined; });
-                var spy = spyOn(proj_files.xcode, 'removeHeaderFile');
-
-                ios['header-file'].uninstall(headers[0], temp, dummy_id, null, proj_files);
-                expect(spy).toHaveBeenCalledWith(slashJoin('Plugins', dummy_id, 'DummyPluginCommand.h'));
-            });
-            it('should call into xcodeproj\'s removeHeaderFile appropriately when element a target-dir', function(){
-                var headers = copyArray(valid_headers).filter(function(s) { return s.targetDir !== undefined; });
-
-                var spy = spyOn(proj_files.xcode, 'removeHeaderFile');
-
-                ios['header-file'].uninstall(headers[0], temp, dummy_id, null, proj_files);
-                expect(spy).toHaveBeenCalledWith(slashJoin('Plugins', dummy_id, 'targetDir', 'TargetDirTest.h'));
-            });
-            it('should rm the file from the right target location', function(){
-                var headers = copyArray(valid_headers).filter(function(s) { return s.targetDir !== undefined; });
-                var spy = spyOn(shell, 'rm');
-
-                ios['header-file'].uninstall(headers[0], temp, dummy_id, null, proj_files);
-                expect(spy).toHaveBeenCalledWith('-rf', path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'targetDir'));
-            });
-        });
-
-        describe('of <resource-file> elements', function() {
-            beforeEach(function() {
-                shell.cp('-rf', ios_config_xml_project, temp);
-            });
-            it('should call into xcodeproj\'s removeResourceFile', function(){
-                var resources = copyArray(valid_resources);
-                var spy = spyOn(proj_files.xcode, 'removeResourceFile');
-
-                ios['resource-file'].uninstall(resources[0], temp, 'pluginid', null, proj_files);
-                expect(spy).toHaveBeenCalledWith(path.join('Resources', 'DummyPlugin.bundle'));
-            });
-            it('should rm the file from the right target location', function(){
-                var resources = copyArray(valid_resources);
-                var spy = spyOn(shell, 'rm');
-
-                ios['resource-file'].uninstall(resources[0], temp, 'pluginid', null, proj_files);
-                expect(spy).toHaveBeenCalledWith('-rf', path.join(temp, 'SampleApp', 'Resources', 'DummyPlugin.bundle'));
-            });
-        });
-        describe('of <framework> elements', function() {
-            beforeEach(function() {
-                shell.cp('-rf', ios_config_xml_project, temp);
-            });
-
-            it('should call into xcodeproj\'s removeFramework', function(){
-                var frameworks = copyArray(valid_custom_frameworks);
-                var spy = spyOn(proj_files.xcode, 'removeFramework');
-
-                ios['framework'].uninstall(frameworks[0], temp, dummy_id, null, proj_files);
-                expect(spy).toHaveBeenCalledWith(path.join(temp, 'SampleApp/Plugins/org.test.plugins.dummyplugin/Custom.framework'), {customFramework:true});
-            });
-
-            // TODO: Add more tests to cover the cases:
-            // * framework with weak attribute
-            // * framework that shouldn't be added/removed
-
-            describe('with custom="true" attribute', function () {
-                it('should rm the file from the right target location', function(){
-                    var frameworks = copyArray(valid_custom_frameworks);
-                    var spy = spyOn(shell, 'rm');
-
-                    ios['framework'].uninstall(frameworks[0], temp, dummy_id, null, proj_files);
-                    expect(spy).toHaveBeenCalledWith('-rf', path.join(temp, 'SampleApp/Plugins/org.test.plugins.dummyplugin/Custom.framework'));
-                });
-            });
-        });
-    });
-});

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/000a61e6/tests/spec/unit/Plugman/pluginHandler.spec.js
----------------------------------------------------------------------
diff --git a/tests/spec/unit/Plugman/pluginHandler.spec.js b/tests/spec/unit/Plugman/pluginHandler.spec.js
new file mode 100644
index 0000000..d093970
--- /dev/null
+++ b/tests/spec/unit/Plugman/pluginHandler.spec.js
@@ -0,0 +1,408 @@
+/**
+    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 os = require('os');
+var fs = require('fs');
+var path = require('path');
+var rewire = require('rewire');
+var shell = require('shelljs');
+
+var PluginInfo = require('cordova-common').PluginInfo;
+var Api = require('../../../../bin/templates/scripts/cordova/Api');
+var projectFile = require('../../../../bin/templates/scripts/cordova/lib/projectFile');
+var pluginHandlers = rewire('../../../../bin/templates/scripts/cordova/lib/plugman/pluginHandlers');
+
+var temp = path.join(os.tmpdir(), 'plugman');
+
+var FIXTURES = path.join(__dirname, '../fixtures');
+var iosProject = path.join(FIXTURES, 'ios-config-xml', '*');
+var faultyplugin = path.join(FIXTURES, 'org.test.plugins.faultyplugin');
+var dummyplugin = path.join(FIXTURES, 'org.test.plugins.dummyplugin');
+var weblessplugin = path.join(FIXTURES, 'org.test.plugins.weblessplugin');
+
+var dummyPluginInfo = new PluginInfo(dummyplugin);
+var dummy_id = dummyPluginInfo.id;
+var valid_source = dummyPluginInfo.getSourceFiles('ios'),
+    valid_headers = dummyPluginInfo.getHeaderFiles('ios'),
+    valid_resources = dummyPluginInfo.getResourceFiles('ios'),
+    valid_custom_frameworks = dummyPluginInfo.getFrameworks('ios').filter(function(f) { return f.custom; });
+
+var faultyPluginInfo = new PluginInfo(faultyplugin);
+var invalid_source = faultyPluginInfo.getSourceFiles('ios');
+var invalid_headers = faultyPluginInfo.getHeaderFiles('ios');
+var invalid_resources = faultyPluginInfo.getResourceFiles('ios');
+var invalid_custom_frameworks = faultyPluginInfo.getFrameworks('ios').filter(function(f) { return f.custom; });
+
+var weblessPluginInfo = new PluginInfo(weblessplugin);
+
+function copyArray(arr) {
+    return Array.prototype.slice.call(arr, 0);
+}
+
+function slashJoin() {
+    // In some places we need to use forward slash instead of path.join().
+    // See CB-7311.
+    return Array.prototype.join.call(arguments, '/');
+}
+
+describe('ios plugin handler', function() {
+    var dummyProject;
+
+    beforeEach(function() {
+        shell.cp('-rf', iosProject, temp);
+        projectFile.purgeProjectFileCache(temp);
+
+        dummyProject = projectFile.parse({
+            root: temp,
+            pbxproj: path.join(temp, 'SampleApp.xcodeproj/project.pbxproj')
+        });
+    });
+
+    afterEach(function() {
+        shell.rm('-rf', temp);
+    });
+
+    describe('installation', function() {
+
+        describe('of <source-file> elements', function() {
+            var install = pluginHandlers.getInstaller('source-file');
+
+            beforeEach(function () {
+                spyOn(dummyProject.xcode, 'addSourceFile');
+            });
+
+            it('should throw if source-file src cannot be found', function() {
+                var source = copyArray(invalid_source);
+                expect(function() {
+                    install(source[1], faultyPluginInfo, dummyProject);
+                }).toThrow();
+            });
+            it('should throw if source-file target already exists', function() {
+                var source = copyArray(valid_source);
+                var target = path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'DummyPluginCommand.m');
+                shell.mkdir('-p', path.dirname(target));
+                fs.writeFileSync(target, 'some bs', 'utf-8');
+                expect(function() {
+                    install(source[0], dummyPluginInfo, dummyProject);
+                }).toThrow();
+            });
+            it('should call into xcodeproj\'s addSourceFile appropriately when element has no target-dir', function() {
+                var source = copyArray(valid_source).filter(function(s) { return s.targetDir === undefined; });
+                install(source[0], dummyPluginInfo, dummyProject);
+                expect(dummyProject.xcode.addSourceFile)
+                    .toHaveBeenCalledWith(slashJoin('Plugins', dummy_id, 'DummyPluginCommand.m'), {});
+            });
+            it('should call into xcodeproj\'s addSourceFile appropriately when element has a target-dir', function() {
+                var source = copyArray(valid_source).filter(function(s) { return s.targetDir !== undefined; });
+                install(source[0], dummyPluginInfo, dummyProject);
+                expect(dummyProject.xcode.addSourceFile)
+                    .toHaveBeenCalledWith(slashJoin('Plugins', dummy_id, 'targetDir', 'TargetDirTest.m'), {});
+            });
+            it('should cp the file to the right target location when element has no target-dir', function() {
+                var source = copyArray(valid_source).filter(function(s) { return s.targetDir === undefined; });
+                var spy = spyOn(shell, 'cp');
+                install(source[0], dummyPluginInfo, dummyProject);
+                expect(spy).toHaveBeenCalledWith('-f', path.join(dummyplugin, 'src', 'ios', 'DummyPluginCommand.m'), path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'DummyPluginCommand.m'));
+            });
+            it('should cp the file to the right target location when element has a target-dir', function() {
+                var source = copyArray(valid_source).filter(function(s) { return s.targetDir !== undefined; });
+                var spy = spyOn(shell, 'cp');
+                install(source[0], dummyPluginInfo, dummyProject);
+                expect(spy).toHaveBeenCalledWith('-f', path.join(dummyplugin, 'src', 'ios', 'TargetDirTest.m'), path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'targetDir', 'TargetDirTest.m'));
+            });
+            it('should call into xcodeproj\'s addFramework appropriately when element has framework=true set', function() {
+                var source = copyArray(valid_source).filter(function(s) { return s.framework; });
+                spyOn(dummyProject.xcode, 'addFramework');
+                install(source[0], dummyPluginInfo, dummyProject);
+                expect(dummyProject.xcode.addFramework)
+                    .toHaveBeenCalledWith(path.join('SampleApp', 'Plugins', dummy_id, 'SourceWithFramework.m'), {weak:false});
+            });
+        });
+
+        describe('of <header-file> elements', function() {
+            var install = pluginHandlers.getInstaller('header-file');
+
+            beforeEach(function () {
+                spyOn(dummyProject.xcode, 'addHeaderFile');
+            });
+
+            it('should throw if header-file src cannot be found', function() {
+                var headers = copyArray(invalid_headers);
+                expect(function() {
+                    install(headers[1], faultyPluginInfo, dummyProject);
+                }).toThrow();
+            });
+            it('should throw if header-file target already exists', function() {
+                var headers = copyArray(valid_headers);
+                var target = path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'DummyPluginCommand.h');
+                shell.mkdir('-p', path.dirname(target));
+                fs.writeFileSync(target, 'some bs', 'utf-8');
+                expect(function() {
+                    install(headers[0], dummyPluginInfo, dummyProject);
+                }).toThrow();
+            });
+            it('should call into xcodeproj\'s addHeaderFile appropriately when element has no target-dir', function() {
+                var headers = copyArray(valid_headers).filter(function(s) { return s.targetDir === undefined; });
+                install(headers[0], dummyPluginInfo, dummyProject);
+                expect(dummyProject.xcode.addHeaderFile)
+                    .toHaveBeenCalledWith(slashJoin('Plugins', dummy_id, 'DummyPluginCommand.h'));
+            });
+            it('should call into xcodeproj\'s addHeaderFile appropriately when element a target-dir', function() {
+                var headers = copyArray(valid_headers).filter(function(s) { return s.targetDir !== undefined; });
+                install(headers[0], dummyPluginInfo, dummyProject);
+                expect(dummyProject.xcode.addHeaderFile)
+                    .toHaveBeenCalledWith(slashJoin('Plugins', dummy_id, 'targetDir', 'TargetDirTest.h'));
+            });
+            it('should cp the file to the right target location when element has no target-dir', function() {
+                var headers = copyArray(valid_headers).filter(function(s) { return s.targetDir === undefined; });
+                var spy = spyOn(shell, 'cp');
+                install(headers[0], dummyPluginInfo, dummyProject);
+                expect(spy).toHaveBeenCalledWith('-f', path.join(dummyplugin, 'src', 'ios', 'DummyPluginCommand.h'), path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'DummyPluginCommand.h'));
+            });
+            it('should cp the file to the right target location when element has a target-dir', function() {
+                var headers = copyArray(valid_headers).filter(function(s) { return s.targetDir !== undefined; });
+                var spy = spyOn(shell, 'cp');
+                install(headers[0], dummyPluginInfo, dummyProject);
+                expect(spy).toHaveBeenCalledWith('-f', path.join(dummyplugin, 'src', 'ios', 'TargetDirTest.h'), path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'targetDir', 'TargetDirTest.h'));
+            });
+        });
+
+        describe('of <resource-file> elements', function() {
+            var install = pluginHandlers.getInstaller('resource-file');
+
+            beforeEach(function () {
+                spyOn(dummyProject.xcode, 'addResourceFile');
+            });
+
+            it('should throw if resource-file src cannot be found', function() {
+                var resources = copyArray(invalid_resources);
+                expect(function() {
+                    install(resources[0], faultyPluginInfo, dummyProject);
+                }).toThrow('cannot find "' + path.resolve(faultyplugin, 'src/ios/IDontExist.bundle') + '" ios <resource-file>');
+            });
+            it('should throw if resource-file target already exists', function() {
+                var resources = copyArray(valid_resources);
+                var target = path.join(temp, 'SampleApp', 'Resources', 'DummyPlugin.bundle');
+                shell.mkdir('-p', path.dirname(target));
+                fs.writeFileSync(target, 'some bs', 'utf-8');
+                expect(function() {
+                    install(resources[0], dummyPluginInfo, dummyProject);
+                }).toThrow('target destination "' + target + '" already exists');
+            });
+            it('should call into xcodeproj\'s addResourceFile', function() {
+                var resources = copyArray(valid_resources);
+                install(resources[0], dummyPluginInfo, dummyProject);
+                expect(dummyProject.xcode.addResourceFile)
+                    .toHaveBeenCalledWith(path.join('Resources', 'DummyPlugin.bundle'));
+            });
+            it('should cp the file to the right target location', function() {
+                var resources = copyArray(valid_resources);
+                var spy = spyOn(shell, 'cp');
+                install(resources[0], dummyPluginInfo, dummyProject);
+                expect(spy).toHaveBeenCalledWith('-R', path.join(dummyplugin, 'src', 'ios', 'DummyPlugin.bundle'), path.join(temp, 'SampleApp', 'Resources'));
+            });
+        });
+
+        describe('of <framework> elements', function() {
+
+            var install = pluginHandlers.getInstaller('framework');
+            beforeEach(function () {
+                spyOn(dummyProject.xcode, 'addFramework');
+            });
+
+            it('should call into xcodeproj\'s addFramework', function() {
+                var frameworks = copyArray(valid_custom_frameworks);
+                install(frameworks[0], dummyPluginInfo, dummyProject);
+                expect(dummyProject.xcode.addFramework)
+                    .toHaveBeenCalledWith(path.normalize('SampleApp/Plugins/org.test.plugins.dummyplugin/Custom.framework'), {customFramework:true});
+            });
+
+            // TODO: Add more tests to cover the cases:
+            // * framework with weak attribute
+            // * framework that shouldn't be added/removed
+
+            describe('with custom="true" attribute', function () {
+                it('should throw if framework src cannot be found', function() {
+                    var frameworks = copyArray(invalid_custom_frameworks);
+                    expect(function() {
+                        install(frameworks[0], faultyPluginInfo, dummyProject);
+                    }).toThrow('cannot find "' + path.resolve(faultyplugin, 'src/ios/NonExistantCustomFramework.framework') + '" ios <framework>');
+                });
+                it('should throw if framework target already exists', function() {
+                    var frameworks = copyArray(valid_custom_frameworks);
+                    var target = path.join(temp, 'SampleApp/Plugins/org.test.plugins.dummyplugin/Custom.framework');
+                    shell.mkdir('-p', target);
+                    expect(function() {
+                        install(frameworks[0], dummyPluginInfo, dummyProject);
+                    }).toThrow('target destination "' + target + '" already exists');
+                });
+                it('should cp the file to the right target location', function() {
+                    var frameworks = copyArray(valid_custom_frameworks);
+                    var spy = spyOn(shell, 'cp');
+                    install(frameworks[0], dummyPluginInfo, dummyProject);
+                    expect(spy).toHaveBeenCalledWith('-R', path.join(dummyplugin, 'src', 'ios', 'Custom.framework'),
+                                                     path.join(temp, 'SampleApp/Plugins/org.test.plugins.dummyplugin'));
+                });
+            });
+        });
+
+        it('of two plugins should apply xcode file changes from both', function(done){
+            var api = new Api('ios', temp);
+            var fail = jasmine.createSpy('fail');
+
+            api.addPlugin(dummyPluginInfo)
+            .then(function () {
+                return api.addPlugin(weblessPluginInfo);
+            })
+            .fail(fail)
+            .done(function() {
+                expect(fail).not.toHaveBeenCalled();
+
+                var xcode = projectFile.parse({
+                    root: temp,
+                    pbxproj: path.join(temp, 'SampleApp.xcodeproj/project.pbxproj')
+                }).xcode;
+
+                // from org.test.plugins.dummyplugin
+                expect(xcode.hasFile(slashJoin('Resources', 'DummyPlugin.bundle'))).toEqual(jasmine.any(Object));
+                expect(xcode.hasFile(slashJoin('Plugins','org.test.plugins.dummyplugin', 'DummyPluginCommand.h'))).toEqual(jasmine.any(Object));
+                expect(xcode.hasFile(slashJoin('Plugins','org.test.plugins.dummyplugin', 'DummyPluginCommand.m'))).toEqual(jasmine.any(Object));
+                expect(xcode.hasFile(slashJoin('Plugins','org.test.plugins.dummyplugin','targetDir','TargetDirTest.h'))).toEqual(jasmine.any(Object));
+                expect(xcode.hasFile(slashJoin('Plugins','org.test.plugins.dummyplugin','targetDir','TargetDirTest.m'))).toEqual(jasmine.any(Object));
+                expect(xcode.hasFile('usr/lib/libsqlite3.dylib')).toEqual(jasmine.any(Object));
+                expect(xcode.hasFile(slashJoin('SampleApp','Plugins','org.test.plugins.dummyplugin','Custom.framework'))).toEqual(jasmine.any(Object));
+                // from org.test.plugins.weblessplugin
+                expect(xcode.hasFile(slashJoin('Resources', 'WeblessPluginViewController.xib'))).toEqual(jasmine.any(Object));
+                expect(xcode.hasFile(slashJoin('Plugins','org.test.plugins.weblessplugin','WeblessPluginCommand.h'))).toEqual(jasmine.any(Object));
+                expect(xcode.hasFile(slashJoin('Plugins','org.test.plugins.weblessplugin','WeblessPluginCommand.m'))).toEqual(jasmine.any(Object));
+                expect(xcode.hasFile('usr/lib/libsqlite3.dylib')).toEqual(jasmine.any(Object));
+
+                done();
+            });
+        });
+    });
+
+    describe('uninstallation', function() {
+        describe('of <source-file> elements', function() {
+            var uninstall = pluginHandlers.getUninstaller('source-file');
+            beforeEach(function () {
+                spyOn(dummyProject.xcode, 'removeSourceFile');
+                spyOn(dummyProject.xcode, 'removeFramework');
+            });
+
+            it('should call into xcodeproj\'s removeSourceFile appropriately when element has no target-dir', function(){
+                var source = copyArray(valid_source).filter(function(s) { return s.targetDir === undefined; });
+                uninstall(source[0], dummyPluginInfo, dummyProject);
+                expect(dummyProject.xcode.removeSourceFile).toHaveBeenCalledWith(slashJoin('Plugins', dummy_id, 'DummyPluginCommand.m'));
+            });
+            it('should call into xcodeproj\'s removeSourceFile appropriately when element a target-dir', function(){
+                var source = copyArray(valid_source).filter(function(s) { return s.targetDir !== undefined; });
+                uninstall(source[0], dummyPluginInfo, dummyProject);
+                expect(dummyProject.xcode.removeSourceFile).toHaveBeenCalledWith(slashJoin('Plugins', dummy_id, 'targetDir', 'TargetDirTest.m'));
+            });
+            it('should rm the file from the right target location when element has no target-dir', function(){
+                var source = copyArray(valid_source).filter(function(s) { return s.targetDir === undefined; });
+                var spy = spyOn(shell, 'rm');
+                uninstall(source[0], dummyPluginInfo, dummyProject);
+                expect(spy).toHaveBeenCalledWith('-rf', path.join(temp, 'SampleApp', 'Plugins', dummy_id));
+            });
+            it('should rm the file from the right target location when element has a target-dir', function(){
+                var source = copyArray(valid_source).filter(function(s) { return s.targetDir !== undefined; });
+                var spy = spyOn(shell, 'rm');
+                uninstall(source[0], dummyPluginInfo, dummyProject);
+                expect(spy).toHaveBeenCalledWith('-rf', path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'targetDir'));
+            });
+            it('should call into xcodeproj\'s removeFramework appropriately when element framework=true set', function(){
+                var source = copyArray(valid_source).filter(function(s) { return s.framework; });
+                uninstall(source[0], dummyPluginInfo, dummyProject);
+                expect(dummyProject.xcode.removeFramework).toHaveBeenCalledWith(path.join('SampleApp', 'Plugins', dummy_id, 'SourceWithFramework.m'));
+            });
+        });
+
+        describe('of <header-file> elements', function() {
+            var uninstall = pluginHandlers.getUninstaller('header-file');
+            beforeEach(function () {
+                spyOn(dummyProject.xcode, 'removeHeaderFile');
+            });
+
+            it('should call into xcodeproj\'s removeHeaderFile appropriately when element has no target-dir', function(){
+                var headers = copyArray(valid_headers).filter(function(s) { return s.targetDir === undefined; });
+                uninstall(headers[0], dummyPluginInfo, dummyProject);
+                expect(dummyProject.xcode.removeHeaderFile).toHaveBeenCalledWith(slashJoin('Plugins', dummy_id, 'DummyPluginCommand.h'));
+            });
+            it('should call into xcodeproj\'s removeHeaderFile appropriately when element a target-dir', function(){
+                var headers = copyArray(valid_headers).filter(function(s) { return s.targetDir !== undefined; });
+                uninstall(headers[0], dummyPluginInfo, dummyProject);
+                expect(dummyProject.xcode.removeHeaderFile).toHaveBeenCalledWith(slashJoin('Plugins', dummy_id, 'targetDir', 'TargetDirTest.h'));
+            });
+            it('should rm the file from the right target location', function(){
+                var headers = copyArray(valid_headers).filter(function(s) { return s.targetDir !== undefined; });
+                var spy = spyOn(shell, 'rm');
+                uninstall(headers[0], dummyPluginInfo, dummyProject);
+                expect(spy).toHaveBeenCalledWith('-rf', path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'targetDir'));
+            });
+        });
+
+        describe('of <resource-file> elements', function() {
+            var uninstall = pluginHandlers.getUninstaller('resource-file');
+            beforeEach(function () {
+                spyOn(dummyProject.xcode, 'removeResourceFile');
+            });
+
+            it('should call into xcodeproj\'s removeResourceFile', function(){
+                var resources = copyArray(valid_resources);
+                uninstall(resources[0], dummyPluginInfo, dummyProject);
+                expect(dummyProject.xcode.removeResourceFile).toHaveBeenCalledWith(path.join('Resources', 'DummyPlugin.bundle'));
+            });
+            it('should rm the file from the right target location', function(){
+                var resources = copyArray(valid_resources);
+                var spy = spyOn(shell, 'rm');
+                uninstall(resources[0], dummyPluginInfo, dummyProject);
+                expect(spy).toHaveBeenCalledWith('-rf', path.join(temp, 'SampleApp', 'Resources', 'DummyPlugin.bundle'));
+            });
+        });
+
+        describe('of <framework> elements', function() {
+            var uninstall = pluginHandlers.getUninstaller('framework');
+            beforeEach(function () {
+                spyOn(dummyProject.xcode, 'removeFramework');
+            });
+
+            it('should call into xcodeproj\'s removeFramework', function(){
+                var frameworks = copyArray(valid_custom_frameworks);
+                uninstall(frameworks[0], dummyPluginInfo, dummyProject);
+                expect(dummyProject.xcode.removeFramework)
+                    .toHaveBeenCalledWith(path.join(temp, 'SampleApp/Plugins/org.test.plugins.dummyplugin/Custom.framework'), {customFramework:true});
+            });
+
+            // TODO: Add more tests to cover the cases:
+            // * framework with weak attribute
+            // * framework that shouldn't be added/removed
+
+            describe('with custom="true" attribute', function () {
+                it('should rm the file from the right target location', function(){
+                    var frameworks = copyArray(valid_custom_frameworks);
+                    var spy = spyOn(shell, 'rm');
+                    uninstall(frameworks[0], dummyPluginInfo, dummyProject);
+                    expect(spy).toHaveBeenCalledWith('-rf', path.join(temp, 'SampleApp/Plugins/org.test.plugins.dummyplugin/Custom.framework'));
+                });
+            });
+        });
+    });
+});


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org