Skip to content

Conversation

@mansoorkhan96
Copy link
Contributor

@mansoorkhan96 mansoorkhan96 commented Sep 10, 2025

This pull request adds the ability to test and interact with browser dialogs. Playwright automatically dismisses the dialogs if they are not explicitly interrupted in tests. However, sometimes you might want to make sure if certain dialogs appear, under certain conditions and maybe with some dynamic content or alert.

Example:

use Pest\Browser\Playwright\Dialog;

$page = visit('/');

$page->onDialog(function (Dialog $dialog): void {
    expect($dialog->type())->toBe('alert');
    expect($dialog->message())->toBe('Hello World!');

    $dialog->accept();
});

$page->click('#alert-btn');

@mansoorkhan96 mansoorkhan96 marked this pull request as ready for review September 10, 2025 17:05
@mansoorkhan96
Copy link
Contributor Author

@jasonmccreary Would love to get your feedback on this, if you have time.

@biinari
Copy link
Contributor

biinari commented Oct 5, 2025

This is really useful in testing an app that has many confirm dialogs. There's just a little thing that has been tripping me up.

When an expectation in the dialog handler function fails, it can cause a hang where the dialog remains open (with no information on which test case is running). This happens if the interaction that opened the dialog uses an automatic selector.

Demonstration with a test case:

it('does not hang when dialog expectation fails', function (): void {
    Route::get('/', fn (): string => '
        <button id="confirm-btn" onclick="confirm(\'Are you sure?\');">Show Confirm</button>
    ');

    $page = visit('/');

    $page->onDialog(function (Dialog $dialog): void {
        expect($dialog->message())->toBe('Wrong text');

        $dialog->accept();
    });

    // $page->click('#confirm-btn'); // times out as desired and fails with "Timeout 1000ms exceeded"
    $page->click('Show Confirm'); // makes test hang with dialog still open
})->throws(ExpectationFailedException::class);

This can be worked around by a try / catch in the dialog handler:

    $page->onDialog(function (Dialog $dialog): void {
        try {
            expect($dialog->message())->toBe('Wrong text');
        } catch (ExpectationFailedException $e) {
            $dialog->dismiss();
            throw $e;
        }

        $dialog->accept();
    });

That also gives a nicer result of making the test fail with the original expectation failure rather than a timeout for the click, i.e. "Failed asserting that two strings are identical." (with a diff).

Does this try / catch inside the handler feel too long-winded for inclusion in example usage?

Would it be appropriate to catch this exception in Pest\Browser\Playwright\Page->handleDialogEvent(), dismiss the dialog if it has not yet been dismissed / accepted, and re-throw the exception?

@mansoorkhan96
Copy link
Contributor Author

@biinari I will look into this.

@mansoorkhan96 mansoorkhan96 force-pushed the feat/add-ability-to-interact-with-dialogs branch from 320bc6b to 70e03bd Compare October 11, 2025 07:37
@mansoorkhan96
Copy link
Contributor Author

@biinari Added the try catch to properly avoid test freezing issue.
Thanks for the feedback.

@EdgarsK
Copy link

EdgarsK commented Dec 4, 2025

Any updates on when this will be merged?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants