【问题标题】:How to open a new tab in CasperJS如何在 CasperJS 中打开一个新选项卡
【发布时间】:2014-07-22 06:51:39
【问题描述】:

我使用 CasperJS 测试框架制作一些测试套件已经快一个月了,但我在其中一个中遇到了问题。

这是我想要做的:我正在浏览一个 url (page1),我必须从另一个 url 执行另一个操作(模拟我们在图形浏览器上的新标签)而不退出第一个 (page1 )。第二个 url 的操作将改变我的第一个。希望它足够清楚:)

所以现在当我到达观察我的第一个网址的步骤时,我通过执行thenOpen() 打开第二个网址,所以它正在执行一个新的导航步骤,我正在失去当前会话,我无法重新开始它。我尝试了很多方法,例如使用历史记录,重新打开页面,使用 CasperJS 中的事件,也尝试使用 PhantomJS 但没有成功。

下面是一些伪代码,以使其更清晰:

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();
    });
});

我真的很想使用 CasperJS 来做到这一点,但我开始认为这是不可能的,我开始寻找不同的解决方案,例如这篇文章: CasperJS, parallel browsing WITH the testing framework。但我以前从未使用过 node.js,所以如果这是唯一的方法,请给我一些例子。

【问题讨论】:

标签: javascript node.js casperjs


【解决方案1】:

一般来说,这是不可能的,因为 casper 脚本只在一个 phantomjs 运行时中运行。在你的情况下,这似乎是可能的。

注意:因为这依赖于第二个 casper 实例,所以不能在 casper test 环境中使用。

您可以在外部 casper 实例 (casper1) 的一步内创建一个新的 casper 实例 (casper2)。然后,您必须指示 casper1 等待 casper2 实例完成,因为 casper 本质上是异步的。请记住,这与新选项卡完全一样,因此实例将共享缓存、cookie 和存储。

这是一个示例脚本:

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();
});

这里我使用了 Promise 链式/构建器模式。您甚至可以制作自己的函数来隐藏复杂性并使其重复可用:

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();
});

您可以在 child casper 实例中使用多个步骤,但不要忘记指定一个好的超时时间。

【讨论】:

  • 我们如何使用 casperjs test 子命令来做到这一点?因为我们无法在测试环境中覆盖预配置的 casper 实例。
  • 这是不可能的。然后,您必须通过 child_process 模块生成一个孩子。可以将其编写为将被沙盒化的评估调用。
猜你喜欢
  • 1970-01-01
  • 2019-12-01
  • 1970-01-01
  • 2012-11-05
  • 2011-04-02
  • 2017-05-22
  • 1970-01-01
  • 2010-11-14
  • 1970-01-01
相关资源
最近更新 更多