Files
goodbuddy/src/renderer/src/browser-viewport-occlusion.test.ts
T
mesalogo 1c22e1a06d fix: keep browser overlays and knowledge controls usable
Native browser pages could cover application dialogs and overlapping menus
or notifications. Suspend only the viewport while covered and restore the
same active page afterward, including nested dialogs and terminal prompts.

Keep knowledge source controls at their full height, constrain long library
cards and titles, and update automatic names when switching remote targets
without overwriting edited or saved names. Restore packaged release-note
loading now that the history exceeds its previous size limit.

Add focused regressions and real Electron UI evidence. Clean up temporary
Harness fixture directories at test completion instead of accumulating them.

Release note: 修复内嵌浏览器遮挡弹窗和浮层、知识库来源选项被压缩及长名称显示异常;切换远端知识库时自动名称正确更新,并恢复更新说明显示。
2026-09-13 19:46:37 +08:00

52 lines
2.2 KiB
TypeScript

import { afterEach, describe, expect, it, vi } from 'vitest'
import { isBrowserViewportOccluded } from './browser-viewport-occlusion'
afterEach(() => {
document.body.replaceChildren()
vi.restoreAllMocks()
})
function setup(attributes: Record<string, string>, overlaps = true) {
const host = document.createElement('div')
const parent = document.createElement('div')
const overlay = document.createElement('section')
for (const [name, value] of Object.entries(attributes)) {
overlay.setAttribute(name, value)
}
parent.append(overlay)
document.body.append(host, parent)
const viewport = new DOMRect(600, 100, 400, 500)
vi.spyOn(overlay, 'getBoundingClientRect').mockReturnValue(
new DOMRect(overlaps ? 700 : 10, 200, 200, 100)
)
return { host, parent, overlay, viewport }
}
describe('native browser overlay detection', () => {
it('blocks an application modal even when its surface does not overlap the page', () => {
const { host, viewport } = setup({ 'aria-modal': 'true' }, false)
expect(isBrowserViewportOccluded(host, viewport)).toBe(true)
})
it.each(['dialog', 'alertdialog', 'menu'])('detects overlapping %s without requiring modal focus setup', role => {
const { host, viewport } = setup({ role })
expect(isBrowserViewportOccluded(host, viewport)).toBe(true)
})
it.each(['hidden', 'display', 'visibility', 'ancestor-display'])('ignores a modal hidden by %s', kind => {
const { host, parent, overlay, viewport } = setup({ 'aria-modal': 'true' })
if (kind === 'hidden') parent.hidden = true
if (kind === 'display') overlay.style.display = 'none'
if (kind === 'visibility') overlay.style.visibility = 'hidden'
if (kind === 'ancestor-display') parent.style.display = 'none'
expect(isBrowserViewportOccluded(host, viewport)).toBe(false)
})
it('does not treat inline statuses and error messages as overlays', () => {
const { host, viewport } = setup({ role: 'alert' })
expect(isBrowserViewportOccluded(host, viewport)).toBe(false)
})
it('does not let a surrounding non-modal container hide its own browser', () => {
const { host, overlay, viewport } = setup({ role: 'dialog' })
overlay.append(host)
expect(isBrowserViewportOccluded(host, viewport)).toBe(false)
})
})