如何单元测试页面导航?

时间:2011-11-14 20:42:39

标签: javascript unit-testing browser window.location

用例是这样的:我想在页面中运行代码进行单元测试(在浏览器中,QUnit或类似的东西)。页面可以做的一件事就是导航到另一个页面。我在捕捉此事件时遇到问题,因为:

  • beforeunload无法停止操作(因此第一次导航会破坏我的测试)
  • 尝试重新定义window.location或window.location.href并且getter返回旧值并且禁止使用间谍设置器

我理解有安全理由不允许停止导航,但对于开发而言,能够这样做是非常有用的。

有没有可能做到这一点(我没有直接控制测试运行器,所以我不能只加载iframe中的代码并让它导航然后检查iframe的位置)?

编辑:更具体一点:我想测试,是否,基于来自facebook的记录/连接状态(我使用facebook-stub从github到mock fb),有正确的处理程序安装在登录按钮(例如,$('#login-btn')),通过单击导航页面到facebook oauth对话框,服务器流程(此处的详细信息并不重要)。

所以我希望能够做到这一点:

// set up fb mock to not be connected
fbAsyncInit(); // simulate the startup of app
$('#login-btn').click();
equal(document.location.href, "http://www.facebook.com/oauth/...", "OAuth dialog not started.");

但是如果当然没有实际导航。怎么做测试?

3 个答案:

答案 0 :(得分:5)

你所做的事实上不是单元测试,更像是验收测试。

您应该查看selenium web driver,它可以轻松测试页面导航等内容。

答案 1 :(得分:1)

我现在看到你不能监视一个二传手(这是我在下面推荐的)。我已经写了解决方案,所以我想我会发布它以防万一没有限制的人访问此页面...

定义可公开访问的功能以进行导航,例如:

MyNameSpace.navigate = function( url ) {
    window.location.href = url;
};

现在,在您的测试中,您可以将对MyNameSpace.navigate()的调用存根,并确保正确调用它。这是一个示例(不确定您正在使用的测试框架,所以如果实施不清楚,请告诉我。)

设置并拆除:

setUp( function() {
    this._navigate = MyNameSpace.navigate;
    MyNameSpace.navigate = function( url ) {
        this.calledWith = url;
    };
});
tearDown( function() {
    MyNameSpace.navigate = this._navigate;
});

你的测试,重新实施:

test( function() {
    // set up fb mock to not be connected
    fbAsyncInit(); // simulate the startup of app
    $('#login-btn').click();
    equal(MyNameSpace.navigate.calledWith, "http://www.facebook.com/oauth/...", "OAuth dialog not started.");
});

您查询window.location.href的想法不仅会测试您的应用程序代码,还会测试浏览器本身(即,当我的应用程序设置window.location.href时,浏览器是否会正确重定向)。专用的navigate方法允许您测试应用程序内部是否按预期运行,同时阻止浏览器响应。

答案 2 :(得分:0)

您可以查看此How far can you go with JavaScript testing?问题。

硒确实很好,众所周知,但我个人认为它很老,不太可用。我建议使用Ghostbuster(参见introduction),这是一个无头Webkit,运行用Javascript或Coffeescript编写的测试。

您给出的测试用例如下:

phantom.test.root = "http://localhost/"     # or whatever your testing env's root

phantom.test.add "Facebook login", ->       # this adds a test
  @get '/yourLoginPage', ->                 # relative to the previous root
    @body.click '#login-btn'
    @assertLocation "http://www.facebook.com/oauth/..."
    @succeed()                              # all tests must succeed

:)