zombie-globbies
Version:
A very quick fix for [**Zombie**](https://github.com/assaf/zombie) to permit to crawl correctly webpages with attributes on the html tag (eg: html lang="en").
1,141 lines (1,008 loc) • 33.2 kB
JavaScript
var Assert, BROWSER_FEATURES, BROWSER_OPTIONS, Browser, Console, Cookie, Cookies, Credentials, DEFAULT_FEATURES, DNSMask, Debug, EventEmitter, EventLoop, File, HTML, Interact, JSDOM_PATH, MOUSE_EVENT_NAMES, Mime, Path, PortMap, Promise, Resources, Storages, Tough, URL, XPathResult, assert, createTabs, debug, format, ms,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
__slice = [].slice;
Path = require("path");
JSDOM_PATH = require.resolve("jsdom");
assert = require("assert");
Assert = require("./assert");
createTabs = require("./tabs");
Console = require("./console");
Cookies = require("./cookies");
Debug = require("debug");
DNSMask = require("./dns_mask");
EventEmitter = require("events").EventEmitter;
EventLoop = require("./eventloop");
format = require("util").format;
File = require("fs");
Interact = require("./interact");
HTML = require("jsdom").defaultLevel;
Mime = require("mime");
ms = require("ms");
Promise = require("bluebird").Promise;
PortMap = require("./port_map");
Resources = require("./resources");
Storages = require("./storage");
Tough = require("tough-cookie");
Cookie = Tough.Cookie;
URL = require("url");
XPathResult = require("" + JSDOM_PATH + "/../jsdom/level3/xpath").XPathResult;
require("./jsdom_patches");
require("./forms");
require("./dom_focus");
require("./dom_iframe");
debug = Debug("zombie");
BROWSER_OPTIONS = ["features", "headers", "htmlParser", "waitDuration", "proxy", "referer", "silent", "site", "strictSSL", "userAgent", "maxRedirects", "language", "runScripts", "localAddress"];
BROWSER_FEATURES = ["scripts", "css", "img", "iframe"];
DEFAULT_FEATURES = "scripts no-css no-img iframe";
MOUSE_EVENT_NAMES = ["mousedown", "mousemove", "mouseup"];
Browser = (function(_super) {
__extends(Browser, _super);
function Browser(options) {
var browser, extension, name, _i, _j, _len, _len1, _ref;
if (options == null) {
options = {};
}
browser = this;
this.cookies = new Cookies();
this._storages = new Storages();
this._interact = Interact.use(this);
this._windowInScope = null;
this.assert = new Assert(this);
this.console = new Console(this);
this.on("console", function(level, message) {
if (browser.silent) {
return debug(">> " + message);
} else {
return console.log(message);
}
});
this.on("log", function() {
var args;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
return debug.apply(null, args);
});
this.referer = null;
this.resources = new Resources(this);
this.on("request", function(request) {});
this.on("response", function(request, response) {
return browser.log("" + (request.method || "GET") + " " + response.url + " => " + response.statusCode);
});
this.on("redirect", function(request, response, redirectRequest) {
return browser.log("" + (request.method || "GET") + " " + request.url + " => " + response.statusCode + " " + response.url);
});
this.on("loaded", function(document) {
return browser.log("Loaded document", document.location.href);
});
this.tabs = createTabs(this);
this.on("opened", function(window) {
return browser.log("Opened window", window.location.href, window.name || "");
});
this.on("closed", function(window) {
return browser.log("Closed window", window.location.href, window.name || "");
});
this.on("active", function(window) {
var element, onfocus;
onfocus = window.document.createEvent("HTMLEvents");
onfocus.initEvent("focus", false, false);
window.dispatchEvent(onfocus);
if (element = window.document.activeElement) {
onfocus = window.document.createEvent("HTMLEvents");
onfocus.initEvent("focus", false, false);
return element.dispatchEvent(onfocus);
}
});
this.on("inactive", function(window) {
var element, onblur;
if (element = window.document.activeElement) {
onblur = window.document.createEvent("HTMLEvents");
onblur.initEvent("blur", false, false);
element.dispatchEvent(onblur);
}
onblur = window.document.createEvent("HTMLEvents");
onblur.initEvent("blur", false, false);
return window.dispatchEvent(onblur);
});
this.eventLoop = new EventLoop(this);
this.errors = [];
this.on("error", (function(_this) {
return function(error) {
_this.errors.push(error);
return _this.log(error.message, error.stack);
};
})(this));
this.on("done", (function(_this) {
return function(timedOut) {
if (timedOut) {
return _this.log("Event loop timed out");
} else {
return _this.log("Event loop is empty");
}
};
})(this));
this.on("timeout", (function(_this) {
return function(fn, delay) {
return _this.log("Fired timeout after " + delay + "ms delay");
};
})(this));
this.on("interval", (function(_this) {
return function(fn, interval) {
return _this.log("Fired interval every " + interval + "ms");
};
})(this));
this.on("link", (function(_this) {
return function(url, target) {
return _this.log("Follow link to " + url);
};
})(this));
this.on("submit", (function(_this) {
return function(url, target) {
return _this.log("Submit form to " + url);
};
})(this));
for (_i = 0, _len = BROWSER_OPTIONS.length; _i < _len; _i++) {
name = BROWSER_OPTIONS[_i];
if (options.hasOwnProperty(name)) {
this[name] = options[name];
} else if (Browser["default"].hasOwnProperty(name)) {
this[name] = Browser["default"][name];
}
}
_ref = Browser._extensions;
for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
extension = _ref[_j];
extension(this);
}
}
Browser.extend = function(extension) {
return Browser._extensions.push(extension);
};
Browser._extensions = [];
Browser.prototype.hasFeature = function(name, ifMissing) {
var features;
if (ifMissing == null) {
ifMissing = true;
}
if (this.features) {
features = this.features.split(/\s+/);
if (~features.indexOf(name)) {
return true;
}
if (~features.indexOf("no-" + name)) {
return false;
}
}
return ifMissing;
};
Browser.prototype.withOptions = function(options, fn) {
var k, restore, v, _ref;
console.log("visit with options is deprecated and will be removed soon");
if (options) {
restore = {};
for (k in options) {
v = options[k];
if (~BROWSER_OPTIONS.indexOf(k)) {
_ref = [this[k], v], restore[k] = _ref[0], this[k] = _ref[1];
}
}
return (function(_this) {
return function() {
for (k in restore) {
v = restore[k];
_this[k] = v;
}
};
})(this);
} else {
return function() {};
}
};
Browser.prototype.fork = function() {
var forked, name, opt, _i, _len;
opt = {};
for (_i = 0, _len = BROWSER_OPTIONS.length; _i < _len; _i++) {
name = BROWSER_OPTIONS[_i];
opt[name] = this[name];
}
forked = Browser.create(opt);
forked.loadCookies(this.saveCookies());
forked.loadStorage(this.saveStorage());
forked.location = this.location.href;
return forked;
};
Browser.prototype.__defineGetter__("window", function() {
return this.tabs.current;
});
Browser.prototype.open = function(options) {
var name, referer, url;
if (options) {
url = options.url, name = options.name, referer = options.referer;
}
return this.tabs.open({
url: url,
name: name,
referer: referer
});
};
Browser.prototype.__defineGetter__("error", function() {
return this.errors[this.errors.length - 1];
});
Browser.prototype.wait = function(options, callback) {
var completionFunction, promise, waitDuration, _ref;
if (arguments.length === 1 && typeof options === "function") {
_ref = [options, null], callback = _ref[0], options = _ref[1];
}
assert(!callback || typeof callback === "function", "Second argument expected to be a callback function or null");
if (typeof options === "number") {
waitDuration = options;
} else if (typeof options === "string") {
waitDuration = options;
} else if (typeof options === "function") {
waitDuration = this.waitDuration;
completionFunction = options;
} else if (options) {
waitDuration = options.duration || this.waitDuration;
if (options.element) {
completionFunction = function(window) {
return !!window.document.querySelector(options.element);
};
} else {
completionFunction = options["function"];
}
} else {
waitDuration = this.waitDuration;
}
if (this.window) {
promise = this.eventLoop.wait(waitDuration, completionFunction);
} else {
promise = Promise.reject(new Error("No window open"));
}
if (callback) {
promise.done(callback, callback);
} else {
return promise;
}
};
Browser.prototype.waitForServer = function(options, callback) {
var promise, _ref;
assert(this.window, "No window open");
if (arguments.length === 1 && typeof options === "function") {
_ref = [options, null], callback = _ref[0], options = _ref[1];
}
promise = new Promise((function(_this) {
return function(resolve, reject) {
return _this.eventLoop.once("server", function() {
return resolve(_this.wait(options, null));
});
};
})(this));
if (callback) {
promise.done(callback, callback);
} else {
return promise;
}
};
Browser.prototype.fire = function(selector, eventName, callback) {
var event, eventType, target;
assert(this.window, "No window open");
target = this.query(selector);
assert(target && target.dispatchEvent, "No target element (note: call with selector/element, event name and callback)");
if (~MOUSE_EVENT_NAMES.indexOf(eventName)) {
eventType = "MouseEvents";
} else {
eventType = "HTMLEvents";
}
event = this.document.createEvent(eventType);
event.initEvent(eventName, true, true);
target.dispatchEvent(event);
if (callback !== false) {
return this.wait(callback);
}
};
Browser.prototype.click = function(selector, callback) {
return this.fire(selector, "click", callback);
};
Browser.prototype.dispatchEvent = function(selector, event) {
var target;
target = this.query(selector);
assert(this.window, "No window open");
return target.dispatchEvent(event);
};
Browser.prototype.queryAll = function(selector, context) {
var elements;
if (Array.isArray(selector)) {
return selector;
} else if (selector instanceof HTML.Element) {
return [selector];
} else if (selector) {
context || (context = this.document);
elements = context.querySelectorAll(selector);
return Array.prototype.slice.call(elements, 0);
} else {
return [];
}
};
Browser.prototype.query = function(selector, context) {
if (selector instanceof HTML.Element) {
return selector;
}
if (selector) {
context || (context = this.document);
return context.querySelector(selector);
} else {
return context;
}
};
Browser.prototype.$$ = function(selector, context) {
return this.query(selector, context);
};
Browser.prototype.querySelector = function(selector) {
return this.document.querySelector(selector);
};
Browser.prototype.querySelectorAll = function(selector) {
return this.document.querySelectorAll(selector);
};
Browser.prototype.text = function(selector, context) {
if (this.document.documentElement) {
return this.queryAll(selector || "html", context).map(function(e) {
return e.textContent;
}).join("").trim().replace(/\s+/g, " ");
} else if (this.source) {
return this.source.toString();
} else {
return "";
}
};
Browser.prototype.html = function(selector, context) {
if (this.document.documentElement) {
return this.queryAll(selector || "html", context).map(function(e) {
return e.outerHTML.trim();
}).join("");
} else if (this.source) {
return this.source.toString();
} else {
return "";
}
};
Browser.prototype.xpath = function(expression, context) {
return this.document.evaluate(expression, context || this.document.documentElement, null, XPathResult.ANY_TYPE);
};
Browser.prototype.__defineGetter__("document", function() {
if (this.window) {
return this.window.document;
}
});
Browser.prototype.__defineGetter__("body", function() {
return this.document.querySelector("body");
});
Browser.prototype.__defineGetter__("activeElement", function() {
return this.document.activeElement;
});
Browser.prototype.close = function(window) {
return this.tabs.close.apply(this.tabs, arguments);
};
Browser.prototype.destroy = function() {
if (this.tabs) {
this.tabs.closeAll();
return this.tabs = null;
}
};
Browser.prototype.visit = function(url, options, callback) {
var promise, resetOptions, site, _ref;
if (typeof options === "function" && !callback) {
_ref = [options, null], callback = _ref[0], options = _ref[1];
}
if (options) {
resetOptions = this.withOptions(options);
}
if (site = this.site) {
if (!/^(https?:|file:)/i.test(site)) {
site = "http://" + site;
}
url = URL.resolve(site, URL.parse(URL.format(url)));
}
if (this.window) {
this.tabs.close(this.window);
}
this.tabs.open({
url: url,
referer: this.referer
});
if (options) {
promise = this.wait(options)["finally"](resetOptions);
} else {
promise = this.wait(options);
}
if (callback) {
promise.done(callback, callback);
} else {
return promise;
}
};
Browser.prototype.load = function(html, callback) {
var promise;
this.location = "about:blank";
promise = this.wait().then((function(_this) {
return function() {
_this.errors = [];
_this.document.readyState = "loading";
_this.document.open();
_this.document.write(html);
_this.document.close();
return _this.wait;
};
})(this));
if (callback) {
promise.done(callback, callback);
} else {
return promise;
}
};
Browser.prototype.__defineGetter__("location", function() {
if (this.window) {
return this.window.location;
}
});
Browser.prototype.__defineSetter__("location", function(url) {
if (this.window) {
return this.window.location = url;
} else {
return this.open({
url: url
});
}
});
Browser.prototype.__defineGetter__("url", function() {
if (this.window) {
return URL.format(this.window.location);
}
});
Browser.prototype.link = function(selector) {
var error, link, _i, _len, _ref;
if (selector instanceof HTML.Element) {
return selector;
}
try {
link = this.querySelector(selector);
} catch (_error) {
error = _error;
link = null;
}
if (link && link.tagName === "A") {
return link;
}
_ref = this.querySelectorAll("body a");
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
link = _ref[_i];
if (link.textContent.trim() === selector) {
return link;
}
}
return null;
};
Browser.prototype.clickLink = function(selector, callback) {
var link;
link = this.link(selector);
assert(link, "No link matching '" + selector + "'");
return this.click(link, callback);
};
Browser.prototype.__defineGetter__("history", function() {
if (!this.window) {
this.open();
}
return this.window.history;
});
Browser.prototype.back = function(callback) {
this.window.history.back();
return this.wait(callback);
};
Browser.prototype.reload = function(callback) {
this.window.location.reload();
return this.wait(callback);
};
Browser.prototype.authenticate = function(host, create) {
var credentials, _ref;
if (create == null) {
create = true;
}
host || (host = "*");
credentials = (_ref = this._credentials) != null ? _ref[host] : void 0;
if (!credentials) {
if (create) {
credentials = new Credentials();
this._credentials || (this._credentials = {});
this._credentials[host] = credentials;
} else {
credentials = this.authenticate();
}
}
return credentials;
};
Browser.prototype.saveHistory = function() {
return this.window.history.save();
};
Browser.prototype.loadHistory = function(serialized) {
return this.window.history.load(serialized);
};
Browser.prototype.field = function(selector) {
var error, field, forAttr, label, _i, _j, _len, _len1, _ref, _ref1;
if (selector instanceof HTML.Element) {
return selector;
}
try {
field = this.query(selector);
if (field && (field.tagName === "INPUT" || field.tagName === "TEXTAREA" || field.tagName === "SELECT")) {
return field;
}
} catch (_error) {
error = _error;
}
_ref = this.queryAll("input[name],textarea[name],select[name]");
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
field = _ref[_i];
if (field.getAttribute("name") === selector) {
return field;
}
}
_ref1 = this.queryAll("label");
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
label = _ref1[_j];
if (label.textContent.trim() === selector) {
if (forAttr = label.getAttribute("for")) {
return this.document.getElementById(forAttr);
} else {
return label.querySelector("input,textarea,select");
}
}
}
};
Browser.prototype.focus = function(selector) {
var field;
field = this.field(selector) || this.query(selector);
assert(field, "No form field matching '" + selector + "'");
field.focus();
return this;
};
Browser.prototype.fill = function(selector, value) {
var field;
field = this.field(selector);
assert(field && (field.tagName === "TEXTAREA" || (field.tagName === "INPUT")), "No INPUT matching '" + selector + "'");
assert(!field.getAttribute("disabled"), "This INPUT field is disabled");
assert(!field.getAttribute("readonly"), "This INPUT field is readonly");
field.focus();
field.value = value;
this.fire(field, "input", false);
field.blur();
return this;
};
Browser.prototype._setCheckbox = function(selector, value) {
var field;
field = this.field(selector);
assert(field && field.tagName === "INPUT" && field.type === "checkbox", "No checkbox INPUT matching '" + selector + "'");
assert(!field.getAttribute("disabled"), "This INPUT field is disabled");
assert(!field.getAttribute("readonly"), "This INPUT field is readonly");
if (field.checked ^ value) {
field.click();
}
return this;
};
Browser.prototype.check = function(selector) {
return this._setCheckbox(selector, true);
};
Browser.prototype.uncheck = function(selector) {
return this._setCheckbox(selector, false);
};
Browser.prototype.choose = function(selector) {
var field;
field = this.field(selector) || this.field("input[type=radio][value=\"" + (escape(selector)) + "\"]");
assert(field && field.tagName === "INPUT" && field.type === "radio", "No radio INPUT matching '" + selector + "'");
field.click();
return this;
};
Browser.prototype._findOption = function(selector, value) {
var field, option, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2;
field = this.field(selector);
assert(field && field.tagName === "SELECT", "No SELECT matching '" + selector + "'");
assert(!field.getAttribute("disabled"), "This SELECT field is disabled");
assert(!field.getAttribute("readonly"), "This SELECT field is readonly");
_ref = field.options;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
option = _ref[_i];
if (option.value === value) {
return option;
}
}
_ref1 = field.options;
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
option = _ref1[_j];
if (option.label === value) {
return option;
}
}
_ref2 = field.options;
for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
option = _ref2[_k];
if (option.textContent.trim() === value) {
return option;
}
}
throw new Error("No OPTION '" + value + "'");
};
Browser.prototype.select = function(selector, value) {
var option;
option = this._findOption(selector, value);
this.selectOption(option);
return this;
};
Browser.prototype.selectOption = function(selector) {
var option, select;
option = this.query(selector);
if (option && !option.getAttribute("selected")) {
select = this.xpath("./ancestor::select", option).iterateNext();
option.setAttribute("selected", "selected");
select.focus();
this.fire(select, "change", false);
}
return this;
};
Browser.prototype.unselect = function(selector, value) {
var option;
option = this._findOption(selector, value);
this.unselectOption(option);
return this;
};
Browser.prototype.unselectOption = function(selector) {
var option, select;
option = this.query(selector);
if (option && option.getAttribute("selected")) {
select = this.xpath("./ancestor::select", option).iterateNext();
assert(select.multiple, "Cannot unselect in single select");
option.removeAttribute("selected");
select.focus();
this.fire(select, "change", false);
}
return this;
};
Browser.prototype.attach = function(selector, filename) {
var field, file, stat;
field = this.field(selector);
assert(field && field.tagName === "INPUT" && field.type === "file", "No file INPUT matching '" + selector + "'");
if (filename) {
stat = File.statSync(filename);
file = new this.window.File();
file.name = Path.basename(filename);
file.type = Mime.lookup(filename);
file.size = stat.size;
field.files || (field.files = []);
field.files.push(file);
field.value = filename;
}
field.focus();
this.fire(field, "change", false);
return this;
};
Browser.prototype.button = function(selector) {
var button, error, input, inputs, _i, _j, _k, _len, _len1, _len2, _ref;
if (selector instanceof HTML.Element) {
return selector;
}
try {
if (button = this.querySelector(selector)) {
if (button.tagName === "BUTTON" || button.tagName === "INPUT") {
return button;
}
}
} catch (_error) {
error = _error;
}
_ref = this.querySelectorAll("button");
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
button = _ref[_i];
if (button.textContent.trim() === selector) {
return button;
}
}
inputs = this.querySelectorAll("input[type=submit],button");
for (_j = 0, _len1 = inputs.length; _j < _len1; _j++) {
input = inputs[_j];
if (input.name === selector) {
return input;
}
}
for (_k = 0, _len2 = inputs.length; _k < _len2; _k++) {
input = inputs[_k];
if (input.value === selector) {
return input;
}
}
};
Browser.prototype.pressButton = function(selector, callback) {
var button;
assert(button = this.button(selector), "No BUTTON '" + selector + "'");
assert(!button.getAttribute("disabled"), "This button is disabled");
button.focus();
return this.fire(button, "click", callback);
};
Browser.prototype.getCookie = function(identifier, allProperties) {
var cookie;
identifier = this._cookieIdentifier(identifier);
assert(identifier.name, "Missing cookie name");
assert(identifier.domain, "No domain specified and no open page");
cookie = this.cookies.select(identifier)[0];
if (cookie) {
if (allProperties) {
return this._cookieProperties(cookie);
} else {
return cookie.value;
}
} else {
return null;
}
};
Browser.prototype.deleteCookie = function(identifier) {
var cookie;
identifier = this._cookieIdentifier(identifier);
assert(identifier.name, "Missing cookie name");
assert(identifier.domain, "No domain specified and no open page");
cookie = this.cookies.select(identifier)[0];
if (cookie) {
this.cookies["delete"](cookie);
return true;
} else {
return false;
}
};
Browser.prototype.setCookie = function(nameOrOptions, value) {
var domain, location;
if (location = this.location) {
domain = location.hostname;
}
if (typeof nameOrOptions === "string") {
this.cookies.set({
name: nameOrOptions,
value: value || "",
domain: domain,
path: "/",
secure: false,
httpOnly: false
});
} else {
assert(nameOrOptions.name, "Missing cookie name");
this.cookies.set({
name: nameOrOptions.name,
value: nameOrOptions.value || value || "",
domain: nameOrOptions.domain || domain,
path: nameOrOptions.path || "/",
secure: !!nameOrOptions.secure,
httpOnly: !!nameOrOptions.httpOnly,
expires: nameOrOptions.expires,
"max-age": nameOrOptions["max-age"]
});
}
};
Browser.prototype.deleteCookies = function() {
this.cookies.deleteAll();
};
Browser.prototype.saveCookies = function() {
var cookie, serialized, _i, _len, _ref;
serialized = ["# Saved on " + (new Date().toISOString())];
_ref = this.cookies.sort(Tough.cookieCompare);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
cookie = _ref[_i];
serialized.push(cookie.toString());
}
return serialized.join("\n") + "\n";
};
Browser.prototype.loadCookies = function(serialized) {
var line, _i, _len, _ref, _results;
_ref = serialized.split(/\n+/);
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
line = _ref[_i];
line = line.trim();
if (line[0] === "#" || line === "") {
continue;
}
_results.push(this.cookies.push(Cookie.parse(line)));
}
return _results;
};
Browser.prototype._cookieProperties = function(cookie) {
var properties;
properties = {
name: cookie.key,
value: cookie.value,
domain: cookie.domain,
path: cookie.path
};
if (cookie.secure) {
properties.secure = true;
}
if (cookie.httpOnly) {
properties.httpOnly = true;
}
if (cookie.expires && cookie.expires < Infinity) {
properties.expires = cookie.expires;
}
return properties;
};
Browser.prototype._cookieIdentifier = function(identifier) {
var domain, location, path;
location = this.location;
domain = location && location.hostname;
path = location && location.pathname || "/";
if (typeof identifier === "string") {
identifier = {
name: identifier,
domain: domain,
path: path
};
} else {
identifier = {
name: identifier.name,
domain: identifier.domain || domain,
path: identifier.path || path
};
}
return identifier;
};
Browser.prototype.localStorage = function(host) {
return this._storages.local(host);
};
Browser.prototype.sessionStorage = function(host) {
return this._storages.session(host);
};
Browser.prototype.saveStorage = function() {
return this._storages.save();
};
Browser.prototype.loadStorage = function(serialized) {
return this._storages.load(serialized);
};
Browser.prototype.evaluate = function(code, filename) {
if (!this.window) {
this.open();
}
return this.window._evaluate(code, filename);
};
Browser.prototype.onalert = function(fn) {
return this._interact.onalert(fn);
};
Browser.prototype.onconfirm = function(question, response) {
return this._interact.onconfirm(question, response);
};
Browser.prototype.onprompt = function(message, response) {
return this._interact.onprompt(message, response);
};
Browser.prototype.prompted = function(message) {
return this._interact.prompted(message);
};
Browser.prototype.__defineGetter__("statusCode", function() {
if (this.window && this.window._response) {
return this.window._response.statusCode;
} else {
return null;
}
});
Browser.prototype.__defineGetter__("success", function() {
var statusCode;
statusCode = this.statusCode;
return statusCode >= 200 && statusCode < 400;
});
Browser.prototype.__defineGetter__("redirected", function() {
return this.window && this.window._response && this.window._response.redirects > 0;
});
Browser.prototype.__defineGetter__("source", function() {
if (this.window && this.window._response) {
return this.window._response.body;
} else {
return null;
}
});
Browser.prototype.viewInBrowser = function(browser) {
return require("./bcat").bcat(this.html());
};
Browser.prototype.log = function() {
var args;
if (typeof arguments[0] === "function") {
args = [arguments[0]()];
} else {
args = arguments;
}
return this.emit("log", format.apply(null, args));
};
Browser.prototype.dump = function() {
var html, indent;
indent = function(lines) {
return lines.map(function(l) {
return " " + l + "\n";
}).join("");
};
process.stdout.write("Zombie: " + Browser.VERSION + "\n\n");
process.stdout.write("URL: " + this.window.location.href + "\n");
process.stdout.write("History:\n" + (indent(this.window.history.dump())) + "\n");
process.stdout.write("Cookies:\n" + (indent(this.cookies.dump())) + "\n");
process.stdout.write("Storage:\n" + (indent(this._storages.dump())) + "\n");
process.stdout.write("Eventloop:\n" + (indent(this.eventLoop.dump())) + "\n");
if (this.document) {
html = this.document.outerHTML;
if (html.length > 497) {
html = html.slice(0, 497) + "...";
}
return process.stdout.write("Document:\n" + (indent(html.split("\n"))) + "\n");
} else {
if (!this.document) {
return process.stdout.write("No document\n");
}
}
};
return Browser;
})(EventEmitter);
Browser.VERSION = JSON.parse(File.readFileSync("" + __dirname + "/../../package.json")).version;
Browser["default"] = {
features: DEFAULT_FEATURES,
htmlParser: null,
maxRedirects: 5,
proxy: null,
silent: false,
site: void 0,
strictSSL: false,
localAddress: '0.0.0.0',
userAgent: "Mozilla/5.0 Chrome/10.0.613.0 Safari/534.15 Zombie.js/" + Browser.VERSION,
language: "en-US",
waitDuration: "5s",
runScripts: true
};
Browser.create = function(options) {
return new Browser(options);
};
Browser.debug = function() {
if (!Debug.enabled("zombie")) {
Debug.enable("zombie");
return debug = Debug("zombie");
}
};
Browser.dns = new DNSMask();
Browser.ports = new PortMap();
Browser.localhost = function(hostname, port) {
Browser.dns.localhost(hostname);
Browser.ports.map(hostname, port);
if (!Browser["default"].site) {
return Browser["default"].site = hostname.replace(/^\*\./, "");
}
};
Credentials = (function() {
function Credentials() {}
Credentials.prototype.apply = function(headers) {
var base64;
switch (this.scheme) {
case "basic":
base64 = new Buffer(this.user + ":" + this.password).toString("base64");
return headers["authorization"] = "Basic " + base64;
case "bearer":
return headers["authorization"] = "Bearer " + this.token;
case "oauth":
return headers["authorization"] = "OAuth " + this.token;
}
};
Credentials.prototype.basic = function(user, password) {
this.user = user;
this.password = password;
return this.scheme = "basic";
};
Credentials.prototype.bearer = function(token) {
this.token = token;
return this.scheme = "bearer";
};
Credentials.prototype.oauth = function(token) {
this.token = token;
return this.scheme = "oauth";
};
Credentials.prototype.reset = function() {
delete this.scheme;
delete this.token;
delete this.user;
return delete this.password;
};
return Credentials;
})();
module.exports = Browser;