在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