From f718594c2ec6c43812702eba03c7508d4141e2c1 Mon Sep 17 00:00:00 2001 From: john gravois Date: Fri, 11 Nov 2016 10:56:52 -0800 Subject: [PATCH 1/4] add test --- spec/Tasks/QuerySpec.js | 25 +++++++++++++++++++++++++ src/Tasks/Query.js | 9 +++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/spec/Tasks/QuerySpec.js b/spec/Tasks/QuerySpec.js index 011a1bdd1..a12b32a4b 100644 --- a/spec/Tasks/QuerySpec.js +++ b/spec/Tasks/QuerySpec.js @@ -193,6 +193,15 @@ describe('L.esri.Query', function () { } }; + var sampleNaNExtentResponse = { + 'extent': { + 'xmin': 'NaN', + 'ymin': 'NaN', + 'xmax': 'NaN', + 'ymax': 'NaN' + } + }; + var sampleCountResponse = { 'count': 1 }; @@ -619,6 +628,22 @@ describe('L.esri.Query', function () { server.respond(); }); + it('should query nullified bounds', function (done) { + server.respondWith('GET', featureLayerUrl + 'query?returnGeometry=true&where=1%3D2&outSr=4326&outFields=*&returnExtentOnly=true&f=json', JSON.stringify(sampleNaNExtentResponse)); + + task.where('1=2'); + var request = task.bounds(function (error, latlngbounds, raw) { + expect(latlngbounds).to.deep.equal(null); + expect(raw).to.deep.equal(sampleNaNExtentResponse); + done(); + }); + + expect(request).to.be.an.instanceof(XMLHttpRequest); + + server.respond(); + task.where('1=1'); + }); + it('should query count', function (done) { server.respondWith('GET', featureLayerUrl + 'query?returnGeometry=true&where=1%3D1&outSr=4326&outFields=*&returnCountOnly=true&f=json', JSON.stringify(sampleCountResponse)); diff --git a/src/Tasks/Query.js b/src/Tasks/Query.js index 17b14d117..510fb28ba 100644 --- a/src/Tasks/Query.js +++ b/src/Tasks/Query.js @@ -131,12 +131,17 @@ export var Query = Task.extend({ }, context); }, - // only valid for Feature Services running on ArcGIS Server 10.3 or ArcGIS Online + // only valid for Feature Services running on ArcGIS Server 10.3+ or ArcGIS Online bounds: function (callback, context) { this._cleanParams(); this.params.returnExtentOnly = true; return this.request(function (error, response) { - callback.call(context, error, (response && response.extent && Util.extentToBounds(response.extent)), response); + if (!response.extent || response.extent.xmin === 'NaN') { + // if an extent with "NaN" coordinates is returned from ArcGIS Server, just pass a null geometry + callback.call(context, error, null, response); + } else { + callback.call(context, error, (response && response.extent && Util.extentToBounds(response.extent)), response); + } }, context); }, From 726151f9e4a2c148abd33b5193d6787ce268aa40 Mon Sep 17 00:00:00 2001 From: john gravois Date: Fri, 11 Nov 2016 11:04:24 -0800 Subject: [PATCH 2/4] better to place the logic in extentToBounds --- src/Tasks/Query.js | 7 +------ src/Util.js | 11 ++++++++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Tasks/Query.js b/src/Tasks/Query.js index 510fb28ba..f48b3a652 100644 --- a/src/Tasks/Query.js +++ b/src/Tasks/Query.js @@ -136,12 +136,7 @@ export var Query = Task.extend({ this._cleanParams(); this.params.returnExtentOnly = true; return this.request(function (error, response) { - if (!response.extent || response.extent.xmin === 'NaN') { - // if an extent with "NaN" coordinates is returned from ArcGIS Server, just pass a null geometry - callback.call(context, error, null, response); - } else { - callback.call(context, error, (response && response.extent && Util.extentToBounds(response.extent)), response); - } + callback.call(context, error, (response && response.extent && Util.extentToBounds(response.extent)), response); }, context); }, diff --git a/src/Util.js b/src/Util.js index c14e8783f..3d2680314 100644 --- a/src/Util.js +++ b/src/Util.js @@ -29,9 +29,14 @@ export function shallowClone (obj) { // convert an extent (ArcGIS) to LatLngBounds (Leaflet) export function extentToBounds (extent) { - var sw = L.latLng(extent.ymin, extent.xmin); - var ne = L.latLng(extent.ymax, extent.xmax); - return L.latLngBounds(sw, ne); + // "NaN" coordinates from ArcGIS Server indicate a null geometry + if (extent.xmin !== 'NaN' && extent.ymin !== 'NaN' && extent.xmax !== 'NaN' && extent.ymax !== 'NaN') { + var sw = L.latLng(extent.ymin, extent.xmin); + var ne = L.latLng(extent.ymax, extent.xmax); + return L.latLngBounds(sw, ne); + } else { + return null; + } } // convert an LatLngBounds (Leaflet) to extent (ArcGIS) From a5e8b28cf85e09ec9397bea75873ed631006313e Mon Sep 17 00:00:00 2001 From: john gravois Date: Fri, 11 Nov 2016 11:18:36 -0800 Subject: [PATCH 3/4] try caching node dependencies on travis again --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 5553b6377..d445b799d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,3 +8,6 @@ before_script: - npm prune before_install: - npm i -g npm@^3.0.0 +cache: + directories: # Cache dependencies + - node_modules From 316dac3919c55a3648fdec570de33eb57e6d5a17 Mon Sep 17 00:00:00 2001 From: john gravois Date: Tue, 15 Nov 2016 11:49:48 -0800 Subject: [PATCH 4/4] throw an error when encountering null bounds --- spec/Tasks/QuerySpec.js | 2 ++ src/Tasks/Query.js | 9 ++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/spec/Tasks/QuerySpec.js b/spec/Tasks/QuerySpec.js index a12b32a4b..2bef8a188 100644 --- a/spec/Tasks/QuerySpec.js +++ b/spec/Tasks/QuerySpec.js @@ -193,6 +193,7 @@ describe('L.esri.Query', function () { } }; + // this is how ArcGIS Server returns a null extent (for now) var sampleNaNExtentResponse = { 'extent': { 'xmin': 'NaN', @@ -633,6 +634,7 @@ describe('L.esri.Query', function () { task.where('1=2'); var request = task.bounds(function (error, latlngbounds, raw) { + expect(error.message).to.equal('Invalid Bounds'); expect(latlngbounds).to.deep.equal(null); expect(raw).to.deep.equal(sampleNaNExtentResponse); done(); diff --git a/src/Tasks/Query.js b/src/Tasks/Query.js index f48b3a652..6770aa70b 100644 --- a/src/Tasks/Query.js +++ b/src/Tasks/Query.js @@ -136,7 +136,14 @@ export var Query = Task.extend({ this._cleanParams(); this.params.returnExtentOnly = true; return this.request(function (error, response) { - callback.call(context, error, (response && response.extent && Util.extentToBounds(response.extent)), response); + if (response && response.extent && Util.extentToBounds(response.extent)) { + callback.call(context, error, Util.extentToBounds(response.extent), response); + } else { + error = { + message: 'Invalid Bounds' + }; + callback.call(context, error, null, response); + } }, context); },