diff --git a/jest.config.js b/jest.config.js index 9baa7487..7ed520db 100644 --- a/jest.config.js +++ b/jest.config.js @@ -15,6 +15,7 @@ module.exports = { }, automock: false, setupFiles: ['./jest.setup.js'], + setupFilesAfterEnv: ['./jest.extend.js'], globals: { 'ts-jest': { tsConfig: { diff --git a/jest.extend.js b/jest.extend.js new file mode 100644 index 00000000..12849b5a --- /dev/null +++ b/jest.extend.js @@ -0,0 +1,100 @@ +function toBeValidCoordinate(coord) { + // coordinate must have two dimensions + if (!Array.isArray(coord) || coord.length !== 2) { + return { + pass: false, + message: `coordinate must have two dimensions`, + }; + } + + // coordinate dimensions must be valid numbers + if ( + typeof coord[0] !== 'number' || + isNaN(coord[0]) || + typeof coord[1] !== 'number' || + isNaN(coord[1]) + ) { + return { + pass: false, + message: `coordinate dimensions must be valid numbers`, + }; + } + + // coordinate valid + return { + pass: true, + message: `coordinate valid`, + }; +} + +function toBeValidBounds(bounds) { + // null bounds are valid + if (bounds === null) { + return { + pass: true, + message: `null bounds are valid`, + }; + } + + // bounds must be a coordinate pair + if (!Array.isArray(bounds) || bounds.length !== 2) { + return { + pass: false, + message: `bounds must be a coordinate pair`, + }; + } + + // validate south-west + const validateSW = toBeValidCoordinate(bounds[0]); + if (!validateSW.pass) { + return validateSW; + } + + // validate north-east + const validateNE = toBeValidCoordinate(bounds[1]); + if (!validateNE.pass) { + return validateNE; + } + + // corners + const [south, west] = bounds[0]; + const [north, east] = bounds[1]; + + // bounds represents a point + // note: this is not really a valid bounds but we will allow it + if (south === north && west === east) { + return { + pass: true, + message: `bounds represents a point`, + }; + } + + // west should be less than or equal to east + // @note: this is not the strictly case for bounds which cross the antimeridian + if (west > east) { + return { + pass: false, + message: `west should be less than or equal to east`, + }; + } + + // south should be less than or equal to north + // @note: this is not the strictly case for bounds which cross a pole + if (south > north) { + return { + pass: false, + message: `south should be less than or equal to north`, + }; + } + + // bounds valid + return { + pass: true, + message: `bounds valid`, + }; +} + +expect.extend({ + toBeValidCoordinate, + toBeValidBounds, +}); diff --git a/src/providers/__tests__/algoliaProvider.spec.js b/src/providers/__tests__/algoliaProvider.spec.js index df2e25ba..31a020ae 100644 --- a/src/providers/__tests__/algoliaProvider.spec.js +++ b/src/providers/__tests__/algoliaProvider.spec.js @@ -15,5 +15,6 @@ describe('AlgoliaProvider', () => { expect(result.label).toBeTruthy(); expect(result.x).toEqual(fixtures.hits[0]._geoloc.lng); expect(result.y).toEqual(fixtures.hits[0]._geoloc.lat); + expect(result.bounds).toBeValidBounds(); }); }); diff --git a/src/providers/__tests__/bingProvider.spec.js b/src/providers/__tests__/bingProvider.spec.js index 9816908a..b05f5594 100644 --- a/src/providers/__tests__/bingProvider.spec.js +++ b/src/providers/__tests__/bingProvider.spec.js @@ -56,10 +56,7 @@ describe('BingProvider', () => { expect(result.y).toEqual( fixtures.resourceSets[0].resources[0].point.coordinates[0], ); - expect(result.bounds[0][0]).toBeGreaterThan(result.bounds[0][1]); - expect(result.bounds[1][0]).toBeGreaterThan(result.bounds[1][1]); - expect(result.bounds[0][0]).toBeLessThan(result.bounds[1][0]); - expect(result.bounds[0][1]).toBeLessThan(result.bounds[1][1]); + expect(result.bounds).toBeValidBounds(); }); test.skip('Can get localized results', async () => { diff --git a/src/providers/__tests__/esriProvider.spec.js b/src/providers/__tests__/esriProvider.spec.js index c0e46178..5f255f32 100644 --- a/src/providers/__tests__/esriProvider.spec.js +++ b/src/providers/__tests__/esriProvider.spec.js @@ -15,9 +15,6 @@ describe('EsriProvider', () => { expect(result.label).toBeTruthy(); expect(result.x).toEqual(fixtures.locations[0].feature.geometry.x); expect(result.y).toEqual(fixtures.locations[0].feature.geometry.y); - expect(result.bounds[0][0]).toBeGreaterThan(result.bounds[0][1]); - expect(result.bounds[1][0]).toBeGreaterThan(result.bounds[1][1]); - expect(result.bounds[0][0]).toBeLessThan(result.bounds[1][0]); - expect(result.bounds[0][1]).toBeLessThan(result.bounds[1][1]); + expect(result.bounds).toBeValidBounds(); }); }); diff --git a/src/providers/__tests__/geocodeEarthProvider.spec.js b/src/providers/__tests__/geocodeEarthProvider.spec.js index d9cc0ee2..3cfb881c 100644 --- a/src/providers/__tests__/geocodeEarthProvider.spec.js +++ b/src/providers/__tests__/geocodeEarthProvider.spec.js @@ -17,14 +17,7 @@ describe('GeocodeEarthProvider', function () { expect(result.label).toBeTruthy(); expect(result.x).toEqual(+feat.geometry.coordinates[0]); expect(result.y).toEqual(+feat.geometry.coordinates[1]); - - // bounding box range checks - if (feat.bbox) { - expect(result.bounds[0][0]).toBeLessThan(result.bounds[1][0]); // south less than north - expect(result.bounds[0][1]).toBeLessThan(result.bounds[1][1]); // west less than east - } else { - expect(result.bounds).toBeFalsy(); - } + expect(result.bounds).toBeValidBounds(); }); }); }); diff --git a/src/providers/__tests__/googleProvider.spec.js b/src/providers/__tests__/googleProvider.spec.js index b500ba67..3f2c412d 100644 --- a/src/providers/__tests__/googleProvider.spec.js +++ b/src/providers/__tests__/googleProvider.spec.js @@ -19,10 +19,7 @@ describe('GoogleProvider', () => { expect(result.label).toBeTruthy(); expect(result.x).toEqual(fixtures.results[0].geometry.location.lng); expect(result.y).toEqual(fixtures.results[0].geometry.location.lat); - expect(result.bounds[0][0]).toBeGreaterThan(result.bounds[0][1]); - expect(result.bounds[1][0]).toBeGreaterThan(result.bounds[1][1]); - expect(result.bounds[0][0]).toBeLessThan(result.bounds[1][0]); - expect(result.bounds[0][1]).toBeLessThan(result.bounds[1][1]); + expect(result.bounds).toBeValidBounds(); }); test.skip('Can get localized results', async () => { diff --git a/src/providers/__tests__/hereProvider.spec.js b/src/providers/__tests__/hereProvider.spec.js index a1d5c614..810b1715 100644 --- a/src/providers/__tests__/hereProvider.spec.js +++ b/src/providers/__tests__/hereProvider.spec.js @@ -20,6 +20,6 @@ describe('HereProvider', () => { expect(result.x).toEqual(+fixtures.items[0].position.lng); expect(result.y).toEqual(+fixtures.items[0].position.lat); // here provider doesn't return bounds :( - expect(result.bounds).toBeFalsy(); + expect(result.bounds).toBeValidBounds(); }); }); diff --git a/src/providers/__tests__/locationiqProvider.spec.js b/src/providers/__tests__/locationiqProvider.spec.js index 4f79519e..9a1a1d29 100644 --- a/src/providers/__tests__/locationiqProvider.spec.js +++ b/src/providers/__tests__/locationiqProvider.spec.js @@ -19,10 +19,7 @@ describe('LocationIQProvider', () => { expect(result.label).toBeTruthy(); expect(result.x).toEqual(+fixtures[0].lon); expect(result.y).toEqual(+fixtures[0].lat); - expect(result.bounds[0][0]).toBeGreaterThan(result.bounds[0][1]); - expect(result.bounds[1][0]).toBeGreaterThan(result.bounds[1][1]); - expect(result.bounds[0][0]).toBeLessThan(result.bounds[1][0]); - expect(result.bounds[0][1]).toBeLessThan(result.bounds[1][1]); + expect(result.bounds).toBeValidBounds(); }); test.skip('Can get localized results', async () => { diff --git a/src/providers/__tests__/opencageProvider.spec.js b/src/providers/__tests__/opencageProvider.spec.js index b5667c8f..9c807993 100644 --- a/src/providers/__tests__/opencageProvider.spec.js +++ b/src/providers/__tests__/opencageProvider.spec.js @@ -13,10 +13,7 @@ test.skip('Can fetch results with OpenCage', async () => { t.truthy(result.label); t.true(result.x > 5 && result.x < 6); t.true(result.y > 50 && result.y < 55); - t.true(result.bounds[0][0] > result.bounds[0][1]); - t.true(result.bounds[1][0] > result.bounds[1][1]); - t.true(result.bounds[0][0] < result.bounds[1][0]); - t.true(result.bounds[0][1] < result.bounds[1][1]); + expect(result.bounds).toBeValidBounds(); }); test.skip('Can get localized results', async () => { diff --git a/src/providers/__tests__/openstreetmapProvider.spec.js b/src/providers/__tests__/openstreetmapProvider.spec.js index 689215d3..c2724bfa 100644 --- a/src/providers/__tests__/openstreetmapProvider.spec.js +++ b/src/providers/__tests__/openstreetmapProvider.spec.js @@ -15,10 +15,7 @@ describe('OpenStreetMapProvider', function () { expect(result.label).toBeTruthy(); expect(result.x).toEqual(+fixtures[0].lon); expect(result.y).toEqual(+fixtures[0].lat); - expect(result.bounds[0][0]).toBeGreaterThan(result.bounds[0][1]); - expect(result.bounds[1][0]).toBeGreaterThan(result.bounds[1][1]); - expect(result.bounds[0][0]).toBeLessThan(result.bounds[1][0]); - expect(result.bounds[0][1]).toBeLessThan(result.bounds[1][1]); + expect(result.bounds).toBeValidBounds(); }); test.skip('Can get localized results', async () => { diff --git a/src/providers/__tests__/peliasProvider.spec.js b/src/providers/__tests__/peliasProvider.spec.js index 3f1bd5a6..abc14ed9 100644 --- a/src/providers/__tests__/peliasProvider.spec.js +++ b/src/providers/__tests__/peliasProvider.spec.js @@ -17,14 +17,7 @@ describe('PeliasProvider', function () { expect(result.label).toBeTruthy(); expect(result.x).toEqual(+feat.geometry.coordinates[0]); expect(result.y).toEqual(+feat.geometry.coordinates[1]); - - // bounding box range checks - if (feat.bbox) { - expect(result.bounds[0][0]).toBeLessThan(result.bounds[1][0]); // south less than north - expect(result.bounds[0][1]).toBeLessThan(result.bounds[1][1]); // west less than east - } else { - expect(result.bounds).toBeFalsy(); - } + expect(result.bounds).toBeValidBounds(); }); }); });