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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f710cbda8c2d259e3f8819259d0e207871fe7276
4
+ data.tar.gz: db63a077b1335c06eb9cd91d09c0ef81ef3f11b9
5
+ SHA512:
6
+ metadata.gz: 75f64909a5703a3a34802a01817a2b02dd76310102513208bd909cfed38cff551930793c3c07514f3efbb9a9ef5051187ba88b2189ea20c9030a0119559c4248
7
+ data.tar.gz: 20a98f89b9e22ec9d3207ce34ffdcf6bf117194669b001001bf9419ac1efd1471fda11811dbab0128a9e80adfa710d3750d10237416234eb795fd4bddb175c35
data/README.md CHANGED
@@ -105,6 +105,8 @@ and the following optional features:
105
105
  * `page.status_code`
106
106
  * `page.response_headers`
107
107
  * `page.save_screenshot`
108
+ * `page.render_base64`
109
+ * `page.scroll_to`
108
110
  * cookie handling
109
111
  * drag-and-drop
110
112
 
@@ -119,6 +121,15 @@ render feature, so you can specify other extensions like `.pdf`, `.gif`, etc.)
119
121
  By default, only the viewport will be rendered (the part of the page that is in view). To render
120
122
  the entire page, use `save_screenshot('/path/to/file.png', :full => true)`.
121
123
 
124
+ You also have an ability to render selected element. Pass option `selector` with
125
+ any valid element selector to make a screenshot bounded by that element
126
+ `save_screenshot('/path/to/file.png', :selector => '#id')`.
127
+
128
+ If you need for some reasons base64 encoded screenshot you can simply call
129
+ `render_base64` that will return you encoded image. Additional options are the
130
+ same as for `save_screenshot` except the first argument which is format (:png by
131
+ default, acceptable :png, :gif, :jpeg).
132
+
122
133
  ### Resizing the window ###
123
134
 
124
135
  Sometimes the window size is important to how things are rendered. Poltergeist sets the window
@@ -153,17 +164,33 @@ Capybara.javascript_driver = :poltergeist_debug
153
164
  [Read more
154
165
  here](http://jonathanleighton.com/articles/2012/poltergeist-0-6-0/)
155
166
 
156
- ### Setting request headers ###
167
+ ### Manipulating request headers ###
168
+
169
+ You can manipulate HTTP request headers with these methods:
170
+
171
+ ``` ruby
172
+ page.driver.headers # => {}
173
+ page.driver.headers = { "User-Agent" => "Poltergeist" }
174
+ page.driver.add_headers("Referer" => "https://example.com")
175
+ page.driver.headers # => { "User-Agent" => "Poltergeist", "Referer" => "https://example.com" }
176
+ ```
157
177
 
158
- Additional HTTP request headers can be set like so:
178
+ Notice that `headers=` will overwrite already set headers. You should use
179
+ `add_headers` if you want to add a few more. These headers will apply to all
180
+ subsequent HTTP requests (including requests for assets, AJAX, etc). They will
181
+ be automatically cleared at the end of the test. You have ability to set headers
182
+ only for the initial request:
159
183
 
160
184
  ``` ruby
161
185
  page.driver.headers = { "User-Agent" => "Poltergeist" }
186
+ page.driver.add_header("Referer", "http://example.com", permanent: false)
187
+ page.driver.headers # => { "User-Agent" => "Poltergeist", "Referer" => "http://example.com" }
188
+ visit(login_path)
189
+ page.driver.headers # => { "User-Agent" => "Poltergeist" }
162
190
  ```
163
191
 
164
- The extra headers will apply to all subsequent HTTP requests (including
165
- requests for assets, AJAX, etc). They will be automatically cleared at
166
- the end of the test.
192
+ This way your temporary headers will be sent only for the initial request, all
193
+ subsequent request will only contain your permanent headers.
167
194
 
168
195
  ### Inspecting network traffic ###
169
196
 
@@ -186,6 +213,32 @@ The following methods are used to inspect and manipulate cookies:
186
213
  object.
187
214
  * `page.driver.remove_cookie(name)` - remove a cookie
188
215
 
216
+ ### Window switching ###
217
+
218
+ The following methods can be used to execute commands inside different windows:
219
+
220
+ * `page.driver.window_handles` - an array containing the names of all
221
+ the open windows.
222
+
223
+ * `page.within_window(name) { # actions }` - executes
224
+ the passed block in the context of the named window.
225
+
226
+ Example:
227
+
228
+ ``` ruby
229
+ find_link("Login with Facebook").trigger("click")
230
+
231
+ sleep(0.1)
232
+
233
+ fb_popup = page.driver.window_handles.last
234
+ page.within_window fb_popup do
235
+ fill_in "email", :with => "facebook_email@email.tst"
236
+ fill_in "pass", :with => "my_pass"
237
+ click_button "Log In"
238
+ end
239
+ ```
240
+
241
+
189
242
  ## Customization ##
190
243
 
191
244
  You can customize the way that Capybara sets up Poltegeist via the following code in your
@@ -205,7 +258,7 @@ end
205
258
  output, but this goes to `STDOUT` due to technical limitations.
206
259
  * `:logger` (Object responding to `puts`) - When present, debug output is written to this object
207
260
  * `:phantomjs_logger` (`IO` object) - Where the `STDOUT` from PhantomJS is written to. This is
208
- where you `console.log` statements will show up. Default: `STDOUT`
261
+ where your `console.log` statements will show up. Default: `STDOUT`
209
262
  * `:timeout` (Numeric) - The number of seconds we'll wait for a response
210
263
  when communicating with PhantomJS. Default is 30.
211
264
  * `:inspector` (Boolean, String) - See 'Remote Debugging', above.
@@ -294,6 +347,13 @@ documentation on asynchronous
294
347
  Javascript](https://github.com/jnicklas/capybara#asynchronous-javascript-ajax-and-friends)
295
348
  which explains the tools that Capybara provides for dealing with this.
296
349
 
350
+ ### Memory leak ###
351
+
352
+ If you run a few capybara sessions manually please make sure you've called
353
+ `session.driver.quit` when you don't need session anymore. Forgetting about this
354
+ causes memory leakage and your system's resources can be exhausted earlier than
355
+ you may expect.
356
+
297
357
  ### General troubleshooting hints ###
298
358
 
299
359
  * Configure Poltergeist with `:debug` turned on so you can see its
@@ -324,263 +384,8 @@ Include as much information as possible. For example:
324
384
 
325
385
  ## Changes ##
326
386
 
327
- ### 1.3.0 ###
328
-
329
- #### Features ####
330
-
331
- * Add support for PhantomJS 1.7's `cookiesEnabled` API
332
- (Micah Frost)
333
-
334
- #### Bug fixes ####
335
-
336
- * Fix logging of mouse event co-ordinates
337
- * Invalid selectors throw a useful error message
338
- * Tie us to the 0.4 version of faye-websocket since the 0.5 version
339
- contains breaking changes.
340
-
341
- ### 1.2.0 ###
342
-
343
- #### Features ####
344
-
345
- * Support for Windows hosted Poltergeist (Aaron Tull).
346
- * Capybara 2.1 support
347
-
348
- #### Bug fixes ####
349
-
350
- * Reverted the "native" implementation for filling in form fields,
351
- which was introduced in 1.0. This implementation caused various bugs
352
- and in general doesn't seem to be worth the trouble at the moment.
353
- It can be reconsidered in the future when PhantomJS has upgraded its
354
- WebKit version. [Issue #176, #223]
355
- * Run phantomjs in a new process group so ^C doesn't trigger a
356
- DeadClient error [Issue #252]
357
-
358
- ### 1.1.1 ###
359
-
360
- #### Features ####
361
-
362
- * Changed Capybara dependency to `~> 2.0.1` because Poltergeist 1.1 is
363
- not compatible with Capybara 2.1.
364
-
365
- ### 1.1.0 ###
366
-
367
- #### Features ####
368
-
369
- * Add support for custom phantomjs loggers via `:phantomjs_logger` option.
370
- (Gabe Bell)
371
- * Add `page.driver.click(x, y)` to click precise coordinates.
372
- (Micah Geisel)
373
- * Add Capybara 2.0 support. Capybara 1.1 and Ruby 1.8 are *no
374
- longer supported*. (Mauro Asprea) [Issue #163]
375
- * Add `node.base.double_click` to double click the node.
376
- (Andy Shen)
377
- * The `:debug` option now causes the PhantomJS portion of Poltergeist
378
- to output some additional debug info, which may be useful in
379
- figuring out timeout errors.
380
- * Add the ability to extend the phantomjs environment via browser
381
- options. e.g.
382
- `Capybara::Poltergeist::Driver.new( app, :extensions => ['file.js', 'another.js'])`
383
- (Jon Rowe)
384
-
385
- #### Bug fixes ####
386
-
387
- * Fix timing issue when using `within_frame` that could cause errors.
388
- [Issue #183, #211] (@errm, @motemen)
389
- * Fix bug with `within_frame` not properly switching the context back
390
- after the block has executed. [Issue #242]
391
- * Fix calculation of click position when clicking within a frame.
392
- [Issue #222, #225]
393
- * Fix error raising when calling `expires` if not set on cookie.
394
- [Issue #203] (@arnvald)
395
- * Fix the `:js_errors` option. Previously errors were not being
396
- reported, but would still cause commands to fail. [Issue #229]
397
- * Fix incorrect time zone handling when setting cookie expiry time
398
- [Issue #228]
399
- * Send SIGKILL to PhantomJS if it doesn't exit within 2 seconds
400
- [Issue #196]
401
- * Provide a more informative message for the `ObsoleteNode` error.
402
- [Issue #192]
403
- * Fix `ObsoleteNode` error when using `attach_file` with the `jQuery
404
- File Upload` plugin. [Issue #115]
405
- * Ensure that a `String` is passed over-the-wire to PhantomJS for
406
- file input paths, allowing `attach_file` to be called with arbitry
407
- objects such as a Pathname. (@mjtko) [Issue #215]
408
- * Cookies can now be set before the first request. [Issue #193]
409
-
410
- ### 1.0.2 ###
411
-
412
- #### Bug fixes ####
413
-
414
- * Clearing the value before setting a new value by sending a backspace.
415
- This fixes the issue that you can't set an empty value. [Issue #184]
416
-
417
- ### 1.0.1 ###
418
-
419
- #### Bug fixes ####
420
-
421
- * Don't use a fixed port number by default; find an available port.
422
- The port can still be configured to a fixed value using the `:port`
423
- option. The reverts the default behaviour to how it was before the
424
- 1.0 release. [Issue #174]
425
-
426
- ### 1.0 ###
427
-
428
- #### Features ####
429
-
430
- * Click co-ordinates are shown in the debug log. You can use this in
431
- combination with `page.driver.render` to work out where clicks are
432
- actually happening if you are having trouble.
433
- * Added `:port` configuration option and made the default port 44678
434
- rather than a random available port.
435
- * Support for Capybara's `page.response_headers` API to retrieve the
436
- headers of the last page load.
437
- * Support for cookie manipulation. [Issue #12]
438
- * Frame switching support now uses native PhantomJS APIs. (This might
439
- make it work better, but in general it's a badly tested area both in
440
- Capybara and Poltergeist.)
441
- * Support for the Capybara window switching API (`page.within_window`).
442
-
443
- #### Bug fixes ####
444
-
445
- * Prevent `TypeError: 'undefined' is not an object (evaluating
446
- 'rect.top')` error when clicking an element with `display: none`.
447
- The click will fail, but an obsolete node error will be raised, meaning
448
- that Capybara's retry mechanisms will kick in. [Issue #130]
449
- * Mouse over the element we will click, before clicking it. This
450
- enables `:hover` effects etc to trigger before the click happens,
451
- which can affect the click in some cases. [Issue #120]
452
- * Don't blow up when `evaluate_script` is called with a cyclic
453
- structure.
454
- * Fix the text method for title elements, so it doesn't return an
455
- empty string.
456
- * Fixed problem with cookies not being clearer between tests on
457
- PhantomJS 1.7
458
- * Fixed Javascript errors during page load causes TimeoutErrors.
459
- [Issue #124]
460
- * Ensure the User-Agent header can be set successfully. (Klaus Hartl)
461
- [Issue #127]
462
- * Use `el.innerText` for `Node#text`. This ensures that e.g. `<br>` is
463
- returned as a space. It also simplifies the method. [Issue #139]
464
- * Fix status code support when a response redirects to another URL.
465
- This was previously tested to ensure it would return the status code
466
- of the redirected URL, but the test was falsely broken and the
467
- implementation was also broken.
468
- * Fixed visiting URLs where only a hash change occurs (no HTTP
469
- request). [Issue #79]
470
- * Setting `page.driver.headers` now applies the headers to all
471
- requests, not just calls to `visit`. (So XHR, asset requests, etc
472
- will all receive the headers.) [Issue #149]
473
-
474
- ### 0.7 ###
475
-
476
- #### Features ####
477
-
478
- * Added an option `:js_errors`, allowing poltergeist to continue
479
- running after JS errors. (John Griffin & Tom Stuart) [Issue #62] [Issue #69]
480
- * Added an option `:window_size`, allowing users to specify
481
- dimensions to which the browser window will be resized.
482
- (Tom Stuart) [Issue #53]
483
- * Capybara 1.0 is no longer supported. Capybara ~> 1.1 is required.
484
- * Added ability to set arbitrary http request headers
485
- * Inspect network traffic on the page via
486
- `page.driver.network_traffic` (Doug McInnes) [Issue #77]
487
- * Added an option `:phantomjs_options`, allowing users to specify
488
- additional command-line options passed to phantomjs executable.
489
- (wynst) [Issue #97]
490
- * Scroll element into viewport if needed on click (Gabriel Sobrinho)
491
- [Issue #83]
492
- * Added status code support. (Dmitriy Nesteryuk and Jon Leighton) [Issue #37]
493
-
494
- #### Bug fixes ###
495
-
496
- * Fix issue with `ClickFailed` exception happening with a negative
497
- co-ordinate (which should be impossible). (Jon Leighton, Gabriel
498
- Sobrinho, Tom Stuart) [Issue #60]
499
- * Fix issue with `undefined method map for "[]":String`, which
500
- happened when dealing with pages that include JS rewriting
501
- Array.prototype.toJSON. (Tom Stuart) [Issue #63]
502
-
503
- ### 0.6 ###
504
-
505
- #### Features ####
506
-
507
- * Updated to PhantomJS 1.5.0, giving us proper support for reporting
508
- Javascript exception backtraces.
509
-
510
- ### 0.5 ###
511
-
512
- #### Features ####
513
-
514
- * Detect if clicking an element will fail. If the click will actually
515
- hit another element (because that element is in front of the one we
516
- want to click), the user will now see an exception explaining what
517
- happened and which element would actually be targeted by the click. This
518
- should aid debugging. [Issue #25]
519
- * Click elements at their middle position rather than the top-left.
520
- This is presumed to be more likely to succeed because the top-left
521
- may be obscured by overlapping elements, negative margins, etc. [Issue #26]
522
- * Add experimental support for using the remote WebKit web inspector.
523
- This will only work with PhantomJS 1.5, which is not yet released,
524
- so it won't be officially supported by Poltergeist until 1.5 is
525
- released. [Issue #31]
526
- * Add `page.driver.quit` method. If you spawn additional Capybara
527
- sessions, you might want to use this to reap the child phantomjs
528
- process. [Issue #24]
529
- * Errors produced by Javascript on the page will now generate an
530
- exception within Ruby. [Issue #27]
531
- * JRuby support. [Issue #20]
532
-
533
- #### Bug fixes ####
534
-
535
- * Fix bug where we could end up interacting with an obsolete element. [Issue #30]
536
- * Raise an suitable error if PhantomJS returns a non-zero exit status.
537
- Previously a version error would be raised, indicating that the
538
- PhantomJS version was too old when in fact it did not start at all. [Issue #23]
539
- * Ensure the `:timeout` option is actually used. [Issue #36]
540
- * Nodes need to know which page they are associated with. Before this,
541
- if Javascript caused a new page to load, existing node references
542
- would be wrong, but wouldn't raise an ObsoleteNode error. [Issue #39]
543
- * In some circumstances, we could end up missing an inline element
544
- when attempting to click it. This is due to the use of
545
- `getBoundingClientRect()`. We're now using `getClientRects()` to
546
- address this.
547
-
548
- ### 0.4 ###
549
-
550
- * Element click position is now calculated using the native
551
- `getBoundingClientRect()` method, which will be faster and less
552
- buggy.
553
- * Handle `window.confirm()`. Always returns true, which is the same
554
- as capybara-webkit. [Issue #10]
555
- * Handle `window.prompt()`. Returns the default value, if present, or
556
- null.
557
- * Fix bug with page Javascript page loading causing problems. [Issue #19]
558
-
559
- ### 0.3 ###
560
-
561
- * There was a bad bug to do with clicking elements in a page where the
562
- page is smaller than the window. The incorrect position would be
563
- calculated, and so the click would happen in the wrong place. This is
564
- fixed. [Issue #8]
565
- * Poltergeist didn't work in conjunction with the Thin web server,
566
- because that server uses Event Machine, and Poltergeist was assuming
567
- that it was the only thing in the process using EventMachine.
568
-
569
- To solve this, EventMachine usage has been completely removed, which
570
- has the welcome side-effect of being more efficient because we
571
- no longer have the overhead of running a mostly-idle event loop.
572
-
573
- [Issue #6]
574
- * Added the `:timeout` option to configure the timeout when talking to
575
- PhantomJS.
576
-
577
- ### 0.2 ###
578
-
579
- * First version considered 'ready', hopefully fewer problems.
580
-
581
- ### 0.1 ###
582
-
583
- * First version, various problems.
387
+ Version history and a list of next-release features and fixes can be found in
388
+ the [changelog](CHANGELOG.md).
584
389
 
585
390
  ## License ##
586
391
 
@@ -15,6 +15,7 @@ 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'
18
19
  require 'capybara/poltergeist/network_traffic'
19
20
  require 'capybara/poltergeist/errors'
20
21
  require 'capybara/poltergeist/cookie'
@@ -1,5 +1,5 @@
1
1
  require "capybara/poltergeist/errors"
2
- require 'json'
2
+ require 'multi_json'
3
3
  require 'time'
4
4
 
5
5
  module Capybara::Poltergeist
@@ -118,6 +118,10 @@ module Capybara::Poltergeist
118
118
  command 'pop_frame'
119
119
  end
120
120
 
121
+ def window_handles
122
+ command 'pages'
123
+ end
124
+
121
125
  def within_window(name, &block)
122
126
  command 'push_window', name
123
127
  yield
@@ -153,8 +157,18 @@ module Capybara::Poltergeist
153
157
  command 'reset'
154
158
  end
155
159
 
160
+ def scroll_to(left, top)
161
+ command 'scroll_to', left, top
162
+ end
163
+
156
164
  def render(path, options = {})
157
- command 'render', path.to_s, !!options[:full]
165
+ check_render_options!(options)
166
+ command 'render', path.to_s, !!options[:full], options[:selector]
167
+ end
168
+
169
+ def render_base64(format, options = {})
170
+ check_render_options!(options)
171
+ command 'render_base64', format.to_s, !!options[:full], options[:selector]
158
172
  end
159
173
 
160
174
  def resize(width, height)
@@ -174,10 +188,22 @@ module Capybara::Poltergeist
174
188
  command('equals', page_id, id, other_id)
175
189
  end
176
190
 
191
+ def get_headers
192
+ command 'get_headers'
193
+ end
194
+
177
195
  def set_headers(headers)
178
196
  command 'set_headers', headers
179
197
  end
180
198
 
199
+ def add_headers(headers)
200
+ command 'add_headers', headers
201
+ end
202
+
203
+ def add_header(header, permanent)
204
+ command 'add_header', header, permanent
205
+ end
206
+
181
207
  def response_headers
182
208
  command 'response_headers'
183
209
  end
@@ -221,7 +247,7 @@ module Capybara::Poltergeist
221
247
  message = { 'name' => name, 'args' => args }
222
248
  log message.inspect
223
249
 
224
- json = JSON.load(server.send(JSON.generate(message)))
250
+ json = JSON.load(server.send(JSON.dump(message)))
225
251
  log json.inspect
226
252
 
227
253
  if json['error']
@@ -240,5 +266,12 @@ module Capybara::Poltergeist
240
266
  def log(message)
241
267
  logger.puts message if logger
242
268
  end
269
+
270
+ def check_render_options!(options)
271
+ if !!options[:full] && options.has_key?(:selector)
272
+ warn "Ignoring :selector in #render since :full => true was given at #{caller.first}"
273
+ options.delete(:selector)
274
+ end
275
+ end
243
276
  end
244
277
  end