15

我相当确定问题在于设置为在 $(document).ready 上运行的 jquery 绑定没有可用的夹具 html。因此,当我发生旨在通过 jquery 函数更改 DOM 的事件时,什么也没有发生,我的测试也失败了。我在这里看到了这个问题的“解决方案”,但是对我有用的解决方案需要更改我的工作 jquery 函数以与 .live 方法而不是 .click 方法绑定。我对此有两个问题。首先,我不想更改我的工作代码,以便测试能够正确通过。测试框架应该测试代码是否可以在应用程序中工作,其中 DOM 加载和 javascript 绑定以正确的顺序发生。我对解决方案的第二个问题是 .on 和 .delegate 由于某种原因都不起作用,最终起作用的唯一方法是使用当前正在弃用的 .live 方法。总之,我想弄清楚如何更改我的测试或测试框架本身,以便在 $(document).ready 中运行的函数之前加载固定装置。

我正在使用rails 3.2.8,并且设置了两个不同的分支来进行茉莉花测试。其中一个分支使用 jasminerice gem,另一个使用 jasmine-rails gem。Javascript 和 jQuery(使用 .live 方法时)测试在这两种设置中都正确通过。

这是使用茉莉花的分支的描述:

以下是我的 Gemfile.lock 文件中描述 jasmine 和 jQuery 设置的行:

jasminerice (0.0.9)
  coffee-rails
  haml
jquery-rails (2.1.3)
  railties (>= 3.1.0, < 5.0)
  thor (~> 0.14)

Jasminerice 默认包含jasmine-jquery扩展。jasmine-jQuery 扩展提供了我在测试中使用的 toHaveText 方法。

直接位于 spec/javascripts 目录中的测试文件 jasmine_jquery_test.js 包含以下内容:

#= require application

describe ("my basic jasmine jquery test", function(){

    beforeEach(function(){
        $('<a id="test_link" href="somewhere.html">My test link</a>').appendTo('body');
    });

    afterEach(function(){
        $('a#test_link').remove();
    });

    it ("does some basic jQuery thing", function () {
        $('a#test_link').click();
        expect($("a#test_link")).toHaveText('My test link is now longer');
    });

    it ("does some the same basic jQuery thing with a different trigger type", function () {
        $('a#test_link').trigger('click');
        expect($("a#test_link")).toHaveText('My test link is now longer');
    });

});
describe ('subtraction', function(){

    var a = 1;
    var b = 2;

    it("returns the correct answer", function(){
        expect(subtraction(a,b)).toBe(-1);
    });

});

我位于 app/assets/javascripts 目录中的 javascript 文件 tests.js 包含以下内容:

function subtraction(a,b){
    return a - b;
}

jQuery (function($) {
/* 
    The function I would rather use - 
    $("a#test_link").click(changeTheTextOfTheLink)
    function changeTheTextOfTheLink(e) {
        e.preventDefault()
        $("a#test_link").append(' is now longer');
    }
*/

    $("a#test_link").live('click', function(e) {
        e.preventDefault();
        $("a#test_link").append(' is now longer');
    });

});

我位于同一 app/assets/javascripts 目录中的 application.js 文件具有以下内容:

//= require jquery
//= require jquery_ujs
//= require bootstrap
//= require vendor
//= require_tree . 

jasmine-rails 分支的描述可以在我的第一个 jasmine test 相关 stackoverflow question的内容中找到。

因此,如果有人知道如何操作测试,以便在加载装置后运行 $(document).ready 函数,我非常想听听您的想法?

4

6 回答 6

6

将 jQuery 直接添加到 html 夹具对我来说可以获得所需的行为。这并不完全是这个问题的答案,但我开始相信它是目前可用的最佳解决方案。我在 jasmine-rails gem 设置中所做的更改,我还没有在 jasminerice 分支中尝试过。

这是我的测试文件:

describe ("my basic jasmine jquery test", function(){

    beforeEach(function(){
        loadFixtures('myfixture.html');
    });

    it ("does some basic jQuery thing", function () {
        $('a#test_link').click();
        expect($("a#test_link")).toHaveText('My test link is now longer');
    });

    it ("does the same basic jQuery thing with a different event initiation method", function () {
        $('a#test_link').trigger('click');
        expect($("a#test_link")).toHaveText('My test link is now longer');
    });

});
describe ('substraction', function(){

    var a = 1;
    var b = 2;

    it("returns the correct answer", function(){
        expect(substraction(a,b)).toBe(-1);
    });

});

这是我的夹具文件:

<a id="test_link" href="somewhere.html">My test link</a>

<script>
    $("a#test_link").click(changeTheTextOfTheLink)
    function changeTheTextOfTheLink(e) {
        e.preventDefault()
        $("a#test_link").append(' is now longer');
    }
</script>
于 2012-10-10T00:49:55.970 回答
1

就个人而言,我认为这是一个错误 jasmine-jquery。我通过使我的装置成为 SpecRunner.html 的一部分来“解决”这个问题。不理想,但它适用于简单的情况。

于 2012-10-06T03:40:07.973 回答
1

你试过 jasmine-jquery 吗?

https://github.com/velesin/jasmine-jquery

从它的github页面,

jasmine-jquery 为 Jasmine JavaScript 测试框架提供了两个扩展:

一组用于 jQuery 框架的自定义匹配器 用于处理规范中的 HTML、CSS 和 JSON 固定装置的 API

于 2013-11-08T11:51:20.513 回答
1

我使用dom_munger为我自动生成夹具,因此在夹具中手动添加 jquery 代码对我来说不是一个选项。我一直在寻找相同的答案,而我现在能想到的最佳解决方案是在 jQuery 中使用事件委托。

例如,不要这样写:

$('#target').click(function(){
    // Do work
});

做这个:

$(document).on('click', '#target', function(){
    // Do work
});

通过这种方式,监听器被附加到文档,该文档在加载夹具之前存在。因此,当#target 上发生点击事件时,它会冒泡到文档中。文档检查源是否匹配第二个参数 - '#target'。如果匹配,将调用处理函数。

我知道这有一些限制,例如初始化插件,但它确实解决了部分问题。

于 2014-03-19T08:41:08.420 回答
1

我对这里描述的方法采取了稍微不同的方法来解决这个限制。

免责声明:我为 Microsoft 工作,因此未经法律批准,我无法在此处发布我的实际源代码,因此我将仅描述一种行之有效的方法。

我没有尝试改变document.ready工作方式,而是修改了 jasmine-jquery 源以支持一个调用的函数,该函数fixturesReady需要一个回调。

本质上,这是在 IIFE 中定义的,并为每个事件名称私有地保存一组回调,这些回调在触发器上进行迭代。

然后在这个块上你可以放置触发器:

jasmine.Fixtures.prototype.load = function() {
  this.cleanUp()
  this.createContainer_(this.read.apply(this, arguments))

  fixturesReady.trigger("loaded", arguments); // <----- ADD THIS

}

因此,现在在您的测试中,您可以针对以下代码进行编码:

fixturesReady(yourCallback)

而且您知道当yourCallback被调用时,您可以安全地在 DOM 中查询您的夹具元素。

此外,如果您使用async.beforeEachjasmine 插件,您可以这样做:

async.beforeEach(function(done){

    fixturesReady(done);

    ...

    loadFixtures("....");

});

希望对您有所帮助,并为您提供解决此问题的一些想法。

注意:如果需要,请记住在您的插件中清除afterEach块中的任何回调:)

于 2014-04-14T13:40:49.463 回答
1

自从提出这个问题(并接受了答案)以来已经有一段时间了。

这是一种更好的方法来构建测试并加载脚本以使用 jasmine 进行测试。

模板/link.tmpl.html

<a id="test_link" href="somewhere.html">My test link</a>

js/test-link.js

$("a#test_link").click(changeTheTextOfTheLink)
function changeTheTextOfTheLink(e) {
    e.preventDefault()
    $("a#test_link").append(' is now longer');
}

规格/链接-test.spec.js

describe ("my basic jasmine jquery test", function(){

    jasmine.getFixtures().fixturesPath = ''

    var loadScript = function(path) {
      appendSetFixtures('<script src="' + path + '"></script>');
    };

    beforeEach(function(){
        loadFixtures('templates/link.tmpl.html');
        loadScript('js/test-link.js');
    });

    it ("does some basic jQuery thing", function () {
        $('a#test_link').click();
        expect($("a#test_link")).toHaveText('My test link is now longer');
    });

    it ("does the same basic jQuery thing with a different event initiation method", function () {
        $('a#test_link').trigger('click');
        expect($("a#test_link")).toHaveText('My test link is now longer');
    });

});

规格赛跑者

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
  <title>Spec Runner</title>

  <link rel="stylesheet" type="text/css" href="lib/jasmine-2.0.3/jasmine.css">
  <script type="text/javascript" src="lib/jasmine-2.0.3/jasmine.js"></script>
  <script type="text/javascript" src="lib/jasmine-2.0.3/jasmine-html.js"></script>
  <script src="lib/jasmine-2.2/boot.js"></script>

  <script type="text/javascript" src="lib/jquery-2.1.3.min.js"></script>
  <script type="text/javascript" src="lib/jasmine-jquery.js"></script>

  <script type="text/javascript" src="specs/link-test.spec.js"></script>
</head>

<body>
</body>
</html>
于 2015-04-25T13:11:58.143 回答