Why does $state change on $apply with Karma/Jasmine


#1

Hi

I am trying to create unit tests for my app. Testing a controller, when calling $scope.$apply (to resolve promises), my test fails:

Error: Unexpected request: GET app/login/login.html
No more request expected
    at $httpBackend (E:/mood/www/lib/angular-mocks/angular-mocks.js:1210:9)
    at sendReq (E:/mood/www/lib/ionic/js/ionic.bundle.js:19165:9)
    at serverRequest (E:/mood/www/lib/ionic/js/ionic.bundle.js:18877:16)
    at processQueue (E:/mood/www/lib/ionic/js/ionic.bundle.js:23399:28)
    at E:/mood/www/lib/ionic/js/ionic.bundle.js:23415:27
    at Scope.$eval (E:/mood/www/lib/ionic/js/ionic.bundle.js:24678:28)
    at Scope.$digest (E:/mood/www/lib/ionic/js/ionic.bundle.js:24489:31)
    at Scope.$apply (E:/mood/www/lib/ionic/js/ionic.bundle.js:24783:24)
    at Object.<anonymous> (E:/mood/www/app/mood/moodCtrl.unit.spec.js:112:16)

The app uses Firebase and mockfirebase for testing. But it does not seem to be due to $requireAuth not resolving and switching $state to login.

Why does $state change to login? How can i figure out what triggers the $state switch?


#2

could you show us your testfile and the real ctrl code?


#3

$state didn’t change as i thought, it was just fetching all template files on $apply.

Using quick fix from github.com/angular-ui/ui-router/issues/212:

$httpBackend.whenGET(/app.*/).respond(200, '');

I find it strange that Angular requesting template files makes a test fail.


#4

in an unit test --> you are testing only a single component (controller, directive, service, …)
But if you are using something like modal and your controller loads a template --> the angular template cachefactory loads the template and this is simply a get-request on a webserver.

and that the tests fails is okay --> because you want to test this component, sometimes you forget to remove some code you do not need. And know you are like what the heck is happening… why are the controller loads non expected templates or sends strange requests.


#5

It is loading all template file defined in $stateProvider.
From reading the previous linked issue, it seems that $ionicTemplateCache service is causing this.
I did not succeed in disabling it in the test though.


#6

hey there:

iam using this module to avoid that --> it converts html templates to js files and put them in the templateCache:

install it --> add it to you devDependencies in your package.json

after that pu the following in your karma.conf:

preprocessors: {
    'app/templates/**/*.html': ['ng-html2js'], // add your template paths
},

ngHtml2JsPreprocessor: { // this changes the name of the files --> e.g. stripping app and add/assets as new path
    stripPrefix: 'app',
    prependPrefix: '/assets'
}

#7

I’ve tried that now, but it’s not working. My config file:

module.exports = function(config) {
    config.set({

        // base path that will be used to resolve all patterns (eg. files, exclude)
        basePath: '',


        // frameworks to use
        // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
        frameworks: ['jasmine'],


        // list of files / patterns to load in the browser
        files: [
            'www/lib/ionic/js/ionic.bundle.js',
            'www/lib/firebase-3.2.1.js',
            'www/lib/angularfire-1.1.3.min.js',
            'www/lib/momentjs/min/moment.min.js',
            'www/lib/momentjs/min/locales.min.js',
            'www/lib/humanize-duration/humanize-duration.js',
            'www/lib/angular-timer.min.js',
            'www/lib/firechat/firechat.js',
            'www/lib/angular-mocks/angular-mocks.js',
            'www/lib/mockfirebase/browser/mockfirebase.js',
            'www/app/app.modules.js',
            'www/app/**/*.js'
        ],

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

        preprocessors: {
            'www/app/**/*.html': ['ng-html2js'], // add your template paths
        },

        ngHtml2JsPreprocessor: { // this changes the name of the files --> e.g. stripping app and add/assets as new path
            stripPrefix: 'app',
            prependPrefix: '/assets'
        },


        // test results reporter to use
        // possible values: 'dots', 'progress'
        // available reporters: https://npmjs.org/browse/keyword/karma-reporter
        reporters: ['progress'],


        // web server port
        port: 9876,


        // enable / disable colors in the output (reporters and logs)
        colors: true,


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


        // enable / disable watching file and executing tests whenever any file changes
        autoWatch: true,


        // start these browsers
        // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
        browsers: ['Chrome'],


        // Continuous Integration mode
        // if true, Karma captures browsers, runs the tests and exits
        singleRun: false,

        // Concurrency level
        // how many browser should be started simultanous
        concurrency: Infinity
    })
}

#8

did you installed it via npm before?

And btw. use $rootScope.$digest() and not $rootScope.$apply() in your tests


#9

Yes, i did npm install karma-ng-html2js-preprocessor --save-dev


#10

A bit late, but still, I’ve solved it differently. I’ve got all my states in a different file (routes.js) so I just don’t load it in karma config, BANG, no error!

Hope it’ll help someone else.