diff --git a/js/geo/lng_lat.js b/js/geo/lng_lat.js index 7400fb203cd..704bd0aa8e6 100644 --- a/js/geo/lng_lat.js +++ b/js/geo/lng_lat.js @@ -82,9 +82,11 @@ LngLat.prototype.toString = function () { LngLat.convert = function (input) { if (input instanceof LngLat) { return input; - } - if (Array.isArray(input)) { + } else if (input && input.hasOwnProperty('lng') && input.hasOwnProperty('lat')) { + return new LngLat(input.lng, input.lat); + } else if (Array.isArray(input) && input.length === 2) { return new LngLat(input[0], input[1]); + } else { + throw new Error("`LngLatLike` argument must be specified as a LngLat instance, an object {lng: , lat: }, or an array of [, ]"); } - return input; }; diff --git a/js/geo/lng_lat_bounds.js b/js/geo/lng_lat_bounds.js index 53e4e770ec3..b20098f383b 100644 --- a/js/geo/lng_lat_bounds.js +++ b/js/geo/lng_lat_bounds.js @@ -80,7 +80,14 @@ LngLatBounds.prototype = { if (!sw2 || !ne2) return this; } else { - return obj ? this.extend(LngLat.convert(obj) || LngLatBounds.convert(obj)) : this; + if (Array.isArray(obj)) { + if (obj.every(Array.isArray)) { + return this.extend(LngLatBounds.convert(obj)); + } else { + return this.extend(LngLat.convert(obj)); + } + } + return this; } if (!sw && !ne) { diff --git a/test/js/geo/lng_lat.test.js b/test/js/geo/lng_lat.test.js index 183b8d609c8..8c501997d98 100644 --- a/test/js/geo/lng_lat.test.js +++ b/test/js/geo/lng_lat.test.js @@ -23,8 +23,12 @@ test('LngLat', function(t) { t.test('#convert', function(t) { t.ok(LngLat.convert([0, 10]) instanceof LngLat, 'convert creates a LngLat instance'); + t.ok(LngLat.convert({lng: 0, lat: 10}) instanceof LngLat, 'convert creates a LngLat instance'); + t.ok(LngLat.convert({lng: 0, lat: 0}) instanceof LngLat, 'convert creates a LngLat instance'); t.ok(LngLat.convert(new LngLat(0, 0)) instanceof LngLat, 'convert creates a LngLat instance'); - t.equal(LngLat.convert('othervalue'), 'othervalue', 'passes through other values'); + t.throws(function() { + LngLat.convert(0, 10); + }, "`LngLatLike` argument must be specified as a LngLat instance, an object {lng: , lat: }, or an array of [, ]", 'detects and throws on invalid input'); t.end(); }); diff --git a/test/js/geo/lng_lat_bounds.test.js b/test/js/geo/lng_lat_bounds.test.js index f4355106792..b9aadba1f11 100644 --- a/test/js/geo/lng_lat_bounds.test.js +++ b/test/js/geo/lng_lat_bounds.test.js @@ -55,6 +55,13 @@ test('LngLatBounds', function(t) { t.equal(bounds.getNorth(), 10); t.equal(bounds.getEast(), 10); + bounds.extend(new LngLat(-15, -15)); + + t.equal(bounds.getSouth(), -15); + t.equal(bounds.getWest(), -15); + t.equal(bounds.getNorth(), 10); + t.equal(bounds.getEast(), 10); + t.end(); }); @@ -68,6 +75,14 @@ test('LngLatBounds', function(t) { t.equal(bounds1.getNorth(), 10); t.equal(bounds1.getEast(), 10); + var bounds3 = [[-15, -15], [15, 15]]; + bounds1.extend(bounds3); + + t.equal(bounds1.getSouth(), -15); + t.equal(bounds1.getWest(), -15); + t.equal(bounds1.getNorth(), 15); + t.equal(bounds1.getEast(), 15); + t.end(); }); diff --git a/test/js/ui/camera.test.js b/test/js/ui/camera.test.js index 3aa868f30df..c0e787f8c30 100644 --- a/test/js/ui/camera.test.js +++ b/test/js/ui/camera.test.js @@ -35,6 +35,13 @@ test('camera', function(t) { t.end(); }); + t.test('throws on invalid center argument', function(t) { + t.throws(function() { + camera.jumpTo({center: 1}); + }, Error, 'throws with non-LngLatLike argument'); + t.end(); + }); + t.test('keeps current center if not specified', function(t) { camera.jumpTo({}); t.deepEqual(camera.getCenter(), { lng: 1, lat: 2 }); @@ -144,6 +151,13 @@ test('camera', function(t) { t.end(); }); + t.test('throws on invalid center argument', function(t) { + t.throws(function() { + camera.jumpTo({center: 1}); + }, Error, 'throws with non-LngLatLike argument'); + t.end(); + }); + t.test('emits move events, preserving eventData', function(t) { var started, moved, ended, eventData = { data: 'ok' }; @@ -305,6 +319,14 @@ test('camera', function(t) { t.end(); }); + t.test('throws on invalid center argument', function(t) { + var camera = createCamera(); + t.throws(function() { + camera.panTo({center: 1}); + }, Error, 'throws with non-LngLatLike argument'); + t.end(); + }); + t.test('pans with specified offset', function(t) { var camera = createCamera(); camera.panTo([100, 0], { offset: [100, 0], duration: 0 }); @@ -706,6 +728,14 @@ test('camera', function(t) { t.end(); }); + t.test('throws on invalid center argument', function(t) { + var camera = createCamera(); + t.throws(function() { + camera.flyTo({center: 1}); + }, Error, 'throws with non-LngLatLike argument'); + t.end(); + }); + t.test('zooms to specified level', function(t) { var camera = createCamera(); camera.flyTo({ zoom: 3.2, animate: false }); diff --git a/test/js/ui/map.test.js b/test/js/ui/map.test.js index d0db577f55d..7611110cee2 100755 --- a/test/js/ui/map.test.js +++ b/test/js/ui/map.test.js @@ -430,6 +430,17 @@ test('Map', function(t) { t.end(); }); + t.test('throws on invalid bounds', function(t) { + var map = createMap({zoom:0}); + t.throws(function() { + map.setMaxBounds([-130.4297, 50.0642], [-61.52344, 24.20688]); + }, Error, 'throws on two decoupled array coordinate arguments'); + t.throws(function() { + map.setMaxBounds(-130.4297, 50.0642, -61.52344, 24.20688); + }, Error, 'throws on individual coordinate arguments'); + t.end(); + }); + function toFixed(bounds) { var n = 10; return [