fixed remaining test issues, updated live.js to meet requirements

This commit is contained in:
Chris Phipps
2026-05-30 20:04:46 +00:00
committed by mc-bot
parent e72031d35d
commit 47d96fcdb8
3 changed files with 302 additions and 238 deletions
+282 -212
View File
File diff suppressed because it is too large Load Diff
+11 -17
View File
@@ -23,15 +23,15 @@ test('Canvas array, flag, and loop are implemented', () => {
test('Leaflet integration and resizing handles DPR correctly', () => {
assert.ok(src.includes('map.latLngToLayerPoint'), 'Map de-sync regression: Canvas not using LayerPoints for CSS transform sync');
assert.ok(src.includes('animCtx.setTransform(dpr, 0, 0, dpr, 0, 0)'), 'HiDPI regression: resizeAnimCanvas does not reset transform matrix');
assert.ok(src.includes('matchMedia'), 'Monitor drag regression: DPR listener missing');
assert.ok(src.includes('matchMedia(`(resolution'), 'Monitor drag regression: DPR listener missing');
});
console.log('\n=== Battery / GPU Optimization (State Machine) ===');
test('Engine gracefully sleeps and wakes', () => {
assert.ok(src.includes('isAnimating = false'), 'Battery drain regression: Engine does not explicitly sleep on empty queue');
assert.ok(src.includes('window._wakeCanvasEngine'), 'Wake controller missing: _wakeCanvasEngine not exposed');
assert.ok(src.includes('anim.lastTick = null'), 'Time-jump regression: Engine does not nullify tick on pause');
assert.ok(src.includes('_liveTestSeams.wake'), 'Wake controller missing: wake not exposed on _liveTestSeams');
assert.ok(src.includes('.lastTick = null'), 'Time-jump regression: Engine does not nullify tick on pause');
});
console.log('\n=== Concurrency cap ===');
@@ -64,7 +64,7 @@ test('Destroy function cleanly halts canvas engine', () => {
test('Entry points guard against destroyed map', () => {
const lineStart = src.indexOf('function drawAnimatedLine(');
const lineBody = src.substring(lineStart, lineStart + 150);
const lineBody = src.substring(lineStart, lineStart + 250);
assert.ok(lineBody.includes('!map || !animCtx'), 'Race condition: drawAnimatedLine missing map/ctx null guard');
});
@@ -74,14 +74,14 @@ test('no setInterval remains in animation hot path', () => {
// The only acceptable setIntervals are the UI ones (timeline, clock, prune, rate counter)
// Count total setInterval occurrences
const matches = src.match(/setInterval\(/g) || [];
// Count known OK ones: _timelineRefreshInterval, _lcdClockInterval, _pruneInterval, _rateCounterInterval
const okPatterns = ['_timelineRefreshInterval', '_lcdClockInterval', '_pruneInterval', '_rateCounterInterval'];
// Count known OK ones: _timelineRefreshInterval, _lcdClockInterval, _pruneInterval, _rateCounterInterval, _affinityInterval
const okPatterns = ['_timelineRefreshInterval', '_lcdClockInterval', '_pruneInterval', '_rateCounterInterval', '_affinityInterval'];
let okCount = 0;
for (const p of okPatterns) {
if (src.includes(p + ' = setInterval') || src.includes(p + '= setInterval')) okCount++;
}
// Allow some non-animation setIntervals (the 4 UI ones above)
assert.ok(matches.length <= okCount + 1,
assert.ok(matches.length <= okCount + 1,
`Found ${matches.length} setInterval calls, expected at most ${okCount + 1} (non-animation). Some animation setIntervals may remain.`);
});
@@ -111,16 +111,10 @@ test2('animatePath fadeOut() has null guard', () => {
assert.ok(fadeOutBody.includes('!animLayer || !pathsLayer'), 'fadeOut() missing animLayer/pathsLayer null guard');
});
test2('drawAnimatedLine animateLine() has null guard', () => {
const lineStart = src2.indexOf('function animateLine(now)');
const lineBody = src2.substring(lineStart, lineStart + 200);
assert.ok(lineBody.includes('!animLayer || !pathsLayer'), 'animateLine() missing animLayer/pathsLayer null guard');
});
test2('drawAnimatedLine animateFade() has null guard', () => {
const fadeStart = src2.indexOf('function animateFade(now)');
const fadeBody = src2.substring(fadeStart, fadeStart + 200);
assert.ok(fadeBody.includes('!pathsLayer'), 'animateFade() missing pathsLayer null guard');
test2('drawAnimatedLine renderFades() has null guard', () => {
const fadeStart = src2.indexOf('function renderFades(now)');
const fadeBody = src2.substring(fadeStart, fadeStart + 300);
assert.ok(fadeBody.includes('!pathsLayer'), 'renderFades() missing pathsLayer null guard');
});
test2('pulseNode animatePulse() has null guard', () => {
+9 -9
View File
@@ -3,7 +3,7 @@ const { test, expect } = require('@playwright/test');
test.describe('Live Map Canvas Animation Engine', () => {
test('canvas initializes and animations drain correctly', async ({ page }) => {
// 1. Load the map route
await page.goto('/#/map');
await page.goto('/#/live');
// Ensure the map container has loaded
const mapContainer = page.locator('#liveMap');
@@ -19,15 +19,15 @@ test.describe('Live Map Canvas Animation Engine', () => {
await page.evaluate((count) => {
// Ensure the VCR speed is at standard 1x for predictable timing
if (window._liveVcrSetMode) window._liveVcrSetMode('LIVE');
for (let i = 0; i < count; i++) {
window._liveDrawAnimatedLine(
[37.4, -122.0],
[37.5, -122.1],
'#00ff00',
null,
null,
'00AA',
[37.4, -122.0],
[37.5, -122.1],
'#00ff00',
null,
null,
'00AA',
'test-hash-' + i
);
}
@@ -48,7 +48,7 @@ test.describe('Live Map Canvas Animation Engine', () => {
return await page.evaluate(() => window._liveTestSeams.getAnimCount());
}, {
message: 'activeAnimations did not drain to 0 within 2x duration',
timeout: 1500,
timeout: 1500,
}).toBe(0);
// 5. Assert the engine gracefully went back to sleep