MADCookie
MADCookie

Reputation: 2662

In Selenium IDE, can Locator use XPath and storedVars

I have a XPath that will select a specific radio button item of my HTML. I would like to enhance my locator to be more dynamic by using a stored variable to represent the text for which my XPath is using to lock on.

This is my current setup

Command: Click

Target:

//*[contains(@for,'Page149.Question48.TypeChoiceOneAnswerRadioButton.holder_ctl02')
and text()="Below 70 – May be too low"]

I would like to replace the literal text "Below 70 – May be too low" with a variable. My proposed Target is failing to evaluate. I hope I just have the syntax incorrect.

Can I do this? Can I use stored variables with XPath locators?

Proposed Target:

//*[contains(@for,'Page149.Question48.TypeChoiceOneAnswerRadioButton.holder_ctl02')
and text()=${radioText}] 

EDIT: Adding code. I made a simple example of my HTML radio button list and isolated my Selenium commands. I am using the Selenium IDE in the Firefox. My commands example has comments.

Sample HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Untitled Page</title>
</head>
<body>
    <table border="0" class="srvy_radiobuttonlist" id="ctl00_cphSurveyControls_surveyCategoryPage_Page51.Question5.TypeChoiceOneAnswerRadioButton.holder_ctl02">
        <tbody>
            <tr>
                <td>
                    <input type="radio" checked="checked" value="Page51.Question5.Answer580" name="ctl00$cphSurveyControls$surveyCategoryPage$Page51.Question5.TypeChoiceOneAnswerRadioButton.holder$ctl02"
                        id="ctl00_cphSurveyControls_surveyCategoryPage_Page51.Question5.TypeChoiceOneAnswerRadioButton.holder_ctl02_0"><label
                            for="ctl00_cphSurveyControls_surveyCategoryPage_Page51.Question5.TypeChoiceOneAnswerRadioButton.holder_ctl02_0">Male</label>
                </td>
                <td>
                    <input type="radio" value="Page51.Question5.Answer581" name="ctl00$cphSurveyControls$surveyCategoryPage$Page51.Question5.TypeChoiceOneAnswerRadioButton.holder$ctl02"
                        id="ctl00_cphSurveyControls_surveyCategoryPage_Page51.Question5.TypeChoiceOneAnswerRadioButton.holder_ctl02_1"><label
                            for="ctl00_cphSurveyControls_surveyCategoryPage_Page51.Question5.TypeChoiceOneAnswerRadioButton.holder_ctl02_1">Female</label>
                </td>
            </tr>
        </tbody>
    </table>
</body>
</html>

Mocked up Selenium IDE

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head profile="http://selenium-ide.openqa.org/profiles/test-case">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="selenium.base" href="http://localhost" />
<title>LocatorTest</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">LocatorTest</td></tr>
</thead><tbody>
<!--Select Male-->
<tr>
    <td>click</td>
    <td>//*[contains(@id,'Page51.Question5.TypeChoiceOneAnswerRadioButton.holder_ctl02_0')]</td>
    <td></td>
</tr>
<tr>
    <td>store</td>
    <td>Female</td>
    <td>Gender</td>
</tr>
<tr>
    <td>assertTextPresent</td>
    <td>${Gender}</td>
    <td></td>
</tr>
<tr>
    <td>assertTextPresent</td>
    <td>javascript{ storedVars['Gender']}</td>
    <td></td>
</tr>
<!--FYI, locates first item in radio collection-->
<tr>
    <td>click</td>
    <td>//*[contains(@for,'Page51.Question5.TypeChoiceOneAnswerRadioButton.holder_ctl02')]</td>
    <td></td>
</tr>
<!--Works to select female-->
<tr>
    <td>click</td>
    <td>//*[contains(@for,'Page51.Question5.TypeChoiceOneAnswerRadioButton.holder_ctl02') and text()='Female']</td>
    <td></td>
</tr>
<tr>
    <td>click</td>
    <td>//*[contains(@for,'Page51.Question5.TypeChoiceOneAnswerRadioButton.holder_ctl02') and contains(text(),'Female')]</td>
    <td></td>
</tr>
<!---- not found -->
<tr>
    <td>click</td>
    <td>//*[contains(@for,'Page51.Question5.TypeChoiceOneAnswerRadioButton.holder_ctl02') and contains(text(),${Gender})]</td>
    <td></td>
</tr>
<!--Works to select female-->
<tr>
    <td>click</td>
    <td>//*[contains(text(),'Female')]</td>
    <td></td>
</tr>
<!---- not found -->
<tr>
    <td>click</td>
    <td>//*[contains(text(),${Gender})]</td>
    <td></td>
</tr>
</tbody></table>
</body>
</html>

Upvotes: 4

Views: 9583

Answers (3)

ento
ento

Reputation: 5889

You need quotation marks around the variable.

//*[contains(text(),'${Gender}')]

And yes, I have successfully used an XPath locator with stored variables, though it was not with 'click' but with 'waitForXpathCount'. At first it didn't work and I had to resort to printf-debugging to get to the cause. The reason it didn't work is irrelevant here(I didn't set the target appropriately), but I think a list of relevant files will be of interest to those having trouble with Selenium IDE.

Location of the files on a Mac:

~/Library/Application Support/Firefox/Profiles/[your profile]/extensions/{a6fd85ed-e919-4a43-a5af-8da18bda539f}/chrome/content/selenium-core/scripts/

Important files:

  • selenium-api.js
    Core command handlers. ex. Selenium.prototype.doClick
  • selenium-browserbot.js
    Responsible for interfacing with the browser. The doClick handler above calls BrowserBot.prototype.findElement, for instance.
  • selenium-executionloop.js
    Calls command handlers. Most importantly in this case, preprocesses the locator string with selenium.preprocessParameter(command.target). selenium.preprocessParameter can be found in selenium-api.js.
  • htmlutils.js
    Provides XPathEvaluator

How to print to the IDE log:

LOG.error("Useful debugging information");

You need to restart Firefox each time you make a change to Selenium IDE's internals (I couldn't find a way to reload it on the fly).

Additionally, you can test your XPath expression like $x("xpath/expr/with/stored/variables/replaced/accordingly") on a normal Firefox JS console.

Upvotes: 4

Ross Patterson
Ross Patterson

Reputation: 9570

Yes, that should work just fine. The documentation shows a simple example:

type    |   textElement |   Full name is: ${fullname}

The obvious question would be "Where did you get the value of radioText from?", followed closely by "Are you sure there is no other text in it?" (because you coded "text()='xxx'", not "contains(text(), '...')". Or perhaps you really did leave out the quotes in the code, not just in your example (i.e., "text()=xxx", not "text()='xxx'")?

Upvotes: 0

kenneth koontz
kenneth koontz

Reputation: 869

What is the HTML element you are selecting? Can you provide the HTML? Yes, this is possible. What binding are you using? ie. Python, Ruby, Java???

You can do something like this:

var = selenium.get_eval(locator)

Upvotes: 0

Related Questions