Javascript – TypeError: undefined is not an object (evaluating ‘scope.awesomeThings’)

angularjsgruntjsjavascriptkarma-jasmineyeoman-generator-angular

I got this error every time I run grunt test command. I setup a project using yo angular and try to run example code given in yeoman's scaffold. I don't what went wrong here, below are code which I tried to test.

controller/main.js

angular.module('brandPortalApp')
  .controller('MainCtrl', function ($scope) {
    $scope.awesomeThings = [
      'HTML5 Boilerplate',
      'AngularJS',
      'Karma'
    ];
  });

test/controllers/main.js

'use strict';

describe('Controller: MainCtrl', function () {
  // load the controller's module
  beforeEach(module('brandPortalApp'));
  var MainCtrl,
  scope;

  // Initialize the controller and a mock scope
  beforeEach(inject(function ($controller, $rootScope) {
    scope = $rootScope.$new();
    MainCtrl = $controller('MainCtrl', {
      $scope: scope
    });
  }));

  it('should attach a list of awesomeThings to the scope', function () {
    expect(scope.awesomeThings.length).toBe(3);
  });
});

karma.conf.js

// Karma configuration
// http://karma-runner.github.io/0.12/config/configuration-file.html
// Generated on 2016-05-27 using
// generator-karma 0.8.3

module.exports = function(config) {
  'use strict';

  config.set({
    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // base path, that will be used to resolve files and exclude
    basePath: '../',

    // testing framework to use (jasmine/mocha/qunit/...)
    frameworks: ['jasmine'],

    // list of files / patterns to load in the browser
    files: [
      'bower_components/angular/angular.js',
      'bower_components/angular-mocks/angular-mocks.js',
      'bower_components/angular-animate/angular-animate.js',
      'bower_components/angular-aria/angular-aria.js',
      'bower_components/angular-cookies/angular-cookies.js',
      'bower_components/angular-messages/angular-messages.js',
      'bower_components/angular-resource/angular-resource.js',
      'bower_components/angular-route/angular-route.js',
      'bower_components/angular-sanitize/angular-sanitize.js',
      'bower_components/angular-touch/angular-touch.js',
      'app/scripts/**/*.js',
      'test/mock/**/*.js',
      'test/spec/**/*.js'
    ],

    // list of files / patterns to exclude
    exclude: [],

    // web server port
    port: 8080,

    // Start these browsers, currently available:
    // - Chrome
    // - ChromeCanary
    // - Firefox
    // - Opera
    // - Safari (only Mac)
    // - PhantomJS
    // - IE (only Windows)
    browsers: [
      'PhantomJS'
    ],

    // Which plugins to enable
    plugins: [
      'karma-phantomjs-launcher',
      'karma-jasmine'
    ],

    // Continuous Integration mode
    // if true, it capture browsers, run tests and exit
    singleRun: false,

    colors: true,

    // level of logging
    // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
    logLevel: config.LOG_INFO,

    // Uncomment the following lines if you are using grunt's server to run the tests
    // proxies: {
    //   '/': 'http://localhost:9000/'
    // },
    // URL root prevent conflicts with the site root
    // urlRoot: '_karma_'
  });
};

In Terminal

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

Running "karma:unit" (karma) task WARN [watcher]: Pattern
"/Users/kiwitech/Brand-Portal/test/mock/**/*.js" does not match any
file. INFO [karma]: Karma v0.13.22 server started at
http://localhost:8080/ INFO [launcher]: Starting browser PhantomJS
INFO [PhantomJS 2.1.1 (Mac OS X 0.0.0)]: Connected on socket
/#NDwIB4AQl7giaVxJAAAA with id 29519679 PhantomJS 2.1.1 (Mac OS X
0.0.0) Controller: MainCtrl should attach a list of awesomeThings to the scope FAILED
forEach@/Users/kiwitech/Brand-Portal/bower_components/angular/angular.js:322:24
loadModules@/Users/kiwitech/Brand-Portal/bower_components/angular/angular.js:4548:12
createInjector@/Users/kiwitech/Brand-Portal/bower_components/angular/angular.js:4470:30
workFn@/Users/kiwitech/Brand-Portal/bower_components/angular-mocks/angular-mocks.js:2464:60
/Users/kiwitech/Brand-Portal/bower_components/angular/angular.js:4588:53
TypeError: undefined is not an object (evaluating 'scope.todos') in /Users/kiwitech/Brand-Portal/test/spec/controllers/main.js (line
20)
/Users/kiwitech/Brand-Portal/test/spec/controllers/main.js:20:17 PhantomJS 2.1.1 (Mac OS X 0.0.0): Executed 1 of 1 (1 FAILED) ERROR
(0.005 secs / 0.015 secs) Warning: Task "karma:unit" failed. Use
–force to continue.

Aborted due to warnings.

I checked other question related to this but those solution not work for this.

Thanks for help!!

Best Answer

I'm not sure if you solved it, but in case you didn't, the issue is with paths in karma.conf.js. I had a similar issue with my angularApp.

As I'm not sure what your architecture is, I made test by myself (pretty much dirty, ie: not optimized), and of course paths should be changed according to the architecture you have.

jasmineApp folder:

├── app
│   └── scripts
├── bower_components
│   ├── angular
│   ├── angular-animate
│   ├── angular-aria
│   ├── angular-cookies
│   ├── angular-messages
│   ├── angular-mocks
│   ├── angular-resource
│   ├── angular-route
│   ├── angular-sanitize
│   └── angular-touch
└── test
    └── controllers

testing file is test/controllers/main.js:

'use strict';

  // run first test to check karma - I always run this simple test
  // before starting with real tests

  describe('Simple test', function(){
    it("a is in fact 'hello world'", function(){
      var a = "Hello world";
      expect(a).toBe('Hello world');
    });
  });

  describe('Controller: MainCtrl', function () {

    // load the controller's module
    beforeEach(module('brandPortalApp'));

    var MainCtrl,
      scope;

    // Initialize the controller and a mock scope
    beforeEach(inject(function ($controller, $rootScope) {
      scope = $rootScope.$new();
      MainCtrl = $controller('MainCtrl', {
        $scope: scope
      });
    }));

    it('should attach a list of awesomeThings to the scope', function () {
      expect(scope.awesomeThings.length).toBe(3);
    });
  });

controller file is app/controller/main.js:

angular.module('brandPortalApp',[])
console.log('loaded')
angular.module('brandPortalApp')
  .controller('MainCtrl', function ($scope) {
    $scope.awesomeThings = [
      'HTML5 Boilerplate',
      'AngularJS',
      'Karma'
    ];
  });

karma.config.js is something like this:

// Karma configuration
// http://karma-runner.github.io/0.12/config/configuration-file.html
// Generated on 2016-05-27 using
// generator-karma 0.8.3

module.exports = function(config) {
  'use strict';

  config.set({
    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // base path, that will be used to resolve files and exclude
    basePath: '../',

    // testing framework to use (jasmine/mocha/qunit/...)
    frameworks: ['jasmine'],

    // list of files / patterns to load in the browser
    files: [
      'jasmineApp/bower_components/angular/angular.js',
      'jasmineApp/bower_components/angular-mocks/angular-mocks.js',
      'jasmineApp/bower_components/angular-animate/angular-animate.js',
      'jasmineApp/bower_components/angular-aria/angular-aria.js',
      'jasmineApp/bower_components/angular-cookies/angular-cookies.js',
      'jasmineApp/bower_components/angular-messages/angular-messages.js',
      'jasmineApp/bower_components/angular-resource/angular-resource.js',
      'jasmineApp/bower_components/angular-route/angular-route.js',
      'jasmineApp/bower_components/angular-sanitize/angular-sanitize.js',
      'jasmineApp/bower_components/angular-touch/angular-touch.js',

      'jasmineApp/app/scripts/**/*.js',
      //'test/mock/**/*.js',
      'jasmineApp/test/controllers/main.js'
    ],

    // list of files / patterns to exclude
    exclude: [],

    // web server port
    port: 8080,

    // Start these browsers, currently available:
    // - Chrome
    // - ChromeCanary
    // - Firefox
    // - Opera
    // - Safari (only Mac)
    // - PhantomJS
    // - IE (only Windows)
    browsers: [
      'PhantomJS'
    ],

    // Which plugins to enable
    plugins: [
      'karma-phantomjs-launcher',
      'karma-jasmine'
    ],

    // Continuous Integration mode
    // if true, it capture browsers, run tests and exit
    singleRun: false,

    colors: true,

    // level of logging
    // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
    logLevel: config.LOG_INFO,

    // Uncomment the following lines if you are using grunt's server to run the tests
    // proxies: {
    //   '/': 'http://localhost:9000/'
    // },
    // URL root prevent conflicts with the site root
    // urlRoot: '_karma_'
  });
};

running test the output is OK:

21 07 2016 10:58:38.705:WARN [karma]: No captured browser, open http://localhost:8080/
21 07 2016 10:58:38.718:INFO [karma]: Karma v1.1.1 server started at http://localhost:8080/
21 07 2016 10:58:38.719:INFO [launcher]: Launching browser PhantomJS with unlimited concurrency
21 07 2016 10:58:38.755:INFO [launcher]: Starting browser PhantomJS
21 07 2016 10:58:39.017:INFO [PhantomJS 2.1.1 (Linux 0.0.0)]: Connected on socket /#BUObAGDOLqCbC0uRAAAA with id 56816897
PhantomJS 2.1.1 (Linux 0.0.0) LOG: 'loaded'

PhantomJS 2.1.1 (Linux 0.0.0): Executed 1 of 1 SUCCESS (0.006 secs / 0.009 secs)

Changing the path for main.js file in karma.config.js from working one

'jasmineApp/app/scripts/**/*.js',

to this

'app/scripts/**/*.js', // wrong path

the error you got, is back:

21 07 2016 11:01:48.645:WARN [watcher]: Pattern "/var/www/NODEJS/app/scripts/**/*.js" does not match any file.
21 07 2016 11:01:48.664:WARN [karma]: No captured browser, open http://localhost:8080/
21 07 2016 11:01:48.674:INFO [karma]: Karma v1.1.1 server started at http://localhost:8080/
21 07 2016 11:01:48.674:INFO [launcher]: Launching browser PhantomJS with unlimited concurrency
21 07 2016 11:01:48.690:INFO [launcher]: Starting browser PhantomJS
21 07 2016 11:01:48.955:INFO [PhantomJS 2.1.1 (Linux 0.0.0)]: Connected on socket /#YK-fqsro3-ebMO2kAAAA with id 84208961
PhantomJS 2.1.1 (Linux 0.0.0) Controller: MainCtrl should attach a list of awesomeThings to the scope FAILED
    forEach@jasmineApp/bower_components/angular/angular.js:321:24
    loadModules@jasmineApp/bower_components/angular/angular.js:4592:12
    createInjector@jasmineApp/bower_components/angular/angular.js:4514:30
    workFn@jasmineApp/bower_components/angular-mocks/angular-mocks.js:3067:60
    loaded@http://localhost:8080/context.js:151:17
    jasmineApp/bower_components/angular/angular.js:4632:53
    TypeError: undefined is not an object (evaluating 'scope.awesomeThings') in jasmineApp/test/controllers/main.js (line 20)
    jasmineApp/test/controllers/main.js:20:19
    loaded@http://localhost:8080/context.js:151:17
PhantomJS 2.1.1 (Linux 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.042 secs / 0.007 secs)

I hope will help.