Fix null-access errors in "addTo/removeFrom*PbxGroup" methods

The project exposes a few methods to add/remove children from PbxGroups
* `addToPluginsPbxGroup` / `removeFromPluginsPbxGroup`
* `addToResourcesPbxGroup` / `removeFromResourcesPbxGroup`
* `addToFrameworksPbxGroup` / `removeFromFrameworksPbxGroup`
* `addToProductsPbxGroup` / `removeFromProductsPbxGroup`
which are used internally in:
* `addPluginFile` / `removePluginFile`
* `addResourceFile` / `removeResourceFile`
* `addProductFile` / `removeProductFile`
* `addFramework` / `removeFramework`

But neither of these methods do a check whether the `PbxGroup` actually
exists before trying to modify it - this can result in a possible
null-access error.
I ran into this problem when trying to add a framework to a project
which didn't have a `Frameworks` `PbxGroup`.

This commit adds checks to these methods to test for existence of the
`PbxGroup`s and creates them if they don't exist or does an early exit
in the case of removal.

 This closes #3
diff --git a/lib/pbxProject.js b/lib/pbxProject.js
index e2e88aa..4243f65 100644
--- a/lib/pbxProject.js
+++ b/lib/pbxProject.js
@@ -608,10 +608,17 @@
 
 pbxProject.prototype.addToPluginsPbxGroup = function(file) {
     var pluginsGroup = this.pbxGroupByName('Plugins');
-    pluginsGroup.children.push(pbxGroupChild(file));
+    if (!pluginsGroup) {
+        this.addPbxGroup([file.path], 'Plugins');
+    } else {
+        pluginsGroup.children.push(pbxGroupChild(file));
+    }
 }
 
 pbxProject.prototype.removeFromPluginsPbxGroup = function(file) {
+    if (!this.pbxGroupByName('Plugins')) {
+        return null;
+    }
     var pluginsGroupChildren = this.pbxGroupByName('Plugins').children, i;
     for (i in pluginsGroupChildren) {
         if (pbxGroupChild(file).value == pluginsGroupChildren[i].value &&
@@ -624,10 +631,17 @@
 
 pbxProject.prototype.addToResourcesPbxGroup = function(file) {
     var pluginsGroup = this.pbxGroupByName('Resources');
-    pluginsGroup.children.push(pbxGroupChild(file));
+    if (!pluginsGroup) {
+        this.addPbxGroup([file.path], 'Resources');
+    } else {
+        pluginsGroup.children.push(pbxGroupChild(file));
+    }
 }
 
 pbxProject.prototype.removeFromResourcesPbxGroup = function(file) {
+    if (!this.pbxGroupByName('Resources')) {
+        return null;
+    }
     var pluginsGroupChildren = this.pbxGroupByName('Resources').children, i;
     for (i in pluginsGroupChildren) {
         if (pbxGroupChild(file).value == pluginsGroupChildren[i].value &&
@@ -640,7 +654,11 @@
 
 pbxProject.prototype.addToFrameworksPbxGroup = function(file) {
     var pluginsGroup = this.pbxGroupByName('Frameworks');
-    pluginsGroup.children.push(pbxGroupChild(file));
+    if (!pluginsGroup) {
+        this.addPbxGroup([file.path], 'Frameworks');
+    } else {
+        pluginsGroup.children.push(pbxGroupChild(file));
+    }
 }
 
 pbxProject.prototype.removeFromFrameworksPbxGroup = function(file) {
@@ -680,10 +698,17 @@
 
 pbxProject.prototype.addToProductsPbxGroup = function(file) {
     var productsGroup = this.pbxGroupByName('Products');
-    productsGroup.children.push(pbxGroupChild(file));
+    if (!productsGroup) {
+        this.addPbxGroup([file.path], 'Products');
+    } else {
+        productsGroup.children.push(pbxGroupChild(file));
+    }
 }
 
 pbxProject.prototype.removeFromProductsPbxGroup = function(file) {
+    if (!this.pbxGroupByName('Products')) {
+        return null;
+    }
     var productsGroupChildren = this.pbxGroupByName('Products').children, i;
     for (i in productsGroupChildren) {
         if (pbxGroupChild(file).value == productsGroupChildren[i].value &&
diff --git a/test/group.js b/test/group.js
index b907c7e..b23d18e 100644
--- a/test/group.js
+++ b/test/group.js
@@ -1,4 +1,5 @@
 var pbx = require('../lib/pbxProject'),
+    pbxFile = require('../lib/pbxFile'),
     project,
     projectHash;
 
@@ -137,6 +138,85 @@
     }
 }
 
+exports.predefinedPbxGroups = {
+    setUp: function(callback) {
+        project = new pbx('test/parser/projects/empty-groups.pbxproj').parseSync();
+
+        this.file = new pbxFile('some-file.m');
+        this.file.fileRef = project.generateUuid();
+        project.addToPbxFileReferenceSection(this.file);
+
+        callback();
+    },
+
+    'should add a file to "Plugins" group': function(test) {
+        project.addToPluginsPbxGroup(this.file);
+        var foundInGroup = findChildInGroup(project.pbxGroupByName('Plugins'), this.file.fileRef);
+        test.ok(foundInGroup);
+        test.done();
+    },
+
+    'should remove a file from "Plugins" group': function(test) {
+        project.addToPluginsPbxGroup(this.file);
+        project.removeFromPluginsPbxGroup(this.file);
+
+        var foundInGroup = findChildInGroup(project.pbxGroupByName('Plugins'), this.file.fileRef);
+        test.ok(!foundInGroup);
+        test.done();
+    },
+
+    'should add a file to "Resources" group': function(test) {
+        project.addToResourcesPbxGroup(this.file);
+
+        var foundInGroup = findChildInGroup(project.pbxGroupByName('Resources'), this.file.fileRef);
+        test.ok(foundInGroup);
+        test.done();
+    },
+
+    'should remove a file from "Resources" group': function(test) {
+        project.addToResourcesPbxGroup(this.file);
+        project.removeFromResourcesPbxGroup(this.file);
+
+        var foundInGroup = findChildInGroup(project.pbxGroupByName('Resources'), this.file.fileRef);
+        test.ok(!foundInGroup);
+        test.done();
+    },
+
+    'should add a file to "Frameworks" group': function(test) {
+        project.addToFrameworksPbxGroup(this.file);
+
+        var foundInGroup = findChildInGroup(project.pbxGroupByName('Frameworks'), this.file.fileRef);
+        test.ok(foundInGroup);
+        test.done();
+    },
+
+    'should remove a file from "Frameworks" group': function(test) {
+        project.addToFrameworksPbxGroup(this.file);
+        project.removeFromFrameworksPbxGroup(this.file);
+
+        var foundInGroup = findChildInGroup(project.pbxGroupByName('Frameworks'), this.file.fileRef);
+        test.ok(!foundInGroup);
+        test.done();
+    },
+
+    'should add a file to "Products" group': function(test) {
+        project.addToProductsPbxGroup(this.file);
+
+        var foundInGroup = findChildInGroup(project.pbxGroupByName('Products'), this.file.fileRef);
+        test.ok(foundInGroup);
+        test.done();
+    },
+
+    'should remove a file from "Products" group': function(test) {
+        project.addToProductsPbxGroup(this.file);
+        project.removeFromProductsPbxGroup(this.file);
+
+        var foundInGroup = findChildInGroup(project.pbxGroupByName('Products'), this.file.fileRef);
+        test.ok(!foundInGroup);
+        test.done();
+    }
+};
+
 exports.addSourceFileToGroup = {
     'should create group + add source file' : function(test) {
         var testKey = project.pbxCreateGroup('Test', 'Test');
diff --git a/test/parser/projects/empty-groups.pbxproj b/test/parser/projects/empty-groups.pbxproj
new file mode 100644
index 0000000..6322052
--- /dev/null
+++ b/test/parser/projects/empty-groups.pbxproj
@@ -0,0 +1,16 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 45;
+	objects = {
+/* Begin PBXFileReference section */
+/* End PBXFileReference section */
+/* Begin PBXBuildFile section */
+/* End PBXBuildFile section */
+/* Begin PBXGroup section */
+/* End PBXGroup section */
+	};
+	rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
+}