playwright-crx

repository·main·Indexed 20 days ago

https://github.com/ruifigueira/playwright-crx

A specialized version of the Playwright library designed to run as a Chrome Extension. It leverages the chrome.debugger API to enable browser automation and script recording directly within the browser environment, allowing control of browser pages from a background service worker.

Tokens
364.2K
Snippets
1.3K
Records
1.6K
Agent score
70%

What's inside playwright-crx

  1. Introduction to API testing with Playwright Java

    main

    Playwright provides access to the REST API of your application via the APIRequestContext class. This allows you to send HTTP(S) requests directly from Java without loading a web page or executing JavaScript in a browser.

    Common use cases include:

    • Testing your server's API directly.
    • Preparing server-side state (e.g., creating a user or repository) before running browser-based tests.
    • Validating server-side post-conditions after performing actions in the browser.
  2. Use the Keyboard API for virtual keyboard management

    main

    The Keyboard class provides an API for managing a virtual keyboard. It offers high-level methods like type for sending character sequences and low-level methods like down, up, and insertText for manual event control.

    Key distinction:

    • Use type to generate keydown, keypress/input, and keyup events.
    • Use down and up to simulate holding modifier keys (e.g., Shift, Control).
    • Use insertText to dispatch only input events without keydown or keyup events.

    Best Practices:

    • For most input tasks, prefer Locator.fill over Keyboard.type.
    • If you need to simulate a user typing one by one, use Locator.pressSequentially instead of Keyboard.type.
    • For simple key presses, prefer Locator.press over Keyboard.press.

    Example of holding Shift to select text:

    await page.keyboard.type('Hello World!');
    await page.keyboard.press('ArrowLeft');
    
    await page.keyboard.down('Shift');
    for (let i = 0; i < ' World'.length; i++)
      await page.keyboard.press('ArrowLeft');
    await page.keyboard.up('Shift');
    
    await page.keyboard.press('Backspace');
    // Result text will end up saying 'Hello!'
    await page.keyboard.type('Hello World!');
    await page.keyboard.press('ArrowLeft');
    
    await page.keyboard.down('Shift');
    for (let i = 0; i < ' World'.length; i++)
      await page.keyboard.press('ArrowLeft');
    await page.keyboard.up('Shift');
    
    await page.keyboard.press('Backspace');
  3. Benefits of migrating to Playwright Test

    main

    Migrating to Playwright Test provides several advanced testing capabilities:

    • Cross-Browser/OS: Run tests across all web engines (Chrome, Firefox, Safari) on Windows, macOS, and Ubuntu.
    • Isolation: Run tests in parallel with full isolation.
    • Advanced Features: Support for multiple origins, iframes, tabs, and browser contexts.
    • Developer Tools:
      • UI Mode: Time-travel debugging and watch mode.
      • Playwright Inspector: For step-through debugging.
      • Codegen: Automatic test generation.
      • Tracing: Post-mortem debugging with full execution context.
  4. Benefits of using Playwright Test runner

    main

    Playwright Test is the recommended first-party test runner. It provides:

    • Zero-config TypeScript support.
    • Cross-engine execution: Run tests across Chrome, Firefox, and Safari on any OS.
    • Isolation: Run tests in parallel across multiple browsers and contexts.
    • Advanced Features: Built-in support for multiple origins, iframes, tabs, and contexts.
    • Tooling: Bundled with Playwright Inspector, Code Generation (codegen), and Playwright Tracing for post-mortem debugging.
  5. What is an ElementHandle and when to use it

    main

    An ElementHandle represents a specific in-page DOM element. You can create them using Page.querySelector (or page.$).

    ⚠️ Warning: Use Locators instead Use of ElementHandle is discouraged. You should use Locator objects and web-first assertions instead.

    Key Differences:

    • ElementHandle: Points to a particular DOM element. If the element changes (e.g., via a React re-render), the handle may point to a stale or detached element, leading to unexpected behavior.
    • Locator: Captures the logic to find an element. Every time a locator is used, it re-locates the element using the selector, ensuring it always interacts with the most up-to-date DOM element.

    Lifecycle:

    • ElementHandle prevents the DOM element from being garbage collected until the handle is disposed using JSHandle.dispose.
    • They are automatically disposed when their origin frame is navigated.
    // ElementHandle approach (Discouraged)
    const handle = await page.$('text=Submit');
    await handle.click();
    
    // Locator approach (Recommended)
    const locator = page.getByText('Submit');
    await locator.click();
  6. Overview of the Clock API

    main

    The Page.clock API allows you to manipulate and control time within tests, enabling precise validation of time-dependent features like rendering time, timeouts, and scheduled tasks without real-time delays.

    It overrides native global classes and functions including:

    • Date and performance
    • setTimeout, clearTimeout, setInterval, clearInterval
    • requestAnimationFrame, cancelAnimationFrame
    • requestIdleCallback, cancelIdleCallback
    • Event.timeStamp

    Important: If you use install, it must be called before any other clock-related calls (like setInterval). Calling them out of order results in undefined behavior because install replaces the native definitions.

  7. Get a frame using a selector or URL

    main

    There are several ways to retrieve a Frame object depending on the available identifiers:

    1. By Name: Use the string name of the frame attribute: page.frame('frame-name').
    2. By URL: Use a string or regular expression to match the frame's URL: page.frame({ url: /.*domain.*/ }).
    3. Via ElementHandle: If you have an ElementHandle representing the iframe element, you can use contentFrameAsync() to get the frame object.
    // Get frame using the frame's name attribute
    var frame = page.Frame("frame-login");
    
    // Get frame using the frame's URL
    var frame = page.FrameByUrl("*domain.");
    
    // Get frame using any other selector via ElementHandle
    var frameElementHandle = await page.EvaluateAsync("window.frames[1]");
    var frame = await frameElementHandle.ContentFrameAsync();
    
    // Interact with the frame
    await frame.FillAsync("#username-input", "John");
  8. What are Handles in Playwright

    main

    Playwright uses handles to reference objects that live inside the browser's execution context from the Playwright process. There are two primary types:

    1. JSHandle: References any JavaScript object in the page (e.g., window, an array, or a custom object).
    2. ElementHandle: References DOM elements. Since DOM elements are also JavaScript objects, an ElementHandle is a specialized JSHandle with additional methods for performing actions on elements and asserting their properties.

    Handles allow you to evaluate code on the object, retrieve properties, and pass them as parameters to other evaluations.