poltergeist 1.5.1 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
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