poltergeist 1.1.2 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +50 -21
- data/lib/capybara/poltergeist.rb +1 -0
- data/lib/capybara/poltergeist/browser.rb +39 -15
- data/lib/capybara/poltergeist/client.rb +11 -7
- data/lib/capybara/poltergeist/client/agent.coffee +104 -19
- data/lib/capybara/poltergeist/client/browser.coffee +34 -18
- data/lib/capybara/poltergeist/client/compiled/agent.js +154 -26
- data/lib/capybara/poltergeist/client/compiled/browser.js +54 -22
- data/lib/capybara/poltergeist/client/compiled/connection.js +0 -2
- data/lib/capybara/poltergeist/client/compiled/main.js +32 -15
- data/lib/capybara/poltergeist/client/compiled/node.js +13 -19
- data/lib/capybara/poltergeist/client/compiled/web_page.js +19 -5
- data/lib/capybara/poltergeist/client/main.coffee +9 -4
- data/lib/capybara/poltergeist/client/node.coffee +11 -19
- data/lib/capybara/poltergeist/client/web_page.coffee +4 -5
- data/lib/capybara/poltergeist/driver.rb +15 -3
- data/lib/capybara/poltergeist/errors.rb +20 -5
- data/lib/capybara/poltergeist/node.rb +32 -6
- data/lib/capybara/poltergeist/utility.rb +9 -0
- data/lib/capybara/poltergeist/version.rb +1 -1
- metadata +14 -7
@@ -1,12 +1,10 @@
|
|
1
1
|
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
2
2
|
|
3
3
|
Poltergeist.Connection = (function() {
|
4
|
-
|
5
4
|
function Connection(owner, port) {
|
6
5
|
this.owner = owner;
|
7
6
|
this.port = port;
|
8
7
|
this.commandReceived = __bind(this.commandReceived, this);
|
9
|
-
|
10
8
|
this.socket = new WebSocket("ws://127.0.0.1:" + this.port + "/");
|
11
9
|
this.socket.onmessage = this.commandReceived;
|
12
10
|
this.socket.onclose = function() {
|
@@ -1,11 +1,11 @@
|
|
1
|
-
var Poltergeist,
|
1
|
+
var Poltergeist, _ref,
|
2
2
|
__hasProp = {}.hasOwnProperty,
|
3
3
|
__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; };
|
4
4
|
|
5
5
|
Poltergeist = (function() {
|
6
|
-
|
7
6
|
function Poltergeist(port, width, height) {
|
8
7
|
var that;
|
8
|
+
|
9
9
|
this.browser = new Poltergeist.Browser(this, width, height);
|
10
10
|
this.connection = new Poltergeist.Connection(this, port);
|
11
11
|
that = this;
|
@@ -16,10 +16,13 @@ Poltergeist = (function() {
|
|
16
16
|
}
|
17
17
|
|
18
18
|
Poltergeist.prototype.runCommand = function(command) {
|
19
|
+
var error;
|
20
|
+
|
19
21
|
this.running = true;
|
20
22
|
try {
|
21
23
|
return this.browser[command.name].apply(this.browser, command.args);
|
22
|
-
} catch (
|
24
|
+
} catch (_error) {
|
25
|
+
error = _error;
|
23
26
|
if (error instanceof Poltergeist.Error) {
|
24
27
|
return this.sendError(error);
|
25
28
|
} else {
|
@@ -57,7 +60,6 @@ Poltergeist = (function() {
|
|
57
60
|
window.Poltergeist = Poltergeist;
|
58
61
|
|
59
62
|
Poltergeist.Error = (function() {
|
60
|
-
|
61
63
|
function Error() {}
|
62
64
|
|
63
65
|
return Error;
|
@@ -65,11 +67,11 @@ Poltergeist.Error = (function() {
|
|
65
67
|
})();
|
66
68
|
|
67
69
|
Poltergeist.ObsoleteNode = (function(_super) {
|
68
|
-
|
69
70
|
__extends(ObsoleteNode, _super);
|
70
71
|
|
71
72
|
function ObsoleteNode() {
|
72
|
-
|
73
|
+
_ref = ObsoleteNode.__super__.constructor.apply(this, arguments);
|
74
|
+
return _ref;
|
73
75
|
}
|
74
76
|
|
75
77
|
ObsoleteNode.prototype.name = "Poltergeist.ObsoleteNode";
|
@@ -86,27 +88,43 @@ Poltergeist.ObsoleteNode = (function(_super) {
|
|
86
88
|
|
87
89
|
})(Poltergeist.Error);
|
88
90
|
|
89
|
-
Poltergeist.
|
91
|
+
Poltergeist.FrameNotFound = (function(_super) {
|
92
|
+
__extends(FrameNotFound, _super);
|
93
|
+
|
94
|
+
function FrameNotFound(frameName) {
|
95
|
+
this.frameName = frameName;
|
96
|
+
}
|
90
97
|
|
91
|
-
|
98
|
+
FrameNotFound.prototype.name = "Poltergeist.FrameNotFound";
|
92
99
|
|
93
|
-
function
|
100
|
+
FrameNotFound.prototype.args = function() {
|
101
|
+
return [this.frameName];
|
102
|
+
};
|
103
|
+
|
104
|
+
return FrameNotFound;
|
105
|
+
|
106
|
+
})(Poltergeist.Error);
|
107
|
+
|
108
|
+
Poltergeist.MouseEventFailed = (function(_super) {
|
109
|
+
__extends(MouseEventFailed, _super);
|
110
|
+
|
111
|
+
function MouseEventFailed(eventName, selector, position) {
|
112
|
+
this.eventName = eventName;
|
94
113
|
this.selector = selector;
|
95
114
|
this.position = position;
|
96
115
|
}
|
97
116
|
|
98
|
-
|
117
|
+
MouseEventFailed.prototype.name = "Poltergeist.MouseEventFailed";
|
99
118
|
|
100
|
-
|
101
|
-
return [this.selector, this.position];
|
119
|
+
MouseEventFailed.prototype.args = function() {
|
120
|
+
return [this.eventName, this.selector, this.position];
|
102
121
|
};
|
103
122
|
|
104
|
-
return
|
123
|
+
return MouseEventFailed;
|
105
124
|
|
106
125
|
})(Poltergeist.Error);
|
107
126
|
|
108
127
|
Poltergeist.JavascriptError = (function(_super) {
|
109
|
-
|
110
128
|
__extends(JavascriptError, _super);
|
111
129
|
|
112
130
|
function JavascriptError(errors) {
|
@@ -124,7 +142,6 @@ Poltergeist.JavascriptError = (function(_super) {
|
|
124
142
|
})(Poltergeist.Error);
|
125
143
|
|
126
144
|
Poltergeist.BrowserError = (function(_super) {
|
127
|
-
|
128
145
|
__extends(BrowserError, _super);
|
129
146
|
|
130
147
|
function BrowserError(message, stack) {
|
@@ -4,7 +4,7 @@ Poltergeist.Node = (function() {
|
|
4
4
|
var name, _fn, _i, _len, _ref,
|
5
5
|
_this = this;
|
6
6
|
|
7
|
-
Node.DELEGATES = ['
|
7
|
+
Node.DELEGATES = ['allText', 'visibleText', 'getAttribute', 'value', 'set', 'setAttribute', 'isObsolete', 'removeAttribute', 'isMultiple', 'select', 'tagName', 'find', 'isVisible', 'position', 'trigger', 'parentId', 'mouseEventTest', 'scrollIntoView', 'isDOMEqual', 'isDisabled'];
|
8
8
|
|
9
9
|
function Node(page, id) {
|
10
10
|
this.page = page;
|
@@ -19,6 +19,7 @@ Poltergeist.Node = (function() {
|
|
19
19
|
_fn = function(name) {
|
20
20
|
return Node.prototype[name] = function() {
|
21
21
|
var args;
|
22
|
+
|
22
23
|
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
23
24
|
return this.page.nodeCall(this.id, name, args);
|
24
25
|
};
|
@@ -28,8 +29,9 @@ Poltergeist.Node = (function() {
|
|
28
29
|
_fn(name);
|
29
30
|
}
|
30
31
|
|
31
|
-
Node.prototype.
|
32
|
+
Node.prototype.mouseEventPosition = function() {
|
32
33
|
var middle, pos, viewport;
|
34
|
+
|
33
35
|
viewport = this.page.viewportSize();
|
34
36
|
pos = this.position();
|
35
37
|
middle = function(start, end, size) {
|
@@ -41,27 +43,26 @@ Poltergeist.Node = (function() {
|
|
41
43
|
};
|
42
44
|
};
|
43
45
|
|
44
|
-
Node.prototype.
|
46
|
+
Node.prototype.mouseEvent = function(name) {
|
45
47
|
var pos, test;
|
46
|
-
|
47
|
-
event = 'click';
|
48
|
-
}
|
48
|
+
|
49
49
|
this.scrollIntoView();
|
50
|
-
pos = this.
|
51
|
-
test = this.
|
50
|
+
pos = this.mouseEventPosition();
|
51
|
+
test = this.mouseEventTest(pos.x, pos.y);
|
52
52
|
if (test.status === 'success') {
|
53
|
-
this.page.mouseEvent(
|
53
|
+
this.page.mouseEvent(name, pos.x, pos.y);
|
54
54
|
return pos;
|
55
55
|
} else {
|
56
|
-
throw new Poltergeist.
|
56
|
+
throw new Poltergeist.MouseEventFailed(name, test.selector, pos);
|
57
57
|
}
|
58
58
|
};
|
59
59
|
|
60
60
|
Node.prototype.dragTo = function(other) {
|
61
61
|
var otherPosition, position;
|
62
|
+
|
62
63
|
this.scrollIntoView();
|
63
|
-
position = this.
|
64
|
-
otherPosition = other.
|
64
|
+
position = this.mouseEventPosition();
|
65
|
+
otherPosition = other.mouseEventPosition();
|
65
66
|
this.page.mouseEvent('mousedown', position.x, position.y);
|
66
67
|
return this.page.mouseEvent('mouseup', otherPosition.x, otherPosition.y);
|
67
68
|
};
|
@@ -70,13 +71,6 @@ Poltergeist.Node = (function() {
|
|
70
71
|
return this.page === other.page && this.isDOMEqual(other.id);
|
71
72
|
};
|
72
73
|
|
73
|
-
Node.prototype.set = function(value) {
|
74
|
-
this.focusAndHighlight();
|
75
|
-
this.page.sendEvent('keypress', 16777219);
|
76
|
-
this.page.sendEvent('keypress', value.toString());
|
77
|
-
return this.blur();
|
78
|
-
};
|
79
|
-
|
80
74
|
return Node;
|
81
75
|
|
82
76
|
}).call(this);
|
@@ -14,6 +14,7 @@ Poltergeist.WebPage = (function() {
|
|
14
14
|
|
15
15
|
function WebPage(_native) {
|
16
16
|
var callback, _i, _len, _ref;
|
17
|
+
|
17
18
|
this["native"] = _native;
|
18
19
|
this["native"] || (this["native"] = require('webpage').create());
|
19
20
|
this._source = "";
|
@@ -32,6 +33,7 @@ Poltergeist.WebPage = (function() {
|
|
32
33
|
_fn = function(command) {
|
33
34
|
return WebPage.prototype[command] = function() {
|
34
35
|
var args;
|
36
|
+
|
35
37
|
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
36
38
|
return this.runCommand(command, args);
|
37
39
|
};
|
@@ -63,6 +65,7 @@ Poltergeist.WebPage = (function() {
|
|
63
65
|
|
64
66
|
WebPage.prototype.injectAgent = function() {
|
65
67
|
var extension, _k, _len2, _ref2, _results;
|
68
|
+
|
66
69
|
if (this["native"].evaluate(function() {
|
67
70
|
return typeof __poltergeist;
|
68
71
|
}) === "undefined") {
|
@@ -103,6 +106,7 @@ Poltergeist.WebPage = (function() {
|
|
103
106
|
|
104
107
|
WebPage.prototype.onErrorNative = function(message, stack) {
|
105
108
|
var stackString;
|
109
|
+
|
106
110
|
stackString = message;
|
107
111
|
stack.forEach(function(frame) {
|
108
112
|
stackString += "\n";
|
@@ -131,6 +135,7 @@ Poltergeist.WebPage = (function() {
|
|
131
135
|
|
132
136
|
WebPage.prototype.onResourceReceivedNative = function(response) {
|
133
137
|
var _ref2;
|
138
|
+
|
134
139
|
if ((_ref2 = this._networkTraffic[response.id]) != null) {
|
135
140
|
_ref2.responseParts.push(response);
|
136
141
|
}
|
@@ -156,6 +161,10 @@ Poltergeist.WebPage = (function() {
|
|
156
161
|
return this._source;
|
157
162
|
};
|
158
163
|
|
164
|
+
WebPage.prototype.title = function() {
|
165
|
+
return this["native"].frameTitle;
|
166
|
+
};
|
167
|
+
|
159
168
|
WebPage.prototype.errors = function() {
|
160
169
|
return this._errors;
|
161
170
|
};
|
@@ -170,6 +179,7 @@ Poltergeist.WebPage = (function() {
|
|
170
179
|
|
171
180
|
WebPage.prototype.responseHeaders = function() {
|
172
181
|
var headers;
|
182
|
+
|
173
183
|
headers = {};
|
174
184
|
this._responseHeaders.forEach(function(item) {
|
175
185
|
return headers[item.name] = item.value;
|
@@ -228,15 +238,12 @@ Poltergeist.WebPage = (function() {
|
|
228
238
|
|
229
239
|
WebPage.prototype.popFrame = function() {
|
230
240
|
this.frames.pop();
|
231
|
-
|
232
|
-
return this["native"].switchToMainFrame();
|
233
|
-
} else {
|
234
|
-
return this["native"].switchToFrame(this.frames[this.frames.length - 1]);
|
235
|
-
}
|
241
|
+
return this["native"].switchToParentFrame();
|
236
242
|
};
|
237
243
|
|
238
244
|
WebPage.prototype.getPage = function(name) {
|
239
245
|
var page;
|
246
|
+
|
240
247
|
if (this.sub_pages[name]) {
|
241
248
|
return this.sub_pages[name];
|
242
249
|
} else {
|
@@ -249,6 +256,7 @@ Poltergeist.WebPage = (function() {
|
|
249
256
|
|
250
257
|
WebPage.prototype.dimensions = function() {
|
251
258
|
var scroll, viewport;
|
259
|
+
|
252
260
|
scroll = this.scrollPosition();
|
253
261
|
viewport = this.viewportSize();
|
254
262
|
return {
|
@@ -263,6 +271,7 @@ Poltergeist.WebPage = (function() {
|
|
263
271
|
|
264
272
|
WebPage.prototype.validatedDimensions = function() {
|
265
273
|
var dimensions, document;
|
274
|
+
|
266
275
|
dimensions = this.dimensions();
|
267
276
|
document = dimensions.document;
|
268
277
|
if (dimensions.right > document.width) {
|
@@ -291,6 +300,7 @@ Poltergeist.WebPage = (function() {
|
|
291
300
|
|
292
301
|
WebPage.prototype.evaluate = function() {
|
293
302
|
var args, fn;
|
303
|
+
|
294
304
|
fn = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
|
295
305
|
this.injectAgent();
|
296
306
|
return JSON.parse(this["native"].evaluate("function() { return PoltergeistAgent.stringify(" + (this.stringifyCall(fn, args)) + ") }"));
|
@@ -298,6 +308,7 @@ Poltergeist.WebPage = (function() {
|
|
298
308
|
|
299
309
|
WebPage.prototype.execute = function() {
|
300
310
|
var args, fn;
|
311
|
+
|
301
312
|
fn = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
|
302
313
|
return this["native"].evaluate("function() { " + (this.stringifyCall(fn, args)) + " }");
|
303
314
|
};
|
@@ -312,9 +323,11 @@ Poltergeist.WebPage = (function() {
|
|
312
323
|
|
313
324
|
WebPage.prototype.bindCallback = function(name) {
|
314
325
|
var that;
|
326
|
+
|
315
327
|
that = this;
|
316
328
|
return this["native"][name] = function() {
|
317
329
|
var result;
|
330
|
+
|
318
331
|
if (that[name + 'Native'] != null) {
|
319
332
|
result = that[name + 'Native'].apply(that, arguments);
|
320
333
|
}
|
@@ -326,6 +339,7 @@ Poltergeist.WebPage = (function() {
|
|
326
339
|
|
327
340
|
WebPage.prototype.runCommand = function(name, args) {
|
328
341
|
var result;
|
342
|
+
|
329
343
|
result = this.evaluate(function(name, args) {
|
330
344
|
return __poltergeist.externalCall(name, args);
|
331
345
|
}, name, args);
|
@@ -50,10 +50,15 @@ class Poltergeist.ObsoleteNode extends Poltergeist.Error
|
|
50
50
|
args: -> []
|
51
51
|
toString: -> this.name
|
52
52
|
|
53
|
-
class Poltergeist.
|
54
|
-
constructor: (@
|
55
|
-
name: "Poltergeist.
|
56
|
-
args: -> [@
|
53
|
+
class Poltergeist.FrameNotFound extends Poltergeist.Error
|
54
|
+
constructor: (@frameName) ->
|
55
|
+
name: "Poltergeist.FrameNotFound"
|
56
|
+
args: -> [@frameName]
|
57
|
+
|
58
|
+
class Poltergeist.MouseEventFailed extends Poltergeist.Error
|
59
|
+
constructor: (@eventName, @selector, @position) ->
|
60
|
+
name: "Poltergeist.MouseEventFailed"
|
61
|
+
args: -> [@eventName, @selector, @position]
|
57
62
|
|
58
63
|
class Poltergeist.JavascriptError extends Poltergeist.Error
|
59
64
|
constructor: (@errors) ->
|
@@ -1,10 +1,10 @@
|
|
1
1
|
# Proxy object for forwarding method calls to the node object inside the page.
|
2
2
|
|
3
3
|
class Poltergeist.Node
|
4
|
-
@DELEGATES = ['
|
4
|
+
@DELEGATES = ['allText', 'visibleText', 'getAttribute', 'value', 'set', 'setAttribute', 'isObsolete',
|
5
5
|
'removeAttribute', 'isMultiple', 'select', 'tagName', 'find',
|
6
|
-
'isVisible', 'position', 'trigger', 'parentId', '
|
7
|
-
'scrollIntoView', 'isDOMEqual', '
|
6
|
+
'isVisible', 'position', 'trigger', 'parentId', 'mouseEventTest',
|
7
|
+
'scrollIntoView', 'isDOMEqual', 'isDisabled']
|
8
8
|
|
9
9
|
constructor: (@page, @id) ->
|
10
10
|
|
@@ -16,7 +16,7 @@ class Poltergeist.Node
|
|
16
16
|
this.prototype[name] = (args...) ->
|
17
17
|
@page.nodeCall(@id, name, args)
|
18
18
|
|
19
|
-
|
19
|
+
mouseEventPosition: ->
|
20
20
|
viewport = @page.viewportSize()
|
21
21
|
pos = this.position()
|
22
22
|
|
@@ -28,34 +28,26 @@ class Poltergeist.Node
|
|
28
28
|
y: middle(pos.top, pos.bottom, viewport.height)
|
29
29
|
}
|
30
30
|
|
31
|
-
|
31
|
+
mouseEvent: (name) ->
|
32
32
|
this.scrollIntoView()
|
33
33
|
|
34
|
-
pos = this.
|
35
|
-
test = this.
|
34
|
+
pos = this.mouseEventPosition()
|
35
|
+
test = this.mouseEventTest(pos.x, pos.y)
|
36
36
|
|
37
37
|
if test.status == 'success'
|
38
|
-
@page.mouseEvent(
|
38
|
+
@page.mouseEvent(name, pos.x, pos.y)
|
39
39
|
pos
|
40
40
|
else
|
41
|
-
throw new Poltergeist.
|
41
|
+
throw new Poltergeist.MouseEventFailed(name, test.selector, pos)
|
42
42
|
|
43
43
|
dragTo: (other) ->
|
44
44
|
this.scrollIntoView()
|
45
45
|
|
46
|
-
position = this.
|
47
|
-
otherPosition = other.
|
46
|
+
position = this.mouseEventPosition()
|
47
|
+
otherPosition = other.mouseEventPosition()
|
48
48
|
|
49
49
|
@page.mouseEvent('mousedown', position.x, position.y)
|
50
50
|
@page.mouseEvent('mouseup', otherPosition.x, otherPosition.y)
|
51
51
|
|
52
52
|
isEqual: (other) ->
|
53
53
|
@page == other.page && this.isDOMEqual(other.id)
|
54
|
-
|
55
|
-
set: (value) ->
|
56
|
-
this.focusAndHighlight()
|
57
|
-
# Sending backspace to clear the input
|
58
|
-
# keycode from: https://github.com/ariya/phantomjs/commit/cab2635e66d74b7e665c44400b8b20a8f225153a#L0R370
|
59
|
-
@page.sendEvent('keypress', 16777219)
|
60
|
-
@page.sendEvent('keypress', value.toString())
|
61
|
-
this.blur()
|
@@ -101,6 +101,9 @@ class Poltergeist.WebPage
|
|
101
101
|
source: ->
|
102
102
|
@_source
|
103
103
|
|
104
|
+
title: ->
|
105
|
+
@native.frameTitle
|
106
|
+
|
104
107
|
errors: ->
|
105
108
|
@_errors
|
106
109
|
|
@@ -155,11 +158,7 @@ class Poltergeist.WebPage
|
|
155
158
|
|
156
159
|
popFrame: ->
|
157
160
|
@frames.pop()
|
158
|
-
|
159
|
-
if @frames.length == 0
|
160
|
-
@native.switchToMainFrame()
|
161
|
-
else
|
162
|
-
@native.switchToFrame(@frames[@frames.length - 1])
|
161
|
+
@native.switchToParentFrame()
|
163
162
|
|
164
163
|
getPage: (name) ->
|
165
164
|
if @sub_pages[name]
|
@@ -106,8 +106,20 @@ module Capybara::Poltergeist
|
|
106
106
|
browser.source.to_s
|
107
107
|
end
|
108
108
|
|
109
|
-
def
|
110
|
-
browser.
|
109
|
+
def title
|
110
|
+
browser.title
|
111
|
+
end
|
112
|
+
|
113
|
+
def find(method, selector)
|
114
|
+
browser.find(method, selector).map { |page_id, id| Capybara::Poltergeist::Node.new(self, page_id, id) }
|
115
|
+
end
|
116
|
+
|
117
|
+
def find_xpath(selector)
|
118
|
+
find :xpath, selector
|
119
|
+
end
|
120
|
+
|
121
|
+
def find_css(selector)
|
122
|
+
find :css, selector
|
111
123
|
end
|
112
124
|
|
113
125
|
def click(x, y)
|
@@ -199,7 +211,7 @@ module Capybara::Poltergeist
|
|
199
211
|
end
|
200
212
|
|
201
213
|
def invalid_element_errors
|
202
|
-
[Capybara::Poltergeist::ObsoleteNode, Capybara::Poltergeist::
|
214
|
+
[Capybara::Poltergeist::ObsoleteNode, Capybara::Poltergeist::MouseEventFailed]
|
203
215
|
end
|
204
216
|
end
|
205
217
|
end
|