Files
theia-code-os/examples/playwright/docs/EXTENSIBILITY.md
mawkone 8bb5110148
Some checks failed
Playwright Tests / Playwright Tests (ubuntu-22.04, Node.js 22.x) (push) Has been cancelled
3PP License Check / 3PP License Check (11, 22.x, ubuntu-22.04) (push) Has been cancelled
Publish packages to NPM / Perform Publishing (push) Has been cancelled
deploy: current vibn theia state
Made-with: Cursor
2026-02-27 12:01:08 -08:00

4.4 KiB

Extensibility

Theia is an extensible tool platform for building custom tools with custom user interface elements, such as views, editors, commands, etc. Correspondingly, Theia 🎭 Playwright supports adding dedicated page objects for your custom user interface elements. Depending on the nature of your custom components, you can extend the generic base objects, such as for views or editors, or add your own from scratch.

Custom commands or menu items

Commands and menu items are handled by their label, so no further customization of the page object framework is required. Simply interact with them via the menu or quick commands.

const app = await TheiaAppLoader.load({ playwright, browser });
const menuBar = app.menuBar;

const yourMenu = await menuBar.openMenu('Your Menu');
const yourItem = await mainMenu.menuItemByName('Your Item');

expect(await yourItem?.hasSubmenu()).toBe(true);

Custom Theia applications

The main entry point of the page object model is TheiaApp. To add further capabilities to it, for instance a custom toolbar, extend the TheiaApp class and add an accessor for a custom toolbar page object.

export class MyTheiaApp extends TheiaApp {
  readonly toolbar = new MyToolbar(this);
}

export class MyToolbar extends TheiaPageObject {
  selector = 'div#myToolbar';
  async clickItem1(): Promise<void> {
    await this.page.click(`${this.selector} .item1`);
  }
}

const ws = new TheiaWorkspace([path.resolve(__dirname, '../../src/tests/resources/sample-files1']);
const app = await TheiaAppLoader.load({ playwright, browser }, ws, MyTheiaApp);
await app.toolbar.clickItem1();

Custom views and status indicators

Many custom Theia applications add dedicated views, editors, or status indicators. To support these custom user interface elements in the testing framework, you can add dedicated page objects for them. Typically, these dedicated page objects for your custom user interface elements are subclasses of the generic classes, TheiaView, TheiaEditor, etc. Consequently, they inherit the generic behavior of views or editors, such as activating or closing them, querying the title, check whether editors are dirty, etc.

Let's take a custom view as an example. This custom view has a button that we want to be able to click.

export class MyView extends TheiaView {
  constructor(public app: TheiaApp) {
    super(
      {
        tabSelector: '#shell-tab-my-view', // the id of the tab
        viewSelector: '#my-view-container', // the id of the view container
        viewName: 'My View', // the user visible view name
      },
      app
    );
  }

  async clickMyButton(): Promise<void> {
    await this.activate();
    const viewElement = await this.viewElement();
    const button = await viewElement?.waitForSelector('#idOfMyButton');
    await button?.click();
  }
}

So first, we create a new class that inherits all generic view capabilities from TheiaView. We have to specify the selectors for the tab and for the view container element that we specify in the view implementation. Optionally we can specify a view name, which corresponds to the label in Theia's view menu. This information is enough to open, close, find and interact with the view.

Additionally, we can add further custom methods for the specific actions and queries we want to use for our custom view. As an example, MyView above introduces a method that allows to click a button.

To use this custom page object in a test, we pass our custom page object as a parameter when opening the view with app.openView.

const app = await TheiaAppLoader.load({ playwright, browser });
const myView = await app.openView(MyView);
await myView.clickMyButton();

A similar approach is used for custom editors. The only difference is that we extend TheiaEditor instead and pass our custom page object as an argument to app.openEditor. As a reference for custom views and editors, please refer to the existing page objects, such as TheiaPreferenceView, TheiaTextEditor, etc.

Custom status indicators are supported with the same mechanism. They are accessed via TheiaApp.statusBar.

const app = await TheiaAppLoader.load({ playwright, browser });
const problemIndicator = await app.statusBar.statusIndicator(
  TheiaProblemIndicator
);
const numberOfProblems = await problemIndicator.numberOfProblems();
expect(numberOfProblems).to.be(2);