import { handleFiles } from "../src/fileLoader.js"; import { appState } from "../src/state.js"; import { initDB } from "../src/db.js"; const resultsEl = document.getElementById('results'); function test(description, testFunction) { // Simple async test runner wrapper (async () => { try { await testFunction(); console.log(`✅ PASS: ${description}`); resultsEl.innerHTML += `

PASS: ${description}

`; } catch (error) { console.error(`❌ FAIL: ${description}`, error); resultsEl.innerHTML += `

FAIL: ${description}

${error.stack || error}

`; } })(); } // --- Setup & Mocks --- // Initialize DB for tests async function setupTestEnvironment() { return new Promise((resolve) => { initDB(() => { console.log("Test DB initialized"); resolve(); }); }); } // Mock URL.createObjectURL URL.createObjectURL = (blob) => { return "blob:mock-url-" + Math.random(); }; URL.revokeObjectURL = () => {}; // Mock Worker class MockWorker { constructor(scriptUrl) { console.log("MockWorker created for:", scriptUrl); this.onmessage = null; } postMessage(msg) { console.log("MockWorker received message:", msg); // Simulate success response if (this.onmessage) { // Simulate parsing delay setTimeout(() => { this.onmessage({ data: { type: 'complete', data: { // Correct mock parsed data structure radarFrames: [ { timestamp: 1000, pointCloud: [], tracks: [] } ], tracks: [] } } }); }, 50); } } terminate() {} } window.Worker = MockWorker; // Mock p5 window.p5 = class MockP5 { constructor(sketch, node) { console.log("MockP5 created"); sketch(this); } createCanvas() { return { parent: () => {} }; } background() {} fill() {} stroke() {} rect() {} ellipse() {} push() {} pop() {} translate() {} scale() {} frameRate() {} noLoop() {} loop() {} redraw() {} resizeCanvas() {} select() { return { html: () => {}, position: () => {}, style: () => {} }; } createGraphics() { return { background: () => {}, clear: () => {}, image: () => {} }; } image() {} text() {} textSize() {} textAlign() {} noStroke() {} color() { return {}; } textFont() {} drawSnrLegendToBuffer() {} }; // --- Tests --- (async function runTests() { await setupTestEnvironment(); test("fileLoader.js: handleFiles should parse JSON and update appState", async () => { // 1. Setup appState.vizData = null; const mockJsonFile = new File(['{"some": "json"}'], "test_data.json", { type: "application/json" }); // 2. Execution handleFiles([mockJsonFile]); // 3. Verification (Wait for async operations) // We need to wait long enough for DB save + Worker + Processing await new Promise(resolve => setTimeout(resolve, 500)); if (!appState.vizData) { throw new Error("appState.vizData was not populated after loading JSON."); } if (appState.jsonFilename !== "test_data.json") { throw new Error(`Expected jsonFilename to be 'test_data.json', got '${appState.jsonFilename}'`); } }); test("fileLoader.js: handleFiles should handle video loading (simulated)", async () => { // 1. Setup appState.vizData = null; appState.videoFilename = ""; const videoPlayer = document.getElementById('video-player'); // Use MutationObserver to watch for src changes const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.type === "attributes" && mutation.attributeName === "src") { console.log("Video src changed, triggering events..."); // Trigger events asynchronously to simulate browser behavior setTimeout(() => { videoPlayer.dispatchEvent(new Event('loadedmetadata')); videoPlayer.dispatchEvent(new Event('canplaythrough')); }, 50); } }); }); observer.observe(videoPlayer, { attributes: true }); const mockVideoFile = new File(['fake video content'], "test_video.mp4", { type: "video/mp4" }); // 2. Execute handleFiles([mockVideoFile]); // 3. Verify await new Promise(resolve => setTimeout(resolve, 500)); // Wait for events observer.disconnect(); // Cleanup if (appState.videoFilename !== "test_video.mp4") { throw new Error(`Expected videoFilename to be 'test_video.mp4', got '${appState.videoFilename}'`); } }); })();