feat: add weekly curriculum cover image upload and display
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const vm = require('node:vm');
|
||||
|
||||
const html = fs.readFileSync(path.join(__dirname, '../src/renderer/public/slam-viewer/index.html'), 'utf8');
|
||||
const source = html.slice(html.indexOf('function hasLiveCameraState()'), html.indexOf("cameraPreview?.addEventListener('load'"));
|
||||
let now = 10000;
|
||||
let requests = 0;
|
||||
let ok = true;
|
||||
let visible = false;
|
||||
let afterBlob = () => {};
|
||||
const context = vm.createContext({
|
||||
ENABLE_CAMERA_PREVIEW: true,
|
||||
cameraFrameRequestInFlight: false,
|
||||
cameraFrameRetryAt: 0,
|
||||
cameraFrameObjectUrl: null,
|
||||
cameraPreview: {},
|
||||
latestSlamState: null,
|
||||
latestSlamStateReceivedAt: now,
|
||||
document: { hidden: false },
|
||||
Date: { now: () => now },
|
||||
BACKEND_URL: 'http://localhost:8765',
|
||||
AbortSignal,
|
||||
URL: { createObjectURL: () => 'blob:frame', revokeObjectURL() {} },
|
||||
setCameraPreviewAvailable(value) { visible = value; },
|
||||
async fetch() {
|
||||
requests++;
|
||||
return { ok, async blob() { afterBlob(); return {}; } };
|
||||
},
|
||||
});
|
||||
vm.runInContext(source, context);
|
||||
const refresh = () => context.refreshCameraFrame();
|
||||
const available = (value) => {
|
||||
context.latestSlamState = { topic_status: { camera_image: { available: value } } };
|
||||
context.latestSlamStateReceivedAt = now;
|
||||
};
|
||||
|
||||
(async () => {
|
||||
await refresh();
|
||||
available(false);
|
||||
await refresh();
|
||||
assert.equal(requests, 0, 'Absent camera must not fetch frames');
|
||||
available(true);
|
||||
await refresh();
|
||||
assert.equal(requests, 1);
|
||||
assert.equal(context.cameraPreview.src, 'blob:frame');
|
||||
now += 3001;
|
||||
await refresh();
|
||||
assert.equal(requests, 1, 'Stale websocket state must stop polling');
|
||||
assert.equal(visible, false);
|
||||
available(true);
|
||||
ok = false;
|
||||
await refresh();
|
||||
await refresh();
|
||||
assert.equal(requests, 2, 'HTTP errors must back off');
|
||||
now += 5000;
|
||||
available(true);
|
||||
ok = true;
|
||||
afterBlob = () => available(false);
|
||||
context.cameraPreview.src = '';
|
||||
await refresh();
|
||||
assert.equal(context.cameraPreview.src, '', 'Late responses must not revive a disconnected camera');
|
||||
assert.equal(context.cameraFrameRequestInFlight, false);
|
||||
afterBlob = () => {};
|
||||
available(true);
|
||||
await refresh();
|
||||
assert.equal(context.cameraPreview.src, 'blob:frame', 'Camera reconnect must resume frames');
|
||||
console.log('camera preview polling tests passed');
|
||||
})().catch((error) => { console.error(error); process.exitCode = 1; });
|
||||
Reference in New Issue
Block a user