Files
gods-eye-view/src/tooling/viteBuild.test.mjs
T
Claude 56586a234b feat(vcam): use a phone on the network as a virtual camera
SCENES > VCAM pairs a phone through a QR code and turns it into a
handheld camera, after Unreal's Live Link VCAM and Blender's VirtuCamera:

- Android Chrome tracks 6DoF through WebXR immersive-ar; iPhone Safari,
  which has no WebXR AR, tracks rotation through DeviceOrientation, and
  thumb sticks dolly, truck, crane and pan.
- A motion scale (1:1 walk to 1:10000 orbit), smoothing, height and
  horizon locks, hold/clutch and recenter, none of which make the camera
  jump. Focal length and scale-aware depth of field with tap-to-focus.
- The phone shows the app's render as a monitor (newest-frame JPEG pull).
- REC records a take as a version-7 track shot in the selected scene.
- The rig claims the camera through the navigation seam (Cockpit refuses
  it) and holds on any other navigation, scene run or globe input.

Pairing never exposes the app: a loopback-only session request starts a
separate HTTPS listener (VCAM_PORT, default 4174) that serves only the
static phone page and a token-paired relay, and stops after the last
session. Its certificate comes from a local CA built with node:crypto, which
an iPhone can trust once; without it the phone falls back from WebSocket to
HTTPS requests, which iOS allows past a certificate warning.

scripts/qa-vcam.mjs drives it end to end: the real phone page over the
HTTPS fallback, a scripted 6DoF phone, a recorded and replayed take, depth
of field and camera handoff.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015H1iLusTzWpVKitGic2AW8
2026-10-19 04:03:02 +00:00

251 lines
10 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import { BROWSER_CSP, createBrowserViteConfig } from '../../build/vite.js';
import standaloneConfig, * as compatibility from '../../vite.config.js';
import * as providers from '../../server/providers/local.js';
test('explicit build inputs preserve browser-only defines, plugin order and loopback protections', () => {
const plugin = { name: 'fixture-provider' };
const config = createBrowserViteConfig({
plugins: [plugin],
googleApiKey: 'browser-fixture',
cesiumToken: 'ion-fixture',
});
// The Host check runs before every other plugin's middleware.
assert.equal(config.plugins[0].name, 'host-check');
assert.equal(config.plugins[0].enforce, 'pre');
assert.equal(config.plugins[3], plugin);
assert.equal(config.server.host, 'localhost');
assert.equal(config.server.port, 4173);
assert.deepEqual(config.server.allowedHosts, ['localhost', '127.0.0.1']);
assert.ok(config.server.fs.deny.includes('**/ENVIRONMENT'));
assert.ok(config.server.fs.deny.includes('.env.*'));
assert.equal(config.server.headers['X-Frame-Options'], 'DENY');
assert.equal(config.server.headers['X-Content-Type-Options'], 'nosniff');
const csp = config.server.headers['Content-Security-Policy'];
assert.equal(csp, BROWSER_CSP);
for (const directive of [
"script-src 'self' 'unsafe-eval' blob:",
"object-src 'none'",
"base-uri 'self'",
"frame-ancestors 'none'",
]) {
assert.ok(csp.includes(directive), directive);
}
assert.ok(!csp.includes("script-src 'self' 'unsafe-inline'"));
assert.deepEqual(config.preview.headers, config.server.headers);
assert.deepEqual(config.define, {
'import.meta.env.GOOGLE_MAPS_API_KEY': '"browser-fixture"',
'import.meta.env.CESIUM_ION_TOKEN': '"ion-fixture"',
'import.meta.env.MAPILLARY_CLIENT_TOKEN': '""',
});
assert.equal(
createBrowserViteConfig({ mapillaryToken: 'MLY|1|abc' }).define[
'import.meta.env.MAPILLARY_CLIENT_TOKEN'
],
'"MLY|1|abc"',
);
// A wildcard bind keeps the Host-header check; LAN names are explicit.
for (const host of ['0.0.0.0', '::'])
assert.deepEqual(
createBrowserViteConfig({ host, port: '4800' }).server.allowedHosts,
['localhost', '127.0.0.1'],
);
assert.deepEqual(
createBrowserViteConfig({
host: '0.0.0.0',
allowedHosts: ['localhost', '127.0.0.1', 'globe.lan'],
}).server.allowedHosts,
['localhost', '127.0.0.1', 'globe.lan'],
);
assert.equal(
createBrowserViteConfig({ host: '::', port: '4800' }).server.port,
4800,
);
});
test('build helper does not discover environment values or construct local providers', () => {
const before = process.env.GOOGLE_MAPS_API_KEY;
process.env.GOOGLE_MAPS_API_KEY = 'environment-fixture';
try {
const config = createBrowserViteConfig();
assert.equal(
config.define['import.meta.env.GOOGLE_MAPS_API_KEY'],
undefined,
);
assert.deepEqual(
config.plugins.slice(3).map((plugin) => plugin.name),
['embed-framing', 'panel-build'],
);
} finally {
if (before === undefined) delete process.env.GOOGLE_MAPS_API_KEY;
else process.env.GOOGLE_MAPS_API_KEY = before;
}
});
test('root config retains existing named exports and standalone provider order', () => {
for (const [name, value] of Object.entries(providers))
assert.equal(compatibility[name], value, name);
const config = standaloneConfig({ mode: 'test' });
assert.deepEqual(
config.plugins.slice(3, -6).map((plugin) => plugin.name),
providers.localProviderPlugins().map((plugin) => plugin.name),
);
assert.equal(config.plugins.at(-7).name, 'gev-key-setup');
// The local MCP route follows every provider and precedes the API fallback.
assert.equal(config.plugins.at(-6).name, 'local-mcp');
// The phone camera's desktop routes also answer before the API fallback.
assert.equal(config.plugins.at(-5).name, 'gev-vcam');
assert.equal(config.plugins.at(-4).name, 'api-not-found');
// Config-only, so it sits after the provider slice rather than in it.
assert.equal(config.plugins.at(-3).name, 'gev-unwatched-runtime-dirs');
assert.equal(config.plugins.at(-2).name, 'embed-framing');
assert.equal(config.plugins.at(-1).name, 'panel-build');
});
test('directories the server writes while it runs are kept out of the dev watcher', () => {
// Providers write cache files and logs here while the app runs; none of it is
// source, so the dev watcher has no reason to stat it.
const config = standaloneConfig({ mode: 'test' });
const plugin = config.plugins.find(
({ name }) => name === 'gev-unwatched-runtime-dirs',
);
// Dev only: preview and build have no watcher.
assert.equal(plugin.apply, 'serve');
assert.deepEqual(plugin.config().server.watch.ignored, [
'**/.gev-cache/**',
'**/.gev-logs/**',
]);
});
test('build export resolves in Node and has no browser fallback', async () => {
const exported = await import('gods-eye-view/build/vite');
assert.equal(exported.createBrowserViteConfig, createBrowserViteConfig);
const pkg = JSON.parse(
readFileSync(new URL('../../package.json', import.meta.url)),
);
assert.deepEqual(pkg.exports['./build/vite'], { node: './build/vite.js' });
});
test('only embed-mode documents may be framed, and only by the allowed ancestors', async () => {
const { embedFramingPlugin, isEmbedDocumentRequest } =
await import('../../build/embed-framing.js');
assert.equal(isEmbedDocumentRequest('/?embed=1'), true);
assert.equal(isEmbedDocumentRequest('/index.html?embed=1#v=2'), true);
assert.equal(isEmbedDocumentRequest('/?embed=0'), false);
assert.equal(isEmbedDocumentRequest('/api/x?embed=1'), false);
assert.equal(isEmbedDocumentRequest('/src/main.js?embed=1'), false);
let middleware;
embedFramingPlugin({ ancestors: 'https://a.example' }).configureServer({
middlewares: { use: (handler) => (middleware = handler) },
});
const response = () => {
const headers = new Map();
return {
headers,
setHeader(name, value) {
headers.set(name.toLowerCase(), value);
return this;
},
};
};
const embedded = response();
middleware({ url: '/?embed=1' }, embedded, () => {});
// The server's protections, written later at send time.
embedded.setHeader('X-Frame-Options', 'DENY');
embedded.setHeader('Content-Security-Policy', "frame-ancestors 'none'");
embedded.setHeader('Content-Type', 'text/html');
assert.deepEqual(Object.fromEntries(embedded.headers), {
'content-security-policy': 'frame-ancestors https://a.example',
'content-type': 'text/html',
});
let open;
embedFramingPlugin({ ancestors: '*' }).configureServer({
middlewares: { use: (handler) => (open = handler) },
});
const anywhere = response();
open({ url: '/?embed=1' }, anywhere, () => {});
anywhere.setHeader('X-Frame-Options', 'DENY');
anywhere.setHeader('Content-Security-Policy', "frame-ancestors 'none'");
assert.deepEqual(Object.fromEntries(anywhere.headers), {});
// A full policy keeps its other directives; only the framing rule changes.
const full = "default-src 'self'; script-src 'self'; frame-ancestors 'none'";
const embeddedFull = response();
middleware({ url: '/?embed=1' }, embeddedFull, () => {});
embeddedFull.setHeader('Content-Security-Policy', full);
assert.equal(
embeddedFull.headers.get('content-security-policy'),
"default-src 'self'; script-src 'self'; frame-ancestors https://a.example",
);
const anywhereFull = response();
open({ url: '/?embed=1' }, anywhereFull, () => {});
anywhereFull.setHeader('Content-Security-Policy', full);
assert.equal(
anywhereFull.headers.get('content-security-policy'),
"default-src 'self'; script-src 'self'",
);
const normal = response();
middleware({ url: '/' }, normal, () => {});
normal.setHeader('X-Frame-Options', 'DENY');
normal.setHeader('Content-Security-Policy', "frame-ancestors 'none'");
assert.deepEqual(Object.fromEntries(normal.headers), {
'x-frame-options': 'DENY',
'content-security-policy': "frame-ancestors 'none'",
});
// Unset, no page may frame even embed-mode documents.
for (const ancestors of ['', ' ']) {
const plugin = embedFramingPlugin({ ancestors });
assert.equal(plugin.name, 'embed-framing');
assert.equal(plugin.configureServer, undefined);
assert.equal(plugin.configurePreviewServer, undefined);
}
});
test('the CSP admits the event media embeds and the Maps JavaScript API, and no other script origin', async () => {
const { embeddedMediaFrameUrl, resolveEmbeddedMediaSource } =
await import('../../src/data/bhoteKoshiEmbeddedMedia.js');
const directive = (name) =>
BROWSER_CSP.split(';')
.map((part) => part.trim())
.find((part) => part.startsWith(`${name} `))
?.split(/\s+/)
.slice(1) ?? [];
const scripts = directive('script-src');
const frames = directive('frame-src');
// The player API, the Facebook SDK and X's widget script.
for (const origin of [
'https://www.youtube.com',
'https://connect.facebook.net',
'https://platform.twitter.com',
])
assert.ok(scripts.includes(origin), origin);
// Only those three and Google Street View's Maps JavaScript API, never a
// wildcard or a scheme.
assert.deepEqual(
scripts.filter(
(source) => source.startsWith('http') || source === 'https:',
),
[
'https://www.youtube.com',
'https://connect.facebook.net',
'https://platform.twitter.com',
'https://maps.googleapis.com',
],
);
assert.ok(!scripts.some((source) => source.includes('*')));
// Every frame the event builds for a YouTube or Facebook source is allowed.
for (const link of [
'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
'https://youtu.be/dQw4w9WgXcQ',
'https://www.facebook.com/facebook/videos/10153231379946729/',
]) {
const source = resolveEmbeddedMediaSource(link);
assert.ok(source, link);
const origin = new URL(embeddedMediaFrameUrl(source, {})).origin;
assert.ok(frames.includes(origin), `${link} -> ${origin}`);
}
// X posts load in X's own frames.
assert.ok(frames.includes('https://platform.twitter.com'));
});