Lichtblick uses Page Object Models (POMs) located in e2e/page-objects/ to encapsulate UI interactions. This allows tests to focus on behavior rather than brittle selectors.
When to use POMs: Use them for common, repeated interactions like dismissing dialogs, navigating sidebars, or controlling playback.
When to use direct selectors: Use direct selectors only for one-off, test-specific elements that do not appear across multiple tests.
Available POMs
| POM | Purpose | Key Methods |
|---|
DataSourceDialog | Data source dialog interactions | close(), openConnection(), isVisible(), getLocator() |
Sidebar | Left/right sidebar tabs | openLayoutsTab(), openTopicsTab(), toggleLeftSidebar(), getLeftSidebar(), getPanelSettingsTab() |
PlayerControls | Playback controls | play(), pause(), seekForward(), setSpeed(), getTimestampValue(), getPlayButton(), getSlider() |
LayoutManager | Layout CRUD | openDefaultLayout(), createNewLayout(), selectPanel(), revertLayout(), getLayoutListItem() |
ExtensionManager | Extension workflows | open(), search(), findExtension(), uninstall(), getSearchBar() |
AppMenu | App menu navigation | openFile(), openViewMenu(), importLayoutFromMenu(), getMenuButton() |
Panels | Panel operations | addPanel(), addPanelFromSearch(), setTopicPath(), splitPanelDown(), getAddPanelButton(), getLogPanelRoot() |
import { test, expect } from "../../../fixtures/electron";
import { DataSourceDialog, Sidebar, LayoutManager } from "../../../page-objects";
test("create a new layout", async ({ mainWindow }) => {
const dialog = new DataSourceDialog(mainWindow);
const sidebar = new Sidebar(mainWindow);
const layout = new LayoutManager(mainWindow);
// Given
await dialog.close();
await sidebar.openLayoutsTab();
// When
await layout.openDefaultLayout();
await layout.createNewLayout();
await layout.selectPanel("Diagnostics – Detail (ROS)");
// Then
await expect(mainWindow.getByText("Unnamed layout").nth(0)).toBeVisible();
});