Search code examples
javascripthtmlpuppeteer

How do you click on an element with text in Puppeteer?


Is there any method or solution to click on an element with text? I couldn't find one in the API.

For example I have the following HTML:

<div class="elements">
    <button>Button text</button>
    <a href=#>Href text</a>
    <div>Div text</div>
</div>

And I want to click on an element in which text is wrapped (click on the button inside .elements), like so:

Page.click('Button text', '.elements')

Solution

  • Short answer

    This XPath expression will query a button which contains the text "Button text":

    const [button] = await page.$x("//button[contains(., 'Button text')]");
    if (button) {
        await button.click();
    }
    

    To also respect the <div class="elements"> surrounding the buttons, use the following code:

    const [button] = await page.$x("//div[@class='elements']/button[contains(., 'Button text')]");
    

    Explanation

    To explain why using the text node (text()) is wrong in some cases, let's look at an example:

    <div>
        <button>Start End</button>
        <button>Start <em>Middle</em> End</button>
    </div>
    

    First, let's check the results when using contains(text(), 'Text'):

    • //button[contains(text(), 'Start')] will return both two nodes (as expected)
    • //button[contains(text(), 'End')] will only return one nodes (the first) as text() returns a list with two texts (Start and End), but contains will only check the first one
    • //button[contains(text(), 'Middle')] will return no results as text() does not include the text of child nodes

    Here are the XPath expressions for contains(., 'Text'), which works on the element itself including its child nodes:

    • //button[contains(., 'Start')] will return both two buttons
    • //button[contains(., 'End')] will again return both two buttons
    • //button[contains(., 'Middle')] will return one (the last button)

    So in most cases, it makes more sense to use the . instead of text() in an XPath expression.