web-dev-qa-db-ja.com

javascriptがドキュメントを「準備完了」と見なす前に、ジャスミンテストフィクスチャをロードするにはどうすればよいですか?

$(document).readyで実行するように設定されたjqueryバインディングでは、フィクスチャhtmlを使用できないことが問題であると確信しています。したがって、jquery関数を介してDOMに変更を加えることを目的としたイベントが発生しても、何も起こらず、テストは失敗します。この問題の「解決策」を見ました ここ 、しかし私のために働いたその解決策は、.clickメソッドの代わりに.liveメソッドでバインドするように私の働いているjquery関数を変更する必要がありました。これには2つの問題があります。まず、テストが正しく合格するように、作業コードを変更する必要はありません。テストフレームワークは、コードがアプリで機能するかどうかをテストする必要があります。アプリでは、DOMの読み込みとJavaScriptのバインドが正しい順序で行われます。このソリューションで私が抱えている2番目の問題は、.onと.delegateの両方が何らかの理由で機能せず、最終的に機能するのは、現在非推奨になっている.liveメソッドを使用することだけでした。結論として、$(document).readyで実行される関数の前にフィクスチャがロードされるように、テストまたはテストフレームワーク自体を変更する方法を理解したいと思います。

私はRails 3.2.8で作業しており、ジャスミンテストを実験するために2つの異なるブランチを設定しています。ブランチの1つはジャスミネリスの宝石を使用し、もう1つはジャスミン-レールの宝石を使用しています。 JavascriptとjQuery(.liveメソッドを使用する場合)のテストはすべて、これらのセットアップの両方で適切に合格します。

Jasminericeを使用したブランチの説明は次のとおりです。

ジャスミンとjQueryのセットアップを説明するGemfile.lockファイルの行は次のとおりです。

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ブランチの説明は、私の 最初のジャスミンテスト関連のstackoverflowの質問 のコンテンツにあります。

それで、フィクスチャがロードされた後に$(document).ready関数が実行されるようにテストを操作する方法を誰かが知っているなら、私はあなたの考えを聞きたいですか?

15

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>
6

個人的には、これはバグjasmine-jqueryだと思います。フィクスチャをSpecRunner.htmlの一部にすることで、これを「解決」しました。理想的ではありませんが、単純なケースで機能します。

1
Guy Royse

Jasmine-jqueryを試しましたか?

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

Githubページから、

jasmine-jqueryは、Jasmine JavaScript TestingFrameworkに2つの拡張機能を提供します。

jQueryフレームワークのカスタムマッチャーのセット仕様でHTML、CSS、およびJSONフィクスチャを処理するためのAPI

1
LeeGee

この質問がされてからしばらく経ちました(そして答えが受け入れられました)。

これは、テストを構造化し、ジャスミンでテストするためのスクリプトをロードするためのより良いアプローチです。

テンプレート/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');
}

specs/link-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>
1
Nicholas Murray

この制限を解決するために、ここで説明するアプローチとは少し異なるアプローチを採用しました。

免責事項:私はマイクロソフトで働いているため、法的な承認なしに実際のソースコードをここに投稿することはできません。代わりに、適切に機能するアプローチについて説明します。

document.readyの動作を変更しようとするのではなく、コールバックを受け取るfixturesReadyという関数をサポートするようにjasmine-jqueryソースを変更しました。

基本的に、これは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.beforeEach jasmineプラグインを使用している場合は、次のようにすることができます。

async.beforeEach(function(done){

    fixturesReady(done);

    ...

    loadFixtures("....");

});

それがこの問題を解決するためのいくつかのアイデアを提供するのに役立つことを願っています。

注:プラグインでは、必要に応じてafterEachブロック内のコールバックをクリアすることを忘れないでください:)

1
Darius

dom_munger を使用してフィクスチャを自動的に生成したため、フィクスチャ内にjqueryコードを手動で追加することはできません。私は同じ答えを探していましたが、今考えられる最善の解決策は、jQueryでイベントデリゲートを使用することです。

たとえば、これを書く代わりに:

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

これを行う:

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

このようにして、リスナーは、フィクスチャがロードされる前に存在するドキュメントにアタッチされます。したがって、クリックイベントが#targetで発生すると、ドキュメントにバブルアップします。ドキュメントは、Originが2番目の引数( '#target')と一致するかどうかを確認します。一致する場合、ハンドラー関数が呼び出されます。

プラグインの初期化など、これには制限があることは知っていますが、問題の一部は解決します。

1
Yunzhou