I have a product page which has the sizes inside containers, i tried to list elements and get size by text but the list always returns zero, i tried the xpath of the parent and child and i get the same error, How can i list the sizes and select specific size ?
public void chooseSize(String size) {
String selectedSize;
List<WebElement> sizesList = actions.driver.findElements(By.xpath("SelectSizeLoactor"));
try {
for (int i = 0; i <= sizesList.size(); i++) {
if (sizesList.get(i).getText().toLowerCase().contains(size.toLowerCase()));
{
selectedSize = sizesList.get(i).getText();
sizesList.get(i).click();
assertTrue(selectedSize.equals(size));
}
}
} catch (Exception e) {
Assert.fail("Couldn't select size cause of " + e.getMessage());
}
It looks to me like the proper selector would be:
actions.driver.findElements(By.cssSelector(".SizeSelection-option"))
Try below options
List<WebElement> sizesList = actions.driver.findElements(By.xpath("//[#class='SelectSizeLoactor']"));
List<WebElement> sizesList = actions.driver.findElements(By.cssSelector(".SelectSizeLoactor"));
I found a quick solution i used part of the xpath with text() and passed the value of that text later then added the last of the xpath and it worked!
String SelectSizeLoactor = "//button[text()='"
public void chooseSize(String size) {
String selectedSize;
WebElement sizeLocator = actions.driver.findElement(By.xpath(SelectSizeLoactor+size.toUpperCase()+"']"));
try {
if (sizeLocator.getText().toUpperCase().contains(size.toUpperCase()));
{
selectedSize = sizeLocator.getText();
sizeLocator.click();
assertTrue(selectedSize.equals(size));
}
} catch (Exception e) {
Assert.fail("Couldn't select size cause of " + e.getMessage());
}
}
Related
I'm trying to click on element by text from list of elements, but sometimes elements could have the same text and if statement not executed.
public void clickByText() {
String myText = "Text1";
List<WebElement> elements = driver.findElements(myElements);
for (WebElement e : elements) {
if (e.getText().equals(myText)) {
e.click();
break;
} else {
System.out.println("not exists");
break;
}
}
}
Maybe don't look for the text by equals, use contains.
Remove the break from your code, this makes only the else or only the if block to run only once.
code example:
public void clickByText() {
String myText = "Text1";
List<WebElement> elements = driver.findElements(myElements);
for (WebElement e : elements) {
if (e.getText().contains(myText)) {
e.click();
} else {
System.out.println("not exists: " + e.getText());
}
}
}
I think it's an issue with duplicates. since list in Java can contains duplicates, whereas set do not. try the below code :
List<WebElement> elements = driver.findElements(By.cssSelector(""));
Set<WebElement> setElements = new HashSet<WebElement>(elements);
for (WebElement e : elements) {
// rest of your code
}
Appium is able to see and find elements that is not displayed on screen
I am trying to build a test automation project, I would like my driver to scroll down
and then perform some operation. but for some reason appium is able to find element even without scrolling down . I am not sure how appium is able to identify element that is not on screen and is only visible to naked eye when you scroll down. Anyone with similar issue found a workaround ?
I am using ExpectedCondition.visibilityOF(element) to determine if element is vsible on screen
public boolean verifyCoverage(String coverage, String value, String type) throws IOException, InterruptedException {
int counter = 0;
for (int i = 0; i < 15; i++) {
AndroidElement element = (AndroidElement) driver.findElementByAndroidUIAutomator("UiSelector().textContains(\"" + coverage + "\")");
//WebElement coverageOption= driver.findElementByXPath("//android.widget.Button[contains(text(),'"+coverage+"')]");
if (AndroidUtilities.waitForVisibility(driver, element)) {
return true;
}
else {
System.out.println ("Cannot see");
return false;
}
}
public static boolean waitForVisibility(AndroidDriver<WebElement> driver, AndroidElement AndroidElement){
try{
// driver.findElementByAndroidUIAutomator("UiSelector().resourceId(\""+targetResourceId+"\")");
WebDriverWait wait = new WebDriverWait(driver, 60);
wait.until(ExpectedConditions.visibilityOf(AndroidElement));
boolean isElementPresent = AndroidElement.isDisplayed();
return isElementPresent;
}catch(Exception e){
boolean isElementPresent = false;
System.out.println(e.getMessage());
return isElementPresent;
}
}
As an answer i would recommend you to use visibilityOfElementLocated instean of visibilityOf.
Plus, if you want to check an element for the existence without getting exceptions, try to take that approach:
if (!((AndroidDriver)driver).findElementsByAndroidUIAutomator("UiSelector().textContains(\"" + coverage + "\")").isEmpty()) {
//some logic when element is located
} else {
//scroll to the particular element
}
You can try these two solution within the page it will able to scroll to the element and do your actions .
MobileBy.AndroidUIAutomator("new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().textContains(\""+element+"\").instance(0))"));
MobileBy.AndroidUIAutomator("new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().textMatches(\"" + NumbersCount + "\").instance(0))"));
What I want to do is:
1- Going to this site: http://www.emlakyonetim.com.tr/tr-TR/sitelerimiz ,
2- Click on first dropdown - click a city, click second dropdown - click a county, click third dropdown.
At short, second dropdown items are dependant on first one and third dropdown items are dependant on second one.
Code (not complete):
#Test
public void SiteCek() throws InterruptedException
{
driver.get("http://www.emlakyonetim.com.tr/tr-TR/sitelerimiz");
Thread.sleep(2000);
driver.findElement(By.id("select2-city-list-container")).click();
List<WebElement> elm = driver.findElements(By.xpath("//*[#class='select2-results__option']"));
for(int i = 1; i < elm.size(); i++)
{
By ID = By.id(driver.findElements(By.xpath("//*[#class='select2-results__option']")).get(i).getText());
System.out.println(ID);
driver.findElements(By.xpath("//*[#class='select2-results__option']")).get(i).click();
Thread.sleep(500);
}
}
I get java.lang.IndexOutOfBoundsException: Index: 2, Size: 0 error after city "ADANA".
If I manage to handle first error, I will write second and third for loops, so code is this for now.
When the issue is solved I want to get all cities first. Then countys of each city. Then sites of each county. This must be done dynamically as the size of city list, county list and site list. To do that I need three nested for loops. After all of that, each value must be written in excel.
here is the code that worked for me
public void testMethod() {
driver.manage().window().maximize();
WebElement firstDropDown = driver.findElement(By.id("select2-city-list-container"));
firstDropDown.click();
sleep();
List<WebElement> citiesEls = getCitiesEls();
Map<String, Map<String, List<String>>> cityData = new HashMap<>();
for (int i = 0; i < citiesEls.size(); i++) {
//we need to take this element every iteration, because it gets reloaded every time we open the dropdown
WebElement cityEl = driver.findElement(By.id("select2-city-list-results")).findElements(By.xpath("//*[contains(#id,'select2-city-list-result')]")).get(i);
String cityText = cityEl.getText();
cityEl.click();
sleep();
cityData.put(cityText, getRegions());
firstDropDown.click();
sleep();
}
System.out.println(cityData);
}
private Map<String, List<String>> getRegions() {
WebElement secondDropDown = driver.findElement(By.id("select2-region-list-container"));
secondDropDown.click();
sleep();
List<WebElement> regionsEls = getRegionEls();
Map<String, List<String>> regionData = new HashMap<>();
for (int i = 0; i < regionsEls.size(); i++) {
WebElement regionEl = driver.findElement(By.id("select2-region-list-results")).findElements(By.xpath("//*[contains(#id,'select2-region-list-result')]")).get(i);
String regionText = regionEl.getText();
regionEl.click();
WebElement thirdDropDown = driver.findElement(By.id("select2-site-list-container"));
thirdDropDown.click();
List<WebElement> sitesEl = getSiteEls();
List<String> sitesTexts = getSites(sitesEl);
//populate region data
regionData.put(regionText, sitesTexts);
secondDropDown.click();
sleep();
}
return regionData;
}
private List<String> getSites(List<WebElement> sitesEl) {
List<String> sitesTexts = new ArrayList<>();
for (WebElement siteEl : sitesEl) {
sitesTexts.add(siteEl.getText());
}
return sitesTexts;
}
private List<WebElement> getSiteEls() {
WebElement ulSites = driver.findElement(By.id("select2-site-list-results"));
return ulSites.findElements(By.xpath("//*[contains(#id,'select2-site-list-result')]"));
}
private List<WebElement> getRegionEls() {
return driver.findElement(By.id("select2-region-list-results")).findElements(By.xpath("//*[contains(#id,'select2-region-list-result')]"));
}
private List<WebElement> getCitiesEls() {
return driver.findElement(By.id("select2-city-list-results")).findElements(By.xpath("//*[contains(#id,'select2-city-list-result')]"));
}
As data is dynamically changed after each click, you might need some delays after each click. The code below worked well on Mac+Chrome. Nevertheless, if it fails from you end do add a sleep method call after each click.
private void sleep() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
}
Important note: Sleeps are not recommended to use, and should be used only as the quick temporary workaround. More robust solution is to use smart waits
I have this method which tries to count the images that don't have any alt attribute (not even alt='').
private int countImagesWithoutAlt(String page){
int nbImages = 0;
int nbImagesWithoutAlt = 0;
try {
Document dom = Jsoup.connect(page).get();
Elements images = dom.getElementsByTag("img");
nbImages = images.size();
for (Element image : images) {
if(image.attr("alt") == null){
nbImagesWithoutAlt ++;
}
}
return nbImagesWithoutAlt ;
} catch (IOException e) {
System.out.println("Problem on " + page + " : " + e);
return 0;
}
}
The problem is, even if I have <img src="blabla"/>, the condition image.attr("alt") == null is false. How come? And how can I fix this code?
Thanks a lot.
For the ones who want to know why I want to differenciate with no "alt" and with empty "alt" attribute. In my context (accessibility testing), it doesn't always matter if the "alt" attribute is empty. It may mean that the image is only decorative does not need a description. But, if there is no "alt" attribute at all, the screen reader is likely to say "image", which is not relevant for the one using it.
Alright I found a way to do it!
private String countImagesWithoutAlt(String page){
try {
Document dom = Jsoup.connect(page).get();
Elements images = dom.getElementsByTag("img");
int nbImages = images.size();
Elements imagesWithoutAlt = dom.getElementsByTag("img").not("[alt]");
int nBImagesWithoutAlt = imagesWithoutAlt.size();
return page + "," + nbImages + "," + nBImagesWithoutAlt;
} catch (IOException e) {
System.out.println("Problem on " + page + " : " + e);
return null;
}
}
The interesting part is :
Elements imagesWithoutAlt = dom.getElementsByTag("img").not("[alt]");
Using Selenium to gather text of all p elements within a specific div. I noticed while using List, Selenium scanned the whole DOM and stored empty text. So, I wanted to iterate through the DOM and only store values that are not equal to empty text via java.util.Iterator. Is this possible? Is there a more efficient way other than the List approach?
Iterator Approach:
public static boolean FeatureFunctionsCheck(String Feature){
try
{
Iterator<WebElement> all = (Iterator<WebElement>) Driver.Instance.findElement(By.xpath("//a[contains(text()," + Feature + ")]/ancestor::h3/following-sibling::div/div[#class='navMenu']/p"));
boolean check = false;
while(all.hasNext() && check){
WebElement temp = all.next();
if(!temp.getText().equals(""))
{
Log.Info("Functions: " + temp.getText());
all = (Iterator<WebElement>) Driver.Instance.findElement(By.xpath("//a[contains(text()," + Feature + ")]/ancestor::h3/following-sibling::div/div[#class='navMenu']/p"));
}
else
check = true;
}
return false;
}
catch(Exception e)
{
Log.Error("Failed()" + e);
return false;
}
}
Iterator Approach throws exception...
java.lang.ClassCastException: org.openqa.selenium.remote.RemoteWebElement cannot be cast to java.util.Iterator
List Approach Works, However Not Sure If This Is Efficient
public static boolean FeatureFunctionsCheck(String Feature){
try
{
List<WebElement> AllModelFunctions = new ArrayList<WebElement>();
Log.Info("[Test-235]: Selecting Feature");
for(WebElement element: AllModelFunctions){
if(!element.getText().equals(""))
{
Log.Info("Functions: " + element.getText());
}
}
return false;
}
catch(Exception e)
{
Log.Error("Failed()" + e);
return false;
}
}
findElement returns one WebElement. What you probably meant to do is to search for all elements with given xpath, using findElements:
Driver.Instance.findElements(...
Also the syntax is over-complicated. You can just get the list and iterate through it:
List<WebElement> elements = Driver.Instance.findElements(...);
for(WebElement element : elements) {
if(!element.getText().equals(""))
{
Log.Info("Functions: " + element.getText());
}
}
BTW I have to fully trust that Driver.Instance is an instance of the driver (typically in Java you don't have capitals for class instances, so I'm not sure if I understood it right). A more common syntax would be something like:
WebDriver driver = new FirefoxDriver(); // or another browser
driver.findElements(...);
// ...