Reputation:
I have a block of code like so:
<ul class="open-menu">
<span>
<li data-testid="menu-item" class="menu-item option">
<svg>...</svg>
<div>
<strong>Text Here</strong>
<small>...</small>
</div>
</li>
<li data-testid="menu-item" class="menu-item option">
<svg>...</svg>
<div>
<strong>Text</strong>
<small>...</small>
</div>
</li>
</span>
</ul>
I'm trying to select a menu item based on exact text like so in the dev tools:
$x('.//*[contains(@data-testid, "menu-item") and normalize-space() = "Text"]');
But this doesn't seem to be selecting the element. However, when I do:
$x('.//*[contains(@data-testid, "menu-item")]');
I can see both of the menu items.
UPDATE:
It seems that this works:
$x('.//*[contains(@class, "menu-item") and normalize-space() = "Text"]');
Not sure why using a class in this context works and not a data-testid. How can I get my xpath selector to work with my data-testid?
Upvotes: 1
Views: 1103
Reputation: 33361
data-testid="menu-item"
is matching both the outer li
elements while text content you are looking for is inside the inner strong
element.
So, to locate the outer li
element based on it's data-testid
attribute value and it's inner strong
element text value you can use XPath expression like this:
//*[contains(@data-testid, "menu-item") and .//normalize-space() = "Text"]
Or
.//*[contains(@data-testid, "menu-item") and .//*[normalize-space() = "Text"]]
I have tested, both expressions are working correctly
Upvotes: 0
Reputation: 1811
Why is this exact text selector not working
The fact that both li
elements are matched by the XPath expression
if omitting the condition normalize-space() = "Text"
is a clue.
normalize-space()
returns ... Text Here ...
for the first li
in the posted XML and ... Text ...
for the second (or some other
content in place of ...
from div/svg
or div/small
) causing
normalize-space() = "Text"
to fail.
In an update you say the same condition succeeds. This has nothing to
do with using @class
instead of @data-testid
; it must be triggered
by some content change.
How can I get my xpath selector to work with my data-testid?
By testing for an exact text match in the li
's descendant strong
element,
.//*[@data-testid = "menu-item" and div/strong = "Text"]
which matches the second li
. Making the test more robust is usually
in order, e.g.
.//*[contains(@data-testid,"menu-item") and normalize-space(div/strong) = "Text"]
Append /div/small
or /descendant::small
, for example, to the XPath
expression to extract just the small
text.
Upvotes: 2