You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by pu...@apache.org on 2012/11/06 01:38:29 UTC

[21/25] js commit: add window8 test case & readme.txt

add window8 test case & readme.txt


Project: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/commit/1aa4b3ec
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/tree/1aa4b3ec
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/diff/1aa4b3ec

Branch: refs/heads/master
Commit: 1aa4b3ecb5854c2800856e63c7b87179c987f1e4
Parents: 8bc917e
Author: mingfeng <mi...@gmail.com>
Authored: Thu Oct 18 10:56:17 2012 +0800
Committer: mingfeng <mi...@gmail.com>
Committed: Thu Oct 18 10:56:17 2012 +0800

----------------------------------------------------------------------
 test/window8/README.txt             |   14 +
 test/window8/accelerometer.tests.js |  192 ++
 test/window8/battery.tests.js       |    5 +
 test/window8/camera.tests.js        |  192 ++
 test/window8/capture.tests.js       |  262 +++
 test/window8/compass.tests.js       |   76 +
 test/window8/contacts.tests.js      |  451 ++++
 test/window8/device.tests.js        |   34 +
 test/window8/file.tests.js          | 3481 ++++++++++++++++++++++++++++++
 test/window8/filetransfer.tests.js  |   72 +
 test/window8/geolocation.tests.js   |  106 +
 test/window8/media.tests.js         |  137 ++
 test/window8/network.tests.js       |   25 +
 test/window8/notification.tests.js  |   20 +
 test/window8/platform.tests.js      |   35 +
 test/window8/storage.tests.js       |  405 ++++
 16 files changed, 5507 insertions(+), 0 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/1aa4b3ec/test/window8/README.txt
----------------------------------------------------------------------
diff --git a/test/window8/README.txt b/test/window8/README.txt
new file mode 100644
index 0000000..1c75ba5
--- /dev/null
+++ b/test/window8/README.txt
@@ -0,0 +1,14 @@
+How to create a new win8-metro app using PhoneGap?
+
+1.	Follow the instructions listed in README.md up to creating the pkg/ directory in your project.
+2.	Create a javascript/html Windows 8 (formerly Metro Style) app or use an existing one from Visual Studio 2012.
+3.  Copy the 'cordova.windows8.js' in pkg/ directory to the position you decide in your metro project created before.
+4.  On each html page in the project that needs the cordova scripts, add these lines to those files:
+         <script src="//Microsoft.WinJS.1.0.RC/js/base.js"></script>
+    	 <script src="//Microsoft.WinJS.1.0.RC/js/ui.js"></script>
+
+    	 <script type="text/javascript" src="../js/cordova.windows8.js"></script>
+
+    If one or more are exist, you could go ahead without adding the existing scripts again.
+5.  Confirm that these links correctly reference the files. If not, update the location pointed to by source accordingly.
+6.	Build and run.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/1aa4b3ec/test/window8/accelerometer.tests.js
----------------------------------------------------------------------
diff --git a/test/window8/accelerometer.tests.js b/test/window8/accelerometer.tests.js
new file mode 100644
index 0000000..36a8849
--- /dev/null
+++ b/test/window8/accelerometer.tests.js
@@ -0,0 +1,192 @@
+describe('Accelerometer (navigator.accelerometer)', function () {
+    it("should exist", function () {
+        expect(navigator.accelerometer).toBeDefined();
+    });
+
+    describe("getCurrentAcceleration", function () {
+        it("should exist", function () {
+            expect(typeof navigator.accelerometer.getCurrentAcceleration).toBeDefined();
+            expect(typeof navigator.accelerometer.getCurrentAcceleration == 'function').toBe(true);
+        });
+
+        it("success callback should be called with an Acceleration object", function () {
+            var win = jasmine.createSpy().andCallFake(function (a) {
+                expect(a).toBeDefined();
+                expect(a.x).toBeDefined();
+                expect(typeof a.x == 'number').toBe(true);
+                expect(a.y).toBeDefined();
+                expect(typeof a.y == 'number').toBe(true);
+                expect(a.z).toBeDefined();
+                expect(typeof a.z == 'number').toBe(true);
+                expect(a.timestamp).toBeDefined();
+                expect(typeof a.timestamp).toBe('number');
+            }),
+                fail = jasmine.createSpy();
+
+            runs(function () {
+                navigator.accelerometer.getCurrentAcceleration(win, fail);
+            });
+
+            waitsFor(function () { return win.wasCalled; }, "win never called", Tests.TEST_TIMEOUT);
+
+            runs(function () {
+                expect(fail).not.toHaveBeenCalled();
+            });
+        });
+
+        it("success callback Acceleration object should have (reasonable) values for x, y and z expressed in m/s^2", function () {
+            var reasonableThreshold = 15;
+            var win = jasmine.createSpy().andCallFake(function (a) {
+                expect(a.x).toBeLessThan(reasonableThreshold);
+                expect(a.x).toBeGreaterThan(reasonableThreshold * -1);
+                expect(a.y).toBeLessThan(reasonableThreshold);
+                expect(a.y).toBeGreaterThan(reasonableThreshold * -1);
+                expect(a.z).toBeLessThan(reasonableThreshold);
+                expect(a.z).toBeGreaterThan(reasonableThreshold * -1);
+            }),
+                fail = jasmine.createSpy();
+
+            runs(function () {
+                navigator.accelerometer.getCurrentAcceleration(win, fail);
+            });
+
+            waitsFor(function () { return win.wasCalled; }, "win never called", Tests.TEST_TIMEOUT);
+
+            runs(function () {
+                expect(fail).not.toHaveBeenCalled();
+            });
+        });
+
+        it("success callback Acceleration object should return a recent timestamp", function () {
+            var veryRecently = (new Date()).getTime();
+            // Need to check that dates returned are not vastly greater than a recent time stamp.
+            // In case the timestamps returned are ridiculously high
+            var reasonableTimeLimit = veryRecently + 5000; // 5 seconds from now
+            var win = jasmine.createSpy().andCallFake(function (a) {
+                expect(a.timestamp).toBeGreaterThan(veryRecently);
+                expect(a.timestamp).toBeLessThan(reasonableTimeLimit);
+            }),
+                fail = jasmine.createSpy();
+
+            runs(function () {
+                navigator.accelerometer.getCurrentAcceleration(win, fail);
+            });
+
+            waitsFor(function () { return win.wasCalled; }, "win never called", Tests.TEST_TIMEOUT);
+
+            runs(function () {
+                expect(fail).not.toHaveBeenCalled();
+            });
+        });
+    });
+
+    describe("watchAcceleration", function () {
+        var id=0;
+        afterEach(function () {
+            navigator.accelerometer.clearWatch(id);
+        });
+
+        it("should exist", function () {
+            expect(navigator.accelerometer.watchAcceleration).toBeDefined();
+            expect(typeof navigator.accelerometer.watchAcceleration == 'function').toBe(true);
+        });
+        it("success callback should be called with an Acceleration object", function () {
+            var win = jasmine.createSpy().andCallFake(function (a) {
+                expect(a).toBeDefined();
+                expect(a.x).toBeDefined();
+                expect(typeof a.x == 'number').toBe(true);
+                expect(a.y).toBeDefined();
+                expect(typeof a.y == 'number').toBe(true);
+                expect(a.z).toBeDefined();
+                expect(typeof a.z == 'number').toBe(true);
+                expect(a.timestamp).toBeDefined();
+                expect(typeof a.timestamp).toBe('number');
+            }),
+                fail = jasmine.createSpy();
+
+            runs(function () {
+                id = navigator.accelerometer.watchAcceleration(win, fail, { frequency: 500 });
+            });
+
+            waitsFor(function () { return win.wasCalled; }, "win never called", Tests.TEST_TIMEOUT);
+
+            runs(function () {
+                expect(fail).not.toHaveBeenCalled();
+            });
+        });
+
+        it("success callback Acceleration object should have (reasonable) values for x, y and z expressed in m/s^2", function () {
+            var reasonableThreshold = 15;
+            var win = jasmine.createSpy().andCallFake(function (a) {
+                expect(a.x).toBeLessThan(reasonableThreshold);
+                expect(a.x).toBeGreaterThan(reasonableThreshold * -1);
+                expect(a.y).toBeLessThan(reasonableThreshold);
+                expect(a.y).toBeGreaterThan(reasonableThreshold * -1);
+                expect(a.z).toBeLessThan(reasonableThreshold);
+                expect(a.z).toBeGreaterThan(reasonableThreshold * -1);
+            }),
+                fail = jasmine.createSpy();
+
+            runs(function () {
+                id = navigator.accelerometer.watchAcceleration(win, fail, { frequency: 500 });
+            });
+
+            waitsFor(function () { return win.wasCalled; }, "win never called", Tests.TEST_TIMEOUT);
+
+            runs(function () {
+                expect(fail).not.toHaveBeenCalled();
+            });
+        });
+
+        it("success callback Acceleration object should return a recent timestamp", function () {
+            var veryRecently = (new Date()).getTime();
+            // Need to check that dates returned are not vastly greater than a recent time stamp.
+            // In case the timestamps returned are ridiculously high
+            var reasonableTimeLimit = veryRecently + 5000; // 5 seconds from now
+            var win = jasmine.createSpy().andCallFake(function (a) {
+                expect(a.timestamp).toBeGreaterThan(veryRecently);
+                expect(a.timestamp).toBeLessThan(reasonableTimeLimit);
+            }),
+                fail = jasmine.createSpy();
+
+            runs(function () {
+                id = navigator.accelerometer.watchAcceleration(win, fail, { frequency: 500 });
+            });
+
+            waitsFor(function () { return win.wasCalled; }, "win never called", Tests.TEST_TIMEOUT);
+
+            runs(function () {
+                expect(fail).not.toHaveBeenCalled();
+            });
+        });
+    });
+
+    describe("clearWatch", function () {
+        it("should exist", function () {
+            expect(navigator.accelerometer.clearWatch).toBeDefined();
+            expect(typeof navigator.accelerometer.clearWatch == 'function').toBe(true);
+        });
+
+        it("should clear an existing watch", function () {
+            var id,
+                win = jasmine.createSpy();
+
+            runs(function () {
+                id = navigator.accelerometer.watchAcceleration(win, function () { }, { frequency: 100 });
+            });
+
+            waitsFor(function () { return win.wasCalled; }, "win never called", Tests.TEST_TIMEOUT);
+
+            runs(function () {
+                win.reset();
+                navigator.accelerometer.clearWatch(id);
+            });
+
+            waits(201);
+
+            runs(function () {
+                expect(win).not.toHaveBeenCalled();
+            });
+        });
+    });
+});

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/1aa4b3ec/test/window8/battery.tests.js
----------------------------------------------------------------------
diff --git a/test/window8/battery.tests.js b/test/window8/battery.tests.js
new file mode 100644
index 0000000..7bb25af
--- /dev/null
+++ b/test/window8/battery.tests.js
@@ -0,0 +1,5 @@
+describe('Battery (navigator.battery)', function () {;
+    it("should exist", function() {
+        expect(navigator.battery).toBeDefined();
+    });
+});

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/1aa4b3ec/test/window8/camera.tests.js
----------------------------------------------------------------------
diff --git a/test/window8/camera.tests.js b/test/window8/camera.tests.js
new file mode 100644
index 0000000..b6ef7bd
--- /dev/null
+++ b/test/window8/camera.tests.js
@@ -0,0 +1,192 @@
+describe('Camera (navigator.camera)', function () {
+	it("should exist", function() {
+        expect(navigator.camera).toBeDefined();
+	});
+
+	it("should contain a getPicture function", function() {
+        expect(navigator.camera.getPicture).toBeDefined();
+		expect(typeof navigator.camera.getPicture == 'function').toBe(true);
+	});
+});
+
+describe('Camera Constants (window.Camera + navigator.camera)', function () {
+    it("window.Camera should exist", function() {
+        expect(window.Camera).toBeDefined();
+    });
+
+    it("should contain two DestinationType constants", function() {
+        expect(Camera.DestinationType.DATA_URL).toBe(0);
+        expect(Camera.DestinationType.FILE_URI).toBe(1);
+        expect(navigator.camera.DestinationType.DATA_URL).toBe(0);
+        expect(navigator.camera.DestinationType.FILE_URI).toBe(1);
+    });
+
+    it("should contain two EncodingType constants", function() {
+        expect(Camera.EncodingType.JPEG).toBe(0);
+        expect(Camera.EncodingType.PNG).toBe(1);
+        expect(navigator.camera.EncodingType.JPEG).toBe(0);
+        expect(navigator.camera.EncodingType.PNG).toBe(1);
+    });
+
+    it("should contain three MediaType constants", function() {
+        expect(Camera.MediaType.PICTURE).toBe(0);
+        expect(Camera.MediaType.VIDEO).toBe(1);
+        expect(Camera.MediaType.ALLMEDIA).toBe(2);
+        expect(navigator.camera.MediaType.PICTURE).toBe(0);
+        expect(navigator.camera.MediaType.VIDEO).toBe(1);
+        expect(navigator.camera.MediaType.ALLMEDIA).toBe(2);
+    });
+    it("should contain three PictureSourceType constants", function() {
+        expect(Camera.PictureSourceType.PHOTOLIBRARY).toBe(0);
+        expect(Camera.PictureSourceType.CAMERA).toBe(1);
+        expect(Camera.PictureSourceType.SAVEDPHOTOALBUM).toBe(2);
+        expect(navigator.camera.PictureSourceType.PHOTOLIBRARY).toBe(0);
+        expect(navigator.camera.PictureSourceType.CAMERA).toBe(1);
+        expect(navigator.camera.PictureSourceType.SAVEDPHOTOALBUM).toBe(2);
+    });
+
+});
+
+describe('Test getPicture function', function () {
+    it("should retrieve a base64 data when DestinationType equals DATA_URL", function () {
+        var onPhotoDataSuccess = jasmine.createSpy().andCallFake(function (imageData) {
+            var image = new Image();
+            image.src = "data:image/jpeg;base64," + imageData;
+            
+        })
+        var onFail = jasmine.createSpy().andCallFake(function (message) {
+            console.log(message);
+        })
+
+        runs(function () {
+            navigator.camera.getPicture(onPhotoDataSuccess, onFail, { quality: 50, destinationType: navigator.camera.DestinationType.DATA_URL, saveToPhotoAlbum: true, targetHeight: 600, targetWidth: 800 });
+        });
+
+        waitsFor(function () { return onPhotoDataSuccess.wasCalled; }, "Insert callback never called", 30000);
+
+        runs(function () {
+            expect(onPhotoDataSuccess).toHaveBeenCalled();
+            expect(onFail).not.toHaveBeenCalled();
+        })
+    })
+
+    it("should retrieve a URI when DestinationType equals FILE_URL", function () {
+        var onPhotoDataSuccess = jasmine.createSpy().andCallFake(function (imageURI) {
+            var image = new Image();
+            image.src = imageURI;
+            //console.log("src=" + image.src);
+            expect(String(image.src).substr(0, 3)).toBe("ms-");
+        })
+        var onFail = jasmine.createSpy().andCallFake(function (message) {
+            console.log(message);
+        })
+
+        runs(function () {
+            navigator.camera.getPicture(onPhotoDataSuccess, onFail, { quality: 50, destinationType: navigator.camera.DestinationType.FILE_URI, saveToPhotoAlbum: true, targetHeight: 600, targetWidth: 800 });
+        });
+
+        waitsFor(function () { return onPhotoDataSuccess.wasCalled; }, "Insert callback never called", 30000);
+
+        runs(function () {
+            expect(onPhotoDataSuccess).toHaveBeenCalled();
+            expect(onFail).not.toHaveBeenCalled();
+        })
+    })
+    it("should retrieve a jpg when PictureSourceType equals PHOTOLIBRARY", function () {
+        var onPhotoDataSuccess = jasmine.createSpy().andCallFake(function (imageURI) {
+            //expect(String(imageURI).substr(0, 3)).toBe('C:\\');
+            var image = new Image();
+            image.src = imageURI;
+            console.log("src=" + image.src);
+            expect(String(image.src).substr(0, 3)).toBe("ms-");
+        })
+        var onFail = jasmine.createSpy().andCallFake(function (message) {
+            console.log(message);
+        })
+
+        runs(function () {
+            navigator.camera.getPicture(onPhotoDataSuccess, onFail, { quality: 50, destinationType: navigator.camera.DestinationType.FILE_URI, sourceType: navigator.camera.PictureSourceType.PHOTOLIBRARY, targetWidth: 200, targetHeight: 150 });
+        });
+
+        waitsFor(function () { return onPhotoDataSuccess.wasCalled; }, "Insert callback never called", 30000);
+
+        runs(function () {
+            expect(onPhotoDataSuccess).toHaveBeenCalled();
+            expect(onFail).not.toHaveBeenCalled();
+        })
+    })
+
+    it("should retrieve a png when EncodingType equals PNG", function () {
+        var onPhotoDataSuccess = jasmine.createSpy().andCallFake(function (imageURI) {
+            var extensionArr = String(imageURI).split(".");
+            expect(extensionArr[extensionArr.length - 1]).toBe('png');
+        })
+        var onFail = jasmine.createSpy().andCallFake(function (message) {
+            console.log(message);
+        })
+
+        runs(function () {
+            navigator.camera.getPicture(onPhotoDataSuccess, onFail, { quality: 50, destinationType: navigator.camera.DestinationType.FILE_URI, saveToPhotoAlbum: true, encodingType: navigator.camera.EncodingType.PNG, targetWidth: 200, targetHeight: 150 });
+        });
+
+        waitsFor(function () { return onPhotoDataSuccess.wasCalled; }, "Insert callback never called", 30000);
+
+        runs(function () {
+            expect(onPhotoDataSuccess).toHaveBeenCalled();
+            expect(onFail).not.toHaveBeenCalled();
+        })
+    })
+
+    
+    it("should retrieve nothing when mediaType is Video from photolibrary.(You must keep your photolibrary only to contain image files) ", function () {
+        var onPhotoDataSuccess = jasmine.createSpy().andCallFake(function (imageURI) {
+            var image = new Image();
+            image.src = imageURI;
+            //console.log("src=" + image.src);
+            expect(String(image.src).substr(0, 3)).toBe("ms-");
+        })
+        var onFail = jasmine.createSpy().andCallFake(function (message) {
+            expect(message).toBe("User didn't choose a file.");
+        })
+
+        runs(function () {
+            navigator.camera.getPicture(onPhotoDataSuccess, onFail, { quality: 50, destinationType: navigator.camera.DestinationType.FILE_URI, saveToPhotoAlbum: true, encodingType: navigator.camera.EncodingType.PNG, sourceType: navigator.camera.PictureSourceType.PHOTOLIBRARY, mediaType: navigator.camera.MediaType.VIDEO});
+        })
+
+        waitsFor(function () { return onFail.wasCalled; }, "Insert callback never called", 10000);
+
+        runs(function () {
+            expect(onPhotoDataSuccess).not.toHaveBeenCalled();
+            expect(onFail).toHaveBeenCalled();
+        })
+    })
+
+    it("should retrieve a specific pixels when targetWidth or targetHeight is given.", function () {
+        var onPhotoDataSuccess = jasmine.createSpy().andCallFake(function (imageURI) {
+            // Todo: get the real pixels of the picture instead of finding it in the directory
+            var image = new Image();
+            image.src = imageURI;
+            
+            image.onload = function () {
+                console.log(image.height);
+                expect(image.width).toBe(1280);
+            }
+            
+        })
+        var onFail = jasmine.createSpy().andCallFake(function (message) {
+            console.log(message);
+        })
+
+        runs(function () {
+            navigator.camera.getPicture(onPhotoDataSuccess, onFail, { quality: 50, destinationType: navigator.camera.DestinationType.FILE_URI, saveToPhotoAlbum: true, targetWidth: 1280, targetHeight: 960});
+        });
+
+        waitsFor(function () { return onPhotoDataSuccess.wasCalled; }, "Insert callback never called", 30000);
+
+        runs(function () {
+            expect(onPhotoDataSuccess).toHaveBeenCalled();
+            expect(onFail).not.toHaveBeenCalled();
+        })
+    })
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/1aa4b3ec/test/window8/capture.tests.js
----------------------------------------------------------------------
diff --git a/test/window8/capture.tests.js b/test/window8/capture.tests.js
new file mode 100644
index 0000000..43dde88
--- /dev/null
+++ b/test/window8/capture.tests.js
@@ -0,0 +1,262 @@
+describe('Capture (navigator.device.capture)', function () {
+    it("should exist", function() {
+        expect(navigator.device).toBeDefined();
+        expect(navigator.device.capture).toBeDefined();
+    });
+
+    it("should have the correct properties ", function() {
+        expect(navigator.device.capture.supportedAudioModes).toBeDefined();
+        expect(navigator.device.capture.supportedImageModes).toBeDefined();
+        expect(navigator.device.capture.supportedVideoModes).toBeDefined();
+    });
+
+    it("should contain a captureAudio function", function() {
+        expect(navigator.device.capture.captureAudio).toBeDefined();
+        expect(typeof navigator.device.capture.captureAudio == 'function').toBe(true);
+    });
+
+    it("should contain a captureImage function", function() {
+        expect(navigator.device.capture.captureImage).toBeDefined();
+        expect(typeof navigator.device.capture.captureImage == 'function').toBe(true);
+    });
+
+    it("should contain a captureVideo function", function() {
+        expect(navigator.device.capture.captureVideo).toBeDefined();
+        expect(typeof navigator.device.capture.captureVideo == 'function').toBe(true);
+    });
+
+    describe('CaptureAudioOptions', function () {
+        it("CaptureAudioOptions constructor should exist", function() {
+            var options = new CaptureAudioOptions();
+            expect(options).toBeDefined();
+            expect(options.limit).toBeDefined();
+            expect(options.duration).toBeDefined();
+            expect(options.mode).toBeDefined();
+        });
+    });
+
+    describe('CaptureImageOptions', function () {
+        it("CaptureImageOptions constructor should exist", function() {
+            var options = new CaptureImageOptions();
+            expect(options).toBeDefined();
+            expect(options.limit).toBeDefined();
+            expect(options.mode).toBeDefined();
+        });
+    });
+
+    describe('CaptureVideoOptions', function () {
+        it("CaptureVideoOptions constructor should exist", function() {
+            var options = new CaptureVideoOptions();
+            expect(options).toBeDefined();
+            expect(options.limit).toBeDefined();
+            expect(options.duration).toBeDefined();
+            expect(options.mode).toBeDefined();
+        });
+    });
+
+    describe('CaptureError interface', function () {
+        it("CaptureError constants should be defined", function() {
+            expect(CaptureError.CAPTURE_INTERNAL_ERR).toBe(0);
+            expect(CaptureError.CAPTURE_APPLICATION_BUSY).toBe(1);
+            expect(CaptureError.CAPTURE_INVALID_ARGUMENT).toBe(2);
+            expect(CaptureError.CAPTURE_NO_MEDIA_FILES).toBe(3);
+        });
+
+        it("CaptureError properties should exist", function() {
+            var error = new CaptureError();
+            expect(error).toBeDefined();
+            expect(error.code).toBeDefined();
+        });
+    });
+
+    describe('MediaFileData', function () {
+        it("MediaFileData constructor should exist", function() {
+            var fileData = new MediaFileData();
+            expect(fileData).toBeDefined();
+            expect(fileData.bitrate).toBeDefined();
+            expect(fileData.codecs).toBeDefined();
+            expect(fileData.duration).toBeDefined();
+            expect(fileData.height).toBeDefined();
+            expect(fileData.width).toBeDefined();
+        });
+    });
+
+    describe('MediaFile', function () {
+        it("MediaFile constructor should exist", function() {
+            var fileData = new MediaFile();
+            expect(fileData).toBeDefined();
+            expect(fileData.name).toBeDefined();
+            expect(fileData.fullPath).toBeDefined();
+            expect(fileData.type).toBeDefined();
+            expect(fileData.lastModifiedDate).toBeDefined();
+            expect(fileData.size).toBeDefined();
+        });
+    });
+
+    describe('Test captureAudio function', function () {
+        it("should capture a audio when the function invoked (w/ duration).", function () {
+            var captureSuccess = jasmine.createSpy().andCallFake(function (mediaFiles) {
+                expect(mediaFiles.fullPath.substr(0, 3)).toBe("C:\\");
+                // TODO: Check the recording result by yourself.
+                //console.log(mediaFiles.fullPath);
+            })
+            var captureError = jasmine.createSpy().andCallFake(function (error) {
+                console.log("code:" + error.code);
+            })
+            runs(function () {
+                navigator.device.capture.captureAudio(captureSuccess , captureError , {duration:10});
+            });
+
+            waitsFor(function () { return captureSuccess.wasCalled; }, "captureSuccess callback never called", 30000);
+
+            runs(function () {
+                expect(captureSuccess).toHaveBeenCalled();
+                expect(captureError).not.toHaveBeenCalled();
+            })
+        });
+    });
+
+    describe('Test captureVideo function', function () {
+        it("should capture a video when the function invoked (w/ duration).", function () {
+            var captureSuccess = jasmine.createSpy().andCallFake(function (mediaFiles) {
+                expect(mediaFiles.fullPath.substr(0, 3)).toBe("C:\\");
+                // TODO: Check the video by yourself.
+                //console.log(mediaFiles.fullPath);
+            })
+            var captureError = jasmine.createSpy().andCallFake(function (error) {
+                console.log("code:" + error.code);
+            })
+            runs(function () {
+                navigator.device.capture.captureVideo(captureSuccess, captureError, { duration: 10 });
+            });
+
+            waitsFor(function () { return captureSuccess.wasCalled; }, "captureSuccess callback never called", 70000);
+
+            runs(function () {
+                expect(captureSuccess).toHaveBeenCalled();
+                expect(captureError).not.toHaveBeenCalled();
+            })
+        });
+    });
+
+    describe('Test captureImage function', function () {
+        it("should capture a image when the function invoked.", function () {
+            var captureSuccess = jasmine.createSpy().andCallFake(function (mediaFiles) {
+                expect(mediaFiles.fullPath.substr(0, 3)).toBe("C:\\");
+                // TODO: Check the video by yourself.
+                //console.log(mediaFiles.fullPath);
+            })
+            var captureError = jasmine.createSpy().andCallFake(function (error) {
+                console.log("code:" + error.code);
+            })
+            runs(function () {
+                navigator.device.capture.captureImage(captureSuccess, captureError);
+            });
+
+            waitsFor(function () { return captureSuccess.wasCalled; }, "captureSuccess callback never called", 70000);
+
+            runs(function () {
+                expect(captureSuccess).toHaveBeenCalled();
+                expect(captureError).not.toHaveBeenCalled();
+            })
+        });
+    });
+
+    describe('Test getFormatData function', function () {
+        it("should get format data about image.", function () {
+            var success = jasmine.createSpy().andCallFake(function (mediaFileData) {
+                console.dir(mediaFileData);
+                expect(mediaFileData.codecs).toBeDefined();
+                expect(mediaFileData.bitrate).toBe(0);
+                expect(mediaFileData.height).toBeDefined();
+                expect(mediaFileData.width).toBeDefined();
+                expect(mediaFileData.duration).toBe(0);
+            })
+            var fail = jasmine.createSpy().andCallFake(function (error) {})
+            var captureSuccess = jasmine.createSpy().andCallFake(function (mediaFiles) {
+                runs(function () {
+                    
+                    mediaFiles.getFormatData(success, fail);
+                });
+                waitsFor(function () { return success.wasCalled; }, "success callback never called", 7500);
+            })
+            var captureError = jasmine.createSpy().andCallFake(function (error) {
+                console.log("code:" + error.code);
+            })
+            runs(function () {
+                navigator.device.capture.captureImage(captureSuccess, captureError);
+            });
+
+            waitsFor(function () { return captureSuccess.wasCalled; }, "captureSuccess callback never called", 70000);
+
+            runs(function () {
+                expect(captureSuccess).toHaveBeenCalled();
+                expect(captureError).not.toHaveBeenCalled();
+            })
+        });
+
+        it("should get format data about video.", function () {
+            var success = jasmine.createSpy().andCallFake(function (mediaFileData) {
+                console.dir(mediaFileData);
+                expect(mediaFileData.codecs).toBeDefined();
+                expect(mediaFileData.bitrate).toBeDefined();
+                expect(mediaFileData.height).toBeDefined();
+                expect(mediaFileData.width).toBeDefined();
+                expect(mediaFileData.duration).toBeDefined();
+            })
+            var fail = jasmine.createSpy().andCallFake(function (error) { })
+            var captureSuccess = jasmine.createSpy().andCallFake(function (mediaFiles) {
+                runs(function () {
+
+                    mediaFiles.getFormatData(success, fail);
+                });
+                waitsFor(function () { return success.wasCalled; }, "success callback never called", 7500);
+            })
+            var captureError = jasmine.createSpy().andCallFake(function (error) {
+                console.log("code:" + error.code);
+            })
+            runs(function () {
+                navigator.device.capture.captureVideo(captureSuccess, captureError, { duration: 10 });
+            });
+
+            waitsFor(function () { return captureSuccess.wasCalled; }, "captureSuccess callback never called", 70000);
+
+            runs(function () {
+                expect(captureSuccess).toHaveBeenCalled();
+                expect(captureError).not.toHaveBeenCalled();
+            })
+        });
+
+        it("should get format data about audio.", function () {
+            var success = jasmine.createSpy().andCallFake(function (mediaFileData) {
+                console.dir(mediaFileData);
+                expect(mediaFileData.codecs).toBeDefined();
+                expect(mediaFileData.bitrate).toBeDefined();
+                expect(mediaFileData.height).toBe(0);
+                expect(mediaFileData.width).toBe(0);
+                expect(mediaFileData.duration).toBeDefined();
+            })
+            var fail = jasmine.createSpy().andCallFake(function (error) { })
+            var captureSuccess = jasmine.createSpy().andCallFake(function (mediaFiles) {
+                runs(function () {
+
+                    mediaFiles.getFormatData(success, fail);
+                });
+                waitsFor(function () { return success.wasCalled; }, "success callback never called", 7500);
+            })
+            var captureError = jasmine.createSpy().andCallFake(function (error) {
+                console.log("code:" + error.code);
+            })
+            runs(function () {
+                navigator.device.capture.captureAudio(captureSuccess, captureError, { duration: 10 });
+            });
+
+            waitsFor(function () { return captureSuccess.wasCalled; }, "captureSuccess callback never called", 70000);
+
+            runs(function () {
+                expect(captureSuccess).toHaveBeenCalled();
+                expect(captureError).not.toHaveBeenCalled();
+            })
+        });
+    });
+});

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/1aa4b3ec/test/window8/compass.tests.js
----------------------------------------------------------------------
diff --git a/test/window8/compass.tests.js b/test/window8/compass.tests.js
new file mode 100644
index 0000000..d635e44
--- /dev/null
+++ b/test/window8/compass.tests.js
@@ -0,0 +1,76 @@
+describe('Compass (navigator.compass)', function () {
+    it("should exist", function () {
+        expect(navigator.compass).toBeDefined();
+    });
+
+    it("should contain a getCurrentHeading function", function () {
+        expect(navigator.compass.getCurrentHeading).toBeDefined();
+        expect(typeof navigator.compass.getCurrentHeading == 'function').toBe(true);
+    });
+
+    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(typeof a.timestamp == 'number').toBe(true);
+        }),
+            fail = jasmine.createSpy();
+
+        runs(function () {
+            navigator.compass.getCurrentHeading(win, fail);
+        });
+
+        waitsFor(function () { return win.wasCalled; }, "success callback never called", Tests.TEST_TIMEOUT);
+
+        runs(function () {
+            expect(fail).not.toHaveBeenCalled();
+            expect(win).toHaveBeenCalled();
+        });
+    });
+
+    it("should contain a watchHeading function", function () {
+        expect(navigator.compass.watchHeading).toBeDefined();
+        expect(typeof navigator.compass.watchHeading == 'function').toBe(true);
+    });
+
+    it("should contain a clearWatch function", function () {
+        expect(navigator.compass.clearWatch).toBeDefined();
+        expect(typeof navigator.compass.clearWatch == 'function').toBe(true);
+    });
+
+    describe('Compass Constants (window.CompassError)', function () {
+        it("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("should exist", function () {
+            expect(CompassHeading).toBeDefined();
+        });
+
+        it("should be able to create 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(typeof h.timestamp == 'number').toBe(true);
+        });
+
+        it("should be able to creat 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(typeof h.timestamp == 'number').toBe(true);
+        });
+    });
+});

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/1aa4b3ec/test/window8/contacts.tests.js
----------------------------------------------------------------------
diff --git a/test/window8/contacts.tests.js b/test/window8/contacts.tests.js
new file mode 100644
index 0000000..e4344bd
--- /dev/null
+++ b/test/window8/contacts.tests.js
@@ -0,0 +1,451 @@
+// global to store a contact so it doesn't have to be created or retrieved multiple times
+// all of the setup/teardown test methods can reference the following variables to make sure to do the right cleanup
+var gContactObj = null;
+var gContactId = null;
+
+var removeContact = function(){
+    if (gContactObj) {
+        gContactObj.remove(function(){},function(){
+            console.log("[CONTACTS ERROR]: removeContact cleanup method failed to clean up test artifacts.");
+        });
+        gContactObj = null;
+    }
+};
+
+describe("Contacts (navigator.contacts)", function () {
+    it("should exist", function() {
+        expect(navigator.contacts).toBeDefined();
+    });
+
+    it("should contain a find function", function() {
+        expect(navigator.contacts.find).toBeDefined();
+        expect(typeof navigator.contacts.find).toBe('function');
+    });
+
+    describe("find method", function() {
+        it("success callback should be called with an array", function() {
+            var win = jasmine.createSpy().andCallFake(function(result) {
+                    expect(result).toBeDefined();
+                    expect(result instanceof Array).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();
+            });
+        }); 
+
+        it("should throw an exception if success callback is empty", function() {
+            var fail = function() {};
+            var obj = new ContactFindOptions();
+            obj.filter="";
+            obj.multiple=true;
+
+            expect(function () {
+                navigator.contacts.find(["displayName", "name", "emails", "phoneNumbers"], null, fail, obj);
+            }).toThrow();
+        }); 
+
+        it("error callback should be called when no fields are specified", function() {
+            var win = jasmine.createSpy(),
+                fail = jasmine.createSpy(function(result) { 
+                    expect(result).toBeDefined();
+                    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 fail.wasCalled; }, Tests.TEST_TIMEOUT);
+
+            runs(function () { 
+                expect(win).not.toHaveBeenCalled();
+                expect(fail).toHaveBeenCalled();
+            });
+        });
+
+        describe("with newly-created contact", function () {
+
+            afterEach(removeContact);
+
+            it("should be able to find a contact by name", function() {
+                var foundName = jasmine.createSpy().andCallFake(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;
+                    }),
+                    fail = jasmine.createSpy(),
+                    test = jasmine.createSpy().andCallFake(function(savedContact) {
+                        console.log('in test');
+                        // update so contact will get removed
+                        gContactObj = savedContact;
+                        // ----
+                        // Find asserts
+                        // ---
+                        var findWin = jasmine.createSpy().andCallFake(function(object) {
+                                console.log('in findwin');
+                                expect(object instanceof Array).toBe(true);
+                                expect(object.length >= 1).toBe(true);
+                                expect(foundName(object)).toBe(true);
+                            }),
+                            findFail = jasmine.createSpy(),
+                            obj = new ContactFindOptions();
+
+                        obj.filter="Delete";
+                        obj.multiple=true;
+
+                        runs(function () {
+                            navigator.contacts.find(["displayName", "name", "phoneNumbers", "emails"], findWin, findFail, obj);
+                        });
+
+                        waitsFor(function () { return foundName.wasCalled; }, "foundName not done", Tests.TEST_TIMEOUT);
+
+                        runs(function () {
+                            expect(findFail).not.toHaveBeenCalled();
+                            expect(fail).not.toHaveBeenCalled();
+                        });
+                    });
+
+                runs(function () {
+                    gContactObj = new Contact();
+                    gContactObj.name = new ContactName();
+                    gContactObj.name.familyName = "Delete";
+                    gContactObj.save(test, fail);
+                });
+
+                waitsFor(function () { return test.wasCalled; }, "test not done", Tests.TEST_TIMEOUT);
+            });
+        });
+    });
+
+    describe('create method', function() {
+
+        it("should exist", function() {
+            expect(navigator.contacts.create).toBeDefined();
+            expect(typeof navigator.contacts.create).toBe('function');
+        });
+
+        it("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);
+        });
+    });
+
+    describe("Contact object", function () {
+        it("should be able to create instance", 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("ContactField object should coerce type and value properties to strings", function() {
+            var contactField = new ContactField(12345678, 12345678, true);
+            expect(contactField.type).toBe("12345678");
+            expect(contactField.value).toBe("12345678");
+        });	
+
+        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);
+        });	
+
+        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);
+        });
+        
+        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');
+        });
+    });
+
+    describe('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();
+            });
+        });
+    });
+
+    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();
+            });
+        });
+    });
+
+    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() {
+                            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) {
+                            throw("Newly created contact's remove function invoked error callback. Test failed.");
+                        });
+                    };
+                    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"], findWin, findFail, obj);
+                }, function(e) {
+                    throw("Contact creation failed, error callback was invoked.");
+                });
+            });
+
+            waitsFor(function () { return done; }, Tests.TEST_TIMEOUT);
+        });
+    });
+
+    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-js/blob/1aa4b3ec/test/window8/device.tests.js
----------------------------------------------------------------------
diff --git a/test/window8/device.tests.js b/test/window8/device.tests.js
new file mode 100644
index 0000000..cc322d6
--- /dev/null
+++ b/test/window8/device.tests.js
@@ -0,0 +1,34 @@
+describe('Device Information (window.device)', function () {
+	it("should exist", function() {
+        expect(window.device).toBeDefined();
+	});
+
+	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);
+	});
+
+	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);
+	});
+
+	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);
+	});
+
+	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') {
+		    expect((new String(window.device.uuid)).length > 0).toBe(true);
+		} else {
+			expect(window.device.uuid > 0).toBe(true);
+		}
+	});
+
+	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);
+	});
+});