xpathselenium-ide

workaround for using wildcards in Selenium IDE for assert text


I want to use Selenium IDE to open this webpage and check to see if some text is contained in a specific place

At the moment I can only match for the entire text First-Play Zoft Touch Dodgeball, Red

To do this I use

Command | Target | Value

`assert text` `xpath=//div[@id='vvp-items-grid']/div/div/div/a/span/span[2]` `First-Play Zoft Touch Dodgeball, Red`

Now, because Selenium IDE does't support wildcards at the moment I have to use a method that makes my brain hurt

My objective is to see if the word "dodgeball" is present. How the heck do I use contains and dodgeball in conjunction with that xpath locator?

What's really confusing to me is that there's a ., in the example given ? Why is that there? Is to "escape" ? because it's extremely confusing and unreadable to me.


Solution

  • The . character in XPath is a reference to the context node. Think of this as the "current" node which provides the context in which an XPath expression is evaluated. You could see it as analogous to the this keyword in some object-oriented languages.

    The [ and ] characters are used in XPath to define a predicate, which is a filter, applied to a set of nodes selected by the portion of the XPath expression which is to the left of the predicate. The predicate filters that set of nodes to produce a subset containing just the nodes for which the boolean expression contained inside the predicate evaluates to true. The XPath processor takes each node in the nodeset, one by one, and evaluates the expression with that node as the context node. So a . in the predicate is a reference to the node which the filter is currently deciding on.

    e.g. if $x is a nodeset, then $x[true()] is the same set, because the XPath function true() always returns true, regardless of the context node. The expression $x[contains(., 'dodgeball')] will return the subset of nodes in the set $x whose string value contains the string dodgeball.

    You can use assertElementPresent with an XPath like this:

    //div[@id='vvp-items-grid']/div/div/div/a/span/span[2][contains(., 'Dodgeball')]
    

    Here, the first part of the XPath expression (//div[@id='vvp-items-grid']/div/div/div/a/span/span[2]) will return a set of span elements, and the predicate that follows it ([contains(., 'Dodgeball')]) will be evaluated once for each element in that set, with . referring to each element in question, and producing a new nodeset which contains only elements which do contain the Dodgeball text.

    Note that the contains function is case sensitive; if you want to find Dodgeball you'll need to use the string Dodgeball, not dodgeball. If you want to perform a case-insensitive comparison, you need to use the translate function to convert the text you're looking at in your XML into either upper- or lower-case, and compare that result to an upper- or lower-case version of your keyword. e.g. Instead of

    contains(., 'Dodgeball')
    

    ... you could use:

    contains(
       translate(
          ., 
          'abcdefghijklmnopqrstuvwxyz', 
          'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
       ), 
       'DODGEBALL'
    )