├── .gitmodules ├── tests ├── suites │ ├── .casper │ ├── casper │ │ ├── .casper │ │ ├── getplaintext.js │ │ ├── exists.js │ │ ├── prompt.js │ │ ├── debug.js │ │ ├── reload.js │ │ ├── start.js │ │ ├── callback.js │ │ ├── global.js │ │ ├── callutils.js │ │ ├── location.js │ │ ├── encode.js │ │ ├── onerror.js │ │ ├── history.js │ │ ├── visible.js │ │ ├── agent.js │ │ ├── newpage.js │ │ ├── auth.js │ │ ├── scroll.js │ │ ├── elementattribute.js │ │ ├── alert.js │ │ ├── flow.coffee │ │ ├── headers.js │ │ ├── scripts.js │ │ ├── xpath.js │ │ ├── content.js │ │ ├── resources.js │ │ ├── events.js │ │ ├── request.js │ │ ├── frames.js │ │ ├── confirm.js │ │ ├── capture.js │ │ ├── navigation.js │ │ ├── viewport.js │ │ ├── encodedurl.js │ │ ├── logging.js │ │ ├── fetchtext.js │ │ ├── urls.js │ │ ├── steps.js │ │ ├── mouseevents.js │ │ ├── hooks.js │ │ ├── keys.js │ │ └── bypass.js │ ├── tester │ │ ├── .casper │ │ ├── setup-teardown.js │ │ ├── skip.js │ │ ├── test-order.js │ │ ├── setup-teardown-async.js │ │ ├── begin-config.js │ │ ├── testsuite.js │ │ └── testcase.js │ ├── coffee.coffee │ ├── pagestack.js │ ├── fs.js │ ├── require.js │ └── http_status.js ├── testdir │ ├── 03_a.js │ ├── 03_b.js │ ├── 01_a │ │ ├── abc.js │ │ └── def.js │ ├── 02_b │ │ └── abc.js │ └── 04 │ │ ├── 01_init.js │ │ └── 02_do.js ├── site │ ├── dummy.json │ ├── dummy.txt │ ├── dummy.js │ ├── plaintext.notype │ ├── images │ │ └── phantom.png │ ├── page1.html │ ├── page2.html │ ├── page3.html │ ├── includes │ │ ├── include1.js │ │ └── include2.js │ ├── test.html │ ├── alert.html │ ├── frame1.html │ ├── error.html │ ├── has%20space.html │ ├── callback.html │ ├── elementattribute.html │ ├── field-file-multiple.html │ ├── frame3.html │ ├── confirm.html │ ├── result.html │ ├── frame2.html │ ├── prompt.html │ ├── frames.html │ ├── global.html │ ├── multiple-forms.html │ ├── resources.html │ ├── field-array.html │ ├── visible.html │ ├── urls.html │ ├── index.html │ ├── popup.html │ ├── waitFor.html │ ├── area.html │ ├── mouse-events.html │ └── click.html ├── sample_modules │ ├── config.json │ ├── csmodule.coffee │ └── jsmodule.js ├── clitests │ ├── modules │ │ ├── sub │ │ │ ├── mod.js │ │ │ └── coffeemod.coffee │ │ ├── node_modules │ │ │ ├── bar.js │ │ │ ├── json.json │ │ │ ├── baz │ │ │ │ ├── baz.js │ │ │ │ └── package.json │ │ │ └── foo │ │ │ │ └── index.js │ │ ├── test.js │ │ ├── test_node_mod.js │ │ ├── test_node_mod_index.js │ │ ├── test_node_json.js │ │ ├── test_node_mod_json_package.js │ │ ├── test_node_subdir │ │ │ └── test_node_mod.js │ │ ├── test_coffee.js │ │ ├── mod.js │ │ └── test_patched_require.js │ ├── error │ │ └── syntax.js │ ├── scripts │ │ ├── script.js │ │ └── options.js │ ├── fail-fast │ │ ├── standard │ │ │ ├── test1.js │ │ │ ├── test2.js │ │ │ ├── test3.js │ │ │ └── hook.js │ │ └── manual-abort │ │ │ └── index.js │ └── tester │ │ ├── failing.js │ │ ├── passing.js │ │ ├── dubious.js │ │ ├── skipped.js │ │ ├── exit.js │ │ ├── step_throws.js │ │ ├── casper-instance-override.js │ │ ├── mytest.js │ │ └── waitFor_timeout.js └── selftest.js ├── .gitattributes ├── docs ├── _themes │ └── casperjs │ │ ├── theme.conf │ │ ├── localtoc.html │ │ ├── layout.html │ │ ├── sourcelink.html │ │ └── addon.html ├── _static │ ├── images │ │ ├── .npmignore │ │ ├── bg.png │ │ ├── demo.png │ │ ├── tar.png │ │ ├── zip.png │ │ ├── forkme.png │ │ ├── colorizer.png │ │ ├── logoutput.png │ │ ├── cow-test-ko.png │ │ ├── cow-test-ok.png │ │ ├── logo_casperjs.ai │ │ ├── testsuiteok.png │ │ ├── casperjs-logo.png │ │ ├── logo_casperjs.eps │ │ ├── logo_casperjs.pdf │ │ ├── casperjs-rounded.png │ │ ├── evaluate-diagram.png │ │ ├── casperjs-logo-medium.png │ │ ├── casperjs-logo-small.png │ │ ├── casperjs-logo-xsmall.png │ │ ├── split-test-results.png │ │ ├── casperjs-logo-squared.png │ │ └── casperjs-logo-squared-inv.png │ └── casperjs-favicon.ico ├── upgrading │ └── index.rst ├── changelog.rst ├── Makefile ├── README.md ├── modules │ ├── index.rst │ └── colorizer.rst ├── license.rst ├── index.rst ├── known_issues.rst ├── credits.rst ├── logging.rst ├── writing_modules.rst └── selectors.rst ├── bin ├── casperjs.exe └── usage.txt ├── CHANGELOG.md ├── .gitignore ├── .eslintignore ├── samples ├── download.coffee ├── logcolor.coffee ├── each.coffee ├── customevents.coffee ├── download.js ├── logcolor.js ├── statushandlers.coffee ├── customevents.js ├── each.js ├── cliplay.coffee ├── statushandlers.js ├── metaextract.coffee ├── translate.coffee ├── extends.coffee ├── metaextract.js ├── cliplay.js ├── translate.js ├── timeout.coffee ├── screenshot.coffee ├── events.coffee ├── extends.js ├── googlelinks.coffee ├── multirun.coffee ├── steptimeout.coffee ├── customlogging.coffee ├── screenshot.js ├── googletesting.coffee ├── events.js ├── timeout.js ├── customlogging.js ├── googlepagination.coffee ├── googlelinks.js ├── steptimeout.js ├── googlematch.coffee ├── googletesting.js ├── multirun.js ├── dynamic.coffee ├── googlepagination.js ├── googlematch.js ├── dynamic.js ├── bbcshots.coffee └── bbcshots.js ├── Makefile ├── package.json ├── LICENSE.md ├── casperjs.gemspec ├── rpm ├── build └── casperjs.spec ├── CONTRIBUTORS.md └── modules └── http.js /.gitmodules: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/suites/.casper: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/testdir/03_a.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/testdir/03_b.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/suites/casper/.casper: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/suites/tester/.casper: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/testdir/01_a/abc.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/testdir/01_a/def.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/testdir/02_b/abc.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/testdir/04/01_init.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/testdir/04/02_do.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /tests/site/dummy.json: -------------------------------------------------------------------------------- 1 | {"dummy":"json"} 2 | -------------------------------------------------------------------------------- /tests/site/dummy.txt: -------------------------------------------------------------------------------- 1 | some dummy text 2 | -------------------------------------------------------------------------------- /tests/site/dummy.js: -------------------------------------------------------------------------------- 1 | document.write('foo'); 2 | -------------------------------------------------------------------------------- /tests/sample_modules/config.json: -------------------------------------------------------------------------------- 1 | {"ok": true} 2 | -------------------------------------------------------------------------------- /tests/sample_modules/csmodule.coffee: -------------------------------------------------------------------------------- 1 | exports.ok = true 2 | -------------------------------------------------------------------------------- /tests/sample_modules/jsmodule.js: -------------------------------------------------------------------------------- 1 | exports.ok = true; 2 | -------------------------------------------------------------------------------- /tests/clitests/modules/sub/mod.js: -------------------------------------------------------------------------------- 1 | exports.name = 'world'; 2 | -------------------------------------------------------------------------------- /docs/_themes/casperjs/theme.conf: -------------------------------------------------------------------------------- 1 | [theme] 2 | inherit = basic 3 | -------------------------------------------------------------------------------- /tests/clitests/modules/node_modules/bar.js: -------------------------------------------------------------------------------- 1 | module.exports = 42; 2 | -------------------------------------------------------------------------------- /tests/clitests/modules/node_modules/json.json: -------------------------------------------------------------------------------- 1 | {"universe": 42} 2 | -------------------------------------------------------------------------------- /tests/clitests/modules/sub/coffeemod.coffee: -------------------------------------------------------------------------------- 1 | module.exports = 42 2 | -------------------------------------------------------------------------------- /tests/site/plaintext.notype: -------------------------------------------------------------------------------- 1 | This is a plain and very simple sentence. -------------------------------------------------------------------------------- /tests/clitests/error/syntax.js: -------------------------------------------------------------------------------- 1 | qsfjdhf!èrè"èqwnfkmsghfkswjdgfjksn 2 | -------------------------------------------------------------------------------- /tests/clitests/modules/node_modules/baz/baz.js: -------------------------------------------------------------------------------- 1 | module.exports = 42; 2 | -------------------------------------------------------------------------------- /tests/clitests/modules/node_modules/foo/index.js: -------------------------------------------------------------------------------- 1 | module.exports = 42; 2 | -------------------------------------------------------------------------------- /docs/_static/images/.npmignore: -------------------------------------------------------------------------------- 1 | .npmignore 2 | *.ai 3 | *.pdf 4 | *.eps 5 | -------------------------------------------------------------------------------- /bin/casperjs.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tes/casperjs/master/bin/casperjs.exe -------------------------------------------------------------------------------- /tests/clitests/modules/node_modules/baz/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "baz.js" 3 | } 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | [This file has moved to Github](https://github.com/casperjs/casperjs/releases) 2 | -------------------------------------------------------------------------------- /docs/_static/images/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tes/casperjs/master/docs/_static/images/bg.png -------------------------------------------------------------------------------- /docs/_static/images/demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tes/casperjs/master/docs/_static/images/demo.png -------------------------------------------------------------------------------- /docs/_static/images/tar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tes/casperjs/master/docs/_static/images/tar.png -------------------------------------------------------------------------------- /docs/_static/images/zip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tes/casperjs/master/docs/_static/images/zip.png -------------------------------------------------------------------------------- /tests/site/images/phantom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tes/casperjs/master/tests/site/images/phantom.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /*.xml 3 | /*.png 4 | /docs/*.js 5 | /docs/*.xml 6 | /docs/_build 7 | /tmp 8 | *.pyc 9 | -------------------------------------------------------------------------------- /docs/_static/images/forkme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tes/casperjs/master/docs/_static/images/forkme.png -------------------------------------------------------------------------------- /docs/upgrading/index.rst: -------------------------------------------------------------------------------- 1 | Upgrading 2 | ========= 3 | 4 | .. toctree:: 5 | :maxdepth: 1 6 | 7 | 1.1 8 | -------------------------------------------------------------------------------- /docs/_static/casperjs-favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tes/casperjs/master/docs/_static/casperjs-favicon.ico -------------------------------------------------------------------------------- /docs/_static/images/colorizer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tes/casperjs/master/docs/_static/images/colorizer.png -------------------------------------------------------------------------------- /docs/_static/images/logoutput.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tes/casperjs/master/docs/_static/images/logoutput.png -------------------------------------------------------------------------------- /docs/_static/images/cow-test-ko.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tes/casperjs/master/docs/_static/images/cow-test-ko.png -------------------------------------------------------------------------------- /docs/_static/images/cow-test-ok.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tes/casperjs/master/docs/_static/images/cow-test-ok.png -------------------------------------------------------------------------------- /docs/_static/images/logo_casperjs.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tes/casperjs/master/docs/_static/images/logo_casperjs.ai -------------------------------------------------------------------------------- /docs/_static/images/testsuiteok.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tes/casperjs/master/docs/_static/images/testsuiteok.png -------------------------------------------------------------------------------- /docs/_static/images/casperjs-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tes/casperjs/master/docs/_static/images/casperjs-logo.png -------------------------------------------------------------------------------- /docs/_static/images/logo_casperjs.eps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tes/casperjs/master/docs/_static/images/logo_casperjs.eps -------------------------------------------------------------------------------- /docs/_static/images/logo_casperjs.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tes/casperjs/master/docs/_static/images/logo_casperjs.pdf -------------------------------------------------------------------------------- /tests/clitests/scripts/script.js: -------------------------------------------------------------------------------- 1 | var casper = require('casper').create(); 2 | casper.echo('it works'); 3 | casper.exit(); 4 | -------------------------------------------------------------------------------- /docs/_static/images/casperjs-rounded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tes/casperjs/master/docs/_static/images/casperjs-rounded.png -------------------------------------------------------------------------------- /docs/_static/images/evaluate-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tes/casperjs/master/docs/_static/images/evaluate-diagram.png -------------------------------------------------------------------------------- /docs/_static/images/casperjs-logo-medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tes/casperjs/master/docs/_static/images/casperjs-logo-medium.png -------------------------------------------------------------------------------- /docs/_static/images/casperjs-logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tes/casperjs/master/docs/_static/images/casperjs-logo-small.png -------------------------------------------------------------------------------- /docs/_static/images/casperjs-logo-xsmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tes/casperjs/master/docs/_static/images/casperjs-logo-xsmall.png -------------------------------------------------------------------------------- /docs/_static/images/split-test-results.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tes/casperjs/master/docs/_static/images/split-test-results.png -------------------------------------------------------------------------------- /docs/_static/images/casperjs-logo-squared.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tes/casperjs/master/docs/_static/images/casperjs-logo-squared.png -------------------------------------------------------------------------------- /docs/_static/images/casperjs-logo-squared-inv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tes/casperjs/master/docs/_static/images/casperjs-logo-squared-inv.png -------------------------------------------------------------------------------- /tests/clitests/fail-fast/standard/test1.js: -------------------------------------------------------------------------------- 1 | casper.test.begin('test 1', 1, function(test) { 2 | test.assert(true); 3 | test.done(); 4 | }); 5 | -------------------------------------------------------------------------------- /tests/clitests/fail-fast/standard/test2.js: -------------------------------------------------------------------------------- 1 | casper.test.begin('test 2', 1, function(test) { 2 | test.assert(false); 3 | test.done(); 4 | }); 5 | -------------------------------------------------------------------------------- /tests/clitests/fail-fast/standard/test3.js: -------------------------------------------------------------------------------- 1 | casper.test.begin('test 3', 1, function(test) { 2 | test.assert(true); 3 | test.done(); 4 | }); 5 | -------------------------------------------------------------------------------- /tests/clitests/modules/test.js: -------------------------------------------------------------------------------- 1 | var casper = require('casper').create(); 2 | var mod = require('./mod'); 3 | console.log(mod.hello); 4 | casper.exit(); 5 | -------------------------------------------------------------------------------- /tests/clitests/modules/test_node_mod.js: -------------------------------------------------------------------------------- 1 | var casper = require('casper').create(); 2 | var foo = require('foo'); 3 | console.log(foo); 4 | casper.exit(); 5 | -------------------------------------------------------------------------------- /tests/clitests/modules/test_node_mod_index.js: -------------------------------------------------------------------------------- 1 | var casper = require('casper').create(); 2 | var bar = require('bar'); 3 | console.log(bar); 4 | casper.exit(); 5 | -------------------------------------------------------------------------------- /tests/clitests/tester/failing.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | casper.test.begin('true', 1, function(test) { 3 | test.assert(false); 4 | test.done(); 5 | }); 6 | -------------------------------------------------------------------------------- /tests/clitests/tester/passing.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | casper.test.begin('true', 1, function(test) { 3 | test.assert(true); 4 | test.done(); 5 | }); 6 | -------------------------------------------------------------------------------- /tests/clitests/modules/test_node_json.js: -------------------------------------------------------------------------------- 1 | var casper = require('casper').create(); 2 | var json = require('json'); 3 | console.log(json.universe); 4 | casper.exit(); 5 | -------------------------------------------------------------------------------- /tests/clitests/modules/test_node_mod_json_package.js: -------------------------------------------------------------------------------- 1 | var casper = require('casper').create(); 2 | var baz = require('baz'); 3 | console.log(baz); 4 | casper.exit(); 5 | -------------------------------------------------------------------------------- /tests/clitests/modules/test_node_subdir/test_node_mod.js: -------------------------------------------------------------------------------- 1 | var casper = require('casper').create(); 2 | var foo = require('foo'); 3 | console.log(foo); 4 | casper.exit(); 5 | -------------------------------------------------------------------------------- /tests/clitests/tester/dubious.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | casper.test.begin('dubious test', 2, function(test) { 3 | test.assert(true); 4 | test.done(); 5 | }); 6 | -------------------------------------------------------------------------------- /docs/_themes/casperjs/localtoc.html: -------------------------------------------------------------------------------- 1 | {%- if display_toc %} 2 |

{{ _('Document Outline') }}

3 | {{ toc }} 4 | {%- endif %} 5 | -------------------------------------------------------------------------------- /tests/clitests/modules/test_coffee.js: -------------------------------------------------------------------------------- 1 | var casper = require('casper').create(); 2 | var coffeemod = require('./sub/coffeemod'); 3 | console.log(coffeemod); 4 | casper.exit(); 5 | -------------------------------------------------------------------------------- /docs/changelog.rst: -------------------------------------------------------------------------------- 1 | Changelog 2 | ========= 3 | 4 | The CasperJS changelog is `hosted on github `_. 5 | -------------------------------------------------------------------------------- /tests/clitests/tester/skipped.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | casper.test.begin('skipped test', 2, function(test) { 3 | test.skip(1); 4 | test.assert(true); 5 | test.done(); 6 | }); 7 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 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 | 14 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | CasperJS Sphinx Documentation 2 | ============================= 3 | 4 | Sphinx documentation for [CasperJS](http://casperjs.org/) 1.1-DEV and future 5 | versions. Work in progress. 6 | -------------------------------------------------------------------------------- /tests/clitests/modules/mod.js: -------------------------------------------------------------------------------- 1 | /*global patchRequire*/ 2 | var require = patchRequire(require); 3 | var utils = require('utils'); 4 | exports.hello = utils.format('hello, %s', require('./sub/mod').name); 5 | -------------------------------------------------------------------------------- /tests/clitests/scripts/options.js: -------------------------------------------------------------------------------- 1 | var require = patchRequire(require); 2 | var casper = require('casper').create(); 3 | var utils = require('utils'); 4 | utils.dump(casper.cli.options); 5 | casper.exit(); 6 | -------------------------------------------------------------------------------- /tests/clitests/modules/test_patched_require.js: -------------------------------------------------------------------------------- 1 | var require = patchRequire(require); 2 | var casper = require('casper').create(); 3 | var mod = require('./mod'); 4 | console.log(mod.hello); 5 | casper.exit(); 6 | -------------------------------------------------------------------------------- /tests/clitests/tester/exit.js: -------------------------------------------------------------------------------- 1 | casper.test.on("exit", function() { 2 | console.log("exited"); 3 | }) 4 | 5 | casper.test.begin("sample", function(test) { 6 | test.assert(true); 7 | test.done(); 8 | }); 9 | -------------------------------------------------------------------------------- /tests/site/page1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CasperJS test page 1 6 | 7 | Booh. 8 | -------------------------------------------------------------------------------- /tests/site/page2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CasperJS test page 2 6 | 7 | Booh. 8 | -------------------------------------------------------------------------------- /tests/site/page3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CasperJS test page 1 6 | 7 | Booh. 8 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | docs 2 | modules/vendors 3 | modules/events.js 4 | modules/querystring.js 5 | samples/** 6 | tests/** 7 | tests/clitests/** 8 | tests/testdir/** 9 | tests/suites/** 10 | tests/site/** 11 | tmp 12 | ./*.js 13 | ./phantomjs*/* 14 | ./engine/* 15 | -------------------------------------------------------------------------------- /tests/clitests/fail-fast/standard/hook.js: -------------------------------------------------------------------------------- 1 | /* global casper */ 2 | 3 | casper.test.on('fail', function doSomething() { 4 | 'use strict'; 5 | casper.echo('fail event fired!'); 6 | }); 7 | casper.test.begin('hook', 0, function(t) { 8 | 'use strict'; 9 | t.done(); 10 | }); 11 | -------------------------------------------------------------------------------- /tests/site/includes/include1.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | "use strict"; 3 | var elem = document.createElement('div'); 4 | elem.setAttribute('id', 'include1'); 5 | elem.appendChild(document.createTextNode('include1')); 6 | document.querySelector('body').appendChild(elem); 7 | })(); 8 | -------------------------------------------------------------------------------- /tests/site/includes/include2.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | "use strict"; 3 | var elem = document.createElement('div'); 4 | elem.setAttribute('id', 'include2'); 5 | elem.appendChild(document.createTextNode('include2')); 6 | document.querySelector('body').appendChild(elem); 7 | })(); 8 | -------------------------------------------------------------------------------- /tests/site/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CasperJS test target 6 | 7 | 8 | test form 9 | 10 | -------------------------------------------------------------------------------- /samples/download.coffee: -------------------------------------------------------------------------------- 1 | ### 2 | Download the google logo image onto the local filesystem 3 | ### 4 | 5 | casper = require("casper").create() 6 | 7 | casper.start "http://www.google.fr/", -> 8 | @echo @download "http://www.google.fr/images/srpr/logo3w.png", "logo.png" 9 | 10 | casper.run() 11 | -------------------------------------------------------------------------------- /tests/clitests/tester/step_throws.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | casper.test.begin('step throws', 1, function(test) { 3 | casper.start(); 4 | casper.then(function() { 5 | throw new Error('oops!') 6 | }); 7 | casper.run(function() { 8 | test.done(); 9 | }) 10 | }); 11 | -------------------------------------------------------------------------------- /tests/site/alert.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CasperJS test alert 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /tests/site/frame1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CasperJS frame 1 6 | 7 | 8 |

This is frame 1.

9 | 10 | 11 | -------------------------------------------------------------------------------- /samples/logcolor.coffee: -------------------------------------------------------------------------------- 1 | casper = require("casper").create 2 | verbose: true 3 | logLevel: "debug" 4 | 5 | casper.log "this is a debug message", "debug" 6 | casper.log "and an informative one", "info" 7 | casper.log "and a warning", "warning" 8 | casper.log "and an error", "error" 9 | 10 | casper.exit() 11 | -------------------------------------------------------------------------------- /samples/each.coffee: -------------------------------------------------------------------------------- 1 | casper = require("casper").create() 2 | 3 | links = [ 4 | "http://google.com/" 5 | "http://yahoo.com/" 6 | "http://bing.com/" 7 | ] 8 | 9 | casper.start() 10 | 11 | casper.each links, (self, link) -> 12 | @thenOpen link, -> @echo "#{@getTitle()} - #{link}" 13 | 14 | casper.run() 15 | -------------------------------------------------------------------------------- /tests/site/error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CasperJS error test 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /tests/site/has%20space.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CasperJS test url with encoded space 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /tests/site/callback.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CasperJS test callback 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /tests/clitests/tester/casper-instance-override.js: -------------------------------------------------------------------------------- 1 | // this should never happen 2 | // http://docs.casperjs.org/en/latest/testing.html#test-command-args-and-options 3 | var casper = require("casper").create(); 4 | 5 | casper.test.begin("foo", function(test) { 6 | "use strict"; 7 | test.assert(true); 8 | test.done(); 9 | }); 10 | -------------------------------------------------------------------------------- /tests/site/elementattribute.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 |
6 |
7 | 8 | -------------------------------------------------------------------------------- /samples/customevents.coffee: -------------------------------------------------------------------------------- 1 | casper = require("casper").create() 2 | 3 | # listening to a custom event 4 | casper.on "google.loaded", (title) -> 5 | @echo "Google page title is #{title}" 6 | 7 | casper.start "http://google.com/", -> 8 | # emitting a custom event 9 | @emit "google.loaded", @getTitle() 10 | 11 | casper.run() 12 | -------------------------------------------------------------------------------- /tests/site/field-file-multiple.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Form field file multiple test 5 | 6 | 7 |
8 | 9 |
10 | 11 | -------------------------------------------------------------------------------- /tests/site/frame3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CasperJS frame 3 6 | 7 | 8 |

This is frame 3.

9 |

frame 2

10 | 11 | 12 | -------------------------------------------------------------------------------- /tests/site/confirm.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CasperJS test confirm 6 | 7 | 8 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tests/site/result.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CasperJS test form result 6 | 7 | 8 |

this is the result page

9 |

Return back home

10 | 11 | -------------------------------------------------------------------------------- /tests/clitests/tester/mytest.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | /*global CasperError casper console phantom require*/ 3 | casper.start('about:blank', function() { 4 | this.test.pass('ok1'); 5 | }); 6 | 7 | casper.then(function() { 8 | this.test.pass('ok2'); 9 | }); 10 | 11 | casper.run(function() { 12 | this.test.pass('ok3'); 13 | this.test.done(); 14 | }); 15 | -------------------------------------------------------------------------------- /tests/site/frame2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CasperJS frame 2 6 | 7 | 8 |

This is frame 2.

9 |

frame 3

10 | 11 | 12 | -------------------------------------------------------------------------------- /tests/site/prompt.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CasperJS test prompt 6 | 7 | 8 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/modules/index.rst: -------------------------------------------------------------------------------- 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 `_. 10 | 11 | .. toctree:: 12 | :glob: 13 | 14 | * 15 | -------------------------------------------------------------------------------- /tests/site/frames.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CasperJS test frames 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tests/site/global.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /samples/download.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | /*global CasperError, console, phantom, require*/ 3 | 4 | /** 5 | * download the google logo image onto the local filesystem 6 | */ 7 | 8 | var casper = require("casper").create(); 9 | 10 | casper.start("http://www.google.fr/", function() { 11 | this.download("http://www.google.fr/images/srpr/logo3w.png", "logo.png"); 12 | }); 13 | 14 | casper.run(); 15 | -------------------------------------------------------------------------------- /samples/logcolor.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | /*global CasperError, console, phantom, require*/ 3 | 4 | var casper = require("casper").create({ 5 | verbose: true, 6 | logLevel: "debug" 7 | }); 8 | 9 | casper.log("this is a debug message", "debug"); 10 | casper.log("and an informative one", "info"); 11 | casper.log("and a warning", "warning"); 12 | casper.log("and an error", "error"); 13 | 14 | casper.exit(); 15 | -------------------------------------------------------------------------------- /tests/site/multiple-forms.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Multiple forms test 5 | 6 | 7 |
8 | 9 | 10 |
11 |
12 | 13 | 14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /tests/suites/casper/getplaintext.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | casper.test.begin('getPlainText() tests', 1, function(test) { 3 | casper.start('tests/site/plaintext.notype', function() { 4 | test.assertEquals(this.getPlainText(), 'This is a plain and very simple sentence.', 5 | 'Casper.getPlainText() can retrieve plain text with no content type'); 6 | }).run(function() { 7 | test.done(); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /samples/statushandlers.coffee: -------------------------------------------------------------------------------- 1 | ### 2 | This script will add a custom HTTP status code handler, here for 404 pages. 3 | ### 4 | 5 | casper = require("casper").create 6 | httpStatusHandlers: 7 | 404: (self, resource) -> 8 | @echo "Resource at #{resource.url} not found (404)", "COMMENT" 9 | verbose: true 10 | 11 | casper.start "http://www.google.com/plop", -> 12 | @echo "Done." 13 | @exit() 14 | 15 | casper.run() 16 | -------------------------------------------------------------------------------- /tests/suites/casper/exists.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | casper.test.begin('exists() tests', 2, function(test) { 3 | casper.start('tests/site/index.html', function() { 4 | test.assert(this.exists('a'), 'Casper.exists() can check if an element exists'); 5 | test.assertNot(this.exists('chucknorriz'), 'Casper.exists() can check than an element does not exist'); 6 | }).run(function() { 7 | test.done(); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /tests/suites/casper/prompt.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | casper.test.begin('prompt tests', 1, function(test) { 3 | casper.setFilter('page.prompt', function(message, value) { 4 | return 'Chuck ' + value; 5 | }); 6 | casper.start('tests/site/prompt.html', function() { 7 | test.assertEquals(this.getGlobal('username'), 'Chuck Norris', 'prompted value has been received'); 8 | }).run(function() { 9 | test.done(); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /samples/customevents.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | /*global CasperError, console, phantom, require*/ 3 | 4 | var casper = require("casper").create(); 5 | 6 | // listening to a custom event 7 | casper.on("google.loaded", function(title) { 8 | this.echo("Google page title is " + title); 9 | }); 10 | 11 | casper.start("http://google.com/", function() { 12 | // emitting a custom event 13 | this.emit("google.loaded", this.getTitle()); 14 | }); 15 | 16 | casper.run(); 17 | -------------------------------------------------------------------------------- /samples/each.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | /*global CasperError, console, phantom, require*/ 3 | 4 | var casper = require("casper").create(); 5 | 6 | var links = [ 7 | "http://google.com/", 8 | "http://yahoo.com/", 9 | "http://bing.com/" 10 | ]; 11 | 12 | casper.start(); 13 | 14 | casper.each(links, function(self, link) { 15 | this.thenOpen(link, function() { 16 | this.echo(this.getTitle() + " - " + link); 17 | }); 18 | }); 19 | 20 | casper.run(); 21 | -------------------------------------------------------------------------------- /tests/site/resources.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CasperJS test resource 6 | 7 | 8 | 9 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /tests/suites/casper/debug.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | casper.test.begin('getHTML() tests', 2, function(test) { 3 | casper.start('tests/site/index.html', function() { 4 | test.assertEquals(this.getHTML('ul li'), 'one', 5 | 'Casper.getHTML() retrieves inner HTML by default'); 6 | test.assertEquals(this.getHTML('ul li', true), '
  • one
  • ', 7 | 'Casper.getHTML() can retrieve outer HTML'); 8 | }).run(function() { 9 | test.done(); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /tests/clitests/fail-fast/manual-abort/index.js: -------------------------------------------------------------------------------- 1 | casper.test.begin('test abort()', 10, function(test) { 2 | "use strict"; 3 | for (var i = 0; i < 10; i++) { 4 | test.assert(true, 'test ' + (i + 1)); 5 | if (i === 4) { 6 | test.abort('this is my abort message'); 7 | } 8 | } 9 | test.done(); 10 | }); 11 | 12 | casper.test.begin('should not being executed', 1, function(test) { 13 | "use strict"; 14 | test.fail('damn.'); 15 | test.done(); 16 | }); 17 | -------------------------------------------------------------------------------- /tests/site/field-array.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CasperJS test form 6 | 7 | 8 |
    9 | 10 | 11 | 12 |
    13 | 14 | 15 | -------------------------------------------------------------------------------- /bin/usage.txt: -------------------------------------------------------------------------------- 1 | Usage: casperjs [options] script.[js|coffee] [script argument [script argument ...]] 2 | casperjs [options] test [test path [test path ...]] 3 | casperjs [options] selftest 4 | 5 | Options: 6 | 7 | --verbose Prints log messages to the console 8 | --log-level Sets logging level 9 | --help Prints this help 10 | --version Prints out CasperJS version 11 | --engine=name Use the given engine. Current supported engine: phantomjs and slimerjs 12 | 13 | Read the docs http://docs.casperjs.org/ 14 | -------------------------------------------------------------------------------- /docs/_themes/casperjs/layout.html: -------------------------------------------------------------------------------- 1 | {%- extends "basic/layout.html" %} 2 | {% block extrahead %} 3 | 4 | 5 | 6 | 7 | {% endblock extrahead %} 8 | -------------------------------------------------------------------------------- /samples/cliplay.coffee: -------------------------------------------------------------------------------- 1 | casper = require("casper").create() 2 | dump = require("utils").dump 3 | 4 | # removing default options passed by the Python executable 5 | casper.cli.drop "cli" 6 | casper.cli.drop "casper-path" 7 | 8 | if casper.cli.args.length is 0 and Object.keys(casper.cli.options).length is 0 9 | casper 10 | .echo("Pass some args and options to see how they are handled by CasperJS") 11 | .exit(1) 12 | 13 | casper.echo "Casper CLI passed args:" 14 | dump casper.cli.args 15 | 16 | casper.echo "Casper CLI passed options:" 17 | dump casper.cli.options 18 | 19 | casper.exit() 20 | -------------------------------------------------------------------------------- /samples/statushandlers.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | /*global CasperError, console, phantom, require*/ 3 | 4 | /** 5 | * This script will add a custom HTTP status code handler, here for 404 pages. 6 | */ 7 | 8 | var casper = require("casper").create({ 9 | httpStatusHandlers: { 10 | 404: function(self, resource) { 11 | this.echo("Resource at " + resource.url + " not found (404)", "COMMENT"); 12 | } 13 | }, 14 | verbose: true 15 | }); 16 | 17 | casper.start("http://www.google.com/plop", function() { 18 | this.echo("Done."); 19 | this.exit(); 20 | }); 21 | 22 | casper.run(); 23 | -------------------------------------------------------------------------------- /tests/suites/casper/reload.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0, max-statements:0*/ 2 | 3 | casper.test.begin('reload() tests', 3, function(test) { 4 | var formUrl = 'tests/site/form.html'; 5 | 6 | casper.start(formUrl, function() { 7 | this.fill("form", {email: "foo@foo.com"}, false); 8 | }); 9 | casper.once("page.resource.requested", function(resource) { 10 | test.assert(resource.url.indexOf(formUrl) > 0); 11 | }).reload(function() { 12 | test.assertUrlMatches(formUrl); 13 | test.assertField("email", ""); 14 | }).run(function() { 15 | test.done(); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /tests/site/visible.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CasperJS test index 6 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /tests/site/urls.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CasperJS url tests 6 | 7 | 8 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /tests/suites/casper/start.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | casper.test.begin('start() tests', 4, function(test) { 3 | casper.start('tests/site/index.html', function() { 4 | test.pass('Casper.start() can chain a next step'); 5 | test.assertTitle('CasperJS test index', 'Casper.start() opened the passed url'); 6 | test.assertEval(function() { 7 | return typeof(__utils__) === "object"; 8 | }, 'Casper.start() injects ClientUtils instance within remote DOM'); 9 | }); 10 | 11 | test.assert(casper.started, 'Casper.start() started'); 12 | 13 | casper.run(function() { 14 | test.done(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /tests/suites/tester/setup-teardown.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | 3 | var setUp, tearDown; 4 | 5 | casper.test.setUp(function() { 6 | setUp = true; 7 | }); 8 | 9 | casper.test.tearDown(function() { 10 | tearDown = true; 11 | // reset 12 | casper.test.setUp(); 13 | casper.test.tearDown(); 14 | }); 15 | 16 | casper.test.begin('setUp() tests', 1, function(test) { 17 | test.assertTrue(setUp, 'Tester.setUp() executed the setup function'); 18 | test.done(); 19 | }); 20 | 21 | casper.test.begin('tearDown() tests', 1, function(test) { 22 | test.assertTrue(tearDown, 'Tester.tearDown() executed the tear down function'); 23 | test.done(); 24 | }); 25 | -------------------------------------------------------------------------------- /samples/metaextract.coffee: -------------------------------------------------------------------------------- 1 | casper = require("casper").create() 2 | url = casper.cli.get 0 3 | metas = [] 4 | 5 | if not url 6 | casper 7 | .echo("Usage: $ casperjs metaextract.coffee ") 8 | .exit 1 9 | 10 | casper.start url, -> 11 | metas = @evaluate -> 12 | metas = [] 13 | castarray = (arr) -> [].slice.call(arr) 14 | for elem in castarray document.querySelectorAll "meta" 15 | meta = {} 16 | for attr in castarray elem.attributes 17 | meta[attr.name] = attr.value 18 | metas.push meta 19 | metas 20 | 21 | casper.run -> 22 | require("utils").dump metas 23 | this.exit() 24 | -------------------------------------------------------------------------------- /tests/suites/casper/callback.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | casper.test.begin('callback events', 1, { 3 | ok: false, 4 | 5 | tearDown: function(test) { 6 | casper.removeAllListeners('remote.callback'); 7 | }, 8 | 9 | test: function(test) { 10 | var self = this; 11 | 12 | casper.once('remote.callback', function(data) { 13 | self.ok = (data.hello === 'world'); 14 | }); 15 | 16 | casper.start('tests/site/callback.html', function() { 17 | test.assert(self.ok, 'callback event has been intercepted'); 18 | }); 19 | 20 | casper.run(function() { 21 | test.done(); 22 | }); 23 | } 24 | }); 25 | -------------------------------------------------------------------------------- /tests/suites/casper/global.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | casper.test.begin('getGLobal() tests', 3, function(test) { 3 | casper.start('tests/site/global.html', function() { 4 | test.assertEquals(this.getGlobal('myGlobal'), 'awesome string', 5 | 'Casper.getGlobal() can retrieve a remote global variable'); 6 | test.assertEquals(this.getGlobal('myObject').foo.bar, 'baz', 7 | 'Casper.getGlobal() can retrieves a serializable object'); 8 | test.assertRaises(this.getGlobal, ['myUnencodableGlobal'], 9 | 'Casper.getGlobal() does not fail trying to encode an unserializable global'); 10 | }).run(function() { 11 | test.done(); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /tests/site/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CasperJS test index 6 | 7 | 8 | 9 | test 10 | form 11 |
      12 |
    • one
    • 13 |
    • two
    • 14 |
    • three
    • 15 |
    16 | 17 |

    Title

    18 | 19 |
    Exports
    20 | 21 | 22 | -------------------------------------------------------------------------------- /tests/site/popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CasperJS test popup 6 | 7 | 8 | new window 9 | close 10 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: default test test-dotNET docs selftest compile-dotNET selftest-dotNET clitest clitest-dotNET lint 2 | 3 | default: test 4 | 5 | test: selftest clitest lint 6 | 7 | test-dotNET: compile-dotNET selftest-dotNET clitest-dotNET lint 8 | 9 | docs: 10 | sphinx-build -b html ./docs docs/_build 11 | 12 | selftest: 13 | bin/casperjs --help 14 | bin/casperjs selftest 15 | 16 | compile-dotNET: 17 | mcs -langversion:3 -out:bin/casperjs.exe src/casperjs.cs 18 | 19 | selftest-dotNET: 20 | mono bin/casperjs.exe --help 21 | mono bin/casperjs.exe selftest 22 | 23 | clitest: 24 | python tests/clitests/runtests.py 25 | 26 | clitest-dotNET: 27 | python tests/clitests/runtests.py casperjs.exe 28 | 29 | lint: 30 | eslint . 31 | -------------------------------------------------------------------------------- /samples/translate.coffee: -------------------------------------------------------------------------------- 1 | ### 2 | Translation using the Google Translate Service. 3 | 4 | Usage: 5 | 6 | $ casperjs translate.coffee --target=fr "hello world" 7 | bonjour tout le monde 8 | ### 9 | system = require("system") 10 | casper = require("casper").create() 11 | format = require("utils").format 12 | source = casper.cli.get("source") or "auto" 13 | target = casper.cli.get("target") 14 | text = casper.cli.get(0) 15 | result = undefined 16 | 17 | casper.warn("The --target option is mandatory.").exit 1 unless target 18 | 19 | casper.start(format("http://translate.google.com/#%s/%s/%s", source, target, text), -> 20 | @fill "form#gt-form", text: text 21 | ).waitForSelector "span.hps", -> @echo @fetchText("#result_box") 22 | 23 | casper.run() 24 | -------------------------------------------------------------------------------- /samples/extends.coffee: -------------------------------------------------------------------------------- 1 | casper = require("casper").create 2 | loadImages: false 3 | logLevel: "debug" 4 | verbose: true 5 | 6 | links = 7 | "http://edition.cnn.com/": 0 8 | "http://www.nytimes.com/": 0 9 | "http://www.bbc.co.uk/": 0 10 | "http://www.guardian.co.uk/": 0 11 | 12 | fantomas = Object.create(casper) 13 | 14 | fantomas.countLinks = -> 15 | @evaluate -> 16 | __utils__.findAll("a[href]").length 17 | 18 | fantomas.renderJSON = (what) -> 19 | @echo JSON.stringify(what, null, " ") 20 | 21 | fantomas.start() 22 | 23 | Object.keys(links).forEach (url) -> 24 | fantomas.thenOpen url, -> 25 | links[url] = @countLinks() 26 | 27 | fantomas.run -> 28 | @renderJSON(links) 29 | @exit() 30 | -------------------------------------------------------------------------------- /tests/suites/tester/skip.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | casper.test.begin('Skip tests after', 4, function(test) { 3 | test.assert(true, 'First test executed'); 4 | test.assert(true, 'Second test executed'); 5 | test.skip(2, 'Two tests skipped'); 6 | test.done(); 7 | }); 8 | 9 | casper.test.begin('Skip tests before', 4, function(test) { 10 | test.skip(2, 'Two tests skipped'); 11 | test.assert(true, 'Third test executed'); 12 | test.assert(true, 'Fourth test executed'); 13 | test.done(); 14 | }); 15 | 16 | casper.test.begin('Skip tests (asynchronous)', 1, function(test) { 17 | casper.start('tests/site/index.html', function() { 18 | test.skip(1); 19 | }).run(function() { 20 | test.done(); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /docs/_themes/casperjs/sourcelink.html: -------------------------------------------------------------------------------- 1 |

    Index

    2 |

    Thesaurus

    3 | 4 | {%- if show_source and has_source and sourcename %} 5 |

    {{ _('This Page') }}

    6 | 16 | {%- endif %} 17 | -------------------------------------------------------------------------------- /tests/suites/tester/test-order.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | /*global CasperError, casper, console, phantom, require*/ 3 | var fs = require('fs'); 4 | 5 | casper.test.begin('Tester.sortFiles()', 1, function suite(test) { 6 | var testDirRoot = fs.pathJoin(phantom.casperPath, 'tests', 'testdir'); 7 | var files = test.findTestFiles(testDirRoot); 8 | var expected = [ 9 | "01_a/abc.js", 10 | "01_a/def.js", 11 | "02_b/abc.js", 12 | "03_a.js", 13 | "03_b.js", 14 | "04/01_init.js", 15 | "04/02_do.js" 16 | ].map(function(entry) { 17 | return fs.pathJoin.apply(fs, [testDirRoot].concat(entry.split('/'))); 18 | }); 19 | test.assertEquals(files, expected, 'findTestFiles() find test files and sort them'); 20 | test.done(); 21 | }); 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "casperjs", 3 | "description": "A navigation scripting & testing utility for PhantomJS and SlimerJS", 4 | "version": "1.1.3", 5 | "keywords": [ 6 | "phantomjs", 7 | "slimerjs", 8 | "test", 9 | "testing", 10 | "scraping" 11 | ], 12 | "bin": "./bin/casperjs", 13 | "author": { 14 | "name": "CasperJS Organization", 15 | "web": "https://casperjs.org/" 16 | }, 17 | "bugs": { 18 | "url": "https://github.com/casperjs/casperjs/issues" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "git://github.com/casperjs/casperjs.git" 23 | }, 24 | "licenses": [ 25 | { 26 | "type": "MIT", 27 | "url": "http://www.opensource.org/licenses/mit-license.php" 28 | } 29 | ], 30 | "homepage": "http://casperjs.org" 31 | } 32 | -------------------------------------------------------------------------------- /tests/suites/tester/setup-teardown-async.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | 3 | var setUp, tearDown; 4 | 5 | casper.test.setUp(function(done) { 6 | setTimeout(function() { 7 | setUp = true; 8 | done(); 9 | }, 50); 10 | }); 11 | 12 | casper.test.tearDown(function(done) { 13 | setTimeout(function() { 14 | tearDown = true; 15 | done(); 16 | // reset 17 | casper.test.setUp(); 18 | casper.test.tearDown(); 19 | }, 50); 20 | }); 21 | 22 | casper.test.begin('setUp() tests', 1, function(test) { 23 | test.assertTrue(setUp, 'Tester.setUp() executed the async setup function'); 24 | test.done(); 25 | }); 26 | 27 | casper.test.begin('tearDown() tests', 1, function(test) { 28 | test.assertTrue(tearDown, 'Tester.tearDown() executed the async tear down function'); 29 | test.done(); 30 | }); 31 | -------------------------------------------------------------------------------- /tests/suites/casper/callutils.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | casper.test.begin('Casper.callUtils()', 2, function(test) { 3 | casper.start("tests/site/index.html", function(){ 4 | this.evaluate(function() { 5 | /*global __utils__*/ 6 | __utils__.testCallUtils = function() { 7 | return [].slice.call(arguments); 8 | }; 9 | }); 10 | 11 | test.assertEquals(casper.callUtils("testCallUtils", "a", "b", "c"), 12 | ["a", "b", "c"], 13 | "Casper.callUtils() invokes a client side utility"); 14 | 15 | test.assertThrows(casper.callUtils, ["xxx", "a", "b", "c"], 16 | "Casper.callUtils() raises an error if used inappropriately"); 17 | }); 18 | 19 | casper.run(function() { 20 | test.done(); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /tests/suites/coffee.coffee: -------------------------------------------------------------------------------- 1 | "A small subset of the run.js written in coffeescript" 2 | 3 | steps = 0 4 | 5 | casper.options.onStepComplete = -> steps++ 6 | 7 | casper.test.begin "writing async tests in coffeescript", 4, (test) -> 8 | casper.start "tests/site/index.html", -> 9 | test.assertTitle "CasperJS test index", "Casper.start() casper can start itself an open an url" 10 | test.assertEquals @fetchText("ul li"), "onetwothree", "Casper.fetchText() can retrieves text contents" 11 | @click "a[href=\"test.html\"]" 12 | 13 | casper.then -> 14 | test.assertTitle "CasperJS test target", "Casper.click() casper can click on a text link" 15 | @click "a[href=\"form.html\"]" 16 | 17 | casper.run -> 18 | test.assertEquals steps, 3, "Casper.options.onStepComplete() is called on step complete" 19 | @options.onStepComplete = null 20 | @test.done() 21 | -------------------------------------------------------------------------------- /samples/metaextract.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | /*global CasperError, console, phantom, require*/ 3 | 4 | var casper = require("casper").create(); 5 | var url = casper.cli.get(0); 6 | var metas = []; 7 | 8 | if (!url) { 9 | casper 10 | .echo("Usage: $ casperjs metaextract.js ") 11 | .exit(1) 12 | ; 13 | } 14 | 15 | casper.start(url, function() { 16 | metas = this.evaluate(function() { 17 | var metas = []; 18 | [].forEach.call(document.querySelectorAll("meta"), function(elem) { 19 | var meta = {}; 20 | [].slice.call(elem.attributes).forEach(function(attr) { 21 | meta[attr.name] = attr.value; 22 | }); 23 | metas.push(meta); 24 | }); 25 | return metas; 26 | }); 27 | }); 28 | 29 | casper.run(function() { 30 | require("utils").dump(metas); 31 | this.exit(); 32 | }); 33 | -------------------------------------------------------------------------------- /tests/suites/casper/location.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | /*global CasperError, casper, console, phantom, require*/ 3 | var utils = require('utils'); 4 | 5 | if (utils.ltVersion(phantom.version, '1.8.0')) { 6 | // https://github.com/casperjs/casperjs/issues/101 7 | casper.warn('document.location is broken under phantomjs < 1.8'); 8 | casper.test.done(); 9 | } else { 10 | casper.test.begin('document.location tests', 1, function(test) { 11 | casper.start('tests/site/index.html', function() { 12 | this.evaluate(function() { 13 | document.location = '/tests/site/form.html'; 14 | }); 15 | }); 16 | casper.then(function() { 17 | test.assertUrlMatches(/form\.html$/, 'document.location works as expected'); 18 | }); 19 | casper.run(function() { 20 | test.done(); 21 | }); 22 | }); 23 | } 24 | -------------------------------------------------------------------------------- /samples/cliplay.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | /*global CasperError, console, phantom, require*/ 3 | 4 | var casper = require("casper").create(); 5 | var dump = require("utils").dump; 6 | 7 | // removing default options passed by the Python executable 8 | casper.cli.drop("cli"); 9 | casper.cli.drop("casper-path"); 10 | 11 | if (casper.cli.args.length === 0 && Object.keys(casper.cli.options).length === 0) { 12 | casper 13 | .echo("Pass some args and options to see how they are handled by CasperJS") 14 | .exit(1) 15 | ; 16 | } 17 | 18 | casper.echo("Casper CLI passed args:"); 19 | dump(casper.cli.args); 20 | 21 | casper.echo("Casper CLI passed options:"); 22 | dump(casper.cli.options); 23 | 24 | casper.echo("Casper CLI passed RAW args:"); 25 | dump(casper.cli.raw.args); 26 | 27 | casper.echo("Casper CLI passed RAW options:"); 28 | dump(casper.cli.raw.options); 29 | 30 | casper.exit(); 31 | -------------------------------------------------------------------------------- /tests/suites/casper/encode.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | var fs = require('fs'); 3 | 4 | casper.test.begin('base64encode() and download() tests', 2, function(test) { 5 | // FIXME: https://github.com/ariya/phantomjs/pull/364 has been merged, update scheme 6 | casper.start('file://' + phantom.casperPath + '/tests/site/index.html', function() { 7 | var imageUrl = 'file://' + phantom.casperPath + '/tests/site/images/phantom.png', 8 | image = this.base64encode(imageUrl); 9 | test.assertEquals(image.length, 6160, 'Casper.base64encode() can retrieve base64 contents'); 10 | this.download(imageUrl, '__test_logo.png'); 11 | test.assert(fs.exists('__test_logo.png'), 'Casper.download() downloads a file'); 12 | if (fs.exists('__test_logo.png')) { 13 | fs.remove('__test_logo.png'); 14 | } 15 | }).run(function() { 16 | test.done(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /tests/suites/casper/onerror.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | casper.test.begin('page.error event tests', 2, function(test) { 3 | var error = {}; 4 | var expectedMessage; 5 | if (phantom.casperEngine === 'phantomjs') { 6 | expectedMessage = "ReferenceError: Can't find variable: plop"; 7 | } 8 | else { 9 | expectedMessage = "ReferenceError: plop is not defined"; 10 | } 11 | casper.once("page.error", function onError(msg, trace) { 12 | error.msg = msg; 13 | error.trace = trace; 14 | }); 15 | casper.start('tests/site/error.html', function() { 16 | test.assertEquals(error.msg, expectedMessage, 17 | "page.error event has been caught OK"); 18 | test.assertMatch(error.trace[0].file, /error.html/, 19 | "page.error retrieves correct stack trace"); 20 | }); 21 | casper.run(function() { 22 | test.done(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /samples/translate.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | /*global CasperError, console, phantom, require*/ 3 | 4 | /** 5 | * Translation using the Google Translate Service. 6 | * 7 | * Usage: 8 | * 9 | * $ casperjs translate.js --target=fr "hello world" 10 | * bonjour tout le monde 11 | */ 12 | var system = require('system'), 13 | casper = require('casper').create(), 14 | format = require('utils').format, 15 | source = casper.cli.get('source') || 'auto', 16 | target = casper.cli.get('target'), 17 | text = casper.cli.get(0), 18 | result; 19 | 20 | if (!target) { 21 | casper.warn('The --target option is mandatory.').exit(1); 22 | } 23 | 24 | casper.start(format('http://translate.google.com/#%s/%s/%s', source, target, text), function() { 25 | this.fill('form#gt-form', {text: text}); 26 | }).waitForSelector('span.hps', function() { 27 | this.echo(this.fetchText("#result_box")); 28 | }); 29 | 30 | casper.run(); 31 | -------------------------------------------------------------------------------- /tests/suites/casper/history.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | casper.test.begin('handling navigation history', 4, function(test) { 3 | casper.start('tests/site/page1.html'); 4 | casper.thenOpen('tests/site/page2.html'); 5 | casper.thenOpen('tests/site/page3.html'); 6 | casper.back(); 7 | casper.then(function() { 8 | test.assertMatch(this.getCurrentUrl(), /page2\.html$/, 9 | 'Casper.back() can go back an history step'); 10 | }); 11 | casper.forward(); 12 | casper.then(function() { 13 | test.assertMatch(this.getCurrentUrl(), /page3\.html$/, 14 | 'Casper.forward() can go forward an history step'); 15 | }); 16 | casper.run(function() { 17 | test.assert(this.history.length > 0, 'Casper.history contains urls'); 18 | test.assertMatch(this.history[0], /page1\.html$/, 19 | 'Casper.history has the correct first url'); 20 | test.done(); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /samples/timeout.coffee: -------------------------------------------------------------------------------- 1 | ### 2 | Just a silly game. 3 | 4 | $ casperjs samples/timeout.js 500 5 | Will google.com load in less than 500ms? 6 | NOPE. 7 | 8 | $ casperjs samples/timeout.js 1000 9 | Will google.com load in less than 1000ms? 10 | NOPE. 11 | 12 | $ casperjs samples/timeout.js 1500 13 | Will google.com load in less than 1500ms? 14 | NOPE. 15 | 16 | $ casperjs samples/timeout.js 2000 17 | Will google.com load in less than 2000ms? 18 | YES! 19 | ### 20 | 21 | casper = require("casper").create 22 | onTimeout: -> 23 | @echo "NOPE.", "RED_BAR" 24 | @exit() 25 | 26 | timeout = ~~casper.cli.get 0 27 | if timeout < 1 28 | casper 29 | .echo("You must pass a valid timeout value") 30 | .exit(1) 31 | 32 | casper.echo "Will google.com load in less than #{timeout}ms?" 33 | casper.options.timeout = timeout 34 | 35 | casper.start "http://www.google.com/", -> 36 | @echo "YES!", "GREEN_BAR" 37 | @exit() 38 | 39 | casper.run() -------------------------------------------------------------------------------- /samples/screenshot.coffee: -------------------------------------------------------------------------------- 1 | ### 2 | This script will capture a screenshot of a twitter account page 3 | Usage: $ casperjs screenshot.coffee 4 | ### 5 | 6 | casper = require("casper").create 7 | viewportSize: 8 | width: 1024 9 | height: 768 10 | 11 | twitterAccount = casper.cli.get 0 12 | filename = casper.cli.get 1 13 | 14 | if not twitterAccount or not filename or not /\.(png|jpg|pdf)$/i.test filename 15 | casper 16 | .echo("Usage: $ casperjs screenshot.coffee ") 17 | .exit(1) 18 | 19 | casper.start "https://twitter.com/#{twitterAccount}", -> 20 | @waitForSelector ".stream-container", (-> 21 | @captureSelector filename, "html" 22 | @echo "Saved screenshot of #{@getCurrentUrl()} to #{filename}" 23 | ), (-> 24 | @die("Timeout reached. Fail whale?") 25 | @exit() 26 | ), 12000 27 | 28 | casper.run() 29 | -------------------------------------------------------------------------------- /tests/suites/casper/visible.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | casper.test.begin('visibility tests', 5, function(test) { 3 | casper.start('tests/site/visible.html', function() { 4 | test.assert(!this.visible('#img1'), 'Casper.visible() can detect if an element is invisible'); 5 | test.assert(this.visible('#img2'), 'Casper.visible() can detect if an element is visible'); 6 | test.assert(!this.visible('#img3'), 'Casper.visible() can detect if an element is invisible'); 7 | test.assert(this.visible('img'), 'Casper.visible() can detect if an element is visible'); 8 | this.waitWhileVisible('#img1', function() { 9 | test.pass('Casper.waitWhileVisible() can wait while an element is visible'); 10 | }, function() { 11 | test.fail('Casper.waitWhileVisible() can wait while an element is visible'); 12 | }, 2000); 13 | }); 14 | 15 | casper.run(function() { 16 | test.done(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /tests/site/waitFor.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | waitFor test 6 | 7 | 8 | 9 |
      10 |
    • one
    • 11 |
    • two
    • 12 |
    • three
    • 13 |
    14 |
    15 | Loading... 16 |
    17 |
    Voilà
    18 |

    I'm hidden.

    19 |

    I'm visible.

    20 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /samples/events.coffee: -------------------------------------------------------------------------------- 1 | ### 2 | This script will add a custom HTTP status code handler, here for 404 pages. 3 | ### 4 | 5 | casper = require("casper").create() 6 | 7 | casper.on "http.status.200", (resource) -> 8 | @echo "#{resource.url} is OK", "INFO" 9 | 10 | casper.on "http.status.301", (resource) -> 11 | @echo "#{resource.url} is permanently redirected", "PARAMETER" 12 | 13 | casper.on "http.status.302", (resource) -> 14 | @echo "#{resource.url} is temporarily redirected", "PARAMETER" 15 | 16 | casper.on "http.status.404", (resource) -> 17 | @echo "#{resource.url} is not found", "COMMENT" 18 | 19 | casper.on "http.status.500", (resource) -> 20 | @echo "#{resource.url} is in error", "ERROR" 21 | 22 | links = [ 23 | "http://google.com/" 24 | "http://www.google.com/" 25 | "http://www.google.com/plop" 26 | ] 27 | 28 | casper.start() 29 | 30 | casper.each links, (self, link) -> 31 | self.thenOpen link, -> 32 | @echo "#{link} loaded" 33 | 34 | casper.run() 35 | -------------------------------------------------------------------------------- /tests/suites/casper/agent.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | function testUA(ua, match) { 3 | casper.test.assertMatch( 4 | ua, match, 'Default user agent matches ' + match 5 | ); 6 | } 7 | 8 | function fetchUA(requestData, request) { 9 | var headers = requestData.headers.filter(function(header) { 10 | return header.name === "User-Agent"; 11 | }); 12 | casper.test.assert(headers.length > 0); 13 | testUA(headers.pop().value, /plop/); 14 | } 15 | 16 | casper.test.begin('userAgent() tests', 3, { 17 | originalUA: casper.options.pageSettings.userAgent, 18 | 19 | tearDown: function(test) { 20 | casper.userAgent(this.originalUA); 21 | }, 22 | 23 | test: function(test) { 24 | testUA(casper.options.pageSettings.userAgent, /CasperJS/); 25 | casper.start().userAgent('plop').once('resource.requested', fetchUA); 26 | casper.thenOpen('tests/site/index.html').run(function() { 27 | test.done(); 28 | }); 29 | } 30 | }); 31 | 32 | -------------------------------------------------------------------------------- /samples/extends.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | /*global CasperError, console, phantom, require*/ 3 | 4 | var casper = require("casper").create({ 5 | loadImages: false, 6 | logLevel: "debug", 7 | verbose: true 8 | }); 9 | 10 | var links = { 11 | "http://edition.cnn.com/": 0, 12 | "http://www.nytimes.com/": 0, 13 | "http://www.bbc.co.uk/": 0, 14 | "http://www.guardian.co.uk/": 0 15 | }; 16 | 17 | var fantomas = Object.create(casper); 18 | 19 | fantomas.countLinks = function() { 20 | return this.evaluate(function() { 21 | return __utils__.findAll("a[href]").length; 22 | }); 23 | }; 24 | 25 | fantomas.renderJSON = function(what) { 26 | this.echo(JSON.stringify(what, null, " ")); 27 | }; 28 | 29 | fantomas.start(); 30 | 31 | Object.keys(links).forEach(function(url) { 32 | fantomas.thenOpen(url, function() { 33 | links[url] = this.countLinks(); 34 | }); 35 | }); 36 | 37 | fantomas.run(function() { 38 | this.renderJSON(links); 39 | this.exit(); 40 | }); 41 | -------------------------------------------------------------------------------- /samples/googlelinks.coffee: -------------------------------------------------------------------------------- 1 | links = [] 2 | casper = require("casper").create() 3 | 4 | getLinks = -> 5 | links = document.querySelectorAll("h3.r a") 6 | Array::map.call links, (e) -> 7 | try 8 | (/url\?q=(.*)&sa=U/).exec(e.getAttribute("href"))[1] 9 | catch e 10 | e.getAttribute "href" 11 | 12 | casper.start "http://google.fr/", -> 13 | # search for 'casperjs' from google form 14 | @fill "form[action=\"/search\"]", q: "casperjs", true 15 | 16 | casper.then -> 17 | # aggregate results for the 'casperjs' search 18 | links = @evaluate(getLinks) 19 | # now search for 'phantomjs' by fillin the form again 20 | @fill "form[action=\"/search\"]", q: "phantomjs", true 21 | 22 | casper.then -> 23 | # aggregate results for the 'phantomjs' search 24 | links = links.concat(@evaluate(getLinks)) 25 | 26 | casper.run -> 27 | # echo results in some pretty fashion 28 | @echo links.length + " links found:" 29 | @echo " - " + links.join("\n - ") 30 | @exit() 31 | -------------------------------------------------------------------------------- /tests/suites/casper/newpage.js: -------------------------------------------------------------------------------- 1 | /*global casper*/ 2 | /*jshint strict:false*/ 3 | casper.test.begin('newPage() tests', 5, function(test) { 4 | casper.start('tests/site/index.html', function() { 5 | test.assertTitle('CasperJS test index', 'Casper.start() opened the first page'); 6 | test.assertEval(function() { 7 | return typeof(__utils__) === "object"; 8 | }, 'Casper.start() injects ClientUtils instance within remote DOM'); 9 | }).then(function(){ 10 | casper.newPage(); 11 | casper.thenOpen('tests/site/page1.html', function(){ 12 | test.assertTitle('CasperJS test page 1', 'casper.newPage() created a new page object'); 13 | test.assertEval(function() { 14 | return typeof(__utils__) === "object"; 15 | }, 'Casper.newPage() injects ClientUtils instance within remote DOM'); 16 | }); 17 | }).run(function() { 18 | test.done(); 19 | }); 20 | test.assert(casper.started, 'Casper.start() started'); 21 | }); 22 | -------------------------------------------------------------------------------- /samples/multirun.coffee: -------------------------------------------------------------------------------- 1 | casper = require("casper").create verbose: true 2 | 3 | countLinks = -> 4 | document.querySelectorAll('a').length 5 | 6 | suites = [ 7 | -> 8 | @echo "Suite 1" 9 | @start "http://google.com/", -> @echo "Page title: #{@getTitle()}" 10 | @then -> @echo "#{@evaluate(countLinks)} links" 11 | -> 12 | @echo "Suite 2" 13 | @start "http://yahoo.com/", -> @echo "Page title: #{@getTitle()}" 14 | @then -> @echo "#{@evaluate(countLinks)} links" 15 | -> 16 | @echo "Suite 3" 17 | @start "http://bing.com/", -> @echo "Page title: #{@getTitle()}" 18 | @then -> @echo "#{@evaluate(countLinks)} links" 19 | ] 20 | 21 | casper.start() 22 | 23 | casper.then -> 24 | @echo("Starting") 25 | 26 | currentSuite = 0; 27 | 28 | check = -> 29 | if suites[currentSuite] 30 | suites[currentSuite].call @ 31 | currentSuite++; 32 | casper.run check 33 | else 34 | @echo "All done." 35 | @exit() 36 | 37 | casper.run check 38 | -------------------------------------------------------------------------------- /samples/steptimeout.coffee: -------------------------------------------------------------------------------- 1 | failed = [] 2 | start = null 3 | links = [ 4 | "http://google.com/" 5 | "http://akei.com/" 6 | "http://lemonde.fr/" 7 | "http://liberation.fr/" 8 | "http://cdiscount.fr/" 9 | ] 10 | 11 | casper = require("casper").create 12 | onStepTimeout: -> 13 | failed.push @requestUrl 14 | @test.fail "#{@requestUrl} loads in less than #{timeout}ms." 15 | 16 | casper.on "load.finished", -> 17 | @echo "#{@requestUrl} loaded in #{new Date() - start}ms", "PARAMETER" 18 | 19 | timeout = ~~casper.cli.get(0) 20 | timeout = 1000 if timeout < 1 21 | casper.options.stepTimeout = timeout 22 | 23 | casper.echo "Testing with timeout=#{timeout}ms, please be patient." 24 | 25 | casper.start() 26 | 27 | casper.each links, (self, link) -> 28 | @then -> 29 | @test.comment "Loading #{link}" 30 | start = new Date() 31 | @open link 32 | @then -> 33 | if @requestUrl not in failed 34 | @test.pass "#{@requestUrl} loaded in less than #{timeout}ms." 35 | 36 | casper.run -> 37 | @test.renderResults true 38 | -------------------------------------------------------------------------------- /samples/customlogging.coffee: -------------------------------------------------------------------------------- 1 | ### 2 | A basic custom logging implementation. The idea is to (extremely) verbosely 3 | log every received resource. 4 | ### 5 | casper = require("casper").create 6 | verbose: true # we want to see the log printed out to the console 7 | logLevel: "verbose" # of course we want to see logs to our new level :) 8 | 9 | ### 10 | Every time a resource is received, a new log entry is added to the stack 11 | at the 'verbose' level. 12 | ### 13 | casper.on 'resource.received', (resource) -> 14 | infos = [] 15 | props = [ 16 | "url" 17 | "status" 18 | "statusText" 19 | "redirectURL" 20 | "bodySize" 21 | ] 22 | infos.push resource[prop] for prop in props 23 | infos.push "[#{header.name}: #{header.value}]" for header in resource.headers 24 | @log infos.join(", "), "verbose" 25 | 26 | # add a new 'verbose' logging level at the lowest priority 27 | casper.logLevels = ["verbose"].concat casper.logLevels 28 | 29 | # test our new logger with google 30 | casper.start("http://www.google.com/").run -> 31 | @exit() 32 | -------------------------------------------------------------------------------- /tests/suites/casper/auth.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0, max-statements:0*/ 2 | 3 | casper.test.begin('HTTP authentication tests', 8, function(test) { 4 | casper.start('tests/site/index.html'); 5 | 6 | casper.configureHttpAuth('http://localhost/'); 7 | test.assertEquals(casper.page.settings.userName, undefined); 8 | test.assertEquals(casper.page.settings.password, undefined); 9 | 10 | casper.configureHttpAuth('http://niko:plop@localhost/'); 11 | test.assertEquals(casper.page.settings.userName, 'niko'); 12 | test.assertEquals(casper.page.settings.password, 'plop'); 13 | 14 | casper.configureHttpAuth('http://localhost/', {username: 'john', password: 'doe'}); 15 | test.assertEquals(casper.page.settings.userName, 'john'); 16 | test.assertEquals(casper.page.settings.password, 'doe'); 17 | 18 | casper.configureHttpAuth('http://niko:plop@localhost/', {username: 'john', password: 'doe'}); 19 | test.assertEquals(casper.page.settings.userName, 'niko'); 20 | test.assertEquals(casper.page.settings.password, 'plop'); 21 | 22 | casper.run(function() { 23 | test.done(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-2015 Nicolas Perriault 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /tests/suites/casper/scroll.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | casper.test.begin('Casper.scrollTo()', 2, function(test) { 3 | casper.start().then(function() { 4 | this.setContent('
    large div is large
    '); 5 | this.scrollTo(1000, 1000); 6 | test.assertEquals(this.getGlobal("scrollX"), 1000, "scrollTo() scrolls to X position"); 7 | test.assertEquals(this.getGlobal("scrollY"), 1000, "scrollTo() scrolls to Y position"); 8 | }); 9 | 10 | casper.run(function() { 11 | test.done(); 12 | }); 13 | }); 14 | 15 | 16 | casper.test.begin('Casper.scrollToBottom()', 1, function(test) { 17 | casper.start().then(function() { 18 | this.setContent('
    long div is long
    '); 19 | this.scrollToBottom(); 20 | test.assertEval(function() { 21 | /*global __utils__*/ 22 | return __utils__.getDocumentHeight() - window.innerHeight === window.scrollY; 23 | }, "scrollToBottom() scrolls to max Y by default"); 24 | }); 25 | 26 | casper.run(function() { 27 | test.done(); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /tests/suites/casper/elementattribute.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | var x = require('casper').selectXPath; 3 | 4 | casper.test.begin('getElementAttribute() tests', 4, function(test) { 5 | casper.start('tests/site/elementattribute.html', function() { 6 | test.assertEquals(this.getElementAttribute('.testo', 'data-stuff'), 7 | 'beautiful string', 'Casper.getElementAttribute() works with a CSS selector'); 8 | test.assertEquals(this.getElementAttribute(x('//div[@class]'), 'data-stuff'), 9 | 'beautiful string', 'Casper.getElementAttribute() works with a XPath selector'); 10 | }).then(function() { 11 | test.assertEquals(this.getElementsAttribute('.testo', 'data-stuff'), 12 | ['beautiful string', 'not as beautiful string'], 13 | 'Casper.getElementsAttribute() works with a CSS selector'); 14 | test.assertEquals(this.getElementsAttribute(x('//div[@class]'), 'data-stuff'), 15 | ['beautiful string', 'not as beautiful string'], 16 | 'Casper.getElementsAttribute() works with a XPath selector'); 17 | }).run(function() { 18 | test.done(); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /samples/screenshot.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | /*global CasperError, console, phantom, require*/ 3 | 4 | /** 5 | * This script will capture a screenshot of a twitter account page 6 | * Usage: $ casperjs screenshot.js 7 | */ 8 | 9 | var casper = require("casper").create({ 10 | viewportSize: { 11 | width: 1024, 12 | height: 768 13 | } 14 | }); 15 | 16 | var twitterAccount = casper.cli.get(0); 17 | var filename = casper.cli.get(1); 18 | 19 | if (!twitterAccount || !filename || !/\.(png|jpg|pdf)$/i.test(filename)) { 20 | casper 21 | .echo("Usage: $ casperjs screenshot.js ") 22 | .exit(1) 23 | ; 24 | } 25 | 26 | casper.start("https://twitter.com/" + twitterAccount, function() { 27 | this.waitForSelector(".stream-container", (function() { 28 | this.captureSelector(filename, "html"); 29 | this.echo("Saved screenshot of " + (this.getCurrentUrl()) + " to " + filename); 30 | }), (function() { 31 | this.die("Timeout reached. Fail whale?"); 32 | this.exit(); 33 | }), 12000); 34 | }); 35 | 36 | casper.run(); 37 | -------------------------------------------------------------------------------- /samples/googletesting.coffee: -------------------------------------------------------------------------------- 1 | # Google sample testing. 2 | # 3 | # Usage: 4 | # $ casperjs test googletesting.coffee 5 | casper.test.begin 'Google search retrieves 10 or more results', 5, (test) -> 6 | casper.start "http://www.google.fr/", -> 7 | test.assertTitle "Google", "google homepage title is the one expected" 8 | test.assertExists 'form[action="/search"]', "main form is found" 9 | @fill 'form[action="/search"]', q: "foo", true 10 | 11 | casper.then -> 12 | test.assertTitle "foo - Recherche Google", "google title is ok" 13 | test.assertUrlMatch /q=foo/, "search term has been submitted" 14 | test.assertEval (-> 15 | __utils__.findAll("h3.r").length >= 10 16 | ), "google search for \"foo\" retrieves 10 or more results" 17 | 18 | casper.run -> test.done() 19 | 20 | casper.test.begin "Casperjs.org is first ranked", 1, (test) -> 21 | casper.start "http://www.google.fr/", -> 22 | @fill "form[action=\"/search\"]", q: "casperjs", true 23 | 24 | casper.then -> 25 | test.assertSelectorContains ".g", "casperjs.org", "casperjs.org is first ranked" 26 | 27 | casper.run -> test.done() 28 | 29 | -------------------------------------------------------------------------------- /tests/suites/pagestack.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0, max-statements:0*/ 2 | var pagestack = require('pagestack'); 3 | var utils = require('utils'); 4 | var webpage = require('webpage'); 5 | 6 | casper.test.begin('pagestack module tests', 14, function(test) { 7 | var stack = pagestack.create(); 8 | var page1 = webpage.create(); 9 | page1.url = 'page1.html'; 10 | stack.push(page1); 11 | test.assertEquals(stack.length, 1); 12 | test.assert(utils.isWebPage(stack[0])); 13 | test.assertEquals(stack[0], page1); 14 | test.assertEquals(stack.list().length, 1); 15 | test.assertEquals(stack.list()[0], page1.url); 16 | 17 | var page2 = webpage.create(); 18 | page2.url = 'page2.html'; 19 | stack.push(page2); 20 | test.assertEquals(stack.length, 2); 21 | test.assert(utils.isWebPage(stack[1])); 22 | test.assertEquals(stack[1], page2); 23 | test.assertEquals(stack.list().length, 2); 24 | test.assertEquals(stack.list()[1], page2.url); 25 | 26 | test.assertEquals(stack.clean(), 1); 27 | test.assertEquals(stack[0], page2); 28 | test.assertEquals(stack.list().length, 1); 29 | test.assertEquals(stack.list()[0], page2.url); 30 | 31 | test.done(); 32 | }); 33 | -------------------------------------------------------------------------------- /samples/events.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | /*global CasperError, console, phantom, require*/ 3 | 4 | /** 5 | * This script will add a custom HTTP status code handler, here for 404 pages. 6 | */ 7 | var casper = require("casper").create(); 8 | 9 | casper.on("http.status.200", function(resource) { 10 | this.echo(resource.url + " is OK", "INFO"); 11 | }); 12 | 13 | casper.on("http.status.301", function(resource) { 14 | this.echo(resource.url + " is permanently redirected", "PARAMETER"); 15 | }); 16 | 17 | casper.on("http.status.302", function(resource) { 18 | this.echo(resource.url + " is temporarily redirected", "PARAMETER"); 19 | }); 20 | 21 | casper.on("http.status.404", function(resource) { 22 | this.echo(resource.url + " is not found", "COMMENT"); 23 | }); 24 | 25 | casper.on("http.status.500", function(resource) { 26 | this.echo(resource.url + " is in error", "ERROR"); 27 | }); 28 | 29 | var links = [ 30 | "http://google.com/", 31 | "http://www.google.com/", 32 | "http://www.google.com/plop" 33 | ]; 34 | 35 | casper.start(); 36 | 37 | casper.each(links, function(self, link) { 38 | self.thenOpen(link, function() { 39 | this.echo(link + " loaded"); 40 | }); 41 | }); 42 | 43 | casper.run(); 44 | -------------------------------------------------------------------------------- /samples/timeout.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | /*global CasperError, console, phantom, require*/ 3 | 4 | /** 5 | * Just a silly game. 6 | * 7 | * $ casperjs samples/timeout.js 500 8 | * Will google.com load in less than 500ms? 9 | * NOPE. 10 | * 11 | * $ casperjs samples/timeout.js 1000 12 | * Will google.com load in less than 1000ms? 13 | * NOPE. 14 | * 15 | * $ casperjs samples/timeout.js 1500 16 | * Will google.com load in less than 1500ms? 17 | * NOPE. 18 | * 19 | * $ casperjs samples/timeout.js 2000 20 | * Will google.com load in less than 2000ms? 21 | * YES! 22 | */ 23 | 24 | var casper = require("casper").create({ 25 | onTimeout: function() { 26 | this 27 | .echo("NOPE.", "RED_BAR") 28 | .exit() 29 | ; 30 | } 31 | }); 32 | 33 | var timeout = ~~casper.cli.get(0); 34 | 35 | if (timeout < 1) { 36 | casper 37 | .echo("You must pass a valid timeout value") 38 | .exit(1) 39 | ; 40 | } 41 | 42 | casper.echo("Will google.com load in less than " + timeout + "ms?"); 43 | casper.options.timeout = timeout; 44 | 45 | casper.start("http://www.google.com/", function() { 46 | this.echo("YES!", "GREEN_BAR"); 47 | this.exit(); 48 | }); 49 | 50 | casper.run(); 51 | -------------------------------------------------------------------------------- /samples/customlogging.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | /*global CasperError, console, phantom, require*/ 3 | 4 | /** 5 | * A basic custom logging implementation. The idea is to (extremely) verbosely 6 | * log every received resource. 7 | */ 8 | var casper = require("casper").create({ 9 | verbose: true, 10 | logLevel: "verbose" 11 | }); 12 | 13 | /** 14 | * Every time a resource is received, a new log entry is added to the stack at 15 | * the 'verbose' level. 16 | */ 17 | casper.on('resource.received', function(resource) { 18 | var infos = []; 19 | var props = [ 20 | "url", 21 | "status", 22 | "statusText", 23 | "redirectURL", 24 | "bodySize" 25 | ]; 26 | props.forEach(function(prop) { 27 | infos.push(resource[prop]); 28 | }); 29 | resource.headers.forEach(function(header) { 30 | infos.push("[" + header.name + ": " + header.value + "]"); 31 | }); 32 | this.log(infos.join(", "), "verbose"); 33 | }); 34 | 35 | // add a new 'verbose' logging level at the lowest priority 36 | casper.logLevels = ["verbose"].concat(casper.logLevels); 37 | 38 | // test our new logger with google 39 | casper.start("http://www.google.com/").run(function() { 40 | this.exit(); 41 | }); 42 | -------------------------------------------------------------------------------- /tests/suites/casper/alert.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | casper.test.begin('alert events', 1, { 3 | ok: false, 4 | 5 | tearDown: function(test) { 6 | casper.removeAllListeners('remote.alert'); 7 | }, 8 | 9 | test: function(test) { 10 | var self = this; 11 | 12 | casper.once('remote.alert', function(message) { 13 | self.ok = (message === 'plop'); 14 | }); 15 | 16 | casper.start('tests/site/alert.html', function() { 17 | test.assert(self.ok, 'alert event has been intercepted'); 18 | }); 19 | 20 | casper.run(function() { 21 | test.done(); 22 | }); 23 | } 24 | }); 25 | 26 | casper.test.begin("Casper.waitForAlert() waits for an alert", 1, function(test) { 27 | casper.start().then(function() { 28 | this.evaluate(function() { 29 | setTimeout(function() { 30 | alert("plop"); 31 | }, 500); 32 | }); 33 | }); 34 | 35 | casper.waitForAlert(function(response) { 36 | test.assertEquals(response.data, "plop", 37 | "Casper.waitForAlert() can wait for an alert to be triggered"); 38 | }); 39 | 40 | casper.run(function() { 41 | test.done(); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /tests/suites/casper/flow.coffee: -------------------------------------------------------------------------------- 1 | casper.test.begin 'handling waits and timeouts', 13, (test) -> 2 | step = 0 3 | 4 | casper.start "tests/site/resources.html", -> 5 | test.assertEquals ++step, 1, "step 1" 6 | @wait 400, -> 7 | test.assertEquals ++step, 2, "step 1.1" 8 | @wait 200, -> 9 | test.assertEquals ++step, 3, "step 1.1.1" 10 | @wait 200, -> 11 | test.assertEquals ++step, 4, "step 1.1.1.1" 12 | @then -> 13 | test.assertEquals ++step, 5, "step 1.1.2.1" 14 | @wait 400, -> 15 | test.assertEquals ++step, 6, "step 1.2" 16 | 17 | casper.wait 200, -> 18 | test.assertEquals ++step, 7, "step 2" 19 | 20 | casper.waitForSelector( 21 | '#noneExistingSelector' 22 | -> test.fail "should run into timeout" 23 | -> test.assertEquals ++step, 8, "step 3 sucessfully timed out" 24 | 1000 25 | ) 26 | casper.then -> 27 | test.assertEquals ++step, 9, "step 4" 28 | @wait 300, -> 29 | test.assertEquals ++step, 10, "step 4.1" 30 | @wait 300, -> 31 | test.assertEquals ++step, 11, "step 4.1.1" 32 | @wait 100, -> 33 | test.assertEquals ++step, 12, "step 5.2" 34 | 35 | casper.then -> 36 | test.assertEquals ++step, 13, "last step" 37 | 38 | casper.run(-> test.done()) 39 | -------------------------------------------------------------------------------- /casperjs.gemspec: -------------------------------------------------------------------------------- 1 | # by hannyu 2 | 3 | CASPERJS_VERSION = File.read("package.json")[/version.*:.*"(.*?)"/,1].gsub(/[\-_\+]/,".") 4 | 5 | Gem::Specification.new do |s| 6 | s.name = "casperjs" 7 | s.version = CASPERJS_VERSION 8 | s.homepage = "http://casperjs.org/" 9 | s.authors = ["Nicolas Perriault", ] 10 | s.email = ["nperriault@gmail.com",] 11 | s.description = "CasperJS is a navigation scripting & testing utility for [PhantomJS](http://www.phantomjs.org/). 12 | It eases the process of defining a full navigation scenario and provides useful 13 | high-level functions, methods & syntaxic sugar for doing common tasks." 14 | s.summary = "Navigation scripting & testing utility for PhantomJS" 15 | s.extra_rdoc_files = ["LICENSE.md", "README.md"] 16 | s.files = Dir["LICENSE.md", "README.md", "CHANGELOG.md", "package.json", "casperjs.gemspec", 17 | "bin/bootstrap.js", "bin/usage.txt", "bin/casperjs_python", 18 | "docs/**/*", "modules/**/*", "samples/**/*", "tests/**/*"] 19 | s.bindir = "rubybin" 20 | s.executables = [ "casperjs" ] 21 | s.license = "MIT" 22 | s.requirements = [ "PhantomJS v1.7" ] 23 | end 24 | -------------------------------------------------------------------------------- /tests/suites/fs.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | var fs = require('fs'); 3 | 4 | casper.test.begin('fs.dirname() tests', 8, function(test) { 5 | var tests = { 6 | '/local/plop/foo.js': '/local/plop', 7 | 'local/plop/foo.js': 'local/plop', 8 | './local/plop/foo.js': './local/plop', 9 | 'c:\\local\\plop\\foo.js': 'c:/local/plop', 10 | 'D:\\local\\plop\\foo.js': 'D:/local/plop', 11 | 'D:\\local\\plop\\': 'D:/local/plop', 12 | 'c:\\': 'c:', 13 | 'c:': 'c:' 14 | }; 15 | for (var testCase in tests) { 16 | test.assertEquals(fs.dirname(testCase), tests[testCase], 'fs.dirname() does its job for ' + testCase); 17 | } 18 | test.done(); 19 | }); 20 | 21 | casper.test.begin('fs.isWindows() tests', 6, function(test) { 22 | var tests = { 23 | '/': false, 24 | '/local/plop/foo.js': false, 25 | 'D:\\local\\plop\\': true, 26 | 'c:\\': true, 27 | 'c:': true, 28 | '\\\\Server\\Plop': true 29 | }; 30 | for (var testCase in tests) { 31 | test.assertEquals(fs.isWindows(testCase), tests[testCase], 'fs.isWindows() does its job for ' + testCase); 32 | } 33 | test.done(); 34 | }); 35 | -------------------------------------------------------------------------------- /samples/googlepagination.coffee: -------------------------------------------------------------------------------- 1 | ### 2 | Capture multiple pages of google search results 3 | 4 | Usage: $ casperjs googlepagination.coffee my search terms 5 | 6 | (all arguments will be used as the query) 7 | ### 8 | 9 | casper = require("casper").create( 10 | waitTimeout: 1000 11 | pageSettings: 12 | userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:23.0) Gecko/20130404 Firefox/23.0" 13 | ) 14 | currentPage = 1 15 | 16 | if casper.cli.args.length is 0 17 | casper 18 | .echo("Usage: $ casperjs googlepagination.coffee my search terms") 19 | .exit(1) 20 | 21 | terminate = -> 22 | @echo("that's all, folks.").exit(); 23 | 24 | processPage = -> 25 | @echo "capturing page #{currentPage}" 26 | @capture "google-results-p#{currentPage}.png" 27 | 28 | # don't go too far down the rabbit hole 29 | if currentPage >= 5 || !@exists "#pnnext" 30 | return terminate.call casper 31 | 32 | currentPage++ 33 | @echo "requesting next page: #{currentPage}" 34 | url = @getCurrentUrl() 35 | @thenClick("#pnnext").then -> 36 | @waitFor (-> 37 | url isnt @getCurrentUrl() 38 | ), processPage, terminate 39 | 40 | casper.start "http://google.fr/", -> 41 | @fill 'form[action="/search"]', q: casper.cli.args.join(" "), true 42 | 43 | casper.waitForSelector "#pnnext", processPage, terminate 44 | 45 | casper.run() 46 | -------------------------------------------------------------------------------- /tests/suites/casper/headers.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | var server = require('webserver').create(); 3 | var service = server.listen(8090, function(request, response) { 4 | response.statusCode = 200; 5 | response.headers = { 6 | 'Content-Language': 'en', 7 | 'Content-Type': 'text/html', 8 | 'Date': new Date().toUTCString() 9 | }; 10 | response.write("ok"); 11 | response.close(); 12 | }); 13 | 14 | casper.test.begin('Casper.headers.get() using file protocol', 1, function(test) { 15 | casper.start('file://' + phantom.casperPath + 'tests/site/index.html', function(response) { 16 | test.assertEquals(response, {data: null}, 'Empty http response on local page'); 17 | }).run(function() { 18 | test.done(); 19 | }); 20 | }); 21 | 22 | casper.test.begin('Casper.headers.get() using http protocol', 3, function(test) { 23 | casper.start('http://localhost:8090/', function(response) { 24 | var headers = response.headers; 25 | test.assertEquals(headers.get('Content-Language'), 'en', 'Checking existing header (case sensitive)'); 26 | test.assertEquals(headers.get('content-language'), 'en', 'Checking existing header (case insensitive)'); 27 | test.assertEquals(headers.get('X-Is-Troll'), null, 'Checking unexisting header'); 28 | }).run(function() { 29 | server.close(); 30 | test.done(); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /samples/googlelinks.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | /*global CasperError, console, phantom, require*/ 3 | 4 | var links = []; 5 | var casper = require("casper").create(); 6 | 7 | function getLinks() { 8 | var links = document.querySelectorAll("h3.r a"); 9 | return Array.prototype.map.call(links, function(e) { 10 | try { 11 | // google handles redirects hrefs to some script of theirs 12 | return (/url\?q=(.*)&sa=U/).exec(e.getAttribute("href"))[1]; 13 | } catch (err) { 14 | return e.getAttribute("href"); 15 | } 16 | }); 17 | } 18 | 19 | casper.start("http://google.fr/", function() { 20 | // search for 'casperjs' from google form 21 | this.fill('form[action="/search"]', { q: "casperjs" }, true); 22 | }); 23 | 24 | casper.then(function() { 25 | // aggregate results for the 'casperjs' search 26 | links = this.evaluate(getLinks); 27 | // now search for 'phantomjs' by fillin the form again 28 | this.fill('form[action="/search"]', { q: "phantomjs" }, true); 29 | }); 30 | 31 | casper.then(function() { 32 | // aggregate results for the 'phantomjs' search 33 | links = links.concat(this.evaluate(getLinks)); 34 | }); 35 | 36 | casper.run(function() { 37 | // echo results in some pretty fashion 38 | this.echo(links.length + " links found:"); 39 | this.echo(" - " + links.join("\n - ")); 40 | this.exit(); 41 | }); 42 | -------------------------------------------------------------------------------- /tests/suites/casper/scripts.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | casper.test.begin('remote script includes tests', 4, { 3 | setUp: function() { 4 | casper.options.remoteScripts = [ 5 | 'includes/include1.js', // local includes are actually served 6 | 'includes/include2.js' // through the local test webserver 7 | ]; 8 | }, 9 | 10 | tearDown: function() { 11 | casper.options.remoteScripts = []; 12 | }, 13 | 14 | test: function(test) { 15 | casper.start('tests/site/index.html', function() { 16 | test.assertSelectorHasText('#include1', 'include1', 17 | 'Casper.includeRemoteScripts() includes a first remote script on start'); 18 | test.assertSelectorHasText('#include2', 'include2', 19 | 'Casper.includeRemoteScripts() includes a second remote script on start'); 20 | }); 21 | 22 | casper.thenOpen('tests/site/form.html', function() { 23 | test.assertSelectorHasText('#include1', 'include1', 24 | 'Casper.includeRemoteScripts() includes a first remote script on second step'); 25 | test.assertSelectorHasText('#include2', 'include2', 26 | 'Casper.includeRemoteScripts() includes a second remote script on second step'); 27 | }); 28 | 29 | casper.run(function() { 30 | test.done(); 31 | }); 32 | } 33 | }); 34 | -------------------------------------------------------------------------------- /tests/suites/tester/begin-config.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0, eqeqeq:0*/ 2 | var steps = []; 3 | 4 | casper.test.begin('Tester.begin() configuration', 10, { 5 | fixtures: [1, 2, 3], 6 | 7 | _this: function() { 8 | return this; 9 | }, 10 | 11 | setUp: function(test) { 12 | steps.push('setUp'); 13 | test.pass('config.setUp() has been called'); 14 | test.assert(this == this._this(), 'config.setUp() is using the expected context'); 15 | test.assertEquals(this.fixtures, [1, 2, 3], 'config.setUp() accesses fixtures'); 16 | }, 17 | 18 | tearDown: function(test) { 19 | steps.push('tearDown'); 20 | test.pass('config.tearDown() has been called'); 21 | test.assert(this == this._this(), 'config.test() is using the expected context'); 22 | test.assertEquals(this.fixtures, [1, 2, 3], 'config.tearDown() accesses fixtures'); 23 | test.assertEquals(steps, ['setUp', 'test', 'tearDown'], 24 | 'Tester.begin() has processed the configuration in the expected order'); 25 | }, 26 | 27 | test: function(test) { 28 | steps.push('test'); 29 | test.pass('config.test() has been called'); 30 | test.assert(this == this._this(), 'config.tearDown() is using the expected context'); 31 | test.assertEquals(this.fixtures, [1, 2, 3], 'config.test() accesses fixtures'); 32 | test.done(); 33 | } 34 | }); 35 | -------------------------------------------------------------------------------- /rpm/build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # A little helper script to build the RPM. 4 | 5 | if [ ! -f "../package.json" ]; then 6 | echo "Execute rpm build script in rpm directory" 7 | exit 1 8 | fi 9 | 10 | name="casperjs" 11 | name=${name%.spec} 12 | topdir=$(mktemp -d "${TMPDIR:-/tmp}/${name}-build-XXXXXX") 13 | # Get version from package.json 14 | version=$(grep '"version"' ../package.json | sed 's/.*"\(.*\)": "\(.*\)".*/\2/' | sed 's/[-]//') 15 | builddir=${TMPDIR:-/tmp}/${name}-${version} 16 | sourcedir="${topdir}/SOURCES" 17 | buildroot="${topdir}/BUILD/${name}-${version}-root" 18 | 19 | mkdir -p ${topdir}/{RPMS,SRPMS,SOURCES,BUILD} 20 | mkdir -p ${buildroot} ${builddir} 21 | 22 | echo "=> Copying sources..." 23 | ( cd .. && tar cf - ./[A-Z]* ./package.json ./bin ./samples ./tests ./modules | tar xf - -C ${builddir} ) 24 | 25 | echo "=> Creating source tarball under ${sourcedir}..." 26 | ( cd ${builddir}/.. && tar zcf ${sourcedir}/${name}-${version}.tar.gz ${name}-${version} ) 27 | 28 | echo "=> Building RPM..." 29 | rpm=$(rpmbuild --define "_topdir ${topdir}" --define "_version ${version}" --buildroot ${buildroot} --clean -bb ${name}.spec | awk '/\/RPMS\// { print $2; }') 30 | 31 | if [ $? -ne 0 ]; then 32 | echo "Failed to build RPM package." 33 | exit 1 34 | fi 35 | 36 | echo ${rpm} 37 | cp ${rpm} ${TMPDIR:-/tmp}/ 38 | rm -fr ${topdir} 39 | 40 | echo "RPM package build finished." 41 | echo ${TMPDIR:-/tmp}/${rpm##*/} 42 | -------------------------------------------------------------------------------- /docs/license.rst: -------------------------------------------------------------------------------- 1 | .. _license: 2 | 3 | .. index:: Licensing 4 | 5 | ======= 6 | License 7 | ======= 8 | 9 | `CasperJS `_ is released under the terms of the 10 | `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. 30 | -------------------------------------------------------------------------------- /tests/suites/casper/xpath.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | var x = require('casper').selectXPath; 3 | 4 | casper.test.begin('XPath tests', 6, function(test) { 5 | casper.start('tests/site/index.html', function() { 6 | test.assertExists({ 7 | type: 'xpath', 8 | path: '/html/body/ul/li[2]' 9 | }, 'XPath selector can find an element'); 10 | test.assertDoesntExist({ 11 | type: 'xpath', 12 | path: '/html/body/ol/li[2]' 13 | }, 'XPath selector does not retrieve a nonexistent element'); 14 | test.assertExists(x('/html/body/ul/li[2]'), 'selectXPath() shortcut can find an element as well'); 15 | test.assertEvalEquals(function() { 16 | return __utils__.findAll({type: 'xpath', path: '/html/body/ul/li'}).length; 17 | }, 3, 'Correct number of elements are found'); 18 | }); 19 | 20 | casper.thenClick(x('/html/body/a[2]'), function() { 21 | test.assertTitle('CasperJS test form', 'Clicking XPath works as expected'); 22 | this.fill(x('/html/body/form'), { 23 | email: 'chuck@norris.com' 24 | }); 25 | test.assertEvalEquals(function() { 26 | return document.querySelector('input[name="email"]').value; 27 | }, 'chuck@norris.com', 'Casper.fill() can fill an input[type=text] form field'); 28 | }); 29 | 30 | casper.run(function() { 31 | test.done(); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /tests/suites/casper/content.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | var fs = require("fs"); 3 | 4 | casper.test.begin("Casper.getPageContent() text/html content", 1, function(test) { 5 | casper.start("tests/site/test.html"); 6 | casper.waitForUrl("tests/site/test.html", function() { 7 | test.assertMatch(this.getPageContent(), /CasperJS test target/, 8 | "Casper.getPageContent() retrieves text/html content"); 9 | }); 10 | casper.run(function() { 11 | test.done(); 12 | }); 13 | }); 14 | 15 | casper.test.begin("Casper.getPageContent() non text/html content", 2, function(test) { 16 | // NOTE due to a bug in slimerjs we can only use text/* and 17 | // application/json content here 18 | // https://github.com/laurentj/slimerjs/issues/405 19 | casper.start("tests/site/dummy.json"); 20 | casper.waitForUrl("tests/site/dummy.json", function() { 21 | test.assertEquals(this.getPageContent(), '{"dummy":"json"}\n', 22 | "Casper.getPageContent() retrieves application/json content"); 23 | }); 24 | casper.thenOpen("tests/site/dummy.txt"); 25 | casper.waitForUrl("tests/site/dummy.txt", function() { 26 | test.assertEquals(this.getPageContent(), 'some dummy text\n', 27 | "Casper.getPageContent() retrieves text/plain content"); 28 | }); 29 | 30 | casper.run(function() { 31 | test.done(); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /samples/steptimeout.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | /*global CasperError, console, phantom, require*/ 3 | 4 | var failed = []; 5 | var start = null; 6 | var links = [ 7 | "http://google.com/'", 8 | "http://akei.com/'", 9 | "http://lemonde.fr/'", 10 | "http://liberation.fr/'", 11 | "http://cdiscount.fr/" 12 | ]; 13 | 14 | var casper = require("casper").create({ 15 | onStepTimeout: function() { 16 | failed.push(this.requestUrl); 17 | this.test.fail(this.requestUrl + " loads in less than " + timeout + "ms."); 18 | } 19 | }); 20 | 21 | casper.on("load.finished", function() { 22 | this.echo(this.requestUrl + " loaded in " + (new Date() - start) + "ms", "PARAMETER"); 23 | }); 24 | 25 | var timeout = ~~casper.cli.get(0); 26 | casper.options.stepTimeout = timeout > 0 ? timeout : 1000; 27 | 28 | casper.echo("Testing with timeout=" + casper.options.stepTimeout + "ms, please be patient."); 29 | 30 | casper.start(); 31 | 32 | casper.each(links, function(casper, link) { 33 | this.then(function() { 34 | this.test.comment("Loading " + link); 35 | start = new Date(); 36 | this.open(link); 37 | }); 38 | this.then(function() { 39 | var message = this.requestUrl + " loads in less than " + timeout + "ms."; 40 | if (failed.indexOf(this.requestUrl) === -1) { 41 | this.test.pass(message); 42 | } 43 | }); 44 | }); 45 | 46 | casper.run(function() { 47 | this.test.renderResults(true); 48 | }); 49 | -------------------------------------------------------------------------------- /tests/suites/casper/resources.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | casper.test.begin("Basic resources tests", 5, function(test) { 3 | casper.start("tests/site/resources.html", function() { 4 | test.assertEquals(this.resources.length, 1, "only one resource found"); 5 | }); 6 | 7 | casper.waitForResource("dummy.js", function() { 8 | test.assertEquals(this.resources.length, 2, "two resources found"); 9 | test.assertResourceExists(/dummy\.js/i, "phantom image found via test RegExp"); 10 | test.assertResourceExists(function(res) { 11 | return res.url.match("dummy.js"); 12 | }, "phantom image found via test Function"); 13 | test.assertResourceExists("dummy.js?querystring", "phantom image found via test String"); 14 | }, function onTimeout() { 15 | test.fail("waitForResource timeout occured"); 16 | }); 17 | 18 | casper.run(function() { 19 | test.done(); 20 | }); 21 | }); 22 | 23 | casper.test.begin('"resource.error" event', 3, function(test) { 24 | casper.on("resource.error", function(error) { 25 | test.assertType(error, "object", '"resource.error" triggered error information'); 26 | test.assert(error.errorCode === 203, '"resource.error" error code is correct'); 27 | test.assertMatch(error.url, /non-existant\.html$/, '"resource.error" url is correct'); 28 | }); 29 | 30 | casper.start('tests/site/non-existant.html').run(function() { 31 | casper.removeAllListeners("resource.error"); 32 | test.done(); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /tests/suites/require.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | var fs = require('fs'); 3 | var modroot = fs.pathJoin(phantom.casperPath, 'tests', 'sample_modules'); 4 | 5 | casper.test.begin('Javascript module loading', 1, function(test) { 6 | var jsmod; 7 | try { 8 | jsmod = require(fs.pathJoin(modroot, 'jsmodule')); 9 | test.assertTrue(jsmod.ok, 'require() patched version can load a js module'); 10 | } catch (e) { 11 | test.fail('require() patched version can load a js module'); 12 | } 13 | test.done(); 14 | }); 15 | 16 | // only test if the engine supports coffeescript 17 | if (".coffee" in require.extensions) { 18 | casper.test.begin('CoffeeScript module loading', 1, function(test) { 19 | var csmod; 20 | try { 21 | csmod = require(fs.pathJoin(modroot, 'csmodule')); 22 | test.assertTrue(csmod.ok, 'require() patched version can load a coffeescript module'); 23 | } catch (e) { 24 | test.fail('require() patched version can load a coffeescript module'); 25 | } 26 | test.done(); 27 | }); 28 | } 29 | 30 | casper.test.begin('JSON module loading', 1, function(test) { 31 | var config; 32 | try { 33 | config = require(fs.pathJoin(modroot, 'config.json')); 34 | test.assertTrue(config.ok, 'require() patched version can load a json module'); 35 | } catch (e) { 36 | test.fail('require() patched version can load a json module'); 37 | } 38 | test.done(); 39 | }); 40 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | ====================== 2 | CasperJS documentation 3 | ====================== 4 | 5 | CasperJS_ is a navigation scripting & testing utility for the PhantomJS_ (WebKit) and SlimerJS_ (Gecko) headless browsers, 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 | cookbook 26 | changelog 27 | upgrading/index 28 | known_issues 29 | credits 30 | license 31 | 32 | You can also search the :ref:`genindex` if you're looking for something particular. 33 | 34 | .. index:: Community, Contributing, Help, Support 35 | 36 | Community 37 | --------- 38 | 39 | - `get the code <https://github.com/casperjs/casperjs>`_ and `contribute <https://github.com/casperjs/casperjs/blob/master/CONTRIBUTING.md#contribution-guide>`_ 40 | - join the `mailing list <https://groups.google.com/forum/#!forum/casperjs>`_ 41 | - check out `the ecosystem <https://github.com/casperjs>`_ 42 | - follow `@casperjs\_org <https://twitter.com/casperjs_org>`_ on Twitter 43 | - there's also a `Google+ account <https://plus.google.com/106641872690063476159>`_ (not much updated though) 44 | 45 | 46 | .. _CasperJS: http://casperjs.org/ 47 | .. _PhantomJS: http://phantomjs.org/ 48 | .. _SlimerJS: http://slimerjs.org/ 49 | -------------------------------------------------------------------------------- /docs/known_issues.rst: -------------------------------------------------------------------------------- 1 | .. _known_issues: 2 | 3 | .. index:: Known Issues 4 | 5 | Known Issues 6 | ============ 7 | This is a non-exhaustive list of issues that the CasperJS team is aware of and tracking. 8 | 9 | PhantomJS 10 | --------- 11 | **Versions below 2.0.0**: 12 | 13 | - `phantomjs-issue-10795: <https://github.com/ariya/phantomjs/issues/10795>`_ 14 | 15 | There is a known issue while doing clicks within the page that causes execution to halt. It has been fixed in v2.0.0+ in phantomjs. 16 | 17 | It is mentioned in the following issues: `#233 <https://github.com/casperjs/casperjs/issues/223>`_ 18 | 19 | :: 20 | 21 | console.log('START click'); 22 | console.log(document.getElementById('foo').toString()); 23 | console.log(document.getElementById('foo').click()); // this ends execution 24 | console.log('END click'); // this never gets called 25 | 26 | **Version 2.0.0**: 27 | 28 | - `phantomjs-issue-12506: <https://github.com/ariya/phantomjs/issues/12506>`_ 29 | 30 | Webpage.uploadFile is not working. It has been fixed in v2.0.1+ in phantomjs. 31 | 32 | - `phantomjs-issue-12410: <https://github.com/ariya/phantomjs/issues/12410>`_ 33 | 34 | Quote from `PhantomJS 2.0 Release Note <http://phantomjs.org/release-2.0.html>`_: 35 | 36 | "PhantomJS 2 can not run scripts written in CoffeeScript anymore (see issue `12410 <https://github.com/ariya/phantomjs/issues/12410>`_). As a workaround, CoffeeScript users can still compile their scripts to JavaScript first before executing it with PhantomJS." -------------------------------------------------------------------------------- /samples/googlematch.coffee: -------------------------------------------------------------------------------- 1 | ### 2 | Takes provided terms passed as arguments and query google for the number of 3 | estimated results each have. 4 | 5 | Usage: 6 | $ casperjs googlematch.coffee nicolas chuck borris 7 | nicolas: 69600000 8 | chuck: 49500000 9 | borris: 2370000 10 | winner is "nicolas" with 69600000 results 11 | ### 12 | 13 | casper = require("casper").create verbose: true 14 | 15 | casper.fetchScore = -> 16 | @evaluate -> 17 | result = __utils__.findOne('#resultStats').innerText 18 | parseInt /Environ ([0-9\s]{1,}).*/.exec(result)[1].replace(/\s/g, '') 19 | 20 | terms = casper.cli.args # terms are passed through command-line arguments 21 | 22 | if terms.length < 2 23 | casper 24 | .echo("Usage: $ casperjs googlematch.js term1 term2 [term3]...") 25 | .exit(1) 26 | 27 | scores = [] 28 | 29 | casper.echo "Let the match begin between \"#{terms.join '", "'}\"!" 30 | 31 | casper.start "http://google.fr/" 32 | 33 | casper.each terms, (self, term) -> 34 | @then -> @fill 'form[action="/search"]', { q: term }, true 35 | @then -> 36 | score = @fetchScore() 37 | scores.push term: term, score: score 38 | @echo "#{term}: #{score}" 39 | 40 | casper.run -> 41 | if scores.length is 0 42 | @echo "No result found" 43 | else 44 | scores.sort (a, b) -> b.score - a.score 45 | winner = scores[0] 46 | @echo "Winner is \"" + winner.term + "\" with " + winner.score + " results" 47 | @exit() 48 | -------------------------------------------------------------------------------- /tests/suites/casper/events.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | casper.test.begin('events', 2, function(test) { 3 | casper.plopped = false; 4 | casper.once("plop", function() { 5 | this.plopped = true; 6 | }); 7 | test.assert(Object.keys(casper._events).some(function(i) { 8 | return i === "plop"; 9 | }), "on() has set an event handler"); 10 | casper.emit("plop"); 11 | test.assert(casper.plopped, "emit() emits an event"); 12 | test.done(); 13 | }); 14 | 15 | casper.test.begin('filters', 3, function(test) { 16 | casper.foo = 0; 17 | casper.setFilter("test", function(a) { 18 | this.foo = 42; 19 | return a + 1; 20 | }); 21 | test.assert(Object.keys(casper._filters).some(function(i) { 22 | return i === "test"; 23 | }), "setFilter() has set a filter"); 24 | test.assertEquals(casper.filter("test", 1), 2, "filter() filters a value"); 25 | test.assertEquals(casper.foo, 42, "filter() applies the correct context"); 26 | delete casper.foo; 27 | test.done(); 28 | }); 29 | 30 | casper.test.begin('events order', 2, function(test) { 31 | casper.mowed = "Moo"; 32 | casper.on("mow", function() { 33 | this.mowed = casper.mowed + " Moo"; 34 | }); 35 | casper.emit("mow"); 36 | test.assertEquals(casper.mowed, "Moo Moo", "mowed has the correct value"); 37 | 38 | casper.prependListener("mow", function() { 39 | this.mowed = this.mowed + " Boo"; 40 | }); 41 | casper.emit("mow"); 42 | test.assertEquals(casper.mowed, "Moo Moo Boo Moo", "mowed has the correct value"); 43 | test.done(); 44 | }); 45 | -------------------------------------------------------------------------------- /samples/googletesting.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | /*global CasperError, casper, console, phantom, require*/ 3 | /** 4 | * Google sample testing. 5 | * 6 | * Usage: 7 | * 8 | * $ casperjs test googletesting.js 9 | */ 10 | casper.test.begin('Google search retrieves 10 or more results', 5, function suite(test) { 11 | casper.start("http://www.google.fr/", function() { 12 | test.assertTitle("Google", "google homepage title is the one expected"); 13 | test.assertExists('form[action="/search"]', "main form is found"); 14 | this.fill('form[action="/search"]', { 15 | q: "casperjs" 16 | }, true); 17 | }); 18 | 19 | casper.then(function() { 20 | test.assertTitle("casperjs - Recherche Google", "google title is ok"); 21 | test.assertUrlMatch(/q=casperjs/, "search term has been submitted"); 22 | test.assertEval(function() { 23 | return __utils__.findAll("h3.r").length >= 10; 24 | }, "google search for \"casperjs\" retrieves 10 or more results"); 25 | }); 26 | 27 | casper.run(function() { 28 | test.done(); 29 | }); 30 | }); 31 | 32 | casper.test.begin('Casperjs.org is first ranked', 1, function suite(test) { 33 | casper.start("http://www.google.fr/", function() { 34 | this.fill('form[action="/search"]', { 35 | q: "casperjs" 36 | }, true); 37 | }); 38 | 39 | casper.then(function() { 40 | test.assertSelectorContains(".g", "casperjs.org", "casperjs.org is first ranked"); 41 | }); 42 | 43 | casper.run(function() { 44 | test.done(); 45 | }); 46 | }); 47 | -------------------------------------------------------------------------------- /tests/suites/casper/request.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | var currentRequest; 3 | 4 | function onResourceRequested(requestData, request) { 5 | currentRequest = requestData; 6 | } 7 | 8 | function testHeader(header) { 9 | return header.name === 'Accept' && header.value === 'application/json'; 10 | } 11 | 12 | casper.test.begin('requests tests', 3, { 13 | setUp: function() { 14 | casper.on('page.resource.requested', onResourceRequested); 15 | }, 16 | 17 | tearDown: function() { 18 | currentRequest = undefined; 19 | casper.removeListener('page.resource.requested', onResourceRequested); 20 | }, 21 | 22 | test: function(test) { 23 | casper.start('tests/site/index.html', function() { 24 | test.assertNot(currentRequest.headers.some(testHeader), 25 | "Casper.open() sets no custom header by default"); 26 | }); 27 | 28 | casper.thenOpen('tests/site/index.html', { 29 | headers: { 30 | Accept: 'application/json' 31 | } 32 | }, function() { 33 | test.assert(currentRequest.headers.some(testHeader), 34 | "Casper.open() can set a custom header"); 35 | }); 36 | 37 | casper.thenOpen('tests/site/index.html', function() { 38 | test.assertNot(currentRequest.headers.some(testHeader), 39 | "Casper.open() custom headers option is not persistent"); 40 | }); 41 | 42 | casper.run(function() { 43 | this.removeAllListeners('page.resource.requested'); 44 | test.done(); 45 | }); 46 | } 47 | }); 48 | -------------------------------------------------------------------------------- /tests/suites/casper/frames.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | casper.test.begin('handling frames', 16, function(test) { 3 | casper.start('tests/site/frames.html'); 4 | 5 | casper.withFrame('frame1', function() { 6 | test.assertTitle('CasperJS frame 1'); 7 | test.assertExists("#f1"); 8 | test.assertDoesntExist("#f2"); 9 | test.assertEval(function() { 10 | return '__utils__' in window && 'getBinary' in __utils__; 11 | }, '__utils__ object is available in child frame'); 12 | test.assertMatches(this.page.frameContent, /This is frame 1/); 13 | test.assertMatches(this.getHTML(), /This is frame 1/); 14 | }); 15 | 16 | casper.withFrame('frame2', function() { 17 | test.assertTitle('CasperJS frame 2'); 18 | test.assertExists("#f2"); 19 | test.assertDoesntExist("#f1"); 20 | test.assertEval(function() { 21 | return '__utils__' in window && 'getBinary' in __utils__; 22 | }, '__utils__ object is available in other child frame'); 23 | this.clickLabel('frame 3'); 24 | }); 25 | 26 | casper.withFrame('frame2', function() { 27 | test.assertTitle('CasperJS frame 3'); 28 | }); 29 | 30 | casper.withFrame(0, function() { 31 | test.assertTitle('CasperJS frame 1'); 32 | test.assertExists("#f1"); 33 | test.assertDoesntExist("#f2"); 34 | }); 35 | 36 | casper.withFrame(1, function() { 37 | test.assertTitle('CasperJS frame 3'); 38 | }); 39 | 40 | casper.run(function() { 41 | test.assertTitle('CasperJS test frames'); 42 | test.done(); 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /tests/suites/casper/confirm.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | casper.test.begin('can confirm dialog', 2, { 3 | received: undefined, 4 | 5 | setUp: function(test) { 6 | var self = this; 7 | casper.removeAllFilters('page.confirm'); 8 | casper.setFilter('page.confirm', function(message) { 9 | self.received = message; 10 | return true; 11 | }); 12 | }, 13 | 14 | tearDown: function(test) { 15 | casper.removeAllFilters('page.confirm'); 16 | }, 17 | 18 | test: function(test) { 19 | var self = this; 20 | casper.start('tests/site/confirm.html', function() { 21 | test.assert(this.getGlobal('confirmed'), 'confirmation dialog accepted'); 22 | }).run(function() { 23 | test.assertEquals(self.received, 'are you sure?', 'confirmation message is ok'); 24 | test.done(); 25 | }); 26 | } 27 | }); 28 | 29 | casper.test.begin('can cancel dialog', 1, { 30 | received: undefined, 31 | 32 | setUp: function(test) { 33 | var self = this; 34 | casper.removeAllFilters('page.confirm'); 35 | casper.setFilter('page.confirm', function(message) { 36 | return false; 37 | }); 38 | }, 39 | 40 | tearDown: function(test) { 41 | casper.removeAllFilters('page.confirm'); 42 | }, 43 | 44 | test: function(test) { 45 | var self = this; 46 | casper.start('tests/site/confirm.html', function() { 47 | test.assertNot(this.getGlobal('confirmed'), 'confirmation dialog canceled'); 48 | }).run(function() { 49 | test.done(); 50 | }); 51 | } 52 | }); 53 | -------------------------------------------------------------------------------- /samples/multirun.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | /*global CasperError, console, phantom, require*/ 3 | 4 | var casper = require("casper").create({ 5 | verbose: true 6 | }); 7 | 8 | var countLinks = function() { 9 | return document.querySelectorAll('a').length; 10 | }; 11 | 12 | var suites = [ 13 | function() { 14 | this.echo("Suite 1"); 15 | this.start("http://google.com/", function() { 16 | this.echo("Page title: " + (this.getTitle())); 17 | }); 18 | this.then(function() { 19 | this.echo((this.evaluate(countLinks)) + " links"); 20 | }); 21 | }, function() { 22 | this.echo("Suite 2"); 23 | this.start("http://yahoo.com/", function() { 24 | this.echo("Page title: " + (this.getTitle())); 25 | }); 26 | this.then(function() { 27 | this.echo((this.evaluate(countLinks)) + " links"); 28 | }); 29 | }, function() { 30 | this.echo("Suite 3"); 31 | this.start("http://bing.com/", function() { 32 | this.echo("Page title: " + (this.getTitle())); 33 | }); 34 | this.then(function() { 35 | this.echo((this.evaluate(countLinks)) + " links"); 36 | }); 37 | } 38 | ]; 39 | 40 | casper.start(); 41 | 42 | casper.then(function() { 43 | this.echo("Starting"); 44 | }); 45 | 46 | var currentSuite = 0; 47 | 48 | var check = function() { 49 | if (suites[currentSuite]) { 50 | suites[currentSuite].call(this); 51 | currentSuite++; 52 | casper.run(check); 53 | } else { 54 | this.echo("All done."); 55 | this.exit(); 56 | } 57 | }; 58 | 59 | casper.run(check); 60 | -------------------------------------------------------------------------------- /samples/dynamic.coffee: -------------------------------------------------------------------------------- 1 | casper = require("casper").create 2 | verbose: true 3 | 4 | # The base links array 5 | links = [ 6 | "http://google.com/" 7 | "http://yahoo.com/" 8 | "http://bing.com/" 9 | ] 10 | 11 | currentLink = 0; 12 | 13 | # If we don't set a limit, it could go on forever 14 | upTo = ~~casper.cli.get(0) || 10 15 | 16 | ### 17 | Get the links, and add them to the links array 18 | (It could be done all in one step, but it is intentionally splitted) 19 | ### 20 | addLinks = (link) -> 21 | @then -> 22 | found = @evaluate searchLinks 23 | @echo "#{found.length} links found on #{link}" 24 | links = links.concat found 25 | 26 | ### 27 | Fetch all <a> elements from the page and return 28 | the ones which contains a href starting with 'http://' 29 | ### 30 | searchLinks = -> 31 | filter = Array::filter 32 | map = Array::map 33 | map.call filter.call(document.querySelectorAll("a"), (a) -> 34 | (/^http:\/\/.*/i).test a.getAttribute("href") 35 | ), (a) -> 36 | a.getAttribute "href" 37 | 38 | # Just opens the page and prints the title 39 | start = (link) -> 40 | @start link, -> 41 | @echo "Page title: #{ @getTitle() }" 42 | 43 | # As long as it has a next link, and is under the maximum limit, will keep running 44 | check = -> 45 | if links[currentLink] && currentLink < upTo 46 | @echo "--- Link #{currentLink} ---" 47 | start.call @, links[currentLink] 48 | addLinks.call @, links[currentLink] 49 | currentLink++ 50 | @run check 51 | else 52 | @echo "All done." 53 | @exit() 54 | 55 | casper.start() 56 | 57 | casper.then -> 58 | @echo "Starting" 59 | 60 | casper.run check 61 | -------------------------------------------------------------------------------- /tests/suites/casper/capture.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | var fs = require('fs'); 3 | 4 | casper.test.begin('Casper.capture() tests', 1, { 5 | testFile: '/tmp/__casper_test_capture.png', 6 | 7 | setUp: function(test) { 8 | if (fs.exists(this.testFile) && fs.isFile(this.testFile)) { 9 | try { 10 | fs.remove(this.testFile); 11 | } catch (e) { 12 | } 13 | } 14 | }, 15 | 16 | tearDown: function(test) { 17 | try { 18 | fs.remove(this.testFile); 19 | } catch(e) { 20 | } 21 | }, 22 | 23 | test: function(test) { 24 | var self = this; 25 | 26 | casper.start('tests/site/index.html', function() { 27 | this.viewport(300, 200); 28 | this.capture(self.testFile); 29 | test.assert(fs.isFile(self.testFile), 'Casper.capture() captured a screenshot'); 30 | }); 31 | 32 | casper.run(function() { 33 | test.done(); 34 | }); 35 | } 36 | }); 37 | 38 | casper.test.begin('Casper.captureBase64() tests', 3, function(test) { 39 | casper.start('tests/site/index.html', function() { 40 | test.assert(this.captureBase64('png').length > 0, 41 | 'Casper.captureBase64() rendered a page capture as base64'); 42 | test.assert(this.captureBase64('png', 'ul').length > 0, 43 | 'Casper.captureBase64() rendered a capture from a selector as base64'); 44 | test.assert(this.captureBase64('png', {top: 0, left: 0, width: 30, height: 30}).length > 0, 45 | 'Casper.captureBase64() rendered a capture from a clipRect as base64'); 46 | }).run(function() { 47 | test.done(); 48 | }); 49 | }); 50 | -------------------------------------------------------------------------------- /samples/googlepagination.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | /*global CasperError, console, phantom, require*/ 3 | 4 | /** 5 | * Capture multiple pages of google search results 6 | * 7 | * Usage: $ casperjs googlepagination.coffee my search terms 8 | * 9 | * (all arguments will be used as the query) 10 | */ 11 | 12 | var casper = require("casper").create({ 13 | waitTimeout: 1000, 14 | pageSettings: { 15 | userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:23.0) Gecko/20130404 Firefox/23.0" 16 | } 17 | }); 18 | var currentPage = 1; 19 | 20 | if (casper.cli.args.length === 0) { 21 | casper 22 | .echo("Usage: $ casperjs googlepagination.js my search terms") 23 | .exit(1) 24 | ; 25 | } 26 | 27 | var terminate = function() { 28 | this.echo("that's all, folks.").exit(); 29 | }; 30 | 31 | var processPage = function() { 32 | var url; 33 | this.echo("capturing page " + currentPage); 34 | this.capture("google-results-p" + currentPage + ".png"); 35 | 36 | // don't go too far down the rabbit hole 37 | if (currentPage >= 5 || !this.exists("#pnnext")) { 38 | return terminate.call(casper); 39 | } 40 | 41 | currentPage++; 42 | this.echo("requesting next page: " + currentPage); 43 | url = this.getCurrentUrl(); 44 | this.thenClick("#pnnext").then(function() { 45 | this.waitFor(function() { 46 | return url !== this.getCurrentUrl(); 47 | }, processPage, terminate); 48 | }); 49 | }; 50 | 51 | casper.start("http://google.fr/", function() { 52 | this.fill('form[action="/search"]', { 53 | q: casper.cli.args.join(" ") 54 | }, true); 55 | }); 56 | 57 | casper.waitForSelector('#pnnext', processPage, terminate); 58 | 59 | casper.run(); 60 | -------------------------------------------------------------------------------- /tests/suites/casper/navigation.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | var server = require('webserver').create(); 3 | var service = server.listen(8090, function(request, response) { 4 | response.statusCode = 200; 5 | response.setHeader('Content-type', 'text/html'); 6 | response.write('<a href="/link">a link</a>'); 7 | response.write('<form action="/form" method="POST"><input type="submit" /></form>'); 8 | response.close(); 9 | }); 10 | 11 | casper.test.begin('Link Navigation updates response', 2, function(test) { 12 | casper.start('http://localhost:8090', function(response) { 13 | casper.click('a'); 14 | casper.then(function(response) { 15 | test.assertUrlMatch( 16 | /\/link$/, 17 | 'URL matches anchor href' 18 | ); 19 | test.assertEquals( 20 | response.url, 21 | casper.page.url, 22 | 'response is consistent with the internal page' 23 | ); 24 | 25 | }); 26 | }).run(function() { 27 | test.done(); 28 | }); 29 | }); 30 | 31 | casper.test.begin('Form Submittal updates the response', 2, function(test) { 32 | casper.start('http://localhost:8090', function(response) { 33 | casper.fill('form', {}, true); 34 | casper.then(function(response) { 35 | test.assertUrlMatch( 36 | /\/form$/, 37 | 'URL matches form action' 38 | ); 39 | test.assertEquals( 40 | response.url, 41 | casper.page.url, 42 | 'response is consistent with the internal page' 43 | ); 44 | }); 45 | }).run(function() { 46 | test.done(); 47 | server.close(); 48 | }); 49 | }); 50 | -------------------------------------------------------------------------------- /docs/credits.rst: -------------------------------------------------------------------------------- 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.linkedin.com/pub/j%C3%A9r%C3%A9my-forveille/15/315/691>`_ 65 | 66 | You can download the logo sources here: 67 | 68 | - `logo CasperJS (PDF) <_static/images/logo_casperjs.pdf>`_ 69 | - `logo CasperJS (EPS) <_static/images/logo_casperjs.eps>`_ 70 | - `logo CasperJS (AI) <_static/images/logo_casperjs.ai>`_ 71 | 72 | These assets are under `MIT license <http://en.wikipedia.org/wiki/MIT_License>`_ 73 | -------------------------------------------------------------------------------- /tests/suites/casper/viewport.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | var utils = require('utils'); 3 | 4 | casper.test.begin('viewport() tests', 3, function(test) { 5 | casper.start(); 6 | casper.viewport(1337, 999); 7 | test.assertEquals(casper.page.viewportSize.width, 1337, 8 | 'Casper.viewport() can change the width of page viewport'); 9 | test.assertEquals(casper.page.viewportSize.height, 999, 10 | 'Casper.viewport() can change the height of page viewport'); 11 | test.assertRaises(casper.viewport, ['a', 'b'], 12 | 'Casper.viewport() validates viewport size data'); 13 | test.done(); 14 | }); 15 | 16 | casper.test.begin('viewport() asynchronous tests', 2, function(test) { 17 | var screenshotData; 18 | 19 | casper.start('tests/site/index.html').viewport(800, 600, function() { 20 | this.setContent(utils.format('<img src="data:image/png;base64,%s">', 21 | this.captureBase64('png',{ 22 | top: 0, 23 | left: 0, 24 | width: 800, 25 | height: 600 26 | }))); 27 | }); 28 | 29 | casper.then(function() { 30 | var imgInfo = this.getElementInfo('img'); 31 | // sometimes, setting viewport could take more time in slimerjs/gecko 32 | // and the image is not still ready: :-/ 33 | if (!test.skipIfEngine(2, { 34 | name: 'slimerjs', 35 | message: 'Casper.viewport() change test' 36 | })) { 37 | test.assertEquals(imgInfo.width, 800, 'Casper.viewport() changes width asynchronously'); 38 | test.assertEquals(imgInfo.height, 600, 'Casper.viewport() changes height asynchronously'); 39 | } 40 | }); 41 | 42 | casper.run(function() { 43 | test.done(); 44 | }); 45 | }); 46 | -------------------------------------------------------------------------------- /tests/suites/casper/encodedurl.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | 3 | var urlWithEncodedSpace = 'tests/site/has%20space.html'; 4 | var urlWithoutSpace = 'tests/site/index.html'; 5 | 6 | var urls = [urlWithEncodedSpace, urlWithoutSpace]; 7 | if (casper.cli.options.reverse) urls.reverse(); 8 | 9 | var phantomVersion = 'phantomjs ' + phantom.version.major + '.' + phantom.version.minor + '.' + phantom.version.patch; 10 | 11 | var numPageResourcesRequested = 0; 12 | var numPageResourcesReceived = 0; 13 | 14 | casper.on ('page.resource.requested', function ResourceRequested (resource) { 15 | ++numPageResourcesRequested; 16 | }); 17 | 18 | casper.on ('page.resource.received', function ResourceReceived (resource) { 19 | ++numPageResourcesReceived; 20 | }); 21 | 22 | casper.test.begin(phantomVersion + ' ' + urls[0] + ' then ' + urls[1], 8, function(test) { 23 | 24 | casper.start(urls[0], function CheckResponse1(response1) { 25 | test.assertEquals(numPageResourcesRequested, 1, 'page.resource.requested 1'); 26 | test.assertEquals(numPageResourcesReceived, 1, 'page.resource.received 1'); 27 | test.assertEquals(response1.status, 200, 'status 200 for ' + urls[0]); 28 | test.assertEquals(response1.url, casper.filter('open.location', urls[0]) || urls[0], 'opened ' + urls[0]); // Mimic Casper.prototype.open 29 | 30 | casper.thenOpen (urls[1], function CheckResponse2(response2) { 31 | test.assertEquals(numPageResourcesRequested, 2, 'page.resource.requested 2'); 32 | test.assertEquals(numPageResourcesReceived, 2, 'page.resource.received 2'); 33 | test.assertEquals(response2.status, 200, 'status 200 for ' + urls[1]); 34 | test.assertEquals(response2.url, casper.filter('open.location', urls[1]) || urls[1], 'opened ' + urls[1]); // Mimic Casper.prototype.open 35 | }); 36 | }); 37 | 38 | casper.run(function() { 39 | test.done(); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /tests/suites/casper/logging.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | 3 | casper.test.begin('logging tests', 4, function(test) { 4 | var oldLevel; 5 | casper.start('tests/site/index.html'); 6 | 7 | casper.then(casper.createStep(function() { 8 | oldLevel = casper.options.logLevel; 9 | 10 | casper.result.log = []; 11 | casper.options.logLevel = 'info'; 12 | casper.options.verbose = false; 13 | }, {skipLog: true})); 14 | 15 | casper.then(casper.createStep(function() { 16 | casper.log('foo', 'info'); 17 | }, {skipLog: true})); 18 | 19 | casper.then(casper.createStep(function() { 20 | test.assert(casper.result.log.some(function(e) { 21 | return e.message === 'foo' && e.level === 'info'; 22 | }), 'Casper.log() adds a log entry'); 23 | }, {skipLog: true})); 24 | 25 | casper.then(casper.createStep(function() { 26 | casper.options.logLevel = 'debug'; 27 | casper.options.verbose = false; 28 | casper.evaluate(function() { 29 | __utils__.log('debug message'); 30 | __utils__.log('info message', 'info'); 31 | }); 32 | }, {skipLog: true})); 33 | 34 | casper.then(casper.createStep(function() { 35 | test.assert(casper.result.log.some(function(e) { 36 | return e.message === 'debug message' && e.level === 'debug' && e.space === 'remote'; 37 | }), 'ClientUtils.log() adds a log entry'); 38 | test.assert(casper.result.log.some(function(e) { 39 | return e.message === 'info message' && e.level === 'info' && e.space === 'remote'; 40 | }), 'ClientUtils.log() adds a log entry at a given level'); 41 | test.assertEquals(this.result.log.length, 3, 'Casper.log() logged messages'); 42 | }, {skipLog: true})); 43 | 44 | casper.run(function() { 45 | test.done(); 46 | casper.options.logLevel = oldLevel; 47 | casper.options.verbose = true; 48 | }); 49 | }); 50 | -------------------------------------------------------------------------------- /tests/suites/casper/fetchtext.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | casper.test.begin('fetchText() basic tests', 1, function(test) { 3 | casper.start('tests/site/index.html', function() { 4 | test.assertEquals(this.fetchText('ul li'), 'onetwothree', 5 | 'Casper.fetchText() can retrieve text contents'); 6 | }).run(function() { 7 | test.done(); 8 | }); 9 | }); 10 | 11 | casper.test.begin('fetchText() basic tests', 1, function(test) { 12 | casper.start('tests/site/index.html', function() { 13 | test.assertEquals(this.fetchText('input[name="dummy_name"]'), 'dummy_value', 14 | 'Casper.fetchText() can retrieve text contents from an input element'); 15 | }).run(function() { 16 | test.done(); 17 | }); 18 | }); 19 | 20 | casper.test.begin('fetchText() handles HTML entities', 1, function(test) { 21 | casper.start().then(function() { 22 | this.setContent('<html><body>Voilà</body></html>'); 23 | test.assertEquals(this.fetchText('body'), 'Voilà', 24 | 'Casper.fetchText() fetches decoded text'); 25 | }); 26 | casper.run(function() { 27 | test.done(); 28 | }); 29 | }); 30 | 31 | casper.test.begin('fetchText() handles empty elements', 1, function(test) { 32 | casper.start().then(function() { 33 | this.setContent('<html><body></body></html>'); 34 | test.assertEquals(this.fetchText('body'), '', 35 | 'Casper.fetchText() fetches empty string'); 36 | }); 37 | casper.run(function() { 38 | test.done(); 39 | }); 40 | }); 41 | 42 | casper.test.begin('fetchText() handles plain texts', 1, function(test) { 43 | casper.start().then(function() { 44 | this.setContent('This is a plain text.'); 45 | test.assertEquals(this.fetchText('html'), 'This is a plain text.', 46 | 'Casper.fetchText() handles plain texts'); 47 | }); 48 | casper.run(function() { 49 | test.done(); 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /samples/googlematch.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | /*global CasperError, console, phantom, require*/ 3 | 4 | /** 5 | * Takes provided terms passed as arguments and query google for the number of 6 | * estimated results each have. 7 | * 8 | * Usage: 9 | * $ casperjs googlematch.js nicolas chuck borris 10 | * nicolas: 69600000 11 | * chuck: 49500000 12 | * borris: 2370000 13 | * winner is "nicolas" with 69600000 results 14 | */ 15 | 16 | var casper = require("casper").create({ 17 | verbose: true 18 | }); 19 | 20 | casper.fetchScore = function() { 21 | return this.evaluate(function() { 22 | var result = __utils__.findOne('#resultStats').innerText; 23 | return parseInt(/Environ ([0-9\s]{1,}).*/.exec(result)[1].replace(/\s/g, ''), 10); 24 | }); 25 | }; 26 | 27 | var terms = casper.cli.args; 28 | 29 | if (terms.length < 2) { 30 | casper 31 | .echo("Usage: $ casperjs googlematch.js term1 term2 [term3]...") 32 | .exit(1) 33 | ; 34 | } 35 | 36 | var scores = []; 37 | 38 | casper.echo("Let the match begin between \"" + (terms.join('", "')) + "\"!"); 39 | 40 | casper.start("http://google.fr/"); 41 | 42 | casper.each(terms, function(casper, term, i) { 43 | this.echo('Fetching score for ' + term); 44 | this.then(function() { 45 | this.fill('form[action="/search"]', {q: '"' + term + '"'}, true); 46 | }); 47 | this.then(function() { 48 | var score = this.fetchScore(); 49 | scores.push({ 50 | term: term, 51 | score: score 52 | }); 53 | this.echo(term + ': ' + score); 54 | }); 55 | }); 56 | 57 | casper.run(function() { 58 | if (scores.length === 0) { 59 | this.echo("No result found"); 60 | } else { 61 | scores.sort(function(a, b) { 62 | return b.score - a.score; 63 | }); 64 | var winner = scores[0]; 65 | this.echo("Winner is \"" + winner.term + "\" with " + winner.score + " results"); 66 | } 67 | this.exit(); 68 | }); 69 | -------------------------------------------------------------------------------- /samples/dynamic.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | /*global CasperError, console, phantom, require*/ 3 | 4 | var casper = require("casper").create({ 5 | verbose: true 6 | }); 7 | 8 | // The base links array 9 | var links = [ 10 | "http://google.com/", 11 | "http://yahoo.com/", 12 | "http://bing.com/" 13 | ]; 14 | 15 | // If we don't set a limit, it could go on forever 16 | var upTo = ~~casper.cli.get(0) || 10; 17 | 18 | var currentLink = 0; 19 | 20 | // Get the links, and add them to the links array 21 | // (It could be done all in one step, but it is intentionally splitted) 22 | function addLinks(link) { 23 | this.then(function() { 24 | var found = this.evaluate(searchLinks); 25 | this.echo(found.length + " links found on " + link); 26 | links = links.concat(found); 27 | }); 28 | } 29 | 30 | // Fetch all <a> elements from the page and return 31 | // the ones which contains a href starting with 'http://' 32 | function searchLinks() { 33 | var filter, map; 34 | filter = Array.prototype.filter; 35 | map = Array.prototype.map; 36 | return map.call(filter.call(document.querySelectorAll("a"), function(a) { 37 | return (/^http:\/\/.*/i).test(a.getAttribute("href")); 38 | }), function(a) { 39 | return a.getAttribute("href"); 40 | }); 41 | } 42 | 43 | // Just opens the page and prints the title 44 | function start(link) { 45 | this.start(link, function() { 46 | this.echo('Page title: ' + this.getTitle()); 47 | }); 48 | } 49 | 50 | // As long as it has a next link, and is under the maximum limit, will keep running 51 | function check() { 52 | if (links[currentLink] && currentLink < upTo) { 53 | this.echo('--- Link ' + currentLink + ' ---'); 54 | start.call(this, links[currentLink]); 55 | addLinks.call(this, links[currentLink]); 56 | currentLink++; 57 | this.run(check); 58 | } else { 59 | this.echo("All done."); 60 | this.exit(); 61 | } 62 | } 63 | 64 | casper.start().then(function() { 65 | this.echo("Starting"); 66 | }); 67 | 68 | casper.run(check); 69 | -------------------------------------------------------------------------------- /tests/suites/casper/urls.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | 3 | casper.test.begin('urls tests', 9, function(test) { 4 | var assertURL = function(match, message) { 5 | test.assertHttpStatus(200); 6 | test.assertUrlMatches(match, message); 7 | }; 8 | 9 | casper.start('tests/site/urls.html#fragment'); 10 | 11 | casper.waitForUrl(/urls.html/, function() { 12 | assertURL('urls.html', 'Casper.start loads URL with fragment'); 13 | test.assertEqual(casper.evaluate(function() { 14 | return location.hash; 15 | }), '#fragment', 'location.hash equals fragment'); 16 | }); 17 | 18 | casper.then(function() { 19 | this.clickLabel('raw unicode', 'a'); 20 | }); 21 | 22 | casper.waitForUrl(/Forlì/, 23 | assertURL.bind(this, 24 | 'Forlì', 25 | 'Casper.getCurrentUrl() retrieves a raw unicode URL' 26 | )); 27 | 28 | casper.then(function() { 29 | this.clickLabel('escaped', 'a'); 30 | }); 31 | 32 | casper.waitForUrl(/Farlì/, 33 | assertURL.bind(this, 34 | 'Farlì', 35 | 'Casper.getCurrentUrl() retrieves an escaped URL' 36 | )); 37 | 38 | casper.then(function() { 39 | this.clickLabel('uri encoded', 'a'); 40 | }); 41 | 42 | casper.waitForUrl(/Furlì/, 43 | assertURL.bind(this, 44 | 'Furlì', 45 | 'Casper.getCurrentUrl() retrieves a decoded URL' 46 | )); 47 | 48 | casper.run(function() { 49 | test.done(); 50 | }); 51 | }); 52 | 53 | // https://github.com/casperjs/casperjs/issues/841 54 | casper.test.begin('url tests with javascript disabled', 1, function(test) { 55 | casper.options.pageSettings.javascriptEnabled = false; 56 | casper.start('tests/site/urls.html'); 57 | casper.then(function() { 58 | test.assertMatch(this.getCurrentUrl(), /urls\.html$/, 59 | 'Casper.getCurrentUrl() can work, with javascript disabled'); 60 | }); 61 | casper.run(function() { 62 | test.done(); 63 | casper.options.pageSettings.javascriptEnabled = true; 64 | }); 65 | }); 66 | -------------------------------------------------------------------------------- /CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | # CasperJS contributors 2 | 3 | You can check out the [contribution graphs on github](https://github.com/casperjs/casperjs/graphs/contributors). 4 | 5 | ``` 6 | $ git shortlog -s -n | cut -c8- 7 | Nicolas Perriault 8 | Mickaël Andrieu 9 | Laurent Jouanneau 10 | hexid 11 | Brikou CARRE 12 | oncletom 13 | Matt DuVall 14 | Nathan Black 15 | hannyu 16 | Julien Muetton 17 | Chris Bosco 18 | Matt Bowman 19 | Shiryaev Andrey 20 | mickaelandrieu 21 | Clochix 22 | Chris Lorenzo 23 | Victor Yap 24 | JF Paradis 25 | Matthew DuVall 26 | Rob Barreca 27 | Oleg Pudeyev 28 | pborreli 29 | nrabinowitz 30 | Darrell Hamilton 31 | Tyler Ritchie 32 | Andrew Childs 33 | Eric Bouchut 34 | Dave Lee 35 | Solomon White 36 | Luke Rodgers 37 | reina.sweet 38 | renatodarrigo 39 | Donovan Hutchinson 40 | Sean Massa 41 | Vladimir Chizhov 42 | Samuel Gabel 43 | Reina Sweet 44 | Jan Schaumann 45 | fwebdev 46 | Reid Lynch 47 | Justin Collum 48 | Philip Hansen 49 | Michael Geers 50 | Orchestrator81 51 | Nick Currier 52 | Julien Moulin 53 | Elmar Langholz 54 | Jason Funk 55 | Lee Byrd 56 | Thomas Rosenau 57 | V Sreekanth 58 | Patrick Reagan 59 | Andrew de Andrade 60 | Andy Shinn 61 | Ben Johnson 62 | Ben Lowery 63 | Bert Pareyn 64 | Brandon Bethke 65 | Charlie Park 66 | Chris Winters 67 | Christophe Benz 68 | Dharrya 69 | Dmitry Menshikov 70 | Florent DUBOST 71 | Harrison Reiser 72 | Itamar Nabriski 73 | Ivan 74 | Jamey J. DeOrio 75 | Jan Pochyla 76 | Jan-Martin Fruehwacht 77 | John F. Douthat 78 | Julian Gruber 79 | Justin Marsan 80 | Justin Slattery 81 | Justine Tunney 82 | KaroDidi 83 | Leandro Boscariol 84 | Maisons du monde 85 | Marcel Duran 86 | Mathieu Agopian 87 | Mehdi Kabab 88 | Miguel González 89 | Mikhail Korobov 90 | Mikko Peltonen 91 | Narno 92 | Pascal Borreli 93 | Phillip Alexander 94 | Rafael 95 | Rafael Garcia 96 | Raphaël Benitte 97 | Rock Li 98 | Scott 99 | Thomas Parisot 100 | Tim Bunce 101 | Tzvi Friedman 102 | Yasuo Ohgaki 103 | Yevgeny Smirnov 104 | alfetopito 105 | jayseeg 106 | jean-philippe serafin 107 | shekyan 108 | snkashis 109 | ``` 110 | -------------------------------------------------------------------------------- /docs/logging.rst: -------------------------------------------------------------------------------- 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. 70 | -------------------------------------------------------------------------------- /samples/bbcshots.coffee: -------------------------------------------------------------------------------- 1 | ### 2 | Create a mosaic image from all headline photos on BBC homepage 3 | ### 4 | 5 | casper = require("casper").create() 6 | nbLinks = 0 7 | currentLink = 1 8 | images = [] 9 | 10 | # helper to hide some element from remote DOM 11 | casper.hide = (selector) -> 12 | @evaluate (selector) -> 13 | document.querySelector(selector).style.display = "none" 14 | , selector 15 | 16 | casper.start "http://www.bbc.co.uk/", -> 17 | nbLinks = @evaluate -> 18 | return __utils__.findAll('#promo2_carousel_items_items li').length 19 | @echo "#{nbLinks} items founds" 20 | # hide navigation arrows 21 | @hide ".nav_left" 22 | @hide ".nav_right" 23 | @mouse.move "#promo2_carousel" 24 | 25 | casper.waitUntilVisible ".autoplay.nav_pause", -> 26 | @echo "Moving over pause button" 27 | @mouse.move ".autoplay.nav_pause" 28 | @click ".autoplay.nav_pause" 29 | @echo "Clicked on pause button" 30 | @waitUntilVisible ".autoplay.nav_play", -> 31 | @echo "Carousel has been paused" 32 | # hide play button 33 | @hide ".autoplay" 34 | 35 | # Capture carrousel area 36 | next = -> 37 | image = "bbcshot#{currentLink}.png" 38 | images.push image 39 | @echo "Processing image #{currentLink}" 40 | @captureSelector image, '.carousel_viewport' 41 | if currentLink < nbLinks 42 | @click ".carousel_itemList_li[rel='#{currentLink}']" 43 | @wait 1000, -> 44 | @then next 45 | currentLink++ 46 | else 47 | @then buildPage 48 | 49 | # Building resulting page and image 50 | buildPage = -> 51 | @echo "Build result page" 52 | fs = require "fs" 53 | @viewport 624, 400 54 | pageHtml = "<html><body style='background:black;margin:0;padding:0'>" 55 | images.forEach (image) -> 56 | pageHtml += "<img src='file://#{fs.workingDirectory}/#{image}'><br>" 57 | pageHtml += "</body></html>" 58 | fs.write "result.html", pageHtml, 'w' 59 | @thenOpen "file://#{fs.workingDirectory}/result.html", -> 60 | @echo "Resulting image saved to result.png" 61 | @capture "result.png" 62 | 63 | casper.then next 64 | 65 | casper.run() 66 | -------------------------------------------------------------------------------- /tests/suites/casper/steps.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | casper.test.begin('steps tests', 8, function(test) { 3 | casper.start('tests/site/index.html'); 4 | 5 | var nsteps = casper.steps.length; 6 | 7 | casper.then(function(response) { 8 | test.assertTitle('CasperJS test index', 9 | 'Casper.then() added a new step'); 10 | }); 11 | 12 | test.assertEquals(casper.steps.length, nsteps + 1, 13 | 'Casper.then() can add a new step'); 14 | 15 | casper.thenOpen('tests/site/test.html'); 16 | 17 | test.assertEquals(casper.steps.length, nsteps + 2, 18 | 'Casper.thenOpen() can add a new step'); 19 | 20 | casper.thenOpen('tests/site/test.html', function() { 21 | test.assertTitle('CasperJS test target', 22 | 'Casper.thenOpen() opened a location and executed a step'); 23 | }); 24 | 25 | test.assertEquals(casper.steps.length, nsteps + 4, 26 | 'Casper.thenOpen() can add a new step for opening, plus another step'); 27 | 28 | casper.each([1, 2, 3], function(self, item, i) { 29 | test.assertEquals(i, item - 1, 30 | 'Casper.each() passes a contextualized index'); 31 | }); 32 | 33 | casper.run(function() { 34 | test.done(); 35 | }); 36 | }); 37 | 38 | casper.test.begin('eachThen() tests', 2, function(test) { 39 | var received = []; 40 | var receivedFalsy = []; 41 | 42 | casper.start().eachThen([1, 2, 3], function(response) { 43 | if (!response) { 44 | test.fail('No response received'); 45 | } 46 | received.push(response.data); 47 | }); 48 | 49 | casper.then(function() { 50 | test.assertEquals(received, [1, 2, 3], 51 | 'Casper.eachThen() passes item to step data'); 52 | }); 53 | 54 | casper.eachThen([false, 0, ''], function(response) { 55 | if (!response) { 56 | test.fail('No response received'); 57 | } 58 | receivedFalsy.push(response.data); 59 | }); 60 | 61 | casper.then(function() { 62 | test.assertEquals(receivedFalsy, [false, 0, ''], 63 | 'Casper.eachThen() passes falsy items to step data'); 64 | }); 65 | 66 | casper.run(function() { 67 | test.done(); 68 | }); 69 | }); 70 | -------------------------------------------------------------------------------- /tests/suites/tester/testsuite.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | /*global CasperError, casper, console, phantom, require*/ 3 | 4 | var TestCaseResult = require('tester').TestCaseResult, 5 | TestSuiteResult = require('tester').TestSuiteResult; 6 | 7 | function generateCaseResult(options) { 8 | var i, 9 | nPasses = options && ~~options.nPasses, 10 | nFailures = options && ~~options.nFailures, 11 | caseResult = new TestCaseResult(options); 12 | for (i = 0; i < nFailures; i++) { 13 | caseResult.addFailure({}, i * 1000); 14 | } 15 | for (i = 0; i < nPasses; i++) { 16 | caseResult.addSuccess({}, i * 1000); 17 | } 18 | return caseResult; 19 | } 20 | 21 | casper.test.begin('TestSuiteResult() basic tests', 8, function(test) { 22 | var suiteResult = new TestSuiteResult(); 23 | test.assertEquals(suiteResult.constructor.name, 'Array', 'TestSuiteResult() is derived from Array'); 24 | test.assertEquals(suiteResult.countTotal(), 0); 25 | test.assertEquals(suiteResult.countFailed(), 0); 26 | test.assertEquals(suiteResult.countPassed(), 0); 27 | test.assertEquals(suiteResult.getAllFailures(), []); 28 | test.assertEquals(suiteResult.getAllPasses(), []); 29 | test.assertEquals(suiteResult.getAllResults(), []); 30 | test.assertEquals(suiteResult.calculateDuration(), 0); 31 | test.done(); 32 | }); 33 | 34 | casper.test.begin('TestSuiteResult() accumulation tests', 7, function(test) { 35 | var suiteResult = new TestSuiteResult(); 36 | suiteResult.push(generateCaseResult({ 37 | name: 'foo', 38 | file: '/tmp/foo', 39 | nPasses: 4, 40 | nFailures: 1 41 | })); 42 | suiteResult.push(generateCaseResult({ 43 | name: 'bar', 44 | file: '/tmp/bar', 45 | nPasses: 3, 46 | nFailures: 0 47 | })); 48 | test.assertEquals(suiteResult.countTotal(), 8); 49 | test.assertEquals(suiteResult.countFailed(), 1); 50 | test.assertEquals(suiteResult.countPassed(), 7); 51 | test.assertEquals(suiteResult.getAllFailures().length, 1); 52 | test.assertEquals(suiteResult.getAllPasses().length, 7); 53 | test.assertEquals(suiteResult.getAllResults().length, 8); 54 | test.assertEquals(suiteResult.calculateDuration(), 9000); 55 | test.done(); 56 | }); 57 | -------------------------------------------------------------------------------- /docs/writing_modules.rst: -------------------------------------------------------------------------------- 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 use 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 | require = patchRequire global.require 28 | 29 | utils = require 'utils' 30 | magic = 42 31 | exports.answer = -> 32 | utils.format "it's ${magic}" 33 | 34 | From your root casper script:: 35 | 36 | var universe = require('./universe'); 37 | console.log(universe.answer()); // prints "It's 42" 38 | 39 | .. versionadded:: 1.1. 40 | 41 | .. hint:: 42 | 43 | CasperJS allows using nodejs modules installed through npm_. Note that since CasperJS uses it's own JavaScript environment, npm modules that use node-specific features will not work under CasperJS. 44 | 45 | As an example, let's install the underscore_ library: 46 | 47 | .. _npm: https://npmjs.org/ 48 | .. _underscore: http://underscorejs.org/ 49 | 50 | .. code-block:: text 51 | 52 | $ npm install underscore 53 | 54 | 55 | Then, ``require`` it like you would with any other nodejs compliant module:: 56 | 57 | //npm-underscore-test.js 58 | var _ = require('underscore'); 59 | var casper = require('casper').create(); 60 | var urls = _.uniq([ 61 | 'http://google.com/', 62 | 'http://docs.casperjs.org/', 63 | 'http://google.com/' 64 | ]); 65 | 66 | casper.start().eachThen(urls, function(response) { 67 | this.thenOpen(response.data, function(response) { 68 | this.echo(this.getTitle()); 69 | }); 70 | }); 71 | 72 | casper.run(); 73 | 74 | 75 | Finally, you’ll probably get something like this: 76 | 77 | .. code-block:: text 78 | 79 | $ casperjs npm-underscore-test.js 80 | Google 81 | CasperJS documentation | CasperJS 1.1.0-DEV documentation 82 | 83 | 84 | -------------------------------------------------------------------------------- /tests/site/area.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html> 3 | 4 | <head> 5 | <title>Move to Click Position 6 | 47 | 48 | 49 | 50 |
    51 |
    52 |
    53 | 54 |
    55 |
    56 |
    57 | 58 | 59 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /modules/http.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Casper is a navigation utility for PhantomJS. 3 | * 4 | * Documentation: http://casperjs.org/ 5 | * Repository: http://github.com/casperjs/casperjs 6 | * 7 | * Copyright (c) 2011-2012 Nicolas Perriault 8 | * 9 | * Part of source code is Copyright Joyent, Inc. and other Node contributors. 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a 12 | * copy of this software and associated documentation files (the "Software"), 13 | * to deal in the Software without restriction, including without limitation 14 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 15 | * and/or sell copies of the Software, and to permit persons to whom the 16 | * Software is furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included 19 | * in all copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 22 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 24 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 27 | * DEALINGS IN THE SOFTWARE. 28 | * 29 | */ 30 | 31 | var require = patchRequire(require); 32 | var utils = require('utils'); 33 | 34 | /* 35 | * Building an Array subclass 36 | */ 37 | function responseHeaders(){} 38 | responseHeaders.prototype = []; 39 | 40 | /** 41 | * Retrieves a given header based on its name 42 | * 43 | * @param String name A case-insensitive response header name 44 | * @return mixed A header string or `null` if not found 45 | */ 46 | responseHeaders.prototype.get = function get(name){ 47 | "use strict"; 48 | var headerValue = null; 49 | name = name.toLowerCase(); 50 | this.some(function(header){ 51 | if (header.name.toLowerCase() === name){ 52 | headerValue = header.value; 53 | return true; 54 | } 55 | }); 56 | return headerValue; 57 | }; 58 | 59 | /** 60 | * Augments the response with proper prototypes. 61 | * 62 | * @param Mixed response Phantom response or undefined (generally with local files) 63 | * @return Object Augmented response 64 | */ 65 | exports.augmentResponse = function(response) { 66 | "use strict"; 67 | if (!utils.isHTTPResource(response)) { 68 | return; 69 | } 70 | response.headers.__proto__ = responseHeaders.prototype; 71 | return response; 72 | }; 73 | -------------------------------------------------------------------------------- /samples/bbcshots.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | /*global CasperError, console*/ 3 | 4 | /** 5 | * Create a mosaic image from all headline photos on BBC homepage 6 | */ 7 | var casper = require("casper").create(); 8 | var nbLinks = 0; 9 | var currentLink = 1; 10 | var images = []; 11 | var buildPage, next; 12 | 13 | // helper to hide some element from remote DOM 14 | casper.hide = function(selector) { 15 | this.evaluate(function(selector) { 16 | document.querySelector(selector).style.display = "none"; 17 | }, selector); 18 | }; 19 | 20 | casper.start("http://www.bbc.co.uk/", function() { 21 | nbLinks = this.evaluate(function() { 22 | return __utils__.findAll('#promo2_carousel_items_items li').length; 23 | }); 24 | this.echo(nbLinks + " items founds"); 25 | // hide navigation arrows 26 | this.hide(".nav_left"); 27 | this.hide(".nav_right"); 28 | this.mouse.move("#promo2_carousel"); 29 | }); 30 | 31 | casper.waitUntilVisible(".autoplay.nav_pause", function() { 32 | this.echo("Moving over pause button"); 33 | this.mouse.move(".autoplay.nav_pause"); 34 | this.click(".autoplay.nav_pause"); 35 | this.echo("Clicked on pause button"); 36 | this.waitUntilVisible(".autoplay.nav_play", function() { 37 | this.echo("Carousel has been paused"); 38 | // hide play button 39 | this.hide(".autoplay"); 40 | }); 41 | }); 42 | 43 | // Capture carrousel area 44 | next = function() { 45 | var image; 46 | image = "bbcshot" + currentLink + ".png"; 47 | images.push(image); 48 | this.echo("Processing image " + currentLink); 49 | this.captureSelector(image, '.carousel_viewport'); 50 | if (currentLink < nbLinks) { 51 | this.click(".carousel_itemList_li[rel='" + currentLink + "']"); 52 | this.wait(1000, function() { 53 | this.then(next); 54 | currentLink++; 55 | }); 56 | } else { 57 | this.then(buildPage); 58 | } 59 | }; 60 | 61 | // Building resulting page and image 62 | buildPage = function() { 63 | var fs, pageHtml; 64 | this.echo("Build result page"); 65 | fs = require("fs"); 66 | this.viewport(624, 400); 67 | pageHtml = ""; 68 | images.forEach(function(image) { 69 | pageHtml += "
    "; 70 | }); 71 | pageHtml += ""; 72 | fs.write("result.html", pageHtml, 'w'); 73 | this.thenOpen("file://" + fs.workingDirectory + "/result.html", function() { 74 | this.echo("Resulting image saved to result.png"); 75 | this.capture("result.png"); 76 | }); 77 | }; 78 | 79 | casper.then(next); 80 | 81 | casper.run(); 82 | -------------------------------------------------------------------------------- /tests/site/mouse-events.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CasperJS test mouse events 6 | 7 | 8 | 9 | test 10 | test 11 | test 12 | test 13 | test 14 | test 15 | test 16 | test 17 | MENU (move over me) 18 |
    • test
    • 19 | 21 | 22 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /tests/suites/casper/mouseevents.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0, max-statements:0*/ 2 | casper.on('remote.message',function(e){ 3 | console.log(e); 4 | }); 5 | 6 | casper.test.begin('mouseEvent() tests', 20, function(test) { 7 | casper.start('tests/site/mouse-events.html', function() { 8 | test.assert(this.mouseEvent('mousedown', '#test1'), 'Casper.mouseEvent() can dispatch a mousedown event'); 9 | test.assert(this.mouseEvent('mousedown', '#test2'), 'Casper.mouseEvent() can dispatch a mousedown event handled by unobstrusive js'); 10 | test.assert(this.mouseEvent('mouseup', '#test3'), 'Casper.mouseEvent() can dispatch a mouseup event'); 11 | test.assert(this.mouseEvent('mouseup', '#test4'), 'Casper.mouseEvent() can dispatch a mouseup event handled by unobstrusive js'); 12 | test.assert(this.mouseEvent('mouseover', '#test5'), 'Casper.mouseEvent() can dispatch a mouseover event'); 13 | test.assert(this.mouseEvent('mouseover', '#test6'), 'Casper.mouseEvent() can dispatch a mouseover event handled by unobstrusive js'); 14 | test.assert(this.mouseEvent('mouseout', '#test7'), 'Casper.mouseEvent() can dispatch a mouseout event'); 15 | test.assert(this.mouseEvent('mouseout', '#test8'), 'Casper.mouseEvent() can dispatch a mouseout event handled by unobstrusive js'); 16 | test.assertFalsy(this.mouseEvent('click', '#test9'), 'Casper.mouseEvent() can dispatch a click event on an hidden element'); 17 | test.assertFalsy(this.mouseEvent('click', '#test10'), 'Casper.mouseEvent() can dispatch a click event handled by unobstrusive js on an hidden element '); 18 | }); 19 | 20 | casper.then(function() { 21 | var results = this.getGlobal('results'); 22 | test.assert(results.test1, 'Casper.mouseEvent() triggered mousedown'); 23 | test.assert(results.test2, 'Casper.mouseEvent() triggered mousedown via unobstrusive js'); 24 | test.assert(results.test3, 'Casper.mouseEvent() triggered mouseup'); 25 | test.assert(results.test4, 'Casper.mouseEvent() triggered mouseup via unobstrusive js'); 26 | test.assert(results.test5, 'Casper.mouseEvent() triggered mouseover'); 27 | test.assert(results.test6, 'Casper.mouseEvent() triggered mouseover via unobstrusive js'); 28 | test.assert(results.test7, 'Casper.mouseEvent() triggered mouseout'); 29 | test.assert(results.test8, 'Casper.mouseEvent() triggered mouseout via unobstrusive js'); 30 | test.assertFalsy(results.test9, 'Casper.mouseEvent() triggered click on an hidden element'); 31 | test.assertFalsy(results.test10, 'Casper.mouseEvent() triggered click on an hidden element via unobstrusive js'); 32 | }); 33 | 34 | casper.run(function() { 35 | test.done(); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /tests/selftest.js: -------------------------------------------------------------------------------- 1 | 2 | var require = patchRequire(require); 3 | var colorizer = require('colorizer').create('Colorizer'); 4 | var fs = require('fs'); 5 | var utils = require('utils'); 6 | var server = require('webserver').create(); 7 | var service; 8 | var testServerPort = 54321; 9 | 10 | var contentTypes = { 11 | html: {type: 'text/html', binMode: false}, 12 | js: {type: 'application/javascript', binMode: false}, 13 | json: {type: 'application/json', binMode: false}, 14 | txt: {type: 'text/plain', binMode: false}, 15 | png: {type: 'image/png', binMode: true}, 16 | notype: {type: null, binMode: false}, 17 | _default: {type: 'application/octet-stream', binMode: true} 18 | }; 19 | var extensionRE = /\.([a-zA-Z]*)$/; 20 | 21 | function info(message) { 22 | "use strict"; 23 | console.log(colorizer.colorize('INFO', 'INFO_BAR') + ' ' + message); 24 | } 25 | 26 | service = server.listen(testServerPort, function(request, response) { 27 | "use strict"; 28 | /*eslint max-statements:0*/ 29 | var requestPath = request.url; 30 | if (requestPath.indexOf('?') !== -1) { 31 | requestPath = request.url.split('?')[0]; 32 | } 33 | var pageFile = fs.pathJoin(phantom.casperPath, requestPath); 34 | if (!fs.exists(pageFile) || !fs.isFile(pageFile)) { 35 | response.statusCode = 404; 36 | console.log(utils.format('Test server url not found: %s (file: %s)', request.url, pageFile), "warning"); 37 | response.write("404 - NOT FOUND"); 38 | } else { 39 | var headers = {}; 40 | var binMode; 41 | 42 | var extension = extensionRE.exec(pageFile); 43 | extension = extension && extension[1]; 44 | var contentType = contentTypes[extension] || 45 | contentTypes._default; 46 | 47 | if (contentType.type) { 48 | headers['Content-Type'] = contentType.type; 49 | } 50 | binMode = contentType.binMode; 51 | 52 | response.writeHead(200, headers); 53 | 54 | if (binMode) { 55 | response.write(fs.read(pageFile, 'b')); 56 | } 57 | else { 58 | response.write(fs.read(pageFile)); 59 | } 60 | } 61 | response.close(); 62 | }); 63 | 64 | // overriding Casper.open to prefix all test urls 65 | casper.setFilter('open.location', function(location) { 66 | "use strict"; 67 | if (/^file/.test(location)) { 68 | return location; 69 | } 70 | if (!/^http/.test(location)) { 71 | return utils.format('http://localhost:%d/%s', testServerPort, location); 72 | } 73 | return location; 74 | }); 75 | 76 | // test suites completion listener 77 | casper.test.on('tests.complete', function() { 78 | "use strict"; 79 | server.close(); 80 | }); 81 | -------------------------------------------------------------------------------- /tests/suites/casper/hooks.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | casper.test.begin('onStepComplete() hook tests', 1, function(test) { 3 | var stepResults = []; 4 | casper.options.onStepComplete = function(self, stepResult) { 5 | stepResults.push(stepResult); 6 | }; 7 | casper.start('tests/site/index.html', function() { 8 | return 'ok'; 9 | }); 10 | casper.run(function() { 11 | test.assert(stepResults.indexOf('ok') > -1, 12 | 'Casper.options.onStepComplete() is called on step complete'); 13 | this.options.onStepComplete = undefined; 14 | test.done(); 15 | }); 16 | }); 17 | 18 | casper.test.begin('onResourceRequested() & onResourceReceived() hook tests', 6, function(test) { 19 | var requests = [], responses = []; 20 | casper.options.onResourceRequested = function(self, request) { 21 | requests.push(request); 22 | }; 23 | casper.options.onResourceReceived = function(self, response) { 24 | responses.push(response); 25 | }; 26 | casper.start('tests/site/index.html', function() { 27 | test.assert(requests.some(function(request) { 28 | return (/index\.html$/).test(request.url); 29 | }), 'onResourceRequested() receives page requests'); 30 | test.assert(requests.some(function(request) { 31 | return (/phantom\.png$/).test(request.url); 32 | }), 'onResourceRequested() receives image requests'); 33 | test.assert(responses.some(function(response) { 34 | return response.stage === 'start' && (/index\.html$/).test(response.url); 35 | }), 'onResourceReceived() receives page response on load start'); 36 | test.assert(responses.some(function(response) { 37 | return response.stage === 'end' && (/index\.html$/).test(response.url); 38 | }), 'onResourceReceived() receives page response on load end'); 39 | test.assert(responses.some(function(response) { 40 | return response.stage === 'start' && (/phantom\.png$/).test(response.url); 41 | }), 'onResourceReceived() receives image response on load start'); 42 | test.assert(responses.some(function(response) { 43 | return response.stage === 'end' && (/phantom\.png$/).test(response.url); 44 | }), 'onResourceReceived() receives image response on load end'); 45 | }); 46 | casper.run(function() { 47 | this.options.onResourceReceived = this.options.onResourceRequested = undefined; 48 | test.done(); 49 | }); 50 | }); 51 | 52 | casper.test.begin('onAlert() hook tests', 1, function(test) { 53 | var message; 54 | casper.options.onAlert = function(self, msg) { 55 | message = msg; 56 | }; 57 | casper.start('tests/site/alert.html', function() { 58 | test.assertEquals(message, 'plop', 'Casper.options.onAlert() can intercept an alert message'); 59 | }); 60 | casper.run(function() { 61 | this.options.onAlert = null; 62 | test.done(); 63 | }); 64 | }); 65 | -------------------------------------------------------------------------------- /tests/suites/http_status.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | /** 3 | * Special test server to test for HTTP status codes 4 | * 5 | */ 6 | var fs = require('fs'); 7 | var utils = require('utils'); 8 | 9 | casper.test.begin("HTTP status code handling", 163, { 10 | setUp: function(test) { 11 | this.server = require('webserver').create(); 12 | this.server.listen(8090, function (request, response) { 13 | response.statusCode = parseInt(/^\/(\d+)$/.exec(request.url)[1], 10); 14 | response.write(""); 15 | response.close(); 16 | }); 17 | var isGecko = (phantom.casperEngine === 'slimerjs'); 18 | 19 | this.testCodes = [ 20 | 100, 101, 200, 201, 202, 203, 204, 205, 206, 207, 210, 21 | 300, 301, 302, 303, 304, 305, 307, 310 22 | ]; 23 | if (!isGecko) { 24 | // it seems that the network layer of Gecko does not process these response 25 | this.testCodes.push(102); 26 | this.testCodes.push(118); 27 | } 28 | 29 | if (utils.ltVersion(phantom.version, '1.9.0') || 30 | utils.gteVersion(phantom.version, '1.9.2') || 31 | isGecko) { 32 | // https://github.com/ariya/phantomjs/issues/11163 33 | this.testCodes = this.testCodes.concat([ 34 | 400, 401, 402, 403, 404, 405, 406, 407, 409, 410, 411, 412, 413, 35 | 414, 415, 416, 417, 418, 422, 423, 424, 425, 426, 449, 450, 36 | 500, 501, 502, 503, 504, 505, 507, 509 37 | ]); 38 | if (!isGecko) { 39 | // it seems that the network layer of Gecko has a different 40 | // behavior for 408 than PhantomJS's webkit 41 | this.testCodes.push(408); 42 | } 43 | } 44 | if ((this.testCodes.length * 3) < 165 ) { 45 | test.skip(163 - (this.testCodes.length * 3 - 2) ); 46 | } 47 | }, 48 | 49 | tearDown: function() { 50 | this.server.close(); 51 | }, 52 | 53 | test: function(test) { 54 | casper.start(); 55 | 56 | // file protocol 57 | casper.thenOpen('file://' + phantom.casperPath + '/tests/site/index.html', function() { 58 | this.test.assertHttpStatus(null, 'file:// protocol does not set a HTTP status'); 59 | }); 60 | 61 | casper.each(this.testCodes, function(self, code) { 62 | if (code === 100) { 63 | // HTTP 100 is CONTINUE, so don't expect a terminated response 64 | return; 65 | } 66 | this.thenOpen('http://localhost:8090/' + code, function(resource) { 67 | test.assertEquals(resource.status, code, 68 | 'Status is stored in resource.status'); 69 | test.assertEquals(this.currentHTTPStatus, code, 70 | 'Status is stored in casper.currentHTTPStatus'); 71 | test.assertHttpStatus(code, utils.format('HTTP %d handled' , code)); 72 | }); 73 | }); 74 | 75 | casper.run(function() { 76 | this.test.done(); 77 | }); 78 | } 79 | }); 80 | -------------------------------------------------------------------------------- /rpm/casperjs.spec: -------------------------------------------------------------------------------- 1 | %define name casperjs 2 | %if "%{_version}" 3 | %define version %{_version} 4 | %else 5 | %define version 1.0 6 | %endif 7 | %define release 1 8 | %define prefix /usr 9 | 10 | %define mybuilddir %{_builddir}/%{name}-%{version}-root 11 | 12 | Summary: open source navigation scripting & testing utility written in Javascript 13 | Name: %{name} 14 | Version: %{version} 15 | License: BSD 16 | Release: %{release} 17 | Packager: Jan Schaumann 18 | Group: Utilities/Misc 19 | Source: %{name}-%{version}.tar.gz 20 | BuildRoot: /tmp/%{name}-%{version}-root 21 | 22 | Requires: phantomjs 23 | 24 | %description 25 | CasperJS is an open source navigation scripting & testing utility written 26 | in Javascript and based on PhantomJS. It eases the process of defining a 27 | full navigation scenario and provides useful high-level functions, methods 28 | & syntactic sugar for doing common tasks 29 | 30 | %prep 31 | %setup -q 32 | 33 | %install 34 | mkdir -p %{mybuilddir}%{prefix}/bin 35 | mkdir -p %{mybuilddir}%{prefix}/share/%{name}/bin 36 | mkdir -p %{mybuilddir}%{prefix}/share/%{name}/modules 37 | mkdir -p %{mybuilddir}%{prefix}/share/%{name}/samples 38 | mkdir -p %{mybuilddir}%{prefix}/share/%{name}/tests 39 | 40 | cp bin/%{name} %{mybuilddir}%{prefix}/share/%{name}/bin/ 41 | ln -s %{prefix}/share/%{name}/bin/%{name} %{mybuilddir}%{prefix}/bin/%{name} 42 | cp bin/bootstrap.js %{mybuilddir}%{prefix}/share/%{name}/bin/ 43 | # Yes, this tool needs this file in the 'bin' directory. 44 | cp bin/usage.txt %{mybuilddir}%{prefix}/share/%{name}/bin/ 45 | cp CHANGELOG.md %{mybuilddir}%{prefix}/share/%{name}/ 46 | cp CONTRIBUTING.md %{mybuilddir}%{prefix}/share/%{name}/ 47 | cp CONTRIBUTORS.md %{mybuilddir}%{prefix}/share/%{name}/ 48 | cp LICENSE.md %{mybuilddir}%{prefix}/share/%{name}/ 49 | cp README.md %{mybuilddir}%{prefix}/share/%{name}/ 50 | cp package.json %{mybuilddir}%{prefix}/share/%{name}/ 51 | cp -R modules/* %{mybuilddir}%{prefix}/share/%{name}/modules/ 52 | cp -R samples/* %{mybuilddir}%{prefix}/share/%{name}/samples/ 53 | cp -R tests/* %{mybuilddir}%{prefix}/share/%{name}/tests/ 54 | 55 | %files 56 | %defattr(0444,root,root) 57 | %attr(0555,root,root)%{prefix}/bin/%{name} 58 | %attr(0555,root,root)%{prefix}/share/%{name}/bin/%{name} 59 | %attr(0555,root,root)%{prefix}/share/%{name}/bin/bootstrap.js 60 | %{prefix}/share/%{name}/bin/usage.txt 61 | %{prefix}/share/%{name}/CHANGELOG.md 62 | %{prefix}/share/%{name}/CONTRIBUTING.md 63 | %{prefix}/share/%{name}/CONTRIBUTORS.md 64 | %{prefix}/share/%{name}/LICENSE.md 65 | %{prefix}/share/%{name}/README.md 66 | %{prefix}/share/%{name}/package.json 67 | %{prefix}/share/%{name}/modules/* 68 | %{prefix}/share/%{name}/samples/* 69 | %{prefix}/share/%{name}/tests/* 70 | 71 | %changelog 72 | * Fri Nov 15 2013 Yasuo Ohgaki 73 | - update spec for master and other branches 74 | 75 | * Mon Dec 24 2012 Nicolas Perriault 76 | - removed 'injector.js' module 77 | 78 | * Mon Dec 10 2012 Jan Schaumann 79 | - include 'tests' 80 | 81 | * Mon Nov 26 2012 Jan Schaumann 82 | - first rpm version 83 | -------------------------------------------------------------------------------- /tests/suites/casper/keys.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | /*global CasperError, casper, console, phantom, require*/ 3 | var utils = require('utils'); 4 | 5 | casper.test.begin('sendKeys() tests', 4, function(test) { 6 | casper.start('tests/site/form.html', function() { 7 | this.sendKeys('input[name="email"]', 'duke@nuk.em'); 8 | this.sendKeys('input[name="language"]', 'fr', {keepFocus: true}); 9 | this.click('#autocomplete li:first-child'); 10 | this.sendKeys('textarea', "Damn, I’m looking good."); 11 | var values = this.getFormValues('form[action="result.html"]'); 12 | test.assertEquals(values.email, 'duke@nuk.em', 13 | 'Casper.sendKeys() sends keys to given input'); 14 | test.assertEquals(values.language, 'french', 15 | 'Casper.sendKeys() sends keys to given input and keeps focus afterweards'); 16 | test.assertEquals(values.content, "Damn, I’m looking good.", 17 | 'Casper.sendKeys() sends keys to given textarea'); 18 | 19 | this.sendKeys('input[name="notype"]', "I have no type."); 20 | values = this.getFormValues('form#no-type-test-form'); 21 | test.assertEquals(values.notype, "I have no type.", 22 | 'Casper.sendKeys() sends keys to given input without type attribute'); 23 | }).run(function() { 24 | test.done(); 25 | }); 26 | }); 27 | 28 | casper.test.begin('sendKeys() works on content-editable elements', 1, function(test) { 29 | casper.start('tests/site/elementattribute.html', function() { 30 | this.click('#content-editable-div'); 31 | this.sendKeys('#content-editable-div', 'A Clockwork Orange'); 32 | }).then(function() { 33 | test.assertSelectorHasText('#content-editable-div','A Clockwork Orange'); 34 | }).run(function() { 35 | test.done(); 36 | }); 37 | }); 38 | 39 | if (utils.gteVersion(phantom.version, '1.9.0')) { 40 | casper.test.begin('sendKeys() key modifiers tests', 1, function(test) { 41 | casper.start().then(function() { 42 | this.setContent([ 43 | '', 44 | '' 47 | ].join('')); 48 | this.sendKeys('input', 'k'); 49 | this.sendKeys('input', 'k', {modifiers: "ctrl"}); 50 | this.sendKeys('input', 'k', {modifiers: "ctrl+alt"}); 51 | test.assertEquals(this.getGlobal('keys'), 52 | [ 53 | {code: 107, alt: false, ctrl: false}, 54 | {code: 107, alt: false, ctrl: true}, 55 | {code: 107, alt: true, ctrl: true} 56 | ], 'sendKeys() uses key modifiers'); 57 | }).run(function() { 58 | test.done(); 59 | }); 60 | }); 61 | } 62 | 63 | casper.test.begin('sendKeys() reset option', 1, function(test) { 64 | casper.start('tests/site/form.html', function() { 65 | this.sendKeys('textarea', 'foo'); 66 | this.sendKeys('textarea', 'bar', {reset: true}); 67 | var values = this.getFormValues('form[action="result.html"]'); 68 | test.assertEquals(values.content, "bar"); 69 | }).run(function() { 70 | test.done(); 71 | }); 72 | }); 73 | -------------------------------------------------------------------------------- /docs/_themes/casperjs/addon.html: -------------------------------------------------------------------------------- 1 |

      Donate

      2 | 16 | -------------------------------------------------------------------------------- /docs/selectors.rst: -------------------------------------------------------------------------------- 1 | .. _selectors: 2 | 3 | .. index:: selector, DOM, HTML 4 | 5 | ========= 6 | Selectors 7 | ========= 8 | 9 | CasperJS makes a heavy use of selectors in order to work with the `DOM `_, and can transparently use either `CSS3 `_ or `XPath `_ expressions. 10 | 11 | All the examples below are based on this HTML code: 12 | 13 | .. code-block:: html 14 | 15 | 16 | 17 | 18 | 19 | My page 20 | 21 | 22 |

      Hello

      23 |
        24 |
      • one
      • 25 |
      • two
      • 26 |
      • three
      • 27 |
      28 |

      ©2012 myself

      29 | 30 | 31 | 32 | .. index:: CSS, CSS3 33 | 34 | CSS3 35 | ---- 36 | 37 | By default, CasperJS accepts `CSS3 selector strings `_ to check for elements within the DOM. 38 | 39 | To check if the ``

      `` 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 `:: 52 | 53 | casper.test.begin('The heading exists', 1, function suite(test) { 54 | casper.start('http://domain.tld/page.html', function() { 55 | test.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 | test.assertExists('h1.page-title'); 66 | test.assertSelectorHasText('h1.page-title', 'Hello'); 67 | test.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 `_ 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() ` method when you want to fill **file fields**; PhantomJS natively only allows the use of CSS3 selectors in its `uploadFile method `_, hence this limitation. 100 | -------------------------------------------------------------------------------- /tests/suites/tester/testcase.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0, max-statements:0, complexity:0*/ 2 | 3 | var TestCaseResult = require('tester').TestCaseResult; 4 | 5 | casper.test.begin('TestCaseResult.constructor() tests', 4, function(test) { 6 | var caseResult1 = new TestCaseResult(); 7 | test.assertType(caseResult1.name, "undefined", 'TestCaseResult.constructor() name is undefined by default'); 8 | test.assertType(caseResult1.file, "undefined", 'TestCaseResult.constructor() file is undefined by default'); 9 | var caseResult2 = new TestCaseResult({name: 'foo', file: '/tmp/foo'}); 10 | test.assertEquals(caseResult2.name, "foo", 'TestCaseResult.constructor() can set name'); 11 | test.assertEquals(caseResult2.file, "/tmp/foo", 'TestCaseResult.constructor() can set file'); 12 | test.done(); 13 | }); 14 | 15 | casper.test.begin('TestCaseResult.addSuccess() and TestCaseResult.addFailure() tests', 22, function(test) { 16 | var caseResult = new TestCaseResult({name: 'foo', file: '/tmp/foo'}); 17 | test.assertEquals(caseResult.assertions, 0, 'test case result counts no assertion by default'); 18 | test.assertEquals(caseResult.passed, 0, 'test case result counts no success by default'); 19 | test.assertEquals(caseResult.failed, 0, 'test case result counts no failure by default'); 20 | test.assertEquals(caseResult.calculateDuration(), 0, 21 | 'TestCaseResult.calculateDuration() computes initial tests duration'); 22 | var success = {}; 23 | caseResult.addSuccess(success, 1337); 24 | test.assertEquals(caseResult.assertions, 1, 'test case result counts one assertion'); 25 | test.assertEquals(caseResult.passed, 1, 'test case result counts one success'); 26 | test.assertEquals(caseResult.failed, 0, 'test case result counts no failure'); 27 | test.assertEquals(caseResult.passes[0], success, 'TestCaseResult.addSuccess() added a success to the stack'); 28 | test.assertEquals(caseResult.passes[0].time, 1337, 'TestCaseResult.addSuccess() added test duration'); 29 | test.assertEquals(caseResult.passes[0].suite, 'foo', 'TestCaseResult.addSuccess() added suite name'); 30 | test.assertEquals(caseResult.calculateDuration(), 1337, 31 | 'TestCaseResult.calculateDuration() computes tests duration'); 32 | var failure = {}; 33 | caseResult.addFailure(failure, 42); 34 | test.assertEquals(caseResult.assertions, 2, 'test case result counts two assertions'); 35 | test.assertEquals(caseResult.passed, 1, 'test case result counts one success'); 36 | test.assertEquals(caseResult.failed, 1, 'test case result counts no failure'); 37 | test.assertEquals(caseResult.failures[0], failure, 'TestCaseResult.addFailure() added a failure to the stack'); 38 | test.assertEquals(caseResult.failures[0].time, 42, 'TestCaseResult.addFailure() added test duration'); 39 | test.assertEquals(caseResult.failures[0].suite, 'foo', 'TestCaseResult.addFailure() added suite name'); 40 | test.assertEquals(caseResult.calculateDuration(), 1337 + 42, 41 | 'TestCaseResult.calculateDuration() computes new tests duration'); 42 | caseResult.addSuccess({}, 1000); 43 | test.assertEquals(caseResult.assertions, 3, 'test case result counts three assertions'); 44 | test.assertEquals(caseResult.passed, 2, 'test case result counts two successes'); 45 | test.assertEquals(caseResult.failed, 1, 'test case result counts one failure'); 46 | test.assertEquals(caseResult.calculateDuration(), 1337 + 42 + 1000, 47 | 'TestCaseResult.calculateDuration() computes new tests duration'); 48 | test.done(); 49 | }); 50 | -------------------------------------------------------------------------------- /tests/suites/casper/bypass.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | casper.test.begin('Casper.bypass() can bypass a step', 2, function(test) { 3 | casper.start(); 4 | casper.then(function(){ 5 | test.fail("This test should not be executed."); 6 | }); 7 | casper.once("step.bypassed", function(step) { 8 | test.pass("step.bypassed event has been catched"); 9 | }).bypass(1).run(function() { 10 | test.pass("Step has been bypassed"); 11 | test.done(); 12 | }); 13 | }); 14 | 15 | casper.test.begin('Casper.bypass() can bypass multiple steps', 1, function(test) { 16 | casper.start(); 17 | casper.then(function() { 18 | test.pass("This test should be executed."); 19 | }); 20 | casper.then(function() { 21 | this.bypass(2); 22 | }); 23 | casper.then(function() { 24 | test.fail("This test should not be executed."); 25 | }); 26 | casper.then(function() { 27 | test.fail("Nor this one."); 28 | }); 29 | casper.run(function() { 30 | test.done(); 31 | }); 32 | }); 33 | 34 | casper.test.begin('Casper.thenBypass()', 1, function(test) { 35 | casper. 36 | thenBypass(1). 37 | then(function() { 38 | test.fail("This test should be bypassed."); 39 | }). 40 | then(function() { 41 | test.pass("This test should be executed."); 42 | }); 43 | 44 | casper.run(function() { 45 | test.done(); 46 | }); 47 | }); 48 | 49 | casper.test.begin('Casper.thenBypassIf()', 3, function(test) { 50 | casper. 51 | thenBypassIf(true, 1, "Bypass if with function"). 52 | then(function() { 53 | test.fail("This test should be bypassed."); 54 | }). 55 | then(function() { 56 | test.pass("This test should be executed."); 57 | }). 58 | thenBypassIf(function() { 59 | return true; 60 | }, 1, "Bypass if with function"). 61 | then(function() { 62 | test.fail("This test should be bypassed."); 63 | }). 64 | then(function() { 65 | test.pass("This test should be executed."); 66 | }). 67 | thenBypassIf(function() { 68 | return false; 69 | }, 1, "Do not bypass if with function"). 70 | then(function() { 71 | test.pass("This test should be executed."); 72 | }); 73 | 74 | casper.run(function() { 75 | test.done(); 76 | }); 77 | }); 78 | 79 | casper.test.begin('Casper.thenBypassUnless()', 3, function(test) { 80 | casper. 81 | thenBypassUnless(false, 1, "Bypass unless with function"). 82 | then(function() { 83 | test.fail("This test should be bypassed."); 84 | }). 85 | then(function() { 86 | test.pass("This test should be executed."); 87 | }). 88 | thenBypassUnless(function() { 89 | return false; 90 | }, 1, "Bypass unless with function"). 91 | then(function() { 92 | test.fail("This test should be bypassed."); 93 | }). 94 | then(function() { 95 | test.pass("This test should be executed."); 96 | }). 97 | thenBypassUnless(function() { 98 | return true; 99 | }, 1, "Do not bypass unless with function"). 100 | then(function() { 101 | test.pass("This test should be executed."); 102 | }); 103 | 104 | casper.run(function() { 105 | test.done(); 106 | }); 107 | }); 108 | -------------------------------------------------------------------------------- /tests/site/click.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CasperJS test click 6 | 7 | 8 | test1 9 | test2 10 | test3 11 | test4 12 | test5 13 | Label with double "quotes" 14 | Label with single 'quotes' 15 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /tests/clitests/tester/waitFor_timeout.js: -------------------------------------------------------------------------------- 1 | /*eslint strict:0*/ 2 | 3 | casper.options.waitTimeout = 500; 4 | 5 | casper.test.begin('waitForSelector fails with expected message', 1, function(test) { 6 | casper.start('../site/waitFor.html'); 7 | 8 | casper.waitForSelector('p.nonexistent', function() { 9 | throw new Error('waitForSelector found something it should not have'); 10 | }); 11 | 12 | casper.run(function() { 13 | test.done(); 14 | }); 15 | }); 16 | 17 | casper.test.begin('waitWhileSelector fails with expected message', 1, function(test) { 18 | casper.start('../site/waitFor.html'); 19 | 20 | casper.waitForSelector('#encoded'); 21 | 22 | casper.waitWhileSelector('#encoded', function() { 23 | throw new Error('waitWhileSelector thought something got removed when it did not'); 24 | }); 25 | 26 | casper.run(function() { 27 | test.done(); 28 | }); 29 | }); 30 | 31 | casper.test.begin('waitForSelectorTextChange fails with expected message', 1, function(test) { 32 | casper.start('../site/waitFor.html'); 33 | 34 | casper.waitForSelectorTextChange('#encoded', function() { 35 | throw new Error('waitForSelectorTextChange thought text changed when it did not'); 36 | }); 37 | 38 | casper.run(function() { 39 | test.done(); 40 | }); 41 | }); 42 | 43 | casper.test.begin('waitUntilVisible fails with expected message', 1, function(test) { 44 | casper.start('../site/waitFor.html'); 45 | 46 | casper.waitUntilVisible('p[style]', function() { 47 | throw new Error('waitUntilVisible falsely identified a hidden paragraph'); 48 | }); 49 | 50 | casper.run(function() { 51 | test.done(); 52 | }); 53 | }); 54 | 55 | casper.test.begin('waitWhileVisible fails with expected message', 1, function(test) { 56 | casper.start('../site/waitFor.html'); 57 | 58 | casper.waitWhileVisible('img', function() { 59 | throw new Error('waitWhileVisible thought something disappeared when it did not'); 60 | }); 61 | 62 | casper.run(function() { 63 | test.done(); 64 | }); 65 | }); 66 | 67 | casper.test.begin('waitForUrl fails with expected message', 1, function(test) { 68 | casper.start('../site/waitFor.html'); 69 | 70 | casper.waitForUrl(/github\.com/, function() { 71 | throw new Error('waitForUrl thought we actually navigated to GitHub'); 72 | }); 73 | 74 | casper.run(function() { 75 | test.done(); 76 | }); 77 | }); 78 | 79 | casper.test.begin('waitForPopup fails with expected message', 1, function(test) { 80 | casper.start('../site/waitFor.html'); 81 | 82 | casper.waitForPopup(/foobar/, function() { 83 | throw new Error('waitForPopup found something it should not have'); 84 | }); 85 | 86 | casper.run(function() { 87 | test.done(); 88 | }); 89 | }); 90 | 91 | casper.test.begin('waitForText fails with expected message', 1, function(test) { 92 | casper.start('../site/waitFor.html'); 93 | 94 | casper.waitForText("Lorem ipsum", function() { 95 | throw new Error('waitForText found something it should not have'); 96 | }); 97 | 98 | casper.run(function() { 99 | test.done(); 100 | }); 101 | }); 102 | 103 | casper.test.begin('waitFor fails with expected message', 1, function(test) { 104 | casper.start('../site/waitFor.html'); 105 | 106 | casper.waitFor(function() { 107 | return false 108 | }, function() { 109 | throw new Error('waitFor fasely succeeded'); 110 | }); 111 | 112 | casper.run(function() { 113 | test.done(); 114 | }); 115 | }); -------------------------------------------------------------------------------- /docs/modules/colorizer.rst: -------------------------------------------------------------------------------- 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() ` 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 `. 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 | 103 | --------------------------------------------------------------------------------