Created
December 31, 2012 16:46
-
-
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()`.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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