mardi 23 février 2016

Testing function bound to resize event on AngularJS window

I'm new to JS in general, and definitely new to Angular, Mocha, Sinon, etc.

I have an angular service factory, which checks the size of the window to calculate a relative size, then binds to the resize event on $window. See the code below.

angular.module('components').factory('SizeService', function ($window, $rootScope) {

  var f = {};
  var screenSize = 0;

  function calculateScreenSize() {
    if ($window.innerWidth >= 1368) {
      return 'lg';
    } else if ($window.innerWidth >= 1050) {
      return 'md';
    ... //additional else if blocks
  }
  screenSize = calculateScreenSize();

  f.getScreenSize = function () {
    return screenSize;
  };

  angular.element($window).bind('resize', function () {
    var newScreenSize = calculateScreenSize();
    if (screenSize !== newScreenSize) {
      var lastScreenSize = screenSize;
      screenSize = newScreenSize;

      $rootScope.$broadcast('sizeChange', lastScreenSize, screenSize);
      $rootScope.$apply();
    }
  });

  return f;
});

I'd like to test the bind, and ensure that resizing across the boundaries properly emits the new relative size of the screen.

At the simplest form, I'd like to just set the size of the window initially, set the new size, and ensure that the SizeService responds appropriately. I can't seem to find any information about simulating events bound using angular.element.bind in unit tests.

My current test code is:

describe('Size Service', function() {
  var service, sandbox, $scope, testWindow;

  beforeEach(module('components'));

  function initializeWindowAndService(windowWidth) {
    testWindow = {innerWidth: windowWidth};

    module(function($provide) {
      $provide.value('$window', testWindow);
    });

    inject(function ($injector, $rootScope) {
      $scope = $rootScope;

      service = $injector.get('SizeService');
    });
  }

  it('calculates large screen size correctly', function() {
    initializeWindowAndService(2000);
    expect(queryService.getScreenSize()).to.equal('lg');
  });
  ... //tests for other sizes/boundaries/etc

  it('handles resize events correctly', function() {
    intializeWindowAndService(2000);
    expect(queryService.getScreenSize()).to.equal('lg');

    testWindow.innerWidth = 1300;
    //mystery code to trigger resize event, digest, etc

    expect(queryService.getScreenSize()).to.equal('md');
  });
});

Is there code I can put in the "mystery code" comment that will trigger a resize event through the normal Angular channels? It needs to work with Chrome (48), Firefox (38), and PhantomJS (1.9.8). I'd prefer not to significantly refactor the original code, though I'm open to suggestions if it will make testing easier and more intuitive.

Thanks in advance!

Aucun commentaire:

Enregistrer un commentaire