How can I get my jasmine tests fixtures to load before the javascript considers the document to be “ready”?

后端 未结 6 2396
星月不相逢
星月不相逢 2021-01-01 21:51

I am fairly certain that the issue is that the jquery bindings set to run on $(document).ready do not have the fixture html available to them. So when my events occur that

相关标签:
6条回答
  • 2021-01-01 22:16

    Have you tried jasmine-jquery?

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

    From it's github page,

    jasmine-jquery provides two extensions for Jasmine JavaScript Testing Framework:

    a set of custom matchers for jQuery framework an API for handling HTML, CSS, and JSON fixtures in your specs

    0 讨论(0)
  • 2021-01-01 22:22

    Adding the jQuery directly to the html fixture worked for me to get the desired behavior. It is not exactly an answer to this question, but I am starting to believe it's the best solution currently available. My changes where made in the jasmine-rails gem set-up and I haven't yet tried it in the jasminerice branch.

    Here is my test file:

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

    And here is my fixture file:

    <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>
    
    0 讨论(0)
  • 2021-01-01 22:23

    Personally, I consider this to be a bug jasmine-jquery. I "solved" this by making my fixtures part of the SpecRunner.html. Not ideal but it works in simple cases.

    0 讨论(0)
  • 2021-01-01 22:26

    I used dom_munger to automatically generate the fixture for me, so adding the jquery code manually inside the fixture isn't an option for me. I've been searching for the same answer, and the best solution I can think of right now is to use event delegate in jQuery.

    For example, instead of writing this:

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

    Do this:

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

    In this way, the listener is attached to the document, which is present before the fixture is loaded. So when the click event happens on #target, it bubbles up to document. Document checks if the origin matches the second argument - '#target'. If it matches, the handler function will be called.

    I know there are limitations to this, such as initializing plug-ins, but it does solve part of the problem.

    0 讨论(0)
  • 2021-01-01 22:27

    It has been a while since this question was asked (and an answer accepted).

    Here is a better approach to structure your test and load the script for testing with jasmine.

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

    Spec Runner

    <!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>
    
    0 讨论(0)
  • 2021-01-01 22:31

    I took a slightly different approach to those described here to solve this limitation.

    Disclaimer: I work for Microsoft so I cannot post my actual source code here without legal approval, so instead I'll just describe an approach that works well.

    Rather than trying to change how document.ready works, I modified the jasmine-jquery source to support a function called fixturesReady that takes a callback.

    Essentially this is defined inside an IIFE, and holds an array of callbacks per event name privately, that are iterated over on trigger.

    Then on this chunk you can put the trigger:

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

    So in your tests now you can code against:

    fixturesReady(yourCallback)
    

    And you know that when yourCallback is invoked you can safely query the DOM for your fixture elements.

    Additionally, if you're using the async.beforeEach jasmine plugin you could do this:

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

    Hope that helps, and serves to give you some ideas about solving this problem.

    NOTE: Remember in your plugin to clear any callbacks in an afterEach block if necessary :)

    0 讨论(0)
提交回复
热议问题