Skip to content

Instantly share code, notes, and snippets.

@adtaylor
Created December 31, 2012 16:46
Show Gist options
  • Save adtaylor/4421197 to your computer and use it in GitHub Desktop.
Save adtaylor/4421197 to your computer and use it in GitHub Desktop.
A simple and dirty way to test applications that rely on the HTML5 Geolocation API. Useful for headless testing that do not include the API. Includes tests - just run `navigator.geolocation.metaTesting()`.
# A faked Geolocation Class
#
# @example Usage
# window.navigator = { geolocation : new Geolocation() };
#
# @example A sucessful Geolocation call
# navigator.geolocation.getCurrentPosition(
# function(position) {
# console.log(position);
# },
# function(error) {
# console.log(error);
# }
# );
#
# @example A error Geolocation call
#
# navigator.geolocation.testLocation.isSuccess = false;
# navigator.geolocation.getCurrentPosition(
# function(position) {
# console.log(position);
# },
# function(error) {
# console.log(error);
# }
# );
#
# @example Simulate a wait for user response
#
# navigator.geolocation.testLocation.wait = 4000; // 4 seconds
# navigator.geolocation.getCurrentPosition(
# function(position) {
# console.log(position);
# },
# function(error) {
# console.log(error);
# }
# );
#
class Geolocation
# Construct a new Geolocation
#
constructor: ->
@testLocation =
"isSuccess":true
"errorCode": 1
"lat":51.51120218219914
"lng":-0.1606783540893275
"accuracy":122000
"wait": 0
getCurrentPosition: (successCb, errorCb, options) ->
setTimeout(
=>
if @testLocation.isSuccess
successCb(new Geoposition())
else
errorCb new PositionError @testLocation.errorCode
,@testLocation.wait)
metaTesting: ()->
# Test Defaults
#
testTime = 500
tests = []
# Provides a default location
#
tests.push =>
success = (position) =>
lat = position.coords.latitude is @testLocation.lat
lng = position.coords.longitude is @testLocation.lng
@_assert lat and lng, "Provides a default location."
error = (error) ->
window.navigator.geolocation.getCurrentPosition success, error
# Location can be changed
#
tests.push =>
window.navigator.geolocation.testLocation.lat = newLat = 50.51120218219914
window.navigator.geolocation.testLocation.lng = newLng = -1.0606783540893275
success = (position) =>
lat = position.coords.latitude is newLat
lng = position.coords.longitude is newLng
@_assert lat and lng, "Location can be changed."
error = (error) ->
window.navigator.geolocation.getCurrentPosition success, error
# Provides an error
#
tests.push =>
window.navigator.geolocation.testLocation.isSuccess = false
success = (position) =>
error = (error) =>
@_assert true, "Provides an error."
window.navigator.geolocation.getCurrentPosition success, error
# Error Code can be changed
#
tests.push =>
window.navigator.geolocation.testLocation.isSuccess = false
window.navigator.geolocation.testLocation.errorCode = 2
success = (position) =>
error = (error) =>
@_assert error.code is 2, "Error Code can be changed."
window.navigator.geolocation.getCurrentPosition success, error
# Can simulate a wait
#
tests.push =>
wait = 200
window.navigator.geolocation.testLocation.wait = wait
start = new Date()
success = (position) =>
diff = (new Date()).getTime() - start.getTime()
@_assert diff >= wait and diff <= (wait + 50) , "Can simulate a wait."
error = (error) => @_assert false, "Can simulate a wait."
window.navigator.geolocation.getCurrentPosition success, error
# Test runnergvt
#
intervalID = window.setInterval(
=>
if not tests.length then return clearInterval(intervalID)
window.navigator.geolocation.testLocation = (new Geolocation()).testLocation
tests[0]()
tests.shift()
, testTime)
# Return the string as a title - no real use
#
"Meta Testing…"
_assert: ( outcome, description ) ->
msg = "#{if outcome then '✔' else '✘'} #{description}"
if window.console
console[if outcome then 'log' else 'error'] msg
else
alert msg
# A faked Coordinates class
#
class Coordinates
# Construct a new Coordinate object
#
# always consumes the data in the testLocation object
# else mocks the browser by returning null
#
constructor: ()->
testLocation = navigator.geolocation.testLocation
@accuracy = testLocation.accuracy || null
@altitude = testLocation.altitude || null
@altitudeAccuracy = testLocation.altitudeAccuracy || null
@heading = testLocation.heading || null
@latitude = testLocation.lat || null
@longitude = testLocation.lng || null
@speed = testLocation.speed || null
# A faked Geoposition class
#
class Geoposition
# Construct a new Geoposition
#
constructor: ->
@timestamp = new Date().getTime()
@coords = new Coordinates()
# A faked PositionError Class
#
class PositionError
# Construct a new PositionError
#
# @param [Integer] code The code of the error wished to fake
constructor: (@code)->
@message = @_messages[@code]
# These messages are here to help debugging
#
# "The message attribute must return an error message describing the
# details of the error encountered. This attribute is primarily intended
# for debugging and developers should not use it directly in their application user interface."
# http://dev.w3.org/geo/api/spec-source.html#message
#
_messages:
# The ever helpful…
0: "Unknown error"
# PERMISSION_DENIED (numeric value 1)
1: "The location acquisition process failed because the document does not have permission to use the Geolocation API."
# POSITION_UNAVAILABLE (numeric value 2)
2: "The position of the device could not be determined. For instance, one or more of the location providers used in the location acquisition process reported an internal error that caused the process to fail entirely."
# TIMEOUT (numeric value 3)
3: "The length of time specified by the timeout property has elapsed before the implementation could successfully acquire a new Position object."
do ->
# Brutally override the navigator class
#
window.navigator =
geolocation : new Geolocation()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment