Files
OpenHands/__tests__/components/browser.test.tsx
T
DevinandTim O'Farrell efe35446d0 Fix browser panel screenshot flow (#963)
Stop clearing browser state when the Browser tab first mounts, and instead
reset it only when switching to a different conversation. This preserves the
URL and screenshot that were already emitted for the active conversation.

Also update the canvas_ui browser guidance so agents capture a screenshot with
browser_get_state(include_screenshot=true) before opening the Browser tab.
browser_navigate alone only updates the URL, which left the panel blank even
though navigation succeeded.

Add regression coverage for both behaviors:
- preloaded browser screenshots survive first Browser tab mount
- browser state still resets on conversation change
- canvas_ui browser instructions require screenshot capture before opening
  the Browser tab

Co-authored-by: Tim O'Farrell <tofarr@gmail.com>
2026-06-01 09:02:52 -06:00

83 lines
2.5 KiB
TypeScript

import { describe, it, expect, afterEach, beforeEach, vi } from "vitest";
import { screen, render } from "@testing-library/react";
import React from "react";
// Mock modules before importing the component
vi.mock("#/hooks/use-conversation-id", () => ({
useOptionalConversationId: () => ({ conversationId: "test-conversation-id" }),
useConversationId: () => ({ conversationId: "test-conversation-id" }),
}));
vi.mock("#/context/conversation-context", () => ({
useConversation: () => ({ conversationId: "test-conversation-id" }),
ConversationProvider: ({ children }: { children: React.ReactNode }) =>
children,
}));
vi.mock("react-i18next", async () => {
const actual = await vi.importActual("react-i18next");
return {
...(actual as object),
useTranslation: () => ({
t: (key: string) => key,
i18n: {
changeLanguage: () => new Promise(() => {}),
},
}),
};
});
import { BrowserPanel } from "#/components/features/browser/browser";
import { useBrowserStore } from "#/stores/browser-store";
describe("Browser", () => {
beforeEach(() => {
useBrowserStore.getState().reset();
});
afterEach(() => {
useBrowserStore.getState().reset();
vi.clearAllMocks();
});
it("renders a message if no screenshotSrc is provided", () => {
useBrowserStore.setState({
url: "https://example.com",
screenshotSrc: "",
});
render(<BrowserPanel />);
expect(screen.getByText("BROWSER$NO_PAGE_LOADED")).toBeInTheDocument();
});
it("renders the url and a screenshot", () => {
useBrowserStore.setState({
url: "https://example.com",
screenshotSrc:
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mN0uGvyHwAFCAJS091fQwAAAABJRU5ErkJggg==",
});
render(<BrowserPanel />);
expect(screen.getByText("https://example.com")).toBeInTheDocument();
expect(screen.getByAltText("BROWSER$SCREENSHOT_ALT")).toBeInTheDocument();
});
it("does not clear a preloaded screenshot when the browser tab first mounts", () => {
const screenshotSrc =
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mN0uGvyHwAFCAJS091fQwAAAABJRU5ErkJggg==";
useBrowserStore.setState({
url: "https://example.com",
screenshotSrc,
});
render(<BrowserPanel />);
expect(useBrowserStore.getState().screenshotSrc).toBe(screenshotSrc);
expect(screen.getByAltText("BROWSER$SCREENSHOT_ALT")).toBeInTheDocument();
expect(screen.queryByText("BROWSER$NO_PAGE_LOADED")).not.toBeInTheDocument();
});
});