Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

angular jasmine: 'undefined' is not an object - broadcast within timeout - error

I have a function like this:

 $scope.doIt = function( x, y )
 {
   $timeout( function ()
   {
     $rootScope.$broadcast( 'xxx',
     {
        message: xxx,
        status: xxx
     } );
   } ); 
 }

This function works fine so far. But while writing a test I had some trouble.

describe( 'test doIt function...', function ()
      {
        var $rootScope, $timeout;

        beforeEach( inject( function ( _$rootScope_, _$timeout_ )
        {
          $rootScope = _$rootScope_;
          $timeout = _$timeout_;
          spyOn( $rootScope, '$broadcast' );
          spyOn( scope, 'doIt' ).and.callThrough();
        } ) );

        it( 'test broadcast will be called', inject( function ()
        {
          var testObj = {
            message: 'test1',
            status: 'test2'
          };

          scope.doIt( 'test1', 'test2' );

          expect( $rootScope.$broadcast ).not.toHaveBeenCalledWith( 'xxx', testObj );

          $timeout.flush();

          expect( $rootScope.$broadcast ).toHaveBeenCalledWith( 'xxx', testObj );

        } ) );
      }
    );

This will end up in the following error:

TypeError: 'undefined' is not an object (evaluating '$rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl, $location.$$state, oldState).defaultPrevented')

Why? What I am doing wrong? Without $timeout in function and test it works fine.

Thanks in advance for your help.

:)

Edit: Another broadcast then expected is issuing this issue. hmm

like image 378
Andy D. Avatar asked Dec 24 '14 08:12

Andy D.


2 Answers

I have fixed this problem by returning preventDefault

spyOn($rootScope, '$broadcast').and.returnValue({preventDefault: true})
like image 185
George Chen Avatar answered Oct 20 '22 21:10

George Chen


Problem -

Angular framework is trying to invoke $broadcast function and expecting a object from that function in return which have defaultPrevented property.

But because of

spyOn( $rootScope, '$broadcast' );

statement in beforeEach block the actual implementation of $broadcast couldn't be invoked and hence it does not return a object which contains defaultPrevented property.

Solution -

Move the spyOn( $rootScope, '$broadcast' ); statement from beforeEach block to it block exactly before scope.doIt( 'test1', 'test2' );.

like image 39
Prash Avatar answered Oct 20 '22 20:10

Prash