@@ -452,13 +452,12 @@ export const ContextPanel: React.FC = () => {
|
|||||||
|
|
||||||
// Lets an agent's browser.open create the tab it needs when none is open yet.
|
// Lets an agent's browser.open create the tab it needs when none is open yet.
|
||||||
// Registered from the panel because opening a tab is panel state, not
|
// Registered from the panel because opening a tab is panel state, not
|
||||||
// something the browser view itself can do before it exists. Background on
|
// something the browser view itself can do before it exists. Reveal the
|
||||||
// purpose: an agent working a page must not pop the panel open (or steal
|
// panel so Electron gives the webview a composited surface; capturePage()
|
||||||
// the active surface) under the user — the tab mounts invisibly, and the
|
// cannot capture the zero-width webview inside a closed panel.
|
||||||
// rail is where the user opens it when curious.
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!effectiveDirectory) return;
|
if (!effectiveDirectory) return;
|
||||||
return registerBrowserOpener((url) => openContextBrowser(effectiveDirectory, url, { reveal: false }));
|
return registerBrowserOpener((url) => openContextBrowser(effectiveDirectory, url));
|
||||||
}, [effectiveDirectory, openContextBrowser]);
|
}, [effectiveDirectory, openContextBrowser]);
|
||||||
const reorderContextPanelTabs = useUIStore((state) => state.reorderContextPanelTabs);
|
const reorderContextPanelTabs = useUIStore((state) => state.reorderContextPanelTabs);
|
||||||
const setSelectedFilePath = useFilesViewTabsStore((state) => state.setSelectedPath);
|
const setSelectedFilePath = useFilesViewTabsStore((state) => state.setSelectedPath);
|
||||||
|
|||||||
+43
@@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
* Regression coverage for https://github.com/openchamber/openchamber/issues/3175
|
||||||
|
*
|
||||||
|
* A full ContextPanel mount is not available in bun test because its import
|
||||||
|
* graph includes a Vite worker URL. This test follows the source-level guard
|
||||||
|
* pattern used by the neighboring ContextPanel regression tests and exercises
|
||||||
|
* the real store behavior that the registered opener delegates to.
|
||||||
|
*/
|
||||||
|
import { beforeEach, describe, expect, test } from 'bun:test';
|
||||||
|
import { readFileSync } from 'node:fs';
|
||||||
|
import { dirname, join } from 'node:path';
|
||||||
|
import { fileURLToPath } from 'node:url';
|
||||||
|
|
||||||
|
import { useUIStore } from '@/stores/useUIStore';
|
||||||
|
|
||||||
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||||
|
const contextPanelSource = readFileSync(join(__dirname, '..', 'ContextPanel.tsx'), 'utf-8');
|
||||||
|
const DIRECTORY = '/path/to/repository';
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
useUIStore.setState({ contextPanelByDirectory: {}, contextRailOrder: [] });
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('issue #3175 browser capture while the context panel is closed', () => {
|
||||||
|
test('registers the agent browser opener without suppressing panel reveal', () => {
|
||||||
|
expect(contextPanelSource).toContain(
|
||||||
|
'registerBrowserOpener((url) => openContextBrowser(effectiveDirectory, url))',
|
||||||
|
);
|
||||||
|
expect(contextPanelSource).not.toContain(
|
||||||
|
'openContextBrowser(effectiveDirectory, url, { reveal: false })',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('opening the agent browser gives its webview a visible panel surface', () => {
|
||||||
|
useUIStore.getState().openContextBrowser(DIRECTORY, 'https://example.com');
|
||||||
|
|
||||||
|
const panel = useUIStore.getState().contextPanelByDirectory[DIRECTORY];
|
||||||
|
expect(panel.isOpen).toBe(true);
|
||||||
|
expect(panel.tabs).toHaveLength(1);
|
||||||
|
expect(panel.tabs[0]?.mode).toBe('browser');
|
||||||
|
expect(panel.tabs[0]?.targetPath).toBe('https://example.com');
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user