poltergeist 1.3.0 → 1.4.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.
- checksums.yaml +7 -0
- data/README.md +68 -263
- data/lib/capybara/poltergeist.rb +1 -0
- data/lib/capybara/poltergeist/browser.rb +36 -3
- data/lib/capybara/poltergeist/client.rb +32 -31
- data/lib/capybara/poltergeist/client/agent.coffee +7 -6
- data/lib/capybara/poltergeist/client/browser.coffee +47 -13
- data/lib/capybara/poltergeist/client/compiled/agent.js +6 -24
- data/lib/capybara/poltergeist/client/compiled/browser.js +76 -39
- data/lib/capybara/poltergeist/client/compiled/main.js +0 -2
- data/lib/capybara/poltergeist/client/compiled/node.js +0 -4
- data/lib/capybara/poltergeist/client/compiled/web_page.js +42 -24
- data/lib/capybara/poltergeist/client/web_page.coffee +28 -8
- data/lib/capybara/poltergeist/driver.rb +31 -5
- data/lib/capybara/poltergeist/errors.rb +19 -19
- data/lib/capybara/poltergeist/json.rb +25 -0
- data/lib/capybara/poltergeist/node.rb +1 -1
- data/lib/capybara/poltergeist/version.rb +1 -1
- data/lib/capybara/poltergeist/web_socket_server.rb +13 -76
- metadata +47 -63
@@ -5,7 +5,6 @@ var Poltergeist, _ref,
|
|
5
5
|
Poltergeist = (function() {
|
6
6
|
function Poltergeist(port, width, height) {
|
7
7
|
var that;
|
8
|
-
|
9
8
|
this.browser = new Poltergeist.Browser(this, width, height);
|
10
9
|
this.connection = new Poltergeist.Connection(this, port);
|
11
10
|
that = this;
|
@@ -17,7 +16,6 @@ Poltergeist = (function() {
|
|
17
16
|
|
18
17
|
Poltergeist.prototype.runCommand = function(command) {
|
19
18
|
var error;
|
20
|
-
|
21
19
|
this.running = true;
|
22
20
|
try {
|
23
21
|
return this.browser.runCommand(command.name, command.args);
|
@@ -19,7 +19,6 @@ Poltergeist.Node = (function() {
|
|
19
19
|
_fn = function(name) {
|
20
20
|
return Node.prototype[name] = function() {
|
21
21
|
var args;
|
22
|
-
|
23
22
|
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
24
23
|
return this.page.nodeCall(this.id, name, args);
|
25
24
|
};
|
@@ -31,7 +30,6 @@ Poltergeist.Node = (function() {
|
|
31
30
|
|
32
31
|
Node.prototype.mouseEventPosition = function() {
|
33
32
|
var middle, pos, viewport;
|
34
|
-
|
35
33
|
viewport = this.page.viewportSize();
|
36
34
|
pos = this.position();
|
37
35
|
middle = function(start, end, size) {
|
@@ -45,7 +43,6 @@ Poltergeist.Node = (function() {
|
|
45
43
|
|
46
44
|
Node.prototype.mouseEvent = function(name) {
|
47
45
|
var pos, test;
|
48
|
-
|
49
46
|
this.scrollIntoView();
|
50
47
|
pos = this.mouseEventPosition();
|
51
48
|
test = this.mouseEventTest(pos.x, pos.y);
|
@@ -59,7 +56,6 @@ Poltergeist.Node = (function() {
|
|
59
56
|
|
60
57
|
Node.prototype.dragTo = function(other) {
|
61
58
|
var otherPosition, position;
|
62
|
-
|
63
59
|
this.scrollIntoView();
|
64
60
|
position = this.mouseEventPosition();
|
65
61
|
otherPosition = other.mouseEventPosition();
|
@@ -6,7 +6,7 @@ Poltergeist.WebPage = (function() {
|
|
6
6
|
|
7
7
|
WebPage.CALLBACKS = ['onAlert', 'onConsoleMessage', 'onLoadFinished', 'onInitialized', 'onLoadStarted', 'onResourceRequested', 'onResourceReceived', 'onError', 'onNavigationRequested', 'onUrlChanged', 'onPageCreated'];
|
8
8
|
|
9
|
-
WebPage.DELEGATES = ['open', 'sendEvent', 'uploadFile', 'release', 'render'];
|
9
|
+
WebPage.DELEGATES = ['open', 'sendEvent', 'uploadFile', 'release', 'render', 'renderBase64'];
|
10
10
|
|
11
11
|
WebPage.COMMANDS = ['currentUrl', 'find', 'nodeCall', 'documentSize', 'beforeUpload', 'afterUpload'];
|
12
12
|
|
@@ -14,14 +14,13 @@ Poltergeist.WebPage = (function() {
|
|
14
14
|
|
15
15
|
function WebPage(_native) {
|
16
16
|
var callback, _i, _len, _ref;
|
17
|
-
|
18
17
|
this["native"] = _native;
|
19
18
|
this["native"] || (this["native"] = require('webpage').create());
|
20
|
-
this._source =
|
19
|
+
this._source = null;
|
21
20
|
this._errors = [];
|
22
21
|
this._networkTraffic = {};
|
22
|
+
this._temp_headers = {};
|
23
23
|
this.frames = [];
|
24
|
-
this.sub_pages = {};
|
25
24
|
_ref = WebPage.CALLBACKS;
|
26
25
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
27
26
|
callback = _ref[_i];
|
@@ -33,7 +32,6 @@ Poltergeist.WebPage = (function() {
|
|
33
32
|
_fn = function(command) {
|
34
33
|
return WebPage.prototype[command] = function() {
|
35
34
|
var args;
|
36
|
-
|
37
35
|
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
38
36
|
return this.runCommand(command, args);
|
39
37
|
};
|
@@ -57,6 +55,7 @@ Poltergeist.WebPage = (function() {
|
|
57
55
|
WebPage.prototype.onInitializedNative = function() {
|
58
56
|
this._source = null;
|
59
57
|
this.injectAgent();
|
58
|
+
this.removeTempHeaders();
|
60
59
|
return this.setScrollPosition({
|
61
60
|
left: 0,
|
62
61
|
top: 0
|
@@ -65,7 +64,6 @@ Poltergeist.WebPage = (function() {
|
|
65
64
|
|
66
65
|
WebPage.prototype.injectAgent = function() {
|
67
66
|
var extension, _k, _len2, _ref2, _results;
|
68
|
-
|
69
67
|
if (this["native"].evaluate(function() {
|
70
68
|
return typeof __poltergeist;
|
71
69
|
}) === "undefined") {
|
@@ -106,7 +104,6 @@ Poltergeist.WebPage = (function() {
|
|
106
104
|
|
107
105
|
WebPage.prototype.onErrorNative = function(message, stack) {
|
108
106
|
var stackString;
|
109
|
-
|
110
107
|
stackString = message;
|
111
108
|
stack.forEach(function(frame) {
|
112
109
|
stackString += "\n";
|
@@ -135,7 +132,6 @@ Poltergeist.WebPage = (function() {
|
|
135
132
|
|
136
133
|
WebPage.prototype.onResourceReceivedNative = function(response) {
|
137
134
|
var _ref2;
|
138
|
-
|
139
135
|
if ((_ref2 = this._networkTraffic[response.id]) != null) {
|
140
136
|
_ref2.responseParts.push(response);
|
141
137
|
}
|
@@ -179,7 +175,6 @@ Poltergeist.WebPage = (function() {
|
|
179
175
|
|
180
176
|
WebPage.prototype.responseHeaders = function() {
|
181
177
|
var headers;
|
182
|
-
|
183
178
|
headers = {};
|
184
179
|
this._responseHeaders.forEach(function(item) {
|
185
180
|
return headers[item.name] = item.value;
|
@@ -219,14 +214,45 @@ Poltergeist.WebPage = (function() {
|
|
219
214
|
return this["native"].clipRect = rect;
|
220
215
|
};
|
221
216
|
|
217
|
+
WebPage.prototype.elementBounds = function(selector) {
|
218
|
+
return this["native"].evaluate(function(selector) {
|
219
|
+
return document.querySelector(selector).getBoundingClientRect();
|
220
|
+
}, selector);
|
221
|
+
};
|
222
|
+
|
222
223
|
WebPage.prototype.setUserAgent = function(userAgent) {
|
223
224
|
return this["native"].settings.userAgent = userAgent;
|
224
225
|
};
|
225
226
|
|
227
|
+
WebPage.prototype.getCustomHeaders = function() {
|
228
|
+
return this["native"].customHeaders;
|
229
|
+
};
|
230
|
+
|
226
231
|
WebPage.prototype.setCustomHeaders = function(headers) {
|
227
232
|
return this["native"].customHeaders = headers;
|
228
233
|
};
|
229
234
|
|
235
|
+
WebPage.prototype.addTempHeader = function(header) {
|
236
|
+
var name, value, _results;
|
237
|
+
_results = [];
|
238
|
+
for (name in header) {
|
239
|
+
value = header[name];
|
240
|
+
_results.push(this._temp_headers[name] = value);
|
241
|
+
}
|
242
|
+
return _results;
|
243
|
+
};
|
244
|
+
|
245
|
+
WebPage.prototype.removeTempHeaders = function() {
|
246
|
+
var allHeaders, name, value, _ref2;
|
247
|
+
allHeaders = this.getCustomHeaders();
|
248
|
+
_ref2 = this._temp_headers;
|
249
|
+
for (name in _ref2) {
|
250
|
+
value = _ref2[name];
|
251
|
+
delete allHeaders[name];
|
252
|
+
}
|
253
|
+
return this.setCustomHeaders(allHeaders);
|
254
|
+
};
|
255
|
+
|
230
256
|
WebPage.prototype.pushFrame = function(name) {
|
231
257
|
if (this["native"].switchToFrame(name)) {
|
232
258
|
this.frames.push(name);
|
@@ -236,6 +262,10 @@ Poltergeist.WebPage = (function() {
|
|
236
262
|
}
|
237
263
|
};
|
238
264
|
|
265
|
+
WebPage.prototype.pages = function() {
|
266
|
+
return this["native"].pagesWindowName;
|
267
|
+
};
|
268
|
+
|
239
269
|
WebPage.prototype.popFrame = function() {
|
240
270
|
this.frames.pop();
|
241
271
|
return this["native"].switchToParentFrame();
|
@@ -243,20 +273,14 @@ Poltergeist.WebPage = (function() {
|
|
243
273
|
|
244
274
|
WebPage.prototype.getPage = function(name) {
|
245
275
|
var page;
|
246
|
-
|
247
|
-
if (
|
248
|
-
return
|
249
|
-
} else {
|
250
|
-
page = this["native"].getPage(name);
|
251
|
-
if (page) {
|
252
|
-
return this.sub_pages[name] = new Poltergeist.WebPage(page);
|
253
|
-
}
|
276
|
+
page = this["native"].getPage(name);
|
277
|
+
if (page) {
|
278
|
+
return new Poltergeist.WebPage(page);
|
254
279
|
}
|
255
280
|
};
|
256
281
|
|
257
282
|
WebPage.prototype.dimensions = function() {
|
258
283
|
var scroll, viewport;
|
259
|
-
|
260
284
|
scroll = this.scrollPosition();
|
261
285
|
viewport = this.viewportSize();
|
262
286
|
return {
|
@@ -271,7 +295,6 @@ Poltergeist.WebPage = (function() {
|
|
271
295
|
|
272
296
|
WebPage.prototype.validatedDimensions = function() {
|
273
297
|
var dimensions, document;
|
274
|
-
|
275
298
|
dimensions = this.dimensions();
|
276
299
|
document = dimensions.document;
|
277
300
|
if (dimensions.right > document.width) {
|
@@ -300,7 +323,6 @@ Poltergeist.WebPage = (function() {
|
|
300
323
|
|
301
324
|
WebPage.prototype.evaluate = function() {
|
302
325
|
var args, fn;
|
303
|
-
|
304
326
|
fn = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
|
305
327
|
this.injectAgent();
|
306
328
|
return JSON.parse(this["native"].evaluate("function() { return PoltergeistAgent.stringify(" + (this.stringifyCall(fn, args)) + ") }"));
|
@@ -308,7 +330,6 @@ Poltergeist.WebPage = (function() {
|
|
308
330
|
|
309
331
|
WebPage.prototype.execute = function() {
|
310
332
|
var args, fn;
|
311
|
-
|
312
333
|
fn = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
|
313
334
|
return this["native"].evaluate("function() { " + (this.stringifyCall(fn, args)) + " }");
|
314
335
|
};
|
@@ -323,11 +344,9 @@ Poltergeist.WebPage = (function() {
|
|
323
344
|
|
324
345
|
WebPage.prototype.bindCallback = function(name) {
|
325
346
|
var that;
|
326
|
-
|
327
347
|
that = this;
|
328
348
|
return this["native"][name] = function() {
|
329
349
|
var result;
|
330
|
-
|
331
350
|
if (that[name + 'Native'] != null) {
|
332
351
|
result = that[name + 'Native'].apply(that, arguments);
|
333
352
|
}
|
@@ -339,7 +358,6 @@ Poltergeist.WebPage = (function() {
|
|
339
358
|
|
340
359
|
WebPage.prototype.runCommand = function(name, args) {
|
341
360
|
var result;
|
342
|
-
|
343
361
|
result = this.evaluate(function(name, args) {
|
344
362
|
return __poltergeist.externalCall(name, args);
|
345
363
|
}, name, args);
|
@@ -3,7 +3,7 @@ class Poltergeist.WebPage
|
|
3
3
|
'onLoadStarted', 'onResourceRequested', 'onResourceReceived',
|
4
4
|
'onError', 'onNavigationRequested', 'onUrlChanged', 'onPageCreated']
|
5
5
|
|
6
|
-
@DELEGATES = ['open', 'sendEvent', 'uploadFile', 'release', 'render']
|
6
|
+
@DELEGATES = ['open', 'sendEvent', 'uploadFile', 'release', 'render', 'renderBase64']
|
7
7
|
|
8
8
|
@COMMANDS = ['currentUrl', 'find', 'nodeCall', 'documentSize', 'beforeUpload', 'afterUpload']
|
9
9
|
|
@@ -12,11 +12,11 @@ class Poltergeist.WebPage
|
|
12
12
|
constructor: (@native) ->
|
13
13
|
@native or= require('webpage').create()
|
14
14
|
|
15
|
-
@_source =
|
15
|
+
@_source = null
|
16
16
|
@_errors = []
|
17
17
|
@_networkTraffic = {}
|
18
|
+
@_temp_headers = {}
|
18
19
|
@frames = []
|
19
|
-
@sub_pages = {}
|
20
20
|
|
21
21
|
for callback in WebPage.CALLBACKS
|
22
22
|
this.bindCallback(callback)
|
@@ -34,6 +34,7 @@ class Poltergeist.WebPage
|
|
34
34
|
onInitializedNative: ->
|
35
35
|
@_source = null
|
36
36
|
@injectAgent()
|
37
|
+
this.removeTempHeaders()
|
37
38
|
this.setScrollPosition(left: 0, top: 0)
|
38
39
|
|
39
40
|
injectAgent: ->
|
@@ -143,12 +144,31 @@ class Poltergeist.WebPage
|
|
143
144
|
setClipRect: (rect) ->
|
144
145
|
@native.clipRect = rect
|
145
146
|
|
147
|
+
elementBounds: (selector) ->
|
148
|
+
@native.evaluate(
|
149
|
+
(selector) -> document.querySelector(selector).getBoundingClientRect(),
|
150
|
+
selector
|
151
|
+
)
|
152
|
+
|
146
153
|
setUserAgent: (userAgent) ->
|
147
154
|
@native.settings.userAgent = userAgent
|
148
155
|
|
156
|
+
getCustomHeaders: ->
|
157
|
+
@native.customHeaders
|
158
|
+
|
149
159
|
setCustomHeaders: (headers) ->
|
150
160
|
@native.customHeaders = headers
|
151
161
|
|
162
|
+
addTempHeader: (header) ->
|
163
|
+
for name, value of header
|
164
|
+
@_temp_headers[name] = value
|
165
|
+
|
166
|
+
removeTempHeaders: ->
|
167
|
+
allHeaders = this.getCustomHeaders()
|
168
|
+
for name, value of @_temp_headers
|
169
|
+
delete allHeaders[name]
|
170
|
+
this.setCustomHeaders(allHeaders)
|
171
|
+
|
152
172
|
pushFrame: (name) ->
|
153
173
|
if @native.switchToFrame(name)
|
154
174
|
@frames.push(name)
|
@@ -156,16 +176,16 @@ class Poltergeist.WebPage
|
|
156
176
|
else
|
157
177
|
false
|
158
178
|
|
179
|
+
pages: ->
|
180
|
+
@native.pagesWindowName
|
181
|
+
|
159
182
|
popFrame: ->
|
160
183
|
@frames.pop()
|
161
184
|
@native.switchToParentFrame()
|
162
185
|
|
163
186
|
getPage: (name) ->
|
164
|
-
|
165
|
-
|
166
|
-
else
|
167
|
-
page = @native.getPage(name)
|
168
|
-
@sub_pages[name] = new Poltergeist.WebPage(page) if page
|
187
|
+
page = @native.getPage(name)
|
188
|
+
new Poltergeist.WebPage(page) if page
|
169
189
|
|
170
190
|
dimensions: ->
|
171
191
|
scroll = this.scrollPosition()
|
@@ -143,6 +143,10 @@ module Capybara::Poltergeist
|
|
143
143
|
browser.within_window(name, &block)
|
144
144
|
end
|
145
145
|
|
146
|
+
def window_handles
|
147
|
+
browser.window_handles
|
148
|
+
end
|
149
|
+
|
146
150
|
def reset!
|
147
151
|
browser.reset
|
148
152
|
@started = false
|
@@ -153,19 +157,40 @@ module Capybara::Poltergeist
|
|
153
157
|
end
|
154
158
|
alias_method :render, :save_screenshot
|
155
159
|
|
160
|
+
def render_base64(format = :png, options = {})
|
161
|
+
browser.render_base64(format, options)
|
162
|
+
end
|
163
|
+
|
156
164
|
def resize(width, height)
|
157
165
|
browser.resize(width, height)
|
158
166
|
end
|
159
167
|
alias_method :resize_window, :resize
|
160
168
|
|
169
|
+
def scroll_to(left, top)
|
170
|
+
browser.scroll_to(left, top)
|
171
|
+
end
|
172
|
+
|
161
173
|
def network_traffic
|
162
174
|
browser.network_traffic
|
163
175
|
end
|
164
176
|
|
177
|
+
def headers
|
178
|
+
browser.get_headers
|
179
|
+
end
|
180
|
+
|
165
181
|
def headers=(headers)
|
166
182
|
browser.set_headers(headers)
|
167
183
|
end
|
168
184
|
|
185
|
+
def add_headers(headers)
|
186
|
+
browser.add_headers(headers)
|
187
|
+
end
|
188
|
+
|
189
|
+
def add_header(name, value, options = {})
|
190
|
+
permanent = options.fetch(:permanent, true)
|
191
|
+
browser.add_header({ name => value }, permanent)
|
192
|
+
end
|
193
|
+
|
169
194
|
def response_headers
|
170
195
|
browser.response_headers
|
171
196
|
end
|
@@ -177,11 +202,12 @@ module Capybara::Poltergeist
|
|
177
202
|
def set_cookie(name, value, options = {})
|
178
203
|
options[:name] ||= name
|
179
204
|
options[:value] ||= value
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
205
|
+
options[:domain] ||= begin
|
206
|
+
if @started
|
207
|
+
URI.parse(browser.current_url).host
|
208
|
+
else
|
209
|
+
Capybara.app_host || "127.0.0.1"
|
210
|
+
end
|
185
211
|
end
|
186
212
|
|
187
213
|
browser.set_cookie(options)
|
@@ -20,7 +20,7 @@ module Capybara
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def to_s
|
23
|
-
stack
|
23
|
+
[message, stack].join("\n")
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
@@ -140,28 +140,28 @@ module Capybara
|
|
140
140
|
end
|
141
141
|
|
142
142
|
class PhantomJSTooOld < Error
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
143
|
+
def self.===(other)
|
144
|
+
if Cliver::Dependency::VersionMismatch === other
|
145
|
+
warn "{name} exception has been deprecated in favor of using the " +
|
146
|
+
"cliver gem for command-line dependency detection. Please " +
|
147
|
+
"handle Cliver::Dependency::VersionMismatch instead."
|
148
|
+
true
|
149
|
+
else
|
150
|
+
super
|
151
|
+
end
|
151
152
|
end
|
152
153
|
end
|
153
154
|
|
154
155
|
class PhantomJSFailed < Error
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
"a Javascript REPL."
|
156
|
+
def self.===(other)
|
157
|
+
if Cliver::Dependency::NotMet === other
|
158
|
+
warn "{name} exception has been deprecated in favor of using the " +
|
159
|
+
"cliver gem for command-line dependency detection. Please " +
|
160
|
+
"handle Cliver::Dependency::NotMet instead."
|
161
|
+
true
|
162
|
+
else
|
163
|
+
super
|
164
|
+
end
|
165
165
|
end
|
166
166
|
end
|
167
167
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Capybara::Poltergeist
|
2
|
+
module JSON
|
3
|
+
def self.load(message)
|
4
|
+
if dumpy_multi_json?
|
5
|
+
MultiJson.load(message)
|
6
|
+
else
|
7
|
+
MultiJson.decode(message)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.dump(message)
|
12
|
+
if dumpy_multi_json?
|
13
|
+
MultiJson.dump(message)
|
14
|
+
else
|
15
|
+
MultiJson.encode(message)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def self.dumpy_multi_json?
|
22
|
+
MultiJson.respond_to?(:dump) && MultiJson.respond_to?(:load)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|