You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by an...@apache.org on 2012/08/24 22:29:39 UTC

[6/72] [abbrv] [tizen SDK samples ] mobile-spec test app

http://git-wip-us.apache.org/repos/asf/incubator-cordova-tizen/blob/38e0ccf7/tizen SDK samples/mobile-spec/autotest/tests/filetransfer.tests.js
----------------------------------------------------------------------
diff --git a/tizen SDK samples/mobile-spec/autotest/tests/filetransfer.tests.js b/tizen SDK samples/mobile-spec/autotest/tests/filetransfer.tests.js
new file mode 100644
index 0000000..0779116
--- /dev/null
+++ b/tizen SDK samples/mobile-spec/autotest/tests/filetransfer.tests.js	
@@ -0,0 +1,407 @@
+describe('FileTransfer', function() {
+
+    // https://github.com/don/cordova-filetransfer
+    var server = "http://cordova-filetransfer.jitsu.com";
+
+    // deletes and re-creates the specified content
+    var writeFile = function(fileName, fileContent, success, error) {
+        var content = fileContent;
+        deleteEntry(fileName, function() {
+            root.getFile(fileName, {create: true}, function(fileEntry) {
+                fileEntry.createWriter(function (writer) {
+
+                    writer.onwrite = function(evt) {
+                        success(fileEntry);
+                    };
+
+                    writer.onabort = function(evt) {
+                        error(evt);
+                    };
+
+                    writer.error = function(evt) {
+                        error(evt);
+                    };
+
+                    writer.write(content + "\n");
+                }, error);
+            }, error);
+        }, error);
+    };
+
+    var getMalformedUrl = function() {
+        if (device.platform.match(/Android/i)) {
+            // bad protocol causes a MalformedUrlException on Android
+            return "httpssss://example.com";
+        } else {
+            // iOS doesn't care about protocol, space in hostname causes error
+            return "httpssss://exa mple.com";
+        }
+    };
+
+    // NOTE: copied from file.tests.js
+    // deletes specified file or directory
+    var deleteEntry = function(name, success, error) {
+        // deletes entry, if it exists
+        window.resolveLocalFileSystemURI(root.toURL() + '/' + name,
+            function(entry) {
+                if (entry.isDirectory === true) {
+                    entry.removeRecursively(success, error);
+                } else {
+                    entry.remove(success, error);
+                }
+            }, success);
+    };
+    // deletes and re-creates the specified file
+    var createFile = function(fileName, success, error) {
+        deleteEntry(fileName, function() {
+            root.getFile(fileName, {create: true}, success, error);
+        }, error);
+    };
+    // deletes file, if it exists, then invokes callback
+    var deleteFile = function(fileName, callback) {
+        root.getFile(fileName, null,
+            // remove file system entry
+            function(entry) {
+                entry.remove(callback, function() { console.log('[ERROR] deleteFile cleanup method invoked fail callback.'); });
+            },
+            // doesn't exist
+            callback);
+    };
+    // end copied from file.tests.js
+
+    it("should exist and be constructable", function() {
+        var ft = new FileTransfer();
+        expect(ft).toBeDefined();
+    });
+    it("should contain proper functions", function() {
+        var ft = new FileTransfer();
+        expect(typeof ft.upload).toBe('function');
+        expect(typeof ft.download).toBe('function');
+    });
+    describe('FileTransferError', function() {
+        it("FileTransferError constants should be defined", function() {
+            expect(FileTransferError.FILE_NOT_FOUND_ERR).toBe(1);
+            expect(FileTransferError.INVALID_URL_ERR).toBe(2);
+            expect(FileTransferError.CONNECTION_ERR).toBe(3);
+        });
+    });
+
+    describe('download method', function() {
+
+        // NOTE: if download tests are failing, check the white list
+        // Android
+        //   <access origin="httpssss://example.com"/>
+        //   <access origin="apache.org" subdomains="true" />
+        //   <access origin="cordova-filetransfer.jitsu.com"/>
+        // iOS
+        //   # Cordova.plist
+        //   ExternalHosts
+        //     - Item 1 String cordova-filetransfer.jitsu.com
+        //     - Item 2 String *.apache.org
+
+        it("should be able to download a file", function() {
+            var fail = jasmine.createSpy();
+            var remoteFile = server + "/robots.txt"
+            var localFileName = remoteFile.substring(remoteFile.lastIndexOf('/')+1);
+            var downloadWin = jasmine.createSpy().andCallFake(function(entry) {
+                expect(entry.name).toBe(localFileName);
+                deleteFile(localFileName);
+            });
+
+            runs(function() {
+                var ft = new FileTransfer();
+                ft.download(remoteFile, root.fullPath + "/" + localFileName, downloadWin, fail);
+            });
+
+            waitsFor(function() { return downloadWin.wasCalled; }, "downloadWin", Tests.TEST_TIMEOUT);
+
+            runs(function() {
+                expect(downloadWin).toHaveBeenCalled();
+                expect(fail).not.toHaveBeenCalled();
+            });
+        });
+        it("should get http status on failure", function() {
+            var downloadWin = jasmine.createSpy();
+
+            var remoteFile = server + "/404";
+            var localFileName = remoteFile.substring(remoteFile.lastIndexOf('/')+1);
+            var downloadFail = jasmine.createSpy().andCallFake(function(error) {
+                expect(error.http_status).toBe(404);
+                expect(error.http_status).not.toBe(401, "Ensure " + remoteFile + " is in the white list");
+                deleteFile(localFileName);
+            });
+
+            runs(function() {
+                var ft = new FileTransfer();
+                ft.download(remoteFile, root.fullPath + "/" + localFileName, downloadWin, downloadFail);
+            });
+
+            waitsFor(function() { return downloadFail.wasCalled; }, "downloadFail", Tests.TEST_TIMEOUT);
+
+            runs(function() {
+                expect(downloadFail).toHaveBeenCalled();
+                expect(downloadWin).not.toHaveBeenCalled();
+            });
+        });
+        it("should handle malformed urls", function() {
+
+            var downloadWin = jasmine.createSpy();
+
+            var remoteFile = getMalformedUrl();
+            var localFileName = "download_malformed_url.txt";
+            var downloadFail = jasmine.createSpy().andCallFake(function(error) {
+
+                // Note: Android needs the bad protocol to be added to the access list
+                // <access origin=".*"/> won't match because ^https?:// is prepended to the regex
+                // The bad protocol must begin with http to avoid automatic prefix
+                expect(error.http_status).not.toBe(401, "Ensure " + remoteFile + " is in the white list");
+                expect(error.code).toBe(FileTransferError.INVALID_URL_ERR);
+                deleteFile(localFileName);
+            });
+
+            runs(function() {
+                var ft = new FileTransfer();
+                ft.download(remoteFile, root.fullPath + "/" + localFileName, downloadWin, downloadFail);
+            });
+
+            waitsFor(function() { return downloadFail.wasCalled; }, "downloadFail", Tests.TEST_TIMEOUT);
+
+            runs(function() {
+                expect(downloadFail).toHaveBeenCalled();
+                expect(downloadWin).not.toHaveBeenCalled();
+            });
+        });
+        it("should handle unknown host", function() {
+            var downloadWin = jasmine.createSpy();
+
+            var remoteFile = "http://foobar.apache.org/index.html";
+            var localFileName = remoteFile.substring(remoteFile.lastIndexOf('/')+1);
+            var downloadFail = jasmine.createSpy().andCallFake(function(error) {
+                expect(error.code).toBe(FileTransferError.CONNECTION_ERR);
+            });
+
+            runs(function() {
+                var ft = new FileTransfer();
+                ft.download(remoteFile, root.fullPath + "/" + localFileName, downloadWin, downloadFail);
+            });
+
+            waitsFor(function() { return downloadFail.wasCalled; }, "downloadFail", Tests.TEST_TIMEOUT);
+
+            runs(function() {
+                expect(downloadFail).toHaveBeenCalled();
+                expect(downloadWin).not.toHaveBeenCalled();
+            });
+        });
+        it("should handle bad file path", function() {
+            var fail = jasmine.createSpy();
+            var downloadWin = jasmine.createSpy();
+
+            var remoteFile = server;
+            var badFilePath = "c:\\54321";
+            var downloadFail = jasmine.createSpy().andCallFake(function(error) {
+                expect(error.code).toBe(FileTransferError.FILE_NOT_FOUND_ERR);
+            });
+
+            runs(function() {
+                var ft = new FileTransfer();
+                ft.download(remoteFile, badFilePath, downloadWin, downloadFail);
+            });
+
+            waitsFor(function() { return downloadFail.wasCalled; }, "downloadFail", Tests.TEST_TIMEOUT);
+
+            runs(function() {
+                expect(downloadFail).toHaveBeenCalled();
+                expect(downloadWin).not.toHaveBeenCalled();
+                expect(fail).not.toHaveBeenCalled();
+            });
+        });
+    });
+    describe('upload method', function() {
+
+        it("should be able to upload a file", function() {
+            var fail = jasmine.createSpy();
+            var uploadFail = jasmine.createSpy();
+
+            var remoteFile = server + "/upload";
+            var localFileName = "upload.txt";
+
+            var uploadWin = jasmine.createSpy().andCallFake(function(uploadResult) {
+                expect(uploadResult.bytesSent).toBeGreaterThan(0);
+                expect(uploadResult.responseCode).toBe(200);
+                expect(uploadResult.response).toBeDefined();
+                deleteEntry(localFileName);
+            });
+
+            var fileWin = function(fileEntry) {
+                ft = new FileTransfer();
+
+                var options = new FileUploadOptions();
+                options.fileKey = "file";
+                options.fileName = localFileName;
+                options.mimeType = "text/plain";
+
+                var params = new Object();
+                params.value1 = "test";
+                params.value2 = "param";
+                options.params = params;
+
+                // removing options cause Android to timeout
+                ft.upload(fileEntry.fullPath, remoteFile, uploadWin, uploadFail, options);
+            };
+
+            runs(function() {
+                writeFile(localFileName, "this file should upload", fileWin, fail);
+            });
+
+            waitsFor(function() { return uploadWin.wasCalled; }, "uploadWin", Tests.TEST_TIMEOUT);
+
+            runs(function() {
+                expect(uploadWin).toHaveBeenCalled();
+                expect(uploadFail).not.toHaveBeenCalled();
+                expect(fail).not.toHaveBeenCalled();
+            });
+        });
+        it("should get http status on failure", function() {
+            var fail = jasmine.createSpy();
+            var uploadWin = jasmine.createSpy();
+
+            var remoteFile = server + "/403";
+            var localFileName = "upload_expect_fail.txt";
+            var uploadFail = jasmine.createSpy().andCallFake(function(error) {
+                expect(error.http_status).toBe(403);
+                expect(error.http_status).not.toBe(401, "Ensure " + remoteFile + " is in the white list");
+                deleteEntry(localFileName);
+            });
+
+            var fileWin = function(fileEntry) {
+                var ft = new FileTransfer();
+
+                var options = new FileUploadOptions();
+                options.fileKey="file";
+                options.fileName=fileEntry.name;
+                options.mimeType="text/plain";
+
+                ft.upload(fileEntry.fullPath, remoteFile, uploadWin, uploadFail, options);
+            };
+
+            runs(function() {
+                writeFile(localFileName, "this file should fail to upload", fileWin, fail);
+            });
+
+            waitsFor(function() { return uploadFail.wasCalled; }, "Expecting file upload to fail", Tests.TEST_TIMEOUT);
+
+            runs(function() {
+                expect(uploadFail).toHaveBeenCalled();
+                expect(uploadWin).not.toHaveBeenCalled();
+                expect(fail).not.toHaveBeenCalled();
+            });
+        });
+        it("should handle malformed urls", function() {
+            var fail = jasmine.createSpy();
+            var uploadWin = jasmine.createSpy();
+
+            var remoteFile = getMalformedUrl();
+            var localFileName = "malformed_url.txt";
+            var uploadFail = jasmine.createSpy().andCallFake(function(error) {
+                expect(error.code).toBe(FileTransferError.INVALID_URL_ERR);
+                expect(error.http_status).not.toBe(401, "Ensure " + remoteFile + " is in the white list");
+                deleteFile(localFileName);
+            });
+            var fileWin = function(fileEntry) {
+                var ft = new FileTransfer();
+                ft.upload(fileEntry.fullPath, remoteFile, uploadWin, uploadFail, {});
+            };
+
+            runs(function() {
+                writeFile(localFileName, "Some content", fileWin, fail);
+            });
+
+            waitsFor(function() { return uploadFail.wasCalled; }, "uploadFail", Tests.TEST_TIMEOUT);
+
+            runs(function() {
+                expect(uploadFail).toHaveBeenCalled();
+                expect(uploadWin).not.toHaveBeenCalled();
+                expect(fail).not.toHaveBeenCalled();
+            });
+        });
+        it("should handle unknown host", function() {
+            var fail = jasmine.createSpy();
+            var uploadWin = jasmine.createSpy();
+
+            var remoteFile = "http://foobar.apache.org/robots.txt";
+            var localFileName = remoteFile.substring(remoteFile.lastIndexOf('/')+1);
+            var uploadFail = jasmine.createSpy().andCallFake(function(error) {
+                expect(error.code).toBe(FileTransferError.CONNECTION_ERR);
+                expect(error.http_status).not.toBe(401, "Ensure " + remoteFile + " is in the white list");
+                deleteFile(localFileName);
+            });
+            var fileWin = function(fileEntry) {
+                var ft = new FileTransfer();
+                ft.upload(fileEntry.fullPath, remoteFile, uploadWin, uploadFail, {});
+            };
+
+            runs(function() {
+                writeFile(localFileName, "# allow all", fileWin, fail);
+            });
+
+            waitsFor(function() { return uploadFail.wasCalled; }, "uploadFail", Tests.TEST_TIMEOUT);
+
+            runs(function() {
+                expect(uploadFail).toHaveBeenCalled();
+                expect(uploadWin).not.toHaveBeenCalled();
+                expect(fail).not.toHaveBeenCalled();
+            });
+        });
+        it("should handle missing file", function() {
+            var fail = jasmine.createSpy();
+            var uploadWin = jasmine.createSpy();
+
+            var remoteFile = server + "/upload";
+            var localFileName = "does_not_exist.txt";
+
+            var uploadFail = jasmine.createSpy().andCallFake(function(error) {
+                expect(error.code).toBe(FileTransferError.FILE_NOT_FOUND_ERR);
+                expect(error.http_status).not.toBe(401, "Ensure " + remoteFile + " is in the white list");
+            });
+
+            runs(function() {
+                deleteFile(localFileName, function() {
+                    var ft = new FileTransfer();
+                    ft.upload(root.fullPath + "/" + localFileName, remoteFile, uploadWin, uploadFail);
+                }, fail);
+            });
+
+            waitsFor(function() { return uploadFail.wasCalled; }, "uploadFail", Tests.TEST_TIMEOUT);
+
+            runs(function() {
+                expect(uploadFail).toHaveBeenCalled();
+                expect(uploadWin).not.toHaveBeenCalled();
+                expect(fail).not.toHaveBeenCalled();
+            });
+        });
+        it("should handle bad file path", function() {
+            var uploadWin = jasmine.createSpy();
+
+            var remoteFile = server + "/upload";
+
+            var uploadFail = jasmine.createSpy().andCallFake(function(error) {
+                expect(error.code).toBe(FileTransferError.FILE_NOT_FOUND_ERR);
+                expect(error.http_status).not.toBe(401, "Ensure " + remoteFile + " is in the white list");
+            });
+
+            runs(function() {
+                var ft = new FileTransfer();
+                ft.upload("/usr/local/bad/file/path.txt", remoteFile, uploadWin, uploadFail);
+            });
+
+            waitsFor(function() { return uploadFail.wasCalled; }, "uploadFail", Tests.TEST_TIMEOUT);
+
+            runs(function() {
+                expect(uploadFail).toHaveBeenCalled();
+                expect(uploadWin).not.toHaveBeenCalled();
+            });
+
+        });
+
+    });
+});

http://git-wip-us.apache.org/repos/asf/incubator-cordova-tizen/blob/38e0ccf7/tizen SDK samples/mobile-spec/autotest/tests/geolocation.tests.js
----------------------------------------------------------------------
diff --git a/tizen SDK samples/mobile-spec/autotest/tests/geolocation.tests.js b/tizen SDK samples/mobile-spec/autotest/tests/geolocation.tests.js
new file mode 100644
index 0000000..685a7d6
--- /dev/null
+++ b/tizen SDK samples/mobile-spec/autotest/tests/geolocation.tests.js	
@@ -0,0 +1,142 @@
+describe('Geolocation (navigator.geolocation)', function () {
+    it("should exist", function() {
+        expect(navigator.geolocation).toBeDefined();
+    });
+
+    it("should contain a getCurrentPosition function", function() {
+        expect(typeof navigator.geolocation.getCurrentPosition).toBeDefined();
+        expect(typeof navigator.geolocation.getCurrentPosition == 'function').toBe(true);
+    });
+
+    it("should contain a watchPosition function", function() {
+        expect(typeof navigator.geolocation.watchPosition).toBeDefined();
+        expect(typeof navigator.geolocation.watchPosition == 'function').toBe(true);
+    });
+
+    it("should contain a clearWatch function", function() {
+        expect(typeof navigator.geolocation.clearWatch).toBeDefined();
+        expect(typeof navigator.geolocation.clearWatch == 'function').toBe(true);
+    });
+
+    describe('getCurrentPosition method', function() {
+        describe('error callback', function() {
+            it("should be called if we set timeout to 0 and maximumAge to a very small number", function() {
+                console.log("Here I am");
+                var win = jasmine.createSpy(),
+                    fail = jasmine.createSpy();
+
+                runs(function () {
+                    navigator.geolocation.getCurrentPosition(win, fail, {
+                        maximumAge: 0,
+                        timeout: 0
+                    });
+                });
+
+                waitsFor(function () { return fail.wasCalled; }, "fail never called", 250); //small timeout as this should fire very fast
+
+                runs(function () {
+                    expect(win).not.toHaveBeenCalled();
+                });
+            });
+        });
+
+        describe('success callback', function() {
+            it("should be called with a Position object", function() {
+                var win = jasmine.createSpy().andCallFake(function(p) {
+                          expect(p.coords).toBeDefined();
+                          expect(p.timestamp).toBeDefined();
+                          expect(p.timestamp instanceof Date).toBe(true);
+                      }),
+                      fail = jasmine.createSpy();
+
+                runs(function () {
+                    navigator.geolocation.getCurrentPosition(win, fail, {
+                        maximumAge:300000 // 5 minutes maximum age of cached position
+                    });
+                });
+
+                waitsFor(function () { return win.wasCalled; }, "win never called", 20000);
+
+                runs(function () {
+                    expect(fail).not.toHaveBeenCalled();
+                });
+            });
+        });
+    });
+
+    describe('watchPosition method', function() {
+        describe('error callback', function() {
+            var errorWatch = null;
+
+            afterEach(function() {
+                navigator.geolocation.clearWatch(errorWatch);
+            });
+            it("should be called if we set timeout to 0 and maximumAge to a very small number", function() {
+                var win = jasmine.createSpy(),
+                    fail = jasmine.createSpy();
+
+                runs(function () {
+                    errorWatch = navigator.geolocation.watchPosition(win, fail, {
+                        maximumAge: 0,
+                        timeout: 0
+                    });
+                });
+
+                waitsFor(function () { return fail.wasCalled; }, "fail never called", 250); // small timeout as this hsould fire very quickly
+
+                runs(function () {
+                    expect(win).not.toHaveBeenCalled();
+                });
+            });
+        });
+
+        describe('success callback', function() {
+            var successWatch = null;
+
+            afterEach(function() {
+                navigator.geolocation.clearWatch(successWatch);
+            });
+            it("should be called with a Position object", function() {
+                var win = jasmine.createSpy().andCallFake(function(p) {
+                          expect(p.coords).toBeDefined();
+                          expect(p.timestamp).toBeDefined();
+                          expect(p.timestamp instanceof Date).toBe(true);
+                      }),
+                      fail = jasmine.createSpy();
+
+                runs(function () {
+                    successWatch = navigator.geolocation.watchPosition(win, fail, {
+                        maximumAge:300000 // 5 minutes maximum age of cached position
+                    });
+                });
+
+                waitsFor(function () { return win.wasCalled; }, "win never called", 20000);
+
+                runs(function () {
+                    expect(fail).not.toHaveBeenCalled();
+                });
+            });
+        });
+    });
+
+    describe("Geolocation model", function () {
+        it("should be able to define a Position object with coords and timestamp properties", function() {
+            var pos = new Position({}, new Date());
+            expect(pos).toBeDefined();
+            expect(pos.coords).toBeDefined();
+            expect(pos.timestamp).toBeDefined();
+        });
+
+        it("should be able to define a Coordinates object with latitude, longitude, accuracy, altitude, heading, speed and altitudeAccuracy properties", function() {
+            var coords = new Coordinates(1,2,3,4,5,6,7);
+            expect(coords).toBeDefined();
+            expect(coords.latitude).toBeDefined();
+            expect(coords.longitude).toBeDefined();
+            expect(coords.accuracy).toBeDefined();
+            expect(coords.altitude).toBeDefined();
+            expect(coords.heading).toBeDefined();
+            expect(coords.speed).toBeDefined();
+            expect(coords.altitudeAccuracy).toBeDefined();
+        });
+    });
+});

http://git-wip-us.apache.org/repos/asf/incubator-cordova-tizen/blob/38e0ccf7/tizen SDK samples/mobile-spec/autotest/tests/media.tests.js
----------------------------------------------------------------------
diff --git a/tizen SDK samples/mobile-spec/autotest/tests/media.tests.js b/tizen SDK samples/mobile-spec/autotest/tests/media.tests.js
new file mode 100644
index 0000000..d0e6c4f
--- /dev/null
+++ b/tizen SDK samples/mobile-spec/autotest/tests/media.tests.js	
@@ -0,0 +1,144 @@
+describe('Media', function () {
+	it("should exist", function() {
+        expect(Media).toBeDefined();
+		expect(typeof Media).toBe("function");
+	});
+
+    it("should have the following properties", function() {
+        var media1 = new Media("dummy");
+        expect(media1.id).toBeDefined();
+        expect(media1.src).toBeDefined();
+        expect(media1._duration).toBeDefined();
+        expect(media1._position).toBeDefined();
+        media1.release();
+    });
+
+	it("should define constants for Media errors", function() {
+        expect(MediaError).toBeDefined();
+        expect(MediaError.MEDIA_ERR_NONE_ACTIVE).toBe(0);
+        expect(MediaError.MEDIA_ERR_ABORTED).toBe(1);
+		expect(MediaError.MEDIA_ERR_NETWORK).toBe(2);
+		expect(MediaError.MEDIA_ERR_DECODE).toBe(3);
+		expect(MediaError.MEDIA_ERR_NONE_SUPPORTED).toBe(4);
+	});
+
+    it("should contain a play function", function() {
+        var media1 = new Media();
+        expect(media1.play).toBeDefined();
+        expect(typeof media1.play).toBe('function');
+        media1.release();
+    });
+
+    it("should contain a stop function", function() {
+        var media1 = new Media();
+        expect(media1.stop).toBeDefined();
+        expect(typeof media1.stop).toBe('function');
+        media1.release();
+    });
+
+    it("should contain a seekTo function", function() {
+        var media1 = new Media();
+        expect(media1.seekTo).toBeDefined();
+        expect(typeof media1.seekTo).toBe('function');
+        media1.release();
+    });
+
+    it("should contain a pause function", function() {
+        var media1 = new Media();
+        expect(media1.pause).toBeDefined();
+        expect(typeof media1.pause).toBe('function');
+        media1.release();
+    });
+
+    it("should contain a getDuration function", function() {
+        var media1 = new Media();
+        expect(media1.getDuration).toBeDefined();
+        expect(typeof media1.getDuration).toBe('function');
+        media1.release();
+    });
+
+    it("should contain a getCurrentPosition function", function() {
+        var media1 = new Media();
+        expect(media1.getCurrentPosition).toBeDefined();
+        expect(typeof media1.getCurrentPosition).toBe('function');
+        media1.release();
+    });
+
+    it("should contain a startRecord function", function() {
+        var media1 = new Media();
+        expect(media1.startRecord).toBeDefined();
+        expect(typeof media1.startRecord).toBe('function');
+        media1.release();
+    });
+
+    it("should contain a stopRecord function", function() {
+        var media1 = new Media();
+        expect(media1.stopRecord).toBeDefined();
+        expect(typeof media1.stopRecord).toBe('function');
+        media1.release();
+    });
+
+    it("should contain a release function", function() {
+        var media1 = new Media();
+        expect(media1.release).toBeDefined();
+        expect(typeof media1.release).toBe('function');
+        media1.release();
+    });
+
+    it("should contain a setVolume function", function() {
+        var media1 = new Media();
+        expect(media1.setVolume).toBeDefined();
+        expect(typeof media1.setVolume).toBe('function');
+        media1.release();
+    });
+
+	it("should return MediaError for bad filename", function() {
+		var badMedia = null,
+            win = jasmine.createSpy(),
+            fail = jasmine.createSpy().andCallFake(function (result) {
+                expect(result).toBeDefined();
+                expect(result.code).toBe(MediaError.MEDIA_ERR_ABORTED);
+            });
+            
+        runs(function () {
+            badMedia = new Media("invalid.file.name", win,fail);
+            badMedia.play();
+        });
+
+        waitsFor(function () { return fail.wasCalled; }, Tests.TEST_TIMEOUT);
+
+        runs(function () {
+            expect(win).not.toHaveBeenCalled();
+            badMedia.release();
+        });
+	});
+
+    it("position should be set properly", function() {
+        var media1 = new Media("http://audio.ibeat.org/content/p1rj1s/p1rj1s_-_rockGuitar.mp3"),
+            test = jasmine.createSpy().andCallFake(function(position) {
+                    console.log("position = " + position);
+                    expect(position).toBeGreaterThan(0.0);
+                    media1.stop()
+                    media1.release();
+                });
+
+        media1.play();
+
+        waits(5000);
+
+        runs(function () {
+            media1.getCurrentPosition(test, function () {});
+        });
+
+        waitsFor(function () { return test.wasCalled; }, Tests.TEST_TIMEOUT);
+    });
+
+    it("duration should be set properly", function() {
+        var media1 = new Media("http://audio.ibeat.org/content/p1rj1s/p1rj1s_-_rockGuitar.mp3");
+        media1.play();
+        waits(5000);
+        runs(function () {
+            expect(media1.getDuration()).toBeGreaterThan(0.0);
+        });
+    });
+});

http://git-wip-us.apache.org/repos/asf/incubator-cordova-tizen/blob/38e0ccf7/tizen SDK samples/mobile-spec/autotest/tests/network.tests.js
----------------------------------------------------------------------
diff --git a/tizen SDK samples/mobile-spec/autotest/tests/network.tests.js b/tizen SDK samples/mobile-spec/autotest/tests/network.tests.js
new file mode 100644
index 0000000..780097f
--- /dev/null
+++ b/tizen SDK samples/mobile-spec/autotest/tests/network.tests.js	
@@ -0,0 +1,25 @@
+describe('Network (navigator.network)', function () {
+	it("should exist", function() {
+        expect(navigator.network).toBeDefined();
+	});
+
+    describe('Network Information API', function () {
+        it("connection should exist", function() {
+            expect(navigator.network.connection).toBeDefined();
+        });
+
+        it("should contain connection properties", function() {
+            expect(navigator.network.connection.type).toBeDefined();
+        });
+
+        it("should define constants for connection status", function() {
+            expect(Connection.UNKNOWN).toBe("unknown");
+            expect(Connection.ETHERNET).toBe("ethernet");
+            expect(Connection.WIFI).toBe("wifi");
+            expect(Connection.CELL_2G).toBe("2g");
+            expect(Connection.CELL_3G).toBe("3g");
+            expect(Connection.CELL_4G).toBe("4g");
+            expect(Connection.NONE).toBe("none");
+        });
+    });
+});

http://git-wip-us.apache.org/repos/asf/incubator-cordova-tizen/blob/38e0ccf7/tizen SDK samples/mobile-spec/autotest/tests/notification.tests.js
----------------------------------------------------------------------
diff --git a/tizen SDK samples/mobile-spec/autotest/tests/notification.tests.js b/tizen SDK samples/mobile-spec/autotest/tests/notification.tests.js
new file mode 100644
index 0000000..61c795d
--- /dev/null
+++ b/tizen SDK samples/mobile-spec/autotest/tests/notification.tests.js	
@@ -0,0 +1,20 @@
+describe('Notification (navigator.notification)', function () {
+	it("should exist", function() {
+        expect(navigator.notification).toBeDefined();
+	});
+
+	it("should contain a vibrate function", function() {
+		expect(typeof navigator.notification.vibrate).toBeDefined();
+		expect(typeof navigator.notification.vibrate).toBe("function");
+	});
+
+	it("should contain a beep function", function() {
+		expect(typeof navigator.notification.beep).toBeDefined();
+		expect(typeof navigator.notification.beep).toBe("function");
+	});
+
+	it("should contain a alert function", function() {
+		expect(typeof navigator.notification.alert).toBeDefined();
+		expect(typeof navigator.notification.alert).toBe("function");
+	});
+});

http://git-wip-us.apache.org/repos/asf/incubator-cordova-tizen/blob/38e0ccf7/tizen SDK samples/mobile-spec/autotest/tests/platform.tests.js
----------------------------------------------------------------------
diff --git a/tizen SDK samples/mobile-spec/autotest/tests/platform.tests.js b/tizen SDK samples/mobile-spec/autotest/tests/platform.tests.js
new file mode 100644
index 0000000..f44fcb3
--- /dev/null
+++ b/tizen SDK samples/mobile-spec/autotest/tests/platform.tests.js	
@@ -0,0 +1,10 @@
+describe('Platform (cordova)', function () {
+    it("should exist", function() {
+        expect(cordova).toBeDefined();
+    });
+
+    it("exec method should exist", function() {
+        expect(cordova.exec).toBeDefined();
+        expect(typeof cordova.exec).toBe('function');
+    });
+});

http://git-wip-us.apache.org/repos/asf/incubator-cordova-tizen/blob/38e0ccf7/tizen SDK samples/mobile-spec/autotest/tests/storage.tests.js
----------------------------------------------------------------------
diff --git a/tizen SDK samples/mobile-spec/autotest/tests/storage.tests.js b/tizen SDK samples/mobile-spec/autotest/tests/storage.tests.js
new file mode 100644
index 0000000..a921de3
--- /dev/null
+++ b/tizen SDK samples/mobile-spec/autotest/tests/storage.tests.js	
@@ -0,0 +1,161 @@
+describe("Session Storage", function () {
+    it("should exist", function () {
+        expect(window.sessionStorage).toBeDefined();
+        expect(typeof window.sessionStorage.length).not.toBe('undefined');
+        expect(typeof(window.sessionStorage.key)).toBe('function');
+        expect(typeof(window.sessionStorage.getItem)).toBe('function');
+        expect(typeof(window.sessionStorage.setItem)).toBe('function');
+        expect(typeof(window.sessionStorage.removeItem)).toBe('function');
+        expect(typeof(window.sessionStorage.clear)).toBe('function');
+    });
+
+    it("check length", function () {
+        expect(window.sessionStorage.length).toBe(0);
+        window.sessionStorage.setItem("key","value");
+        expect(window.sessionStorage.length).toBe(1);
+        window.sessionStorage.removeItem("key");   
+        expect(window.sessionStorage.length).toBe(0);
+    });
+
+    it("check key", function () {
+        expect(window.sessionStorage.key(0)).toBe(null);
+        window.sessionStorage.setItem("test","value");
+        expect(window.sessionStorage.key(0)).toBe("test");
+        window.sessionStorage.removeItem("test");   
+        expect(window.sessionStorage.key(0)).toBe(null);
+    });
+
+    it("check getItem", function() {
+        expect(window.sessionStorage.getItem("item")).toBe(null);
+        window.sessionStorage.setItem("item","value");
+        expect(window.sessionStorage.getItem("item")).toBe("value");
+        window.sessionStorage.removeItem("item");   
+        expect(window.sessionStorage.getItem("item")).toBe(null);
+    });
+
+    it("check setItem", function() {
+        expect(window.sessionStorage.getItem("item")).toBe(null);
+        window.sessionStorage.setItem("item","value");
+        expect(window.sessionStorage.getItem("item")).toBe("value");
+        window.sessionStorage.setItem("item","newval");
+        expect(window.sessionStorage.getItem("item")).toBe("newval");
+        window.sessionStorage.removeItem("item");   
+        expect(window.sessionStorage.getItem("item")).toBe(null);
+    });
+
+    it("can remove an item", function () {
+        expect(window.sessionStorage.getItem("item")).toBe(null);
+        window.sessionStorage.setItem("item","value");
+        expect(window.sessionStorage.getItem("item")).toBe("value");
+        window.sessionStorage.removeItem("item");   
+        expect(window.sessionStorage.getItem("item")).toBe(null);
+    });
+
+    it("check clear", function() {
+        window.sessionStorage.setItem("item1","value");
+        window.sessionStorage.setItem("item2","value");
+        window.sessionStorage.setItem("item3","value");
+        expect(window.sessionStorage.length).toBe(3);
+        window.sessionStorage.clear();
+        expect(window.sessionStorage.length).toBe(0);
+    });
+
+    it("check dot notation", function() {
+        expect(window.sessionStorage.item).not.toBeDefined();
+        window.sessionStorage.item = "value";
+        expect(window.sessionStorage.item).toBe("value");
+        window.sessionStorage.removeItem("item");   
+        expect(window.sessionStorage.item).not.toBeDefined();
+    });
+
+    describe("Local Storage", function () {
+        it("should exist", function() {
+            expect(window.localStorage).toBeDefined();
+            expect(window.localStorage.length).toBeDefined();
+            expect(typeof window.localStorage.key).toBe("function");
+            expect(typeof window.localStorage.getItem).toBe("function");
+            expect(typeof window.localStorage.setItem).toBe("function");
+            expect(typeof window.localStorage.removeItem).toBe("function");
+            expect(typeof window.localStorage.clear).toBe("function");
+        });  
+
+        it("check length", function() {
+            expect(window.localStorage.length).toBe(0);
+            window.localStorage.setItem("key","value");
+            expect(window.localStorage.length).toBe(1);
+            window.localStorage.removeItem("key");   
+            expect(window.localStorage.length).toBe(0);
+        });
+
+        it("check key", function() {
+            expect(window.localStorage.key(0)).toBe(null);
+            window.localStorage.setItem("test","value");
+            expect(window.localStorage.key(0)).toBe("test");
+            window.localStorage.removeItem("test");   
+            expect(window.localStorage.key(0)).toBe(null);
+        });
+
+        it("check getItem", function() {
+            expect(window.localStorage.getItem("item")).toBe(null);
+            window.localStorage.setItem("item","value");
+            expect(window.localStorage.getItem("item")).toBe("value");
+            window.localStorage.removeItem("item");   
+            expect(window.localStorage.getItem("item")).toBe(null);
+        });
+
+        it("check setItem", function() {
+            expect(window.localStorage.getItem("item")).toBe(null);
+            window.localStorage.setItem("item","value");
+            expect(window.localStorage.getItem("item")).toBe("value");
+            window.localStorage.setItem("item","newval");
+            expect(window.localStorage.getItem("item")).toBe("newval");
+            window.localStorage.removeItem("item");   
+            expect(window.localStorage.getItem("item")).toBe(null);
+        });
+
+        it("check removeItem", function() {
+            expect(window.localStorage.getItem("item")).toBe(null);
+            window.localStorage.setItem("item","value");
+            expect(window.localStorage.getItem("item")).toBe("value");
+            window.localStorage.removeItem("item");   
+            expect(window.localStorage.getItem("item")).toBe(null);
+        });
+
+        it("check clear", function() {
+            expect(window.localStorage.getItem("item1")).toBe(null);
+            expect(window.localStorage.getItem("item2")).toBe(null);
+            expect(window.localStorage.getItem("item3")).toBe(null);
+            window.localStorage.setItem("item1","value");
+            window.localStorage.setItem("item2","value");
+            window.localStorage.setItem("item3","value");
+            expect(window.localStorage.getItem("item1")).toBe("value");
+            expect(window.localStorage.getItem("item2")).toBe("value");
+            expect(window.localStorage.getItem("item3")).toBe("value");
+            expect(window.localStorage.length).toBe(3);
+            window.localStorage.clear();
+            expect(window.localStorage.length).toBe(0);
+            expect(window.localStorage.getItem("item1")).toBe(null);
+            expect(window.localStorage.getItem("item2")).toBe(null);
+            expect(window.localStorage.getItem("item3")).toBe(null);
+        });
+
+        it("check dot notation", function() {
+            expect(window.localStorage.item).not.toBeDefined();
+            window.localStorage.item = "value";
+            expect(window.localStorage.item).toBe("value");
+            window.localStorage.removeItem("item");   
+            expect(window.localStorage.item).not.toBeDefined();
+        });
+    });
+
+    describe("HTML 5 Storage", function () {
+        it("should exist", function() {
+            expect(window.openDatabase);
+        });
+
+        it("Should open a database", function() {
+            var db = openDatabase("Database", "1.0", "HTML5 Database API example", 200000);
+            expect(db).toBeDefined();
+        });
+    });
+});

http://git-wip-us.apache.org/repos/asf/incubator-cordova-tizen/blob/38e0ccf7/tizen SDK samples/mobile-spec/battery/index.html
----------------------------------------------------------------------
diff --git a/tizen SDK samples/mobile-spec/battery/index.html b/tizen SDK samples/mobile-spec/battery/index.html
new file mode 100644
index 0000000..394988c
--- /dev/null
+++ b/tizen SDK samples/mobile-spec/battery/index.html	
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta name="viewport" content="width=device-width,height=device-height,user-scalable=no,maximum-scale=1.0,initial-scale=1.0" />
+    <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <!-- ISO-8859-1 -->
+    <title>Cordova Mobile Spec</title>
+    <link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title" charset="utf-8">
+    <script type="text/javascript" charset="utf-8" src="../cordova.js"></script>      
+
+      
+<script type="text/javascript" charset="utf-8">
+
+    var deviceReady = false;
+    
+    /**
+     * Function called when page has finished loading.
+     */
+    function init() {
+        document.addEventListener("deviceready", function() {
+                deviceReady = true;
+                console.log("Device="+device.platform+" "+device.version);
+            }, false);
+        window.setTimeout(function() {
+            if (!deviceReady) {
+                alert("Error: PhoneGap did not initialize.  Demo will not run correctly.");
+            }
+        },1000);
+    }
+
+    /* Battery */
+    function updateInfo(info) {
+        document.getElementById('level').innerText = info.level;
+        document.getElementById('isPlugged').innerText = info.isPlugged;
+        if (info.level > 5) {
+            document.getElementById('crit').innerText = "false";
+        }
+        if (info.level > 20) {
+            document.getElementById('low').innerText = "false";
+        }
+    }
+    
+    function batteryLow(info) {
+        document.getElementById('low').innerText = "true";
+    }
+    
+    function batteryCritical(info) {
+        document.getElementById('crit').innerText = "true";
+    }
+    
+    function addBattery() {
+        window.addEventListener("batterystatus", updateInfo, false);
+    }
+    
+    function removeBattery() {
+        window.removeEventListener("batterystatus", updateInfo, false);
+    }
+    
+    function addLow() {
+        window.addEventListener("batterylow", batteryLow, false);
+    }
+    
+    function removeLow() {
+        window.removeEventListener("batterylow", batteryLow, false);
+    }
+    
+    function addCritical() {
+        window.addEventListener("batterycritical", batteryCritical, false);
+    }
+    
+    function removeCritical() {
+        window.removeEventListener("batterycritical", batteryCritical, false);
+    }
+
+</script>
+
+  </head>
+  <body onload="init();" id="stage" class="theme">
+  
+    <h1>Battery</h1>
+    <div id="info">
+        <b>Status:</b> <span id="battery_status"></span><br>
+        Level: <span id="level"></span><br/>
+        Plugged: <span id="isPlugged"></span><br/>
+        Low: <span id="low"></span><br/>
+        Critical: <span id="crit"></span><br/>
+    </div>
+    <h2>Action</h2>
+    <div class="btn large" onclick="addBattery();">Add "batterystatus" listener</div>
+    <div class="btn large" onclick="removeBattery();">Remove "batterystatus" listener</div>
+    <div class="btn large" onclick="addLow();">Add "batterylow" listener</div>
+    <div class="btn large" onclick="removeLow();">Remove "batterylow" listener</div>
+    <div class="btn large" onclick="addCritical();">Add "batterycritical" listener</div>
+    <div class="btn large" onclick="removeCritical();">Remove "batterycritical" listener</div>
+    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+  </body>
+</html>      

http://git-wip-us.apache.org/repos/asf/incubator-cordova-tizen/blob/38e0ccf7/tizen SDK samples/mobile-spec/camera/index.html
----------------------------------------------------------------------
diff --git a/tizen SDK samples/mobile-spec/camera/index.html b/tizen SDK samples/mobile-spec/camera/index.html
new file mode 100755
index 0000000..bc3b554
--- /dev/null
+++ b/tizen SDK samples/mobile-spec/camera/index.html	
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta name="viewport" content="width=device-width,height=device-height,user-scalable=no,maximum-scale=1.0,initial-scale=1.0" />
+    <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <!-- ISO-8859-1 -->
+    <title>Cordova Mobile Spec</title>
+    <link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title" charset="utf-8">
+    <script type="text/javascript" charset="utf-8" src="../cordova.js"></script>      
+
+      
+<script type="text/javascript" charset="utf-8">
+
+    var deviceReady = false;
+
+    //-------------------------------------------------------------------------
+    // Camera 
+    //-------------------------------------------------------------------------
+
+    /**
+     * Capture picture
+     */
+    function getPicture() {
+        
+        //navigator.camera.getPicture(onPhotoDataSuccess, onFail, { quality: 50, 
+        //    destinationType: Camera.DestinationType.FILE_URI, sourceType : Camera.PictureSourceType.CAMERA });
+        
+        navigator.camera.getPicture(
+            function(data) {
+                var img = document.getElementById('camera_image');
+                img.style.visibility = "visible";
+                img.style.display = "block";
+                //img.src = "data:image/jpeg;base64," + data;
+                img.src = data;
+                document.getElementById('camera_status').innerHTML = "Success";
+            },
+            function(e) {
+                console.log("Error getting picture: " + e);
+                document.getElementById('camera_status').innerHTML = "Error getting picture.";
+            },
+            { quality: 50, destinationType:
+            Camera.DestinationType.FILE_URI, sourceType : Camera.PictureSourceType.CAMERA});
+    };
+
+    /**
+     * Select image from library
+     */
+    function getImage() {
+        navigator.camera.getPicture(
+            function(data) {
+                var img = document.getElementById('camera_image');
+                img.style.visibility = "visible";
+                img.style.display = "block";
+                //img.src = "data:image/jpeg;base64," + data;
+                img.src = data;
+                document.getElementById('camera_status').innerHTML = "Success";
+            },
+            function(e) {
+                console.log("Error getting picture: " + e);
+                document.getElementById('camera_status').innerHTML = "Error getting picture.";
+            },
+            { quality: 50, destinationType:
+            Camera.DestinationType.FILE_URI, sourceType: Camera.PictureSourceType.PHOTOLIBRARY});
+    };
+
+    
+    /**
+     * Function called when page has finished loading.
+     */
+    function init() {
+        document.addEventListener("deviceready", function() {
+                deviceReady = true;
+                console.log("Device="+device.platform+" "+device.version);
+            }, false);
+        window.setTimeout(function() {
+        	if (!deviceReady) {
+        		alert("Error: PhoneGap did not initialize.  Demo will not run correctly.");
+        	}
+        },1000);
+    }
+
+</script>
+
+  </head>
+  <body onload="init();" id="stage" class="theme">
+  
+    <h1>Camera</h1>
+    <div id="info">
+        <b>Status:</b> <span id="camera_status"></span><br>
+        <img style="width:120px;height:120px;visibility:hidden;display:none;" id="camera_image" src="" />
+    </div>
+    <h2>Action</h2>
+    <div class="btn large" onclick="getPicture();">Take Picture</div>
+    <div class="btn large" onclick="getImage();">Select Image from Library</div>
+    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+  </body>
+</html>      

http://git-wip-us.apache.org/repos/asf/incubator-cordova-tizen/blob/38e0ccf7/tizen SDK samples/mobile-spec/compass/index.html
----------------------------------------------------------------------
diff --git a/tizen SDK samples/mobile-spec/compass/index.html b/tizen SDK samples/mobile-spec/compass/index.html
new file mode 100755
index 0000000..8dbf99a
--- /dev/null
+++ b/tizen SDK samples/mobile-spec/compass/index.html	
@@ -0,0 +1,128 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta name="viewport" content="width=device-width,height=device-height,user-scalable=no,maximum-scale=1.0,initial-scale=1.0" />
+    <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <!-- ISO-8859-1 -->
+    <title>Cordova Mobile Spec</title>
+    <link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title" charset="utf-8">
+    <script type="text/javascript" charset="utf-8" src="../cordova.js"></script>      
+
+      
+<script type="text/javascript" charset="utf-8">
+
+    var deviceReady = false;
+
+    function roundNumber(num) {
+        var dec = 3;
+        var result = Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
+        return result;
+    }
+
+    //-------------------------------------------------------------------------
+    // Compass
+    //-------------------------------------------------------------------------
+    var watchCompassId = null;
+
+    /**
+     * Start watching compass
+     */
+    var watchCompass = function() {
+        console.log("watchCompass()");
+
+        // Success callback
+        var success = function(a){
+            document.getElementById('compassHeading').innerHTML = roundNumber(a.magneticHeading);
+        };
+
+        // Fail callback
+        var fail = function(e){
+            console.log("watchCompass fail callback with error code "+e);
+            stopCompass();
+            setCompassStatus(e);
+        };
+
+        // Update heading every 1 sec
+        var opt = {};
+        opt.frequency = 1000;
+        watchCompassId = navigator.compass.watchHeading(success, fail, opt);
+
+        setCompassStatus("Running");
+    };
+
+    /**
+     * Stop watching the acceleration
+     */
+    var stopCompass = function() {
+        setCompassStatus("Stopped");
+        if (watchCompassId) {
+            navigator.compass.clearWatch(watchCompassId);
+            watchCompassId = null;
+        }
+    };
+
+    /**
+     * Get current compass
+     */
+    var getCompass = function() {
+        console.log("getCompass()");
+
+        // Stop compass if running
+        stopCompass();
+
+        // Success callback
+        var success = function(a){
+            document.getElementById('compassHeading').innerHTML = roundNumber(a.magneticHeading);
+        };
+
+        // Fail callback
+        var fail = function(e){
+            console.log("getCompass fail callback with error code "+e);
+            setCompassStatus(e);
+        };
+
+        // Make call
+        var opt = {};
+        navigator.compass.getCurrentHeading(success, fail, opt);
+    };
+
+    /**
+     * Set compass status
+     */
+    var setCompassStatus = function(status) {
+        document.getElementById('compass_status').innerHTML = status;
+    };
+    
+    /**
+     * Function called when page has finished loading.
+     */
+    function init() {
+        document.addEventListener("deviceready", function() {
+                deviceReady = true;
+                console.log("Device="+device.platform+" "+device.version);
+            }, false);
+        window.setTimeout(function() {
+        	if (!deviceReady) {
+        		alert("Error: PhoneGap did not initialize.  Demo will not run correctly.");
+        	}
+        },1000);
+    }
+
+</script>
+
+  </head>
+  <body onload="init();" id="stage" class="theme">
+  
+    <h1>Compass</h1>
+    <div id="info">
+        <b>Status:</b> <span id="compass_status">Stopped</span>
+        <table width="100%"><tr>
+            <td width="33%">Heading: <span id="compassHeading"> </span></td>
+        </tr></table>
+    </div>
+    <h2>Action</h2>
+    <div class="btn large" onclick="getCompass();">Get Compass</div>
+    <div class="btn large" onclick="watchCompass();">Start Watching Compass</div>
+    <div class="btn large" onclick="stopCompass();">Stop Watching Compass</div>
+    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+  </body>
+</html>      

http://git-wip-us.apache.org/repos/asf/incubator-cordova-tizen/blob/38e0ccf7/tizen SDK samples/mobile-spec/config.xml
----------------------------------------------------------------------
diff --git a/tizen SDK samples/mobile-spec/config.xml b/tizen SDK samples/mobile-spec/config.xml
new file mode 100644
index 0000000..d6afff6
--- /dev/null
+++ b/tizen SDK samples/mobile-spec/config.xml	
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<widget xmlns="http://www.w3.org/ns/widgets" xmlns:tizen="http://tizen.org/ns/widgets" version="2.0 Beta" viewmodes="fullscreen" id="http://yourdomain/mobile-spec">  
+	<icon src="apple-touch-icon.png"/>  
+	<content src="index.html"/>  
+	<name>mobile-spec</name>
+		<feature name="http://tizen.org/api/alarm" required="true"/>  
+	<feature name="http://tizen.org/api/alarm.read" required="true"/>  
+	<feature name="http://tizen.org/api/alarm.write" required="true"/>  
+	<feature name="http://tizen.org/api/application" required="true"/>  
+	<feature name="http://tizen.org/api/application.kill" required="true"/>  
+	<feature name="http://tizen.org/api/application.launch" required="true"/>  
+	<feature name="http://tizen.org/api/application.read" required="true"/>  
+	<feature name="http://tizen.org/api/bluetooth" required="true"/>  
+	<feature name="http://tizen.org/api/bluetooth.admin" required="true"/>  
+	<feature name="http://tizen.org/api/bluetooth.gap" required="true"/>  
+	<feature name="http://tizen.org/api/bluetooth.spp" required="true"/>  
+	<feature name="http://tizen.org/api/calendar" required="true"/>  
+	<feature name="http://tizen.org/api/calendar.read" required="true"/>  
+	<feature name="http://tizen.org/api/calendar.write" required="true"/>  
+	<feature name="http://tizen.org/api/call" required="true"/>  
+	<feature name="http://tizen.org/api/call.history" required="true"/>  
+	<feature name="http://tizen.org/api/call.history.read" required="true"/>  
+	<feature name="http://tizen.org/api/call.history.write" required="true"/>  
+	<feature name="http://tizen.org/api/call.state" required="true"/>  
+	<feature name="http://tizen.org/api/contact" required="true"/>  
+	<feature name="http://tizen.org/api/contact.read" required="true"/>  
+	<feature name="http://tizen.org/api/contact.write" required="true"/>  
+	<feature name="http://tizen.org/api/filesystem" required="true"/>  
+	<feature name="http://tizen.org/api/filesystem.read" required="true"/>  
+	<feature name="http://tizen.org/api/filesystem.write" required="true"/>  
+	<feature name="http://tizen.org/api/geocoder" required="true"/>  
+	<feature name="http://tizen.org/api/lbs" required="true"/>  
+	<feature name="http://tizen.org/api/mediacontent" required="true"/>  
+	<feature name="http://tizen.org/api/mediacontent.read" required="true"/>  
+	<feature name="http://tizen.org/api/messaging" required="true"/>  
+	<feature name="http://tizen.org/api/messaging.read" required="true"/>  
+	<feature name="http://tizen.org/api/messaging.send" required="true"/>  
+	<feature name="http://tizen.org/api/messaging.write" required="true"/>  
+	<feature name="http://tizen.org/api/nfc" required="true"/>  
+	<feature name="http://tizen.org/api/nfc.p2p" required="true"/>  
+	<feature name="http://tizen.org/api/nfc.tag" required="true"/>  
+	<feature name="http://tizen.org/api/systeminfo" required="true"/>  
+	<feature name="http://tizen.org/api/time" required="true"/>  
+	<feature name="http://tizen.org/api/time.read" required="true"/>  
+	<feature name="http://tizen.org/api/time.write" required="true"/>  
+	<feature name="http://tizen.org/api/tizen" required="true"/>  
+</widget>

http://git-wip-us.apache.org/repos/asf/incubator-cordova-tizen/blob/38e0ccf7/tizen SDK samples/mobile-spec/contacts/index.html
----------------------------------------------------------------------
diff --git a/tizen SDK samples/mobile-spec/contacts/index.html b/tizen SDK samples/mobile-spec/contacts/index.html
new file mode 100755
index 0000000..950e1cc
--- /dev/null
+++ b/tizen SDK samples/mobile-spec/contacts/index.html	
@@ -0,0 +1,112 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta name="viewport" content="width=device-width,height=device-height,user-scalable=no,maximum-scale=1.0,initial-scale=1.0" />
+    <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <!-- ISO-8859-1 -->
+    <title>Cordova Mobile Spec</title>
+    <link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title" charset="utf-8">
+    <script type="text/javascript" charset="utf-8" src="../cordova.js"></script>      
+
+      
+<script type="text/javascript" charset="utf-8">
+
+    var deviceReady = false;
+
+    //-------------------------------------------------------------------------
+    // Contacts
+    //-------------------------------------------------------------------------
+    function getContacts() {
+        obj = new ContactFindOptions();
+        obj.filter = "D"; //Brooks";
+        obj.multiple = true;
+        navigator.contacts.find(
+            ["displayName", "name", "phoneNumbers", "emails", "urls", "note"],
+            function(contacts) {
+                var s = "";
+                if (contacts.length == 0) {
+                    s = "No contacts found";
+                }
+                else {
+                    s = "Number of contacts: "+contacts.length+"<br><table width='100%'><tr><th>Name</th><td>Phone</td><td>Email</td></tr>";
+                    for (var i=0; i<contacts.length; i++) {
+                        var contact = contacts[i];
+                        s = s + "<tr><td>" + contact.name.formatted + "</td><td>";
+                        if (contact.phoneNumbers && contact.phoneNumbers.length > 0) {
+                            s = s + contact.phoneNumbers[0].value;
+                        }
+                        s = s + "</td><td>"
+                        if (contact.emails && contact.emails.length > 0) {
+                            s = s + contact.emails[0].value;
+                        }
+                        s = s + "</td></tr>";
+                    }
+                    s = s + "</table>";
+                }
+                document.getElementById('contacts_results').innerHTML = s;
+            },
+            function(e) {
+                document.getElementById('contacts_results').innerHTML = "Error: "+e.code;
+            },
+            obj);
+    };
+
+    function addContact(){
+        console.log("addContact()");
+        try{
+            var contact = navigator.contacts.create({"displayName": "Dooney Evans"});
+            var contactName = {
+                formatted: "Dooney Evans",
+                familyName: "Evans",
+                givenName: "Dooney",
+                middleName: ""
+            };
+
+            contact.name = contactName;
+
+            var phoneNumbers = [1];
+            phoneNumbers[0] = new ContactField('work', '512-555-1234', true);
+            contact.phoneNumbers = phoneNumbers;
+
+            contact.save(
+                function() { alert("Contact saved.");},
+                function(e) { alert("Contact save failed: " + e.code); }
+            );
+            console.log("you have saved the contact");
+        }
+        catch (e){
+            alert(e);
+        }
+
+    };
+    
+    /**
+     * Function called when page has finished loading.
+     */
+    function init() {
+        document.addEventListener("deviceready", function() {
+                deviceReady = true;
+                console.log("Device="+device.platform+" "+device.version);
+            }, false);
+        window.setTimeout(function() {
+        	if (!deviceReady) {
+        		alert("Error: PhoneGap did not initialize.  Demo will not run correctly.");
+        	}
+        },1000);
+    }
+
+</script>
+
+  </head>
+  <body onload="init();" id="stage" class="theme">
+  
+    <h1>Contacts</h1>    
+    <div id="info">
+        <b>Results:</b><br>
+        <span id="contacts_results"> </span>
+    </div>
+    <h2>Action</h2>
+    <div class="btn large" onclick="getContacts();">Get phone's contacts</div>
+    <div class="btn large" onclick="addContact();">Add a new contact 'Dooney Evans'</div>
+    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
+  </body>
+</html>