lundi 19 septembre 2016

How to mock $window.Notification

I am still learning the ropes when it comes to unit testing with angular. I have an angular service that I use to create HTML5 notifications. Code is similar to the following:

(function() {
  'use strict';

  angular
    .module('blah')
    .factory('OffPageNotification', offPageNotificationFactory);

  function offPageNotificationFactory($window) {
    //Request permission for HTML5 notifications as soon as we can
    if($window.Notification && $window.Notification.permission !== 'denied')     {
      $window.Notification.requestPermission(function (status) { });
    }

    function OffPageNotification () {
      var self = Object.create(OffPageNotification.prototype);
      self.visibleNotification = null;
      return self;
    }


 OffPageNotification.prototype.startNotification = function (options) {
      var self = this;
      self.options = options;
      if(self.options.showHtml5Notification && (!self.options.onlyShowIfPageIsHidden || $window.document.hidden)) {
    if($window.Notification && $window.Notification.permission !== 'denied')     {
          self.visibleNotification = new $window.Notification('Notification',     {
              body: self.options.notificationText,
              icon: self.options.notificationIcon
            });
        }
      }
    };

    .
    .
    .
  return new OffPageNotification();
  }
})();

I am attempting to write unit tests for this but am unsure how to mock $window.Notification so it can be used as both a constructor...

self.visibleNotification = new $window.Notification(....)

and also contain properties

if($window.Notification && $window.Notification.permission !== 'denied')

and methods....

$window.Notification.requestPermission(

An example of something I have tried is:

     describe('startNotification', function() {

     beforeEach(function() {
       var mockNotification = function (title, options) {
         this.title = title;
         this.options = options;
         this.requestPermission = sinon.stub();
       };

       mockNotification.prototype.permission = 'granted';

       mockWindow = {
         Notification: new mockNotification('blah', {}),
         document: {hidden: true}
       };

       inject(function (_OffPageNotification_) {
         OffPageNotification = _OffPageNotification_;
       });
     });

     it('should display a html5 notification if the relevant value is true in the options, and permission has been granted', function(){
       var options = {
         showHtml5Notification: true,
         onlyShowIfPageIsHidden: true
       };
       OffPageNotification.startNotification(options);
     });
  });

I get an error saying '$window.Notification is not a constructor' with this setup and I understand why (I am passing in an instantiated version of the mockNotification). But if I set mockWindow.Notification = mockNotification then I get an error when it calls requestPermission since this is undefined.

Any help is appreciated

Aucun commentaire:

Enregistrer un commentaire