You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by sh...@apache.org on 2016/08/15 23:26:50 UTC

ios commit: CB-9825 - Cocoapod integration for plugins

Repository: cordova-ios
Updated Branches:
  refs/heads/master 172349d63 -> 826db773d


CB-9825 - Cocoapod integration for plugins

This closes #234

Signed-off-by: Shazron Abdullah <sh...@apache.org>


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

Branch: refs/heads/master
Commit: 826db773df6b0297a9d0b2e7889b9a028a80fe5f
Parents: 172349d
Author: juliascript <ju...@gmail.com>
Authored: Fri Jul 1 11:51:36 2016 -0700
Committer: Shazron Abdullah <sh...@apache.org>
Committed: Mon Aug 15 16:30:11 2016 -0700

----------------------------------------------------------------------
 bin/templates/scripts/cordova/Api.js            | 127 +++++++++++++++-
 .../cordova/lib/plugman/pluginHandlers.js       |  41 +++--
 bin/templates/scripts/cordova/lib/podMod.js     | 148 +++++++++++++++++++
 .../plugin.xml                                  |  14 ++
 .../www/test.js                                 |   0
 .../sample-cordova-plugin-with-spec/plugin.xml  |  14 ++
 .../sample-cordova-plugin-with-spec/www/test.js |   0
 .../fixtures/testProj/platforms/ios/.gitignore  |   4 +
 tests/spec/unit/podMod.spec.js                  |  87 +++++++++++
 9 files changed, 418 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/826db773/bin/templates/scripts/cordova/Api.js
----------------------------------------------------------------------
diff --git a/bin/templates/scripts/cordova/Api.js b/bin/templates/scripts/cordova/Api.js
index 9a184d7..fe9f440 100644
--- a/bin/templates/scripts/cordova/Api.js
+++ b/bin/templates/scripts/cordova/Api.js
@@ -23,7 +23,6 @@ var fs = require('fs');
 var path = require('path');
 var unorm = require('unorm');
 var projectFile = require('./lib/projectFile');
-
 var CordovaError = require('cordova-common').CordovaError;
 var CordovaLogger = require('cordova-common').CordovaLogger;
 var events = require('cordova-common').events;
@@ -54,7 +53,6 @@ function setupEvents(externalEventEmitter) {
 function Api(platform, platformRootDir, events) {
     // 'platform' property is required as per PlatformApi spec
     this.platform = platform || 'ios';
-
     this.root = platformRootDir || path.resolve(__dirname, '..');
 
     setupEvents(events);
@@ -67,7 +65,6 @@ function Api(platform, platformRootDir, events) {
         if (!xcodeProjDir) {
             throw new CordovaError('The provided path "' + this.root + '" is not a Cordova iOS project.');
         }
-
         var cordovaProjName = xcodeProjDir.substring(xcodeProjDir.lastIndexOf(path.sep)+1, xcodeProjDir.indexOf('.xcodeproj'));
         xcodeCordovaProj = path.join(this.root, cordovaProjName);
     } catch(e) {
@@ -217,6 +214,91 @@ Api.prototype.addPlugin = function (plugin, installOptions) {
 
     return PluginManager.get(this.platform, this.locations, xcodeproj)
         .addPlugin(plugin, installOptions)
+        .then(function() {
+            var project_dir = this.locations.root;
+            var project_path = this.locations.xcodeProjDir;
+            var project_name = this.locations.xcodeCordovaProj.split('/').pop();
+            
+            if (plugin.getFrameworks(this.platform).length === 0) return;
+            events.emit('verbose', 'Adding pods since the plugin contained <framework>');
+                    
+            var pods_file = path.join(project_dir, 'pods.json');
+            var pods = {};
+            
+            try {
+                delete require.cache[require.resolve(pods_file)];
+                pods = require(pods_file);
+            } catch (e) { 
+                /* no pods.json exists */ 
+                // create an empty pods.json file 
+                fs.writeFileSync(pods_file, JSON.stringify({}));
+                delete require.cache[require.resolve(pods_file)];
+                pods = require(pods_file);
+            }  
+
+            var podMod = require('./lib/podMod');
+            var frameworkTags = plugin.getFrameworks(this.platform);
+
+            // filter framework tags for type "podspec" 
+            var array_of_pod_objects = frameworkTags.filter(function(obj){
+                return (obj.type == 'podspec'); 
+            });
+
+            var podIsAlreadyInPodfile;
+            var specForPodInSecondPluginIsDifferentFromSpecAlreadyInPodfile;
+            
+            array_of_pod_objects.forEach(function (obj) {
+                //check if pod already exists, if so if spec has changed 
+                //if pods.json does not exist yet, create it
+                // if it does not exist, only overwrite the type and spec, NOT the count
+                var nameOfPod = obj.src;
+
+                if(!pods[nameOfPod]) {
+                    pods[nameOfPod] = {'type': obj.type, 'spec': obj.spec};
+                    podIsAlreadyInPodfile = false;
+                } else {
+                    podIsAlreadyInPodfile = true;
+                    if (pods[nameOfPod].spec == obj.spec) {
+                        //same version
+                        pods[nameOfPod].spec = obj.spec;
+                        specForPodInSecondPluginIsDifferentFromSpecAlreadyInPodfile = false;
+                    } else {
+                        //different version
+                        //give warning, don't update anything
+                        specForPodInSecondPluginIsDifferentFromSpecAlreadyInPodfile = true;
+                        events.emit('warn', plugin.id + ' depends on ' + obj.src + '@' + obj.spec + ', which conflicts with another plugin. ' + obj.src + '@' + pods[nameOfPod].spec + ' is already installed and was not overwritten.');
+                    }
+                }
+
+                // add a count incase multiple plugins depend on it.
+                if (pods[nameOfPod].count) {
+                    pods[nameOfPod].count = pods[nameOfPod].count + 1;
+                } else {
+                    pods[nameOfPod].count = 1;
+                }
+
+                if (podIsAlreadyInPodfile) {
+                    try { 
+                       fs.writeFileSync(pods_file, JSON.stringify(pods, null, 4));
+                    } catch (e) {
+                        throw new CordovaError('\nPod was not able to be added to pods.json in Api.js\n\n' + e);
+                    }
+                } else if (!podIsAlreadyInPodfile) {
+                    //add the pods to the Podfile, then add to pods.json
+                    podMod.addToPodfileSync(project_name, project_path, nameOfPod, obj.spec, pods_file); 
+                    events.emit('verbose', 'About to add ' + nameOfPod + ' to pods json');
+                    //write out updated pods.json, 
+                    // keep track of the order of the pods
+                    try { 
+                        fs.writeFileSync(pods_file, JSON.stringify(pods, null, 4));
+                    } catch (e) {
+                        throw new CordovaError('\nPod was not able to be added to pods.json in Api.js\n\n' + e);
+                    }
+                }
+            });
+            events.emit('verbose', 'Running pod install');
+            podMod.installAllPods(project_dir, false);
+        }.bind(this))
         // CB-11022 return non-falsy value to indicate
         // that there is no need to run prepare after
         .thenResolve(true);
@@ -236,10 +318,47 @@ Api.prototype.addPlugin = function (plugin, installOptions) {
  *   CordovaError instance.
  */
 Api.prototype.removePlugin = function (plugin, uninstallOptions) {
-
     var xcodeproj = projectFile.parse(this.locations);
     return PluginManager.get(this.platform, this.locations, xcodeproj)
         .removePlugin(plugin, uninstallOptions)
+        .then(function() {
+            if (plugin.getFrameworks(this.platform).length === 0) return;
+                events.emit('verbose', 'Removing pods since the plugin contained <framework>');
+                //require script to run pod remove
+                //pods.json might not exist (if not pods were removed). 
+                //the pod will already be removed from pods.json at this stage
+                //need to check podfile and see if a pod exists in podfile that doesn't exist in pods.json. If so, remove it.
+
+                // which pods are in the plugin? 
+                var frameworkTags = plugin.getFrameworks(this.platform);
+                var project_dir = this.locations.root;
+                var pods_file = path.join(project_dir, 'pods.json');
+
+                delete require.cache[require.resolve(pods_file)];
+                var pods = require(pods_file);
+            
+                // filter framework tags for type "podspec" 
+                var array_of_pod_objects = frameworkTags.filter(function(obj){
+                    return (obj.type == 'podspec'); 
+                });
+
+                var podMod = require('./lib/podMod');
+                
+                array_of_pod_objects.forEach(function (obj) {
+                    // according to pods.json, does more than one plugin depend on the pod?
+                    if (pods[obj.src].count > 1) {
+                        // if so, only subtract one from the count in pods.json
+                        pods[obj.src].count = pods[obj.src].count - 1;
+                    } else {
+                        // if not, remove the pod from the Podfile 
+                        podMod.removeFromPodfileSync(project_dir, obj.src); 
+                        // update pods.json
+                        delete pods[obj.src];
+                    }
+                    fs.writeFileSync(pods_file, JSON.stringify(pods, null, 4));
+                });
+                podMod.installAllPods(project_dir, false);
+        }.bind(this))
         // CB-11022 return non-falsy value to indicate
         // that there is no need to run prepare after
         .thenResolve(true);

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/826db773/bin/templates/scripts/cordova/lib/plugman/pluginHandlers.js
----------------------------------------------------------------------
diff --git a/bin/templates/scripts/cordova/lib/plugman/pluginHandlers.js b/bin/templates/scripts/cordova/lib/plugman/pluginHandlers.js
index 5c432fa..40da442 100644
--- a/bin/templates/scripts/cordova/lib/plugman/pluginHandlers.js
+++ b/bin/templates/scripts/cordova/lib/plugman/pluginHandlers.js
@@ -66,17 +66,20 @@ var handlers = {
         install:function(obj, plugin, project, options) {
             var src = obj.src,
                 custom = obj.custom;
-
             if (!custom) {
                 var keepFrameworks = keep_these_frameworks;
 
-                if (keepFrameworks.indexOf(src) < 0) {
-                    project.xcode.addFramework(src, {weak: obj.weak});
-                    project.frameworks[src] = (project.frameworks[src] || 0) + 1;
+                if (keepFrameworks.indexOf(src) < 0) { 
+                    if (obj.type === 'podspec') {
+                        //podspec handled in Api.js
+                    } else {
+                        project.frameworks[src] = project.frameworks[src] || 0;
+                        project.frameworks[src]++;
+                        project.xcode.addFramework(src, {weak: obj.weak});
+                    }
                 }
                 return;
             }
-
             var srcFile = path.resolve(plugin.dir, src),
                 targetDir = path.resolve(project.plugins_dir, plugin.id, path.basename(src));
             if (!fs.existsSync(srcFile)) throw new CordovaError('Cannot find framework "' + srcFile + '" for plugin ' + plugin.id + ' in iOS platform');
@@ -91,18 +94,30 @@ var handlers = {
             }
         },
         uninstall:function(obj, plugin, project, options) {
+            var podsJSON = require(path.join(project.projectDir, 'pods.json'));
             var src = obj.src;
 
-            if (!obj.custom) {
+            if (!obj.custom) { //CB-9825 cocoapod integration for plugins
                 var keepFrameworks = keep_these_frameworks;
-
                 if (keepFrameworks.indexOf(src) < 0) {
-                    project.frameworks[src] = (project.frameworks[src] || 1) - 1;
-                    if (project.frameworks[src] < 1) {
-                        // Only remove non-custom framework from xcode project
-                        // if there is no references remains
-                        project.xcode.removeFramework(src);
-                        delete project.frameworks[src];
+                    if (obj.type === 'podspec') {
+                        if(podsJSON[src]) {
+                            if(podsJSON[src].count > 1) {
+                                podsJSON[src].count = podsJSON[src].count - 1;
+                            } else {
+                                delete podsJSON[src];
+                            }
+                        }
+                    } else {
+                        //this should be refactored 
+                        project.frameworks[src] = project.frameworks[src] || 1;
+                        project.frameworks[src]--;
+                        if (project.frameworks[src] < 1) {
+                            // Only remove non-custom framework from xcode project
+                            // if there is no references remains
+                            project.xcode.removeFramework(src);
+                            delete project.frameworks[src];
+                        }
                     }
                 }
                 return;

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/826db773/bin/templates/scripts/cordova/lib/podMod.js
----------------------------------------------------------------------
diff --git a/bin/templates/scripts/cordova/lib/podMod.js b/bin/templates/scripts/cordova/lib/podMod.js
new file mode 100644
index 0000000..7325fb2
--- /dev/null
+++ b/bin/templates/scripts/cordova/lib/podMod.js
@@ -0,0 +1,148 @@
+var fs = require('fs'),
+    path = require('path'),
+    util = require('util'),
+    events = require('cordova-common').events,
+    superspawn = require('cordova-common').superspawn,
+    CordovaError = require('cordova-common').CordovaError;
+
+var opts = {};
+/*
+-- After pods are installed in a .xcworkspace, all existing ios code needs to go into the WORKSPACE file -- will need to 
+    create a workspace file and then embed the Xcode project  
+
+        - Holly might have done some work on this, see the docs: 
+          https://github.com/phonegap/phonegap-webview-ios not sure how applicable it can be to our case
+*/
+function removeProjectFromPath (pathToProjectFile) {
+    var arrayOfDirectories = [];
+    //remove the project from the path
+    arrayOfDirectories = pathToProjectFile.split(path.sep);
+    arrayOfDirectories.pop();
+    var pathToProjectDirectory = arrayOfDirectories.join(path.sep);
+    return pathToProjectDirectory;
+}
+
+function createPodfile (projectName, pathToProjectFile) {
+    var pathToProjectDirectory = removeProjectFromPath(pathToProjectFile);
+    var pathToPodfile = path.join(pathToProjectDirectory, 'Podfile');
+    var podfileText = util.format('platform :ios, \'8.0\'\n\ntarget \'%s\' do\n\n  project \'%s\'\n\n  \n\nend' , projectName, pathToProjectFile);
+    fs.writeFileSync(pathToPodfile, podfileText);
+}
+
+function editPodfileSync (Podfile, pod, isRemoval) {
+    var podfileContents = fs.readFileSync(Podfile, 'utf8');
+    //split by \n, add in the pod after the project line, shift the rest down
+    var podfileContentsArray = podfileContents.split('\n');
+
+    if (isRemoval) {
+        var linesInPodfileToKeep = podfileContentsArray.filter(function(lineInPodfile) {
+            return (lineInPodfile.indexOf(pod) === -1);
+        });
+        
+        podfileContents = linesInPodfileToKeep.join('\n');
+    } else {
+        var lineNumberForInjectionWithinPodfile = 5;
+        podfileContentsArray.splice(lineNumberForInjectionWithinPodfile, 0, pod);
+        podfileContents = podfileContentsArray.join('\n');
+    }
+    return podfileContents;
+}
+
+function installAllPods (path, isPathToProjectFile) {
+    // change working directory for all calls of pod install to platforms/ios
+    if (isPathToProjectFile){
+        //if the path passed leads to the project, and not the dir that contains the proj
+         //remove the project from the path
+        path = removeProjectFromPath(path);
+    }
+    opts.cwd = path;
+    superspawn.spawn('pod', ['install'], opts);
+}
+
+function addToPodfileSync (projectName, pathToProjectFile, nameOfPod, podSpec, podsJSON) {
+    //  nameOfPod           = obj.src                   //from framework tag
+    //  podSpec             = obj.spec                  //from framework tag   
+    //  podsJSON            = pods.json file in cordovaProjectDir/platforms/ios/
+
+    // readFileSync will currently truncate the Podfile if it exists
+    // if a Podfile doesn't exist, one will be created
+
+    // this code will be run during cordova plugin add x -- which has to be run in the cordova project dir
+    
+    //-----------
+    //ERROR
+    //
+    //if no podName is specified, console err 
+    if (nameOfPod === '' || nameOfPod === ' '){
+        throw new CordovaError('\nERROR: name of pod is not specified\n');
+    }
+    //-----------
+
+    podSpec = podSpec || ''; //spec is optional
+    
+    var stringToWrite; //overwrites Podfile
+    var lineToInjectInPodfile; //adds pod
+    var pathToProject = removeProjectFromPath(pathToProjectFile);
+    var podfile = path.join(pathToProject, 'Podfile');
+    var podfileExistsInCurrentDirectory = fs.existsSync(podfile);
+    var podExistsInPodsJSON = podsJSON[nameOfPod];
+    var podRequestedForSpecChange;
+   
+    if (podSpec === '') {
+        lineToInjectInPodfile = util.format('pod \'%s\'', nameOfPod);
+        podRequestedForSpecChange = false;
+    } else {
+        if (podExistsInPodsJSON){
+            if (podsJSON[nameOfPod].spec !== podSpec){
+                podRequestedForSpecChange = true; 
+            }
+        } else {
+            lineToInjectInPodfile = util.format('pod \'%s\', \'%s\'', nameOfPod, podSpec);
+            podRequestedForSpecChange = false; 
+        }
+    }
+
+    //does Podfile exist in the current directory?
+    if (podfileExistsInCurrentDirectory) {
+        events.emit('verbose', 'Podfile found in platforms/ios');
+        //is the pod already in the Podfile? 
+        if (podExistsInPodsJSON) {
+            events.emit('verbose', 'Selected pod already exists in Podfile according to pods.json');
+            //if pod is in Podfile, is there a change in spec? 
+            if (podRequestedForSpecChange) {
+                //if spec change requested, it won't make it to this point-- TODO: rm this line 
+                events.emit('verbose', 'Pod requested for spec change');
+            } // no change in spec handled above
+        } else if (!podExistsInPodsJSON) {
+            //if pod not already in Podfile, inject the line in the existing Podfile
+            events.emit('verbose', 'Pod not found in Podfile. Injecting now...');
+            stringToWrite = editPodfileSync(podfile, lineToInjectInPodfile);
+        }
+    } else if (!podfileExistsInCurrentDirectory) {
+        //create the Podfile and inject the line
+        events.emit('verbose', 'Creating new Podfile in platforms/ios');
+        createPodfile(projectName, pathToProjectFile);
+        events.emit('verbose', 'Adding pod to Podfile');
+        stringToWrite = editPodfileSync(podfile, lineToInjectInPodfile);
+    }
+    
+    if (stringToWrite) {
+        events.emit('verbose', 'Overwriting Podfile');
+        fs.writeFileSync(podfile, stringToWrite, 'utf8');
+    } else {
+        //the code should have returned early by now
+    }
+    events.emit('verbose', 'Pods installed in xcode workspace in platforms/ios');
+}
+
+function removeFromPodfileSync (projectDirectory, pod) {
+    var podfile = path.join(projectDirectory, 'Podfile');
+    var stringToWrite = editPodfileSync(podfile, pod, true);
+    fs.writeFileSync(podfile, stringToWrite);
+}
+
+module.exports = {
+    addToPodfileSync        : addToPodfileSync,
+    removeFromPodfileSync   : removeFromPodfileSync,
+    installAllPods          : installAllPods
+};
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/826db773/tests/spec/unit/fixtures/sample-cocoapod-plugin-no-spec-overlapping-dependency/plugin.xml
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/sample-cocoapod-plugin-no-spec-overlapping-dependency/plugin.xml b/tests/spec/unit/fixtures/sample-cocoapod-plugin-no-spec-overlapping-dependency/plugin.xml
new file mode 100644
index 0000000..25eb367
--- /dev/null
+++ b/tests/spec/unit/fixtures/sample-cocoapod-plugin-no-spec-overlapping-dependency/plugin.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    id="sample-cocoapod-plugin-no-spec-overlapping-dependency"
+    version="1.1.3-dev">
+
+    <name>Test Plugin</name>
+
+    <asset src="www/test.js" target="test.js" />
+    <platform name="ios">
+        <framework src="AFNetworking" weak="false" type="podspec"/>
+    </platform>
+</plugin>
+

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/826db773/tests/spec/unit/fixtures/sample-cocoapod-plugin-no-spec-overlapping-dependency/www/test.js
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/sample-cocoapod-plugin-no-spec-overlapping-dependency/www/test.js b/tests/spec/unit/fixtures/sample-cocoapod-plugin-no-spec-overlapping-dependency/www/test.js
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/826db773/tests/spec/unit/fixtures/sample-cordova-plugin-with-spec/plugin.xml
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/sample-cordova-plugin-with-spec/plugin.xml b/tests/spec/unit/fixtures/sample-cordova-plugin-with-spec/plugin.xml
new file mode 100644
index 0000000..0d8bf9a
--- /dev/null
+++ b/tests/spec/unit/fixtures/sample-cordova-plugin-with-spec/plugin.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    id="sample-cordova-plugin-with-spec"
+    version="1.1.3-dev">
+
+    <name>Test Plugin</name>
+
+    <asset src="www/test.js" target="test.js" />
+    <platform name="ios">
+        <framework src="AFNetworking" spec="~> 2.0" weak="false" type="podspec"/>
+    </platform>
+</plugin>
+

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/826db773/tests/spec/unit/fixtures/sample-cordova-plugin-with-spec/www/test.js
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/sample-cordova-plugin-with-spec/www/test.js b/tests/spec/unit/fixtures/sample-cordova-plugin-with-spec/www/test.js
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/826db773/tests/spec/unit/fixtures/testProj/platforms/ios/.gitignore
----------------------------------------------------------------------
diff --git a/tests/spec/unit/fixtures/testProj/platforms/ios/.gitignore b/tests/spec/unit/fixtures/testProj/platforms/ios/.gitignore
new file mode 100644
index 0000000..86d0cb2
--- /dev/null
+++ b/tests/spec/unit/fixtures/testProj/platforms/ios/.gitignore
@@ -0,0 +1,4 @@
+# Ignore everything in this directory
+*
+# Except this file
+!.gitignore
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/826db773/tests/spec/unit/podMod.spec.js
----------------------------------------------------------------------
diff --git a/tests/spec/unit/podMod.spec.js b/tests/spec/unit/podMod.spec.js
new file mode 100644
index 0000000..c942fdb
--- /dev/null
+++ b/tests/spec/unit/podMod.spec.js
@@ -0,0 +1,87 @@
+var fs = require('fs'),
+	path = require('path'),
+	util = require('util'),
+	superspawn = require('cordova-common').superspawn,
+	CordovaError = require('cordova-common').CordovaError;
+
+var podMod = require(path.resolve(path.join(__dirname, '..', '..', '..', 'bin', 'templates', 'scripts', 'cordova', 'lib', 'podMod.js')));
+
+var fixtureProject = { 'path' : path.resolve(__dirname, 'fixtures', 'testProj'), 
+						'pathToProjectFile' : path.resolve(__dirname, 'fixtures', 'testProj', 'platforms', 'ios', 'HelloCordova.xcodeproj'),
+						'pathToProjectDirectory' : path.resolve(__dirname, 'fixtures', 'testProj', 'platforms', 'ios'),
+						'id' : 'testProj' };
+
+var samplePods = { 'AFNetworking' : 'AFNetworking', 
+					'emptyPod' : '' };
+var sampleSpec = { 'AFNetworkingSpec' : '~> 2.0', 
+					'emptySpec' : '' };
+var samplePodsJSON = { 'AFNetworkingPodsJSON' : {'AFNetworking' : {'count': 1, 'spec' : '~> 2.0'}},
+						'emptyPodsJSON' : {} };
+
+
+var fixturePodfile = path.resolve(__dirname, 'fixtures', 'testProj', 'platforms', 'ios', 'Podfile');
+
+
+// tests are nested in a describe to ensure clean up happens after all unit tests are run
+describe('unit tests for pod module', function () {
+
+	describe('tests', function () {
+		describe('installPodSync', function () {
+			beforeEach(function () {
+				spyOn(fs, 'writeFileSync').andCallThrough();
+			});
+
+			afterEach(function () {
+			    fs.writeFileSync(fixturePodfile, util.format('platform :ios, \'8.0\'\n\ntarget \'%s\' do\n\n  project \'%s\'\n\n  \n\nend' , fixtureProject.id, fixtureProject.pathToProjectFile));
+			});
+
+			it ('throws cordova error when no pod name provided', function () {
+				//expect cordova error to have been thrown
+				expect( function () { podMod.addToPodfileSync(fixtureProject.id, fixtureProject.pathToProjectFile, samplePods.emptyPod, sampleSpec.emptySpec, samplePodsJSON.emptyPodsJSON); } ).toThrow(new CordovaError('\nERROR: name of pod is not specified\n'));
+			});
+
+			it ('writes to the Podfile via fs.writeFileSync', function () {
+				podMod.addToPodfileSync(fixtureProject.id, fixtureProject.pathToProjectFile, samplePods.AFNetworking, sampleSpec.AFNetworkingSpec, samplePodsJSON.emptyPodsJSON);
+				expect(fs.writeFileSync).toHaveBeenCalled();
+			});
+
+			it ('does not write to Podfile when pod already installed', function () {
+				podMod.addToPodfileSync(fixtureProject.id, fixtureProject.pathToProjectFile, samplePods.AFNetworking, sampleSpec.AFNetworkingSpec, samplePodsJSON.AFNetworkingPodsJSON);
+				expect(fs.writeFileSync).not.toHaveBeenCalled();
+			});
+		});
+
+		describe('uninstallPodSync', function () {
+			beforeEach(function () {
+				spyOn(fs, 'writeFileSync').andCallThrough();
+			});
+
+			afterEach(function () {
+				fs.writeFileSync(fixturePodfile, util.format('platform :ios, \'8.0\'\n\ntarget \'%s\' do\n\n  project \'%s\'\n\n  \n\nend' , fixtureProject.id, fixtureProject.pathToProjectFile));
+			});
+
+			it ('removes pod from Podfile', function () {
+				podMod.removeFromPodfileSync(fixtureProject.pathToProjectDirectory, samplePods.AFNetworking);
+
+				expect(fs.writeFileSync).toHaveBeenCalled();
+				var fixturePodfileContent = fs.readFileSync(fixturePodfile, 'utf8');
+				expect(fixturePodfileContent.indexOf(samplePods.AFNetworking) === -1);
+			});
+		});
+
+		describe('installPodSuperspawn', function () {
+			beforeEach(function () {
+				spyOn(superspawn, 'spawn').andCallThrough();
+			});
+
+			it ('calls superspawn with pod install', function () {
+				podMod.installAllPods(fixtureProject.pathToProjectFile, true);
+				expect(superspawn.spawn).toHaveBeenCalled();
+			});
+		});
+	});
+
+	it('tear down', function () {
+		fs.unlinkSync(fixturePodfile);
+	});
+});
\ No newline at end of file


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