diff --git a/package.json b/package.json index a26c9237..e9ee4f2d 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "@typescript-eslint/parser": "^5.30.6", "babel-jest": "^29.0.0", "babel-jest-assertions": "^0.1.0", + "check-geographic-coordinates": "^0.0.10", "eslint": "^8.0.0", "eslint-config-prettier": "^8.3.0", "eslint-import-resolver-typescript": "^3.2.5", diff --git a/src/matchers/index.js b/src/matchers/index.js index 88d9fa2b..f7312c01 100644 --- a/src/matchers/index.js +++ b/src/matchers/index.js @@ -18,6 +18,8 @@ export { toBeFalse } from './toBeFalse'; export { toBeFinite } from './toBeFinite'; export { toBeFrozen } from './toBeFrozen'; export { toBeFunction } from './toBeFunction'; +export { toBeGeoLatitude } from './toBeGeoLatitude'; +export { toBeGeoLongitude } from './toBeGeoLongitude'; export { toBeHexadecimal } from './toBeHexadecimal'; export { toBeInteger } from './toBeInteger'; export { toBeNaN } from './toBeNaN'; diff --git a/src/matchers/toBeGeoLatitude.js b/src/matchers/toBeGeoLatitude.js new file mode 100644 index 00000000..f41c9bf5 --- /dev/null +++ b/src/matchers/toBeGeoLatitude.js @@ -0,0 +1,21 @@ +import { latitude } from 'check-geographic-coordinates'; + +export function toBeGeoLatitude(actual) { + const { matcherHint, printReceived } = this.utils; + + const passMessage = + matcherHint('.not.toBeGeoLatitude', 'received', '') + + '\n\n' + + 'Expected value to not be of type latitude, received:\n' + + ` ${printReceived(actual)}`; + + const failMessage = + matcherHint('.toBeGeoLatitude', 'received', '') + + '\n\n' + + 'Expected value to be of type latitude, received:\n' + + ` ${printReceived(actual)}`; + + const pass = latitude(actual) ? true : false; + + return { pass, message: () => (pass ? passMessage : failMessage) }; +} diff --git a/src/matchers/toBeGeoLongitude.js b/src/matchers/toBeGeoLongitude.js new file mode 100644 index 00000000..d56b5467 --- /dev/null +++ b/src/matchers/toBeGeoLongitude.js @@ -0,0 +1,21 @@ +import { longitude } from 'check-geographic-coordinates'; + +export function toBeGeoLongitude(actual) { + const { matcherHint, printReceived } = this.utils; + + const passMessage = + matcherHint('.not.toBeGeoLongitude', 'received', '') + + '\n\n' + + 'Expected value to not be of type longitude, received:\n' + + ` ${printReceived(actual)}`; + + const failMessage = + matcherHint('.toBeGeoLongitude', 'received', '') + + '\n\n' + + 'Expected value to be of type longitude, received:\n' + + ` ${printReceived(actual)}`; + + const pass = longitude(actual) ? true : false; + + return { pass, message: () => (pass ? passMessage : failMessage) }; +} diff --git a/test/matchers/__snapshots__/toBeGeoLatitude.test.js.snap b/test/matchers/__snapshots__/toBeGeoLatitude.test.js.snap new file mode 100644 index 00000000..08d840db --- /dev/null +++ b/test/matchers/__snapshots__/toBeGeoLatitude.test.js.snap @@ -0,0 +1,36 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`.not.toBeGeoLatitude fails when given a latitude number 1`] = ` +"expect(received).not.toBeGeoLatitude() + +Expected value to not be of type latitude, received: + 41.902783" +`; + +exports[`.not.toBeGeoLatitude fails when given a latitude string 1`] = ` +"expect(received).not.toBeGeoLatitude() + +Expected value to not be of type latitude, received: + "41.902783"" +`; + +exports[`.toBeGeoLatitude fails when not given a latitude negative number 1`] = ` +"expect(received).toBeGeoLatitude() + +Expected value to be of type latitude, received: + -90.1" +`; + +exports[`.toBeGeoLatitude fails when not given a latitude positive number 1`] = ` +"expect(received).toBeGeoLatitude() + +Expected value to be of type latitude, received: + 90.1" +`; + +exports[`.toBeGeoLatitude fails when not given a latitude string 1`] = ` +"expect(received).toBeGeoLatitude() + +Expected value to be of type latitude, received: + "any_not_valid_latitude"" +`; diff --git a/test/matchers/__snapshots__/toBeGeoLongitude.test.js.snap b/test/matchers/__snapshots__/toBeGeoLongitude.test.js.snap new file mode 100644 index 00000000..2c4f20a1 --- /dev/null +++ b/test/matchers/__snapshots__/toBeGeoLongitude.test.js.snap @@ -0,0 +1,36 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`.not.toBeGeoLongitude fails when given a longitude number 1`] = ` +"expect(received).not.toBeGeoLongitude() + +Expected value to not be of type longitude, received: + 12.496366" +`; + +exports[`.not.toBeGeoLongitude fails when given a longitude string 1`] = ` +"expect(received).not.toBeGeoLongitude() + +Expected value to not be of type longitude, received: + "12.496366"" +`; + +exports[`.toBeGeoLongitude fails when not given a longitude negative number 1`] = ` +"expect(received).toBeGeoLongitude() + +Expected value to be of type longitude, received: + -180.1" +`; + +exports[`.toBeGeoLongitude fails when not given a longitude positive number 1`] = ` +"expect(received).toBeGeoLongitude() + +Expected value to be of type longitude, received: + 180.1" +`; + +exports[`.toBeGeoLongitude fails when not given a longitude string 1`] = ` +"expect(received).toBeGeoLongitude() + +Expected value to be of type longitude, received: + "any_not_valid_longitude"" +`; diff --git a/test/matchers/toBeGeoLatitude.test.js b/test/matchers/toBeGeoLatitude.test.js new file mode 100644 index 00000000..9c03a787 --- /dev/null +++ b/test/matchers/toBeGeoLatitude.test.js @@ -0,0 +1,44 @@ +import * as matcher from 'src/matchers/toBeGeoLatitude'; + +expect.extend(matcher); + +const ROME = { latitude: 41.902783, longitude: 12.496366 }; + +describe('.toBeGeoLatitude', () => { + test('passes when given valid latitude number', () => { + expect(ROME.latitude).toBeGeoLatitude(); + }); + + test('passes when given valid latitude string', () => { + expect(`${ROME.latitude}`).toBeGeoLatitude(); + }); + + test('fails when not given a latitude string', () => { + expect(() => expect('any_not_valid_latitude').toBeGeoLatitude()).toThrowErrorMatchingSnapshot(); + }); + + test('fails when not given a latitude positive number', () => { + expect(() => expect(90.1).toBeGeoLatitude()).toThrowErrorMatchingSnapshot(); + }); + + test('fails when not given a latitude negative number', () => { + expect(() => expect(-90.1).toBeGeoLatitude()).toThrowErrorMatchingSnapshot(); + }); +}); + +describe('.not.toBeGeoLatitude', () => { + test.each([['true'], [{}], [[]], [() => {}], [undefined], [null], [NaN]])( + 'passes when item is not of type latitude: %s', + given => { + expect(given).not.toBeGeoLatitude(); + }, + ); + + test('fails when given a latitude number', () => { + expect(() => expect(ROME.latitude).not.toBeGeoLatitude()).toThrowErrorMatchingSnapshot(); + }); + + test('fails when given a latitude string', () => { + expect(() => expect(`${ROME.latitude}`).not.toBeGeoLatitude()).toThrowErrorMatchingSnapshot(); + }); +}); diff --git a/test/matchers/toBeGeoLongitude.test.js b/test/matchers/toBeGeoLongitude.test.js new file mode 100644 index 00000000..5a02f5e0 --- /dev/null +++ b/test/matchers/toBeGeoLongitude.test.js @@ -0,0 +1,44 @@ +import * as matcher from 'src/matchers/toBeGeoLongitude'; + +expect.extend(matcher); + +const ROME = { latitude: 41.902783, longitude: 12.496366 }; + +describe('.toBeGeoLongitude', () => { + test('passes when given valid longitude number', () => { + expect(ROME.longitude).toBeGeoLongitude(); + }); + + test('passes when given valid longitude string', () => { + expect(`${ROME.longitude}`).toBeGeoLongitude(); + }); + + test('fails when not given a longitude string', () => { + expect(() => expect('any_not_valid_longitude').toBeGeoLongitude()).toThrowErrorMatchingSnapshot(); + }); + + test('fails when not given a longitude positive number', () => { + expect(() => expect(180.1).toBeGeoLongitude()).toThrowErrorMatchingSnapshot(); + }); + + test('fails when not given a longitude negative number', () => { + expect(() => expect(-180.1).toBeGeoLongitude()).toThrowErrorMatchingSnapshot(); + }); +}); + +describe('.not.toBeGeoLongitude', () => { + test.each([['true'], [{}], [[]], [() => {}], [undefined], [null], [NaN]])( + 'passes when item is not of type longitude: %s', + given => { + expect(given).not.toBeGeoLongitude(); + }, + ); + + test('fails when given a longitude number', () => { + expect(() => expect(ROME.longitude).not.toBeGeoLongitude()).toThrowErrorMatchingSnapshot(); + }); + + test('fails when given a longitude string', () => { + expect(() => expect(`${ROME.longitude}`).not.toBeGeoLongitude()).toThrowErrorMatchingSnapshot(); + }); +}); diff --git a/website/docs/matchers/Geographic.mdx b/website/docs/matchers/Geographic.mdx new file mode 100644 index 00000000..f753393f --- /dev/null +++ b/website/docs/matchers/Geographic.mdx @@ -0,0 +1,25 @@ +import { TestFile } from '../../src/components/CustomSandpack'; + +# Geographic + +### .toBeGeoLatitude() + +Use `.toBeGeoLatitude` when checking if a value is a `latitude`. + + + {`test('passes when value is a latitude', () => { + const ROME = { latitude: 41.902783, longitude: 12.496366 }; + expect(ROME.latitude).toBeGeoLatitude(); +});`} + + +### .toBeGeoLongitude() + +Use `.toBeGeoLongitude` when checking if a value is a `longitude`. + + + {`test('passes when value is a longitude', () => { + const ROME = { latitude: 41.902783, longitude: 12.496366 }; + expect(ROME.longitude).toBeGeoLongitude(); +});`} + diff --git a/website/docs/matchers/index.md b/website/docs/matchers/index.md index f44e50eb..5ac82a63 100644 --- a/website/docs/matchers/index.md +++ b/website/docs/matchers/index.md @@ -105,3 +105,8 @@ sidebar_position: 1 ## [Symbol](/docs/matchers/symbol) - [.toBeSymbol()](/docs/matchers/symbol/#tobesymbol) + +## [Geographic](/docs/matchers/geographic) + +- [.toBeGeoLatitude()](/docs/matchers/geographic/#tobegeolatitude) +- [.toBeGeoLongitude()](/docs/matchers/geographic/#tobegeolongitude) diff --git a/yarn.lock b/yarn.lock index 2125ad5d..ca46fd07 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1843,6 +1843,11 @@ char-regex@^2.0.0: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-2.0.1.tgz#6dafdb25f9d3349914079f010ba8d0e6ff9cd01e" integrity sha512-oSvEeo6ZUD7NepqAat3RqoucZ5SeqLJgOvVIwkafu6IP3V0pO38s/ypdVUmDDK6qIIHNlYHJAKX9E7R7HoKElw== +check-geographic-coordinates@^0.0.10: + version "0.0.10" + resolved "https://registry.yarnpkg.com/check-geographic-coordinates/-/check-geographic-coordinates-0.0.10.tgz#10240bfead3e81ea054ad526d973ceccf46657eb" + integrity sha512-wgMiNEVXsvdh5TaEkwvPXgfpRyVcz8nimfiw8x/7c9sNsG/mPjB2iyKftdYv72e1KY/kHp/Vh9OZc2MHur/evw== + chokidar@^3.4.0: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"