alexcrack / angular-ui-notification

Angular.js service providing simple notifications using Bootstrap 3 styles with css transitions for animating
MIT License
536 stars 169 forks source link

Unit test failure - Cannot read property 'offsetHeight' of undefined #97

Closed hotdog1987 closed 7 years ago

hotdog1987 commented 7 years ago

Hello, I wrote a custom service inside which i have calls to pop up the angular-ui-notification:

// IIFE construct for the service
(function(angular){
  // callback for the service
  function NotificationService(Notification,$rootScope){
    var self = this;

    /**
     * Clear Notification Messages
     */
    self.clearMessage = function(){
      console.log('Clear called in the service');
      Notification.clearAll();
    };

    /**
     * A Simple UI Notification Message with Timeout(delay)
     * @Param text  This is the actual notification message that needs to be displayed
     * @Param type  This is the type of the Notification message to be displayed. Possible values are info, success, warning, error
     * @Param titleInfo This is the text for the title of the message
     */
    self.showMessage = function(type, delayTime, $scope){
      self.clearMessage();
      switch (type){
        case 'info': {
          Notification.info({templateUrl: "app/components/Notifications/notification_template.html", scope: $scope, delay: delayTime});
        }
        break;
        case 'warning': {
          Notification.warning({templateUrl: "app/components/Notifications/notification_template.html", scope: $scope, delay: delayTime});
        }
        break;
        case 'success': {
          Notification.success({templateUrl: "app/components/Notifications/notification_template.html", scope: $scope, delay: delayTime});
        }
        break;
        case 'error': {
          Notification.error({templateUrl: "app/components/Notifications/notification_template.html", scope: $scope, delay: delayTime});
        }
        break;
      }
    };

    self.uiErrorConstant = function(title,message){
      $rootScope.notificationTitle = title;
      $rootScope.notificationMsg = message;
      $rootScope.notificationId = null;
      self.showMessage('error',null,$rootScope);
    }
  }

  // inject the dependencies - optional
  NotificationService.$inject = ['Notification','$rootScope'];
  angular.module('Notifications',['ui-notification'])
  .config(function(NotificationProvider) {
      NotificationProvider.setOptions({
          positionX: 'right',
          positionY: 'top',
          closeOnClick: false
      });
  })
  .service('NotificationService', NotificationService);
})(window.angular || (window.angular = {}));

Now, when I'm write unit test to another service which has the above service as dependency, i'm getting this error:

TypeError: Cannot read property 'offsetHeight' of undefined
            at client/bower_components/angular-ui-notification/dist/angular-ui-notification.js:147:59
            at client/bower_components/angular/angular.js:11477:13
            at processQueue (client/bower_components/angular/angular.js:16383:28)
            at client/bower_components/angular/angular.js:16399:27
            at Scope.$eval (client/bower_components/angular/angular.js:17682:28)
            at Scope.$digest (client/bower_components/angular/angular.js:17495:31)
            at Scope.$apply (client/bower_components/angular/angular.js:17790:24)
            at done (client/bower_components/angular/angular.js:11831:47)
            at handleResponse (client/bower_components/angular-mocks/angular-mocks.js:1368:9)
            at Function.$httpBackend.flush (client/bower_components/angular-mocks/angular-mocks.js:1808:26)

UNIT TEST:

describe('MyService Test', function() {
    beforeEach(module('MyApp'));
    beforeEach(module('httpIntercept'));

    var $scope, $window, $state, $rootScope, $mdDialog, $httpBackend, mappingConstant, $document, $compile, elem, MyService ;

    beforeEach(inject(function(_$rootScope_,_$window_,_$state_,_$mdDialog_, _$httpBackend_, _mappingConstant_, _$document_, _$compile_, _MyService_) {
        // The injector unwraps the underscores (_) from around the parameter names when matching
        $rootScope = _$rootScope_;
        $scope = _$rootScope_.$new();
        MyService = _MyService_;
        $mdDialog = _$mdDialog_;
        $httpBackend = _$httpBackend_;
        mappingConstant = _mappingConstant_;
        $document = _$document_;
        $compile = _$compile_;

    $httpBackend.whenGET('app/pages/login/login.html').respond(200);
    $httpBackend.whenGET('app/pages/home/home.html').respond(200);

    }));

    it('Case 01 - Logic for initialization:', function() {
      MyService.init($scope);
      expect(true).toBe(true);
  });

  it('Case 02 - Logic for PUT call:', function() {
    $scope.request = {
      name: null
    };
    $httpBackend.when('PUT','/rest/MyService/confirmChange').respond(200,{
      "status":"SUCCESS",
      "results": [{
        id: '1',
        name: 'test'
      }]
    });

    $httpBackend.whenGET('../index.html').respond(200);
    $httpBackend.whenGET('app/components/Notifications/notification_template.html').respond(200);

    MyService.confirmChange({},$scope,$mdDialog);
    $httpBackend.expect('PUT','/rest/MyService/confirmChange');
    $httpBackend.flush();

    expect($rootScope.showProgress).toBeFalsy();
  });
});

Any help would be greatly appreciated. Thanks.

hotdog1987 commented 7 years ago

Looks like the $httpBackend.whenGET('app/components/Notifications/notification_template.html') was incorrect. Instead i tried $templateCache.put('app/components/Notifications/notification_template.html', '<div class="ui-notification custom-template"></div>'); The reason being that the element was never created and that the ui notification points to undefined template. Once, the cache has the template it went through.

Sorry for any inconvenience caused.