Selenium couldn't find an element inside the iframe - selenium

I am creating an automated test cases for this page https://cloud.google.com/products/calculator in scope of my practical task using Selenium + Java.
At some point I've faced with a problem when the WebDriver couldn't find an element inside the iframe, even if in the previous test case I was able to interact with the elements of this iframe.
All my test cases are running one by one without closing the driver and each next test case can passed only if the previous test case passed as well.
Here is my GitHub repo:
https://github.com/SerhiiVeselov/hurt-me-planty.git
Here are my test cases:
#BeforeAll
public static void driverSetup() {
driver = new ChromeDriver();
driver.manage().window().maximize();
mainPage = new MainPage(driver);
searchResultsPage = new SearchResultsPage(driver);
pricingCalculatorPage = new PricingCalculatorPage(driver);
fluentWait = new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(10))
.pollingEvery(Duration.ofSeconds(2))
.ignoring(NoSuchElementException.class);
}
#Test
#Order(1)
#DisplayName("Search of the Pricing Calculator page")
public void openPricingCalculator() {
mainPage.openPage();
fluentWait.until(ExpectedConditions.visibilityOf(mainPage.getCookiesOkBtn()));
mainPage.closeCookiesPopUp();
mainPage.openSearchField();
mainPage.enterSearchRequest();
fluentWait.until(ExpectedConditions.visibilityOf(mainPage.getSuggestSearchResult()));
mainPage.clickSuggestSearchResult();
fluentWait.until(ExpectedConditions.visibilityOf(searchResultsPage.getSearchResultsTab()));
searchResultsPage.clickPricingCalculatorLink();
assertEquals("https://cloud.google.com/products/calculator", driver.getCurrentUrl());
fluentWait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(pricingCalculatorPage.getCloudSideFrame()));
fluentWait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt((pricingCalculatorPage.getMyFrame())));
}
#Test
#Order(2)
#DisplayName("Fill the Calculation Form")
public void fillCalculationForm() {
pricingCalculatorPage.enterNumberOfInstances();
pricingCalculatorPage.selectOperatingSystem();
pricingCalculatorPage.selectProvisioningModel();
pricingCalculatorPage.selectMachineType();
pricingCalculatorPage.checkAddGpuCheckBox();
pricingCalculatorPage.selectGpuType();
pricingCalculatorPage.selectGpuQuantity();
pricingCalculatorPage.selectLocalSsd();
pricingCalculatorPage.selectDatacenterLocation();
pricingCalculatorPage.addToEstimate();
fluentWait.until(ExpectedConditions.visibilityOf(pricingCalculatorPage.getTotalEstimatedCost()));
assertEquals("Instance type: n1-standard-8", pricingCalculatorPage.getInstanceTypeTest().getText());
}
#Test
#Order(3)
#DisplayName("Check the name of the Machine type")
public void verifyMachineType() {
assertEquals("Instance type: n1-standard-8", pricingCalculatorPage.getInstanceTypeTest().getText());
}
Here is the webpage for which I've created 2d and 3d test cases: https://cloud.google.com/products/calculator
page for automation in 2d and 3d test cases
So far, 1st and 2d test cases are passing and working as expected. But 3d test case is failing all the time cause the WebDriver couldn't find the element from the getInstanceTypeTest method:
org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"xpath","selector":"//div[contains(text(), 'Instance type')]"}
Most of elements I interested in are located inside the same iframe (id=myFrame).
I have a selector for instanceTypeTest WebElement creared using xpath //div[contains(text(), 'Instance type')].
In 3d test case I want to check this field and get from it a text value to compare it with the value which was selected at the left form at https://cloud.google.com/products/calculator page.
I guess, after I filling the left form with data and clicking the 'ADD TO ESTIMATE' button something is happening with the iframes or the driver is loosing it's focus to the right frame.
I tried to add at the beginning of the 3d test case some code which should take driver back to the default web page content and then switch driver to outer iframe (cloudSideFrame) and after that - to inner iframe (myFrame):
driver.switchTo().defaultContent(); fluentWait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(pricingCalculatorPage.getCloudSideFrame())); fluentWait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt((pricingCalculatorPage.getMyFrame())));
It didn't help me. Driver still couldn't find Instance type field.
I can't understand why driver could find some elements inside the iframe even if it could find some others inside the same iframe.
Please help me to solve this problem.

Related

Selenium: How to assert that image is displayed under a certain section of a webpage

I am attempting to write a test that is able to do the following:
1. Navigate to a website.
2. Navigate to a page under the menu.
3. Once in that page, assert that the image I want is displayed under a section labeled "SECTION".
Here is my code (approach 1):
public void test1() throws Exception {
WebElement compare_image = driver.findElement(By.linkText("URL link where the image is located"));
driver.get("website URL");
WebElement image = driver.findElement(By.cssSelector("cssSelector for image from FireFox -> inspect element -> copy CSS selector"));
assertEquals(image, compare_image); }
I am very new to Selenium and QA automation, so any detailed help would be appreciated as my google searches so far are coming up short. It is giving me an element not present exception for the findElement call, but I don't know why as I tried all the Bys I could get from inspect element.
Am I approaching this correctly? If not, what can I do differently?
If you want to check image is present or not under a section then you have to create a webelement for that section.
WebElement section= driver.findElement(By.xpath("//img(#class=‘Section')"));
Now create an image element under section element.
WebElement image= section.findElement(By.xpath("//img(#class=‘Test Image')"));
Now check image is exist or not.
boolean imagePresent = image.isDisplayed();
Now assert on boolean result.
assertTrue(imagePresent, “No image is exist”);
Note: Please take care of locators for section and Image as you didn’t provide Html for it. Code will work perfectly.

Selenium - move page to front

I am performing a web page scrape and update using Selenium and phantomJS webdriver. At one stage, completing one page can bring up either page_A or page_B. The page I want is page_B. If page_A appears, I can locate the elements:
<li class="menu_item">
<a class="menu_item_anchor_selected" href="#page_a">Page_A</a>
</li>
<li class="menu_item">
<a class="menu_item_anchor" href="#page_b">Page_B</a>
</li>
and I can then extract the target from the anchor to page_B. However, once loaded by the driver, every element on page_B remains invisible.
public class fill_page_B (WebDriver driver, String target) throws Exception
{
String currentUrl = driver.getCurrentUrl;
String page_B_Url = currentUrl + target;
driver.get (page_B_Url);
// prove that page_B actually loaded
String page = driver.getPageSource ();
System.println (page);
WebElement we = driver.findElement (By.id ("MyId"));
// ignore test for we exists; it does
WebDriver wait = new WebDriverWait (driver, 60); // should be long enough!
wait.until (ExpectedConditions.visibilityOf (we)); // fails
. . .
}
I have tried using:
driver.manage().window().maximize();
and other tricks to ensure the window hasn't shrunk to make the required control outside the viewable window and other, similar tricks to make sure it hasn't migrated off the screen entirely.
I have also tried:
JavascriptExecutor jse = (JavascriptExecutor) driver;
jse.executeScript ("arguments[0].checked=true;", we);
to force the element to be visible. This approach however merely threw an Exception "cannot click on option element. Executing JavaScript click function returned an unexpected error etc."
However, when I ran my application again, this time using an Internet Explorer driver, I noticed that when I got page_B (and proved it by displaying the page contents in the system log), page_A was still visible. I did try resizing page_A (which was previously maximized) before getting page_B, but this made no difference; everything on page_B remained invisible and unclickable.
Any suggestions as to how Selenium could deal with this?

How to find element in frame in Selenium

I used below code for finding the element in the frame but I got the error
kindly explain by this framebyinedex, framebystring, framebywebelement:
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
public class Framebyindex
{
public static void main(String[] args)
{
WebDriver f1=new FirefoxDriver();
f1.get("http://spicareers.com/spicareers/");
f1.switchTo().frame(1);
f1.findElement(By.linkText(" .Net - Senior Developer ")).click();
}
}
The error is:
Exception in thread "main" org.openqa.selenium.NoSuchElementException: Unable to locate element: {"method":"link text","selector":" .Net - Senior Developer "}
Before you have to switch to the frame:
driver.get("http://spicareers.com/spicareers/");
WebElement frame= driver.findElement(By.xpath("//frame[#name='JRAMPSMainFrame']"));
driver.switchTo().frame(frame);
and after you could try with:
WebElement myEl= driver.findElement(By.xpath("//*[contains(text(), ' .Net - Senior Developer ')]"));
myEl.click();
Finally, if you want to switch back:
driver.switchTo().defaultContent();
EDIT
The interested element is inside the iframe with name "JRAMPSMainFrame". If you inspect your html, you could notice this:
NoSuchElementException simply means that, the selenium did not detect a link with the text as you asked it.
I suggest you to work with use by.xpath to resolve it. To get the xpath of the element, take the below steps on your chrome, or firefox browser.
Right click on the element (here the link)
Click on inspect. It opens the inspect console (Elements tab) in your browser, and highlights the clicked element.
Right click on the element in the elements tab
Choose copy
Copy Xpath
In your code, replace By.linkText with By.xpath
Paste the value as an string into the xpath("you paste here")
Or simpler, watch this video
Seems like you have selected a wrong frame or the link text might contain more spaces.
Chrome developer tools is your best friend in this situation. Use it to find the element correctly and to identify the frame.
SELECT FRAME
Open the application in chrome.
Open developer tools
Click Console tab of developer tool
Select you frame from the drop down
In the above picture there is only one frame.
FIND ELEMENT
After selecting the frame, type $x("//a[normalize-space(.) = '.Net - Senior Developer']") to check your xpath.
$x("") is the function for checking xpath in browser.
Using the above mechanism find the frame and the element.
Cheers!
If you take a closer look at the HTML of http://spicareers.com/spicareers/ the WebElement with text as .Net - Senior Developer is within an <iframe> tag. So before accessing the intended WebElement we have to switch to the frame first either through the frame_name, frame_id or frame_index as follows:
System.setProperty("webdriver.chrome.driver", "C:\\Utility\\BrowserDrivers\\geckodriver.exe");
WebDriver driver = new FirefoxDriver();
driver.get("http://spicareers.com/spicareers/");
driver.switchTo().frame("JRAMPSMainFrame"); //using "frame_name"
WebElement elem = driver.findElement(By.xpath("//*[contains(text(), ' .Net - Senior Developer ')]"));
elem.click();
You can use this code, First enter into the frame using name locator and try to locate the career option then
Try this code, I have modified your code:
public class Framebyindex
{
public static void main(String[] args)
{
WebDriver f1=new FirefoxDriver();
f1.get("http://spicareers.com/spicareers/");
f1.switchTo().frame( f1.findElement(By.name("JRAMPSMainFrame")));
WebElement netCareer= f1.findElement(By.xpath("//*[contains(text(), ' .Net - Senior Developer ')]"));
netCareer.click();
}
}
By using:
https://github.com/nick318/FindElementInFrames
you can write following:
SearchByFramesFactory searchFactory = new SearchByFramesFactory(driver);
SearchByFrames searchInFrame = searchFactory.search(() -> driver.findElement(By.xpath("//*[contains(text(), ' .Net - Senior Developer ')]")));
searchInFrame.getElem().ifPresent(WebElement::click);

Selenium - clicking on youtube links

I just tried to open the first search result of the youtube link.
Here is my code. Since the youtube results are in iFrame, I used SwitchTo.frame()method.
String browser = "Chrome";
WebDriver b = null;
if(browser.equals("Chrome")) {
System.setProperty("webdriver.chrome.driver", "C:\\chromedriver_win32\\chromedriver.exe");
b = new ChromeDriver();
}
else if (browser.equals("firefox")) {
b = new FirefoxDriver();
}
b.get("http://www.youtube.com/");
b.findElement(By.xpath("//*[#id='masthead-search-term']")).sendKeys("selenium tutorial for beginner");
b.findElement(By.xpath("//*[#id='masthead-search-term']")).sendKeys(Keys.RETURN);
b.switchTo().frame("pyv-iframe"); //youtube search results are in iframe
//b.findElement(By.linkText("Selenium IDE Demo - Quick Beginner's Tutorial")).click();
b.findElement(By.xpath("//*[#id='search-results']/li[1]/div[2]/h3/a/span")).click();
While running this code it returns as
Exception in thread "main" org.openqa.selenium.NoSuchElementException: no such element
at findElement By xpath. Please tell me what am I missing. Please see me as a newbie to Selenium.
I'm not sure why you are saying that the results are in an <iframe>... I'm not seeing an iframe. Here is your script using the getting started with selenium framework:
#Config(url="http://youtube.com")
public class YouTubeTest extends AutomationTest {
#Test
public void myTest() {
setText(By.id("masthead-search-term"), "selenium tutorial for beginner")
.click(By.id("search-btn"))
// navigate to a search result based on index
.click(By.cssSelector("ol#search-results > li:nth-child(X) a.yt-uix-tile-link"))
;
}
}
on the click(By.cssSelector you need to replace the X value with 1, 2, etc.. whatever the index of the link you want to click is.
(If you aren't using that framework you can easily translate the code and extract the selectors I use)
I did investigate on the Youtube page in Selenium IDE and it did get me these results:
driver = new FirefoxDriver();
baseUrl = "http://www.youtube.com/";
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
driver.get(baseUrl + "/results?search_query=selenium&sm=3");
driver.findElement(By.id("masthead-search-term")).clear();
driver.findElement(By.id("masthead-search-term")).sendKeys("selenium");
driver.findElement(By.cssSelector("span.yt-ui-ellipsis-wrapper")).click();
Please note the last line: Thats where I clicked on the first search result. After investigating the Youtube page with Web Developer tools I realised that here is a iframe but it contains only some tracking code for AdSense (my guess)
General note: Always try to investigate with Selenium IDE first. It saved me from a lots of nightmares about my selenium code ;)

selenium span link li not working

I am new to selenium. I am practicing to write a test case on http://www.countdown.tfl.gov.uk. Below are the steps I followed:
a) I opened the browser to selenium Web Driver
b) Found the search text Box and enter H32 and clicked on search button to selenium.
Till this part it works fine.
Now on the page I am actually getting two records on the left side of the page under the search. I am actually trying to click on the first one i.e. "Towards Southall,Townhall" link. Nothing is happening.
Below is my code:
public class CountdownTest {
#Test
public void tflpageOpen(){
WebDriver driver = openWebDriver();
searchforBus(driver,"H32");
selectrouteDirection(driver)
}
//open the countdowntfl page
private WebDriver openWebDriver(){
WebDriver driver = WebDriverFactory.getWebDriver("FireFox");
driver.get("http://www.countdown.tfl.gov.uk");
return driver;
}
private void searchforBus(WebDriver driver,String search){
WebElement searchBox = driver.findElement(By.xpath("//input[#id='initialSearchField']"));
searchBox.sendKeys(search);
WebElement searchButton = driver.findElement(By.xpath("//button[#id='ext-gen35']"));
searchButton.click();
}
private void selectrouteDirection(WebDriver driver){
WebElement towardssouthallLink= driver.findElement(By.xpath("//span[#id='ext-gen165']']"));
((WebElement) towardssouthallLink).click();
}
}
Please help me.
Thanks.
Since you are getting NoSuchElement Exception now, you may try the following code with the usage of WebDriver explicit wait.
WebDriverWait wait = new WebDriverWait(driver, 15);
WebElement towardssouthallLink = wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("(//*[#id='route-search']//li/span)[1]")));
towardssouthallLink.click();
Or WebDriver implicit wait
WebDriver driver = WebDriverFactory.getWebDriver("FireFox");
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
driver.get("http://www.countdown.tfl.gov.uk");
Tips:
The search results need some time to be retrieved, so please use Explicit wait or Implicit wait.
Don't use locators like span[#id='ext-gen165'], they are ExtJs auto generated.
In this case, css selector can also be used: #route-search li:nth-of-type(1) > span
You aren't calling selectrouteDirection.
You probably want:
#Test
public void tflpageOpen(){
WebDriver driver = openWebDriver();
searchforBus(driver,"H32");
selectrouteDirection(driver);
}
You also don't need to cast here:
((WebElement) towardssouthallLink).click();
It's already a WebElement anyway.
I found that id for those links are dynamically generated. ids are of the form 'ext-genXXX' where XXX is number which is dynamically generated hence varies each time.
Actually, you should try with linkText:
For 'Towards Southall, Town Hall'
driver.findElement(By.linkText("Towards Southall, Town Hall")).click
For 'Towards Hounslow, Bus Station'
driver.findElement(By.linkText("Towards Hounslow, Bus Station")).click
Here is a logic:
Get all elements which have id starts with 'ext-gen' & iterate over it & click on link with matching text. Following is Ruby code(sorry, I don't know Java well):
links = driver.find_elements(:xpath, "//span[starts-with(#id, 'ext-gen')]")
links.each do |link|
if link.text == "Towards Southall, Town Hall"
link.click
break
end
end