1
0
Fork 0
mirror of https://github.com/teampoltergeist/poltergeist.git synced 2022-11-09 12:05:00 -05:00

added javascript code to fire keyup/keydown/keypress/focus/blur events

This commit is contained in:
Dmitriy Nesteryuk 2012-04-28 00:54:47 +03:00
parent 479da435fa
commit 7cb46fbc3c
8 changed files with 430 additions and 73 deletions

View file

@ -7,8 +7,8 @@ class PoltergeistAgent
@windows = [] @windows = []
this.pushWindow(window) this.pushWindow(window)
externalCall: (name, arguments) -> externalCall: (name, args) ->
{ value: this[name].apply(this, arguments) } { value: this[name].apply(this, args) }
pushWindow: (new_window) -> pushWindow: (new_window) ->
@windows.push(new_window) @windows.push(new_window)
@ -55,10 +55,10 @@ class PoltergeistAgent
get: (id) -> get: (id) ->
@nodes[id] or= new PoltergeistAgent.Node(this, @elements[id]) @nodes[id] or= new PoltergeistAgent.Node(this, @elements[id])
nodeCall: (id, name, arguments) -> nodeCall: (id, name, args) ->
node = this.get(id) node = this.get(id)
throw new PoltergeistAgent.ObsoleteNode if node.isObsolete() throw new PoltergeistAgent.ObsoleteNode if node.isObsolete()
node[name].apply(node, arguments) node[name].apply(node, args)
class PoltergeistAgent.ObsoleteNode class PoltergeistAgent.ObsoleteNode
toString: -> "PoltergeistAgent.ObsoleteNode" toString: -> "PoltergeistAgent.ObsoleteNode"
@ -91,7 +91,28 @@ class PoltergeistAgent.Node
changed: -> changed: ->
event = document.createEvent('HTMLEvents') event = document.createEvent('HTMLEvents')
event.initEvent("change", true, false) event.initEvent('change', true, false)
@element.dispatchEvent(event)
keyupdowned: (eventName, keyCode) ->
event = document.createEvent('UIEvents')
event.initEvent(eventName, true, true)
event.keyCode = keyCode
event.which = keyCode
event.charCode = 0
@element.dispatchEvent(event)
keypressed: (altKey, ctrlKey, shiftKey, metaKey, keyCode, charCode) ->
event = document.createEvent('UIEvents')
event.initEvent('keypress', true, true)
event.window = @agent.window
event.altKey = altKey
event.ctrlKey = ctrlKey
event.shiftKey = shiftKey
event.metaKey = metaKey
event.keyCode = keyCode
event.charCode = charCode
event.which = keyCode
@element.dispatchEvent(event) @element.dispatchEvent(event)
insideBody: -> insideBody: ->
@ -130,8 +151,19 @@ class PoltergeistAgent.Node
if (@element.maxLength >= 0) if (@element.maxLength >= 0)
value = value.substr(0, @element.maxLength) value = value.substr(0, @element.maxLength)
@element.value = value @element.value = ''
this.trigger('focus')
for char in value
@element.value += char
keyCode = this.characterToKeyCode(char)
this.keyupdowned('keydown', keyCode)
this.keypressed(false, false, false, false, char.charCodeAt(0), char.charCodeAt(0))
this.keyupdowned('keyup', keyCode)
this.changed() this.changed()
this.trigger('blur')
isMultiple: -> isMultiple: ->
@element.multiple @element.multiple
@ -209,6 +241,45 @@ class PoltergeistAgent.Node
selector += ".#{className}" selector += ".#{className}"
selector selector
characterToKeyCode: (character) ->
code = character.toUpperCase().charCodeAt(0)
specialKeys =
96: 192 #`
45: 189 #-
61: 187 #=
91: 219 #[
93: 221 #]
92: 220 #\
59: 186 #;
39: 222 #'
44: 188 #,
46: 190 #.
47: 191 #/
127: 46 #delete
126: 192 #~
33: 49 #!
64: 50 #@
35: 51 ##
36: 52 #$
37: 53 #%
94: 54 #^
38: 55 #&
42: 56 #*
40: 57 #(
41: 48 #)
95: 189 #_
43: 187 #+
123: 219 #{
125: 221 #}
124: 220 #|
58: 186 #:
34: 222 #"
60: 188 #<
62: 190 #>
63: 191 #?
specialKeys[code] || code
window.__poltergeist = new PoltergeistAgent window.__poltergeist = new PoltergeistAgent
document.addEventListener( document.addEventListener(

View file

@ -1,101 +1,134 @@
// Generated by CoffeeScript 1.3.1
var PoltergeistAgent; var PoltergeistAgent;
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
PoltergeistAgent = (function() { PoltergeistAgent = (function() {
PoltergeistAgent.name = 'PoltergeistAgent';
function PoltergeistAgent() { function PoltergeistAgent() {
this.elements = []; this.elements = [];
this.nodes = {}; this.nodes = {};
this.windows = []; this.windows = [];
this.pushWindow(window); this.pushWindow(window);
} }
PoltergeistAgent.prototype.externalCall = function(name, arguments) {
PoltergeistAgent.prototype.externalCall = function(name, args) {
return { return {
value: this[name].apply(this, arguments) value: this[name].apply(this, args)
}; };
}; };
PoltergeistAgent.prototype.pushWindow = function(new_window) { PoltergeistAgent.prototype.pushWindow = function(new_window) {
this.windows.push(new_window); this.windows.push(new_window);
this.window = new_window; this.window = new_window;
this.document = this.window.document; this.document = this.window.document;
return null; return null;
}; };
PoltergeistAgent.prototype.popWindow = function() { PoltergeistAgent.prototype.popWindow = function() {
this.windows.pop(); this.windows.pop();
this.window = this.windows[this.windows.length - 1]; this.window = this.windows[this.windows.length - 1];
this.document = this.window.document; this.document = this.window.document;
return null; return null;
}; };
PoltergeistAgent.prototype.pushFrame = function(id) { PoltergeistAgent.prototype.pushFrame = function(id) {
return this.pushWindow(this.document.getElementById(id).contentWindow); return this.pushWindow(this.document.getElementById(id).contentWindow);
}; };
PoltergeistAgent.prototype.popFrame = function() { PoltergeistAgent.prototype.popFrame = function() {
return this.popWindow(); return this.popWindow();
}; };
PoltergeistAgent.prototype.currentUrl = function() { PoltergeistAgent.prototype.currentUrl = function() {
return window.location.toString(); return window.location.toString();
}; };
PoltergeistAgent.prototype.find = function(selector, within) { PoltergeistAgent.prototype.find = function(selector, within) {
var i, ids, results, _ref; var i, ids, results, _i, _ref;
if (within == null) { if (within == null) {
within = this.document; within = this.document;
} }
results = this.document.evaluate(selector, within, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); results = this.document.evaluate(selector, within, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
ids = []; ids = [];
for (i = 0, _ref = results.snapshotLength; 0 <= _ref ? i < _ref : i > _ref; 0 <= _ref ? i++ : i--) { for (i = _i = 0, _ref = results.snapshotLength; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
ids.push(this.register(results.snapshotItem(i))); ids.push(this.register(results.snapshotItem(i)));
} }
return ids; return ids;
}; };
PoltergeistAgent.prototype.register = function(element) { PoltergeistAgent.prototype.register = function(element) {
this.elements.push(element); this.elements.push(element);
return this.elements.length - 1; return this.elements.length - 1;
}; };
PoltergeistAgent.prototype.documentSize = function() { PoltergeistAgent.prototype.documentSize = function() {
return { return {
height: this.document.documentElement.scrollHeight, height: this.document.documentElement.scrollHeight,
width: this.document.documentElement.scrollWidth width: this.document.documentElement.scrollWidth
}; };
}; };
PoltergeistAgent.prototype.get = function(id) { PoltergeistAgent.prototype.get = function(id) {
var _base; var _base;
return (_base = this.nodes)[id] || (_base[id] = new PoltergeistAgent.Node(this, this.elements[id])); return (_base = this.nodes)[id] || (_base[id] = new PoltergeistAgent.Node(this, this.elements[id]));
}; };
PoltergeistAgent.prototype.nodeCall = function(id, name, arguments) {
PoltergeistAgent.prototype.nodeCall = function(id, name, args) {
var node; var node;
node = this.get(id); node = this.get(id);
if (node.isObsolete()) { if (node.isObsolete()) {
throw new PoltergeistAgent.ObsoleteNode; throw new PoltergeistAgent.ObsoleteNode;
} }
return node[name].apply(node, arguments); return node[name].apply(node, args);
}; };
return PoltergeistAgent; return PoltergeistAgent;
})(); })();
PoltergeistAgent.ObsoleteNode = (function() { PoltergeistAgent.ObsoleteNode = (function() {
ObsoleteNode.name = 'ObsoleteNode';
function ObsoleteNode() {} function ObsoleteNode() {}
ObsoleteNode.prototype.toString = function() { ObsoleteNode.prototype.toString = function() {
return "PoltergeistAgent.ObsoleteNode"; return "PoltergeistAgent.ObsoleteNode";
}; };
return ObsoleteNode; return ObsoleteNode;
})(); })();
PoltergeistAgent.Node = (function() { PoltergeistAgent.Node = (function() {
Node.name = 'Node';
Node.EVENTS = { Node.EVENTS = {
FOCUS: ['blur', 'focus', 'focusin', 'focusout'], FOCUS: ['blur', 'focus', 'focusin', 'focusout'],
MOUSE: ['click', 'dblclick', 'mousedown', 'mouseenter', 'mouseleave', 'mousemove', 'mouseover', 'mouseout', 'mouseup'] MOUSE: ['click', 'dblclick', 'mousedown', 'mouseenter', 'mouseleave', 'mousemove', 'mouseover', 'mouseout', 'mouseup']
}; };
function Node(agent, element) { function Node(agent, element) {
this.agent = agent; this.agent = agent;
this.element = element; this.element = element;
} }
Node.prototype.parentId = function() { Node.prototype.parentId = function() {
return this.agent.register(this.element.parentNode); return this.agent.register(this.element.parentNode);
}; };
Node.prototype.find = function(selector) { Node.prototype.find = function(selector) {
return this.agent.find(selector, this.element); return this.agent.find(selector, this.element);
}; };
Node.prototype.isObsolete = function() { Node.prototype.isObsolete = function() {
var obsolete; var obsolete,
obsolete = __bind(function(element) { _this = this;
obsolete = function(element) {
if (element.parentNode != null) { if (element.parentNode != null) {
if (element.parentNode === this.agent.document) { if (element.parentNode === _this.agent.document) {
return false; return false;
} else { } else {
return obsolete(element.parentNode); return obsolete(element.parentNode);
@ -103,20 +136,48 @@ PoltergeistAgent.Node = (function() {
} else { } else {
return true; return true;
} }
}, this); };
return obsolete(this.element); return obsolete(this.element);
}; };
Node.prototype.changed = function() { Node.prototype.changed = function() {
var event; var event;
event = document.createEvent('HTMLEvents'); event = document.createEvent('HTMLEvents');
event.initEvent("change", true, false); event.initEvent('change', true, false);
return this.element.dispatchEvent(event); return this.element.dispatchEvent(event);
}; };
Node.prototype.keyupdowned = function(eventName, keyCode) {
var event;
event = document.createEvent('UIEvents');
event.initEvent(eventName, true, true);
event.keyCode = keyCode;
event.which = keyCode;
event.charCode = 0;
return this.element.dispatchEvent(event);
};
Node.prototype.keypressed = function(altKey, ctrlKey, shiftKey, metaKey, keyCode, charCode) {
var event;
event = document.createEvent('UIEvents');
event.initEvent('keypress', true, true);
event.window = this.agent.window;
event.altKey = altKey;
event.ctrlKey = ctrlKey;
event.shiftKey = shiftKey;
event.metaKey = metaKey;
event.keyCode = keyCode;
event.charCode = charCode;
event.which = keyCode;
return this.element.dispatchEvent(event);
};
Node.prototype.insideBody = function() { Node.prototype.insideBody = function() {
return this.element === this.agent.document.body || this.agent.document.evaluate('ancestor::body', this.element, null, XPathResult.BOOLEAN_TYPE, null).booleanValue; return this.element === this.agent.document.body || this.agent.document.evaluate('ancestor::body', this.element, null, XPathResult.BOOLEAN_TYPE, null).booleanValue;
}; };
Node.prototype.text = function() { Node.prototype.text = function() {
var el, i, node, results, text, _ref; var el, i, node, results, text, _i, _ref;
if (!this.isVisible()) { if (!this.isVisible()) {
return ''; return '';
} }
@ -127,7 +188,7 @@ PoltergeistAgent.Node = (function() {
} }
results = this.agent.document.evaluate('.//text()[not(ancestor::script)]', el, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); results = this.agent.document.evaluate('.//text()[not(ancestor::script)]', el, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
text = ''; text = '';
for (i = 0, _ref = results.snapshotLength; 0 <= _ref ? i < _ref : i > _ref; 0 <= _ref ? i++ : i--) { for (i = _i = 0, _ref = results.snapshotLength; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
node = results.snapshotItem(i); node = results.snapshotItem(i);
if (this.isVisible(node.parentNode)) { if (this.isVisible(node.parentNode)) {
text += node.textContent; text += node.textContent;
@ -135,6 +196,7 @@ PoltergeistAgent.Node = (function() {
} }
return text; return text;
}; };
Node.prototype.getAttribute = function(name) { Node.prototype.getAttribute = function(name) {
if (name === 'checked' || name === 'selected') { if (name === 'checked' || name === 'selected') {
return this.element[name]; return this.element[name];
@ -142,6 +204,7 @@ PoltergeistAgent.Node = (function() {
return this.element.getAttribute(name); return this.element.getAttribute(name);
} }
}; };
Node.prototype.value = function() { Node.prototype.value = function() {
var option, _i, _len, _ref, _results; var option, _i, _len, _ref, _results;
if (this.element.tagName === 'SELECT' && this.element.multiple) { if (this.element.tagName === 'SELECT' && this.element.multiple) {
@ -158,22 +221,38 @@ PoltergeistAgent.Node = (function() {
return this.element.value; return this.element.value;
} }
}; };
Node.prototype.set = function(value) { Node.prototype.set = function(value) {
var char, keyCode, _i, _len;
if (this.element.maxLength >= 0) { if (this.element.maxLength >= 0) {
value = value.substr(0, this.element.maxLength); value = value.substr(0, this.element.maxLength);
} }
this.element.value = value; this.element.value = '';
return this.changed(); this.trigger('focus');
for (_i = 0, _len = value.length; _i < _len; _i++) {
char = value[_i];
this.element.value += char;
keyCode = this.characterToKeyCode(char);
this.keyupdowned('keydown', keyCode);
this.keypressed(false, false, false, false, char.charCodeAt(0), char.charCodeAt(0));
this.keyupdowned('keyup', keyCode);
}
this.changed();
return this.trigger('blur');
}; };
Node.prototype.isMultiple = function() { Node.prototype.isMultiple = function() {
return this.element.multiple; return this.element.multiple;
}; };
Node.prototype.setAttribute = function(name, value) { Node.prototype.setAttribute = function(name, value) {
return this.element.setAttribute(name, value); return this.element.setAttribute(name, value);
}; };
Node.prototype.removeAttribute = function(name) { Node.prototype.removeAttribute = function(name) {
return this.element.removeAttribute(name); return this.element.removeAttribute(name);
}; };
Node.prototype.select = function(value) { Node.prototype.select = function(value) {
if (value === false && !this.element.parentNode.multiple) { if (value === false && !this.element.parentNode.multiple) {
return false; return false;
@ -183,9 +262,11 @@ PoltergeistAgent.Node = (function() {
return true; return true;
} }
}; };
Node.prototype.tagName = function() { Node.prototype.tagName = function() {
return this.element.tagName; return this.element.tagName;
}; };
Node.prototype.isVisible = function(element) { Node.prototype.isVisible = function(element) {
if (!element) { if (!element) {
element = this.element; element = this.element;
@ -198,6 +279,7 @@ PoltergeistAgent.Node = (function() {
return true; return true;
} }
}; };
Node.prototype.position = function() { Node.prototype.position = function() {
var rect; var rect;
rect = this.element.getClientRects()[0]; rect = this.element.getClientRects()[0];
@ -210,6 +292,7 @@ PoltergeistAgent.Node = (function() {
height: rect.height height: rect.height
}; };
}; };
Node.prototype.trigger = function(name) { Node.prototype.trigger = function(name) {
var event; var event;
if (Node.EVENTS.MOUSE.indexOf(name) !== -1) { if (Node.EVENTS.MOUSE.indexOf(name) !== -1) {
@ -223,6 +306,7 @@ PoltergeistAgent.Node = (function() {
} }
return this.element.dispatchEvent(event); return this.element.dispatchEvent(event);
}; };
Node.prototype.clickTest = function(x, y) { Node.prototype.clickTest = function(x, y) {
var el, origEl; var el, origEl;
el = origEl = document.elementFromPoint(x, y); el = origEl = document.elementFromPoint(x, y);
@ -240,6 +324,7 @@ PoltergeistAgent.Node = (function() {
selector: origEl && this.getSelector(origEl) selector: origEl && this.getSelector(origEl)
}; };
}; };
Node.prototype.getSelector = function(el) { Node.prototype.getSelector = function(el) {
var className, selector, _i, _len, _ref; var className, selector, _i, _len, _ref;
selector = el.tagName !== 'HTML' ? this.getSelector(el.parentNode) + ' ' : ''; selector = el.tagName !== 'HTML' ? this.getSelector(el.parentNode) + ' ' : '';
@ -254,15 +339,62 @@ PoltergeistAgent.Node = (function() {
} }
return selector; return selector;
}; };
Node.prototype.characterToKeyCode = function(character) {
var code, specialKeys;
code = character.toUpperCase().charCodeAt(0);
specialKeys = {
96: 192,
45: 189,
61: 187,
91: 219,
93: 221,
92: 220,
59: 186,
39: 222,
44: 188,
46: 190,
47: 191,
127: 46,
126: 192,
33: 49,
64: 50,
35: 51,
36: 52,
37: 53,
94: 54,
38: 55,
42: 56,
40: 57,
41: 48,
95: 189,
43: 187,
123: 219,
125: 221,
124: 220,
58: 186,
34: 222,
60: 188,
62: 190,
63: 191
};
return specialKeys[code] || code;
};
return Node; return Node;
})(); })();
window.__poltergeist = new PoltergeistAgent; window.__poltergeist = new PoltergeistAgent;
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
return console.log('__DOMContentLoaded'); return console.log('__DOMContentLoaded');
}); });
window.confirm = function(message) { window.confirm = function(message) {
return true; return true;
}; };
window.prompt = function(message, _default) { window.prompt = function(message, _default) {
return _default || null; return _default || null;
}; };

View file

@ -1,31 +1,39 @@
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __slice = Array.prototype.slice; // Generated by CoffeeScript 1.3.1
var __slice = [].slice;
Poltergeist.Browser = (function() { Poltergeist.Browser = (function() {
Browser.name = 'Browser';
function Browser(owner) { function Browser(owner) {
this.owner = owner; this.owner = owner;
this.state = 'default'; this.state = 'default';
this.page_id = 0; this.page_id = 0;
this.resetPage(); this.resetPage();
} }
Browser.prototype.resetPage = function() { Browser.prototype.resetPage = function() {
var _this = this;
if (this.page != null) { if (this.page != null) {
this.page.release(); this.page.release();
} }
this.page = new Poltergeist.WebPage; this.page = new Poltergeist.WebPage;
this.page.onLoadStarted = __bind(function() { this.page.onLoadStarted = function() {
if (this.state === 'clicked') { if (_this.state === 'clicked') {
return this.state = 'loading'; return _this.state = 'loading';
} }
}, this); };
this.page.onLoadFinished = __bind(function(status) { this.page.onLoadFinished = function(status) {
if (this.state === 'loading') { if (_this.state === 'loading') {
this.sendResponse(status); _this.sendResponse(status);
return this.state = 'default'; return _this.state = 'default';
} }
}, this); };
return this.page.onInitialized = __bind(function() { return this.page.onInitialized = function() {
return this.page_id += 1; return _this.page_id += 1;
}, this); };
}; };
Browser.prototype.sendResponse = function(response) { Browser.prototype.sendResponse = function(response) {
var errors; var errors;
errors = this.page.errors(); errors = this.page.errors();
@ -36,6 +44,7 @@ Poltergeist.Browser = (function() {
return this.owner.sendResponse(response); return this.owner.sendResponse(response);
} }
}; };
Browser.prototype.getNode = function(page_id, id, callback) { Browser.prototype.getNode = function(page_id, id, callback) {
if (page_id === this.page_id) { if (page_id === this.page_id) {
return callback.call(this, this.page.get(id)); return callback.call(this, this.page.get(id));
@ -43,6 +52,7 @@ Poltergeist.Browser = (function() {
return this.owner.sendError(new Poltergeist.ObsoleteNode); return this.owner.sendError(new Poltergeist.ObsoleteNode);
} }
}; };
Browser.prototype.nodeCall = function() { Browser.prototype.nodeCall = function() {
var args, callback, fn, id, page_id; var args, callback, fn, id, page_id;
page_id = arguments[0], id = arguments[1], fn = arguments[2], args = 4 <= arguments.length ? __slice.call(arguments, 3) : []; page_id = arguments[0], id = arguments[1], fn = arguments[2], args = 4 <= arguments.length ? __slice.call(arguments, 3) : [];
@ -57,42 +67,53 @@ Poltergeist.Browser = (function() {
} }
}); });
}; };
Browser.prototype.visit = function(url) { Browser.prototype.visit = function(url) {
this.state = 'loading'; this.state = 'loading';
return this.page.open(url); return this.page.open(url);
}; };
Browser.prototype.current_url = function() { Browser.prototype.current_url = function() {
return this.sendResponse(this.page.currentUrl()); return this.sendResponse(this.page.currentUrl());
}; };
Browser.prototype.body = function() { Browser.prototype.body = function() {
return this.sendResponse(this.page.content()); return this.sendResponse(this.page.content());
}; };
Browser.prototype.source = function() { Browser.prototype.source = function() {
return this.sendResponse(this.page.source()); return this.sendResponse(this.page.source());
}; };
Browser.prototype.find = function(selector) { Browser.prototype.find = function(selector) {
return this.sendResponse({ return this.sendResponse({
page_id: this.page_id, page_id: this.page_id,
ids: this.page.find(selector) ids: this.page.find(selector)
}); });
}; };
Browser.prototype.find_within = function(page_id, id, selector) { Browser.prototype.find_within = function(page_id, id, selector) {
return this.nodeCall(page_id, id, 'find', selector, this.sendResponse); return this.nodeCall(page_id, id, 'find', selector, this.sendResponse);
}; };
Browser.prototype.text = function(page_id, id) { Browser.prototype.text = function(page_id, id) {
return this.nodeCall(page_id, id, 'text', this.sendResponse); return this.nodeCall(page_id, id, 'text', this.sendResponse);
}; };
Browser.prototype.attribute = function(page_id, id, name) { Browser.prototype.attribute = function(page_id, id, name) {
return this.nodeCall(page_id, id, 'getAttribute', name, this.sendResponse); return this.nodeCall(page_id, id, 'getAttribute', name, this.sendResponse);
}; };
Browser.prototype.value = function(page_id, id) { Browser.prototype.value = function(page_id, id) {
return this.nodeCall(page_id, id, 'value', this.sendResponse); return this.nodeCall(page_id, id, 'value', this.sendResponse);
}; };
Browser.prototype.set = function(page_id, id, value) { Browser.prototype.set = function(page_id, id, value) {
return this.nodeCall(page_id, id, 'set', value, function() { return this.nodeCall(page_id, id, 'set', value, function() {
return this.sendResponse(true); return this.sendResponse(true);
}); });
}; };
Browser.prototype.select_file = function(page_id, id, value) { Browser.prototype.select_file = function(page_id, id, value) {
return this.nodeCall(page_id, id, 'isMultiple', function(multiple, node) { return this.nodeCall(page_id, id, 'isMultiple', function(multiple, node) {
if (multiple) { if (multiple) {
@ -107,62 +128,75 @@ Poltergeist.Browser = (function() {
return this.sendResponse(true); return this.sendResponse(true);
}); });
}; };
Browser.prototype.select = function(page_id, id, value) { Browser.prototype.select = function(page_id, id, value) {
return this.nodeCall(page_id, id, 'select', value, this.sendResponse); return this.nodeCall(page_id, id, 'select', value, this.sendResponse);
}; };
Browser.prototype.tag_name = function(page_id, id) { Browser.prototype.tag_name = function(page_id, id) {
return this.nodeCall(page_id, id, 'tagName', this.sendResponse); return this.nodeCall(page_id, id, 'tagName', this.sendResponse);
}; };
Browser.prototype.visible = function(page_id, id) { Browser.prototype.visible = function(page_id, id) {
return this.nodeCall(page_id, id, 'isVisible', this.sendResponse); return this.nodeCall(page_id, id, 'isVisible', this.sendResponse);
}; };
Browser.prototype.evaluate = function(script) { Browser.prototype.evaluate = function(script) {
return this.sendResponse(JSON.parse(this.page.evaluate("function() { return JSON.stringify(" + script + ") }"))); return this.sendResponse(JSON.parse(this.page.evaluate("function() { return JSON.stringify(" + script + ") }")));
}; };
Browser.prototype.execute = function(script) { Browser.prototype.execute = function(script) {
this.page.execute("function() { " + script + " }"); this.page.execute("function() { " + script + " }");
return this.sendResponse(true); return this.sendResponse(true);
}; };
Browser.prototype.push_frame = function(id) { Browser.prototype.push_frame = function(id) {
this.page.pushFrame(id); this.page.pushFrame(id);
return this.sendResponse(true); return this.sendResponse(true);
}; };
Browser.prototype.pop_frame = function() { Browser.prototype.pop_frame = function() {
this.page.popFrame(); this.page.popFrame();
return this.sendResponse(true); return this.sendResponse(true);
}; };
Browser.prototype.click = function(page_id, id) { Browser.prototype.click = function(page_id, id) {
return this.nodeCall(page_id, id, 'isObsolete', function(obsolete, node) { return this.nodeCall(page_id, id, 'isObsolete', function(obsolete, node) {
var click; var click,
_this = this;
this.state = 'clicked'; this.state = 'clicked';
click = node.click(); click = node.click();
return setTimeout(__bind(function() { return setTimeout(function() {
if (this.state === 'clicked') { if (_this.state === 'clicked') {
this.state = 'default'; _this.state = 'default';
if (click instanceof Poltergeist.ClickFailed) { if (click instanceof Poltergeist.ClickFailed) {
return this.owner.sendError(click); return _this.owner.sendError(click);
} else { } else {
return this.sendResponse(true); return _this.sendResponse(true);
} }
} }
}, this), 10); }, 10);
}); });
}; };
Browser.prototype.drag = function(page_id, id, other_id) { Browser.prototype.drag = function(page_id, id, other_id) {
return this.nodeCall(page_id, id, 'isObsolete', function(obsolete, node) { return this.nodeCall(page_id, id, 'isObsolete', function(obsolete, node) {
node.dragTo(this.page.get(other_id)); node.dragTo(this.page.get(other_id));
return this.sendResponse(true); return this.sendResponse(true);
}); });
}; };
Browser.prototype.trigger = function(page_id, id, event) { Browser.prototype.trigger = function(page_id, id, event) {
return this.nodeCall(page_id, id, 'trigger', event, function() { return this.nodeCall(page_id, id, 'trigger', event, function() {
return this.sendResponse(event); return this.sendResponse(event);
}); });
}; };
Browser.prototype.reset = function() { Browser.prototype.reset = function() {
this.resetPage(); this.resetPage();
return this.sendResponse(true); return this.sendResponse(true);
}; };
Browser.prototype.render = function(path, full) { Browser.prototype.render = function(path, full) {
var dimensions, document, viewport; var dimensions, document, viewport;
dimensions = this.page.validatedDimensions(); dimensions = this.page.validatedDimensions();
@ -195,6 +229,7 @@ Poltergeist.Browser = (function() {
} }
return this.sendResponse(true); return this.sendResponse(true);
}; };
Browser.prototype.resize = function(width, height) { Browser.prototype.resize = function(width, height) {
this.page.setViewportSize({ this.page.setViewportSize({
width: width, width: width,
@ -202,9 +237,13 @@ Poltergeist.Browser = (function() {
}); });
return this.sendResponse(true); return this.sendResponse(true);
}; };
Browser.prototype.exit = function() { Browser.prototype.exit = function() {
return phantom.exit(); return phantom.exit();
}; };
Browser.prototype.noop = function() {}; Browser.prototype.noop = function() {};
return Browser; return Browser;
})();
})();

View file

@ -1,20 +1,30 @@
// Generated by CoffeeScript 1.3.1
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
Poltergeist.Connection = (function() { Poltergeist.Connection = (function() {
Connection.name = 'Connection';
function Connection(owner, port) { function Connection(owner, port) {
this.owner = owner; this.owner = owner;
this.port = port; this.port = port;
this.commandReceived = __bind(this.commandReceived, this); this.commandReceived = __bind(this.commandReceived, this);
this.socket = new WebSocket("ws://127.0.0.1:" + this.port + "/"); this.socket = new WebSocket("ws://127.0.0.1:" + this.port + "/");
this.socket.onmessage = this.commandReceived; this.socket.onmessage = this.commandReceived;
this.socket.onclose = function() { this.socket.onclose = function() {
return phantom.exit(); return phantom.exit();
}; };
} }
Connection.prototype.commandReceived = function(message) { Connection.prototype.commandReceived = function(message) {
return this.owner.runCommand(JSON.parse(message.data)); return this.owner.runCommand(JSON.parse(message.data));
}; };
Connection.prototype.send = function(message) { Connection.prototype.send = function(message) {
return this.socket.send(JSON.stringify(message)); return this.socket.send(JSON.stringify(message));
}; };
return Connection; return Connection;
})();
})();

View file

@ -1,15 +1,16 @@
var Poltergeist; // Generated by CoffeeScript 1.3.1
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { var Poltergeist,
for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
function ctor() { this.constructor = child; } __hasProp = {}.hasOwnProperty,
ctor.prototype = parent.prototype; __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; };
child.prototype = new ctor;
child.__super__ = parent.prototype;
return child;
};
Poltergeist = (function() { Poltergeist = (function() {
Poltergeist.name = 'Poltergeist';
function Poltergeist(port) { function Poltergeist(port) {
this.onError = __bind(this.onError, this); this.onError = __bind(this.onError, this);
var that; var that;
this.browser = new Poltergeist.Browser(this); this.browser = new Poltergeist.Browser(this);
this.connection = new Poltergeist.Connection(this, port); this.connection = new Poltergeist.Connection(this, port);
@ -19,15 +20,18 @@ Poltergeist = (function() {
}; };
this.running = false; this.running = false;
} }
Poltergeist.prototype.runCommand = function(command) { Poltergeist.prototype.runCommand = function(command) {
this.running = true; this.running = true;
return this.browser[command.name].apply(this.browser, command.args); return this.browser[command.name].apply(this.browser, command.args);
}; };
Poltergeist.prototype.sendResponse = function(response) { Poltergeist.prototype.sendResponse = function(response) {
return this.send({ return this.send({
response: response response: response
}); });
}; };
Poltergeist.prototype.sendError = function(error) { Poltergeist.prototype.sendError = function(error) {
return this.send({ return this.send({
error: { error: {
@ -36,6 +40,7 @@ Poltergeist = (function() {
} }
}); });
}; };
Poltergeist.prototype.onError = function(message, stack) { Poltergeist.prototype.onError = function(message, stack) {
if (message === 'PoltergeistAgent.ObsoleteNode') { if (message === 'PoltergeistAgent.ObsoleteNode') {
return this.sendError(new Poltergeist.ObsoleteNode); return this.sendError(new Poltergeist.ObsoleteNode);
@ -43,70 +48,122 @@ Poltergeist = (function() {
return this.sendError(new Poltergeist.BrowserError(message, stack)); return this.sendError(new Poltergeist.BrowserError(message, stack));
} }
}; };
Poltergeist.prototype.send = function(data) { Poltergeist.prototype.send = function(data) {
if (this.running) { if (this.running) {
this.connection.send(data); this.connection.send(data);
return this.running = false; return this.running = false;
} }
}; };
return Poltergeist; return Poltergeist;
})(); })();
window.Poltergeist = Poltergeist; window.Poltergeist = Poltergeist;
Poltergeist.Error = (function() { Poltergeist.Error = (function() {
Error.name = 'Error';
function Error() {} function Error() {}
return Error; return Error;
})(); })();
Poltergeist.ObsoleteNode = (function() {
__extends(ObsoleteNode, Poltergeist.Error); Poltergeist.ObsoleteNode = (function(_super) {
__extends(ObsoleteNode, _super);
ObsoleteNode.name = 'ObsoleteNode';
function ObsoleteNode() { function ObsoleteNode() {
ObsoleteNode.__super__.constructor.apply(this, arguments); return ObsoleteNode.__super__.constructor.apply(this, arguments);
} }
ObsoleteNode.prototype.name = "Poltergeist.ObsoleteNode"; ObsoleteNode.prototype.name = "Poltergeist.ObsoleteNode";
ObsoleteNode.prototype.args = function() { ObsoleteNode.prototype.args = function() {
return []; return [];
}; };
ObsoleteNode.prototype.toString = function() { ObsoleteNode.prototype.toString = function() {
return this.name; return this.name;
}; };
return ObsoleteNode; return ObsoleteNode;
})();
Poltergeist.ClickFailed = (function() { })(Poltergeist.Error);
__extends(ClickFailed, Poltergeist.Error);
Poltergeist.ClickFailed = (function(_super) {
__extends(ClickFailed, _super);
ClickFailed.name = 'ClickFailed';
function ClickFailed(selector, position) { function ClickFailed(selector, position) {
this.selector = selector; this.selector = selector;
this.position = position; this.position = position;
} }
ClickFailed.prototype.name = "Poltergeist.ClickFailed"; ClickFailed.prototype.name = "Poltergeist.ClickFailed";
ClickFailed.prototype.args = function() { ClickFailed.prototype.args = function() {
return [this.selector, this.position]; return [this.selector, this.position];
}; };
return ClickFailed; return ClickFailed;
})();
Poltergeist.JavascriptError = (function() { })(Poltergeist.Error);
__extends(JavascriptError, Poltergeist.Error);
Poltergeist.JavascriptError = (function(_super) {
__extends(JavascriptError, _super);
JavascriptError.name = 'JavascriptError';
function JavascriptError(errors) { function JavascriptError(errors) {
this.errors = errors; this.errors = errors;
} }
JavascriptError.prototype.name = "Poltergeist.JavascriptError"; JavascriptError.prototype.name = "Poltergeist.JavascriptError";
JavascriptError.prototype.args = function() { JavascriptError.prototype.args = function() {
return [this.errors]; return [this.errors];
}; };
return JavascriptError; return JavascriptError;
})();
Poltergeist.BrowserError = (function() { })(Poltergeist.Error);
__extends(BrowserError, Poltergeist.Error);
Poltergeist.BrowserError = (function(_super) {
__extends(BrowserError, _super);
BrowserError.name = 'BrowserError';
function BrowserError(message, stack) { function BrowserError(message, stack) {
this.message = message; this.message = message;
this.stack = stack; this.stack = stack;
} }
BrowserError.prototype.name = "Poltergeist.BrowserError"; BrowserError.prototype.name = "Poltergeist.BrowserError";
BrowserError.prototype.args = function() { BrowserError.prototype.args = function() {
return [this.message, this.stack]; return [this.message, this.stack];
}; };
return BrowserError; return BrowserError;
})();
})(Poltergeist.Error);
phantom.injectJs("" + phantom.libraryPath + "/web_page.js"); phantom.injectJs("" + phantom.libraryPath + "/web_page.js");
phantom.injectJs("" + phantom.libraryPath + "/node.js"); phantom.injectJs("" + phantom.libraryPath + "/node.js");
phantom.injectJs("" + phantom.libraryPath + "/connection.js"); phantom.injectJs("" + phantom.libraryPath + "/connection.js");
phantom.injectJs("" + phantom.libraryPath + "/browser.js"); phantom.injectJs("" + phantom.libraryPath + "/browser.js");
new Poltergeist(phantom.args[0]);
new Poltergeist(phantom.args[0]);

View file

@ -30,11 +30,34 @@ describe Capybara::Session do
end end
describe 'Node#set' do describe 'Node#set' do
it 'should fire the change event' do before do
@session.visit('/poltergeist/with_js') @session.visit('/poltergeist/with_js')
@session.find(:css, '#change_me').set("Hello!") @session.find(:css, '#change_me').set("Hello!")
end
it 'should fire the change event' do
@session.find(:css, '#changes').text.should == "Hello!" @session.find(:css, '#changes').text.should == "Hello!"
end end
it 'should fire the keydown event' do
@session.find(:css, '#changes_on_keydown').text.should == "6"
end
it 'should fire the keyup event' do
@session.find(:css, '#changes_on_keyup').text.should == "6"
end
it 'should fire the keypress event' do
@session.find(:css, '#changes_on_keypress').text.should == "6"
end
it 'should fire the focus event' do
@session.find(:css, '#changes_on_focus').text.should == "Focus"
end
it 'should fire the blur event' do
@session.find(:css, '#changes_on_blur').text.should == "Blur"
end
end end
it 'should support running multiple sessions at once' do it 'should support running multiple sessions at once' do

View file

@ -3,7 +3,27 @@ $(function() {
$('#remove_me').remove() $('#remove_me').remove()
}) })
$('#change_me').change(function(event) { var increment = function(index, oldText) {
$('#changes').text($('#change_me').val()) return parseInt(oldText || 0) + 1;
}) }
$('#change_me')
.change(function(event) {
$('#changes').text($(this).val())
})
.keydown(function(event) {
$('#changes_on_keydown').text(increment)
})
.keyup(function(event) {
$('#changes_on_keyup').text(increment)
})
.keypress(function() {
$('#changes_on_keypress').text(increment)
})
.focus(function(event) {
$('#changes_on_focus').text('Focus')
})
.blur(function() {
$('#changes_on_blur').text('Blur')
})
}) })

View file

@ -13,5 +13,10 @@
<p><input type="text" id="change_me"></p> <p><input type="text" id="change_me"></p>
<p id="changes"></p> <p id="changes"></p>
<p id="changes_on_keydown"></p>
<p id="changes_on_keyup"></p>
<p id="changes_on_focus"></p>
<p id="changes_on_blur"></p>
<p id="changes_on_keypress"></p>
</body> </body>
</html> </html>