CasperJS

Índice

1 Introducción

Los tests que son hechos por humanos se hacen desde el navegador y haciendo el énfasis en lo que se ve. Los tests hechos por CasperJS son hechos en JS para simular la acción de los humanos.

2 Login: Hagamos algo

Para hacer un login se podría simular de la siguiente manera:

var casper = require('casper').create();

casper.start('http://dominio, function() {
    this.fill('form#user-login-form', {
	'name':    'nombre',
	'pass':    'pass',
    }, true);
});

casper.run(function() {
    this.echo('message sent').exit();
});

casper.thenOpen('http://dominio/page, function() {
    this.echo(this.getTitle());
});

Primero se crea el objeto casper, seguidamente se inicia y se rellenan los campos de formulario y ya estamos listos para acceder a páginas que requerían autenticación.

Después llamamos a casper con

$ casperjs login.js

3 Navegación: Chequeando enlaces

Un test que puede ser de interés es navegar por las páginas de nuestro sitio web.

var casper = require('casper').create();

casper.start('http://www.gnu.org', function() {
    this.echo(this.getTitle());
});

casper.run(function() {
    this.echo('message sent').exit();
});

casper.thenOpen('http://gnu.org/education/education.html', function() {
    this.echo(this.getTitle());
});

casper.thenOpen('http://gnu.org/licenses/licenses.html', function() {
    this.echo(this.getTitle());
});

Después llamamos a casper con

$ casperjs navigation.js

Tal vez haya gente que prefiera automatizar las cuestiones de revisar enlaces rotos con link checker, pero este código sí sirve de ejemplo de juguete para ir aprendiendo CasperJS.

Una opción más profesional a la revisión de enlaces con CasperJS nos la da Netsniff Spider.

4 Visible: Qué se pinta, qué se ve

Es posible determinar si un elemento de la web es visible o no. Veamos un ejemplo:

var casper = require('casper').create();

casper.start('http://google.com/', function() {
    if (this.visible('#hplogo')) {
	this.echo("I can see the logo");
    } else {
	this.echo("I can't see the logo");
    }
});


casper.run();

Después llamamos a casper con

$ casperjs visible.js

5 Viewport: Automatizando diferentes tamaños de pantalla

Otra cuestión que se puede automatizar con CasperJS es ver si un sitio web se ve bien con diferentes tamaños de pantalla lo que se suele llamar responsive. Veamos el siguiente código:

var casper = require("casper").create();

var screenshotUrl = 'http://google.com/',
    screenshotNow = new Date(),
    screenshotDateTime = screenshotNow.getFullYear() + pad(screenshotNow.getMonth() + 1) + pad(screenshotNow.getDate()) + '-' + pad(screenshotNow.getHours()) + pad(screenshotNow.getMinutes()) + pad(screenshotNow.getSeconds()),
    viewports = [
      {
	'name': 'smartphone-portrait',
	'viewport': {width: 320, height: 480}
      },
      {
	'name': 'smartphone-landscape',
	'viewport': {width: 480, height: 320}
      },
      {
	'name': 'tablet-portrait',
	'viewport': {width: 768, height: 1024}
      },
      {
	'name': 'tablet-landscape',
	'viewport': {width: 1024, height: 768}
      },
      {
	'name': 'desktop-standard',
	'viewport': {width: 1280, height: 1024}
      }
    ];

if (casper.cli.args.length < 1) {
  casper
    .echo("Usage: $ casperjs screenshots.js http://example.com")
    .exit(1)
  ;
} else {
  screenshotUrl = casper.cli.args[0];
}

casper.start(screenshotUrl, function() {
  this.echo('Current location is ' + this.getCurrentUrl(), 'info');
});

casper.each(viewports, function(casper, viewport) {
  this.then(function() {
    this.viewport(viewport.viewport.width, viewport.viewport.height);
  });
  this.thenOpen(screenshotUrl, function() {
    this.wait(5000);
  });
  this.then(function(){
    this.echo('Screenshot for ' + viewport.name + ' (' + viewport.viewport.width + 'x' + viewport.viewport.height + ')', 'info');
    this.capture('screenshots/' + screenshotDateTime + '/' + viewport.name + '-' + viewport.viewport.width + 'x' + viewport.viewport.height + '.png', {
	top: 0,
	left: 0,
	width: viewport.viewport.width,
	height: viewport.viewport.height
    });
  });
});

casper.run();

function pad(number) {
  var r = String(number);
  if ( r.length === 1 ) {
    r = '0' + r;
  }
  return r;
}

Podemos llamar a este código con algo similar a:

$ casperjs screenshot.js http://misitio.com

Y crea un directorio screenshots con una serie de pantallazos en las diferentes resoluciones.

6 Scraping en Google Translate

Mientras el html no cambia es posible hacer scraping web para tener scripting de cosas que se nos devuelve por Internet. Veamos un ejemplo, usando google translate:

var system = require('system'),
    casper = require('casper').create(),
    format = require('utils').format,
    source = casper.cli.get('source') || 'auto',
    target = casper.cli.get('target'),
    text   = casper.cli.get(0),
    result;

if (!target) {
    casper.warn('The --target option is mandatory.').exit(1);
}

casper.start(format('http://translate.google.com/#%s/%s/%s', source, target, text), function() {
    this.fill('form#gt-form', {text: text});
}).waitForSelector('span.hps', function() {
    this.echo(this.fetchText("#result_box"));
});

casper.run();

Ahora se puede utilizar con

$ casperjs translate.js --target='es' "hello world"

7 Testing

Básicamente las herramientas de test actuales se basan en crear asertos/aserciones, veamos un ejemplo de esto en CasperJS:

var x = require('casper').selectXPath;

casper.test.begin('Tests homepage structure', 7, function suite(test) {

  casper.start('http://www.davidam.com', function() {
    // Verify that the main menu links are present.
    test.assertExists('a.org-effectiveness', '"Org Effectiveness" link is found.');
    test.assertExists('a.drupal-el', '"Drupal el" link is found.');
    test.assertExists('a.orgmode-drupal', '"Orgmode Drupal" link is found.');

    casper.waitForSelector(x("//*[normalize-space(text())='Traducción de una Introducción a GCC']"),
       function success() {
	   test.assertExists(x("//*[normalize-space(text())='Traducción de una Introducción a GCC']"));
	 },
       function fail() {
	   test.assertExists(x("//*[normalize-space(text())='Traducción de una Introducción a GCC']"));
       });
    casper.waitForSelector(x("//*[normalize-space(text())='fuentes']"),
       function success() {
	   test.assertExists(x("//*[normalize-space(text())='fuentes']"));
       },
       function fail() {
	   test.assertExists(x("//*[normalize-space(text())='fuentes']"));
       });
    casper.waitForSelector(x("//*[normalize-space(text())='Traducción de Guía Compacta de Org Mode']"),
       function success() {
	   test.assertExists(x("//*[normalize-space(text())='Traducción de Guía Compacta de Org Mode']"));
	 },
       function fail() {
	   test.assertExists(x("//*[normalize-space(text())='Traducción de Guía Compacta de Org Mode']"));
       });

    // 10 articles should be listed.
    test.assertElementCount('.box', 10, '10 boxes are listed.');
  });

  casper.run(function() {
    test.done();
  });
});

Se puede utilizar con

$ casperjs test davidam-test.js

8 Resurrectio

¿Eres de los que piensan que programar es aburrido? Eres un fantasma que merece una resurrección :D. Resurrectio permite generar código CasperJS, mientras tu haces clicks de ratón y escribes en el navegador.

9 Performance

También es posible chequear tiempos de carga con CasperJS:

var casper = require("casper").create();
var start = new Date().getTime();
var links = [
    "http://google.com/",
    "http://yahoo.com/",
    "http://duckduckgo.com/",
    "http://bing.com/"
];

casper.start();

casper.each(links, function(self, link) {
    this.thenOpen(link, function() {
	var now = new Date().getTime();
	this.echo(link + ' loaded in ' + (now - start) + 'ms');
	start = now;
    });
});

casper.run();

10 Referencias

11 Licencia

Autor: David Arroyo Menéndez

Created: 2016-01-11 lun 09:53

Emacs 24.4.1 (Org mode 8.2.10)

Validate