{
  "name": "zombie",
  "version": "2.5.1",
  "description": "Insanely fast, full-stack, headless browser testing using Node.js",
  "homepage": "http://zombie.labnotes.org/",
  "author": {
    "name": "Assaf Arkin",
    "email": "assaf@labnotes.org",
    "url": "http://labnotes.org/"
  },
  "contributors": [
    {
      "name": "Bob Lail",
      "email": "bob.lailfamily@gmail.com",
      "url": "http://boblail.tumblr.com/"
    },
    {
      "name": "Brian McDaniel",
      "url": "https://github.com/brianmcd"
    },
    {
      "name": "Damian Janowski"
    },
    {
      "name": "José Valim",
      "email": "jose.valim@plataformatec.com.br",
      "url": "http://blog.plataformatec.com.br/"
    }
  ],
  "keywords": [
    "test",
    "tests",
    "testing",
    "TDD",
    "spec",
    "specs",
    "BDD",
    "headless",
    "browser",
    "html",
    "html5",
    "dom",
    "css",
    "javascript",
    "integration",
    "ajax",
    "full-stack",
    "DSL"
  ],
  "main": "lib/zombie",
  "scripts": {
    "build": "gulp build",
    "test": "mocha",
    "prepublish": "gulp build",
    "postpublish": "gulp tag"
  },
  "engines": {
    "node": "0.10.x"
  },
  "dependencies": {
    "bluebird": "^2.3.11",
    "debug": "^2.0.0",
    "eventsource": "^0.1.4",
    "iconv-lite": "^0.4.0",
    "jsdom": "1.4.0",
    "lazybird": "^1.0.0",
    "mime": "^1.2.11",
    "ms": "^0.7.0",
    "request": "^2.48.0",
    "tough-cookie": "^0.12.1",
    "ws": "^0.6.0"
  },
  "devDependencies": {
    "body-parser": "^1.10.0",
    "coffee-script": "^1.8.0",
    "cookie-parser": "^1.3.3",
    "express": "^4.10.4",
    "gulp": "^3.8.10",
    "gulp-clean": "^0.3.1",
    "gulp-coffee": "^2.2.0",
    "gulp-exec": "^2.1.1",
    "gulp-notify": "^2.0.1",
    "gulp-util": "^3.0.1",
    "mocha": "^2.0.1",
    "morgan": "^1.5.0",
    "multiparty": "^4.1.0",
    "replay": "^1.12.0",
    "requirejs": "^2.1.15",
    "traceur": "^0.0.79"
  },
  "repository": {
    "type": "git",
    "url": "http://github.com/assaf/zombie"
  },
  "bugs": {
    "url": "http://github.com/assaf/zombie/issues"
  },
  "licenses": [
    {
      "type": "MIT",
      "url": "https://github.com/assaf/zombie/blob/master/MIT-LICENSE"
    }
  ],
  "readme": "# Zombie.js\n### Insanely fast, headless full-stack testing using Node.js\n\n**NOTE:** This documentation is still work in progress.  Please help make it\nbetter by adding as much as you can and submitting a pull request.\n\nYou can also consult [the older 1.4 documentation](http://zombie.labnotes.org).\n\n\n## The Bite\n\nIf you're going to write an insanely fast, headless browser, how can you not\ncall it Zombie?  Zombie it is.\n\nZombie.js is a lightweight framework for testing client-side JavaScript code in\na simulated environment.  No browser required.\n\nLet's try to sign up to a page and see what happens:\n\n```js\nvar Browser = require('zombie');\nvar assert  = require('assert');\n\n// We call our test example.com\nBrowser.localhost('example.com', 3000);\n\n// Load the page from localhost\nvar browser = Browser.create();\nbrowser.visit('/signup', function (error) {\n  assert.ifError(error);\n\n  // Fill email, password and submit form\n  browser.\n    fill('email', 'zombie@underworld.dead').\n    fill('password', 'eat-the-living').\n    pressButton('Sign Me Up!', function(error) {\n      assert.ifError(error);\n\n      // Form submitted, new page loaded.\n      browser.assert.success();\n      browser.assert.text('title', 'Welcome To Brains Depot');\n\n    });\n\n});\n```\n\nIf you prefer using promises:\n\n```js\nvar Browser = require('zombie');\n\n// We call our test example.com\nBrowser.localhost('example.com', 3000);\n\n// Load the page from localhost\nvar browser = Browser.create();\nbrowser.visit('/signup')\n  .then(function() {\n    // Fill email, password and submit form\n    browser.fill('email', 'zombie@underworld.dead');\n    browser.fill('password', 'eat-the-living');\n    return browser.pressButton('Sign Me Up!');\n  })\n  .done(function() {\n    // Form submitted, new page loaded.\n    browser.assert.success();\n    browser.assert.text('title', 'Welcome To Brains Depot');\n  });\n```\n\nWell, that was easy.\n\n\n\n\n## Table of Contents\n\n* [Installing](#installing)\n* [Browser](#browser)\n* [Cookies](#cookies)\n* [Tabs](#tabs)\n* [Assertions](#assertions)\n* [Events](#events)\n* [Resources](#resources)\n* [Debugging](#debugging)\n* [FAQ](#faq)\n\n\n\n\n## Installing\n\nTo install Zombie.js you will need [Node.js](http://nodejs.org/) 0.8 or later,\n[NPM](https://npmjs.org/), a [C++ toolchain and\nPython](https://github.com/TooTallNate/node-gyp).\n\nOne-click installers for Windows, OS X, Linux and SunOS are available directly\nfrom the [Node.js site](http://nodejs.org/download/).\n\nOn OS X you can download the full XCode from the Apple Store, or install the\n[OSX GCC toolchain](https://github.com/kennethreitz/osx-gcc-installer) directly\n(smaller download).\n\nYou can also install Node and NPM using the wonderful\n[Homebrew](http://mxcl.github.com/homebrew/) (if you're serious about developing\non the Mac, you should be using Homebrew):\n\n```sh\n$ brew install node\n$ node --version\nv0.10.25\n$ npm --version\n1.3.24\n$ npm install zombie --save-dev\n```\n\nOn Windows you will need to install a recent version of Python and Visual\nStudio. See [node-gyp for specific installation\ninstructions](https://github.com/TooTallNate/node-gyp) and\n[Chocolatey](http://chocolatey.org/) for easy package management.\n\n\n\n\n## Browser\n\n#### browser.assert\n\nMethods for making assertions against the browser, such as\n`browser.assert.element('.foo')`.\n\nSee [Assertions](#assertions) for detailed discussion.\n\n#### browser.console\n\nProvides access to the browser console (same as `window.console`).\n\n#### browser.referer\n\nYou can use this to set the HTTP Referer header.\n\n#### browser.resources\n\nAccess to history of retrieved resources.  Also provides methods for retrieving\nresources and managing the resource pipeline.  When things are not going your\nway, try calling `browser.resources.dump()`.\n\nSee [Resources](#resources) for detailed discussion.\n\n#### browser.tabs\n\nArray of all open tabs (windows).  Allows you to operate on more than one open\nwindow at a time.\n\nSee [Tabs](#tabs) for detailed discussion.\n\n#### Browser.localhost(hostname, port)\n\nEven though your test server is running on localhost and unprivileged port, this\nmethod makes it possible to access it as a different domain name and through\nport 80.\n\nIt also sets the default site URL, so your tests don't have to specify the\nhostname every time.\n\nLet's say your test server runs on port 3000, and you want to write tests that\nvisit `example.com`:\n\n```\nBrowser.localhost('example.com', 3000);\n```\n\nYou can now visit `http://example.com/path` and it will talk to your local\nserver on port 3000.  In fact, `example.com` becomes the default domain, so your\ntests can be as simple as:\n\n```\n// Global setting, applies to all browser instances\nBrowser.localhost('*.example.com', 3000);\n\n// Browser instance for this test\nvar browser = Browser.create();\nbrowser.visit('/path', function() {\n  // It picks example.com as the default host\n  browser.assert.url('http://example.com/path');\n});\n```\n\nNotice the asterisk in the above example, that tells Zombie to route all\nsub-domains, so you can visit `foo.example.com` and `bar.example.com` in your\ntest case.\n\nIf you need to map multiple domains and/or ports, see [DNS Masking](#dnsmasking)\nand [Port Mapping](#portmapping).\n\nIf you need more flexibility, consider that `Browser.localhost` is just a\nshortcut for making these three changes:\n\n- `Browser.dns.localhost(hostname)` will make any DNS lookup of hostname resolve\n  to 127.0.0.1 (see [DNS Masking](#dnsmasking))\n- `Browser.ports.map(hostname, port)` will redirect any HTTP request to hostname\n  from port 80 to the designated port (see [Port Mapping](#portmapping))\n- `Browser.default.size = hostname` will add the hostname to any relative URL\n  (e.g. when using `browser.visit`)\n\n\n#### browser.proxy\n\nThe `proxy` option takes a URL so you can tell Zombie what protocol, host and port to use. Also supports Basic authentication, e.g.:\n\n    browser.proxy = \"http://me:secret@myproxy:8080\"\n\n\n#### browser.eventLoop\n#### browser.errors\n\n\n### Extending The Browser\n\n```js\nBrowser.extend(function(browser) {\n  browser.on('console', function(level, message) {\n    logger.log(message);\n  });\n  browser.on('log', function(level, message) {\n    logger.log(message);\n  });\n});\n```\n\n\n## Cookies\n\nAre delicious.  Also, somewhat tricky to work with.   A browser will only send a\ncookie to the server if it matches the request domain and path.\n\nMost modern Web applications don't care so much about the path and set all\ncookies to the root path of the application (`/`), but do pay attention to the\ndomain.\n\nConsider this code:\n\n```js\nbrowser.setCookie(name: 'session', domain: 'example.com', value: 'delicious');\nbrowser.visit('http://example.com', function() {\n  var value = browser.getCookie('session');\n  console.log('Cookie', value);\n});\n```\n\nIn order for the cookie to be set in this example, we need to specify the cookie\nname, domain and path.  In this example we omit the path and choose the default\n`/`.\n\nTo get the cookie in this example, we only need the cookie name, because at that\npoint the browser has an open document, and it can use the domain of that\ndocument to find the right cookie.  We do need to specify a domain if we're\ninterested in other cookies, e.g for a 3rd party widget.\n\nThere may be multiple cookies that match the same host, for example, cookies set\nfor `.example.com` and `www.example.com` will both match `www.example.com`, but\nonly the former will match `example.com`.  Likewise, cookies set for `/` and\n`/foo` will both match a request for `/foo/bar`.\n\n`getCookie`, `setCookie` and `deleteCookie` always operate on a single cookie,\nand they match the most specific one, starting with the cookies that have the\nlongest matching domain, followed by the cookie that has the longest matching\npath.\n\nIf the first argument is a string, they look for a cookie with that name using\nthe hostname of the currently open page as the domain and `/` as the path.  To\nbe more specific, the first argument can be an object with the properties\n`name`, `domain` and `path`.\n\nThe following are equivalent:\n\n```js\nbrowser.getCookie('session');\nbrowser.getCookie({ name: 'session',\n                    domain: browser.location.hostname,\n                    path: browser.location.pathname });\n```\n\n\n`getCookie` take a second argument.  If false (or missing), it returns the\nvalue of the cookie.  If true, it returns an object with all the cookie\nproperties: `name`, `value`, `domain`, `path`, `expires`, `httpOnly` and\n`secure`.\n\n\n#### browser.cookies\n\nReturns an object holding all cookies used by this browser.\n\n#### browser.cookies.dump(stream?)\n\nDumps all cookies to standard output, or the output stream.\n\n#### browser.deleteCookie(identifier)\n\nDeletes a cookie matching the identifier.\n\nThe identifier is either the name of a cookie, or an object with the property\n`name` and the optional properties `domain` and `path`.\n\n#### browser.deleteCookies()\n\nDeletes all cookies.\n\n#### browser.getCookie(identifier, allProperties?)\n\nReturns a cookie matching the identifier.\n\nThe identifier is either the name of a cookie, or an object with the property\n`name` and the optional properties `domain` and `path`.\n\nIf `allProperties` is true, returns an object with all the cookie properties,\notherwise returns the cookie value.\n\n#### browser.setCookie(name, value)\n\nSets the value of a cookie based on its name.\n\n#### browser.setCookie(cookie)\n\nSets the value of a cookie based on the following properties:\n\n* `domain` - Domain of the cookie (requires, defaults to hostname of currently\n  open page)\n* `expires` - When cookie it set to expire (`Date`, optional, defaults to\n  session)\n* `maxAge` - How long before cookie expires (in seconds, defaults to session)\n* `name` - Cookie name (required)\n* `path` - Path for the cookie (defaults to `/`)\n* `httpOnly` - True if HTTP-only (not accessible from client-side JavaScript,\n  defaults to false)\n* `secure` - True if secure (requires HTTPS, defaults to false)\n* `value` - Cookie value (required)\n\n\n\n\n## Tabs\n\nJust like your favorite Web browser, Zombie manages multiple open windows as\ntabs.  New browsers start without any open tabs.  As you visit the first page,\nZombie will open a tab for it.\n\nAll operations against the `browser` object operate on the currently active tab\n(window) and most of the time you only need to interact with that one tab.  You\ncan access it directly via `browser.window`.\n\nWeb pages can open additional tabs using the `window.open` method, or whenever a\nlink or form specifies a target (e.g. `target=_blank` or `target=window-name`).\nYou can also open additional tabs by calling `browser.open`.  To close the\ncurrently active tab, close the window itself.\n\nYou can access all open tabs from `browser.tabs`.  This property is an\nassociative array, you can access each tab by its index number, and iterate over\nall open tabs using functions like `forEach` and `map`.\n\nIf a window was opened with a name, you can also access it by its name.  Since\nnames may conflict with reserved properties/methods, you may need to use\n`browser.tabs.find`.\n\nThe value of a tab is the currently active window.  That window changes when you\nnavigate forwards and backwards in history.  For example, if you visited the URL\n'/foo' and then the URL '/bar', the first tab (`browser.tabs[0]`) would be a\nwindow with the document from '/bar'.  If you then navigate back in history, the\nfirst tab would be the window with the document '/foo'.\n\nThe following operations are used for managing tabs:\n\n#### browser.close(window)\n\nCloses the tab with the given window.\n\n#### browser.close()\n\nCloses the currently open tab.\n\n#### browser.tabs\n\nReturns an array of all open tabs.\n\n#### browser.tabs[number]\n\nReturns the tab with that index number.\n\n#### browser.tabs[string]\n#### browser.tabs.find(string)\n\nReturns the tab with that name.\n\n#### browser.tabs.closeAll()\n\nCloses all tabs.\n\n#### browser.tabs.current\n\nThis is a read/write property.  It returns the currently active tab.\n\nCan also be used to change the currently active tab.  You can set it to a\nwindow (e.g. as currently returned from `browser.current`), a window name or the\ntab index number.\n\n#### browser.tabs.dump(output)\n\nDump a list of all open tabs to standard output, or the output stream.\n\n#### browser.tabs.index\n\nReturns the index of the currently active tab.\n\n#### browser.tabs.length\n\nReturns the number of currently opened tabs.\n\n#### browser.open(url: 'http://example.com')\n\nOpens and returns a new tab.  Supported options are:\n- `name` - Window name.\n- `url` - Load document from this URL.\n\n#### browser.window\n\nReturns the currently active window, same as `browser.tabs.current.`\n\n\n\n\n## Assertions\n\nTo make life easier, Zombie introduces a set of convenience assertions that you\ncan access directly from the browser object.  For example, to check that a page\nloaded successfuly:\n\n```js\nbrowser.assert.success();\nbrowser.assert.text('title', 'My Awesome Site');\nbrowser.assert.element('#main');\n```\n\nThese assertions are available from the `browser` object since they operate on a\nparticular browser instance -- generally dependent on the currently open window,\nor document loaded in that window.\n\nMany assertions require an element/elements as the first argument, for example,\nto compare the text content (`assert.text`), or attribute value\n(`assert.attribute`).  You can pass one of the following values:\n\n- An HTML element or an array of HTML elements\n- A CSS selector string (e.g. \"h2\", \".book\", \"#first-name\")\n\nMany assertions take an expected value and compare it against the actual value.\nFor example, `assert.text` compares the expected value against the text contents\nof one or more strings.  The expected value can be one of:\n\n- A JavaScript primitive value (string, number)\n- `undefined` or `null` are used to assert the lack of value\n- A regular expression\n- A function that is called with the actual value and returns true if the\n  assertion is true\n- Any other object will be matched using `assert.deepEqual`\n\nNote that in some cases the DOM specification indicates that lack of value is an\nempty string, not `null`/`undefined`.\n\nAll assertions take an optional last argument that is the message to show if the\nassertion fails.  Better yet, use a testing framework like\n[Mocha](https://github.com/mochajs/mocha) that has good diff support and\ndon't worry about these messages.\n\n\n### Available Assertions\n\nThe following assertions are available:\n\n#### assert.attribute(selection, name, expected, message)\n\nAsserts the named attribute of the selected element(s) has the expected value.\n\nFails if no element found.\n\n```js\nbrowser.assert.attribute('form', 'method', 'post');\nbrowser.assert.attribute('form', 'action', '/customer/new');\n// Disabled with no attribute value, i.e. <button disabled>\nbrowser.assert.attribute('button', 'disabled', '');\n// No disabled attribute i.e. <button>\nbrowser.assert.attribute('button', 'disabled', null);\n```\n\n#### assert.className(selection, className, message)\n\nAsserts that selected element(s) has that and only that class name.  May also be\nspace-separated list of class names.\n\nFails if no element found.\n\n```js\nbrowser.assert.className('form input[name=email]', 'has-error');\n```\n\n#### assert.cookie(identifier, expected, message)\n\nAsserts that a cookie exists and  has the expected value, or if `expected` is\n`null`, that no such cookie exists.\n\nThe identifier is either the name of a cookie, or an object with the property\n`name` and the optional properties `domain` and `path`.\n\n```js\nbrowser.assert.cookie('flash', 'Missing email addres');\n```\n\n#### assert.element(selection, message)\n\nAsserts that one element matching selection exists.\n\nFails if no element or more than one matching element are found.\n\n```js\nbrowser.assert.element('form');\nbrowser.assert.element('form input[name=email]');\nbrowser.assert.element('form input[name=email].has-error');\n```\n\n#### assert.elements(selection, count, message)\n\nAsserts how many elements exist in the selection.\n\nThe argument `count` can be a number, or an object with the following\nproperties:\n\n- `atLeast` - Expecting to find at least that many elements\n- `atMost`  - Expecting to find at most that many elements\n- `exactly` - Expecting to find exactly that many elements\n\n```js\nbrowser.assert.elements('form', 1);\nbrowser.assert.elements('form input', 3);\nbrowser.assert.elements('form input.has-error', { atLeast: 1 });\nbrowser.assert.elements('form input:not(.has-error)', { atMost: 2 });\n```\n\n#### assert.evaluate(expression, expected, message)\n\nEvaluates the JavaScript expression in the context of the currently open window.\n\nWith one argument, asserts that the value is equal to `true`.\n\nWith two/three arguments, asserts that the returned value matches the expected\nvalue.\n\n```js\nbrowser.assert.evaluate('$('form').data('valid')');\nbrowser.assert.evaluate('$('form').data('errors').length', 3);\n```\n\n#### assert.global(name, expected, message)\n\nAsserts that the global (window) property has the expected value.\n\n#### assert.hasClass(selection, className, message)\n\nAsserts that selected element(s) have the expected class name.  Elements may\nhave other class names (unlike `assert.className`).\n\nFails if no element found.\n\n```js\nbrowser.assert.hasClass('form input[name=email]', 'has-error');\n```\n\n#### assert.hasFocus(selection, message)\n\nAsserts that selected element has the focus.\n\nIf the first argument is `null`, asserts that no element has the focus.\n\nOtherwise, fails if element not found, or if more than one element found.\n\n```js\nbrowser.assert.hasFocus('form input:nth-child(1)');\n```\n\n#### assert.hasNoClass(selection, className, message)\n\nAsserts that selected element(s) does not have the expected class name.  Elements may\nhave other class names (unlike `assert.className`).\n\nFails if no element found.\n\n```js\nbrowser.assert.hasNoClass('form input', 'has-error');\n```\n\n#### assert.input(selection, expected, message)\n\nAsserts that selected input field(s) (`input`, `textarea`, `select` etc) have\nthe expected value.\n\nFails if no element found.\n\n```js\nbrowser.assert.input('form input[name=text]', 'Head Eater');\n```\n\n#### assert.link(selection, text, url, message)\n\nAsserts that at least one link exists with the given selector, text and URL.\nThe selector can be `a`, but a more specific selector is recommended.\n\nURL can be relative to the current document, or a regular expression.\n\nFails if no element is selected that also has the specified text content and\nURL.\n\n```js\nbrowser.assert.link('footer a', 'Privacy Policy', '/privacy');\n```\n\n#### assert.prompted(messageShown, message)\n\nAsserts the browser prompted with a given message.\n\n```js\nbrowser.assert.prompted('Are you sure?');\n```\n\n#### assert.redirected(message)\n\nAsserts the browser was redirected when retrieving the current page.\n\n#### assert.success(message)\n\nAsserts the current page loaded successfully (status code 2xx or 3xx).\n\n#### assert.status(code, message)\n\nAsserts the current page loaded with the expected status code.\n\n```js\nbrowser.assert.status(404);\n```\n\n#### assert.style(selection, style, expected, message)\n\nAsserts that selected element(s) have the expected value for the named style\nproperty.  For example:\n\nFails if no element found, or element style does not match expected value.\n\n```js\nbrowser.assert.style('#show-hide.hidden', 'display', 'none');\nbrowser.assert.style('#show-hide:not(.hidden)', 'display', '');\n```\n\n#### assert.text(selection, expected, message)\n\nAsserts that selected element(s) have the expected text content.  For example:\n\nFails if no element found that has that text content.\n\n```js\nbrowser.assert.text('title', 'My Awesome Page');\n```\n\n#### assert.url(url, message)\n\nAsserts the current page has the expected URL.\n\nThe expected URL can be one of:\n\n- The full URL as a string\n- A regular expression\n- A function, called with the URL and returns true if the assertion is true\n- An [object](http://nodejs.org/api/url.html#url_url_parse_urlstr_parsequerystring_slashesdenotehost), in which case individual properties are matched against the URL\n\nFor example:\n\n```js\nbrowser.assert.url('http://localhost/foo/bar');\nbrowser.assert.url(new RegExp('^http://localhost/foo/\\\\w+$'));\nbrowser.assert.url({ pathame: '/foo/bar' });\nbrowser.assert.url({ query: { name: 'joedoe' } });\n```\n\n\n### Roll Your Own Assertions\n\nNot seeing an assertion you want?  You can add your own assertions to the\nprototype of `Browser.Assert`.\n\nFor example:\n\n```js\n// Asserts the browser has the expected number of open tabs.\nBrowser.Assert.prototype.openTabs = function(expected, message) {\n  assert.equal(this.browser.tabs.length, expected, message);\n};\n```\n\nOr application specific:\n\n\n```js\n// Asserts which links is highlighted in the navigation bar\nBrowser.Assert.navigationOn = function(linkText) {\n  this.assert.element('.navigation-bar');\n  this.assert.text('.navigation-bar a.highlighted', linkText);\n};\n```\n\n\n\n\n## Events\n\nEach browser instance is an `EventEmitter`, and will emit a variety of events\nyou can listen to.\n\nSome things you can do with events:\n\n- Trace what the browser is doing, e.g. log every page loaded, every DOM event\n  emitted, every timeout fired\n- Wait for something to happen, e.g. form submitted, link clicked, input element\n  getting the focus\n- Strip out code from HTML pages, e.g remove analytics code when running tests\n- Add event listeners to the page before any JavaScript executes\n- Mess with the browser, e.g. modify loaded resources, capture and change DOM\n  events\n\n#### console (level, message)\n\nEmitted whenever a message is printed to the console (`console.log`,\n`console.error`, `console.trace`, etc).\n\nThe first argument is the logging level, and the second argument is the message.\n\nThe logging levels are: `debug`, `error`, `info`, `log`, `trace` and `warn`.\n\n#### active (window)\n\nEmitted when this window becomes the active window.\n\n#### closed (window)\n\nEmitted when this window is closed.\n\n#### done ()\n\nEmitted when the event loop goes empty.\n\n#### evaluated (code, result, filename)\n\nEmitted after JavaScript code is evaluated.\n\nThe first argument is the JavaScript function or code (string).  The second\nargument is the result.  The third argument is the filename.\n\n#### event (event, target)\n\nEmitted whenever a DOM event is fired on the target element, document or window.\n\n#### focus (element)\n\nEmitted whenever an element receives the focus.\n\n#### inactive (window)\n\nEmitted when this window is no longer the active window.\n\n#### interval (function, interval)\n\nEmitted whenever an interval (`setInterval`) is fired.\n\nThe first argument is the function or code to evaluate, the second argument is\nthe interval in milliseconds.\n\n#### link (url, target)\n\nEmitted when a link is clicked.\n\nThe first argument is the URL of the new location, the second argument\nidentifies the target window (`_self`, `_blank`, window name, etc).\n\n#### loaded (document)\n\nEmitted when a document has been loaded into a window or frame.\n\nThis event is emitted after the HTML is parsed, and some scripts executed.\n\n#### loading (document)\n\nEmitted when a document is about to be loaded into a window or frame.\n\nThis event is emitted when the document is still empty, before parsing any HTML.\n\n#### opened (window)\n\nEmitted when a new window is opened.\n\n#### redirect (request, response, redirectRequest)\n\nEmitted when following a redirect.\n\nThe first argument is the request, the second argument is the response that\ncaused the redirect, and the third argument is the new request to follow the\nredirect.  See [Resources](#resources) for more details.\n\nThe URL of the new resource to retrieve is given by `response.url`.\n\n#### request (request)\n\nEmitted before making a request to retrieve a resource.\n\nThe first argument is the request object.  See [Resources](#resources) for more\ndetails.\n\n#### response (request, response)\n\nEmitted after receiving the response (excluding redirects).\n\nThe first argument is the request object, the second argument is the response\nobject.  See [Resources](#resources) for more details.\n\n#### submit (url, target)\n\nEmitted whenever a form is submitted.\n\nThe first argument is the URL of the new location, the second argument\nidentifies the target window (`_self`, `_blank`, window name, etc).\n\n#### timeout (function, delay)\n\nEmitted whenever a timeout (`setTimeout`) is fired.\n\nThe first argument is the function or code to evaluate, the second argument is\nthe delay in milliseconds.\n\n\n\n\n## Resources\n\nZombie can retrieve with resources - HTML pages, scripts, XHR requests - over\nHTTP, HTTPS and from the file system.\n\nMost work involving resources is done behind the scenes, but there are few\nnotable features that you'll want to know about. Specifically, if you need to do\nany of the following:\n\n- Inspect the history of retrieved resources, useful for troubleshooting issues\n  related to resource loading\n- Simulate a failed server\n- Change the order in which resources are retrieved, or otherwise introduce\n  delays to simulate a real world network\n- Mock responses from servers you don't have access to, or don't want to access\n  from test environment\n- Request resources directly, but have Zombie handle cookies, authentication,\n  etc\n- Implement new mechanism for retrieving resources, for example, add new\n  protocols or support new headers\n\n\n### The Resources List\n\nEach browser provides access to its resources list through `browser.resources`.\n\nThe resources list is an array of all resouces requested by the browser.  You\ncan iterate and manipulate it just like any other JavaScript array.\n\nEach resource provides four properties:\n\n- `request`   - The request object\n- `response`  - The resource object (if received)\n- `error`     - The error received instead of response\n- `target`    - The target element or document (when loading HTML page, script,\n  etc)\n\nThe request object consists of:\n\n- `method`      - HTTP method, e.g. \"GET\"\n- `url`         - The requested URL\n- `headers`     - All request headers\n- `body`        - The request body can be `Buffer` or string; only applies to\n  POST and PUT methods\n- `multipart`  - Used instead of a body to support file upload\n- `time`        - Timestamp when request was made\n- `timeout`     - Request timeout (0 for no timeout)\n\nThe response object consists of:\n\n- `url`         - The actual URL of the resource; different from request URL if\n  there were any redirects\n- `statusCode`  - HTTP status code, eg 200\n- `statusText`  - HTTP static code as text, eg \"OK\"\n- `headers`     - All response headers\n- `body`        - The response body, may be `Buffer` or string, depending on the\n  content type encoding\n- `redirects`   - Number of redirects followed (0 if no redirects)\n- `time`        - Timestamp when response was completed\n\nRequest for loading pages and scripts include the target DOM element or\ndocument. This is used internally, and may also give you more insight as to why\na request is being made.\n\n\n### Mocking, Failing and Delaying Responses\n\nTo help in testing, Zombie includes some convenience methods for mocking,\nfailing and delaying responses.\n\nFor example, to mock a response:\n\n```js\nbrowser.resources.mock('http://3rd.party.api/v1/request', {\n  statusCode: 200,\n  headers:    { 'ContentType': 'application/json' },\n  body:       JSON.stringify({ 'count': 5 })\n})\n```\n\nIn the real world, servers and networks often fail.  You can test for these\nconditions by asking Zombie to simulate a failure.  For example:\n\n```js\nbrowser.resources.fail('/form/post');\n```\n\nResource URLs can be absolute or relative strings or regular expressions.\nRelative URLs will match any request with the same path, so only use relative\nURLs that are specific to a given request.  If the resource URL is a regular\nexpression, it will be tested against the requested URL and the handler used\nif there is a match.\n\nAnother issue you'll encounter in real-life applications are network latencies.\nWhen running tests, Zombie will request resources in the order in which they\nappear on the page, and likely receive them from the local server in that same\norder.\n\nOccassionally you'll need to force the server to return resources in a different\norder, for example, to check what happens when script A loads after script B.\nYou can introduce a delay into any response as simple as:\n\n```js\nbrowser.resources.delay('http://3d.party.api/v1/request', 50);\n```\n\n\n### The Pipeline\n\nZombie uses a pipeline to operate on resources.  You can extend that pipeline\nwith your own set of handlers, for example, to support additional protocols,\ncontent types, special handlers, better resource mocking, etc.\n\nThe pipeline consists of a set of handlers.  There are two types of handlers:\n\nFunctions with two arguments deal with requests.  They are called with the\nrequest object and a callback, and must call that callback with one of:\n\n- No arguments to pass control to the next handler\n- An error to stop processing and return that error\n- `null` and the response objec to return that response\n\nFunctions with three arguments deal with responses.  They are called with the\nrequest object, response object and a callback, and must call that callback with\none of:\n\n- No arguments to pass control to the next handler\n- An error to stop processing and return that error\n\nTo add a new handle to the end of the pipeline:\n\n```js\nbrowser.resources.addHandler(function(request, next) {\n  // Let's delay this request by 1/10th second\n  setTimeout(function() {\n    Resources.httpRequest(request, next);\n  }, Math.random() * 100);\n});\n```\n\nIf you need anything more complicated, you can access the pipeline directly via\n`browser.resources.pipeline`.\n\nYou can add handlers to all browsers via `Browser.Resources.addHandler`.  These\nhandlers are automatically added to every new `browser.resources` instance.\n\n```js\nBrowser.Resources.addHandler(function(request, response, next) {\n  // Log the response body\n  console.log('Response body: ' + response.body);\n  next();\n});\n```\n\nWhen handlers are executed, `this` is set to the browser instance.\n\n\n### Operating On Resources\n\nIf you need to retrieve or operate on resources directly, you can do that as\nwell, using all the same features available to Zombie, including mocks, cookies,\nauthentication, etc.\n\n#### resources.addHandler(handler)\n\nAdds a handler to the pipeline of this browser instance.  To add a handler to the\npipeline of every browser instance, use `Browser.Resources.addHandler`.\n\n#### resources.delay(url, delay)\n\nRetrieve the resource with the given URL, but only after a delay.\n\n#### resources.dump(output)\n\nDumps the resources list to the output stream (defaults to standard output\nstream). \n\n#### resources.fail(url, error)\n\nDo not attempt to retrieve the resource with the given URL, but act as if the\nrequest failed with the given message.\n\nThis is used to simulate network failures (can't resolve hostname, can't make\nconnection, etc).  To simulate server failures (status codes 5xx), use\n`resources.mock`.\n\n#### resources.pipeline\n\nReturns the current pipeline (array of handlers) for this browser instance.\n\n#### resources.get(url, callback)\n\nRetrieves a resource with the given URL and passes response to the callback.\n\nFor example:\n\n```js\nbrowser.resources.get('http://some.service', function(error, response) {\n  console.log(response.statusText);\n  console.log(response.body);\n});\n```\n\n#### resources.mock(url, response)\n\nDo not attempt to retrieve the resource with the given URL, but return the\nresponse object instead.\n\n#### resources.post(url, options, callback)\n\nPosts a document to the resource with the given URL and passes the response to\nthe callback.\n\nSupported options are:\n\n- `body`- Request document body\n- `headers` - Headers to include in the request\n- `params` - Parameters to pass in the document body\n- `timeout` - Request timeout in milliseconds (0 or `null` for no timeout)\n\nFor example:\n\n```js\nvar params  = { 'count': 5 };\nbrowser.resources.post('http://some.service',\n                       { params: params },\n                       function(error, response) {\n  . . .\n});\n\nvar headers = { 'Content-Type': 'application/x-www-form-urlencoded' };\nbrowser.resources.post('http://some.service',\n                       { headers: headers, body: 'count=5' },\n                       function(error, response) {\n   . . .\n});\n```\n\n\n#### resources.request(method, url, options, callback)\n\nMakes an HTTP request to the resource and passes the response to the callback.\n\nSupported options are:\n\n- `body`- Request document body\n- `headers` - Headers to include in the request\n- `params` - Parameters to pass in the query string (`GET`, `DELETE`) or\n  document body (`POST`, `PUT`)\n- `timeout` - Request timeout in milliseconds (0 or `null` for no timeout)\n\nFor example:\n\n```js\nbrowser.resources.request('DELETE',\n                          'http://some.service',\n                          function(error) {\n  . . .\n});\n```\n\n#### resources.restore(url)\n\nReset any special resource handling from a previous call to `delay`, `fail` or\n`mock`.\n\n\n### DNS masking\n\nYou can use DNS masking to test your application with real domain names.  For\nexample:\n\n```\nBrowser.dns.localhost('*.example.com');\nBrowser.defaults.site = 'http://example.com:3000';\n\nbrowser = Browser.create();\nbrowser.visit('/here', function(error, browser) {\n  browser.assert.url('http://example.com:3000/here');\n});\n```\n\nThe DNS masking offered by Zombie only works within the local Node process, and\nwill not interfere or affect any other application you run.\n\nUse `Browser.dns.map(domain, type, ip)` to map a domain name, and a particular\nrecord type (e.g. A, CNAME even MX) to the given IP address.  For example:\n\n```\nBrowser.dns.map('*.example.com', 'A', '127.0.0.1');    // IPv4\nBrowser.dns.map('*.example.com', 'AAAA', '::1');       // IPv6\nBrowser.dns.map('*.example.com', 'CNAME', 'localhost');\n```\n\nSince these are the most common mapping, you can call `map` with two arguments\nand Zombie will infer if the second argumet is an IPv4 address, IPv6 address or\nCNAME.\n\nOf for short, just map the A and AAAA records like this:\n\n```\nBrowser.dns.localhost('*.example.com') // IPv4 and IPv6\n```\n\nIf you use an asertisk, it will map the domain itself and all sub-domains,\nincluding `www.example.com`, `assets.example.com` and `example.com`.  Don't use\nan asterisk if you only want to map the specific domain.\n\nFor MX records:\n\n```\nBrowser.dns.map('example.com', 'MX', { exchange: 'localhost', priority: 10 });\n```\n\n\n### Port Mapping\n\nYour test server is most likely not running on a privileged port, but you can\ntell Zombie to map port 80 to the test server's port for a given domain.\n\nFor example, if your test server is running on port 3000, you can tell Zombie to\nmap port 80 to port 3000:\n\n```\nBrowser.ports.map('localhost', 3000);\n```\n\nIf you're testing sub-domains, you can also apply the mapping to all sub-domains\nwith an asterisk, for example:\n\n```\nBrowser.ports.map('*.example.com', 3000);\n```\n\n\n\n\n\n## Debugging\n\nTo see what your code is doing, you can use `console.log` and friends from both\nclient-side scripts and your test code.\n\nIf you want to disable console output from scripts, set `browser.silent = true`\nor once for all browser instances with `Browser.default.silent = true`.\n\nFor more details about what Zombie is doing (windows opened, requests made,\nevent loop, etc), run with the environment variable `DEBUG=zombie`.  Zombie uses\nthe [debug](https://github.com/visionmedia/debug) module, so if your code also\nuses it, you can selectively control which modules should output debug\ninformation.\n\nSome objects, like the browser, history, resources, tabs and windows also\ninclude `dump` method that will dump the current state to the console.\n\n\n\n\n## FAQ\n\n**Q:** *How do I get Zombie working with http://google.com (or any other public\nweb site)?*\n\n**A:** Zombie is intended for **functional testing of Web applications**.\n\nZombie is not intended for scraping web sites.  You can use Zombie however you\nwant to, just be advised it might not work and will never get fixed.\n\n\n**Q:** *How do I report a bug?*\n\n**A:** [Open an issue on Github](https://github.com/assaf/zombie/issues).  But\nfirst, read the answer to the next question.\n\n\n**Q:** *How do I get someone to look at my bug?*\n\n**A:** By **isolating, testing and pull requesting**:\n\n1.  Isolate to the minimum HTML/JS/etc that's necessary to prove the bug.\n    That means code that works directly with the DOM.  No one else is going to\n    do the work of isolating the test case from thousands of lines of\n    Angular/Backbone/jQuery/etc.\n2.  Write a test case that will go green when that bug is fixed.\n    The [Zombie test suite](https://github.com/assaf/zombie/tree/master/test)\n    has over 680 test cases, you can easily find one to copy and adapt.\n3.  Submit a pull request with the test case, and if you have any, the suggested\n    solution.\n\n\n**Q:** *I found a bug in Zombie, here's a stack trace line showing where\nContextify/JSDOM/CSSOM/htmlparser/whatever is crashing.*\n\n**A:** You found a bug that happens when you call some method on Zombie.\nThere's a chance it's a bug in Zombie, and there's a chance it's an issue with\none of the many dependencies, as shows in the stack trace.\n\nIf you're looking for the quickest solution, try to find the responsible\ncomponent and report the issue there.  The developers of\nContextify/JSDOM/CSSOM/htmlparser/whatever are not monitoring the Zombie issues\nlist.\n\n\n**Q:** *But how can I find what component is repsonsible for that bug?*\n\n**A:** There is no Zombie developer team with privileged access.\n\nThe [full source code](https://github.com/assaf/zombie) for Zombie is available\nhere.  The dependencies are [listed\nhere](https://github.com/assaf/zombie/blob/master/package.json).  Everything,\neven the Node and V8 runtimes are open source.\n\n\n**Q:** *Zombie not working for me, can you fix it?*\n\n**A:** Zombie is an open source project.  It's free as in \"do whatever you want\nwith it!\"\n\nZombie is not free as in \"open bar\".  You get as much out of it as you put into\nit, plus everyone else's contributions.\n\n",
  "readmeFilename": "README.md",
  "_id": "zombie@2.5.1",
  "dist": {
    "shasum": "fcfca9bf33749c3324b2d17a81598df088cb5c9f"
  },
  "_from": "zombie@",
  "_resolved": "https://registry.npmjs.org/zombie/-/zombie-2.5.1.tgz"
}
