Search code examples
javascriptangularjsgruntjsbowerintern

getting angular and intern.io working together


I'm trying to set up Intern.io so I can test my angular app. I'm also using Grunt and Bower. I'm just trying to get barebones watch task that automatically runs the tests. My problem when I try to run tests is I get the following error message:

Running "intern:app" (intern) task
ReferenceError: window is not defined
    at /Users/evanvandegriff/Documents/work/nomi_v2/nomi_v2/web/vendor/src/angular/angular.js:19288:3
    at Function.vm.runInThisContext (/Users/evanvandegriff/Documents/work/nomi_v2/nomi_v2/web/node_modules/intern/node_modules/istanbul/lib/hook.js:163:16)
    at /Users/evanvandegriff/Documents/work/nomi_v2/nomi_v2/web/node_modules/intern/node_modules/dojo/dojo.js:760:8
    at fs.js:271:14
    at Object.oncomplete (fs.js:107:15)
Warning: ReferenceError: window is not defined
    at /Users/evanvandegriff/Documents/work/nomi_v2/nomi_v2/web/vendor/src/angular/angular.js:19288:3
    at Function.vm.runInThisContext (/Users/evanvandegriff/Documents/work/nomi_v2/nomi_v2/web/node_modules/intern/node_modules/istanbul/lib/hook.js:163:16)
    at /Users/evanvandegriff/Documents/work/nomi_v2/nomi_v2/web/node_modules/intern/node_modules/dojo/dojo.js:760:8
    at fs.js:271:14
    at Object.oncomplete (fs.js:107:15) Use --force to continue.

My app.js looks like:

angular.module( 'ngNomi', [

])

.config( function myAppConfig () {

})

.run( function run () {

})

.controller( 'AppCtrl', function AppCtrl ( $scope, $location ) {

});

Here is my intern.js file:

// Learn more about configuring this file at <https://github.com/theintern/intern/wiki/Configuring-Intern>.
// These default settings work OK for most people. The options that *must* be changed below are the
// packages, suites, excludeInstrumentation, and (if you want functional tests) functionalSuites.
define({
    // The port on which the instrumenting proxy will listen
    proxyPort: 9000,

    // A fully qualified URL to the Intern proxy
    proxyUrl: 'http://localhost:9000/',

    // Default desired capabilities for all environments. Individual capabilities can be overridden by any of the
    // specified browser environments in the `environments` array below as well. See
    // https://code.google.com/p/selenium/wiki/DesiredCapabilities for standard Selenium capabilities and
    // https://saucelabs.com/docs/additional-config#desired-capabilities for Sauce Labs capabilities.
    // Note that the `build` capability will be filled in with the current commit ID from the Travis CI environment
    // automatically
    capabilities: {
        'selenium-version': '2.41.0'
    },

    // Browsers to run integration testing against. Note that version numbers must be strings if used with Sauce
    // OnDemand. Options that will be permutated are browserName, version, platform, and platformVersion; any other
    // capabilities options specified for an environment will be copied as-is
    environments: [
        { browserName: 'internet explorer', version: '11', platform: 'Windows 8.1' },
        { browserName: 'internet explorer', version: '10', platform: 'Windows 8' },
        { browserName: 'internet explorer', version: '9', platform: 'Windows 7' },
        { browserName: 'firefox', version: '28', platform: [ 'OS X 10.9', 'Windows 7', 'Linux' ] },
        { browserName: 'chrome', version: '34', platform: [ 'OS X 10.9', 'Windows 7', 'Linux' ] },
        { browserName: 'safari', version: '6', platform: 'OS X 10.8' },
        { browserName: 'safari', version: '7', platform: 'OS X 10.9' }
    ],

    // Maximum number of simultaneous integration tests that should be executed on the remote WebDriver service
    maxConcurrency: 3,

    // Name of the tunnel class to use for WebDriver tests
    tunnel: 'SauceLabsTunnel',

    // The desired AMD loader to use when running unit tests (client.html/client.js). Omit to use the default Dojo
    // loader
    // useLoader: {
    //  'host-node': 'dojo/dojo',
    //  'host-browser': 'node_modules/dojo/dojo.js'
    // },

    // Configuration options for the module loader; any AMD configuration options supported by the specified AMD loader
    // can be used here
    loader: {
        packages: [
            { name: 'angular', location: 'vendor/src/angular/angular' },
            { name: 'angular-mocks', location: 'vendor/src/angular/angular-mocks' }
        ]
    },

    // Non-functional test suite(s) to run in each browser
    suites: [ 'src/app.test.js' ],

    // Functional test suite(s) to run in each browser once non-functional tests are completed
    functionalSuites: [ /* 'myPackage/tests/functional' */ ],

    // A regular expression matching URLs to files that should not be included in code coverage analysis
    excludeInstrumentation: /^node_modules/
});

Basically, how do I get the window to be defined in that file when running tests?


Solution

  • I think it is a matter of expectation of how intern.js views the testing landscape. Angular inherently runs in a browser context, so it needs a window global. The main iffe on line 24699 does (window). We must use intern-runner not intern-client so we can drive a browser, that has a window context.

    But you probably want to run headless and fast, like Karma examples show. So, we simply configure intern.js to use phantomjs under the hood to run our unit test with intern-runner. It is a "suite" (unit test) in the intern world that must be run in a browser context, like phantomjs. This is good for developers, who need rapid fire testing in a browser, but don't want to deal with firing up a browser in their desktop os. You will need selenium-server running to drive phantom. So:

    1.) run selenium-server standalone, I use : https://www.npmjs.org/package/selenium-standalone locally. Start this in a separate cmd console.

    selenium-standalone start

    2.) npm install phantomjs

    3.) In the intern-config file do:

         environments: [
           { browserName: 'phantomjs' }
          ],
      loader: {
            // Packages that should be registered with the loader in each testing environment
            packages: [
                { name: 'angular', location: 'bower_components/angular' },
                { name: 'angular-mocks', location: 'bower_components/angular-mocks' }
            ]
    
      },
    

    4.) Run $node node_modules\intern\bin\intern-runner config=your/config suites=angular-test

    And you will be golden.

    Here is my baby step unit test, proving angular loads. From there, you can do anything angulary you wish with angular mocks, or whatever.

    define([
            'intern/chai!expect',
            'intern!bdd',
            'intern/order!angular/angular'
        ], function (expect, bdd) {
    
            function inject (fn) {
                return function() {
                    angular.injector(['ng']).invoke(fn);
                }
            }
    
            bdd.describe('Scope Test', function () {
                var ctrl, scope;
    
                bdd.beforeEach(inject(function ($controller, $rootScope) {
                    scope = $rootScope.$new();
                }));
    
                bdd.it('should have an angular object', function () {
    
                    expect(angular).to.be.an('object');
                });
    
    
                });
    
    
    });