Search code examples
pythonpytestplaywrightplaywright-python

How to make assertion of dialog.message in playwright?


In one of my tests I need to assert message in browser dialog. I created dialog handler in test

page.on('dialog', BasePage.dialog_handle)

page is default playwright fixture.

The handler itself is

def dialog_handle(dialog):
    message = dialog.message
    dialog.dismiss()

Here is full example of the test with dialog on the page

from playwright.sync_api import Page


def dialog_handle(dialog):
    message = dialog.message
    dialog.dismiss()


def test_dialog(page):
    page.goto('https://dialog.antonzimaiev.repl.co')
    page.on('dialog', dialog_handle)
    page.get_by_role("button", name="Диалог Alert").click()

How can I retrieve dialog.message to assert it using pytest?


Solution

  • This can be solved with some scoping readjustments:

    from playwright.sync_api import sync_playwright  # 1.37.0
    
    
    def test_dialog(page):
        dialog_message = None
    
        def handle_dialog(dialog):
            nonlocal dialog_message
    
            # assert here
            print(dialog.message) # => Hello from Open Solutions 🙂
    
            # or save the message in the enclosing scope...
            dialog_message = dialog.message
            dialog.dismiss()
    
        page.goto("https://dialog.antonzimaiev.repl.co")
        page.once("dialog", handle_dialog)
        page.get_by_role("button", name="Диалог Alert").click()
    
        # ... and assert here
        print(dialog_message) # => Hello from Open Solutions 🙂
    
    
    if __name__ == "__main__":
        with sync_playwright() as p:
            browser = p.chromium.launch(headless=True)
            page = browser.new_page()
            test_dialog(page)
    

    There's nothing special about pytest per se here--you can drop the test_dialog function body right into a pytest test case and use assertions from that, or any other testing library you like.

    Race conditions aren't an issue here since the dialog blocks the script after the .click() operation until it's dismissed.


    This pattern can be factored to be reusable across tests or in a POM, if that's a concern. For example:

    def accept_dialog(page, trigger_dialog):
        dialog_message = None
    
        def handle_dialog(dialog):
            nonlocal dialog_message
            dialog_message = dialog.message
            dialog.dismiss()
    
        page.once("dialog", handle_dialog)
        trigger_dialog()
        return dialog_message
    
    
    def test_dialog(page):
        page.goto("https://dialog.antonzimaiev.repl.co")
        dialog_message = accept_dialog(
            page,
            lambda: page.get_by_role("button", name="Диалог Alert").click()
        )
        print(dialog_message) # => Hello from Open Solutions 🙂