phantom
Version:
PhantomJS integration module for NodeJS
136 lines (117 loc) • 3.3 kB
Flow
// @flow
import Phantom from './phantom';
/**
* Page class that proxies everything to phantomjs
*/
export default class Page {
$phantom: Phantom;
target: string;
constructor(phantom: Phantom, pageId: string) {
this.target = `page$${pageId}`;
this.$phantom = phantom;
}
/**
* Add an event listener to the page on phantom
*
* @param event The name of the event (Ej. onResourceLoaded)
* @param [runOnPhantom=false] Indicate if the event must run on the phantom runtime or not
* @param listener The event listener. When runOnPhantom=true, this listener code would be
* run on phantom, and thus, all the closure info wont work
* @returns {*}
*/
on(event: string, runOnPhantom: boolean = false, listener: Function, ...args: any[]) {
let mustRunOnPhantom;
let callback;
let params;
if (typeof runOnPhantom === 'function') {
mustRunOnPhantom = false;
params = [listener, ...args];
callback = runOnPhantom.bind(this);
} else {
params = args;
mustRunOnPhantom = runOnPhantom;
callback = mustRunOnPhantom ? listener : listener.bind(this);
}
return this.$phantom.on(event, this.target, mustRunOnPhantom, callback, params);
}
/**
* Removes an event listener
*
* @param event the event name
* @returns {*}
*/
off(event: string) {
return this.$phantom.off(event, this.target);
}
/**
* Invokes an asynchronous method
*/
invokeAsyncMethod(...args: any[]) {
return this.$phantom.execute(this.target, 'invokeAsyncMethod', args);
}
/**
* Invokes a method
*/
invokeMethod(...args: any[]) {
return this.$phantom.execute(this.target, 'invokeMethod', args);
}
/**
* Defines a method
*/
defineMethod(name: string, definition: Function) {
return this.$phantom.execute(this.target, 'defineMethod', [name, definition]);
}
/**
* Gets or sets a property
*/
property(...args: any[]): Promise<*> {
if (args.length > 1 && typeof args[1] === 'function') {
throw new Error('page.property(key, function(){}) has been removed. Use page.on(key, function(){}) instead.');
}
return this.$phantom.execute(this.target, 'property', args);
}
/**
* Gets or sets a setting
*/
setting(...args: any[]): Promise<*> {
return this.$phantom.execute(this.target, 'setting', args);
}
cookies(): Promise<*> {
return this.property('cookies');
}
}
const asyncMethods = ['includeJs', 'open'];
const methods = [
'addCookie',
'clearCookies',
'close',
'deleteCookie',
'evaluate',
'evaluateAsync',
'evaluateJavaScript',
'injectJs',
'openUrl',
'reload',
'render',
'renderBase64',
'sendEvent',
'setContent',
'setProxy',
'stop',
'switchToFrame',
'switchToMainFrame',
'goBack',
'uploadFile',
];
asyncMethods.forEach((method) => {
// $FlowFixMe: no way to provide dynamic functions
Page.prototype[method] = function _(...args: any[]) {
return this.invokeAsyncMethod.apply(this, [method, ...args]);
};
});
methods.forEach((method) => {
// $FlowFixMe: no way to provide dynamic functions
Page.prototype[method] = function _(...args: any[]) {
return this.invokeMethod.apply(this, [method, ...args]);
};
});