Element is no longer attached to the Dom error for link - selenium

I try to get a href from an anchor according to linkText given with func param (for example here Westwood or Linda).
In the code below I changed classes values (cause of company info), but beside thats the code. For each <tr> the hrefs are identical for both <td>, but different from <tr> to <tr>
I get the 1st href with:
driver.findElemnt(By.xpath("//a[#class = 'class Name of a']").getAttribute("href")
or the same with:
xpath="//a[#class = 'class Name of a'][1]";
but when I go:
"//a[#class = 'class Name of a'][2]" or 3 or 4...
or when I use:
By.partialLinkText
It fails, so I never get beyond the 1st <td> of the first <tr>.
The Error: oopenqa.selenium.StaleElementReferenceException : Element
is no longer attached to the Dom.
The Elements are visible all the time, so its not a visibility problem.
This is the html:
<tr class="Class name for tr here">
<td headers="description _ CustomerList:lastName">
Westwood
</td>
<td headers="description _CustomerList:firstName">
Linda
</td>
</tr>

You're trying to retrieve the second anchor tag within the same parent (in the example document: table cells).
Instead of
//a[#class = 'class Name of a'][2]
query the second anchor tag in the whole document:
(//a[#class = 'class Name of a'])[2]
Some more examples how to use positional predicates (I omitted the class predicate here):
Anchor tags from all second table cells per row:
//td[2]/a
Second anchor tag per row:
//tr//a[2]

Related

How to use v-show with dynamic element in Vuejs

I have a dynamic table rendering where columns and rows of the table are rendered dynamically.
So here I have two sibling <td> elements in each row:
<td :key="`td3-${index}`" :id="`show_${key}`" v-show="`show_${key}`">
<input type="text" :v-model="key" :name="key" :value="entry[key]" />
</td>
<td :key="`td4-${index}`">
Edit
</td>
In the onclick event of the link in the second <td> I have to show and hide the first <td> element. Since it's dynamic I will have multiple rows. So I declared a dynamic boolean in my data to show and hide the specific <td> based on the click of another <td> in the same row.
v-show="`show_${key}`" - this is show property with dynamic key
show_firstname: false,
show_lastname: false,
show_email: false,
show_orgname: false
I created separate boolean elements for every <td> in each row.
But whenever I change the value of v-show property with the on click of second <td> element it's not making any difference. So I could not show or hide the <td>. Maybe v-show takes "`show_${key}`" as a string value not replacing true or false correctly. Can someone help me how can I achieve this?
Why don't you try organising the show_ in an object instead of a flat list of properties?
https://codesandbox.io/embed/vue-template-csncc?fontsize=14&hidenavigation=1&theme=dark

How to assign 50% of participants to one survey and 50% to another

I am using the "Survey Link" template to create a project on Mechanical Turk.
I am running an A/B test. I would like to direct 50% of workers to one link, and 50% to another link.
How do I do this?
From the "Design Layout" page, click on "Source". This will let you edit the html/javascript/css for the survey.
You'll find a <table> element with a <tbody> element. Change the <tbody> element to this:
<tbody>
<tr class="survey-one">
<td><label>Survey link:</label></td>
<td><a class="dont-break-out" href="http://link-to-survey-1">http://link-to-survey-1</a></td>
</tr>
<tr class="survey-two">
<td><label>Survey link:</label></td>
<td><a class="dont-break-out" href="http://link-to-survey-2">http://link-to-survey-2</a></td>
</tr>
</tbody>
This simply adds another row to the table for the link for your second survey. Note the link-to-survey-1 and link-to-survey-2 that you'll need to replace with your own links.
A bit lower in the file, you'll see the <style> element. Add this to it:
.survey-hidden {
display: none;
}
And a bit lower, you'll see a <script> element. At the bottom of it, right before the });, add the following javascript:
var surveyToHide = (Math.random() >= 0.5) ? '.survey-one' : '.survey-two';
$(surveyToHide).addClass('survey-hidden');
This randomly picks one of your suveys, and makes it hidden, so that the worker sees only one.

selenium webdriver validate if checkbox is checked

I need to perform validation against the table that is being displayed like this.
code sample how I'm trying to find the checkbox Element
//navigate t the second tr where the input and img tags are stored
List<WebElement> daysCheckBox = this.driver.findElements(By.xpath(".//*[#id='RULE_KEY']/div/div/div/div/div/center[1]/table[2]/tbody/tr[2]/td"));
System.out.println("Test checkbox");
for(WebElement td : daysCheckBox){
System.out.println(td.getTagName());
}
The problems I have is that this table come with 2 tags first row represents the days and the second "checkboxes" as you can see they line up with days, however checkbox have no link to each day. I have tried to solve this with reverse logic to try to identify the input tag if it is disabled. But when the box is selected it turns from input tag into img tag, also when I identify input tags I cannot pinpoint what day deselected box it corresponds to.
Does anyone have any advice or suggestion how to approach this type of validation?
Thank you.
I have put the source to make it clearer how the picture above is presented.
<tbody>
<tr bgcolor="whitesmoke">
<td><b>Sun</b></td>
<td><b>Mon</b></td>
<td><b>Tues</b></td>
<td><b>Wed</b></td>
<td><b>Thurs</b></td>
<td><b>Fri</b></td>
<td><b>Sat</b></td>
</tr>
<tr>
<td><img src="webwb/dhtmlx_iconcheckall.gif" /></td>
<td><input disabled="disabled" type="checkbox" /></td>
<td><input disabled="disabled" type="checkbox" /></td>
<td><input disabled="disabled" type="checkbox" /></td>
<td><img src="webwb/dhtmlx_iconcheckall.gif" /></td>
<td><img src="webwb/dhtmlx_iconcheckall.gif" /></td>
<td><input disabled="disabled" type="checkbox" /></td>
</tr>
</tbody>
You can create method which will convert Your table to Java Map for example:
public static Map<String,String> getTableAsMap(WebDriver driver)
{
Map<String,String> checkboxMap = new TreeMap<>();
List<WebElement> header = driver.findElements(By.xpath("((//tbody/tr)[1])/td/*"));
List<WebElement> checkboxes = driver.findElements(By.xpath("((//tbody/tr)[2])/td/*"));
for(int i = 0;i<header.size();i++){
//Only for testing purpose
System.out.printf("KEY: %s, VALUE: %s\n",header.get(i).getText(),checkboxes.get(i).getAttribute("disabled"));
checkboxMap.put(
header.get(i).getText(),
checkboxes.get(i).getAttribute("disabled")
);
}
return checkboxMap;
}
Then In your main class with driver use:
Webdriver driver = new FirefoxDriver();
Map<String,String> map = getTableAsMap(driver);
System.out.println(map.get("Fri"));
System.out.println(map.get("Sat"));
For disabled (non selected) checkbox You will receive true for selected there will be null. Both as String.
as you haven't posted the code, my answer also doesn't have a code :)
Create the WebElement for second row, i.e. xpath: //tbody/tr[2]
Now traverse all the tds inside this row and check their child element.
If the child element is input you know that checkbox is not selected else it is.
About for which day, you know the first is Sunday and Second is Monday and so on..
The Page Object Model approach may be effective to deal with this scenario. So, you can refresh your page object after some action/set of actions.
Since you mentioned that once a checkbox is checked the tag gets changed for the element, so I assume this can happen multiple times in the page based on user activity.
I can suggest that you implement a callback that reloads the and set the page objects on user action say click. With the page objects, you always have track of all the WebElements, accessibility and any change of state.

Click on specific button based on name of the class or elements

I captured the testName by using driver.find_element_by_xpath("//td[contains(.,'%s')]" % test_name)
How can I capture class name based on testName?
I am trying to click on menu-button if it contains specific test name
<tr class="row-1">
<td>testName</td>
<td>testDes</td>
<td class="menu">
<div class="menu-button">
</div>
</td>
</tr>
This is one possible XPath expression :
//tr[td[contains(.,'testName')]]/td[#class='menu']/div[#class='menu-button']
Basically the above XPath locate tr element having child td value equals "testName", then return the corresponding div[#class='menu-button'] element.

Selenium Webdriver - Retrieve dynamic value in a datagrid

I have a datagrid that I need to retrieve the value next to the item that I can identify dynamically.
What the scenario is trying to do:
This is HTML form a Roles Datagrid which contains a Role Name and a count of permissions. An admin would click on a role, a dialog box would pop up and the admin would update the role and save. The Role count would update. My script checks that the number increments and decrements based on the scenario.
What I'm trying to do is come up with a script that will search based on role name in the "data-rk" attribute and then collect the data in the adjacent permissions count column.
Here is the table:
<tbody id="rolesForm:rolesTable_data" class="ui-datatable-data ui-widget-content">
<tr class="ui-widget-content ui-datatable-even" aria-selected="false" role="row"
data-rk="Role1" data-ri="0">
<td role="gridcell">Role1</td>
<td role="gridcell">
<span id="rolesForm:rolesTable:0:permissions">3</span>
</td>
</tr>
<tr class="ui-widget-content ui-datatable-odd ui-state-hover" aria-
selected="false" role="row" data-rk="Role2" data-ri="1">
<td role="gridcell">Role2</td>
<td role="gridcell">
<span id="rolesForm:rolesTable:1:permissions">38</span>
</td>
</tr>
Any suggestion on how to retrieve that data?
The following code will help you get the count for the specific data-rk attribute that you want. For this example, I am searching for a tr element having data-rk attribute "Role1"
First find the table body element by it's ID attribute and then get the string in the permissions count column from within this element as follows:
WebElement table = driver.findElementById("rolesForm:rolesTable_data");
String pCount = table.findElement(By.xpath("/tr[#data-rk=\"Role1\"]/td[2]")).getText();
// The returned object is a string. If you like, you could convert it to an integer
int count = Integer.parseInt(pCount);
Please note that this code will only return the first tr element that satisfies the condition. If your table is going to have multiple tr elements that satisfy this condition, then you will have to create a list of tr elements and then iterate over them to get the count. You can get the list as follows:
WebElement table = driver.findElementById("rolesForm:rolesTable_data");
List<WebElement> rows = table.findElements(By.xpath("/tr[#data-rk=\"Role1\"]);
// Iterate over rows to get each count
for (WebElement row : rows) {
String pCount = row.findElement(By.xpath("/td[2]")).getText();
// Do whatever you want with pCount
}