Unable to get elements from HTML web page - c#

I'm trying to populate an HTML web page (http://wasitviewed.com) in C# using Selenium but no matter what i try, it always crashes when I try and find the website elements with the following error:
OpenQA.Selenium.NoSuchElementException: 'no such element: Unable to locate element: {"method":"name","selector":"href"}
I'm using the below code:
using (IWebDriver driver = new ChromeDriver())
{
driver.Navigate().GoToUrl("http://www.wasitviewed.com/");
IWebElement query = driver.FindElement(By.Name("href"));
query.SendKeys("test");
}
I've also tried using xPath but that also fails.
Is there an easier way to find the elements of the web page or is there a way i can loop through the whole web page to find the different elements and their respective id's?

In the above mentioned URL, all the elements are resides within an iframe. So, you need to move the foucs into the frame before finding the query element,otherwise NoSuchElementException will be thrown.
Whenever any element is present inside the iframe, you need to move the foucs to the frame using any one of the below startegy.
Using Index:
Index starts frame 0.So, you can switch to the frame using the index as below
driver.SwitchTo().Frame(0);//Here only one frame is available.so, Index is 0
Using Frame Name or Id:
Select a frame by its (frame) name or ID. name attributes are always given precedence over the id attributes.
driver.SwitchTo().Frame(<<Frame Name or ID>>);
Currently, frame name/id is not available in the mentioned URL.
So, you cannot use the Frame name or ID.
Using Frame WebElement:
You need to find the Frame WebElement using any one of the Locator strategies (Name,Id,ClassName,TagName,XPath,CssSelector)
and it can be used to move the foucs to the respective frame.
//Here only one frame is available.So, I have used FindElement
var frameElement= driver.FindElement(By.TagName("iframe"));
driver.SwitchTo().Frame(frameElement);
Working Code:
Option 1 :
using (IWebDriver driver = new ChromeDriver())
{
driver.Navigate().GoToUrl("http://www.wasitviewed.com/");
driver.SwitchTo().Frame(0);
IWebElement query = driver.FindElement(By.Name("href"));
query.SendKeys("test");
}
Option 2:
using (IWebDriver driver = new ChromeDriver())
{
driver.Navigate().GoToUrl("http://www.wasitviewed.com/");
var frameElement= driver.FindElement(By.TagName("iframe"));
driver.SwitchTo().Frame(frameElement);
IWebElement query = driver.FindElement(By.Name("href"));
query.SendKeys("test");
}

Your required <input> element is inside an iframe. You need to switch to that before performing actions on any elements inside the iframe.
IWebElement yourIFrame= driver.FindElement(By.XPath("//iframe"));
driver.SwitchTo().Frame(yourIFrame);
Now, this should work -
IWebElement query = driver.FindElement(By.Name("href"));
query.SendKeys("test");
Also, once you are done dealing with inside iframe, you can switch back to default content by -
driver.SwitchTo().DefaultContent();

As your element in iframe so first go to iframe then locate the element for functioning
IWebElement FirstIFrame= driver.FindElement(By.XPath("//iframe[#src='index.php']"));
driver.SwitchTo().Frame(FirstIFrame);
//Now perform operations
IWebElement query = driver.FindElement(By.Name("href"));
query.SendKeys("test");

As per your question the elements within the url http://wasitviewed.com/ are within an <iframe>. So once you access the url first you need to induce WebDriverWait for the desired <iframe> to be available and switch to it then you need to induce WebDriverWait again for the desired element to be clickable and you can use the following solution:
driver.Navigate().GoToUrl("http://www.wasitviewed.com/");
new WebDriverWait(driver, TimeSpan.FromSeconds(10)).Until(ExpectedConditions.FrameToBeAvailableAndSwitchToIt(By.XPath("//iframe[#src='index.php']")));
new WebDriverWait(driver, TimeSpan.FromSeconds(10)).Until(ExpectedConditions.ElementToBeClickable(By.XPath("//input[#class='inputText' and #name='href']"))).SendKeys("test");

btw. when you will be confused with iframe, which iframe you should use to switch, then you can also use something like
driver.SwitchTo().DefaultContent();
or
driver.SwitchTo().Window(driver.WindowHandles.Last()); <-- this switch to the last, this is good in some case, when you are already switched in 2-3 level of iframe and you want to return. I am using with both very often.
both I am using also when I am working with pop up windows.

Related

C# Selenium fails to correctly assert

Test below fails, saying that xpath expression is not correct. I did it according to online tutorials.
// open browser
IWebDriver webDriver = new FirefoxDriver();
// navigate to site
webDriver.Navigate().GoToUrl("https://localhost:44311/");
// identify details button
IWebElement detailsLink = webDriver.FindElement(By.XPath("//*[contains(., 'Details')]"));
// operation
detailsLink.Click();
var detailsLabel = webDriver.FindElement(By.XPath("//div[text() = 'Change in $'"));
// assertion
Assert.That(detailsLabel.Displayed);
I want to create simple Selenium test.
I'm pressing specific button to open new page
Checking if specific object is loaded correctly on that page
Button is <a></a> with Details inside. There are actually duplicates of that, the only unique thing is href. This might be the first issue, but I don't know how to "catch" it.
detailsLabel is actually a <div>Change in $</div> with class that I think is irrelevant to the tests.
So, my question is, how to write this test correctly? Test itself should be more or less fine, but detailsLink and detailsLabel has certain issues.
Edit
IWebElement detailsLink = webDriver.FindElement(By.CssSelector("[href*='Details?cryptocurrency=BTC']"));
//operation
detailsLink.Click();
var detailsLabel = webDriver.FindElement(By.XPath("//div[contains(text(),'Change in $')]"));
Return exception Selenium.StaleElementReferenceException for detailsLink
Edit
IWebElement detailsLink = webDriver.FindElement(By.CssSelector("[href*='Details?cryptocurrency=BTC']"));
detailsLink.Click();
var detailsLabel = webDriver.FindElement(By.XPath("//*[text()='Change in $```
Test fails at `detailsLabel`, fails to find our target `div`.
To validate if //*[contains(., 'Details')] xpath is unique you can do something like
List<WebElement>list = webDriver.FindElements(By.XPath("//*[contains(., 'Details')]"));
now, if list is empty - this means your locator is wrong and if it contains more than 1 element your locator is not unique.
But the better way is to validate this manually and directly on the webpage with F12 Inspector tool on your browser.
To locate the element containing some href without the specific href text use //href in case href is an element tag. Otherwise use //*[#href] if href is an attribute.
For the detailsLabel try using //div[contains(text(),'Change in')] xpath
I used Java syntax, but it's similar enough to C#

How to fix 'NoElementException' in Appium & C# for which I tried various solution?

I'm new to C# but have good experience with Appium.
For the screen in question, there is an edit field 'Please enter your appcode'. Appium desktop is identifying the element with 'id' easily. After identification, I am trying to click and have to enter a value for appcode. Surprisingly in java, this element is identified easily with 'Id'.
I have tried with 'FindElementById','FindElementByAccessibilityId' and 'FindElementByXPath' but none of them is working.
I also tried with Explicit wait.
IWebElement Appcode = driver.FindElementByAccessibilityId("com.abc.dbanking:id/appcode_tie");
or
IWebElement Appcode = driver.FindElementById("com.abc.dbanking:id/appcode_tie");
or
IWebElement Appcode = driver.FindElementByXPath("//android.widget.EditText(#resource-id = 'com.abc.dbanking:id/appcode_tie'));
or
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(45));
IWebElement Appcode = wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementToBeClickable(By.Id("com.abc.dbanking:id/appcode_tie")));
But every time I am getting 'NoSuchElementException' and driver is not able to locate this element on the page.
try
IWebElement element = driver.FindElementById("appcode_tie");
or
IWebElement element = driver.FindElementByXPath("//*[contains(#resource-id, 'appcode_tie')]");

ExpectedConditions.ElementIsVisible returns TimeoutException even when element is present

I'm using Selenium ChromeDriver v2.40, Chrome version 67.
var driver = Browser.GetChromeDriver();
driver.Navigate().GoToUrl(url);
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
var abc=driver.FindElement(By.XPath("//*[#id='pdp-size-select']"));
var aaa=wait.Until(d => d.FindElement(By.XPath("//*[#id='pdp-size-select']")));
abc.Click(); // failed because elementisnotvisible
the above two findelement works fine, can get value but cannot click because the element is not visible
so i go on to try ExpectedConditions, and no luck with this:
wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementIsVisible(By.XPath("//*[#id='pdp-size-select']")));
Above code returns:
OpenQA.Selenium.WebDriverTimeoutException: 'Timed out after 10 seconds'
Does it have any backward compatibility issues with Chrome v67?
As per the error elementisnotvisible seems you are pretty close. Moving forward as you are trying to invoke Click() on the element, so instead of ExpectedConditions as ElementIsVisible() you need to use ElementToBeClickable() as follows:
new WebDriverWait(driver, TimeSpan.FromSeconds(10)).Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementToBeClickable(By.XPath("//*[#id='pdp-size-select']"))).Click();
With out any reference to SeleniumExtras and WaitHelpers the line of code will be:
new WebDriverWait(driver, TimeSpan.FromSeconds(10)).Until(ExpectedConditions.ElementToBeClickable(By.XPath("//*[#id='pdp-size-select']"))).Click();
Note: As you mentioned you are using Chrome v67.x ensure that you are using ChromeDriver v2.40 (but not ChromeDriver v2.4)
Update
Debugging further it seems the Locator Strategy you have adapted, identifies exactly two (2) elements within the HTML DOM. So you need to construct a unique locator to identify and click the desired element as follows:
new WebDriverWait(driver, TimeSpan.FromSeconds(10)).Until(ExpectedConditions.ElementToBeClickable(By.XPath("//a[#data-track-action='Product-Page']//following::select[#id='pdp-size-select']"))).Click();
Note: The desired element is a select element and if you desire to interect with the <select> element as per best practices you need to use the SelectElement Class from OpenQA.Selenium.Support.UI Namespace.

C# Selenium Can't Locate to any Element

Why C# + Selenium can't locate to any element from this URL only
I want to try to filling data to textbox programmatically using c# + selenium.
I had tried for some sites and it worked, but only that site it doesn't work. This is my code.
class Program
{
static void Main(string[] args)
{
Test test = new Test();
test.testDriver();
Console.WriteLine(Environment.NewLine + "Done!");
Console.ReadLine();
}
}
public class Test
{
public void testDriver()
{
IWebDriver driver = new FirefoxDriver();
driver.Navigate().GoToUrl(#"http://atrium.xsis.co.id/#!/");
IWebElement login = driver.FindElement(By.Name("email")); //Unable to locate element
//IWebElement login = driver.FindElement(By.Id("email")); //Unable to locate element
//IWebElement login = driver.FindElement(By.Name("password")); //Unable to locate element
//IWebElement login = driver.FindElement(By.Id("password")); //Unable to locate element
//IWebElement login = driver.FindElement(By.XPath("//input[#id='password']")); //Unable to locate element
//IWebElement login = driver.FindElement(By.XPath("//input[#id='email']")); //Unable to locate element
//IWebElement login = driver.FindElement(By.XPath("//input[#name='password']")); //Unable to locate element
//IWebElement login = driver.FindElement(By.XPath("//input[#name='email']")); //Unable to locate element
login.SendKeys("MyName");
login.Submit();
//------------------------------Some sites, i have tried
/* --It Worked
driver.Navigate().GoToUrl(#"https://accounts.google.com/");
IWebElement login = driver.FindElement(By.Name("identifier"));
login.SendKeys("MyName");
login.Submit();
*/
/* --It Worked
driver.Navigate().GoToUrl(#"https://web.facebook.com/");
IWebElement login = driver.FindElement(By.Name("email"));
login.SendKeys("MyName");
login.Submit();
*/
/* --It Worked
driver.Navigate().GoToUrl(#"https://stackoverflow.com/");
IWebElement login = driver.FindElement(By.Name("display-name"));
login.SendKeys("MyName");
login.Submit();
*/
/* --It Worked
driver.Navigate().GoToUrl(#"https://github.com/login?");
IWebElement login = driver.FindElement(By.Name("login"));
login.SendKeys("MyName");
login.Submit();
*/
}
}
I think that is simple code, just locate specific element. Or use other method if the web using IFrame, but there is no frame.
I am using vs 2013 community edition, WebDriver.dll version 3.4.0.0, RunTime version v4.0.30319., and Firefox 54.0.1 (32-bit).
There's something which is kind of cool and annoying at sometime in Selenium, it literally try to work exactly as if the user where using the browser. Hence you gotta be sure that the element exposed on your screen and the user can click on it, otherwise you must scrool until it.
Another important thing is the bootstrap, which sometimes change the visibility of its elements and replace to others.
Scrool to elements on page's bottom.
Guarantee the element is literally visible.
Check whether there's something over the element.
I can't comment yet and I'd prefer that this be a comment, but here goes anyway.
I tried browsing to the site you reference and can't get there. Not sure if it's live or not or just blocked by my company's firewall. I really wanted to look at the code for the site because I've seen issues like this before. Typically when I've seen this it's either a locater issue or an iframe issue. If you could post the html from the site that would help diagnose your issue. Oh, and the code you have written looks correct, but that doesn't help if Selenium is looking in the wrong frame.
So, here's what I would try.
First, I'd use FireFox's developer version and inspect the element. Make sure it's not inside of a frame that you haven't noticed.
Second, I'd try to locate by CSSSelector. I know that it should work by Id or XPath, but sometimes it doesn't and I don't know why. However, I have had luck with locating by CSSSelector when the others fail. You can copy the CSS Selector directly out of the inspection window in FireFox's developer version.
Third, if none of that works, I'd pass a SwitchTo the Default Content Frame, just in case the entire page is in a frame that is buried inside a div that you're missing. The code for that is:
driver.SwitchTo().DefaultContent();
Finally, the last thing I would try is adding some explicit waits just in case there is an element loading after you are trying to access it. Unfortunately this happens more than I'd like.
This would be my final, kitchen sink, approach.
Thread.Sleep(2000);
driver.SwitchTo().DefaultContent();
Thread.Sleep(2000);
By emailLocator = By.CSSSelector("insert CSS Selector Here");
IWebElement email = driver.FindElement(emailLocator);
email.SendKeys("email address");
If that still doesn't work, please post the html for the page you're trying to access and we'll see if we can figure out why it's failing to locate the element.
Your code looks good... something simple like your first attempt, By.Id("email"), should have worked. When it doesn't you want to look first to see if the desired element is in an IFRAME. In this case, it isn't.
The next thing you should try is an explicit wait, WebDriverWait.
IWebElement email = new WebDriverWait(Driver, TimeSpan.FromSeconds(3)).Until(ExpectedConditions.ElementIsVisible(By.Id("email")));
email.SendKeys("MyName");
email.Submit();
The wait.Until() returns the element waited for so you can capture that by assigning the return to a variable and then using it, as I did above.
Have you tried using Xpath?
driver.findElement(By.xpath("//input[#name='email']"))
I find that sometimes Selenium is finicky and you need to try other approaches to find elements.

How to workaround certain differences between PhantomJSDriver and ChromeDriver

I have an issue when switching from ChromeDriver to PhantomJSWebDriver, that I need a workaround for.
Using the ChromeDriver I perform a .Click on a visible element, with another visible element next to it. the .Click makes the web page place a 'popup' over these elements. I then perform a .Click on an element within this 'popup' and it then goes away, and I am able to perform a .Click on the second of the original elements and it all works fine.
However, when I switch to using the PhantomJSDriver it complains that the second element is NOT visible after the 'popup' has been removed, and so wont do the .Click.
Is this a known issue with the PhantomJS driver, or is there some way to get it to 're-evaluate' what is visible? I have tried using a DriverWait looking for the element and waiting for it to be 'Displayed' but that doesn't work
WebDriverWait waitforpopdown = new WebDriverWait(driver, TimeSpan.FromSeconds(15));
waitforpopdown.Until(d => {
var elpd = driver.FindElement(By.ClassName(trid));
return elpd.Displayed;
});
I'm using PhantomJS 2.1.1 and Selenium 2.52.0.0 and using C#
I had the same problem with PhantomJSDriver. It hasn't the same javascript engine than Chrome, FF and IE.
I "fixed" my problem by installing a selenium server that is running chrome on a docker. If you have the ability to do that, I would recommend to work that way. It's an actual chrome browser that is running, so you don't have any difference between your different types of chromes.
You can find information about it on the following page : https://github.com/peroumal1/docker-chrome-selenium
EDIT : You have to declare your driver like this (note that it's java Syntax, but I'm sure you'll be able to find the C# syntax) :
return new RemoteWebDriver(new URL("http://myurl.url:8888"), DesiredCapabilities.chrome());

Categories