Poltergeist #visit doesn't [always] load the page - poltergeist

I have an integration test that runs through a "confirm details" process, and then goes back to the main page to verify that the details have indeed been processed.
However, when I visit the main page near the end of the test, it doesn't go there...
within '#confirm_details' do
page.find_button("Continue").trigger('click')
end
find("#email_confirmation_modal a.email_confirmation_yes").trigger('click')
expect(page).to have_css('span.balance') # Probably a false positive, but I've also
# checked for elements that should only be there after the click
visit '/myaccount'
expect(page).to have_current_path '/myaccount'
... result:
Failure/Error: expect(page).to have_current_path('/myaccount')
expected "/sign_up/confirm_details" to equal "/myaccount"
... but sometimes it's fine. Anyone have an idea why?
(I'll add other details here as I think of them.)
The my_account action in the controller doesn't always get fired (this should surely be the app's entry point, right?)
When it does work, the page loads in well under a second, so it's not running into the 2-second limit. In fact I've tried looping visit '/myaccount' until page.current_path == '/myaccount' and it hung.

Page load is not guaranteed to have finished when visit returns (drivers try to do their best on that, but it's not always possible). For that reason you should always use a Capybara provided matcher when there is one for what you're trying to test since they have waiting/retrying behavior built in. In your case you should never use the RSpec provided eq matcher with current_path, instead you should be using the Capybara provided have_current_path matcher.
visit '/myaccount'
expect(page).to have_current_path('/myaccount')
If that doesn't fix your issue then it's likely to be something with your code that is filling in the "confirm details" so you'll probably want to add the tests full code to the question.

Related

WKWebView - didFinishNavigation or decidePolicyForNavigationResponse not being called on goBack action

I am not sure whether its a usual behavior or not, but, on [WKWebView goBack] navigates to previous page from the Back-Forward list. but, in my case on very first back action, it does not calls didFinishNavigation delegate method.
So, if it's usual behavior then how to detects that page loading is completed after back the action.
Are you seeing this on a specific iOS version? Im seeing this too, only and error is being thrown and the page just stops loading, hence didFinish... not being called.
I've only started seeing this since 13.4 (or 13.4.1)
--- EDIT ---
I do have a workaround.
This appears to happen more often on slower networks and when the user interacts before a page is fully loaded. Normally if a user taps back before the page they visited finished loading then a "Cancelled" error is thrown.
What seems to be happening now is, if the page they are returning to never finished loading at the point they left, then the error is thrown again, but this time referencing the page they are returning to. and more importantly the web view is no longer loading at this point.
what we have done is monitor this and check to see if the page is not loading, and if it isn't, reload it. This seems to work and while not ideal, its buying us some time to investigate a proper fix.
In addition, I put a retry limit on this and we show an error with a reload button after the third attempt, though in practice we've never seen it go beyond the first reload attempt.
The fact that the error is thrown almost instantaneously means the reload adds no perceivable delay for the user.
I even see this on the simulator. Navigate to google.com, click privacy, then goBack and while the page loads normally, navigation reports a failure with error:
Error Domain=NSURLErrorDomain Code=-999 "(null)" UserInfo={NSErrorFailingURLStringKey=https://www.google.com/, NSErrorFailingURLKey=https://www.google.com/, _WKRecoveryAttempterErrorKey=<WKReloadFrameErrorRecoveryAttempter: 0x600003904e40>}
What you need to do is capture this with the didFailNavigation: delegate method and handle it gracefully (if you see a consistent error like the above you can even treat it exactly the same as success).

How to make an action when the page fails to load?

How do I know when a page fails to load?
When there's a server error, and I get the gray window that sayd "Google Chrome fails to load this page..." or "this page in not available" ?
I want to add my extension an option of auto refresh after 10 seconds. I work with some web-app that sometimes the server fails to load for some reason, and a refresh just brings it back to life.
So I'm looking for auto-refresh in this case.
Thanks in advance!
You may want to take a look at the chrome.webRequest.onErrorOccurred.addListener(function details){} listener. Per the documentation, errors that are triggered by any event before the completion of a request will fire the onErrorOccurred method. The details will contain information about the error, but in your case it sounds like any triggered error should cause a refresh, so perhaps something like this (completely untested, more theoretical :) ):
chrome.webRequest.onErrorOccurred.addListener(function details){
chrome.tabs.reload(details.tabId);
}

Capybara Cucumber test fail to find xpath when browser is minimized

I'm running a scenario where form fields are automatically filled in with invalid values which trigger some javascripts to show warnings under each incorrectly filled field when I blur.
The test passes when the browser is in focus. It finds the xpath with the "expected warning" that I pass. But if I minimize or just click on another application, it fails to find the xpath.
I'm running Firefox 3.6 (going to update it soon) and the way I'm doing to find the xpath is by using "page.should have_xpath(xpath)"
Does anyone have any idea how what might solve this? It's really important for me to run it with the browser minimized.
Edit and alternative solution:
I guess the timing issue that occurs in events such as blur followed by finding a certain xpath in a minimized browser inherent to the driver itself. Therefore, I decided to run the tests in a Virtual Frame Buffer using xvfb in Linux and it seems to be working really well. I'm planning on applying this to be triggered by Hudson/Jenkins whenever a change is committed.
Could it be a timing issue? Perhaps if the browser isn't frontmost and maximised, the rendering is not happening quickly enough for the content be present when Capybara checks for it.
Also: How are you triggering the blur event?

How to use Geb to check element attribute value after page event

After a bit of help here, I am writing a functional web test using Geb and want to test the disabled attribute value of an form submit button both before and after an event has occurred, the flow should be as follows:
Load page, submit button is declared as disabled in page source so should be disabled e.g. <input type="submit" class="submit" disabled="true"/>.
Check a checkbox on the page, this should result in a piece of JQuery code executing which will enable the disabled submit button programatically using: $('input.submit').attr('disabled', false);
My first attempt was to use the assertion $('input.submit').#disabled == 'true', this appeared to work for the initial check after page load however after executing my JQuery code to enable the button a subsequent check still returns the same result. This has caused me to wonder if this kind of check is only able to report the value at page load time and doesn't see any subsequent programmatic changes?
I then discovered Geb's jquery itegration, I was hoping I could use this to return the value of the submit button and do my assert on this e.g. $('input.submit').jquery.attr('disabled') == false however the Geb documentation confirms that all calls to the .jquery property return the Geb Navigator instance so sadly I don't think I can return the information I want.
I have also doubted whether the JQuery code was actually toggling the submit button disabled state, I have tested this extensively using Firebug and can confirm that this is working perfectly in the browser, so I suspect this is either an issue with my understanding of Geb or perhaps a limitation of Geb itself?
It strikes me that checking the value of element attributes after performing some action on a page might be a common use-case, hence I'm rather hoping that I've missed some trivially simple way of doing this. Would be most grateful for any pointers to help me get this sorted.
Cheers,
Edd
Have done a bit more testing and have now achieved a satisfactory result. I was doing a couple of things which I now believe are inproper, namely trying to set the disabled attribute value to illegal values of true and false like this:
$('input.submit').attr('disabled', true);
$('input.submit').attr('disabled', false);
Looking at the HTML forms specification the disabled attribute is shown not to take a value, rather it's presence alone indicates that an element is disabled. Modifying my code to honour this and remove the attribute to indicate enablement of an element seems to have done the trick:
$('input.submit').attr('disabled', true);
//This time we remove the disabled attribute rather than setting it to false.
$('input.submit').removeAttr('disabled');
Note: I am still setting the value of disabled to true since I can't determine how to set the attribute without setting a value, see this SO post for further details.
Using the above I am now able to use Geb to assert the disabled/ enabled status of elements like this:
//Check that something is disabled.
deleteSelectedButton.#disabled == 'true'
//Check that something is enabled.
deleteSelectedButton.#disabled == 'false'
Note: Geb seems to require a string literal indicating the expected status rather than a boolean, which iirc caused my assertions to fail.
So that's it - all is now working nicely and I'm running along writing loads of Geb tests! Hope this explanation is of some use to others.
Rebroadcasting my post on the Geb mailing list:
After you execute the jQuery code that enables the button, is it possible that you are checking the result before the code has actually enabled the button? For example, are doing something like:
waitFor { $("input.submit").#disabled == "false" }

Adapting Modal Dialog Script to Firefox

I'm adapting my regression tests to test a web app in firefox. The biggest stumbling block seems to be how to automate the modal dialogs in firefox.
In ie I use variations of the script below, but it doesn't work in Firefox. Is there an alternative that will work in both ie and firefox?
popup=Thread.new {
autoit=WIN32OLE.new('AutoItX3.Control')
ret=autoit.WinWait(title,"",60)
if (ret==1)
puts "There is popup."
autoit.WinActivate(title)
button.downcase!
if button.eql?("ok") || button.eql?("yes") || button.eql?("continue")
autoit.Send("{Enter}")
else
autoit.Send("{tab}")
autoit.Send("{Enter}")
end
elsif (ret==0)
puts "No popup, please check your code."
end
}
at_exit { Thread.kill(popup) }
end
button.click_no_wait
check_for_popups("Message from webpage", "OK")
Given you are talking about a javascript created dialog, I really have to ask, is there a lot of value in actually testing those?
It basically amounts to testing the functionality of the browser
If you are talking about the type of popups described here http://wiki.openqa.org/display/WTR/JavaScript+Pop+Ups then I think the first solution, of overriding the javascript may well be your best cross platform option.
The problem with modal dialogs like this is that they are basically a UI even that is happening out at the OS level, it's no longer inside the browser DOM, and thus you need tools that are specific to the OS (like stuff that depends on win32ole, such as autoit) in order to generate the necessary interaction with the native UI and click buttons, send keystrokes etc. Most of the solutions presented should I think work with FF on windows (with proper renaming of expected window titles etc) but would fail on a mac or *nix OS. That means you need a different solution for each OS, which is a pain.
It might simply be easier to verify you can find the proper stuff that would fire the event in the HTML of the page, so you know an event WOULD be fired, and then override things so it isn't. After all it's not really your job to validate that the browser pops up a local dialog when something like alert('This is an alert box') is invoked in javascript. Your concern is that in the HTML a given element is coded to fire off the event that is needed e.g. that there's something like this onClick = 'javascript:x = confirm('Do you really want to do this');" affiliated with the element
I am experiencing a similar problem in Firefox (and I do have to test in Firefox). I can see the code calling the Javascript but when I try to override as described above nothing happens. Is there any kind of a workaround for this? Anticipated updates to Watir? ;-)

Resources