Home > Mobile >  Xpath to encompass two different object structures
Xpath to encompass two different object structures

Time:08-04

I'm automating with Selenium. I'm dealing with 2 variants (mobile, desktop) of a page. Both have a "Login" button, but the HTML is different.

First variant:

 <div role="button"><div ...><span><span>Foo Bar MaybeQuux</span></span></div></div>

Second variant:

<a href="p/q/r" data="loginButton"><div><span><span>Foo Bar MaybeQuux</span></span></div></a>

I've written MaybeQuux as for small screens it turns into Mayb.... However Bar is guaranteed.

Here's my code so far:

def waitClickable(by, text, timeout=60):
    return WebDriverWait(driver, timeout).until(
        EC.element_to_be_clickable(
            (by, text)
        )
    )

waitClickable(By.XPATH, "???").click()

So my question is, would it possible to write a single xpath that can locate both variants?

If so I can avoid the awkwardness of having to wait on an object of unknown form.

ref: Python selenium : Explicitly wait for one of two elements to be loaded

CodePudding user response:

You can use below XPATH

//*[self::div or self::a and starts-with(span, 'Foo Bar Maybe')]

but the easiest way is

//span[starts-with(., 'Foo Bar Mayb')]

or

//span[contains(., 'Bar Mayb')]

CodePudding user response:

This XPath should get the inner span in both cases

'//div[@role="button"]/descendant::span[starts-with(.,"Foo Bar")] | //a[@data="loginButton"]/descendant::span[starts-with(.,"Foo Bar")]'

Alternative expressions

//*[(name()="div" and @role="button") or (name()="a" and @data="loginButton")]/descendant::span[starts-with(.,"Foo Bar")]

//*[(self::div and @role="button") or (self::a and @data="loginButton")]/descendant::span[starts-with(.,"Foo Bar")]

CodePudding user response:

Considering both the HTMLs:

  • First:

    <div role="button"><div ...><span><span>Foo Bar MaybeQuux</span></span></div></div>
    
  • Second:

    <a href="p/q/r" data="loginButton"><div><span><span>Foo Bar MaybeQuux</span></span></div></a>
    

Both have the following identical features:

  • Bar is the guaranteed text
  • Mayb is the guaranteed text
  • The above texts are within a <span>
  • The grandchild <span> is within it's immediate parent <span>
  • The parent <span> is within it's immediate parent <div>

Solution

A common xpath to both the elements would be:

//div/span/span[contains(., 'Bar') and contains(., 'Mayb')]

POC

Maybe

  • Related