poltergeist 1.5.1 → 1.6.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 CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- OTNhZjUzMmZiNmZlNDlkNzdkMjhlNjNhOTlmODhkZWU5YTBhODA2ZQ==
5
- data.tar.gz: !binary |-
6
- ZTFjYzAwNGI3YTM3ZGEwN2M0ZTI3MzAxMzNiYTI4MmY2YWQ2NjhiOA==
2
+ SHA1:
3
+ metadata.gz: 804da55f4a9b382633c1ea2388078a0a464dcf20
4
+ data.tar.gz: 50f49ce4999e47f266a048ada3a4edb453aef88d
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- MTY1MTJiMGYxMTk5NTBlNDVmNDZkMDBlOWQ4ODk4MzNjZjA2ZDc3ZjFhNDZm
10
- MWE4ZGVlYTA1ZmI1NWJkMjc3Y2RiZTE1YzEwNjQ0MzhjZGRhOTQ2NGQ5Zjgx
11
- N2IxZTc0YWFmNTY5MTE5NDA0YjNjMzAyODE5ZjNhMGM5ZDkzZjk=
12
- data.tar.gz: !binary |-
13
- MjI0NTg2YzZhMjg0NzE4NzI2MDhhMjQyODQ2MzY4NDI3MWQxNWY0NGQ3YWUx
14
- ZGIzNDJjZDQ1ZTJkMzVlN2FjYmY2NjUxMTBkZTI5NTE1NGU2M2E2ZjgwMmVj
15
- MWQ0MGQzMzRjZTJjMzA1ZjMxMWM1Mzc0ZjAyNWViOWZlZmY0N2E=
6
+ metadata.gz: 6129b9fb4c4cd02030a40f4d1afe79a4fb8dbb4244c0bb93b00bfd6587dccb93ece045c089c6731e2538c8abd2ea73ceb18c7aa9fe34a883112a5682493caabe
7
+ data.tar.gz: 9abd3b5839e1342411eb869c83917fe1a45341278ec663d870274d9f5ca501f897b1b49505367d5f3601cd80eb0e456999b1cfec49f2c96428477f81e7eae8f7
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011-2013 Jonathan Leighton
1
+ Copyright (c) 2011-2014 Jonathan Leighton
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,15 +1,15 @@
1
1
  # Poltergeist - A PhantomJS driver for Capybara #
2
2
 
3
- [![Build Status](https://secure.travis-ci.org/jonleighton/poltergeist.png)](http://travis-ci.org/jonleighton/poltergeist)
3
+ [![Build Status](https://secure.travis-ci.org/teampoltergeist/poltergeist.png)](http://travis-ci.org/teampoltergeist/poltergeist)
4
4
 
5
5
  Poltergeist is a driver for [Capybara](https://github.com/jnicklas/capybara). It allows you to
6
6
  run your Capybara tests on a headless [WebKit](http://webkit.org) browser,
7
7
  provided by [PhantomJS](http://www.phantomjs.org/).
8
8
 
9
- **If you're viewing this at https://github.com/jonleighton/poltergeist,
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.5.0).](https://github.com/jonleighton/poltergeist/tree/v1.5.0)**
12
+ (1.6.0).](https://github.com/teampoltergeist/poltergeist/tree/v1.6.0)**
13
13
 
14
14
  ## Getting help ##
15
15
 
@@ -17,7 +17,7 @@ Questions should be posted [on Stack
17
17
  Overflow, using the 'poltergeist' tag](http://stackoverflow.com/questions/tagged/poltergeist).
18
18
 
19
19
  Bug reports should be posted [on
20
- GitHub](https://github.com/jonleighton/poltergeist/issues) (and be sure
20
+ GitHub](https://github.com/teampoltergeist/poltergeist/issues) (and be sure
21
21
  to read the bug reporting guidance below).
22
22
 
23
23
  ## Installation ##
@@ -43,17 +43,17 @@ dependencies* (you don't need Qt, or a running X server, etc.)
43
43
 
44
44
  * *Homebrew*: `brew install phantomjs`
45
45
  * *MacPorts*: `sudo port install phantomjs`
46
- * *Manual install*: [Download this](http://phantomjs.googlecode.com/files/phantomjs-1.9.2-macosx.zip)
46
+ * *Manual install*: [Download this](https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-1.9.7-macosx.zip)
47
47
 
48
48
  ### Linux ###
49
49
 
50
- * Download the [32 bit](https://phantomjs.googlecode.com/files/phantomjs-1.9.2-linux-i686.tar.bz2)
51
- or [64 bit](https://phantomjs.googlecode.com/files/phantomjs-1.9.2-linux-x86_64.tar.bz2)
50
+ * Download the [32 bit](https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-1.9.7-linux-i686.tar.bz2)
51
+ or [64 bit](https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-1.9.7-linux-x86_64.tar.bz2)
52
52
  binary.
53
53
  * Extract the tarball and copy `bin/phantomjs` into your `PATH`
54
54
 
55
55
  ### Windows ###
56
- * Download the [precompiled binary](http://phantomjs.googlecode.com/files/phantomjs-1.9.2-windows.zip)
56
+ * Download the [precompiled binary](https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-1.9.7-windows.zip)
57
57
  for Windows
58
58
 
59
59
  ### Manual compilation ###
@@ -61,7 +61,7 @@ for Windows
61
61
  Do this as a last resort if the binaries don't work for you. It will
62
62
  take quite a long time as it has to build WebKit.
63
63
 
64
- * Download [the source tarball](http://phantomjs.googlecode.com/files/phantomjs-1.9.2-source.zip)
64
+ * Download [the source tarball](https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-1.9.7-source.zip)
65
65
  * Extract and cd in
66
66
  * `./build.sh`
67
67
 
@@ -97,7 +97,6 @@ and the following optional features:
97
97
 
98
98
  * `page.evaluate_script` and `page.execute_script`
99
99
  * `page.within_frame`
100
- * `page.within_window`
101
100
  * `page.status_code`
102
101
  * `page.response_headers`
103
102
  * `page.save_screenshot`
@@ -105,6 +104,7 @@ and the following optional features:
105
104
  * `page.driver.scroll_to(left, top)`
106
105
  * `page.driver.basic_authorize(user, password)`
107
106
  * `element.native.send_keys(*keys)`
107
+ * window API
108
108
  * cookie handling
109
109
  * drag-and-drop
110
110
 
@@ -131,11 +131,6 @@ If you need for some reasons base64 encoded screenshot you can simply call
131
131
  same as for `save_screenshot` except the first argument which is format (:png by
132
132
  default, acceptable :png, :gif, :jpeg).
133
133
 
134
- ### Resizing the window ###
135
-
136
- Sometimes the window size is important to how things are rendered. Poltergeist sets the window
137
- size to 1024x768 by default, but you can set this yourself with `page.driver.resize(width, height)`.
138
-
139
134
  ### Clicking precise coordinates ###
140
135
 
141
136
  Sometimes its desirable to click a very specific area of the screen. You can accomplish this with
@@ -216,31 +211,7 @@ The following methods are used to inspect and manipulate cookies:
216
211
  `:secure`, `:httponly`, `:expires`. `:expires` should be a `Time`
217
212
  object.
218
213
  * `page.driver.remove_cookie(name)` - remove a cookie
219
-
220
- ### Window switching ###
221
-
222
- The following methods can be used to execute commands inside different windows:
223
-
224
- * `page.driver.window_handles` - an array containing the names of all
225
- the open windows.
226
-
227
- * `page.within_window(name) { # actions }` - executes
228
- the passed block in the context of the named window.
229
-
230
- Example:
231
-
232
- ``` ruby
233
- find_link("Login with Facebook").trigger("click")
234
-
235
- sleep(0.1)
236
-
237
- fb_popup = page.driver.window_handles.last
238
- page.within_window fb_popup do
239
- fill_in "email", :with => "facebook_email@email.tst"
240
- fill_in "pass", :with => "my_pass"
241
- click_button "Log In"
242
- end
243
- ```
214
+ * `page.driver.clear_cookies` - clear all cookies
244
215
 
245
216
  ### Sending keys ###
246
217
 
@@ -288,12 +259,12 @@ end
288
259
  * `:js_errors` (Boolean) - When false, Javascript errors do not get re-raised in Ruby.
289
260
  * `:window_size` (Array) - The dimensions of the browser window in which to test, expressed
290
261
  as a 2-element array, e.g. [1024, 768]. Default: [1024, 768]
291
- * `:phantomjs_options` (Array) - Additional [command line options](https://github.com/ariya/phantomjs/wiki/API-Reference)
262
+ * `:phantomjs_options` (Array) - Additional [command line options](http://phantomjs.org/api/command-line.html)
292
263
  to be passed to PhantomJS, e.g. `['--load-images=no', '--ignore-ssl-errors=yes']`
293
264
  * `:extensions` (Array) - An array of JS files to be preloaded into
294
265
  the phantomjs browser. Useful for faking unsupported APIs.
295
266
  * `:port` (Fixnum) - The port which should be used to communicate
296
- with the PhantomJS process. Default: 44678.
267
+ with the PhantomJS process. Defaults to a random open port.
297
268
 
298
269
  ## Troubleshooting ##
299
270
 
@@ -309,7 +280,7 @@ occur sporadically and are not easily reproduced.
309
280
 
310
281
  If your crash happens every time, you should read the [PhantomJS crash
311
282
  reporting
312
- guide](https://github.com/ariya/phantomjs/wiki/Crash-Reporting) and file
283
+ guide](http://phantomjs.org/crash-reporting.html) and file
313
284
  a bug against PhantomJS. Feel free to also file a bug against
314
285
  Poltergeist in case there are workarounds that can be implemented within
315
286
  Poltergeist. Also, if lots of Poltergeist users are experiencing the
@@ -412,7 +383,7 @@ the [changelog](CHANGELOG.md).
412
383
 
413
384
  ## License ##
414
385
 
415
- Copyright (c) 2011 Jonathan Leighton
386
+ Copyright (c) 2011-2014 Jonathan Leighton
416
387
 
417
388
  Permission is hereby granted, free of charge, to any person obtaining
418
389
  a copy of this software and associated documentation files (the
@@ -5,9 +5,11 @@ require 'time'
5
5
  module Capybara::Poltergeist
6
6
  class Browser
7
7
  ERROR_MAPPINGS = {
8
- "Poltergeist.JavascriptError" => JavascriptError,
9
- "Poltergeist.FrameNotFound" => FrameNotFound,
10
- "Poltergeist.InvalidSelector" => InvalidSelector
8
+ 'Poltergeist.JavascriptError' => JavascriptError,
9
+ 'Poltergeist.FrameNotFound' => FrameNotFound,
10
+ 'Poltergeist.InvalidSelector' => InvalidSelector,
11
+ 'Poltergeist.StatusFailError' => StatusFailError,
12
+ 'Poltergeist.NoSuchWindowError' => NoSuchWindowError
11
13
  }
12
14
 
13
15
  attr_reader :server, :client, :logger
@@ -49,6 +51,10 @@ module Capybara::Poltergeist
49
51
  command 'title'
50
52
  end
51
53
 
54
+ def parents(page_id, id)
55
+ command 'parents', page_id, id
56
+ end
57
+
52
58
  def find(method, selector)
53
59
  result = command('find', method, selector)
54
60
  result['ids'].map { |id| [result['page_id'], id] }
@@ -70,6 +76,10 @@ module Capybara::Poltergeist
70
76
  command 'delete_text', page_id, id
71
77
  end
72
78
 
79
+ def attributes(page_id, id)
80
+ command 'attributes', page_id, id
81
+ end
82
+
73
83
  def attribute(page_id, id, name)
74
84
  command 'attribute', page_id, id, name.to_s
75
85
  end
@@ -122,21 +132,45 @@ module Capybara::Poltergeist
122
132
  command 'pop_frame'
123
133
  end
124
134
 
135
+ def window_handle
136
+ command 'window_handle'
137
+ end
138
+
125
139
  def window_handles
126
- command 'pages'
140
+ command 'window_handles'
141
+ end
142
+
143
+ def switch_to_window(handle)
144
+ command 'switch_to_window', handle
145
+ end
146
+
147
+ def open_new_window
148
+ command 'open_new_window'
149
+ end
150
+
151
+ def close_window(handle)
152
+ command 'close_window', handle
127
153
  end
128
154
 
129
155
  def within_window(name, &block)
130
- command 'push_window', name
156
+ original = window_handle
157
+ handle = command 'window_handle', name
158
+ handle = name if handle.nil? && window_handles.include?(name)
159
+ raise NoSuchWindowError unless handle
160
+ switch_to_window(handle)
131
161
  yield
132
162
  ensure
133
- command 'pop_window'
163
+ switch_to_window(original)
134
164
  end
135
165
 
136
166
  def click(page_id, id)
137
167
  command 'click', page_id, id
138
168
  end
139
169
 
170
+ def right_click(page_id, id)
171
+ command 'right_click', page_id, id
172
+ end
173
+
140
174
  def double_click(page_id, id)
141
175
  command 'double_click', page_id, id
142
176
  end
@@ -175,6 +209,10 @@ module Capybara::Poltergeist
175
209
  command 'render_base64', format.to_s, !!options[:full], options[:selector]
176
210
  end
177
211
 
212
+ def set_zoom_factor(zoom_factor)
213
+ command 'set_zoom_factor', zoom_factor
214
+ end
215
+
178
216
  def set_paper_size(size)
179
217
  command 'set_paper_size', size
180
218
  end
@@ -240,6 +278,10 @@ module Capybara::Poltergeist
240
278
  command 'remove_cookie', name
241
279
  end
242
280
 
281
+ def clear_cookies
282
+ command 'clear_cookies'
283
+ end
284
+
243
285
  def cookies_enabled=(flag)
244
286
  command 'cookies_enabled', !!flag
245
287
  end
@@ -258,17 +300,23 @@ module Capybara::Poltergeist
258
300
  end
259
301
  end
260
302
 
303
+ def url_blacklist=(blacklist)
304
+ command 'set_url_blacklist', *blacklist
305
+ end
306
+
261
307
  def debug=(val)
262
308
  @debug = val
263
309
  command 'set_debug', !!val
264
310
  end
265
311
 
266
312
  def command(name, *args)
267
- message = { 'name' => name, 'args' => args }
268
- log message.inspect
313
+ message = JSON.dump({ 'name' => name, 'args' => args })
314
+ log message
315
+
316
+ response = server.send(message)
317
+ log response
269
318
 
270
- json = JSON.load(server.send(JSON.dump(message)))
271
- log json.inspect
319
+ json = JSON.load(response)
272
320
 
273
321
  if json['error']
274
322
  klass = ERROR_MAPPINGS[json['error']['name']] || BrowserError
@@ -5,7 +5,7 @@ require 'cliver'
5
5
  module Capybara::Poltergeist
6
6
  class Client
7
7
  PHANTOMJS_SCRIPT = File.expand_path('../client/compiled/main.js', __FILE__)
8
- PHANTOMJS_VERSION = ['~> 1.8','>= 1.8.1']
8
+ PHANTOMJS_VERSION = ['>= 1.8.1', '< 3.0']
9
9
  PHANTOMJS_NAME = 'phantomjs'
10
10
 
11
11
  KILL_TIMEOUT = 2 # seconds
@@ -99,13 +99,13 @@ module Capybara::Poltergeist
99
99
  # it works with JRuby but I've experienced strange mistakes on Rubinius.
100
100
  def redirect_stdout
101
101
  prev = STDOUT.dup
102
- prev.autoclose = false
103
102
  $stdout = @write_io
104
103
  STDOUT.reopen(@write_io)
105
104
  yield
106
105
  ensure
107
106
  STDOUT.reopen(prev)
108
107
  $stdout = STDOUT
108
+ prev.close
109
109
  end
110
110
 
111
111
  def kill_phantomjs
@@ -25,7 +25,7 @@ class PoltergeistAgent
25
25
  throw error
26
26
 
27
27
  currentUrl: ->
28
- encodeURI(window.location.href)
28
+ encodeURI(decodeURI(window.location.href))
29
29
 
30
30
  find: (method, selector, within = document) ->
31
31
  try
@@ -48,8 +48,8 @@ class PoltergeistAgent
48
48
  @elements.length - 1
49
49
 
50
50
  documentSize: ->
51
- height: document.documentElement.scrollHeight,
52
- width: document.documentElement.scrollWidth
51
+ height: document.documentElement.scrollHeight || document.documentElement.clientHeight,
52
+ width: document.documentElement.scrollWidth || document.documentElement.clientWidth
53
53
 
54
54
  get: (id) ->
55
55
  @nodes[id] or= new PoltergeistAgent.Node(this, @elements[id])
@@ -65,6 +65,9 @@ class PoltergeistAgent
65
65
  afterUpload: (id) ->
66
66
  this.get(id).removeAttribute('_poltergeist_selected')
67
67
 
68
+ clearLocalStorage: ->
69
+ localStorage.clear()
70
+
68
71
  class PoltergeistAgent.ObsoleteNode
69
72
  toString: -> "PoltergeistAgent.ObsoleteNode"
70
73
 
@@ -75,7 +78,8 @@ class PoltergeistAgent.Node
75
78
  @EVENTS = {
76
79
  FOCUS: ['blur', 'focus', 'focusin', 'focusout'],
77
80
  MOUSE: ['click', 'dblclick', 'mousedown', 'mouseenter', 'mouseleave', 'mousemove',
78
- 'mouseover', 'mouseout', 'mouseup']
81
+ 'mouseover', 'mouseout', 'mouseup', 'contextmenu'],
82
+ FORM: ['submit']
79
83
  }
80
84
 
81
85
  constructor: (@agent, @element) ->
@@ -83,6 +87,14 @@ class PoltergeistAgent.Node
83
87
  parentId: ->
84
88
  @agent.register(@element.parentNode)
85
89
 
90
+ parentIds: ->
91
+ ids = []
92
+ parent = @element.parentNode
93
+ while parent != document
94
+ ids.push @agent.register(parent)
95
+ parent = parent.parentNode
96
+ ids
97
+
86
98
  find: (method, selector) ->
87
99
  @agent.find(method, selector, @element)
88
100
 
@@ -136,17 +148,25 @@ class PoltergeistAgent.Node
136
148
  @element.textContent
137
149
 
138
150
  visibleText: ->
139
- if @element.nodeName == "TEXTAREA"
140
- @element.textContent
141
- else
142
- @element.innerText
151
+ if this.isVisible()
152
+ if @element.nodeName == "TEXTAREA"
153
+ @element.textContent
154
+ else
155
+ @element.innerText
143
156
 
144
157
  deleteText: ->
145
158
  range = document.createRange()
146
159
  range.selectNodeContents(@element)
160
+ window.getSelection().removeAllRanges()
147
161
  window.getSelection().addRange(range)
148
162
  window.getSelection().deleteFromDocument()
149
163
 
164
+ getAttributes: ->
165
+ attrs = {}
166
+ for attr, i in @element.attributes
167
+ attrs[attr.name] = attr.value.replace("\n","\\n");
168
+ attrs
169
+
150
170
  getAttribute: (name) ->
151
171
  if name == 'checked' || name == 'selected'
152
172
  @element[name]
@@ -219,6 +239,16 @@ class PoltergeistAgent.Node
219
239
  isDisabled: ->
220
240
  @element.disabled || @element.tagName == 'OPTION' && @element.parentNode.disabled
221
241
 
242
+ containsSelection: ->
243
+ selectedNode = document.getSelection().focusNode
244
+
245
+ return false if !selectedNode
246
+
247
+ if selectedNode.nodeType == 3
248
+ selectedNode = selectedNode.parentNode
249
+
250
+ @element.contains(selectedNode)
251
+
222
252
  frameOffset: ->
223
253
  win = window
224
254
  offset = { top: 0, left: 0 }
@@ -257,13 +287,19 @@ class PoltergeistAgent.Node
257
287
  false, false, false, false, 0, null
258
288
  )
259
289
  else if Node.EVENTS.FOCUS.indexOf(name) != -1
260
- event = document.createEvent('HTMLEvents')
261
- event.initEvent(name, true, true)
290
+ event = this.obtainEvent(name)
291
+ else if Node.EVENTS.FORM.indexOf(name) != -1
292
+ event = this.obtainEvent(name)
262
293
  else
263
294
  throw "Unknown event"
264
295
 
265
296
  @element.dispatchEvent(event)
266
297
 
298
+ obtainEvent: (name) ->
299
+ event = document.createEvent('HTMLEvents')
300
+ event.initEvent(name, true, true)
301
+ event
302
+
267
303
  mouseEventTest: (x, y) ->
268
304
  frameOffset = this.frameOffset()
269
305