Selenium click link multiple times - c#

I'm automating tests for our webapp in Selenium WebDriver for C#. One of our test scenarios identified an issue with clicking the save button multiple times resulting in multiple identical records.
The standard IWebElement.Click() causes Selenium to block until the page is fully loaded. That means by the time our second click comes around to executing, the postback has been performed and we're not on the form page anymore.
Does anyone know a means of 'manually' clicking an element that won't cause Selenium to block?

You could either wait for a predetermined amount of time for the page to load:
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));
...or to be more dynamic and wait for your button to appear:
var driver = new WebDriver();
var wait = new WebDriverWait(driver, TimeSpan(0, 1, 0));
wait.Until(d => d.FindElement(By.Id("button"));
Source: https://stackoverflow.com/a/7811812/2006048
Selenium also has source code that is similar to the second method: http://selenium.googlecode.com/svn/trunk/dotnet/src/WebDriver.Support/UI/ExpectedConditions.cs
Let me know if it works out for you. I personally use these options with WatiN:
browser.WaitForComplete();
...or:
browser.WaitUntilContainsText("Text");
It's a shame Selenium does not have the first one.

If we use JavaScript to send our click events, Selenium will not be blocked and we can click multiple times. However, because our click triggers a page load, we cannot reference the element directly. Instead, we need to specify the location to click and then fire our click events.
Because our WebApp uses JQuery, I was able to use the code specified here:
How to simulate a click by using x,y coordinates in JavaScript?
So in the end our C# logic looks something like this:
IWebElement element = driver.findElement(By.id("foobar"));
Point point = element.Location;
IJavascriptExecutor jscript = (IJavascriptExecutor)driver;
jscript.executeScript("$(document.elementFromPoint(arguments[0], arguments[0])).click();", point.X, point.Y);
Although this sends the click event I'm not 100% sure that the element receives it; I'll run some experiments and see.

What you need to do is click via javascript. In java this is done like this:
IJavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", driver.findElement(By.id("gbqfd")));
executor.executeScript("arguments[0].click();", driver.findElement(By.id("gbqfd")));
I actually imagine it is very similar, this will not block selenium and you should be able to chain a few on before the page comes back.
if this newer approach is too slow you might be quicker doing it all in js, e.g.
IJavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("document.getElementById(id).click();");
executor.executeScript("document.getElementById(id).click();");

Related

How to click on a autocomplete item from a list using Selenium and C#

The web page https://www.priceline.com/?tab=cars&vrid=7fb0c3635c8e8e7633afe152907a052e has an <input> element. When I click on it and start typing a <div> with a list of items below appears and I can choose from that list. But when I insert text into that <input> element i.e. the location field, where you see "CIty, Airport or Address" placeholder element on the webpage opened by Selenium, either by actually typing myself or via driver.FindElement(...).SendKeys(...), I see the text, but the list below is not showing.
I don't even know how to approach this. Do I need to configure the driver in a special way?
I assume there is some javascript that intercepts the typing and shows the list below. But, what can be the difference between typing in real life and through Selenium? What can I do?
Selenium Version
Selenium.WebDriver - 4.8.0
Selenium.WebDriver.ChromeDriver - 110.0.5481.7700
It is possible, the way you are doing it is not simulating typing into the input so the event listener that is listening for that simulation isn't being fired. Try this code below which simulates someone actually typing.
using OpenQA.Selenium.Interactions;
// Find the input element
IWebElement inputElement = driver.FindElement(By.Id("input-element-id"));
// Create an Actions object and send keys to the input element
Actions actions = new Actions(driver);
actions.MoveToElement(inputElement)
.Click()
.SendKeys("your text here")
.Perform();
The site is detecting Selenium use and blocking use of the site.
If you navigate to the site in a normal browser, typing in the search field works fine.
If you navigate to the site using Selenium and then use the site manually, the dropdown functionality still doesn't work. If you refresh the page, you get sent to a reCATPCHA page with the message, "Access to this page has been denied because we believe you are using automation tools to browse the website."
The desired element is a dynamic element, so to send some text e.g. Boston within City, Airport or Address field and click on the matching option you need to induce WebDriverWait for the ElementToBeClickable() and you can use either of the following Locator Strategies:
new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable(By.XPath("//input[#data-testid='startLocation-typeahead-input']"))).SendKeys("Boston");
new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable(By.XPath("//div[#data-testid='typeahead-dropdown-card']//div[#role='option' and contains(., 'Boston')]"))).Click();
Browser Snapshot:

Selenium - Wait for OutOfBound element C#

I use Selenium C# binding and I want to click over the addToCart button.
First, I'm waiting the button appears on the page with ExpectedConditions.ToBeClickable.
Then, I need to scroll down the page to be able to click over the button. I used the Selenium.Interactions class but it work as well with js executor.
private By addToCartBy = By.XPath("/html/body/div[2]/div/div/div[1]/div/div[3]/div[2]/div/section[1]/div[2]/aside/div/div[2]/div/div[2]/div/button");
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(5));
IWebElement addToCart = wait.Until(ExpectedConditions.ElementToBeClickable(addToCartBy));
Actions action = new Actions(driver);
action.MoveToElement(addToCart);
action.Perform();
addToCart.Click();
When I perform this test with Chrome driver, the page loads and the navigator scroll down to the element addToCart and click it but I'm unable to get the button working properly.
When I use Firefox driver, it raise this exception:
OpenQA.Selenium.WebDriverException : '(1435, 998) is out of bounds of viewport width (1920) and height (966)'and I'm unable to click over the button
Most of the time, the click will be performed but no action will follow from this. If I want the button to work properly (go the the cart), I need to put a System.Threading.Thread.Sleep(2000) to be effective or a Console.ReadLine(). Even if I disable the automation click and I do it manually, the button don't always proceed.
How can I make sure my element addToCart is displayed after I moved to Element? in a way to click it when he's ready.
Thank you, Eelke Johnson
For some of the scenarios, you can use not
IWebElement.Click();
but
IWebElement.SendKeys(Keys.Enter);
I had some scenarios, where just Click() didn't work for me.Maybe this will help in your situation.
You need to consider a couple of things.
To invoke MoveToElement(), ExpectedConditions as ElementToBeClickable() is overkill. Instead you can do away with ElementIsVisible().
While invoking Click() as per best practices you need to invoke WebDriverWait inconjunction with ExpectedConditions as ElementToBeClickable().
So effectively, your code block will be:
Actions action = new Actions(driver);
action.MoveToElement(new WebDriverWait(driver, TimeSpan.FromSeconds(10)).Until(ExpectedConditions.ElementIsVisible(By.XPath("/html/body/div[2]/div/div/div[1]/div/div[3]/div[2]/div/section[1]/div[2]/aside/div/div[2]/div/div[2]/div/button")))).Perform();
new WebDriverWait(driver, TimeSpan.FromSeconds(10)).Until(ExpectedConditions.ElementToBeClickable(By.XPath("/html/body/div[2]/div/div/div[1]/div/div[3]/div[2]/div/section[1]/div[2]/aside/div/div[2]/div/div[2]/div/button"))).Click();

Stop page load during navigate url in selenium

I am using selenium tool in my C# windows application,
driver.Navigate().GoToUrl(baseURL);
when the the application executing this line the page loads takes 2mins.
During that time, the followin element has found within 10 sec.
driver.FindElement(By.Id("searchTerm"))
I used driver.FindElement(By.Id("searchTerm")).SendKeys(Keys.Escape);
But it wont work properly. The problem is after complete the page load then only the control execute next line . But I need to stop the page if the element has found.
Thanks
You could try issuing the Escape press at the top level, not on the element itself:
if (driver.FindElement(By.Id("searchTerm")) != null) {
Actions action = new Actions(driver);
action.SendKeys(Keys.Escape);
}
That seems to be the most common way of issuing a page load stop.
To stop page load at any moment you can use something like this:
IJavaScriptExecutor js = Brwsr.Instance as IJavaScriptExecutor;
js.ExecuteScript("window.stop();");

C# Selenium WebDriver - Is it possible to check if a certain webpage is already opened in the browser?

I was wondering if it is possible to check with C# and selenium web driver if a certain webpage is opened in the default browser?
My idea is to link certain ticketing system's time tracker with toggl.
For instance - on click of the "Time Track" button in the ticketing system, the program to click the toggl start button programmatically, at the same time.
Yes, it's possible.
You can devise a solution that checks the default window's URL or title.
if (driver.Url == 'http://some_url') { /* you are there */ }
or
if (driver.Title == 'Some Title') { /* the window is open and currently there */ }
Now, if you are running a browser manually using your own browser, then expect Selenium to detect that, then i'm sorry, but that is not possible.
In addition to #sircapsalot answer:
This won't be enough since the goal is to
on click of the "Time Track" button in the ticketing system
First you should be sure that the page has been loaded and the IWebElement is clickable. Without going in some advanced usage (like JS validation of the page state), this should do the work just fine:
var wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(15));
var myElement = wait.Until(x => x.FindElement(By.Id("timeTrackBtnId")));
if(myElement.Displayed)
myElement.Click();
Then go for the
program to click the toggl start button programmatically, at the same time
I'm not sure how you'll sync and how page's JS events will handle this simultaneous actions, but you can try with System.Threading. If the page is created by you maybe this second part (click button, click togl) is better to be handled in the JS code.

Selenium WebDriver SubMenu click not working

I am not able to Click on SubMenu item using selenium webdriver using c#.
I am using IE9 and FireFox 13.
I have tried Action Builder but it does not work.
It gives an error saying element cannot be clicked.
WebDriverWait Wait = new WebDriverWait(webDriver, TimeSpan.FromSeconds(5));
IWebElement menu = Wait.Until((d) => webDriver.FindElement(By.Id("id1")));
IWebElement menuOption = Wait.Until((d)=>webDriver.FindElement(By.Id("ID2")));
Actions builder = new Actions(webDriver);
builder.MoveToElement(menu).Build().Perform();
Thread.Sleep(5);
//then click when menu option is visible
menuOption.Click();
I have used even javascript :
js.ExecuteScript("return $(\"a:contains('ID1')\").mouseover();"); // Mouse hove to main menu
webDriver.FindElement(By.Id("ID2")).Click();
Please give some solution to click on hidden elements
You could use Expected Conditions to wait for element being clickable after hovering above it (Thread.sleep() is almost always the bad choice. And 5 ms won't be enough.).
The docs for this class (ExpectedConditions in OpenQA.Selenium.Support.UI namespace) are broken as I can see them now, but if you can follow the Java code in the link above, here are the Expected conditions for Java - it's really almost the same in C#, too.
Instead of using the statement Thread.sleep(). You can try to click on the element after making sure that it is displayed.
After you get the WebElement you want to click on , check if it is displayed by using the isDisplayed() method within the ExpectedContition statement about which #Slanec is talking about in the above post.
By this you can make sure you will click on the element only after Wait.Until() returns true. i.e the menuOption is displayed.
I'm writing the code in java as I do not know C#. But I guess you can figure out what I'm trying to say -
new WebDriverWait(driver, 60).until(new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver ) {
return driver.findElement(By.Id("ID2")).isDisplayed();
}
});
I hope that this helps you.

Categories