I have a Java application with selenium and phantomJS.
I built a test to login to an application. There is a step where I send the username and password keys, like so:
this.usernameField.sendKeys(username);
this.passwordField.sendKeys(password);
The fields are identified by ID.
The test works fine in Chrome, but in PhantomJS, both keys are sent to the username input.
For example: username: John - Password: banana
In Chrome: Username: [John] Password: [banana]
In PhantomJS: Username: [Johnbanana] Password: []
If I put a break point and wait after sending the username but before sending the password, then release it, it results in: "Username: [John] Password: [banana]"
Sometimes I get "[Johnban] [ana]" or "[Johnbana] [na]" and so on.
Is this a known bug? I was using PhantomJS from org.seleniumhq.selenium:selenium-java:3.4.0 just fine, but now I had to update versions to org.seleniumhq.selenium:selenium-java:3.141.59 and include com.codeborne:phantomjsdriver:1.4.4.
How can I fix this without putting "wait" all over the code?
It is not a bug. You may have the same situation even in your Chrome if your page loads faster than the code execution. It seems like it is the case in your PhantomJS.
What you can do is to avoid wait everywhere in your code, wrap the waiting behavior in some class, wait until the element is visible and take the action in your upper layers.
You can use presenceOfElementLocated to check and get the element
public class ElementFinder {
public WebElement find(By locator) {
WebDriverWait wait = new WebDriverWait(driver, timeout);
WebElement element = wait.until(ExpectedConditions.presenceOfElementLocated(locator));
return element;
}
}
Then find and call your sendKeys. To avoid casting (you should) WebElement, you can use generics, just wanted to give the idea in the example.
Also, you can have a look for PageObjects by Martin Fowler here. It makes it easy for those kinds of operations like I suggested above wrapping InputElements and its behaviors in some object, also for the rest of the page.
Did you try putting in a loop that checks if the entered value by your script is what you expected? Sometimes this will do the trick.
So, in this particular case, switching the order to "password" first and then "username" fixed the issue.
Just to be clear, the page in question is Jira.
Related
i have the following issue, after perform the login, the system load the main page, its like 5 seconds doing it, so after that, the script should type over 3 fields and perform a tab to get more info, but the thing is that sometimes is working and sometimes does not, in 5 chances, only one worked, i do not know if its something about the time to get all fields or something like that, am using IE 9 cause the app only works on IE
Here´s the code:
`
System.setProperty("webdriver.ie.driver","C:\\Apps\\eclipse\\IEDriverServer.ex;
WebDriver driver = new InternetExplorerDriver();
driver.get("http://15.192.41.95/Cabina/asp/Login.asp");
WebElement text1 = driver.findElement(By.id("text1"));
text1.sendKeys("xxxx");
WebElement password1 = driver.findElement(By.id("password1"));
password1.sendKeys("xxxx");
WebElement aceptar = driver.findElement(By.id("ok1"));
aceptar.click();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.switchTo().frame(driver.findElement(By.name("menu")));
WebElement txtNumPolSol = driver.findElement (By.id("txtNumPolSol"));
txtNumPolSol.sendKeys("877885");
WebElement Text8 = driver.findElement(By.name("txtNumofic"));
Text8.sendKeys("228");
WebElement txtCveInc = driver.findElement(By.name("txtCveInc"));
txtCveInc.sendKeys("1");
WebElement clave = driver.findElement(By.id("txtCveInc"));
clave.sendKeys(Keys.TAB);
driver.switchTo().frame(driver.findElement(By.name("dest")));
WebElement txtNomrepo = driver.findElement(By.id("txtNomrepo"));
txtNomrepo.sendKeys("Jorge Villarreal");
driver.findElement(By.id("txtRelacion")).sendKeys("Conductor");
WebElement txtTelrepo = driver.findElement(By.id("txtTelrepo"));
txtTelrepo.sendKeys("83029090");`
Here the different issues i got:
1) Unable to find element with name == txtOficina
2) Element is no longer valid
3) Unable to find element with id == txtCveInc (the field is there)
4) Unable to find element with name == txtCveInc (the field is there)
The steps that the system to get the issues are:
1) Log in (so far so good)
2) The system load the main page (the page has frames and gets all fields in 5 secs...)
3) The script type over the txtNumPolSol, txtNumofic and txtCveInc (most of the issues are in the last two fields)
4) The script performs a tab
5) The system load the some information regarding the record and the script continue...
Note: Almost all the issues occur on step 3...
Thanks for your feedback!
This sounds like a timing problem. Your simulated user is proceeding faster than the page becomes ready. Depending on the timing of the page loading, different problems occur.
The solution is to add a wait after steps that trigger a DOM change than influences your next step, but doesn't cause WebDriver to wait before returning. Google 'webdriver wait for element' to get lots of ways to do it.
I was also facing the similar kind of problem but i tried to find the elements with Css_Selectors and X paths instead of ids, that worked for me
The key here is to add atleast 1 second of implicit wait after every action, i.e. send keys etc. It will allow 'driver.findElement' enough time to find the element. Though I would suggest keeping this code in a testBase or a reusable method.
driver.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);
It will help in making your webtests less flaky.
I'm using webdriver(java) for a unique test where a page reloads itself when you log on, I've been unable to wait for the element to load because it is already there before the reload. So far the only way I've been able to get it to work is to use a thread.sleep, is there a way to listen for a page refresh?
One way to solve this is, to get a reference to the element you need, that appears both on the login-page and the reloaded page.
Then you can use the ExpectedConditions.stalenessOf to occur, and then you can be sure, that the element is removed from the DOM and a new element is created. Well, the last part is not guaranteed by this method, but at least you know that the old element is gone.
The code could look something like this:
WebElement elementOldPage = driver.findElement(By.id("yourid"));
... do login etc ...
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.stalenessOf(elementOldPage));
WebElement elementNewPage = driver.findElement(By.id("yourid"));
Building upon the accepted answer from Kim Schiller one might be interested in the following piece of code. It is surely not perfect due to the sleeps, so be free to suggest improvements to make it more bulletproof. Also note I'm no expert with selenium.
The if branch waits for the top level node in the html to go stale in case of a page reload. The else branch simply waits until the drivers url matches the request url in case we load a different page.
def safe_page_load(url):
if driver.current_url == url:
tmp = driver.find_element_by_xpath('/html')
driver.get(url)
WebDriverWait(driver, 2).until(ExpectedConditions.staleness_of(tmp))
else:
driver.get(url)
while(driver.current_url) != url:
sleep(0.3)
sleep(0.3)
Happy if I could help someone.
Half year before. I already accessed to Factva.com(A NEWS DATABASE WITH ACCESS CONTROL) by Selenium driver,searching news automatically. However, two months ago, Factiva updates its access protocol from HTTP to HTTPS, which disables my program.
Under HTTP, my program can switch to a new URL within the same Chrome(EVEN a new tab). I did this by using the function: chrome.get(URL) where the URL is a direct search link. I even access the new search request by this method. You know, under HTTP search, you can just combine some key words and logic operator to produce a new URL. And I use chrome.get(URL) to switch to the new search results.
However, under HTPPS, I cannot use the above method anymore. When I use the method, Factiva shows the infos that I was in the off-login status( I should login again. Even though if I click the backforward button with my mouse, I can go back to the Factiva webpage and need not login)
My question is: Why my old method didn't work UNDER HTTPS? How can I let Factiva know, even I use the old method, I am already in the access and need not login again!
My old method under HTTP:
Class SearchTXT{
public String getSearchUrl(String keyword, String startTime, String endTime){
String f0=”http://global.factiva.com.***.uk/zhcn/du/headlines.asp?napc=S&searchText=”
String f2="&dateRangeMenu=custom&dateFormat=dmy&dateFrom=";
String f4="&dateTo=";
String f6="&sortBy=y¤tSources=";
String f7=”Wall Street Journal”;
String f8="&searchLanguage=custom&searchLang=EN&dedupe=0&srchuiver=2&accountid=9MEM000300&namespace=16";
Return f0+keyword+f2+startTime+f4+endTime+f6+f7+f8;
}
}
AFTER login the FACTIVA database by Selenium Driver, I got a chrome with the access to FACTIVA.
Then: I use this:
SearchTXT st = new SearchTXT():
String searchURL= st.geSearchUrl(“DELL”, “2011-11-10”, “2014-10-10”);
chrome.get(searchURL);
String pageSource=chrome.getPageSource();
Then I can use Jsoup.jar to Parser and collect the search results.
But this method never works after the updating from HTTP to HTTPS. These days I am so annoying about this problem.
Are there some alternative methods that can access the data under HTTPS? Maybe there are some tricks that can make my old method work again. Otherwise, I have to totally modify my whole key program and use JavascriptExecutor to deal with this problem. That means a heavy work. The worst is that the javascript code on FACTIVA website is very complicated. Some key javascript codes and functions are even not shown on the FACTIVA page source directly.
Thanks a LOT!
I wanted to automate some processes on www.imgur.com, and I decided to use the Selenium WebDriver library for Java. I have been able to get much of my code to work with one hitch: when I access imgur directly only a white screen shoes up and will not change upon refresh. Accessing the sign in page directly yields an SSL error.
System.setProperty("webdriver.chrome.driver","C:\\workspace\\Test\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("https://www.imgur.com/signin");
WebElement username = driver.findElement(By.id("username"));
username.sendKeys("username");
WebElement password = driver.findElement(By.id("password"));
String pass = "password";
password.sendKeys(pass);
password.submit();
driver.get("http://www.imgur.com");
I have been able to work around this by using links google searches provide to imgur, but adding more features will require I be able to manage the URL directly.
Thanks in advance!
It's just http://imgur.com/, not http://www.imgur.com. That's why Google's links work, they are linking to the first one - a different url.
The www prefix is not required by any technical policy. Some choose to have urls both with and without the prefix point to the same server. Some choose to use only one or the other. It seems imgur is going without the prefix.
Here's a little more info on the www prefix:
http://en.wikipedia.org/wiki/World_Wide_Web#WWW_prefix
I have been running into intermittent errors with some java selenium-rc tests which I think are related to a page which has an ajax poll and automatically refreshes when some condition is reached on the server. In this scenario, I have no way of asking selenium to wait for the page to load, and so I run into a bunch of random "Couldn't access document.body" errors.
So, is there some way I can cause selenium to gracefully handle this situation? If not, is there some way I could detect whether the user is selenium from the page's javascript, and disable the automatic refresh?
If it helps at all, the javascript code in the page looks something like...
var ajax = new Ajax(url, {
update: state,
method: 'get',
onComplete: function(message) {
if (some_condition) {
window.location.replace(unescape(window.location));
}
}
});
One solution might be to always use a waitForCondition using isElementPresent before attempting to interact with the application under test. You could put the following method in a superclass to keep your tests more readable. Alternatively you could create helper methods for common Selenium commands that perform this wait.
/** Waits for an element to be present */
public static void waitForElementToBePresent(String locator) {
session().waitForCondition("var value = selenium.isElementPresent('" + locator.replace("'", "\\'") + "'); value == true", "60000");
}
You may also want to wait for the element to be visible, as waiting for it to just be present isn't always enough (imagine a textbox that is always present but hidden until a certain condition). You can combine this with the above method:
/** Waits for an element to be visible */
public static void waitForElementToBeVisible(String locator) {
waitForElementToBePresent(locator);
session().waitForCondition("var value = selenium.isVisible('" + locator.replace("'", "\\'") + "'); value == true", TIMEOUT);
}
Incidentally, the WebDriver (Selenium 2) team are working on having implicit waits, specifically to address AJAX issues where elements are not present immediately.
My solution was to disable the refresh in javascript by wrapping it in something like the following...
var isSeleniumActive = parent.seleniumAlert;
if (isSeleniumActive) {
alert("Selenium");
} else {
alert("Not selenium");
}
I'm not sure if the seleniumAlert function here is likely to sick around forever, so be aware if you're taking this that you may be relying on internal selenium implementation details of selenium.
There i was facing the same problem and i use a single line of code and it helps.
i was getting the error about the page is getting auto refresh
plus this warning:
-1490472087141 Marionette WARN Using deprecated data structure for setting timeouts
all i use is
Thread.sleep(2000)
and it worked for me.
I think that you can pause, or use a click and wait. There are a few good articles on the google. Good luck.
Edit for your comment:
How about the waitFor command?