Search code examples
javascriptrequirejsphantomjsqunitgrunt-contrib-qunit

How to setup grunt task for requirejs and qunit


I am trying to setup a QUnit environment using requirejs and grunt-contrib-qunit.

Here is what I have.

gruntfile:

qunit: {
  all: {
    options: {
      urls: [
        'http://localhost:8000/qunit/qunit-test-suite.html'
      ]
    }
  }
},

connect: {
  server: {
    options: {
      port: 8000,
      base: '.'
    }
  }
},

qunit-test-suite.html:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>QUnit Tests Suite: travis CI Test</title>
  <link rel="stylesheet" href="../components/libs/qunit/qunit/qunit.css">
</head>
<body>

  <div id="qunit"></div>
  <div id="qunit-fixture"></div>

  <script src="../components/libs/qunit/qunit/qunit.js"></script>
  <script>
    QUnit.config.autoload = false;
    QUnit.config.autostart = false;
  </script>

  <script data-main="qunit" src="../components/libs/requirejs/require.js"></script>

</body>
</html>

qunit.js:

require.config({
    baseUrl: "../",
    paths: {
      'jquery': 'components/libs/jquery/dist/jquery.min',

      // Test for Foo
      'foo': 'components/app/foo/foo',
      'test-Foo': 'components/app/foo/test-Foo'
    },
    shim: {
     'QUnit': {
       exports: 'QUnit',
       init: function() {
         QUnit.config.autoload = false;
         QUnit.config.autostart = false;
       }
      }
    }
});

require(['test-Foo'], function (Foo) {
  QUnit.load();
  QUnit.start();
});

test-Foo.js:

define(['foo'], function(Foo) {

  'use strict';

  module("Foo");

  test("Foo return Test", function() {
    equal(Foo.foo(), "foo", "Function should return 'foo'");
    equal(Foo.oof(), "oof", "Function should return 'oof'");
  });

  test("Bar return Test", function() {
    equal(Foo.bar(), "barz", "Function should return 'bar'");
  });

});

Problem is that it all works fine when I open up the test-suite.html in my browser. Once sent to PhantomJS I get the following error:

Running "connect:server" (connect) task
Started connect web server on http://localhost:8000

Running "qunit:all" (qunit) task
Testing http://localhost:8000/qunit/qunit-test-suite.html

>> PhantomJS timed out, possibly due to a missing QUnit start() call.
Warning: 1/1 assertions failed (0ms) Use --force to continue.

Aborted due to warnings.

Full setup: https://github.com/markusfalk/test-travis

Test Run: https://travis-ci.org/markusfalk/test-travis

Thanks for any help :)


Solution

  • With the help of Jörn I came up with a working setup. Trick is to setup requireJS before QUnit loads (moved requireJS config to config.js and load it first).

    Requirements:

    • grunt-contrib-qunit v0.7.0
    • qunit v1.18.0

    HTML test suite:

    <!doctype html>
    <html>
      <head>
        <meta charset="utf-8">
        <title>QUnit Tests Suite: asdf</title>
        <link rel="stylesheet" href="../components/libs/qunit/qunit/qunit.css">
      </head>
      <body>
    
        <div id="qunit"></div>
        <div id="qunit-fixture"></div>
    
        <script src="config.js"></script>
        <script data-main="unit" src="../components/libs/requirejs/require.js"></script>
    
      </body>
    </html>
    

    config.js

    var requirejs = {
      baseUrl: "../",
      paths: {
        //{{app}}
        'foo': 'components/app/foo/foo',
        'test-foo': 'components/app/foo/test-foo',
    
        //{{libs}}
        'unit': 'qunit/unit',
        'qunit': 'components/libs/qunit/qunit/qunit',
        'jquery.exists': 'libs/jquery.exists/jquery.exists',
        'jquery': 'components/libs/jquery/dist/jquery.min'
      },
      'shim': {
        'jquery.exists': ['jquery']
      }
    };
    

    unit.js

    require([
      'qunit',
      'test-foo'
    ],
    function(qunit, TestFoo) {
      TestFoo();
      qunit.start();
    });
    

    test-foo.js:

    define(['jquery', 'qunit', 'foo'], function($, qunit, Foo) {
      'use strict';
      return function() {
        qunit.module("Foo");
        qunit.test("Foo Test", function() {
          equal(Foo.saySomething(), "Hello", "returns 'Hello'");
        });
      };
    });
    

    And finally the module I want to test:

    define(['jquery'], function($) {
      'use strict';
      var Foo = {
        saySomething: function() {
          return "Hello";
        }
      };
      return {
        saySomething: Foo.saySomething
      };
    });