Détail du package

zombie

assaf19.9kMIT6.1.4

Insanely fast, full-stack, headless browser testing using Node.js

test, tests, testing, TDD

readme

Zombie.js

Insanely fast, headless full-stack testing using Node.js

NPM Changelog Travis.ci JS.ORG

The Bite

If you're going to write an insanely fast, headless browser, how can you not call it Zombie? Zombie it is.

Zombie.js is a lightweight framework for testing client-side JavaScript code in a simulated environment. No browser required.

Let's try to sign up to a page and see what happens:

const Browser = require('zombie');

// We're going to make requests to http://example.com/signup
// Which will be routed to our test server localhost:3000
Browser.localhost('example.com', 3000);

describe('User visits signup page', function() {

  const browser = new Browser();

  before(function(done) {
    browser.visit('/signup', done);
  });

  describe('submits form', function() {

    before(function(done) {
      browser
        .fill('email',    'zombie@underworld.dead')
        .fill('password', 'eat-the-living')
        .pressButton('Sign Me Up!', done);
    });

    it('should be successful', function() {
      browser.assert.success();
    });

    it('should see welcome page', function() {
      browser.assert.text('title', 'Welcome To Brains Depot');
    });
  });
});

This example uses the Mocha testing framework, but Zombie will work with other testing frameworks. Since Mocha supports promises, we can also write the test like this:

const Browser = require('zombie');

// We're going to make requests to http://example.com/signup
// Which will be routed to our test server localhost:3000
Browser.localhost('example.com', 3000);

describe('User visits signup page', function() {

  const browser = new Browser();

  before(function() {
    return browser.visit('/signup');
  });

  describe('submits form', function() {

    before(function() {
      browser
        .fill('email',    'zombie@underworld.dead')
        .fill('password', 'eat-the-living');
      return browser.pressButton('Sign Me Up!');
    });

    it('should be successful', function() {
      browser.assert.success();
    });

    it('should see welcome page', function() {
      browser.assert.text('title', 'Welcome To Brains Depot');
    });
  });

});

Well, that was easy.

WARNING: Crawling untrusted web pages with Zombie.js is not safe.

Table of Contents

Installing

To install Zombie.js you will need Node.js:

$ npm install zombie --save-dev

Browser

browser.assert

Methods for making assertions against the browser, such as browser.assert.element('.foo').

See Assertions for detailed discussion.

browser.referer

You can use this to set the HTTP Referer header.

browser.resources

Access to history of retrieved resources. See Resources for detailed discussion.

browser.pipeline

Access to the pipeline for making requests and processing responses. Use this to add new request/response handlers the pipeline for a single browser instance, or use Pipeline.addHandler to modify all instances. See Pipeline.

browser.tabs

Array of all open tabs (windows). Allows you to operate on more than one open window at a time.

See Tabs for detailed discussion.

browser.proxy

The proxy option takes a URL so you can tell Zombie what protocol, host and port to use. Also supports Basic authentication, e.g.:

browser.proxy = 'http://me:secret@myproxy:8080'

browser.attach(selection, filename, callback)

Attaches a file to the specified input field. The second argument is the file name. callback - called with error or nothing.

browser.back([callback])

Navigate to the previous page in history. Returns the zombie.browser.Browser to allow function chaining.

browser.body

Returns a zombie.dom.DOMNode representing the body element of the current document.

browser.check(selector, [callback])

Checks a checkbox. If called without a callback, returns a promise.

browser.choose(selector, [callback])

selects a radio box option. If called without a callback, returns a promise.

browser.clickLink(selector, callback)

Clicks on a link. Clicking on a link can trigger other events, load new page, etc. Use a callback to be notified of completion. Finds link by text content or selector.

browser.dump([output])

Dump information to the console: Zombie version, current URL, history, cookies, event loop, etc. Useful for debugging and submitting error reports. output defaults to process.stdout.

browser.evaluate(code, filename)

Evaluates a JavaScript expression in the context of the current window and returns the result. When evaluating external script, also include filename.

You can also use this to evaluate a function in the context of the window: for timers and asynchronous callbacks (e.g. XHR).

browser.field(selector)

Find and return an input field (INPUT, TEXTAREA or SELECT) based on a CSS selector, field name (its name attribute) or the text value of a label associated with that field (case sensitive, but ignores leading/trailing spaces).

browser.fill(selector, value, callback)

Fill in an input field or text area with the provided value.

browser.fire(selector, eventName, [callback])

Fire a DOM event. You can use this to simulate a DOM event, e.g. clicking a link. These events will bubble up and can be cancelled. Like wait this method takes an optional callback. If called without a callback, returns a promise.

browser.link(selector)

Finds and returns a link by its text content or selector.

browser.load(html, [callback])

Loads the HTML, processes events and calls the callback. Without a callback, returns a promise.

browser.location

Return the location of the current document (same as window.location).

browser.pressButton(selector, [callback])

Press a button (button element or input of type submit). Typically this will submit the form. Use the callback to wait for the from submission, page to load and all events run their course.

browser.query(selector, [context])

Evaluates the CSS selector against the document (or context node) and return an element.
context defaults to document.

browser.queryAll(selector, [context])

Evaluates the CSS selector against the document (or context node) and return array of nodes. context defaults to document.

browser.querySelector(selector)

Selects the first matching element and returns it.

browser.redirected

Returns True if the page request followed a redirect.

browser.reload()

Reloads the current page. Returns the zombie.browser.Browser to allow function chaining.

browser.select(selector, value, [callback])

Selects an option inside of selector with given value. If called without a callback, returns a promise.

browser.selectOption(selector, [callback])

Selects an option.

browser.status

Returns the status code returned for this window (200, 303, etc). The same as browser.statusCode

browser.success

Return true if last response had status code 200 .. 299

browser.text(selector, [context])

Returns the text contents of the selected elements. context defaults to document.

browser.uncheck(selector, [callback])

Unchecks a checkbox. If called without a callback, returns a promise.

browser.unselect(selector, value, [callback])

Unselects an option. If called without a callback, returns a promise.

browser.unselectOption(selector, [callback])

Unselects the an option. If called without a callback, returns a promise.

browser.visit(url, options, [callback])

Loads document from the specified URL, processes events and calls the callback, or returns a promise.

browser.click(selector, [callback])

Click on the selected element. If called without callback, returns a promise.

browser.errors

Collection of errors accumulated by the browser while loading page and executing scripts.

browser.source

Returns a string of the source HTML from the last response.

browser.html(element)

Returns a string of HTML for a selected HTML element. If argument element is undefined, the function returns a string of the source HTML from the last response.

Example uses:

browser.html('div');
browser.html('div#contain');
browser.html('.selector');
browser.html();

Browser.localhost(host, port)

Allows you to make requests against a named domain and HTTP/S port, and will route it to the test server running on localhost and unprivileged port.

For example, if you want to call your application "example.com", and redirect traffic from port 80 to the test server that's listening on port 3000, you can do this:

Browser.localhost('example.com', 3000)
browser.visit('/path', function() {
  console.log(browser.location.href);
});
=> 'http://example.com/path'

The first time you call Browser.localhost, if you didn't specify Browser.site, it will set it to the hostname (in the above example, "example.com"). Whenever you call browser.visit with a relative URL, it appends it to Browser.site, so you don't need to repeat the full URL in every test case.

You can use wildcards to map domains and all hosts within these domains, and you can specify the source port to map protocols other than HTTP. For example:

// HTTP requests for example.test www.example.test will be answered by localhost
// server running on port 3000
Browser.localhost('*.example.test', 3000);
// HTTPS requests will be answered by localhost server running on port 3001
Browser.localhost('*.example.test:443', 3001);

The underlying implementation hacks net.Socket.connect, so it will route any TCP connection made by the Node application, whether Zombie or any other library. It does not affect other processes running on your machine.

Browser.extend

You can use this to customize new browser instances for your specific needs. The extension function is called for every new browser instance, and can change properties, bind methods, register event listeners, etc.

Browser.extend(function(browser) {
  browser.on('console', function(level, message) {
    logger.log(message);
  });
  browser.on('log', function(level, message) {
    logger.log(message);
  });
});

Assertions

To make life easier, Zombie introduces a set of convenience assertions that you can access directly from the browser object. For example, to check that a page loaded successfully:

browser.assert.success();
browser.assert.text('title', 'My Awesome Site');
browser.assert.element('#main');

These assertions are available from the browser object since they operate on a particular browser instance -- generally dependent on the currently open window, or document loaded in that window.

Many assertions require an element/elements as the first argument, for example, to compare the text content (assert.text), or attribute value (assert.attribute). You can pass one of the following values:

  • An HTML element or an array of HTML elements
  • A CSS selector string (e.g. "h2", ".book", "#first-name")

Many assertions take an expected value and compare it against the actual value. For example, assert.text compares the expected value against the text contents of one or more strings. The expected value can be one of:

  • A JavaScript primitive value (string, number)
  • undefined or null are used to assert the lack of value
  • A regular expression
  • A function that is called with the actual value and returns true if the assertion is true
  • Any other object will be matched using assert.deepEqual

Note that in some cases the DOM specification indicates that lack of value is an empty string, not null/undefined.

All assertions take an optional last argument that is the message to show if the assertion fails. Better yet, use a testing framework like Mocha that has good diff support and don't worry about these messages.

Available Assertions

The following assertions are available:

assert.attribute(selection, name, expected, message)

Asserts the named attribute of the selected element(s) has the expected value.

Fails if no element found.

browser.assert.attribute('form', 'method', 'post');
browser.assert.attribute('form', 'action', '/customer/new');
// Disabled with no attribute value, i.e. <button disabled>
browser.assert.attribute('button', 'disabled', '');
// No disabled attribute i.e. <button>
browser.assert.attribute('button', 'disabled', null);

assert.className(selection, className, message)

Asserts that selected element(s) has that and only that class name. May also be space-separated list of class names.

Fails if no element found.

browser.assert.className('form input[name=email]', 'has-error');

assert.cookie(identifier, expected, message)

Asserts that a cookie exists and has the expected value, or if expected is null, that no such cookie exists.

The identifier is either the name of a cookie, or an object with the property name and the optional properties domain and path.

browser.assert.cookie('flash', 'Missing email address');

assert.element(selection, message)

Asserts that one element matching selection exists.

Fails if no element or more than one matching element are found.

browser.assert.element('form');
browser.assert.element('form input[name=email]');
browser.assert.element('form input[name=email].has-error');

assert.elements(selection, count, message)

Asserts how many elements exist in the selection.

The argument count can be a number, or an object with the following properties:

  • atLeast - Expecting to find at least that many elements
  • atMost - Expecting to find at most that many elements
  • exactly - Expecting to find exactly that many elements
browser.assert.elements('form', 1);
browser.assert.elements('form input', 3);
browser.assert.elements('form input.has-error', { atLeast: 1 });
browser.assert.elements('form input:not(.has-error)', { atMost: 2 });

assert.evaluate(expression, expected, message)

Evaluates the JavaScript expression in the context of the currently open window.

With one argument, asserts that the value is equal to true.

With two/three arguments, asserts that the returned value matches the expected value.

browser.assert.evaluate('$("form").data("valid")');
browser.assert.evaluate('$("form").data("errors").length', 3);

assert.global(name, expected, message)

Asserts that the global (window) property has the expected value.

assert.hasClass(selection, className, message)

Asserts that selected element(s) have the expected class name. Elements may have other class names (unlike assert.className).

Fails if no element found.

browser.assert.hasClass('form input[name=email]', 'has-error');

assert.hasFocus(selection, message)

Asserts that selected element has the focus.

If the first argument is null, asserts that no element has the focus.

Otherwise, fails if element not found, or if more than one element found.

browser.assert.hasFocus('form input:nth-child(1)');

assert.hasNoClass(selection, className, message)

Asserts that selected element(s) does not have the expected class name. Elements may have other class names (unlike assert.className).

Fails if no element found.

browser.assert.hasNoClass('form input', 'has-error');

assert.input(selection, expected, message)

Asserts that selected input field(s) (input, textarea, select etc) have the expected value.

Fails if no element found.

browser.assert.input('form input[name=text]', 'Head Eater');

assert.link(selection, text, url, message)

Asserts that at least one link exists with the given selector, text and URL. The selector can be a, but a more specific selector is recommended.

URL can be relative to the current document, or a regular expression.

Fails if no element is selected that also has the specified text content and URL.

browser.assert.link('footer a', 'Privacy Policy', '/privacy');

assert.redirected(message)

Asserts the browser was redirected when retrieving the current page.

assert.success(message)

Asserts the current page loaded successfully (status code 2xx or 3xx).

assert.status(code, message)

Asserts the current page loaded with the expected status code.

browser.assert.status(404);

assert.style(selection, style, expected, message)

Asserts that selected element(s) have the expected value for the named style property. For example:

Fails if no element found, or element style does not match expected value.

browser.assert.style('#show-hide.hidden', 'display', 'none');
browser.assert.style('#show-hide:not(.hidden)', 'display', '');

assert.text(selection, expected, message)

Asserts that selected element(s) have the expected text content. For example:

Fails if no element found that has that text content.

browser.assert.text('title', 'My Awesome Page');

assert.url(url, message)

Asserts the current page has the expected URL.

The expected URL can be one of:

  • The full URL as a string
  • A regular expression
  • A function, called with the URL and returns true if the assertion is true
  • An object, in which case individual properties are matched against the URL

For example:

browser.assert.url('http://localhost/foo/bar');
browser.assert.url(new RegExp('^http://localhost/foo/\\w+$'));
browser.assert.url({ pathname: '/foo/bar' });
browser.assert.url({ query: { name: 'joedoe' } });

Roll Your Own Assertions

Not seeing an assertion you want? You can add your own assertions to the prototype of Browser.Assert.

For example:

// Asserts the browser has the expected number of open tabs.
Browser.Assert.prototype.openTabs = function(expected, message) {
  assert.equal(this.browser.tabs.length, expected, message);
};

Or application specific:

// Asserts which links is highlighted in the navigation bar
Browser.Assert.navigationOn = function(linkText) {
  this.assert.element('.navigation-bar');
  this.assert.text('.navigation-bar a.highlighted', linkText);
};

Cookies

Are delicious. Also, somewhat tricky to work with. A browser will only send a cookie to the server if it matches the request domain and path.

Most modern Web applications don't care so much about the path and set all cookies to the root path of the application (/), but do pay attention to the domain.

Consider this code:

browser.setCookie({ name: 'session', domain: 'example.com', value: 'delicious' });
browser.visit('http://example.com', function() {
  const value = browser.getCookie('session');
  console.log('Cookie', value);
});

In order for the cookie to be set in this example, we need to specify the cookie name, domain and path. In this example we omit the path and choose the default /.

To get the cookie in this example, we only need the cookie name, because at that point the browser has an open document, and it can use the domain of that document to find the right cookie. We do need to specify a domain if we're interested in other cookies, e.g for a 3rd party widget.

There may be multiple cookies that match the same host, for example, cookies set for .example.com and www.example.com will both match www.example.com, but only the former will match example.com. Likewise, cookies set for / and /foo will both match a request for /foo/bar.

getCookie, setCookie and deleteCookie always operate on a single cookie, and they match the most specific one, starting with the cookies that have the longest matching domain, followed by the cookie that has the longest matching path.

If the first argument is a string, they look for a cookie with that name using the hostname of the currently open page as the domain and / as the path. To be more specific, the first argument can be an object with the properties name, domain and path.

The following are equivalent:

browser.getCookie('session');
browser.getCookie({ name: 'session',
                    domain: browser.location.hostname,
                    path: browser.location.pathname });

getCookie take a second argument. If false (or missing), it returns the value of the cookie. If true, it returns an object with all the cookie properties: name, value, domain, path, expires, httpOnly and secure.

browser.cookies

Returns an object holding all cookies used by this browser.

browser.cookies.dump(output?)

Dumps all cookies to standard output, or the output stream.

browser.deleteCookie(identifier)

Deletes a cookie matching the identifier.

The identifier is either the name of a cookie, or an object with the property name and the optional properties domain and path.

browser.deleteCookies()

Deletes all cookies.

browser.getCookie(identifier, allProperties?)

Returns a cookie matching the identifier.

The identifier is either the name of a cookie, or an object with the property name and the optional properties domain and path.

If allProperties is true, returns an object with all the cookie properties, otherwise returns the cookie value.

browser.setCookie(name, value)

Sets the value of a cookie based on its name.

browser.setCookie(cookie)

Sets the value of a cookie based on the following properties:

  • domain - Domain of the cookie (requires, defaults to hostname of currently open page)
  • expires - When cookie it set to expire (Date, optional, defaults to session)
  • maxAge - How long before cookie expires (in seconds, defaults to session)
  • name - Cookie name (required)
  • path - Path for the cookie (defaults to /)
  • httpOnly - True if HTTP-only (not accessible from client-side JavaScript, defaults to false)
  • secure - True if secure (requires HTTPS, defaults to false)
  • value - Cookie value (required)

Tabs

Just like your favorite Web browser, Zombie manages multiple open windows as tabs. New browsers start without any open tabs. As you visit the first page, Zombie will open a tab for it.

All operations against the browser object operate on the currently active tab (window) and most of the time you only need to interact with that one tab. You can access it directly via browser.window.

Web pages can open additional tabs using the window.open method, or whenever a link or form specifies a target (e.g. target=_blank or target=window-name). You can also open additional tabs by calling browser.open. To close the currently active tab, close the window itself.

You can access all open tabs from browser.tabs. This property is an associative array, you can access each tab by its index number, and iterate over all open tabs using functions like forEach and map.

If a window was opened with a name, you can also access it by its name. Since names may conflict with reserved properties/methods, you may need to use browser.tabs.find.

The value of a tab is the currently active window. That window changes when you navigate forwards and backwards in history. For example, if you visited the URL '/foo' and then the URL '/bar', the first tab (browser.tabs[0]) would be a window with the document from '/bar'. If you then navigate back in history, the first tab would be the window with the document '/foo'.

The following operations are used for managing tabs:

browser.tabs

Returns an array of all open tabs.

browser.tabs[number]

Returns the tab with that index number.

browser.tabs[string]

browser.tabs.find(string)

Returns the tab with that name.

browser.tabs.closeAll()

Closes all tabs.

browser.tabs.current

This is a read/write property. It returns the currently active tab.

Can also be used to change the currently active tab. You can set it to a window (e.g. as currently returned from browser.current), a window name or the tab index number.

browser.tabs.dump(output?)

Dump a list of all open tabs to standard output, or the output stream.

browser.tabs.index

Returns the index of the currently active tab.

browser.tabs.length

Returns the number of currently opened tabs.

browser.open (url)

Opens and returns a new tab. Supported options are:

  • name - Window name.
  • url - Load document from this URL.

browser.window

Returns the currently active window, same as browser.tabs.current.

Debugging

To see what your code is doing, you can use console.log and friends from both client-side scripts and your test code.

To see everything Zombie does (opening windows, loading URLs, firing events, etc), set the environment variable DEBUG=zombie. Zombie uses the debug module. For example:

$ DEBUG=zombie mocha

You can also turn debugging on from your code (e.g. a specific test you're trying to troubleshoot) by calling browser.debug().

Some objects, like the browser, history, resources, tabs and windows also include dump method that will dump the current state to the console, or an output stream of your choice. For example:

browser.dump();
browser.dump(process.stderr);

If you want to disable console output from scripts, set browser.silent = true or once for all browser instances with Browser.silent = true.

Events

Each browser instance is an EventEmitter, and will emit a variety of events you can listen to.

Some things you can do with events:

  • Trace what the browser is doing, e.g. log every page loaded, every DOM event emitted, every timeout fired
  • Wait for something to happen, e.g. form submitted, link clicked, input element getting the focus
  • Strip out code from HTML pages, e.g remove analytics code when running tests
  • Add event listeners to the page before any JavaScript executes
  • Mess with the browser, e.g. modify loaded resources, capture and change DOM events

console (level, message)

Emitted whenever a message is printed to the console (console.log, console.error, console.trace, etc).

The first argument is the logging level, and the second argument is the message.

The logging levels are: debug, error, info, log, trace and warn.

active (window)

Emitted when this window becomes the active window.

closed (window)

Emitted when this window is closed.

done ()

Emitted when the event loop goes empty.

error (error)

Error when loading a resource, or evaluating JavaScript.

evaluated (code, result, filename)

Emitted after JavaScript code is evaluated.

The first argument is the JavaScript function or code (string). The second argument is the result. The third argument is the filename.

event (event, target)

Emitted whenever a DOM event is fired on the target element, document or window.

focus (element)

Emitted whenever an element receives the focus.

idle ()

Event loop is idle.

inactive (window)

Emitted when this window is no longer the active window.

interval (function, interval)

Emitted whenever an interval (setInterval) is fired.

The first argument is the function or code to evaluate, the second argument is the interval in milliseconds.

link (url, target)

Emitted when a link is clicked.

The first argument is the URL of the new location, the second argument identifies the target window (_self, _blank, window name, etc).

loaded (document)

Emitted when a document has been loaded into a window or frame.

This event is emitted after the HTML is parsed, and some scripts executed.

loading (document)

Emitted when a document is about to be loaded into a window or frame.

This event is emitted when the document is still empty, before parsing any HTML.

opened (window)

Emitted when a new window is opened.

redirect (request, response)

Emitted when following a redirect.

request (request)

Emitted before making a request to retrieve a resource.

The first argument is the request object. See Resources for more details.

response (request, response)

Emitted after receiving the response (excluding redirects).

The first argument is the request object, the second argument is the response object. See Resources for more details.

serverEvent ()

Browser received server initiated event (e.g. EventSource message).

setInterval (function, interval)

Event loop fired a setInterval event.

setTimeout (function, delay)

Event loop fired a setTimeout event.

submit (url, target)

Emitted whenever a form is submitted.

The first argument is the URL of the new location, the second argument identifies the target window (_self, _blank, window name, etc).

timeout (function, delay)

Emitted whenever a timeout (setTimeout) is fired.

The first argument is the function or code to evaluate, the second argument is the delay in milliseconds.

xhr (event, url)

Called for each XHR event (progress, abort, readystatechange, loadend, etc).

Authentication

Zombie supports HTTP basic access authentication. To provide the login credentials:

browser.on('authenticate', function(authentication) {
  authentication.username = 'myusername';
  authentication.password = 'mypassword';
});

browser.visit('/mypage');

Resources

Zombie can retrieve with resources - HTML pages, scripts, XHR requests - over HTTP, HTTPS and from the file system.

Most work involving resources is done behind the scenes, but there are few notable features that you'll want to know about. Specifically, if you need to do any of the following:

  • Inspect the history of retrieved resources, useful for troubleshooting issues related to resource loading
  • Request resources directly, but have Zombie handle cookies, authentication, etc
  • Implement new mechanism for retrieving resources, for example, add new protocols or support new headers (see Pipeline)

The Resources List

Each browser provides access to the list of resources loaded by the currently open window via browser.resources. You can iterate over this list just like any JavaScript array.

Each resource provides three properties:

  • request - The request object
  • response - The resource object (if received)
  • error - The error generated (no response)

The request object is based on the Fetch API Request object.

The response object is based on the Fetch API Response object. Note that the fetch API has the property status, whereas Node HTTP module uses statusCode.

browser.fetch(input, init)

You can use the browser directly to make requests against external resources. These requests will share the same cookies, authentication and other browser settings (also pipeline).

The fetch method is based on the Fetch API.

For example:

browser.fetch(url)
  .then(function(response) {
    console.log('Status code:', response.status);
    if (response.status === 200)
      return response.text();
  })
  .then(function(text) {
    console.log('Document:', text);
  })
  .catch(function(error) {
    console.log('Network error');
  });

To access the response document body as a Node buffer, use the following:

response.arrayBuffer()
  .then(Buffer) // arrayBuffer -> Buffer
  .then(function(buffer) {
    assert( Buffer.isBuffer(buffer) );
  });

resources.dump(output?)

Dumps the resources list to the output stream (defaults to standard output stream).

Pipeline

Zombie uses a pipeline to operate on resources. You can extend that pipeline with your own set of handlers, for example, to support additional protocols, content types, special handlers, etc.

The pipeline consists of a set of handlers. There are two types of handlers:

Functions with two arguments deal with requests. They are called with the browser and request object. They may modify the request object, and they may either return null (pass control to the next handler) or return the Response object, or return a promise that resolves to either outcome.

Functions with three arguments deal with responses. They are called with the browser, request and response objects. They may modify the response object, and must return a Response object, either the same as the argument or a new Response object, either directly or through a promise.

To add a new handle to the end of the pipeline:

browser.pipeline.addHandler(function(browser, request) {
  // Let's delay this request by 1/10th second
  return new Promise(function(resolve) {
    setTimeout(resolve, 100);
  });
});

You can add handlers to all browsers via Pipeline.addHandler. These handlers are automatically added to every new browser.pipeline instance.

Pipeline.addHandler(function(browser, request, response) {
  // Log the response body
  console.log('Response body: ' + response.body);
});

changelog

Version 6.1.4 2018-11-27

Updated dependencies

747 passing (23s) 12 pending

Version 6.1.3 2018-08-11

Upgraded to JSDom 11.12.0 #1168

747 passing (20s) 12 pending

Version 6.1.2 2018-04-29

Tested with Node 10.

CORS and Access-Control-Allow-Methods #1161

747 passing (19s) 12 pending

Version 6.1.1 2018-04-07

Fixes btoa and atob function to match browser's spec #1160

742 passing (20s) 12 pending

Version 6.1.0 2018-04-02

Documenting browser.evaluate #1014

Fix potential memory leak when deleting all cookies #1016

Fetch HeadersInit as an Array fixed and tests #1037

Added ability to disable html5 history using history5 option #359

Clear cookie header on redirect #1038

Reorder events in selectOption - causes a bad interaction in some 2-way binding scenarios #1023

Inline scripts with invalid type attribute get executed #978

742 passing (20s) 12 pending

Version 6.0.0 2018-04-02

Zombie 6.0.0 is tested to run on Node 8.10 and Node 9.8. We no longer support Node 4/6.

Upgraded from JSDOM 7.2.2 to JSDOM 11.5.1. Tons on new stuff, see: https://github.com/jsdom/jsdom/blob/master/Changelog.md#1151

Various browser methods, like focus, fill, etc now take a callback, or return a promise.

Resolved issue with about:blank pages.

737 passing (20s) 12 pending

Version 5.0.8 2018-02-22

FIXED rerouting in Node 8

Version 5.0.7 2017-06-26

FIXED browser.fill with React was not working

732 passing (28s) 12 pending

Version 5.0.6 2017-06-26

ADDED support for cancelAnimationFrame

ADDED support for document.hasFocus

732 passing (22s) 12 pending

Version 5.0.5 2016-11-22

CHANGED Support aborting XMLHttpRequests in the DONE state

731 passing (22s) 12 pending

Version 5.0.4 2016-11-09

CHANGED Honor timeout in refresh meta tag.

727 passing (17s) 12 pending

Version 5.0.3 2016-11-09

CHANGED button() to find input elements with type 'reset' and 'button' in addition to 'submit'

727 passing (17s) 12 pending

Version 5.0.2 2016-11-08

ADDED implementations of offsetWidth, offsetHeight and fixed getClientRects so that jquery will detect reliableHiddenOffsets as true

726 passing (17s) 12 pending

Version 5.0.1 2016-11-04

ADDED stub implementation of HTMLElement.getClientRects() to support jquery 1.12 implementation of width()

701 passing (16s) 12 pending

Version 5.0.0 2016-11-03

Bumping the major version because jsdom is such a core component to zombie that major updates to it have the impact to show as breaking changes to zombie users.

UPDATED jsdom to ^7

701 passing (16s) 12 pending

Version 4.3.0 2016-10-24

ADDED support for node v6

CHANGED updated to use ws 1.x

701 passing (14s) 12 pending

Version 4.2.1 2015-10-28

FIXED missing lib directory

697 passing (27s) 12 pending

Version 4.2.0 2015-10-28

CHANGED updated to use Bluebird 3.x

697 passing (23s) 12 pending

Version 4.1.0 2015-08-21

FIXED using properties instead of attributes whenever possible

FIXED storage should use Map instead of object literal

697 passing (23s) 12 pending

Version 4.0.13 2015-06-25

FIXED Multipart submission breaks for simple values

697 passing (24s) 12 pending

Version 4.0.12 2015-06-23

Work around some Babel.js bugs.

697 passing (24s) 12 pending

Version 4.0.11 2015-06-12

Upgraded to JSDOM 5.3.0.

697 passing (24s) 12 pending

Version 4.0.10 2015-04-29

Upgraded to JSDOM 5.2.0 and tough-cookie 1.1.0

694 passing (22s) 12 pending

Version 4.0.9 2015-04-25

Upgraded to JSDOM 5.1.0

FIXED assertion errors not propagating out of wait callback

694 passing (22s) 12 pending

Version 4.0.8 2015-04-19

Upgraded to JSDOM 5.0.1

ADDED expose Browser.Request/Response/Headers

CHANGED use regexp instead of startsWith

694 passing (22s) 12 pending

Version 4.0.7 2015-04-10

Version 4.0 requires io.js, see: https://github.com/tmpvar/jsdom/blob/master/Changelog.md#400

ADDED preliminary support for the Fetch API (https://fetch.spec.whatwg.org/)

ADDED you can use the browser.fetch to retrieve any resources, using the cookies, pipeline and all other browser settings

CHANGED upgraded to JSDOM 4.1

CHANGED use browser.status instead of browser.statusCode (HTML APIs use status and statusText)

CHANGED browser.resources is now just an array of all resources requested when processing the currently open window. Resources no longer shared by all windows, and other features (pipeline configuration, fetch resources) moved elsewhere.

CHANGED separated pipeline from resources. Use browser.pipeline.addHandler to add request/response handler to the browser instance, or Pipeline.addHandler to add handler to all new instances.

CHANGED pipeline API changed as well. Request handler called with browser instance and Fetch Request object, can return null or a Fetch Response object. Response handler called with browser instance, request and response object, should return same or new response object. Handlers no longer using callbacks, if you need asynchronous behavior, return a promise.

FIXED empty cookie and referer header no longer sent #881

FIXED added navigator.appVersion #885

REMOVED document.window, use document.defaultView instead

REMOVED browser.close confusing method name, use browser.window.close if you really need to close the window.

694 passing (21s) 12 pending

Version 3.1.1 2015-03-26

FIXED file URLs not resolving correctly #886 (Jeffrey Jagoda)

Version 3.1.0 2015-03-15

3.1 is the first official release of Zombie 3.x. It is a major upgrade from 2.5, and as such has several breaking changes. Please check the list of changes below to learn what has changed.

ADDED DOM URL class

ADDED XHR events emitted to browser

ADDED wait() ends with error if Browser cannot load all resources on the page (e.g. doesn't get to load scripts)

ADDED submitting form using an image input will include coordinates #865 (Werner Beroux)

REMOVED browser.fork no longer supported

REMOVED browser.htmlParser option no longer supported, always using default browser (parser5)

REMOVED Browser.visit(url, options) no longer changes instance options

REMOVED resources.mock/fail/delay, use Nock instead

REMOVED protocol and bcat, no tests

REMOVED Browser.create

REMOVED Browser.dns and Browser.ports, switching to different implementation

CHANGED Browser.debug -> browser.debug (per instance)

CHANGED browser.referer -> browser.referrer

CHANGED Browser.default.<name> = <value> deprecated, use Browser.<name> = <value> instead

CHANGED timeout event -> setTimeout, interval -> setInterval

CHANGED removed onalert/onconfirm/onprompt, use browser.on('alert', fn) etc

CHANGED credentials replaced with browser.on('authenticate', fn)

CHANGED browser.wait() runs event loop so you can catch done/error events

CHANGED event loop done event renamed to idle

CHANGED upgraded to JSDOM 3.1, added io.js and Node 0.12 support

CHANGED all dump() methods now accept output stream or output to stdout

CHANGED XHR errors no longer stop the event loop

If you are wondering what happened to 3.0, there were 16 test relases of 3.0 leading up to 3.1. Test releases are tagged as next instead of latest. NPM defaults to showing and installing latest versions, you have to explicitly instruct it toinstall` next versions.

688 passing (22s) 12 pending

Version 2.5.1 2014-12-08

ADDED waitForServer to wait for a server-initiated event before running wait method. Accepts the same arguments as wait.

Currently supports EventSource aka Server-Sent Events.

CHANGED load is now asynchronous just like wait. Use a callback or promise before accessing the document.

703 passing (12s) 8 pending

Version 2.5.0 2014-12-01

ADDED support for navigator.mimeTypes

CHANGED wait() returns a lazy promise

Prior to this change, calling wait() without a callback would return a promise, which will resolve by running the event loop for completion, even if you don't provide any callbacks.

This is not specifically a problem with wait, but with methods that end by calling wait, like clickLink and pressButton.

After this change, wait() will do nothing, unless you either supply a callback, or use the promise by means of calling then/catch/done on it.

You can achieve the old behavior by calling browser.wait().done().

REMOVED Passing an options object to browser.visit is deprecated and will be removed soon. Passing an options object to Browser.visit is still supported.

UPGRADED to JSDOM 1.4.0

700 passing (12s) 8 pending

Version 2.4.0 2014-11-27

FIXED eliminated endless spinning of the event loop

NOTE this may break your tests suite if you added an asynchronous event listener in your Node code but forgot to wait() for the event to fire. For example:

https://github.com/assaf/zombie/commit/d83c901a07bd09cb9c583a57a0b4cd431bf71f8f#diff-cb54bacfa1b84057366b12e8b5c961d3L350

695 passing (10s)
8 pending

Version 2.3.2 2014-11-26

FIXED XHR status and response text in case of error #811

FIXED XHR events for abort and timeout

FIXED ReferenceError: id is not defined

695 passing
11 sec to complete

Version 2.3.1 2014-11-26

ADDED XHR now supports progress events

691 passing
11 sec to complete

Version 2.3.0 2014-11-25

ADDED requestAnimationFrame

FIXED don't process responses to aborted XHR requests

UPDATED to JSDOM 1.3.1

688 passing
11 sec to complete

Version 2.2.1 2014-11-14

FIXED request 2.48.0 leaks globals, reverting to 2.47.0

686 passing
11 sec to complete

Version 2.2.0 2014-11-14

ADDED window.location.origin #796

FIXED updated to JSDOM 1.2.1

FIXED browser.evaluate({throws error}) should throw an error #790

FIXED changing location.hash should be synchronous #781

FIXED DNS.lookup(null) should resolve to null IP #783

FIXED Browser should show errors for resources that fail to load #794

REMOVED no longer support cookie folding with comma #792

687 passing
11 sec to complete

Version 2.1.1 2014-10-23

FIXED pushState/replaceState should change history immediately #781

682 passing
10 sec to complete

Version 2.1.0 2014-10-22

ADDED browser.assert.link can use regular expression to match link URL #770

ADDED window now has access to XPathResult and friends #762

FIXED images seem to load twice #780

680 passing
10 sec to complete

Version 2.0.8 2014-10-14

FIXED bump to JSDOM 1.0.3 to fix cssstyle-browserify dependency

FIXED console.debug fails when brower.silent = false

671 passing
10 sec to complete

Version 2.0.7 2014-10-13

FIXED csstyle bug: Cannot find module './properties'

671 passing
11 sec to complete

Version 2.0.6 2014-10-11

CHANGED Output from console.log() and friends goes to console unless browser.silent = true. You can also set it globally with Browser.default.silent = true. Console output always visible when debugging (DEBUG=zombie).

ADDED documentation for debugging using DEBUG=zombie and browser.silent.

671 passing
11 sec to complete

Version 2.0.5 2014-10-10

NOTE This version introduces a bug from JSDOM, whereby resetting a form will not reset <select> elements correctly

UPDATED to latest JSDOM

FIXED Exceptions are being swallowed #761

Minor other bug fixes

671 passing
11 sec to complete

Version 2.0.4 2014-09-26

FIXED browser will sometimes run code asynchronously outside a wait

FIXED browser.wait should return a promise when called without open window #755

FIXED complain when using event loop of destroyed browser

672 tests
12 sec to complete

Version 2.0.3 2014-09-25

FIXED window.cookies fails with error #610

FIXED HTMLImageElement._attrModified not passing callback to HTML.resourceLoader.load #624

FIXED Add raise method to xhr to catch errors in handlers #681

FIXED Chunked and gzipped content is not decompressed #707

672 tests
11 sec to complete

Version 2.0.2 2014-09-25

ADDED Only decode HTML documents, and support meta tag with charset

CHANGED Switched from using encoding to iconv-lite

CHANGED Switched from using Q to Bluebird

671 tests
12 sec to complete

Version 2.0.1 2014-09-24

FIXED DNS.lookup should use lookup, not resolve

Version 2.0.0 2014-09-24

Much much has changed, and the documentation has not caught up. Here's a partial and incomplete list.

browser.tabs replaces browser.windows. Is now an array so you can access a tab directly (e.g. browser.tabs[0]), and also switch tabs more easily (e.g. browser.tabs.current = 0).

console.log, console.error and friends now emit a console event from the browser. First argument is the output type (e.g. "log"), second is the formatted text.

console.error and console.assert output to standard error (unless silent).

browser.url returns the URL of the current document.

New browser has no open window. You need to call visit, open or set location.

Brand new implementation of browser history, fixes the "two URLs, one window" issue.

browser.request and browser.response return the request/response used for the last top-most page load. All other resources available from browser.resources. These replace lastRequest and lastResponse.

Added browser.activeElement (removed browser.focus) and support for autofocus attribute.

Browser is now an EventEmitter so you can hook into it and instrument it.

The wait method now takes two optional parameters: options that determine how long to wait and a callback. Options include duration, function and element, the later completing when the element is found in the document.

The wait method's wait function now receives two parameters: the active window and how long the wait is for the next event (0 to Infinity).

The visit method now passes applicable options to wait (duration, function, etc).

The maxWait option is now called waitDuration and waitFor is no longer supported. waitDuration should be provided in milliseconds (maxWait was provided in seconds)

Introducing assertsions to make your life all the more easier, for example:

browser.element("h1") browser.text("h1", "Header") browser.elements("li", { atLeast: 5 }) browser.assert.url("http://example.com")

Added support for deflat and gzip responses.

New API for accessing resources, use browser.resources. Lots of goodies like allowing you to retrieve resources directory (resources.get, resources.post), define how resources are handled, emulate server failures (resources.fail), delay responses (resources.delay), even mock responses (resources.mock).

676 tests
12 sec to complete

Version 1.4.1 2012-08-22

Fixed another timer edge case.

550 tests
14.5 sec to complete

Version 1.4.0 2012-08-22

Support for browser custom headers ():

browser.headers = "Accept-Language": "da, en-gb"

browser.fork() now copies browser options (Jakub Kulhan).

Fixed window.close() to properly dispose of the context, and added browser.close() to properly close all windows and cleanup. If you're running into memory issues, use either method.

Share the same location instance between history stack entries (David Stendardi)

Do not down-case file: URLs.

Implemented Node.contains (Dave Dopson).

Setting element.style.width now reflected in value of element.clientWidth and element.offsetWidth (and same for height).

Upgraded dependencies, tested with Node 0.8.6, jQuery 1.8.0, require.js 2.0.6.

Fail if Contextify module not available.

Fixed edge case where timers may fire after browser.wait returns.

550 tests
14.5 sec to complete

Version 1.3.1 2012-06-05

The id, name and value properties should be empty strings if the corresponding attribute is not set.

537 tests
13.0 sec to complete

Version 1.3.0 2012-06-05

Note that browser.text now trims and strips consecutive whitespace.

Added maximum waiting period with the maxWait browser option, which defaults to 5 seconds.

You can set maxWait and wait duration as number of milliseconds or textual value like "5s", "1m", etc.

Fixed a.href to not break when missing href attribute.

Fixed JS execution bug that messes with require.js.

Fixed failing to create empty document on HTTP error.

531 tests
12.8 sec to complete

Version 1.2.0 2012-05-28

Added browser.load for loading HTML instead of hitting a URL.

Allow browser.select to use the option text.

Reload document when forking browser.

Set accept-encoding to "identity".

JSON.parse now respects Array.prototype.

Implemented window.resizeBy and window.resizeTo.

If DOM attribute is not set, getAttribute will return null just like any browser (though the spec insists on empty string).

Fix all file loading (document and resources) to use same code path.

531 tests
12.5 sec to complete

Version 1.1.7 2012-05-27

Create DOM document after Web page has loaded. If you want to set document location and wait for document to load, so this:

browser.location = url; browser.on("loaded", function() { // Called after document has loaded ... })

Remove 'Content Type' and 'Content Length' on redirect (re-fixed.)

513 tests
12.2 sec to complete

Version 1.1.6 2012-05-26

Fire focus and blur events when filling fields, selecting fields, pressing button and switching windows.

Both focus and blur methods now work and you can get the activeElement.

Tweak to in-line script processing to fix a problem no one reported.

513 tests
12.3 sec to complete

Version 1.1.5 2012-05-24

The wait function (and its derivatives) now return most recent error in callback.

To use promises and duration function, call wait with two arguments, second one being null.

Workaround for the tricky getElementById("foo").querySelector("#foo .bar") behavior that JSDOM doesn't get quite right.

500 tests
12.3 sec to complete

Version 1.1.4 2012-05-22

Make sure wait callback doesn't get the wrong this.

496 tests
11.5 sec to complete

Version 1.1.3 2012-05-22

Fixed setting cookie on redirect to different domain.

Fixed iframe doesn't retain value of src attribute.

Fixed window.close property not set (Jerome Gravel-Niquet).

Added documentation and tests for promises.

496 tests
11.9 sec to complete

Version 1.1.2 2012-05-16

Trim stack trace at call to contextify.run. Also, if you upgrade, Contextify no longer dumps error messages to stderr.

489 tests
11.8 sec to complete

Version 1.1.1 2012-05-16

Fixes visit and wait silencing any exceptions thrown during the callback's execution.

Added empty navigator.plugins.

Added atob and btoa.

489 tests
12.0 sec to complete

Version 1.1.0 2012-05-13

Fixed onload event not firing on window.

Added navigator.cookieEnabled and navigator.vendor.

Added empty Accept-Encoding header since there's no gzip/compress support at the moment.

Fixed Browser default settings.

Upgraded to HTML5 0.3.8.

487 tests
11.8 sec to complete

Version 1.0.0 2012-05-10

Yes, that is right, Zombie now supports promises. Like this:

browser.visit("http://localhost:3000/").
  then(function() {
    assert.equal(browser.text("H1"), "Deferred zombies");
    // Chaining works by returning a promise here
    return browser.clickLink("Hit me");
  }).
  then(function() {
    assert.equal(browser.text("H1"), "Ouch");
  });

A new way to set authentication credentials so they can be applied to specific host (e.g. HTTP Basic one host, OAuth Bearer another). Like this:

// HTTP Basic takes user and password
browser.authenticate().basic("me", "secret")
// OAuth 2.0 Bearer takes an access token
browser.authenticate("example.com:443").bearer("12345")
// Show the authentication credentials in use
console.log(browser.authenticate().token)

Successfully testing Facebook Connect using Zombie (see test/facebook_connect_test.coffee).

487 tests
12.1 sec to complete

Version 0.13.14 2012-05-09

Changed browser option windowName to just name.

Setting browser option to undefined no longer resets it to default (that was a stupid idea).

Support for opening link in specified target (named window, _self, _parent, _top or _blank).

Fixed Zombie retaining multiple values for the same cookie (domain/path/key).

485 tests
11.9 sec to complete

Version 0.13.13 2012-05-09

Should be windows.select not windows.switch.

462 tests
11.4 sec to complete

Version 0.13.12 2012-05-09

Cleaned up and documented browser.windows.

Brought back JSDOM offset patches, Google Maps fails badly without these.

462 tests
11.4 sec to complete

Version 0.13.11 2012-05-08

Fix loading URL with document fragment remove document fragment from page location.

459 tests
9.9 sec to complete

Version 0.13.10 2012-05-07

Fixed basic/token authentication working for pages but not resources like JS, CSS (David Newell).

Old-style event handlers (onclick, onsubmit, etc) now have access to event through window.event.

Old-style event handlers can return false to prevent default behavior.

Added window.Event and its siblings UIEvent, MouseEvent, MutationEvent and StorageEvent.

457 tests
10.2 sec to complete

Version 0.13.9 2012-05-07

Make sure you can window.frames[name].postMessage.

453 tests
9.9 sec to complete

Version 0.13.8 2012-05-04

Redirection is now handled by Zombie instead of Request, set cookies to the right domain.

Run without Coffee-Script.

453 tests
9.7 sec to complete

Version 0.13.7 2012-05-03

Added support for postMessage.

Added support for window.open() and working with more than one window at a time (browser.windows).

When following redirect with # in it, fire the hashchange event.

IFrame window name based on element's name attribute.

Fixed IFrame document and window to include Zombie enhancements.

Zombie can now show FB Connect form.

453 tests
9.8 sec to complete

Version 0.13.6 2012-05-02

You can now set document location to javascript:expression and it will evaluate that expression.

440 tests
9.6 sec to complete

Version 0.13.5 2012-05-02

Switched default HTML parser back to the more forgiving HTML5:

  • Supports scripts with CDATA
  • Supports tag soups
  • Preserve order of execution between in-line and loaded JS code
  • Support document.write

Fix textContent of elements that have comments in them to not exclude the comment text .

438 tests
9.7 sec to complete

Version 0.13.4 2012-05-01

Upgraded to JSDOM 0.2.14. This includes an upgrade to Contextify which fixes an edge case with JS scoping. It also translates to 10% faster tests (On My Machine).

But HTML processing is a bit more picky right now.

Methods like visit now pass error to the callback if they fail to load or parse the page. JavaScript execution errors are handled separately.

436 tests
8.0 sec to complete

Version 0.13.3 2012-04-30

Fixed failing to redirect after POST request (Vincent P).

426 tests
8.8 sec to complete

Version 0.13.2 2012-04-26

Fixed iframes not loading properly of firing onload event when setting src attribute.

426 tests
9.6 sec to complete

Version 0.13.1 2012-04-26

Switched from testing with Vows to testing with Mocha. Tests now running sequentially.

Fixed a couple of issues with cookies, also switched to a better implementation, see Tough Cookie

Zombie now submits empty text fields and checked checkboxes with no value.

Support for script type="text/coffeescript" (audreyt).

425 tests
10.0 sec to complete

Version 0.13.0 2012-04-25

Now requires Node 0.6.x or later. Also upgraded to CoffeeScript 1.3.1, which helped find a couple of skipped tests.

Added support for proxies by using the excellent Request module

Added File object in browser (Ian Young)

Added support for EventSource (see Server-Sent Events)

Version 0.12.15 2012-02-23

Maintenance release: JSDOM 0.2.11/12 is broken, fixing to 0.2.10 (Mike Swift)

Version 0.12.14 2012-02-07

Fix redirect not passing the same headers again.

412 tests
6.4 sec to complete

Version 0.12.13 2012-01-18

Browser.fire takes no options (that was an undocumented argument), and always fires events that bubble and can be cancelled.

Clicking on checkbox or radio button now changes the value and propagated the click event. If preventDefault, the value is changed back.

411 tests
6.0 sec to complete

Version 0.12.12 2012-01-16

Added element offset properties. Google Maps demand these.

406 tests
5.9 sec to complete

Version 0.12.11 2012-01-06

Maintenance update, mostly more test coverage, and updates to dependencies.

403 tests
4.4 sec to complete

Version 0.12.10 2012-01-01

Brought back Web Sockets support (Justin Latimer)

Using JSDOM offsets (Justin Tulloss)

388 tests
3.8 sec to complete

Version 0.12.9 2011-12-23

Added support for httpOnly cookies.

You can now call browser.cookies with no arguments to return cookies for the current domain (based on the hostname of the currently loaded page).

You can now pass referer header:

browser.visit("/page", referer: "http://google.com", function() {
  . . .
})

Apply 5 second time limit on browser.wait, even if there's something going on (e.g. pull requests).

387 tests
3.9 sec to complete

Version 0.12.8 2011-12-20

Browser implementations of clearInterval/clearTimeout do not throw exceptions (Justin Tulloss)

Fix resources.toString throwing an error (Mr Rogers)

374 tests
3.9 sec to complete

Version 0.12.7 2011-12-19

Methods like visit and fire no longer call wait if there's no callback.

The wait callback is called from nextTick. Fixes a possible race condition.

366 Tests
3.7 sec to complete

Version 0.12.6 2011-12-18

You can now tell browser.wait when to complete processing events by passing either duration (in milliseconds) or a function that returns true when done. For example:

browser.wait(500, function() {
  // Waits no longer than 0.5 second
})

function mapIsVisible(window) {
  return window.querySelector("#map");
}
browser.wait(mapIsVisible, function() {
  // Waits until the map element is visible on the page
})

Reduced default waitFor from 5 seconds to 0.5 seconds. That seems good enough default for most pages.

366 Tests
3.7 sec to complete

Version 0.12.5 2011-12-16

Zombie and Browser are no longer distinct namespaces. What you require is the Browser class that also includes all the methods previously defined for Zombie. For example:

var Browser = require("zombie")

// This setting applies to all browsers
Browser.debug = true
// Create and use a new browser instance
var browser = new Browser()
browser.visit("http://localhost:3001", function() {
  ...
})

Added browser.history for accessing history for the current window, browser.back for navigating to the previous page and browser.reload for reloading the current page.

Fixed a bug whereby navigating back in push-state history would reload document.

363 Tests
2.4 sec to complete

Version 0.12.4 2011-12-16

Return undefined for response status when there is no response.

362 Tests
2.4 sec to complete

Version 0.12.3 2011-12-13

Fixed issue when globally declared variables with no values are not accessible (Brian McDaniel)

362 Tests
2.6 sec to complete

Version 0.12.2 2011-12-12

Added global options, for example:

Zombie.site = "http://localhost:3003"
Zombie.visit("/browser/test", function() {
  ...
})

You can put Zombie in debug mode by setting environment variable DEBUG, for example:

$ DEBUG=true vows

Also added silent option to suppress all console.log output from scripts.

Support origin in websockets (Glen Mailer)

Proper support for CSS style opacity property.

360 Tests
2.5 sec to complete

Version 0.12.1 2011-12-06

Added browser.success, returns true if status code is 2xx.

Updated documentation to better reflect new API features and behaviors. Catching up on the many changes since 0.11.

DOM events now dispatched asynchronously as part of event loop.

Allow //<hostname> URLs to be used in more places

359 Tests
2.4 sec to complete

Version 0.12.0 2011-12-06

Zombie is now using real timers instead of the fake clock. That means that a setTimeout(fn, 5000) will actually take 5 seconds to complete.

The wait method will wait for short timers (up to 5 seconds), which are quite common for some UI effects, setting up the page, etc. The maximum wait time is specified by the browser option waitFor.

If you need to wait longer, you can call wait with a time duration as the first argument.

Log redirect and error responses in debug mode.

353 Tests
2.4 sec to complete

Version 0.11.8 2011-12-04

Added browser.query and browser.queryAll. Deprecated browser.css; planning to use it for something else post 1.0.

Calling html or text when the document is not an HTML page returns the text contents. Particularly useful if you're looking at the contents of what should be an HTML page, but got 404 or 500 insteas.

357 Tests
2.0 sec to complete

Version 0.11.7 2011-11-30

Fixed console.log formatting %s, %d (Quang Van).

Fixed viewInBrowser.

Updated documentation to mention browser.errors andbrowser.resources, and thatcake watchandcake build` are no longer necessary.

Fix to load cookies that contain equal signs and quotes in the value.

347 Tests
2.0 sec to complete

Version 0.11.6 2011-11-27

Fixed loading of cookies/history from file, so empty lines are ignored.

Show JavaScript source location when failing to execute in script element.

Don't execute timer/interval that has been removed.

347 Tests
2.0 sec to complete

Version 0.11.5 2011-11-27

Fixes Browser is not defined error.

347 Tests
2.0 sec to complete

Version 0.11.4 2011-11-27

Added missing zombie.js.

347 Tests
2.0 sec to complete

Version 0.11.3 2011-11-26

Iframes will now load their content when setting src attribute.

Internal changes: resources, event loop associated with browser, history associated with window.

Updated installation instructions for Ubuntu.

347 Tests
2.2 sec to complete

Version 0.11.2 2011-11-22

Send Content-Length in URL-encoded form requests (Sven Bange).

Added support for HTTP Basic and OAuth 2.0 authorization (Paul Dixon).

344 Tests
1.9 sec to complete

Version 0.11.1 2011-11-21

Better error reporting when executing JS asynchronoulsy (timers, XHR).

Event loop keeps processing past errors.

333 Tests
1.8 sec to complete

Version 0.11.0 2011-11-20

Changed error handling for the better.

Calling browser.wait or browser.visit no longer passed the resource/JavaScript error as the first argument, and will continue processing if there are multiple errors.

Instead, an array of errors is passed as the fourth argument. You can also access browser.errors and to get just the last one, e.g. to check if any errors were reported, use browser.error.

Using console.log(browser) will puke over your terminal, so we add global defaults for sanity.

Set console.depth to specify how many times to recurse while formatting the object (default is zero).

Set console.showHidden to show non-enumerable properties (defaults to false).

333 Tests
1.7 sec to complete

Version 0.10.3 2011-11-18

Added site option allowing you to call visit with a relative path. Example:

browser = new Browser(site: "localhost:3000")
browser.visit("/testing", function(error, browser) {
})

Fixed uploading of attachments to work with Connect/Express (and possibly other servers). Formidable (used by Connect) does not support Base64 encoding. Sending binary instead.

Tested on Node 0.6.1.

330 Tests
2.1 sec to complete

Version 0.10.2 2011-10-13

Fixed #173 browser.open() causes Segmentation fault (Brian McDaniel)

Upgraded to JSDOM 0.2.7.

Version 0.10.1 2011-09-08

Tests that this == window == top == parent. True when evaluated within the context of the browser, not necessarily when using browser.window.

Removed JSDOM patch for iframes, no tests failing, let's see what happens ...

Fixes #164 jQuery selectors with explicit context fail.

Better stack traces for client-side JS. This will help in debugging and filing issues.

Updated installation instructions for OS X/Windows.

Upgraded to JSDOM 0.2.4 and testing with jQuery 1.6.3.

329 Tests
2.9 sec to complete

Version 0.10.0 2011-08-27

Upgraded to JSDOM 0.2.3 which brings us a Window context that works for asynchronous invocations (that would be timers, XHR and browser.evaluate), and many many other improvements.

Tested for compatibility with jQuery 1.6.2. Yes. It works.

NOTE: This release uses htmlparser as the default parser, while waiting for some bug fixes on HTML5. Unfortunately, htmlparser is limited in what it can accept and properly parse. Be aware of the following issues:

  • Your document must have html, head and body elements.
  • No CDATAs. But then again, CDATA is so 1999.
  • Tag soups break the parser.
  • Scripts can't use document.write. Again, it's not 1999.

Added browser.loadCSS option. Set this to load external stylesheets. Defaults to true.

Added browser.htmlParser option. Tells JSDOM which HTML5 parser to use. Use null for the default parser.

Fixed handling of file protocol.

Version 0.9.7 2011-07-28

Fixed: require.paths is deprecated [#158]

Fixed: missing pathname support for window.location.href [#156]

Fixed: not running script specs due to bug in CoffeeScript (iPaul Covell) [#151]

Updated documentation to clarify installation instructions for OS X and Ubuntu.

311 Tests
4.5 sec to complete

Version 0.9.6 2011-07-28

Implements file:// requests using node.js' native fs module rather than leaning on its http module (Ryan Petrello)

Added a basic infection/installation section to documentation (terryp)

Modified resources and xhr to better work with SSL (Ken Sternberg)

Version 0.9.5 2011-04-11

Callbacks on input/select changes (Julien Guimont)

Fix type that broke compatibility with jQuery 1.5.1 (Chad Humphries)

Enabled window.Image to accept height and width attributes [#35]

Implemented window.navigator.javaEnabled() [#35]

Added setter for document.location [#90]

Fixed XPath Sorting / Specs (Blake Imsland)

311 Tests
4.5 sec to complete

Version 0.9.4 2011-02-22

Added preliminary support for Web sockets (Ben Ford).

Fixes eval to execute in the global scope.

Fixes error when dumping cookies (Christian Joudrey).

Fixed some typos in the README (Jeff Hanke).

Speed bump from running on Node 0.4.1.

295 Tests
2.9 sec to complete

Version 0.9.3 2011-02-22

Fixes seg fault when Zombie fails to compile a script.

293 Tests
3.3 sec to complete

Version 0.9.2 2011-02-21

Fixes a couple of specs, plugs hole in array to prevent segfaults, and adds try/catch to leave context after executing script.

292 Tests
3.3 sec to complete

Version 0.9.1 2011-02-17

Some internal changes to history. Breaks iframe.

289 Tests
3.3 sec to complete

Version 0.9.0 2011-02-17

New isolated contexts for executing JavaScript. This solves a long standing problems with pages that have more than one script. Briefly speaking, each window gets it's own context/global scope that is shared by all scripts loaded for that page, but isolated from all other windows.

Fixes error handling on timeout/XHR scripts, these now generate an onerror event.

Eventloop is now associated with window instead of browser.

Fixes URL resolution in XHR requests with no port.

293 Tests
3.3 sec to complete

Version 0.8.13 2011-02-11

Tested with Node 0.4.0.

Add support for IFRAMEs (Damian Janowski).

Upgraded to HTML5 0.2.13.

Fixes #71 cookie names now preserve case.

Fixes #69 incorrectly resolving partial URLs in XHR requests.

Fixes browser.clock to use Date.now instead of new Date (faster).

Fixes browser.dump.

In debug mode, show when firing timeout/interval.

Added cake install.

293 Tests
3.7 sec to complete

Version 0.8.12 2011-02-01

Tested with Node 0.3.7 in preparation for Node 0.4.0.

Added browser.fork (Josh Adell):

Return a new browser using a snapshot of this browser's state. This method clones the forked browser's cookies, history and storage. The two browsers are independent, actions you perform in one browser do not affect the other.

Particularly useful for constructing a state (e.g. sign in, add items to a shopping cart) and using that as the base for multiple tests, and for running parallel tests in Vows.

Fix firing the change event on SELECT elements when using jQuery (Damian Janowski).

Fix for jQuery.ajax receiving a non-string data option (Damian Janowski).

Fix to allow script elements that are not JavaScript (Sean Coates).

NOTE: In this release I started running the test suite using cake test and recording the time reported by Vows. This doesn't count the time it takes to fire up Node, Cake, etc, so the reported time is approximately a second smaller than the previously reported time for 0.8.11. All other things being equal.

292 Tests
3.7 sec to complete

Version 0.8.11 2011-01-25

Added browser.source which returns the unmodified source of the current page (Bob Lail).

Added support for the Referer header (Vinicius Baggio).

If cookies do not specify a path, they are set to the root path rather than to the request path (Bob Lail).

Cookies are allowed to specify paths other than the request path (Bob Lail).

Ensure fields are sent in the order they are described (José Valim).

Fix parsing of empty body (Vinicius Baggio).

Add support for window.screen (Damian Janowski).

Zombie now sends V0 cookies (Assaf Arkin).

Fix for loading scripts over SSL (Damian Janowski).

Added window.resources to return all resources loaded by the page (including the page itself). You can see what the page is up with:

browser.window.resources.dump()

Modified lastRequest/lastResponse to use the window resources, fixed browser.status and browser.redirected to only look at the page resource itself.

282 Tests
4.3 sec to complete

Version 0.8.10 2011-01-13

Allow setting cookies from subdomains (Damian Janowski & Michel Martens).

Modified browser.fire to fire MouseEvents as well (Bob Lail).

Added window.title accessor (Bob Lail).

Fixed window.navigator.userAgent to return userAgent property (same as sent to server) (Assaf Arkin).

Added support for alert, confirm and prompt (Assaf Arkin).

Added accessors for status code from last respone (browser.statusCode) and whether last response followed a redirect (browser.redirected) (Assaf Arkin).

The visit, clickLink and pressButton methods now pass three arguments to the callback: error, browser and status code (Assaf Arkin).

265 Tests
3.7 sec to complete

Version 0.8.9 2011-01-10

Properly use the existance operator so empty strings are sent (José Valim).

Fix to XPath evaluation and sorting by document order (José Valim).

Added unselect, selectOption and unselectOption to browser (Bob Lail).

Added cookies.clear (Bob Lail).

You can now call browser methods that accept a selector (e.g. fill, select) with the element itself.

Fix to populate fields even if field type is invalid (Bob Lail).

Update to HTML5 0.2.12.

238 Tests
3.2 sec to complete

Version 0.8.8 2011-01-04

Fixed script execution order: now in document order even when mixing internal and external scripts.

Fixed image submit (José Valim).

Ensure checkboxes are properly serialized (José Valim).

It should send first select option if none was chosen (José Valim).

231 Tests
3.3 sec to complete

Version 0.8.7 2011-01-04

Adds DOM Level 3 XPath support.

Added support for file upload: browser.attach(selector, filename).

Send script errors to window.onerror and report them back to visit callback.

Support select with multiple options (José Valim).

Fix handling of unknown input fields and select fields (José Valim).

Fix issue 24, search and hash must be empty string not null.

Support Node 0.3.3 (thanks Pete Bevin)

For the brave enough to hack a Zombie, we now support (and cake setup assumes) npm bundle.

224 Tests
3.1 sec to complete

Version 0.8.6 2010-12-31

Now supports cookies on redirect (thanks Łukasz Piestrzeniewicz).

Handle server returning multiple Set-Cookie headers.

The clickLink and pressButton methods should always pass to callback and not throw error directly.

Now supports HTTPS.

198 Tests
2.6 sec to complete

Version 0.8.5 2010-12-31

Re-implemented bcat in JavaScript, so no need to install bcat to use Zombie.

197 Tests
2.6 sec to complete

Version 0.8.4 2010-12-30

Added browser.field (find an input field, textarea, etc), browser.link (find a link) and browser.button (find a button) methods.

Added browser.evaluate to evaluate any arbitrary JavaScript in the window context and return the result.

Added browser.viewInBrowser which uses bcat to view page in your browser of choice.

197 Tests
2.6 sec to complete

Version 0.8.3 2010-12-30

Zombie now shares global variables between scripts.

199 Tests
2.4 sec to complete

Version 0.8.2 2010-12-30

Fixed bug whereby Zombie hangs when making requests to a URL that has no path (e.g. http://localhost).

198 Tests
2.5 sec to complete

Version 0.8.1 2010-12-29

Added User-Agent string. You can change it by setting the browser option userAgent.

There was an error with browser.location: documentation said it returns a Location object but also just a URL. Since Location object is more consistent with window.location, accepted that interpretation.

Location.assign did not load a page if the page was already loaded in the browser. Changed it to load the page (add caching later on).

196 Tests
2.6 sec to complete

Version 0.8.0 2010-12-29

Fixed issue 8, wrong location of package.json.

Upgraded to JSDOM 0.1.22 and using HTML5 parser throughout.

Added browser.runScript option. Set to false if you don't want the browser to execute scripts.

You can now set browser options when initializing a new browser, on existing Browser object or for the duration of a request by passing them as second argument to visit.

Browser now has a property called debug that you can set to true/false (was a function), and separately a method called log that logs messages when debugging is enabled.

Added new page covering the browser API.

194 Tests
2.5 sec to complete

Version 0.7.7 2010-12-28

Fix JSDOM queue and with it issue #6.

189 Tests
2.3 sec to complete

Version 0.7.6 2010-12-28

HTML5 doesn't play nice with JSDOM, bringing back html-parser to handle innerHTML (full document parsing still handled by HTML5).

Added documentation page for CSS selectors.

Man pages now moved to section 7.

Added zombie.version.

189 Tests
2.3 sec to complete

Version 0.7.5 2010-12-28

Previous fix for document.write was incomplete, this one works better.

189 Tests
2.5 sec to complete

Version 0.7.4 2010-12-28

Now parsing documents using HTML5, which can deal better with tag soup.

Added support for scripts that use document.write.

Added troublehsooting guide.

Fixed naming issue: browser.last_request is now lastRequest, same for lastResponse and lastError.

189 Tests
2.5 sec to complete

Version 0.7.3 2010-12-27

Fixed non-sensical error message when selector fails matching a node (fill, check, select, etc).

Added debugging to help you figure out what's happening when tests run:

  • Call browser.debug with a boolean to turn debugging on/off.
  • Call browser.debug with a boolean and function to turn debugging on/off only while calling that function.
  • Call browser.debug with multiple arguments to print them (same as console.log).
  • Call browser.debug with a function to print the result of that function call.

Added an all revealing browser.dump: history, cookies, storage, document, etc. Simply call: browser.dump

Testing that Zombie.js can handle jQuery live form submit event. Yes it can!

185 Tests
1.8 sec to complete

Version 0.7.2 2010-12-27

In CoffeeScript 1.0 loops no longer try preserve block scope when functions are being generated within the loop body. Unfortunately, this broke a bunch of stuff when running Zombie from CoffeeScript source. It had effect when running the compiled JavaScript.

Changed: window.location now returns the same Location object until you navigate to a different page.

183 Tests
1.8 sec to complete

Version 0.7.1 2010-12-22

Removed CoffeeScript from runtime dependency list.

Version 0.7.0 2010-12-22

Added querySelector and querySelectorAll based on the DOM Selector API. Use this instead of find method.

Browser is now an EventEmitter, you can listen to drain (event queue empty), error (loading page) and loaded (what is says).

You can now use pressButton with inputs of type button and reset (previously just submit).

More, better, documentation.

187 tests
2.0 sec to complete

Version 0.6.5 2010-12-21

Fixed lack of JavaScript source code: CoffeeScript moved to src, JavaScript compiled into lib, life is grand again.

Changelog is now Markdown file and part of the documentation.

Version 0.6.4 2010-12-21

First documentation you can actually use.

Version 0.6.3 2010-12-21

Fixed documentation link.

man zombie

Version 0.6.2 2010-12-21

First NPM release.

Started working on documentation site.

Added cake setup to get you up and running with development dependencies.

Remove Vows as runtime dependency. Use whichever framework you like. Moved sizzle.js from dep to vendor. Moved scripts used during tests to spec/.scripts.

178 tests
1.8 sec to complete

Version 0.6.1 2010-12-20

Changed browser.cookies from getter to function that accepts cookie domain (host and port) and path, and returns wrapper to access specific cookie context.

Fixed: browser now creates new window for each new document.

Added window.JSON.

178 tests
1.8 sec to complete

Version 0.6.0 2010-12-20

First release that I could use to test an existing project.

Supports for navigation, filling and submitting forms, and selecting document content using Sizzle. Browser features include evaluating JavaScript (jQuery, Sammy.js), timers, XHR, cookies, local and session storage.

Still very rough around the edges.

175 tests
1.8 sec to complete