javascriptunit-testingiframejasminefuncunit

unit testing JS app with page reloads and iframes


I have an app for which page reloads / navigation and iframes are crucial and those part seem very tricky to cover with unit tests.

I want to be able to write smt. like this:

it('should fire appropriate callbacks on start and page reload', function() {
  app.start();
  expect(app.onStart).toHaveBeenCalled();
  page.reload();
  expect(app.onRestart).toHaveBeenCalled();
}

it('should know whether it runs in iframe or not', function() {
  expect(app.isInIframe()).toBe(false);
  iframe = createTestIframe();
  expect(iframe.getApp().isInIframe()).toBe(true);
}

Unit testing frameworks I know of (mocha, Jasmine, QUnit) are all designed to do entire test suite on one page, in top context.

On the other hand, functional testing frameworks (FuncUnit, TestCafé, Selenium WebDriver) seem to focus on high-level abstractions, such as "click an element", "check element's value" etc, not giving an ability to dig into code execution.

Disclaimer: I'm rather new to testing in general, so maybe I should look at the problem from a different perspective altogether.


Solution

  • Intern is designed exactly to enable these sorts of functional tests in these sorts of situations, and was actually created due to the issue you describe where existing JS test frameworks didn’t enable these sorts of interactions. It includes a functional testing interface that would work like so, assuming app is on the Node.js side of things, you’d do something like this:

    define([ 'intern!bdd', 'intern/chai!expect', 'my/app' ], function (bdd, expect, app) {
       var it = bdd.it;
    
       it('should fire appropriate callbacks on start and page reload', function() {
         app.start();
         return this.remote.get('http://path/to/server')
           .then(function () {
             expect(app.onStart).toHaveBeenCalled();
           })
           .refresh()
           .then(function () {
             expect(app.onRestart).toHaveBeenCalled();
           });
       });
    
       // ...etc.
    });
    

    The Intern tutorial provides a better overview of the difference between unit and functional testing and how to use both. Unlike some other suggestion like CasperJS, it actually will run your functional tests against real browsers, using the standard WebDriver API, in conjunction with a service like Sauce Labs or your own Selenium server.