Qunit error: assertion outside test context
Asked Answered
O

2

11

I've searched all over and it appears this error is due to not using asyncTest properly. However, per the documentation, it appears that I am doing it correctly. I'm guessing I'm missing a small detail somewhere and need an extra pair of eyes...

I'm trying to test some code that makes an ajax request to get a page and then loads it in a lightbox. lightbox-content does not show up in the DOM until after the ajax call has completed and can be displayed. So, I can only check for it in my onComplete call back, which is where I have my test to see if it loaded it correctly.

Here is my code:

asyncTest('mytest', 1, function() {
    utils.lightbox.show('/login', {
        onComplete: function() {
            ok($('#lighbox-content').is(':visible'), 'Lightbox loaded the /login page.');
            start();
        }
    });
});

I get the error:

Uncaught Error: assertion outside test context, was at HTMLDivElement.window.utils

Can anyone see where I'm going wrong?

Observation answered 5/6, 2013 at 20:22 Comment(2)
Is the missing t in lighbox-content a typo while posting your question?Shermanshermie
I have the same error message, the error appears inside on('load' callback instead of onComplete, but I think it's all the same under the hood. Have you tried downgrading to different QUnit version?Tadich
S
7

I agree that your code matches the documentation as far as I can tell.

Update

Even though the documentation doesn't show it, I wonder if you must tell QUnit to stop at some point so it knows to wait after the test function returns. I would think that QUnit assumes this since it's an async test, but it's worth a shot.

asyncTest('mytest', 1, function() {
    stop();
    ...
});

I've been using Sinon.JS to avoid making the AJAX calls in the first place. This has three immediate benefits:

  1. I don't depend on a server to respond to the requests.
  2. I can specify different results for each test.
  3. The tests run much faster.

The mocking can be done at the XMLHttpRequest level or on the jQuery method and is quite easy. Here's an example from one of my tests:

module("geo", {
    setup: function () {
        this.server = sinon.fakeServer.create();
    },

    teardown: function () {
        this.server.restore();
    }
}

test("returns detected ZIP code", function () {
    this.server.respondWith("/geo/detect-zip-from-ip",
                            [ 200, { "Content-Type": "text/html" }, '90210' ]);
    geo.detectZip(function (zip) {
        assertThat(zip, is('90210'));
    });
    this.server.respond();
});
Shermanshermie answered 10/6, 2013 at 20:35 Comment(3)
Thanks David. I'll play around with this and give it a shot. I'm still interested in the Qunit issue too.Observation
It was the "stop();" thing for me. Thanks for reminding it. :)Skyline
@Observation Any luck solving this issue?Shermanshermie
T
0

I have found a solution for my case, hope your problem has the same source.

Explaining in words:

  • I have a complicated asynchronous test
  • I have delayed events, and there are ok and equal assertions inside
  • Of course, all this is wrapped inside asyncTest
  • But, when the test is "completed" and I call start(), the event handlers remain there
  • After calling start(), all further calls of ok inside that asyncTest become illegal
  • And throw exceptions
  • I wonder what happens if the number in expect(in your example it's the second parameter) is exceeded. The same exception?

Explaining in code:

    asyncTest('mytest', /*1,*/ function() {

          function imgLoadedOrFailed (result) {
              clearTimeout(imageTimeToLive);
              img.off();
              ok(result, 'Image in carousel pane has been loaded');
          }

          var imageTimeToLive = setTimeout(
                  imgLoadedOrFailed.bind(this, false), 
                  5000),
              img = panes[index].find('img:first');

          if (img) {
              img.on('load', imgLoadedOrFailed.bind(this, true));
              img.on('error', imgLoadedOrFailed.bind(this, false));
          }
      });


      // at some point I call: start();

In this example, when I "finish" the test calling start(), the onload and onerror events can still happen.

Tadich answered 25/7, 2013 at 12:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.