mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 02:44:02 +00:00
- The chip reads GOOGLE STREET VIEW (and its caption link likewise). - Providers declare the imagery filters they honour (`filters`, default pano + since). Street View declares none: every panorama is 360° and it draws no coverage to thin, so its lookups ignore the filters and the panel hides IMAGERY and SINCE while it is the only lit provider. - The legend lists only providers that draw coverage lines, with Selected only beside one: Street View alone shows no legend. - Providers may pick their on-globe marker (`marker`); Street View's is a Google-blue field-of-view cone from a white-ringed dot, in place of GEV's amber pin, and switches back for a Mapillary photo. Co-Authored-By: Claude Opus 5.5 <[email protected]>
121 lines
3.4 KiB
JavaScript
121 lines
3.4 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import { filtersOf, requiresKeyIdFor, validateProviders } from './registry.js';
|
|
|
|
const def = (overrides = {}) => ({
|
|
id: 'mapillary',
|
|
name: 'Mapillary',
|
|
label: 'MAPILLARY',
|
|
requiresKeyId: 'mapillary',
|
|
pickPrefix: 'mly:',
|
|
colors: { coverage: '#05cb63' },
|
|
credit: { html: 'Mapillary' },
|
|
create: () => ({}),
|
|
...overrides,
|
|
});
|
|
|
|
test('a valid list is frozen in registration order', () => {
|
|
const list = validateProviders([
|
|
def(),
|
|
def({ id: 'panoramax', pickPrefix: 'pnx:', requiresKeyId: null }),
|
|
]);
|
|
assert.ok(Object.isFrozen(list));
|
|
assert.deepEqual(
|
|
list.map((p) => p.id),
|
|
['mapillary', 'panoramax'],
|
|
);
|
|
});
|
|
|
|
test('an empty provider list is valid and has no key requirement', () => {
|
|
assert.deepEqual(validateProviders([]), []);
|
|
assert.ok(Object.isFrozen(validateProviders([])));
|
|
assert.equal(requiresKeyIdFor([]), null);
|
|
});
|
|
|
|
test('non-arrays, duplicate ids and malformed ids are rejected', () => {
|
|
assert.throws(() => validateProviders(null), /array/);
|
|
assert.throws(() => validateProviders([def(), def()]), /Duplicate/);
|
|
assert.throws(() => validateProviders([def({ id: 'Bad Id' })]), /slug/);
|
|
});
|
|
|
|
test('every required field is checked by name', () => {
|
|
for (const key of [
|
|
'name',
|
|
'label',
|
|
'pickPrefix',
|
|
'colors',
|
|
'credit',
|
|
'create',
|
|
])
|
|
assert.throws(
|
|
() => validateProviders([def({ [key]: undefined })]),
|
|
new RegExp(`lacks ${key}`),
|
|
key,
|
|
);
|
|
assert.throws(() => validateProviders([def({ create: 1 })]), /create/);
|
|
assert.throws(() => validateProviders([def({ credit: {} })]), /credit/);
|
|
assert.throws(
|
|
() => validateProviders([def({ colors: { pano: '#f0f' } })]),
|
|
/coverage colour/,
|
|
);
|
|
assert.throws(
|
|
() => validateProviders([def({ pickPrefix: '' })]),
|
|
/pick prefix/,
|
|
);
|
|
});
|
|
|
|
test('overlapping pick prefixes are rejected either way round', () => {
|
|
assert.throws(
|
|
() => validateProviders([def(), def({ id: 'other', pickPrefix: 'mly:x' })]),
|
|
/overlaps/,
|
|
);
|
|
assert.throws(
|
|
() =>
|
|
validateProviders([def({ pickPrefix: 'mly:x' }), def({ id: 'other' })]),
|
|
/overlaps/,
|
|
);
|
|
assert.doesNotThrow(() =>
|
|
validateProviders([def(), def({ id: 'other', pickPrefix: 'ml:' })]),
|
|
);
|
|
});
|
|
|
|
test('requiresKeyIdFor is the shared key, or null once providers differ', () => {
|
|
assert.equal(requiresKeyIdFor([def()]), 'mapillary');
|
|
assert.equal(
|
|
requiresKeyIdFor([def(), def({ id: 'b', pickPrefix: 'b:' })]),
|
|
'mapillary',
|
|
);
|
|
assert.equal(
|
|
requiresKeyIdFor([
|
|
def(),
|
|
def({ id: 'b', pickPrefix: 'b:', requiresKeyId: null }),
|
|
]),
|
|
null,
|
|
);
|
|
assert.equal(
|
|
requiresKeyIdFor([
|
|
def(),
|
|
def({ id: 'b', pickPrefix: 'b:', requiresKeyId: 'google-maps' }),
|
|
]),
|
|
null,
|
|
);
|
|
assert.equal(requiresKeyIdFor([def({ requiresKeyId: null })]), null);
|
|
});
|
|
|
|
test('a provider may narrow the filters it honours and pick a view-cone marker', () => {
|
|
assert.deepEqual(filtersOf(def()), ['pano', 'since'], 'both by default');
|
|
const narrowed = def({
|
|
filters: [],
|
|
marker: { kind: 'view-cone', color: '#4285f4' },
|
|
});
|
|
assert.deepEqual(filtersOf(validateProviders([narrowed])[0]), []);
|
|
assert.throws(
|
|
() => validateProviders([def({ filters: ['colour'] })]),
|
|
/filters must list pano or since/,
|
|
);
|
|
assert.throws(
|
|
() => validateProviders([def({ marker: { kind: 'pegman' } })]),
|
|
/marker must be/,
|
|
);
|
|
});
|