Commit 6034ce18 6034ce18de6206892c671bfb148d662039a42de5 by Nicolas Perriault

local docs - fixes #393

1 parent 354aed31
1 .PHONY: all default
2
3 default: all
4
5 all: build open
6
7 build:
8 sphinx-build . _build
9
10 open:
11 open _build/index.html
12
13
1 CasperJS Sphinx Documentation
2 =============================
3
4 Sphinx documentation for [CasperJS](http://casperjs.org/) 1.1-DEV and future
5 versions. Work in progress.
1 - credits jeremy (logo)
No preview for this file type
1 <h3>Donate</h3>
2 <div class="donate">
3 <div class="paypal">
4 <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
5 <input type="hidden" name="cmd" value="_s-xclick">
6 <input type="hidden" name="encrypted" value="-----BEGIN PKCS7-----MIIHRwYJKoZIhvcNAQcEoIIHODCCBzQCAQExggEwMIIBLAIBADCBlDCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb20CAQAwDQYJKoZIhvcNAQEBBQAEgYC4JCGS/3BUKEbRk75JLTu8saEZukn/6Zl5RMoVI55A2wpXdaYcILRy3L7CC4Exu9QaUzHTqQY5livIcptZaOM+aJYYr4ltJbyRW1hvFfrp0ZKMEgUuaU3m9+KQl4kzF9mRUIb5fwTd2j0FfEOllIDYLhEs6sCf39iI8yNeHsuTqjELMAkGBSsOAwIaBQAwgcQGCSqGSIb3DQEHATAUBggqhkiG9w0DBwQIHb+LDTLRE8+AgaD85VPtS5//ZnqYKJMBxlWxI6ob8L8Zk71t9NAwDY3YB3phdkyYSQtax1QxSYz1zFdNlaN5+zlFVg3chctbR6W/kC1sf4hI+AVRm9JlwYKdPOE2FOescC7QuqwAiCZlTfdejznoE0B3aVfq4OMx2k0STtVv3Ld9prW57EtMZ7xDXIW5ss62IWpsBY8eW2VPbX/Xy8TncrpDLHzJ67OKmj/KoIIDhzCCA4MwggLsoAMCAQICAQAwDQYJKoZIhvcNAQEFBQAwgY4xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLUGF5UGFsIEluYy4xEzARBgNVBAsUCmxpdmVfY2VydHMxETAPBgNVBAMUCGxpdmVfYXBpMRwwGgYJKoZIhvcNAQkBFg1yZUBwYXlwYWwuY29tMB4XDTA0MDIxMzEwMTMxNVoXDTM1MDIxMzEwMTMxNVowgY4xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLUGF5UGFsIEluYy4xEzARBgNVBAsUCmxpdmVfY2VydHMxETAPBgNVBAMUCGxpdmVfYXBpMRwwGgYJKoZIhvcNAQkBFg1yZUBwYXlwYWwuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBR07d/ETMS1ycjtkpkvjXZe9k+6CieLuLsPumsJ7QC1odNz3sJiCbs2wC0nLE0uLGaEtXynIgRqIddYCHx88pb5HTXv4SZeuv0Rqq4+axW9PLAAATU8w04qqjaSXgbGLP3NmohqM6bV9kZZwZLR/klDaQGo1u9uDb9lr4Yn+rBQIDAQABo4HuMIHrMB0GA1UdDgQWBBSWn3y7xm8XvVk/UtcKG+wQ1mSUazCBuwYDVR0jBIGzMIGwgBSWn3y7xm8XvVk/UtcKG+wQ1mSUa6GBlKSBkTCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb22CAQAwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCBXzpWmoBa5e9fo6ujionW1hUhPkOBakTr3YCDjbYfvJEiv/2P+IobhOGJr85+XHhN0v4gUkEDI8r2/rNk1m0GA8HKddvTjyGw/XqXa+LSTlDYkqI8OwR8GEYj4efEtcRpRYBxV8KxAW93YDWzFGvruKnnLbDAF6VR5w/cCMn5hzGCAZowggGWAgEBMIGUMIGOMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxFDASBgNVBAoTC1BheVBhbCBJbmMuMRMwEQYDVQQLFApsaXZlX2NlcnRzMREwDwYDVQQDFAhsaXZlX2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNvbQIBADAJBgUrDgMCGgUAoF0wGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMTIwNjI0MTUzOTU1WjAjBgkqhkiG9w0BCQQxFgQUCTlRbQ9Lu+bilBvGXOco0qlRC/8wDQYJKoZIhvcNAQEBBQAEgYBVibaMfUxJXJkA636MBqV4iWXc/F070Tsov5/kALg++/rD5qmH5MV6U8X0H8V1bCFZMBpTtLbCQ9xgeMjaK1gaCrvUw0503tBnvuPDz4bS1dspNHE9boiBJdN5vNZGqxXKij8CgKBeHYmcyCKjywHyUfSDADt1vgb7qQ5bOIvbzA==-----END PKCS7-----">
7 <input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif" border="0" name="submit" alt="Donate" title="Donate">
8 <img alt="" border="0" src="https://www.paypalobjects.com/fr_FR/i/scr/pixel.gif" width="1" height="1">
9 </form>
10 <small>(ghosts have bills, you know)</small>
11 </div>
12 <div class="flattr">
13 <a href="http://flattr.com/thing/586241/CasperJS-a-navigation-scripting-and-testing-utility-for-PhantomJS" class="flattr" target="_blank"><img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0"></a>
14 </div>
15 </div>
1 {%- extends "basic/layout.html" %}
2 {% block extrahead %}
3 <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Asap:400,700,400italic,700italic&amp;subset=latin,latin-ext">
4 <link rel="stylesheet" title="Dark theme" href="{{ pathto('_static/casperjs-dark.css', 1) }}">
5 <link rel="alternate stylesheet" title="Light theme" href="{{ pathto('_static/casperjs-light.css', 1) }}">
6 <script type="text/javascript" src="{{ pathto('_static/style-switcher.js', 1) }}"></script>
7 {% endblock extrahead %}
1 {%- if display_toc %}
2 <h3><a href="{{ pathto(master_doc) }}">{{ _('Document Outline') }}</a></h3>
3 {{ toc }}
4 {%- endif %}
1 <h3>Index</h3>
2 <p><a href="{{ pathto('genindex') }}">Thesaurus</a></p>
3
4 {%- if show_source and has_source and sourcename %}
5 <h3>{{ _('This Page') }}</h3>
6 <ul class="this-page-menu">
7 <li><a href="{{ pathto('_sources/' + sourcename, true)|e }}"
8 rel="nofollow">{{ _('Show Source') }}</a></li>
9 {% if display_github %}
10 <li><a href="https://github.com/{{ github_user }}/{{ github_repo }}/blob/{{ github_version }}{{ conf_py_path }}{{ pagename }}.rst">
11 Show on GitHub</a></li>
12 <li><a href="https://github.com/{{ github_user }}/{{ github_repo }}/edit/{{ github_version }}{{ conf_py_path }}{{ pagename }}.rst">
13 Edit on GitHub</a></li>
14 {% endif %}
15 </ul>
16 {%- endif %}
1 /**
2 * casper.css
3 * ~~~~~~~~~~~~~~~
4 *
5 * CasperJS stylesheet, based on RTD one:
6 *
7 * Sphinx stylesheet -- sphinxdoc theme. Originally created by
8 * Armin Ronacher for Werkzeug.
9 *
10 * Customized for ReadTheDocs by Eric Pierce & Eric Holscher
11 *
12 * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
13 * :license: BSD, see LICENSE for details.
14 *
15 */
16
17 @import url("basic.css");
18
19 /* PAGE LAYOUT -------------------------------------------------------------- */
20
21 body {
22 font: 100%/1.5 Asap, "ff-meta-web-pro-1", "ff-meta-web-pro-2", Arial, "Helvetica Neue", sans-serif;
23 text-align: center;
24 color: #fff;
25 background-color: #222;
26 padding: 0;
27 margin: 0;
28 }
29
30 img {
31 border: 0;
32 max-width: 100%;
33 }
34
35 .body > .admonition.note {
36 margin: 0 0 2em 0;
37 }
38 .body > .admonition.note .first {
39 display: none;
40 }
41
42 div.document {
43 text-align: left;
44 background-color: #333;
45 }
46
47 div.bodywrapper {
48 background: #111 url(images/bg.png);
49 border-left: 1px solid #333;
50 border-bottom: 1px solid #333;
51 margin: 0 18em 0 0;
52 }
53
54 div.body {
55 margin: 0;
56 padding: 0.5em 1.3em;
57 min-width: 20em;
58 }
59
60 div.related {
61 font-size: 1em;
62 background-color: #465158;
63 }
64
65 div.documentwrapper {
66 float: left;
67 width: 100%;
68 background-color: #333;
69 }
70
71
72 /* HEADINGS --------------------------------------------------------------- */
73
74 h1 {
75 margin: 0;
76 padding: 0 0 0.3em 0;
77 font-size: 2em;
78 line-height: 1.15;
79 color: #fff;
80 clear: both;
81 }
82
83 h2 {
84 margin: 2em 0 0.2em 0;
85 font-size: 1.35em;
86 padding: 0;
87 color: #fff;
88 }
89 .section h2 {
90 border-bottom: 3px solid #777;
91 margin-top: 2.5em
92 }
93
94 h3 {
95 margin: 1em 0 -0.3em 0;
96 font-size: 1.2em;
97 color: #fff;
98 }
99
100 div.body h1 a, div.body h2 a, div.body h3 a, div.body h4 a, div.body h5 a, div.body h6 a {
101 color: #fff;
102 }
103
104 h1 a.anchor, h2 a.anchor, h3 a.anchor, h4 a.anchor, h5 a.anchor, h6 a.anchor {
105 display: none;
106 margin: 0 0 0 0.3em;
107 padding: 0 0.2em 0 0.2em;
108 color: #333 !important;
109 }
110
111 h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor,
112 h5:hover a.anchor, h6:hover a.anchor {
113 display: inline;
114 }
115
116 h1 a.anchor:hover, h2 a.anchor:hover, h3 a.anchor:hover, h4 a.anchor:hover,
117 h5 a.anchor:hover, h6 a.anchor:hover {
118 color: #777;
119 background-color: #eee;
120 }
121
122
123 /* LINKS ------------------------------------------------------------------ */
124
125 /* Normal links get a pseudo-underline */
126 a {
127 color: #0bc;
128 text-decoration: none;
129 }
130 a.reference, a.internal {
131 color: #abf;
132 }
133
134 a.reference em, a.internal em {
135 font-style: normal;
136 }
137
138 /* Links in sidebar, TOC, index trees and tables have no underline */
139 .sphinxsidebar a,
140 .toctree-wrapper a,
141 .indextable a,
142 #indices-and-tables a {
143 color: #0bc;
144 text-decoration: none;
145 border-bottom: none;
146 }
147
148 /* Most links get an underline-effect when hovered */
149 a:hover,
150 div.toctree-wrapper a:hover,
151 .indextable a:hover,
152 #indices-and-tables a:hover {
153 color: #2be;
154 text-decoration: none;
155 }
156
157 /*toctree dedicated styles*/
158 div.toctree-wrapper ul {
159 list-style-type: none;
160 padding-left: 2em;
161 }
162
163 div.toctree-wrapper ul ul {
164 margin-top: .5em;
165 }
166
167 div.toctree-wrapper li {
168 margin-bottom: .5em;
169 }
170 div.toctree-wrapper a, .toctree-wrapper a:visited {
171 padding: .2em .4em;
172 background-color: #555;
173 color:#fff;
174 -webkit-border-radius: 4px;
175 -moz-border-radius: 4px;
176 border-radius: 4px;
177 }
178 div.toctree-wrapper a:hover {
179 color: #eee;
180 background-color: #777;
181 }
182
183 /* Footer links */
184 div.footer a {
185 color: #0bc;
186 text-decoration: none;
187 border: none;
188 }
189 div.footer a:hover {
190 color: #2be;
191 border: none;
192 }
193
194 /* Permalink anchor (subtle grey with a red hover) */
195 div.body a.headerlink {
196 color: #ccc;
197 font-size: 1em;
198 margin-left: 6px;
199 padding: 0 4px 0 4px;
200 text-decoration: none;
201 border: none;
202 }
203 div.body a.headerlink:hover {
204 color: #fff;
205 border: none;
206 }
207
208
209 /* NAVIGATION BAR --------------------------------------------------------- */
210
211 div.related ul {
212 height: 2.5em;
213 min-height: 2.5em;
214 background-color: #2c2c2c;
215 background-image: -moz-linear-gradient(top, #333333, #222222);
216 background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222));
217 background-image: -webkit-linear-gradient(top, #333333, #222222);
218 background-image: -o-linear-gradient(top, #333333, #222222);
219 background-image: linear-gradient(to bottom, #333333, #222222);
220 background-repeat: repeat-x;
221 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff333333', endColorstr='#ff222222', GradientType=0);
222 border-bottom: 1px solid #222;
223 -moz-border-radius: 4px;
224 -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
225 -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
226 box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
227 *zoom: 1;
228 }
229
230 div.related ul li {
231 margin: 0;
232 padding: 0.65em 0;
233 float: left;
234 display: block;
235 color: white; /* For the >> separators */
236 font-size: 0.8em;
237 }
238
239 div.related ul li.right {
240 float: right;
241 margin-right: 5px;
242 color: transparent; /* Hide the | separators */
243 }
244
245 /* "Breadcrumb" links in nav bar */
246 div.related ul li a {
247 order: none;
248 background-color: inherit;
249 font-weight: bold;
250 margin: 6px 0 6px 4px;
251 line-height: 1.75em;
252 color: #ffffff;
253 padding: 0.4em 0.8em;
254 border: none;
255 border-radius: 3px;
256 }
257 /* previous / next / modules / index links look more like buttons */
258 div.related ul li.right a {
259 margin: 0.375em 0;
260 background-color: #555;
261 text-shadow: 0 1px rgba(0, 0, 0, 0.5);
262 border-radius: 3px;
263 -webkit-border-radius: 3px;
264 -moz-border-radius: 3px;
265 }
266 /* All navbar links light up as buttons when hovered */
267 div.related ul li a:hover {
268 background-color: #777;
269 color: #fff;
270 text-decoration: none;
271 border-radius: 3px;
272 -webkit-border-radius: 3px;
273 -moz-border-radius: 3px;
274 }
275 /* Take extra precautions for tt within links */
276 a tt,
277 div.related ul li a tt {
278 background: inherit !important;
279 color: inherit !important;
280 }
281
282 .sphinxsidebar a tt span.pre {
283 color: #eee;
284 background-color: #444;
285 padding: 0 .5em;
286 border-radius: 4px;
287 }
288
289 .sphinxsidebar a:active tt span.pre {
290 color: #f66;
291 }
292
293
294 /* SIDEBAR ---------------------------------------------------------------- */
295
296 div.sphinxsidebarwrapper {
297 padding: 0;
298 }
299
300 div.sphinxsidebar {
301 margin: 0;
302 margin-left: -100%;
303 float: right;
304 top: 3em;
305 left: 0;
306 padding: 0 1em;
307 width: 18em;
308 font-size: 90%;
309
310 }
311
312 div.sphinxsidebar img {
313 max-width: 12em;
314 }
315
316 div.sphinxsidebar input[type="image"] {
317 display: inline;
318 float: none;
319 border: 0;
320 }
321
322 div.sphinxsidebar h3,
323 div.sphinxsidebar h4,
324 div.sphinxsidebar p.logo {
325 margin: 1.2em 0 0.3em 0;
326 font-size: 1em;
327 padding: 0;
328 color: #fff;
329 font-family: Asap, Arial, "ff-meta-web-pro-1", "ff-meta-web-pro-2", "Arial", "Helvetica Neue", sans-serif;
330 }
331
332 div.sphinxsidebar h3 a {
333 color: #fff;
334 }
335
336 div.sphinxsidebar ul,
337 div.sphinxsidebar p {
338 margin-top: 0;
339 padding-left: 0;
340 line-height: 130%;
341
342 }
343
344 /* No bullets for nested lists, but a little extra indentation */
345 div.sphinxsidebar ul ul {
346 list-style-type: none;
347 margin-left: 1.2em;
348 padding: 0;
349 }
350
351 /* A little top/bottom padding to prevent adjacent links' borders
352 * from overlapping each other */
353 div.sphinxsidebar ul li {
354 padding: 0;
355 margin: 2px 0;
356 }
357
358 /* A little left-padding to make these align with the ULs */
359 div.sphinxsidebar p.topless {
360 padding-left: 0 0 0 1em;
361 }
362
363 /* Make these into hidden one-liners */
364 div.sphinxsidebar ul li,
365 div.sphinxsidebar p.topless {
366 white-space: nowrap;
367 overflow: hidden;
368 border: 1px solid transparent; /* To prevent things jumping around on hover */
369 }
370 /* ...which become visible when hovered */
371 div.sphinxsidebar ul li:hover,
372 div.sphinxsidebar p.topless:hover {
373 background-color: #333;
374 overflow: visible;
375
376
377 }
378
379 /* Search text box and "Go" button */
380 #searchbox {
381 margin-top: 2em;
382 margin-bottom: 1em;
383 background: #666;
384 padding: 0.5em;
385 border-radius: 6px;
386 -moz-border-radius: 6px;
387 -webkit-border-radius: 6px;
388 margin-right: 0;
389 }
390 #searchbox h3 {
391 margin-top: 0;
392 }
393
394 /* Make search box and button abut and have a border */
395 input,
396 div.sphinxsidebar input {
397 border: 1px solid #999;
398 float: left;
399 }
400
401 /* Search textbox */
402 input[type="text"] {
403 margin: 0;
404 padding: 0 3px;
405 height: 20px;
406 width: 144px;
407 border-top-left-radius: 3px;
408 border-bottom-left-radius: 3px;
409 -moz-border-radius-topleft: 3px;
410 -moz-border-radius-bottomleft: 3px;
411 -webkit-border-top-left-radius: 3px;
412 -webkit-border-bottom-left-radius: 3px;
413 }
414 /* Search button */
415 input[type="submit"] {
416 margin: 0 0 0 -1px; /* -1px prevents a double-border with textbox */
417 height: 22px;
418 color: #444;
419 background-color: #e8ecef;
420 padding: 1px 4px;
421 font-weight: bold;
422 border-top-right-radius: 3px;
423 border-bottom-right-radius: 3px;
424 -moz-border-radius-topright: 3px;
425 -moz-border-radius-bottomright: 3px;
426 -webkit-border-top-right-radius: 3px;
427 -webkit-border-bottom-right-radius: 3px;
428 }
429 input[type="submit"]:hover {
430 color: #000;
431 background-color: #ddd;
432 }
433
434 div.sphinxsidebar p.searchtip {
435 clear: both;
436 padding: 0.5em 0 0 0;
437 color: #fff;
438 font-size: 0.9em;
439 }
440
441 /* Sidebar links are unusual */
442 div.sphinxsidebar li a,
443 div.sphinxsidebar p a {
444 color: #eee;
445 border-radius: 3px;
446 -moz-border-radius: 3px;
447 -webkit-border-radius: 3px;
448 border: 1px solid transparent; /* To prevent things jumping around on hover */
449 padding: 0 5px 0 5px;
450 }
451 div.sphinxsidebar li a:hover,
452 div.sphinxsidebar p a:hover {
453 color: #fff;
454 background-color: #333;
455 }
456 div.sphinxsidebar p.logo a {
457 border: 0;
458 }
459
460 /* Tweak any link appearing in a heading */
461 div.sphinxsidebar h3 a {
462 }
463
464
465 /* OTHER STUFF ------------------------------------------------------------ */
466
467 /* labels */
468 .versionmodified {
469 font-style: normal;
470 }
471
472 .bookmarklet, .versionadded, .versionchanged {
473 display: inline-block;
474 padding: 4px 6px;
475 font-size: 13.536px;
476 font-weight: bold;
477 line-height: 14px;
478 color: #ffffff;
479 vertical-align: baseline;
480 white-space: nowrap;
481 text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
482 background-color: #999999;
483 -webkit-border-radius: 3px;
484 -moz-border-radius: 3px;
485 border-radius: 3px;
486 text-align: center;
487 font-style: normal;
488 }
489 .bookmarklet a, .versionadded a, .versionchanged a {
490 color: #fff;
491 }
492
493 .bookmarklet {
494 background-color: #2d6987;
495 }
496
497 .versionadded {
498 background-color: #468847;
499 }
500 div.admonition p.versionadded,
501 div.warning p.versionadded {
502 padding: 4px 6px;
503 }
504
505 .versionchanged {
506 background-color: #b04040;
507 }
508 div.admonition p.versionchanged,
509 div.warning p.versionchanged {
510 padding: 4px 6px;
511 }
512
513 /* Standard tags */
514 cite, code, tt {
515 font-family: 'Source Code Pro', 'Consolas', 'Deja Vu Sans Mono',
516 'Bitstream Vera Sans Mono', monospace;
517 font-size: 0.95em;
518 letter-spacing: 0.01em;
519 }
520
521 tt {
522 color: #f66;
523 background-color: #444;
524 padding: 0 5px;
525 font-size: 95%;
526 -webkit-border-radius: 4px;
527 -moz-border-radius: 4px;
528 border-radius: 4px;
529 }
530
531 h1 tt, h2 tt, h3 tt, h4 tt, h5 tt {
532 padding: 0;
533 background: none;
534 }
535
536 tt.descname, tt.descclassname, tt.xref {
537 border: 0;
538 }
539
540 hr {
541 border-top: 1px solid #777;
542 border-bottom: none;
543 margin: 2em auto;
544 width: 50%;
545 }
546
547
548 pre, #_fontwidthtest {
549 font-family: 'Source Code Pro', 'Consolas', 'Deja Vu Sans Mono',
550 'Bitstream Vera Sans Mono', monospace;
551 margin: 1em 2em;
552 font-size: 0.95em;
553 letter-spacing: 0.015em;
554 line-height: 120%;
555 padding: 0.5em;
556 border: 1px solid #ccc;
557 background-color: #eee;
558 border-radius: 6px;
559 -moz-border-radius: 6px;
560 -webkit-border-radius: 6px;
561 }
562
563 pre a {
564 color: inherit;
565 text-decoration: underline;
566 }
567
568 td.linenos pre {
569 margin: 1em 0em;
570 }
571
572 td.code pre {
573 margin: 1em 0em;
574 }
575
576 div.quotebar {
577 background-color: #f8f8f8;
578 max-width: 250px;
579 float: right;
580 padding: 2px 7px;
581 border: 1px solid #ccc;
582 }
583
584 div.topic {
585 background-color: #333;
586 border: 0;
587 padding-bottom: .5em;
588 border-radius: 4px;
589 -moz-border-radius: 4px;
590 -webkit-border-radius: 4px;
591 }
592
593 table {
594 border-collapse: collapse;
595 margin: 0 -0.5em 0 -0.5em;
596 }
597
598 table td, table th {
599 padding: 0.2em 0.5em 0.2em 0.5em;
600 }
601
602
603 /* ADMONITIONS AND WARNINGS ------------------------------------------------- */
604
605 /* Shared by admonitions, warnings and sidebars */
606 div.admonition,
607 div.warning,
608 div.sidebar {
609 font-size: 0.9em;
610 margin: 2em;
611 padding: 0;
612 /*
613 border-radius: 6px;
614 -moz-border-radius: 6px;
615 -webkit-border-radius: 6px;
616 */
617 }
618 div.admonition p,
619 div.warning p,
620 div.sidebar p {
621 margin: 0.5em 1em 0.5em 1em;
622 padding: 0;
623 }
624 div.admonition pre,
625 div.warning pre,
626 div.sidebar pre {
627 margin: 0.4em 1em 0.4em 1em;
628 }
629 div.admonition p.admonition-title,
630 div.warning p.admonition-title,
631 div.sidebar p.sidebar-title {
632 margin: 0;
633 padding: 0.1em 0 0.1em 0.5em;
634 color: white;
635 font-weight: bold;
636 font-size: 1.1em;
637 text-shadow: 0 1px rgba(0, 0, 0, 0.5);
638 }
639 div.admonition ul, div.admonition ol,
640 div.warning ul, div.warning ol,
641 div.sidebar ul, div.sidebar ol {
642 margin: 0.1em 0.5em 0.5em 3em;
643 padding: 0;
644 }
645
646
647 /* Admonitions and sidebars only */
648 div.admonition, div.sidebar {
649 border: none;
650 background-color: #555;
651 color: #fff;
652 padding: .5em;
653 margin-bottom: 1em;
654 -webkit-border-radius: 4px;
655 -moz-border-radius: 4px;
656 border-radius: 4px;
657
658 }
659 div.admonition p.admonition-title,
660 div.sidebar p.sidebar-title {
661 padding-bottom: .5em;
662 border-bottom: 1px solid #888;
663 }
664
665
666 /* Warnings only */
667 div.warning {
668 background-color: #333;
669 }
670 div.warning p.admonition-title {
671 background-color: #b04040;
672 border-bottom: 1px solid #900000;
673 border-radius: 4px;
674 }
675
676
677 /* Sidebars only */
678 div.sidebar {
679 max-width: 30%;
680 }
681
682
683
684 div.versioninfo {
685 margin: 1em 0 0 0;
686 border: 1px solid #ccc;
687 background-color: #DDEAF0;
688 padding: 8px;
689 line-height: 1.3em;
690 font-size: 0.9em;
691 }
692
693 .viewcode-back {
694 font-family: Asap, 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
695 'Verdana', sans-serif;
696 }
697
698 div.viewcode-block:target {
699 background-color: #f4debf;
700 border-top: 1px solid #ac9;
701 border-bottom: 1px solid #ac9;
702 }
703
704 dl {
705 margin: 1em 0 2.5em 0;
706 }
707
708 /* Highlight target when you click an internal link */
709 dt:target {
710 background: #ffe080;
711 }
712 /* Don't highlight whole divs */
713 div.highlight {
714 background: transparent;
715 }
716 div.highlight pre,
717 div.highlight-javascript pre,
718 div.highlight-html pre {
719 background-color: #4b4b4b;
720 background-color: rgba(75, 75, 75, 0.5);
721 color: #eee;
722 font-size: 15px;
723 line-height: 21px;
724 white-space: pre;
725 overflow: auto;
726 border: none;
727 }
728 div.admonition pre {
729 background-color: #333;
730 }
731
732 /* But do highlight spans (so search results can be highlighted) */
733 span.highlight {
734 background: #111;
735 }
736
737 div.highlight .c1 {
738 color: #999;
739 }
740 div.highlight .cp {
741 color: #3aC;
742 }
743
744 div.highlight .s,
745 div.highlight .s1,
746 div.highlight .s2 {
747 color: orange;
748 }
749
750 div.highlight .kc {
751 color: red;
752 }
753 div.highlight .k,
754 div.highlight .kd {
755 color: #3aC;
756 }
757
758 div.highlight .nb {
759 color: #e88;
760 }
761 div.highlight .nx {
762 color: #fff;
763 }
764
765 div.highlight .p {
766 color: #eee;
767 }
768
769 div.footer {
770 color: #eeeeee;
771 padding: 1em 2em 1em 2em;
772 clear: both;
773 font-size: 0.8em;
774 text-align: center;
775 background-color: #222;
776 }
777
778 p {
779 margin: 0.8em 0 0.5em 0;
780 }
781
782 .section p img.math {
783 margin: 0;
784 }
785
786
787 .section p img {
788 margin: 1em 2em;
789 }
790
791
792 /* MOBILE LAYOUT -------------------------------------------------------------- */
793
794 @media screen and (max-width: 600px) {
795
796 h1, h2, h3, h4, h5 {
797 position: relative;
798 }
799
800 ul {
801 padding-left: 1.25em;
802 }
803
804 div.bodywrapper a.headerlink, #indices-and-tables h1 a {
805 color: #e6e6e6;
806 font-size: 80%;
807 float: right;
808 line-height: 1.8;
809 position: absolute;
810 right: -0.7em;
811 visibility: inherit;
812 }
813
814 div.bodywrapper h1 a.headerlink, #indices-and-tables h1 a {
815 line-height: 1.5;
816 }
817
818 pre {
819 font-size: 0.7em;
820 overflow: auto;
821 word-wrap: break-word;
822 white-space: pre-wrap;
823 }
824
825 div.related ul {
826 height: 2.5em;
827 padding: 0;
828 text-align: left;
829 }
830
831 div.related ul li {
832 clear: both;
833 color: #465158;
834 padding: 0.2em 0;
835 }
836
837 div.related ul li:last-child {
838 border-bottom: 1px dotted #8ca1af;
839 padding-bottom: 0.4em;
840 margin-bottom: 1em;
841 width: 100%;
842 }
843
844 div.related ul li a {
845 color: #fff;
846 padding-right: 0;
847 }
848
849 div.related ul li a:hover {
850 background: inherit;
851 color: inherit;
852 }
853
854 div.related ul li.right {
855 clear: none;
856 padding: 0.65em 0;
857 margin-bottom: 0.5em;
858 }
859
860 div.related ul li.right a {
861 color: #fff;
862 padding-right: 0.8em;
863 }
864
865 div.related ul li.right a:hover {
866 background-color: #8ca1af;
867 }
868
869 div.body {
870 clear: both;
871 min-width: 0;
872 word-wrap: break-word;
873 }
874
875 div.bodywrapper {
876 margin: 0 0 0 0;
877 }
878
879 div.sphinxsidebar {
880 float: none;
881 margin: 0;
882 width: auto;
883 }
884
885 div.sphinxsidebar input[type="text"] {
886 height: 2em;
887 line-height: 2em;
888 width: 70%;
889 }
890
891 div.sphinxsidebar input[type="submit"] {
892 height: 2em;
893 margin-left: 0.5em;
894 width: 20%;
895 }
896
897 div.sphinxsidebar p.searchtip {
898 background: inherit;
899 margin-bottom: 1em;
900 }
901
902 div.sphinxsidebar ul li, div.sphinxsidebar p.topless {
903 white-space: normal;
904 }
905
906 .bodywrapper img {
907 display: block;
908 margin-left: auto;
909 margin-right: auto;
910 max-width: 100%;
911 }
912
913 div.documentwrapper {
914 float: none;
915 }
916
917 div.admonition, div.warning, pre, blockquote {
918 margin-left: 0em;
919 margin-right: 0em;
920 }
921
922 .body p img {
923 margin: 0;
924 }
925
926 #searchbox {
927 background: transparent;
928 }
929
930 .related:not(:first-child) li {
931 display: none;
932 }
933
934 .related:not(:first-child) li.right {
935 display: block;
936 }
937
938 div.footer {
939 padding: 1em;
940 }
941
942 .rtd_doc_footer .rtd-badge {
943 float: none;
944 margin: 1em auto;
945 position: static;
946 }
947
948 .rtd_doc_footer .rtd-badge.revsys-inline {
949 margin-right: auto;
950 margin-bottom: 2em;
951 }
952
953 table.indextable {
954 display: block;
955 width: auto;
956 }
957
958 .indextable tr {
959 display: block;
960 }
961
962 .indextable td {
963 display: block;
964 padding: 0;
965 width: auto !important;
966 }
967
968 .indextable td dt {
969 margin: 1em 0;
970 }
971
972 ul.search {
973 margin-left: 0.25em;
974 }
975
976 ul.search li div.context {
977 font-size: 90%;
978 line-height: 1.1;
979 margin-bottom: 1;
980 margin-left: 0;
981 }
982
983 }
984
985 .donate {
986 text-align: center;
987 }
988
989 .donate .flattr {
990 margin-top: 1.5em;
991 }
1 /*
2 * rtd.css
3 * ~~~~~~~~~~~~~~~
4 *
5 * Sphinx stylesheet -- sphinxdoc theme. Originally created by
6 * Armin Ronacher for Werkzeug.
7 *
8 * Customized for ReadTheDocs by Eric Pierce & Eric Holscher
9 *
10 * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
11 * :license: BSD, see LICENSE for details.
12 *
13 */
14
15 /* RTD colors
16 * light blue: #e8ecef
17 * medium blue: #8ca1af
18 * dark blue: #465158
19 * dark grey: #444444
20 *
21 * white hover: #d1d9df;
22 * medium blue hover: #697983;
23 * green highlight: #8ecc4c
24 * light blue (project bar): #e8ecef
25 */
26
27 @import url("basic.css");
28
29 /* PAGE LAYOUT -------------------------------------------------------------- */
30
31 body {
32 font: 100%/1.5 "ff-meta-web-pro-1","ff-meta-web-pro-2",Arial,"Helvetica Neue",sans-serif;
33 text-align: center;
34 color: black;
35 background-color: #465158;
36 padding: 0;
37 margin: 0;
38 }
39
40 img {
41 border: 0;
42 max-width: 100%;
43 }
44
45 div.document {
46 text-align: left;
47 background-color: #e8ecef;
48 }
49
50 div.bodywrapper {
51 background-color: #ffffff;
52 border-left: 1px solid #ccc;
53 border-bottom: 1px solid #ccc;
54 margin: 0 0 0 16em;
55 }
56
57 div.body {
58 margin: 0;
59 padding: 0.5em 1.3em;
60 min-width: 20em;
61 }
62
63 div.related {
64 font-size: 1em;
65 background-color: #465158;
66 }
67
68 div.documentwrapper {
69 float: left;
70 width: 100%;
71 background-color: #e8ecef;
72 }
73
74
75 /* HEADINGS --------------------------------------------------------------- */
76
77 h1 {
78 margin: 0;
79 padding: 0.7em 0 0.3em 0;
80 font-size: 1.5em;
81 line-height: 1.15;
82 color: #111;
83 clear: both;
84 }
85
86 h2 {
87 margin: 2em 0 0.2em 0;
88 font-size: 1.35em;
89 padding: 0;
90 color: #465158;
91 }
92
93 h3 {
94 margin: 1em 0 -0.3em 0;
95 font-size: 1.2em;
96 color: #6c818f;
97 }
98
99 div.body h1 a, div.body h2 a, div.body h3 a, div.body h4 a, div.body h5 a, div.body h6 a {
100 color: black;
101 }
102
103 h1 a.anchor, h2 a.anchor, h3 a.anchor, h4 a.anchor, h5 a.anchor, h6 a.anchor {
104 display: none;
105 margin: 0 0 0 0.3em;
106 padding: 0 0.2em 0 0.2em;
107 color: #aaa !important;
108 }
109
110 h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor,
111 h5:hover a.anchor, h6:hover a.anchor {
112 display: inline;
113 }
114
115 h1 a.anchor:hover, h2 a.anchor:hover, h3 a.anchor:hover, h4 a.anchor:hover,
116 h5 a.anchor:hover, h6 a.anchor:hover {
117 color: #777;
118 background-color: #eee;
119 }
120
121
122 /* LINKS ------------------------------------------------------------------ */
123
124 /* Normal links get a pseudo-underline */
125 a {
126 color: #444;
127 text-decoration: none;
128 border-bottom: 1px solid #ccc;
129 }
130
131 /* Links in sidebar, TOC, index trees and tables have no underline */
132 .sphinxsidebar a,
133 .toctree-wrapper a,
134 .indextable a,
135 #indices-and-tables a {
136 color: #444;
137 text-decoration: none;
138 border-bottom: none;
139 }
140
141 /* Most links get an underline-effect when hovered */
142 a:hover,
143 div.toctree-wrapper a:hover,
144 .indextable a:hover,
145 #indices-and-tables a:hover {
146 color: #111;
147 text-decoration: none;
148 border-bottom: 1px solid #111;
149 }
150
151 /* Footer links */
152 div.footer a {
153 color: #86989B;
154 text-decoration: none;
155 border: none;
156 }
157 div.footer a:hover {
158 color: #a6b8bb;
159 text-decoration: underline;
160 border: none;
161 }
162
163 /* Permalink anchor (subtle grey with a red hover) */
164 div.body a.headerlink {
165 color: #ccc;
166 font-size: 1em;
167 margin-left: 6px;
168 padding: 0 4px 0 4px;
169 text-decoration: none;
170 border: none;
171 }
172 div.body a.headerlink:hover {
173 color: #c60f0f;
174 border: none;
175 }
176
177
178 /* NAVIGATION BAR --------------------------------------------------------- */
179
180 div.related ul {
181 height: 2.5em;
182 }
183
184 div.related ul li {
185 margin: 0;
186 padding: 0.65em 0;
187 float: left;
188 display: block;
189 color: white; /* For the >> separators */
190 font-size: 0.8em;
191 }
192
193 div.related ul li.right {
194 float: right;
195 margin-right: 5px;
196 color: transparent; /* Hide the | separators */
197 }
198
199 /* "Breadcrumb" links in nav bar */
200 div.related ul li a {
201 order: none;
202 background-color: inherit;
203 font-weight: bold;
204 margin: 6px 0 6px 4px;
205 line-height: 1.75em;
206 color: #ffffff;
207 padding: 0.4em 0.8em;
208 border: none;
209 border-radius: 3px;
210 }
211 /* previous / next / modules / index links look more like buttons */
212 div.related ul li.right a {
213 margin: 0.375em 0;
214 background-color: #697983;
215 text-shadow: 0 1px rgba(0, 0, 0, 0.5);
216 border-radius: 3px;
217 -webkit-border-radius: 3px;
218 -moz-border-radius: 3px;
219 }
220 /* All navbar links light up as buttons when hovered */
221 div.related ul li a:hover {
222 background-color: #8ca1af;
223 color: #ffffff;
224 text-decoration: none;
225 border-radius: 3px;
226 -webkit-border-radius: 3px;
227 -moz-border-radius: 3px;
228 }
229 /* Take extra precautions for tt within links */
230 a tt,
231 div.related ul li a tt {
232 background: inherit !important;
233 color: inherit !important;
234 }
235
236
237 /* SIDEBAR ---------------------------------------------------------------- */
238
239 div.sphinxsidebarwrapper {
240 padding: 0;
241 }
242
243 div.sphinxsidebar {
244 margin: 0;
245 margin-left: -100%;
246 float: left;
247 top: 3em;
248 left: 0;
249 padding: 0 1em;
250 width: 14em;
251 font-size: 1em;
252 text-align: left;
253 background-color: #e8ecef;
254 }
255
256 div.sphinxsidebar img {
257 max-width: 12em;
258 }
259
260 div.sphinxsidebar input[type="image"] {
261 display: inline;
262 float: none;
263 border: 0;
264 }
265
266 div.sphinxsidebar h3,
267 div.sphinxsidebar h4,
268 div.sphinxsidebar p.logo {
269 margin: 1.2em 0 0.3em 0;
270 font-size: 1em;
271 padding: 0;
272 color: #222222;
273 font-family: "ff-meta-web-pro-1", "ff-meta-web-pro-2", "Arial", "Helvetica Neue", sans-serif;
274 }
275
276 div.sphinxsidebar h3 a {
277 color: #444444;
278 }
279
280 div.sphinxsidebar ul,
281 div.sphinxsidebar p {
282 margin-top: 0;
283 padding-left: 0;
284 line-height: 130%;
285 background-color: #e8ecef;
286 }
287
288 /* No bullets for nested lists, but a little extra indentation */
289 div.sphinxsidebar ul ul {
290 list-style-type: none;
291 margin-left: 1.5em;
292 padding: 0;
293 }
294
295 /* A little top/bottom padding to prevent adjacent links' borders
296 * from overlapping each other */
297 div.sphinxsidebar ul li {
298 padding: 1px 0;
299 }
300
301 /* A little left-padding to make these align with the ULs */
302 div.sphinxsidebar p.topless {
303 padding-left: 0 0 0 1em;
304 }
305
306 /* Make these into hidden one-liners */
307 div.sphinxsidebar ul li,
308 div.sphinxsidebar p.topless {
309 white-space: nowrap;
310 overflow: hidden;
311 }
312 /* ...which become visible when hovered */
313 div.sphinxsidebar ul li:hover,
314 div.sphinxsidebar p.topless:hover {
315 overflow: visible;
316 }
317
318 /* Search text box and "Go" button */
319 #searchbox {
320 margin-top: 2em;
321 margin-bottom: 1em;
322 background: #ddd;
323 padding: 0.5em;
324 border-radius: 6px;
325 -moz-border-radius: 6px;
326 -webkit-border-radius: 6px;
327 }
328 #searchbox h3 {
329 margin-top: 0;
330 }
331
332 /* Make search box and button abut and have a border */
333 input,
334 div.sphinxsidebar input {
335 border: 1px solid #999;
336 float: left;
337 }
338
339 /* Search textbox */
340 input[type="text"] {
341 margin: 0;
342 padding: 0 3px;
343 height: 20px;
344 width: 144px;
345 border-top-left-radius: 3px;
346 border-bottom-left-radius: 3px;
347 -moz-border-radius-topleft: 3px;
348 -moz-border-radius-bottomleft: 3px;
349 -webkit-border-top-left-radius: 3px;
350 -webkit-border-bottom-left-radius: 3px;
351 }
352 /* Search button */
353 input[type="submit"] {
354 margin: 0 0 0 -1px; /* -1px prevents a double-border with textbox */
355 height: 22px;
356 color: #444;
357 background-color: #e8ecef;
358 padding: 1px 4px;
359 font-weight: bold;
360 border-top-right-radius: 3px;
361 border-bottom-right-radius: 3px;
362 -moz-border-radius-topright: 3px;
363 -moz-border-radius-bottomright: 3px;
364 -webkit-border-top-right-radius: 3px;
365 -webkit-border-bottom-right-radius: 3px;
366 }
367 input[type="submit"]:hover {
368 color: #ffffff;
369 background-color: #8ecc4c;
370 }
371
372 div.sphinxsidebar p.searchtip {
373 clear: both;
374 padding: 0.5em 0 0 0;
375 background: #ddd;
376 color: #666;
377 font-size: 0.9em;
378 }
379
380 /* Sidebar links are unusual */
381 div.sphinxsidebar li a,
382 div.sphinxsidebar p a {
383 background: #e8ecef; /* In case links overlap main content */
384 border-radius: 3px;
385 -moz-border-radius: 3px;
386 -webkit-border-radius: 3px;
387 border: 1px solid transparent; /* To prevent things jumping around on hover */
388 padding: 0 5px 0 5px;
389 }
390 div.sphinxsidebar li a:hover,
391 div.sphinxsidebar p a:hover {
392 color: #111;
393 text-decoration: none;
394 border: 1px solid #888;
395 }
396 div.sphinxsidebar p.logo a {
397 border: 0;
398 }
399
400 /* Tweak any link appearing in a heading */
401 div.sphinxsidebar h3 a {
402 }
403
404
405
406
407 /* OTHER STUFF ------------------------------------------------------------ */
408
409 cite, code, tt {
410 font-family: 'Consolas', 'Deja Vu Sans Mono',
411 'Bitstream Vera Sans Mono', monospace;
412 font-size: 0.95em;
413 letter-spacing: 0.01em;
414 }
415
416 tt {
417 background-color: #f2f2f2;
418 color: #444;
419 }
420
421 tt.descname, tt.descclassname, tt.xref {
422 border: 0;
423 }
424
425 hr {
426 border: 1px solid #abc;
427 margin: 2em;
428 }
429
430
431 pre, #_fontwidthtest {
432 font-family: 'Consolas', 'Deja Vu Sans Mono',
433 'Bitstream Vera Sans Mono', monospace;
434 margin: 1em 2em;
435 font-size: 0.95em;
436 letter-spacing: 0.015em;
437 line-height: 120%;
438 padding: 0.5em;
439 border: 1px solid #ccc;
440 background-color: #eee;
441 border-radius: 6px;
442 -moz-border-radius: 6px;
443 -webkit-border-radius: 6px;
444 }
445
446 pre a {
447 color: inherit;
448 text-decoration: underline;
449 }
450
451 td.linenos pre {
452 margin: 1em 0em;
453 }
454
455 td.code pre {
456 margin: 1em 0em;
457 }
458
459 div.quotebar {
460 background-color: #f8f8f8;
461 max-width: 250px;
462 float: right;
463 padding: 2px 7px;
464 border: 1px solid #ccc;
465 }
466
467 div.topic {
468 background-color: #f8f8f8;
469 }
470
471 table {
472 border-collapse: collapse;
473 margin: 0 -0.5em 0 -0.5em;
474 }
475
476 table td, table th {
477 padding: 0.2em 0.5em 0.2em 0.5em;
478 }
479
480
481 /* ADMONITIONS AND WARNINGS ------------------------------------------------- */
482
483 /* Shared by admonitions, warnings and sidebars */
484 div.admonition,
485 div.warning,
486 div.sidebar {
487 font-size: 0.9em;
488 margin: 2em;
489 padding: 0;
490 /*
491 border-radius: 6px;
492 -moz-border-radius: 6px;
493 -webkit-border-radius: 6px;
494 */
495 }
496 div.admonition p,
497 div.warning p,
498 div.sidebar p {
499 margin: 0.5em 1em 0.5em 1em;
500 padding: 0;
501 }
502 div.admonition pre,
503 div.warning pre,
504 div.sidebar pre {
505 margin: 0.4em 1em 0.4em 1em;
506 }
507 div.admonition p.admonition-title,
508 div.warning p.admonition-title,
509 div.sidebar p.sidebar-title {
510 margin: 0;
511 padding: 0.1em 0 0.1em 0.5em;
512 color: white;
513 font-weight: bold;
514 font-size: 1.1em;
515 text-shadow: 0 1px rgba(0, 0, 0, 0.5);
516 }
517 div.admonition ul, div.admonition ol,
518 div.warning ul, div.warning ol,
519 div.sidebar ul, div.sidebar ol {
520 margin: 0.1em 0.5em 0.5em 3em;
521 padding: 0;
522 }
523
524
525 /* Admonitions and sidebars only */
526 div.admonition, div.sidebar {
527 border: 1px solid #609060;
528 background-color: #e9ffe9;
529 }
530 div.admonition p.admonition-title,
531 div.sidebar p.sidebar-title {
532 background-color: #70A070;
533 border-bottom: 1px solid #609060;
534 }
535
536
537 /* Warnings only */
538 div.warning {
539 border: 1px solid #900000;
540 background-color: #ffe9e9;
541 }
542 div.warning p.admonition-title {
543 background-color: #b04040;
544 border-bottom: 1px solid #900000;
545 }
546
547
548 /* Sidebars only */
549 div.sidebar {
550 max-width: 30%;
551 }
552
553
554
555 div.versioninfo {
556 margin: 1em 0 0 0;
557 border: 1px solid #ccc;
558 background-color: #DDEAF0;
559 padding: 8px;
560 line-height: 1.3em;
561 font-size: 0.9em;
562 }
563
564 .viewcode-back {
565 font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
566 'Verdana', sans-serif;
567 }
568
569 div.viewcode-block:target {
570 background-color: #f4debf;
571 border-top: 1px solid #ac9;
572 border-bottom: 1px solid #ac9;
573 }
574
575 dl {
576 margin: 1em 0 2.5em 0;
577 }
578
579 /* Highlight target when you click an internal link */
580 dt:target {
581 background: #ffe080;
582 }
583 /* Don't highlight whole divs */
584 div.highlight {
585 background: transparent;
586 }
587 /* But do highlight spans (so search results can be highlighted) */
588 span.highlight {
589 background: #ffe080;
590 }
591
592 div.footer {
593 background-color: #465158;
594 color: #eeeeee;
595 padding: 0 2em 2em 2em;
596 clear: both;
597 font-size: 0.8em;
598 text-align: center;
599 }
600
601 p {
602 margin: 0.8em 0 0.5em 0;
603 }
604
605 .section p img.math {
606 margin: 0;
607 }
608
609
610 .section p img {
611 margin: 1em 2em;
612 }
613
614
615 /* MOBILE LAYOUT -------------------------------------------------------------- */
616
617 @media screen and (max-width: 600px) {
618
619 h1, h2, h3, h4, h5 {
620 position: relative;
621 }
622
623 ul {
624 padding-left: 1.25em;
625 }
626
627 div.bodywrapper a.headerlink, #indices-and-tables h1 a {
628 color: #e6e6e6;
629 font-size: 80%;
630 float: right;
631 line-height: 1.8;
632 position: absolute;
633 right: -0.7em;
634 visibility: inherit;
635 }
636
637 div.bodywrapper h1 a.headerlink, #indices-and-tables h1 a {
638 line-height: 1.5;
639 }
640
641 pre {
642 font-size: 0.7em;
643 overflow: auto;
644 word-wrap: break-word;
645 white-space: pre-wrap;
646 }
647
648 div.related ul {
649 height: 2.5em;
650 padding: 0;
651 text-align: left;
652 }
653
654 div.related ul li {
655 clear: both;
656 color: #465158;
657 padding: 0.2em 0;
658 }
659
660 div.related ul li:last-child {
661 border-bottom: 1px dotted #8ca1af;
662 padding-bottom: 0.4em;
663 margin-bottom: 1em;
664 width: 100%;
665 }
666
667 div.related ul li a {
668 color: #465158;
669 padding-right: 0;
670 }
671
672 div.related ul li a:hover {
673 background: inherit;
674 color: inherit;
675 }
676
677 div.related ul li.right {
678 clear: none;
679 padding: 0.65em 0;
680 margin-bottom: 0.5em;
681 }
682
683 div.related ul li.right a {
684 color: #fff;
685 padding-right: 0.8em;
686 }
687
688 div.related ul li.right a:hover {
689 background-color: #8ca1af;
690 }
691
692 div.body {
693 clear: both;
694 min-width: 0;
695 word-wrap: break-word;
696 }
697
698 div.bodywrapper {
699 margin: 0 0 0 0;
700 }
701
702 div.sphinxsidebar {
703 float: none;
704 margin: 0;
705 width: auto;
706 }
707
708 div.sphinxsidebar input[type="text"] {
709 height: 2em;
710 line-height: 2em;
711 width: 70%;
712 }
713
714 div.sphinxsidebar input[type="submit"] {
715 height: 2em;
716 margin-left: 0.5em;
717 width: 20%;
718 }
719
720 div.sphinxsidebar p.searchtip {
721 background: inherit;
722 margin-bottom: 1em;
723 }
724
725 div.sphinxsidebar ul li, div.sphinxsidebar p.topless {
726 white-space: normal;
727 }
728
729 .bodywrapper img {
730 display: block;
731 margin-left: auto;
732 margin-right: auto;
733 max-width: 100%;
734 }
735
736 div.documentwrapper {
737 float: none;
738 }
739
740 div.admonition, div.warning, pre, blockquote {
741 margin-left: 0em;
742 margin-right: 0em;
743 }
744
745 .body p img {
746 margin: 0;
747 }
748
749 #searchbox {
750 background: transparent;
751 }
752
753 .related:not(:first-child) li {
754 display: none;
755 }
756
757 .related:not(:first-child) li.right {
758 display: block;
759 }
760
761 div.footer {
762 padding: 1em;
763 }
764
765 .rtd_doc_footer .rtd-badge {
766 float: none;
767 margin: 1em auto;
768 position: static;
769 }
770
771 .rtd_doc_footer .rtd-badge.revsys-inline {
772 margin-right: auto;
773 margin-bottom: 2em;
774 }
775
776 table.indextable {
777 display: block;
778 width: auto;
779 }
780
781 .indextable tr {
782 display: block;
783 }
784
785 .indextable td {
786 display: block;
787 padding: 0;
788 width: auto !important;
789 }
790
791 .indextable td dt {
792 margin: 1em 0;
793 }
794
795 ul.search {
796 margin-left: 0.25em;
797 }
798
799 ul.search li div.context {
800 font-size: 90%;
801 line-height: 1.1;
802 margin-bottom: 1;
803 margin-left: 0;
804 }
805 }
806
807 .donate {
808 text-align: center;
809 }
810
811 .donate .flattr {
812 margin-top: 1.5em;
813 }
814
815
816 .highlight .hll { background-color: #ffffcc }
817 .highlight { background: #eeffcc; }
818 .highlight .c { color: #408090; font-style: italic } /* Comment */
819 .highlight .err { border: 1px solid #FF0000 } /* Error */
820 .highlight .k { color: #007020; font-weight: bold } /* Keyword */
821 .highlight .o { color: #666666 } /* Operator */
822 .highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */
823 .highlight .cp { color: #007020 } /* Comment.Preproc */
824 .highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */
825 .highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
826 .highlight .gd { color: #A00000 } /* Generic.Deleted */
827 .highlight .ge { font-style: italic } /* Generic.Emph */
828 .highlight .gr { color: #FF0000 } /* Generic.Error */
829 .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
830 .highlight .gi { color: #00A000 } /* Generic.Inserted */
831 .highlight .go { color: #303030 } /* Generic.Output */
832 .highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
833 .highlight .gs { font-weight: bold } /* Generic.Strong */
834 .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
835 .highlight .gt { color: #0040D0 } /* Generic.Traceback */
836 .highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
837 .highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
838 .highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
839 .highlight .kp { color: #007020 } /* Keyword.Pseudo */
840 .highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
841 .highlight .kt { color: #902000 } /* Keyword.Type */
842 .highlight .m { color: #208050 } /* Literal.Number */
843 .highlight .s { color: #4070a0 } /* Literal.String */
844 .highlight .na { color: #4070a0 } /* Name.Attribute */
845 .highlight .nb { color: #007020 } /* Name.Builtin */
846 .highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
847 .highlight .no { color: #60add5 } /* Name.Constant */
848 .highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */
849 .highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */
850 .highlight .ne { color: #007020 } /* Name.Exception */
851 .highlight .nf { color: #06287e } /* Name.Function */
852 .highlight .nl { color: #002070; font-weight: bold } /* Name.Label */
853 .highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
854 .highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */
855 .highlight .nv { color: #bb60d5 } /* Name.Variable */
856 .highlight .nx { color: #111111 } /* Std */
857 .highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */
858 .highlight .w { color: #bbbbbb } /* Text.Whitespace */
859 .highlight .mf { color: #208050 } /* Literal.Number.Float */
860 .highlight .mh { color: #208050 } /* Literal.Number.Hex */
861 .highlight .mi { color: #208050 } /* Literal.Number.Integer */
862 .highlight .mo { color: #208050 } /* Literal.Number.Oct */
863 .highlight .sb { color: #4070a0 } /* Literal.String.Backtick */
864 .highlight .sc { color: #4070a0 } /* Literal.String.Char */
865 .highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
866 .highlight .s2 { color: #4070a0 } /* Literal.String.Double */
867 .highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
868 .highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */
869 .highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
870 .highlight .sx { color: #c65d09 } /* Literal.String.Other */
871 .highlight .sr { color: #235388 } /* Literal.String.Regex */
872 .highlight .s1 { color: #4070a0 } /* Literal.String.Single */
873 .highlight .ss { color: #517918 } /* Literal.String.Symbol */
874 .highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
875 .highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
876 .highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
877 .highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
878 .highlight .il { color: #208050 } /* Literal.Number.Integer.Long */
879
880 /* https://github.com/n1k0/casperjs-docs/issues/2 */
881 #casperjs-documentation img {
882 -webkit-filter: drop-shadow(0 1px 20px rgba(0,0,0,.5));
883 -moz-filter: drop-shadow(0 1px 20px rgba(0,0,0,.5));
884 -ms-filter: drop-shadow(0 1px 20px rgba(0,0,0,.5));
885 -o-filter: drop-shadow(0 1px 20px rgba(0,0,0,.5));
886 filter: drop-shadow(0 1px 20px rgba(0,0,0,.5));
887 }
1 /**
2 * http://www.alistapart.com/articles/alternate/
3 *
4 * var cookie = readCookie("style");
5 * var title = cookie ? cookie : getPreferredStyleSheet();
6 * setActiveStyleSheet(title);
7 */
8 (function(exports, $) {
9 function setActiveStyleSheet(title) {
10 var i, a, main;
11 for (i = 0; (a = document.getElementsByTagName("link")[i]); i++) {
12 if (a.getAttribute("rel").indexOf("style") !== -1 && a.getAttribute("title")) {
13 a.disabled = true;
14 if (a.getAttribute("title") === title) {
15 a.disabled = false;
16 }
17 }
18 }
19 }
20 exports.setActiveStyleSheet = setActiveStyleSheet;
21
22 function getActiveStyleSheet() {
23 var i, a;
24 for (i = 0; (a = document.getElementsByTagName("link")[i]); i++) {
25 if (a.getAttribute("rel").indexOf("style") !== -1 && a.getAttribute("title") && !a.disabled) {
26 return a.getAttribute("title");
27 }
28 }
29 return null;
30 }
31 exports.getActiveStyleSheet = getActiveStyleSheet;
32
33 function getPreferredStyleSheet() {
34 var i, a;
35 for (i = 0; (a = document.getElementsByTagName("link")[i]); i++) {
36 if (a.getAttribute("rel").indexOf("style") !== -1 &&
37 a.getAttribute("rel").indexOf("alt") === -1 &&
38 a.getAttribute("title")) {
39 return a.getAttribute("title");
40 }
41 }
42 return null;
43 }
44 exports.getPreferredStyleSheet = getPreferredStyleSheet;
45
46 function createCookie(name, value, days) {
47 var expires = "";
48 if (days) {
49 var date = new Date();
50 date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
51 expires = "; expires=" + date.toGMTString();
52 }
53 document.cookie = name + "=" + value + expires + "; path=/";
54 }
55
56 function readCookie(name) {
57 var nameEQ = name + "=";
58 var ca = document.cookie.split(';');
59 for (var i = 0; i < ca.length; i++) {
60 var c = ca[i];
61 while (c.charAt(0) === ' ') {
62 c = c.substring(1, c.length);
63 }
64 if (c.indexOf(nameEQ) === 0) {
65 return c.substring(nameEQ.length, c.length);
66 }
67 }
68 return null;
69 }
70
71 function createSwitcher() {
72 var $nav = $('.related').find('ul');
73 var styles = $('link').filter(function(i, link){
74 return $(link).attr('rel').indexOf('style') > -1 && $(link).attr('title');
75 }).map(function(i, link) {
76 return $(link).attr('title');
77 });
78 $(styles).each(function(i, style) {
79 var $link = $('<a/>').attr('href', '#')
80 .attr('title', style)
81 .addClass('style-switch')
82 .text(style);
83 $nav.prepend($('<li/>').addClass('right').append($link));
84 });
85 $('.style-switch').bind('click', function(event) {
86 event.preventDefault();
87 setActiveStyleSheet($(this).attr('title'));
88 });
89 }
90
91 exports.onload = function(e) {
92 var cookie = readCookie("style");
93 var title = cookie ? cookie : getPreferredStyleSheet();
94 setActiveStyleSheet(title);
95 createSwitcher();
96 }
97
98 exports.onunload = function(e) {
99 var title = getActiveStyleSheet();
100 createCookie("style", title, 365);
101 }
102
103 var cookie = readCookie("style");
104 var title = cookie ? cookie : getPreferredStyleSheet();
105 setActiveStyleSheet(title);
106 })(window, window.jQuery);
1 [theme]
2 inherit = basic
1 Changelog
2 =========
3
4 The CasperJS changelog is `hosted on github <https://github.com/n1k0/casperjs/blob/master/CHANGELOG.md#casperjs-changelog>`_.
1 .. _cli:
2
3 .. index:: Command line, CLI, PhantomJS, Shell, arguments, options
4
5 ======================
6 Using the command line
7 ======================
8
9 CasperJS ships with a built-in command line parser on top of PhantomJS' one, located in the ``cli`` module; it exposes passed arguments as **positional ones** and **named options**
10
11 But no worries for manipulating the ``cli`` module parsing API, a ``Casper`` instance always contains a ready to use ``cli`` property, allowing easy access of all these parameters.
12
13 Let's consider this simple casper script::
14
15 var casper = require("casper").create();
16
17 casper.echo("Casper CLI passed args:");
18 require("utils").dump(casper.cli.args);
19
20 casper.echo("Casper CLI passed options:");
21 require("utils").dump(casper.cli.options);
22
23 casper.exit();
24
25 .. note::
26
27 Please note the two ``casper-path`` and ``cli`` options; these are passed to the casper script through the ``casperjs`` Python executable.
28
29 Execution results::
30
31 $ casperjs test.js arg1 arg2 arg3 --foo=bar --plop anotherarg
32 Casper CLI passed args: [
33 "arg1",
34 "arg2",
35 "arg3",
36 "anotherarg"
37 ]
38 Casper CLI passed options: {
39 "casper-path": "/Users/niko/Sites/casperjs",
40 "cli": true,
41 "foo": "bar",
42 "plop": true
43 }
44
45 Getting, checking or dropping parameters::
46
47 var casper = require("casper").create();
48 casper.echo(casper.cli.has(0));
49 casper.echo(casper.cli.get(0));
50 casper.echo(casper.cli.has(3));
51 casper.echo(casper.cli.get(3));
52 casper.echo(casper.cli.has("foo"));
53 casper.echo(casper.cli.get("foo"));
54 casper.cli.drop("foo");
55 casper.echo(casper.cli.has("foo"));
56 casper.echo(casper.cli.get("foo"));
57 casper.exit();
58
59 Execution results:
60
61 .. code-block:: text
62
63 $ casperjs test.js arg1 arg2 arg3 --foo=bar --plop anotherarg
64 true
65 arg1
66 true
67 anotherarg
68 true
69 bar
70 false
71 undefined
72
73 .. hint::
74
75 What if you want to check if any arg or option has been passed to your script? Here you go::
76
77 // removing default options passed by the Python executable
78 casper.cli.drop("cli");
79 casper.cli.drop("casper-path");
80
81 if (casper.cli.args.length === 0 && Object.keys(casper.cli.options).length === 0) {
82 casper.echo("No arg nor option passed").exit();
83 }
84
85 `casperjs` native options
86 -------------------------
87
88 .. versionadded:: 1.1
89
90 .. index:: Logging, log levels
91
92 The `casperjs` command has two available options:
93
94 - ``--direct``: to prints out log messages to the console
95 - ``--log-level=[debug|info|warning|error]`` to set the :ref:`logging level <logging>`
96
97 Example:
98
99 .. code-block:: text
100
101 $ casperjs --direct --log-level=debug myscript.js
102
103 Last but not least, you can still use all PhantomJS standard CLI options as you would do with any other phantomjs script:
104
105 .. code-block:: text
106
107 $ casperjs --web-security=no --cookies-file=/tmp/mycookies.txt myscript.js
108
109 .. hint::
110
111 To remember what the native phantomjs available cli options are, run the ``phantomjs --help`` command.
112
113
114 .. index:: Raw values
115
116 Raw parameter values
117 --------------------
118
119 .. versionadded:: 1.0
120
121 By default, the cli object will process every passed argument & cast them to the appropriate detected type; example script::
122
123 var casper = require('casper').create();
124 var utils = require('utils');
125
126 utils.dump(casper.cli.get('foo'));
127
128 casper.exit();
129
130 If you run this script:
131
132 .. code-block:: text
133
134 $ casperjs c.js --foo=01234567
135 1234567
136
137 As you can see, the ``01234567`` value has been cast to a *Number*.
138
139 Sometimes, you just want the original string; then you can use the ``raw`` property of the ``cli`` object, which contains the raw values passed parameters::
140
141 var casper = require('casper').create();
142 var utils = require('utils');
143
144 utils.dump(casper.cli.get('foo'));
145 utils.dump(casper.cli.raw.get('foo'));
146
147 casper.exit();
148
149 Sample usage:
150
151 .. code-block:: text
152
153 $ casperjs c.js --foo=01234567
154 1234567
155 "01234567"
156
1 # -*- coding: utf-8 -*-
2 #
3 # CasperJS documentation
4 #
5 # If extensions (or modules to document with autodoc) are in another directory,
6 # add these directories to sys.path here. If the directory is relative to the
7 # documentation root, use os.path.abspath to make it absolute, like shown here.
8 #sys.path.insert(0, os.path.abspath('.'))
9
10 from datetime import date
11
12 # -- General configuration -----------------------------------------------------
13
14 # If your documentation needs a minimal Sphinx version, state it here.
15 #needs_sphinx = '1.0'
16
17 # Add any Sphinx extension module names here, as strings. They can be extensions
18 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
19 extensions = ['sphinx.ext.autodoc', 'sphinx.ext.extlinks']
20
21 # Add any paths that contain templates here, relative to this directory.
22 templates_path = ['_templates']
23
24 highlight_language = 'javascript'
25
26 # The suffix of source filenames.
27 source_suffix = '.rst'
28
29 # Prolog
30 rst_prolog = ('.. note:: This is the documentation for the |release| version of'
31 ' CasperJS. Find docs for 1.0 stable'
32 ' `on the official website <http://casperjs.org/>`_.\n')
33
34 # The encoding of source files.
35 source_encoding = 'utf-8'
36
37 # The master toctree document.
38 master_doc = 'index'
39
40 # General information about the project.
41 project = u'CasperJS'
42 copyright = (u'2011-%d Nicolas Perriault and contributors. CasperJS logo by Jeremy Forveille'
43 % date.today().year)
44
45 # The version info for the project you're documenting, acts as replacement for
46 # |version| and |release|, also used in various other places throughout the
47 # built documents.
48 #
49 # The short X.Y version.
50 version = '1.1'
51 # The full version, including alpha/beta/rc tags.
52 release = '1.1.0-DEV'
53
54 # The language for content autogenerated by Sphinx. Refer to documentation
55 # for a list of supported languages.
56 #language = None
57
58 # There are two options for replacing |today|: either, you set today to some
59 # non-false value, then it is used:
60 #today = ''
61 # Else, today_fmt is used as the format for a strftime call.
62 #today_fmt = '%B %d, %Y'
63
64 # List of patterns, relative to source directory, that match files and
65 # directories to ignore when looking for source files.
66 exclude_patterns = ['_build', 'README.md']
67
68 # The reST default role (used for this markup: `text`) to use for all documents.
69 #default_role = None
70
71 # If true, '()' will be appended to :func: etc. cross-reference text.
72 #add_function_parentheses = True
73
74 # If true, the current module name will be prepended to all description
75 # unit titles (such as .. function::).
76 #add_module_names = True
77
78 # If true, sectionauthor and moduleauthor directives will be shown in the
79 # output. They are ignored by default.
80 #show_authors = False
81
82 # The name of the Pygments (syntax highlighting) style to use.
83 #pygments_style = 'default'
84
85 # A list of ignored prefixes for module index sorting.
86 #modindex_common_prefix = []
87
88
89 # -- Options for HTML output ---------------------------------------------------
90
91 # The theme to use for HTML and HTML Help pages. See the documentation for
92 # a list of builtin themes.
93 html_theme = 'casperjs'
94
95 # Theme options are theme-specific and customize the look and feel of a theme
96 # further. For a list of options available for each theme, see the
97 # documentation.
98 #html_theme_options = {}
99
100 # Add any paths that contain custom themes here, relative to this directory.
101 html_theme_path = ['_themes']
102
103 # The name for this set of Sphinx documents. If None, it defaults to
104 # "<project> v<release> documentation".
105 #html_title = None
106
107 # A shorter title for the navigation bar. Default is the same as html_title.
108 #html_short_title = None
109
110 # The name of an image file (relative to this directory) to place at the top
111 # of the sidebar.
112 #html_logo = None
113
114 # The name of an image file (within the static path) to use as favicon of the
115 # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
116 # pixels large.
117 html_favicon = 'casperjs-favicon.ico'
118
119 # Add any paths that contain custom static files (such as style sheets) here,
120 # relative to this directory. They are copied after the builtin static files,
121 # so a file named "default.css" will overwrite the builtin "default.css".
122 html_static_path = ['_static']
123
124 # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
125 # using the given strftime format.
126 #html_last_updated_fmt = '%b %d, %Y'
127
128 # If true, SmartyPants will be used to convert quotes and dashes to
129 # typographically correct entities.
130 #html_use_smartypants = True
131
132 # Custom sidebar templates, maps document names to template names.
133 html_sidebars = {
134 '*': [
135 'globaltoc.html',
136 'relations.html',
137 'sourcelink.html',
138 'searchbox.html',
139 'addon.html'
140 ],
141 'modules/*': [
142 'localtoc.html',
143 'globaltoc.html',
144 'relations.html',
145 'sourcelink.html',
146 'searchbox.html',
147 'addon.html'
148 ],
149 }
150
151 # Additional templates that should be rendered to pages, maps page names to
152 # template names.
153 #html_additional_pages = {}
154
155 # If false, no module index is generated.
156 #html_domain_indices = True
157
158 # If false, no index is generated.
159 #html_use_index = True
160
161 # If true, the index is split into individual pages for each letter.
162 #html_split_index = False
163
164 # If true, links to the reST sources are added to the pages.
165 #html_show_sourcelink = True
166
167 # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
168 #html_show_sphinx = True
169
170 # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
171 #html_show_copyright = True
172
173 # If true, an OpenSearch description file will be output, and all pages will
174 # contain a <link> tag referring to it. The value of this option must be the
175 # base URL from which the finished HTML is served.
176 #html_use_opensearch = ''
177
178 # This is the file name suffix for HTML files (e.g. ".xhtml").
179 #html_file_suffix = None
180
181 # Output file base name for HTML help builder.
182 htmlhelp_basename = 'casper-docs'
183
184
185 # -- Options for LaTeX output --------------------------------------------------
186
187 latex_elements = {
188 # The paper size ('letterpaper' or 'a4paper').
189 #'papersize': 'letterpaper',
190
191 # The font size ('10pt', '11pt' or '12pt').
192 #'pointsize': '10pt',
193
194 # Additional stuff for the LaTeX preamble.
195 #'preamble': '',
196 }
197
198 # Grouping the document tree into LaTeX files. List of tuples
199 # (source start file, target name, title, author, documentclass [howto/manual]).
200 # latex_documents = [
201 # (),
202 # ]
203
204 # The name of an image file (relative to this directory) to place at the top of
205 # the title page.
206 #latex_logo = None
207
208 # For "manual" documents, if this is true, then toplevel headings are parts,
209 # not chapters.
210 #latex_use_parts = False
211
212 # If true, show page references after internal links.
213 #latex_show_pagerefs = False
214
215 # If true, show URL addresses after external links.
216 #latex_show_urls = False
217
218 # Documents to append as an appendix to all manuals.
219 #latex_appendices = []
220
221 # If false, no module index is generated.
222 #latex_domain_indices = True
223
224
225 # -- Options for manual page output --------------------------------------------
226
227 # One entry per manual page. List of tuples
228 # (source start file, name, description, authors, manual section).
229 man_pages = [
230 ('index', 'casperjs', u'casperjs documentation', [u'Nicolas Perriault'], 1)
231 ]
232
233 # If true, show URL addresses after external links.
234 #man_show_urls = False
235
236
237 # -- Options for Texinfo output ------------------------------------------------
238
239 # Grouping the document tree into Texinfo files. List of tuples
240 # (source start file, target name, title, author,
241 # dir menu entry, description, category)
242 texinfo_documents = [
243 ('index', 'CasperJS', u'CasperJS Documentation',
244 u'Nicolas Perriault', 'CasperJS', 'CasperJS docs.', 'Miscellaneous'),
245 ]
246
247 # Documents to append as an appendix to all manuals.
248 #texinfo_appendices = []
249
250 # If false, no module index is generated.
251 #texinfo_domain_indices = True
252
253 # How to display URL addresses: 'footnote', 'no', or 'inline'.
254 #texinfo_show_urls = 'footnote'
255
256
257 extlinks = {
258 'issue': ('https://github.com/n1k0/casperjs/issues/%s', '#'),
259 'repo': ('https://github.com/n1k0/casperjs/%s', ''),
260 }
1 Credits
2 =======
3
4 Author
5 ------
6
7 CasperJS is mainly developed by `Nicolas Perriault <https://nicolas.perriault.net/>`_ on its free time.
8
9 If you want to thank him and/or sponsor the development of CasperJS, please consider donating (see links in the sidebar).
10
11 Contributors
12 ------------
13
14 These people have contributed to CasperJS:
15
16 - Brikou CARRE
17 - Thomas Parisot
18 - Han Yu
19 - Chris Lorenzo
20 - Victor Yap
21 - Rob Barreca
22 - Tyler Ritchie
23 - Nick Rabinowitz
24 - Pascal Borreli
25 - Dave Lee
26 - Andrew Childs
27 - Solomon White
28 - Reina Sweet
29 - Jan Schaumann
30 - Elmar Langholz
31 - Clochix
32 - Donovan Hutchinson
33 - Julien Moulin
34 - Michael Geers
35 - Jason Funk
36 - Vladimir Chizhov
37 - Jean-Philippe Serafin
38 - snkashis
39 - Rafael
40 - Andrew de Andrade
41 - Ben Lowery
42 - Chris Winters
43 - Christophe Benz
44 - Harrison Reiser
45 - Jan Pochyla
46 - Jan-Martin Fruehwacht
47 - Julian Gruber
48 - Justin Slattery
49 - Justine Tunney
50 - KaroDidi
51 - Leandro Boscariol
52 - Maisons du monde
53 - Marcel Duran
54 - Mathieu Agopian
55 - Mehdi Kabab
56 - Mikko Peltonen
57 - Rafael Garcia
58 - Raphaël Benitte
59 - Tim Bunce
60
61 Logo
62 ----
63
64 CasperJS logo designed by `Jeremy Forveille <http://www.forveillejeremy.com/>`_
1 .. _debugging:
2
3 .. index:: Bugs, Debugging
4
5 =========
6 Debugging
7 =========
8
9 .. contents:: A few tips for debugging your casper scripts:
10 :local:
11
12
13 Use the :index:`verbose` mode
14 -----------------------------
15
16 By default & by design, a ``Casper`` instance won't print anything to the console. This can be very limitating & frustrating when creating or debugging scripts, so a good practice is to always start coding a script using these :index:`settings`::
17
18 var casper = require('casper').create({
19 verbose: true,
20 logLevel: "debug"
21 });
22
23 The ``verbose`` setting will tell Casper to write every logged message at the ``logLevel`` logging level onto the standard output, so you'll be able to trace every step made.
24
25 .. warning::
26
27 Output will then be pretty verbose, and will potentially display sensitive informations onto the console. **Use with care on production.**
28
29
30 Hook in the deep using :index:`events`
31 --------------------------------------
32
33 :doc:`Events <events-filters>` are a very powerful features of CasperJS, and you should probably give it a look if you haven't already.
34
35 Some interesting events you may eventually use to debug your scripts:
36
37 - The ``http.status.XXX`` event will be emitted everytime a resource is sent with the `HTTP code <http://en.wikipedia.org/wiki/List_of_HTTP_status_codes>`_ corresponding to ``XXX``;
38 - The ``remote.alert`` everytime an ``alert()`` call is performed client-side;
39 - ``remote.message`` everytime a message is sent to the client-side console;
40 - ``step.added`` everytime a step is added to the stack;
41 - etc…
42
43 Listening to an event is dead easy::
44
45 casper.on('http.status.404', function(resource) {
46 this.log('Hey, this one is 404: ' + resource.url, 'warning');
47 });
48
49 Ensure to check the :ref:`full list <events_list>` of all the other available events.
50
51
52 .. _debugging_dump:
53
54 Dump serialized values to the console
55 -------------------------------------
56
57 Sometimes it's helpful to inspect a variable, especially Object contents. The :ref:`utils_dump() <utils_dump>` function can achieve just that::
58
59 require('utils').dump({
60 foo: {
61 bar: 42
62 },
63 });
64
65 .. note::
66
67 :ref:`utils_dump() <utils_dump>` won't be able to serialize function nor complex cyclic structures though.
68
69
70 Localize yourself in modules
71 ----------------------------
72
73 If you're creating Casper modules, a cool thing to know is that there's a special built-in variable available in every module, ``__file__``, which contains the absolute path to current javascript file (the module file).
74
75
76 Name your closures
77 ------------------
78
79 Probably one of the most easy but effective best practice, always name your closures:
80
81 **Hard to track:**
82
83 ::
84
85 casper.start('http://foo.bar/', function() {
86 this.evaluate(function() {
87 // ...
88 });
89 });
90
91 **Easier:**
92
93 ::
94
95 casper.start('http://foo.bar/', function afterStart() {
96 this.evaluate(function evaluateStuffAfterStart() {
97 // ...
98 });
99 });
100
101 That way, everytime one is failing, its name will be printed out in the :index:`stack trace`, **so you can more easily locate it within your code**.
102
103 .. note::
104
105 This one also applies for all your other Javascript works, of course ;)
1 .. _events_filters:
2
3 Events & filters
4 ================
5
6 CasperJS provides an `event handler <#events>`_ very similar to the `nodejs <http://nodejs.org>`_' `one <https://github.com/joyent/node/blob/master/lib/events.js>`_; actually it borrows most of its codebase. CasperJS also adds `filters <#filters>`_, which are basically ways to alter values asynchronously.
7
8
9 .. index:: ! events
10
11 Events
12 ------
13
14 Using events is pretty much straightforward if you're a node developer, or if you worked with any evented system before::
15
16 var casper = require('casper').create();
17
18 casper.on('resource.received', function(resource) {
19 casper.echo(resource.url);
20 });
21
22 Emitting you own events
23 +++++++++++++++++++++++
24
25 Of course you can emit your own events, using the ``Casper.emit()`` method::
26
27 var casper = require('casper').create();
28
29 // listening to a custom event
30 casper.on('google.loaded', function() {
31 this.echo('Google page title is ' + this.getTitle());
32 });
33
34 casper.start('http://google.com/', function() {
35 // emitting a custom event
36 this.emit('google.loaded');
37 });
38
39 casper.run();
40
41 .. _events_list:
42
43 Events reference
44 ++++++++++++++++
45
46 ``back``
47 ~~~~~~~~
48
49 **Arguments:** ``None``
50
51 Emitted when the embedded browser is asked to go back a step in its history.
52
53 ``capture.saved``
54 ~~~~~~~~~~~~~~~~~
55
56 **Arguments:** ``targetFile``
57
58 Emitted when a :index:`screenshot` image has been captured.
59
60 .. index:: click
61
62 ``click``
63 ~~~~~~~~~
64
65 **Arguments:** ``selector``
66
67 Emitted when the ``Casper.click()`` method has been called.
68
69 ``die``
70 ~~~~~~~
71
72 **Arguments:** ``message, status``
73
74 Emitted when the ``Casper.die()`` method has been called.
75
76 .. index:: download
77
78 ``downloaded.file``
79 ~~~~~~~~~~~~~~~~~~~
80
81 **Arguments:** ``targetPath``
82
83 Emitted when a file has been downloaded by :ref:`Casper.download() <casper_download>`; ``target`` will contain the path to the downloaded file.
84
85 .. index:: error
86
87 ``error``
88 ~~~~~~~~~
89
90 **Arguments:** ``msg, backtrace``
91
92 .. versionadded:: 0.6.9
93
94 Emitted when an error hasn't been caught. Do basically what PhantomJS' ``onError()`` native handler does.
95
96 .. index:: exit
97
98 ``exit``
99 ~~~~~~~~
100
101 **Arguments:** ``status``
102
103 Emitted when the ``Casper.exit()`` method has been called.
104
105 .. index:: fill
106
107 ``fill``
108 ~~~~~~~~
109
110 **Arguments:** ``selector, vals, submit``
111
112 Emitted when a form is filled using the ``Casper.fill()`` method.
113
114 ``forward``
115 ~~~~~~~~~~~
116
117 **Arguments:** ``None``
118
119 Emitted when the embedded browser is asked to go forward a step in its history.
120
121 .. index:: auth
122
123 ``http.auth``
124 ~~~~~~~~~~~~~
125
126 **Arguments:** ``username, password``
127
128 Emitted when http authentication parameters are set.
129
130 .. index:: HTTP
131
132 ``http.status.[code]``
133 ~~~~~~~~~~~~~~~~~~~~~~
134
135 **Arguments:** ``resource``
136
137 Emitted when any given HTTP reponse is received with the status code specified by ``[code]``, eg.::
138
139 casper.on('http.status.404', function(resource) {
140 casper.echo(resource.url + ' is 404');
141 })
142
143 ``load.started``
144 ~~~~~~~~~~~~~~~~
145
146 **Arguments:** ``None``
147
148 Emitted when PhantomJS' ``WebPage.onLoadStarted`` event callback is called.
149
150 ``load.failed``
151 ~~~~~~~~~~~~~~~
152
153 **Arguments:** ``Object``
154
155 Emitted when PhantomJS' ``WebPage.onLoadFinished`` event callback has been called and failed.
156
157 ``load.finished``
158 ~~~~~~~~~~~~~~~~~
159
160 **Arguments:** ``status``
161
162 Emitted when PhantomJS' ``WebPage.onLoadFinished`` event callback is called.
163
164 .. index:: log
165
166 ``log``
167 ~~~~~~~
168
169 **Arguments:** ``entry``
170
171 Emitted when the ``Casper.log()`` method has been called. The ``entry`` parameter is an Object like this::
172
173 {
174 level: "debug",
175 space: "phantom",
176 message: "A message",
177 date: "a javascript Date instance"
178 }
179
180 ..index:: click
181
182 ``mouse.click``
183 ~~~~~~~~~~~~~~~
184
185 **Arguments:** ``args``
186
187 Emitted when the mouse left-click something or somewhere.
188
189 ``mouse.down``
190 ~~~~~~~~~~~~~~
191
192 **Arguments:** ``args``
193
194 Emitted when the mouse presses on something or somewhere with the left button.
195
196 ``mouse.move``
197 ~~~~~~~~~~~~~~
198
199 **Arguments:** ``args``
200
201 Emitted when the mouse moves onto something or somewhere.
202
203 ``mouse.up``
204 ~~~~~~~~~~~~
205
206 **Arguments:** ``args``
207
208 Emitted when the mouse releases the left button over something or somewhere.
209
210 ``navigation.requested``
211 ~~~~~~~~~~~~~~~~~~~~~~~~
212
213 **Arguments:** ``url, navigationType, navigationLocked, isMainFrame``
214
215 .. versionadded:: 1.0
216
217 Emitted each time a navigation operation has been requested. Available navigation types are: ``LinkClicked``, ``FormSubmitted``, ``BackOrForward``, ``Reload``, ``FormResubmitted`` and ``Other``.
218
219 .. index:: HTTP
220
221 ``open``
222 ~~~~~~~~
223
224 ``location, settings``
225
226 Emitted when an HTTP request is sent. First callback arg is the location, second one is a request settings Object of the form::
227
228 {
229 method: "post",
230 data: "foo=42&chuck=norris"
231 }
232
233 ``page.created``
234 ~~~~~~~~~~~~~~~~
235
236 **Arguments:** ``page``
237
238 Emitted when PhantomJS' ``WebPage`` object used by CasperJS has been created.
239
240 ``page.error``
241 ~~~~~~~~~~~~~~
242
243 **Arguments:** ``message, trace``
244
245 Emitted when retrieved page leaved a Javascript error uncaught::
246
247 casper.on("page.error", function(msg, trace) {
248 this.echo("Error: " + msg, "ERROR");
249 });
250
251 ``page.initialized``
252 ~~~~~~~~~~~~~~~~~~~~
253
254 **Arguments:** ``WebPage``
255
256 Emitted when PhantomJS' ``WebPage`` object used by CasperJS has been initialized.
257
258 .. index:: HTTP
259
260 ``page.resource.received``
261 ~~~~~~~~~~~~~~~~~~~~~~~~~~
262
263 **Arguments:** ``response``
264
265 Emitted when the HTTP response corresponding to current required url has been received.
266
267 .. index:: HTTP
268
269 ``page.resource.requested``
270 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
271
272 **Arguments:** ``request``
273
274 Emitted when a new HTTP request is performed to open the required url.
275
276 ``popup.created``
277 ~~~~~~~~~~~~~~~~~
278
279 **Arguments:** ``WebPage``
280
281 Emitted when a new window has been opened.
282
283 ``popup.loaded``
284 ~~~~~~~~~~~~~~~~
285
286 **Arguments:** ``WebPage``
287
288 Emitted when a new window has been loaded.
289
290 ``popup.closed``
291 ~~~~~~~~~~~~~~~~
292
293 **Arguments:** ``WebPage``
294
295 Emitted when a new opened window has been closed.
296
297 ``popup.created``
298 ~~~~~~~~~~~~~~~~~
299
300 **Arguments:** ``WebPage``
301
302 Emitted when a new window has been opened.
303
304 ``remote.alert``
305 ~~~~~~~~~~~~~~~~
306
307 **Arguments:** ``message``
308
309 Emitted when a remote ``alert()`` call has been performed.
310
311 ``remote.message``
312 ~~~~~~~~~~~~~~~~~~
313
314 **Arguments:** ``msg``
315
316 Emitted when any remote console logging call has been performed.
317
318 ``resource.received``
319 ~~~~~~~~~~~~~~~~~~~~~
320
321 **Arguments:** ``resource``
322
323 Emitted when any resource has been received.
324
325 ``resource.requested``
326 ~~~~~~~~~~~~~~~~~~~~~~
327
328 **Arguments:** ``request``
329
330 Emitted when any resource has been requested.
331
332 ``run.complete``
333 ~~~~~~~~~~~~~~~~
334
335 **Arguments:** ``None``
336
337 Emitted when the whole series of steps in the stack have been executed.
338
339 ``run.start``
340 ~~~~~~~~~~~~~
341
342 **Arguments:** ``None``
343
344 Emitted when ``Casper.run()`` is called.
345
346 ``starting``
347 ~~~~~~~~~~~~
348
349 **Arguments:** ``None``
350
351 Emitted when ``Casper.start()`` is called.
352
353 ``started``
354 ~~~~~~~~~~~
355
356 **Arguments:** ``None``
357
358 Emitted when Casper has been started using ``Casper.start()``.
359
360 ``step.added``
361 ~~~~~~~~~~~~~~
362
363 **Arguments:** ``step``
364
365 Emitted when a new navigation step has been added to the stack.
366
367 ``step.complete``
368 ~~~~~~~~~~~~~~~~~
369
370 **Arguments:** ``stepResult``
371
372 Emitted when a navigation step has been executed.
373
374 ``step.created``
375 ~~~~~~~~~~~~~~~~
376
377 **Arguments:** ``fn``
378
379 Emitted when a new navigation step has been created.
380
381 ``step.start``
382 ~~~~~~~~~~~~~~
383
384 **Arguments:** ``step``
385
386 Emitted when a navigation step has been started.
387
388 ``step.timeout``
389 ~~~~~~~~~~~~~~~~
390
391 **Arguments:** ``None``
392
393 Emitted when a navigation step has been executed.
394
395 ``timeout``
396 ~~~~~~~~~~~
397
398 **Arguments:** ``None``
399
400 Emitted when the execution time of the script has reached the ``Casper.options.timeout`` value.
401
402 ``url.changed``
403 ~~~~~~~~~~~~~~~
404
405 **Arguments:** ``url``
406
407 .. versionadded:: 1.0
408
409 Emitted each time the current page url changes.
410
411 .. index:: viewport
412
413 ``viewport.changed``
414 ~~~~~~~~~~~~~~~~~~~~
415
416 **Arguments:** ``[width, height]``
417
418 Emitted when the viewport has been changed.
419
420 ``wait.done``
421 ~~~~~~~~~~~~~
422
423 **Arguments:** ``None``
424
425 Emitted when a ``Casper.wait()``\ *operation ends.*
426
427 ``wait.start``
428 ~~~~~~~~~~~~~~
429
430 **Arguments:** ``None``
431
432 Emitted when a ``Casper.wait()`` operation starts.
433
434 ``waitFor.timeout``
435 ~~~~~~~~~~~~~~~~~~~
436
437 **Arguments:** ``None``
438
439 Emitted when the execution time of a ``Casper.wait*()`` operation has exceeded the value of ``Casper.options.stepTimeout``.
440
441
442 .. index:: filters
443
444 Filters
445 -------
446
447 Filters allow you to alter some values asynchronously. Sounds obscure? Let's take a simple example and imagine you would like to alter every single url opened by CasperJS to append a ``foo=42`` query string parameter::
448
449 var casper = require('casper').create();
450
451 casper.setFilter('open.location', function(location) {
452 return /\?+/.test(location) ? location += "&foo=42" : location += "?foo=42";
453 });
454
455 There you have it, every single requested url will have this appended. Let me bet you'll find far more interesting use cases than my silly one ;)
456
457 Here'a the list of all available filters with their expected return value:
458
459 Filters reference
460 +++++++++++++++++
461
462 .. index:: screenshot
463
464 ``capture.target_filename``
465 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
466
467 **Arguments:** ``args``
468
469 **Return type:** ``String``
470
471 Allows to alter the value of the filename where a screen capture should be stored.
472
473 ``echo.message``
474 ~~~~~~~~~~~~~~~~
475
476 **Arguments:** ``message``
477
478 **Return type:** ``String``
479
480 Allows to alter every message written onto stdout.
481
482 ``log.message``
483 ~~~~~~~~~~~~~~~
484
485 **Arguments:** ``message``
486
487 **Return type:** ``String``
488
489 Allows to alter every log message.
490
491 ``open.location``
492 ~~~~~~~~~~~~~~~~~
493
494 **Arguments:** ``args``
495
496 **Return type:** ``String``
497
498 Allows to alter every url before it being opened.
499
500 ``page.confirm``
501 ~~~~~~~~~~~~~~~~
502
503 **Arguments:** ``message``
504
505 **Return type:** ``Boolean``
506
507 .. versionadded:: 1.0
508
509 Allows to react on a javascript ``confirm()`` call::
510
511 casper.setFilter("page.confirm", function(msg) {
512 return msg === "Do you like vbscript?" ? false : true;
513 });
514
515 ``page.prompt``
516 ~~~~~~~~~~~~~~~
517
518 **Arguments:** ``message, value``
519
520 **Return type:** ``String``
521
522 .. versionadded:: 1.0
523
524 Allows to react on a javascript ``prompt()`` call::
525
526 casper.setFilter("page.prompt", function(msg, value) {
527 if (msg === "What's your name?") {
528 return "Chuck";
529 }
530 });
1 .. _extending:
2
3 .. index:: extending, inheritance, prototype
4
5 =========
6 Extending
7 =========
8
9 Sometimes it can be convenient to add your own methods to a ``Casper`` object instance; you can easily do so as illustrated in the example below::
10
11 var casper = require('casper').create({
12 verbose: true,
13 logLevel: "debug"
14 });
15
16 var links = {
17 'http://edition.cnn.com/': 0,
18 'http://www.nytimes.com/': 0,
19 'http://www.bbc.co.uk/': 0,
20 'http://www.guardian.co.uk/': 0
21 };
22
23 casper.countLinks = function() {
24 return this.evaluate(function() {
25 return __utils__.findAll('a[href]').length;
26 });
27 };
28
29 casper.renderJSON = function(what) {
30 return this.echo(JSON.stringify(what, null, ' '));
31 };
32
33 casper.start();
34
35 casper.each(Object.keys(links), function(casper, link) {
36 this.thenOpen(link, function() {
37 links[link] = this.countLinks();
38 });
39 });
40
41 casper.run(function() {
42 this.renderJSON(links).exit();
43 });
44
45 But that's just plain old *monkey-patching* the ``casper`` object, and you may probably want a more OO approach… That's where the ``inherits()`` function from the ``utils`` module and ported from `nodejs <http://nodejs.org/>`_ comes handy::
46
47 var Casper = require('casper').Casper;
48 var utils = require('utils');
49 var links = {
50 'http://edition.cnn.com/': 0,
51 'http://www.nytimes.com/': 0,
52 'http://www.bbc.co.uk/': 0,
53 'http://www.guardian.co.uk/': 0
54 };
55
56 function Fantomas() {
57 Fantomas.super_.apply(this, arguments);
58 }
59
60 // Let's make our Fantomas class extending the Casper one
61 // please note that at this point, CHILD CLASS PROTOTYPE WILL BE OVERRIDEN
62 utils.inherits(Fantomas, Casper);
63
64 Fantomas.prototype.countLinks = function() {
65 return this.evaluate(function() {
66 return __utils__.findAll('a[href]').length;
67 });
68 };
69
70 Fantomas.prototype.renderJSON = function(what) {
71 return this.echo(JSON.stringify(what, null, ' '));
72 };
73
74 var fantomas = new Fantomas({
75 verbose: true,
76 logLevel: "debug"
77 });
78
79 fantomas.start();
80
81 Object.keys(links).forEach(function(url) {
82 fantomas.thenOpen(url, function() {
83 links[url] = this.countLinks();
84 });
85 });
86
87 fantomas.run(function() {
88 this.renderJSON(links).exit();
89 });
90
91 .. note::
92
93 The use of the ``super_`` child class property which becomes available once its parent has been defined using ``inherits()``; it contains a reference to the parent constructor.
94
95 **Don't forget to call ``Casper``'s parent constructor!**
96
97 Of course this approach is bit more verbose than the easy *monkey-patching* one, so please ensure you're not just overengineering stuff by subclassing the ``Casper`` class.
98
99
100 .. index:: coffeescript
101
102 Using CoffeeScript
103 ~~~~~~~~~~~~~~~~~~
104
105 If you're writing your casper scripts using `CoffeeScript <http://coffeescript.org/>`_, extending casper is getting a bit more straightforward:
106
107 .. code-block:: coffeescript
108
109 links =
110 'http://edition.cnn.com/': 0
111 'http://www.nytimes.com/': 0
112 'http://www.bbc.co.uk/': 0
113 'http://www.guardian.co.uk/': 0
114
115 class Fantomas extends require('casper').Casper
116 countLinks: ->
117 @evaluate ->
118 __utils__.findAll('a').length
119
120 renderJSON: (what) ->
121 @echo JSON.stringify what, null, ' '
122
123 fantomas = new Fantomas
124 loadImages: false
125 logLevel: "debug"
126 verbose: true
127
128 fantomas.start()
129
130 for url of links
131 do (url) ->
132 fantomas.thenOpen url, ->
133 links[url] = @countLinks()
134
135 fantomas.run ->
136 @renderJSON links
137 @exit()
138
1 .. _faq:
2
3 .. index:: FAQ, Help
4
5 ===
6 FAQ
7 ===
8
9 .. contents:: Here's a selection of the most frequently asked questions by CasperJS newcomers:
10 :local:
11 :backlinks: top
12
13 .. index:: Node.js
14
15 Is CasperJS a `node.js <http://nodejs.org/>`_ library?
16 ------------------------------------------------------
17
18 **No.** CasperJS is written on top of PhantomJS_, which is a node-independent Qt_/WebKit_ based library. If you try to run your CasperJS script with node, it just won't work out of the box.
19
20 .. hint:: If you want to drive CasperJS from node, try `SpookyJS <https://github.com/WaterfallEngineering/SpookyJS>`_.
21
22
23 .. index:: Bugs, Contributing, error
24
25 I'm stuck! I think there's a bug! What can I do?
26 ------------------------------------------------
27
28 Before rage-tweeting:
29
30 1. Read the `docs <http://casperjs.org/>`_
31 2. Check if an `issue <https://github.com/n1k0/casperjs/issues>`_ has been open about your problem already
32 3. Check you're running the `latest stable tag <https://github.com/n1k0/casperjs/tags>`_
33 4. Check you're running the `latest version <http://code.google.com/p/phantomjs/downloads/list>`_ of PhantomJS_
34 5. Ask on the `project mailing list <https://groups.google.com/forum/#!forum/casperjs>`_:
35
36 a. try to post a reproducible, minimal test case
37 b. compare casperjs results with native phantomjs ones
38 c. if the problem also occurs with native phantomjs, ask on `phantomjs mailing list <https://groups.google.com/forum/#!forum/phantomjs>`_
39
40 6. Eventually, `file an issue <https://github.com/n1k0/casperjs/issues/new>`_.
41
42
43 .. index:: Testing
44
45 The ``casper.test`` property is undefined, I can't write any test!
46 ------------------------------------------------------------------
47
48 That's because as of 1.1, the ``casper.test`` property is only set to a :doc:`Tester <modules/tester>` instance when using the ``casperjs test`` subcommand.
49
50 You may want to read the :doc:`testing documentation <testing>` for more information.
51
52
53 .. index:: Code reuse
54
55 I keep copy and pasting stuff in my test scripts, that's boring
56 ---------------------------------------------------------------
57
58 Have a look at `this gist <https://gist.github.com/3813361>`_, it might help.
59
60 Also, don't forget that CasperJS supports a `CommonJS-compliant module pattern <http://wiki.commonjs.org/wiki/Modules/1.1>`_ implementation.
61
62 .. note::
63
64 CasperJS' implementation of ``require()`` differs a bit from the one provided by PhantomJS_, but I personnaly never really encountered any functional difference.
65
66
67 .. index:: Versionning
68
69 What is the versioning policy of CasperJS?
70 ------------------------------------------
71
72 Releases will follow the `SemVer standard <http://semver.org/>`_; they
73 will be numbered with the follow format:
74
75 .. code-block:: text
76
77 <major>.<minor>.<patch>[-<identifier>]
78
79 And constructed with the following guidelines:
80
81 - Breaking backwards compatibility bumps the major
82 - New additions without breaking backwards compatibility bumps the minor
83 - Bug fixes and misc changes bump the patch
84 - Unstable, special and trunk versions will have a proper identifier
85
86
87 .. index:: jQuery
88
89 Can I use jQuery with CasperJS?
90 -------------------------------
91
92 Sure, you can use `jQuery <http://jquery.com/>`_, as every single other javascript library on Earth.
93
94 A first solution is to inject it into the remote DOM environment by hand using the standard ``WebPage.injectJs()`` method::
95
96 casper.page.injectJs('/path/to/jquery.js');
97
98 If you need jQuery being available everytime, you can also make it being injected in every received response by setting the ``clientScripts`` option of CasperJS::
99
100 var casper = require('casper').create({
101 clientScripts: ["includes/jquery.min.js"]
102 });
103
104 .. note::
105
106 You can't *inject* scripts using the HTTP protocol, you actually have to use a relative/absolute filesystem path to the script resource.
107
108
109 .. index:: Windows, Python, Ruby
110
111 Can I use CasperJS without using the ``casperjs`` executable?
112 -------------------------------------------------------------
113
114 Yes, you can call a CasperJS script directly with the ``phantomjs``
115 executable, but if you do so, you must set the ``phantom.casperPath``
116 property to the path where the library root is located on your system::
117
118 // casperscript.js
119 phantom.casperPath = '/path/to/casperjs';
120 phantom.injectJs(phantom.casperPath + '/bin/bootstrap.js');
121
122 var casper = require('casper').create();
123 // ...
124
125 You can run such a script like any other standard PhantomJS_ script::
126
127 $ phantomjs casperscript.js
128
129 **If you're on Windows**, this is the way you may manage to get casper
130 working the most easily::
131
132 phantom.casperPath = 'C:\\path\\to\\your\\repo\\lib\\casperjs-0.6.X';
133 phantom.injectJs(phantom.casperPath + '\\bin\\bootstrap.js');
134
135 var casper = require('casper').create();
136
137 // do stuff
138
139
140 .. index:: HTTP
141
142 How can I catch HTTP 404 and other status codes?
143 ------------------------------------------------
144
145 You can define your own `HTTP status
146 code <http://en.wikipedia.org/wiki/List_of_HTTP_status_codes>`_ handlers
147 by using the ``httpStatusHandlers`` option of the Casper object. You can
148 also catch other HTTP status codes as well, as demoed below::
149
150 var casper = require('casper').create();
151
152 casper.on('http.status.404', function(resource) {
153 this.echo('wait, this url is 404: ' + resource.url);
154 });
155
156 casper.on('http.status.500', function(resource) {
157 this.echo('woops, 500 error: ' + resource.url);
158 });
159
160 casper.start('http://mywebsite/404', function() {
161 this.echo('We suppose this url return an HTTP 404');
162 });
163
164 casper.thenOpen('http://mywebsite/500', function() {
165 this.echo('We suppose this url return an HTTP 500');
166 });
167
168 casper.run(function() {
169 this.echo('Done.').exit();
170 });
171
172 .. hint::
173
174 Check out all the other cool :doc:`events <events-filters>` you may use as well.
175
176
177 .. index:: log, Logging
178
179 Where does CasperJS write its logfile?
180 --------------------------------------
181
182 Nowhere. CasperJS doesn't write logs on the filesystem. You have to implement this by yourself if needed.
183
184
185 .. index:: __utils__, AJAX
186
187 What's this mysterious ``__utils__`` object?
188 --------------------------------------------
189
190 The ``__utils__`` object is actually a :ref:`ClientUtils object <clientutils_prototype>` which have been automatically injected into the page DOM and is therefore alway available.
191
192 So everytime to perform an :ref:`evaluate() <casper_evaluate>` call, you have this instance available to perform common operation like:
193
194 - fetching nodes using CSS3 or XPath selectors,
195 - retrieving information about element properties (attributes, size, bounds, etc.),
196 - sending AJAX requests,
197 - triggering DOM events
198
199 Check out the :doc:`whole API <modules/clientutils>`. You even have :ref:`a bookmarklet <bookmarklet>` to play around with this ``__utils__`` instance right within your browser console!
200
201 .. note::
202
203 You're not obliged at all to use the ``__utils__`` instance in your scripts. It's just there because it's used by CasperJS internals.
204
205
206 .. index:: Step stack, Asynchronicity
207
208 How does ``then()`` and the step stack work?
209 --------------------------------------------
210
211 Disclaimer This entry is based on an `answer I made on Stack Overflow <http://stackoverflow.com/a/11957919/330911>`_.
212
213 The ``then()`` method basically adds a new navigation step in a stack. A step is a javascript function which can do two different things:
214
215 1. waiting for the previous step - if any - being executed
216 2. waiting for a requested url and related page to load
217
218 Let's take a simple navigation scenario::
219
220 var casper = require('casper').create();
221
222 casper.start();
223
224 casper.then(function step1() {
225 this.echo('this is step one');
226 });
227
228 casper.then(function step2() {
229 this.echo('this is step two');
230 });
231
232 casper.thenOpen('http://google.com/', function step3() {
233 this.echo('this is step 3 (google.com is loaded)');
234 });
235
236 You can print out all the created steps within the stack like this::
237
238 require('utils').dump(casper.steps.map(function(step) {
239 return step.toString();
240 }));
241
242 That gives::
243
244 $ casperjs test-steps.js
245 [
246 "function step1() { this.echo('this is step one'); }",
247 "function step2() { this.echo('this is step two'); }",
248 "function _step() { this.open(location, settings); }",
249 "function step3() { this.echo('this is step 3 (google.com is loaded)'); }"
250 ]
251
252 Notice the ``_step()`` function which has been added automatically by CasperJS to load the url for us; when the url is loaded, the next step available in the stack — which is ``step3()`` — is *then* called.
253
254 When you have defined your navigation steps, ``run()`` executes them one by one sequentially::
255
256 casper.run();
257
258 .. note:: The callback/listener stuff is an implementation of the `Promise pattern <http://blog.thepete.net/blog/2011/07/02/javascript-promises/>`_.
259
260
261 Is it possible to achieve parallel browsing using CasperJS?
262 -----------------------------------------------------------
263
264 `Officially no <https://groups.google.com/d/topic/casperjs/Scx4Cjqp7hE/discussion>`_, but you may want to try.
265
266
267 Can I access & manipulate DOM elements directly from the CasperJS environment?
268 ------------------------------------------------------------------------------
269
270 No. Like in PhantomJS, you have to use :ref:`Casper#evaluate() <casper_evaluate>` to access actual page DOM and manipulate elements.
271
272 For example, you **can't** do this::
273
274 // this won't work
275 casper.then(function() {
276 var titleNode = document.querySelector('h1');
277 this.echo('Title is: ' + titleNode.textContent);
278 titleNode.textContent = 'New title';
279 this.echo('Title is now: ' + titleNode.textContent);
280 });
281
282 You have to use the :ref:`Casper#evaluate() <casper_evaluate>` method in order to communicate with the page DOM::
283
284 // this will
285 casper.then(function() {
286 var titleText = this.evaluate(function() {
287 return document.querySelector('h1').textContent;
288 });
289 this.echo('Title is: ' + titleText);
290 this.evaluate(function() {
291 document.querySelector('h1').textContent = 'New title';
292 });
293 this.echo('Title is now: ' + this.evaluate(function() {
294 return document.querySelector('h1').textContent;
295 }));
296 });
297
298 Of course, it's a whole lot more verbose, but Casper provides convenient methods to ease accessing elements properties, eg. :ref:`Casper#fetchText() <casper_fetchtext>` and :ref:`Casper#getElementInfo() <casper_getelementinfo>`::
299
300 // this will
301 casper.then(function() {
302 this.echo('Title is: ' + this.fetchText('h1'));
303 this.evaluate(function() {
304 document.querySelector('h1').textContent = 'New title';
305 });
306 this.echo('Element HTML is now: ' + this.getElementInfo('h1').html);
307 });
308
309 .. _faq_javascript:
310
311 Okay, honestly, I'm stuck with Javascript.
312 ------------------------------------------
313
314 Don't worry, you're not alone. Javascript is a great language, but it's far more difficult to master than one might expect at first look.
315
316 Here are some great resources to get started efficiently with the language:
317
318 - Learn and practice Javascript online at `Code Academy <http://www.codecademy.com/tracks/javascript>`_
319 - `Eloquent Javascript <http://eloquentjavascript.net/contents.html>`_
320 - `JavaScript Enlightenment <http://www.javascriptenlightenment.com/JavaScript_Enlightenment.pdf>`_ (PDF)
321 - last, a `great tutorial on Advanced Javascript Techniques <http://ejohn.org/apps/learn/>`_ by John Resig, the author of jQuery. If you master this one, you're almost done with the language.
322
323 .. _PhantomJS: http://phantomjs.org/
324 .. _Qt: http://qt.digia.com/
325 .. _WebKit: http://www.webkit.org/
1 ======================
2 CasperJS documentation
3 ======================
4
5 CasperJS_ is a navigation scripting & testing utility for PhantomJS_, written in Javascript.
6
7 .. figure:: _static/images/casperjs-logo.png
8 :align: right
9
10 .. toctree::
11 :maxdepth: 2
12
13 installation
14 quickstart
15 cli
16 selectors
17 testing
18 modules/index
19 writing_modules
20 events-filters
21 logging
22 extending
23 debugging
24 faq
25 changelog
26 upgrading/index
27 credits
28 license
29
30 You can also search the :ref:`genindex` if you're looking for something particular.
31
32 .. index:: Community, Contributing, Help, Support
33
34 Community
35 ---------
36
37 - `get the code <https://github.com/n1k0/casperjs>`_ and `contribute <https://github.com/n1k0/casperjs/blob/master/CONTRIBUTING.md#contribution-guide>`_
38 - join the `mailing list <https://groups.google.com/forum/#!forum/casperjs>`_
39 - check out `the ecosystem <https://github.com/casperjs>`_
40 - follow `@casperjs\_org <https://twitter.com/casperjs_org>`_ on Twitter
41 - there's also a `Google+ account <https://plus.google.com/106641872690063476159>`_ (not much updated though)
42
43
44 .. _CasperJS: http://casperjs.org/
45 .. _PhantomJS: http://phantomjs.org/
1 .. _installation:
2 .. index:: Installation
3
4 ============
5 Installation
6 ============
7
8 CasperJS can be installed on most Linuxes, OSX and Windows.
9
10 Prerequisites
11 -------------
12
13 .. index:: PhantomJS, Python
14
15 - PhantomJS_ 1.8.1 or greater. Installation instructions can be found `here <http://phantomjs.org/download.html>`_
16 - Python_ 2.6 or greater
17
18 .. note::
19
20 .. versionadded:: 1.0
21
22 A `Ruby <http://ruby-lang.org/>`_ version of the ``casperjs`` executable is also available in the ``rubybin/`` directory; in order to use the :index:`Ruby` version instead of the Python one:
23
24 .. code-block:: text
25
26 $ ln -sf `pwd`/rubybin/casperjs /usr/local/bin/casperjs
27
28 Or using the ruby interpreter:
29
30 .. code-block:: text
31
32 $ ruby /path/to/casperjs/rubybin/casperjs
33 CasperJS version 1.1-DEV at /path/to/casperjs/rubybin/casperjs, using PhantomJS version 1.7.0
34 ...
35
36 .. index:: Homebrew
37
38 Installing from Homebrew (OSX)
39 ------------------------------
40
41 Installation of both PhantomJS and CasperJS can be achieved through `Homebrew <http://mxcl.github.com/homebrew/>`_::
42
43 $ brew install casperjs
44
45 .. index:: git
46
47 Installing from git
48 -------------------
49
50 Installation can be achieved using `git <http://git-scm.com/>`_. The code is mainly hosted on `Github <https://github.com/n1k0/casperjs>`_.
51
52 From a stable tag
53 ~~~~~~~~~~~~~~~~~
54
55 .. code-block:: text
56
57 $ git clone git://github.com/n1k0/casperjs.git
58 $ cd casperjs
59 $ git checkout tags/1.0
60 $ ln -sf `pwd`/bin/casperjs /usr/local/bin/casperjs
61
62 Once PhantomJS and CasperJS installed on your machine, you should obtain something like this:
63
64 .. code-block:: text
65
66 $ phantomjs --version
67 1.7
68 $ casperjs --version
69 1.0
70
71 From the master branch
72 ~~~~~~~~~~~~~~~~~~~~~~
73
74 The ``master`` branch hosts the current development version of CasperJS.
75
76 .. code-block:: text
77
78 $ git clone git://github.com/n1k0/casperjs.git
79 $ cd casperjs
80 $ git checkout master
81 $ ln -sf `pwd`/bin/casperjs /usr/local/bin/casperjs
82
83 To check your current installed version:
84
85 .. code-block:: text
86
87 $ casperjs --version
88 1.1-DEV
89
90 You are now ready to write your :doc:`first script <quickstart>`!
91
92
93 Installing from an archive
94 --------------------------
95
96 You can download tagged archives of CasperJS code:
97
98 **Latest stable version:**
99
100 - https://github.com/n1k0/casperjs/zipball/1.0.0 (zip)
101 - https://github.com/n1k0/casperjs/tarball/1.0.0 (tar.gz)
102
103 **Latest development version (master branch):**
104
105 - https://github.com/n1k0/casperjs/zipball/master (zip)
106 - https://github.com/n1k0/casperjs/tarball/master (tar.gz)
107
108 Operations are then the same as with a git checkout.
109
110
111 .. index:: Windows
112
113 CasperJS on Windows
114 -------------------
115
116 Phantomjs installation additions
117 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
118
119 - Append ``";C:\phantomjs"`` to your ``PATH`` environment variable.
120 - Modify this path appropriately if you installed PhantomJS to a different location.
121
122 Casperjs installation additions
123 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
124
125 .. versionadded:: 1.0
126
127 CasperJS, as of 1.0.0-RC3, ships with a Batch script so you don't need Python nor Ruby to use it.
128
129 - Append ``";C:\casperjs\batchbin"`` to your ``PATH`` environment variable.
130 - Modify this path appropriately if you installed CasperJS to a different location.
131
132 You can now run any regular casper scripts that way:
133
134 .. code-block:: text
135
136 C:> casperjs.bat myscript.js
137
138 Earlier versions of CasperJS
139 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
140
141 Before 1.0.0-RC3, you had to setup your casper scripts that way::
142
143 phantom.casperPath = 'C:\\casperjs-1.1';
144 phantom.injectJs(phantom.casperPath + '\\bin\\bootstrap.js');
145
146 var casper = require('casper').create();
147
148 // do stuff
149
150 Run the script using the ``phantom.exe`` program:
151
152 .. code-block:: text
153
154 C:> phantomjs.exe myscript.js
155
156 .. note::
157
158 There is no output coloration when running CasperJS on Microsoft platforms.
159
160
161 .. index:: Bugs, REPL
162
163 Known Bugs & Limitations
164 ------------------------
165
166 - Due to its asynchronous nature, CasperJS doesn't work well with `PhantomJS' REPL <http://code.google.com/p/phantomjs/wiki/InteractiveModeREPL>`_.
167
168 .. _PhantomJS: http://phantomjs.org/
169 .. _Python: http://python.org/
1 .. _license:
2
3 .. index:: Licensing
4
5 =======
6 License
7 =======
8
9 `CasperJS <http://casperjs.org>`_ is released under the terms of the
10 `MIT license <http://en.wikipedia.org/wiki/MIT_License>`_.
11
12 ::
13
14 Copyright (c) 2011-{{year}} Nicolas Perriault
15 Permission is hereby granted, free of charge, to any person obtaining a
16 copy of this software and associated documentation files (the "Software"),
17 to deal in the Software without restriction, including without limitation
18 the rights to use, copy, modify, merge, publish, distribute, sublicense,
19 and/or sell copies of the Software, and to permit persons to whom the
20 Software is furnished to do so, subject to the following conditions:
21 The above copyright notice and this permission notice shall be included
22 in all copies or substantial portions of the Software.
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 DEALINGS IN THE SOFTWARE.
1 .. _logging:
2
3 .. index:: Logging, log levels
4
5 =======
6 Logging
7 =======
8
9 CasperJS allows logging using the :ref:`casper.log() <casper_log>` method and these standard event levels:
10
11 - ``debug``
12 - ``info``
13 - ``warning``
14 - ``error``
15
16 Sample use::
17
18 var casper = require('casper').create();
19 casper.log('plop', 'debug');
20 casper.log('plip', 'warning');
21
22 .. index:: verbose
23
24 Now, there are two things to distinguish: log *storage* and log *display*; by default CasperJS won't print the logs to the standard output. In order to do so, you must enable the ``verbose`` Casper option::
25
26 var casper = require('casper').create({
27 verbose: true
28 });
29
30 Also, by default Casper is configured to filter logging which is under the ``error`` level; you can override this setting by configuring the ``logLevel`` option::
31
32 var casper = require('casper').create({
33 verbose: true,
34 logLevel: 'debug'
35 });
36
37 You can also dump a JSON log of your Casper suite just by rendering the contents of the ``Casper.logs`` property::
38
39 var casper = require('casper').create({
40 // ...
41 casper.run(function() {
42 require('utils').dump(this.logs);
43 this.exit();
44 });
45
46 Last, if you print log messages to the standard output using the ``verbose`` option, you'll get some fancy colors::
47
48 var casper = require('casper').create({
49 verbose: true,
50 logLevel: 'debug'
51 })
52 casper.log('this is a debug message', 'debug');
53 casper.log('and an informative one', 'info');
54 casper.log('and a warning', 'warning');
55 casper.log('and an error', 'error');
56 casper.exit();
57
58 This will give the following output:
59
60 .. figure:: _static/images/logoutput.png
61 :align: center
62 :alt: image
63
64 image
65
66
67 .. hint::
68
69 CasperJS doesn't write logs on the filesystem. You have to implement this by yourself if needed.
1 .. _casper_module:
2
3 =====================
4 The ``casper`` module
5 =====================
6
7 .. index:: Casper
8
9 The ``Casper`` class
10 ++++++++++++++++++++
11
12 The easiest way to get a casper instance is to use the module's ``create()`` method::
13
14 var casper = require('casper').create();
15
16 But you can also retrieve the main Function and instantiate it by yourself::
17
18 var casper = new require('casper').Casper();
19
20 .. hint::
21
22 Also, check out :doc:`how to extend Casper with your own methods <../extending>`.
23
24 Both the ``Casper`` constructor and the ``create()`` function accept a single ``options`` argument which is a standard javascript object::
25
26 var casper = require('casper').create({
27 verbose: true,
28 logLevel: "debug"
29 });
30
31 .. _casper_options:
32
33 .. index:: Casper options, options
34
35 ``Casper.options``
36 ++++++++++++++++++
37
38 An ``options`` object can be passed to the ``Casper`` constructor, eg.::
39
40 var casper = require('casper').create({
41 clientScripts: [
42 'includes/jquery.js', // These two scripts will be injected in remote
43 'includes/underscore.js' // DOM on every request
44 ],
45 pageSettings: {
46 loadImages: false, // The WebPage instance used by Casper will
47 loadPlugins: false // use these settings
48 },
49 logLevel: "info", // Only "info" level messages will be logged
50 verbose: true // log messages will be printed out to the console
51 });
52
53 You can also alter options at runtime::
54
55 var casper = require('casper').create();
56 casper.options.waitTimeout = 1000;
57
58 The whole list of available options is detailed below.
59
60 .. index:: Client scripts
61
62 .. _casper_option_clientscripts:
63
64 ``clientScripts``
65 -------------------------------------------------------------------------------
66
67 **Type:** ``Array``
68
69 **Default:** ``[]``
70
71 A collection of script filepaths to include in every page loaded
72
73 .. index:: exit, error
74
75 ``exitOnError``
76 -------------------------------------------------------------------------------
77
78 **Type:** ``Boolean``
79
80 **Default:** ``true``
81
82 Sets if CasperJS must exit when an uncaught error has been thrown by the script.
83
84 .. index:: HTTP
85
86 ``httpStatusHandlers``
87 -------------------------------------------------------------------------------
88
89 **Type:** ``Object``
90
91 **Default:** ``{}``
92
93 A javascript Object containing functions to call when a requested resource has a given HTTP status code. A dedicated sample is provided as an example.
94
95 .. index:: Logging
96
97 ``logLevel``
98 -------------------------------------------------------------------------------
99
100 **Type:** ``String``
101
102 **Default:** ``"error"``
103
104 Logging level (see the logging section for more information)
105
106 ``onAlert``
107 -------------------------------------------------------------------------------
108
109 **Type:** ``Function``
110
111 **Default:** ``null``
112
113 A function to be called when a javascript alert() is triggered
114
115 ``onDie``
116 -------------------------------------------------------------------------------
117
118 **Type:** ``Function``
119
120 **Default:** ``null``
121
122 A function to be called when Casper#die() is called
123
124 .. index:: error, Error handling
125
126 ``onError``
127 -------------------------------------------------------------------------------
128
129 **Type:** ``Function``
130
131 **Default:** ``null``
132
133 A function to be called when an "error" level event occurs
134
135 .. index:: error, Error handling
136
137 ``onLoadError``
138 -------------------------------------------------------------------------------
139
140 **Type:** ``Function``
141
142 **Default:** ``null``
143
144 A function to be called when a requested resource cannot be loaded
145
146 ``onPageInitialized``
147 -------------------------------------------------------------------------------
148
149 **Type:** ``Function``
150
151 **Default:** ``null``
152
153 A function to be called after ``WebPage`` instance has been initialized
154
155 .. index:: HTTP
156
157 ``onResourceReceived``
158 -------------------------------------------------------------------------------
159
160 **Type:** ``Function``
161
162 **Default:** ``null``
163
164 Proxy method for PhantomJS' ``WebPage#onResourceReceived()`` callback, but the current Casper instance is passed as first argument.
165
166 .. index:: HTTP
167
168 ``onResourceRequested``
169 -------------------------------------------------------------------------------
170
171 **Type:** ``Function``
172
173 **Default:** ``null``
174
175 Proxy method for PhantomJS' WebPage#onResourceRequested() callback, but the current Casper instance is passed as first argument.
176
177 .. index:: Step stack
178
179 ``onStepComplete``
180 -------------------------------------------------------------------------------
181
182 **Type:** ``Function``
183
184 **Default:** ``null``
185
186 A function to be executed when a step function execution is finished.
187
188 .. index:: Step stack, Error handling, timeout
189
190 ``onStepTimeout``
191 -------------------------------------------------------------------------------
192
193 **Type:** ``Function``
194
195 **Default:** ``Function``
196
197 A function to be executed when a step function execution time exceeds the value of the stepTimeout option, if any has been set.
198
199 By default, on timeout the script will exit displaying an error, except in test environment where it will just add a failure to the suite results.
200
201 .. index:: Error handling, timeout
202
203 ``onTimeout``
204 -------------------------------------------------------------------------------
205
206 **Type:** ``Function``
207
208 **Default:** ``Function``
209
210 A function to be executed when script execution time exceeds the value of the timeout option, if any has been set.
211
212 By default, on timeout the script will exit displaying an error, except in test environment where it will just add a failure to the suite results.
213
214 .. index:: Error handling, timeout
215
216 ``onWaitTimeout``
217 -------------------------------------------------------------------------------
218
219 **Type:** ``Function``
220
221 **Default:** ``Function``
222
223 A function to be executed when a ``waitFor*`` function execution time exceeds the value of the waitTimeout option, if any has been set.
224
225 By default, on timeout the script will exit displaying an error, except in test environment where it will just add a failure to the suite results.
226
227 ``page``
228 -------------------------------------------------------------------------------
229
230 **Type:** ``WebPage``
231
232 **Default:** ``null``
233
234 An existing PhantomJS ``WebPage`` instance
235
236 .. index:: settings, PhantomJS, SSL, auth, XSS
237
238 ``pageSettings``
239 -------------------------------------------------------------------------------
240
241 **Type:** ``Object``
242
243 **Default:** ``{}``
244
245 PhantomJS's WebPage settings object. Available settings are:
246
247 - ``javascriptEnabled`` defines whether to execute the script in the page or not (default to ``true``)
248 - ``loadImages`` defines whether to load the inlined images or not
249 - ``loadPlugins`` defines whether to load NPAPI plugins (Flash, Silverlight, …) or not
250 - ``localToRemoteUrlAccessEnabled`` defines whether local resource (e.g. from file) can access remote URLs or not (default to ``false``)
251 - ``userAgent`` defines the user agent sent to server when the web page requests resources
252 - ``userName`` sets the user name used for HTTP authentication
253 - ``password`` sets the password used for HTTP authentication
254 - ``XSSAuditingEnabled`` defines whether load requests should be monitored for cross-site scripting attempts (default to ``false``)
255
256 .. index:: Remote scripts
257
258 ``remoteScripts``
259 -------------------------------------------------------------------------------
260
261 **Type:** ``Array``
262
263 **Default:** ``[]``
264
265 .. versionadded:: 1.0
266
267 A collection of remote script urls to include in every page loaded
268
269 .. index:: Logging
270
271 ``safeLogs``
272 -------------------------------------------------------------------------------
273
274 **Type:** ``Boolean``
275
276 **Default:** ``true``
277
278 .. versionadded:: 1.0
279
280 When this option is set to true — which is the default, any password information entered in <input type="password"> will be obfuscated in log messages. Set safeLogs to false to disclose passwords in plain text (not recommended).
281
282 .. index:: Step stack, timeout
283
284 ``stepTimeout``
285 -------------------------------------------------------------------------------
286
287 **Type:** ``Number``
288
289 **Default:** ``null``
290
291 Max step timeout in milliseconds; when set, every defined step function will have to execute before this timeout value has been reached. You can define the onStepTimeout() callback to catch such a case. By default, the script will die() with an error message.
292
293 .. index:: timeout
294
295 ``timeout``
296 -------------------------------------------------------------------------------
297
298 **Type:** ``Number``
299
300 **Default:** ``null``
301
302 Max timeout in milliseconds
303
304 .. index:: verbose
305
306 ``verbose``
307 -------------------------------------------------------------------------------
308
309 **Type:** ``Boolean``
310
311 **Default:** ``false``
312
313 Realtime output of log messages
314
315 .. index:: viewport
316
317 ``viewportSize``
318 -------------------------------------------------------------------------------
319
320 **Type:** ``Object``
321
322 **Default:** ``null``
323
324 Viewport size, eg. ``{width: 800, height: 600}``
325
326 .. note::
327
328 PhantomJS ships with a default viewport of 400x300, and CasperJS won't override it by default.
329
330 .. index:: timeout
331
332 ``waitTimeout``
333 -------------------------------------------------------------------------------
334
335 **Type:** ``Number``
336
337 **Default:** ``5000``
338
339 Default wait timeout, for ``wait*`` family functions.
340
341
342 ``Casper`` prototype
343 ++++++++++++++++++++
344
345 ``back()``
346 -------------------------------------------------------------------------------
347
348 **Signature:** ``back()``
349
350 Moves back a step in browser's history::
351
352 casper.start('http://foo.bar/1')
353 casper.thenOpen('http://foo.bar/2');
354 casper.thenOpen('http://foo.bar/3');
355 casper.back();
356 casper.run(function() {
357 console.log(this.getCurrentUrl()); // 'http://foo.bar/2'
358 });
359
360 Also have a look at ``Casper.forward()``.
361
362 .. _casper_base64encode:
363
364 .. index:: Base64
365
366 ``base64encode()``
367 -------------------------------------------------------------------------------
368
369 **Signature:** ``base64encode(String url [, String method, Object data])``
370
371 Encodes a resource using the base64 algorithm synchronously using
372 client-side XMLHttpRequest.
373
374 .. note::
375
376 We cannot use ``window.btoa()`` because it fails miserably in the version of WebKit shipping with PhantomJS.
377
378 Example: retrieving google logo image encoded in base64::
379
380 var base64logo = null;
381 casper.start('http://www.google.fr/', function() {
382 base64logo = this.base64encode('http://www.google.fr/images/srpr/logo3w.png');
383 });
384
385 casper.run(function() {
386 this.echo(base64logo).exit();
387 });
388
389 You can also perform an HTTP POST request to retrieve the contents to
390 encode::
391
392 var base46contents = null;
393 casper.start('http://domain.tld/download.html', function() {
394 base46contents = this.base64encode('http://domain.tld/', 'POST', {
395 param1: 'foo',
396 param2: 'bar'
397 });
398 });
399
400 casper.run(function() {
401 this.echo(base46contents).exit();
402 });
403
404 .. index:: bypass, Step stack
405
406 ``bypass()``
407 -------------------------------------------------------------------------------
408
409 **Signature:** ``bypass(Numbr nb)``
410
411 Bypasses a given number of defined navigation steps::
412
413 casper.start();
414 casper.then(function() {
415 // This step will be executed
416 });
417 casper.then(function() {
418 this.bypass(2);
419 });
420 casper.then(function() {
421 // This test won't be executed
422 });
423 casper.then(function() {
424 // Nor this one
425 });
426 casper.run();
427
428 .. _casper_click:
429
430 .. index:: click
431
432 ``click()``
433 -------------------------------------------------------------------------------
434
435 **Signature:** ``click(String selector)``
436
437 Performs a click on the element matching the provided :doc:`selector expression <../selectors>`. The method tries two strategies sequentially:
438
439 1. trying to trigger a MouseEvent in Javascript
440 2. using native QtWebKit event if the previous attempt failed
441
442 Example::
443
444 casper.start('http://google.fr/');
445
446 casper.thenEvaluate(function(term) {
447 document.querySelector('input[name="q"]').setAttribute('value', term);
448 document.querySelector('form[name="f"]').submit();
449 }, 'CasperJS');
450
451 casper.then(function() {
452 // Click on 1st result link
453 this.click('h3.r a');
454 });
455
456 casper.then(function() {
457 console.log('clicked ok, new location is ' + this.getCurrentUrl());
458 });
459
460 casper.run();
461
462 .. index:: click
463
464 ``clickLabel()``
465 -------------------------------------------------------------------------------
466
467 **Signature:** ``clickLabel(String label[, String tag])``
468
469 .. versionadded:: 0.6.1
470
471 Clicks on the first DOM element found containing ``label`` text. Optionaly ensures that the element node name is ``tag``::
472
473 // <a href="...">My link is beautiful</a>
474 casper.then(function() {
475 this.clickLabel('My link is beautiful', 'a');
476 });
477
478 // <button type="submit">But my button is sexier</button>
479 casper.then(function() {
480 this.clickLabel('But my button is sexier', 'button');
481 });
482
483 .. index:: screenshot
484
485 ``capture()``
486 -------------------------------------------------------------------------------
487
488 **Signature:** ``capture(String targetFilepath, Object clipRect)``
489
490 Proxy method for PhantomJS' ``WebPage#render``. Adds a ``clipRect`` parameter for automatically setting page ``clipRect`` setting and reverts it back once done::
491
492 casper.start('http://www.google.fr/', function() {
493 this.capture('google.png', {
494 top: 100,
495 left: 100,
496 width: 500,
497 height: 400
498 });
499 });
500
501 casper.run();
502
503 .. index:: screenshot, Base64
504
505 ``captureBase64()``
506 -------------------------------------------------------------------------------
507
508 **Signature:** ``captureBase64(String format[, Mixed area])``
509
510 .. versionadded:: 0.6.5
511
512 Computes the `Base64 <http://en.wikipedia.org/wiki/Base64>`_ representation of a binary image capture of the current page, or an area within the page, in a given format.
513
514 Supported image formats are ``bmp``, ``jpg``, ``jpeg``, ``png``, ``ppm``, ``tiff``, ``xbm`` and ``xpm``.
515
516 The ``area`` argument can be either of the following types:
517
518 - ``String``: area is a CSS3 selector string, eg. ``div#plop form[name="form"] input[type="submit"]``
519 - ``clipRect``: area is a clipRect object, eg. ``{"top":0,"left":0,"width":320,"height":200}``
520 - ``Object``: area is a :doc:`selector object <../selectors>`, eg. an XPath selector
521
522 Example::
523
524 casper.start('http://google.com', function() {
525 // selector capture
526 console.log(this.captureBase64('png', '#lga'));
527 // clipRect capture
528 console.log(this.captureBase64('png', {
529 top: 0,
530 left: 0,
531 width: 320,
532 height: 200
533 }));
534 // whole page capture
535 console.log(this.captureBase64('png'));
536 });
537
538 casper.run();
539
540 .. _casper_captureselector:
541
542 .. index:: screenshot
543
544 ``captureSelector()``
545 -------------------------------------------------------------------------------
546
547 **Signature:** ``captureSelector(String targetFile, String selector)``
548
549 Captures the page area containing the provided selector and saves it to ``targetFile``::
550
551 casper.start('http://www.weather.com/', function() {
552 this.captureSelector('weather.png', '#wx-main');
553 });
554
555 casper.run();
556
557 ``clear()``
558 -------------------------------------------------------------------------------
559
560 **Signature:** ``clear()``
561
562 .. versionadded:: 0.6.5
563
564 Clears the current page execution environment context. Useful to avoid having previously loaded DOM contents being still active.
565
566 Think of it as a way to stop javascript execution within the remote DOM environment::
567
568 casper.start('http://www.google.fr/', function() {
569 this.clear(); // javascript execution in this page has been stopped
570 });
571
572 casper.then(function() {
573 // ...
574 });
575
576 casper.run();
577
578 .. index:: Debugging
579
580 ``debugHTML()``
581 -------------------------------------------------------------------------------
582
583 **Signature:** ``debugHTML([String selector, Boolean outer])``
584
585 Outputs the results of `getHTML()`_ directly to the console. It takes the same arguments as ``getHTML()``.
586
587 .. index:: Debugging
588
589 ``debugPage()``
590 -------------------------------------------------------------------------------
591
592 **Signature:** ``debugPage()``
593
594 Logs the textual contents of the current page directly to the standard output, for debugging purpose::
595
596 casper.start('http://www.google.fr/', function() {
597 this.debugPage();
598 });
599
600 casper.run();
601
602 ``die()``
603 -------------------------------------------------------------------------------
604
605 **Signature:** ``die(String message[, int status])``
606
607 Exits phantom with a logged error message and an optional exit status code::
608
609 casper.start('http://www.google.fr/', function() {
610 this.die("Fail.", 1);
611 });
612
613 casper.run();
614
615 .. _casper_download:
616
617 .. index:: download
618
619 ``download()``
620 -------------------------------------------------------------------------------
621
622 **Signature:** ``download(String url, String target[, String method, Object data])``
623
624 Saves a remote resource onto the filesystem. You can optionally set the HTTP method using the ``method`` argument, and pass request arguments through the ``data`` object (see `base64encode()`_)::
625
626 casper.start('http://www.google.fr/', function() {
627 var url = 'http://www.google.fr/intl/fr/about/corporate/company/';
628 this.download(url, 'google_company.html');
629 });
630
631 casper.run(function() {
632 this.echo('Done.').exit();
633 });
634
635 ``each()``
636 -------------------------------------------------------------------------------
637
638 **Signature:** ``each(Array array, Function fn)``
639
640 Iterates over provided array items and execute a callback::
641
642 var links = [
643 'http://google.com/',
644 'http://yahoo.com/',
645 'http://bing.com/'
646 ];
647
648 casper.start().each(links, function(self, link) {
649 self.thenOpen(link, function() {
650 this.echo(this.getTitle());
651 });
652 });
653
654 casper.run();
655
656 .. hint::
657
658 Have a look at the `googlematch.js <https://github.com/n1k0/casperjs/blob/master/samples/googlematch.js>`_ sample script for a concrete use case.
659
660 .. _casper_echo:
661
662 .. index:: echo, Printing
663
664 ``echo()``
665 -------------------------------------------------------------------------------
666
667 **Signature:** ``echo(String message[, String style])``
668
669 Prints something to stdout, optionally with some fancy color (see the :ref:`colorizer module <colorizer_module>` for more information)::
670
671 casper.start('http://www.google.fr/', function() {
672 this.echo('Page title is: ' + this.evaluate(function() {
673 return document.title;
674 }), 'INFO'); // Will be printed in green on the console
675 });
676
677 casper.run();
678
679 .. index:: evaluate, DOM
680
681 .. _casper_evaluate:
682
683 ``evaluate()``
684 -------------------------------------------------------------------------------
685
686 **Signature:** ``evaluate(Function fn[, arg1[, arg2[, …]]])``
687
688 Basically `PhantomJS' WebPage#evaluate <https://github.com/ariya/phantomjs/wiki/API-Reference#wiki-webpage-evaluate>`_ equivalent. Evaluates an expression **in the current page DOM context**::
689
690 casper.evaluate(function(username, password) {
691 document.querySelector('#username').value = username;
692 document.querySelector('#password').value = password;
693 document.querySelector('#submit').click();
694 }, 'sheldon.cooper', 'b4z1ng4');
695
696 .. note::
697
698 For filling and submitting forms, rather use the `fill()`_ method.
699
700 .. warning::
701
702 The pre-1.0 way of passing arguments using an object has been kept for BC purpose, though it may `not work in some case <https://github.com/n1k0/casperjs/issues/349>`_; so you're encouraged to use the method described above.
703
704 .. topic:: Understanding ``evaluate()``
705
706 The concept behind this method is probably the most difficult to understand when discovering CasperJS. As a reminder, think of the ``evaluate()`` method as a *gate* between the CasperJS environment and the one of the page you have opened; everytime you pass a closure to ``evaluate()``, you're entering the page and execute code as if you were using the browser console.
707
708 Here's a quickly drafted diagram trying to basically explain the separation of concerns:
709
710 .. figure:: ../_static/images/evaluate-diagram.png
711 :align: center
712
713 ``evaluateOrDie()``
714 -------------------------------------------------------------------------------
715
716 **Signature:** ``evaluateOrDie(Function fn[, String message])``
717
718 Evaluates an expression within the current page DOM and ``die()`` if it returns anything but ``true``::
719
720 casper.start('http://foo.bar/home', function() {
721 this.evaluateOrDie(function() {
722 return /logged in/.match(document.title);
723 }, 'not authenticated');
724 });
725
726 casper.run();
727
728 .. index:: exit
729
730 ``exit()``
731 -------------------------------------------------------------------------------
732
733 **Signature:** ``exit([int status])``
734
735 Exits PhantomJS with an optional exit status code.
736
737 .. index:: DOM
738
739 ``exists()``
740 -------------------------------------------------------------------------------
741
742 **Signature:** ``exists(String selector)``
743
744 Checks if any element within remote DOM matches the provided :doc:`selector <../selectors>`::
745
746 casper.start('http://foo.bar/home', function() {
747 if (this.exists('#my_super_id')) {
748 this.echo('found #my_super_id', 'INFO');
749 } else {
750 this.echo('#my_super_id not found', 'ERROR');
751 }
752 });
753
754 casper.run();
755
756 .. _casper_fetchtext:
757
758 ``fetchText()``
759 -------------------------------------------------------------------------------
760
761 **Signature:** ``fetchText(String selector)``
762
763 Retrieves text contents matching a given :doc:`selector expression <../selectors>`. If you provide one matching more than one element, their textual contents will be concatenated::
764
765 casper.start('http://google.com/search?q=foo', function() {
766 this.echo(this.fetchText('h3'));
767 }).run();
768
769 ``forward()``
770 -------------------------------------------------------------------------------
771
772 **Signature:** ``forward()``
773
774 Moves a step forward in browser's history::
775
776 casper.start('http://foo.bar/1')
777 casper.thenOpen('http://foo.bar/2');
778 casper.thenOpen('http://foo.bar/3');
779 casper.back(); // http://foo.bar/2
780 casper.back(); // http://foo.bar/1
781 casper.forward(); // http://foo.bar/2
782 casper.run();
783
784 Also have a look at `back()`_.
785
786 .. _casper_log:
787
788 .. index:: Logging
789
790 ``log()``
791 -------------------------------------------------------------------------------
792
793 **Signature:** ``log(String message[, String level, String space])``
794
795 Logs a message with an optional level in an optional space. Available levels are ``debug``, ``info``, ``warning`` and ``error``. A space is a kind of namespace you can set for filtering your logs. By default, Casper logs messages in two distinct spaces: ``phantom`` and ``remote``, to distinguish what happens in the PhantomJS environment from the remote one::
796
797 casper.start('http://www.google.fr/', function() {
798 this.log("I'm logging an error", "error");
799 });
800
801 casper.run();
802
803 .. _casper_fill:
804
805 .. index:: Form
806
807 ``fill()``
808 -------------------------------------------------------------------------------
809
810 **Signature:** ``fill(String selector, Object values[, Boolean submit])``
811
812 Fills the fields of a form with given values and optionally submits it.
813
814 Example with this sample html form:
815
816 .. code-block :: html
817
818 <form action="/contact" id="contact-form" enctype="multipart/form-data">
819 <input type="text" name="subject"/>
820 <textearea name="content"></textearea>
821 <input type="radio" name="civility" value="Mr"/> Mr
822 <input type="radio" name="civility" value="Mrs"/> Mrs
823 <input type="text" name="name"/>
824 <input type="email" name="email"/>
825 <input type="file" name="attachment"/>
826 <input type="checkbox" name="cc"/> Receive a copy
827 <input type="submit"/>
828 </form>
829
830 A script to fill and submit this form::
831
832 casper.start('http://some.tld/contact.form', function() {
833 this.fill('form#contact-form', {
834 'subject': 'I am watching you',
835 'content': 'So be careful.',
836 'civility': 'Mr',
837 'name': 'Chuck Norris',
838 'email': 'chuck@norris.com',
839 'cc': true,
840 'attachment': '/Users/chuck/roundhousekick.doc'
841 }, true);
842 });
843
844 casper.then(function() {
845 this.evaluateOrDie(function() {
846 return /message sent/.test(document.body.innerText);
847 }, 'sending message failed');
848 });
849
850 casper.run(function() {
851 this.echo('message sent').exit();
852 });
853
854 .. warning::
855
856 1. The ``fill()`` method currently can't fill **file fields using XPath selectors**; PhantomJS natively only allows the use of CSS3 selectors in its uploadFile method, hence this limitation.
857 2. Please Don't use CasperJS nor PhantomJS to send spam, or I'll be calling the Chuck. More seriously, please just don't.
858
859 .. index:: URL
860
861 ``getCurrentUrl()``
862 -------------------------------------------------------------------------------
863
864 **Signature:** ``getCurrentUrl()``
865
866 Retrieves current page URL. Note that the url will be url-decoded::
867
868 casper.start('http://www.google.fr/', function() {
869 this.echo(this.getCurrentUrl()); // "http://www.google.fr/"
870 });
871
872 casper.run();
873
874 .. index:: DOM
875
876 ``getElementAttribute()``
877 -------------------------------------------------------------------------------
878
879 **Signature:** ``getElementAttribute(String selector, String attribute)``
880
881 .. versionadded:: 1.0
882
883 Retrieves the value of an attribute on the first element matching the provided :doc:`selector <../selectors>`::
884
885 var casper = require('casper').create();
886
887 casper.start('http://www.google.fr/', function() {
888 require('utils').dump(this.getElementAttribute('div[title="Google"]', 'title')); // "Google"
889 });
890
891 casper.run();
892
893 .. index:: DOM
894
895 ``getElementBounds()``
896 -------------------------------------------------------------------------------
897
898 **Signature:** ``getElementBounds(String selector)``
899
900 Retrieves boundaries for a DOM element matching the provided :doc:`selector <../selectors>`.
901
902 It returns an Object with four keys: ``top``, ``left``, ``width`` and ``height``, or ``null`` if the selector doesn't exist::
903
904 var casper = require('casper').create();
905
906 casper.start('http://www.google.fr/', function() {
907 require('utils').dump(this.getElementBounds('div[title="Google"]'));
908 });
909
910 casper.run();
911
912 This will output something like::
913
914 {
915 "height": 95,
916 "left": 352,
917 "top": 16,
918 "width": 275
919 }
920
921 .. index:: DOM
922
923 ``getElementsBounds()``
924 -------------------------------------------------------------------------------
925
926 **Signature:** ``getElementsBounds(String selector)``
927
928 .. versionadded:: 1.0
929
930 Retrieves a list of boundaries for all DOM elements matching the provided :doc:`selector <../selectors>`.
931
932 It returns an array of objects with four keys: ``top``, ``left``, ``width`` and ``height`` (see `getElementBounds()`_).
933
934 .. _casper_getelementinfo:
935
936 .. index:: DOM
937
938 ``getElementInfo()``
939 -------------------------------------------------------------------------------
940
941 **Signature:** ``getElementInfo(String selector)``
942
943 .. versionadded:: 1.0
944
945 Retrieves information about the first element matching the provided :doc:`selector <../selectors>`::
946
947 casper.start('http://google.com/', function() {
948 require('utils').dump(this.getElementInfo('#hplogo'));
949 });
950
951 Gives something like::
952
953 {
954 "nodeName": "div",
955 "attributes": {
956 "dir": "ltr",
957 "title": "Google",
958 "align": "left",
959 "id": "hplogo",
960 "onload": "window.lol&&lol()",
961 "style": "background:url(images/srpr/logo3w.png) no-repeat;background-size:275px 95px;height:95px;width:275px"
962 },
963 "tag": "<div dir=\"ltr\" title=\"Google\" align=\"left\" id=\"hplogo\" onload=\"window.lol&amp;&amp;lol()\" style=\"background:url(images/srpr/logo3w.png) no-repeat;background-size:275px 95px;height:95px;width:275px\"><div nowrap=\"nowrap\" style=\"color:#777;font-size:16px;font-weight:bold;position:relative;left:214px;top:70px\">France</div></div>",
964 "html": "<div nowrap=\"nowrap\" style=\"color:#777;font-size:16px;font-weight:bold;position:relative;left:214px;top:70px\">France</div>",
965 "text": "France\n",
966 "x": 582.5,
967 "y": 192,
968 "width": 275,
969 "height": 95,
970 "visible": true
971 }
972
973 .. index:: Form
974
975 ``getFormValues()``
976 -------------------------------------------------------------------------------
977
978 **Signature:** ``getFormValues(String selector)``
979
980 .. versionadded:: 1.0
981
982 Retrieves a given form all of its field values::
983
984 casper.start('http://www.google.fr/', function() {
985 this.fill('form', {q: 'plop'}, false);
986 this.echo(this.getFormValues('form').q); // 'plop'
987 });
988
989 casper.run();
990
991 .. index:: Globals, window
992
993 ``getGlobal()``
994 -------------------------------------------------------------------------------
995
996 **Signature:** ``getGlobal(String name)``
997
998 Retrieves a global variable value within the remote DOM environment by its name. Basically, ``getGlobal('foo')`` will retrieve the value of ``window.foo`` from the page::
999
1000 casper.start('http://www.google.fr/', function() {
1001 this.echo(this.getGlobal('innerWidth')); // 1024
1002 });
1003
1004 casper.run();
1005
1006 .. index:: Debugging
1007
1008 ``getHTML()``
1009 -------------------------------------------------------------------------------
1010
1011 **Signature:** ``getHTML([String selector, Boolean outer])``
1012
1013 .. versionadded:: 1.0
1014
1015 Retrieves HTML code from the current page. By default, it outputs the whole page HTML contents::
1016
1017 casper.start('http://www.google.fr/', function() {
1018 this.echo(this.getHTML());
1019 });
1020
1021 casper.run();
1022
1023 The ``getHTML()`` method can also dump HTML contents matching a given :doc:`selector <../selectors>`; for example with this HTML code:
1024
1025 .. code-block:: html
1026
1027 <html>
1028 <body>
1029 <h1 id="foobar">Plop</h1>
1030 </body>
1031 </html>
1032
1033 You can fetch those contents using::
1034
1035 casper.start('http://www.site.tld/', function() {
1036 this.echo(this.getHTML('h1#foobar')); // => 'Plop'
1037 });
1038
1039 The ``outer`` argument allows to retrieve the outer HTML contents of the matching element::
1040
1041 casper.start('http://www.site.tld/', function() {
1042 this.echo(this.getHTML('h1#foobar', true)); // => '<h1 id="foobar">Plop</h1>'
1043 });
1044
1045 ``getPageContent()``
1046 -------------------------------------------------------------------------------
1047
1048 **Signature:** ``getPageContent()``
1049
1050 .. versionadded:: 1.0
1051
1052 Retrieves current page contents, dealing with exotic other content types than HTML::
1053
1054 var casper = require('casper').create();
1055
1056 casper.start().then(function() {
1057 this.open('http://search.twitter.com/search.json?q=casperjs', {
1058 method: 'get',
1059 headers: {
1060 'Accept': 'application/json'
1061 }
1062 });
1063 });
1064
1065 casper.run(function() {
1066 require('utils').dump(JSON.parse(this.getPageContent()));
1067 this.exit();
1068 });
1069
1070 .. index:: DOM
1071
1072 ``getTitle()``
1073 -------------------------------------------------------------------------------
1074
1075 **Signature:** ``getTitle()``
1076
1077 Retrieves current page title::
1078
1079 casper.start('http://www.google.fr/', function() {
1080 this.echo(this.getTitle()); // "Google"
1081 });
1082
1083 casper.run();
1084
1085 .. _casper_mouseevent:
1086
1087 .. index:: events
1088
1089 ``mouseEvent()``
1090 -------------------------------------------------------------------------------
1091
1092 **Signature:** ``mouseEvent(String type, String selector)``
1093
1094 .. versionadded:: 0.6.9
1095
1096 Triggers a mouse event on the first element found matching the provided selector.
1097
1098 Supported events are ``mouseup``, ``mousedown``, ``click``, ``mousemove``, ``mouseover`` and ``mouseout``::
1099
1100 casper.start('http://www.google.fr/', function() {
1101 this.mouseEvent('click', 'h2 a');
1102 });
1103
1104 casper.run();
1105
1106 .. index:: HTTP, HTTP Request, HTTP Method, HTTP Headers
1107
1108 ``open()``
1109 -------------------------------------------------------------------------------
1110
1111 **Signature:** ``open(String location, Object Settings)``
1112
1113 Performs an HTTP request for opening a given location. You can forge ``GET``, ``POST``, ``PUT``, ``DELETE`` and ``HEAD`` requests.
1114
1115 Example for a standard ``GET`` request::
1116
1117 casper.start();
1118
1119 casper.open('http://www.google.com/').then(function() {
1120 this.echo('GOT it.');
1121 });
1122
1123 casper.run();
1124
1125 Example for a ``POST`` request::
1126
1127 casper.start();
1128
1129 casper.open('http://some.testserver.com/post.php', {
1130 method: 'post',
1131 data: {
1132 'title': 'Plop',
1133 'body': 'Wow.'
1134 }
1135 });
1136
1137 casper.then(function() {
1138 this.echo('POSTED it.');
1139 });
1140
1141 casper.run();
1142
1143 To pass nested parameters arrays::
1144
1145 casper.open('http://some.testserver.com/post.php', {
1146 method: 'post',
1147 data: {
1148 'standard_param': 'foo',
1149 'nested_param[]': [ // please note the use of square brackets!
1150 'Something',
1151 'Something else'
1152 ]
1153 }
1154 });
1155
1156 .. versionadded:: 1.0
1157
1158 You can also set custom request headers to send when performing an outgoing request, passing the ``headers`` option::
1159
1160 casper.open('http://some.testserver.com/post.php', {
1161 method: 'post',
1162 data: {
1163 'title': 'Plop',
1164 'body': 'Wow.'
1165 },
1166 headers: {
1167 'Accept-Language': 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3'
1168 }
1169 });
1170
1171 ``reload()``
1172 -------------------------------------------------------------------------------
1173
1174 **Signature:** ``reload([Function then])``
1175
1176 .. versionadded:: 1.0
1177
1178 Reloads current page location::
1179
1180 casper.start('http://google.com', function() {
1181 this.echo("loaded");
1182 this.reload(function() {
1183 this.echo("loaded again");
1184 });
1185 });
1186
1187 casper.run();
1188
1189 ``repeat()``
1190 -------------------------------------------------------------------------------
1191
1192 **Signature:** ``repeat(int times, Function then)``
1193
1194 Repeats a navigation step a given number of times::
1195
1196 casper.start().repeat(3, function() {
1197 this.echo("Badger");
1198 });
1199
1200 casper.run();
1201
1202 .. _casper_resourceexists:
1203
1204 .. index:: HTTP
1205
1206 ``resourceExists()``
1207 -------------------------------------------------------------------------------
1208
1209 **Signature:** ``resourceExists(Mixed test)``
1210
1211 Checks if a resource has been loaded. You can pass either a function or a string to perform the test::
1212
1213 casper.start('http://www.google.com/', function() {
1214 if (this.resourceExists('logo3w.png')) {
1215 this.echo('Google logo loaded');
1216 } else {
1217 this.echo('Google logo not loaded', 'ERROR');
1218 }
1219 });
1220
1221 casper.run();
1222
1223 .. note::
1224
1225 If you want to wait for a resource to be loaded, use the `waitForResource()`_ method.
1226
1227 .. index:: Step stack, run
1228
1229 ``run()``
1230 -------------------------------------------------------------------------------
1231
1232 **Signature:** ``run(fn onComplete[, int time])``
1233
1234 Runs the whole suite of steps and optionally executes a callback when they've all been done. Obviously, **calling this method is mandatory** in order to run the Casper navigation suite.
1235
1236 Casper suite **won't run**::
1237
1238 casper.start('http://foo.bar/home', function() {
1239 // ...
1240 });
1241
1242 // hey, it's missing .run() here!
1243
1244 Casper suite **will run**::
1245
1246 casper.start('http://foo.bar/home', function() {
1247 // ...
1248 });
1249
1250 casper.run();
1251
1252 ``Casper.run()`` also accepts an ``onComplete`` callback, which you can consider as a custom final step to perform when all the other steps have been executed. Just don't forget to ``exit()`` Casper if you define one!::
1253
1254 casper.start('http://foo.bar/home', function() {
1255 // ...
1256 });
1257
1258 casper.then(function() {
1259 // ...
1260 });
1261
1262 casper.run(function() {
1263 this.echo('So the whole suite ended.');
1264 this.exit(); // <--- don't forget me!
1265 });
1266
1267 .. index:: Form
1268
1269 ``sendKeys()``
1270 -------------------------------------------------------------------------------
1271
1272 **Signature:** ``sendKeys(Selector selector, String keys[, Object options])``
1273
1274 .. versionadded:: 1.0
1275
1276 Sends native keyboard events to the element matching the provided :doc:`selector <../selectors>`::
1277
1278 casper.then(function() {
1279 this.sendKeys('form.contact input#name', 'Duke');
1280 this.sendKeys('form.contact textarea#message', "Damn, I'm looking good.");
1281 this.click('form.contact input[type="submit"]');
1282 });
1283
1284 .. index:: auth
1285
1286 ``setHttpAuth()``
1287 -------------------------------------------------------------------------------
1288
1289 **Signature:** ``setHttpAuth(String username, String password)``
1290
1291 Sets ``HTTP_AUTH_USER`` and ``HTTP_AUTH_PW`` values for HTTP based authentication systems::
1292
1293 casper.start();
1294
1295 casper.setHttpAuth('sheldon.cooper', 'b4z1ng4');
1296
1297 casper.thenOpen('http://password-protected.domain.tld/', function() {
1298 this.echo("I'm in. Bazinga.");
1299 })
1300 casper.run();
1301
1302 Of course you can directly pass the auth string in the url to open::
1303
1304 var url = 'http://sheldon.cooper:b4z1ng4@password-protected.domain.tld/';
1305
1306 casper.start(url, function() {
1307 this.echo("I'm in. Bazinga.");
1308 })
1309
1310 casper.run();
1311
1312 .. index:: start, initialization
1313
1314 ``start()``
1315 -------------------------------------------------------------------------------
1316
1317 **Signature:** ``start(String url[, Function then])``
1318
1319 Configures and starts Casper, then open the provided ``url`` and optionally adds the step provided by the ``then`` argument::
1320
1321 casper.start('http://google.fr/', function() {
1322 this.echo("I'm loaded.");
1323 });
1324
1325 casper.run();
1326
1327 Alternatively::
1328
1329 casper.start('http://google.fr/');
1330
1331 casper.then(function() {
1332 this.echo("I'm loaded.");
1333 });
1334
1335 casper.run();
1336
1337 Or alternatively::
1338
1339 casper.start('http://google.fr/');
1340
1341 casper.then(function() {
1342 casper.echo("I'm loaded.");
1343 });
1344
1345 casper.run();
1346
1347 Matter of taste!
1348
1349 .. note::
1350
1351 You must call the ``start()`` method in order to be able to add navigation steps and run the suite. If you don't you'll get an error message inviting you to do so anyway.
1352
1353 ``status()``
1354 -------------------------------------------------------------------------------
1355
1356 **Signature:** ``status(Boolean asString)``
1357
1358 .. versionadded:: 1.0
1359
1360 Returns the status of current Casper instance::
1361
1362 casper.start('http://google.fr/', function() {
1363 this.echo(this.status(true));
1364 });
1365
1366 casper.run();
1367
1368 .. index:: Step stack, Asynchronicity
1369
1370 ``then()``
1371 -------------------------------------------------------------------------------
1372
1373 **Signature:** ``then(Function then)``
1374
1375 This method is the standard way to add a new navigation step to the stack, by providing a simple function::
1376
1377 casper.start('http://google.fr/');
1378
1379 casper.then(function() {
1380 this.echo("I'm in your google.");
1381 });
1382
1383 casper.then(function() {
1384 this.echo('Now, let me write something');
1385 });
1386
1387 casper.then(function() {
1388 this.echo('Oh well.');
1389 });
1390
1391 casper.run();
1392
1393 You can add as many steps as you need. Note that the current ``Casper`` instance automatically binds the ``this`` keyword for you within step functions.
1394
1395 To run all the steps you defined, call the `run()`_ method, and voila.
1396
1397 .. index:: HTTP Response
1398
1399 .. note::
1400
1401 You must `start()`_ the casper instance in order to use the ``then()`` method.
1402
1403 .. topic:: Accessing the current HTTP response
1404
1405 .. versionadded:: 1.0
1406
1407 You can access the current HTTP response object using the first parameter of your step callback::
1408
1409 casper.start('http://www.google.fr/', function(response) {
1410 require('utils').dump(response);
1411 });
1412
1413 That gives:
1414
1415 .. code-block:: text
1416
1417 $ casperjs dump-headers.js
1418 {
1419 "contentType": "text/html; charset=UTF-8",
1420 "headers": [
1421 {
1422 "name": "Date",
1423 "value": "Thu, 18 Oct 2012 08:17:29 GMT"
1424 },
1425 {
1426 "name": "Expires",
1427 "value": "-1"
1428 },
1429 // ... lots of other headers
1430 ],
1431 "id": 1,
1432 "redirectURL": null,
1433 "stage": "end",
1434 "status": 200,
1435 "statusText": "OK",
1436 "time": "2012-10-18T08:17:37.068Z",
1437 "url": "http://www.google.fr/"
1438 }
1439
1440 So to fetch a particular header by its name::
1441
1442 casper.start('http://www.google.fr/', function(response) {
1443 this.echo(response.headers.get('Date'));
1444 });
1445
1446 That gives:
1447
1448 .. code-block:: text
1449
1450 $ casperjs dump-headers.js
1451 Thu, 18 Oct 2012 08:26:34 GMT
1452
1453 .. index:: bypass, Step stack
1454
1455 ``thenBypass()``
1456 -------------------------------------------------------------------------------
1457
1458 **Signature:** ``thenBypass(Number nb)``
1459
1460 Adds a navigation step which will bypass a given number of following steps::
1461
1462 casper.start('http://foo.bar/');
1463 casper.thenBypass(2);
1464 casper.then(function() {
1465 // This test won't be executed
1466 });
1467 casper.then(function() {
1468 // Nor this one
1469 });
1470 casper.then(function() {
1471 // While this one will
1472 });
1473 casper.run();
1474
1475 ``thenBypassIf()``
1476 -------------------------------------------------------------------------------
1477
1478 **Signature:** ``thenBypassIf(Mixed condition, Number nb)``
1479
1480 Bypass a given number of navigation steps if the provided condition is truthy or is a function that returns a truthy value::
1481
1482 var universe = {
1483 answer: 42
1484 };
1485 casper.start('http://foo.bar/');
1486 casper.thenBypassIf(function() {
1487 return universe && universe.answer === 42;
1488 }, 2);
1489 casper.then(function() {
1490 // This step won't be executed as universe.answer is 42
1491 });
1492 casper.then(function() {
1493 // Nor this one
1494 });
1495 casper.then(function() {
1496 // While this one will
1497 });
1498 casper.run();
1499
1500 ``thenBypassUnless()``
1501 -------------------------------------------------------------------------------
1502
1503 **Signature:** ``thenBypassUnless(Mixed condition, Number nb)``
1504
1505 Opposite of `thenBypassIf()`_.
1506
1507 ``thenClick()``
1508 -------------------------------------------------------------------------------
1509
1510 **Signature:** ``thenClick(String selector[, Function then])``
1511
1512 Adds a new navigation step to click a given selector and optionally add a new navigation step in a single operation::
1513
1514 // Querying for "Chuck Norris" on Google
1515 casper.start('http://casperjs.org/').thenClick('a', function() {
1516 this.echo("I clicked on first link found, the page is now loaded.");
1517 });
1518
1519 casper.run();
1520
1521 This method is basically a convenient a shortcut for chaining a `then()`_ and an `evaluate()`_ calls.
1522
1523 ``thenEvaluate()``
1524 -------------------------------------------------------------------------------
1525
1526 **Signature:** ``thenEvaluate(Function fn[, arg1[, arg2[, …]]])``
1527
1528 Adds a new navigation step to perform code evaluation within the current retrieved page DOM::
1529
1530 // Querying for "Chuck Norris" on Google
1531 casper.start('http://google.fr/').thenEvaluate(function(term) {
1532 document.querySelector('input[name="q"]').setAttribute('value', term);
1533 document.querySelector('form[name="f"]').submit();
1534 }, 'Chuck Norris');
1535
1536 casper.run();
1537
1538 This method is basically a convenient a shortcut for chaining a `then()`_ and an `evaluate()`_ calls.
1539
1540 ``thenOpen()``
1541 -------------------------------------------------------------------------------
1542
1543 **Signature:** ``thenOpen(String location[, mixed options])``
1544
1545 Adds a new navigation step for opening a new location, and optionally add a next step when its loaded::
1546
1547 casper.start('http://google.fr/').then(function() {
1548 this.echo("I'm in your google.");
1549 });
1550
1551 casper.thenOpen('http://yahoo.fr/', function() {
1552 this.echo("Now I'm in your yahoo.")
1553 });
1554
1555 casper.run();
1556
1557 .. versionadded:: 1.0
1558
1559 You can also specify request settings by passing a setting object (see `open()`_) as the second argument::
1560
1561 casper.start().thenOpen('http://url.to/some/uri', {
1562 method: "post",
1563 data: {
1564 username: 'chuck',
1565 password: 'n0rr15'
1566 }
1567 }, function() {
1568 this.echo("POST request has been sent.")
1569 });
1570
1571 casper.run();
1572
1573 ``thenOpenAndEvaluate()``
1574 -------------------------------------------------------------------------------
1575
1576 **Signature:** ``thenOpenAndEvaluate(String location[, Function then[, arg1[, arg2[, …]]])``
1577
1578 Basically a shortcut for opening an url and evaluate code against remote DOM environment::
1579
1580 casper.start('http://google.fr/').then(function() {
1581 this.echo("I'm in your google.");
1582 });
1583
1584 casper.thenOpenAndEvaluate('http://yahoo.fr/', function() {
1585 var f = document.querySelector('form');
1586 f.querySelector('input[name=q]').value = 'chuck norris';
1587 f.submit();
1588 });
1589
1590 casper.run(function() {
1591 this.debugPage();
1592 this.exit();
1593 });
1594
1595 ``toString()``
1596 -------------------------------------------------------------------------------
1597
1598 **Signature:** ``toString()``
1599
1600 .. versionadded:: 1.0
1601
1602 Returns a string representation of current Casper instance::
1603
1604 casper.start('http://google.fr/', function() {
1605 this.echo(this); // [object Casper], currently at http://google.fr/
1606 });
1607
1608 casper.run();
1609
1610 .. index:: User Agent
1611
1612 ``userAgent()``
1613 -------------------------------------------------------------------------------
1614
1615 **Signature:** ``userAgent(String agent)``
1616
1617 .. versionadded:: 1.0
1618
1619 Sets the `User-Agent string <http://en.wikipedia.org/wiki/User-Agent>`_ to send through headers when performing requests::
1620
1621 casper.start();
1622
1623 casper.userAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X)');
1624
1625 casper.thenOpen('http://google.com/', function() {
1626 this.echo("I'm a Mac.");
1627 });
1628
1629 casper.userAgent('Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)');
1630
1631 casper.thenOpen('http://google.com/', function() {
1632 this.echo("I'm a PC.");
1633 });
1634
1635 casper.run();
1636
1637 .. index:: viewport
1638
1639 ``viewport()``
1640 -------------------------------------------------------------------------------
1641
1642 **Signature:** ``viewport(Number width, Number height[, Function then])``
1643
1644 Changes current viewport size::
1645
1646 casper.viewport(1024, 768);
1647
1648 To be sure page reflowing has occured, you have to use it asynchronously::
1649
1650 casper.viewport(1024, 768).then(function() {
1651 // new view port is now effective
1652 });
1653
1654 .. versionadded:: 1.1
1655
1656 As of 1.1 you can pass a `then` step function directly to ``viewport()``::
1657
1658 casper.viewport(1024, 768, function() {
1659 // new view port is effective
1660 });
1661
1662 .. note::
1663
1664 PhantomJS comes with a default viewport size of 400x300, and CasperJS doesn't override it by default.
1665
1666 .. index:: DOM
1667
1668 ``visible()``
1669 -------------------------------------------------------------------------------
1670
1671 **Signature:** ``visible(String selector)``
1672
1673 Checks if the DOM element matching the provided :doc:`selector expression <../selectors>` is visible in remote page::
1674
1675 casper.start('http://google.com/', function() {
1676 if (this.visible('#hplogo')) {
1677 this.echo("I can see the logo");
1678 } else {
1679 this.echo("I can't see the logo");
1680 }
1681 });
1682
1683 .. index:: wait, sleep
1684
1685 ``wait()``
1686 -------------------------------------------------------------------------------
1687
1688 **Signature:** ``wait(Number timeout[, Function then])``
1689
1690 Pause steps suite execution for a given amount of time, and optionally execute a step on done::
1691
1692 casper.start('http://yoursite.tld/', function() {
1693 this.wait(1000, function() {
1694 this.echo("I've waited for a second.");
1695 });
1696 });
1697
1698 casper.run();
1699
1700 You can also write the same thing like this::
1701
1702 casper.start('http://yoursite.tld/');
1703
1704 casper.wait(1000, function() {
1705 this.echo("I've waited for a second.");
1706 });
1707
1708 casper.run();
1709
1710 .. index:: Asynchronicity
1711
1712 ``waitFor()``
1713 -------------------------------------------------------------------------------
1714
1715 **Signature:** ``waitFor(Function testFx[, Function then, Function onTimeout, Number timeout])``
1716
1717 Waits until a function returns true to process any next step.
1718
1719 You can also set a callback on timeout using the ``onTimeout`` argument, and set the timeout using the ``timeout`` one, in milliseconds. The default timeout is set to 5000ms::
1720
1721 casper.start('http://yoursite.tld/');
1722
1723 casper.waitFor(function check() {
1724 return this.evaluate(function() {
1725 return document.querySelectorAll('ul.your-list li').length > 2;
1726 });
1727 }, function then() {
1728 this.captureSelector('yoursitelist.png', 'ul.your-list');
1729 });
1730
1731 casper.run();
1732
1733 Example using the ``onTimeout`` callback::
1734
1735 casper.start('http://yoursite.tld/');
1736
1737 casper.waitFor(function check() {
1738 return this.evaluate(function() {
1739 return document.querySelectorAll('ul.your-list li').length > 2;
1740 });
1741 }, function then() { // step to execute when check() is ok
1742 this.captureSelector('yoursitelist.png', 'ul.your-list');
1743 }, function timeout() { // step to execute if check has failed
1744 this.echo("I can't haz my screenshot.").exit();
1745 });
1746
1747 casper.run();
1748
1749 .. _casper_waitforpopup:
1750
1751 .. index:: Popups, New window, window.open, Tabs
1752
1753 ``waitForPopup()``
1754 -------------------------------------------------------------------------------
1755
1756 **Signature:** ``waitForPopup(String|RegExp urlPattern[, Function then, Function onTimeout, Number timeout])``
1757
1758 .. versionadded:: 1.0
1759
1760 Waits for a popup having its url matching the provided pattern to be opened and loaded.
1761
1762 The currently loaded popups are available in the ``Casper.popups`` array-like property::
1763
1764 casper.start('http://foo.bar/').then(function() {
1765 this.test.assertTitle('Main page title');
1766 this.clickLabel('Open me a popup');
1767 });
1768
1769 // this will wait for the popup to be opened and loaded
1770 casper.waitForPopup(/popup\.html$/, function() {
1771 this.test.assertEquals(this.popups.length, 1);
1772 });
1773
1774 // this will set the popup DOM as the main active one only for time the
1775 // step closure being executed
1776 casper.withPopup(/popup\.html$/, function() {
1777 this.test.assertTitle('Popup title');
1778 });
1779
1780 // next step will automatically revert the current page to the initial one
1781 casper.then(function() {
1782 this.test.assertTitle('Main page title');
1783 });
1784
1785 .. index:: HTTP, Asynchronicity
1786
1787 ``waitForResource()``
1788 -------------------------------------------------------------------------------
1789
1790 **Signature:** ``waitForResource(Function testFx[, Function then, Function onTimeout, Number timeout])``
1791
1792 Wait until a resource that matches the given ``testFx`` is loaded to process a next step. Uses `waitFor()`_::
1793
1794 casper.start('http://foo.bar/');
1795
1796 casper.waitForResource("foobar.png", function() {
1797 this.echo('foobar.png has been loaded.');
1798 });
1799
1800 casper.run();
1801
1802 .. index:: selector
1803
1804 ``waitForSelector()``
1805 -------------------------------------------------------------------------------
1806
1807 **Signature:** ``waitForSelector(String selector[, Function then, Function onTimeout, Number timeout])``
1808
1809 Waits until an element matching the provided :doc:`selector expression <../selectors>` exists in remote DOM to process any next step. Uses `waitFor()`_::
1810
1811 casper.start('https://twitter.com/#!/n1k0');
1812
1813 casper.waitForSelector('.tweet-row', function() {
1814 this.captureSelector('twitter.png', 'html');
1815 });
1816
1817 casper.run();
1818
1819 .. index:: selector
1820
1821 ``waitWhileSelector()``
1822 -------------------------------------------------------------------------------
1823
1824 **Signature:** ``waitWhileSelector(String selector[, Function then, Function onTimeout, Number timeout])``
1825
1826 Waits until an element matching the provided :doc:`selector expression <../selectors>` does not exist in remote DOM to process a next step. Uses `waitFor()`_::
1827
1828 casper.start('http://foo.bar/');
1829
1830 casper.waitWhileSelector('.selector', function() {
1831 this.echo('.selector is no more!');
1832 });
1833
1834 casper.run();
1835
1836 ``waitForSelectorTextChange()``
1837 -------------------------------------------------------------------------------
1838
1839 **Signature:** ``waitForSelectorTextChange(String selectors[, Function then, Function onTimeout, Number timeout])``
1840
1841 Waits until the text on an element matching the provided :doc:`selector expression <../selectors>`
1842 is changed to a different value before processing the next step. Uses `waitFor()`_::
1843
1844 casper.start('http://foo.bar/');
1845
1846 casper.waitForSelectorTextChange('.selector', function() {
1847 this.echo('The text on .selector has been changed.);
1848 });
1849
1850 casper.run();
1851
1852 ``waitForText()``
1853 -------------------------------------------------------------------------------
1854
1855 **Signature:** ``waitForText(String text[, Function then, Function onTimeout, Number timeout])``
1856 .. versionadded:: 1.0
1857
1858 Waits until the passed text is present in the page contents before processing the immediate next step. Uses `waitFor()`_::
1859
1860 casper.start('http://why.univer.se/').waitForText("42", function() {
1861 this.echo('Found the answer.');
1862 });
1863
1864 casper.run();
1865
1866 ``waitUntilVisible()``
1867 -------------------------------------------------------------------------------
1868
1869 **Signature:** ``waitUntilVisible(String selector[, Function then, Function onTimeout, Number timeout])``
1870
1871 Waits until an element matching the provided :doc:`selector expression <../selectors>` is visible in the remote DOM to process a next step. Uses `waitFor()`_.
1872
1873 ``waitWhileVisible()``
1874 -------------------------------------------------------------------------------
1875
1876 **Signature:** ``waitWhileVisible(String selector[, Function then, Function onTimeout, Number timeout])``
1877
1878 Waits until an element matching the provided :doc:`selector expression <../selectors>` is no longer visible in remote DOM to process a next step. Uses `waitFor()`_.
1879
1880 ``warn()``
1881 -------------------------------------------------------------------------------
1882
1883 **Signature:** ``warn(String message)``
1884
1885 Logs and prints a warning message to the standard output::
1886
1887 casper.warn("I'm a warning message.");
1888
1889 .. note::
1890
1891 Calling ``warn()`` will trigger the ``warn`` :ref:`event <events_filters>`.
1892
1893 .. index:: Frames, Iframes, Framesets
1894
1895 ``withFrame()``
1896 -------------------------------------------------------------------------------
1897
1898 **Signature:** ``withFrame(String|Number frameInfo, Function then)``
1899
1900 .. versionadded:: 1.0
1901
1902 Switches the main page to the frame having the name or frame index number matching the passed argument, and processes a step.
1903
1904 The page context switch only lasts until the step execution is finished::
1905
1906 casper.start('tests/site/frames.html', function() {
1907 this.test.assertTitle('FRAMESET TITLE');
1908 });
1909
1910 casper.withFrame('frame1', function() {
1911 this.test.assertTitle('FRAME TITLE');
1912 });
1913
1914 casper.withFrame(0, function() {
1915 this.test.assertTitle('FRAME TITLE');
1916 });
1917
1918 casper.then(function() {
1919 this.test.assertTitle('FRAMESET TITLE');
1920 });
1921
1922 .. _casper_withpopup:
1923
1924 .. index:: Popups, New window, window.open, Tabs
1925
1926 ``withPopup()``
1927 -------------------------------------------------------------------------------
1928
1929 **Signature:** ``withPopup(Mixed popupInfo, Function then)``
1930
1931 .. versionadded:: 1.0
1932
1933 Switches the main page to a popup matching the information passed as argument, and processes a step. The page context switch only lasts until the step execution is finished::
1934
1935 casper.start('http://foo.bar/').then(function() {
1936 this.test.assertTitle('Main page title');
1937 this.clickLabel('Open me a popup');
1938 });
1939
1940 // this will wait for the popup to be opened and loaded
1941 casper.waitForPopup(/popup\.html$/, function() {
1942 this.test.assertEquals(this.popups.length, 1);
1943 });
1944
1945 // this will set the popup DOM as the main active one only for time the
1946 // step closure being executed
1947 casper.withPopup(/popup\.html$/, function() {
1948 this.test.assertTitle('Popup title');
1949 });
1950
1951 // next step will automatically revert the current page to the initial one
1952 casper.then(function() {
1953 this.test.assertTitle('Main page title');
1954 });
1955
1956 .. note::
1957
1958 The currently loaded popups are available in the ``Casper.popups`` array-like property.
1959
1960 .. index:: Zoom
1961
1962 ``zoom()``
1963 -------------------------------------------------------------------------------
1964
1965 **Signature:** ``zoom(Number factor)``
1966
1967 .. versionadded:: 1.0
1968
1969 Sets the current page zoom factor::
1970
1971 var casper = require('casper').create();
1972
1973 casper.start().zoom(2).thenOpen('http://google.com', function() {
1974 this.capture('big-google.png');
1975 });
1976
1977 casper.run();
1978
1 .. _clientutils_module:
2
3 .. index:: Client utils, __utils__, DOM
4
5 ==========================
6 The ``clientutils`` module
7 ==========================
8
9 Casper ships with a few client-side utilities which are injected in the remote DOM environment, and accessible from there through the ``__utils__`` object instance of the ``ClientUtils`` class from the ``clientutils`` module.
10
11 .. note::
12
13 These tools are provided to avoid coupling CasperJS to any third-party library like :index:`jQuery`, Mootools or something; but you can always include these and have them available client-side using the :ref:`Casper.options.clientScripts <casper_option_clientscripts>` option.
14
15 .. _bookmarklet:
16
17 .. index:: bookmarklet, DOM, Debugging
18
19 Bookmarklet
20 +++++++++++
21
22 A bookmarklet is also available to help injecting Casper's client-side utilities in the DOM of your favorite browser.
23
24 Just drag the link above onto your favorites toobar; when clicking, a ``__utils__`` object will be available within the console of your browser:
25
26 .. raw:: html
27
28 <div class="bookmarklet">
29 <a href="javascript:(function(){void(function(){if(!document.getElementById('CasperUtils')){var%20CasperUtils=document.createElement('script');CasperUtils.id='CasperUtils';CasperUtils.src='https://raw.github.com/n1k0/casperjs/master/modules/clientutils.js';document.documentElement.appendChild(CasperUtils);var%20interval=setInterval(function(){if(typeof%20ClientUtils==='function'){window.__utils__=new%20window.ClientUtils();clearInterval(interval);}},50);}}());})();">CasperJS Utils</a>
30 </div>
31
32 .. note::
33
34 CasperJS and PhantomJS being based on `Webkit <http://webkit.org/>`_, you're strongly encouraged to use a recent Webkit compatible browser to use this bookmarklet (Chrome, Safari, etc…)
35
36
37 .. _clientutils_prototype:
38
39 ``ClientUtils`` prototype
40 +++++++++++++++++++++++++
41
42 .. index:: echo
43
44 ``echo()``
45 -------------------------------------------------------------------------------
46
47 **Signature:** ``echo(String message)``
48
49 .. versionadded:: 1.0
50
51 Print a message out to the casper console from the remote page DOM environment::
52
53 casper.start('http://foo.ner/').thenEvaluate(function() {
54 __utils__.echo('plop'); // this will be printed to your shell at runtime
55 });
56
57 .. index:: Base64
58
59 ``encode()``
60 -------------------------------------------------------------------------------
61
62 **Signature:** ``encode(String contents)``
63
64 Encodes a string using the `base64 algorithm <http://en.wikipedia.org/wiki/Base64>`_. For the records, CasperJS doesn't use builtin ``window.btoa()`` function because it can't deal efficiently with strings encoded using >8b characters::
65
66 var base64;
67 casper.start('http://foo.bar/', function() {
68 base64 = this.evaluate(function() {
69 return __utils__.encode("I've been a bit cryptic recently");
70 });
71 });
72
73 casper.run(function() {
74 this.echo(base64).exit();
75 });
76
77 .. index:: DOM
78
79 ``exists()``
80 -------------------------------------------------------------------------------
81
82 **Signature:** ``exists(String selector)``
83
84 Checks if a DOM element matching a given :ref:`selector expression <selectors>` exists::
85
86 var exists;
87 casper.start('http://foo.bar/', function() {
88 exists = this.evaluate(function() {
89 return __utils__.exists('#some_id');
90 });
91 });
92
93 casper.run(function() {
94 this.echo(exists).exit();
95 });
96
97 ``findAll()``
98 -------------------------------------------------------------------------------
99
100 **Signature:** ``findAll(String selector)``
101
102 Retrieves all DOM elements matching a given :ref:`selector expression <selectors>`::
103
104 var links;
105 casper.start('http://foo.bar/', function() {
106 links = this.evaluate(function() {
107 var elements = __utils__.findAll('a.menu');
108 return Array.prototype.forEach.call(elements, function(e) {
109 return e.getAttribute('href');
110 });
111 });
112 });
113
114 casper.run(function() {
115 this.echo(JSON.stringify(links)).exit();
116 });
117
118 ``findOne()``
119 -------------------------------------------------------------------------------
120
121 **Signature:** ``findOne(String selector)``
122
123 Retrieves a single DOM element by a :ref:`selector expression <selectors>`::
124
125 var href;
126 casper.start('http://foo.bar/', function() {
127 href = this.evaluate(function() {
128 return __utils__.findOne('#my_id').getAttribute('href');
129 });
130 });
131
132 casper.run(function() {
133 this.echo(href).exit();
134 });
135
136 .. index:: Base64
137
138 ``getBase64()``
139 -------------------------------------------------------------------------------
140
141 **Signature:** ``getBase64(String url[, String method, Object data])``
142
143 This method will retrieved a base64 encoded version of any resource behind a url. For example, let's imagine we want to retrieve the base64 representation of some website's logo::
144
145 var logo = null;
146 casper.start('http://foo.bar/', function() {
147 logo = this.evaluate(function() {
148 var imgUrl = document.querySelector('img.logo').getAttribute('src');
149 return __utils__.getBase64(imgUrl);
150 });
151 });
152
153 casper.run(function() {
154 this.echo(logo).exit();
155 });
156
157 .. index:: Binary
158
159 ``getBinary()``
160 -------------------------------------------------------------------------------
161
162 **Signature:** ``getBinary(String url[, String method, Object data])``
163
164 This method will retrieved the raw contents of a given binary resource; unfortunately though, PhantomJS cannot process these data directly so you'll have to process them within the remote DOM environment. If you intend to download the resource, use `getBase64()`_ or :ref:`Casper.base64encode() <casper_base64encode>` instead::
165
166 casper.start('http://foo.bar/', function() {
167 this.evaluate(function() {
168 var imgUrl = document.querySelector('img.logo').getAttribute('src');
169 console.log(__utils__.getBinary(imgUrl));
170 });
171 });
172
173 casper.run();
174
175 ``getDocumentHeight()``
176 -------------------------------------------------------------------------------
177
178 **Signature:** ``getDocumentHeight()``
179
180 .. versionadded:: 1.0
181
182 Retrieves current document height::
183
184 var documentHeight;
185
186 casper.start('http://google.com/', function() {
187 documentHeight = this.evaluate(function() {
188 return __utils__.getDocumentHeight();
189 });
190 this.echo('Document height is ' + documentHeight + 'px');
191 });
192
193 casper.run();
194
195 ``getElementBounds()``
196 -------------------------------------------------------------------------------
197
198 **Signature:** ``getElementBounds(String selector)``
199
200 Retrieves boundaries for a DOM elements matching the provided :ref:`selector <selectors>`.
201
202 It returns an Object with four keys: ``top``, ``left``, ``width`` and ``height``, or ``null`` if the selector doesn't exist.
203
204 ``getElementsBounds()``
205 -------------------------------------------------------------------------------
206
207 **Signature:** ``getElementsBounds(String selector)``
208
209 Retrieves boundaries for all DOM element matching the provided :ref:`selector <selectors>`.
210
211 It returns an array of objects each having four keys: ``top``, ``left``, ``width`` and ``height``.
212
213 .. index:: XPath
214
215 ``getElementByXPath()``
216 -------------------------------------------------------------------------------
217
218 **Signature:** ``getElementByXPath(String expression [, HTMLElement scope])``
219
220 Retrieves a single DOM element matching a given :ref:`XPath expression <selectors>`.
221
222 .. versionadded:: 1.0
223
224 The ``scope`` argument allow to set the context for executing the XPath query::
225
226 // will be performed against the whole document
227 __utils__.getElementByXPath('.//a');
228
229 // will be performed against a given DOM element
230 __utils__.getElementByXPath('.//a', __utils__.findOne('div.main'));
231
232 .. index:: XPath
233
234 ``getElementsByXPath()``
235 -------------------------------------------------------------------------------
236
237 **Signature:** ``getElementsByXPath(String expression [, HTMLElement scope])``
238
239 Retrieves all DOM elements matching a given :ref:`XPath expression <selectors>`, if any.
240
241 .. versionadded:: 1.0
242
243 The ``scope`` argument allows to set the context for executing the XPath query.
244
245 .. index:: Form
246
247 ``getFieldValue()``
248 -------------------------------------------------------------------------------
249
250 **Signature:** ``getFieldValue(String inputName)``
251
252 .. versionadded:: 1.0
253
254 Retrieves the value from the field named against the ``inputNamed`` argument:
255
256 .. code-block:: html
257
258 <form>
259 <input type="text" name="plop" value="42">
260 </form>
261
262 Using the ``getFieldValue()`` method for ``plop``::
263
264 __utils__.getFieldValue('plop'); // 42
265
266 .. index:: Form
267
268 ``getFormValues()``
269 -------------------------------------------------------------------------------
270
271 **Signature:** ``getFormValues(String selector)``
272
273 .. versionadded:: 1.0
274
275 Retrieves a given form and all of its field values:
276
277 .. code-block:: html
278
279 <form id="login" action="/login">
280 <input type="text" name="username" value="foo">
281 <input type="text" name="password" value="bar">
282 <input type="submit">
283 </form>
284
285 To get the form values::
286
287 __utils__.getFormValues('form#login'); // {username: 'foo', password: 'bar'}
288
289 ``mouseEvent()``
290 -------------------------------------------------------------------------------
291
292 **Signature:** ``mouseEvent(String type, String selector)``
293
294 Dispatches a mouse event to the DOM element behind the provided selector.
295
296 Supported events are ``mouseup``, ``mousedown``, ``click``, ``mousemove``, ``mouseover`` and ``mouseout``.
297
298 .. index:: XPath
299
300 ``removeElementsByXPath()``
301 -------------------------------------------------------------------------------
302
303 **Signature:** ``removeElementsByXPath(String expression)``
304
305 Removes all DOM elements matching a given :ref:`XPath expression <selectors>`.
306
307 .. index:: AJAX
308
309 ``sendAJAX()``
310 -----------------------------------------------------------------------------
311
312 **Signature:** ``sendAJAX(String url[, String method, Object data, Boolean async])``
313
314 .. versionadded:: 1.0
315
316 Sends an AJAX request, using the following parameters:
317
318 - ``url``: The url to request.
319 - ``method``: The HTTP method (default: ``GET``).
320 - ``data``: Request parameters (default: ``null``).
321 - ``async``: Flag for an asynchroneous request? (default: ``false``)
322
323 .. warning::
324
325 Don't forget to pass the ``--web-security=no`` option in your CLI call in order to perform cross-domains requests when needed::
326
327 var data, wsurl = 'http://api.site.com/search.json';
328
329 casper.start('http://my.site.com/', function() {
330 data = this.evaluate(function(wsurl) {
331 return JSON.parse(__utils__.sendAJAX(wsurl, 'GET', null, false));
332 }, {wsurl: wsurl});
333 });
334
335 casper.then(function() {
336 require('utils').dump(data);
337 });
338
339 ``visible()``
340 -------------------------------------------------------------------------------
341
342 **Signature:** ``visible(String selector)``
343
344 Checks if an element is visible::
345
346 var logoIsVisible = casper.evaluate(function() {
347 return __utils__.visible('h1');
348 });
349
1 .. _colorizer_module:
2
3 .. index:: Colors, colorizer
4
5 ========================
6 The ``colorizer`` module
7 ========================
8
9 The ``colorizer`` module contains a ``Colorizer`` class which can generate ANSI colored strings::
10
11 var colorizer = require('colorizer').create('Colorizer');
12 console.log(colorizer.colorize("Hello World", "INFO"));
13
14 Though most of the times you will use it transparently using the :ref:`Casper.echo() <casper_echo>` method::
15
16 casper.echo('an informative message', 'INFO'); // printed in green
17 casper.echo('an error message', 'ERROR'); // printed in red
18
19 Skipping CasperJS styling operations
20 ------------------------------------
21
22 If you wish to skip the whole coloration operation and get uncolored plain text, just set the ``colorizerType`` casper option to ``Dummy``::
23
24 var casper = require('casper').create({
25 colorizerType: 'Dummy'
26 });
27
28 casper.echo("Hello", "INFO");
29
30 .. index:: Windows
31
32 .. note::
33
34 That's especially useful if you're using CasperJS on the Windows platform, as there's no support for colored output on this platform.
35
36 .. _colorizer_styles:
37
38 .. index:: Printing styles
39
40 Available predefined styles
41 ---------------------------
42
43 Available predefined styles are:
44
45 - ``ERROR``: white text on red background
46 - ``INFO``: green text
47 - ``TRACE``: green text
48 - ``PARAMETER``: cyan text
49 - ``COMMENT``: yellow text
50 - ``WARNING``: red text
51 - ``GREEN_BAR``: white text on green background
52 - ``RED_BAR``: white text on red background
53 - ``INFO_BAR``: cyan text
54 - ``WARN_BAR``: white text on orange background
55
56 Here's a sample output of what it can look like:
57
58 .. figure:: ../_static/images/colorizer.png
59 :align: center
60
61 ``colorize()``
62 -------------------------------------------------------------------------------
63
64 **Signature:** ``colorize(String text, String styleName)``
65
66 Computes a colored version of the provided text string using a given predefined style::
67
68 var colorizer = require('colorizer').create();
69 console.log(colorizer.colorize("I'm a red error", "ERROR"));
70
71 .. note::
72
73 Most of the time you won't have to use a ``Colorizer`` instance directly as CasperJS provides all the necessary methods.
74
75 See the list of the :ref:`predefined styles available <colorizer_styles>`.
76
77 ``format()``
78 -------------------------------------------------------------------------------
79
80 **Signature:** ``format(String text, Object style)``
81
82 Formats a text string using the provided style definition. A style definition is a standard javascript ``Object`` instance which can define the following properties:
83
84 - String ``bg``: background color name
85 - String ``fg``: foreground color name
86 - Boolean ``bold``: apply bold formatting
87 - Boolean ``underscore``: apply underline formatting
88 - Boolean ``blink``: apply blink formatting
89 - Boolean ``reverse``: apply reverse formatting
90 - Boolean ``conceal``: apply conceal formatting
91
92 .. note::
93
94 Available color names are ``black``, ``red``, ``green``, ``yellow``, ``blue``, ``magenta``, ``cyan`` and ``white``::
95
96 var colorizer = require('colorizer').create();
97 colorizer.format("We all live in a yellow submarine", {
98 bg: 'yellow',
99 fg: 'blue',
100 bold: true
101 });
102
1 .. _modules_index:
2
3 .. index:: modules
4
5 =================
6 API Documentation
7 =================
8
9 Here you'll find a quite complete reference of the CasperJS API. If something is erroneous or missing, please `file an issue <https://github.com/n1k0/casperjs/issues/new>`_.
10
11 .. toctree::
12 :glob:
13
14 *
1 .. _tester_module:
2
3 .. index:: Testing
4
5 =====================
6 The ``tester`` module
7 =====================
8
9 Casper ships with a ``tester`` module and a ``Tester`` class providing an API for unit & functional testing purpose. By default you can access an instance of this class through the ``test`` property of any ``Casper`` class instance.
10
11 .. note::
12
13 The best way to learn how to use the Tester API and see it in action is probably to have a look at `CasperJS' own test suites <https://github.com/n1k0/casperjs/blob/master/tests/suites/>`_.
14
15
16 The ``Tester`` prototype
17 ++++++++++++++++++++++++
18
19 ``assert()``
20 -------------------------------------------------------------------------------
21
22 **Signature:** ``assert(Boolean condition[, String message])``
23
24 Asserts that the provided condition strictly resolves to a boolean ``true``::
25
26 casper.test.assert(true, "true's true");
27 casper.test.assert(!false, "truth is out");
28
29 .. seealso:: `assertNot()`_
30
31 .. index:: DOM
32
33 ``assertDoesntExist()``
34 -------------------------------------------------------------------------------
35
36 **Signature:** ``assertDoesntExist(String selector[, String message])``
37
38 Asserts that an element matching the provided :ref:`selector expression <selectors>` doesn't exists within the remote DOM environment::
39
40 casper.test.begin('assertDoesntExist() tests', 1, function(test) {
41 casper.start().then(function() {
42 this.setContent('<div class="heaven"></div>');
43 test.assertDoesntExist('.taxes');
44 }).run(function() {
45 test.done();
46 });
47 });
48
49 .. seealso:: `assertExists()`_
50
51 ``assertEquals()``
52 -------------------------------------------------------------------------------
53
54 **Signature:** ``assertEquals(mixed testValue, mixed expected[, String message])``
55
56 Asserts that two values are strictly equivalent::
57
58 casper.test.begin('assertEquals() tests', 3, function(test) {
59 test.assertEquals(1 + 1, 2);
60 test.assertEquals([1, 2, 3], [1, 2, 3]);
61 test.assertEquals({a: 1, b: 2}, {a: 1, b: 2});
62 test.done();
63 });
64
65 .. seealso:: `assertNotEquals()`_
66
67 .. index:: evaluate
68
69 ``assertEval()``
70 -------------------------------------------------------------------------------
71
72 **Signature:** ``assertEval(Function fn[, String message, Mixed arguments])``
73
74 Asserts that a :ref:`code evaluation in remote DOM <casper_evaluate>` strictly resolves to a boolean ``true``::
75
76 casper.test.begin('assertEval() tests', 1, function(test) {
77 casper.start().then(function() {
78 this.setContent('<div class="heaven">beer</div>');
79 test.assertEval(function() {
80 return __utils__.findOne('.heaven').textContent === 'beer';
81 });
82 }).run(function() {
83 test.done();
84 });
85 });
86
87 ``assertEvalEquals()``
88 -------------------------------------------------------------------------------
89
90 **Signature:** ``assertEvalEquals(Function fn, mixed expected[, String message, Mixed arguments])``
91
92 Asserts that the result of a :ref:`code evaluation in remote DOM <casper_evaluate>` strictly equals to the expected value::
93
94 casper.test.begin('assertEvalEquals() tests', 1, function(test) {
95 casper.start().then(function() {
96 this.setContent('<div class="heaven">beer</div>');
97 test.assertEvalEquals(function() {
98 return __utils__.findOne('.heaven').textContent;
99 }, 'beer');
100 }).run(function() {
101 test.done();
102 });
103 });
104
105 .. _tester_assertelementcount:
106
107 ``assertElementCount()``
108 -------------------------------------------------------------------------------
109
110 **Signature:** ``assertElementCount(String selector, Number count[, String message])``
111
112 Asserts that a :ref:`selector expression <selectors>` matches a given number of elements::
113
114 casper.test.begin('assertElementCount() tests', 3, function(test) {
115 casper.start().then(function() {
116 this.page.content = '<ul><li>1</li><li>2</li><li>3</li></ul>';
117 test.assertElementCount('ul', 1);
118 test.assertElementCount('li', 3);
119 test.assertElementCount('address', 0);
120 }).run(function() {
121 test.done();
122 });
123 });
124
125 .. index:: DOM
126
127 ``assertExists()``
128 -------------------------------------------------------------------------------
129
130 **Signature:** ``assertExists(String selector[, String message])``
131
132 Asserts that an element matching the provided :ref:`selector expression <selectors>` exists in remote DOM environment::
133
134 casper.test.begin('assertExists() tests', 1, function(test) {
135 casper.start().then(function() {
136 this.setContent('<div class="heaven">beer</div>');
137 test.assertExists('.heaven');
138 }).run(function() {
139 test.done();
140 });
141 });
142
143 .. seealso:: `assertDoesntExist()`_
144
145 .. index:: falsiness
146
147 ``assertFalsy()``
148 -------------------------------------------------------------------------------
149
150 **Signature:** ``assertFalsy(Mixed subject[, String message])``
151
152 .. versionadded:: 1.0
153
154 Asserts that a given subject is `falsy <http://11heavens.com/falsy-and-truthy-in-javascript>`_.
155
156 .. seealso:: `assertTruthy()`_
157
158 .. index:: Form
159
160 ``assertField()``
161 -------------------------------------------------------------------------------
162
163 **Signature:** ``assertField(String inputName, String expected[, String message])``
164
165 Asserts that a given form field has the provided value::
166
167 casper.test.begin('assertField() tests', 1, function(test) {
168 casper.start('http://www.google.fr/', function() {
169 this.fill('form[name="gs"]', { q: 'plop' }, false);
170 test.assertField('q', 'plop');
171 }).run(function() {
172 test.done();
173 });
174 });
175
176 .. versionadded:: 1.0
177
178 This also works with any input type: ``select``, ``textarea``, etc.
179
180 .. index:: HTTP, HTTP Status Code
181
182 ``assertHttpStatus()``
183 -------------------------------------------------------------------------------
184
185 **Signature:** ``assertHttpStatus(Number status[, String message])``
186
187 Asserts that current `HTTP status code <http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html>`_ is the same as the one passed as argument::
188
189 casper.test.begin('casperjs.org is up and running', 1, function(test) {
190 casper.start('http://casperjs.org/', function() {
191 test.assertHttpStatus(200);
192 }).run(function() {
193 test.done();
194 });
195 });
196
197 ``assertMatch()``
198 -------------------------------------------------------------------------------
199
200 **Signature:** ``assertMatch(mixed subject, RegExp pattern[, String message])``
201
202 Asserts that a provided string matches a provided javascript ``RegExp`` pattern::
203
204 casper.test.assertMatch('Chuck Norris', /^chuck/i, 'Chuck Norris' first name is Chuck');
205
206 .. seealso::
207
208 - `assertUrlMatch()`_
209 - `assertTitleMatch()`_
210
211 ``assertNot()``
212 -------------------------------------------------------------------------------
213
214 **Signature:** ``assertNot(mixed subject[, String message])``
215
216 Asserts that the passed subject resolves to some `falsy value <http://11heavens.com/falsy-and-truthy-in-javascript>`_::
217
218 casper.test.assertNot(false, "Universe is still operational");
219
220 .. seealso:: `assert()`_
221
222 ``assertNotEquals()``
223 -------------------------------------------------------------------------------
224
225 **Signature:** ``assertNotEquals(mixed testValue, mixed expected[, String message])``
226
227 .. versionadded:: 0.6.7
228
229 Asserts that two values are **not** strictly equals::
230
231 casper.test.assertNotEquals(true, "true");
232
233 .. seealso:: `assertEquals()`_
234
235 ``assertNotVisible()``
236 -------------------------------------------------------------------------------
237
238 **Signature:** ``assertNotVisible(String selector[, String message])``
239
240 Asserts that the element matching the provided :ref:`selector expression <selectors>` is not visible::
241
242 casper.test.begin('assertNotVisible() tests', 1, function(test) {
243 casper.start().then(function() {
244 this.setContent('<div class=".foo" style="display:none>boo</div>');
245 test.assertNotVisible('.foo');
246 }).run(function() {
247 test.done();
248 });
249 });
250
251 .. seealso:: `assertVisible()`_
252
253 .. index:: error
254
255 ``assertRaises()``
256 -------------------------------------------------------------------------------
257
258 **Signature:** ``assertRaises(Function fn, Array args[, String message])``
259
260 Asserts that the provided function called with the given parameters raises a javascript ``Error``::
261
262 casper.test.assertRaises(function(throwIt) {
263 if (throwIt) {
264 throw new Error('thrown');
265 }
266 }, [true], 'Error has been raised.');
267
268 casper.test.assertRaises(function(throwIt) {
269 if (throwIt) {
270 throw new Error('thrown');
271 }
272 }, [false], 'Error has been raised.'); // fails
273
274 ``assertSelectorDoesntHaveText()``
275 -------------------------------------------------------------------------------
276
277 **Signature:** ``assertSelectorDoesntHaveText(String selector, String text[, String message])``
278
279 Asserts that given text does not exist in all the elements matching the provided :ref:`selector expression <selectors>`::
280
281 casper.test.begin('assertSelectorDoesntHaveText() tests', 1, function(test) {
282 casper.start('http://google.com/', function() {
283 test.assertSelectorDoesntHaveText('title', 'Yahoo!');
284 }).run(function() {
285 test.done();
286 });
287 });
288
289 .. seealso:: `assertSelectorHasText()`_
290
291 .. index:: selector, DOM
292
293 ``assertSelectorHasText()``
294 -------------------------------------------------------------------------------
295
296 **Signature:** ``assertSelectorHasText(String selector, String text[, String message])``
297
298 Asserts that given text exists in elements matching the provided :ref:`selector expression <selectors>`::
299
300 casper.test.begin('assertSelectorHasText() tests', 1, function(test) {
301 casper.start('http://google.com/', function() {
302 test.assertSelectorDoesntHaveText('title', 'Google');
303 }).run(function() {
304 test.done();
305 });
306 });
307
308 .. seealso:: `assertSelectorDoesntHaveText()`_
309
310 .. index:: HTTP
311
312 ``assertResourceExists()``
313 -------------------------------------------------------------------------------
314
315 **Signature:** ``assertResourceExists(Function testFx[, String message])``
316
317 The ``testFx`` function is executed against all loaded assets and the test passes when at least one resource matches::
318
319 casper.test.begin('assertResourceExists() tests', 1, function(test) {
320 casper.start('http://www.google.fr/', function() {
321 test.assertResourceExists(function(resource) {
322 return resource.url.match('logo3w.png');
323 });
324 }).run(function() {
325 test.done();
326 });
327 });
328
329 Shorter::
330
331 casper.test.begin('assertResourceExists() tests', 1, function(test) {
332 casper.start('http://www.google.fr/', function() {
333 test.assertResourceExists('logo3w.png');
334 }).run(function() {
335 test.done();
336 });
337 });
338
339 .. hint::
340
341 Check the documentation for :ref:`Casper.resourceExists() <casper_resourceexists>`.
342
343 ``assertTextExists()``
344 -------------------------------------------------------------------------------
345
346 **Signature:** ``assertTextExists(String expected[, String message])``
347
348 Asserts that body **plain text content** contains the given string::
349
350 casper.test.begin('assertTextExists() tests', 1, function(test) {
351 casper.start('http://www.google.fr/', function() {
352 test.assertTextExists('google', 'page body contains "google"');
353 }).run(function() {
354 test.done();
355 });
356 });
357
358 .. seealso:: `assertTextDoesntExist()`_
359
360 ``assertTextDoesntExist()``
361 -------------------------------------------------------------------------------
362
363 **Signature:** ``assertTextDoesntExist(String unexpected[, String message])``
364
365 .. versionadded:: 1.0
366
367 Asserts that body **plain text content** doesn't contain the given string::
368
369 casper.test.begin('assertTextDoesntExist() tests', 1, function(test) {
370 casper.start('http://www.google.fr/', function() {
371 test.assertTextDoesntExist('bing', 'page body does not contain "bing"');
372 }).run(function() {
373 test.done();
374 });
375 });
376
377 .. seealso:: `assertTextExists()`_
378
379 ``assertTitle()``
380 -------------------------------------------------------------------------------
381
382 **Signature:** ``assertTitle(String expected[, String message])``
383
384 Asserts that title of the remote page equals to the expected one::
385
386 casper.test.begin('assertTitle() tests', 1, function(test) {
387 casper.start('http://www.google.fr/', function() {
388 test.assertTitle('Google', 'google.fr has the correct title');
389 }).run(function() {
390 test.done();
391 });
392 });
393
394 .. seealso:: `assertTitleMatch()`_
395
396 ``assertTitleMatch()``
397 -------------------------------------------------------------------------------
398
399 **Signature:** ``assertTitleMatch(RegExp pattern[, String message])``
400
401 Asserts that title of the remote page matches the provided RegExp pattern::
402
403 casper.test.begin('assertTitleMatch() tests', 1, function(test) {
404 casper.start('http://www.google.fr/', function() {
405 test.assertTitleMatch(/Google/, 'google.fr has a quite predictable title');
406 }).run(function() {
407 test.done();
408 });
409 });
410
411 .. seealso:: `assertTitle()`_
412
413 .. index:: truthiness
414
415 ``assertTruthy()``
416 -------------------------------------------------------------------------------
417
418 **Signature:** ``assertTruthy(Mixed subject[, String message])``
419
420 .. versionadded:: 1.0
421
422 Asserts that a given subject is `truthy <http://11heavens.com/falsy-and-truthy-in-javascript>`_.
423
424 .. seealso:: `assertFalsy()`_
425
426 .. index:: Type
427
428 ``assertType()``
429 -------------------------------------------------------------------------------
430
431 **Signature:** ``assertType(mixed input, String type[, String message])``
432
433 Asserts that the provided input is of the given type::
434
435 casper.test.begin('assertType() tests', 1, function suite(test) {
436 test.assertType(42, "number", "Okay, 42 is a number");
437 test.assertType([1, 2, 3], "array", "We can test for arrays too!");
438 test.done();
439 });
440
441 .. note:: Type names are always expressed in lower case.
442
443 .. index:: URL
444
445 ``assertUrlMatch()``
446 -------------------------------------------------------------------------------
447
448 **Signature:** ``assertUrlMatch(Regexp pattern[, String message])``
449
450 Asserts that the current page url matches the provided RegExp pattern::
451
452 casper.test.begin('assertUrlMatch() tests', 1, function(test) {
453 casper.start('http://www.google.fr/', function() {
454 test.assertUrlMatch(/^http:\/\//', 'google.fr is served in http://');
455 }).run(function() {
456 test.done();
457 });
458 });
459
460 .. index:: DOM
461
462 ``assertVisible()``
463 -------------------------------------------------------------------------------
464
465 **Signature:** ``assertVisible(String selector[, String message])``
466
467 Asserts that the element matching the provided :ref:`selector expression <selectors>` is visible::
468
469 casper.test.begin('assertVisible() tests', 1, function(test) {
470 casper.start('http://www.google.fr/', function() {
471 test.assertVisible('h1');
472 }).run(function() {
473 test.done();
474 });
475 });
476
477 .. seealso:: `assertNotVisible()`_
478
479 .. _tester_begin:
480
481 .. index:: Test suite, planned tests, Asynchronicity, Termination
482
483 ``begin()``
484 -------------------------------------------------------------------------------
485
486 **Signatures:**
487
488 - ``begin(String description, Number planned, Function suite)``
489 - ``begin(String description, Function suite)``
490 - ``begin(String description, Number planned, Object config)``
491 - ``begin(String description, Object config)``
492
493 .. versionadded:: 1.1
494
495 Starts a suite of ``<planned>`` tests (if defined). The ``suite`` callback will get the current ``Tester`` instance as its first argument::
496
497 function Cow() {
498 this.mowed = false;
499 this.moo = function moo() {
500 this.mowed = true; // mootable state: don't do that
501 return 'moo!';
502 };
503 }
504
505 // unit style synchronous test case
506 casper.test.begin('Cow can moo', 2, function suite(test) {
507 var cow = new Cow();
508 test.assertEquals(cow.moo(), 'moo!');
509 test.assert(cow.mowed);
510 test.done();
511 });
512
513 .. note::
514
515 The ``planned`` argument is especially useful in case a given test script is abruptly interrupted leaving you with no obvious way to know it and an erroneously successful status.
516
517 A more asynchronous example::
518
519 casper.test.begin('Casperjs.org is navigable', 2, function suite(test) {
520 casper.start('http://casperjs.org/', function() {
521 test.assertTitleMatches(/casperjs/i);
522 this.clickLabel('Testing');
523 });
524
525 casper.then(function() {
526 test.assertUrlMatches(/testing\.html$/);
527 });
528
529 casper.run(function() {
530 test.done();
531 });
532 });
533
534 .. important::
535
536 `done()`_ **must** be called in order to terminate the suite. This is specially important when doing asynchronous tests so ensure it's called when everything has actually been performed.
537
538 .. seealso:: `done()`_
539
540 ``Tester#begin()`` also accepts a test configuration object, so you can add ``setUp()`` and ``tearDown()`` methods::
541
542 // cow-test.js
543 casper.test.begin('Cow can moo', 2, {
544 setUp: function(test) {
545 this.cow = new Cow();
546 },
547
548 tearDown: function(test) {
549 this.cow.destroy();
550 },
551
552 test: function(test) {
553 test.assertEquals(this.cow.moo(), 'moo!');
554 test.assert(this.cow.mowed);
555 test.done();
556 }
557 });
558
559 .. index:: Colors
560
561 ``colorize()``
562 -------------------------------------------------------------------------------
563
564 **Signature:** ``colorize(String message, String style)``
565
566 Render a colorized output. Basically a proxy method for ``Casper.Colorizer#colorize()``.
567
568 ``comment()``
569 -------------------------------------------------------------------------------
570
571 **Signature:** ``comment(String message)``
572
573 Writes a comment-style formatted message to stdout::
574
575 casper.test.comment("Hi, I'm a comment");
576
577 .. _tester_done:
578
579 .. index:: Test suite, Asynchronicity, Termination, done()
580
581 ``done()``
582 -------------------------------------------------------------------------------
583
584 **Signature:** ``done()``
585
586 .. versionchanged:: 1.1 ``planned`` parameter is deprecated
587
588 Flag a test suite started with `begin()`_ as processed::
589
590 casper.test.begin('my test suite', 2, function(test) {
591 test.assert(true);
592 test.assertNot(false);
593 test.done();
594 });
595
596 More asynchronously::
597
598 casper.test.begin('Casperjs.org is navigable', 2, function suite(test) {
599 casper.start('http://casperjs.org/', function() {
600 test.assertTitleMatches(/casperjs/i);
601 this.clickLabel('Testing');
602 });
603
604 casper.then(function() {
605 test.assertUrlMatches(/testing\.html$/);
606 });
607
608 casper.run(function() {
609 test.done();
610 });
611 });
612
613 .. seealso:: `begin()`_
614
615 ``error()``
616 -------------------------------------------------------------------------------
617
618 **Signature:** ``error(String message)``
619
620 Writes an error-style formatted message to stdout::
621
622 casper.test.error("Hi, I'm an error");
623
624 .. index:: Test failure
625
626 ``fail()``
627 -------------------------------------------------------------------------------
628
629 **Signature:** ``fail(String message)``
630
631 Adds a failed test entry to the stack::
632
633 casper.test.fail("Georges W. Bush");
634
635 .. seealso:: `pass()`_
636
637 ``formatMessage()``
638 -------------------------------------------------------------------------------
639
640 **Signature:** ``formatMessage(String message, String style)``
641
642 Formats a message to highlight some parts of it. Only used internally by the tester.
643
644 ``getFailures()``
645 -------------------------------------------------------------------------------
646
647 **Signature:** ``getFailures()``
648
649 .. versionadded:: 1.0
650
651 Retrieves failures for current test suite::
652
653 casper.test.assertEquals(true, false);
654 require('utils').dump(casper.test.getFailures());
655 casper.test.done();
656
657 That will give something like this:
658
659 .. code-block:: text
660
661 $ casperjs test test-getFailures.js
662 Test file: test-getFailures.js
663 FAIL Subject equals the expected value
664 # type: assertEquals
665 # subject: true
666 # expected: false
667 {
668 "length": 1,
669 "cases": [
670 {
671 "success": false,
672 "type": "assertEquals",
673 "standard": "Subject equals the expected value",
674 "file": "test-getFailures.js",
675 "values": {
676 "subject": true,
677 "expected": false
678 }
679 }
680 ]
681 }
682 FAIL 1 tests executed, 0 passed, 1 failed.
683
684 Details for the 1 failed test:
685
686 In c.js:0
687 assertEquals: Subject equals the expected value
688
689 ``getPasses()``
690 -------------------------------------------------------------------------------
691
692 **Signature:** ``getPasses()``
693
694 .. versionadded:: 1.0
695
696 Retrieves a report for successful test cases in the current test suite::
697
698 casper.test.assertEquals(true, true);
699 require('utils').dump(casper.test.getPasses());
700 casper.test.done();
701
702 That will give something like this::
703
704 $ casperjs test test-getPasses.js
705 Test file: test-getPasses.js
706 PASS Subject equals the expected value
707 {
708 "length": 1,
709 "cases": [
710 {
711 "success": true,
712 "type": "assertEquals",
713 "standard": "Subject equals the expected value",
714 "file": "test-getPasses.js",
715 "values": {
716 "subject": true,
717 "expected": true
718 }
719 }
720 ]
721 }
722 PASS 1 tests executed, 1 passed, 0 failed.
723
724 ``info()``
725 -------------------------------------------------------------------------------
726
727 **Signature:** ``info(String message)``
728
729 Writes an info-style formatted message to stdout::
730
731 casper.test.info("Hi, I'm an informative message.");
732
733 .. index:: Test success
734
735 ``pass()``
736 -------------------------------------------------------------------------------
737
738 **Signature:** ``pass(String message)``
739
740 Adds a successful test entry to the stack::
741
742 casper.test.pass("Barrack Obama");
743
744 .. seealso:: `fail()`_
745
746 ``renderResults()``
747 -------------------------------------------------------------------------------
748
749 **Signature:** ``renderResults(Boolean exit, Number status, String save)``
750
751 Render test results, save results in an XUnit formatted file, and optionally exits phantomjs::
752
753 casper.test.renderResults(true, 0, 'test-results.xml');
754
755 .. note::
756
757 This method is not to be called when using the ``casperjs test`` command (see documentation for :doc:`testing <../testing>`), where it's done automatically for you.
758
759 ``skip()``
760 -------------------------------------------------------------------------------
761
762 **Signature:** ``skip(Number nb, String message)``
763
764 Skips a given number of planned tests::
765
766 casper.test.begin('Skip tests', 4, function(test) {
767 test.assert(true, 'First test executed');
768 test.assert(true, 'Second test executed');
769 test.skip(2, 'Two tests skipped');
770 test.done();
771 });
1 .. _utils_module:
2
3 .. index:: Utilities, Helpers
4
5 ====================
6 The ``utils`` module
7 ====================
8
9 This module provides simple helper functions, some of them being very specific to CasperJS though.
10
11 Functions reference
12 +++++++++++++++++++
13
14 Usage is pretty much straightforward::
15
16 var utils = require('utils');
17
18 utils.dump({plop: 42});
19
20 ``betterTypeOf()``
21 -------------------------------------------------------------------------------
22
23 **Signature:** ``betterTypeOf(input)``
24
25 Provides a better ``typeof`` operator equivalent, eg. able to retrieve the ``Array`` type.
26
27 .. index:: dump, Serialization, Debugging, JSON
28
29 .. _utils_dump:
30
31 ``dump()``
32 -------------------------------------------------------------------------------
33
34 **Signature:** ``dump(value)``
35
36 Dumps a JSON_ representation of passed argument to the standard output. Useful for :ref:`debugging your scripts <debugging_dump>`.
37
38 ``fileExt()``
39 -------------------------------------------------------------------------------
40
41 **Signature:** ``fileExt(file)``
42
43 Retrieves the extension of passed filename.
44
45 ``fillBlanks()``
46 -------------------------------------------------------------------------------
47
48 **Signature:** ``fillBlanks(text, pad)``
49
50 Fills a string with trailing spaces to match ``pad`` length.
51
52 .. index:: String formatting
53
54 ``format()``
55 -------------------------------------------------------------------------------
56
57 **Signature:** ``format(f)``
58
59 Formats a string against passed args. ``sprintf`` equivalent.
60
61 .. note::
62
63 This is a port of nodejs ``util.format()``.
64
65 ``getPropertyPath()``
66 -------------------------------------------------------------------------------
67
68 **Signature:** ``getPropertyPath(Object obj, String path)``
69
70 .. versionadded:: 1.0
71
72 Retrieves the value of an Object foreign property using a dot-separated path string::
73
74 var account = {
75 username: 'chuck',
76 skills: {
77 kick: {
78 roundhouse: true
79 }
80 }
81 }
82 utils.getPropertyPath(account, 'skills.kick.roundhouse'); // true
83
84 .. warning::
85
86 This function doesn't handle object key names containing a dot.
87
88 .. index:: inheritance
89
90 ``inherits()``
91 -------------------------------------------------------------------------------
92
93 **Signature:** ``inherits(ctor, superCtor)``
94
95 Makes a constructor inheriting from another. Useful for subclassing and :doc:`extending <../extending>`.
96
97 .. note::
98
99 This is a port of nodejs ``util.inherits()``.
100
101 ``isArray()``
102 -------------------------------------------------------------------------------
103
104 **Signature:** ``isArray(value)``
105
106 Checks if passed argument is an instance of ``Array``.
107
108 ``isCasperObject()``
109 -------------------------------------------------------------------------------
110
111 **Signature:** ``isCasperObject(value)``
112
113 Checks if passed argument is an instance of ``Casper``.
114
115 ``isClipRect()``
116 -------------------------------------------------------------------------------
117
118 **Signature:** ``isClipRect(value)``
119
120 Checks if passed argument is a ``cliprect`` object.
121
122 .. index:: falsiness
123
124 ``isFalsy()``
125 -------------------------------------------------------------------------------
126
127 **Signature:** ``isFalsy(subject)``
128
129 .. versionadded:: 1.0
130
131 Returns subject `falsiness <http://11heavens.com/falsy-and-truthy-in-javascript>`_.
132
133 ``isFunction()``
134 -------------------------------------------------------------------------------
135
136 **Signature:** ``isFunction(value)``
137
138 Checks if passed argument is a function.
139
140 ``isJsFile()``
141 -------------------------------------------------------------------------------
142
143 **Signature:** ``isJsFile(file)``
144
145 Checks if passed filename is a Javascript one (by checking if it has a ``.js`` or ``.coffee`` file extension).
146
147 ``isNull()``
148 -------------------------------------------------------------------------------
149
150 **Signature:** ``isNull(value)``
151
152 Checks if passed argument is a ``null``.
153
154 ``isNumber()``
155 -------------------------------------------------------------------------------
156
157 **Signature:** ``isNumber(value)``
158
159 Checks if passed argument is an instance of ``Number``.
160
161 ``isObject()``
162 -------------------------------------------------------------------------------
163
164 **Signature:** ``isObject(value)``
165
166 Checks if passed argument is an object.
167
168 ``isString()``
169 -------------------------------------------------------------------------------
170
171 **Signature:** ``isString(value)``
172
173 Checks if passed argument is an instance of ``String``.
174
175 .. index:: truthiness
176
177 ``isTruthy()``
178 -------------------------------------------------------------------------------
179
180 **Signature:** ``isTruthy(subject)``
181
182 .. versionadded:: 1.0
183
184 Returns subject `truthiness <http://11heavens.com/falsy-and-truthy-in-javascript>`_.
185
186 ``isType()``
187 -------------------------------------------------------------------------------
188
189 **Signature:** ``isType(what, type)``
190
191 Checks if passed argument has its type matching the ``type`` argument.
192
193 ``isUndefined()``
194 -------------------------------------------------------------------------------
195
196 **Signature:** ``isUndefined(value)``
197
198 Checks if passed argument is ``undefined``.
199
200 ``isWebPage()``
201 -------------------------------------------------------------------------------
202
203 **Signature:** ``isWebPage(what)``
204
205 Checks if passed argument is an instance of native PhantomJS' ``WebPage`` object.
206
207 ``mergeObjects()``
208 -------------------------------------------------------------------------------
209
210 **Signature:** ``mergeObjects(origin, add)``
211
212 Merges two objects recursively.
213
214 .. index:: DOM
215
216 ``node()``
217 -------------------------------------------------------------------------------
218
219 **Signature:** ``node(name, attributes)``
220
221 Creates an (HT\|X)ML element, having optional ``attributes`` added.
222
223 .. index:: JSON
224
225 ``serialize()``
226 -------------------------------------------------------------------------------
227
228 **Signature:** ``serialize(value)``
229
230 Serializes a value using JSON_ format. Will serialize functions as strings. Useful for :doc:`debugging <../debugging>` and comparing objects.
231
232 ``unique()``
233 -------------------------------------------------------------------------------
234
235 **Signature:** ``unique(array)``
236
237 Retrieves unique values from within a given ``Array``.
238
239 .. _JSON: http://json.org/
1 .. _quickstart:
2
3 ==========
4 Quickstart
5 ==========
6
7 Once CasperJS is :doc:`properly installed <installation>`, you can write your first script. You can use plain :ref:`Javascript <quickstart_javascript>` or :ref:`CoffeeScript <quickstart_coffeescript>`.
8
9 .. hint::
10
11 If you're not too comfortable with Javascript, a :ref:`dedicated FAQ entry <faq_javascript>` is waiting for you.
12
13 .. _quickstart_javascript:
14
15 A minimal scraping script
16 -------------------------
17
18 Fire up your favorite editor, create and save a ``sample.js`` file like below::
19
20 var casper = require('casper').create();
21
22 casper.start('http://casperjs.org/', function() {
23 this.echo(this.getTitle());
24 });
25
26 casper.thenOpen('http://phantomjs.org', function() {
27 this.echo(this.getTitle());
28 });
29
30 casper.run();
31
32 Run it:
33
34 .. code-block:: text
35
36 $ casperjs sample.js
37
38 You should get something like this:
39
40 .. code-block:: text
41
42 $ casperjs c.js
43 CasperJS, a navigation scripting and testing utility for PhantomJS | CasperJS 1.0.0
44 PhantomJS: Headless WebKit with JavaScript API
45
46 .. topic:: What did we just do?
47
48 1. we created a new :ref:`Casper <casper_module>` instance
49 2. we started it and opened ``http://casperjs.org/``
50 3. *once* the page has been loaded, we asked to print the title of that webpage (the content of its ``<title>`` tag)
51 4. *then* we opened another url, ``http://phantomjs.org/``
52 5. *once* the new page has been loaded, we asked to print its title too
53 6. we executed the whole process
54
55
56 Now let's scrape Google!
57 ------------------------
58
59 In the following example, we'll query google for two terms consecutively, *"casperjs"* and *"phantomjs"*, aggregate the result links in a standard ``Array`` and output the result to the console.
60
61 Fire up your favorite editor and save the javascript code below in a
62 ``googlelinks.js`` file::
63
64 var links = [];
65 var casper = require('casper').create();
66
67 function getLinks() {
68 var links = document.querySelectorAll('h3.r a');
69 return Array.prototype.map.call(links, function(e) {
70 return e.getAttribute('href')
71 });
72 }
73
74 casper.start('http://google.fr/', function() {
75 // search for 'casperjs' from google form
76 this.fill('form[action="/search"]', { q: 'casperjs' }, true);
77 });
78
79 casper.then(function() {
80 // aggregate results for the 'casperjs' search
81 links = this.evaluate(getLinks);
82 // now search for 'phantomjs' by filling the form again
83 this.fill('form[action="/search"]', { q: 'phantomjs' }, true);
84 });
85
86 casper.then(function() {
87 // aggregate results for the 'phantomjs' search
88 links = links.concat(this.evaluate(getLinks));
89 });
90
91 casper.run(function() {
92 // echo results in some pretty fashion
93 this.echo(links.length + ' links found:');
94 this.echo(' - ' + links.join('\n - ')).exit();
95 });
96
97 Run it:
98
99 .. code-block:: text
100
101 $ casperjs googlelinks.js
102 20 links found:
103 - https://github.com/n1k0/casperjs
104 - https://github.com/n1k0/casperjs/issues/2
105 - https://github.com/n1k0/casperjs/tree/master/samples
106 - https://github.com/n1k0/casperjs/commits/master/
107 - http://www.facebook.com/people/Casper-Js/100000337260665
108 - http://www.facebook.com/public/Casper-Js
109 - http://hashtags.org/tag/CasperJS/
110 - http://www.zerotohundred.com/newforums/members/casper-js.html
111 - http://www.yellowpages.com/casper-wy/j-s-enterprises
112 - http://local.trib.com/casper+wy/j+s+chinese+restaurant.zq.html
113 - http://www.phantomjs.org/
114 - http://code.google.com/p/phantomjs/
115 - http://code.google.com/p/phantomjs/wiki/QuickStart
116 - http://svay.com/blog/index/post/2011/08/31/Paris-JS-10-%3A-Introduction-%C3%A0-PhantomJS
117 - https://github.com/ariya/phantomjs
118 - http://dailyjs.com/2011/01/28/phantoms/
119 - http://css.dzone.com/articles/phantom-js-alternative
120 - http://pilvee.com/blog/tag/phantom-js/
121 - http://ariya.blogspot.com/2011/01/phantomjs-minimalistic-headless-webkit.html
122 - http://www.readwriteweb.com/hack/2011/03/phantomjs-the-power-of-webkit.php
123
124
125 .. _quickstart_coffeescript:
126
127 .. index:: coffeescript
128
129 CoffeeScript version
130 --------------------
131
132 You can also write Casper scripts using the `CoffeeScript syntax <http://jashkenas.github.com/coffee-script/>`_:
133
134 .. code-block:: coffeescript
135
136 getLinks = ->
137 links = document.querySelectorAll "h3.r a"
138 Array::map.call links, (e) -> e.getAttribute "href"
139
140 links = []
141 casper = require('casper').create()
142
143 casper.start "http://google.fr/", ->
144 # search for 'casperjs' from google form
145 @fill "form[action='/search']", q: "casperjs", true
146
147 casper.then ->
148 # aggregate results for the 'casperjs' search
149 links = @evaluate getLinks
150 # search for 'phantomjs' from google form
151 @fill "form[action='/search']", q: "phantomjs", true
152
153 casper.then ->
154 # concat results for the 'phantomjs' search
155 links = links.concat @evaluate(getLinks)
156
157 casper.run ->
158 # display results
159 @echo links.length + " links found:"
160 @echo(" - " + links.join("\n - ")).exit()
161
162 Just remember to suffix your script with the ``.coffee`` extension.
163
164 A minimal testing script
165 ------------------------
166
167 CasperJS is also a :ref:`testing framework <testing>`; test scripts are slightly different than scraping ones, though they share most of their API. A simplest test script::
168
169 // hello-test.js
170 casper.test.assert(true);
171 casper.test.done();
172
173 Run it using the ``casperjs test`` subcommand:
174
175 .. code-block:: text
176
177 $ casperjs test hello-test.js
178 Test file: hello-test.js
179 PASS Subject is strictly true
180 PASS 1 tests executed in 0.103s, 1 passed, 0 failed.
181
182 .. note::
183
184 As you can see, there's no need to create a ``casper`` instance in a test script as a preconfigured one has already made available for you.
185
186 You can read more about testing in the :ref:`dedicated section <testing>`.
1 .. _selectors:
2
3 .. index:: selector, DOM, HTML
4
5 =========
6 Selectors
7 =========
8
9 CasperJS makes an heavy use of selectors in order to work with the `DOM <http://www.w3.org/TR/dom/>`_, and can transparently use either `CSS3 <http://www.w3.org/TR/selectors/>`_ or `XPath <http://www.w3.org/TR/xpath/>`_ expressions.
10
11 All the examples below are based on this HTML code:
12
13 .. code-block:: html
14
15 <!doctype html>
16 <html>
17 <head>
18 <meta charset="utf-8">
19 <title>My page</title>
20 </head>
21 <body>
22 <h1 class="page-title">Hello</h1>
23 <ul>
24 <li>one</li>
25 <li>two</li>
26 <li>three</li>
27 </ul>
28 <footer><p>©2012 myself</p></footer>
29 </body>
30 </html>
31
32 .. index:: CSS, CSS3
33
34 CSS3
35 ----
36
37 By default, CasperJS accepts `CSS3 selector strings <http://www.w3.org/TR/selectors/#selectors>`_ to check for elements within the DOM.
38
39 To check if the ``<h1 class="page-title">`` element exists in the example page, you can use::
40
41 var casper = require('casper').create();
42
43 casper.start('http://domain.tld/page.html', function() {
44 if (this.exists('h1.page-title')) {
45 this.echo('the heading exists');
46 }
47 });
48
49 casper.run();
50
51 Or if you're using the :doc:`testing framework <testing>`::
52
53 casper.test.begin('The heading exists', 1, function suite(test) {
54 casper.start('http://domain.tld/page.html', function() {
55 this.assertExists('h1.page-title');
56 }).run(function() {
57 test.done();
58 });
59 });
60
61 Some other convenient testing methods are relying on selectors::
62
63 casper.test.begin('Page content tests', 3, function suite(test) {
64 casper.start('http://domain.tld/page.html', function() {
65 this.assertExists('h1.page-title');
66 this.assertSelectorHasText('h1.page-title', 'Hello');
67 this.assertVisible('footer');
68 }).run(function() {
69 test.done();
70 });
71 });
72
73 .. index:: XPath
74
75 XPath
76 -----
77
78 .. versionadded:: 0.6.8
79
80 You can alternatively use `XPath expressions <http://en.wikipedia.org/wiki/XPath>`_ instead::
81
82 casper.start('http://domain.tld/page.html', function() {
83 this.test.assertExists({
84 type: 'xpath',
85 path: '//*[@class="plop"]'
86 }, 'the element exists');
87 });
88
89 To ease the use and reading of XPath expressions, a ``selectXPath`` helper is available from the ``casper`` module::
90
91 var x = require('casper').selectXPath;
92
93 casper.start('http://domain.tld/page.html', function() {
94 this.test.assertExists(x('//*[@id="plop"]'), 'the element exists');
95 });
96
97 .. warning::
98
99 The only limitation of XPath use in CasperJS is in the :ref:`casper.fill() <casper_fill>` method when you want to fill **file fields**; PhantomJS natively only allows the use of CSS3 selectors in its `uploadFile method <https://github.com/ariya/phantomjs/wiki/API-Reference#wiki-webpage-uploadFile>`_, hence this limitation.
1 .. _testing:
2
3 .. index:: Testing
4
5 =======
6 Testing
7 =======
8
9 CasperJS ships with its own :doc:`testing framework <modules/tester>`, providing a handful set of tools to ease testing your webapps.
10
11 .. warning::
12
13 .. versionchanged:: 1.1
14
15 The testing framework — hence its whole API — can only be used when using the ``casperjs test`` subcommand.
16
17 If you try to use the ``casper.test`` property out of the testing environment, you'll get an error.
18
19 .. index:: Unit testing
20
21 Unit testing
22 ------------
23
24 Imagine a dumb ``Cow`` object we want to unit test::
25
26 function Cow() {
27 this.mowed = false;
28 this.moo = function moo() {
29 this.mowed = true; // mootable state: don't do that at home
30 return 'moo!';
31 };
32 }
33
34 Let's write a tiny test suite for it::
35
36 // cow-test.js
37 casper.test.begin('Cow can moo', 2, function suite(test) {
38 var cow = new Cow();
39 test.assertEquals(cow.moo(), 'moo!');
40 test.assert(cow.mowed);
41 test.done();
42 });
43
44 Run the tests using the ``casperjs test`` command:
45
46 .. code-block:: text
47
48 $ casperjs test cow-test.js
49
50 You should theoretically get something like this:
51
52 .. figure:: _static/images/cow-test-ok.png
53 :align: center
54
55 Make it fail::
56
57 casper.test.begin('Cow can moo', 2, function suite(test) {
58 var cow = new Cow();
59 test.assertEquals(cow.moo(), 'BAZINGA!');
60 test.assert(cow.mowed);
61 test.done();
62 });
63
64 You'll get this instead:
65
66 .. figure:: _static/images/cow-test-ko.png
67 :align: center
68
69 .. hint::
70
71 The whole ``tester`` module API is documented :doc:`here <modules/tester>`.
72
73
74 .. index:: Functional testing, Browser testing, Test suite
75
76 Browser tests
77 -------------
78
79 Now let's write a suite for testing google search (yes, you read it well)::
80
81 // googletesting.js
82 casper.test.begin('Google search retrieves 10 or more results', 5, function suite(test) {
83 casper.start("http://www.google.fr/", function() {
84 test.assertTitle("Google", "google homepage title is the one expected");
85 test.assertExists('form[action="/search"]', "main form is found");
86 this.fill('form[action="/search"]', {
87 q: "casperjs"
88 }, true);
89 });
90
91 casper.then(function() {
92 test.assertTitle("casperjs - Recherche Google", "google title is ok");
93 test.assertUrlMatch(/q=casperjs/, "search term has been submitted");
94 test.assertEval(function() {
95 return __utils__.findAll("h3.r").length >= 10;
96 }, "google search for \"casperjs\" retrieves 10 or more results");
97 });
98
99 casper.run(function() {
100 test.done();
101 });
102 });
103
104 Now run the tests suite:
105
106 .. code-block:: text
107
108 $ casperjs test googletesting.js
109
110 You'll probably get something like this:
111
112 .. figure:: _static/images/testsuiteok.png
113 :align: center
114
115
116 Advanced techniques
117 -------------------
118
119 The :ref:`Tester#begin() <tester_begin>` accepts either a function or an object to describe a suite; the object option allows to set up ``setUp()`` and ``tearDown()`` functions::
120
121 // cow-test.js
122 casper.test.begin('Cow can moo', 2, {
123 setUp: function(test) {
124 this.cow = new Cow();
125 },
126
127 tearDown: function(test) {
128 this.cow.destroy();
129 },
130
131 test: function(test) {
132 test.assertEquals(this.cow.moo(), 'moo!');
133 test.assert(this.cow.mowed);
134 test.done();
135 }
136 });
137
138
139 Test command args and options
140 -----------------------------
141
142 Arguments
143 ~~~~~~~~~
144
145 The ``capserjs test`` command will treat every passed argument as file or directory paths containing tests. It will recursively scan any passed directory to search for ``*.js`` or ``*.coffee`` files and add them to the stack.
146
147 .. warning ::
148
149 There are two important conditions when writing tests:
150
151 - You **must not** create a new ``Casper`` instance in a test file;
152 - You **must** call ``Tester.done()`` when all the tests contained in a suite (or in a file) have been executed.
153
154 Options
155 ~~~~~~~
156
157 Options are prefixed with a double-dash (``--``):
158
159 - ``--xunit=<filename>`` will export test suite results in a :ref:`XUnit XML file <xunit_report>`
160 - ``--direct`` will print :doc:`log messages <logging>` directly to the console
161 - ``--log-level=<logLevel>`` sets the logging level (see the :doc:`related section <logging>`)
162
163 .. versionadded:: 1.0
164
165 - ``--includes=foo.js,bar.js`` will include the ``foo.js`` and ``bar.js`` files before each test file execution;
166 - ``--pre=pre-test.js`` will add the tests contained in ``pre-test.js`` **before** executing the whole test suite;
167 - ``--post=post-test.js`` will add the tests contained in ``post-test.js`` **after** having executed the whole test suite;
168 - ``--fail-fast`` will terminate the current test suite as soon as a first failure is encountered.
169
170 Sample custom command:
171
172 .. code-block:: text
173
174 $ casperjs test --includes=foo.js,bar.js \
175 --pre=pre-test.js \
176 --post=post-test.js \
177 --direct \
178 --log-level=debug \
179 --fail-fast \
180 test1.js test2.js /path/to/some/test/dir
181
182 .. hint::
183
184 A `demo gist <https://gist.github.com/3813361>`_ is also available in order to get you started with a sample suite involving some of these options.
185
186
187 .. _xunit_report:
188
189 .. index:: XUnit, XML, Jenkins, Continuous Integration
190
191 Exporting results in XUnit format
192 ---------------------------------
193
194 CasperJS can export the results of the test suite to an XUnit XML file, which is compatible with continuous integration tools such as `Jenkins <http://jenkins-ci.org/>`_. To save the XUnit log of your test suite, use the ``--xunit`` option:
195
196 .. code-block:: text
197
198 $ casperjs test googletesting.js --save=log.xml
199
200 You should get a pretty XUnit XML report like this:
201
202 .. code-block:: xml
203
204 <?xml version="1.0" encoding="UTF-8"?>
205 <testsuites duration="1.249">
206 <testsuite errors="0" failures="0" name="Google search retrieves 10 or more results" package="googletesting" tests="5" time="1.249" timestamp="2012-12-30T21:27:26.320Z">
207 <testcase classname="googletesting" name="google homepage title is the one expected" time="0.813"/>
208 <testcase classname="googletesting" name="main form is found" time="0.002"/>
209 <testcase classname="googletesting" name="google title is ok" time="0.416"/>
210 <testcase classname="googletesting" name="search term has been submitted" time="0.017"/>
211 <testcase classname="googletesting" name="google search for &quot;casperjs&quot; retrieves 10 or more results" time="0.001"/>
212 <system-out/>
213 </testsuite>
214 </testsuites>
215
216 CasperJS own tests
217 ------------------
218
219 CasperJS has its own unit and functional test suite, located in the ``tests`` subfolder. To run this test suite:
220
221 .. code-block:: text
222
223 $ casperjs selftest
224
225 .. note::
226
227 Running this test suite is a great way to find any bug on your platform. If it fails, feel free to `file an issue <https://github.com/n1k0/casperjs/issues/new>`_ or to ask on the `CasperJS mailing-list <https://groups.google.com/forum/#!forum/casperjs>`_.
228
229
230 .. index:: extending
231
232 Extending Casper for Testing
233 ----------------------------
234
235 This command:
236
237 .. code-block:: text
238
239 $ casperjs test [path]
240
241 is just a shortcut for this one:
242
243 .. code-block:: text
244
245 $ casper /path/to/casperjs/tests/run.js [path]
246
247 So if you want to extend Casper capabilities for your tests, your best bet is to write your own runner and extend the casper object instance from there.
248
249 .. hint::
250
251 You can find the default runner code in `run.js <https://github.com/n1k0/casperjs/blob/master/tests/run.js>`_.
1 Upgrading to 1.1
2 ================
3
4 The most visible change is the way you write tests. With 1.0, you were able to access a ``.test`` property from any casper script and so running a suite using the standard ``casperjs`` executable::
5
6 // 1.0 style test script not using the `casperjs test` subcommand
7 var casper = require('casper').create();
8
9 casper.start('http://foo.bar/', function() {
10 this.test.assert(true);
11 });
12
13 casper.run(function() {
14 this.test.done(1);
15 this.test.renderResults(true);
16 });
17
18 In 1.1, the test framework has been heavily refactored to decouple the tester from a casper instance as much as possible, so it's no more possible to run a test suite right from the standard ``casperjs`` command as you would have done with the script shown above.
19
20 Instead you now have to use the :doc:`casperjs test <../testing>` subcommand mandatorily to access a tester instance from the ``casper.test`` property.
21
22 .. warning::
23
24 As of 1.1:
25
26 - you shouldn't invoke the ``renderResults()`` method directly anymore
27 - you shouldn't use the ``done()`` first argument to set planned test as it's been deprecated
28 - you can't access the ``casper.test`` property when not using the ``casperjs test`` subcommand
29
30 If you try, you'll get an error::
31
32 // test.js
33 var casper = require('casper').create();
34 casper.test.assert(true);
35
36 Will give:
37
38 .. code-block:: text
39
40 $ casperjs test.js
41 CasperError: casper.test property is only available using the `casperjs test` command
42
43 The new ``Tester#begin()`` method
44 ---------------------------------
45
46 However, a new :ref:`begin() <tester_begin>` method as been added to the :ref:`Tester <tester_module>` prototype, to ease describing your tests::
47
48 casper.test.begin('Description of my test', 1, function(test) {
49 test.assert(true);
50 test.done();
51 });
52
53 More asynchronously::
54
55 casper.test.begin('Description of my test', 1, function(test) {
56 casper.start('http://foo.bar/', function() {
57 test.assert(true);
58 });
59
60 casper.run(function() {
61 test.done();
62 });
63 });
64
65 .. note::
66
67 Please note that ``begin()``'s the second argument which is now the place to set the number of planned tests.
1 Upgrading
2 =========
3
4 .. toctree::
5 :maxdepth: 1
6
7 1.1
1 .. _writing_modules:
2
3 .. index:: Modules, Modules, Custom module
4
5 Writing CasperJS modules
6 ========================
7
8 As of 1.1, CasperJS relies on PhantomJS' native ``require()`` function internally though it had to be patched in order to allow requiring casper modules using their full name, eg. ``require('casper')``.
9
10 So if you plan to write your own modules and uses casperjs' ones from them, be sure to call the ``patchRequire()`` function::
11
12 // my module, stored in universe.js
13 // patching phantomjs' require()
14 var require = patchRequire(require);
15
16 // now you're ready to go
17 var utils = require('utils');
18 var magic = 42;
19 exports.answer = function() {
20 return utils.format("it's %d", magic);
21 };
22
23 .. warning::
24
25 When using CoffeeScript ``global.require`` must be passed to ``patchRequire()`` instead of just ``require``.
26
27 From your root casper script::
28
29 var universe = require('./universe');
30 console.log(universe.answer()); // prints "It's 42"