Selenium wait for element to reload - selenium

I'm trying to do the following:
I have a page that has a list of comments (each comment is a div and the list is a div containing all of these).
There's a button at the end of the page to load more comments. These comments are load as an "infinite scroll". They are appended to the ones present.
I have to perform in Selenium a click to this button to bring more comments and then wait until the new comments are loaded.
How do I do this? I have no way of differentiating the new comments from the old ones. Is there a hook to know when an element changes? I mean, when an element gets added more elements to it's children.

I don't know about a hook; Selenium seems to implement these waits with "polling" rather than hooks.
So, can you wait on a condition, the condition being that the list contains the expected new number of comments?

Related

Robot Framework- Loading Spinner selector

I have this problem where I have to validate if a loading spinner is present, it's present for about 1 second on the page, i have found the xpath selector of the loading spinner but selenium library could not find it is there another way to find out a selector of something that dissapears after a short while? Note: The xpath is definitely correct. There is no id on the loading spinner either.
This is the code i have tried
Validate Loading Spinner
Wait until page contains xpath=//*[#id="app"]/div/div[1]/div[3]/div/div/div/div/svg
I have also tried Element should contain and Page should contain but that does not find the locator.
You should be using one of the keywords that is validating an element is present - Wait Until Element Is Visible, or Wait Until Page Contains Element - both of which support a timeout argument, for how much to wait.
Afterwards, you'd better use the opposite keyword - Wait Until Element Is Not Visible, to make sure the spinner disappears and you can continue with the test.
There is a problem with your locator - xpath has some issues if the element is svg, most of the times it can't address it directly. So instead of specifying it explicitly in the path, look for a node whose name happens to be "svg"; e.g.:
xpath=//*[#id="app"]/div/div[1]/div[3]/div/div/div/div/*[local-name() = "svg"]
(^ changed the last element in the path)
Slightly offtopic - try to have less rigid locators - this one specifies an absolute path from the element with id "app" and down (a div child, then its first div child, then that one's third div child, and so on and so forth). If the element structure changes even slightly, the locator will stop working (say, in a bug fix, or re-positioning it, or just with using a HF of an JS library).
Try to find an element that's 1-2 levels higher than your target svg - by a solid class value, or structure that's unique, and use it as an anchor.
I reckon you used wrong keyword
Validate Loading Spinner
Wait until page contains ELEMENT xpath=//*[#id="app"]/div/div[1]/div[3]/div/div/div/div/svg
Both work:
Validate Loading Spinner
wait until page contains element xpath=//*
[#id="app"]/div/div[1]/div[3]/div/div/div/div/*[local-name() = "svg"]
and
Wait until page contains ELEMENT xpath=//*[#id="app"]/div/div[1]/div[3]/div/div/div/div/svg
I had a very similar issue

Serenity BDD - How to reload page elements using pagefactory

i'm having a issue regarding element loading using pagefactory:
#Findy(id = painelDeContole)
private WebElementFacade painelDeControleBtn;
The trick is,
on this menu i have to do a mouse-over action on "... mais" to open a sub-menu like this:
But when i call painelDeControleBtn.isVisible() it's return false. (Last image, second icon)
I need some way to reload the page element and truly verify if the element is visible after the mouse-over action.
I've already searched for some method to do this inside PageObject and WebElementFacade but hasn't found any.
I'd like to maintaing the usage of pagefactory if possible..
Because of the way #FindBy loads elements, it may be present on the screen but not yet visible, or it may not wait until the element appears before returning the result. To do this reliably you will get better results with dynamic lookups, e.g.
$("#painelDeContole").isVisible();
or
$("#painelDeContole").waitUntilVisible();

What to do when waiting for an element is not enough?

I am writing selenium test scripts using the industry standard of webdriver waits before interacting with elements, but I still frequently find my tests are failing, and it seems to be due to a race condition.
Here's the example I have been running into lately:
Go to the product catalog page
Apply a filter
Wait for the filter to be applied
Click the save button on the product which loads after the filter is applied
Step number 4 only works if I place a Thread.Sleep() in front of the step - using webdriverwait is not enough. I'm guessing this is because the webdriverwait only waits until the element is attached to the DOM, even though the relevant JavaScript click event has not been added to the element.
How do you get around this issue? Is there an industry standard for dealing with this race condition?
EDIT This was resolved by upgrading to the latest version firefox. Thanks everyone!
As we discovered in comments, updating Firefox to the latest version did the trick.
The code looks really good to me and makes total sense.
What I would try is to move to the element before making a click:
Actions builder = new Actions(WebDriver);
IWebElement saveButton = wait.Until(ExpectedConditions.ElementIsVisible(By.CssSelector(".button-wishlist")));
Actions hoverClick = builder.MoveToElement(saveButton).Click();
hoverClick.Build().Perform();
As we've discovered in comments, the issue is related to the size of the window (the test passed without a Thread.sleep() if the browser window is maximized). This makes me think that if you scroll to the element before making a click it could be enough to make it work:
IWebElement saveButton = wait.Until(ExpectedConditions.ElementIsVisible(By.CssSelector(".button-wishlist")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].scrollIntoView(true);", saveButton);
Actions hoverClick = builder.MoveToElement(saveButton).Click();
hoverClick.Build().Perform();
Take a look at this SO post for custom wait method. Sounds like element presence is not enough of a check in your case because the button may be present at all times in the DOM. What you need is something along the lines of ExpectedConditions.elementToBeClickable().
I am not familiar with the C# API but it looks like there is no built in method to do the same thing as in Java. So you could write a custom wait function that will have checks according to your needs.

Seaside calling a component inside javascript

I have a seaside application with a master-detail page. The master page has a table that consists of a list of tr records. When the user clicks a particular tr element, I want to call a detail component, which'll show the individual record's data.
Since I cannot make a tr element with callback or have it contain an anchor with a callback, I want the tr's onClick property to have some JavaScript which'll call: subcomponent . When I tried this, I got an error saying call: can only be used in callbacks and tasks.
Using ajax is a workaround, however it breaks the back button.
Edit:
More generally, I'd like to know how to set callback like behaviour for various JavaScript events.
Well, you cannot render a component in a tr element, but you could add some anchor or other element in one of its td children.
For my project I did roughly the following: I added an anchor to each row with a special css class, e.g. '.dblclick-action'. This anchor has a normal Seaside callback.
Then I bound a dblclick handler to the tr element that does something like document.location=$(this).find('.dblclick.ction').get(0).href;
I am not close to a Smalltalk image now to give you source code, but I hope you get the idea: you don't use Ajax to click the link in that particular row, but instead have the browser navigate to the callback that is associated to the link in that row. You could say you use the tr.'s dblclick handler to click the link and then let the normal Seaside stuff do its work. No magic there. You can find a little bit more info here.
If you don't want the anchor to be visible you may want to experiment with making the anchor invisible (display: none) or the like.
If you are a bit more experiment friendly, you can also try saving a callback on the server and render its url with callback id as an attribute of the tr element and use the dblclick handler to follow the link from that attribute you extract the value of an attribute in query using attr().
I forgot to answer your initial question: you cannot issue a call: from javascript. But you can use the document.location trick to re/misuse an existing link to a callback on the page using the technique I described in my first answer.

How to click on Toolbar Item with selenium?

Web page contain a button with some text for example "Test". This button actually is a toolbar element. ( class ="tbButton" id="id",text="Test") and redirects to a certain table when press on it.
When try to use the following click methods
selenium.click("id");
selenium.doubleClick("id");
selenium.click("//*[text()='Test'and contains(#class, 'tbButton')] ");
the button does not react
Could enybody show an alternative methods that is able to resolve a problem
It's hard to know exactly what the problem is without knowing more about the actual contents of the page you are testing. Is there an example of the toolbar online somewhere?
With modern interfaces, locating elements with Selenium is not always an exact science. Here are a few suggestions:
With modern interfaces you often find that the DOM is being manipulated, so it is possible that the identifier you are using is no longer valid by the time you get to your click(). Use Firebug to check that you have the correct element.
Often it helps to click on the parent of the element, such as a div or the parent table cell. Again, use FireBug, to try some other elements near your toolbar button. Alternatively, Firebug sometimes reveals that the element contains other elements. You might have more luck changing the target to a contained element instead.
Sometimes you have to play around with some of the alternative actions. For instance, some controls respond to a mouseDown() followed by a mouseUp(), but not to a click(). Again you can often get hints from looking at the source with Firebug.