Determining field identifier that is dynamically generated

Determining field identifier that is dynamically generated

by Mike Churchward -
Number of replies: 9
Picture of Core developers Picture of Plugin developers Picture of Testers
Hi -

I'm writing Behat tests for a plugin, and I've come up against a problem I'm not sure how to solve.

The plugin outputs form elements automatically, based on the data entered when the instance was created. So the "id" and "name" attributes are created based on database id's and other real-time generated data.

In the case I am having issues with, there is a series of radio buttons, and one of those has an associated text field. I want to write a test where that button is selected and the text entered into the text field.

The problem I'm having is that I don't know how to identify the input field in the Behat test statements, without knowing what the data id's are. Is there a way to enter text data into a text field based on its position on the page, or some other factor of position?

Thanks ahead of time.

mike


Average of ratings: -
In reply to Mike Churchward

Re: Determining field identifier that is dynamically generated

by Tim Hunt -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers

The thing to realise is: If you cannot easily identify the field using it's label, then a disabled user, accessing Moodle with a screen-reader is not going to be able to access it either.

So, in this sort of situation, the best resolution is to solve the underlying accessibility bug.

If that is not possible, then you can probably uniquely locate the field using an xpath expression.

Average of ratings: Useful (2)
In reply to Tim Hunt

Re: Determining field identifier that is dynamically generated

by Mike Churchward -
Picture of Core developers Picture of Plugin developers Picture of Testers

Thanks for the help Tim.

I "sort of" understand what you are saying, but I'm still not sure how to handle it. Let me provide the HTML that I'm looking at:

<fieldset class="qn-container" id="qn-213">
<legend id="yui_3_17_2_1_1454945634930_403" class="qn-legend">
<div id="yui_3_17_2_1_1454945634930_404" class="qn-info">
<div class="accesshide">Question #</div>
<h2 id="yui_3_17_2_1_1454945634930_405" class="qn-number">2</h2>
</div>
<div class="accesshide">Response is required</div>
<img class="req" title="Response is required" alt="Response is required" src="http://localhost/moodlehq.git/theme/image.php/clean/core/1454790405/req">
</legend>
<div id="yui_3_17_2_1_1454945634930_399" class="qn-content">
<div id="yui_3_17_2_1_1454945634930_398" class="qn-question ">
<div id="yui_3_17_2_1_1454945634930_397" class="no-overflow">
<p id="yui_3_17_2_1_1454945634930_396">Select one<br></p>
</div>
</div>

<div id="yui_3_17_2_1_1454945634930_400" class="qn-answer">
<input name="q213" id="auto-rb0006" value="82" onclick="other_check_empty(name, value)" type="radio">
<label id="yui_3_17_2_1_1454945634930_401" for="auto-rb0006">Green</label><br>
<input name="q213" id="auto-rb0007" value="83" onclick="other_check_empty(name, value)" type="radio">
<label id="yui_3_17_2_1_1454945634930_402" for="auto-rb0007">Orange</label><br>
<input name="q213" id="auto-rb0008" value="84" onclick="other_check_empty(name, value)" type="radio">
<label for="auto-rb0008">Yellow</label><br>
<input name="q213" id="auto-rb0009" value="other_85" onclick="other_check_empty(name, value)" type="radio">
<label for="auto-rb0009">Another colour:</label>
<input id="yui_3_17_2_1_1454945634930_408" size="25" name="q213_85" onclick="other_check(name)" type="text">&nbsp;<br>
</div>

</div>
</fieldset>
I have attached an image of what that chunk of screen looks like as well.
So what I am struggling with is identifying the last two "input" elements in a Behat test. The "id", "name" and "value" fields are generated programmatically from the their data identifiers in the database. I believe it still contains the information needed for accessibility, but I am open to whatever changes have to be made to make this correct.

mike
Attachment Screen Shot 2016-02-08 at 10.34.08 AM.png
In reply to Mike Churchward

Re: Determining field identifier that is dynamically generated

by Mike Churchward -
Picture of Core developers Picture of Plugin developers Picture of Testers

So, I guess I could add a label to the text box, and just hide the text from the display page? Then I could select the input by the label text.

Now, how can I identify the radio button to set the value? I believe that to set a radio button in Behat, I need to use:

"I set the field [radio button name] to "[specific radio button value]"

But, the value of the button is generated at run time, so I don't know the value when I write the test. Is there some other way to select a specific radio button?

mike

Average of ratings: Useful (1)
In reply to Mike Churchward

Re: Determining field identifier that is dynamically generated

by Mike Churchward -
Picture of Core developers Picture of Plugin developers Picture of Testers

Okay. I think I solved this.

I made the text field accessible by adding a "hidden" label to the text input field. That allowed me to identify it to Behat, and will presumably improve accessibility as well. The I used the 'I click on "[radio label]" "radio"' statement in Behat to select the radio button. It seems to work, so I hope I did that right.

mike

Average of ratings: Useful (1)
In reply to Mike Churchward

Re: Determining field identifier that is dynamically generated

by Tim Hunt -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers

That sounds about right. Well worked out.

In reply to Mike Churchward

Re: Determining field identifier that is dynamically generated

by Rajesh Taneja -

Hello Mike,


You can use either one of the following to select radio.

# Select green radio button.
And I set the field "Green" to "1"
# Select another colour radio and set the text color.
And I set the field "Another colour:" to "1"
And I set the field "q213_85" to "White"
# Select orange radio button uing xpath.
And I set the field with xpath "//label[contains(normalize-space(.), 'Orange')]/preceding-sibling::input[@type='radio'][1]" to "1"
# Set value in text field using xpath.
And I set the field with xpath "//input[@type='text' and @name='q213_85']" to "bool"

Average of ratings: Useful (1)
In reply to Rajesh Taneja

Re: Determining field identifier that is dynamically generated

by Mike Churchward -
Picture of Core developers Picture of Plugin developers Picture of Testers

Hi Raj -

I can't do something like:

And I set the field with xpath "//input[@type='text' and @name='q213_85']" to "bool"

Because the name 'q213_85' is generated at run time and used database id values. I can't know the name when I write the test.

The 'xpath' example you provided might work. But in the end, Tim's advice was correct. Really, I needed a label around all of the form fields, even if the labels are set to not display. The labels will be better for accessibility issues, and provide a better identifier for the Behat test.

mike

In reply to Mike Churchward

Re: Determining field identifier that is dynamically generated

by Rajesh Taneja -

Hello Mike,

Surely adding label is a better solution for accessibility and easy/clear behat scenario. 

Reason I added that comment is to show that, if you don't have a label then you can still use behat steps to achieve what you want. If q213_85 is random then you can change xpath to look for a text field after radio input or in the fieldset.

Cheers

Rajesh

In reply to Rajesh Taneja

Re: Determining field identifier that is dynamically generated

by Mike Churchward -
Picture of Core developers Picture of Plugin developers Picture of Testers

Thanks Raj.

I put that "xpath" part in my hip pocket. That will be something useful as I continue to write more tests. wink

mike