mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 02:14:01 +00:00
Seven contributed CCTV camera packs (Ontario 511, Fintraffic Finland, DriveBC, TxDOT Texas, Estonia Tallinn + Tarktee, Warendorf, Live Traffic NSW) on a fair per-pack catalog cap; semantic camera labels; monitor planes lifted clear of the terrain from a precomputed, bundled ground-height dataset. Default catalog 800 → 3,446 cameras. Full context in PR #433. Co-authored-by: sendmebits <[email protected]> Co-authored-by: avocadoAgent <[email protected]> Co-authored-by: Alex Harvey <[email protected]> Co-authored-by: Jason Meredith <[email protected]> Co-authored-by: Daniel Smith <[email protected]> Co-authored-by: Vladimir Sobolev <[email protected]> Co-authored-by: Matthias Schneider <[email protected]> Co-authored-by: Cyber Knight <[email protected]> Co-authored-by: NovaSoft Australia <[email protected]>
197 lines
6.1 KiB
JavaScript
197 lines
6.1 KiB
JavaScript
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import {
|
|
loadNswSourcesFromOpenData,
|
|
nswCameraLabel,
|
|
nswCameraToSource,
|
|
} from '../../server/providers/cctv/sources.js';
|
|
import {
|
|
cctvUpstreamUserAgent,
|
|
fetchCctvImageFromUpstream,
|
|
} from '../../server/providers/cctv/media.js';
|
|
import {
|
|
NSW_CAMERAS_URL,
|
|
NSW_IMAGE_USER_AGENT,
|
|
} from '../../server/providers/cctv/constants.js';
|
|
|
|
const feature = (overrides = {}, props = {}) => ({
|
|
type: 'Feature',
|
|
id: '5_ways_miranda',
|
|
geometry: { type: 'Point', coordinates: [151.1036, -34.0337] },
|
|
properties: {
|
|
region: 'SYD_SOUTH',
|
|
title: '5 Ways (Miranda)',
|
|
view: '5 Ways at The Boulevarde looking west towards Sutherland.',
|
|
direction: 'W',
|
|
href: 'https://webcams.transport.nsw.gov.au/livetraffic-webcams/cameras/5_ways_miranda.jpeg',
|
|
...props,
|
|
},
|
|
...overrides,
|
|
});
|
|
|
|
test('NSW label prefers the view sentence and falls back to the title for works notices', () => {
|
|
assert.equal(
|
|
nswCameraLabel({ title: '5 Ways (Miranda)', view: '5 Ways looking west.' }),
|
|
'5 Ways looking west.',
|
|
);
|
|
assert.equal(
|
|
nswCameraLabel({ title: 'Victoria Pass', view: 'x'.repeat(200) }),
|
|
'Victoria Pass',
|
|
);
|
|
assert.equal(nswCameraLabel({ title: 'T', view: 'line one\nline two' }), 'T');
|
|
assert.equal(nswCameraLabel({}), '');
|
|
});
|
|
|
|
test('NSW feature maps to a source with a compass heading and a pinned image host', () => {
|
|
const source = nswCameraToSource(feature({}, { direction: 'N-E' }));
|
|
assert.equal(source.id, 'nsw-5_ways_miranda');
|
|
assert.equal(source.city, 'SYD SOUTH');
|
|
assert.equal(source.provider, 'Live Traffic NSW');
|
|
assert.equal(source.lat, -34.0337);
|
|
assert.equal(source.lon, 151.1036);
|
|
assert.equal(source.headingDeg, 45);
|
|
assert.equal(source.headingConfidence, 'high');
|
|
assert.equal(source.sourceKind, 'nsw-livetraffic');
|
|
assert.match(source.license, /CC BY 4.0/);
|
|
assert.equal(source.url, source.snapshotUrl);
|
|
});
|
|
|
|
test('NSW mapping rejects off-host images and unusable geometry', () => {
|
|
assert.equal(
|
|
nswCameraToSource(feature({}, { href: 'https://evil.example/x.jpeg' })),
|
|
null,
|
|
);
|
|
assert.equal(nswCameraToSource(feature({ geometry: null })), null);
|
|
assert.equal(nswCameraToSource(feature({ id: '' })), null);
|
|
const noBearing = nswCameraToSource(feature({}, { direction: '' }));
|
|
assert.equal(noBearing.headingConfidence, 'low');
|
|
assert.ok(Number.isFinite(noBearing.headingDeg));
|
|
});
|
|
|
|
test('NSW loader reads the keyless feed and caps around Sydney', async (t) => {
|
|
t.mock.method(console, 'log', () => {});
|
|
const requested = [];
|
|
t.mock.method(globalThis, 'fetch', async (url) => {
|
|
requested.push(String(url));
|
|
return Response.json({
|
|
type: 'FeatureCollection',
|
|
features: [
|
|
feature(),
|
|
feature({ id: 'other' }, { href: 'https://evil.example/x.jpeg' }),
|
|
],
|
|
});
|
|
});
|
|
const cameras = await loadNswSourcesFromOpenData();
|
|
assert.deepEqual(requested, [NSW_CAMERAS_URL]);
|
|
assert.deepEqual(
|
|
cameras.map((camera) => camera.id),
|
|
['nsw-5_ways_miranda'],
|
|
);
|
|
});
|
|
|
|
test('the browser User-Agent applies to the NSW image host only', async () => {
|
|
assert.equal(
|
|
cctvUpstreamUserAgent(
|
|
'https://webcams.transport.nsw.gov.au/livetraffic-webcams/cameras/x.jpeg',
|
|
),
|
|
NSW_IMAGE_USER_AGENT,
|
|
);
|
|
assert.equal(
|
|
cctvUpstreamUserAgent(
|
|
'https://webcams.transport.nsw.gov.au.evil.test/x.jpeg',
|
|
),
|
|
'gods-eye-view-cctv-proxy/1.0',
|
|
);
|
|
assert.equal(
|
|
cctvUpstreamUserAgent(
|
|
'https://example.test/webcams.transport.nsw.gov.au/x.jpeg',
|
|
),
|
|
'gods-eye-view-cctv-proxy/1.0',
|
|
);
|
|
assert.equal(
|
|
cctvUpstreamUserAgent('not a url'),
|
|
'gods-eye-view-cctv-proxy/1.0',
|
|
);
|
|
|
|
const seen = [];
|
|
await fetchCctvImageFromUpstream(
|
|
'https://cctv.austinmobility.io/image/1.jpg',
|
|
{
|
|
timeoutMs: 100,
|
|
fetchImpl: async (url, init) => {
|
|
seen.push(init.headers['User-Agent']);
|
|
return new Response(Buffer.from([0xff, 0xd8, 0xff]), {
|
|
headers: { 'Content-Type': 'image/jpeg' },
|
|
});
|
|
},
|
|
},
|
|
);
|
|
assert.deepEqual(seen, ['gods-eye-view-cctv-proxy/1.0']);
|
|
});
|
|
|
|
test('the frame path follows redirects within the host only', async () => {
|
|
const jpeg = () =>
|
|
new Response(Buffer.from([0xff, 0xd8, 0xff]), {
|
|
headers: { 'Content-Type': 'image/jpeg' },
|
|
});
|
|
const redirect = (location) =>
|
|
new Response(null, { status: 302, headers: { location } });
|
|
const start = 'https://cctv.austinmobility.io/image/1.jpg';
|
|
|
|
const sameHost = [];
|
|
const followed = await fetchCctvImageFromUpstream(start, {
|
|
timeoutMs: 100,
|
|
fetchImpl: async (url, init) => {
|
|
assert.equal(init.redirect, 'manual', 'the fetch itself never follows');
|
|
sameHost.push(url);
|
|
return sameHost.length === 1 ? redirect('/image/moved/1.jpg') : jpeg();
|
|
},
|
|
});
|
|
assert.equal(followed?.ok, true);
|
|
assert.deepEqual(sameHost, [
|
|
start,
|
|
'https://cctv.austinmobility.io/image/moved/1.jpg',
|
|
]);
|
|
|
|
const offHost = [];
|
|
const refused = await fetchCctvImageFromUpstream(start, {
|
|
timeoutMs: 100,
|
|
fetchImpl: async (url) => {
|
|
offHost.push(url);
|
|
return redirect('https://evil.example/1.jpg');
|
|
},
|
|
});
|
|
assert.equal(refused, null);
|
|
assert.deepEqual(offHost, [start], 'the off-host target is never requested');
|
|
|
|
// Same host on another port, a plaintext downgrade, and a protocol-relative
|
|
// other host are all a different origin and are refused.
|
|
for (const target of [
|
|
'https://cctv.austinmobility.io:8443/image/1.jpg',
|
|
'http://cctv.austinmobility.io/image/1.jpg',
|
|
'//evil.example/1.jpg',
|
|
]) {
|
|
const seen = [];
|
|
const result = await fetchCctvImageFromUpstream(start, {
|
|
timeoutMs: 100,
|
|
fetchImpl: async (url) => {
|
|
seen.push(url);
|
|
return redirect(target);
|
|
},
|
|
});
|
|
assert.equal(result, null, target);
|
|
assert.deepEqual(seen, [start], target);
|
|
}
|
|
|
|
let hops = 0;
|
|
const looped = await fetchCctvImageFromUpstream(start, {
|
|
timeoutMs: 100,
|
|
fetchImpl: async () => {
|
|
hops += 1;
|
|
return redirect('/image/again.jpg');
|
|
},
|
|
});
|
|
assert.equal(looped, null);
|
|
assert.equal(hops, 3, 'at most two redirect hops are followed');
|
|
});
|