J. Muetton
ITNetwork, 8 mars 2013
Cette présentation est composée de beaucoup de code pour faciliter votre démarrage !
Architecture
Il sait faire
// Créer un navigateur
var casper = require('casper').create();
// Lancer un navigateur à une URL donnée
casper.start('http://google.fr/', function onReady () {
/* Initialize */
});
// Interragir avec la page
casper.then(function() {
this.fill('form[action="/search"]', { q: 'itn' }, true);
});
// Interragir avec la réponse
casper.then(function() {
this.click('h3.r a');
});
// Lancer la recette
casper.run(function() {
this.echo('Done.').exit(0);
});
Prendre une capture d'écran (doc)
casper.capture('./screenshot.png');
Injecter du code dans le navigateur (doc)
casper.evaluate(function (tag) {
return document.querySelector(tag).innerHTML;
}, 'title');
Attendre qu'un élément existe (doc)
casper.waitForSelector('.tweet-row', function() {});
Installer phantom
Télécharger l'exécutable pour
votre plateforme puis ajoutez le au PATH
ou à /usr/local/bin
récupérer casper
Il suffit ensuite de récupérer la dernière version via git :
$ git clone git://github.com/n1k0/casperjs.git
$ cd casperjs
$ git checkout tags/1.0.2 # replace with last tag
Casper est installé, rendons le exécutable
$ ln -sf `pwd`/bin/casperjs /usr/local/bin/casperjs
Ajouter ";C:\{CASPER_DIR}\batchbin"
au PATH
.
# A la place de la commande casper
C:> casperjs.bat myscript.js
Plus d'infos sur le site de CasperJS3>
CSS3
casper.start('http://example.org', function () {
casper.getHTML('h3 a:first-child');
});
XPath
var x = require('casper').selectXPath;
casper.start('http://example.org', function () {
casper.captureSelector('screen.png', x('//*[@id="plop"]'));
});
Rester flexible face aux évolutions du markup
casper.thenClick('nav a.parameters');
var x = require('casper').selectXPath;
casper.thenClick(x('//nav//a[contains(., "Paramètres")]'));
Factoriser dans des méthodes
casper.
thenGoToMenu("Administration", "Paramètres");
Un ensemble d'évènements pour étendre CasperJs
var f = require('utils').format;
casper.on('viewport.changed', function (size) {
this.log(f('resized to %dx%d', size[0], size[1]));
});
Evènements personnalisés
casper.on('app.signin', function (username) {
this.echo('signed in');
})
// ...
casper.emit('app.signin', "demo")
// Envoi de la requête
casper.start('http://www.wikipedia.org/');
// ...
// Exécution serveur
// ...
casper.then(function () { // réponse
// Nouvelle requête
this.fill('form.search-form', {
search: "github"
}, true);
});
// ...
// Exécution serveur
// ...
casper.then(function () { // réponse
var res = this.getHTML('#mw-content-text p:first-of-type');
this.echo(res);
});
casper.run(function() { this.exit(0); });
Testons l'autocomplétion de elasticsearch
casper.start('http://elasticsearch.org/');
// rempli le champs texte
casper.then(function () {
this.click('input#search');
this.sendKeys('input#search', 'guide');
});
// Attente des résultats
casper.waitUntilVisible(
'.ui-autocomplete.ui-menu',
function () {
// cliquer sur le premier résultat
this.click('.ui-autocomplete.ui-menu a:first-of-type');
});
casper.run(function() { this.exit(0); });
deferred
.La doc c'est par là3>
On déclare toujours ses variables.
var foo = "bar",
i;
for (var j = 0 ; j < 2 ; j++ ) {
// ...
}
Les {
sont toujours en fin de ligne
function foo () {
}
Attention au this
!
Tutoriels
Video / Articles
C'est un vrai langage et il faut l'apprendre !3>
// à partir de 1.1
casper.test.begin('ITN popup', 3, function (test) {
casper.start('http://www.itnetwork.fr/').
then(function () {
test.assertVisible('div#overlay');
test.assertExists('.skipTeaser');
}).
thenClick('.skipTeaser').
waitWhileVisible('div#overlay', function () {
test.pass("Overlay is hidden.");
}, function onError () {
test.fail("Overlay did not hide.");
}, 5000). // 5 seconds
run(function() {
test.done();
test.renderResults(true);
}); });
Sous Linux
$ casperjs test itnPopupTest.js
Sous Windows
C:\tests\> casperjs.bat test itnPopupTest.js
Résultat
PASS Selector is visible
PASS Found an element matching: .skipTeaser
PASS Overlay is hidden.
PASS 3 tests executed, 3 passed, 0 failed.
Casper propose une librairie d'assertions
// simple
casper.test.pass("Perfect")
casper.test.fail("Perfect")
// DOM
casper.test.assertVisible('.selector')
casper.test.assertSelectorExists('.selector')
// text
casper.test.assertSelectorHasText('title', 'U rock')
casper.test.assertTextDoesntExist('bing', 'body without "bing"');
// http
casper.test.assertHttpStatus(200)
plus sur la page dédiée3>
Lire une variable
// tests/includes/pre.js
var screenshot = casper.cli.get('screenshot') ||
'./build/error.png';
Capture en cas d'erreur
// tests/includes/pre.js
casper.on('error', function on_error(failure) {
casper.echo(failure, 'ERROR');
casper.capture(screenshot);
casper.exit(1);
});
Factorisons tout ce qui doit être répété :
var auth = {
username: "httpuser",
password: "httppassword"
};
casper.setupAndStart = function () {
if (!this.started) {
this.start();
}
// set viewport
this.viewport(1280,1024);
// http authentication
this.setHttpAuth(auth.username, auth.password);
return this;
};
// tests/includes/pre.js
casper.signIn = function signIn (username, password) {
if (!this.started) { this.setupAndStart(); }
this.thenOpen('https://mysecuresite.io/login')
this.then(function () {
this.fill('form[/login]', {
username: username || "demo",
password: password || "$ecr3t"
}, true);
});
this.then(function () {
this.test.assertHttpStatus(200, 'user has signed in');
});
// fluid interface
return this;
}
casper.test.begin('Access admin area', 1, function (test) {
casper.setupAndStart().
signIn("admin", "$ecr3t").
thenClick('header nav li>a:contains("Administration")').
then(function () {
if ("200" !== this.status(true)) {
// fin du test
test.fail("Accès à l'administration refusé.");
}
test.assertTextExists('Bienvenue Démo !');
}).
run(function () {
test.done();
});
});
Directement
$ casper test tests/suite --includes=tests/include/pre.js \
--screenshot=build/error.png
Avec un script shell 1/3
#!/usr/bin/env bash
SCRIPTPATH=`readlink -f $0`;
SCRIPTNAME=$(basename $SCRIPTPATH)
ROOT_DIR="$(dirname $(dirname $SCRIPTPATH))"
CASPER_COMMAND="casperjs test $ROOT_DIR/suite --include=$ROOT_DIR/include/pre.js"
XUNIT="build/junit-casper.xml"
SHORT_OPT="t:s:xh"
LONG_OPT="host:,screenshot:caper-xunit,help"
# write usage
function usage {
printf "Launch tests\n"
printf "\n"
printf " $SCRIPTNAME --host http://localhost/\n"
printf "Options\n"
printf "\t-t --host : changes host\n"
printf "\t-s --screenshot : changes screenshot destination\n"
printf "\t-x --casper-xunit : output casper tests in xunit format\n"
printf "\t-h --help : this help\n"
}
# parse arguments
OPTS=$( getopt -o "$SHORT_OPT" -l "$LONG_OPT" -- "$@" )
if [ $? != 0 ]; then
usage;
exit 1;
fi
eval set -- "$OPTS"
# read options
while true ; do
case "$1" in
-t|--host) HOST="$2"
shift2;;
-s|--screenshot) SCREENSHOT="$2"
shift2;;
-h|--help) usage
exit 0;;
-x|--casper-xunit)
CASPER_COMMAND="$CASPER_COMMAND --xunit=$XUNIT"
shift2;;
--) shift
break;;
esac
done
# extend comand with options
CASPER_COMMAND="$CASPER_COMMAND --host=$HOST"
CASPER_COMMAND="$CASPER_COMMAND --screenshot=$ERROR"
$CASPER_COMMAND
En tant qu'administrateur, Quand je clique sur Administration Le panneau d'administration est affiché Quand je clique sur "Utilisateur" La liste des utilisateurs est affichée Quand je clique sur nouveau Un formulaire apparait Quand je soumets ce formulaire avec des données valides La liste des utilisateurs est affichée
La documentation et le code de Resurect.io sont sur github.
Reportez vous à la procédure d'installation.
Les tests générés doivent être modifiés manuellement !3>
Ce projet est au stade expérimental3>
Le projet slimerjs a pour but de :
PhantomJS
Firefox
Table of contents | t |
---|---|
Exposé | ESC |
Autoscale | e |
Full screen slides | f |
Presenter view | p |
Source files | s |
Slide numbers | n |
Blank screen | b |
Notes | 2 |
Help | h |