codeburn/app/renderer/lib/pageVisibility.test.ts
iamtoruk e4bbcaaba7 fix(app): zero background work when hidden; currency applies instantly
Energy (field report: ~3x Chrome drain):
- polls skip entirely while the window is hidden/minimized, with one
  catch-up refresh on return when data is stale; visible-but-unfocused
  keeps polling (second-monitor case)
- all looping animations pause under html.page-hidden (the sidebar
  flame flicker was a perpetual compositor drain)
- default cadence 60s; an explicit stored choice is always honored

Currency (field report: set USD, still saw EUR):
- memo-served payloads re-applied their embedded stale currency; config
  mutations now purge the renderer memo and force-refresh, and a
  switching payload can never overwrite the applied currency
- USD default verified end to end

Measured: hidden window = 0 new CLI spawns over 5 cadences (was: full
polling forever). App 340/340, build + package green.
2026-07-16 18:41:28 -07:00

42 lines
1.6 KiB
TypeScript

// @vitest-environment jsdom
import { afterEach, describe, it, expect } from 'vitest'
import { installPageHiddenClass } from './pageVisibility'
function setVisibility(state: 'visible' | 'hidden') {
Object.defineProperty(document, 'visibilityState', { configurable: true, get: () => state })
}
afterEach(() => {
document.documentElement.classList.remove('page-hidden')
delete (document as unknown as { visibilityState?: unknown }).visibilityState
})
describe('installPageHiddenClass', () => {
it('toggles the page-hidden class on <html> as visibility changes, and stops after dispose', () => {
setVisibility('visible')
const dispose = installPageHiddenClass()
expect(document.documentElement.classList.contains('page-hidden')).toBe(false)
setVisibility('hidden')
document.dispatchEvent(new Event('visibilitychange'))
expect(document.documentElement.classList.contains('page-hidden')).toBe(true)
setVisibility('visible')
document.dispatchEvent(new Event('visibilitychange'))
expect(document.documentElement.classList.contains('page-hidden')).toBe(false)
dispose()
setVisibility('hidden')
document.dispatchEvent(new Event('visibilitychange'))
// Disposed: the class is no longer maintained.
expect(document.documentElement.classList.contains('page-hidden')).toBe(false)
})
it('reflects an already-hidden window immediately on install', () => {
setVisibility('hidden')
const dispose = installPageHiddenClass()
expect(document.documentElement.classList.contains('page-hidden')).toBe(true)
dispose()
})
})