jonasnas
jonasnas

Reputation: 3580

unit test template in angular modal service ($uibModal)

I have a very simple service.show() which basically calls $uibModal with some configuration and returns the modal instance

function modalService($uibModal) {
  return {
    show(message) {
      return $uibModal.open({
        bindToController: true,
        controllerAs: '$ctrl',
        template: "<div id='message'>{{$ctrl.message}}</div>",
        controller: [function() {
          this.message = message;
        }]
      });
    }
  }
}

I would like to write a test to validate actual modal and if it contains expected message. Something like this:

it('should show correct message', (done) => {
    modal = modalService.show('hello');
    modal.rendered.then(()=> {
      expect($('#message').text()).toBe('hello');
      done()
    });
  });

but rendered promise is never resolved. I can do some workaround like wrapping expect into $timeout and do $timeout.flush() but not sure if this is correct way and even in this way I still can't do a cleanup (afterEach) to close the modal and be ready to test another message.

Upvotes: 0

Views: 808

Answers (1)

Gaurav
Gaurav

Reputation: 1233

The correct way will be to open the modal window look for the message and close it and as bootstrap is using ngAnimate for the animation we will have to include ngAnimateMock module to flush the pending animation.

Check the below code for the solution:

var myApp = angular.module('myApp', ['ngAnimate', 'ui.bootstrap']);

myApp.factory('modalService', ['$uibModal', function($uibModal) {
  return {
    show(message) {
      return $uibModal.open({
        bindToController: true,
        controllerAs: '$ctrl',
        template: '<div id="message">{{$ctrl.message}}</div>',
        controller: [function() {
          this.message = message;
        }]
      });
    }
  }
}]);

describe('modalService service', function() {
  describe('modalService', function() {
    var modalService;
    var $rootScope;
    var $animate;

    beforeEach(function() {
      module('ngAnimateMock')
      module('uib/template/modal/window.html')
      module('myApp');
    });

    beforeEach(inject(function(_$rootScope_, _modalService_, _$animate_) {
      $rootScope = _$rootScope_;
      modalService = _modalService_;
      $animate = _$animate_;
    }));

    it('should open the dialog with the correct message', () => {
      var modal = modalService.show('hello');

      $rootScope.$digest();
      // Finish the animation.
      $animate.flush();

      expect($('#message').text()).toEqual('hello');

      // Close the dialog.
      modal.close();

      $rootScope.$digest();
      // Finish the animation.
      $animate.flush();
    });

    it('again should show the correct message', () => {
      var modal = modalService.show('new message');

      $rootScope.$digest();
      // Finish the animation.
      $animate.flush();

      expect($('#message').text()).toEqual('new message');

      // Close the dialog.
      modal.close();

      $rootScope.$digest();
      // Finish the animation.
      $animate.flush();
    });
  });
});
<body>
  <!-- because we are testing our controller and not running we don't need a controller or even a module -->
  <!-- so there is no ng-app or ng-controller in the markup -->

  <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/jasmine/2.0.0/jasmine.css">

  <!-- the order that these files load is critical, think twice before changing -->
  <script src="//cdnjs.cloudflare.com/ajax/libs/jasmine/2.0.0/jasmine.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/jasmine/2.0.0/jasmine-html.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/jasmine/2.0.0/boot.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.js"></script>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-animate.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-mocks.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/2.5.0/ui-bootstrap-tpls.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/2.5.0/ui-bootstrap.min.js"></script>

  <h2>Finished jasmine-unit-test</h2>

</body>

Upvotes: 1

Related Questions