test(desktop): convert zoom source-regex test to behavior test
Extracted zoomWiringForWindowKind() + ZOOM_WINDOW_CONFIG into zoom.ts so
the pet-overlay-
opts-out / chat-windows-keep-zoom contract is tested via the pure
config,
not by reading source. Callers in main.ts now use
zoomWiringForWindowKind()
instead of inline { zoom: false } / default { zoom: true }.
This commit is contained in:
parent
c3aa81be2f
commit
b034fa7026
3 changed files with 44 additions and 30 deletions
|
|
@ -4709,7 +4709,8 @@ import {
|
|||
installZoomReassertOnWindowEvents,
|
||||
percentToZoomLevel,
|
||||
ZOOM_STORAGE_KEY,
|
||||
zoomLevelToPercent
|
||||
zoomLevelToPercent,
|
||||
zoomWiringForWindowKind
|
||||
} from './zoom'
|
||||
|
||||
function setAndPersistZoomLevel(window, zoomLevel) {
|
||||
|
|
@ -6995,7 +6996,7 @@ function spawnSecondaryWindow({
|
|||
win.on('enter-full-screen', () => sendWindowStateChanged(true))
|
||||
win.on('leave-full-screen', () => sendWindowStateChanged(false))
|
||||
|
||||
wireCommonWindowHandlers(win)
|
||||
wireCommonWindowHandlers(win, zoomWiringForWindowKind('chat'))
|
||||
|
||||
win.loadURL(
|
||||
buildSessionWindowUrl(sessionId, {
|
||||
|
|
@ -7105,9 +7106,9 @@ function spawnPetOverlayWindow(bounds) {
|
|||
// Not supported everywhere — best effort.
|
||||
}
|
||||
|
||||
// Pet overlay opts out of global UI zoom (see wireCommonWindowHandlers): it
|
||||
// Pet overlay opts out of global UI zoom (see zoomWiringForWindowKind): it
|
||||
// owns its window-fit + scale, and inheriting zoom would crop the sprite.
|
||||
wireCommonWindowHandlers(win, { zoom: false })
|
||||
wireCommonWindowHandlers(win, zoomWiringForWindowKind('petOverlay'))
|
||||
|
||||
win.once('ready-to-show', () => {
|
||||
if (!win.isDestroyed()) {
|
||||
|
|
@ -7239,7 +7240,7 @@ function createWindow() {
|
|||
// window-all-closed from quitting on Windows/Linux).
|
||||
mainWindow.on('closed', () => closePetOverlay())
|
||||
|
||||
wireCommonWindowHandlers(mainWindow)
|
||||
wireCommonWindowHandlers(mainWindow, zoomWiringForWindowKind('chat'))
|
||||
|
||||
mainWindow.webContents.on('render-process-gone', (_event, details) => {
|
||||
rememberLog(`[renderer] render-process-gone reason=${details?.reason} exitCode=${details?.exitCode}`)
|
||||
|
|
|
|||
|
|
@ -5,10 +5,8 @@
|
|||
*/
|
||||
|
||||
import assert from 'node:assert/strict'
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
|
||||
import { test } from 'vitest'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
import {
|
||||
clampZoomLevel,
|
||||
|
|
@ -16,7 +14,8 @@ import {
|
|||
percentToZoomLevel,
|
||||
ZOOM_REASSERT_WINDOW_EVENTS,
|
||||
ZOOM_STORAGE_KEY,
|
||||
zoomLevelToPercent
|
||||
zoomLevelToPercent,
|
||||
zoomWiringForWindowKind
|
||||
} from './zoom'
|
||||
|
||||
test('storage key stays stable so persisted zoom survives upgrades', () => {
|
||||
|
|
@ -66,12 +65,14 @@ test('extreme percentages clamp to the level bounds', () => {
|
|||
|
||||
test('installZoomReassertOnWindowEvents wires show and restore', () => {
|
||||
const handlers = new Map()
|
||||
|
||||
const win = {
|
||||
isDestroyed: () => false,
|
||||
on(event, listener) {
|
||||
handlers.set(event, listener)
|
||||
}
|
||||
}
|
||||
|
||||
let calls = 0
|
||||
installZoomReassertOnWindowEvents(win, () => {
|
||||
calls += 1
|
||||
|
|
@ -86,12 +87,14 @@ test('installZoomReassertOnWindowEvents wires show and restore', () => {
|
|||
test('installZoomReassertOnWindowEvents skips destroyed windows', () => {
|
||||
const handlers = new Map()
|
||||
let destroyed = false
|
||||
|
||||
const win = {
|
||||
isDestroyed: () => destroyed,
|
||||
on(event, listener) {
|
||||
handlers.set(event, listener)
|
||||
}
|
||||
}
|
||||
|
||||
let calls = 0
|
||||
installZoomReassertOnWindowEvents(win, () => {
|
||||
calls += 1
|
||||
|
|
@ -101,25 +104,17 @@ test('installZoomReassertOnWindowEvents skips destroyed windows', () => {
|
|||
assert.equal(calls, 0)
|
||||
})
|
||||
|
||||
// Source assertion (see windows-child-process.test.ts for the established
|
||||
// pattern): wireCommonWindowHandlers lives in the electron main entry with heavy
|
||||
// Electron deps, so we assert the wiring contract against source rather than
|
||||
// booting a BrowserWindow. Locks in that the pet overlay opts OUT of global UI
|
||||
// zoom while chat windows keep it — the whole reason this fix is scoped.
|
||||
test('pet overlay opts out of global UI zoom; chat windows keep it', () => {
|
||||
const electronDir = path.dirname(fileURLToPath(import.meta.url))
|
||||
const source = fs.readFileSync(path.join(electronDir, 'main.ts'), 'utf8').replace(/\r\n/g, '\n')
|
||||
|
||||
// The shared helper gates all zoom wiring behind an opt-out flag.
|
||||
assert.match(source, /function wireCommonWindowHandlers\(win, \{ zoom = true \}/)
|
||||
|
||||
// The pet overlay window is the only caller that disables zoom.
|
||||
assert.match(source, /wireCommonWindowHandlers\(win, \{ zoom: false \}\)/)
|
||||
|
||||
// Zoom restore now flows through the shared helper, so createWindow must not
|
||||
// reassert it directly (that would double-fire and drift from session windows).
|
||||
const finishLoad = source.indexOf("mainWindow.webContents.once('did-finish-load'")
|
||||
assert.notEqual(finishLoad, -1, 'missing mainWindow did-finish-load handler')
|
||||
const snippet = source.slice(finishLoad, finishLoad + 300)
|
||||
assert.doesNotMatch(snippet, /restorePersistedZoomLevel\(mainWindow\)/)
|
||||
// Zoom-wiring contract: chat windows keep global UI zoom, the pet overlay
|
||||
// opts out. Tested via the extracted config — no source-text regex.
|
||||
test('chat windows opt into zoom', () => {
|
||||
assert.deepEqual(zoomWiringForWindowKind('chat'), { zoom: true })
|
||||
})
|
||||
|
||||
test('pet overlay opts out of zoom', () => {
|
||||
assert.deepEqual(zoomWiringForWindowKind('petOverlay'), { zoom: false })
|
||||
})
|
||||
|
||||
test('unknown window kinds default to chat (zoom enabled)', () => {
|
||||
assert.deepEqual(zoomWiringForWindowKind('unknown'), { zoom: true })
|
||||
assert.deepEqual(zoomWiringForWindowKind(undefined), { zoom: true })
|
||||
})
|
||||
|
|
|
|||
|
|
@ -46,7 +46,25 @@ export function installZoomReassertOnWindowEvents(win, reassert) {
|
|||
if (win.isDestroyed?.()) {
|
||||
return
|
||||
}
|
||||
|
||||
reassert()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Zoom-wiring decision per window kind. Chat windows (main + session) keep
|
||||
* global UI zoom; the pet overlay opts out because it sizes its own OS window
|
||||
* to the sprite and inheriting zoom would crop it.
|
||||
*
|
||||
* Extracted so the "pet opts out, everything else opts in" contract is
|
||||
* unit-testable without booting a BrowserWindow or reading source.
|
||||
*/
|
||||
export const ZOOM_WINDOW_CONFIG = {
|
||||
chat: { zoom: true },
|
||||
petOverlay: { zoom: false }
|
||||
} as const
|
||||
|
||||
export function zoomWiringForWindowKind(kind) {
|
||||
return ZOOM_WINDOW_CONFIG[kind] ?? ZOOM_WINDOW_CONFIG.chat
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue