maquette

repository·main·Indexed 21 days ago

https://github.com/afassoftware/maquette

A minimalistic Virtual DOM implementation for JavaScript (version 4.1.4) designed for small bundle sizes, animated transitions, and ease of unit testing. It synchronizes the browser's DOM tree with application data using a lightweight footprint of approximately 3.7Kb gzipped.

Tokens
4.1K
Snippets
14
Records
23
Agent score
73%

What's inside maquette

  1. What is Maquette and when should I use it?

    main

    Maquette is a lightweight JavaScript utility designed to synchronize the DOM tree in the browser with your application data using a Virtual DOM technique.

    Key advantages include:

    • Lightweight: Extremely small footprint (approx. 3.7Kb gzipped).
    • Animations: Supports animating changes made to the DOM.
    • Testability: Designed to make frontend logic easy to unit-test.
  2. Run Maquette Browser Tests

    main

    Navigate to the browser-tests directory to execute the tests using various modes:

    TaskCommand
    Run all tests (headless)npm test
    Run tests with browser visiblenpm run test:headed
    Debug tests interactivelynpm run test:debug
    Run tests with Playwright UInpm run test:ui
    View test reportnpm run report
    npm test
  3. Setup Maquette Browser Tests

    main

    To run the end-to-end browser tests, you must first build the maquette package and install the dependencies for the TodoMVC example from the repository root, then install the test dependencies within the browser-tests directory.

    1. Prepare the Repository Root

    From the repository root, install core dependencies and build the distribution files, then install the TodoMVC bower dependencies:

    # From the repository root
    npm ci
    npm run dist
    
    # Install TodoMVC bower dependencies
    cd examples/todomvc
    npm install --no-save bower
    npx bower install
    cd ../..

    2. Install Test Dependencies

    Navigate to the browser-tests directory to install Playwright and the Chromium browser:

    cd browser-tests
    npm install
    npx playwright install chromium
    cd browser-tests
    npm install
    npx playwright install chromium
  4. How to write new browser tests

    main

    The test suite uses the Page Object Model (POM) pattern to encapsulate page interactions. When writing new tests, follow these steps:

    1. Update the Page Object: If you need to interact with new elements or perform new actions, add them to tests/TodoPage.ts.
    2. Write the Spec: Create new spec files or add to tests/todomvc.spec.ts.
    3. Group Tests: Use test.describe() to organize related test cases.
    4. Use the Page Object: Always use the TodoPage instance for interactions and assertions to maintain consistency.

    Example Test Case

    test('should do something', async () => {
      await todoPage.addTodo('My todo');
      await todoPage.assertTodos(['My todo']);
    });
  5. Implement the MaquetteComponent pattern

    main

    While not strictly enforced by the core engine, the MaquetteComponent interface is a recommended pattern for building self-contained, reusable parts of your application.

    To implement it, create an object or class with a render() method that returns a VNode or null.

    interface MyComponent extends MaquetteComponent {
      render(): VNode {
        return h('div', { class: 'my-component' }, 'Hello World');
      }
    }
  6. Define VNode properties and animations

    main

    A VNode is a virtual representation of a DOM node. Its behavior and appearance are defined by VNodeProperties.

    Lifecycle Animations

    Inside VNodeProperties, you can define animations for different lifecycle stages:

    • enterAnimation(element, properties): Triggered when a node is added to an existing parent.
    • exitAnimation(element, removeElement, properties): Triggered when a node is removed. Call removeElement() to complete the removal.
    • updateAnimation(element, properties, previousProperties): Triggered when node properties (attributes, styles, classes, or text) change.

    Lifecycle Callbacks

    • afterCreate(element, projectionOptions, vnodeSelector, properties, children): Executed after the node and its children are added to the DOM.
    • afterUpdate(element, projectionOptions, vnodeSelector, properties, children): Executed every time the node is updated.
    • afterRemoved(element): Called when a node is removed from the tree.

    Common Properties

    • key: A unique identifier used to track nodes among siblings (essential for dynamic lists).
    • bind: Used to set the this context for event handlers.
    • on / onCapture: Objects containing event handlers (e.g., onclick). projector.scheduleRender() is called automatically when these are invoked.
    • classes: An object for dynamic CSS classes (e.g., { active: true }).
    • styles: An object for inline styles (e.g., { color: 'red' }).
    • innerHTML: Sets non-interactive HTML (use with caution regarding XSS).
  7. Configure Playwright test execution settings (use)

    main

    The use object in the Playwright configuration defines shared settings for all test projects. For Maquette, these settings are optimized for local development and CI environments:

    • baseURL: Set to http://127.0.0.1:8080 (uses 127.0.0.1 to avoid IPv6 resolution issues).
    • actionTimeout: Timeout for actions like click or fill. Set to 3,000ms locally and 10,000ms on CI.
    • expect.timeout: Timeout for assertions. Set to 3,000ms locally and 10,000ms on CI.
    • trace: Set to on-first-retry to collect traces only when a test fails and is retried.
    • screenshot: Set to only-on-failure to capture screenshots only when a test fails.
    use: {
      baseURL: "http://127.0.0.1:8080",
      actionTimeout: process.env.CI ? 10000 : 3000,
      trace: "on-first-retry",
      screenshot: "only-on-failure",
    },
    expect: {
      timeout: process.env.CI ? 10000 : 3000,
    }
  8. Configure the Maquette web server for testing

    main

    The webServer configuration automatically manages a local development server before tests run.

    • command: npx http-server .. -p 8080 -c-1 (starts a server on port 8080 with no cache).
    • url: http://127.0.0.1:8080 (the URL to wait for before starting tests).
    • reuseExistingServer: Set to true locally (if process.env.CI is not present) to speed up test runs if a server is already running.
    • timeout: 120,000ms (time allowed for the server to start).
    webServer: {
      command: "npx http-server .. -p 8080 -c-1",
      url: "http://127.0.0.1:8080",
      reuseExistingServer: !process.env.CI,
      timeout: 120 * 1000,
    }
  9. Configure Playwright for Maquette browser tests

    main

    The Playwright configuration for Maquette defines how browser tests are executed, including timeouts, parallelization, and environment-specific behaviors (CI vs. local).

    Key settings include:

    • testDir: Set to ./tests.
    • timeout: Global test timeout is 60,000ms.
    • fullyParallel: Enabled to run files in parallel.
    • forbidOnly: Enabled when process.env.CI is present to prevent accidental test.only commits.
    • retries: Set to 2 on CI, 0 locally.
    • workers: Limited to 1 on CI to prevent flakiness; otherwise, uses default.
    • reporter: Uses github and html (with open: 'never') on CI; uses html locally.

    To run tests, ensure your environment matches the expected baseURL and webServer configuration.

    import { defineConfig, devices } from "@playwright/test";
    
    export default defineConfig({
      testDir: "./tests",
      timeout: 60000,
      fullyParallel: true,
      forbidOnly: !!process.env.CI,
      retries: process.env.CI ? 2 : 0,
      workers: process.env.CI ? 1 : undefined,
      reporter: process.env.CI ? [["github"], ["html", { open: "never" }]] : "html",
    });
  10. Configure browser projects in Playwright

    main

    The projects array defines which browsers the tests should run against. By default, Maquette is configured for Chromium.

    To test on other browsers, you can uncomment the following configurations:

    • firefox: Uses devices['Desktop Firefox'].
    • webkit: Uses devices['Desktop Safari'].

    Example configuration for Chromium:

    projects: [
      {
        name: "chromium",
        use: { ...devices["Desktop Chrome"] },
      },
    ],
    projects: [
      {
        name: "chromium",
        use: { ...devices["Desktop Chrome"] },
      },
    ]
  11. Reference: Browser Test Project Structure

    main

    The browser-tests directory is organized as follows:

    • playwright.config.ts: Playwright configuration (defines web server on port 8080, browser defaults, and CI settings).
    • package.json: Test dependencies and execution scripts.
    • tests/TodoPage.ts: Page Object Model implementation for TodoMVC.
    • tests/todomvc.spec.ts: Test specifications.
    • README.md: Documentation.
  12. Reference: TodoPage Page Object API

    main

    The TodoPage class in tests/TodoPage.ts provides the following API for interacting with the TodoMVC application:

    • Navigation: goto(), goBack()
    • Actions: addTodo(), toggleTodoAt(), doubleClickTodoAt(), etc.
    • Assertions: assertTodos(), assertCompletedStates(), etc.