blob: ad3c508d27ff3298d76f7ca14774b797e4899bf8 [file] [log] [blame]
/*
*
* 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.
*
*/
describe("geolocation", function () {
var geo = require('cordova/plugin/geolocation'),
Position = require('cordova/plugin/Position'),
PositionError = require('cordova/plugin/PositionError'),
s, e,
exec = require('cordova/exec');
beforeEach(function () {
s = jasmine.createSpy("success");
e = jasmine.createSpy("error");
exec.reset();
geo.lastPosition = null; // reset the cached position
});
describe("getCurrentPosition", function() {
describe("and passed-in arguments", function () {
it("uses default PositionOptions if none are specified", function () {
geo.getCurrentPosition(s, e);
expect(exec).toHaveBeenCalledWith(jasmine.any(Function), jasmine.any(Function), "Geolocation", "getLocation", [false, 0]);
});
it("uses the enableHighAccuracy option if specified", function () {
geo.getCurrentPosition(s, e, {enableHighAccuracy: true});
expect(exec).toHaveBeenCalledWith(jasmine.any(Function), jasmine.any(Function), "Geolocation", "getLocation", [true, 0]);
});
it("uses the maximumAge option if specified", function () {
geo.getCurrentPosition(s, e, {maximumAge: 100});
expect(exec).toHaveBeenCalledWith(jasmine.any(Function), jasmine.any(Function), "Geolocation", "getLocation", [false, 100]);
});
it("uses a timeout value of 0 if specified and negative, which should call the error callback immediately (since we have no cached position)", function () {
geo.getCurrentPosition(s, e, {timeout: -1000});
expect(e).toHaveBeenCalledWith({
code:PositionError.TIMEOUT,
message:"timeout value in PositionOptions set to 0 and no cached Position object available, or cached Position object's age exceeds provided PositionOptions' maximumAge parameter."
});
});
it("can be used with one, two or three arguments", function() {
expect(function() { geo.getCurrentPosition(s); }).not.toThrow();
expect(function() { geo.getCurrentPosition(s,e); }).not.toThrow();
expect(function() { geo.getCurrentPosition(s,e,{}); }).not.toThrow();
});
it("should throw an exception if used with no arguments", function() {
expect(function() { geo.getCurrentPosition();}).toThrow();
});
});
describe("position acquisition", function() {
it("should provide a cached position if one exists and has a timestamp value conforming with passed in maximumAge", function() {
// Create a date object from 2 seconds ago to store as cached position.
var d = new Date();
d.setTime(d.getTime() - 2000);
var p = new Position(null, d);
geo.lastPosition = p;
geo.getCurrentPosition(s, e, {maximumAge:3000});
expect(s).toHaveBeenCalledWith(p);
expect(exec).not.toHaveBeenCalled();
});
it("should fire exec if a cached position exists but whose timestamp is longer than the maximumAge parameter", function() {
// Create a date object from 2 seconds ago to store as cached position.
var d = new Date();
d.setTime(d.getTime() - 2000);
var p = new Position(null, d);
geo.lastPosition = p;
geo.getCurrentPosition(s, e, {maximumAge:100});
expect(exec).toHaveBeenCalledWith(jasmine.any(Function), jasmine.any(Function), "Geolocation", "getLocation", [false, 100]);
});
it("should fire error callback with TIMEOUT code after timeout period has elapsed and no position is available", function() {
runs(function() {
geo.getCurrentPosition(s, e, {timeout: 50});
expect(exec).toHaveBeenCalledWith(jasmine.any(Function), jasmine.any(Function), "Geolocation", "getLocation", [false, 0]);
});
waitsFor(function() { return e.wasCalled; }, 200);
runs(function() {
expect(e).toHaveBeenCalledWith({
code:PositionError.TIMEOUT,
message:"Position retrieval timed out."
});
});
});
it("should not fire error callback with TIMEOUT if a position is obtained within the timeout period", function() {
runs(function() {
geo.getCurrentPosition(s, e, {timeout:50});
// Call the success callback to "fake" the native framework returning a (empty) position object.
// This should also disable the timeout timer.
exec.mostRecentCall.args[0]({});
});
waitsFor(function() { return e.wasCalled || s.wasCalled; }, 200);
runs(function() {
expect(e).not.toHaveBeenCalled();
expect(s).toHaveBeenCalled();
});
});
it("should fire error callback with POSITION_UNAVAILABLE if error occurs during acquisition before timeout expires", function() {
geo.getCurrentPosition(s, e, {timeout: 50});
// Call the error callback to "fake" the native framework returning an error object.
var eObj = {
code:PositionError.POSITION_UNAVAILABLE
};
exec.mostRecentCall.args[1](eObj);
expect(e).toHaveBeenCalledWith({
code:PositionError.POSITION_UNAVAILABLE,
message:""
});
});
it("should not fire error callback with TIMEOUT if error occurs during acquisition before timeout expires", function() {
runs(function() {
geo.getCurrentPosition(s, e, {timeout: 50});
// Call the error callback to "fake" the native framework returning an error object.
var eObj = {
code:PositionError.POSITION_UNAVAILABLE
};
exec.mostRecentCall.args[1](eObj);
});
waitsFor(function() { return e.wasCalled; }, 200);
runs(function() {
expect(e).not.toHaveBeenCalledWith({
code:PositionError.TIMEOUT,
message:"Position retrieval timed out."
});
});
});
});
});
describe("watchPosition", function () {
describe("arguments", function () {
it("uses default PositionOptions if none are specified", function () {
var id = geo.watchPosition(s, e);
expect(exec).toHaveBeenCalledWith(jasmine.any(Function), jasmine.any(Function), "Geolocation", "addWatch", [id, false]);
});
it("uses the enableHighAccuracy option if specified", function () {
var id = geo.watchPosition(s, e, {enableHighAccuracy: true});
expect(exec).toHaveBeenCalledWith(jasmine.any(Function), jasmine.any(Function), "Geolocation", "addWatch", [id, true]);
});
it("uses the maximumAge option if specified", function () {
var id = geo.watchPosition(s, e, {maximumAge: 100});
expect(exec).toHaveBeenCalledWith(jasmine.any(Function), jasmine.any(Function), "Geolocation", "addWatch", [id, false]);
});
it("uses a timeout value of 0 if specified and negative, which should call the error callback immediately", function () {
geo.watchPosition(s, e, {timeout: -1000});
expect(e).toHaveBeenCalledWith({
code:PositionError.TIMEOUT,
message:"timeout value in PositionOptions set to 0 and no cached Position object available, or cached Position object's age exceeds provided PositionOptions' maximumAge parameter."
});
});
it("can be used with one, two or three arguments", function() {
expect(function() { geo.watchPosition(s); }).not.toThrow();
expect(function() { geo.watchPosition(s,e); }).not.toThrow();
expect(function() { geo.watchPosition(s,e,{}); }).not.toThrow();
});
it("should throw an exception if used with no arguments", function() {
expect(function() { geo.watchPosition();}).toThrow();
});
});
describe("position acquisition", function() {
it("should invoke the success callback every time the position changes", function() {
runs(function() {
geo.watchPosition(s, e);
});
waits(1);
runs(function() {
exec.mostRecentCall.args[0]({}); // fake success callback from native
expect(s).toHaveBeenCalled();
s.reset();
exec.mostRecentCall.args[0]({}); // fake success callback from native
expect(s).toHaveBeenCalled();
});
});
it("should invoke the error callback if position could not be retrieved", function() {
geo.watchPosition(s, e);
exec.mostRecentCall.args[1]({
code:PositionError.POSITION_UNAVAILABLE
});
expect(e).toHaveBeenCalledWith({
code:PositionError.POSITION_UNAVAILABLE,
message:""
});
});
it("should invoke the error callback if no position could be acquired within the specified timeout", function() {
runs(function() {
geo.watchPosition(s, e, {timeout:50});
});
waitsFor(function() { return e.wasCalled; }, 200);
runs(function() {
expect(e).toHaveBeenCalledWith({
code:PositionError.TIMEOUT,
message:"Position retrieval timed out."
});
});
});
it("should invoke the error callback if no position could be acquired within the specified timeout, even after successfully retrieving the position once", function() {
runs(function() {
geo.watchPosition(s, e, {timeout:50});
});
waits(1);
runs(function() {
exec.mostRecentCall.args[0]({}); // fire new position return
expect(s).toHaveBeenCalled();
});
waits(1);
runs(function() {
// The error callback should NOT be fired, since the timeout should have reset when we fired a new position return above
expect(e).not.toHaveBeenCalled();
});
waitsFor(function() { return e.wasCalled; }, 200);
runs(function() {
// NOW the error callback should be fired with a TIMEOUT error
expect(e).toHaveBeenCalledWith({
code:PositionError.TIMEOUT,
message:"Position retrieval timed out."
});
});
});
});
});
describe("clearWatch", function () {
it("should tell native to remove an id from the watch list if it exists", function() {
var id = geo.watchPosition(s, e);
exec.reset();
geo.clearWatch(id);
expect(exec).toHaveBeenCalledWith(null, null, "Geolocation", "clearWatch", [id]);
});
it("should not call into native if id does not exist", function() {
var id = "this is bat country";
geo.clearWatch(id);
expect(exec).not.toHaveBeenCalled();
});
it("watchPosition followed by clearWatch should not invoke any success callbacks", function() {
// watchPosition calls native getLocation then addWatch method in order.
var id = geo.watchPosition(s, e);
// Get ref to getLocation success callback, to fake the native interaction.
var getLocationWin = exec.argsForCall[0][0];
// Next clear the watch id, but call the get location success callback as if the native framework has fired it after a clear watch.
geo.clearWatch(id);
getLocationWin({});
// End result: expect the success callback not to have been called.
expect(s).not.toHaveBeenCalled();
});
});
});