Is it possible for selenium to find a label element by its "for" attribute using xpath? - selenium

Is it possible for selenium to find a label element by its "for" attribute using xpath?
I'm testing a site that has 7 yes or no questions in row. The way the CSS is done, you click on the label instead of the input radio button. Normally I'd just find the element by text content, but there is a yes and no for each question.
I'm thinking that a work-around would be to do a javascript click on the input button to get around the "element is not visible" error that I get when trying to .click() the input directly, but I wanted to see if there was a better way to locate the label which is what users would actually be clicking.
*Edit for all of your who can't remember what a label element looks like. How would you select the middle one from this group?
<label for="superLongSetOfRandomCharacters123" class="common-to-all-buttons"> No </label>
<label for="superLongSetOfRandomCharacters345" class="common-to-all-buttons"> No </label>
<label for="superLongSetOfRandomCharacters456" class="common-to-all-buttons"> No </label>
More specifically, this is how they sit in the DOM
<ul class="list-view list-view-dividers">
<li class="list-view-item">
<div class="content">
<div id="variableValue1" class="multipleChoice">
<div class="form-row">
<label>Question 1</label>
<div class="form-row">
<table class="choices" id="randomlyGenerated-1">
<tbody>
<tr>
<td>
<div class="ui-radio"><label for="randomlyGenerated1" class="ui-btn ui-corner-all ui-btn-inherit ui-btn-icon-left ui-radio-off"> Yes</label><input id="randomlyGenerated1" type="radio" name="randomlyGenerated1" value="Yes"></div>
</td>
<td>
<div class="ui-radio"><label for="randomlyGenerated2" class="ui-btn ui-corner-all ui-btn-inherit ui-btn-icon-left ui-radio-off"> No</label><input id="randomlyGenerated2" type="radio" name="randomlyGenerated2" value="No"></div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="randomlyGenerated1-Error" class="component-error"></div>
</div>
</div>
</li>
<li class="list-view-item">
<div class="content">
<div id="variableValue2" class="multipleChoice">
<div class="form-row">
<label>Question 2</label>
<div class="form-row">
<table class="choices" id="randomlyGenerated-2">
<tbody>
<tr>
<td>
<div class="ui-radio"><label for="randomlyGenerated21" class="ui-btn ui-corner-all ui-btn-inherit ui-btn-icon-left ui-radio-off"> Yes</label><input id="randomlyGenerated21" type="radio" name="randomlyGenerated21" value="Yes"></div>
</td>
<td>
<div class="ui-radio"><label for="randomlyGenerated22" class="ui-btn ui-corner-all ui-btn-inherit ui-btn-icon-left ui-radio-off"> No</label><input id="randomlyGenerated22" type="radio" name="randomlyGenerated22" value="No"></div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="randomlyGenerated2-Error" class="component-error"></div>
</div>
</div>
</li>
</ul>

It works for selecting all labels with target 'for':
label[#for='superLongSetOfRandomCharacters123']
or you can leave #for='' blank for selecting all labels with any values (i.e. label[#for])

I guess, the XPath-Option you are looking for would be "#". so in your case something like [...]/label/#for would return you that for-value, which you could then use to check where you are ;)
Cheers
D

Use find_element_by_xpath
label = self.browser.find_element_by_xpath('//label[#for="id_field"]')

Related

How to use XPath to Find this locater Dynamically

I am trying to find checkbox element with dynamic XPath, I couldn't figure it out Is there anyone can help me?
<tr>
<td>
***<span style="font-weight: bold;">Text Message</span>***
</td>
<td>
<div id="landingzone_form:j_id_94">
<div id="landingzone_form:j_id_95" class="ui-selectbooleancheckbox ui-chkbox ui-widget">
<div class="ui-helper-hidden-accessible">
<input id="landingzone_form:j_id_95_input" name="landingzone_form:j_id_95_input" type="checkbox" autocomplete="off" aria-hidden="true" aria-checked="false" onchange="PrimeFaces.ab({s:"landingzone_form:j_id_95",e:"change",f:"landingzone_form",p:"landingzone_form:j_id_95",fi:"landingzone_form:j_id_94"});">
</div>
<div class="ui-chkbox-box ui-widget ui-corner-all ui-state-default">
***<span class="ui-chkbox-icon ui-icon ui-icon-blank ui-c"></span>***
</div>
</div>
</div>
</td>
</tr>
I am trying to find "" this element from "Text Message". Thank you
Perhaps something like this:
//tr[contains(., 'Text Message')]//span[contains(#class, 'ui-chkbox-icon')]"
You can try this to locate the checkbox by using the css selector
driver.findElement(By.cssSelector(".ui-chkbox-icon.ui-icon.ui-icon-blank.ui-c")).click();

How to use vuejs data property as html attribute

I'm trying to create an accordion with bootstrap in vuejs using a card component in a loop. I want to use the id property of the command variable so that each card has its id so that when we click on a card, only this card will open and not all the cards. Here is my code:
<div id="accordion">
<div class="card" v-for="commande in commandes.data" :key="commande.id">
<div class="card-header" :id="commande.id">
<h3 class="card-title">
<button class="btn btn-link col-md-12" data-toggle="collapse" data-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
<div class="text-primary">{{commande.id}}</div>
</button>
</h3>
</div>
<!-- /.card-header -->
<div id="collapseOne" class="collapse show" :aria-labelledby="commande.id" data-parent="#accordion">
<div class="card-body table-responsive p-0">
<table class="table table-hover">
<tbody>
<tr v-for="(produit, index) in commande.produits" :key="index">
<td>{{produit.designation}}</td>
<td>{{produit.prix_vente}}</td>
<td>{{produit.pivot.quantite}}</td>
<td>{{produit.prix_vente*produit.pivot.quantite}}</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- /.card-body -->
<div class="card-footer">
<pagination :data="commandes" #pagination-change-page="getResults"></pagination>
</div>
</div>
</div>
But when I click on a card, all the others open. it seems that this is due to the data-target attribute of the <button> tag of the card-header and the attribute id of the <div> which contains the card-body. I can't put a variable in the data-target attribute. How to solve this?
If you want to use Vue data properties as HTML Attribute, just put a ":" in front of it.
<div :id="name_of_data_property">

Vue.js doesn't render loop properly when chaning value through the v-model

<template>
<div>
<div class="form-group m-b-5">
<label for="row" class="control-label col-sm-4">Row</label>
<div class="col-sm-8">
<input type="number" id="row" v-model="row_no" min="0">
</div>
</div>
<div class="form-group m-b-5">
<label for="column" class="control-label col-sm-4">Column</label>
<div class="col-sm-8">
<input type="number" id="column" v-model="col_no" min="0">
</div>
</div>
<table class="table table-bordered">
<tr v-for="row of row_no">
<td v-for="col of col_no" v-if="!(row==1&&col==1)">
<span>
{{ row }} {{ col }}
</span>
</td>
<td v-else class="v-hidden">
</td>
</tr>
</table>
</div>
</template>
<script>
export default {
data(){
return {
row_no:5,
col_no:5,
}
}
}
</script>
I am getting the data as follows in the above scenario
But after I change the value in the row from the form I didn't get the expected result as I wanted . It shows data like this when I put row=6
The format I want is like this when I put row=6 when I put data in the form should be like this
Am I doing something wrong . Any help will be appreciated. Thank you in advance
I guess your data after typing in an input form holds a string and not a number.
Try to change your form to
<input type="number" id="row" v-model.number="row_no" min="0">
I hope this helps. For the future, if you have debugging problems like this, I would install
https://github.com/vuejs/vue-devtools
You can check for each component what the data/computed values are and see what type of data a variable holds.

FileUpload with HtmlUnit doesn't fire fileUploadListener-Event (Primefaces auto upload)

I'm trying to automate a file-upload with WebDriver. It works fine for ChromeDriver and FirefoxDriver, but refuses to work for HTMLUnit.
I've already read
Using Webdriver for PrimeFaces file upload
https://stackoverflow.com/questions/21753497/unable-to-automate-filling-of-form-with-file-upload-using-htmlunit
Unable to upload file using Selenium web driver
but both were not helpfull.
The selenium (java)code for this upload-action is quiete simple:
String elementXPath = "//input[contains(#id,'FileUpload_input')]";
WebElement element = driver.findElement(By.xpath(elementXPath));
element.sendKeys(pathToFile);
The html-code of the inputElement is:
<div class="fileupload-buttonbar ui-widget-header ui-corner-top">
<label class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-left fileinput-button" role="button" aria-disabled="false">
<span class="ui-button-icon-left ui-icon ui-icon-plusthick"></span>
<span class="ui-button-text">Upload</span>
<input type="file" id="form:FileUpload_input" name="form:FileUpload_input">
</label>
</div>
<div class="fileupload-content ui-widget-content ui-corner-bottom">
<table class="files"></table>
</div>
maybe necessary, the primefaces-codesnippet of the input-Element:
<div class="#{modalDialog ? 'span5' : 'span6'}">
<p:fileUpload id="FileUpload" mode="advanced" auto="true" sizeLimit="2097152" fileUploadListener="#{ClassView.handleFileUpload}"
label="Upload" allowTypes="/(\.|\/)(gif|GIF|jpe?g|JPE?G|png|PNG)$/" process="#this"
showButtons="false"/>
</div>
As you can see, it's a picure-Upload. The noteworthy characteristic of this upload is, that there is no 'confirm'- or 'submit'-button.
The testautomation works fine for the main-browsers, but fails with htmlUnit. After hours of debugging, I can confirm, that htmlUnit performs the 'sendKeys'-Methode, but this doesn't trigger the fileUploadListener. I already tried to click other Elements, so there is a focusLost-Action, but that didn't help.
Indeed, a 'driver.getPageSource()' after the 'sendKeys' delivers:
<div class="fileupload-buttonbar ui-widget-header ui-corner-top">
<label class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-left fileinput-button" role="button" aria-disabled="false">
<span class="ui-button-icon-left ui-icon ui-icon-plusthick"></span>
<span class="ui-button-text">Upload</span>
<input id="form:FileUpload_input" name="form:FileUpload_input" value="correct\path\to\file\pic.png" type="file" >
</label>
</div>
<div class="fileupload-content ui-widget-content ui-corner-bottom">
<table class="files">
<tbody align="left">
<tr class="template-upload" style="">
<td class="preview"></td>
<td class="name">pic.png</td>
<td class="size"></td>
<td class="progress">
<div class="ui-progressbar ui-widget ui-widget-content ui-corner-all" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="100">
<div class="ui-progressbar-value ui-widget-header ui-corner-left ui-corner-right" style="width: 100%; display: block;"></div>
</div>
</td>
<td class="start">
<button class="ui-button ui-widget ui-state-default ui-corner-all ui-button-icon-only ui-state-hover" type="submit">
<span class="ui-button-icon-left ui-icon ui-icon ui-icon-arrowreturnthick-1-n"></span>
<span class="ui-button-text">ui-button</span>
</button>
</td>
<td class="cancel">
<button class="ui-button ui-widget ui-state-default ui-corner-all ui-button-icon-only">
<span class="ui-button-icon-left ui-icon ui-icon ui-icon-cancel"></span>
<span class="ui-button-text">ui-button</span>
</button>
</td>
</tr>
</tbody>
</table>
</div>
So there are now buttons...why?
I still tried to click the button with xPath "//td[#class='start']//button" but still nothing happend. No Fileupload.
HtmlDriver has javascript enabled and also I'm using NicelyResynchronizingAjaxController(). I already tried waiting for over 30 Seconds but still that doesn't work.
Is there someoone who knows this problem and it's solution...or at least a workaround?
I found the solution by myself.
I was still using selenium 2.40, upgrading to 2.42 solved the problem although the changelog didn't suggested a possible bugfix for my problem.

Assistance with a dynamically generated field

I have another dynamic question for you. I have three input fields that I need to enter values for. These "dijit_form_DateTextBox_36" are created dynamically (the 36 is variable). There is a value earlier in the code that is unique and can be searched for. I know I need to use something like:
driver.findElement(By.xpath("//div[contains(., 'QA GM 04012014 1424 Item Name')]/parent::...somepath.sendKeys("...");
But I am still too new to this stuff to be able to figure it out. And if someone can assist me with what I need to put, as well as how they figured it out, I would greatly appreciate it. I'd really love to solve these on my own! Code is below. Bolded portion is the static text that can be searched. Bolded and italicized lines are the three controls that need to be modified. NOTE: The id="shipDate0_0" is also dynamic, it can be shipDate0_0, shipDate1_0, etc. So can't key on that.
<tr class="tableControlHeader twTableHeaderTR"></tr>
<tr class="tableControlDataRow evenRow twTableTR">
<td class="twTableTD details" align="center" rowspan="2"></td>
<td class="twTableTD details" align="center" rowspan="2">
<p>
<b>
QA GM 04012014 1424 Item Name
</b>
</p>
<br></br>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
</td>
<td class="twTableTD" align="center" rowspan="2"></td>
<td class="twTableTD" align="center"></td>
<td class="twTableTD" align="center"></td>
<td id="shipDate0_0" class="twTableTD" align="center">
<div style="padding-right: 20px;">
<div id="dateWrap-projectedFirstShipDate_0_0" class="inputText_Full twControl twDateSelector" ;="" onblur="updateAvgPerWeek(0,0)" initialvalue="" value="" name="tw#local#quoteComparison#0#country#0#projectedFirstShipDate" style="white-space:nowrap;">
<div id="projectedFirstShipDate_0_0" lang="" dojoattachpoint="pickerDiv" widgetid="projectedFirstShipDate_0_0" name="tw#local#quoteComparison#0#country#0#projectedFirstShipDate">
<span dojoattachpoint="leftPicker">
<div id="widget_dijit_form_DateTextBox_36" class="dijit dijitReset dijitInlineTable dijitLeft dateSelectionSin…tBox dijitComboBox dijitDateTextBox dijitComboBoxOpenOnClick" role="combobox" widgetid="dijit_form_DateTextBox_36">
<div class="dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton dijitArrowButtonContainer" role="presentation" dojoattachpoint="_buttonNode, _popupStateNode" popupactive="true"></div>
<div class="dijitReset dijitValidationContainer"></div>
<div class="dijitReset dijitInputField dijitInputContainer">
<input id="dijit_form_DateTextBox_36" class="dijitReset dijitInputInner" type="text" aria-haspopup="true" role="textbox" dojoattachpoint="textbox,focusNode" autocomplete="off" aria-valuenow="null" aria-invalid="false" tabindex="0" value="" style="" delocalized="null" aria-disabled="false"></input>
<input type="hidden" value=""></input>
</div>
</div>
</span>
<span dojoattachpoint="rightPicker"></span>
<span style="position: absolute;" dojoattachpoint="calImage"></span>
<input id="projectedFirstShipDate_0_0" type="text" isdatefield="true" name="tw#local#quoteComparison#0#country#0#projectedFirstShipDate" style="display:none" dojoattachpoint="hiddenInput" delocalized="null"></input>
</div>
</div>
</div>
</td>
<td id="InDate0_0" class="twTableTD" align="center" ;="" onclick="updateAvgPerWeek(0,0)">
<div style="padding-right: 20px;">
<div id="dateWrap-inDate_0_0" class="inputText_Full twControl twDateSelector" ;="" onblur="updateAvgPerWeek(0,0)" initialvalue="" value="" name="tw#local#quoteComparison#0#country#0#inDate" style="white-space:nowrap;">
<div id="inDate_0_0" lang="" dojoattachpoint="pickerDiv" widgetid="inDate_0_0" name="tw#local#quoteComparison#0#country#0#inDate">
<span dojoattachpoint="leftPicker">
<div id="widget_dijit_form_DateTextBox_35" class="dijit dijitReset dijitInlineTable dijitLeft dateSelectionSin…tBox dijitComboBox dijitDateTextBox dijitComboBoxOpenOnClick" role="combobox" widgetid="dijit_form_DateTextBox_35">
<div class="dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton dijitArrowButtonContainer" role="presentation" dojoattachpoint="_buttonNode, _popupStateNode" popupactive="true"></div>
<div class="dijitReset dijitValidationContainer"></div>
<div class="dijitReset dijitInputField dijitInputContainer">
<input id="dijit_form_DateTextBox_35" class="dijitReset dijitInputInner" type="text" aria-haspopup="true" role="textbox" dojoattachpoint="textbox,focusNode" autocomplete="off" aria-valuenow="null" aria-invalid="false" tabindex="0" value="" style="" delocalized="null" aria-disabled="false"></input>
<input type="hidden" value=""></input>
</div>
</div>
</span>
<span dojoattachpoint="rightPicker"></span>
<span style="position: absolute;" dojoattachpoint="calImage"></span>
<input id="inDate_0_0" type="text" isdatefield="true" name="tw#local#quoteComparison#0#country#0#inDate" style="display:none" dojoattachpoint="hiddenInput" delocalized="null"></input>
</div>
</div>
</div>
</td>
<td id="OutDate0_0" class="twTableTD" align="center" onclick="updateAvgPerWeek(0,0)">
<div style="padding-right: 20px;">
<div id="dateWrap-outDate_0_0" class="inputText_Full twControl twDateSelector" ;="" onblur="updateAvgPerWeek(0,0)" initialvalue="" value="" name="tw#local#quoteComparison#0#country#0#outDate" style="white-space:nowrap;">
<div id="outDate_0_0" lang="" dojoattachpoint="pickerDiv" widgetid="outDate_0_0" name="tw#local#quoteComparison#0#country#0#outDate">
<span dojoattachpoint="leftPicker">
<div id="widget_dijit_form_DateTextBox_34" class="dijit dijitReset dijitInlineTable dijitLeft dateSelectionSin…tBox dijitComboBox dijitDateTextBox dijitComboBoxOpenOnClick" role="combobox" widgetid="dijit_form_DateTextBox_34">
<div class="dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton dijitArrowButtonContainer" role="presentation" dojoattachpoint="_buttonNode, _popupStateNode" popupactive="true"></div>
<div class="dijitReset dijitValidationContainer"></div>
<div class="dijitReset dijitInputField dijitInputContainer">
<input id="dijit_form_DateTextBox_34" class="dijitReset dijitInputInner" type="text" aria-haspopup="true" role="textbox" dojoattachpoint="textbox,focusNode" autocomplete="off" aria-valuenow="null" aria-invalid="false" tabindex="0" value="" style="" delocalized="null" aria-disabled="false"></input>
<input type="hidden" value=""></input>
</div>
</div>
</span>
<span dojoattachpoint="rightPicker"></span>
<span style="position: absolute;" dojoattachpoint="calImage"></span>
<input id="outDate_0_0" type="text" isdatefield="true" name="tw#local#quoteComparison#0#country#0#outDate" style="display:none" dojoattachpoint="hiddenInput" delocalized="null"></input>
</div>
</div>
</div>
</td>
<td id="BuyQuantity0_0" class="twTableTD" align="center" onblur="updateAvgPerWeek(0,0)" name="BuyQuantity0"></td>
<td id="TotalCost0_0" class="twTableTD" align="center" name="TotalCost0"></td>
<td id="NumberOfWarehouses0_0" class="twTableTD" align="center" onblur="updateAvgPerWeek(0,0)" td=""></td>
<!--
# of Warehouses
-->
<td id="AveragePerWarehouse0_0" class="twTableTD" align="center" name="AvgPerWhouseWeek0"></td>
<!--
Cost per Warehouse
-->`enter code here`
<td id="ProjectedSellPrice0_0" class="twTableTD" align="center" td=""></td>
<!--
Projected Sell Price
-->
<td id="PercentOfTotal0_0" class="twTableTD" align="center"></td>
<td class="twTableTD" align="center" rowspan="2"></td>
</tr>
The best xpath I am able to come up with is this:
//td[normalize-space()='QA GM 04012014 1424 Item Name']/following-sibling::td[contains(#id, 'shipDate')]//input[contains(#class,'dijitInputInner')]
Let me explain:
This part finds the td element with the text you're looking for, the normalize-space() call is just like text(), but trims any whitespace before/after the text & I've found it to be invaluable since discovering it a short time ago. text() will return whitespace and is often difficult to match
//td[normalize-space()='QA GM 04012014 1424 Item Name']
This next part finds ALL td's after the previous element. From the code snippet provided this will find ALL 13 td's that follow
/following-sibling::td
Narrow down that set of 13 by finding only the td containing the ID you're interested in, this is better than using a hardcoded number like /following-sibling::td[2] to find the second td
/following-sibling::td[contains(#id, 'shipDate')]
Then find the input field that you're interested in, there are number of ways you could do this, choose whichever you prefer
//input[contains(#class,'dijitInputInner')]
//input[contains(#id,'dijit_form_DateTextBox')]
I hope that's clear enough & works well for you, please let me know if not