TestCafe - Get value of attribute in a dropdown list - testing

There is a search bar with a button to filter. Clicking on the same submenu (dropdown) is displayed. The HTML looks like :
<ul >
<li data-value"svalue1">
<svg>.... </svg>
<p> Value1 </p>
</li>
<li data-value"svalue2">
<svg> ....</svg>
<p> Value2 </p>
</li>
<li data-value"svalue3">
<svg> </svg>
<p> Value3 </p>
</li>
I need to retrieve the values of options as an array and compare.
I am able to assert a single value but unable to store it in an array to compare all together.
var tab = Selector('ul');
-
-
.expect(tab.child('li').nth(3).innerText)
.eql('Value3', 'The value is not correct');
But this doesn't work
for (let i = 0; i < 6; i++) {
myArray.push(tab.child('li').nth(i).innerText);
console.log("value:" + tab.child('li').nth(i).innerText);
}
Prints: value:[object Object]
Any idea?

You need to add the 'await' keyword. For instance:
for (let i = 0; i < 6; i++) {
console.log("value:" + await tab.child('li').nth(i).innerText);
}
Refer to the 'Access Page Element Properties' topic to find this note:
Note that selector's property getters and client functions are asynchronous. If you need their resulting value in your code, use the await keyword. However, you can omit await when you pass a selector property or a client function value into an assertion.

Related

I am facing an issue in retrieving all the list items using selenium webdriver

Problem : I have a list of items inside a div class msb-container.
.There are 162 items in the list .I want to click the 150th item from the list .There also a scroll bar through which we can go doen to other elemenst and select it
How the html looks like :
<div class="mCSB_container" style="position:relative; top:0;">
<ul id="ul-countries">
<li>
<input id="country-3" type="checkbox" name="c:3">
<label for="country-3">Afghanistan</label>
</li>
<li>
<input id="country-6" type="checkbox" name="c:6">
<label for="country-6">Albania</label>
</li>
---other countries
</li>
</ul>
</div>
How my code looks like :
IList<IWebElement> countryList = driver.FindElements(By.XPath("//*[#id='ul-countries']/li"));
for (int i = 0; i <= countryList.Count; i++)
{
string temp = countryList.ElementAt(i).Text;
if (countryList.ElementAt(i).Text == "Brazil")
{
//do something
}
}
I am getting a correct count of 162 countries but i think they are not filled correctly .As when I try to retrieve the text from even the 15th country it gives me empty result .It only fills the text for those list item which can be seen on the screen .Although when I inspect element I can see all the required data in list item through html but not through my code .I tried to put the sleep to but no luck .
Please provide your inputs to solve the above issue.
|
Kindest Regards
IList<IWebElement> countryList = driver.FindElements(By.XPath("//*[#id='ul-countries']/li"));
for (int i = 0; i <= countryList.Count; i++)
{
string temp = countryList.ElementAt(i).findElement(By.CSS("label")).getText();
if (temp.equals("Brazil"))
{
//do something
}
}

Testing relative positions of elements

On the page under test I have the following Support link:
Which is represented with the following HTML:
<div class="ap-version-panel ap-version-support">
<i class="fa fa-external-link"></i>Support
</div>
What I'm trying to is to test that the icon is located before the "Support" text. How can I do that?
I've tried the following - locate the icon element with an XPath that additionally checks that there is "Support" text after and check if the element is present:
expect(element(by.xpath("//text()[. = 'Support']/preceding-sibling::i[contains(#class, 'fa-external-link')]")).isPresent().toBe(true);
This works but it is quite ugly and I don't like that the actual position check is hidden inside the XPath expression which is not really readable and reliable.
I recommend changing the product under test by adding a <span> and move the text "Support" into the <span>.
<div class="ap-version-panel ap-version-support">
<i class="fa fa-external-link"></i><span>Support<span>
</div>
But if you cannot change the product, you can use javascriptExecutor to get childNodes then check order of the nodes:
var aFunctionToCheckOrder = function (arguments) {
var nodes = arguments[0].childNodes;
var result;
// Check nodes[0] = <i>
// Check node [1] is textNode and its value = "Support"
return result;
}
var supportLink = element(by.linkText("Support"));
browser.executeScript(aFunctionToCheckOrder, supportLink).then(...)
As you can see, it is more uglier than your solution. You'd better change your product under test.

Verify a text in the dropdown

I am trying to verify if the text is present in the dropdown menu. My assertion shows all the items, but with an error...expected[]but found[]. Please find below my script and the test failure message. Thanks in advance for the help!
My Script:
driver.findElement(By.cssSelector("#s2id_autogen4 > a.select2-choice > span")).click();;
ArrayList<String> expectedDropDownItems = new ArrayList<String>();
expectedDropDownItems.add("keysearch");
expectedDropDownItems.add("short");
expectedDropDownItems.add("standard");
expectedDropDownItems.add("to-date");
Assert.assertEquals(expectedDropDownItems, driver.findElement(By.xpath(".//*[#id='select2-drop']/ul")).getText());
ERROR MESSAGE:
java.lang.AssertionError: expected [keysearch
short
standard
to-date] but found [[keysearch, short, standard, to-date]]
HTML:
<div style="top: 1973px; left: 261px; width: 500px; display: block;" class="select2-drop select2-with-searchbox select2-drop-active" id="select2-drop">
<div class="select2-search">
<input type="text" class="select2-input" autocomplete="off" tabindex="0">
</div>
<ul class="select2-results" style="">
<li class="select2-results-dept-0 select2-result select2-result-selectable">
<div class="select2-result-label">
<span class="select2-match"></span>keysearch</div></li>
<li class="select2-results-dept-0 select2-result select2-result-selectable">
<div class="select2-result-label">
<span class="select2-match"></span>short</div></li>
<li class="select2-results-dept-0 select2-result select2-result-selectable">
<div class="select2-result-label">
<span class="select2-match"></span>standard</div></li>
<li class="select2-results-dept-0 select2-result select2-result-selectable" style="">
<div class="select2-result-label">
<span class="select2-match"></span>to-date</div></li></ul>
</div>
What you can do is,
1- First get all the elements of the dropdown.
2- Put it in a List
3- Iterate over the list, get texts of each element and then put it in a new ArrayList of Strings.
4- Assert using this ArrayList and the Original ArrayList of items.
Below code will help you out:
//Putting actual items in the Arraylist of expectedDropDownItems
ArrayList<String> expectedDropDownItems = new ArrayList<String>();
expectedDropDownItems.add("keysearch");
expectedDropDownItems.add("short");
expectedDropDownItems.add("standard");
expectedDropDownItems.add("to-date");
//Iterating over expected items and printing
System.out.println("\n--- Expected Items");
for(int i=0;i<expectedDropDownItems.size();i++)
System.out.println(expectedDropDownItems.get(i));
System.out.println("\n");
ArrayList<String> actualDropDownItems = new ArrayList<String>();
//Getting the list of all items in dropdown
List<WebElement> elements = driver.findElements(By.xpath("//div[#class='select2-result-label']"));
//Iterating over the list of dropdown, getting text of each element and adding the text to the Arraylist of actualDropDownItems
for(WebElement element : elements){
System.out.println("Adding element: "+ element.getText());
actualDropDownItems.add(element.getText());
}
//Iterating over actual items and printing
System.out.println("\n--- Actual Items");
for(int i=0;i<actualDropDownItems.size();i++)
System.out.println(actualDropDownItems.get(i));
//Asserting the ArrayLists if they are equal or not
Assert.assertEquals(expectedDropDownItems, actualDropDownItems);
System.out.println("Asserted text match");
According to assertion i can suppose and suggest to do next on attempt to fix your problem (p.s. i'm not good at java, but according my exp in C#):
1. Try to print data returned from driver.findElement(By.xpath(".//*[#id='select2-drop']/ul")).getText() code and make sure that this data really equals to your data from arrayList.
2. If data seem equal, try another assertion methods (such as Assert.That(object, matcher) (e.g. in C# in could be Assert.That(new[]{1}, Is.EquivalentTo(new[]{1}));), Assert.arrayEquals etc)
If both arrays are equal and asserts not help, please provide sample of html and we will try to solve that problem in other way.

Identifying the Web element with same class name in Selenium

I have tried to get the number of tweets(tweet count) through selenium
Here is the page source:
<li class="DashboardProfileCard-stat Arrange-sizeFit">
<a class="DashboardProfileCard-statLink u-textUserColor u-linkClean u-block"
title="1 Tweet"
href="/saisiva14"
data-element-term="tweet_stats">
<span class="DashboardProfileCard-statLabel u-block">Tweets</span>
<span class="DashboardProfileCard-statValue" data-is-compact="false">1</span>
</a>
</li>
<li class="DashboardProfileCard-stat Arrange-sizeFit">
<a class="DashboardProfileCard-statLink u-textUserColor u-linkClean u-block"
title="38 Following"
href="/following"
data-element-term="follower_stats">
<span class="DashboardProfileCard-statLabel u-block">Following</span>
<span class="DashboardProfileCard-statValue" data-is-compact="false">38</span>
</a>
</li>
<li class="DashboardProfileCard-stat Arrange-sizeFit">
<a class="DashboardProfileCard-statLink u-textUserColor u-linkClean u-block"
title="4 Followers"
href="/followers"
data-element-term="following_stats">
<span class="DashboardProfileCard-statLabel u-block">Followers</span>
<span class="DashboardProfileCard-statValue" data-is-compact="false">4</span>
</a>
</li>
I could not able to locate the web element for getting Tweets,Followers & following. The reason is span class names are common for all these elements.Please help me .
To get number of Tweets/ Following/ Followers, You can try the below statements:
System.out.println(driver.findElement(By.xpath("//a[contains(#title, 'Tweet')]/span[2]")).getText());
System.out.println(driver.findElement(By.xpath("//a[contains(#title, 'Following')]/span[2]")).getText());
System.out.println(driver.findElement(By.xpath("//a[contains(#title, 'Followers')]/span[2]")).getText());
To click on the Tweets/ Following/ Followers links, You can try the below statements:
driver.findElement(By.xpath("//a[contains(#title, 'Tweet')]")).click();
driver.findElement(By.xpath("//a[contains(#title, 'Following')]")).click();
driver.findElement(By.xpath("//a[contains(#title, 'Followers')]")).click();
or
driver.findElement(By.xpath("//a[./span[text()='Tweets']]")).click();
driver.findElement(By.xpath("//a[./span[text()='Following']]")).click();
driver.findElement(By.xpath("//a[./span[text()='Followers']]")).click();
The above statements are working fine for me.
try this
IList<IWebElement> elements = driver.FindElements(By.ClassName("DashboardProfileCard-stat"));
foreach (IWebElement element in elements)
{
IWebElement ele = element.FindElement(By.ClassName("DashboardProfileCard-statLabel"));
if (ele.Text == "Tweets")
{
return element.FindElement(By.ClassName("DashboardProfileCard-statValue")).Text;
}
}
this is using C#, you can modify accordingly if anyother language is used.
The selector .DashboardProfileCard-stat span:nth-child(2) should give you the collection of web elements pointing to the count. For example in Java:
ArrayList<WebElement> elements = driver.findElements(By.cssSelector(".DashboardProfileCard-stat span:nth-child(2)"))
Then you can use elements.get(0).getText() for tweets. elements.get(1).getText() for following. elements.get(2).getText() for followers. So:
ArrayList<WebElement> elements = driver.findElements(By.cssSelector(".DashboardProfileCard-stat span:nth-child(2)"));
int tweets = elements.get(0).getText();
int following = elements.get(1).getText();
int followers = elements.get(2).getText();
Of course, do your appropriate safety checks, etc. Check the length of the array before access.
This code is in Java :)
capture all the parents of the "SPAN" into a collection item.
Iterate on the collection to find the span elements (which are child of <a> tag) and capture text based on the class name variation statLabel / statValue".
List<WebElement> webElement = driver.findElements(By.xpath("//li[#class='DashboardProfileCard-stat Arrange-sizeFit']//a"));
for (WebElement element : webElement) {
System.out.println(element.findElement(By.xpath("//span[contains(#class,'statLabel')]")).getText());
System.out.println(element.findElement(By.xpath("//span[contains(#class,'statValue')]")).getText());
}

Selenium get dynamic ID XPath

I'm new on Selenium, new here and my english is not the best.
I'm using selenium with .NET ...
I have a HTML page like this but the number of the events are different:
<div id="eventContent" style="text-align: center;">
<div class="event" id="event-8971062">
<ul>
<li ...></li>
<li ...></li>
<li ...></li>
</ul>
</div>
<div class="event odd" id="event-9224880">
<ul>
<li ...></li>
<li ...></li>
<li ...></li>
</ul>
</div>
</div>
I need to check all datas in the different divs but the count is dynamic and the (event)id is dynamic too. I'm trying to find out the count of the divs at first but this does'nt work. For that I try this:
DefaultSelenium selenium = new DefaultSelenium(...);
decimal count = selenium.GetXpathCount("//div[#id='eventContent']");
but this brings only 1 as result and not two for this example.
when I try:
Console.WriteLine(selenium.GetText("//div[#id='eventContent'][1]"));
it prints all divs, but when I do:
Console.WriteLine(selenium.GetText("//div[#id='eventContent'][1]/div"));
it prints only the first div and I do not understand why.
Could someone be so kind and give me an explaination of whats going on here and where I'm wrong?
Thanks in advance
elur
decimal count = selenium.GetXpathCount("//div[#id='eventContent']");
This will return the count of divs that have an id of eventContent - there is only one div like this, which is why you get a count of 1 (count variables are typically ints rather than decimals, incidentally).
If you want the count of the contained divs, use
int count = selenium.GetXpathCount("//div[#id='eventContent']/div");
This will count the number of div children of the div with an id of eventContent. This should return 2, as desired.
As for your GetText examples, I think GetText will only return the text of the first node that the xpath argument selects. So with
selenium.GetText("//div[#id='eventContent'][1]")
you get the entire text of the parent div, which naturally contains all the child divs, but with
selenium.GetText("//div[#id='eventContent'][1]/div")
you get the text of only the first child div. This xpath selects all the child divs, but GetText operates on a single element only, I believe. If you want to examine the text of each child div in turn, you'll need to first get a count of the child divs, then use for loop to get each one in turn:
for(int i = 1; i <= count; ++i)
{
string childXpath = "//div[#id='eventContent']/div[" + i + "]";
string eventText = selenium.GetText(childXpath);
// Processing of eventText
}
A for loop and manual xpath processing are needed here (rather than the neater foreach), as I believe Selenium doesn't have a way of taking an xpath and returning a collection of elements.
tryed this but returns with 0. I solved this with a while expression where I check with isElementPresent like this:
int a = 1;
while (selenium.IsElementPresent("//div[#id='eventContent'][1]/div[" + a + "]"))
{
// check data here
a++;
}
seems to work so. thanks a lot for your help,
best regards elur