Rock-solid Diagram Editors: End-to-end Testing with Eclipse GLSP

February 14, 2024 | 4 min Read

Industrial-grade diagram editors are intricate, filled with advanced functionalities and complex logic. It’s clear then that automated testing isn’t just beneficial—it’s essential for maintaining a high-quality product. The architectural design of Eclipse GLSP, with its clear separation of concerns and dependency injection, greatly facilitates unit and integration tests. However, the pinnacle of the testing hierarchy—end-to-end tests—has always been a steep hill to climb, as it involves complex SVG interaction within automated tests. That is, until the advent of glsp-playwright.

Developed through a vibrant collaboration with Dr. Dominik Bork of the Business Informatics Group at Vienna University of Technology and the talented master student Haydar Metin, glsp-playwright is a novel framework designed to simplify your end-to-end testing.

Let’s dive into this new experimental addition to GLSP with its 2.0 release!

Introducing glsp-playwright: The What and The How

The new framework “glsp-playwright” offers a library with reusable testing features. Instead of wrestling with SVG interactions, your tests can now directly execute high-level commands like “move node” or “rename node”. This is enabled by a dedicated page object model for a particular diagram editor, which is composed of functionalities  such as the Renamable or Draggable traits, and editor components, such as the Command Palette. This abstraction and encapsulation significantly enhances the maintainability, clarity, and stability of your tests.

At its core, glsp-playwright consists of three foundational elements:

  • Capabilities that facilitate specific user interactions within a GLSP diagram, such as utilizing the command palette and manipulating resize handles.
  • Flows that outline sequences of actions, mirroring user behaviors like clicking and dragging, transforming these into simple test steps.
  • Models that infuse page objects with common behaviors, enhancing the framework’s interaction capabilities. For example, the PLabelledElement model enables tests to retrieve elements by label.

Gluing It Together with Mixins

To create your page object model, you blend glsp-playwright’s capabilities, flows and models using mixins. This allows you to define, for example, a page object signifies a draggable and deletable node type that can be identified by a label with resize handles:

const MyNodeMixin = Mix(PNode)
  .capability(useResizeHandleCapability)
  .flow(useDraggableFlow)
  .flow(useDeletableFlow)
  ...
  .build();
export class MyNode extends MyNodeMixin implements PLabelledElement {...}

In a test case, you can then interact with this page object easily on a very high abstraction level, e.g. finding a node by its label (based on PLabelledElement) and dragging it to a certain position (based on useDraggableFlow).

const myNode = await app.graph.getNodeByLabel('Hello World', MyNode);
await myNode.dragToRelativePosition({ x: 0, y: 150 });

Writing and Running Tests with glsp-playwright

The abstraction layers of glsp-playwright make SVG and HTML complexities transparent, allowing for tests that are both concise and capable of executing detailed user flows. Tests may also query information like element positions and validate the diagram’s state with assertions. Below is an exemplar test:

test.describe('In this blog post', () => {
    let app: WorkflowApp;

    test.beforeEach(async ({ integration }) => {
        app = await GLSPApp.loadApp(WorkflowApp, { type: 'integration', integration });
    });

    test('we say hello to all readers', async () => {
        const task = await app.graph.getNodeByLabel('Push', TaskManual);
        await task.dragToRelativePosition({ x: 0, y: 150 });
        await task.rename('Hello');

        const bounds = await task.bounds();
        const targetPosition = bounds.position('top\_left').moveRelative(150, 0);

        const newTask = await app.createManualTask(targetPosition);
        await newTask.rename('readers');

        const edge = await app.createEdge(task, newTask);

        expect(await edge.sourceId()).toBe(await task.idAttr());
        expect(await edge.targetId()).toBe(await newTask.idAttr());
    });

    test.afterEach(async ({ integration }) => {
        await integration?.close();
    });
});

Supported by Playwright, these tests run efficiently in continuous integration setups and offer a user-friendly CLI. They are also readily debuggable in VS Code. To see it in action, check out the video below:

Platform-Agnostic Tests

Given that GLSP diagram editors integrate smoothly into diverse tool platforms like Eclipse Theia and VS Code, glsp-playwright also flexibly supports testing across these varied environments. It boasts an abstraction layer specifically for encapsulating the nuances of different platforms, ensuring the same tests can be executed to validate the behavior of diagram editors in multiple tool platforms.

Discover glsp-playwright

This novel addition to GLSP is a significant advancement, designed to refine the testing phase of diagram editor development. It offers developers a sophisticated yet simplified means to ensure their editors perform as expected. Give it a spin and explore how it can transform your testing strategy by following the steps documented in the glsp-playwright repository.

For inquiries about Eclipse GLSP, or if you require specific features, don’t hesitate to contact us! EclipseSource is your go-to for custom diagram editors using Eclipse GLSP, adding custom features to GLSP, and for crafting custom IDEs or tools based on VS Code or Eclipse Theia.

Jonas, Maximilian & Philip

Jonas Helming, Maximilian Koegel and Philip Langer co-lead EclipseSource. They work as consultants and software engineers for building web-based and desktop-based tools. …