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/4.1.x
Commit: c0db5e4ecfb4e2afa31fdb277620cc4ebcf7d7f3
Parents: 70e16ef
Author: Vladimir Kotikov <[email protected]>
Authored: Thu Mar 3 17:06:19 2016 +0300
Committer: Vladimir Kotikov <[email protected]>
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/[email protected]  |   1 +
 .../ios/WeblessPlugin.bundle/arrow_right.png    |   1 +
 .../ios/WeblessPlugin.bundle/[email protected] |   1 +
 .../ios/WeblessPlugin.bundle/but_refresh.png    |   1 +
 .../ios/WeblessPlugin.bundle/[email protected] |   1 +
 .../src/ios/WeblessPlugin.bundle/compass.png    |   1 +
 .../src/ios/WeblessPlugin.bundle/[email protected] |   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: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to