Repository: angular/angular.js
File: test/ng/directive/ngEventDirsSpec.js (JavaScript)

Code before:
      });

      inject(function($rootScope, $compile, $exceptionHandler, $log) {

        element = $compile('<button ng-click="click()">Click</button>')($rootScope);
        expect($log.assertEmpty());
        $rootScope.click = function() {
          throw new Error('listener error');
        };

        $rootScope.$watch(function() {
          $rootScope.click();
          $log.log('done');
        });

        $rootScope.$digest();

        // The error gets caught in the traverseScopesLoop try catch, and the $log is never reached
        expect($exceptionHandler.errors).toEqual([Error('listener error')]);
        expect($log.log.logs).toEqual([]);
        $log.reset();
      });
    });


    it('should not stop the digest when the event is fired in a watch expression fn', function() {

      module(function($exceptionHandlerProvider) {
        $exceptionHandlerProvider.mode('log');
      });

      inject(function($rootScope, $compile, $exceptionHandler, $log) {

        element = $compile('<button ng-click="click()">Click</button>')($rootScope);
        $rootScope.click = function() {
          throw new Error('listener error');
        };

        $rootScope.$watch(function() {
          element.triggerHandler('click');
          $log.log('done');
        });

        $rootScope.$digest();

        // The error gets caught in the event directive and never reaches the traverseScopesLoop error handler
        expect($exceptionHandler.errors).toEqual([Error('listener error'), Error('listener error')]);
        expect($log.log.logs).toEqual([['done'], ['done']]);
        $log.reset();
      });
    });

Review comment (suggestion):
@jbedard if you trigger a click event handler inside a watch expression fn, then the additional try catch changes how the error gets logged, and in this case, anything that comes after the handler is called, whereas when you call the handler directly and throw, what comes after the handler is not called. See the test above for the different outcome.

Code after:

        expect($exceptionHandler.errors).toEqual([Error('listener error')]);
        expect($log.log.logs).toEqual([['done']]);
        $log.reset();
      });
    });


    it('should not stop execution if the event is triggered inside a digest', function() {

      module(function($exceptionHandlerProvider) {
        $exceptionHandlerProvider.mode('log');
      });

      inject(function($rootScope, $compile, $exceptionHandler, $log) {

        element = $compile('<button ng-click="click()">Click</button>')($rootScope);
        expect($log.assertEmpty());
        $rootScope.click = function() {
          throw new Error('listener error');
        };

        $rootScope.do = function() {
          element.triggerHandler('click');
          $log.log('done');
        };

        $rootScope.$apply(function() {
          $rootScope.do();
        });

        expect($exceptionHandler.errors).toEqual([Error('listener error')]);
        expect($log.log.logs).toEqual([['done']]);
        $log.reset();
      });
    });


    it('should not stop execution if the event is triggered in a watch expression function', function() {

      module(function($exceptionHandlerProvider) {
        $exceptionHandlerProvider.mode('log');
      });

      inject(function($rootScope, $compile, $exceptionHandler, $log) {

        element = $compile('<button ng-click="click()">Click</button>')($rootScope);
        $rootScope.click = function() {
          throw new Error('listener error');
        };