Workflow Testing with Casperjs

What is casperjs?
CasperJS is a navigation scripting & testing utility
written in Javascript that gives you more time to do this
while spending less time doing this
while spending less time doing this
What can I do with it?
- defining & ordering browsing navigation steps
- filling & submitting forms
- clicking & following links
- capturing screenshots of a page (or part of it)
- testing remote DOM
- logging events
- downloading resources, including binary ones
- writing functional test suites, saving results as JUnit XML
- scraping Web contents
how we're using it here (so far)
- Basic Janrain Login test
(media/web/common/javascript/tests/workflow/login.js)
- Premium Story Anon/Auth'd test (media/web/common/javascript/tests/workflow/premium-story-login.js)
- casper.cmg: Includible Helpers
Basic Janrain Login test
- Opens the specified site's front page (default: test.myajc.com)
- Waits for Janrain to initialize.
- Confirms that the UI is consistent with an anonymous viewer
(.cmUserAnonymous is visible) - Tests that login form displays when asked for
- Tests that the form fills properly
(default: cmg.medhini+goldsmith@gmail.com) -
Tests that the UI changes to logged in state.
(.cmUserAuthed is visible)
- Logs out
Premium Story Anon/Auth'd test
- Retrieve the title and URL for a premium story via API
- Opens story and confirms that the title is as expected
- Waits for Janrain to init
- Confirms UI is consistent with anon state
(same as login.js + story is stubbed, invite block visible, no comments) - Test that login form displays when asked for
- Test that form fills properly
-
Tests that the UI changes to logged in state.
(.cmUserAuthed visible, story unstubs, invite block invisible, comments loaded)
casper.cmg: INCLUDIBLE helpers
- You can require them like so:
var cmg = require('helpers/core'); -
Or by passing --includes=/path/to/tests/workflow/helpers/core.js will give you access to several helpers.
- To initialize them just pass the CLI param above and call
// If you used --includes you'll need // var cmg = casper.cmg; cmg.init(casper);
CMG Helpers
-
on:
- simple event handling: pass event name (currently only 'anonymous' and 'logged_in' are supported)
- allows additional tests/behavior steps to be added before or after logging in
-
testJanrainReady: wait for Janrain to be ready before continuing
-
testUserIsAnonymous:
- free & premium site compatible test that user is anonymous
- fires 'anonymous' callbacks for additional test's that the appropriate anonymous UI is displayed
CMG HELPERS (CONT.)
-
testSignInFormDisplayed and testSignInFormFilled:
test that the UI behaves correctly and allow logging into a site via Janrain
-
testLoginComplete:
- submits login form and waits for the login process to complete
-
fires any registered callbacks for the 'logged_in' event
-
logOut: log out current Janrain user and call casper.test.done unless false is passed
-
testLoginProcess: combines all of the listed helpers above
casper.cmg.testLoginProcess(casper, user [optional], pass [optional], call_done [optional, default true])
Surviving asynchronicity
- If your test requires certain Javascript to be loaded/initialized, use waitFor:
casper.waitFor(function test() { return window.janrain && janrain.ready; }, function then() { test.assertEval(…); }/*, function onTimeout, int timeout, obj timeout details*/); - If your test requires that a certain dynamically loaded/created element exists, use waitForSelector:
casper.waitForSelector('.mySelector', function then() { test.assertExists(…); }/*, function onTimeout, int timeout, obj timeout details*/); - REMEMBER: Everything you do should be inside a casper.then or casper.waitFor* call
Tests
- Test suites's follow this structure:
casper.test.begin(str description, int expectedTests, function theTests(test) { casper.start('http://my.url.tld/path/to/page/', function then(){}); casper.then(function () { /* do testy stuff */ }); casper.waitFor(function () { /* do testy stuff */ }); casper.waitForSelector(function () { /* do testy stuff */ }); // After all of the tests casper.then(function () { test.done(); }); // This is what makes casper actually start doing stuff. casper.run(); });
Don't assert before you evaluate
- The test object knows nothing of the DOM.
- The casper object knows nothing of the DOM.
- Therefore, you must evaluate your code in the browser context.
- Here's what I recommend for more complicated tests:
// for all tests that need to run in page environment test.assertEval(function () { …test code… }, str description) // for all non-test code that needs to be run in page environment this.evaluate(function () { …code to run in browser… }) - There are a number of shortcut methods that hook into the browser environment: assertVisible, assertDoesntExist, assertElementCount, assertExists, assertTextExists, etc.
GOTCHAS & TIPS
- Sometimes the waitFor* will time out due to slow site responses. Re-run the test with a higher --timeout before panicking.
- utils is your friend:
// from evaluate/assertEval __utils__.method() // from top script level require('utils').method()
-
CLI options:
- any --name option passed at the command line is available at casper.cli.options.name (or cmg.options, if you're using it)
- options already used by core helpers: --site, --server, --user, --pass, --timeout
For more info:
Intro to CasperJS
By Aaron McCall
Intro to CasperJS
- 2,264