poltergeist-cj 1.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. data/LICENSE +20 -0
  2. data/README.md +434 -0
  3. data/lib/capybara/poltergeist.rb +27 -0
  4. data/lib/capybara/poltergeist/browser.rb +339 -0
  5. data/lib/capybara/poltergeist/client.rb +151 -0
  6. data/lib/capybara/poltergeist/client/agent.coffee +374 -0
  7. data/lib/capybara/poltergeist/client/browser.coffee +393 -0
  8. data/lib/capybara/poltergeist/client/compiled/agent.js +535 -0
  9. data/lib/capybara/poltergeist/client/compiled/browser.js +526 -0
  10. data/lib/capybara/poltergeist/client/compiled/connection.js +25 -0
  11. data/lib/capybara/poltergeist/client/compiled/main.js +204 -0
  12. data/lib/capybara/poltergeist/client/compiled/node.js +77 -0
  13. data/lib/capybara/poltergeist/client/compiled/web_page.js +421 -0
  14. data/lib/capybara/poltergeist/client/connection.coffee +11 -0
  15. data/lib/capybara/poltergeist/client/main.coffee +89 -0
  16. data/lib/capybara/poltergeist/client/node.coffee +57 -0
  17. data/lib/capybara/poltergeist/client/web_page.coffee +297 -0
  18. data/lib/capybara/poltergeist/cookie.rb +35 -0
  19. data/lib/capybara/poltergeist/driver.rb +278 -0
  20. data/lib/capybara/poltergeist/errors.rb +178 -0
  21. data/lib/capybara/poltergeist/inspector.rb +46 -0
  22. data/lib/capybara/poltergeist/json.rb +25 -0
  23. data/lib/capybara/poltergeist/network_traffic.rb +6 -0
  24. data/lib/capybara/poltergeist/network_traffic/request.rb +26 -0
  25. data/lib/capybara/poltergeist/network_traffic/response.rb +40 -0
  26. data/lib/capybara/poltergeist/node.rb +154 -0
  27. data/lib/capybara/poltergeist/server.rb +36 -0
  28. data/lib/capybara/poltergeist/utility.rb +9 -0
  29. data/lib/capybara/poltergeist/version.rb +5 -0
  30. data/lib/capybara/poltergeist/web_socket_server.rb +96 -0
  31. metadata +285 -0
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011-2014 Jonathan Leighton
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,434 @@
1
+ # Poltergeist - A PhantomJS driver for Capybara #
2
+
3
+ [![Build Status](https://secure.travis-ci.org/teampoltergeist/poltergeist.png)](http://travis-ci.org/teampoltergeist/poltergeist)
4
+
5
+ Poltergeist is a driver for [Capybara](https://github.com/jnicklas/capybara). It allows you to
6
+ run your Capybara tests on a headless [WebKit](http://webkit.org) browser,
7
+ provided by [PhantomJS](http://www.phantomjs.org/).
8
+
9
+ **If you're viewing this at https://github.com/teampoltergeist/poltergeist,
10
+ you're reading the documentation for the master branch.
11
+ [View documentation for the latest release
12
+ (1.5.1).](https://github.com/teampoltergeist/poltergeist/tree/v1.5.1)**
13
+
14
+ ## Getting help ##
15
+
16
+ Questions should be posted [on Stack
17
+ Overflow, using the 'poltergeist' tag](http://stackoverflow.com/questions/tagged/poltergeist).
18
+
19
+ Bug reports should be posted [on
20
+ GitHub](https://github.com/teampoltergeist/poltergeist/issues) (and be sure
21
+ to read the bug reporting guidance below).
22
+
23
+ ## Installation ##
24
+
25
+ Add `poltergeist` to your Gemfile, and in your test setup add:
26
+
27
+ ``` ruby
28
+ require 'capybara/poltergeist'
29
+ Capybara.javascript_driver = :poltergeist
30
+ ```
31
+
32
+ If you were previously using the `:rack_test` driver, be aware that
33
+ your app will now run in a separate thread and this can have
34
+ consequences for transactional tests. [See the Capybara README for more
35
+ detail](https://github.com/jnicklas/capybara/blob/master/README.md#transactions-and-database-setup).
36
+
37
+ ## Installing PhantomJS ##
38
+
39
+ You need at least PhantomJS 1.8.1. There are *no other external
40
+ dependencies* (you don't need Qt, or a running X server, etc.)
41
+
42
+ ### Mac ###
43
+
44
+ * *Homebrew*: `brew install phantomjs`
45
+ * *MacPorts*: `sudo port install phantomjs`
46
+ * *Manual install*: [Download this](https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-1.9.7-macosx.zip)
47
+
48
+ ### Linux ###
49
+
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
+ binary.
53
+ * Extract the tarball and copy `bin/phantomjs` into your `PATH`
54
+
55
+ ### Windows ###
56
+ * Download the [precompiled binary](https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-1.9.7-windows.zip)
57
+ for Windows
58
+
59
+ ### Manual compilation ###
60
+
61
+ Do this as a last resort if the binaries don't work for you. It will
62
+ take quite a long time as it has to build WebKit.
63
+
64
+ * Download [the source tarball](https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-1.9.7-source.zip)
65
+ * Extract and cd in
66
+ * `./build.sh`
67
+
68
+ (See also the [PhantomJS building
69
+ guide](http://phantomjs.org/build.html).)
70
+
71
+ ## Compatibility ##
72
+
73
+ Poltergeist runs on MRI 1.9, JRuby 1.9 and Rubinius 1.9. Poltergeist
74
+ and PhantomJS are currently supported on Mac OS X, Linux, and Windows
75
+ platforms.
76
+
77
+ Ruby 1.8 is no longer supported. The last release to support Ruby 1.8
78
+ was 1.0.2, so you should use that if you still need Ruby 1.8 support.
79
+
80
+ ## Running on a CI ##
81
+
82
+ There are no special steps to take. You don't need Xvfb or any running X
83
+ server at all.
84
+
85
+ [Travis CI](https://travis-ci.org/) has PhantomJS pre-installed.
86
+
87
+ Depending on your tests, one thing that you may need is some fonts. If
88
+ you're getting errors on a CI that don't occur during development then
89
+ try taking some screenshots - it may well be missing fonts throwing
90
+ things off kilter. Your distro will have various font packages available
91
+ to install.
92
+
93
+ ## What's supported? ##
94
+
95
+ Poltergeist supports all the mandatory features for a Capybara driver,
96
+ and the following optional features:
97
+
98
+ * `page.evaluate_script` and `page.execute_script`
99
+ * `page.within_frame`
100
+ * `page.within_window`
101
+ * `page.status_code`
102
+ * `page.response_headers`
103
+ * `page.save_screenshot`
104
+ * `page.driver.render_base64(format, options)`
105
+ * `page.driver.scroll_to(left, top)`
106
+ * `page.driver.basic_authorize(user, password)`
107
+ * `element.native.send_keys(*keys)`
108
+ * cookie handling
109
+ * drag-and-drop
110
+
111
+ There are some additional features:
112
+
113
+ ### Taking screenshots with some extensions ###
114
+
115
+ You can grab screenshots of the page at any point by calling
116
+ `save_screenshot('/path/to/file.png')` (this works the same way as the PhantomJS
117
+ render feature, so you can specify other extensions like `.pdf`, `.gif`, etc.)
118
+ Just in case you render pdf it's might be worth to set `driver.paper_size=` with
119
+ settings provided by PhantomJS in [here](https://github.com/ariya/phantomjs/wiki/API-Reference-WebPage#wiki-webpage-paperSize)
120
+
121
+ By default, only the viewport will be rendered (the part of the page that is in
122
+ view). To render the entire page, use `save_screenshot('/path/to/file.png',
123
+ :full => true)`.
124
+
125
+ You also have an ability to render selected element. Pass option `selector` with
126
+ any valid element selector to make a screenshot bounded by that element
127
+ `save_screenshot('/path/to/file.png', :selector => '#id')`.
128
+
129
+ If you need for some reasons base64 encoded screenshot you can simply call
130
+ `render_base64` that will return you encoded image. Additional options are the
131
+ same as for `save_screenshot` except the first argument which is format (:png by
132
+ default, acceptable :png, :gif, :jpeg).
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
+ ### Clicking precise coordinates ###
140
+
141
+ Sometimes its desirable to click a very specific area of the screen. You can accomplish this with
142
+ `page.driver.click(x, y)`, where x and y are the screen coordinates.
143
+
144
+ ### Remote debugging (experimental) ###
145
+
146
+ If you use the `:inspector => true` option (see below), remote debugging
147
+ will be enabled.
148
+
149
+ When this option is enabled, you can insert `page.driver.debug` into
150
+ your tests to pause the test and launch a browser which gives you the
151
+ WebKit inspector to view your test run with.
152
+
153
+ You can register this debugger driver with a different name and set it
154
+ as the current javascript driver. By example, in your helper file:
155
+
156
+ ```ruby
157
+ Capybara.register_driver :poltergeist_debug do |app|
158
+ Capybara::Poltergeist::Driver.new(app, :inspector => true)
159
+ end
160
+
161
+ # Capybara.javascript_driver = :poltergeist
162
+ Capybara.javascript_driver = :poltergeist_debug
163
+ ```
164
+
165
+ [Read more
166
+ here](http://jonathanleighton.com/articles/2012/poltergeist-0-6-0/)
167
+
168
+ ### Manipulating request headers ###
169
+
170
+ You can manipulate HTTP request headers with these methods:
171
+
172
+ ``` ruby
173
+ page.driver.headers # => {}
174
+ page.driver.headers = { "User-Agent" => "Poltergeist" }
175
+ page.driver.add_headers("Referer" => "https://example.com")
176
+ page.driver.headers # => { "User-Agent" => "Poltergeist", "Referer" => "https://example.com" }
177
+ ```
178
+
179
+ Notice that `headers=` will overwrite already set headers. You should use
180
+ `add_headers` if you want to add a few more. These headers will apply to all
181
+ subsequent HTTP requests (including requests for assets, AJAX, etc). They will
182
+ be automatically cleared at the end of the test. You have ability to set headers
183
+ only for the initial request:
184
+
185
+ ``` ruby
186
+ page.driver.headers = { "User-Agent" => "Poltergeist" }
187
+ page.driver.add_header("Referer", "http://example.com", permanent: false)
188
+ page.driver.headers # => { "User-Agent" => "Poltergeist", "Referer" => "http://example.com" }
189
+ visit(login_path)
190
+ page.driver.headers # => { "User-Agent" => "Poltergeist" }
191
+ ```
192
+
193
+ This way your temporary headers will be sent only for the initial request, all
194
+ subsequent request will only contain your permanent headers.
195
+
196
+ ### Inspecting network traffic ###
197
+
198
+ You can inspect the network traffic (i.e. what resources have been
199
+ loaded) on the current page by calling `page.driver.network_traffic`.
200
+ This returns an array of request objects. A request object has a
201
+ `response_parts` method containing data about the response chunks.
202
+ Please note that network traffic is not cleared when you visit new page.
203
+ You can manually clear the network traffic by calling `page.driver.clear_network_traffic`
204
+ or `page.driver.reset`
205
+
206
+ ### Manipulating cookies ###
207
+
208
+ The following methods are used to inspect and manipulate cookies:
209
+
210
+ * `page.driver.cookies` - a hash of cookies accessible to the current
211
+ page. The keys are cookie names. The values are `Cookie` objects, with
212
+ the following methods: `name`, `value`, `domain`, `path`, `secure?`,
213
+ `httponly?`, `expires`.
214
+ * `page.driver.set_cookie(name, value, options = {})` - set a cookie.
215
+ The options hash can take the following keys: `:domain`, `:path`,
216
+ `:secure`, `:httponly`, `:expires`. `:expires` should be a `Time`
217
+ object.
218
+ * `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
+ ```
244
+
245
+ ### Sending keys ###
246
+
247
+ There's an ability to send arbitrary keys to the element:
248
+
249
+ ``` ruby
250
+ element = find('input#id')
251
+ element.native.send_key('String')
252
+ ```
253
+
254
+ or even more complicated:
255
+
256
+ ``` ruby
257
+ element.native.send_keys('H', 'elo', :Left, 'l') # => 'Hello'
258
+ element.native.send_key(:Enter) # triggers Enter key
259
+ ```
260
+ Since it's implemented natively in PhantomJS this will exactly imitate user
261
+ behavior.
262
+ See more about [sendEvent](http://phantomjs.org/api/webpage/method/send-event.html) and
263
+ [PhantomJS keys](https://github.com/ariya/phantomjs/commit/cab2635e66d74b7e665c44400b8b20a8f225153a)
264
+
265
+ ## Customization ##
266
+
267
+ You can customize the way that Capybara sets up Poltegeist via the following code in your
268
+ test setup:
269
+
270
+ ``` ruby
271
+ Capybara.register_driver :poltergeist do |app|
272
+ Capybara::Poltergeist::Driver.new(app, options)
273
+ end
274
+ ```
275
+
276
+ `options` is a hash of options. The following options are supported:
277
+
278
+ * `:phantomjs` (String) - A custom path to the phantomjs executable
279
+ * `:debug` (Boolean) - When true, debug output is logged to `STDERR`.
280
+ Some debug info from the PhantomJS portion of Poltergeist is also
281
+ output, but this goes to `STDOUT` due to technical limitations.
282
+ * `:logger` (Object responding to `puts`) - When present, debug output is written to this object
283
+ * `:phantomjs_logger` (`IO` object) - Where the `STDOUT` from PhantomJS is written to. This is
284
+ where your `console.log` statements will show up. Default: `STDOUT`
285
+ * `:timeout` (Numeric) - The number of seconds we'll wait for a response
286
+ when communicating with PhantomJS. Default is 30.
287
+ * `:inspector` (Boolean, String) - See 'Remote Debugging', above.
288
+ * `:js_errors` (Boolean) - When false, Javascript errors do not get re-raised in Ruby.
289
+ * `:window_size` (Array) - The dimensions of the browser window in which to test, expressed
290
+ 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)
292
+ to be passed to PhantomJS, e.g. `['--load-images=no', '--ignore-ssl-errors=yes']`
293
+ * `:extensions` (Array) - An array of JS files to be preloaded into
294
+ the phantomjs browser. Useful for faking unsupported APIs.
295
+ * `:port` (Fixnum) - The port which should be used to communicate
296
+ with the PhantomJS process. Defaults to a random open port.
297
+
298
+ ## Troubleshooting ##
299
+
300
+ Unfortunately, the nature of full-stack testing is that things can and
301
+ do go wrong from time to time. This section aims to highlight a number
302
+ of common problems and provide ideas about how you can work around them.
303
+
304
+ ### DeadClient errors ###
305
+
306
+ Sometimes PhantomJS crashes during a test. There are basically two kinds
307
+ of crashes: those that can be reproduced every time, and those that
308
+ occur sporadically and are not easily reproduced.
309
+
310
+ If your crash happens every time, you should read the [PhantomJS crash
311
+ reporting
312
+ guide](http://phantomjs.org/crash-reporting.html) and file
313
+ a bug against PhantomJS. Feel free to also file a bug against
314
+ Poltergeist in case there are workarounds that can be implemented within
315
+ Poltergeist. Also, if lots of Poltergeist users are experiencing the
316
+ same crash then fixing it will move up the priority list.
317
+
318
+ If your crash is sporadic, there is less that can be done. Often these
319
+ issues are very complicated and difficult to track down. It may be that
320
+ the crash has already been fixed in a newer version of WebKit that will
321
+ eventually find its way into PhantomJS. It's still worth reporting your
322
+ bug against PhantomJS, but it's probably not worth filing a bug against
323
+ Poltergeist as there's not much we can do.
324
+
325
+ If you experience sporadic crashes a lot, it may be worth configuring
326
+ your CI to automatically re-run failing tests before reporting a failed
327
+ build.
328
+
329
+ ### MouseEventFailed errors ###
330
+
331
+ When Poltergeist clicks on an element, rather than generating a DOM
332
+ click event, it actually generates a "proper" click. This is much closer
333
+ to what happens when a real user clicks on the page - but it means that
334
+ Poltergeist must scroll the page to where the element is, and work out
335
+ the correct co-ordinates to click. If the element is covered up by
336
+ another element, the click will fail (this is a good thing - because
337
+ your user won't be able to click a covered up element either).
338
+
339
+ Sometimes there can be issues with this behavior. If you have problems,
340
+ it's worth taking screenshots of the page and trying to work out what's
341
+ going on. If your click is failing, but you're not getting a
342
+ `MouseEventFailed` error, then you can turn on the `:debug` option and look
343
+ in the output to see what co-ordinates Poltergeist is using for the
344
+ click. You can then cross-reference this with a screenshot to see if
345
+ something is obviously wrong.
346
+
347
+ If you can't figure out what's going on and just want to work around the
348
+ problem so you can get on with life, consider using a DOM click
349
+ event. For example, if this code is failing:
350
+
351
+ ``` ruby
352
+ click_button "Save"
353
+ ```
354
+
355
+ Then try:
356
+
357
+ ``` ruby
358
+ find_button("Save").trigger('click')
359
+ ```
360
+
361
+ ### Timing problems ###
362
+
363
+ Sometimes tests pass and fail sporadically. This is often because there
364
+ is some problem synchronising events properly. It's often
365
+ straightforward to verify this by adding `sleep` statements into your
366
+ test to allow sufficient time for the page to settle.
367
+
368
+ If you have these types of problems, read through the [Capybara
369
+ documentation on asynchronous
370
+ Javascript](https://github.com/jnicklas/capybara#asynchronous-javascript-ajax-and-friends)
371
+ which explains the tools that Capybara provides for dealing with this.
372
+
373
+ ### Memory leak ###
374
+
375
+ If you run a few capybara sessions manually please make sure you've called
376
+ `session.driver.quit` when you don't need session anymore. Forgetting about this
377
+ causes memory leakage and your system's resources can be exhausted earlier than
378
+ you may expect.
379
+
380
+ ### General troubleshooting hints ###
381
+
382
+ * Configure Poltergeist with `:debug` turned on so you can see its
383
+ communication with PhantomJS.
384
+ * Take screenshots to figure out what the state of your page is when the
385
+ problem occurs.
386
+ * Use the remote web inspector in case it provides any useful insight
387
+ * Consider downloading the Poltergeist source and using `console.log`
388
+ debugging to figure out what's going on inside PhantomJS. (This will
389
+ require an understanding of the Poltergeist source code and PhantomJS,
390
+ so it's only for the committed!)
391
+
392
+ ### Filing a bug ###
393
+
394
+ If you can provide specific steps to reproduce your problem, or have
395
+ specific information that might help other help you track down the
396
+ problem, then please file a bug on Github.
397
+
398
+ Include as much information as possible. For example:
399
+
400
+ * Specific steps to reproduce where possible (failing tests are even
401
+ better)
402
+ * The output obtained from running Poltergeist with `:debug` turned on
403
+ * Screenshots
404
+ * Stack traces if there are any Ruby on Javascript exceptions generated
405
+ * The Poltergeist and PhantomJS version numbers used
406
+ * The operating system name and version used
407
+
408
+ ## Changes ##
409
+
410
+ Version history and a list of next-release features and fixes can be found in
411
+ the [changelog](CHANGELOG.md).
412
+
413
+ ## License ##
414
+
415
+ Copyright (c) 2011-2014 Jonathan Leighton
416
+
417
+ Permission is hereby granted, free of charge, to any person obtaining
418
+ a copy of this software and associated documentation files (the
419
+ "Software"), to deal in the Software without restriction, including
420
+ without limitation the rights to use, copy, modify, merge, publish,
421
+ distribute, sublicense, and/or sell copies of the Software, and to
422
+ permit persons to whom the Software is furnished to do so, subject to
423
+ the following conditions:
424
+
425
+ The above copyright notice and this permission notice shall be
426
+ included in all copies or substantial portions of the Software.
427
+
428
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
429
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
430
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
431
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
432
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
433
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
434
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.