-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(isValid3DCoordinate): add new matcher function
This matcher verifies that a 3D GeoJSON coordinate is appropriately formatted and in range. It makes use of existing functions from the isValid2DCoordinate matcher. Resolves: #2
- Loading branch information
1 parent
7a2184a
commit 0329231
Showing
5 changed files
with
251 additions
and
2 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
const { valid2D } = require('./isValid2DCoordinate') | ||
/** | ||
* A helper function used to verify a coordinate has appropriate longitude, latitude, and altitude values. | ||
* | ||
* @memberof Helpers | ||
* @private | ||
* @ignore | ||
* @param {GeoJSON-Coordinate} coordinate A WGS-84 array of [longitude, latitude, alititude] | ||
* @returns {boolean} True if a valid 3D GeoJSON coordinate, false otherwise | ||
*/ | ||
function valid3D(coordinate) { | ||
if (!Array.isArray(coordinate) || coordinate.length !== 3) { | ||
return false | ||
} | ||
|
||
// The first two elements have to match the same validity requirements as a 2D coordinate. | ||
// Reuse the logic from that function. | ||
if (!valid2D([coordinate[0], coordinate[1]])) { | ||
return false | ||
} | ||
|
||
if (typeof coordinate[2] !== 'number') { | ||
return false | ||
} | ||
|
||
// eslint-disable-next-line no-self-compare | ||
if (coordinate[2] !== coordinate[2]) { | ||
// Accounts for NaN | ||
return false | ||
} | ||
return true | ||
} | ||
|
||
/** | ||
* Verifies a three element coordinate meets WGS-84 and GeoJSON validity requirements. | ||
* | ||
* @memberof Coordinates | ||
* @param {number[]} coordinateArray A three element array of numbers in format [longitude, latitude, altitude]. | ||
* | ||
* Longitude must be between -180 to 180. | ||
* Latitude must be between -90 to 90. | ||
* Altitude must be a number between -Infinity to Infinity. The standard does not specify units it represents (i.e. meters, feet, etc.). | ||
* @returns {JestMatchingObject} Test passed or failed | ||
* @example | ||
* expect([22, 45.733, 20]).isValid3DCoordinate() | ||
* expect([180, 90, -10000]).isValid3DCoordinate() | ||
* @example | ||
* expect([22, 100.56]).not.isValid3DCoordinate() | ||
* expect([22, 45.733, '0']).not.isValid3DCoordinate() | ||
* expect([[22, 45.733, 0]]).not.isValid3DCoordinate() | ||
* expect([[22, 45.733, 0], [180, 90, 0]]).not.isValid3DCoordinate() | ||
*/ | ||
function isValid3DCoordinate(coordinateArray) { | ||
const { printReceived, matcherHint } = this.utils | ||
const passMessage = | ||
// eslint-disable-next-line prefer-template | ||
matcherHint('.not.isValid3DCoordinate', '[longitude, latitude]', '') + | ||
'\n\n' + | ||
`Expected input to not be a three element array with longitude between (-90 to 90) and latitude between (-180 to 180) and numeric altitude.\n\n` + | ||
`Received: ${printReceived(coordinateArray)}` | ||
|
||
const failMessage = | ||
// eslint-disable-next-line prefer-template | ||
matcherHint('.isValid3DCoordinate', '[longitude, latitude]', '') + | ||
'\n\n' + | ||
`Expected a three element array with longitude between (-90 to 90) and latitude between (-180 to 180) and numeric altitude.\n\n` + | ||
`Received: ${printReceived(coordinateArray)}` | ||
|
||
if (valid3D(coordinateArray)) { | ||
return { pass: true, message: () => passMessage } | ||
} | ||
return { pass: false, message: () => failMessage } | ||
} | ||
|
||
exports.valid3D = valid3D | ||
exports.isValid3DCoordinate = isValid3DCoordinate |
17 changes: 17 additions & 0 deletions
17
tests/coordinates/__snapshots__/isValid3DCoordinate.test.js.snap
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`Error Snapshot Testing. Throws error: expect([0, 0, 0]).not.isValid3DCoordinate 1`] = ` | ||
"[2mexpect([22m[31m[longitude, latitude][39m[2m).not.isValid3DCoordinate()[22m | ||
Expected input to not be a three element array with longitude between (-90 to 90) and latitude between (-180 to 180) and numeric altitude. | ||
Received: [31m[0, 0, 0][39m" | ||
`; | ||
|
||
exports[`Error Snapshot Testing. Throws error: expect([0, 0]).isValid3DCoordinate 1`] = ` | ||
"[2mexpect([22m[31m[longitude, latitude][39m[2m).isValid3DCoordinate()[22m | ||
Expected a three element array with longitude between (-90 to 90) and latitude between (-180 to 180) and numeric altitude. | ||
Received: [31m[0, 0][39m" | ||
`; |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
const goodCoordinates = [ | ||
[0, 0, 0], | ||
[102.0, 0.5, 1000], | ||
[172.0, -15, -1000], | ||
[-10.9, 77, 5000], | ||
[-152.0, -33.33333, -5000] | ||
] | ||
const goodBoundaryCoordinates = [ | ||
[180, 0, Infinity], | ||
[-180, 0, Infinity], | ||
[0, 90, Infinity], | ||
[0, -90, Infinity], | ||
[180, 90, -Infinity], | ||
[180, -90, -Infinity], | ||
[-180, 90, -Infinity], | ||
[-180, -90, -Infinity] | ||
] | ||
const coordinatesOutOfRange = [ | ||
[0, 90.0000001, 0], | ||
[0, -90.0000001, 0], | ||
[0, 900000, 0], | ||
[0, -900000, 0], | ||
[180.0000001, 0, 0], | ||
[-180.0000001, 0, 0], | ||
[1800000, 0, 0], | ||
[-1800000, 0, 0], | ||
[181, 91, 0], | ||
[181, -91, 0], | ||
[-181, 91, 0], | ||
[-181, -91, 0] | ||
] | ||
const invalidInputValues = [ | ||
undefined, | ||
null, | ||
true, | ||
false, | ||
200, | ||
-200, | ||
Infinity, | ||
-Infinity, | ||
NaN, | ||
{ coordinates: [0, 0, 0] }, | ||
'', | ||
'Random Coordinate', | ||
'[0, 0, 0]', | ||
'[[0, 0, 0], [0, 0, 0]]' | ||
] | ||
const InvalidAltitudeValues = [ | ||
undefined, | ||
null, | ||
true, | ||
false, | ||
NaN, | ||
{ coordinates: [0, 0, 0] }, | ||
'', | ||
'Random Coordinate', | ||
'[0, 0, 0]', | ||
'[[0, 0, 0], [0, 0, 0]]' | ||
] | ||
|
||
describe('Valid Use Cases', () => { | ||
describe('Expect to pass with good coordinates:', () => { | ||
test.each([...goodCoordinates])('expect([%p, %p, %p])', (longitude, latitude, altitude) => { | ||
expect([longitude, latitude, altitude]).isValid3DCoordinate() | ||
}) | ||
}) | ||
|
||
describe('Expect to pass with good boundary coordinates:', () => { | ||
test.each([...goodBoundaryCoordinates])( | ||
'expect([%p, %p, %p])', | ||
(longitude, latitude, altitude) => { | ||
expect([longitude, latitude, altitude]).isValid3DCoordinate() | ||
} | ||
) | ||
}) | ||
}) | ||
|
||
describe('Invalid Use Cases', () => { | ||
describe('Expect to fail with bad inputs:', () => { | ||
test.each([...invalidInputValues])('expect(%p)', (badInput) => { | ||
expect(badInput).not.isValid3DCoordinate() | ||
}) | ||
}) | ||
|
||
describe('Expect to fail with incorrect number of array elements:', () => { | ||
test.each([[[]], [[20]], [[20, 30]], [[20, 30, 0, 20, 30, 0, 20, 30, 0]]])( | ||
'expect(%p)', | ||
(badInput) => { | ||
expect(badInput).not.isValid3DCoordinate() | ||
} | ||
) | ||
}) | ||
|
||
describe('Expect to fail with out of range lon/lat coordinates:', () => { | ||
test.each([...coordinatesOutOfRange])( | ||
'expect([%p, %p, %p])', | ||
(longitude, latitude, altitude) => { | ||
expect([longitude, latitude, altitude]).not.isValid3DCoordinate() | ||
} | ||
) | ||
}) | ||
|
||
describe('Passing Bad Individual Coordinate Values', () => { | ||
describe('Expect to fail with bad longitude value:', () => { | ||
test.each([...invalidInputValues])('expect([%p, 0, 0])', (longitude) => { | ||
expect([longitude, 0, 0]).not.isValid3DCoordinate() | ||
}) | ||
}) | ||
|
||
describe('Expect to fail with bad latitude value:', () => { | ||
test.each([...invalidInputValues])('expect([0, %p, 0])', (latitude) => { | ||
expect([0, latitude, 0]).not.isValid3DCoordinate() | ||
}) | ||
}) | ||
|
||
describe('Expect to fail with bad altitude value:', () => { | ||
test.each([...InvalidAltitudeValues])('expect([0, 0, %p])', (altitude) => { | ||
expect([0, 0, altitude]).not.isValid3DCoordinate() | ||
}) | ||
}) | ||
|
||
describe('Expect to fail with bad values for all three: ', () => { | ||
test.each([...invalidInputValues])( | ||
'expect(<val>, <val>, <val>), <val> = %p', | ||
(input) => { | ||
expect([input, input, input]).not.isValid3DCoordinate() | ||
} | ||
) | ||
}) | ||
}) | ||
|
||
describe('Expect to fail when arrays are nested too deeply:', () => { | ||
const testArray = [ | ||
[10, 20], | ||
[2, 90], | ||
[95, 5] | ||
] | ||
test.each([[testArray], [[testArray]], [[[testArray]]]])('expect(%p)', (badInput) => { | ||
expect([badInput]).not.isValid2DCoordinate() | ||
}) | ||
}) | ||
}) | ||
|
||
describe('Error Snapshot Testing. Throws error:', () => { | ||
test('expect([0, 0, 0]).not.isValid3DCoordinate', () => { | ||
expect(() => expect([0, 0, 0]).not.isValid3DCoordinate()).toThrowErrorMatchingSnapshot() | ||
}) | ||
|
||
test('expect([0, 0]).isValid3DCoordinate', () => { | ||
expect(() => expect([0, 0]).isValid3DCoordinate()).toThrowErrorMatchingSnapshot() | ||
}) | ||
}) |