Files
orca/src/main/runtime/browser-tab-create-publication.test.ts
T

689 lines
25 KiB
TypeScript

// Every browser-tab placement must publish the created tab through one seam. A placement that
// hand-rolls its own bookkeeping is how a client-placed page once lost its targetGroupId.
import { beforeEach, describe, expect, it, vi } from 'vitest'
import type { AgentBrowserBridge } from '../browser/agent-browser-bridge'
import type { RuntimeBrowserCommandHost } from './browser/browser-command-contracts'
import { RuntimeBrowserPageRegistry } from './runtime-browser-page-registry'
import {
BROWSER_TAB_CREATE_PLACEMENT_KINDS,
BROWSER_TAB_CREATE_PUBLICATION_RULES,
BROWSER_TAB_SWITCH_PLACEMENT_KINDS,
BROWSER_TAB_SWITCH_PUBLICATION_RULES,
browserTabCreateClientPageStartsActive,
browserTabCreateTakesFocus,
browserTabSwitchTakesFocus,
publishCreatedBrowserSessionTab,
publishSwitchedBrowserSessionTab,
resolveBrowserTabCreateFocus,
type BrowserTabCreatePublicationHost
} from './browser-tab-create-publication'
const { ipcMainOnMock, waitForTabRegistrationMock } = vi.hoisted(() => ({
ipcMainOnMock: vi.fn(),
waitForTabRegistrationMock: vi.fn()
}))
vi.mock('electron', () => ({
ipcMain: { on: ipcMainOnMock, removeListener: vi.fn() },
webContents: { fromId: vi.fn() }
}))
vi.mock('../ipc/browser-tab-registration-wait', () => ({
waitForTabRegistration: waitForTabRegistrationMock,
waitForWorktreeTabRegistration: vi.fn()
}))
vi.mock('../browser/browser-session-registry', () => ({
browserSessionRegistry: {
getDefaultProfile: () => ({ id: 'default', partition: 'persist:orca-browser' }),
getProfile: () => null,
resolveKnownPartition: () => 'persist:orca-browser'
}
}))
function createCommandHost(
overrides: Partial<RuntimeBrowserCommandHost>
): RuntimeBrowserCommandHost {
const runtimeBrowserPages = new RuntimeBrowserPageRegistry()
return {
resolveWorktreeSelector: async (selector: string) => ({ id: selector.replace(/^id:/, '') }),
resolveBrowserWorkspace: async (selector: string) => ({ id: selector.replace(/^id:/, '') }),
getRuntimeBrowserPageRegistry: () => runtimeBrowserPages,
getAgentBrowserBridge: () =>
({
getRegisteredTabs: vi.fn(() => new Map([['page-created', 202]])),
setActiveTab: vi.fn()
}) as unknown as AgentBrowserBridge,
getAuthoritativeWindow: vi.fn(),
getAvailableAuthoritativeWindow: vi.fn(() => null),
getOffscreenBrowserBackend: vi.fn(() => null),
...overrides
} as unknown as RuntimeBrowserCommandHost
}
function createPublicationHost(registeredTabs: readonly [string, number][] = [['page-1', 101]]): {
host: BrowserTabCreatePublicationHost
setActiveTab: ReturnType<typeof vi.fn>
markHeadlessBrowserSessionTabActive: ReturnType<typeof vi.fn>
notifyHeadlessBrowserSessionTabsChanged: ReturnType<typeof vi.fn>
} {
const setActiveTab = vi.fn()
const markHeadlessBrowserSessionTabActive = vi.fn()
const notifyHeadlessBrowserSessionTabsChanged = vi.fn()
return {
host: {
getAgentBrowserBridge: () =>
({
getRegisteredTabs: vi.fn(() => new Map(registeredTabs)),
setActiveTab
}) as never,
markHeadlessBrowserSessionTabActive,
notifyHeadlessBrowserSessionTabsChanged
},
setActiveTab,
markHeadlessBrowserSessionTabActive,
notifyHeadlessBrowserSessionTabsChanged
}
}
describe('publishCreatedBrowserSessionTab', () => {
// Why: the per-placement cases below read their expectation off this table, so the table itself
// needs a literal pin — otherwise dropping a step here would silently rewrite what they assert.
it('pins the bookkeeping each placement owns', () => {
expect(BROWSER_TAB_CREATE_PUBLICATION_RULES).toEqual({
client: {
activatesBridgeTab: false,
marksSessionTabFocus: true,
notifiesSessionTabsChanged: true,
hostRowSource: 'session-notify'
},
offscreen: {
activatesBridgeTab: true,
marksSessionTabFocus: true,
notifiesSessionTabsChanged: false,
hostRowSource: 'none'
},
renderer: {
activatesBridgeTab: true,
marksSessionTabFocus: false,
notifiesSessionTabsChanged: false,
hostRowSource: 'create-ipc'
}
})
})
// Why: `session-notify` is not a free-standing choice — the host row rides the very announcement
// `notifiesSessionTabsChanged` gates, so silencing that flag would delete the row with no other
// test noticing. Pin the coupling, not just the two values.
it('gives every session-notify placement the announcement its host row rides on', () => {
// Presence precondition: the loop below only asserts anything about placements that declare
// `session-notify`, so flipping the one that does to `none` in the same edit that silences its
// announcement would satisfy the coupling by emptying it. Name the placement that must declare
// it — a client-placed page reaches the host renderer through no other route.
expect(BROWSER_TAB_CREATE_PUBLICATION_RULES.client.hostRowSource).toBe('session-notify')
for (const placementKind of BROWSER_TAB_CREATE_PLACEMENT_KINDS) {
const rules = BROWSER_TAB_CREATE_PUBLICATION_RULES[placementKind]
if (rules.hostRowSource === 'session-notify') {
expect(
rules.notifiesSessionTabsChanged,
`${placementKind} sources its host row from the session-tabs announcement`
).toBe(true)
}
}
})
it.each(BROWSER_TAB_CREATE_PLACEMENT_KINDS)(
'moves a user-created %s tab into the clicked split group when the placement marks focus',
(placementKind) => {
const { host, markHeadlessBrowserSessionTabActive } = createPublicationHost()
publishCreatedBrowserSessionTab(host, {
placementKind,
browserPageId: 'page-1',
worktreeId: 'wt-1',
focus: resolveBrowserTabCreateFocus({ activate: true }),
targetGroupId: 'group-right'
})
if (BROWSER_TAB_CREATE_PUBLICATION_RULES[placementKind].marksSessionTabFocus) {
expect(markHeadlessBrowserSessionTabActive).toHaveBeenCalledWith('wt-1', 'page-1', {
targetGroupId: 'group-right',
focusesHost: true
})
} else {
expect(markHeadlessBrowserSessionTabActive).not.toHaveBeenCalled()
}
}
)
it.each(BROWSER_TAB_CREATE_PLACEMENT_KINDS)(
'never marks a background %s create active',
(placementKind) => {
const { host, markHeadlessBrowserSessionTabActive } = createPublicationHost()
for (const activate of [undefined, false]) {
publishCreatedBrowserSessionTab(host, {
placementKind,
browserPageId: 'page-1',
worktreeId: 'wt-1',
focus: resolveBrowserTabCreateFocus({ activate }),
targetGroupId: 'group-right'
})
}
expect(markHeadlessBrowserSessionTabActive).not.toHaveBeenCalled()
}
)
it.each(BROWSER_TAB_CREATE_PLACEMENT_KINDS)(
'activates the bridge tab for a %s create only when the placement is bridge-backed',
(placementKind) => {
const { host, setActiveTab } = createPublicationHost()
publishCreatedBrowserSessionTab(host, {
placementKind,
browserPageId: 'page-1',
worktreeId: 'wt-1',
focus: resolveBrowserTabCreateFocus({ activate: true })
})
if (BROWSER_TAB_CREATE_PUBLICATION_RULES[placementKind].activatesBridgeTab) {
expect(setActiveTab).toHaveBeenCalledWith(101, 'wt-1')
} else {
expect(setActiveTab).not.toHaveBeenCalled()
}
}
)
it.each(BROWSER_TAB_CREATE_PLACEMENT_KINDS)(
'notifies session-tab watchers for a %s create only when the placement owns the announcement',
(placementKind) => {
const { host, notifyHeadlessBrowserSessionTabsChanged } = createPublicationHost()
publishCreatedBrowserSessionTab(host, {
placementKind,
browserPageId: 'page-1',
worktreeId: 'wt-1',
focus: resolveBrowserTabCreateFocus({ activate: true })
})
if (BROWSER_TAB_CREATE_PUBLICATION_RULES[placementKind].notifiesSessionTabsChanged) {
expect(notifyHeadlessBrowserSessionTabsChanged).toHaveBeenCalledWith('wt-1')
} else {
expect(notifyHeadlessBrowserSessionTabsChanged).not.toHaveBeenCalled()
}
}
)
it('announces the created tab before it takes focus', () => {
const order: string[] = []
const host: BrowserTabCreatePublicationHost = {
getAgentBrowserBridge: () => null,
markHeadlessBrowserSessionTabActive: () => order.push('mark'),
notifyHeadlessBrowserSessionTabsChanged: () => order.push('notify')
}
publishCreatedBrowserSessionTab(host, {
placementKind: 'client',
browserPageId: 'page-1',
worktreeId: 'wt-1',
focus: resolveBrowserTabCreateFocus({ activate: true })
})
expect(order).toEqual(['notify', 'mark'])
})
it('tolerates a host with no bridge and no session-tab surface', () => {
expect(() =>
publishCreatedBrowserSessionTab(
{ getAgentBrowserBridge: () => null },
{
placementKind: 'offscreen',
browserPageId: 'page-1',
worktreeId: 'wt-1',
focus: resolveBrowserTabCreateFocus({ activate: true })
}
)
).not.toThrow()
})
it('skips bridge activation for a page the bridge has not registered', () => {
const { host, setActiveTab } = createPublicationHost([['page-other', 101]])
publishCreatedBrowserSessionTab(host, {
placementKind: 'renderer',
browserPageId: 'page-1',
worktreeId: 'wt-1',
focus: resolveBrowserTabCreateFocus({ activate: true })
})
expect(setActiveTab).not.toHaveBeenCalled()
})
it('skips the worktree-scoped announcement for an unscoped create', () => {
const { host, notifyHeadlessBrowserSessionTabsChanged } = createPublicationHost()
publishCreatedBrowserSessionTab(host, {
placementKind: 'client',
browserPageId: 'page-1',
focus: resolveBrowserTabCreateFocus({ activate: true })
})
expect(notifyHeadlessBrowserSessionTabsChanged).not.toHaveBeenCalled()
})
})
describe('browser tab-create activation defaults', () => {
it('takes focus only on an explicit activate', () => {
expect(browserTabCreateTakesFocus(true)).toBe(true)
expect(browserTabCreateTakesFocus(false)).toBe(false)
expect(browserTabCreateTakesFocus(undefined)).toBe(false)
})
it('starts a client page active unless the caller opts out', () => {
expect(browserTabCreateClientPageStartsActive(true)).toBe(true)
expect(browserTabCreateClientPageStartsActive(false)).toBe(false)
expect(browserTabCreateClientPageStartsActive(undefined)).toBe(true)
})
})
describe('browser tab-create focus resolution', () => {
it('keeps a local create host-focusing, exactly as it was before navigation existed', () => {
expect(resolveBrowserTabCreateFocus({ activate: true })).toEqual({
navigation: 'all',
selects: true,
focusesHost: true,
startsActive: true
})
})
it('keeps a paired create on the caller when it names no audience', () => {
// An old client cannot send `navigation`; being a paired caller is what narrows it.
expect(resolveBrowserTabCreateFocus({ activate: true, clientKind: 'runtime' })).toMatchObject({
navigation: 'caller',
selects: true,
focusesHost: false
})
})
it.each(['caller', 'clients'] as const)('never focuses the host for navigation %s', (target) => {
expect(resolveBrowserTabCreateFocus({ activate: true, navigation: target }).focusesHost).toBe(
false
)
})
it.each(['host', 'all'] as const)('focuses the host for navigation %s', (target) => {
expect(resolveBrowserTabCreateFocus({ activate: true, navigation: target }).focusesHost).toBe(
true
)
})
it('selects nothing for a background create however it is addressed', () => {
for (const navigation of ['caller', 'host', 'clients', 'all'] as const) {
expect(resolveBrowserTabCreateFocus({ navigation })).toMatchObject({
selects: false,
focusesHost: false
})
expect(resolveBrowserTabCreateFocus({ activate: false, navigation })).toMatchObject({
selects: false,
focusesHost: false
})
}
})
it('leaves the client page registry default on activate alone', () => {
expect(resolveBrowserTabCreateFocus({ navigation: 'caller' }).startsActive).toBe(true)
expect(
resolveBrowserTabCreateFocus({ activate: false, navigation: 'caller' }).startsActive
).toBe(false)
})
})
describe('browser tab-create placement census', () => {
// Why: the rule-driven cases above read their expectation off the table, so each placement also
// needs its real bookkeeping observed through browserTabCreate itself.
describe('through browserTabCreate', () => {
beforeEach(() => {
ipcMainOnMock.mockReset()
waitForTabRegistrationMock.mockReset()
waitForTabRegistrationMock.mockResolvedValue(undefined)
})
it('moves a user-created offscreen tab into the clicked split group', async () => {
const { RuntimeBrowserCommands } = await import('./browser/browser-commands')
const markHeadlessBrowserSessionTabActive = vi.fn()
const commands = new RuntimeBrowserCommands(
createCommandHost({
getOffscreenBrowserBackend: vi.fn(
() =>
({
createTab: vi.fn(async () => ({ browserPageId: 'page-created' })),
closeTab: vi.fn()
}) as never
),
markHeadlessBrowserSessionTabActive
})
)
await commands.browserTabCreate({
worktree: 'id:wt-1',
url: 'about:blank',
activate: true,
targetGroupId: 'group-right'
})
expect(markHeadlessBrowserSessionTabActive).toHaveBeenCalledWith('wt-1', 'page-created', {
targetGroupId: 'group-right',
focusesHost: true
})
markHeadlessBrowserSessionTabActive.mockClear()
await commands.browserTabCreate({
worktree: 'id:wt-1',
url: 'about:blank',
targetGroupId: 'group-right'
})
// Why: agent/background creates must not yank a connected client to the new tab.
expect(markHeadlessBrowserSessionTabActive).not.toHaveBeenCalled()
})
it('leaves renderer tab focus to the create IPC instead of the session-tab marker', async () => {
const { RuntimeBrowserCommands } = await import('./browser/browser-commands')
const webContents = { send: vi.fn() }
webContents.send = vi.fn((_channel: string, data: { requestId: string }) => {
const handler = ipcMainOnMock.mock.calls.find(
([eventName]) => eventName === 'browser:tabCreateReply'
)?.[1] as
| ((event: unknown, reply: { requestId: string; browserPageId?: string }) => void)
| undefined
handler?.({ sender: webContents } as never, {
requestId: data.requestId,
browserPageId: 'page-created'
})
})
const markHeadlessBrowserSessionTabActive = vi.fn()
const commands = new RuntimeBrowserCommands(
createCommandHost({
getAvailableAuthoritativeWindow: vi.fn(() => ({}) as never),
getAuthoritativeWindow: vi.fn(() => ({ webContents }) as never),
markHeadlessBrowserSessionTabActive
})
)
await commands.browserTabCreate({
worktree: 'id:wt-1',
url: 'about:blank',
activate: true,
targetGroupId: 'group-right'
})
expect(webContents.send).toHaveBeenCalledWith(
'browser:requestTabCreate',
expect.objectContaining({ activate: true })
)
expect(markHeadlessBrowserSessionTabActive).not.toHaveBeenCalled()
})
it('does not focus the host renderer for a create addressed to the caller', async () => {
const { RuntimeBrowserCommands } = await import('./browser/browser-commands')
const webContents = { send: vi.fn() }
webContents.send = vi.fn((_channel: string, data: { requestId: string }) => {
const handler = ipcMainOnMock.mock.calls.find(
([eventName]) => eventName === 'browser:tabCreateReply'
)?.[1] as
| ((event: unknown, reply: { requestId: string; browserPageId?: string }) => void)
| undefined
handler?.({ sender: webContents } as never, {
requestId: data.requestId,
browserPageId: 'page-created'
})
})
const commands = new RuntimeBrowserCommands(
createCommandHost({
getAvailableAuthoritativeWindow: vi.fn(() => ({}) as never),
getAuthoritativeWindow: vi.fn(() => ({ webContents }) as never)
})
)
await commands.browserTabCreate(
{ worktree: 'id:wt-1', url: 'about:blank', activate: true, navigation: 'caller' },
{ pairedDeviceId: 'device-a', clientKind: 'runtime' }
)
// The create IPC is the host renderer's only focus signal, so this flag is the steal.
expect(webContents.send).toHaveBeenCalledWith(
'browser:requestTabCreate',
expect.objectContaining({ activate: false })
)
})
it('still places a caller-addressed client page in the clicked split group', async () => {
const { RuntimeBrowserCommands } = await import('./browser/browser-commands')
const markHeadlessBrowserSessionTabActive = vi.fn()
const commands = new RuntimeBrowserCommands(
createCommandHost({
getOffscreenBrowserBackend: vi.fn(
() =>
({
createTab: vi.fn(async () => ({ browserPageId: 'page-created' })),
closeTab: vi.fn()
}) as never
),
markHeadlessBrowserSessionTabActive
})
)
await commands.browserTabCreate(
{
worktree: 'id:wt-1',
url: 'about:blank',
activate: true,
navigation: 'caller',
targetGroupId: 'group-right'
},
{ pairedDeviceId: 'device-a', clientKind: 'runtime' }
)
// Suppressing the focus must not suppress the group move — the same call carries both.
expect(markHeadlessBrowserSessionTabActive).toHaveBeenCalledWith('wt-1', 'page-created', {
targetGroupId: 'group-right',
focusesHost: false,
caller: { clientNavigationId: 'device-a', navigation: 'caller' }
})
})
})
})
describe('publishSwitchedBrowserSessionTab', () => {
// Why: the cases below read their expectation off this table, so the table needs a literal pin.
it('pins the bookkeeping each switch placement owns', () => {
expect(BROWSER_TAB_SWITCH_PUBLICATION_RULES).toEqual({
client: { marksSessionTabFocus: true, notifiesSessionTabsChanged: true },
bridge: { marksSessionTabFocus: true, notifiesSessionTabsChanged: false }
})
})
it('moves the session active tab only when the switch carries focus', () => {
for (const placementKind of BROWSER_TAB_SWITCH_PLACEMENT_KINDS) {
const focused = createPublicationHost()
publishSwitchedBrowserSessionTab(focused.host, {
placementKind,
browserPageId: 'page-1',
worktreeId: 'wt-1',
focus: true
})
// Why the literal: an explicit switch is still host-facing, and the create path's
// caller-local shape must not leak into it.
expect(focused.markHeadlessBrowserSessionTabActive).toHaveBeenCalledWith('wt-1', 'page-1', {
focusesHost: true
})
for (const focus of [false, undefined]) {
const unfocused = createPublicationHost()
publishSwitchedBrowserSessionTab(unfocused.host, {
placementKind,
browserPageId: 'page-1',
worktreeId: 'wt-1',
focus
})
expect(
unfocused.markHeadlessBrowserSessionTabActive,
`${placementKind} switch with focus=${focus} must not yank a connected client`
).not.toHaveBeenCalled()
}
}
})
it('announces a client switch whether or not it took focus, and never a bridge switch', () => {
for (const focus of [true, false, undefined]) {
const client = createPublicationHost()
publishSwitchedBrowserSessionTab(client.host, {
placementKind: 'client',
browserPageId: 'page-1',
worktreeId: 'wt-1',
focus
})
expect(client.notifyHeadlessBrowserSessionTabsChanged).toHaveBeenCalledWith('wt-1')
const bridge = createPublicationHost()
publishSwitchedBrowserSessionTab(bridge.host, {
placementKind: 'bridge',
browserPageId: 'page-1',
worktreeId: 'wt-1',
focus
})
expect(bridge.notifyHeadlessBrowserSessionTabsChanged).not.toHaveBeenCalled()
}
})
it('skips the worktree-scoped announcement for an unscoped switch', () => {
const { host, notifyHeadlessBrowserSessionTabsChanged } = createPublicationHost()
publishSwitchedBrowserSessionTab(host, {
placementKind: 'client',
browserPageId: 'page-1',
focus: true
})
expect(notifyHeadlessBrowserSessionTabsChanged).not.toHaveBeenCalled()
})
it('tolerates a host with no session-tab surface', () => {
expect(() =>
publishSwitchedBrowserSessionTab(
{ getAgentBrowserBridge: () => null } as BrowserTabCreatePublicationHost,
{ placementKind: 'bridge', browserPageId: 'page-1', worktreeId: 'wt-1', focus: true }
)
).not.toThrow()
})
})
describe('browser tab-switch focus rule', () => {
it('takes focus only on an explicit focus flag', () => {
expect(browserTabSwitchTakesFocus(true)).toBe(true)
expect(browserTabSwitchTakesFocus(false)).toBe(false)
expect(browserTabSwitchTakesFocus(undefined)).toBe(false)
})
})
describe('browser tab-switch placement census', () => {
// Why: the rule-driven cases read their expectation off the table, so each branch also needs
// its real bookkeeping observed through browserTabSwitch itself.
describe('through browserTabSwitch', () => {
function createClientSwitchHost(overrides: Partial<RuntimeBrowserCommandHost>): {
host: RuntimeBrowserCommandHost
registry: RuntimeBrowserPageRegistry
} {
const registry = new RuntimeBrowserPageRegistry()
for (const [browserPageId, active] of [
['page-a', true],
['page-b', false]
] as const) {
registry.publishClientPage({
browserPageId,
workspaceId: 'wt-1',
browserProfileId: 'default',
executionHostKey: 'native:runtime-a:7',
placement: {
kind: 'client',
browserHostClientId: 'host-a',
browserHostGeneration: 3,
pageHostGeneration: 9
},
url: 'https://client.test/',
loading: false,
active
})
}
return {
host: createCommandHost({
getAgentBrowserBridge: () => null,
getRuntimeBrowserPageRegistry: () => registry,
...overrides
}),
registry
}
}
it('marks a focused client switch active and leaves an unfocused one alone', async () => {
const { RuntimeBrowserCommands } = await import('./browser/browser-commands')
const markHeadlessBrowserSessionTabActive = vi.fn()
const notifyHeadlessBrowserSessionTabsChanged = vi.fn()
const { host, registry } = createClientSwitchHost({
markHeadlessBrowserSessionTabActive,
notifyHeadlessBrowserSessionTabsChanged
})
const commands = new RuntimeBrowserCommands(host)
await expect(
commands.browserTabSwitch({ worktree: 'id:wt-1', page: 'page-b', focus: true })
).resolves.toEqual({ switched: 1, browserPageId: 'page-b' })
expect(registry.getPage('page-b')?.active).toBe(true)
expect(markHeadlessBrowserSessionTabActive).toHaveBeenCalledWith('wt-1', 'page-b', {
focusesHost: true
})
expect(notifyHeadlessBrowserSessionTabsChanged).toHaveBeenCalledWith('wt-1')
markHeadlessBrowserSessionTabActive.mockClear()
notifyHeadlessBrowserSessionTabsChanged.mockClear()
await commands.browserTabSwitch({ worktree: 'id:wt-1', page: 'page-a' })
// Why: an agent or CLI switch without --focus must not yank a connected client.
expect(markHeadlessBrowserSessionTabActive).not.toHaveBeenCalled()
expect(registry.getPage('page-a')?.active).toBe(true)
expect(notifyHeadlessBrowserSessionTabsChanged).toHaveBeenCalledWith('wt-1')
})
it('marks a focused bridge switch active and leaves an unfocused one alone', async () => {
const { RuntimeBrowserCommands } = await import('./browser/browser-commands')
const markHeadlessBrowserSessionTabActive = vi.fn()
const bridge = {
getRegisteredTabs: vi.fn(() => new Map([['page-server', 100]])),
tabList: vi.fn(() => ({
tabs: [
{
browserPageId: 'page-server',
index: 0,
url: 'about:blank',
title: 'Server page',
active: true
}
]
})),
tabSwitch: vi.fn(async () => ({ switched: 0, browserPageId: 'page-server' }))
} as unknown as AgentBrowserBridge
const commands = new RuntimeBrowserCommands(
createCommandHost({
getAgentBrowserBridge: () => bridge,
markHeadlessBrowserSessionTabActive
})
)
await commands.browserTabSwitch({ worktree: 'id:wt-1', page: 'page-server', focus: true })
expect(markHeadlessBrowserSessionTabActive).toHaveBeenCalledWith('wt-1', 'page-server', {
focusesHost: true
})
markHeadlessBrowserSessionTabActive.mockClear()
await commands.browserTabSwitch({ worktree: 'id:wt-1', page: 'page-server' })
expect(markHeadlessBrowserSessionTabActive).not.toHaveBeenCalled()
})
})
})