VALIDATION LABJAVASCRIPT ALERTS

Overlays

JavaScript Alerts

Handle native alert, confirm, and prompt dialogs with Playwright dialog listeners, accept/dismiss flows, and message assertions.

Intermediate

Scenario

Native browser dialogs freeze page execution. Tests hang unless `page.on('dialog', ...)` or `page.once('dialog', ...)` is registered before the triggering click.

Native dialogs block the page until Playwright handles the dialog event.

Type: none

Action: waiting

Message: No dialog handled yet.

Live widget · interact freely

Manual test checklist

  • 1Trigger the alert and accept it
  • 2Trigger confirm and test both OK and Cancel behavior
  • 3Trigger prompt and submit a custom release tag
  • 4Confirm the dialog message is reflected in the result panel
  • 5Confirm the page cannot be interacted with while the native dialog is open

Expected result

Alert accepts, confirm can accept or dismiss, prompt accepts custom input, and the result panel records dialog type, action, message, and prompt value.

Automation challenge

Register the dialog handler before the click, assert `dialog.message()`, then use `dialog.accept()`, `dialog.dismiss()`, and prompt text across separate tests.

Stable selectors

  • Alert trigger[data-testid="js-alert-trigger"]
  • Confirm trigger[data-testid="js-confirm-trigger"]
  • Prompt trigger[data-testid="js-prompt-trigger"]
  • Dialog result[data-testid="js-dialog-result"]
  • Prompt value[data-testid="js-prompt-value"]

Locator strategy

Three levels from simple IDs to scoped Playwright locators. IDs and names are easy to learn but are not always the best long-term choice when labels change or components repeat.

Use simple IDs and names to understand how locating elements works.

1
2
3
4
await page.goto('https://lab.hakdogan.com/practice/javascript-alerts');

page.once('dialog', (dialog) => dialog.accept());
await page.locator('#js-alert-trigger').click();

Avoid as primary strategies

XPath (unless there is no alternative), long CSS chains, Tailwind-style utility class selectors, generated or unstable IDs, and volatile framework internals break when layout, styling, or DOM structure shifts.

1
2
await page.locator('.w-full.rounded-xl.border.bg-blue-500').fill('demo@example.com');
await page.locator('//div[2]/form/div[1]/input').fill('demo@example.com');

Reference Playwright spec

javascript-alerts.spec.ts
ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import { test, expect } from '@playwright/test';

test.describe('javascript alerts', () => {
  test('accepts alert and reads message', async ({ page }) => {
    await page.goto('https://lab.hakdogan.com/practice/javascript-alerts');

    page.on('dialog', async (dialog) => {
      expect(dialog.message()).toBe('Deployment queued.');
      await dialog.accept();
    });

    await page.getByTestId('js-alert-trigger').click();
    await expect(page.getByTestId('js-dialog-result')).toContainText('accepted');
  });

  test('dismisses confirm', async ({ page }) => {
    await page.goto('https://lab.hakdogan.com/practice/javascript-alerts');

    page.once('dialog', async (dialog) => {
      expect(dialog.message()).toContain('Approve production');
      await dialog.dismiss();
    });

    await page.getByTestId('js-confirm-trigger').click();
    await expect(page.getByTestId('js-dialog-result')).toContainText('dismissed');
  });

  test('accepts prompt input', async ({ page }) => {
    await page.goto('https://lab.hakdogan.com/practice/javascript-alerts');

    page.once('dialog', async (dialog) => {
      await dialog.accept('v2.4.1');
    });

    await page.getByTestId('js-prompt-trigger').click();
    await expect(page.getByTestId('js-prompt-value')).toContainText('v2.4.1');
  });
});

Headed Test Playback

Simulated headed-browser flow — no real browser is launched.

Automation-style playback (Playwright-shaped logs). No real browser; no commands run on your machine.

Idlejavascript-alerts.spec.ts
Failure demos
https://lab.hakdogan.com/practice/javascript-alerts
playwright · headed · chromium0.00s
# awaiting Run Test · terminal scrolls automatically
Steps
  1. Registering dialog listener
  2. Accepting alert
  3. Dismissing confirm
  4. Accepting prompt value
  5. Asserting dialog result
StatusIdle
BrowserChromium
FrameworkPlaywright + TypeScript
Elapsed (live)--
Specjavascript-alerts.spec.ts