poltergeist 1.9.0 → 1.10.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 +4 -4
- data/README.md +25 -15
- data/lib/capybara/poltergeist.rb +0 -1
- data/lib/capybara/poltergeist/browser.rb +21 -7
- data/lib/capybara/poltergeist/client.rb +4 -2
- data/lib/capybara/poltergeist/client/agent.coffee +4 -1
- data/lib/capybara/poltergeist/client/browser.coffee +63 -34
- data/lib/capybara/poltergeist/client/compiled/agent.js +5 -1
- data/lib/capybara/poltergeist/client/compiled/browser.js +117 -74
- data/lib/capybara/poltergeist/client/compiled/main.js +17 -0
- data/lib/capybara/poltergeist/client/compiled/web_page.js +19 -11
- data/lib/capybara/poltergeist/client/main.coffee +5 -0
- data/lib/capybara/poltergeist/client/web_page.coffee +17 -10
- data/lib/capybara/poltergeist/cookie.rb +4 -0
- data/lib/capybara/poltergeist/driver.rb +12 -0
- data/lib/capybara/poltergeist/errors.rb +18 -0
- data/lib/capybara/poltergeist/version.rb +1 -1
- metadata +55 -22
- data/lib/capybara/poltergeist/json.rb +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 475593a2e1c767e61acb2023b065eb7688972efa
|
4
|
+
data.tar.gz: d35e4e7d9d2245564ea960045a891589c6a1dbed
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 14677723d5e05debc486229fbe765a5e4fa6fdd49620daf32bcac5347c8856ea448946babba7904574ab904400ae9ae5db125de9d56683a745f6719a22f4c840
|
7
|
+
data.tar.gz: fd6f1a43a661fc191cc7e80e63ed02bb601dbf21c17f40145a24da82941859add75100da027e8656450c0aed062606d6e17cc33d9e0da538cacd9d2a71358550
|
data/README.md
CHANGED
@@ -9,7 +9,7 @@ provided by [PhantomJS](http://phantomjs.org/).
|
|
9
9
|
**If you're viewing this at https://github.com/teampoltergeist/poltergeist,
|
10
10
|
you're reading the documentation for the master branch.
|
11
11
|
[View documentation for the latest release
|
12
|
-
(1.
|
12
|
+
(1.9.0).](https://github.com/teampoltergeist/poltergeist/tree/v1.9.0)**
|
13
13
|
|
14
14
|
## Getting help ##
|
15
15
|
|
@@ -110,6 +110,7 @@ and the following optional features:
|
|
110
110
|
* `page.driver.scroll_to(left, top)`
|
111
111
|
* `page.driver.basic_authorize(user, password)`
|
112
112
|
* `element.native.send_keys(*keys)`
|
113
|
+
* `page.driver.set_proxy(ip, port, type, user, password)`
|
113
114
|
* window API
|
114
115
|
* cookie handling
|
115
116
|
* drag-and-drop
|
@@ -211,11 +212,11 @@ The following methods are used to inspect and manipulate cookies:
|
|
211
212
|
* `page.driver.cookies` - a hash of cookies accessible to the current
|
212
213
|
page. The keys are cookie names. The values are `Cookie` objects, with
|
213
214
|
the following methods: `name`, `value`, `domain`, `path`, `secure?`,
|
214
|
-
`httponly?`, `expires`.
|
215
|
+
`httponly?`, `samesite`, `expires`.
|
215
216
|
* `page.driver.set_cookie(name, value, options = {})` - set a cookie.
|
216
217
|
The options hash can take the following keys: `:domain`, `:path`,
|
217
|
-
`:secure`, `:httponly`, `:expires`. `:expires` should be a
|
218
|
-
object.
|
218
|
+
`:secure`, `:httponly`, `:samesite`, `:expires`. `:expires` should be a
|
219
|
+
`Time` object.
|
219
220
|
* `page.driver.remove_cookie(name)` - remove a cookie
|
220
221
|
* `page.driver.clear_cookies` - clear all cookies
|
221
222
|
|
@@ -262,7 +263,7 @@ end
|
|
262
263
|
* `:timeout` (Numeric) - The number of seconds we'll wait for a response
|
263
264
|
when communicating with PhantomJS. Default is 30.
|
264
265
|
* `:inspector` (Boolean, String) - See 'Remote Debugging', above.
|
265
|
-
* `:js_errors` (Boolean) - When false,
|
266
|
+
* `:js_errors` (Boolean) - When false, JavaScript errors do not get re-raised in Ruby.
|
266
267
|
* `:window_size` (Array) - The dimensions of the browser window in which to test, expressed
|
267
268
|
as a 2-element array, e.g. [1024, 768]. Default: [1024, 768]
|
268
269
|
* `:phantomjs_options` (Array) - Additional [command line options](http://phantomjs.org/api/command-line.html)
|
@@ -271,20 +272,29 @@ end
|
|
271
272
|
the phantomjs browser. Useful for faking unsupported APIs.
|
272
273
|
* `:port` (Fixnum) - The port which should be used to communicate
|
273
274
|
with the PhantomJS process. Defaults to a random open port.
|
275
|
+
* `:url_blacklist` (Array) - Default session url blacklist - expressed as an array of strings to match against requested URLs.
|
276
|
+
* `:url_whitelist` (Array) - Default session url whitelist - expressed as an array of strings to match against requested URLs.
|
274
277
|
|
275
|
-
### URL Blacklisting ###
|
276
|
-
|
277
|
-
|
278
|
-
to prevent scripts from running on designated domains. If you are experiencing
|
279
|
-
slower run times, consider creating a URL blacklist of domains that are not
|
280
|
-
essential to your testing environment, such as ad networks or analytics.
|
278
|
+
### URL Blacklisting & Whitelisting ###
|
279
|
+
Poltergeist supports URL blacklisting, which allows you
|
280
|
+
to prevent scripts from running on designated domains:
|
281
281
|
|
282
282
|
```ruby
|
283
283
|
page.driver.browser.url_blacklist = ['http://www.example.com']
|
284
284
|
```
|
285
285
|
|
286
|
-
|
287
|
-
|
286
|
+
and also URL whitelisting, which allows scripts to only run
|
287
|
+
on designated domains:
|
288
|
+
|
289
|
+
```ruby
|
290
|
+
page.driver.browser.url_whitelist = ['http://www.example.com']
|
291
|
+
```
|
292
|
+
|
293
|
+
If you are experiencing slower run times, consider creating a
|
294
|
+
URL whitelist of domains that are essential or a blacklist of
|
295
|
+
domains that are not essential, such as ad networks or analytics,
|
296
|
+
to your testing environment.
|
297
|
+
|
288
298
|
|
289
299
|
## Troubleshooting ##
|
290
300
|
|
@@ -358,7 +368,7 @@ test to allow sufficient time for the page to settle.
|
|
358
368
|
|
359
369
|
If you have these types of problems, read through the [Capybara
|
360
370
|
documentation on asynchronous
|
361
|
-
|
371
|
+
JavaScript](https://github.com/jnicklas/capybara#asynchronous-javascript-ajax-and-friends)
|
362
372
|
which explains the tools that Capybara provides for dealing with this.
|
363
373
|
|
364
374
|
### Memory leak ###
|
@@ -392,7 +402,7 @@ Include as much information as possible. For example:
|
|
392
402
|
better)
|
393
403
|
* The output obtained from running Poltergeist with `:debug` turned on
|
394
404
|
* Screenshots
|
395
|
-
* Stack traces if there are any Ruby on
|
405
|
+
* Stack traces if there are any Ruby on JavaScript exceptions generated
|
396
406
|
* The Poltergeist and PhantomJS version numbers used
|
397
407
|
* The operating system name and version used
|
398
408
|
|
data/lib/capybara/poltergeist.rb
CHANGED
@@ -15,7 +15,6 @@ module Capybara
|
|
15
15
|
require 'capybara/poltergeist/web_socket_server'
|
16
16
|
require 'capybara/poltergeist/client'
|
17
17
|
require 'capybara/poltergeist/inspector'
|
18
|
-
require 'capybara/poltergeist/json'
|
19
18
|
require 'capybara/poltergeist/network_traffic'
|
20
19
|
require 'capybara/poltergeist/errors'
|
21
20
|
require 'capybara/poltergeist/cookie'
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require "capybara/poltergeist/errors"
|
2
2
|
require "capybara/poltergeist/command"
|
3
|
-
require '
|
3
|
+
require 'json'
|
4
4
|
require 'time'
|
5
5
|
|
6
6
|
module Capybara::Poltergeist
|
@@ -10,7 +10,8 @@ module Capybara::Poltergeist
|
|
10
10
|
'Poltergeist.FrameNotFound' => FrameNotFound,
|
11
11
|
'Poltergeist.InvalidSelector' => InvalidSelector,
|
12
12
|
'Poltergeist.StatusFailError' => StatusFailError,
|
13
|
-
'Poltergeist.NoSuchWindowError' => NoSuchWindowError
|
13
|
+
'Poltergeist.NoSuchWindowError' => NoSuchWindowError,
|
14
|
+
'Poltergeist.UnsupportedFeature' => UnsupportedFeature
|
14
15
|
}
|
15
16
|
|
16
17
|
attr_reader :server, :client, :logger
|
@@ -163,7 +164,7 @@ module Capybara::Poltergeist
|
|
163
164
|
return locator if window_handles.include? locator
|
164
165
|
|
165
166
|
handle = command 'window_handle', locator
|
166
|
-
raise
|
167
|
+
raise NoSuchWindowError unless handle
|
167
168
|
return handle
|
168
169
|
end
|
169
170
|
|
@@ -218,12 +219,14 @@ module Capybara::Poltergeist
|
|
218
219
|
|
219
220
|
def render(path, options = {})
|
220
221
|
check_render_options!(options)
|
221
|
-
|
222
|
+
options[:full] = !!options[:full]
|
223
|
+
command 'render', path.to_s, options
|
222
224
|
end
|
223
225
|
|
224
226
|
def render_base64(format, options = {})
|
225
227
|
check_render_options!(options)
|
226
|
-
|
228
|
+
options[:full] = !!options[:full]
|
229
|
+
command 'render_base64', format.to_s, options
|
227
230
|
end
|
228
231
|
|
229
232
|
def set_zoom_factor(zoom_factor)
|
@@ -260,6 +263,13 @@ module Capybara::Poltergeist
|
|
260
263
|
command('clear_network_traffic')
|
261
264
|
end
|
262
265
|
|
266
|
+
def set_proxy(ip, port, type, user, password)
|
267
|
+
args = [ip, port, type]
|
268
|
+
args << user if user
|
269
|
+
args << password if password
|
270
|
+
command('set_proxy', *args)
|
271
|
+
end
|
272
|
+
|
263
273
|
def equals(page_id, id, other_id)
|
264
274
|
command('equals', page_id, id, other_id)
|
265
275
|
end
|
@@ -337,6 +347,10 @@ module Capybara::Poltergeist
|
|
337
347
|
command 'set_debug', !!val
|
338
348
|
end
|
339
349
|
|
350
|
+
def clear_memory_cache
|
351
|
+
command 'clear_memory_cache'
|
352
|
+
end
|
353
|
+
|
340
354
|
def command(name, *args)
|
341
355
|
cmd = Command.new(name, *args)
|
342
356
|
log cmd.message
|
@@ -411,8 +425,8 @@ module Capybara::Poltergeist
|
|
411
425
|
# [:Shift, "s"] => { modifier: "shift", key: "S" }
|
412
426
|
# [:Ctrl, :Left] => { modifier: "ctrl", key: :Left }
|
413
427
|
# [:Ctrl, :Shift, :Left] => { modifier: "ctrl,shift", key: :Left }
|
414
|
-
letter = key.
|
415
|
-
symbol = key.map { |k| k.to_s.downcase }.join(',')
|
428
|
+
letter = key.last
|
429
|
+
symbol = key[0...-1].map { |k| k.to_s.downcase }.join(',')
|
416
430
|
|
417
431
|
{ modifier: symbol.to_s.downcase, key: letter.capitalize }
|
418
432
|
when Symbol
|
@@ -33,8 +33,10 @@ module Capybara::Poltergeist
|
|
33
33
|
|
34
34
|
def initialize(server, options = {})
|
35
35
|
@server = server
|
36
|
-
@path = Cliver::detect
|
37
|
-
|
36
|
+
@path = Cliver::detect((options[:path] || PHANTOMJS_NAME), *['>=2.1.0', '< 3.0'])
|
37
|
+
@path ||= Cliver::detect!((options[:path] || PHANTOMJS_NAME), *PHANTOMJS_VERSION).tap do
|
38
|
+
warn "You're running an old version of PhantomJS, update to >= 2.1.1 for a better experience."
|
39
|
+
end
|
38
40
|
|
39
41
|
@window_size = options[:window_size] || [1024, 768]
|
40
42
|
@phantomjs_options = options[:phantomjs_options] || []
|
@@ -169,7 +169,10 @@ class PoltergeistAgent.Node
|
|
169
169
|
if @element.nodeName == "TEXTAREA"
|
170
170
|
@element.textContent
|
171
171
|
else
|
172
|
-
@element
|
172
|
+
if @element instanceof SVGElement
|
173
|
+
@element.textContent
|
174
|
+
else
|
175
|
+
@element.innerText
|
173
176
|
|
174
177
|
deleteText: ->
|
175
178
|
range = document.createRange()
|
@@ -52,6 +52,9 @@ class Poltergeist.Browser
|
|
52
52
|
@page.onPageCreated = (newPage) =>
|
53
53
|
page = new Poltergeist.WebPage(newPage)
|
54
54
|
page.handle = "#{@_counter++}"
|
55
|
+
page.urlBlacklist = @page.urlBlacklist
|
56
|
+
page.urlWhitelist = @page.urlWhitelist
|
57
|
+
page.setViewportSize(@page.viewportSize())
|
55
58
|
@pages.push(page)
|
56
59
|
|
57
60
|
return
|
@@ -65,8 +68,7 @@ class Poltergeist.Browser
|
|
65
68
|
this[command.name].apply(this, command.args)
|
66
69
|
|
67
70
|
debug: (message) ->
|
68
|
-
if @_debug
|
69
|
-
console.log "poltergeist [#{new Date().getTime()}] #{message}"
|
71
|
+
console.log "poltergeist [#{new Date().getTime()}] #{message}" if @_debug
|
70
72
|
|
71
73
|
setModalMessage: (msg) ->
|
72
74
|
@processed_modal_messages.push(msg)
|
@@ -103,15 +105,16 @@ class Poltergeist.Browser
|
|
103
105
|
@current_command.sendResponse(status: 'success')
|
104
106
|
else
|
105
107
|
command = @current_command
|
106
|
-
@currentPage
|
107
|
-
|
108
|
+
loading_page = @currentPage
|
109
|
+
@currentPage.waitState 'default', ->
|
110
|
+
if @statusCode == null && @status == 'fail'
|
108
111
|
command.sendError(new Poltergeist.StatusFailError(url))
|
109
112
|
else
|
110
|
-
command.sendResponse(status: @
|
111
|
-
, max_wait,
|
112
|
-
resources = @
|
113
|
+
command.sendResponse(status: @status)
|
114
|
+
, max_wait, ->
|
115
|
+
resources = @openResourceRequests()
|
113
116
|
msg = if resources.length
|
114
|
-
"Timed out with the following resources still waiting #{
|
117
|
+
"Timed out with the following resources still waiting #{resources.join(',')}"
|
115
118
|
command.sendError(new Poltergeist.StatusFailError(url,msg))
|
116
119
|
return
|
117
120
|
|
@@ -214,12 +217,13 @@ class Poltergeist.Browser
|
|
214
217
|
frame.setAttribute('name', "_random_name_#{new Date().getTime()}")
|
215
218
|
name = frame.getAttribute('name')
|
216
219
|
|
217
|
-
|
220
|
+
frame_url = @frameUrl(name)
|
221
|
+
if frame_url in @currentPage.blockedUrls()
|
218
222
|
command.sendResponse(true)
|
219
223
|
else if @currentPage.pushFrame(name)
|
220
|
-
if @currentPage.currentUrl() == 'about:blank'
|
224
|
+
if frame_url && (frame_url != 'about:blank') && (@currentPage.currentUrl() == 'about:blank')
|
221
225
|
@currentPage.state = 'awaiting_frame_load'
|
222
|
-
@currentPage.waitState 'default',
|
226
|
+
@currentPage.waitState 'default', ->
|
223
227
|
command.sendResponse(true)
|
224
228
|
else
|
225
229
|
command.sendResponse(true)
|
@@ -250,11 +254,11 @@ class Poltergeist.Browser
|
|
250
254
|
|
251
255
|
switch_to_window: (handle) ->
|
252
256
|
command = @current_command
|
253
|
-
|
254
|
-
if
|
255
|
-
if
|
256
|
-
|
257
|
-
@currentPage =
|
257
|
+
new_page = @getPageByHandle(handle)
|
258
|
+
if new_page
|
259
|
+
if new_page != @currentPage
|
260
|
+
new_page.waitState 'default', =>
|
261
|
+
@currentPage = new_page
|
258
262
|
command.sendResponse(true)
|
259
263
|
else
|
260
264
|
command.sendResponse(true)
|
@@ -280,18 +284,18 @@ class Poltergeist.Browser
|
|
280
284
|
# state and wait for onLoadFinished before sending a response.
|
281
285
|
@currentPage.state = 'mouse_event'
|
282
286
|
|
283
|
-
|
284
|
-
|
287
|
+
last_mouse_event = node.mouseEvent(name)
|
288
|
+
event_page = @currentPage
|
285
289
|
command = @current_command
|
286
290
|
|
287
|
-
setTimeout
|
291
|
+
setTimeout ->
|
288
292
|
# If the state is still the same then navigation event won't happen
|
289
|
-
if
|
290
|
-
|
291
|
-
command.sendResponse(position:
|
293
|
+
if event_page.state == 'mouse_event'
|
294
|
+
event_page.state = 'default'
|
295
|
+
command.sendResponse(position: last_mouse_event)
|
292
296
|
else
|
293
|
-
|
294
|
-
command.sendResponse(position:
|
297
|
+
event_page.waitState 'default', ->
|
298
|
+
command.sendResponse(position: last_mouse_event)
|
295
299
|
, 5
|
296
300
|
|
297
301
|
click: (page_id, id) ->
|
@@ -354,16 +358,26 @@ class Poltergeist.Browser
|
|
354
358
|
|
355
359
|
@current_command.sendResponse(true)
|
356
360
|
|
357
|
-
render_base64: (format, full, selector = null)->
|
358
|
-
|
361
|
+
render_base64: (format, { full = false, selector = null } = {})->
|
362
|
+
window_scroll_position = @currentPage.native().evaluate("function(){ return [window.pageXOffset, window.pageYOffset] }")
|
363
|
+
dimensions = this.set_clip_rect(full, selector)
|
359
364
|
encoded_image = @currentPage.renderBase64(format)
|
365
|
+
@currentPage.setScrollPosition(left: dimensions.left, top: dimensions.top)
|
366
|
+
@currentPage.native().evaluate("window.scrollTo", window_scroll_position...)
|
367
|
+
|
360
368
|
@current_command.sendResponse(encoded_image)
|
361
369
|
|
362
|
-
render: (path, full, selector = null) ->
|
370
|
+
render: (path, { full = false, selector = null, format = null, quality = null } = {} ) ->
|
371
|
+
window_scroll_position = @currentPage.native().evaluate("function(){ return [window.pageXOffset, window.pageYOffset] }")
|
363
372
|
dimensions = this.set_clip_rect(full, selector)
|
373
|
+
options = {}
|
374
|
+
options["format"] = format if format?
|
375
|
+
options["quality"] = quality if quality?
|
364
376
|
@currentPage.setScrollPosition(left: 0, top: 0)
|
365
|
-
@currentPage.render(path)
|
377
|
+
@currentPage.render(path, options)
|
366
378
|
@currentPage.setScrollPosition(left: dimensions.left, top: dimensions.top)
|
379
|
+
@currentPage.native().evaluate("window.scrollTo", window_scroll_position...)
|
380
|
+
|
367
381
|
@current_command.sendResponse(true)
|
368
382
|
|
369
383
|
set_clip_rect: (full, selector) ->
|
@@ -400,6 +414,10 @@ class Poltergeist.Browser
|
|
400
414
|
@currentPage.clearNetworkTraffic()
|
401
415
|
@current_command.sendResponse(true)
|
402
416
|
|
417
|
+
set_proxy: (ip, port, type, user, password) ->
|
418
|
+
phantom.setProxy(ip, port, type, user, password)
|
419
|
+
@current_command.sendResponse(true)
|
420
|
+
|
403
421
|
get_headers: ->
|
404
422
|
@current_command.sendResponse(@currentPage.getCustomHeaders())
|
405
423
|
|
@@ -470,7 +488,7 @@ class Poltergeist.Browser
|
|
470
488
|
if @currentPage.canGoBack
|
471
489
|
@currentPage.state = 'loading'
|
472
490
|
@currentPage.goBack()
|
473
|
-
@currentPage.waitState 'default',
|
491
|
+
@currentPage.waitState 'default', ->
|
474
492
|
command.sendResponse(true)
|
475
493
|
else
|
476
494
|
command.sendResponse(false)
|
@@ -480,17 +498,17 @@ class Poltergeist.Browser
|
|
480
498
|
if @currentPage.canGoForward
|
481
499
|
@currentPage.state = 'loading'
|
482
500
|
@currentPage.goForward()
|
483
|
-
@currentPage.waitState 'default',
|
501
|
+
@currentPage.waitState 'default', ->
|
484
502
|
command.sendResponse(true)
|
485
503
|
else
|
486
504
|
command.sendResponse(false)
|
487
505
|
|
488
|
-
set_url_whitelist: ->
|
489
|
-
@currentPage.urlWhitelist =
|
506
|
+
set_url_whitelist: (wildcards...)->
|
507
|
+
@currentPage.urlWhitelist = (@_wildcardToRegexp(wc) for wc in wildcards)
|
490
508
|
@current_command.sendResponse(true)
|
491
509
|
|
492
|
-
set_url_blacklist: ->
|
493
|
-
@currentPage.urlBlacklist =
|
510
|
+
set_url_blacklist: (wildcards...)->
|
511
|
+
@currentPage.urlBlacklist = (@_wildcardToRegexp(wc) for wc in wildcards)
|
494
512
|
@current_command.sendResponse(true)
|
495
513
|
|
496
514
|
set_confirm_process: (process) ->
|
@@ -503,3 +521,14 @@ class Poltergeist.Browser
|
|
503
521
|
|
504
522
|
modal_message: ->
|
505
523
|
@current_command.sendResponse(@processed_modal_messages.shift())
|
524
|
+
|
525
|
+
clear_memory_cache: ->
|
526
|
+
@currentPage.clearMemoryCache()
|
527
|
+
@current_command.sendResponse(true)
|
528
|
+
|
529
|
+
_wildcardToRegexp: (wildcard)->
|
530
|
+
wildcard = wildcard.replace(/[\-\[\]\/\{\}\(\)\+\.\\\^\$\|]/g, "\\$&")
|
531
|
+
wildcard = wildcard.replace(/\*/g, ".*")
|
532
|
+
wildcard = wildcard.replace(/\?/g, ".")
|
533
|
+
new RegExp(wildcard, "i")
|
534
|
+
|
@@ -262,7 +262,11 @@ PoltergeistAgent.Node = (function() {
|
|
262
262
|
if (this.element.nodeName === "TEXTAREA") {
|
263
263
|
return this.element.textContent;
|
264
264
|
} else {
|
265
|
-
|
265
|
+
if (this.element instanceof SVGElement) {
|
266
|
+
return this.element.textContent;
|
267
|
+
} else {
|
268
|
+
return this.element.innerText;
|
269
|
+
}
|
266
270
|
}
|
267
271
|
}
|
268
272
|
};
|
@@ -1,4 +1,5 @@
|
|
1
|
-
var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }
|
1
|
+
var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
|
2
|
+
slice = [].slice;
|
2
3
|
|
3
4
|
Poltergeist.Browser = (function() {
|
4
5
|
function Browser(width, height) {
|
@@ -68,6 +69,9 @@ Poltergeist.Browser = (function() {
|
|
68
69
|
var page;
|
69
70
|
page = new Poltergeist.WebPage(newPage);
|
70
71
|
page.handle = "" + (_this._counter++);
|
72
|
+
page.urlBlacklist = _this.page.urlBlacklist;
|
73
|
+
page.urlWhitelist = _this.page.urlWhitelist;
|
74
|
+
page.setViewportSize(_this.page.viewportSize());
|
71
75
|
return _this.pages.push(page);
|
72
76
|
};
|
73
77
|
})(this);
|
@@ -109,7 +113,7 @@ Poltergeist.Browser = (function() {
|
|
109
113
|
};
|
110
114
|
|
111
115
|
Browser.prototype.visit = function(url, max_wait) {
|
112
|
-
var command, prevUrl;
|
116
|
+
var command, loading_page, prevUrl;
|
113
117
|
if (max_wait == null) {
|
114
118
|
max_wait = 0;
|
115
119
|
}
|
@@ -126,24 +130,21 @@ Poltergeist.Browser = (function() {
|
|
126
130
|
});
|
127
131
|
} else {
|
128
132
|
command = this.current_command;
|
129
|
-
this.currentPage
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
return command.sendError(new Poltergeist.StatusFailError(url, msg));
|
145
|
-
};
|
146
|
-
})(this));
|
133
|
+
loading_page = this.currentPage;
|
134
|
+
this.currentPage.waitState('default', function() {
|
135
|
+
if (this.statusCode === null && this.status === 'fail') {
|
136
|
+
return command.sendError(new Poltergeist.StatusFailError(url));
|
137
|
+
} else {
|
138
|
+
return command.sendResponse({
|
139
|
+
status: this.status
|
140
|
+
});
|
141
|
+
}
|
142
|
+
}, max_wait, function() {
|
143
|
+
var msg, resources;
|
144
|
+
resources = this.openResourceRequests();
|
145
|
+
msg = resources.length ? "Timed out with the following resources still waiting " + (resources.join(',')) : void 0;
|
146
|
+
return command.sendError(new Poltergeist.StatusFailError(url, msg));
|
147
|
+
});
|
147
148
|
}
|
148
149
|
};
|
149
150
|
|
@@ -262,7 +263,7 @@ Poltergeist.Browser = (function() {
|
|
262
263
|
};
|
263
264
|
|
264
265
|
Browser.prototype.pushFrame = function(command, name, timeout) {
|
265
|
-
var frame,
|
266
|
+
var frame, frame_url;
|
266
267
|
if (Array.isArray(name)) {
|
267
268
|
frame = this.node.apply(this, name);
|
268
269
|
name = frame.getAttribute('name') || frame.getAttribute('id');
|
@@ -271,16 +272,15 @@ Poltergeist.Browser = (function() {
|
|
271
272
|
name = frame.getAttribute('name');
|
272
273
|
}
|
273
274
|
}
|
274
|
-
|
275
|
+
frame_url = this.frameUrl(name);
|
276
|
+
if (indexOf.call(this.currentPage.blockedUrls(), frame_url) >= 0) {
|
275
277
|
return command.sendResponse(true);
|
276
278
|
} else if (this.currentPage.pushFrame(name)) {
|
277
|
-
if (this.currentPage.currentUrl() === 'about:blank') {
|
279
|
+
if (frame_url && (frame_url !== 'about:blank') && (this.currentPage.currentUrl() === 'about:blank')) {
|
278
280
|
this.currentPage.state = 'awaiting_frame_load';
|
279
|
-
return this.currentPage.waitState('default',
|
280
|
-
return
|
281
|
-
|
282
|
-
};
|
283
|
-
})(this));
|
281
|
+
return this.currentPage.waitState('default', function() {
|
282
|
+
return command.sendResponse(true);
|
283
|
+
});
|
284
284
|
} else {
|
285
285
|
return command.sendResponse(true);
|
286
286
|
}
|
@@ -330,14 +330,14 @@ Poltergeist.Browser = (function() {
|
|
330
330
|
};
|
331
331
|
|
332
332
|
Browser.prototype.switch_to_window = function(handle) {
|
333
|
-
var command,
|
333
|
+
var command, new_page;
|
334
334
|
command = this.current_command;
|
335
|
-
|
336
|
-
if (
|
337
|
-
if (
|
338
|
-
return
|
335
|
+
new_page = this.getPageByHandle(handle);
|
336
|
+
if (new_page) {
|
337
|
+
if (new_page !== this.currentPage) {
|
338
|
+
return new_page.waitState('default', (function(_this) {
|
339
339
|
return function() {
|
340
|
-
_this.currentPage =
|
340
|
+
_this.currentPage = new_page;
|
341
341
|
return command.sendResponse(true);
|
342
342
|
};
|
343
343
|
})(this));
|
@@ -366,27 +366,26 @@ Poltergeist.Browser = (function() {
|
|
366
366
|
};
|
367
367
|
|
368
368
|
Browser.prototype.mouse_event = function(page_id, id, name) {
|
369
|
-
var command, node;
|
369
|
+
var command, event_page, last_mouse_event, node;
|
370
370
|
node = this.node(page_id, id);
|
371
371
|
this.currentPage.state = 'mouse_event';
|
372
|
-
|
372
|
+
last_mouse_event = node.mouseEvent(name);
|
373
|
+
event_page = this.currentPage;
|
373
374
|
command = this.current_command;
|
374
|
-
return setTimeout(
|
375
|
-
|
376
|
-
|
377
|
-
|
375
|
+
return setTimeout(function() {
|
376
|
+
if (event_page.state === 'mouse_event') {
|
377
|
+
event_page.state = 'default';
|
378
|
+
return command.sendResponse({
|
379
|
+
position: last_mouse_event
|
380
|
+
});
|
381
|
+
} else {
|
382
|
+
return event_page.waitState('default', function() {
|
378
383
|
return command.sendResponse({
|
379
|
-
position:
|
380
|
-
});
|
381
|
-
} else {
|
382
|
-
return _this.currentPage.waitState('default', function() {
|
383
|
-
return command.sendResponse({
|
384
|
-
position: _this.last_mouse_event
|
385
|
-
});
|
384
|
+
position: last_mouse_event
|
386
385
|
});
|
387
|
-
}
|
388
|
-
}
|
389
|
-
}
|
386
|
+
});
|
387
|
+
}
|
388
|
+
}, 5);
|
390
389
|
};
|
391
390
|
|
392
391
|
Browser.prototype.click = function(page_id, id) {
|
@@ -475,31 +474,42 @@ Poltergeist.Browser = (function() {
|
|
475
474
|
return this.current_command.sendResponse(true);
|
476
475
|
};
|
477
476
|
|
478
|
-
Browser.prototype.render_base64 = function(format,
|
479
|
-
var encoded_image;
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
this.set_clip_rect(full, selector);
|
477
|
+
Browser.prototype.render_base64 = function(format, arg) {
|
478
|
+
var dimensions, encoded_image, full, ref, ref1, ref2, ref3, selector, window_scroll_position;
|
479
|
+
ref = arg != null ? arg : {}, full = (ref1 = ref.full) != null ? ref1 : false, selector = (ref2 = ref.selector) != null ? ref2 : null;
|
480
|
+
window_scroll_position = this.currentPage["native"]().evaluate("function(){ return [window.pageXOffset, window.pageYOffset] }");
|
481
|
+
dimensions = this.set_clip_rect(full, selector);
|
484
482
|
encoded_image = this.currentPage.renderBase64(format);
|
483
|
+
this.currentPage.setScrollPosition({
|
484
|
+
left: dimensions.left,
|
485
|
+
top: dimensions.top
|
486
|
+
});
|
487
|
+
(ref3 = this.currentPage["native"]()).evaluate.apply(ref3, ["window.scrollTo"].concat(slice.call(window_scroll_position)));
|
485
488
|
return this.current_command.sendResponse(encoded_image);
|
486
489
|
};
|
487
490
|
|
488
|
-
Browser.prototype.render = function(path,
|
489
|
-
var dimensions;
|
490
|
-
|
491
|
-
|
492
|
-
}
|
491
|
+
Browser.prototype.render = function(path, arg) {
|
492
|
+
var dimensions, format, full, options, quality, ref, ref1, ref2, ref3, ref4, ref5, selector, window_scroll_position;
|
493
|
+
ref = arg != null ? arg : {}, full = (ref1 = ref.full) != null ? ref1 : false, selector = (ref2 = ref.selector) != null ? ref2 : null, format = (ref3 = ref.format) != null ? ref3 : null, quality = (ref4 = ref.quality) != null ? ref4 : null;
|
494
|
+
window_scroll_position = this.currentPage["native"]().evaluate("function(){ return [window.pageXOffset, window.pageYOffset] }");
|
493
495
|
dimensions = this.set_clip_rect(full, selector);
|
496
|
+
options = {};
|
497
|
+
if (format != null) {
|
498
|
+
options["format"] = format;
|
499
|
+
}
|
500
|
+
if (quality != null) {
|
501
|
+
options["quality"] = quality;
|
502
|
+
}
|
494
503
|
this.currentPage.setScrollPosition({
|
495
504
|
left: 0,
|
496
505
|
top: 0
|
497
506
|
});
|
498
|
-
this.currentPage.render(path);
|
507
|
+
this.currentPage.render(path, options);
|
499
508
|
this.currentPage.setScrollPosition({
|
500
509
|
left: dimensions.left,
|
501
510
|
top: dimensions.top
|
502
511
|
});
|
512
|
+
(ref5 = this.currentPage["native"]()).evaluate.apply(ref5, ["window.scrollTo"].concat(slice.call(window_scroll_position)));
|
503
513
|
return this.current_command.sendResponse(true);
|
504
514
|
};
|
505
515
|
|
@@ -549,6 +559,11 @@ Poltergeist.Browser = (function() {
|
|
549
559
|
return this.current_command.sendResponse(true);
|
550
560
|
};
|
551
561
|
|
562
|
+
Browser.prototype.set_proxy = function(ip, port, type, user, password) {
|
563
|
+
phantom.setProxy(ip, port, type, user, password);
|
564
|
+
return this.current_command.sendResponse(true);
|
565
|
+
};
|
566
|
+
|
552
567
|
Browser.prototype.get_headers = function() {
|
553
568
|
return this.current_command.sendResponse(this.currentPage.getCustomHeaders());
|
554
569
|
};
|
@@ -637,11 +652,9 @@ Poltergeist.Browser = (function() {
|
|
637
652
|
if (this.currentPage.canGoBack) {
|
638
653
|
this.currentPage.state = 'loading';
|
639
654
|
this.currentPage.goBack();
|
640
|
-
return this.currentPage.waitState('default',
|
641
|
-
return
|
642
|
-
|
643
|
-
};
|
644
|
-
})(this));
|
655
|
+
return this.currentPage.waitState('default', function() {
|
656
|
+
return command.sendResponse(true);
|
657
|
+
});
|
645
658
|
} else {
|
646
659
|
return command.sendResponse(false);
|
647
660
|
}
|
@@ -653,23 +666,41 @@ Poltergeist.Browser = (function() {
|
|
653
666
|
if (this.currentPage.canGoForward) {
|
654
667
|
this.currentPage.state = 'loading';
|
655
668
|
this.currentPage.goForward();
|
656
|
-
return this.currentPage.waitState('default',
|
657
|
-
return
|
658
|
-
|
659
|
-
};
|
660
|
-
})(this));
|
669
|
+
return this.currentPage.waitState('default', function() {
|
670
|
+
return command.sendResponse(true);
|
671
|
+
});
|
661
672
|
} else {
|
662
673
|
return command.sendResponse(false);
|
663
674
|
}
|
664
675
|
};
|
665
676
|
|
666
677
|
Browser.prototype.set_url_whitelist = function() {
|
667
|
-
|
678
|
+
var wc, wildcards;
|
679
|
+
wildcards = 1 <= arguments.length ? slice.call(arguments, 0) : [];
|
680
|
+
this.currentPage.urlWhitelist = (function() {
|
681
|
+
var i, len, results;
|
682
|
+
results = [];
|
683
|
+
for (i = 0, len = wildcards.length; i < len; i++) {
|
684
|
+
wc = wildcards[i];
|
685
|
+
results.push(this._wildcardToRegexp(wc));
|
686
|
+
}
|
687
|
+
return results;
|
688
|
+
}).call(this);
|
668
689
|
return this.current_command.sendResponse(true);
|
669
690
|
};
|
670
691
|
|
671
692
|
Browser.prototype.set_url_blacklist = function() {
|
672
|
-
|
693
|
+
var wc, wildcards;
|
694
|
+
wildcards = 1 <= arguments.length ? slice.call(arguments, 0) : [];
|
695
|
+
this.currentPage.urlBlacklist = (function() {
|
696
|
+
var i, len, results;
|
697
|
+
results = [];
|
698
|
+
for (i = 0, len = wildcards.length; i < len; i++) {
|
699
|
+
wc = wildcards[i];
|
700
|
+
results.push(this._wildcardToRegexp(wc));
|
701
|
+
}
|
702
|
+
return results;
|
703
|
+
}).call(this);
|
673
704
|
return this.current_command.sendResponse(true);
|
674
705
|
};
|
675
706
|
|
@@ -687,6 +718,18 @@ Poltergeist.Browser = (function() {
|
|
687
718
|
return this.current_command.sendResponse(this.processed_modal_messages.shift());
|
688
719
|
};
|
689
720
|
|
721
|
+
Browser.prototype.clear_memory_cache = function() {
|
722
|
+
this.currentPage.clearMemoryCache();
|
723
|
+
return this.current_command.sendResponse(true);
|
724
|
+
};
|
725
|
+
|
726
|
+
Browser.prototype._wildcardToRegexp = function(wildcard) {
|
727
|
+
wildcard = wildcard.replace(/[\-\[\]\/\{\}\(\)\+\.\\\^\$\|]/g, "\\$&");
|
728
|
+
wildcard = wildcard.replace(/\*/g, ".*");
|
729
|
+
wildcard = wildcard.replace(/\?/g, ".");
|
730
|
+
return new RegExp(wildcard, "i");
|
731
|
+
};
|
732
|
+
|
690
733
|
return Browser;
|
691
734
|
|
692
735
|
})();
|
@@ -214,6 +214,23 @@ Poltergeist.NoSuchWindowError = (function(superClass) {
|
|
214
214
|
|
215
215
|
})(Poltergeist.Error);
|
216
216
|
|
217
|
+
Poltergeist.UnsupportedFeature = (function(superClass) {
|
218
|
+
extend(UnsupportedFeature, superClass);
|
219
|
+
|
220
|
+
function UnsupportedFeature(message1) {
|
221
|
+
this.message = message1;
|
222
|
+
}
|
223
|
+
|
224
|
+
UnsupportedFeature.prototype.name = "Poltergeist.UnsupportedFeature";
|
225
|
+
|
226
|
+
UnsupportedFeature.prototype.args = function() {
|
227
|
+
return [this.message, phantom.version];
|
228
|
+
};
|
229
|
+
|
230
|
+
return UnsupportedFeature;
|
231
|
+
|
232
|
+
})(Poltergeist.Error);
|
233
|
+
|
217
234
|
phantom.injectJs(phantom.libraryPath + "/web_page.js");
|
218
235
|
|
219
236
|
phantom.injectJs(phantom.libraryPath + "/node.js");
|
@@ -117,11 +117,11 @@ Poltergeist.WebPage = (function() {
|
|
117
117
|
WebPage.prototype.onResourceRequestedNative = function(request, net) {
|
118
118
|
var abort, blacklisted, ref2, useWhitelist, whitelisted;
|
119
119
|
useWhitelist = this.urlWhitelist.length > 0;
|
120
|
-
whitelisted = this.urlWhitelist.some(function(
|
121
|
-
return request.url
|
120
|
+
whitelisted = this.urlWhitelist.some(function(whitelisted_regex) {
|
121
|
+
return whitelisted_regex.test(request.url);
|
122
122
|
});
|
123
|
-
blacklisted = this.urlBlacklist.some(function(
|
124
|
-
return request.url
|
123
|
+
blacklisted = this.urlBlacklist.some(function(blacklisted_regex) {
|
124
|
+
return blacklisted_regex.test(request.url);
|
125
125
|
});
|
126
126
|
abort = false;
|
127
127
|
if (useWhitelist && !whitelisted) {
|
@@ -234,13 +234,11 @@ Poltergeist.WebPage = (function() {
|
|
234
234
|
};
|
235
235
|
|
236
236
|
WebPage.prototype._waitState_until = function(state, callback, timeout, timeout_callback) {
|
237
|
-
var d;
|
238
237
|
if (this.state === state) {
|
239
|
-
return callback.call();
|
238
|
+
return callback.call(this);
|
240
239
|
} else {
|
241
|
-
|
242
|
-
|
243
|
-
return timeout_callback.call();
|
240
|
+
if (new Date().getTime() > timeout) {
|
241
|
+
return timeout_callback.call(this);
|
244
242
|
} else {
|
245
243
|
return setTimeout(((function(_this) {
|
246
244
|
return function() {
|
@@ -257,10 +255,10 @@ Poltergeist.WebPage = (function() {
|
|
257
255
|
max_wait = 0;
|
258
256
|
}
|
259
257
|
if (this.state === state) {
|
260
|
-
return callback.call();
|
258
|
+
return callback.call(this);
|
261
259
|
} else {
|
262
260
|
if (max_wait !== 0) {
|
263
|
-
timeout =
|
261
|
+
timeout = new Date().getTime() + (max_wait * 1000);
|
264
262
|
return setTimeout(((function(_this) {
|
265
263
|
return function() {
|
266
264
|
return _this._waitState_until(state, callback, timeout, timeout_callback);
|
@@ -584,6 +582,16 @@ Poltergeist.WebPage = (function() {
|
|
584
582
|
return parser.href;
|
585
583
|
};
|
586
584
|
|
585
|
+
WebPage.prototype.clearMemoryCache = function() {
|
586
|
+
var clearMemoryCache;
|
587
|
+
clearMemoryCache = this["native"]().clearMemoryCache;
|
588
|
+
if (typeof clearMemoryCache === "function") {
|
589
|
+
return clearMemoryCache();
|
590
|
+
} else {
|
591
|
+
throw new Poltergeist.UnsupportedFeature("clearMemoryCache is supported since PhantomJS 2.0.0");
|
592
|
+
}
|
593
|
+
};
|
594
|
+
|
587
595
|
return WebPage;
|
588
596
|
|
589
597
|
})();
|
@@ -87,6 +87,11 @@ class Poltergeist.NoSuchWindowError extends Poltergeist.Error
|
|
87
87
|
name: "Poltergeist.NoSuchWindowError"
|
88
88
|
args: -> []
|
89
89
|
|
90
|
+
class Poltergeist.UnsupportedFeature extends Poltergeist.Error
|
91
|
+
constructor: (@message) ->
|
92
|
+
name: "Poltergeist.UnsupportedFeature"
|
93
|
+
args: -> [@message, phantom.version]
|
94
|
+
|
90
95
|
# We're using phantom.libraryPath so that any stack traces
|
91
96
|
# report the full path.
|
92
97
|
phantom.injectJs("#{phantom.libraryPath}/web_page.js")
|
@@ -83,11 +83,11 @@ class Poltergeist.WebPage
|
|
83
83
|
onResourceRequestedNative: (request, net) ->
|
84
84
|
useWhitelist = @urlWhitelist.length > 0
|
85
85
|
|
86
|
-
whitelisted = @urlWhitelist.some (
|
87
|
-
request.url
|
86
|
+
whitelisted = @urlWhitelist.some (whitelisted_regex) ->
|
87
|
+
whitelisted_regex.test request.url
|
88
88
|
|
89
|
-
blacklisted = @urlBlacklist.some (
|
90
|
-
request.url
|
89
|
+
blacklisted = @urlBlacklist.some (blacklisted_regex) ->
|
90
|
+
blacklisted_regex.test request.url
|
91
91
|
|
92
92
|
abort = false
|
93
93
|
|
@@ -170,20 +170,20 @@ class Poltergeist.WebPage
|
|
170
170
|
|
171
171
|
_waitState_until: (state, callback, timeout, timeout_callback) ->
|
172
172
|
if (@state == state)
|
173
|
-
callback.call()
|
173
|
+
callback.call(this)
|
174
174
|
else
|
175
|
-
|
176
|
-
|
177
|
-
timeout_callback.call()
|
175
|
+
if new Date().getTime() > timeout
|
176
|
+
timeout_callback.call(this)
|
178
177
|
else
|
179
178
|
setTimeout (=> @_waitState_until(state, callback, timeout, timeout_callback)), 100
|
180
179
|
|
181
180
|
waitState: (state, callback, max_wait=0, timeout_callback) ->
|
181
|
+
# callback and timeout_callback will be called with this == the current page
|
182
182
|
if @state == state
|
183
|
-
callback.call()
|
183
|
+
callback.call(this)
|
184
184
|
else
|
185
185
|
if max_wait != 0
|
186
|
-
timeout =
|
186
|
+
timeout = new Date().getTime() + (max_wait*1000)
|
187
187
|
setTimeout (=> @_waitState_until(state, callback, timeout, timeout_callback)), 100
|
188
188
|
else
|
189
189
|
setTimeout (=> @waitState(state, callback)), 100
|
@@ -409,3 +409,10 @@ class Poltergeist.WebPage
|
|
409
409
|
parser = document.createElement('a')
|
410
410
|
parser.href = url
|
411
411
|
return parser.href
|
412
|
+
|
413
|
+
clearMemoryCache: ->
|
414
|
+
clearMemoryCache = this.native().clearMemoryCache
|
415
|
+
if typeof clearMemoryCache == "function"
|
416
|
+
clearMemoryCache()
|
417
|
+
else
|
418
|
+
throw new Poltergeist.UnsupportedFeature("clearMemoryCache is supported since PhantomJS 2.0.0")
|
@@ -26,6 +26,8 @@ module Capybara::Poltergeist
|
|
26
26
|
browser.js_errors = options[:js_errors] if options.key?(:js_errors)
|
27
27
|
browser.extensions = options.fetch(:extensions, [])
|
28
28
|
browser.debug = true if options[:debug]
|
29
|
+
browser.url_blacklist = options[:url_blacklist] if options.key?(:url_blacklist)
|
30
|
+
browser.url_whitelist = options[:url_whitelist] if options.key?(:url_whitelist)
|
29
31
|
browser
|
30
32
|
end
|
31
33
|
end
|
@@ -175,6 +177,8 @@ module Capybara::Poltergeist
|
|
175
177
|
|
176
178
|
def reset!
|
177
179
|
browser.reset
|
180
|
+
browser.url_blacklist = options[:url_blacklist] if options.key?(:url_blacklist)
|
181
|
+
browser.url_whitelist = options[:url_whitelist] if options.key?(:url_whitelist)
|
178
182
|
@started = false
|
179
183
|
end
|
180
184
|
|
@@ -224,6 +228,10 @@ module Capybara::Poltergeist
|
|
224
228
|
browser.clear_network_traffic
|
225
229
|
end
|
226
230
|
|
231
|
+
def set_proxy(ip, port, type = "http", user = nil, password = nil)
|
232
|
+
browser.set_proxy(ip, port, type, user, password)
|
233
|
+
end
|
234
|
+
|
227
235
|
def headers
|
228
236
|
browser.get_headers
|
229
237
|
end
|
@@ -275,6 +283,10 @@ module Capybara::Poltergeist
|
|
275
283
|
browser.cookies_enabled = flag
|
276
284
|
end
|
277
285
|
|
286
|
+
def clear_memory_cache
|
287
|
+
browser.clear_memory_cache
|
288
|
+
end
|
289
|
+
|
278
290
|
# * PhantomJS with set settings doesn't send `Authorize` on POST request
|
279
291
|
# * With manually set header PhantomJS makes next request with
|
280
292
|
# `Authorization: Basic Og==` header when settings are empty and the
|
@@ -115,6 +115,24 @@ module Capybara
|
|
115
115
|
end
|
116
116
|
end
|
117
117
|
|
118
|
+
class UnsupportedFeature < ClientError
|
119
|
+
def name
|
120
|
+
response['name']
|
121
|
+
end
|
122
|
+
|
123
|
+
def unsupported_message
|
124
|
+
response['args'][0]
|
125
|
+
end
|
126
|
+
|
127
|
+
def version
|
128
|
+
response['args'][1].values_at(*%w(major minor patch)).join '.'
|
129
|
+
end
|
130
|
+
|
131
|
+
def message
|
132
|
+
"Running version of PhantomJS #{version} does not support some feature: #{unsupported_message}"
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
118
136
|
class MouseEventFailed < NodeError
|
119
137
|
def name
|
120
138
|
response['args'][0]
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: poltergeist
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jon Leighton
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-06-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: capybara
|
@@ -38,20 +38,6 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 0.2.0
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: multi_json
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '1.0'
|
48
|
-
type: :runtime
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '1.0'
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
42
|
name: cliver
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -126,16 +112,16 @@ dependencies:
|
|
126
112
|
name: rake
|
127
113
|
requirement: !ruby/object:Gem::Requirement
|
128
114
|
requirements:
|
129
|
-
- - "
|
115
|
+
- - ">="
|
130
116
|
- !ruby/object:Gem::Version
|
131
|
-
version: '
|
117
|
+
version: '0'
|
132
118
|
type: :development
|
133
119
|
prerelease: false
|
134
120
|
version_requirements: !ruby/object:Gem::Requirement
|
135
121
|
requirements:
|
136
|
-
- - "
|
122
|
+
- - ">="
|
137
123
|
- !ruby/object:Gem::Version
|
138
|
-
version: '
|
124
|
+
version: '0'
|
139
125
|
- !ruby/object:Gem::Dependency
|
140
126
|
name: image_size
|
141
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -155,6 +141,9 @@ dependencies:
|
|
155
141
|
requirement: !ruby/object:Gem::Requirement
|
156
142
|
requirements:
|
157
143
|
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '1.3'
|
146
|
+
- - ">="
|
158
147
|
- !ruby/object:Gem::Version
|
159
148
|
version: 1.3.3
|
160
149
|
type: :development
|
@@ -162,6 +151,9 @@ dependencies:
|
|
162
151
|
version_requirements: !ruby/object:Gem::Requirement
|
163
152
|
requirements:
|
164
153
|
- - "~>"
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
version: '1.3'
|
156
|
+
- - ">="
|
165
157
|
- !ruby/object:Gem::Version
|
166
158
|
version: 1.3.3
|
167
159
|
- !ruby/object:Gem::Dependency
|
@@ -192,6 +184,48 @@ dependencies:
|
|
192
184
|
- - "~>"
|
193
185
|
- !ruby/object:Gem::Version
|
194
186
|
version: 2.0.0
|
187
|
+
- !ruby/object:Gem::Dependency
|
188
|
+
name: coffee-script-source
|
189
|
+
requirement: !ruby/object:Gem::Requirement
|
190
|
+
requirements:
|
191
|
+
- - "~>"
|
192
|
+
- !ruby/object:Gem::Version
|
193
|
+
version: 1.10.0
|
194
|
+
type: :development
|
195
|
+
prerelease: false
|
196
|
+
version_requirements: !ruby/object:Gem::Requirement
|
197
|
+
requirements:
|
198
|
+
- - "~>"
|
199
|
+
- !ruby/object:Gem::Version
|
200
|
+
version: 1.10.0
|
201
|
+
- !ruby/object:Gem::Dependency
|
202
|
+
name: listen
|
203
|
+
requirement: !ruby/object:Gem::Requirement
|
204
|
+
requirements:
|
205
|
+
- - "~>"
|
206
|
+
- !ruby/object:Gem::Version
|
207
|
+
version: 3.0.6
|
208
|
+
type: :development
|
209
|
+
prerelease: false
|
210
|
+
version_requirements: !ruby/object:Gem::Requirement
|
211
|
+
requirements:
|
212
|
+
- - "~>"
|
213
|
+
- !ruby/object:Gem::Version
|
214
|
+
version: 3.0.6
|
215
|
+
- !ruby/object:Gem::Dependency
|
216
|
+
name: erubis
|
217
|
+
requirement: !ruby/object:Gem::Requirement
|
218
|
+
requirements:
|
219
|
+
- - ">="
|
220
|
+
- !ruby/object:Gem::Version
|
221
|
+
version: '0'
|
222
|
+
type: :development
|
223
|
+
prerelease: false
|
224
|
+
version_requirements: !ruby/object:Gem::Requirement
|
225
|
+
requirements:
|
226
|
+
- - ">="
|
227
|
+
- !ruby/object:Gem::Version
|
228
|
+
version: '0'
|
195
229
|
description: Poltergeist is a driver for Capybara that allows you to run your tests
|
196
230
|
on a headless WebKit browser, provided by PhantomJS.
|
197
231
|
email:
|
@@ -224,7 +258,6 @@ files:
|
|
224
258
|
- lib/capybara/poltergeist/driver.rb
|
225
259
|
- lib/capybara/poltergeist/errors.rb
|
226
260
|
- lib/capybara/poltergeist/inspector.rb
|
227
|
-
- lib/capybara/poltergeist/json.rb
|
228
261
|
- lib/capybara/poltergeist/network_traffic.rb
|
229
262
|
- lib/capybara/poltergeist/network_traffic/error.rb
|
230
263
|
- lib/capybara/poltergeist/network_traffic/request.rb
|
@@ -254,7 +287,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
254
287
|
version: '0'
|
255
288
|
requirements: []
|
256
289
|
rubyforge_project:
|
257
|
-
rubygems_version: 2.
|
290
|
+
rubygems_version: 2.6.4
|
258
291
|
signing_key:
|
259
292
|
specification_version: 4
|
260
293
|
summary: PhantomJS driver for Capybara
|
@@ -1,25 +0,0 @@
|
|
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
|