diff --git a/test/tests.js b/test/tests.js new file mode 100644 index 0000000..4f36dd1 --- /dev/null +++ b/test/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 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 = '
' + name + ': '; + var select = '
'; + + return openDiv + select + defaultOption + options + closeDiv; + } + + /******************************************************************************/ + + var info_div = '

Camera

' + + '
' + + 'Status:
' + + 'img: ' + + 'canvas: ' + + '
', + options_div = '

Cordova Camera API 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) + + '
', + getpicture_div = '
', + inputs_div = '

Native File Inputs

' + + '
input type=file
' + + '
capture=camera
' + + '
capture=camcorder
' + + '
capture=microphone
', + actions_div = '

Actions

' + + '
'; + + 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'); +};