You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by fi...@apache.org on 2012/04/18 23:49:52 UTC

[31/37] spec commit: converted some more tests to jasmine

converted some more tests to jasmine


Project: http://git-wip-us.apache.org/repos/asf/incubator-cordova-mobile-spec/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cordova-mobile-spec/commit/5bef2694
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cordova-mobile-spec/tree/5bef2694
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cordova-mobile-spec/diff/5bef2694

Branch: refs/heads/master
Commit: 5bef2694448c00c4cd19e34a758216db0a6a9678
Parents: a364bd0
Author: Gord Tanner <gt...@gmail.com>
Authored: Wed Apr 4 15:40:19 2012 -0400
Committer: Fil Maj <ma...@gmail.com>
Committed: Mon Apr 16 16:05:16 2012 -0700

----------------------------------------------------------------------
 autotest/pages/accelerometer.html |    3 -
 autotest/pages/capture.html       |    3 -
 autotest/pages/compass.html       |   44 ++
 autotest/pages/contacts.html      |   44 ++
 autotest/pages/device.html        |   44 ++
 autotest/tests/compass.tests.js   |   98 +++-
 autotest/tests/contacts.tests.js  |  760 ++++++++++++++++----------------
 autotest/tests/device.tests.js    |   52 +--
 8 files changed, 622 insertions(+), 426 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cordova-mobile-spec/blob/5bef2694/autotest/pages/accelerometer.html
----------------------------------------------------------------------
diff --git a/autotest/pages/accelerometer.html b/autotest/pages/accelerometer.html
index 01b0970..266f1bf 100644
--- a/autotest/pages/accelerometer.html
+++ b/autotest/pages/accelerometer.html
@@ -95,6 +95,3 @@
 </body>
 >>>>>>> converted accel tests
 </html>
-
-
-

http://git-wip-us.apache.org/repos/asf/incubator-cordova-mobile-spec/blob/5bef2694/autotest/pages/capture.html
----------------------------------------------------------------------
diff --git a/autotest/pages/capture.html b/autotest/pages/capture.html
index 050e2af..abe2f2b 100644
--- a/autotest/pages/capture.html
+++ b/autotest/pages/capture.html
@@ -95,6 +95,3 @@
 </body>
 >>>>>>> converted capture tests
 </html>
-
-
-

http://git-wip-us.apache.org/repos/asf/incubator-cordova-mobile-spec/blob/5bef2694/autotest/pages/compass.html
----------------------------------------------------------------------
diff --git a/autotest/pages/compass.html b/autotest/pages/compass.html
index 1623a5e..84a6b3d 100644
--- a/autotest/pages/compass.html
+++ b/autotest/pages/compass.html
@@ -1,5 +1,6 @@
 <!DOCTYPE html>
 <html>
+<<<<<<< HEAD
   <head>
     <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
     <meta name="viewport" content="width=device-width, height=device-height, user-scalable=yes, initial-scale=1.0;" />
@@ -49,6 +50,49 @@
         </div>
     </body>
 </html>
+=======
+<head>
+  <title>Cordova: Compass API Specs</title>
 
+  <!-- Load jasmine -->
+  <link href="../jasmine.css" rel="stylesheet"/>
+  <script type="text/javascript" src="../jasmine.js"></script>
+  <script type="text/javascript" src="../html/HtmlReporterHelpers.js"></script>
+  <script type="text/javascript" src="../html/HtmlReporter.js"></script>
+  <script type="text/javascript" src="../html/ReporterView.js"></script>
+  <script type="text/javascript" src="../html/SpecView.js"></script>
+  <script type="text/javascript" src="../html/SuiteView.js"></script>
+  <script type="text/javascript" src="../html/TrivialReporter.js"></script>
 
+  <!-- Source -->
+  <script type="text/javascript" src="../../phonegap.js"></script>
 
+  <!-- Load Test Runner -->
+  <script type="text/javascript" src="../test-runner.js"></script>
+
+  <!-- Tests -->
+  <script type="text/javascript" src="../tests/compass.tests.js"></script>
+>>>>>>> converted some more tests to jasmine
+
+  <script type="text/javascript">
+    document.addEventListener('deviceready', function () {
+      var jasmineEnv = jasmine.getEnv();
+      jasmineEnv.updateInterval = 1000;
+
+      var htmlReporter = new jasmine.HtmlReporter();
+
+      jasmineEnv.addReporter(htmlReporter);
+
+      jasmineEnv.specFilter = function(spec) {
+        return htmlReporter.specFilter(spec);
+      };
+
+      jasmineEnv.execute();
+    }, false);
+  </script>
+</head>
+
+<body>
+  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/incubator-cordova-mobile-spec/blob/5bef2694/autotest/pages/contacts.html
----------------------------------------------------------------------
diff --git a/autotest/pages/contacts.html b/autotest/pages/contacts.html
index bbd8642..1d93515 100644
--- a/autotest/pages/contacts.html
+++ b/autotest/pages/contacts.html
@@ -1,5 +1,6 @@
 <!DOCTYPE html>
 <html>
+<<<<<<< HEAD
   <head>
     <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
     <meta name="viewport" content="width=device-width, height=device-height, user-scalable=yes, initial-scale=1.0;" />
@@ -49,6 +50,49 @@
         </div>
     </body>
 </html>
+=======
+<head>
+  <title>Cordova: Contacts API Specs</title>
 
+  <!-- Load jasmine -->
+  <link href="../jasmine.css" rel="stylesheet"/>
+  <script type="text/javascript" src="../jasmine.js"></script>
+  <script type="text/javascript" src="../html/HtmlReporterHelpers.js"></script>
+  <script type="text/javascript" src="../html/HtmlReporter.js"></script>
+  <script type="text/javascript" src="../html/ReporterView.js"></script>
+  <script type="text/javascript" src="../html/SpecView.js"></script>
+  <script type="text/javascript" src="../html/SuiteView.js"></script>
+  <script type="text/javascript" src="../html/TrivialReporter.js"></script>
 
+  <!-- Source -->
+  <script type="text/javascript" src="../../phonegap.js"></script>
 
+  <!-- Load Test Runner -->
+  <script type="text/javascript" src="../test-runner.js"></script>
+
+  <!-- Tests -->
+  <script type="text/javascript" src="../tests/contacts.tests.js"></script>
+>>>>>>> converted some more tests to jasmine
+
+  <script type="text/javascript">
+    document.addEventListener('deviceready', function () {
+      var jasmineEnv = jasmine.getEnv();
+      jasmineEnv.updateInterval = 1000;
+
+      var htmlReporter = new jasmine.HtmlReporter();
+
+      jasmineEnv.addReporter(htmlReporter);
+
+      jasmineEnv.specFilter = function(spec) {
+        return htmlReporter.specFilter(spec);
+      };
+
+      jasmineEnv.execute();
+    }, false);
+  </script>
+</head>
+
+<body>
+  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/incubator-cordova-mobile-spec/blob/5bef2694/autotest/pages/device.html
----------------------------------------------------------------------
diff --git a/autotest/pages/device.html b/autotest/pages/device.html
index 35a71bf..3373ce9 100644
--- a/autotest/pages/device.html
+++ b/autotest/pages/device.html
@@ -1,5 +1,6 @@
 <!DOCTYPE html>
 <html>
+<<<<<<< HEAD
   <head>
     <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
     <meta name="viewport" content="width=device-width, height=device-height, user-scalable=yes, initial-scale=1.0;" />
@@ -49,6 +50,49 @@
         </div>
     </body>
 </html>
+=======
+<head>
+  <title>Cordova: Device API Specs</title>
 
+  <!-- Load jasmine -->
+  <link href="../jasmine.css" rel="stylesheet"/>
+  <script type="text/javascript" src="../jasmine.js"></script>
+  <script type="text/javascript" src="../html/HtmlReporterHelpers.js"></script>
+  <script type="text/javascript" src="../html/HtmlReporter.js"></script>
+  <script type="text/javascript" src="../html/ReporterView.js"></script>
+  <script type="text/javascript" src="../html/SpecView.js"></script>
+  <script type="text/javascript" src="../html/SuiteView.js"></script>
+  <script type="text/javascript" src="../html/TrivialReporter.js"></script>
 
+  <!-- Source -->
+  <script type="text/javascript" src="../../phonegap.js"></script>
 
+  <!-- Load Test Runner -->
+  <script type="text/javascript" src="../test-runner.js"></script>
+
+  <!-- Tests -->
+  <script type="text/javascript" src="../tests/device.tests.js"></script>
+>>>>>>> converted some more tests to jasmine
+
+  <script type="text/javascript">
+    document.addEventListener('deviceready', function () {
+      var jasmineEnv = jasmine.getEnv();
+      jasmineEnv.updateInterval = 1000;
+
+      var htmlReporter = new jasmine.HtmlReporter();
+
+      jasmineEnv.addReporter(htmlReporter);
+
+      jasmineEnv.specFilter = function(spec) {
+        return htmlReporter.specFilter(spec);
+      };
+
+      jasmineEnv.execute();
+    }, false);
+  </script>
+</head>
+
+<body>
+  <a href="javascript:" class="backBtn" onclick="backHome();">Back</a>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/incubator-cordova-mobile-spec/blob/5bef2694/autotest/tests/compass.tests.js
----------------------------------------------------------------------
diff --git a/autotest/tests/compass.tests.js b/autotest/tests/compass.tests.js
index 438e23d..ff75b0f 100644
--- a/autotest/tests/compass.tests.js
+++ b/autotest/tests/compass.tests.js
@@ -1,14 +1,13 @@
-Tests.prototype.CompassTests = function() {
-  module('Compass (navigator.compass)');
-	test("should exist", function() {
-      expect(1);
-      ok(navigator.compass !== null, "navigator.compass should not be null.");
+describe('Compass (navigator.compass)', function () {
+	it("should exist", function() {
+      expect(navigator.compass).toBeDefined();
 	});
-	test("should contain a getCurrentHeading function", function() {
-		expect(2);
-		ok(typeof navigator.compass.getCurrentHeading != 'undefined' && navigator.compass.getCurrentHeading !== null, "navigator.compass.getCurrentHeading should not be null.");
-		ok(typeof navigator.compass.getCurrentHeading == 'function', "navigator.compass.getCurrentHeading should be a function.");
+
+	it("should contain a getCurrentHeading function", function() {
+        expect(navigator.compass.getCurrentHeading).toBeDefined();
+		expect(typeof navigator.compass.getCurrentHeading == 'function').toBe(true);
 	});
+<<<<<<< HEAD
 	test("getCurrentHeading success callback should be called with a Heading object", function() {
 		expect(9);
 		QUnit.stop(Tests.TEST_TIMEOUT);
@@ -26,26 +25,65 @@ Tests.prototype.CompassTests = function() {
 		};
 		var fail = function() { QUnit.start(); };
 		navigator.compass.getCurrentHeading(win, fail);
+=======
+
+	it("getCurrentHeading success callback should be called with a Heading object", function() {
+		var win = jasmine.createSpy().andCallFake(function(a) {
+                expect(a instanceof CompassHeading).toBe(true);
+                expect(a.magneticHeading).toBeDefined();
+                expect(typeof a.magneticHeading == 'number').toBe(true);
+                expect(a.trueHeading).not.toBe(undefined);
+                expect(typeof a.trueHeading == 'number' || a.trueHeading === null).toBe(true);
+                expect(a.headingAccuracy).not.toBe(undefined);
+                expect(typeof a.headingAccuracy == 'number' || a.headingAccuracy === null).toBe(true);
+                expect(a.timestamp instanceof Date).toBe(true);
+            }),
+            fail = jasmine.createSpy();
+
+        runs(function () {
+		    navigator.compass.getCurrentHeading(win, fail);
+        });
+
+        waitsFor(function () { return win.wasCalled; }, "win never called", Tests.TEST_TIMEOUT);
+
+        runs(function () {
+            expect(fail).not.toHaveBeenCalled();
+        });
+>>>>>>> converted some more tests to jasmine
 	});
-	test("should contain a watchHeading function", function() {
-		expect(2);
-		ok(typeof navigator.compass.watchHeading != 'undefined' && navigator.compass.watchHeading !== null, "navigator.compass.watchHeading should not be null.");
-		ok(typeof navigator.compass.watchHeading == 'function', "navigator.compass.watchHeading should be a function.");
+
+	it("should contain a watchHeading function", function() {
+        expect(navigator.compass.watchHeading).toBeDefined();
+		expect(typeof navigator.compass.watchHeading == 'function').toBe(true);
 	});
-	test("should contain a clearWatch function", function() {
-		expect(2);
-		ok(typeof navigator.compass.clearWatch != 'undefined' && navigator.compass.clearWatch !== null, "navigator.compass.clearWatch should not be null.");
-		ok(typeof navigator.compass.clearWatch == 'function', "navigator.compass.clearWatch should be a function!");
+
+	it("should contain a clearWatch function", function() {
+        expect(navigator.compass.clearWatch).toBeDefined();
+		expect(typeof navigator.compass.clearWatch == 'function').toBe(true);
 	});
 
-  module('Compass Constants (window.CompassError)');
-  test("CompassError globals should exist", function() {
-    expect(3);
-    ok(window.CompassError !== null, 'window.CompassError should not be null');
-    equals(window.CompassError.COMPASS_INTERNAL_ERR, 0, 'window.CompassError.COMPASS_INTERNAL_ERR should be 0');
-    equals(window.CompassError.COMPASS_NOT_SUPPORTED, 20, 'window.CompassError.COMPASS_NOT_SUPPORTED should be 20');
-  });
+    describe('Compass Constants (window.CompassError)', function () {
+        it("CompassError globals should exist", function() {
+            expect(window.CompassError).toBeDefined();
+            expect(window.CompassError.COMPASS_INTERNAL_ERR).toBe(0);
+            expect(window.CompassError.COMPASS_NOT_SUPPORTED).toBe(20);
+        });
+    });
+
+    describe('Compass Heading model (CompassHeading)', function () {
+        it("CompassHeading function should exist", function() {
+            expect(CompassHeading).toBeDefined();
+        });
+
+        it("Creating a new CompassHeading instance with no parameters", function() {
+            var h = new CompassHeading();
+            expect(h.magneticHeading).toBeDefined();
+            expect(h.trueHeading).toBeDefined();
+            expect(h.headingAccuracy).toBeDefined();
+            expect(h.timestamp instanceof Date).toBe(true);
+        });
 
+<<<<<<< HEAD
   module('Compass Heading model (CompassHeading)');
   test("CompassHeading function should exist", function() {
     expect(1);
@@ -70,3 +108,15 @@ Tests.prototype.CompassTests = function() {
     ok(typeof h.timestamp == 'number', "CompassHeading instance should have timestamp that is a number");
   });
 };
+=======
+        it("Creating a new CompassHeading instance with parameters", function() {
+            var h = new CompassHeading(1,2,3,4);
+            expect(h.magneticHeading).toBe(1);
+            expect(h.trueHeading).toBe(2);
+            expect(h.headingAccuracy).toBe(3);
+            expect(h.timestamp.valueOf()).toBe(4);
+            expect(h.timestamp instanceof Date).toBe(true);
+        });
+    });
+});
+>>>>>>> converted some more tests to jasmine

http://git-wip-us.apache.org/repos/asf/incubator-cordova-mobile-spec/blob/5bef2694/autotest/tests/contacts.tests.js
----------------------------------------------------------------------
diff --git a/autotest/tests/contacts.tests.js b/autotest/tests/contacts.tests.js
index bfba15c..b653394 100644
--- a/autotest/tests/contacts.tests.js
+++ b/autotest/tests/contacts.tests.js
@@ -12,414 +12,436 @@ var removeContact = function(){
     }
 };
 
-Tests.prototype.ContactsTests = function() {
-    module("Contacts (navigator.contacts)");
-    test("should exist", function() {
-        expect(1);
-        ok(navigator.contacts != null, "navigator.contacts should not be null.");
+describe("Contacts (navigator.contacts)", function () {
+    it("should exist", function() {
+        expect(navigator.contacts).toBeDefined();
     });
-    test("should contain a find function", function() {
-        expect(2);
-        ok(typeof navigator.contacts.find != 'undefined' && navigator.contacts.find != null, "navigator.contacts.find should not be null.");
-        ok(typeof navigator.contacts.find == 'function', "navigator.contacts.find should be a function.");
+
+    it("should contain a find function", function() {
+        expect(navigator.contacts.find).toBeDefined();
+        expect(typeof navigator.contacts.find == 'function').toBe(true);
     });
-    test("contacts.find success callback should be called with an array", function() {
-        expect(2);
-        QUnit.stop(15000);
-        var win = function(result) {
-            ok(typeof result == 'object', "Object returned in contacts.find success callback is of type 'object' (actually array).");
-            ok(typeof result.length == 'number', "Object returned in contacts.find success callback has a length property which is numerical.");
-            QUnit.start();
-        };
-        var fail = function() { QUnit.start(); };
-        var obj = new ContactFindOptions();
-        obj.filter="";
-        obj.multiple=true;
-        navigator.contacts.find(["displayName", "name", "phoneNumbers", "emails"], win, fail, obj);
+
+    it("contacts.find success callback should be called with an array", function() {
+        var win = jasmine.createSpy().andCallFake(function(result) {
+                expect(result).toBe(defined);
+                expect(typeof result.length == 'number').toBe(true);
+            }),
+            fail = jasmine.createSpy(),
+            obj = new ContactFindOptions();
+
+        runs(function () {
+            obj.filter="";
+            obj.multiple=true;
+            navigator.contacts.find(["displayName", "name", "phoneNumbers", "emails"], win, fail, obj);
+        });
+
+        waitsFor(function () { return win.wasCalled; }, "win never called", Tests.TEST_TIMEOUT);
+
+        runs(function () {
+            expect(fail).not.toHaveBeenCalled();
+        });
     }); 
-    test("contacts.find success callback should not be null", function() {
-        expect(1);
+
+    it("contacts.find success callback should not be null", function() {
         var fail = function() {};
         var obj = new ContactFindOptions();
+        var ex;
         obj.filter="";
         obj.multiple=true;
-        try {
+
+        expect(function () {
             navigator.contacts.find(["displayName", "name", "emails", "phoneNumbers"], null, fail, obj);
-        } catch(e) {
-            ok(true, "Trying to find with a null success call back should throw TypeError.");
-        }
+        }).toThrow();
     }); 
-    test("contacts.find error callback should be called when no fields are specified", function() {
-        expect(2);
-        QUnit.stop(Tests.TEST_TIMEOUT);
-        var win = function(result) {
-            ok(false, "Success callback should not fire in this test, failed.");
-            QUnit.start();
-        };
-        var fail = function(result) { 
-            ok(typeof result == 'object', "Object returned in contact.find failure callback is of type 'object' (actually ContactError).");
-            ok(result.code == ContactError.INVALID_ARGUMENT_ERROR, "Object returned in contacts.find failure callback has a code property which equal to ContactError.INVALID_ARGUMENT_ERROR.");
-            QUnit.start(); 
-        };
-        var obj = new ContactFindOptions();
-        obj.filter="";
-        obj.multiple=true;
-        navigator.contacts.find([], win, fail, obj);
-    });
-    module("contacts.find with newly-created contact", {
-        setup:function() {},
-        teardown:removeContact
+
+    it("contacts.find error callback should be called when no fields are specified", function() {
+        var win = jasmine.createSpy(),
+            fail = jasmine.createSpy(function(result) { 
+                expect(typeof result).toBe('object');
+                expect(result.code).toBe(ContactError.INVALID_ARGUMENT_ERROR);
+            }),
+            obj = new ContactFindOptions();
+
+        runs(function () {
+            obj.filter="";
+            obj.multiple=true;
+            navigator.contacts.find([], win, fail, obj);
+        });
+
+        waitsFor(function () { return win.wasCalled; }, Tests.TEST_TIMEOUT);
+
+        runs(function () { 
+            expect(win).not.toHaveBeenCalled();
+        });
     });
-    test("find a contact by name", function() {
-        expect(4);
-        QUnit.stop(7000);
-        // ----
-        // Helper save/create invocations+asserts
-        // ----
-        gContactObj = new Contact();
-        gContactObj.name = new ContactName();
-        gContactObj.name.familyName = "Delete";
-        gContactObj.save(
-            function(savedContact) {
-                ok(true, "Contact's save success callback needs to fire for this test to pass");
+
+    describe("contacts.find with newly-created contact", function () {
+
+        afterEach(removeContact);
+
+        it("find a contact by name", function() {
+            var test = function (savedContact) {
                 // update so contact will get removed
                 gContactObj = savedContact;
                 // ----
                 // Find asserts
                 // ---
-                var findWin = function(object) {
-                    var foundName = function(result) {
-                        var bFound = false;
-                        try {
-                            for (var i=0; i < result.length; i++) {
-                                if (result[i].name.familyName == "Delete") {
-                                    bFound = true;
-                                    break;
+                var findWin = jasmine.createSpy().andCallFake(function(object) {
+                        var foundName = function(result) {
+                            var bFound = false;
+                            try {
+                                for (var i=0; i < result.length; i++) {
+                                    if (result[i].name.familyName == "Delete") {
+                                        bFound = true;
+                                        break;
+                                    }
                                 }
-                            }
-                        } catch(e) {
-                            return false;
-                        } 
-                        return bFound;
-                    }         
-                    ok(object instanceof Array, "Object returned in contacts.find success callback should be instanceof array.");
-                    ok(object.length >= 1, "length of Object returned in contacts.find success callback should have length property >= 1");
-                    ok(foundName(object) == true, "returned contact array should contain a contact with familyName of 'Delete'.");
-                    QUnit.start();
-                };
-                var findFail = function() { 
-                    ok(false, "find method's error callback called, test failed.");
-                    QUnit.start(); 
-                };
-                var obj = new ContactFindOptions();
+                            } catch(e) {
+                                return false;
+                            } 
+                            return bFound;
+                        };         
+                        expect(object instanceof Array).toBe(true);
+                        expect(object.length >= 1).toBe(true);
+                        expect(foundName(object)).toBe(true);
+                        done = true;
+                    }),
+                    findFail = jasmine.createSpy(),
+                    obj = new ContactFindOptions();
+
                 obj.filter="Delete";
                 obj.multiple=true;
-                navigator.contacts.find(["displayName", "name", "phoneNumbers", "emails"], findWin, findFail, obj);
-        },
-        function(e){
-              ok(false, "Contact's save error callback fired; this test cannot continue");
-              QUnit.start();
+
+                runs(function () {
+                    navigator.contacts.find(["displayName", "name", "phoneNumbers", "emails"], findWin, findFail, obj);
+                });
+
+                waitsFor(function () { return foundName.wasCalled; }, "test not done", Tests.TEST_TIMEOUT);
+
+                runs(function () {
+                    expect(findFail).not.toHaveBeenCalled();
+                });
+            },
+            done = false,
+            fail = jasmine.createSpy();
+
+            runs(function () {
+                gContactObj = new Contact();
+                gContactObj.name = new ContactName();
+                gContactObj.name.familyName = "Delete";
+                gContactObj.save(test, fail);
+            });
+
+            waitsFor(function () { return done; }, "test not done", Tests.TEST_TIMEOUT);
+
+            runs(function () {
+                expect(fail).not.toHaveBeenCalled();
+            });
         });
     });
-    module("Contacts (navigator.contacts)");
-    test("should contain a create function", function() {
-        expect(2);
-        ok(typeof navigator.contacts.create != 'undefined' && navigator.contacts.create != null, "navigator.contacts.create should not be null.");
-        ok(typeof navigator.contacts.create == 'function', "navigator.contacts.create should be a function.");
-    });
-    test("contacts.create should return a Contact object", function() {
-        expect(9);
-        var bDay = new Date(1976, 7,4);
-        var obj = navigator.contacts.create({"displayName": "test name", "gender": "male", "note": "my note", "name": {"formatted": "Mr. Test Name"}, "emails": [{"value": "here@there.com"}, {"value": "there@here.com"}], "birthday": bDay});		
-        ok(obj != 'undefined' && obj != null, "navigator.contacts.create should return a Contact object.");
-        ok(obj.displayName == 'test name', "Contact should contain a displayName property.");
-        ok(obj.note == 'my note', "Contact should contain a note property.");
-        ok(obj.name.formatted == 'Mr. Test Name', "Contact should contain a name.formatted property.");
-        ok(obj.emails.length == 2, "Contact should contain and array of emails with 2 entries");
-        ok(obj.emails[0].value == 'here@there.com', "Contact.emails[1] should contain a value.");
-        ok(obj.emails[1].value == 'there@here.com', "Contact.emails[2] should contain a value.");	
-        ok(obj.nickname == null, "Contact object should not contain a nickname property.");
-        ok(obj.birthday instanceof Date && obj.birthday == bDay, "Contact should be a Date object equal to " + bDay);
+
+    describe("Contacts (navigator.contacts)", function () {
+        it("should contain a create function", function() {
+            expect(navigator.contacts.create).toBeDefined();
+            expect(typeof navigator.contacts.create).toBe('function');
+        });
+
+        it("contacts.create should return a Contact object", function() {
+            var bDay = new Date(1976, 7,4);
+            var obj = navigator.contacts.create({"displayName": "test name", "gender": "male", "note": "my note", "name": {"formatted": "Mr. Test Name"}, "emails": [{"value": "here@there.com"}, {"value": "there@here.com"}], "birthday": bDay});		
+
+            expect(obj).toBeDefined();
+            expect(obj.displayName).toBe('test name');
+            expect(obj.note).toBe('my note');
+            expect(obj.name.formatted).toBe('Mr. Test Name');
+            expect(obj.emails.length).toBe(2);
+            expect(obj.emails[0].value).toBe('here@there.com');
+            expect(obj.emails[1].value).toBe('there@here.com');
+            expect(obj.nickname).toBe(null);
+            expect(obj.birthday).toBe(bDay);
+        });
     });
-    module("Contact model");
-    test("should be able to define a Contact object", function() {
-        expect(15);
-        var contact = new Contact("a", "b", new ContactName("a", "b", "c", "d", "e", "f"), "c", [], [], [], [], [], "f", "i",  
-            [], [], []);
-        ok(contact != null, "new Contact() should not be null.");
-        ok(typeof contact.id != 'undefined' && contact.id != null && contact.id == "a", "new Contact() should include a 'id' property.");
-        ok(typeof contact.displayName != 'undefined' && contact.displayName != null && contact.displayName == "b", "new Contact() should include a 'displayName' property.");
-        ok(typeof contact.name != 'undefined' && contact.name != null && contact.name.formatted == "a", "new Contact() should include a 'name' property.");
-        ok(typeof contact.nickname != 'undefined' && contact.nickname != null && contact.nickname == "c", "new Contact() should include a 'nickname' property.");
-        ok(typeof contact.phoneNumbers != 'undefined' && contact.phoneNumbers != null, "new Contact() should include a 'phoneNumbers' property.");
-        ok(typeof contact.emails != 'undefined' && contact.emails != null, "new Contact() should include a 'emails' property.");
-        ok(typeof contact.addresses != 'undefined' && contact.addresses != null, "new Contact() should include a 'addresses' property.");
-        ok(typeof contact.ims != 'undefined' && contact.ims != null, "new Contact() should include a 'ims' property.");
-        ok(typeof contact.organizations != 'undefined' && contact.organizations != null, "new Contact() should include a 'organizations' property.");
-        ok(typeof contact.birthday != 'undefined' && contact.birthday != null && contact.birthday == "f", "new Contact() should include a 'birthday' property.");
-        ok(typeof contact.note != 'undefined' && contact.note != null && contact.note == "i", "new Contact() should include a 'note' property.");
-        ok(typeof contact.photos != 'undefined' && contact.photos != null, "new Contact() should include a 'photos' property.");
-        ok(typeof contact.categories != 'undefined' && contact.categories != null, "new Contact() should include a 'categories' property.");
-        ok(typeof contact.urls != 'undefined' && contact.urls != null, "new Contact() should include a 'urls' property.");
-    });	
-    test("should be able to define a ContactName object", function() {
-        expect(7);
-        var contactName = new ContactName("Dr. First Last Jr.", "Last", "First", "Middle", "Dr.", "Jr.");
-        ok(contactName != null, "new ContactName() should not be null.");
-        ok(typeof contactName.formatted != 'undefined' && contactName.formatted != null && contactName.formatted == "Dr. First Last Jr.", "new ContactName() should include a 'formatted' property.");
-        ok(typeof contactName.familyName != 'undefined' && contactName.familyName != null && contactName.familyName == "Last", "new ContactName() should include a 'familyName' property.");
-        ok(typeof contactName.givenName != 'undefined' && contactName.givenName != null && contactName.givenName == "First", "new ContactName() should include a 'givenName' property.");
-        ok(typeof contactName.middleName != 'undefined' && contactName.middleName != null && contactName.middleName == "Middle", "new ContactName() should include a 'middleName' property.");
-        ok(typeof contactName.honorificPrefix != 'undefined' && contactName.honorificPrefix != null && contactName.honorificPrefix == "Dr.", "new ContactName() should include a 'honorificPrefix' property.");
-        ok(typeof contactName.honorificSuffix != 'undefined' && contactName.honorificSuffix != null && contactName.honorificSuffix == "Jr.", "new ContactName() should include a 'honorificSuffix' property.");
-    });	
-    test("should be able to define a ContactField object", function() {
-        expect(4);
-        var contactField = new ContactField("home", "8005551212", true);
-        ok(contactField != null, "new ContactField() should not be null.");
-        ok(typeof contactField.type != 'undefined' && contactField.type != null && contactField.type == "home", "new ContactField() should include a 'type' property.");
-        ok(typeof contactField.value != 'undefined' && contactField.value != null && contactField.value == "8005551212", "new ContactField() should include a 'value' property.");
-        ok(typeof contactField.pref != 'undefined' && contactField.pref != null && contactField.pref == true, "new ContactField() should include a 'pref' property.");
-    });	
-    test("should be able to define a ContactAddress object", function() {
-        expect(9);
-        var contactAddress = new ContactAddress(true, "home", "a","b","c","d","e","f");
-        ok(contactAddress != null, "new ContactAddress() should not be null.");
-        ok(typeof contactAddress.pref != 'undefined' && contactAddress.pref != null && contactAddress.pref == true, "new ContactAddress() should include a 'pref' property.");
-        ok(typeof contactAddress.type != 'undefined' && contactAddress.type != null && contactAddress.type == "home", "new ContactAddress() should include a 'type' property.");
-        ok(typeof contactAddress.formatted != 'undefined' && contactAddress.formatted != null && contactAddress.formatted == "a", "new ContactAddress() should include a 'formatted' property.");
-        ok(typeof contactAddress.streetAddress != 'undefined' && contactAddress.streetAddress != null && contactAddress.streetAddress == "b", "new ContactAddress() should include a 'streetAddress' property.");
-        ok(typeof contactAddress.locality != 'undefined' && contactAddress.locality != null && contactAddress.locality == "c", "new ContactAddress() should include a 'locality' property.");
-        ok(typeof contactAddress.region != 'undefined' && contactAddress.region != null && contactAddress.region == "d", "new ContactAddress() should include a 'region' property.");
-        ok(typeof contactAddress.postalCode != 'undefined' && contactAddress.postalCode != null && contactAddress.postalCode == "e", "new ContactAddress() should include a 'postalCode' property.");
-        ok(typeof contactAddress.country != 'undefined' && contactAddress.country != null && contactAddress.country == "f", "new ContactAddress() should include a 'country' property.");
-    });	
-    test("should be able to define a ContactOrganization object", function() {
-        expect(6);
-        var contactOrg = new ContactOrganization(true, "home", "a","b","c","d","e","f","g");
-        ok(contactOrg != null, "new ContactOrganization() should not be null.");
-        ok(typeof contactOrg.pref != 'undefined' && contactOrg.pref != null && contactOrg.pref == true, "new ContactOrganization() should include a 'pref' property.");
-        ok(typeof contactOrg.type != 'undefined' && contactOrg.type != null && contactOrg.type == "home", "new ContactOrganization() should include a 'type' property.");
-        ok(typeof contactOrg.name != 'undefined' && contactOrg.name != null && contactOrg.name == "a", "new ContactOrganization() should include a 'name' property.");
-        ok(typeof contactOrg.department != 'undefined' && contactOrg.department != null && contactOrg.department == "b", "new ContactOrganization() should include a 'department' property.");
-        ok(typeof contactOrg.title != 'undefined' && contactOrg.title != null && contactOrg.title == "c", "new ContactOrganization() should include a 'title' property.");
-    });	
-    test("should be able to define a ContactFindOptions object", function() {
-        expect(3);
-        var contactFindOptions = new ContactFindOptions("a", true, "b");
-        ok(contactFindOptions != null, "new ContactFindOptions() should not be null.");
-        ok(typeof contactFindOptions.filter != 'undefined' && contactFindOptions.filter != null && contactFindOptions.filter == "a", "new ContactFindOptions() should include a 'filter' property.");
-        ok(typeof contactFindOptions.multiple != 'undefined' && contactFindOptions.multiple != null && contactFindOptions.multiple == true, "new ContactFindOptions() should include a 'multiple' property.");
-    });	
-    module("Contact Object");
-    test("should contain a clone function", function() {
-        expect(2);
-        var contact = new Contact();
-        ok(typeof contact.clone != 'undefined' && contact.clone != null, "contact.clone should not be null.");
-        ok(typeof contact.clone == 'function', "contact.clone should be a function.");
+
+    describe("Contact model", function () {
+        it("should be able to define a Contact object", function() {
+            var contact = new Contact("a", "b", new ContactName("a", "b", "c", "d", "e", "f"), "c", [], [], [], [], [], "f", "i",  
+                [], [], []);
+            expect(contact).toBeDefined();
+            expect(contact.id).toBe("a");
+            expect(contact.displayName).toBe("b");
+            expect(contact.name.formatted).toBe("a");
+            expect(contact.nickname).toBe("c");
+            expect(contact.phoneNumbers).toBeDefined();
+            expect(contact.emails).toBeDefined();
+            expect(contact.addresses).toBeDefined();
+            expect(contact.ims).toBeDefined();
+            expect(contact.organizations).toBeDefined();
+            expect(contact.birthday).toBe("f");
+            expect(contact.note).toBe("i");
+            expect(contact.photos).toBeDefined();
+            expect(contact.categories).toBeDefined();
+            expect(contact.urls).toBeDefined();
+        });	
+
+        it("should be able to define a ContactName object", function() {
+            var contactName = new ContactName("Dr. First Last Jr.", "Last", "First", "Middle", "Dr.", "Jr.");
+            expect(contactName).toBeDefined();
+            expect(contactName.formatted).toBe("Dr. First Last Jr.");
+            expect(contactName.familyName).toBe("Last");
+            expect(contactName.givenName).toBe("First");
+            expect(contactName.middleName).toBe("Middle");
+            expect(contactName.honorificPrefix).toBe("Dr.");
+            expect(contactName.honorificSuffix).toBe("Jr.");
+        });	
+
+        it("should be able to define a ContactField object", function() {
+            var contactField = new ContactField("home", "8005551212", true);
+            expect(contactField).toBeDefined();
+            expect(contactField.type).toBe("home");
+            expect(contactField.value).toBe("8005551212");
+            expect(contactField.pref).toBe(true);
+        });	
+
+        it("should be able to define a ContactAddress object", function() {
+            var contactAddress = new ContactAddress(true, "home", "a","b","c","d","e","f");
+            expect(contactAddress).toBeDefined();
+            expect(contactAddress.pref).toBe(true);
+            expect(contactAddress.type).toBe("home");
+            expect(contactAddress.formatted).toBe("a");
+            expect(contactAddress.streetAddress).toBe("b");
+            expect(contactAddress.locality).toBe("c");
+            expect(contactAddress.region).toBe("d");
+            expect(contactAddress.postalCode).toBe("e");
+            expect(contactAddress.country).toBe("f");
+        });	
+
+        it("should be able to define a ContactOrganization object", function() {
+            var contactOrg = new ContactOrganization(true, "home", "a","b","c","d","e","f","g");
+            expect(contactOrg).toBeDefined();
+            expect(contactOrg.pref).toBe(true);
+            expect(contactOrg.type).toBe("home");
+            expect(contactOrg.name).toBe("a");
+            expect(contactOrg.department).toBe("b");
+            expect(contactOrg.title).toBe("c");
+        });	
+
+        it("should be able to define a ContactFindOptions object", function() {
+            var contactFindOptions = new ContactFindOptions("a", true, "b");
+            expect(contactFindOptions).toBeDefined();
+            expect(contactFindOptions.filter).toBe("a");
+            expect(contactFindOptions.multiple).toBe(true);
+        });	
     });
-    test("clone function should make deep copy of Contact Object", function() {
-        expect(8);
-        var contact = new Contact();
-        contact.id=1;
-        contact.displayName="Test Name";
-        contact.nickname="Testy";
-        contact.gender="male";
-        contact.note="note to be cloned";
-        contact.name = new ContactName("Mr. Test Name");
-        
-        var clonedContact = contact.clone();
+
+    describe("Contact Object", function () {
+        it("should contain a clone function", function() {
+            var contact = new Contact();
+            expect(contact.clone).toBeDefined();
+            expect(typeof contact.clone).toBe('function');
+        });
+
+        it("clone function should make deep copy of Contact Object", function() {
+            var contact = new Contact();
+            contact.id=1;
+            contact.displayName="Test Name";
+            contact.nickname="Testy";
+            contact.gender="male";
+            contact.note="note to be cloned";
+            contact.name = new ContactName("Mr. Test Name");
+            
+            var clonedContact = contact.clone();
+            
+            expect(contact.id).toBe(1);
+            expect(clonedContact.id).toBe(null);
+            expect(clonedContact.displayName).toBe(contact.displayName);
+            expect(clonedContact.nickname).toBe(contact.nickname);
+            expect(clonedContact.gender).toBe(contact.gender);
+            expect(clonedContact.note).toBe(contact.note);
+            expect(clonedContact.name.formatted).toBe(contact.name.formatted);
+            expect(clonedContact.connected).toBe(contact.connected);
+        });
         
-        ok(contact.id == 1, "contact.id should be 1.");
-        ok(clonedContact.id == null, "clonedContact.id should be null.");
-        ok(clonedContact.displayName == contact.displayName, "displayName's should be equal");
-        ok(clonedContact.nickname == contact.nickname, "nickname's should be equal");
-        ok(clonedContact.gender == contact.gender, "gender's should be equal");
-        ok(clonedContact.note == contact.note, "note's should be equal");
-        ok(clonedContact.name.formatted == contact.name.formatted, "name.formatted's should be equal");
-        ok(clonedContact.connected == contact.connected, "connected's should be equal (null)");
-    });
-    test("should contain a save function", function() {
-        expect(2);
-        var contact = new Contact();
-        ok(typeof contact.save != 'undefined' && contact.save != null, "contact.save should not be null.");
-        ok(typeof contact.save == 'function', "contact.save should be a function.");
-    });
-    test("should contain a remove function", function() {
-        expect(2);
-        var contact = new Contact();
-        ok(typeof contact.remove != 'undefined' && contact.remove != null, "contact.remove should not be null.");
-        ok(typeof contact.remove == 'function', "contact.remove should be a function.");
-    });
-    module('Contact.save method', {
-        setup:function(){},
-        teardown:function(){}
-    });
-    test("should be able to save a contact", function() {
-        QUnit.stop(Tests.TEST_TIMEOUT);
-        expect(9);
-
-        var bDay = new Date(1976, 6,4);
-        gContactObj = navigator.contacts.create({"gender": "male", "note": "my note", "name": {"familyName": "Delete", "givenName": "Test"}, "emails": [{"value": "here@there.com"}, {"value": "there@here.com"}], "birthday": bDay});	
-
-        var saveSuccess = function(obj) {
-            ok(obj != 'undefined' && obj != null, "navigator.contacts.save should return a Contact object.");
-            ok(obj.note == 'my note', "Contact should contain a note property.");
-            ok(obj.name.familyName == 'Delete', "Contact familyName should equal 'Delete'.");
-            ok(obj.name.givenName == 'Test', "Contact givenName should equal 'Test'.");
-            ok(obj.emails.length == 2, "Contact should contain and array of emails with 2 entries.");
-            ok(obj.emails[0].value == 'here@there.com', "Contact.emails[1] should contain a value.");
-            ok(obj.emails[1].value == 'there@here.com', "Contact.emails[2] should contain a value.");	
-            ok(obj.birthday instanceof Date && obj.birthday.toDateString() == bDay.toDateString(), "Contact should be a date object equal to " + bDay.toDateString());
-            ok(obj.addresses == null, "Contact should return null for addresses.");
-            // must store returned object in order to have id for update test below
-            gContactObj = obj;
-            QUnit.start();
-        };
-
-        gContactObj.save(saveSuccess, function(e) {
-            ok(false, "save method error callback called, test failed.");
-            QUnit.start();
+        it("should contain a save function", function() {
+            var contact = new Contact();
+            expect(contact.save).toBeDefined();
+            expect(typeof contact.save).toBe('function');
+        });
+
+        it("should contain a remove function", function() {
+            var contact = new Contact();
+            expect(contact.remove).toBeDefined();
+            expect(typeof contact.remove).toBe('function');
         });
-     });
-    // HACK: there is a reliance between the previous and next test. This is bad form.
-    test("update a contact", function() {
-        expect(6);
-        QUnit.stop(7000);
-        ok(gContactObj != null, "Contact object from previous test should still exist for this update test to pass.");
-
-        var bDay = new Date(1975, 5,4);
-        var noteText = "an UPDATED note";
-
-        var win = function(obj) {
-            ok(obj != 'undefined' && obj != null, "navigator.contacts.save should return a Contact object.");
-            ok(obj.id == gContactObj.id, "Contact id should not have changed");
-            ok(obj.note == noteText, "Contact should contain a note property.");
-            ok(obj.birthday instanceof Date && obj.birthday.toDateString() == bDay.toDateString(), "Contact should be a date object equal to " + bDay.toDateString());
-            ok(obj.emails.length == 1 && obj.emails[0].value == 'here@there.com', "Contact should contain only one email with value 'here@there.com'");
-            removeContact();         // Clean up contact object 
-            QUnit.start();
-        };
-        var fail = function(obj) {
-            removeContact(); // Clean up contact object
-            ok(false, "updating a Contact object then calling .save should not fail. Test failed.");
-            QUnit.start();
-        }
-
-        // remove an email
-        gContactObj.emails[1].value = "";
-        // change birthday
-        gContactObj.birthday = bDay;
-        // update note
-        gContactObj.note = noteText;
-        gContactObj.save(win, fail);
-    });
-    module('Contact.remove method', {
-        setup:function(){},
-        teardown:removeContact
-    });
-    test("calling remove on a contact has an id of null should return ContactError.UNKNOWN_ERROR", function() {
-        QUnit.stop(Tests.TEST_TIMEOUT);
-        expect(2);
-        var win = function(result) {
-            ok(false, "Success callback should not be called when calling remove on a Contact object with no ID.");
-            QUnit.start();
-        };
-        var fail = function(result) {
-            ok(typeof result == 'object', "Object returned in contact.remove failure callback is of type 'object' (actually ContactError).");
-            ok(result.code == ContactError.UNKNOWN_ERROR, "Object returned in contacts.remove failure callback has a code property which equal to ContactError.UNKNOWN_ERROR.");
-            QUnit.start();
-        };
-        var rmContact = new Contact();
-        rmContact.remove(win, fail);
     });
-    test("calling remove on a contact that does not exist should return ContactError.UNKNOWN_ERROR", function() {
-        QUnit.stop(Tests.TEST_TIMEOUT);
-        expect(2);
-
-        var win = function(result) {
-        ok(false, "success callback should never return in this case. Test failed!");
-        QUnit.start();
-        };
-        var fail = function(result) {
-        ok(typeof result == 'object', "Object returned in contact.remove failure callback is of type 'object' (actually ContactError).");
-        ok(result.code == ContactError.UNKNOWN_ERROR, "Object returned in contacts.remove failure callback has a code property which equal to ContactError.UNKNOWN_ERROR.");
-        QUnit.start();
-        };
-        // this is a bit risky as some devices may have contact ids that large
-        var contact = new Contact("this string is supposed to be a unique identifier that will never show up on a device");
-        contact.remove(win, fail);		
+
+    describe('Contact.save method', function () {
+        it("should be able to save a contact", function() {
+            var bDay = new Date(1976, 6,4);
+            gContactObj = navigator.contacts.create({"gender": "male", "note": "my note", "name": {"familyName": "Delete", "givenName": "Test"}, "emails": [{"value": "here@there.com"}, {"value": "there@here.com"}], "birthday": bDay});	
+
+            var saveSuccess = jasmine.createSpy().andCallFake(function(obj) {
+                    expect(obj).toBeDefined();
+                    expect(obj.note).toBe('my note');
+                    expect(obj.name.familyName).toBe('Delete');
+                    expect(obj.name.givenName).toBe('Test');
+                    expect(obj.emails.length).toBe(2);
+                    expect(obj.emails[0].value).toBe('here@there.com');
+                    expect(obj.emails[1].value).toBe('there@here.com');
+                    expect(obj.birthday.toDateString()).toBe(bDay.toDateString());
+                    expect(obj.addresses).toBe(null);
+                    // must store returned object in order to have id for update test below
+                    gContactObj = obj;
+                }),
+                saveFail = jasmine.createSpy();
+
+            runs(function () {
+                gContactObj.save(saveSuccess, saveFail);
+            });
+
+            waitsFor(function () { return saveSuccess.wasCalled; }, "saveSuccess never called", Tests.TEST_TIMEOUT);
+
+            runs(function () {
+                expect(saveFail).not.toHaveBeenCalled();
+            });
+         });
+        // HACK: there is a reliance between the previous and next test. This is bad form.
+        it("update a contact", function() {
+            expect(gContactObj).toBeDefined();
+
+            var bDay = new Date(1975, 5,4);
+            var noteText = "an UPDATED note";
+
+            var win = function(obj) {
+                    expect(obj).toBeDefined();
+                    expect(obj.id).toBe(gContactObj.id);
+                    expect(obj.note).toBe(noteText);
+                    expect(obj.birthday.toDateString()).toBe(bDay.toDateString());
+                    expect(obj.emails.length).toBe(1);
+                    expect(obj.emails[0].value).toBe('here@there.com');
+                    removeContact();         // Clean up contact object 
+                }, fail = jasmine.createSpy().andCallFake(removeContact);
+
+            runs(function () {
+                // remove an email
+                gContactObj.emails[1].value = "";
+                // change birthday
+                gContactObj.birthday = bDay;
+                // update note
+                gContactObj.note = noteText;
+                gContactObj.save(win, fail);
+            });
+
+            waitsFor(function () { return win.wasCalled; }, "saveSuccess never called", Tests.TEST_TIMEOUT);
+
+            runs(function () {
+                expect(fail).not.toHaveBeenCalled();
+            });
+        });
     });
 
-    module("Round trip Contact tests (creating + save + delete + find).", {
-        setup:function(){},
-        teardown:removeContact
+    describe('Contact.remove method', function () {
+        afterEach(removeContact);
+
+        it("calling remove on a contact has an id of null should return ContactError.UNKNOWN_ERROR", function() {
+            var win = jasmine.createSpy();
+            var fail = jasmine.createSpy().andCallFake(function(result) {
+                expect(result.code).toBe(ContactError.UNKNOWN_ERROR);
+            });
+
+            runs(function () {
+                var rmContact = new Contact();
+                rmContact.remove(win, fail);
+            });
+
+            waitsFor(function () { return fail.wasCalled; }, Tests.TEST_TIMEOUT);
+
+            runs(function () {
+                expect(win).not.toHaveBeenCalled();
+            });
+        });
+
+        it("calling remove on a contact that does not exist should return ContactError.UNKNOWN_ERROR", function() {
+            var win = jasmine.createSpy();
+            var fail = jasmine.createSpy().andCallFake(function(result) {
+                expect(result.code).toBe(ContactError.UNKNOWN_ERROR);
+            });
+
+            runs(function () {
+                var rmContact = new Contact();
+                // this is a bit risky as some devices may have contact ids that large
+                var contact = new Contact("this string is supposed to be a unique identifier that will never show up on a device");
+                contact.remove(win, fail);
+            });
+
+            waitsFor(function () { return fail.wasCalled; }, Tests.TEST_TIMEOUT);
+
+            runs(function () {
+                expect(win).not.toHaveBeenCalled();
+            });
+        });
     });
-    test("Creating, saving, finding a contact should work, removing it should work, after which we should not be able to find it, and we should not be able to delete it again.", function() {
-        expect(8);
-        QUnit.stop(7000);
-
-        gContactObj = new Contact();
-        gContactObj.name = new ContactName();
-        gContactObj.name.familyName = "DeleteMe";
-        gContactObj.save(function(c_obj) {
-            ok(true, "Contact creation + saving succeeded, proceeding with test.");
-            var findWin = function(cs) {
-                ok(true, "contacts.find success callback invoked, proceeding with test.");
-                equal(cs.length, 1, "contacts.find success callback should return only 1 item (no one has a contact with 'DeleteMe') as a family name.");
-                //deepEqual(cs[0], gContactObj, "returned Contact object should equal the initially-created Contact object.");
-                // update to have proper saved id
-                gContactObj = cs[0];
-                gContactObj.remove(function() {
-                    ok(true, "Newly created contact's remove function success callback called, proceeding with test.");
-                    var findWinAgain = function(seas) {
-                        ok(true, "Calling find after deleting contact should be a success, proceeding.");
-                        equal(seas.length, 0, "find post-remove should return zero length array of results.");
+
+    describe("Round trip Contact tests (creating + save + delete + find).", function () {
+        afterEach(removeContact);
+
+        it("Creating, saving, finding a contact should work, removing it should work, after which we should not be able to find it, and we should not be able to delete it again.", function() {
+            var done = false;
+            runs(function () {
+                gContactObj = new Contact();
+                gContactObj.name = new ContactName();
+                gContactObj.name.familyName = "DeleteMe";
+                gContactObj.save(function(c_obj) {
+                    var findWin = function(cs) {
+                        expect(cs.length).toBe(1);
+                        // update to have proper saved id
+                        gContactObj = cs[0];
                         gContactObj.remove(function() {
-                            ok(false, "success callback called after non-existent Contact object called remove(). Test failed.");
-                            QUnit.start();
+                            var findWinAgain = function(seas) {
+                                expect(seas.length).toBe(0);
+                                gContactObj.remove(function() {
+                                    throw("success callback called after non-existent Contact object called remove(). Test failed.");
+                                }, function(e) {
+                                    expect(e.code).toBe(ContactError.UNKNOWN_ERROR);
+                                    done = true;
+                                });
+                            };
+                            var findFailAgain = function(e) {
+                                throw("find error callback invoked after delete, test failed.");
+                            };
+                            var obj = new ContactFindOptions();
+                            obj.filter="DeleteMe";
+                            obj.multiple=true;
+                            navigator.contacts.find(["displayName", "name", "phoneNumbers", "emails"], findWinAgain, findFailAgain, obj);
                         }, function(e) {
-                            ok(true, "error callback called after non-existent Contact object called with remove().");
-                            equal(e.code, ContactError.UNKNOWN_ERROR, "error callback should be called with UNKNOWN_ERROR");
-                            QUnit.start();
+                            throw("Newly created contact's remove function invoked error callback. Test failed.");
                         });
                     };
-                    var findFailAgain = function(e) {
-                        ok(false, "find error callback invoked after delete, test failed.");
-                        QUnit.start();
+                    var findFail = function(e) {
+                        throw("Failure callback invoked in navigator.contacts.find call, test failed.");
                     };
                     var obj = new ContactFindOptions();
                     obj.filter="DeleteMe";
                     obj.multiple=true;
-                    navigator.contacts.find(["displayName", "name", "phoneNumbers", "emails"], findWinAgain, findFailAgain, obj);
+                    navigator.contacts.find(["displayName", "name", "phoneNumbers", "emails"], findWin, findFail, obj);
                 }, function(e) {
-                    ok(false, "Newly created contact's remove function invoked error callback. Test failed.");
-                    QUnit.start();
+                    throw("Contact creation failed, error callback was invoked.");
                 });
-            };
-            var findFail = function(e) {
-                ok(false, "Failure callback invoked in navigator.contacts.find call, test failed.");
-                QUnit.start();
-            };
-            var obj = new ContactFindOptions();
-            obj.filter="DeleteMe";
-            obj.multiple=true;
-            navigator.contacts.find(["displayName", "name", "phoneNumbers", "emails"], findWin, findFail, obj);
-        }, function(e) {
-            ok(false, "Contact creation failed, error callback was invoked.");
-            QUnit.start();
+            });
+
+            waitsFor(function () { return done; }, Tests.TEST_TIMEOUT);
         });
     });
 
-    module('ContactError interface');
-    test("ContactError constants should be defined", function() {
-        expect(7);
-        equal(ContactError.UNKNOWN_ERROR, 0, "ContactError.UNKNOWN_ERROR should be defined");
-        equal(ContactError.INVALID_ARGUMENT_ERROR, 1, "ContactError.INVALID_ARGUMENT_ERROR should be defined");
-        equal(ContactError.TIMEOUT_ERROR, 2, "ContactError.TIMEOUT_ERROR should be defined");
-        equal(ContactError.PENDING_OPERATION_ERROR, 3, "ContactError.PENDING_OPERATION_ERROR should be defined");
-        equal(ContactError.IO_ERROR, 4, "ContactError.IO_ERROR should be defined");
-        equal(ContactError.NOT_SUPPORTED_ERROR, 5, "ContactError.NOT_SUPPORTED_ERROR should be defined");
-        equal(ContactError.PERMISSION_DENIED_ERROR, 20, "ContactError.PERMISSION_DENIED_ERROR should be defined");
+    describe('ContactError interface', function () {
+        it("ContactError constants should be defined", function() {
+            expect(ContactError.UNKNOWN_ERROR).toBe(0);
+            expect(ContactError.INVALID_ARGUMENT_ERROR).toBe(1);
+            expect(ContactError.TIMEOUT_ERROR).toBe(2);
+            expect(ContactError.PENDING_OPERATION_ERROR).toBe(3);
+            expect(ContactError.IO_ERROR).toBe(4);
+            expect(ContactError.NOT_SUPPORTED_ERROR).toBe(5);
+            expect(ContactError.PERMISSION_DENIED_ERROR).toBe(20);
+        });
     });
-};
+});

http://git-wip-us.apache.org/repos/asf/incubator-cordova-mobile-spec/blob/5bef2694/autotest/tests/device.tests.js
----------------------------------------------------------------------
diff --git a/autotest/tests/device.tests.js b/autotest/tests/device.tests.js
index bbb4af4..cc322d6 100644
--- a/autotest/tests/device.tests.js
+++ b/autotest/tests/device.tests.js
@@ -1,36 +1,34 @@
-Tests.prototype.DeviceTests = function() {
-	module('Device Information (window.device)');
-	test("should exist", function() {
-  		expect(1);
-  		ok(window.device != null, "window.device should not be null.");
+describe('Device Information (window.device)', function () {
+	it("should exist", function() {
+        expect(window.device).toBeDefined();
 	});
-	test("should contain a platform specification that is a string", function() {
-		expect(2);
-		ok(typeof window.device.platform != 'undefined' && window.device.platform != null, "window.device.platform should not be null.")
-		ok((new String(window.device.platform)).length > 0, "window.device.platform should contain some sort of description.")
+
+	it("should contain a platform specification that is a string", function() {
+        expect(window.device.platform).toBeDefined();
+		expect((new String(window.device.platform)).length > 0).toBe(true);
 	});
-	test("should contain a version specification that is a string", function() {
-		expect(2);
-		ok(typeof window.device.version != 'undefined' && window.device.version != null, "window.device.version should not be null.")
-		ok((new String(window.device.version)).length > 0, "window.device.version should contain some kind of description.")
+
+	it("should contain a version specification that is a string", function() {
+        expect(window.device.version).toBeDefined();
+		expect((new String(window.device.version)).length > 0).toBe(true);
 	});
-	test("should contain a name specification that is a string", function() {
-		expect(2);
-		ok(typeof window.device.name != 'undefined' && window.device.name != null, "window.device.name should not be null.")
-		ok((new String(window.device.name)).length > 0, "window.device.name should contain some kind of description.")
+
+	it("should contain a name specification that is a string", function() {
+        expect(window.device.name).toBeDefined();
+		expect((new String(window.device.name)).length > 0).toBe(true);
 	});
-	test("should contain a UUID specification that is a string or a number", function() {
-		expect(2);
-		ok(typeof window.device.uuid != 'undefined' && window.device.uuid != null, "window.device.uuid should not be null.")
+
+	it("should contain a UUID specification that is a string or a number", function() {
+        expect(window.device.uuid).toBeDefined();
 		if (typeof window.device.uuid == 'string' || typeof window.device.uuid == 'object') {
-			ok((new String(window.device.uuid)).length > 0, "window.device.uuid, as a string, should have at least one character.")
+		    expect((new String(window.device.uuid)).length > 0).toBe(true);
 		} else {
-			ok(window.device.uuid > 0, "window.device.uuid, as a number, should be greater than 0. (should it, even?)")
+			expect(window.device.uuid > 0).toBe(true);
 		}
 	});
-	test("should contain a cordova specification that is a string", function() {
-		expect(2);
-		ok(typeof window.device.cordova != 'undefined' && window.device.cordova != null, "window.device.cordova should not be null.")
-		ok((new String(window.device.cordova)).length > 0, "window.device.cordova should contain some kind of description.")
+
+	it("should contain a cordova specification that is a string", function() {
+        expect(window.device.cordova).toBeDefined();
+		expect((new String(window.device.cordova)).length > 0).toBe(true);
 	});
-};
+});