diff --git a/src/_internal/utils/web-preset.ts b/src/_internal/utils/web-preset.ts index 7637e450e..39535e91c 100644 --- a/src/_internal/utils/web-preset.ts +++ b/src/_internal/utils/web-preset.ts @@ -1,6 +1,6 @@ import type { ProviderConfiguration } from '../types' import { isWindowDefined, isDocumentDefined } from './helper' -import { isUndefined, noop } from './shared' +import { noop } from './shared' /** * Due to the bug https://bugs.chromium.org/p/chromium/issues/detail?id=678075, @@ -22,8 +22,18 @@ const [onWindowEvent, offWindowEvent] = : [noop, noop] const isVisible = () => { - const visibilityState = isDocumentDefined && document.visibilityState - return isUndefined(visibilityState) || visibilityState !== 'hidden' + if (!isDocumentDefined) return true + + try { + const isDocVisible = document.visibilityState !== 'hidden' + + const isDocFocused = + typeof document.hasFocus === 'function' ? document.hasFocus() : true + + return isDocVisible && isDocFocused + } catch (err) { + return true + } } const initFocus = (callback: () => void) => { diff --git a/test/unit/web-preset-visible.test.ts b/test/unit/web-preset-visible.test.ts new file mode 100644 index 000000000..487e9da09 --- /dev/null +++ b/test/unit/web-preset-visible.test.ts @@ -0,0 +1,56 @@ +import { describe, expect, it, beforeEach, afterEach } from 'vitest' +import { preset } from '../../src/_internal/utils/web-preset' + +describe('web-preset isVisible', () => { + let originalDocument: any + + beforeEach(() => { + originalDocument = global.document + global.document = { + visibilityState: 'visible', + hasFocus: () => true + } + }) + + afterEach(() => { + global.document = originalDocument + }) + + it('returns true when document is visible and focused', () => { + global.document.visibilityState = 'visible' + global.document.hasFocus = () => true + expect(preset.isVisible()).toBe(true) + }) + + it('returns false when document is hidden and not focused', () => { + global.document.visibilityState = 'hidden' + global.document.hasFocus = () => false + expect(preset.isVisible()).toBe(false) + }) + + it('returns false when document is hidden but focused', () => { + global.document.visibilityState = 'hidden' + global.document.hasFocus = () => true + expect(preset.isVisible()).toBe(false) + }) + + it('returns false when document is visible but not focused', () => { + global.document.visibilityState = 'visible' + global.document.hasFocus = () => false + expect(preset.isVisible()).toBe(false) + }) + + it('returns true if hasFocus is not a function', () => { + global.document.visibilityState = 'visible' + // @ts-expect-error + global.document.hasFocus = undefined + expect(preset.isVisible()).toBe(true) + }) + + it('returns true if there is an exception', () => { + Object.defineProperty(global, 'document', { + get() { throw new Error('Simulated error') } + }) + expect(preset.isVisible()).toBe(true) + }) +}) \ No newline at end of file