Reputation: 900
I'm trying to write unit tests with Zombie.js. My problem is that AJAX requests aren't finishing when initiated using browser.evaluate
, even though they execute fine when included on the page with a script tag.
I have three files:
index.html
: the HTML page which zombie loadshello.txt
: a plain text file with the contents hello, world
main.js
: a zombie.js program which loads index.html
index.html
and hello.txt
are served using the command python -m SimpleHTTPServer 8009
. (note that I'm using dev.local
, which is a synonym for 127.0.0.1
in my hosts file)
Here is index.html
. It makes an AJAX request to retrieve hello.txt
. This works fine:
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8' />
<title></title>
</head>
<body>
<script type='text/javascript' src='https://code.jquery.com/jquery-2.2.0.min.js'>
</script>
<script type='text/javascript'>
$.support.cors = true;
var doRequest = function(msg) {
$.support.cors = true;
return $.ajax({
url: "http://dev.local:8009/hello.txt",
success: function(v) { console.log("success ", msg, v); }
});
};
</script>
<script type="text/javascript">
console.log("page loaded");
doRequest('script');
</script>
</body>
</html>
Here's main.js
. It navigates to index.html
and tries to evaluate the doRequest
function, which should cause an AJAX request. However, the request never completes, and instead times out.
var Browser = require("zombie");
const browser = new Browser({debug: true});
const rootURL = "http://dev.local:8009/"
browser.visit(rootURL, function(err) {
browser.evaluate('console.log("browser.evaluate ✔");');
browser.evaluate('doRequest("zombie");');
});
Here is the log from running DEBUG=zombie node ./main.js
:
zombie Opened window http://dev.local:8009/ +0ms
zombie GET http://dev.local:8009/ => 200 +38ms
zombie Loaded document http://dev.local:8009/ +36ms
zombie GET https://code.jquery.com/jquery-2.2.0.min.js => 200 +55ms
page loaded
zombie XHR readystatechange http://dev.local:8009/hello.txt +64ms
zombie XHR loadstart http://dev.local:8009/hello.txt +1ms
zombie GET http://dev.local:8009/hello.txt => 200 +9ms
zombie XHR readystatechange http://dev.local:8009/hello.txt +1ms
zombie XHR readystatechange http://dev.local:8009/hello.txt +0ms
zombie XHR readystatechange http://dev.local:8009/hello.txt +1ms
zombie XHR progress http://dev.local:8009/hello.txt +0ms
success script hello, world
zombie XHR load http://dev.local:8009/hello.txt +2ms
zombie XHR loadend http://dev.local:8009/hello.txt +0ms
zombie Fired setTimeout after 0ms delay +1ms
zombie Event loop is empty +0ms
browser.evaluate ✔
zombie XHR readystatechange http://dev.local:8009/hello.txt +4ms
zombie XHR loadstart http://dev.local:8009/hello.txt +0ms
zombie GET http://dev.local:8009/hello.txt => 200 +6ms
Oddly, zombie seems to have actually completed the request: the final line of the log shows that a HTTP 200
response was received, but the event was never given to the handler.
Why doesn't the zombie-initiated request complete correctly?
Upvotes: 1
Views: 897
Reputation: 2625
The above answer is correct. Using wait
, you can get data that is ajaxed. Just another example to adapt by creating a function that accepts the browser as a parameter:
async function getAjaxedData(url, browser) {
return browser.visit(url).wait().then(() => {
// Do stuff
// e.g. browswer.queryAll(selector)
});
}
Upvotes: 0
Reputation: 1718
I got the same issue with zombie.js and so i looked at the source and found the following lines:
// -- Event processing --
// Grabs next event from the queue, processes it and notifies all listeners.
// Keeps processing until the queue is empty or all listeners are gone. You
// only need to bootstrap this when you suspect it's not recursing.
//... more lines ...
// Is there anybody out there?
if (this.waiting === 0)
return;
so no events get fired if noone is waiting you need to add browser.wait()
browser.visit(rootURL, function(err) {
browser.evaluate('console.log("browser.evaluate ✔");');
browser.evaluate('doRequest("zombie");');
browser.wait();
});
Upvotes: 1