or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

configuration.mddialog-handling.mdelement-assertions.mdelement-interactions.mdindex.md
tile.json

dialog-handling.mddocs/

Dialog Handling

Special matcher for handling browser dialogs (alerts, confirmations, prompts) that appear as a result of page interactions. This matcher is only available on Page instances.

Capabilities

Capture Dialogs

Executes a block of code and captures any dialog that appears during execution.

/**
 * Execute block and capture any dialog that appears
 * @param page - Page instance (not available on Frame or ElementHandle)
 * @param block - Async function that should trigger a dialog
 * @returns Promise resolving to the Dialog instance
 */
function toDisplayDialog(
  page: Page,
  block: () => Promise<void>
): Promise<Dialog>;

Usage Examples:

// Capture alert dialog
const dialog = await expect(page).toDisplayDialog(async () => {
  await expect(page).toClick("button", { text: "Show Alert" });
});

console.log(dialog.message()); // Access dialog message
await dialog.accept(); // Accept the dialog

// Capture confirmation dialog
const confirmDialog = await expect(page).toDisplayDialog(async () => {
  await expect(page).toClick("button", { text: "Delete Item" });
});

if (confirmDialog.type() === "confirm") {
  await confirmDialog.accept(); // or dialog.dismiss()
}

// Capture prompt dialog with input
const promptDialog = await expect(page).toDisplayDialog(async () => {
  await expect(page).toClick("button", { text: "Enter Name" });
});

await promptDialog.accept("John Doe"); // Provide input and accept

Dialog Types

The captured Dialog object supports all standard Puppeteer dialog operations:

// Dialog interface from Puppeteer
interface Dialog {
  /** Get the dialog type */
  type(): "alert" | "beforeunload" | "confirm" | "prompt";
  
  /** Get the dialog message text */
  message(): string;
  
  /** Get the default value (for prompt dialogs) */
  defaultValue(): string;
  
  /** Accept the dialog, optionally providing input for prompts */
  accept(promptText?: string): Promise<void>;
  
  /** Dismiss/cancel the dialog */
  dismiss(): Promise<void>;
}

Usage Patterns

Basic Alert Handling

// Simple alert acknowledgment
const dialog = await expect(page).toDisplayDialog(async () => {
  await expect(page).toClick("#alert-button");
});

expect(dialog.type()).toBe("alert");
expect(dialog.message()).toBe("Operation completed!");
await dialog.accept();

Confirmation Dialog Handling

// Handle confirmation dialog
const dialog = await expect(page).toDisplayDialog(async () => {
  await expect(page).toClick("#delete-button");
});

expect(dialog.type()).toBe("confirm");
expect(dialog.message()).toContain("Are you sure");

// Accept or dismiss based on test scenario
await dialog.accept(); // Confirm deletion
// or
// await dialog.dismiss(); // Cancel deletion

Prompt Dialog Handling

// Handle prompt dialog with user input
const dialog = await expect(page).toDisplayDialog(async () => {
  await expect(page).toClick("#name-input-button");
});

expect(dialog.type()).toBe("prompt");
expect(dialog.defaultValue()).toBe(""); // Check default value

await dialog.accept("Test User"); // Provide input and accept

Multiple Actions Triggering Dialog

// Dialog triggered by multiple actions
const dialog = await expect(page).toDisplayDialog(async () => {
  await expect(page).toFill("#amount", "1000");
  await expect(page).toSelect("#currency", "USD");
  await expect(page).toClick("#submit-transfer");
});

expect(dialog.message()).toContain("Transfer $1000");
await dialog.accept();

Error Handling

The toDisplayDialog matcher will:

  • Succeed if a dialog appears during block execution
  • Fail if no dialog appears within the timeout period
  • Fail if the block throws an error before a dialog appears
  • Capture the first dialog that appears (subsequent dialogs are ignored)

Common error scenarios:

// This will timeout if no dialog appears
try {
  const dialog = await expect(page).toDisplayDialog(async () => {
    await expect(page).toClick("#normal-button"); // No dialog triggered
  });
} catch (error) {
  console.log("No dialog was displayed");
}

// This will fail if the action throws before dialog
try {
  const dialog = await expect(page).toDisplayDialog(async () => {
    await expect(page).toClick("#nonexistent-button"); // Throws error
  });
} catch (error) {
  console.log("Block failed before dialog could appear");
}

Dialog Event Handling

The matcher automatically sets up dialog event listeners before executing the block and cleans up afterwards. This ensures:

  • Only dialogs triggered by the block are captured
  • No interference with other dialog handling in your tests
  • Proper cleanup even if the block throws an error

Implementation Note: The matcher uses Puppeteer's page.on('dialog') event listener internally, so you should not set up competing dialog listeners while using this matcher.

Timeout Behavior

The dialog matcher inherits timeout behavior from the global configuration:

import { setDefaultOptions } from "expect-puppeteer";

// Set longer timeout for slow dialog operations
setDefaultOptions({ timeout: 2000 });

const dialog = await expect(page).toDisplayDialog(async () => {
  // This action might take time to trigger the dialog
  await expect(page).toClick("#slow-dialog-button");
});

Browser Compatibility

Dialog handling works with all dialog types across different browsers:

  • Chrome/Chromium: Full support for all dialog types
  • Firefox: Full support for all dialog types
  • Safari: Full support for all dialog types
  • beforeunload dialogs: Require special page navigation to trigger

Note: beforeunload dialogs are typically triggered by navigation attempts and may require specific test setup.