title: Karma-Jasmine: How to properly spy on a Modal?
body: <p><strong>THE SITUATION:</strong></p>
  
  <p>I am unit testing my Angular / Ionic app. </p>
  
  <p>I am having troubles with the modal. 
  At the moment i can test that the modal has been called. That's all so far. I cannot test the proper show() and hide() method of the modal.</p>
  
  <p>I am getting the following errors:</p>
  
  <pre><code>TypeError: $scope.modal_login.show is not a function
  Error: show() method does not exist
  
  TypeError: $scope.modal_login.hide is not a function
  Error: hide() method does not exist
  </code></pre>
  
  <p>I think it depends entirely on the spy. I don't know how to properly spy on the modal, and i think that once that is done, everything will work fine.</p>
  
  <p><strong>THE CODE:</strong></p>
  
  <p><strong>The controller:</strong></p>
  
  <pre><code>$scope.open_login_modal = function() 
  {
      var temp = $ionicModal.fromTemplateUrl('templates/login.html',{scope: $scope});
  
      temp.then(function(modal) { 
          $scope.modal_login = modal;
          $scope.modal_login.show();
  
          $scope.for_test_only = true;
      });
  };
  
  $scope.close_login_modal = function() 
  {
      $scope.modal_login.hide();
  };
  </code></pre>
  
  <p>Note: the code of open_login_modal function has been refactored to facilitate the test. The original code was:</p>
  
  <pre><code>$scope.open_login_modal = function() 
  {
      $ionicModal.fromTemplateUrl('templates/login.html', {
          scope: $scope
      }).then(function(modal) {
  
          $scope.modal_login = modal;
          $scope.modal_login.show();
      }); 
  };
  </code></pre>
  
  <p><strong>The test:</strong></p>
  
  <pre><code>describe('App tests', function() 
  {
      beforeEach(module('my_app.controllers'));
  
      function fakeTemplate() 
      {
          return { 
              then: function(modal){
                  $scope.modal_login = modal;
              }
          }
      }
  
      beforeEach(inject(function(_$controller_, _$rootScope_)
      {
          $controller = _$controller_;
          $rootScope = _$rootScope_;
          $scope = _$rootScope_.$new();
  
          $ionicModal = 
          {
              fromTemplateUrl: jasmine.createSpy('$ionicModal.fromTemplateUrl').and.callFake(fakeTemplate)
          }; 
  
          var controller = $controller('MainCtrl', { $scope: $scope, $rootScope: $rootScope, $ionicModal: $ionicModal });
      }));
  
  
      describe('Modal tests', function() 
      {
          beforeEach(function()
          {
              $scope.open_login_modal();
              spyOn($scope.modal_login, 'show'); // NOT WORKING
              spyOn($scope.modal_login, 'hide'); // NOT WORKING
          });
  
          it('should open login modal', function() 
          {
              expect($ionicModal.fromTemplateUrl).toHaveBeenCalled(); // OK
              expect($ionicModal.fromTemplateUrl.calls.count()).toBe(1); // OK
              expect($scope.modal_login.show()).toHaveBeenCalled(); // NOT PASS
              expect($scope.for_test_only).toEqual(true); // NOT PASS
          });
  
          it('should close login modal', function() 
          {
              $scope.close_login_modal();     
              expect($scope.modal_login.hide()).toHaveBeenCalled(); // NOT PASS
          });
      });
  
  });
  </code></pre>
  
  <p>As you can see from the code $scope.for_test_only it should be equal to true but is not recognized. I get this error message instead:</p>
  
  <pre><code>Expected undefined to equal true.
  </code></pre>
  
  <p>The same happens to the show() and hide() method. They are not seen by the test. </p>
  
  <p>And i think because they are not declared in the spy.</p>
  
  <p><strong>THE QUESTION:</strong></p>
  
  <p>How can i properly spy on a modal?</p>
  
  <p>Thank you very much!</p>