Given a page with a <select> element and some <option>s, that when clicked cause the browser to open a new URL, like (JavaScript code omitted):
<select>
<option value="here">go here</option>
<option value="there">go there</option>
</select>
When I automate this behavior with WebDriver I call
hereOrThereSelectElement.SelectByValue("here");
and then it waits until the new page has loaded.
In my case, the page load for the new location takes more than 60s (intentionally), so I had to increase the command timeout of the WebDriver instance. Unfortunately this timeout will affect all other tests created with the same WebDriver instance.
Also I would like to perform an explicit Wait for the new page to load (to mark it as long running in the test scenario), but in this condition the next command will be called after the SelectByValue command succeeded - so no Wait needed anymore.
I looked into the source and realized that SelectByValue command uses the Click logics which waits for a page to load if needed.
So my question is: How do I explicitly perform a SelectByValue (or Click) without waiting for a new page to load?
Update:
What I actually want to have in my code is:
// the following command should not wait for the new page to load
hereOrThereSelectElement.SelectByValueButDoNotWait("here");
webDriverWait.Until(/* some "page has loaded" check */)
Finally, I found a solution for this.
Meanwhile the problem has slightly shifted to a call to a WebElement's Click() method that ran into the timeout. Nethertheless the following solution applies also to the original problem with calling SelectByValue().
So, one can use Selenium's Actions low-level interactions builder to perform a click on an element.
var actions = new Actions(webDriver);
actions
.MoveToElement(aClickableWebElement);
.Click();
.Build()
.Perform();
Maybe this will help anyone having similar problems.
Related
I am trying to automate the scheduling of pinning items to Pinterest using Tailwindapp.com. I am using a console app in .NET (C#) with Selenium Chromedriver. I start up the browser and enable the tailwind extension and login to tailwind. Then I go to the site I am trying to pin images from, get to the product page, search for the button and attempt to click it. That's where it falls apart. The 'Schedule' button in Tailwind appears over all images on the page as you hover. When I do an XPath search, it only returns a single button for the whole page (the console line below shows 1).
public static void ClickScheduleButton(IWebDriver driver) {
// get all the buttons and then use the first one
IList<IWebElement> buttons = driver.FindElements(By.XPath("//*[#id='tw_schedule_btn']"));
Console.WriteLine("Number of items found: " + buttons.Count());
IWebElement scheduleButton = buttons.ElementAt(0);
Actions actions = new Actions(driver);
actions.MoveToElement(scheduleButton).Click().Perform();
}
On the perform method, I get the following error: OpenQA.Selenium.WebDriverException: 'javascript error: Failed to execute 'elementsFromPoint' on 'Document': The provided double value is non-finite.
From what I've read, this seems to mean that there are more than 1 element but I seem to have ruled this out with the number of buttons found. I have attempted to do a wait to make sure it's available but I do not believe that is the issue.
I have tried to find an example just trying to do this with a Pinterest button because in theory it would be the same logic but I cannot find anything for that either.
My assumption is that it's a problem just getting the button to appear on the correct image? But that's just a guess.
If I'm understanding this correctly you want to click the button who appears in when you hoover the mouse in the image.
If you can hoover the mouse and wait until the expected xpath appears should solve it.
protected virtual void HooverMouse(By element)
{
Actions action = new Actions(driver);
action.MoveToElement(driver.FindElement(element)).Build().Perform();
}
The element will be the first image you have, so you must change your driver.findelements("the button") to the "images" and loop arround this.
In pseudo code will be:
Hoover(image) -> WaitButtonAppears -> ClickButton
The click event is not firing in firefox but works ok in chrome.
The test fails with the error: "Element not found on page."
Below is the code and HTML for the button I want to click.
Browser.ElementClickById("ctl00_ContentPlaceHolderBody_lvProducts_ctrl0_ctrl1_btnAddProductToCart_input");
and inside the elementclickbyid i have:
driver.FindElement(By.Id(elementID)).Click();
HTML code is:
event
You could try working around with a Javascript click.
// declare JS executor
var executor = (IJavaScriptExecutor)Driver;
// locate the input
var input = Driver.FindElement(By.XPath("//input[#type='submit']"));
// execute JS to click
executor.ExecuteScript("arguments[0].click();", input);
I've seen cases where regular Click(); does not work across browsers -- these cases are rare, but using JS click usually works across multiple browsers when I run into this issue.
driver.findElement(By.xpath("//input[#type='submit']")).click();
i am sure you are trying to use browser class to keep your methods there, but try to use xpath not id. just use this code to click what you need. don't use page object model or anything else. don't save it in your browser class under click method. just in your main code use this code to click. and before to run it make sure that you have only one type submit. if its gonna show to you 2 types then use this code
driver.findElement(By.xpath("//input[#type='submit'][1]")).click();
number 1 says click to first submit if the button which you need second then follow the logic and change the number to 2
driver.findElement(By.xpath("//input[#type='submit'][2]")).click();
for better answer share your code class and also URL where you are trying to click button and also which element you are trying to click
Trying to automatize a couple of tests for our projects using the selenium webdriver and C# and i got into the following situation:
When i try to test the main menu the flow goes something like this:
Click on the first menu item (located on top of the page)
Wait for the last element in the page to load so i can make sure the content is fully loaded (sometimes it takes 15-20 seconds for a full page load)
Assert the title text which is located in a div under the main menu
Click on the next menu item and continue with a similar flow
Now my problem is that after the page is loaded and the test must assert the title text (3), i get a crash. I understand that this is happening because C# only reads the content once and can't return to a previous element once it read it.
So my solution that i thought would get me out was to first define the body tag in a variable and then call it for assert and further navigation:
var body = driver.FindElement(By.TagName("body"));
driver.FindElement(By.XPath("/html/body/div[1]/div/div[2]/div[2]/div[2]")).Click(); // click on the first item in the main menu
driver.WaitForElement(By.XPath("/html/path_to_the_last/div[1]")); // waiting for the last element on the page
Assert.AreEqual("Title text", body.FindElement(By.XPath("/html/body/div[1]/div/div[3]/div[3]/div[1]/div/div[1]/div[1]/div[1]/div[1]/div")).Text.Trim()); // assert the title text by calling the initially set variable
body.FindElement(By.XPath("/html/body/div[1]/div/div[2]/div[2]/div[3]")).Click(); // click on the next item in the main menu.
// similar flow to follow until each menu was checked
The thing is that when the webdriver is about to execute the assert - where the variable was first called, it crashes with the following error:
OpenQA.Selenium.StaleElementReferenceException : Element not found in the cache - perhaps the page has changed since it was looked up
Any idea what i did wrong and how should i proceed?
My guess is that when finding items from body-element, your path can't start from the root. So in the assert you should have this:
body.FindElement(By.XPath("./div[1]/div/div[3]/div[3]/div[1]/div/div[1]/div[1]/div[1]/div[1]/div")
There the beginning dot means your body-element.
I need a solution how to wait until the web page is fully loaded. And exactly after that, waiting no longer, I need to perform actions with a web page: get URL of loaded page, check cookie, click <a> elements so on
I use the following code before work with loaded page:
IWait<IWebDriver> wait=new WebDriverWait(drv, TimeSpan.FromSeconds(30.00));
wait.Until(d => ((IJavaScriptExecutor)drv).ExecuteScript("return document.readyState").Equals("complete"));
But this code does not wait in 100% cases until full load of a page in Chrome, and does not work in Internet Explorer!
Could you please offer better solution
Thanks for an answer in advance!
document.readyState does not always return the actual status of page load completion. see if you can wait on a particular element on the page, perhaps which gets loaded last on the page.
I have a method thats run on a button click, with 4 labels. What I need to do is update a label after each block of code executes. I've tried threading, updatepanels, etc and can't seem to get anything to work. I thought the timer would work, but it only ticks when you're not inside a method. The code looks something like this:
private void SomeMethod()
{
label1.text = "Processing...";
AnotherMethod();
label1.text = "Done.";
label2.text = "Processing...";
AnotherAnotherMethod();
label2.text = "Done.";
//etc...
}
You have a misunderstanding of how asp.net works. Your server code runs in response to a request from a browser for a complete html page. This is true even when all you really want to do is run some button click code. The entire page must be rebuilt from scratch anyway, even on postbacks. It's just the way web forms are designed.
As soon as the page is rendered to the browser, that instance of your page class is destroyed. On the next postback you'll start from scratch again, with the notable exceptions of the session, viewstate, and the application cache. Even the page's previous DOM instance in the browser is replaced.
So when you set the text property of the label you aren't directly updating anything visually in the browser. All you are doing is updating some temporary storage in your page class. As the last stage of executing your server code, all those temporary variables are used to render the completed html and the response is finally sent to the browser and shown to the user.
That should be enough information to give you an understanding of why your code doesn't behave as expected. It's running all of the code in the method before any of your property changes make their way to the browser. Therefore, the only thing the user sees is the final state of the operation.
Now ajax can complicate things a bit. When using an ajax control you might not be updating the entire page anymore, but the concept still applies: one request is made, and one response is received and used to update the entire context of the request. You can further muddle things if you have a lot of javascript in place to handle the result of the ajax request.
Unfortunately, there's no quick fix for the code you posted. You'll need to think about how this really works and decide how you want your page to flow.
Can you expose the 3 methods to client script and then call them sequentially from your client side code, when method1 finishes the client script would update the ui then call method2, and so on...