Skip to content

Commit

Permalink
refactor: modify valid 2D and 3D coordinate functions to throw errors…
Browse files Browse the repository at this point in the history
… instead of return false

This allows for more descriptive problems presented to the user when they run their tests with Jest.
It sets up the standard going forward for how these tests should look. Subject to further
refactoring in the future for the failMessage functions.
  • Loading branch information
M-Scott-Lassiter committed May 24, 2022
1 parent 9e49d3d commit c0becfb
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 62 deletions.
12 changes: 9 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,17 @@
*/

/**
* Functions used internal to jest-geojson.
* Core functionality used internal to jest-geojson.
*
* @private
* @ignore
* @namespace Helpers
* @namespace Core
*/

/**
* Coordinate functions used within Core.
*
* @private
* @namespace Core.Coordinates
*/

/**
Expand Down
71 changes: 46 additions & 25 deletions src/matchers/coordinates/isValid2DCoordinate.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,49 @@
/**
* A helper function used to verify a coordinate has appropriate longitude and latitude values.
*
* @memberof Helpers
* @private
* @ignore
* @memberof Core.Coordinates
* @param {GeoJSON-Coordinate} coordinate A WGS-84 array of [longitude, latitude]
* @returns {boolean} True if a valid 2D GeoJSON coordinate, false otherwise
* @returns {boolean} True if a valid 2D GeoJSON coordinate. If invalid, it will throw an error.
* @throws {Error} Input must be an array of only two elments
* @throws {RangeError} Longitude must be a number between -180 and 180
* @throws {RangeError} Latitude must be a number between -90 and 90
*/
function valid2D(coordinate) {
if (!Array.isArray(coordinate) || coordinate.length !== 2) {
return false
throw new Error('Input must be an array of only two elments.')
}

if (typeof coordinate[0] !== 'number' || typeof coordinate[1] !== 'number') {
return false
if (
typeof coordinate[0] !== 'number' ||
coordinate[0] < -180 ||
coordinate[0] > 180 ||
// eslint-disable-next-line no-self-compare
coordinate[0] !== coordinate[0] // Accounts for NaN
) {
throw new Error('Longitude must be a number between -180 and 180.')
}

// eslint-disable-next-line no-self-compare
if (coordinate[0] !== coordinate[0] || coordinate[1] !== coordinate[1]) {
// Accounts for NaN
return false
if (
typeof coordinate[1] !== 'number' ||
coordinate[1] < -90 ||
coordinate[1] > 90 ||
// eslint-disable-next-line no-self-compare
coordinate[1] !== coordinate[1] // Accounts for NaN
) {
throw new Error('Latitude must be a number between -90 and 90.')
}

if (coordinate[0] < -180 || coordinate[0] > 180 || coordinate[1] < -90 || coordinate[1] > 90) {
return false
}
return true
}

// eslint-disable-next-line jsdoc/require-returns
/**
* Verifies a two element coordinate meets WGS-84 and GeoJSON validity requirements.
*
* @memberof Coordinates
* @param {number[]} coordinateArray A two element array of numbers in format [longitude, latitude].
* Longitude must be between -180 to 180.
* Latitude must be between -90 to 90.
* @returns {JestMatchingObject} Test passed or failed
* @example
* expect([22, 45.733]).isValid2DCoordinate()
* expect([180, 90]).isValid2DCoordinate()
Expand All @@ -51,20 +59,33 @@ function isValid2DCoordinate(coordinateArray) {
// eslint-disable-next-line prefer-template
matcherHint('.not.isValid2DCoordinate', '[longitude, latitude]', '') +
'\n\n' +
`Expected input to not be a two element array with longitude between (-90 to 90) and latitude between (-180 to 180).\n\n` +
`Expected input to not be a two element array with longitude between (-90 to 90),
and latitude between (-180 to 180).\n\n` +
`Received: ${printReceived(coordinateArray)}`

const failMessage =
// eslint-disable-next-line prefer-template
matcherHint('.isValid2DCoordinate', '[longitude, latitude]', '') +
'\n\n' +
`Expected a two element array with longitude between (-90 to 90) and latitude between (-180 to 180).\n\n` +
`Received: ${printReceived(coordinateArray)}`
/**
* Combines a custom error message with built in Jest tools to provide a more descriptive error
* meessage to the end user.
*
* @param {string} errorMessage Error message text to return to the user
* @returns {string} Concatenated Jest test result string
*/
function failMessage(errorMessage) {
return (
// eslint-disable-next-line prefer-template, no-unused-expressions
matcherHint('.isValid2DCoordinate', '[longitude, latitude]', '') +
'\n\n' +
`${errorMessage}\n\n` +
`Received: ${printReceived(coordinateArray)}`
)
}

if (valid2D(coordinateArray)) {
return { pass: true, message: () => passMessage }
try {
valid2D(coordinateArray)
} catch (err) {
return { pass: false, message: () => failMessage(err.message) }
}
return { pass: false, message: () => failMessage }
return { pass: true, message: () => passMessage }
}

exports.valid2D = valid2D
Expand Down
65 changes: 37 additions & 28 deletions src/matchers/coordinates/isValid3DCoordinate.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,31 @@ const { valid2D } = require('./isValid2DCoordinate')
/**
* A helper function used to verify a coordinate has appropriate longitude, latitude, and altitude values.
*
* @memberof Helpers
* @private
* @ignore
* @memberof Core.Coordinates
* @param {GeoJSON-Coordinate} coordinate A WGS-84 array of [longitude, latitude, alititude]
* @returns {boolean} True if a valid 3D GeoJSON coordinate, false otherwise
* @returns {boolean} True if a valid 3D GeoJSON coordinate. If invalid, it will throw an error.
* @throws {Error} Input must be an array of only three elments
* @throws {Error} Altitude value must be numeric
*/
function valid3D(coordinate) {
if (!Array.isArray(coordinate) || coordinate.length !== 3) {
return false
throw new Error('Input must be an array of only three elments.')
}

// 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
}
valid2D([coordinate[0], coordinate[1]])

// eslint-disable-next-line no-self-compare
if (coordinate[2] !== coordinate[2]) {
// Accounts for NaN
return false
if (typeof coordinate[2] !== 'number' || coordinate[2] !== coordinate[2]) {
// Self compare accounts for NaN
throw new Error('Altitude value must be numeric.')
}

return true
}

// eslint-disable-next-line jsdoc/require-returns
/**
* Verifies a three element coordinate meets WGS-84 and GeoJSON validity requirements.
*
Expand All @@ -39,8 +35,8 @@ function valid3D(coordinate) {
*
* 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
* Altitude must be a number between -Infinity to Infinity.
* The standard does not specify units altitude represents (i.e. meters, feet, etc.).
* @example
* expect([22, 45.733, 20]).isValid3DCoordinate()
* expect([180, 90, -10000]).isValid3DCoordinate()
Expand All @@ -54,22 +50,35 @@ function isValid3DCoordinate(coordinateArray) {
const { printReceived, matcherHint } = this.utils
const passMessage =
// eslint-disable-next-line prefer-template
matcherHint('.not.isValid3DCoordinate', '[longitude, latitude]', '') +
matcherHint('.not.isValid3DCoordinate', '[longitude, latitude, altitude]', '') +
'\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` +
`Expected input to not be a three element array with longitude between (-90 to 90),
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)}`
/**
* Combines a custom error message with built in Jest tools to provide a more descriptive error
* meessage to the end user.
*
* @param {string} errorMessage Error message text to return to the user
* @returns {string} Concatenated Jest test result string
*/
function failMessage(errorMessage) {
return (
// eslint-disable-next-line prefer-template, no-unused-expressions
matcherHint('.isValid3DCoordinate', '[longitude, latitude, altitude]', '') +
'\n\n' +
`${errorMessage}\n\n` +
`Received: ${printReceived(coordinateArray)}`
)
}

if (valid3D(coordinateArray)) {
return { pass: true, message: () => passMessage }
try {
valid3D(coordinateArray)
} catch (err) {
return { pass: false, message: () => failMessage(err.message) }
}
return { pass: false, message: () => failMessage }
return { pass: true, message: () => passMessage }
}

exports.valid3D = valid3D
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@
exports[`Error Snapshot Testing. Throws error: expect([0, 0]).not.isValid3DCoordinate 1`] = `
"expect([longitude, latitude]).not.isValid2DCoordinate()
Expected input to not be a two element array with longitude between (-90 to 90) and latitude between (-180 to 180).
Expected input to not be a two element array with longitude between (-90 to 90),
and latitude between (-180 to 180).
Received: [0, 0]"
`;

exports[`Error Snapshot Testing. Throws error: expect(false).isValid2DCoordinate() 1`] = `
"expect([longitude, latitude]).isValid2DCoordinate()
Expected a two element array with longitude between (-90 to 90) and latitude between (-180 to 180).
Input must be an array of only two elments.
Received: false"
`;
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
// 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
"[2mexpect([22m[31m[longitude, latitude, altitude][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.
Expected input to not be a three element array with longitude between (-90 to 90),
latitude between (-180 to 180), and numeric altitude.
Received: [0, 0, 0]"
`;

exports[`Error Snapshot Testing. Throws error: expect([0, 0]).isValid3DCoordinate 1`] = `
"[2mexpect([22m[31m[longitude, latitude][39m[2m).isValid3DCoordinate()[22m
"[2mexpect([22m[31m[longitude, latitude, altitude][39m[2m).isValid3DCoordinate()[22m
Expected a three element array with longitude between (-90 to 90) and latitude between (-180 to 180) and numeric altitude.
Input must be an array of only three elments.
Received: [0, 0]"
`;

0 comments on commit c0becfb

Please sign in to comment.