在javascript认为文档“准备好”之前,如何让我的茉莉花测试装置加载?

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

我正在使用rails 3.2.8,我设置了两个不同的分支来试验茉莉花测试。 其中一个分支使用jasminerice gem,另一个使用jasmine-rails gem。 Javascript和jQuery(当使用.live方法时)测试所有这两个菜单中的正确传递。

以下是使用jasminerice的分支的描述:

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

jasminerice (0.0.9) coffee-rails haml jquery-rails (2.1.3) railties (>= 3.1.0,  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(){ $('My test link').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); }); }); 

我的javascript文件tests.js位于app / assets / javascripts目录中,其内容如下:

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

我的application.js文件位于相同的app / assets / javascripts目录中,其内容如下:

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

并且jasmine-rails分支的描述可以在我的第一个jasmine测试相关stackoverflow问题的内容中找到。

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

将jQuery直接添加到html fixture中,可以帮助我获得所需的行为。 这不是这个问题的答案,但我开始相信它是目前可用的最佳解决方案。 我在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); }); }); 

这是我的夹具文件:

 My test link  

就个人而言,我认为这是一个bug jasmine-jquery。 我通过使我的灯具成为SpecRunner.html的一部分来“解决”这个问题。 不理想,但它在简单的情况下工作。

你试过jasmine-jquery吗?

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

从它的github页面,

jasmine-jquery为Jasmine JavaScript Testing Framework提供了两个扩展:

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

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

例如,而不是写这个:

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

做这个:

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

以这种方式,监听器附着到文档,该文档在加载夹具之前存在。 因此,当#target上发生click事件时,它会冒泡到文档。 文档检查原点是否与第二个参数匹配 – ‘#target’。 如果匹配,则将调用处理函数。

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

我对这里描述的方法略有不同,以解决这个限制。

免责声明:我为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以获取fixture元素。

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

 async.beforeEach(function(done){ fixturesReady(done); ... loadFixtures("...."); }); 

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

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

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

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

模板/ link.tmpl.html

 My test link 

JS /测试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(''); }; 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'); }); }); 

Spec Runner

    Spec Runner