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

Related tags

Runner zombie
Overview

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', '[email protected]')
      .then(() => browser.fill('password', 'eat-the-living'))
      .then(() => browser.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() {
      return browser.fill('email', '[email protected]')
      .then(() => browser.fill('password', 'eat-the-living'))
      .then(() => 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. If called without a callback, returns a promise.

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);
});
Comments
  • Window object management

    Window object management

    Adds internal panes, so that when you switch pages inside a window, the actual 'window' object visible both to internal (i.e. inside the page) javascript and external (browser.window) javascript are different, and preserve across backwards and forwards.

    Also adds tests to windows_test.coffee to test for it.

    See https://github.com/assaf/zombie/issues/353

    FYI, this is parented to the commit with the history5 pull request https://github.com/assaf/zombie/pull/359, so it contains that as well. Originally developed on master, then separated into branches at assaf's request, but the split into two branches that are separate but share the original parent didn't work, and rebasing didn't either.

    opened by deitch 35
  • cannot install zombie

    cannot install zombie

    I am using Ubuntu 9.04.

    root@server:~# npm install zombie

    [email protected] install /root/node_modules/zombie node-waf configure build

    sh: node-waf: not found npm ERR! error installing [email protected] Error: [email protected] install: node-waf configure build npm ERR! error installing [email protected] sh "-c" "node-waf configure build" failed with 127 npm ERR! error installing [email protected] at ChildProcess. (/usr/lib/node_modules/npm/lib/utils/exec.js:49:20) npm ERR! error installing [email protected] at ChildProcess.emit (events.js:67:17) npm ERR! error installing [email protected] at ChildProcess.onexit (child_process.js:192:12) npm ERR! [email protected] install: node-waf configure build npm ERR! sh "-c" "node-waf configure build" failed with 127 npm ERR! npm ERR! Failed at the [email protected] install script. npm ERR! This is most likely a problem with the zombie package, npm ERR! not with npm itself. npm ERR! Tell the author that this fails on your system: npm ERR! node-waf configure build npm ERR! You can get their info via: npm ERR! npm owner ls zombie npm ERR! There is likely additional logging output above. npm ERR! npm ERR! System Linux 2.6.31-14-server npm ERR! command "node" "/usr/bin/npm" "install" "zombie" npm ERR! npm ERR! Additional logging details can be found in: npm ERR! /root/npm-debug.log npm not ok

    opened by ghost 34
  • Jsdom 6.5.1 branch

    Jsdom 6.5.1 branch

    This is a new attempt to upgrade of jsdom from 5.3.0 to 6.5.1, related to the issue #939. This replace the previous pull request #982 which was including too many commits.

    It brings 1 breaking change:

    Element.setAttribute now expects two arguments, even for setting properties (such as "checked", "disabled"...): https://developer.mozilla.org/fr/docs/Web/API/Element/setAttribute

    opened by vcarel 29
  • Calling `setTimeout` blocks script

    Calling `setTimeout` blocks script

    Test page:

    <html>
        <head>
            <script src="js/jquery-1.6.2-min.js"></script>
        </head>
        <body>
            <div id="waitable"></div>
    
           <script>
                $(document).ready(function() {
                var t1, t2;
    
                $('#waitable').click(function() {
                    var el = $(this);
    
                    el.html('');
                    clearTimeout(t1);
                    clearTimeout(t2);
    
                    t1 = setTimeout(function() {
                        el.html('<div>arrived</div>');
                    }, 1000);
    
                    t2 = setTimeout(function() {
                        el.html('<div>timeout</div>');
                    }, 2000);
                });
            });
        </script>
        </body>
    </html>
    

    Then I'm visiting that page and doing this through zombie $('#waitable').click(). Control returns back to script after 3 seconds (after all timeouts were executed) and not immediately after setTimeout calls as it should.

    opened by aik099 25
  • Unknown pseudo-class selector

    Unknown pseudo-class selector ":contains"

    Erg.

    Prior to recent update (html5?) - I could do browser.querySelector("#some-div-id table thead tr th:contains('Percent') span:contains('%')")

    now I get: Error: Unknown pseudo-class selector ":contains('Percent') *:contains('%')"

    This happens no matter what the th selector is, as well as the spans contains.

    opened by bigattichouse 25
  • lock html5 to version 0.3.13 as 0.3.15 breaks zombie

    lock html5 to version 0.3.13 as 0.3.15 breaks zombie

    The dependency on the npm module html5 is breaking zombie. The floating patch level increase (~0.3.13) is breaking zombie. The latest version of html5 is 0.3.15 and breaks finding DOM elements in the HTML.

    The simple test that used to work below no longer works with html5 0.3.15.

    it("has a title", function (done) { async.waterfall( [ function (next) { browser.visit(server.url() + "/", next); }, function (next) { expect(browser.text("title")).to.equal( "welcome"); return next(); } ], done ); });

    opened by jsloyer 24
  • [Info] Node.js 0.10.0 exposes probs in Zombie.js 1.4.1 deps

    [Info] Node.js 0.10.0 exposes probs in Zombie.js 1.4.1 deps

    Apparently htlm5 parser issues are exposed ?

    (node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit. Trace at EventEmitter.addListener (events.js:160:15) at EventEmitter.Parser.setup (/usr/local/lib/node_modules/zombie/node_modules/html5/lib/html5/parser.js:2456:17) at EventEmitter.Parser.parse (/usr/local/lib/node_modules/zombie/node_modules/html5/lib/html5/parser.js:2390:7) at HtmlToDom.appendHtmlToElement (/usr/local/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/browser/htmltodom.js:91:50) at Object.innerHTML (/usr/local/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/browser/index.js:481:17) at Object.core.HTMLDocument.write (/usr/local/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/level2/html.js:406:22) at Object.exports.jsdom (/usr/local/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom.js:70:9) at History._createDocument (/usr/local/lib/node_modules/zombie/lib/zombie/history.js:174:22) at /usr/local/lib/node_modules/zombie/lib/zombie/history.js:126:30 at /usr/local/lib/node_modules/zombie/lib/zombie/resources.js:147:16 (node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit. Trace at EventEmitter.addListener (events.js:160:15) at EventEmitter.Parser.setup (/usr/local/lib/node_modules/zombie/node_modules/html5/lib/html5/parser.js:2459:17) at EventEmitter.Parser.parse (/usr/local/lib/node_modules/zombie/node_modules/html5/lib/html5/parser.js:2390:7) at HtmlToDom.appendHtmlToElement (/usr/local/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/browser/htmltodom.js:91:50) at Object.innerHTML (/usr/local/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/browser/index.js:481:17) at Object.core.HTMLDocument.write (/usr/local/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/level2/html.js:406:22) at Object.exports.jsdom (/usr/local/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom.js:70:9) at History._createDocument (/usr/local/lib/node_modules/zombie/lib/zombie/history.js:174:22) at /usr/local/lib/node_modules/zombie/lib/zombie/history.js:126:30 at /usr/local/lib/node_modules/zombie/lib/zombie/resources.js:147:16 15 Mar 11:39:16 - 0 total ITSP links

    ReferenceError: assert is not defined at Object.HTML5Parser.phases.inBody.startTagBody (/usr/local/lib/node_modules/zombie/node_modules/html5/lib/html5/parser.js:1828 :4) at Object.HTML5Parser.phases.base.processStartTag (/usr/local/lib/node_modules/zombie/node_modules/html5/lib/html5/parser.js:65: 40) at EventEmitter.Parser.do_token (/usr/local/lib/node_modules/zombie/node_modules/html5/lib/html5/parser.js:2436:21) at EventEmitter. (/usr/local/lib/node_modules/zombie/node_modules/html5/lib/html5/parser.js:2457:30) at EventEmitter.emit (events.js:117:20) at EventEmitter.emitToken (/usr/local/lib/node_modules/zombie/node_modules/html5/lib/html5/tokenizer.js:99:9) at emit_current_token (/usr/local/lib/node_modules/zombie/node_modules/html5/lib/html5/tokenizer.js:873:3) at tag_name_state (/usr/local/lib/node_modules/zombie/node_modules/html5/lib/html5/tokenizer.js:400:4) at EventEmitter. (/usr/local/lib/node_modules/zombie/node_modules/html5/lib/html5/tokenizer.js:941:10) at EventEmitter.emit (events.js:95:17)

    opened by jsimmonds2 24
  • TypeError: Cannot read property 'prototype' of undefined

    TypeError: Cannot read property 'prototype' of undefined

    Just testing out the fix that was pushed for the segmentation fault 11, and now I am seeing this.

    node.js:134 throw e; // process.nextTick error, or 'error' event on first tick ^ TypeError: Cannot read property 'prototype' of undefined at Object. (/usr/local/lib/node_modules/zombie/lib/zombie/jsdom_patches.js:4:17) at Module._compile (module.js:411:26) at Object..js (module.js:417:10) at Module.load (module.js:343:31) at Function._load (module.js:302:12) at require (module.js:355:19) at Object. (/usr/local/lib/node_modules/zombie/lib/zombie/browser.js:18:1) at Module._compile (module.js:411:26) at Object..js (module.js:417:10) at Module.load (module.js:343:31)

    opened by jaehess 21
  • Ubuntu 10.10 - Test suite causing segmentation fault

    Ubuntu 10.10 - Test suite causing segmentation fault

    The test suite crashes under Ubuntu 10.10.

    cjoudrey@ubuntu:/tmp/zombie$ cake test
    Running test suite ... 
    
    ♢ Browser
    
    Segmentation fault
    

    All the dependencies have been installed via npm.

    priority 
    opened by cjoudrey 21
  • zombie is not refreshing window state on each browser.visit()

    zombie is not refreshing window state on each browser.visit()

    I am doing the following:

    zombie.visit("http://localhost:3000/abc",function(e,browser,status) { browser.visit("http://localhost:3000/def"); });

    Both /abc and /def give the same html (server delivered). Both have the same script tags. Since this does a full page load - even if you use html5 history API, changing the URL in the address bar requires a full page load - all the scripts on the page should get executed the first time and the second time.

    But they don't. Easiest test, just put a script whose entire content is

    console.log("FOO!");

    and the output will show "FOO" exactly once.

    I suspect it is somewhere in jsdom, but not sure.

    The negative side effects:

    • executions that should happen on page load are not happening
    • scripts that bound vars to various elements, e.g. using jQuery, on initial load, and then try to manipulate those elements later, will get "Wrong Document" errors.
    opened by deitch 19
  • Zombie fails after upgrading jQuery from v1.11 to v1.12

    Zombie fails after upgrading jQuery from v1.11 to v1.12

    TypeError: j.getClientRects is not a function
        at k (http://code.jquery.com/jquery-1.12.2.min.js:3:26891)
        at Object.n.extend.pixelMarginRight (http://code.jquery.com/jquery-1.12.2.min.js:3:25936)
        at a.getComputedStyle.Sa (http://code.jquery.com/jquery-1.12.2.min.js:3:27544)
        at Function.n.extend.css (http://code.jquery.com/jquery-1.12.2.min.js:3:30957)
        at Object.n.cssHooks.(anonymous function).get (http://code.jquery.com/jquery-1.12.2.min.js:3:31155)
        at Function.n.extend.css (http://code.jquery.com/jquery-1.12.2.min.js:3:30929)
        at http://code.jquery.com/jquery-1.12.2.min.js:5:534
        at Y (http://code.jquery.com/jquery-1.12.2.min.js:3:4661)
        at n.fn.(anonymous function) [as width] (http://code.jquery.com/jquery-1.12.2.min.js:5:305)
        at HTMLDocument.<anonymous> (http://localhost:3000/support/assets/home.bundle.js?v=v0.0.9:3:2793)
        in http://localhost:3000/support/
    

    The statement that fails in home.bundle.js since the jQuery upgrade is $.width in:

    var el = $('#an_id');
    var w = el.width();
    
    opened by jlchereau 18
  • Bump express from 4.16.4 to 4.17.3

    Bump express from 4.16.4 to 4.17.3

    Bumps express from 4.16.4 to 4.17.3.

    Release notes

    Sourced from express's releases.

    4.17.3

    4.17.2

    4.17.1

    • Revert "Improve error message for null/undefined to res.status"

    4.17.0

    • Add express.raw to parse bodies into Buffer
    • Add express.text to parse bodies into string

    ... (truncated)

    Changelog

    Sourced from express's changelog.

    4.17.3 / 2022-02-16

    4.17.2 / 2021-12-16

    4.17.1 / 2019-05-25

    ... (truncated)

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Bump qs from 6.5.2 to 6.5.3

    Bump qs from 6.5.2 to 6.5.3

    Bumps qs from 6.5.2 to 6.5.3.

    Changelog

    Sourced from qs's changelog.

    6.5.3

    • [Fix] parse: ignore __proto__ keys (#428)
    • [Fix] utils.merge`: avoid a crash with a null target and a truthy non-array source
    • [Fix] correctly parse nested arrays
    • [Fix] stringify: fix a crash with strictNullHandling and a custom filter/serializeDate (#279)
    • [Fix] utils: merge: fix crash when source is a truthy primitive & no options are provided
    • [Fix] when parseArrays is false, properly handle keys ending in []
    • [Fix] fix for an impossible situation: when the formatter is called with a non-string value
    • [Fix] utils.merge: avoid a crash with a null target and an array source
    • [Refactor] utils: reduce observable [[Get]]s
    • [Refactor] use cached Array.isArray
    • [Refactor] stringify: Avoid arr = arr.concat(...), push to the existing instance (#269)
    • [Refactor] parse: only need to reassign the var once
    • [Robustness] stringify: avoid relying on a global undefined (#427)
    • [readme] remove travis badge; add github actions/codecov badges; update URLs
    • [Docs] Clean up license text so it’s properly detected as BSD-3-Clause
    • [Docs] Clarify the need for "arrayLimit" option
    • [meta] fix README.md (#399)
    • [meta] add FUNDING.yml
    • [actions] backport actions from main
    • [Tests] always use String(x) over x.toString()
    • [Tests] remove nonexistent tape option
    • [Dev Deps] backport from main
    Commits
    • 298bfa5 v6.5.3
    • ed0f5dc [Fix] parse: ignore __proto__ keys (#428)
    • 691e739 [Robustness] stringify: avoid relying on a global undefined (#427)
    • 1072d57 [readme] remove travis badge; add github actions/codecov badges; update URLs
    • 12ac1c4 [meta] fix README.md (#399)
    • 0338716 [actions] backport actions from main
    • 5639c20 Clean up license text so it’s properly detected as BSD-3-Clause
    • 51b8a0b add FUNDING.yml
    • 45f6759 [Fix] fix for an impossible situation: when the formatter is called with a no...
    • f814a7f [Dev Deps] backport from main
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Bump decode-uri-component from 0.2.0 to 0.2.2

    Bump decode-uri-component from 0.2.0 to 0.2.2

    Bumps decode-uri-component from 0.2.0 to 0.2.2.

    Release notes

    Sourced from decode-uri-component's releases.

    v0.2.2

    • Prevent overwriting previously decoded tokens 980e0bf

    https://github.com/SamVerschueren/decode-uri-component/compare/v0.2.1...v0.2.2

    v0.2.1

    • Switch to GitHub workflows 76abc93
    • Fix issue where decode throws - fixes #6 746ca5d
    • Update license (#1) 486d7e2
    • Tidelift tasks a650457
    • Meta tweaks 66e1c28

    https://github.com/SamVerschueren/decode-uri-component/compare/v0.2.0...v0.2.1

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Bump copy-props from 2.0.4 to 2.0.5

    Bump copy-props from 2.0.4 to 2.0.5

    Bumps copy-props from 2.0.4 to 2.0.5.

    Release notes

    Sourced from copy-props's releases.

    2.0.5

    Fix

    • Avoids prototype pollution (#7)

    Doc

    • Update license years.
    • Transfer ownership to Gulp Team (#6)

    Build

    • Update dependencies: each-props (>=1.3.2), is-plain-object (>=5.0.0).

    Test

    • Expand test versions to v11〜v14.
    Changelog

    Sourced from copy-props's changelog.

    Changelog

    3.0.1 (2021-10-31)

    Bug Fixes

    • ci: Rename prettierignore typo & avoid formatting web (192badf)
    • Update dependencies (ba8a51c)

    3.0.0 (2021-09-25)

    ⚠ BREAKING CHANGES

    • Normalize repository, dropping node <10.13 support (#8)

    Miscellaneous Chores

    • Normalize repository, dropping node <10.13 support (#8) (85b1165)
    Commits
    • 40b7974 2.0.5
    • 2c738f5 Fix: Avoids prototype pollution (#7)
    • 4cac863 Merge: Transfer ownership to Gulp Team (#6)
    • 54a791d Doc: Transfer ownership to Gulp Team
    • 196fc9e Merge: Update dependencies and expand ci test versions (#5)
    • e89907f Test: Update npm to v4 when nodejs is v5 because of npm install error.
    • e970322 Test: Run coveralls when nodejs >= 6 because of its supports
    • 063e534 Test: Add nodejs v11-v14 into ci test versions
    • 72270af Doc: Update license years
    • f60b928 Build: Update versions of dependencies
    • See full diff in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Bump jsdom from 11.12.0 to 16.5.0

    Bump jsdom from 11.12.0 to 16.5.0

    Bumps jsdom from 11.12.0 to 16.5.0.

    Release notes

    Sourced from jsdom's releases.

    Version 16.5.0

    • Added window.queueMicrotask().
    • Added window.event.
    • Added inputEvent.inputType. (diegohaz)
    • Removed ondragexit from Window and friends, per a spec update.
    • Fixed the URL of about:blank iframes. Previously it was getting set to the parent's URL. (SimonMueller)
    • Fixed the loading of subresources from the filesystem when they had non-ASCII filenames.
    • Fixed the hidden="" attribute to cause display: none per the user-agent stylesheet. (ph-fritsche)
    • Fixed the new File() constructor to no longer convert / to :, per a pending spec update.
    • Fixed mutation observer callbacks to be called with the MutationObserver instance as their this value.
    • Fixed <input type=checkbox> and <input type=radio> to be mutable even when disabled, per a spec update.
    • Fixed XMLHttpRequest to not fire a redundant final progress event if a progress event was previously fired with the same loaded value. This would usually occur with small files.
    • Fixed XMLHttpRequest to expose the Content-Length header on cross-origin responses.
    • Fixed xhr.response to return null for failures that occur during the middle of the download.
    • Fixed edge cases around passing callback functions or event handlers. (ExE-Boss)
    • Fixed edge cases around the properties of proxy-like objects such as localStorage or dataset. (ExE-Boss)
    • Fixed a potential memory leak with custom elements (although we could not figure out how to trigger it). (soncodi)

    Version 16.4.0

    • Added a not-implemented warning if you try to use the second pseudo-element argument to getComputedStyle(), unless you pass a ::part or ::slotted pseudo-element, in which case we throw an error per the spec. (ExE-Boss)
    • Improved the performance of repeated access to el.tagName, which also indirectly improves performance of selector matching and style computation. (eps1lon)
    • Fixed form.elements to respect the form="" attribute, so that it can contain non-descendant form controls. (ccwebdesign)
    • Fixed el.focus() to do nothing on disconnected elements. (eps1lon)
    • Fixed el.focus() to work on SVG elements. (zjffun)
    • Fixed removing the currently-focused element to move focus to the <body> element. (eps1lon)
    • Fixed imgEl.complete to return true for <img> elements with empty or unset src="" attributes. (strager)
    • Fixed imgEl.complete to return true if an error occurs loading the <img>, when canvas is enabled. (strager)
    • Fixed imgEl.complete to return false if the <img> element's src="" attribute is reset. (strager)
    • Fixed the valueMissing validation check for <input type="radio">. (zjffun)
    • Fixed translate="" and draggable="" attribute processing to use ASCII case-insensitivity, instead of Unicode case-insensitivity. (zjffun)

    Version 16.3.0

    • Added firing of focusin and focusout when using el.focus() and el.blur(). (trueadm)
    • Fixed elements with the contenteditable="" attribute to be considered as focusable. (jamieliu386)
    • Fixed window.NodeFilter to be per-Window, instead of shared across all Windows. (ExE-Boss)
    • Fixed edge-case behavior involving use of objects with handleEvent properties as event listeners. (ExE-Boss)
    • Fixed a second failing image load sometimes firing a load event instead of an error event, when the canvas package is installed. (strager)
    • Fixed drawing an empty canvas into another canvas. (zjffun)

    Version 16.2.2

    • Updated StyleSheetList for better spec compliance; notably it no longer inherits from Array.prototype. (ExE-Boss)
    • Fixed requestAnimationFrame() from preventing process exit. This likely regressed in v16.1.0.
    • Fixed setTimeout() to no longer leak the closures passed in to it. This likely regressed in v16.1.0. (AviVahl)
    • Fixed infinite recursion that could occur when calling click() on a <label> element, or one of its descendants.
    • Fixed getComputedStyle() to consider inline style="" attributes. (eps1lon)
    • Fixed several issues with <input type="number">'s stepUp() and stepDown() functions to be properly decimal-based, instead of floating point-based.
    • Fixed various issues where updating selectEl.value would not invalidate properties such as selectEl.selectedOptions. (ExE-Boss)
    • Fixed <input>'s src property, and <ins>/<del>'s cite property, to properly reflect as URLs.
    • Fixed window.addEventLister, window.removeEventListener, and window.dispatchEvent to properly be inherited from EventTarget, instead of being distinct functions. (ExE-Boss)
    • Fixed errors that would occur if attempting to use a DOM object, such as a custom element, as an argument to addEventListener.

    ... (truncated)

    Changelog

    Sourced from jsdom's changelog.

    16.5.0

    • Added window.queueMicrotask().
    • Added window.event.
    • Added inputEvent.inputType. (diegohaz)
    • Removed ondragexit from Window and friends, per a spec update.
    • Fixed the URL of about:blank iframes. Previously it was getting set to the parent's URL. (SimonMueller)
    • Fixed the loading of subresources from the filesystem when they had non-ASCII filenames.
    • Fixed the hidden="" attribute to cause display: none per the user-agent stylesheet. (ph-fritsche)
    • Fixed the new File() constructor to no longer convert / to :, per a pending spec update.
    • Fixed mutation observer callbacks to be called with the MutationObserver instance as their this value.
    • Fixed <input type=checkbox> and <input type=radio> to be mutable even when disabled, per a spec update.
    • Fixed XMLHttpRequest to not fire a redundant final progress event if a progress event was previously fired with the same loaded value. This would usually occur with small files.
    • Fixed XMLHttpRequest to expose the Content-Length header on cross-origin responses.
    • Fixed xhr.response to return null for failures that occur during the middle of the download.
    • Fixed edge cases around passing callback functions or event handlers. (ExE-Boss)
    • Fixed edge cases around the properties of proxy-like objects such as localStorage or dataset. (ExE-Boss)
    • Fixed a potential memory leak with custom elements (although we could not figure out how to trigger it). (soncodi)

    16.4.0

    • Added a not-implemented warning if you try to use the second pseudo-element argument to getComputedStyle(), unless you pass a ::part or ::slotted pseudo-element, in which case we throw an error per the spec. (ExE-Boss)
    • Improved the performance of repeated access to el.tagName, which also indirectly improves performance of selector matching and style computation. (eps1lon)
    • Fixed form.elements to respect the form="" attribute, so that it can contain non-descendant form controls. (ccwebdesign)
    • Fixed el.focus() to do nothing on disconnected elements. (eps1lon)
    • Fixed el.focus() to work on SVG elements. (zjffun)
    • Fixed removing the currently-focused element to move focus to the <body> element. (eps1lon)
    • Fixed imgEl.complete to return true for <img> elements with empty or unset src="" attributes. (strager)
    • Fixed imgEl.complete to return true if an error occurs loading the <img>, when canvas is enabled. (strager)
    • Fixed imgEl.complete to return false if the <img> element's src="" attribute is reset. (strager)
    • Fixed the valueMissing validation check for <input type="radio">. (zjffun)
    • Fixed translate="" and draggable="" attribute processing to use ASCII case-insensitivity, instead of Unicode case-insensitivity. (zjffun)

    16.3.0

    • Added firing of focusin and focusout when using el.focus() and el.blur(). (trueadm)
    • Fixed elements with the contenteditable="" attribute to be considered as focusable. (jamieliu386)
    • Fixed window.NodeFilter to be per-Window, instead of shared across all Windows. (ExE-Boss)
    • Fixed edge-case behavior involving use of objects with handleEvent properties as event listeners. (ExE-Boss)
    • Fixed a second failing image load sometimes firing a load event instead of an error event, when the canvas package is installed. (strager)
    • Fixed drawing an empty canvas into another canvas. (zjffun)

    16.2.2

    • Updated StyleSheetList for better spec compliance; notably it no longer inherits from Array.prototype. (ExE-Boss)
    • Fixed requestAnimationFrame() from preventing process exit. This likely regressed in v16.1.0.
    • Fixed setTimeout() to no longer leak the closures passed in to it. This likely regressed in v16.1.0. (AviVahl)
    • Fixed infinite recursion that could occur when calling click() on a <label> element, or one of its descendants.
    • Fixed getComputedStyle() to consider inline style="" attributes. (eps1lon)
    • Fixed several issues with <input type="number">'s stepUp() and stepDown() functions to be properly decimal-based, instead of floating point-based.

    ... (truncated)

    Commits
    • 2d82763 Version 16.5.0
    • 9741311 Fix loading of subresources with Unicode filenames
    • 5e46553 Use domenic's ESLint config as the base
    • 19b35da Fix the URL of about:blank iframes
    • 017568e Support inputType on InputEvent
    • 29f4fdf Upgrade dependencies
    • e2f7639 Refactor create‑event‑accessor.js to remove code duplication
    • ff69a75 Convert JSDOM to use callback functions
    • 19df6bc Update links in contributing guidelines
    • 1e34ff5 Test triage
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Bump eventsource from 1.0.7 to 2.0.2

    Bump eventsource from 1.0.7 to 2.0.2

    Bumps eventsource from 1.0.7 to 2.0.2.

    Changelog

    Sourced from eventsource's changelog.

    2.0.2

    • Do not include authorization and cookie headers on redirect to different origin (#273 Espen Hovlandsdal)

    2.0.1

    • Fix URL is not a constructor error for browser (#268 Ajinkya Rajput)

    2.0.0

    1.1.1

    • Do not include authorization and cookie headers on redirect to different origin (#273 Espen Hovlandsdal)

    1.1.0

    • Improve performance for large messages across many chunks (#130 Trent Willis)
    • Add createConnection option for http or https requests (#120 Vasily Lavrov)
    • Support HTTP 302 redirects (#116 Ryan Bonte)
    • Prevent sequential errors from attempting multiple reconnections (#125 David Patty)
    • Add new to correct test (#111 Stéphane Alnet)
    • Fix reconnections attempts now happen more than once (#136 Icy Fish)
    Commits
    • 774ed10 2.0.2
    • 53356b5 chore: rebuild polyfill
    • 7ed08fe docs: update HISTORY for v2.0.2
    • dc89cfd refactor: reuse unsafe header regex pattern
    • 10ee0c4 fix: strip sensitive headers on redirect to different origin
    • a95ba90 2.0.1
    • 9321d5c Fix: browser compatibility Merge pull request #268 from ajinkyarajput/ajinkya...
    • a759bc5 Update HISTORY.md
    • f52ed50 Standard: Make URL is global variable
    • 9f28bd6 Make it again browser compatible
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
Releases(6.1.4)
Owner
Assaf Arkin
☕️ Need more coffee
Assaf Arkin
A next-generation code testing stack for JavaScript.

Intern Software testing for humans ⚠️ This documentation is for the development version of Intern. For the current release version, go here. Intern is

Intern: next-gen JavaScript testing 4.4k Jan 7, 2023
Headless Chrome Node.js API

Puppeteer API | FAQ | Contributing | Troubleshooting Puppeteer is a Node library which provides a high-level API to control Chrome or Chromium over th

Puppeteer 81.4k Jan 1, 2023
End-to-end testing framework written in Node.js and using the Webdriver API

Nightwatch.js Homepage | Getting Started | Developer Guide | API Reference | About Automated end-to-end testing framework powered by Node.js and using

Nightwatch.js 11.3k Jan 7, 2023
A simple and stable cross-browser testing tool. 简单稳定的跨浏览器测试工具。

totoro A simple and stable cross-browser testing tool. Latest stable version: v2.0 Change Log 中文版使用文档 0. Features Run in real browsers Support all tes

totoro 568 Dec 21, 2022
A node.js library for testing modern web applications

Taiko Docs | API reference A Node.js library for testing modern web applications What’s Taiko? Taiko is a free and open source browser automation tool

Gauge 3.2k Dec 30, 2022
CasperJS is no longer actively maintained. Navigation scripting and testing utility for PhantomJS and SlimerJS

CasperJS Important note: the master branch hosts the development version of CasperJS, which is now pretty stable and should be the right version to us

CasperJS 7.3k Dec 25, 2022
Next-gen browser and mobile automation test framework for Node.js

Next-gen browser and mobile automation test framework for Node.js. Homepage | Developer Guide | API Reference | Contribute | Changelog | Roadmap Webdr

WebdriverIO 7.9k Jan 3, 2023
A scriptable browser like PhantomJS, based on Firefox

SlimerJS http://slimerjs.org/ SlimerJS is a scriptable browser. It allows you to manipulate a web page with an external Javascript script: opening a w

Laurent Jouanneau 3k Dec 31, 2022
This is a full-stack exercise tracker web application built using the MERN (MongoDB, ExpressJS, ReactJS, NodeJS) stack. You can easily track your exercises with this Full-Stack Web Application.

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

WMouton 2 Dec 25, 2021
ApostropheCMS is a full-featured, open-source CMS built with Node.js that seeks to empower organizations by combining in-context editing and headless architecture in a full-stack JS environment.

ApostropheCMS ApostropheCMS is a full-featured, open source CMS built with Node.js that seeks to empower organizations by combining in-context editing

Apostrophe Technologies 3.9k Jan 4, 2023
ApostropheCMS is a full-featured, open-source CMS built with Node.js that seeks to empower organizations by combining in-context editing and headless architecture in a full-stack JS environment.

ApostropheCMS ApostropheCMS is a full-featured, open source CMS built with Node.js that seeks to empower organizations by combining in-context editing

Apostrophe Technologies 3.9k Jan 4, 2023
A testing focused Remix Stack, that integrates E2E & Unit testing with Playwright, Vitest, MSW and Testing Library. Driven by Prisma ORM. Deploys to Fly.io

Live Demo · Twitter A testing focused Remix Stack, that integrates E2E & Unit testing with Playwright, Vitest, MSW and Testing Library. Driven by Pris

Remix Stacks 18 Oct 31, 2022
Full-Stack Instgram Clone using MERN Stack and Socket.io

Instagram MERN Full-Stack Instgram Clone using MERN Stack and Socket.io Visit Now ?? ??️ Tech Stack Frontend: Backend: Realtime Communication: Cloud S

Jigar Sable 326 Dec 27, 2022
A Full Stack Amazon Clone which created using ReactJS with full E-Commerce Functionality!!

Amazon Clone with ReactJS A small web app that tries to imitate the desktop web version of amazon site, you can add items to the basket, delete them,

Özge Coşkun Gürsucu 50 Oct 3, 2022
It is a solo Project and In this repo I try to build a E-Commerce full-stack website with MERN stack technologies. For Practice purpose.

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

Alok Kumar 5 Aug 3, 2022
Fast and type-safe full stack framework, for TypeScript

Fast and type-safe full stack framework, for TypeScript Why frourio ? Even if you write both the frontend and backend in TypeScript, you can't statica

frourio 1.1k Dec 26, 2022
I built a full-stack project using Node, Express, Mongo, webRTC, socket.io, and of course React JS. This project is inspired by the awesome Clubhouse 😊

codershouse-mern - This Project is Under Development. Below are some of the implemented interface and the remaining features will be updated in future

Bishal Das 35 Nov 18, 2022
A full CRUD application built using the MELN(MongoDB,Express,LiquidJS,Node) stack.

Pokedex Your mission is to be the very best, like no one ever was, at making a Pokémon manager (a Pokédex). Learning Objectives Full CRUD App Prerequi

Anthony Njoroge 5 Sep 23, 2022
Gatsby-blog-cosmicjs - 🚀⚡️ Blazing fast blog built with Gatsby and the Cosmic Headless CMS 🔥

Gatsby + Cosmic This repo contains an example blog website that is built with Gatsby, and Cosmic. See live demo hosted on Netlify Uses the Cosmic Gats

Priya Chakraborty 0 Jan 29, 2022