You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by fi...@apache.org on 2012/05/07 22:52:06 UTC

[1/8] js commit: tweaked our geolocation native framework api (now should support three actions: getLocation, addWatch and clearWatch). finished off tests

Updated Branches:
  refs/heads/master 34f5fec1f -> dd7ab2827


tweaked our geolocation native framework api (now should support three actions: getLocation, addWatch and clearWatch). finished off tests


Project: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/commit/95b11dd0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/tree/95b11dd0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/diff/95b11dd0

Branch: refs/heads/master
Commit: 95b11dd053dc689a1658718252a2d0ecaad53e91
Parents: 0d7e3e7
Author: Fil Maj <ma...@gmail.com>
Authored: Mon Mar 26 15:39:55 2012 -0700
Committer: Fil Maj <ma...@gmail.com>
Committed: Mon May 7 13:51:05 2012 -0700

----------------------------------------------------------------------
 lib/common/plugin/geolocation.js |   64 +++++++++++++++---
 test/test.geolocation.js         |  117 ++++++++++++++++++++++++---------
 2 files changed, 139 insertions(+), 42 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/95b11dd0/lib/common/plugin/geolocation.js
----------------------------------------------------------------------
diff --git a/lib/common/plugin/geolocation.js b/lib/common/plugin/geolocation.js
index 0831d0c..55159f2 100644
--- a/lib/common/plugin/geolocation.js
+++ b/lib/common/plugin/geolocation.js
@@ -32,6 +32,19 @@ function parseParameters(options) {
     return opt;
 }
 
+// Returns a timeout failure, closed over a specified timeout value and error callback.
+function createTimeout(errorCallback, timeout) {
+    var t = setTimeout(function() {
+        clearTimeout(t);
+        t = null;
+        errorCallback({
+            code:PositionError.TIMEOUT,
+            message:"Position retrieval timed out."
+        });
+    }, timeout);
+    return t;
+}
+
 var geolocation = {
     lastPosition:null, // reference to last known (cached) position returned
     /**
@@ -99,22 +112,16 @@ var geolocation = {
                 // If the timeout value was not set to Infinity (default), then
                 // set up a timeout function that will fire the error callback 
                 // if no successful position was retrieved before timeout expired.
-                timeoutTimer = setTimeout(function() {
-                    clearTimeout(timeoutTimer);
-                    timeoutTimer = null;
-                    fail({
-                        code:PositionError.TIMEOUT,
-                        message:"Position retrieval timed out."
-                    });
-                }, options.timeout);
+                timeoutTimer = createTimeout(fail, options.timeout);
             } else {
                 // This is here so the check in the win function doesn't mess stuff up
                 // may seem weird but this guarantees timeoutTimer is 
                 // always truthy before we call into native
                 timeoutTimer = true; 
             }
-            exec(win, fail, "Geolocation", "getLocation", [options.enableHighAccuracy, options.timeout, options.maximumAge]); 
+            exec(win, fail, "Geolocation", "getLocation", [options.enableHighAccuracy, options.maximumAge]); 
         }
+        return timeoutTimer;
     },
     /**
      * Asynchronously watches the geolocation for changes to geolocation.  When a change occurs,
@@ -126,10 +133,46 @@ var geolocation = {
      * @return String                       The watch id that must be passed to #clearWatch to stop watching.
      */
     watchPosition:function(successCallback, errorCallback, options) {
+        if (arguments.length === 0) {
+            throw new Error("watchPosition must be called with at least one argument.");
+        }
         options = parseParameters(options);
 
         var id = utils.createUUID();
 
+        timers[id] = geolocation.getCurrentPosition(successCallback, errorCallback, options);
+
+        var fail = function(e) {
+            clearTimeout(timers[id]);
+            var err = new PositionError(e.code, e.message);
+            if (errorCallback) {
+                errorCallback(err);
+            }
+        };
+
+        var win = function(p) {
+            clearTimeout(timers[id]);
+            if (options.timeout !== Infinity) {
+                timers[id] = createTimeout(fail, options.timeout);
+            }
+            var pos = new Position(
+                {
+                    latitude:p.latitude,
+                    longitude:p.longitude,
+                    altitude:p.altitude,
+                    accuracy:p.accuracy,
+                    heading:p.heading,
+                    velocity:p.velocity,
+                    altitudeAccuracy:p.altitudeAccuracy
+                },
+                p.timestamp || new Date()
+            );
+            geolocation.lastPosition = pos;
+            successCallback(pos);
+        };
+
+        exec(win, fail, "Geolocation", "addWatch", [id, options.enableHighAccuracy]);
+
         return id;
     },
     /**
@@ -139,8 +182,9 @@ var geolocation = {
      */
     clearWatch:function(id) {
         if (id && timers[id] !== undefined) {
-            window.clearInterval(timers[id]);
+            clearTimeout(timers[id]);
             delete timers[id];
+            exec(null, null, "Geolocation", "clearWatch", [id]); 
         }
     }
 };

http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/95b11dd0/test/test.geolocation.js
----------------------------------------------------------------------
diff --git a/test/test.geolocation.js b/test/test.geolocation.js
index 6daaa4c..8ea5139 100644
--- a/test/test.geolocation.js
+++ b/test/test.geolocation.js
@@ -2,7 +2,7 @@ describe("geolocation", function () {
     var geo = require('cordova/plugin/geolocation'),
         Position = require('cordova/plugin/Position'),
         PositionError = require('cordova/plugin/PositionError'),
-        s, e;
+        s, e,
         exec = require('cordova/exec');
 
     beforeEach(function () {
@@ -16,22 +16,17 @@ describe("geolocation", function () {
         describe("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, Infinity, 0]);
-            });
-
-            it("uses the maximumAge option if specified", function () {
-                geo.getCurrentPosition(s, e, {maximumAge: 10});
-                expect(exec).toHaveBeenCalledWith(jasmine.any(Function), jasmine.any(Function), "Geolocation", "getLocation", [false, Infinity, 10]);
+                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, maximumAge: 100});
-                expect(exec).toHaveBeenCalledWith(jasmine.any(Function), jasmine.any(Function), "Geolocation", "getLocation", [true, Infinity, 100]);
+                geo.getCurrentPosition(s, e, {enableHighAccuracy: true});
+                expect(exec).toHaveBeenCalledWith(jasmine.any(Function), jasmine.any(Function), "Geolocation", "getLocation", [true, 0]);
             });
 
-            it("uses the timeout option if specified and positive", function () {
-                geo.getCurrentPosition(s, e, {timeout: 1000});
-                expect(exec).toHaveBeenCalledWith(jasmine.any(Function), jasmine.any(Function), "Geolocation", "getLocation", [false, 1000, 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 () {
@@ -75,13 +70,13 @@ describe("geolocation", function () {
 
                 geo.getCurrentPosition(s, e, {maximumAge:100});
 
-                expect(exec).toHaveBeenCalledWith(jasmine.any(Function), jasmine.any(Function), "Geolocation", "getLocation", [false, Infinity, 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, 50, 0]);
+                    expect(exec).toHaveBeenCalledWith(jasmine.any(Function), jasmine.any(Function), "Geolocation", "getLocation", [false, 0]);
                 });
                 
                 waits(75);
@@ -150,30 +145,23 @@ describe("geolocation", function () {
     });
 
     describe("watchPosition", function () {
-        var utils = require('cordova/utils');
-
         describe("arguments", function () {
             it("uses default PositionOptions if none are specified", function () {
-                geo.watchPosition(s, e);
-                expect(exec).toHaveBeenCalledWith(jasmine.any(Function), jasmine.any(Function), "Geolocation", "getLocation", [false, Infinity, 0]);
-            });
-
-            it("uses the maximumAge option if specified", function () {
-                geo.watchPosition(s, e, {maximumAge: 10});
-                expect(exec).toHaveBeenCalledWith(jasmine.any(Function), jasmine.any(Function), "Geolocation", "getLocation", [false, Infinity, 10]);
+                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 () {
-                geo.watchPosition(s, e, {enableHighAccuracy: true, maximumAge: 100});
-                expect(exec).toHaveBeenCalledWith(jasmine.any(Function), jasmine.any(Function), "Geolocation", "getLocation", [true, Infinity, 100]);
+                var id = geo.watchPosition(s, e, {enableHighAccuracy: true});
+                expect(exec).toHaveBeenCalledWith(jasmine.any(Function), jasmine.any(Function), "Geolocation", "addWatch", [id, true]);
             });
 
-            it("uses the timeout option if specified and positive", function () {
-                geo.watchPosition(s, e, {timeout: 1000});
-                expect(exec).toHaveBeenCalledWith(jasmine.any(Function), jasmine.any(Function), "Geolocation", "getLocation", [false, 1000, 0]);
+            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 (since we have no cached position)", function () {
+            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,
@@ -192,12 +180,77 @@ describe("geolocation", function () {
             });
         });
         describe("position acquisition", function() {
-            it("should invoke the success callback every time the position changes");
-            it("should invoke the error callback if position could not be retrieved");
-            
+            it("should invoke the success callback every time the position changes", function() {
+                runs(function() {
+                    geo.watchPosition(s, e);
+                });
+                waits(50);
+                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});
+                });
+                waits(75);
+                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(25);
+                runs(function() {
+                    exec.mostRecentCall.args[0]({}); // fire new position return
+                    expect(s).toHaveBeenCalled();
+                });
+                waits(30);
+                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();
+                });
+                waits(25);
+                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);
+            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();
+        });
     });
 });