mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 19:04:02 +00:00
feat(search): coordinates and bundled presets resolve keyless (#572)
Supersedes #388 by @KuraPiee, ported onto the current component layout with fixes from review. Verified before merge: format, package boundaries, unit suite, build, and the browser tracking suite; a browser harness for the change where one applies; adversarial review applied. Co-authored-by: KuraPiee <[email protected]>
This commit is contained in:
1 parent
d9fac6d88e
commit
cca6442997
13 files changed
+672
-14
No files matched your search
@@ -0,0 +1,134 @@
|
||||
// COORDINATE PARSING — what the search box accepts as a coordinate, and what it
|
||||
// refuses. A refusal hands the text to the geocoders; a wrong accept flies the
|
||||
// operator somewhere they never asked for and looks like success, so every
|
||||
// malformed and ambiguous form below is pinned.
|
||||
//
|
||||
// Run with: npm test
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import {
|
||||
parseCoordinateQuery,
|
||||
formatCoordinateLabel,
|
||||
} from './coordinateParser.js';
|
||||
|
||||
test('a plain decimal pair is latitude then longitude', () => {
|
||||
assert.deepEqual(parseCoordinateQuery('43.1731, -79.0384'), {
|
||||
lat: 43.1731,
|
||||
lon: -79.0384,
|
||||
label: '43.1731° N, 79.0384° W',
|
||||
});
|
||||
assert.deepEqual(parseCoordinateQuery('43.1731,-79.0384')?.lat, 43.1731);
|
||||
assert.deepEqual(
|
||||
parseCoordinateQuery(' 43.1731 ; -79.0384 ')?.lon,
|
||||
-79.0384,
|
||||
);
|
||||
assert.deepEqual(parseCoordinateQuery('43.1731 -79.0384')?.lon, -79.0384);
|
||||
assert.deepEqual(parseCoordinateQuery('0, 0'), {
|
||||
lat: 0,
|
||||
lon: 0,
|
||||
label: '0.0000° N, 0.0000° E',
|
||||
});
|
||||
assert.deepEqual(parseCoordinateQuery('-33.8568, 151.2153')?.lat, -33.8568);
|
||||
assert.deepEqual(parseCoordinateQuery('30, -97')?.lat, 30);
|
||||
assert.deepEqual(parseCoordinateQuery('.5, -.25')?.lon, -0.25);
|
||||
});
|
||||
|
||||
test('hemisphere letters fix the axis, in either order', () => {
|
||||
assert.deepEqual(parseCoordinateQuery('N 40, W 74'), {
|
||||
lat: 40,
|
||||
lon: -74,
|
||||
label: '40.0000° N, 74.0000° W',
|
||||
});
|
||||
// The reviewer's case: written longitude-first, it must not read as latitude.
|
||||
assert.deepEqual(parseCoordinateQuery('W 40, N 74'), {
|
||||
lat: 74,
|
||||
lon: -40,
|
||||
label: '74.0000° N, 40.0000° W',
|
||||
});
|
||||
assert.deepEqual(parseCoordinateQuery('40N, 74W')?.lon, -74);
|
||||
assert.deepEqual(parseCoordinateQuery('74w, 40n'), {
|
||||
lat: 40,
|
||||
lon: -74,
|
||||
label: '40.0000° N, 74.0000° W',
|
||||
});
|
||||
assert.deepEqual(parseCoordinateQuery('40° N, 74° W')?.lat, 40);
|
||||
// One letter is enough: it fixes its own axis, the other takes what is left.
|
||||
assert.deepEqual(parseCoordinateQuery('40 N, -74')?.lon, -74);
|
||||
assert.deepEqual(parseCoordinateQuery('-74, 40 N'), {
|
||||
lat: 40,
|
||||
lon: -74,
|
||||
label: '40.0000° N, 74.0000° W',
|
||||
});
|
||||
});
|
||||
|
||||
test('malformed and ambiguous coordinates are refused, never guessed', () => {
|
||||
for (const query of [
|
||||
// The reviewer's case: trailing text must not be discarded.
|
||||
'12junk, 34oops',
|
||||
'12junk,34',
|
||||
'43.1731, -79.0384x',
|
||||
'abc, def',
|
||||
'Paris',
|
||||
'New York, NY',
|
||||
'',
|
||||
' ',
|
||||
',',
|
||||
'40',
|
||||
'40,',
|
||||
', 74',
|
||||
'40, 74, 12',
|
||||
'40.0.0, 74',
|
||||
'1e3, 5',
|
||||
'0x40, 74',
|
||||
'40 74 12',
|
||||
// Two letters naming the same axis leaves the other axis unstated.
|
||||
'N 40, N 74',
|
||||
'E 40, W 74',
|
||||
'S 40, 40 S',
|
||||
// A sign and a letter both claim the direction.
|
||||
'-40N, 74W',
|
||||
'N -40, W 74',
|
||||
// Two letters on one component.
|
||||
'N40W, 74',
|
||||
// Out of range.
|
||||
'91, 0',
|
||||
'-90.1, 0',
|
||||
'0, 181',
|
||||
'0, -180.5',
|
||||
'N 100, W 74',
|
||||
// Degrees/minutes/seconds is out of scope and must fall through, not
|
||||
// be read as a decimal pair.
|
||||
'40°26\'46"N, 79°58\'56"W',
|
||||
'40 26 46, 79 58 56',
|
||||
// A grid reference is out of scope too.
|
||||
'33UXP0500444998',
|
||||
]) {
|
||||
assert.equal(
|
||||
parseCoordinateQuery(query),
|
||||
null,
|
||||
`${JSON.stringify(query)} must be refused`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test('non-strings are refused without throwing', () => {
|
||||
for (const query of [null, undefined, 42, {}, [], ['40', '74']])
|
||||
assert.equal(parseCoordinateQuery(query), null);
|
||||
});
|
||||
|
||||
test('the label reads the way a coordinate is written', () => {
|
||||
assert.equal(
|
||||
formatCoordinateLabel(43.1731, -79.0384),
|
||||
'43.1731° N, 79.0384° W',
|
||||
);
|
||||
assert.equal(
|
||||
formatCoordinateLabel(-33.8568, 151.2153),
|
||||
'33.8568° S, 151.2153° E',
|
||||
);
|
||||
assert.equal(formatCoordinateLabel(0, 0), '0.0000° N, 0.0000° E');
|
||||
});
|
||||
|
||||
test('the poles and the dateline are inside the accepted range', () => {
|
||||
assert.deepEqual(parseCoordinateQuery('90, 180')?.lat, 90);
|
||||
assert.deepEqual(parseCoordinateQuery('-90, -180')?.lon, -180);
|
||||
});
|
||||
Reference in new issue
Block a user