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 2014/08/07 20:58:25 UTC

[1/5] git commit: CB-6958. Port camera tests to plugin-test-framework

Repository: cordova-plugin-camera
Updated Branches:
  refs/heads/master 6366aeba4 -> 9064130fc


CB-6958. Port camera tests to plugin-test-framework

Ported camera test from mobilespec to the new test-framework in jasmine
2.0
Added test folder.
Added tes.js file inside the test folder.


Project: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/commit/7305c64d
Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/tree/7305c64d
Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/diff/7305c64d

Branch: refs/heads/master
Commit: 7305c64db09c4c277bbe83a3b1341f6b70a938ec
Parents: 06ecc91
Author: javierbb31 <ja...@gmail.com>
Authored: Mon Jun 30 15:37:18 2014 -0500
Committer: javierbb31 <ja...@gmail.com>
Committed: Mon Jun 30 15:37:18 2014 -0500

----------------------------------------------------------------------
 test/tests.js | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 73 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/blob/7305c64d/test/tests.js
----------------------------------------------------------------------
diff --git a/test/tests.js b/test/tests.js
new file mode 100644
index 0000000..748f3a5
--- /dev/null
+++ b/test/tests.js
@@ -0,0 +1,73 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+exports.defineAutoTests = function() {
+    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("camera.spec.1 window.Camera should exist", function() {
+            expect(window.Camera).toBeDefined();
+        });
+
+        it("camera.spec.2 should contain three DestinationType constants", function() {
+            expect(Camera.DestinationType.DATA_URL).toBe(0);
+            expect(Camera.DestinationType.FILE_URI).toBe(1);
+            expect(Camera.DestinationType.NATIVE_URI).toBe(2);
+            expect(navigator.camera.DestinationType.DATA_URL).toBe(0);
+            expect(navigator.camera.DestinationType.FILE_URI).toBe(1);
+            expect(navigator.camera.DestinationType.NATIVE_URI).toBe(2);
+        });
+
+        it("camera.spec.3 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("camera.spec.4 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("camera.spec.5 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);
+        });
+    });
+};


[3/5] git commit: CB-6958 added manual tests

Posted by pu...@apache.org.
CB-6958 added manual tests


Project: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/commit/10e0efc5
Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/tree/10e0efc5
Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/diff/10e0efc5

Branch: refs/heads/master
Commit: 10e0efc5039284b778599c31cfc54adfd9e0615a
Parents: cb7e193
Author: Staci Cooper <sm...@us.ibm.com>
Authored: Wed Jul 16 15:49:50 2014 -0400
Committer: Staci Cooper <sm...@us.ibm.com>
Committed: Mon Jul 21 15:20:59 2014 -0400

----------------------------------------------------------------------
 test/tests.js | 391 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 383 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/blob/10e0efc5/test/tests.js
----------------------------------------------------------------------
diff --git a/test/tests.js b/test/tests.js
index 748f3a5..4f36dd1 100644
--- a/test/tests.js
+++ b/test/tests.js
@@ -19,24 +19,24 @@
  *
 */
 
-exports.defineAutoTests = function() {
+exports.defineAutoTests = function () {
     describe('Camera (navigator.camera)', function () {
-        it("should exist", function() {
+        it("should exist", function () {
             expect(navigator.camera).toBeDefined();
         });
 
-        it("should contain a getPicture function", function() {
+        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("camera.spec.1 window.Camera should exist", function() {
+        it("camera.spec.1 window.Camera should exist", function () {
             expect(window.Camera).toBeDefined();
         });
 
-        it("camera.spec.2 should contain three DestinationType constants", function() {
+        it("camera.spec.2 should contain three DestinationType constants", function () {
             expect(Camera.DestinationType.DATA_URL).toBe(0);
             expect(Camera.DestinationType.FILE_URI).toBe(1);
             expect(Camera.DestinationType.NATIVE_URI).toBe(2);
@@ -45,14 +45,14 @@ exports.defineAutoTests = function() {
             expect(navigator.camera.DestinationType.NATIVE_URI).toBe(2);
         });
 
-        it("camera.spec.3 should contain two EncodingType constants", function() {
+        it("camera.spec.3 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("camera.spec.4 should contain three MediaType constants", function() {
+        it("camera.spec.4 should contain three MediaType constants", function () {
             expect(Camera.MediaType.PICTURE).toBe(0);
             expect(Camera.MediaType.VIDEO).toBe(1);
             expect(Camera.MediaType.ALLMEDIA).toBe(2);
@@ -61,7 +61,7 @@ exports.defineAutoTests = function() {
             expect(navigator.camera.MediaType.ALLMEDIA).toBe(2);
         });
 
-        it("camera.spec.5 should contain three PictureSourceType constants", function() {
+        it("camera.spec.5 should contain three PictureSourceType constants", function () {
             expect(Camera.PictureSourceType.PHOTOLIBRARY).toBe(0);
             expect(Camera.PictureSourceType.CAMERA).toBe(1);
             expect(Camera.PictureSourceType.SAVEDPHOTOALBUM).toBe(2);
@@ -71,3 +71,378 @@ exports.defineAutoTests = function() {
         });
     });
 };
+
+
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+
+exports.defineManualTests = function (contentEl, createActionButton) {
+    var platformId = cordova.require('cordova/platform').id;
+    var pictureUrl = null;
+    var fileObj = null;
+    var fileEntry = null;
+    var pageStartTime = +new Date();
+
+    //default camera options
+    var camQualityDefault = ['quality value', 50];
+    var camDestinationTypeDefault = ['FILE_URI', 1];
+    var camPictureSourceTypeDefault = ['CAMERA', 1];
+    var camAllowEditDefault = ['allowEdit', false];
+    var camEncodingTypeDefault = ['JPEG', 0];
+    var camMediaTypeDefault = ['mediaType', 0];
+    var camCorrectOrientationDefault = ['correctOrientation', false];
+    var camSaveToPhotoAlbumDefault = ['saveToPhotoAlbum', true];
+
+    var clearLog = function () {
+        var log = document.getElementById('info');
+        log.innerHTML = "";
+    }
+
+    function log(value) {
+        console.log(value);
+        document.getElementById('camera_status').textContent += (new Date() - pageStartTime) / 1000 + ': ' + value + '\n';
+    }
+
+    function clearStatus() {
+        document.getElementById('camera_status').innerHTML = '';
+        document.getElementById('camera_image').src = 'about:blank';
+        var canvas = document.getElementById('canvas');
+        canvas.width = canvas.height = 1;
+        pictureUrl = null;
+        fileObj = null;
+        fileEntry = null;
+    }
+
+    function setPicture(url, callback) {
+        try {
+            window.atob(url);
+            // if we got here it is a base64 string (DATA_URL)
+            url = "data:image/jpeg;base64," + url;
+        } catch (e) {
+            // not DATA_URL
+            log('URL: ' + url.slice(0, 100));
+        }
+
+        pictureUrl = url;
+        var img = document.getElementById('camera_image');
+        var startTime = new Date();
+        img.src = url;
+        img.onloadend = function () {
+            log('Image tag load time: ' + (new Date() - startTime));
+            callback && callback();
+        };
+    }
+
+    function onGetPictureError(e) {
+        log('Error getting picture: ' + e.code);
+    }
+
+    function getPictureWin(data) {
+        setPicture(data);
+        // TODO: Fix resolveLocalFileSystemURI to work with native-uri.
+        if (pictureUrl.indexOf('file:') == 0 || pictureUrl.indexOf('content:') == 0) {
+            resolveLocalFileSystemURI(data, function (e) {
+                fileEntry = e;
+                logCallback('resolveLocalFileSystemURI()', true)(e.toURL());
+            }, logCallback('resolveLocalFileSystemURI()', false));
+        } else if (pictureUrl.indexOf('data:image/jpeg;base64' == 0)) {
+            // do nothing
+        } else {
+            var path = pictureUrl.replace(/^file:\/\/(localhost)?/, '').replace(/%20/g, ' ');
+            fileEntry = new FileEntry('image_name.png', path);
+        }
+    }
+
+    function getPicture() {
+        clearStatus();
+        var options = extractOptions();
+        log('Getting picture with options: ' + JSON.stringify(options));
+        var popoverHandle = navigator.camera.getPicture(getPictureWin, onGetPictureError, options);
+
+        // Reposition the popover if the orientation changes.
+        window.onorientationchange = function () {
+            var newPopoverOptions = new CameraPopoverOptions(0, 0, 100, 100, 0);
+            popoverHandle.setPosition(newPopoverOptions);
+        }
+    }
+
+    function uploadImage() {
+        var ft = new FileTransfer(),
+            uploadcomplete = 0,
+            progress = 0,
+            options = new FileUploadOptions();
+        options.fileKey = "photo";
+        options.fileName = 'test.jpg';
+        options.mimeType = "image/jpeg";
+        ft.onprogress = function (progressEvent) {
+            console.log('progress: ' + progressEvent.loaded + ' of ' + progressEvent.total);
+        };
+        var server = "http://cordova-filetransfer.jitsu.com";
+
+        ft.upload(pictureUrl, server + '/upload', win, fail, options);
+        function win(information_back) {
+            log('upload complete');
+        }
+        function fail(message) {
+            log('upload failed: ' + JSON.stringify(message));
+        }
+    }
+
+    function logCallback(apiName, success) {
+        return function () {
+            log('Call to ' + apiName + (success ? ' success: ' : ' failed: ') + JSON.stringify([].slice.call(arguments)));
+        };
+    }
+
+    /**
+     * Select image from library using a NATIVE_URI destination type
+     * This calls FileEntry.getMetadata, FileEntry.setMetadata, FileEntry.getParent, FileEntry.file, and FileReader.readAsDataURL.
+     */
+    function readFile() {
+        function onFileReadAsDataURL(evt) {
+            var img = document.getElementById('camera_image');
+            img.style.visibility = "visible";
+            img.style.display = "block";
+            img.src = evt.target.result;
+            log("FileReader.readAsDataURL success");
+        };
+
+        function onFileReceived(file) {
+            log('Got file: ' + JSON.stringify(file));
+            fileObj = file;
+
+            var reader = new FileReader();
+            reader.onload = function () {
+                log('FileReader.readAsDataURL() - length = ' + reader.result.length);
+            };
+            reader.onerror = logCallback('FileReader.readAsDataURL', false);
+            reader.readAsDataURL(file);
+        };
+        // Test out onFileReceived when the file object was set via a native <input> elements.
+        if (fileObj) {
+            onFileReceived(fileObj);
+        } else {
+            fileEntry.file(onFileReceived, logCallback('FileEntry.file', false));
+        }
+    }
+    function getFileInfo() {
+        // Test FileEntry API here.
+        fileEntry.getMetadata(logCallback('FileEntry.getMetadata', true), logCallback('FileEntry.getMetadata', false));
+        fileEntry.setMetadata(logCallback('FileEntry.setMetadata', true), logCallback('FileEntry.setMetadata', false), { "com.apple.MobileBackup": 1 });
+        fileEntry.getParent(logCallback('FileEntry.getParent', true), logCallback('FileEntry.getParent', false));
+        fileEntry.getParent(logCallback('FileEntry.getParent', true), logCallback('FileEntry.getParent', false));
+    };
+
+    /**
+     * Copy image from library using a NATIVE_URI destination type
+     * This calls FileEntry.copyTo and FileEntry.moveTo.
+     */
+    function copyImage() {
+        var onFileSystemReceived = function (fileSystem) {
+            var destDirEntry = fileSystem.root;
+
+            // Test FileEntry API here.
+            fileEntry.copyTo(destDirEntry, 'copied_file.png', logCallback('FileEntry.copyTo', true), logCallback('FileEntry.copyTo', false));
+            fileEntry.moveTo(destDirEntry, 'moved_file.png', logCallback('FileEntry.moveTo', true), logCallback('FileEntry.moveTo', false));
+        };
+
+        window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, onFileSystemReceived, null);
+    };
+
+    /**
+     * Write image to library using a NATIVE_URI destination type
+     * This calls FileEntry.createWriter, FileWriter.write, and FileWriter.truncate.
+     */
+    function writeImage() {
+        var onFileWriterReceived = function (fileWriter) {
+            fileWriter.onwrite = logCallback('FileWriter.write', true);
+            fileWriter.onerror = logCallback('FileWriter.write', false);
+            fileWriter.write("some text!");
+        };
+
+        var onFileTruncateWriterReceived = function (fileWriter) {
+            fileWriter.onwrite = logCallback('FileWriter.truncate', true);
+            fileWriter.onerror = logCallback('FileWriter.truncate', false);
+            fileWriter.truncate(10);
+        };
+
+        fileEntry.createWriter(onFileWriterReceived, logCallback('FileEntry.createWriter', false));
+        fileEntry.createWriter(onFileTruncateWriterReceived, null);
+    };
+
+    function displayImageUsingCanvas() {
+        var canvas = document.getElementById('canvas');
+        var img = document.getElementById('camera_image');
+        var w = img.width;
+        var h = img.height;
+        h = 100 / w * h;
+        w = 100;
+        canvas.width = w;
+        canvas.height = h;
+        var context = canvas.getContext('2d');
+        context.drawImage(img, 0, 0, w, h);
+    };
+
+    /**
+     * Remove image from library using a NATIVE_URI destination type
+     * This calls FileEntry.remove.
+     */
+    function removeImage() {
+        fileEntry.remove(logCallback('FileEntry.remove', true), logCallback('FileEntry.remove', false));
+    };
+
+    function testInputTag(inputEl) {
+        clearStatus();
+        // iOS 6 likes to dead-lock in the onchange context if you
+        // do any alerts or try to remote-debug.
+        window.setTimeout(function () {
+            testNativeFile2(inputEl);
+        }, 0);
+    };
+
+    function testNativeFile2(inputEl) {
+        if (!inputEl.value) {
+            alert('No file selected.');
+            return;
+        }
+        fileObj = inputEl.files[0];
+        if (!fileObj) {
+            alert('Got value but no file.');
+            return;
+        }
+        var URLApi = window.URL || window.webkitURL;
+        if (URLApi) {
+            var blobURL = URLApi.createObjectURL(fileObj);
+            if (blobURL) {
+                setPicture(blobURL, function () {
+                    URLApi.revokeObjectURL(blobURL);
+                });
+            } else {
+                log('URL.createObjectURL returned null');
+            }
+        } else {
+            log('URL.createObjectURL() not supported.');
+        }
+    }
+
+    function extractOptions() {
+        var els = document.querySelectorAll('#image-options select');
+        var ret = {};
+        for (var i = 0, el; el = els[i]; ++i) {
+            var value = el.value;
+            if (value === '') continue;
+            if (el.isBool) {
+                ret[el.getAttribute("name")] = !!+value;
+            } else {
+                ret[el.getAttribute("name")] = +value;
+            }
+        }
+        return ret;
+    }
+
+    function createOptionsEl(name, values, selectionDefault) {
+        var openDiv = '<div style="display: inline-block">' + name + ': ';
+        var select = '<select name=' + name + '>';
+
+        var defaultOption = '';
+        if (selectionDefault == undefined) {
+            defaultOption = '<option value="">default</option>';
+        }
+
+        var options = '';
+        if (typeof values == 'boolean') {
+            values = { 'true': 1, 'false': 0 };
+        }
+        for (var k in values) {
+            var isSelected = '';
+            if (selectionDefault) {
+                if (selectionDefault[0] == k) {
+                    isSelected = 'selected';
+                }
+            }
+            options += '<option value="' + values[k] + '" ' + isSelected + '>' + k + '</option>';
+        }
+
+        var closeDiv = '</select></div>';
+
+        return openDiv + select + defaultOption + options + closeDiv;
+    }
+
+    /******************************************************************************/
+
+    var info_div = '<h1>Camera</h1>' +
+            '<div id="info">' +
+            '<b>Status:</b> <div id="camera_status"></div>' +
+            'img: <img width="100" id="camera_image">' +
+            'canvas: <canvas id="canvas" width="1" height="1"></canvas>' +
+            '</div>',
+        options_div = '<h2>Cordova Camera API Options</h2>' +
+            '<div id="image-options">' +
+            createOptionsEl('sourceType', Camera.PictureSourceType, camPictureSourceTypeDefault) +
+            createOptionsEl('destinationType', Camera.DestinationType, camDestinationTypeDefault) +
+            createOptionsEl('encodingType', Camera.EncodingType, camEncodingTypeDefault) +
+            createOptionsEl('mediaType', Camera.MediaType, camMediaTypeDefault) +
+            createOptionsEl('quality', { '0': 0, '50': 50, '80': 80, '100': 100 }, camQualityDefault) +
+            createOptionsEl('targetWidth', { '50': 50, '200': 200, '800': 800, '2048': 2048 }) +
+            createOptionsEl('targetHeight', { '50': 50, '200': 200, '800': 800, '2048': 2048 }) +
+            createOptionsEl('allowEdit', true, camAllowEditDefault) +
+            createOptionsEl('correctOrientation', true, camCorrectOrientationDefault) +
+            createOptionsEl('saveToPhotoAlbum', true, camSaveToPhotoAlbumDefault) +
+            createOptionsEl('cameraDirection', Camera.Direction) +
+            '</div>',
+        getpicture_div = '<div id="getpicture"></div>',
+        inputs_div = '<h2>Native File Inputs</h2>' +
+            '<div>input type=file <input type="file" class="testInputTag"></div>' +
+            '<div>capture=camera <input type="file" accept="image/*;capture=camera" class="testInputTag"></div>' +
+            '<div>capture=camcorder <input type="file" accept="video/*;capture=camcorder" class="testInputTag"></div>' +
+            '<div>capture=microphone <input type="file" accept="audio/*;capture=microphone" class="testInputTag"></div>',
+        actions_div = '<h2>Actions</h2>' +
+            '<div id="actions"></div>';
+
+    contentEl.innerHTML = info_div + options_div + getpicture_div + inputs_div + actions_div;
+    var elements = document.getElementsByClassName("testInputTag");
+    var listener = function (e) {
+        testInputTag(e.target);
+    }
+    for (var i = 0; i < elements.length; ++i) {
+        var item = elements[i];
+        item.addEventListener("change", listener, false);
+    }
+
+    createActionButton('Get picture', function () {
+        getPicture();
+    }, 'getpicture');
+
+    createActionButton('Clear Status', function () {
+        clearStatus();
+    }, 'getpicture');
+
+    createActionButton('Get File Metadata', function () {
+        getFileInfo();
+    }, 'actions');
+
+    createActionButton('Read with FileReader', function () {
+        readFile();
+    }, 'actions');
+
+    createActionButton('Copy Image', function () {
+        copyImage();
+    }, 'actions');
+
+    createActionButton('Write Image', function () {
+        writeImage();
+    }, 'actions');
+
+    createActionButton('Upload Image', function () {
+        uploadImage();
+    }, 'actions');
+
+    createActionButton('Draw Using Canvas', function () {
+        displayImageUsingCanvas();
+    }, 'actions');
+
+    createActionButton('Remove Image', function () {
+        removeImage();
+    }, 'actions');
+};


[4/5] git commit: Renamed test dir, added nested plugin.xml

Posted by pu...@apache.org.
Renamed test dir, added nested plugin.xml


Project: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/commit/dbaa458b
Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/tree/dbaa458b
Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/diff/dbaa458b

Branch: refs/heads/master
Commit: dbaa458b7f0c1abce1a6e9cc100e03dc8b13cf28
Parents: 10e0efc
Author: Staci Cooper <sm...@us.ibm.com>
Authored: Thu Jul 31 12:45:05 2014 -0400
Committer: Staci Cooper <sm...@us.ibm.com>
Committed: Thu Jul 31 12:45:05 2014 -0400

----------------------------------------------------------------------
 test/tests.js    | 448 --------------------------------------------------
 tests/plugin.xml |  31 ++++
 tests/tests.js   | 448 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 479 insertions(+), 448 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/blob/dbaa458b/test/tests.js
----------------------------------------------------------------------
diff --git a/test/tests.js b/test/tests.js
deleted file mode 100644
index 4f36dd1..0000000
--- a/test/tests.js
+++ /dev/null
@@ -1,448 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-exports.defineAutoTests = function () {
-    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("camera.spec.1 window.Camera should exist", function () {
-            expect(window.Camera).toBeDefined();
-        });
-
-        it("camera.spec.2 should contain three DestinationType constants", function () {
-            expect(Camera.DestinationType.DATA_URL).toBe(0);
-            expect(Camera.DestinationType.FILE_URI).toBe(1);
-            expect(Camera.DestinationType.NATIVE_URI).toBe(2);
-            expect(navigator.camera.DestinationType.DATA_URL).toBe(0);
-            expect(navigator.camera.DestinationType.FILE_URI).toBe(1);
-            expect(navigator.camera.DestinationType.NATIVE_URI).toBe(2);
-        });
-
-        it("camera.spec.3 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("camera.spec.4 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("camera.spec.5 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);
-        });
-    });
-};
-
-
-/******************************************************************************/
-/******************************************************************************/
-/******************************************************************************/
-
-exports.defineManualTests = function (contentEl, createActionButton) {
-    var platformId = cordova.require('cordova/platform').id;
-    var pictureUrl = null;
-    var fileObj = null;
-    var fileEntry = null;
-    var pageStartTime = +new Date();
-
-    //default camera options
-    var camQualityDefault = ['quality value', 50];
-    var camDestinationTypeDefault = ['FILE_URI', 1];
-    var camPictureSourceTypeDefault = ['CAMERA', 1];
-    var camAllowEditDefault = ['allowEdit', false];
-    var camEncodingTypeDefault = ['JPEG', 0];
-    var camMediaTypeDefault = ['mediaType', 0];
-    var camCorrectOrientationDefault = ['correctOrientation', false];
-    var camSaveToPhotoAlbumDefault = ['saveToPhotoAlbum', true];
-
-    var clearLog = function () {
-        var log = document.getElementById('info');
-        log.innerHTML = "";
-    }
-
-    function log(value) {
-        console.log(value);
-        document.getElementById('camera_status').textContent += (new Date() - pageStartTime) / 1000 + ': ' + value + '\n';
-    }
-
-    function clearStatus() {
-        document.getElementById('camera_status').innerHTML = '';
-        document.getElementById('camera_image').src = 'about:blank';
-        var canvas = document.getElementById('canvas');
-        canvas.width = canvas.height = 1;
-        pictureUrl = null;
-        fileObj = null;
-        fileEntry = null;
-    }
-
-    function setPicture(url, callback) {
-        try {
-            window.atob(url);
-            // if we got here it is a base64 string (DATA_URL)
-            url = "data:image/jpeg;base64," + url;
-        } catch (e) {
-            // not DATA_URL
-            log('URL: ' + url.slice(0, 100));
-        }
-
-        pictureUrl = url;
-        var img = document.getElementById('camera_image');
-        var startTime = new Date();
-        img.src = url;
-        img.onloadend = function () {
-            log('Image tag load time: ' + (new Date() - startTime));
-            callback && callback();
-        };
-    }
-
-    function onGetPictureError(e) {
-        log('Error getting picture: ' + e.code);
-    }
-
-    function getPictureWin(data) {
-        setPicture(data);
-        // TODO: Fix resolveLocalFileSystemURI to work with native-uri.
-        if (pictureUrl.indexOf('file:') == 0 || pictureUrl.indexOf('content:') == 0) {
-            resolveLocalFileSystemURI(data, function (e) {
-                fileEntry = e;
-                logCallback('resolveLocalFileSystemURI()', true)(e.toURL());
-            }, logCallback('resolveLocalFileSystemURI()', false));
-        } else if (pictureUrl.indexOf('data:image/jpeg;base64' == 0)) {
-            // do nothing
-        } else {
-            var path = pictureUrl.replace(/^file:\/\/(localhost)?/, '').replace(/%20/g, ' ');
-            fileEntry = new FileEntry('image_name.png', path);
-        }
-    }
-
-    function getPicture() {
-        clearStatus();
-        var options = extractOptions();
-        log('Getting picture with options: ' + JSON.stringify(options));
-        var popoverHandle = navigator.camera.getPicture(getPictureWin, onGetPictureError, options);
-
-        // Reposition the popover if the orientation changes.
-        window.onorientationchange = function () {
-            var newPopoverOptions = new CameraPopoverOptions(0, 0, 100, 100, 0);
-            popoverHandle.setPosition(newPopoverOptions);
-        }
-    }
-
-    function uploadImage() {
-        var ft = new FileTransfer(),
-            uploadcomplete = 0,
-            progress = 0,
-            options = new FileUploadOptions();
-        options.fileKey = "photo";
-        options.fileName = 'test.jpg';
-        options.mimeType = "image/jpeg";
-        ft.onprogress = function (progressEvent) {
-            console.log('progress: ' + progressEvent.loaded + ' of ' + progressEvent.total);
-        };
-        var server = "http://cordova-filetransfer.jitsu.com";
-
-        ft.upload(pictureUrl, server + '/upload', win, fail, options);
-        function win(information_back) {
-            log('upload complete');
-        }
-        function fail(message) {
-            log('upload failed: ' + JSON.stringify(message));
-        }
-    }
-
-    function logCallback(apiName, success) {
-        return function () {
-            log('Call to ' + apiName + (success ? ' success: ' : ' failed: ') + JSON.stringify([].slice.call(arguments)));
-        };
-    }
-
-    /**
-     * Select image from library using a NATIVE_URI destination type
-     * This calls FileEntry.getMetadata, FileEntry.setMetadata, FileEntry.getParent, FileEntry.file, and FileReader.readAsDataURL.
-     */
-    function readFile() {
-        function onFileReadAsDataURL(evt) {
-            var img = document.getElementById('camera_image');
-            img.style.visibility = "visible";
-            img.style.display = "block";
-            img.src = evt.target.result;
-            log("FileReader.readAsDataURL success");
-        };
-
-        function onFileReceived(file) {
-            log('Got file: ' + JSON.stringify(file));
-            fileObj = file;
-
-            var reader = new FileReader();
-            reader.onload = function () {
-                log('FileReader.readAsDataURL() - length = ' + reader.result.length);
-            };
-            reader.onerror = logCallback('FileReader.readAsDataURL', false);
-            reader.readAsDataURL(file);
-        };
-        // Test out onFileReceived when the file object was set via a native <input> elements.
-        if (fileObj) {
-            onFileReceived(fileObj);
-        } else {
-            fileEntry.file(onFileReceived, logCallback('FileEntry.file', false));
-        }
-    }
-    function getFileInfo() {
-        // Test FileEntry API here.
-        fileEntry.getMetadata(logCallback('FileEntry.getMetadata', true), logCallback('FileEntry.getMetadata', false));
-        fileEntry.setMetadata(logCallback('FileEntry.setMetadata', true), logCallback('FileEntry.setMetadata', false), { "com.apple.MobileBackup": 1 });
-        fileEntry.getParent(logCallback('FileEntry.getParent', true), logCallback('FileEntry.getParent', false));
-        fileEntry.getParent(logCallback('FileEntry.getParent', true), logCallback('FileEntry.getParent', false));
-    };
-
-    /**
-     * Copy image from library using a NATIVE_URI destination type
-     * This calls FileEntry.copyTo and FileEntry.moveTo.
-     */
-    function copyImage() {
-        var onFileSystemReceived = function (fileSystem) {
-            var destDirEntry = fileSystem.root;
-
-            // Test FileEntry API here.
-            fileEntry.copyTo(destDirEntry, 'copied_file.png', logCallback('FileEntry.copyTo', true), logCallback('FileEntry.copyTo', false));
-            fileEntry.moveTo(destDirEntry, 'moved_file.png', logCallback('FileEntry.moveTo', true), logCallback('FileEntry.moveTo', false));
-        };
-
-        window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, onFileSystemReceived, null);
-    };
-
-    /**
-     * Write image to library using a NATIVE_URI destination type
-     * This calls FileEntry.createWriter, FileWriter.write, and FileWriter.truncate.
-     */
-    function writeImage() {
-        var onFileWriterReceived = function (fileWriter) {
-            fileWriter.onwrite = logCallback('FileWriter.write', true);
-            fileWriter.onerror = logCallback('FileWriter.write', false);
-            fileWriter.write("some text!");
-        };
-
-        var onFileTruncateWriterReceived = function (fileWriter) {
-            fileWriter.onwrite = logCallback('FileWriter.truncate', true);
-            fileWriter.onerror = logCallback('FileWriter.truncate', false);
-            fileWriter.truncate(10);
-        };
-
-        fileEntry.createWriter(onFileWriterReceived, logCallback('FileEntry.createWriter', false));
-        fileEntry.createWriter(onFileTruncateWriterReceived, null);
-    };
-
-    function displayImageUsingCanvas() {
-        var canvas = document.getElementById('canvas');
-        var img = document.getElementById('camera_image');
-        var w = img.width;
-        var h = img.height;
-        h = 100 / w * h;
-        w = 100;
-        canvas.width = w;
-        canvas.height = h;
-        var context = canvas.getContext('2d');
-        context.drawImage(img, 0, 0, w, h);
-    };
-
-    /**
-     * Remove image from library using a NATIVE_URI destination type
-     * This calls FileEntry.remove.
-     */
-    function removeImage() {
-        fileEntry.remove(logCallback('FileEntry.remove', true), logCallback('FileEntry.remove', false));
-    };
-
-    function testInputTag(inputEl) {
-        clearStatus();
-        // iOS 6 likes to dead-lock in the onchange context if you
-        // do any alerts or try to remote-debug.
-        window.setTimeout(function () {
-            testNativeFile2(inputEl);
-        }, 0);
-    };
-
-    function testNativeFile2(inputEl) {
-        if (!inputEl.value) {
-            alert('No file selected.');
-            return;
-        }
-        fileObj = inputEl.files[0];
-        if (!fileObj) {
-            alert('Got value but no file.');
-            return;
-        }
-        var URLApi = window.URL || window.webkitURL;
-        if (URLApi) {
-            var blobURL = URLApi.createObjectURL(fileObj);
-            if (blobURL) {
-                setPicture(blobURL, function () {
-                    URLApi.revokeObjectURL(blobURL);
-                });
-            } else {
-                log('URL.createObjectURL returned null');
-            }
-        } else {
-            log('URL.createObjectURL() not supported.');
-        }
-    }
-
-    function extractOptions() {
-        var els = document.querySelectorAll('#image-options select');
-        var ret = {};
-        for (var i = 0, el; el = els[i]; ++i) {
-            var value = el.value;
-            if (value === '') continue;
-            if (el.isBool) {
-                ret[el.getAttribute("name")] = !!+value;
-            } else {
-                ret[el.getAttribute("name")] = +value;
-            }
-        }
-        return ret;
-    }
-
-    function createOptionsEl(name, values, selectionDefault) {
-        var openDiv = '<div style="display: inline-block">' + name + ': ';
-        var select = '<select name=' + name + '>';
-
-        var defaultOption = '';
-        if (selectionDefault == undefined) {
-            defaultOption = '<option value="">default</option>';
-        }
-
-        var options = '';
-        if (typeof values == 'boolean') {
-            values = { 'true': 1, 'false': 0 };
-        }
-        for (var k in values) {
-            var isSelected = '';
-            if (selectionDefault) {
-                if (selectionDefault[0] == k) {
-                    isSelected = 'selected';
-                }
-            }
-            options += '<option value="' + values[k] + '" ' + isSelected + '>' + k + '</option>';
-        }
-
-        var closeDiv = '</select></div>';
-
-        return openDiv + select + defaultOption + options + closeDiv;
-    }
-
-    /******************************************************************************/
-
-    var info_div = '<h1>Camera</h1>' +
-            '<div id="info">' +
-            '<b>Status:</b> <div id="camera_status"></div>' +
-            'img: <img width="100" id="camera_image">' +
-            'canvas: <canvas id="canvas" width="1" height="1"></canvas>' +
-            '</div>',
-        options_div = '<h2>Cordova Camera API Options</h2>' +
-            '<div id="image-options">' +
-            createOptionsEl('sourceType', Camera.PictureSourceType, camPictureSourceTypeDefault) +
-            createOptionsEl('destinationType', Camera.DestinationType, camDestinationTypeDefault) +
-            createOptionsEl('encodingType', Camera.EncodingType, camEncodingTypeDefault) +
-            createOptionsEl('mediaType', Camera.MediaType, camMediaTypeDefault) +
-            createOptionsEl('quality', { '0': 0, '50': 50, '80': 80, '100': 100 }, camQualityDefault) +
-            createOptionsEl('targetWidth', { '50': 50, '200': 200, '800': 800, '2048': 2048 }) +
-            createOptionsEl('targetHeight', { '50': 50, '200': 200, '800': 800, '2048': 2048 }) +
-            createOptionsEl('allowEdit', true, camAllowEditDefault) +
-            createOptionsEl('correctOrientation', true, camCorrectOrientationDefault) +
-            createOptionsEl('saveToPhotoAlbum', true, camSaveToPhotoAlbumDefault) +
-            createOptionsEl('cameraDirection', Camera.Direction) +
-            '</div>',
-        getpicture_div = '<div id="getpicture"></div>',
-        inputs_div = '<h2>Native File Inputs</h2>' +
-            '<div>input type=file <input type="file" class="testInputTag"></div>' +
-            '<div>capture=camera <input type="file" accept="image/*;capture=camera" class="testInputTag"></div>' +
-            '<div>capture=camcorder <input type="file" accept="video/*;capture=camcorder" class="testInputTag"></div>' +
-            '<div>capture=microphone <input type="file" accept="audio/*;capture=microphone" class="testInputTag"></div>',
-        actions_div = '<h2>Actions</h2>' +
-            '<div id="actions"></div>';
-
-    contentEl.innerHTML = info_div + options_div + getpicture_div + inputs_div + actions_div;
-    var elements = document.getElementsByClassName("testInputTag");
-    var listener = function (e) {
-        testInputTag(e.target);
-    }
-    for (var i = 0; i < elements.length; ++i) {
-        var item = elements[i];
-        item.addEventListener("change", listener, false);
-    }
-
-    createActionButton('Get picture', function () {
-        getPicture();
-    }, 'getpicture');
-
-    createActionButton('Clear Status', function () {
-        clearStatus();
-    }, 'getpicture');
-
-    createActionButton('Get File Metadata', function () {
-        getFileInfo();
-    }, 'actions');
-
-    createActionButton('Read with FileReader', function () {
-        readFile();
-    }, 'actions');
-
-    createActionButton('Copy Image', function () {
-        copyImage();
-    }, 'actions');
-
-    createActionButton('Write Image', function () {
-        writeImage();
-    }, 'actions');
-
-    createActionButton('Upload Image', function () {
-        uploadImage();
-    }, 'actions');
-
-    createActionButton('Draw Using Canvas', function () {
-        displayImageUsingCanvas();
-    }, 'actions');
-
-    createActionButton('Remove Image', function () {
-        removeImage();
-    }, 'actions');
-};

http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/blob/dbaa458b/tests/plugin.xml
----------------------------------------------------------------------
diff --git a/tests/plugin.xml b/tests/plugin.xml
new file mode 100644
index 0000000..403753b
--- /dev/null
+++ b/tests/plugin.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+
+<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:rim="http://www.blackberry.com/ns/widgets"
+    id="org.apache.cordova.camera.tests"
+    version="0.3.1-dev">
+    <name>Cordova Camera Plugin Tests</name>
+    <license>Apache 2.0</license>
+
+    <js-module src="tests.js" name="tests">
+    </js-module>
+</plugin>

http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/blob/dbaa458b/tests/tests.js
----------------------------------------------------------------------
diff --git a/tests/tests.js b/tests/tests.js
new file mode 100644
index 0000000..4f36dd1
--- /dev/null
+++ b/tests/tests.js
@@ -0,0 +1,448 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+exports.defineAutoTests = function () {
+    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("camera.spec.1 window.Camera should exist", function () {
+            expect(window.Camera).toBeDefined();
+        });
+
+        it("camera.spec.2 should contain three DestinationType constants", function () {
+            expect(Camera.DestinationType.DATA_URL).toBe(0);
+            expect(Camera.DestinationType.FILE_URI).toBe(1);
+            expect(Camera.DestinationType.NATIVE_URI).toBe(2);
+            expect(navigator.camera.DestinationType.DATA_URL).toBe(0);
+            expect(navigator.camera.DestinationType.FILE_URI).toBe(1);
+            expect(navigator.camera.DestinationType.NATIVE_URI).toBe(2);
+        });
+
+        it("camera.spec.3 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("camera.spec.4 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("camera.spec.5 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);
+        });
+    });
+};
+
+
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+
+exports.defineManualTests = function (contentEl, createActionButton) {
+    var platformId = cordova.require('cordova/platform').id;
+    var pictureUrl = null;
+    var fileObj = null;
+    var fileEntry = null;
+    var pageStartTime = +new Date();
+
+    //default camera options
+    var camQualityDefault = ['quality value', 50];
+    var camDestinationTypeDefault = ['FILE_URI', 1];
+    var camPictureSourceTypeDefault = ['CAMERA', 1];
+    var camAllowEditDefault = ['allowEdit', false];
+    var camEncodingTypeDefault = ['JPEG', 0];
+    var camMediaTypeDefault = ['mediaType', 0];
+    var camCorrectOrientationDefault = ['correctOrientation', false];
+    var camSaveToPhotoAlbumDefault = ['saveToPhotoAlbum', true];
+
+    var clearLog = function () {
+        var log = document.getElementById('info');
+        log.innerHTML = "";
+    }
+
+    function log(value) {
+        console.log(value);
+        document.getElementById('camera_status').textContent += (new Date() - pageStartTime) / 1000 + ': ' + value + '\n';
+    }
+
+    function clearStatus() {
+        document.getElementById('camera_status').innerHTML = '';
+        document.getElementById('camera_image').src = 'about:blank';
+        var canvas = document.getElementById('canvas');
+        canvas.width = canvas.height = 1;
+        pictureUrl = null;
+        fileObj = null;
+        fileEntry = null;
+    }
+
+    function setPicture(url, callback) {
+        try {
+            window.atob(url);
+            // if we got here it is a base64 string (DATA_URL)
+            url = "data:image/jpeg;base64," + url;
+        } catch (e) {
+            // not DATA_URL
+            log('URL: ' + url.slice(0, 100));
+        }
+
+        pictureUrl = url;
+        var img = document.getElementById('camera_image');
+        var startTime = new Date();
+        img.src = url;
+        img.onloadend = function () {
+            log('Image tag load time: ' + (new Date() - startTime));
+            callback && callback();
+        };
+    }
+
+    function onGetPictureError(e) {
+        log('Error getting picture: ' + e.code);
+    }
+
+    function getPictureWin(data) {
+        setPicture(data);
+        // TODO: Fix resolveLocalFileSystemURI to work with native-uri.
+        if (pictureUrl.indexOf('file:') == 0 || pictureUrl.indexOf('content:') == 0) {
+            resolveLocalFileSystemURI(data, function (e) {
+                fileEntry = e;
+                logCallback('resolveLocalFileSystemURI()', true)(e.toURL());
+            }, logCallback('resolveLocalFileSystemURI()', false));
+        } else if (pictureUrl.indexOf('data:image/jpeg;base64' == 0)) {
+            // do nothing
+        } else {
+            var path = pictureUrl.replace(/^file:\/\/(localhost)?/, '').replace(/%20/g, ' ');
+            fileEntry = new FileEntry('image_name.png', path);
+        }
+    }
+
+    function getPicture() {
+        clearStatus();
+        var options = extractOptions();
+        log('Getting picture with options: ' + JSON.stringify(options));
+        var popoverHandle = navigator.camera.getPicture(getPictureWin, onGetPictureError, options);
+
+        // Reposition the popover if the orientation changes.
+        window.onorientationchange = function () {
+            var newPopoverOptions = new CameraPopoverOptions(0, 0, 100, 100, 0);
+            popoverHandle.setPosition(newPopoverOptions);
+        }
+    }
+
+    function uploadImage() {
+        var ft = new FileTransfer(),
+            uploadcomplete = 0,
+            progress = 0,
+            options = new FileUploadOptions();
+        options.fileKey = "photo";
+        options.fileName = 'test.jpg';
+        options.mimeType = "image/jpeg";
+        ft.onprogress = function (progressEvent) {
+            console.log('progress: ' + progressEvent.loaded + ' of ' + progressEvent.total);
+        };
+        var server = "http://cordova-filetransfer.jitsu.com";
+
+        ft.upload(pictureUrl, server + '/upload', win, fail, options);
+        function win(information_back) {
+            log('upload complete');
+        }
+        function fail(message) {
+            log('upload failed: ' + JSON.stringify(message));
+        }
+    }
+
+    function logCallback(apiName, success) {
+        return function () {
+            log('Call to ' + apiName + (success ? ' success: ' : ' failed: ') + JSON.stringify([].slice.call(arguments)));
+        };
+    }
+
+    /**
+     * Select image from library using a NATIVE_URI destination type
+     * This calls FileEntry.getMetadata, FileEntry.setMetadata, FileEntry.getParent, FileEntry.file, and FileReader.readAsDataURL.
+     */
+    function readFile() {
+        function onFileReadAsDataURL(evt) {
+            var img = document.getElementById('camera_image');
+            img.style.visibility = "visible";
+            img.style.display = "block";
+            img.src = evt.target.result;
+            log("FileReader.readAsDataURL success");
+        };
+
+        function onFileReceived(file) {
+            log('Got file: ' + JSON.stringify(file));
+            fileObj = file;
+
+            var reader = new FileReader();
+            reader.onload = function () {
+                log('FileReader.readAsDataURL() - length = ' + reader.result.length);
+            };
+            reader.onerror = logCallback('FileReader.readAsDataURL', false);
+            reader.readAsDataURL(file);
+        };
+        // Test out onFileReceived when the file object was set via a native <input> elements.
+        if (fileObj) {
+            onFileReceived(fileObj);
+        } else {
+            fileEntry.file(onFileReceived, logCallback('FileEntry.file', false));
+        }
+    }
+    function getFileInfo() {
+        // Test FileEntry API here.
+        fileEntry.getMetadata(logCallback('FileEntry.getMetadata', true), logCallback('FileEntry.getMetadata', false));
+        fileEntry.setMetadata(logCallback('FileEntry.setMetadata', true), logCallback('FileEntry.setMetadata', false), { "com.apple.MobileBackup": 1 });
+        fileEntry.getParent(logCallback('FileEntry.getParent', true), logCallback('FileEntry.getParent', false));
+        fileEntry.getParent(logCallback('FileEntry.getParent', true), logCallback('FileEntry.getParent', false));
+    };
+
+    /**
+     * Copy image from library using a NATIVE_URI destination type
+     * This calls FileEntry.copyTo and FileEntry.moveTo.
+     */
+    function copyImage() {
+        var onFileSystemReceived = function (fileSystem) {
+            var destDirEntry = fileSystem.root;
+
+            // Test FileEntry API here.
+            fileEntry.copyTo(destDirEntry, 'copied_file.png', logCallback('FileEntry.copyTo', true), logCallback('FileEntry.copyTo', false));
+            fileEntry.moveTo(destDirEntry, 'moved_file.png', logCallback('FileEntry.moveTo', true), logCallback('FileEntry.moveTo', false));
+        };
+
+        window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, onFileSystemReceived, null);
+    };
+
+    /**
+     * Write image to library using a NATIVE_URI destination type
+     * This calls FileEntry.createWriter, FileWriter.write, and FileWriter.truncate.
+     */
+    function writeImage() {
+        var onFileWriterReceived = function (fileWriter) {
+            fileWriter.onwrite = logCallback('FileWriter.write', true);
+            fileWriter.onerror = logCallback('FileWriter.write', false);
+            fileWriter.write("some text!");
+        };
+
+        var onFileTruncateWriterReceived = function (fileWriter) {
+            fileWriter.onwrite = logCallback('FileWriter.truncate', true);
+            fileWriter.onerror = logCallback('FileWriter.truncate', false);
+            fileWriter.truncate(10);
+        };
+
+        fileEntry.createWriter(onFileWriterReceived, logCallback('FileEntry.createWriter', false));
+        fileEntry.createWriter(onFileTruncateWriterReceived, null);
+    };
+
+    function displayImageUsingCanvas() {
+        var canvas = document.getElementById('canvas');
+        var img = document.getElementById('camera_image');
+        var w = img.width;
+        var h = img.height;
+        h = 100 / w * h;
+        w = 100;
+        canvas.width = w;
+        canvas.height = h;
+        var context = canvas.getContext('2d');
+        context.drawImage(img, 0, 0, w, h);
+    };
+
+    /**
+     * Remove image from library using a NATIVE_URI destination type
+     * This calls FileEntry.remove.
+     */
+    function removeImage() {
+        fileEntry.remove(logCallback('FileEntry.remove', true), logCallback('FileEntry.remove', false));
+    };
+
+    function testInputTag(inputEl) {
+        clearStatus();
+        // iOS 6 likes to dead-lock in the onchange context if you
+        // do any alerts or try to remote-debug.
+        window.setTimeout(function () {
+            testNativeFile2(inputEl);
+        }, 0);
+    };
+
+    function testNativeFile2(inputEl) {
+        if (!inputEl.value) {
+            alert('No file selected.');
+            return;
+        }
+        fileObj = inputEl.files[0];
+        if (!fileObj) {
+            alert('Got value but no file.');
+            return;
+        }
+        var URLApi = window.URL || window.webkitURL;
+        if (URLApi) {
+            var blobURL = URLApi.createObjectURL(fileObj);
+            if (blobURL) {
+                setPicture(blobURL, function () {
+                    URLApi.revokeObjectURL(blobURL);
+                });
+            } else {
+                log('URL.createObjectURL returned null');
+            }
+        } else {
+            log('URL.createObjectURL() not supported.');
+        }
+    }
+
+    function extractOptions() {
+        var els = document.querySelectorAll('#image-options select');
+        var ret = {};
+        for (var i = 0, el; el = els[i]; ++i) {
+            var value = el.value;
+            if (value === '') continue;
+            if (el.isBool) {
+                ret[el.getAttribute("name")] = !!+value;
+            } else {
+                ret[el.getAttribute("name")] = +value;
+            }
+        }
+        return ret;
+    }
+
+    function createOptionsEl(name, values, selectionDefault) {
+        var openDiv = '<div style="display: inline-block">' + name + ': ';
+        var select = '<select name=' + name + '>';
+
+        var defaultOption = '';
+        if (selectionDefault == undefined) {
+            defaultOption = '<option value="">default</option>';
+        }
+
+        var options = '';
+        if (typeof values == 'boolean') {
+            values = { 'true': 1, 'false': 0 };
+        }
+        for (var k in values) {
+            var isSelected = '';
+            if (selectionDefault) {
+                if (selectionDefault[0] == k) {
+                    isSelected = 'selected';
+                }
+            }
+            options += '<option value="' + values[k] + '" ' + isSelected + '>' + k + '</option>';
+        }
+
+        var closeDiv = '</select></div>';
+
+        return openDiv + select + defaultOption + options + closeDiv;
+    }
+
+    /******************************************************************************/
+
+    var info_div = '<h1>Camera</h1>' +
+            '<div id="info">' +
+            '<b>Status:</b> <div id="camera_status"></div>' +
+            'img: <img width="100" id="camera_image">' +
+            'canvas: <canvas id="canvas" width="1" height="1"></canvas>' +
+            '</div>',
+        options_div = '<h2>Cordova Camera API Options</h2>' +
+            '<div id="image-options">' +
+            createOptionsEl('sourceType', Camera.PictureSourceType, camPictureSourceTypeDefault) +
+            createOptionsEl('destinationType', Camera.DestinationType, camDestinationTypeDefault) +
+            createOptionsEl('encodingType', Camera.EncodingType, camEncodingTypeDefault) +
+            createOptionsEl('mediaType', Camera.MediaType, camMediaTypeDefault) +
+            createOptionsEl('quality', { '0': 0, '50': 50, '80': 80, '100': 100 }, camQualityDefault) +
+            createOptionsEl('targetWidth', { '50': 50, '200': 200, '800': 800, '2048': 2048 }) +
+            createOptionsEl('targetHeight', { '50': 50, '200': 200, '800': 800, '2048': 2048 }) +
+            createOptionsEl('allowEdit', true, camAllowEditDefault) +
+            createOptionsEl('correctOrientation', true, camCorrectOrientationDefault) +
+            createOptionsEl('saveToPhotoAlbum', true, camSaveToPhotoAlbumDefault) +
+            createOptionsEl('cameraDirection', Camera.Direction) +
+            '</div>',
+        getpicture_div = '<div id="getpicture"></div>',
+        inputs_div = '<h2>Native File Inputs</h2>' +
+            '<div>input type=file <input type="file" class="testInputTag"></div>' +
+            '<div>capture=camera <input type="file" accept="image/*;capture=camera" class="testInputTag"></div>' +
+            '<div>capture=camcorder <input type="file" accept="video/*;capture=camcorder" class="testInputTag"></div>' +
+            '<div>capture=microphone <input type="file" accept="audio/*;capture=microphone" class="testInputTag"></div>',
+        actions_div = '<h2>Actions</h2>' +
+            '<div id="actions"></div>';
+
+    contentEl.innerHTML = info_div + options_div + getpicture_div + inputs_div + actions_div;
+    var elements = document.getElementsByClassName("testInputTag");
+    var listener = function (e) {
+        testInputTag(e.target);
+    }
+    for (var i = 0; i < elements.length; ++i) {
+        var item = elements[i];
+        item.addEventListener("change", listener, false);
+    }
+
+    createActionButton('Get picture', function () {
+        getPicture();
+    }, 'getpicture');
+
+    createActionButton('Clear Status', function () {
+        clearStatus();
+    }, 'getpicture');
+
+    createActionButton('Get File Metadata', function () {
+        getFileInfo();
+    }, 'actions');
+
+    createActionButton('Read with FileReader', function () {
+        readFile();
+    }, 'actions');
+
+    createActionButton('Copy Image', function () {
+        copyImage();
+    }, 'actions');
+
+    createActionButton('Write Image', function () {
+        writeImage();
+    }, 'actions');
+
+    createActionButton('Upload Image', function () {
+        uploadImage();
+    }, 'actions');
+
+    createActionButton('Draw Using Canvas', function () {
+        displayImageUsingCanvas();
+    }, 'actions');
+
+    createActionButton('Remove Image', function () {
+        removeImage();
+    }, 'actions');
+};


[2/5] git commit: Merge branch 'master' of https://github.com/javierbb31/cordova-plugin-camera into CB-6958

Posted by pu...@apache.org.
Merge branch 'master' of https://github.com/javierbb31/cordova-plugin-camera into CB-6958


Project: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/commit/cb7e1931
Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/tree/cb7e1931
Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/diff/cb7e1931

Branch: refs/heads/master
Commit: cb7e19311a4d94734bfc57290118ac95400dea1c
Parents: 9a26e97 7305c64
Author: Staci Cooper <sm...@us.ibm.com>
Authored: Wed Jul 16 15:49:20 2014 -0400
Committer: Staci Cooper <sm...@us.ibm.com>
Committed: Wed Jul 16 15:49:20 2014 -0400

----------------------------------------------------------------------
 test/tests.js | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 73 insertions(+)
----------------------------------------------------------------------



[5/5] git commit: Merge branch 'CB-6958' of https://github.com/stacic/cordova-plugin-camera

Posted by pu...@apache.org.
Merge branch 'CB-6958' of https://github.com/stacic/cordova-plugin-camera


Project: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/commit/9064130f
Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/tree/9064130f
Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/diff/9064130f

Branch: refs/heads/master
Commit: 9064130fce1c8c751e63d155f0bc673239d3f0b5
Parents: 6366aeb dbaa458
Author: Jesse MacFadyen <pu...@gmail.com>
Authored: Thu Aug 7 11:58:07 2014 -0700
Committer: Jesse MacFadyen <pu...@gmail.com>
Committed: Thu Aug 7 11:58:07 2014 -0700

----------------------------------------------------------------------
 tests/plugin.xml |  31 ++++
 tests/tests.js   | 448 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 479 insertions(+)
----------------------------------------------------------------------