Unable to locate WebElement using Selenium C# - c#

I've been knocking my head trying to figure out why I can't locate and click this web element!
What I'm trying to do is pretty straightforward, I'm trying to click on any item of the following list: worten list of airpods
And I'm basically trying to locate AND click in some element of this kind:
It's completely impossible. Any help would be greatly appreciated.
I've already tried every type of xpath that I could remember, the only thing that comes close to working is when I copy the full xpath directly from the browser, but even then another error appears stating that the element isn't clickable...and obviously I don't want to deal with a full xpath.
examples of xpaths tried:
//a[#data-sku='7328250'] and its variations (#href instead of #data-sku, etc...)
same thing but with css selectors.

As per the snapshot provided to click on the desired element you can use the aria-label attribute of the <a> element and inducing WebDriverWait for the desired ElementToBeClickable() you can use either of the following Locator Strategies:
Using CssSelector:
IWebElement element = new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable(By.CssSelector("a[aria-label^='APPLE Airpods Pro 2ª Geração']")));
Using XPath:
IWebElement element = new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable(By.XPath("//a[starts-with(#aria-label, 'APPLE Airpods Pro 2ª Geração')]")));

Related

How to click on the SIGN IN button using Selenium and C#

I am trying to create this simple test where you head to the URL, enter your login credentials and then click the button to sign in. It is doing everything, except for clicking the button. I am trying to doing it by calling up ClassName. Can anyone look at my test and see what I am doing wrong?
public void test_search()
{
var driver2 = new ChromeDriver(#"C:\Users\MyName\Desktop\NUnitTestProject1\NUnitTestProject1\bin\Debug\netcoreapp2.1");
driver2.Navigate().GoToUrl("https://portal.crushdata.com/");
driver2.FindElement(By.Name("Email")).SendKeys("email#email.com");
driver2.FindElement(By.Name("Password")).SendKeys("Password");
driver2.FindElement(By.ClassName("btn bg-teal btn-block btn-lg waves-effect")).Click();
}
This is my classname for my button.
Use CSS selector as shown below:
By.ClassName("btn.bg-teal.btn-block.btn-lg.waves-effect")
Each dot represents a class.
See this page for more info and here is an example from that page:
.name1.name2
Selects all elements with both name1 and name2 set within its class attribute
To click on the SIGN IN button you have to induce WebDriverWait for the desired ElementToBeClickable() and you can use either of the following Locator Strategies:
CssSelector:
new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable(By.CssSelector("button.btn.bg-teal.btn-block.btn-lg.waves-effect"))).Click();
XPath:
new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable(By.XPath("//button[text()='SIGN IN']"))).Click();
Try making use of the button xpath.
Open the dev tools. Right click on the button you want to be clicked > Select Inspect >Then right click the html in the dev tools window and Copy Xpath from the Copy option.
Then in you code replace FindElement with FindElementByXPath:
driver2.FindElementByXPath("//*xpath/goes/here")).Click();
Given your shared html block, the following XPath will suffice.
//div[contains(#class = "text-center")]//button[contains(#class, 'btn bg-teal btn-block btn-lg waves-effect') and #type = 'submit']
If the driver is still unable to click you should consider the following:
Is the XPath unique? paste the xpath in chrome's devtools search box in the inspect element tab and make sure the provided xpath is targeting the element you are intending. If this is not the case then you should make the xpath more unique.
Is the element in an iframe? if the element is in an iframe the driver won't be able to locate it by default. In such cases you will need to first switch to the iframe and then attempt to locate and interact with the element.
Is the element clickable, visible and enabled? To check these properties first find the element and store in a separate variable and then check the said properties are true.

What is the best wait strategy in Selenium for interacting with a WebElement

I just started with implementing some UItests for a new WebApplication and noticed that sometimes tests are failing when I wait for an Element to Exist while the same test succeeds when waiting for the Element to be Visible.
So my question is, is there a fixed order in which a webelement becomes "existing", "clickable", "visible","displayed" etc. or does this fully depends on how the developer has implemented the webpage or maybe the JS Framework which is used implementing the application?
It all depends on how the page was written.
Web element does not evolve from one status to another. It may change, but as a result of some dynamic content, actions performed on the page etc.
What those statuses tell us:
Existing - is when the element is in the page DOM. It does not necessarily has to be visible or interactable. It is the basic status, as element cannot have other statuses, without existing. Using the driver.FindElement(By.Xpath(".//*")) will find all elements on the page.
Displayed - when element exists it may be visible. Use IWebElement.Displayed (C# syntax) to check if the element is displayed.
Clickable - sometimes when you try to click the element, the exception may be thrown, saying that something else would get the click. To deal with those issues, see this answer.
How do you check if the element exists? If you are just searching for element, it will throw exception, when element is not found. I suggest using WebDriverWait, to look for element, for certain time period, to deal with loading:
Wait = new WebDriverWait(driver, new TimeSpan(0, 0, timeoutSecond));
Wait.Until(d => d.FindElement(by));
Precisely, Selenium can deal with 3 distinct states of a WebElement with in the HTML DOM:
Element is Exists i.e. Present.
Element is Visible.
Element is Interactive / Clickable.
Honestly, you don't have to keep track of the order in which a webelement becomes existing, clickable, visible, displayed etc.
If your usecase is to validate the existence of any element you need to induce WebDriverWait setting the ExpectedConditions as ElementExists() which is the expectation for checking that an element is present on the DOM of a page. This does not necessarily mean that the element is visible. So the effective line of code will be:
IWebElement element = new WebDriverWait(driver, TimeSpan.FromSeconds(30)).Until(ExpectedConditions.ElementExists(By.CssSelector("element_cssSelector")));
If your usecase is to extract any attribute of any element you need to induce WebDriverWait setting the ExpectedConditions as ElementIsVisible(locator) which is an expectation for checking that an element is present on the DOM of a page and visible. Visibility means that the element is not only displayed but also has a height and width that is greater than 0. So in your usecase effectively the line of code will be:
IWebElement element = new WebDriverWait(driver, TimeSpan.FromSeconds(30)).Until(ExpectedConditions.ElementIsVisible(By.ClassName("element_classname")));
If your usecase is to invoke click() on any element you need to induce WebDriverWait setting the ExpectedConditions as ElementToBeClickable() which is an expectation for for checking an element is visible and enabled such that you can click it. So in your usecase effectively the line of code will be:
new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable(By.XPath("element_xpath"))).Click();

C# + Selenium: automation wait

The below code is not working and it always throws No such element exception at line 2.
wait.IgnoreExceptionTypes(typeof(NoSuchElementException));
wait.Until(ExpectedConditions.ElementToBeClickable(By.XPath(element)));
There could be 2 issues here:
You are trying to find the element before its visible for that you can wait for the element by doing
wait.Until(ExpectedConditions.ElementExists(By.XPath(element)));
where element is the XPath of the element you are trying to find.
You are not finding the element using the correct XPath. If you are using an absolute XPath, avoid doing because while absolute XPath can find the element faster, if the DOM structure changes your path may no longer work.
It is also possible that you are not running your browser in fullscreen, at least this was a valid issue I was facing when my current projects' GUI got changed over. Adding driver.Manage().Window.Maximize(); to my ClassInitialize fixed the issue in a whim.
Another option is that maybe your element is either embedded into an iframe or is overlapped by one.
As mentioned in this answer https://stackoverflow.com/a/44724688/6045154 , I have solved a similar issue with:
IWebElement button = driver.FindElement(By.ClassName("transfer__button"));
IJavaScriptExecutor executor = (IJavaScriptExecutor)driver;
executor.ExecuteScript("arguments[0].click();", button);
Of course this needs to be edited to find your element by the right selector.

C# Selenium can't find element with WebDriverWait, i can see and click on it manually

Element im trying to locate:
WebDriverWait wait = new WebDriverWait(browser, TimeSpan.FromSeconds(60));
wait.Until(ExpectedConditions.ElementExists(By.XPath("//use[#xlink:href='#core_mail']")));
File.WriteAllText("html.txt", browser.PageSource);
that just times out.. and the page loads way before 60 seconds.
svg has a default namespace. You have to account for it:
//svg:use[#xlink:href='#core_mail']
Or ignore it with local-name():
//*[local-name() = 'use' and #xlink:href='#core_mail']
Though, to be fair, you don't have to dive into the markup that deeply, your "email" button is much higher in the tree - see the very first parent element partially visible on the screenshot - that's your desired element you probably want to locate instead.

How to initialize WebElements in Selenium page object

I am new to Selenium and looking forward to learn more, I am using Selenium WebDriver with C#.
This is how I initiate a WebElement:
CarouselSliderNextButton = DriverInitializer.driver
.FindElement(By.XPath("//a[#class='buttons next']"));
But if the element doesn't exist for some reason; hidden for instance, then it doesn't work. I know that I can check if the element exists before I can initiate, but would love to hear from experts if I am doing this the right way.
I am not claiming to be an expert, but this is what I think:
You do not "initiate" a web element
You find a web element
First of all, you need to find the element you want to locate from html file. You may use Google or Firefox in developer mode to find it. I recommend you to install "Firebug" for Firefox, it is very useful.
There are multiple reasons why an element you can "see" from HTML file but you can not locate:
1: this element is on an iframe, this case requires you to locate this iframe first then locate the element
2: this element is not visible yet, for example, a drop down arrow button will only appear if you hover your mouse over a certain area first.
But you are heading to the right direction.
If you're trying to intialise the WebElement, I use:
WebElement element = driver.findElement(By.tagName("div"));
as most DOMs have div tags.
Then after trying to find an element that exists (and isn't a div tag), check:
if (element.getTagName().equals("div")){
System.out.println("Element not found...");
}
var instantEstimateDiv: WebElement? = null => Kotlin
WebElement? instantEstimateDiv= null; => JAVA

Categories

Resources