/* * * 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 () { var fail = function (done, context, message) { // prevents done() to be called several times if (context) { if (context.done) return; context.done = true; } if (message) { expect(false).toBe(true, message); } else { expect(false).toBe(true); } // watchPosition could call its callback sync (before returning the value) // so we invoke done async to make sure we know watcher id to .clear in afterEach setTimeout(function () { done(); }); }, succeed = function (done, context) { // prevents done() to be called several times if (context) { if (context.done) return; context.done = true; } expect(true).toBe(true); // watchPosition could call its callback sync (before returning the value) // so we invoke done async to make sure we know watcher id to .clear in afterEach setTimeout(function () { done(); }); }, isWindowsStore = (cordova.platformId == "windows8") || (cordova.platformId == "windows" && !WinJS.Utilities.isPhone), isAndroid = cordova.platformId == "android"; describe('Geolocation (navigator.geolocation)', function () { it("geolocation.spec.1 should exist", function () { expect(navigator.geolocation).toBeDefined(); }); it("geolocation.spec.2 should contain a getCurrentPosition function", function () { expect(typeof navigator.geolocation.getCurrentPosition).toBeDefined(); expect(typeof navigator.geolocation.getCurrentPosition == 'function').toBe(true); }); it("geolocation.spec.3 should contain a watchPosition function", function () { expect(typeof navigator.geolocation.watchPosition).toBeDefined(); expect(typeof navigator.geolocation.watchPosition == 'function').toBe(true); }); it("geolocation.spec.4 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("geolocation.spec.5 should be called if we set timeout to 0 and maximumAge to a very small number", function (done) { // On Windows, this test prompts user for permission to use geolocation and interrupts autotests running. // On Android geolocation Api is not available on emulator so we pended tests until we found the way to detect // whether we run on emulator or real device from JavaScript. You can still run the tests on Android manually. if (isWindowsStore || isAndroid) { pending(); } navigator.geolocation.getCurrentPosition( fail.bind(null, done), succeed.bind(null, done), { maximumAge: 0, timeout: 0 }); }); }); describe('success callback', function () { it("geolocation.spec.6 should be called with a Position object", function (done) { // On Windows, this test prompts user for permission to use geolocation and interrupts autotests running. // On Android geolocation Api is not available on emulator so we pended tests until we found the way to detect // whether we run on emulator or real device from JavaScript. You can still run the tests on Android manually. if (isWindowsStore || isAndroid) { pending(); } navigator.geolocation.getCurrentPosition(function (p) { expect(p.coords).toBeDefined(); expect(p.timestamp).toBeDefined(); done(); }, fail.bind(null, done), { maximumAge: (5 * 60 * 1000) // 5 minutes maximum age of cached position }); }, 25000); // first geolocation call can take several seconds on some devices }); }); describe('watchPosition method', function () { beforeEach(function(done) { // This timeout is set to lessen the load on platform's geolocation services // which were causing occasional test failures setTimeout(function() { done(); }, 100); }); describe('error callback', function () { var errorWatch = null; afterEach(function () { navigator.geolocation.clearWatch(errorWatch); }); it("geolocation.spec.7 should be called if we set timeout to 0 and maximumAge to a very small number", function (done) { // On Windows, this test prompts user for permission to use geolocation and interrupts autotests running. // On Android geolocation Api is not available on emulator so we pended tests until we found the way to detect // whether we run on emulator or real device from JavaScript. You can still run the tests on Android manually. if (isWindowsStore || isAndroid) { pending(); } var context = this; errorWatch = navigator.geolocation.watchPosition( fail.bind(null, done, context, 'Unexpected win'), succeed.bind(null, done, context), { maximumAge: 0, timeout: 0 }); }); }); describe('success callback', function () { var successWatch = null; afterEach(function () { navigator.geolocation.clearWatch(successWatch); }); it("geolocation.spec.8 should be called with a Position object", function (done) { // On Windows, this test prompts user for permission to use geolocation and interrupts autotests running. // On Android geolocation Api is not available on emulator so we pended tests until we found the way to detect // whether we run on emulator or real device from JavaScript. You can still run the tests on Android manually. if (isWindowsStore || isAndroid) { pending(); } var context = this; successWatch = navigator.geolocation.watchPosition( function (p) { // prevents done() to be called several times if (context.done) return; context.done = true; expect(p.coords).toBeDefined(); expect(p.timestamp).toBeDefined(); // callback could be called sync so we invoke done async to make sure we know watcher id to .clear in afterEach setTimeout(function () { done(); }); }, fail.bind(null, done, context, 'Unexpected fail callback'), { maximumAge: (5 * 60 * 1000) // 5 minutes maximum age of cached position }); }); }); }); }; /******************************************************************************/ /******************************************************************************/ /******************************************************************************/ exports.defineManualTests = function (contentEl, createActionButton) { var newGeolocation = navigator.geolocation; var origGeolocation = cordova.require('cordova/modulemapper').getOriginalSymbol(window, 'navigator.geolocation'); if (!origGeolocation) { origGeolocation = newGeolocation; newGeolocation = null; } var watchLocationId = null; /** * Start watching location */ var watchLocation = function (usePlugin) { console.log("watchLocation()"); var geo = usePlugin ? newGeolocation : origGeolocation; if (!geo) { alert('geolocation object is missing. usePlugin = ' + usePlugin); return; } // Success callback var success = function (p) { setLocationDetails(p); }; // Fail callback var fail = function (e) { console.log("watchLocation fail callback with error code " + e); stopLocation(geo); }; // Get location watchLocationId = geo.watchPosition(success, fail, { enableHighAccuracy: true }); setLocationStatus("Running"); }; /** * Stop watching the location */ var stopLocation = function (usePlugin) { console.log("stopLocation()"); var geo = usePlugin ? newGeolocation : origGeolocation; if (!geo) { alert('geolocation object is missing. usePlugin = ' + usePlugin); return; } setLocationStatus("Stopped"); if (watchLocationId) { geo.clearWatch(watchLocationId); watchLocationId = null; } }; /** * Get current location */ var getLocation = function (usePlugin, opts) { console.log("getLocation()"); var geo = usePlugin ? newGeolocation : origGeolocation; if (!geo) { alert('geolocation object is missing. usePlugin = ' + usePlugin); return; } // Stop location if running stopLocation(geo); // Success callback var success = function (p) { setLocationDetails(p); setLocationStatus("Done"); }; // Fail callback var fail = function (e) { console.log("getLocation fail callback with error code " + e.code); setLocationStatus("Error: " + e.code); }; setLocationStatus("Retrieving location..."); // Get location geo.getCurrentPosition(success, fail, opts || { enableHighAccuracy: true }); //, {timeout: 10000}); }; /** * Set location status */ var setLocationStatus = function (status) { document.getElementById('location_status').innerHTML = status; }; var setLocationDetails = function (p) { var date = (new Date(p.timestamp)); document.getElementById('latitude').innerHTML = p.coords.latitude; document.getElementById('longitude').innerHTML = p.coords.longitude; document.getElementById('altitude').innerHTML = p.coords.altitude; document.getElementById('accuracy').innerHTML = p.coords.accuracy; document.getElementById('heading').innerHTML = p.coords.heading; document.getElementById('speed').innerHTML = p.coords.speed; document.getElementById('altitude_accuracy').innerHTML = p.coords.altitudeAccuracy; document.getElementById('timestamp').innerHTML = date.toDateString() + " " + date.toTimeString(); } /******************************************************************************/ var location_div = '
| Latitude: | ' + '' + ' | (decimal degrees) geographic coordinate [#ref] | ' + '
| Longitude: | ' + '' + ' | (decimal degrees) geographic coordinate [#ref] | ' + '
| Altitude: | ' + '' + ' | null if not supported; ' + '(meters) height above the [WGS84] ellipsoid. [#ref] | ' +
'
| Accuracy: | ' + '' + ' | (meters; non-negative; 95% confidence level) the accuracy level of the latitude and longitude coordinates. [#ref] | ' + '
| Heading: | ' + '' + ' | null if not supported; ' + 'NaN if speed == 0; ' + '(degrees; 0° ≤ heading < 360°) direction of travel of the hosting device- counting clockwise relative to the true north. [#ref] | ' +
'
| Speed: | ' + '' + ' | null if not supported; ' + '(meters per second; non-negative) magnitude of the horizontal component of the hosting device current velocity. [#ref] | ' +
'
| Altitude Accuracy: | ' + '' + ' | null if not supported; (meters; non-negative; 95% confidence level) the accuracy level of the altitude. [#ref] | ' +
'
| Time: | ' + '' + ' | (DOMTimeStamp) when the position was acquired [#ref] | ' + '