function Promise() { [native code] }
n/a
action = function () { var name = arguments[0], childfn, parentfn; if(arguments.length === 2) { parentfn = arguments[1]; } else { parentfn = arguments[2]; childfn = arguments[1]; } // support functions and objects // if it's an object, wrap it's // properties in the queue function if(parentfn) { if (typeof parentfn === 'function') { Nightmare.prototype[name] = queued(name, parentfn); } else { if (!~Nightmare.namespaces.indexOf(name)) { Nightmare.namespaces.push(name); } Nightmare.prototype[name] = function() { var self = this; return keys(parentfn).reduce(function (obj, key) { obj[key] = queued(name, parentfn[key]).bind(self) return obj; }, {}); } } } if(childfn) { if (typeof childfn === 'function') { Nightmare.childActions[name] = childfn; } else { for(var key in childfn){ Nightmare.childActions[name+'.'+key] = childfn; } } } }
...
var Promise = require('bluebird');
var nightmare = Nightmare({ Promise });
```
### Extending Nightmare
#### Nightmare.action(name, [electronAction|electronNamespace], action|namespace)
You can add your own custom actions to the Nightmare prototype. Here's an example:
```js
Nightmare.action('size', function (done) {
this.evaluate_now(function() {
var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0)
...
function FrameManager(window) {
if (!(this instanceof FrameManager)) return new FrameManager(window);
EventEmitter.call(this);
var subscribed = false;
var requestedFrame = false;
var frameRequestTimeout;
var self = this;
this.on('newListener', subscribe);
this.on('removeListener', unsubscribe);
function subscribe(eventName) {
if (!subscribed && eventName === 'data') {
parent.emit('log', 'subscribing to browser window frames');
window.webContents.beginFrameSubscription(receiveFrame);
}
}
function unsubscribe() {
if (!self.listenerCount('data')) {
parent.emit('log', 'unsubscribing from browser window frames')
window.webContents.endFrameSubscription();
subscribed = false;
}
}
function receiveFrame(buffer) {
requestedFrame = false;
clearTimeout(frameRequestTimeout);
self.emit('data', buffer);
}
/**
* In addition to listening for events, calling `requestFrame` will ensure
* that a frame is queued up to render (instead of just waiting for the next
* time the browser chooses to draw a frame).
* @param {Function} [callback] Called when the frame is rendered.
* @param {Number} [timeout=1000] If no frame has been rendered after this
many milliseconds, run the callback anyway. In this case, The
callback's first argument, an image buffer, will be `null`.
*/
this.requestFrame = function(callback, timeout) {
timeout = (timeout == undefined) ? 1000 : timeout;
if (callback) {
this.once('data', callback);
}
if (!requestedFrame) {
requestedFrame = true;
// Force the browser to render new content by using the debugger to
// highlight a portion of the page. This way, we can guarantee a change
// that both requires rendering a frame and does not actually affect
// the content of the page.
if (!window.webContents.debugger.isAttached()) {
try {
window.webContents.debugger.attach();
}
catch (error) {
parent.emit('log', `Failed to attach to debugger for frame subscriptions: ${error}`);
this.emit('data', null);
return;
}
}
if (timeout) {
frameRequestTimeout = setTimeout(function() {
parent.emit('log', `FrameManager timing out after ${timeout} ms with no new rendered frames`);
self.emit('data', null)
}, timeout);
}
parent.emit('log', 'Highlighting page to trigger rendering.');
window.webContents.debugger.sendCommand('DOM.enable')
window.webContents.debugger.sendCommand(
'DOM.highlightRect', HIGHLIGHT_STYLE, function(error) {
window.webContents.debugger.sendCommand('DOM.hideHighlight');
window.webContents.debugger.detach();
});
}
};
}
n/a
authentication = function (login, password, done) { debug('.authentication()'); this.child.call('authentication', login, password, done); }
...
#### .engineVersions()
Gets the versions for Electron and Chromium.
#### .useragent(useragent)
Set the `useragent` used by electron.
#### .authentication(user, password)
Set the `user` and `password` for accessing a web page using basic authentication. Be sure to set it before calling `.goto(url)`.
#### .end()
Complete any queue operations, disconnect and close the electron process. Note that if you're using promises, `.then()` must
be called after `.end()` to run the `.end()` task. Also note that if using a `.end()` callback, the `.end()` call is equivalent
to calling `.end()` followed by `.then(fn)`. Consider:
```js
nightmare
...
back = function (done) { debug('.back()'); this.evaluate_now(function() { window.history.back(); }, done); }
...
- `details`: A string with additional details about the error. This may be null or an empty string.
- `url`: The URL that failed to load
Note that any valid response from a server is considered “successful.” That means things like 404 “not found” errors are successful
results for `goto`. Only things that would cause no page to appear in the browser window, such as no server responding at the given
address, the server hanging up in the middle of a response, or invalid URLs, are errors.
You can also adjust how long `goto` will wait before timing out by setting the [`gotoTimeout` option](#gototimeout-default-30s)
on the Nightmare constructor.
#### .back()
Go back to the previous page.
#### .forward()
Go forward to the next page.
#### .refresh()
Refresh the current page.
...
check = function (selector, done) { debug('.check() ' + selector); this.evaluate_now(function(selector) { var element = document.querySelector(selector); var event = document.createEvent('HTMLEvents'); element.checked = true; event.initEvent('change', true, true); element.dispatchEvent(event); }, done, selector); }
...
> If you don't need the keyboard events, consider using `.insert()` instead as it will be faster and more robust.
#### .insert(selector[, text])
Similar to `.type()`. `.insert()` enters the `text` provided into the `selector` element. Empty or falsey values provided for `
text` will clear the selector's value.
`.insert()` is faster than `.type()` but does not trigger the keyboard events.
#### .check(selector)
checks the `selector` checkbox element.
#### .uncheck(selector)
unchecks the `selector` checkbox element.
#### .select(selector, option)
Changes the `selector` dropdown element to the option with attribute [value=`option`]
...
click = function (selector, done) { debug('.click() on ' + selector); this.evaluate_now(function (selector) { document.activeElement.blur(); var element = document.querySelector(selector); if (!element) { throw new Error('Unable to find element by selector: ' + selector); } var event = document.createEvent('MouseEvent'); event.initEvent('click', true, true); element.dispatchEvent(event); }, done, selector); }
...
```js
var Nightmare = require('nightmare');
var nightmare = Nightmare({ show: true });
nightmare
.goto('https://duckduckgo.com')
.type('#search_form_input_homepage', 'github nightmare')
.click('#search_button_homepage')
.wait('#zero_click_wrapper .c-info__title a')
.evaluate(function () {
return document.querySelector('#zero_click_wrapper .c-info__title a').href;
})
.end()
.then(function (result) {
console.log(result);
...
engineVersions = function (done){ debug('.engineVersions()'); done(null, this.engineVersions); }
...
Defines the number of times to retry an authentication when set up with `.authenticate()`.
```js
var nightmare = Nightmare({
maxAuthRetries: 3
});
```
#### .engineVersions()
Gets the versions for Electron and Chromium.
#### .useragent(useragent)
Set the `useragent` used by electron.
#### .authentication(user, password)
Set the `user` and `password` for accessing a web page using basic authentication. Be sure to set it before calling `.goto(url)`.
...
evaluate = function (fn) { var args = sliced(arguments); var done = args[args.length-1]; var self = this; var newDone = function(){ clearTimeout(timeoutTimer); done.apply(self, arguments); }; var newArgs = [fn, newDone].concat(args.slice(1,-1)); if (typeof fn !== 'function') { return done(new Error('.evaluate() fn should be a function')); } debug('.evaluate() fn on the page'); var timeoutTimer = setTimeout(function(){ done(new Error(`Evaluation timed out after ${self.options.executionTimeout}msec. Are you calling done() or resolving your promises ?`)); }, self.options.executionTimeout); this.evaluate_now.apply(this, newArgs); }
...
var nightmare = Nightmare({ show: true });
nightmare
.goto('https://duckduckgo.com')
.type('#search_form_input_homepage', 'github nightmare')
.click('#search_button_homepage')
.wait('#zero_click_wrapper .c-info__title a')
.evaluate(function () {
return document.querySelector('#zero_click_wrapper .c-info__title a').href;
})
.end()
.then(function (result) {
console.log(result);
})
.catch(function (error) {
...
exists = function (selector, done) { debug('.exists() for ' + selector); this.evaluate_now(function(selector) { return (document.querySelector(selector)!==null); }, done, selector); }
...
Wait until the `fn` evaluated on the page with `arg1, arg2,...` returns `true`. All the `args` are optional. See `.evaluate()` for
usage.
#### .header([header, value])
Add a header override for all HTTP requests. If `header` is undefined, the header overrides will be reset.
### Extract from the Page
#### .exists(selector)
Returns whether the selector exists or not on the page.
#### .visible(selector)
Returns whether the selector is visible or not
#### .on(event, callback)
Capture page events with the callback. You have to call `.on()` before calling `.goto()`. Supported events are [documented here](
http://electron.atom.io/docs/api/web-contents/#instance-events).
...
forward = function (done) { debug('.forward()'); this.evaluate_now(function() { window.history.forward(); }, done); }
...
Note that any valid response from a server is considered “successful.” That means things like 404 “not found” errors are successful
results for `goto`. Only things that would cause no page to appear in the browser window, such as no server responding at the given
address, the server hanging up in the middle of a response, or invalid URLs, are errors.
You can also adjust how long `goto` will wait before timing out by setting the [`gotoTimeout` option](#gototimeout-default-30s)
on the Nightmare constructor.
#### .back()
Go back to the previous page.
#### .forward()
Go forward to the next page.
#### .refresh()
Refresh the current page.
#### .click(selector)
Clicks the `selector` element once.
...
html = function (path, saveType, done) { debug('.html()'); if (typeof path === 'function' && !saveType && !done) { done = path; saveType = undefined; path = undefined; } else if (typeof path === 'object' && typeof saveType === 'function' && !done) { done = saveType; saveType = path; path = undefined; } else if (typeof saveType === 'function' && !done) { done = saveType; saveType = undefined; } this.child.call('html', path, saveType, function (error) { if (error) debug(error); done(error); }); }
...
#### .removeListener(event, callback)
Removes a given listener callback for an event.
#### .screenshot([path][, clip])
Takes a screenshot of the current page. Useful for debugging. The output is always a `png`. Both arguments are optional. If `path
` is provided, it saves the image to the disk. Otherwise it returns a `Buffer` of the image data. If `clip` is provided (as [documented
here](https://github.com/atom/electron/blob/master/docs/api/browser-window.md#wincapturepagerect-callback)), the image will be
clipped to the rectangle.
#### .html(path, saveType)
Save the current page as html as files to disk at the given path. Save type options are [here](https://github.com/atom/electron/
blob/master/docs/api/web-contents.md#webcontentssavepagefullpath-savetype-callback).
#### .pdf(path, options)
Saves a PDF to the specified `path`. Options are [here](https://github.com/electron/electron/blob/v1.4.4/docs/api/web-contents.md
#contentsprinttopdfoptions-callback).
#### .title()
Returns the title of the current page.
...
inject = function (type, file, done) { debug('.inject()-ing a file'); if (type === 'js') { var js = fs.readFileSync(file, { encoding: 'utf-8' }); this._inject(js, done); } else if (type === 'css') { var css = fs.readFileSync(file, { encoding: 'utf-8' }); this.child.call('css', css, done); } else { debug('unsupported file type in .inject()'); done(); } }
...
#### .scrollTo(top, left)
Scrolls the page to desired position. `top` and `left` are always relative to the top left corner of the document.
#### .viewport(width, height)
Set the viewport size.
#### .inject(type, file)
Inject a local `file` onto the current page. The file `type` must be either `js` or `css`.
#### .evaluate(fn[, arg1, arg2,...])
Invokes `fn` on the page with `arg1, arg2,...`. All the `args` are optional. On completion it returns the return value of `fn`.
Useful for extracting information from the page. Here's an example:
```js
var selector = 'h1';
...
insert = function (selector, text, done) { if (arguments.length === 2) { done = text text = null } debug('.insert() %s into %s', text, selector); var child = this.child; focusSelector.bind(this)(function(err) { if(err) { debug('Unable to .insert() into non-existent selector %s', selector); return done(err); } var blurDone = blurSelector.bind(this, done, selector); if ((text || '') == '') { this.evaluate_now(function(selector) { document.querySelector(selector).value = ''; }, blurDone, selector); } else { child.call('insert', text, blurDone); } }, selector); }
...
#### .type(selector[, text])
Enters the `text` provided into the `selector` element. Empty or falsey values provided for `text` will clear the selector'
;s value.
`.type()` mimics a user typing in a textbox and will emit the proper keyboard events
Key presses can also be fired using Unicode values with `.type()`. For example, if you wanted to fire an enter key press, you would
write `.type('body', '\u000d')`.
> If you don't need the keyboard events, consider using `.insert()` instead
as it will be faster and more robust.
#### .insert(selector[, text])
Similar to `.type()`. `.insert()` enters the `text` provided into the `selector` element. Empty or falsey values provided for `
text` will clear the selector's value.
`.insert()` is faster than `.type()` but does not trigger the keyboard events.
#### .check(selector)
...
mousedown = function (selector, done) { debug('.mousedown() on ' + selector); this.evaluate_now(function (selector) { var element = document.querySelector(selector); if (!element) { throw new Error('Unable to find element by selector: ' + selector); } var event = document.createEvent('MouseEvent'); event.initEvent('mousedown', true, true); element.dispatchEvent(event); }, done, selector); }
...
#### .refresh()
Refresh the current page.
#### .click(selector)
Clicks the `selector` element once.
#### .mousedown(selector)
Mousedown the `selector` element once.
#### .mouseup(selector)
Mouseup the `selector` element once.
#### .mouseover(selector)
Mouseover the `selector` element once.
...
mouseover = function (selector, done) { debug('.mouseover() on ' + selector); this.evaluate_now(function (selector) { var element = document.querySelector(selector); if (!element) { throw new Error('Unable to find element by selector: ' + selector); } var event = document.createEvent('MouseEvent'); event.initMouseEvent('mouseover', true, true); element.dispatchEvent(event); }, done, selector); }
...
#### .mousedown(selector)
Mousedown the `selector` element once.
#### .mouseup(selector)
Mouseup the `selector` element once.
#### .mouseover(selector)
Mouseover the `selector` element once.
#### .type(selector[, text])
Enters the `text` provided into the `selector` element. Empty or falsey values provided for `text` will clear the selector'
;s value.
`.type()` mimics a user typing in a textbox and will emit the proper keyboard events
...
mouseup = function (selector, done) { debug('.mouseup() on ' + selector); this.evaluate_now(function (selector) { var element = document.querySelector(selector); if (!element) { throw new Error('Unable to find element by selector: ' + selector); } var event = document.createEvent('MouseEvent'); event.initEvent('mouseup', true, true); element.dispatchEvent(event); }, done, selector); }
...
#### .click(selector)
Clicks the `selector` element once.
#### .mousedown(selector)
Mousedown the `selector` element once.
#### .mouseup(selector)
Mouseup the `selector` element once.
#### .mouseover(selector)
Mouseover the `selector` element once.
#### .type(selector[, text])
Enters the `text` provided into the `selector` element. Empty or falsey values provided for `text` will clear the selector'
;s value.
...
path = function (done) { debug('.path() getting it'); this.evaluate_now(function() { return document.location.pathname; }, done); }
...
#### .title()
Returns the title of the current page.
#### .url()
Returns the url of the current page.
#### .path()
Returns the path name of the current page.
### Cookies
#### .cookies.get(name)
Get a cookie by it's `name`. The url will be the current url.
...
pdf = function (path, options, done) { debug('.pdf()'); if (typeof path === 'function' && !options && !done) { done = path; options = undefined; path = undefined; } else if (typeof path === 'object' && typeof options === 'function' && !done){ done = options; options = path; path = undefined; } else if (typeof options === 'function' && !done) { done = options; options = undefined; } this.child.call('pdf', path, options, function (error, pdf) { if (error) debug(error); var buf = new Buffer(pdf.data); debug('.pdf() captured with length %s', buf.length); path ? fs.writeFile(path, buf, done) : done(null, buf); }); }
...
#### .screenshot([path][, clip])
Takes a screenshot of the current page. Useful for debugging. The output is always a `png`. Both arguments are optional. If `path
` is provided, it saves the image to the disk. Otherwise it returns a `Buffer` of the image data. If `clip` is provided (as [documented
here](https://github.com/atom/electron/blob/master/docs/api/browser-window.md#wincapturepagerect-callback)), the image will be
clipped to the rectangle.
#### .html(path, saveType)
Save the current page as html as files to disk at the given path. Save type options are [here](https://github.com/atom/electron/
blob/master/docs/api/web-contents.md#webcontentssavepagefullpath-savetype-callback).
#### .pdf(path, options)
Saves a PDF to the specified `path`. Options are [here](https://github.com/electron/electron/blob/v1.4.4/docs/api/web-contents.md
#contentsprinttopdfoptions-callback).
#### .title()
Returns the title of the current page.
#### .url()
Returns the url of the current page.
...
refresh = function (done) { debug('.refresh()'); this.evaluate_now(function() { window.location.reload(); }, done); }
...
#### .back()
Go back to the previous page.
#### .forward()
Go forward to the next page.
#### .refresh()
Refresh the current page.
#### .click(selector)
Clicks the `selector` element once.
#### .mousedown(selector)
Mousedown the `selector` element once.
...
screenshot = function (path, clip, done) { debug('.screenshot()'); if (typeof path === 'function') { done = path; clip = undefined; path = undefined; } else if (typeof clip === 'function') { done = clip; clip = (typeof path === 'string') ? undefined : path; path = (typeof path === 'string') ? path : undefined; } this.child.call('screenshot', path, clip, function (error, img) { var buf = new Buffer(img.data); debug('.screenshot() captured with length %s', buf.length); path ? fs.writeFile(path, buf, done) : done(null, buf); }); }
...
#### .once(event, callback)
Similar to `.on()`, but captures page events with the callback one time.
#### .removeListener(event, callback)
Removes a given listener callback for an event.
#### .screenshot([path][, clip])
Takes a screenshot of the current page. Useful for debugging. The output is always a `png`. Both arguments are optional. If `path
` is provided, it saves the image to the disk. Otherwise it returns a `Buffer` of the image data. If `clip` is provided (as [documented
here](https://github.com/atom/electron/blob/master/docs/api/browser-window.md#wincapturepagerect-callback)), the image will be
clipped to the rectangle.
#### .html(path, saveType)
Save the current page as html as files to disk at the given path. Save type options are [here](https://github.com/atom/electron/
blob/master/docs/api/web-contents.md#webcontentssavepagefullpath-savetype-callback).
#### .pdf(path, options)
Saves a PDF to the specified `path`. Options are [here](https://github.com/electron/electron/blob/v1.4.4/docs/api/web-contents.md
#contentsprinttopdfoptions-callback).
...
scrollTo = function (y, x, done) { debug('.scrollTo()'); this.evaluate_now(function (y, x) { window.scrollTo(x, y); }, done, y, x); }
...
#### .uncheck(selector)
unchecks the `selector` checkbox element.
#### .select(selector, option)
Changes the `selector` dropdown element to the option with attribute [value=`option`]
#### .scrollTo(top, left)
Scrolls the page to desired position. `top` and `left` are always relative to the top left corner of the document.
#### .viewport(width, height)
Set the viewport size.
#### .inject(type, file)
...
select = function (selector, option, done) { debug('.select() ' + selector); this.evaluate_now(function(selector, option) { var element = document.querySelector(selector); var event = document.createEvent('HTMLEvents'); element.value = option; event.initEvent('change', true, true); element.dispatchEvent(event); }, done, selector, option); }
...
#### .check(selector)
checks the `selector` checkbox element.
#### .uncheck(selector)
unchecks the `selector` checkbox element.
#### .select(selector, option)
Changes the `selector` dropdown element to the option with attribute [value=`option`]
#### .scrollTo(top, left)
Scrolls the page to desired position. `top` and `left` are always relative to the top left corner of the document.
#### .viewport(width, height)
...
title = function (done) { debug('.title() getting it'); this.evaluate_now(function() { return document.title; }, done); }
...
#### .html(path, saveType)
Save the current page as html as files to disk at the given path. Save type options are [here](https://github.com/atom/electron/
blob/master/docs/api/web-contents.md#webcontentssavepagefullpath-savetype-callback).
#### .pdf(path, options)
Saves a PDF to the specified `path`. Options are [here](https://github.com/electron/electron/blob/v1.4.4/docs/api/web-contents.md
#contentsprinttopdfoptions-callback).
#### .title()
Returns the title of the current page.
#### .url()
Returns the url of the current page.
#### .path()
Returns the path name of the current page.
...
type = function () { var selector = arguments[0], text, done; if(arguments.length == 2) { done = arguments[1]; } else { text = arguments[1]; done = arguments[2]; } debug('.type() %s into %s', text, selector); var self = this; focusSelector.bind(this)(function(err) { if(err) { debug('Unable to .type() into non-existent selector %s', selector); return done(err); } var blurDone = blurSelector.bind(this, done, selector); if ((text || '') == '') { this.evaluate_now(function(selector) { document.querySelector(selector).value = ''; }, blurDone, selector); } else { self.child.call('type', text, blurDone); } }, selector); }
...
```js
var Nightmare = require('nightmare');
var nightmare = Nightmare({ show: true });
nightmare
.goto('https://duckduckgo.com')
.type('#search_form_input_homepage', 'github nightmare')
.click('#search_button_homepage')
.wait('#zero_click_wrapper .c-info__title a')
.evaluate(function () {
return document.querySelector('#zero_click_wrapper .c-info__title a').href;
})
.end()
.then(function (result) {
...
uncheck = function (selector, done){ debug('.uncheck() ' + selector); this.evaluate_now(function(selector) { var element = document.querySelector(selector); var event = document.createEvent('HTMLEvents'); element.checked = null; event.initEvent('change', true, true); element.dispatchEvent(event); }, done, selector); }
...
Similar to `.type()`. `.insert()` enters the `text` provided into the `selector` element. Empty or falsey values provided for `
text` will clear the selector's value.
`.insert()` is faster than `.type()` but does not trigger the keyboard events.
#### .check(selector)
checks the `selector` checkbox element.
#### .uncheck(selector)
unchecks the `selector` checkbox element.
#### .select(selector, option)
Changes the `selector` dropdown element to the option with attribute [value=`option`]
#### .scrollTo(top, left)
Scrolls the page to desired position. `top` and `left` are always relative to the top left corner of the document.
...
url = function (done) { debug('.url() getting it'); this.evaluate_now(function() { return document.location.href; }, done); }
...
#### .pdf(path, options)
Saves a PDF to the specified `path`. Options are [here](https://github.com/electron/electron/blob/v1.4.4/docs/api/web-contents.md
#contentsprinttopdfoptions-callback).
#### .title()
Returns the title of the current page.
#### .url()
Returns the url of the current page.
#### .path()
Returns the path name of the current page.
### Cookies
...
useragent = function (useragent, done) { debug('.useragent() to ' + useragent); this.child.call('useragent', useragent, done); }
...
maxAuthRetries: 3
});
```
#### .engineVersions()
Gets the versions for Electron and Chromium.
#### .useragent(useragent)
Set the `useragent` used by electron.
#### .authentication(user, password)
Set the `user` and `password` for accessing a web page using basic authentication. Be sure to set it before calling `.goto(url)`.
#### .end()
Complete any queue operations, disconnect and close the electron process. Note that if you're using promises, `.then()` must
be called after `.end()` to run the `.end()` task. Also note that if using a `.end()` callback, the `.end()` call is equivalent
to calling `.end()` followed by `.then(fn)`. Consider:
...
viewport = function (width, height, done) { debug('.viewport()'); this.child.call('size', width, height, done); }
...
#### .select(selector, option)
Changes the `selector` dropdown element to the option with attribute [value=`option`]
#### .scrollTo(top, left)
Scrolls the page to desired position. `top` and `left` are always relative to the top left corner of the document.
#### .viewport(width, height)
Set the viewport size.
#### .inject(type, file)
Inject a local `file` onto the current page. The file `type` must be either `js` or `css`.
#### .evaluate(fn[, arg1, arg2,...])
...
visible = function (selector, done) { debug('.visible() for ' + selector); this.evaluate_now(function(selector) { var elem = document.querySelector(selector); if (elem) return (elem.offsetWidth > 0 && elem.offsetHeight > 0); else return false; }, done, selector); }
...
Add a header override for all HTTP requests. If `header` is undefined, the header overrides will be reset.
### Extract from the Page
#### .exists(selector)
Returns whether the selector exists or not on the page.
#### .visible(selector)
Returns whether the selector is visible or not
#### .on(event, callback)
Capture page events with the callback. You have to call `.on()` before calling `.goto()`. Supported events are [documented here](
http://electron.atom.io/docs/api/web-contents/#instance-events).
##### Additional "page" events
...
wait = function () { var args = sliced(arguments); var done = args[args.length-1]; if (args.length < 2) { debug('Not enough arguments for .wait()'); return done(); } var arg = args[0]; if (typeof arg === 'number') { debug('.wait() for ' + arg + 'ms'); if(arg < this.options.waitTimeout){ waitms(arg, done); } else { waitms(this.options.waitTimeout, function(){ done(new Error('.wait() timed out after '+this.options.waitTimeout+'msec')); }.bind(this)); } } else if (typeof arg === 'string') { var timeout = null; if (typeof args[1] === 'number') { timeout = args[1]; } debug('.wait() for '+arg+' element'+(timeout ? ' or '+timeout+'msec' : '')); waitelem.apply({ timeout: timeout }, [this, arg, done]); } else if (typeof arg === 'function') { debug('.wait() for fn'); args.unshift(this); waitfn.apply(this, args); } else { done(); } }
...
var Nightmare = require('nightmare');
var nightmare = Nightmare({ show: true });
nightmare
.goto('https://duckduckgo.com')
.type('#search_form_input_homepage', 'github nightmare')
.click('#search_button_homepage')
.wait('#zero_click_wrapper .c-info__title a')
.evaluate(function () {
return document.querySelector('#zero_click_wrapper .c-info__title a').href;
})
.end()
.then(function (result) {
console.log(result);
})
...
function FrameManager(window) {
if (!(this instanceof FrameManager)) return new FrameManager(window);
EventEmitter.call(this);
var subscribed = false;
var requestedFrame = false;
var frameRequestTimeout;
var self = this;
this.on('newListener', subscribe);
this.on('removeListener', unsubscribe);
function subscribe(eventName) {
if (!subscribed && eventName === 'data') {
parent.emit('log', 'subscribing to browser window frames');
window.webContents.beginFrameSubscription(receiveFrame);
}
}
function unsubscribe() {
if (!self.listenerCount('data')) {
parent.emit('log', 'unsubscribing from browser window frames')
window.webContents.endFrameSubscription();
subscribed = false;
}
}
function receiveFrame(buffer) {
requestedFrame = false;
clearTimeout(frameRequestTimeout);
self.emit('data', buffer);
}
/**
* In addition to listening for events, calling `requestFrame` will ensure
* that a frame is queued up to render (instead of just waiting for the next
* time the browser chooses to draw a frame).
* @param {Function} [callback] Called when the frame is rendered.
* @param {Number} [timeout=1000] If no frame has been rendered after this
many milliseconds, run the callback anyway. In this case, The
callback's first argument, an image buffer, will be `null`.
*/
this.requestFrame = function(callback, timeout) {
timeout = (timeout == undefined) ? 1000 : timeout;
if (callback) {
this.once('data', callback);
}
if (!requestedFrame) {
requestedFrame = true;
// Force the browser to render new content by using the debugger to
// highlight a portion of the page. This way, we can guarantee a change
// that both requires rendering a frame and does not actually affect
// the content of the page.
if (!window.webContents.debugger.isAttached()) {
try {
window.webContents.debugger.attach();
}
catch (error) {
parent.emit('log', `Failed to attach to debugger for frame subscriptions: ${error}`);
this.emit('data', null);
return;
}
}
if (timeout) {
frameRequestTimeout = setTimeout(function() {
parent.emit('log', `FrameManager timing out after ${timeout} ms with no new rendered frames`);
self.emit('data', null)
}, timeout);
}
parent.emit('log', 'Highlighting page to trigger rendering.');
window.webContents.debugger.sendCommand('DOM.enable')
window.webContents.debugger.sendCommand(
'DOM.highlightRect', HIGHLIGHT_STYLE, function(error) {
window.webContents.debugger.sendCommand('DOM.hideHighlight');
window.webContents.debugger.detach();
});
}
};
}
n/a
function EventEmitter() { EventEmitter.init.call(this); }
n/a
function anonymous(obj ) { function escape(html) { return String(html) .replace(/&/g, '&') .replace(/"/g, '"') .replace(/</g, '<') .replace(/>/g, '>'); }; function section(obj, prop, negate, thunk) { var val = obj[prop]; if (Array.isArray(val)) return val.map(thunk).join(''); if ('function' == typeof val) return val.call(obj, thunk(obj)); if (negate) val = !val; if (val) return thunk(obj); return ''; }; return "\n(function javascript () {\n var ipc = (window.__nightmare ? __nightmare.ipc : window[''].nightmare.ipc);\n try {\n var fn = (" + obj.src + "),\n response, \n args = [];\n\n " + section(obj, "args", false, function(obj){ return "args.push(" + obj.argument + ");" }) + "\n\n if(fn.length - 1 == args.length) {\n args.push(((err, v) => {\n if(err) {\n ipc.send('error', err.message || err.toString());\n }\n ipc.send('response', v);\n }));\n fn.apply(null, args);\n } \n else {\n response = fn.apply(null, args);\n if(response && response.then) {\n response.then((v) => {\n ipc.send('response', v);\n })\n .catch((err) => {\n ipc.send('error', err)\n });\n } else {\n ipc.send('response', response);\n }\n }\n } catch (err) {\n ipc.send('error', err.message);\n }\n})()\n" }
n/a
function anonymous(obj ) { function escape(html) { return String(html) .replace(/&/g, '&') .replace(/"/g, '"') .replace(/</g, '<') .replace(/>/g, '>'); }; function section(obj, prop, negate, thunk) { var val = obj[prop]; if (Array.isArray(val)) return val.map(thunk).join(''); if ('function' == typeof val) return val.call(obj, thunk(obj)); if (negate) val = !val; if (val) return thunk(obj); return ''; }; return "\n(function javascript () {\n var ipc = (window.__nightmare ? __nightmare.ipc : window[''].nightmare.ipc);\n try {\n var response = (function () { " + obj.src + "\n})()\n ipc.send('response', response);\n } catch (e) {\n ipc.send('error', e.message);\n }\n})()\n" }
...
#### .scrollTo(top, left)
Scrolls the page to desired position. `top` and `left` are always relative to the top left corner of the document.
#### .viewport(width, height)
Set the viewport size.
#### .inject(type, file)
Inject a local `file` onto the current page. The file `type` must be either `js` or `css`.
#### .evaluate(fn[, arg1, arg2,...])
Invokes `fn` on the page with `arg1, arg2,...`. All the `args` are optional. On completion it returns the return value of `fn`.
Useful for extracting information from the page. Here's an example:
```js
var selector = 'h1';
...