Skip to content

[Feature]: Codegen event consumer plugin system #29970

@ShaMan123

Description

@ShaMan123

🚀 Feature Request

Request

I would like all native events to be supported by codegen on all elements.
However, that might be too much to maintain and of course there are custom events and custom elements.

Proposal

Expose a way for the dev to hook into what codegen does, the events that are subscribed to the DOM and what they output.
If so it might be useful to expose the generic codegen impl so dev can register it themselves and override parts of it (e.g. a dev not wanting the default click cmd to be emitted because they are emitting something else such as a dblclick)
This could be done by registering a component in playwright.config or on the browser context as a fixture for example.
I have been looking at the source code and gathered some entry points, I am willing to contribute.

Code

export class Recorder implements InstrumentationListener {

export class CodeGenerator extends EventEmitter {

private async _performAction(frame: Frame, action: actions.Action) {

private _generateActionCall(subject: string, action: Action): string {

Example

// playwright code

abstract class CodeGenEventHandler {
  private _generator;

  emit(code: string[]) {
    this._generator.append(...code);
  }

  resloveLocator(event) {
    return 'resolved_locator';
  }

  abstract install(window: Window): void;
}
// playwright.config.ts

import { registerCodeGenEventHandler, CodeGenEventHandler } from 'playwright'

registerCodeGenEventHandler(MyCodeGenEventHandler);

class MyCodeGenEventHandler extends CodeGenEventHandler {
  someState: boolean;

  install(window: Window) {
    window.addEventListener('dragstart', this.dragStart);
    window.addEventListener('dragend', this.dragStart);
    window.addEventListener('pointerdown', this.pointerDown);
    window.addEventListener('pointerup', this.pointerDown);
  }

  dragStart = (e: DragEvent) => {
    this.someState = true;
  };

  dragEnd = (e: DragEvent) => {
    this.emit(['await page.dragAndDrop(this.resolveLocator(e), ...);']);
  };

  pointerDown = (e: PointerEvent) => {
    this.someState = false;
  };

  pointerUp = (e: PointerEvent) => {
    this.emit([
      'await page.mouse.down(...);',
      'await page.mouse.move(...);',
      'await page.mouse.up(...);',
    ]);
  };
}

Motivation

I love playwright, it is super powerful.
Codegen itself makes writing tests so simple that it becomes fun.
Without codegen writing tests is not easy nor fun.
Having to obtain event data (e.g. pointer position) etc. adds a lot of friction.
Furthermore, codegen itself interferes with its locator overlay if the events are not handled by it making it impossible to use it to extract useful data such as locator, pointer position etc.

Supporting this feature will make codegen limitless and will not require additional maintenance.

An attempt to provide a codegen distant ancestor (hacked it up): fabricjs/fabric.js#9350

#9503
#19892 => #27985
#21504

Another related request: #28474

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions