diff --git a/frontend/src/simulation/AVRSimulator.ts b/frontend/src/simulation/AVRSimulator.ts index aade5671..2dca3252 100644 --- a/frontend/src/simulation/AVRSimulator.ts +++ b/frontend/src/simulation/AVRSimulator.ts @@ -508,12 +508,12 @@ export class AVRSimulator { this.running = true; console.log('Starting AVR simulation...'); - try { + // Browser-only debug hook. Guarded so node-side vitest runs don't + // ReferenceError on `window` and spam stderr. + if (typeof window !== 'undefined') { const dbg = (window as unknown as { __spiceDebug?: () => void }).__spiceDebug; if (typeof dbg === 'function') dbg(); else console.warn('[spice] __spiceDebug not attached — startSimulation never called'); - } catch (e) { - console.warn('[spice] debug dump failed', e); } // ATmega328p @ 16MHz diff --git a/frontend/src/utils/pinPositionCalculator.ts b/frontend/src/utils/pinPositionCalculator.ts index 09329cbf..704db6ce 100644 --- a/frontend/src/utils/pinPositionCalculator.ts +++ b/frontend/src/utils/pinPositionCalculator.ts @@ -37,14 +37,23 @@ export function calculatePinPosition( // Get the DOM element const element = document.getElementById(componentId); if (!element) { - console.warn(`[pinPositionCalculator] Component ${componentId} not found in DOM`); + // Don't spam the vitest log: in node-side tests there's no real + // DOM and this function gets called per-wire on every render + // (each one logs "Component foo not found in DOM"). In a browser + // the warning is actionable — a wire references a component that + // failed to mount. + if (import.meta.env.MODE !== 'test') { + console.warn(`[pinPositionCalculator] Component ${componentId} not found in DOM`); + } return null; } // Access the pinInfo property (all wokwi-elements expose this) const pinInfo = (element as any).pinInfo; if (!pinInfo || !Array.isArray(pinInfo)) { - console.warn(`[pinPositionCalculator] Component ${componentId} does not have pinInfo`); + if (import.meta.env.MODE !== 'test') { + console.warn(`[pinPositionCalculator] Component ${componentId} does not have pinInfo`); + } return null; } diff --git a/test/backend/unit/test_esp32_wifi_args.py b/test/backend/unit/test_esp32_wifi_args.py index 128aca58..82256209 100644 --- a/test/backend/unit/test_esp32_wifi_args.py +++ b/test/backend/unit/test_esp32_wifi_args.py @@ -101,8 +101,18 @@ class TestEspQemuManagerWifiArgs(unittest.TestCase): """start_instance should accept wifi_enabled and wifi_hostfwd_port.""" from app.services.esp_qemu_manager import EspQemuManager mgr = EspQemuManager() - # Should not raise - with patch('asyncio.create_task'): + + # start_instance calls `asyncio.create_task(self._boot(...))`. The + # `_boot(...)` call creates a coroutine BEFORE create_task sees it, + # so simply mocking create_task with no side-effect lets the + # coroutine leak and trigger a "coroutine never awaited" + # RuntimeWarning in the test log. Close the coroutine inside the + # mock to consume it cleanly. + def consume_coroutine(coro): + coro.close() + return MagicMock() + + with patch('asyncio.create_task', side_effect=consume_coroutine): mgr.start_instance( 'test-client', 'esp32', MagicMock(), firmware_b64=None,