Como posso fazer com que meus equipamentos de testes de jasmine sejam carregados antes que o javascript considere o documento como “pronto”?

Estou bastante certo de que o problema é que as ligações do jquery configuradas para rodar em $ (document) .ready não possuem o fixture html disponível para elas. Então, quando meus events ocorrem que pretendem fazer uma alteração no DOM por meio de uma function jquery, nada acontece e meus testes falham. Eu vi uma “solução” para este problema aqui , mas essa solução que funcionou para mim, exigia mudar minha function jquery de trabalho para ligar com o método .live em vez do método .click. Eu tenho dois problemas com isso. Primeiro eu não quero ter que mudar meu código de trabalho para que os testes passem corretamente. A estrutura de teste deve testar se o código funcionará no aplicativo, onde o carregamento do DOM e as ligações do javascript ocorrem na ordem correta. O segundo problema que tenho com a solução é que .on e .delegate não funcionaram por algum motivo e a única coisa que acabou funcionando foi usar o método .live que está atualmente no processo de ser preterido. Em conclusão, gostaria de descobrir como alterar meus testes ou a própria estrutura de teste, de forma que os fixtures sejam carregados antes das funções executadas em $ (document) .ready.

Eu estou trabalhando com rails 3.2.8 e eu tenho dois ramos diferentes configurados para experimentar o teste de jasmine. Um dos ramos usa a gema jasminerice e o outro usa a gema jasmine-rails. O Javascript e o jQuery (ao usar o método .live) testam todas as passagens corretamente em ambos os setups.

Aqui está uma descrição do ramo usando jasminerice:

Aqui estão as linhas do meu arquivo Gemfile.lock descrevendo a configuração do jasmine e jQuery:

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

O Jasminerice inclui a extensão jasmine-jquery por padrão. A extensão jasmine-jQuery fornece o método toHaveText que estou usando nos testes.

O arquivo de teste jasmine_jquery_test.js que está localizado diretamente no diretório spec / javascripts contém este conteúdo:

 #= 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); }); }); 

Meu arquivo javascript tests.js que está localizado no diretório app / assets / javascripts tem este conteúdo:

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

Meu arquivo application.js localizado no mesmo diretório app / assets / javascripts possui este conteúdo:

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

E a descrição da ramificação jasmine-rails pode ser encontrada no conteúdo da minha primeira pergunta stackoverflow relacionada ao teste de jasmine .

Então, se alguém tem uma idéia de como manipular os testes de modo que as funções $ (document) .ready sejam executadas depois que os equipamentos forem carregados, eu gostaria muito de ouvir seus pensamentos?

Adicionando o jQuery diretamente para o fixture html funcionou para mim para obter o comportamento desejado. Não é exatamente uma resposta para essa pergunta, mas estou começando a acreditar que é a melhor solução atualmente disponível. Minhas alterações foram feitas na configuração gem do jasmine-rails e ainda não tentei no branch jasminerice.

Aqui está o meu arquivo de teste:

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

E aqui está o meu arquivo de fixture:

 My test link  

Pessoalmente, considero isso um bug jasmine-jquery. Eu “resolvi” isso fazendo com que meus acessórios fizessem parte do SpecRunner.html. Não é ideal, mas funciona em casos simples.

Você já tentou jasmine-jquery?

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

De sua página github,

O jasmine-jquery fornece duas extensões para o Jasmine JavaScript Testing Framework:

um conjunto de adaptadores personalizados para a estrutura do jQuery uma API para lidar com fixtures HTML, CSS e JSON em suas especificações

Eu usei dom_munger para gerar automaticamente o equipamento para mim, então adicionar o código jquery manualmente dentro do aparelho não é uma opção para mim. Eu tenho procurado a mesma resposta, e a melhor solução que posso pensar agora é usar o delegado de evento no jQuery.

Por exemplo, em vez de escrever isto:

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

Faça isso:

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

Desta forma, o ouvinte é anexado ao documento, que está presente antes de o equipamento ser carregado. Então, quando o evento click acontece no #target, ele aparece no documento. O documento verifica se a origem corresponde ao segundo argumento – ‘#target’. Se corresponder, a function do manipulador será chamada.

Eu sei que existem limitações para isso, como inicializar plug-ins, mas isso resolve parte do problema.

Eu tomei uma abordagem ligeiramente diferente das descritas aqui para resolver essa limitação.

Isenção de responsabilidade: Eu trabalho para a Microsoft, então não posso postar meu código-fonte real aqui sem a aprovação legal, então vou descrever uma abordagem que funciona bem.

Em vez de tentar alterar o funcionamento do document.ready , modifiquei a fonte jasmine-jquery para suportar uma function chamada fixturesReady que recebe um retorno de chamada.

Essencialmente, isso é definido dentro de um IIFE e contém uma matriz de retornos de chamada por nome de evento de forma privada, que são iterados no acionador.

Então nesse pedaço você pode colocar o gatilho:

 jasmine.Fixtures.prototype.load = function() { this.cleanUp() this.createContainer_(this.read.apply(this, arguments)) fixturesReady.trigger("loaded", arguments); // <----- ADD THIS } 

Então, nos seus testes agora você pode codificar contra:

 fixturesReady(yourCallback) 

E você sabe que quando o seu yourCallback é invocado, você pode consultar com segurança o DOM para seus elementos de fixture.

Além disso, se você estiver usando o plugin async.beforeEach jasmine, poderá fazer isso:

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

Espero que ajude e sirva para lhe dar algumas ideias sobre como resolver este problema.

NOTA: Lembre-se em seu plugin para limpar qualquer retorno de chamada em um bloco afterEach , se necessário 🙂

Já faz um tempo que essa pergunta foi feita (e uma resposta aceita).

Aqui está uma abordagem melhor para estruturar seu teste e carregar o script para testes com o jasmine.

templates / link.tmpl.html

 My test link 

js / test-link.js

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

especificações / link-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'); }); }); 

Corredor da especificação

    Spec Runner