2014-07-22 9 views
7

J'utilise le cadre de tests CasperJS pour faire une suite de tests depuis près d'un mois, mais je suis confronté à un problème dans l'un d'entre eux.Comment ouvrir un nouvel onglet dans CasperJS

Voici ce que je veux faire: Je parcours une URL (page1) et je dois faire une autre action à partir d'une autre URL (simuler un nouvel onglet comme sur notre navigateur graphique) sans quitter la première (Page 1). L'action de la deuxième url va changer mon premier. J'espère que c'est assez clair :)

Donc pour l'instant quand j'atteins l'étape pour observer que sur mon premier url j'ouvre le deuxième en faisant un thenOpen(), ainsi il fait une nouvelle étape de navigation et je perds la session courante et Je ne peux pas y revenir. J'essaye beaucoup de manières telles qu'utiliser l'histoire, rouvrir la page, employer l'événement de CasperJS et aussi essayer avec PhantomJS mais sans succès.

Voici un code pseudo pour le rendre plus clair:

casper.test.begin("A random test suite", 0, function testSuite(test) { 
    casper.start(url1, function() { 
     casper.then(function() { 
      // do some action on the first url 
     }); 

     casper.then(function() { 
      // open url2 and do some action in a new tab to not lose the session of url1 
     }); 

     casper.then(function() { 
      // check url1 (who should be still open) 
     }); 
    }); 

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

Je voudrais vraiment utiliser CasperJS pour faire cela, mais je commence à penser qu'il est impossible, et je commence à regarder dans une solution différente tel que ce poste: CasperJS, parallel browsing WITH the testing framework. Mais je n'ai jamais utilisé node.js auparavant, donc si c'est le seul moyen, donnez-moi un exemple.

+0

duplication possible de [Comment tester deux navigateurs interactifs (par exemple l'application de chat)] (http://stackoverflow.com/questions/24315512/how-to-test-two-interacting-browsers-eg-chat-app) –

Répondre

10

En général, il est impossible parce qu'un script casper exécute dans une seule exécution PhantomJS. Dans votre cas, cela semble possible.

Note: Parce que ce repose sur une deuxième instance de casper, cela ne peut pas être utilisé dans un casper test environnement.

Vous pouvez créer une instance de caspeur (casper2) à l'intérieur d'une étape de l'instance de caspeur externe (casper1). Vous devez ensuite demander à casper1 d'attendre la fin de l'instance casper2, car casper est de nature asynchrone. Gardez à l'esprit que c'est exactement comme un nouvel onglet, donc les instances partageront le cache, les cookies et le stockage.

Voici un exemple de script:

var casper1 = require('casper').create(); 
var casper2done = false; 

casper1.start("http://www.example.com").then(function(){ 
    casper1.capture("casper1_1.png"); 
    var casper2 = require('casper').create(); 
    casper2.start("http://stackoverflow.com/contact").then(function(){ 
     casper1.echo(casper2.getCurrentUrl(), casper2.getTitle()); 
     casper2.capture("casper2.png"); 
    }).run(function(){ 
     this.echo("DONE 2"); 
     casper2done = true; 
    }); 
}).waitFor(function check(){ 
    return casper2done; 
}).then(function(){ 
    casper1.echo(casper1.getCurrentUrl(), casper1.getTitle()); // Comment to fix answer (min 6 chars) 
    casper1.capture("casper1_2.png"); 
}).run(function(){ 
    this.echo("DONE"); 
    this.exit(); 
}); 

J'utilise ici l'enchaînement promesse/modèle de constructeur. Vous pouvez même faire votre propre fonction pour cacher la complexité et le rendre utilisable à plusieurs reprises:

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

// IIFE to hide casper2done variable 
(function(casper){ 
    var casper2done = false; 
    casper.newTab = function(url, then, timeout){ 
     if (typeof url !== "string" || typeof then !== "function") { 
      throw "URL or then callback are missing"; 
     } 
     this.then(function(){ 
      var casper2 = require('casper').create(); 
      casper2.start(url).then(then).run(function(){ 
       casper2done = true; 
      }); 
     }).waitFor(function check(){ 
      return casper2done; 
     }, null, null, timeout).then(function(){ 
      casper2done = false; 
     }); 
     return this; 
    }; 
})(casper); 

casper.start("http://www.example.com").newTab("http://stackoverflow.com/contact", function(){ 
    // this is casper2 
    this.echo(this.getCurrentUrl(), this.getTitle()); 
    this.capture("casper2_1.png"); 
    this.thenClick("a#nav-askquestion"); 
    this.then(function(){ 
     this.echo(this.getCurrentUrl(), this.getTitle()); 
     this.capture("casper2_2.png"); 
    }); 
}, 15000).then(function(){ 
    // this is casper 
    this.echo(casper.getCurrentUrl(), casper.getTitle()); 
    this.capture("casper1.png"); 
}).run(function(){ 
    this.echo("DONE"); 
    this.exit(); 
}); 

Vous pouvez utiliser plusieurs étapes dans votre enfant exemple casper, mais ne pas oublier de spécifier un bon délai.

+0

Comment pouvons-nous faire cela en utilisant la sous-commande de test casperjs? Parce que nous ne pouvons pas remplacer l'instance de casper préconfigurée dans un environnement de test. – TuZ

+0

Cela ne sera pas possible. Ensuite, vous devrez générer un enfant via le module [child_process] (https://github.com/ariya/phantomjs/wiki/Api-reference-childprocess). Il peut être possible de l'écrire comme un appel d'évaluation qui sera sandboxé. –

Questions connexes