CasperJS not finding element by class when loaded via ajax - ajax

I used several methods of attack attempting to get Casper to see the element in question, which gets loaded via a 2nd GET request that returns a bunch of json to get loaded into the page's DOM.
The thing is this.waitForResource(url,....) works fine executing the success callback after about 2 seconds (I have a timeout of 20 set).
I then tried first this.click('.class-name') inside followed by this.evaluate(function(){document.getElementsByClassName('.class-name')[0].click()});
Click via casperJS returns CasperError: Cannot dispatch mousedown event on nonexistent selector: .class-name while I'm not sure what the DOM action does - my this.on('resource.received',....) call immediately after doesn't capture anything so I assume it also had no effect either. DOM code seems to fail silently in Casper sometimes.
What can be done to select elements and click them to download files only after they are loaded into the DOM via ajax?
Is there a better library than CasperJS for this?

Casper has waitForSelector and waitFor methods that will suit your need.
waitFor will wait until provided function returns true
waitForSelector will wait until provided selector is in DOM, so I guess this is the one you want to use.
Additionaly there is waitUntilVisible which wait until an element is visible on screen

Related

Cypress and find the element programatically, but its there and the UI can select it

I am having issues get'ing a css selector, its on the dom, and it can even be selected via the UI.
But cypress fails to get it.
There is not async stuff going on, just the page that was loaded.
As you can see in the image thelement is there, any ideas how to get round this?
If you say that the problem is with loading the page, maybe you should pass timeout paramater to the cy.get(), to make sure that Cypress waits long enough.
cy.get('nli-block-container .block-content', {timeout: 20000})
This should wait for 20 seconds for the element. If that doesn't work, please let me know, because it means that the problem lies elsewhere

Difficulties with Cypress scrollTo method

I am having a few issues testing a virtual scroll component with Cypress. I have a test that checks the li elements present in the DOM after scrolling to the bottom of a container.
When written like this the test passes:
cy.get('.virtual-scroll').scrollTo('bottom')
cy.wait(0)
cy.get('li').last().children('h4').contains('1999')
When written like this it doesn't:
cy.get('.virtual-scroll').scrollTo('bottom')
cy.get('li').last().children('h4').contains('1999')
This also fails:
cy.get('.virtual-scroll').scrollTo('bottom').get('li').last().children('h4').contains('1999')
In the second and third examples, get('li') is returning the li elements present before the scroll has completed, and therefore failing the test. I can fix this by adding .wait, but don't fully understand the behaviour and wonder if this is a bug.
Any ideas?
Make an assertion that will always pass when the DOM is rendered, such as using .get() for an element that gets added to the DOM
ex) if you had a <ul class="myloadedlist">.... :
cy.get('.virtual-scroll').scrollTo('bottom')
cy.get('ul.myloadedlist')
cy.get('li').last().children('h4').contains('1999')
That way, Cypress will continue with the test as soon as that element becomes visible.
Why?
I'm assuming the elements get added to the DOM in some sort of scroll eventListener. In that case this is correct behavior.
Essentially what you've tested is the race condition of a user scrolling very quickly to the bottom of the page, to see that the DOM has not yet finished rendering- a valid senario.
Since you targeted the last() li element, Cypress finds the last element of the page before the DOM gets updated, and expects it to contain 1999, which it does not, even after Cypress retries for 4 seconds.
This is actually a great feature of Cypress, because you can test on the state of the DOM at times that the User might only see for a split second.
In my case, adding a duration to the scroll option did the trick.
cy.get("#dialogContent").scrollTo("center", { duration: 500 });

How does readyState work?

I check the property .readyState of BrowserTestObject using RFT (Rational Functional Tester).
Sometimes before the next step in my test script I need to be sure that the page is 'ready' and all objects are loaded.
Does the .readyState == 4 mean that all objects within the browser are loaded and ready? Could any ajax call in background be still "working" or it must finish before the browser returns .readyState=4? What about a flex application?
Is that behavior browser independent or not really? I am after IE 8 (and firefox 3.6.x)
quick answer is YES if browser implementation is correct.
See here: http://www.whatwg.org/specs/web-apps/current-work/multipage/dom.html#current-document-readiness
I would say no. If I understood discussion here, readyState used thus only refers to the test javascript, nothing else. To wait that the document itself is loaded, you need to hook to document.readyState and wait for it to become "complete". In that case, once the HTML parsing is complete, the document.readyState would be "complete" once and for all, and will not be affected by any XMLHttpRequest whatsoever. Flash plugins could or could not have started; most certainly there would be lots of javascript running; for example $(function() {}) construct in jquery often means that javascript code could start executing only after the browser hits the "complete" state.
To test if any asynchronous requests are going on, I suggest hooking the readyState event of all XMLHttpRequests somehow and make it update a global variable.

Watir and Ajax requests

In my webapp I have a simple textfield. To this textfield I have a jQuery function which will be always executed on every keyup. With this function there is an Ajax request assigned which loads every time the result of the SQL-Query. My code is equivalent to the code of
RailsCasts. Now I'm testing my webapp with Selenium. With this line of code
browser.text_field(:id => 'textfield').set("Search text")
the text will be written and the content will be changed. After it should click on a link which is placed on the dynamic content with this code
browser.a(:id => "link").click
The problem now is that the click event won't be executed. Has somebody an idea what the problem could be? Or maybe an example with Watir and Ajax?
Without an example site to test against it's hard to be sure but I will throw out a few potential solutions for you
If the client side javascript is looking for onkeyup events, you may need to fire one after setting the contents of the field. You can do that via the .fire_event method
You could just be looking at a timing issue. If the nature of the link is changing as a result of the input, it's possible that Watir is firing off the two comments in rapid succession and the client side code is still in the midst of doing it's thing (especially if there is back and forth between the jquery code and the webserver that as happening as that also induces networking delays. You may need a brief sleep between commands (brute force) or to wait for a particular element to assume an expected state (a little more work but also a bit more robust and not subject to breaking is the delay exceeds your sleep duration)
I'd suggest executing the commands manually via IRB (you could just cut and paste from your script as needed) to be able to watch the state of the browser, and note any delay in updating the screen/DOM after a particular action. If stuff works properly in IRB but not when executed via a script it's often taken as confirmation of a timing issue.
If this is the original Watir/Firewatir I would try getting it to hover over the link before it attempts to click it.
I've had this problem previously with links that appear after typing into an "autocomplete" field (i.e. it attempts to guess at the text you want by filtering down from a huge list of possibilities).
Try this:
browser.wait_until{browser.link(:id => "link").present?}
browser.link(:id => "link").fire_event("onmouseover")
browser.link(:id => "link").click
If it works, try it without the .fire_event("onmouseover"), because it could just be that it's trying to click the link before it's visible and failing to do so.
If this is actually a question regarding "Selenium" (wrongly labelled Watir) then ignore all of the above, because I that is an application I've never used.
you can use capybara method.
click_link("link")
for ajax set :js => true in you test case
http://opinionatedprogrammer.com/2011/02/capybara-and-selenium-with-rspec-and-rails-3/

Detect when AJAX changes HTML in a DIV in WebBrowser

After I load a page through a WebBrowser, and I click a link that fires an AJAX script, I need to detect when the AJAX java script finishes loading HTML changes into a div. Since no DocumentCompleted event is fired when the AJAX script is run, I don't know when it finish running. Is there a way I can attach an event to be raised after I know 100% that the javascript finished changing the div?
The project is in C#.
Thanks
I did something similar recently (using jQuery):
$('#mydiv').change(function(){
// do stuff
}
);
Granted, I also use jQuery to set the HTML of that div. I suppose one non-jQuery approach for you could be to set HTML through your own function, which in turn can fire an onchange event.
#New in town: From my experience that is not correct. I use this on multiple DIVs that never get focus in the first place, and it works well and consistently. The normal behavior is as you describe, and normally only applies to the INPUT and SELECT elements, but this is not the case with jQuery.
There is no event. You must patch the JavaScript callback that the browser runs when the reply for the AJAX request comes in. This will contains code like "div.innerHTML = ...". Just put your code below that.

Resources