Skip to content

Testing

Import test utilities from @loc/electron-window/testing — this entry point has no Electron dependency, so it works in any Jest or Vitest environment.

import {
MockWindowProvider,
MockWindow,
getMockWindows,
resetMockWindows,
simulateMockWindowEvent,
} from "@loc/electron-window/testing";

Use MockWindowProvider in place of WindowProvider. Windows that open under it are tracked in memory instead of creating real BrowserWindow instances.

test("opens settings window", async () => {
resetMockWindows();
render(
<MockWindowProvider>
<MyApp />
</MockWindowProvider>,
);
fireEvent.click(screen.getByText("Open Settings"));
await waitFor(() => {
expect(getMockWindows()).toHaveLength(1);
expect(getMockWindows()[0].props.title).toBe("Settings");
});
});

Returns an array of all open mock windows. Each entry has:

PropertyTypeDescription
idstringUnique window identifier
propsobjectThe props passed to <Window>
stateWindowStateLive window state — assert on isFocused, bounds, etc.
eventsWindowEvent[]Event log — everything fired on this window

getMockWindow(id) / getMockWindowByName(name)

Section titled “getMockWindow(id) / getMockWindowByName(name)”

Retrieve a single window. getMockWindowByName matches the name prop on <Window> — cleaner than getMockWindows()[0] when you have multiple windows:

<Window open name="settings" title="Settings">...</Window>
<Window open name="editor" title="Editor">...</Window>
// in the test
const settings = getMockWindowByName("settings");
expect(settings?.props.title).toBe("Settings");

Clears all tracked windows. Call this in beforeEach or at the start of each test.

Use MockWindow to wrap components that call useCurrentWindow(), useWindowFocused(), or other window hooks.

test("shows focused indicator", () => {
render(
<MockWindow state={{ isFocused: true }}>
<StatusBar />
</MockWindow>,
);
expect(screen.getByText("Focused")).toBeInTheDocument();
});

MockWindow accepts a state prop with any subset of WindowState. Unspecified values default to sensible initial values (not focused, not maximized, etc.).

test("handles bounds change", async () => {
resetMockWindows();
render(
<MockWindowProvider>
<MyApp />
</MockWindowProvider>,
);
// ... trigger window open ...
simulateMockWindowEvent(getMockWindows()[0].id, {
type: "boundsChanged",
bounds: { x: 0, y: 0, width: 500, height: 400 },
});
});
typeAdditional fieldsDescription
"focused"Window gained focus
"blurred"Window lost focus
"maximized"Window maximized
"unmaximized"Window restored from maximized
"minimized"Window minimized
"restored"Window restored from minimized
"shown"Window became visible
"hidden"Window was hidden
"enterFullscreen"Window entered fullscreen
"leaveFullscreen"Window exited fullscreen
"boundsChanged"bounds: { x, y, width, height }Window resized or moved
"userCloseRequested"User clicked the close button
"displayChanged"display: DisplayInfoWindow moved to another monitor
"closed"Window was destroyed
"ready"Window ready and content mounted

For the common cases, there are thin wrappers that save a few keystrokes:

simulateMockUserClose(id); // = simulateMockWindowEvent(id, { type: "userCloseRequested" })
simulateMockResize(id, bounds); // = simulateMockWindowEvent(id, { type: "boundsChanged", bounds })