title: Problems with testing SignalR with Jasmine in Angular app
body: <p>I have a serious issue here. My application relies on SignalR functionality, but because of that I am unable to write unit tests. I am new to testing frameworks and have used Jasmine only in simple cases. SignalR has proven to be too much of a challenge for me, but I need to understand how I can successfully test it. 
  This is my CommsApp.ts file [typescript]:</p>
  
  <pre><code>/// &lt;reference path="References.ts" /&gt;
  var commsAnimationsModule = angular.module('forge.communications.animations', ['ngAnimate']);
  var commsDirectivesModule = angular.module('forge.communications.directives', []);
  var commsServicesModule = angular.module('forge.communications.services', []);
  var commsFiltersModule = angular.module('forge.communications.filters', []);
  
  var commsApp = angular.module('forge.communications.CommsApp',
      [
          'ngRoute',
          'ngAnimate',
          'cfValidation',
          'ui.bootstrap',
          'forge.communications.animations',
          'forge.communications.directives',
          'forge.communications.services',
          'forge.communications.filters',
          'angularFileUpload',
          'timeRelative'
      ]);
  
  commsApp.config(function ($routeProvider: ng.route.IRouteProvider, $locationProvider: any) {
  
          $locationProvider.html5Mode(true);
          $routeProvider.
              when('/scheduled-messages', {
                  templateUrl: '/forge/CommsApp/js/Controllers/ScheduledMessageList/ScheduledMessageList.html',
                  controller: 'ScheduledMessageListController'
              }).
              when('/geotriggered-messages', {
                  templateUrl: '/forge/CommsApp/js/Controllers/GeoMessageList/GeoMessageList.html',
                  controller: 'GeoMessageListController'
              }).
              when('/scheduled-message/create', {
                  templateUrl: '/forge/CommsApp/js/Controllers/CreateScheduledMessage/CreateScheduledMessage.html',
                  controller: 'CreateScheduledMessageController'
              }).
              when('/scheduled-message/edit/:id', {
                  templateUrl: '/forge/CommsApp/js/Controllers/EditScheduledMessage/EditScheduledMessage.html',
                  controller: 'EditScheduledMessageController'
              }).
              when('/geotriggered-message/create', {
                  templateUrl: '/forge/CommsApp/js/Controllers/CreateGeotriggeredMessage/CreateGeotriggeredMessage.html',
                  controller: 'CreateGeotriggeredMessageController'
              }).
              when('/geotriggered-message/edit/:id', {
                  templateUrl: '/forge/CommsApp/js/Controllers/EditGeotriggeredMessage/EditGeotriggeredMessage.html',
                  controller: 'EditGeotriggeredMessageController'
              }).
              otherwise({
                  redirectTo: '/scheduled-messages'
              });
      });
  
  commsApp.run(function ($rootScope: ICommsRootScope, commsSignalrEventService: CommsSignalrEventService, commsMgmtHttpService: CommsMgmtHttpServiceClient) {
  
      // set up the items on the root scope
      $rootScope.SelectedLocale = 'en-ie';
      $rootScope.ForgeApplicationKey = "9496B737-7AE2-4FBD-B271-A64160759177";
      $rootScope.AppVersionString = "1.0.0";
      $rootScope.SessionToken = getCookie("ForgeSessionToken");
  
      commsSignalrEventService.initialize().done(() =&gt; {
          // send any messages about a new user logging in to the application here.
      });
  
      // call this at app startup to  pre-cache this data for the create and edit pages
      commsMgmtHttpService.GetUpdateMessageEditorOptions();
  });
  
  function getCookie(name:string) {
      var value = "; " + document.cookie;
      var parts = value.split("; " + name + "=");
      if (parts.length == 2) return parts.pop().split(";").shift();
  }
  </code></pre>
  
  <p>This is the test file (I removed most of the code since it's not working anyway, I have been chasing my own tail here):</p>
  
  <pre><code>describe('forge.communications.CommsApp', function () {
  
      beforeEach(module('forge.communications.CommsApp'));
  
      var route, rootScope, proxy, commsSignalrEventService;
  
      beforeEach(inject(function (_$route_, _$rootScope_, _commsSignalrEventService_) {
          route = _$route_,
          rootScope = _$rootScope_;
          commsSignalrEventService = _commsSignalrEventService_;
      }));
  
      describe("should map routes to controllers and templates", function () {
  
          it("/scheduled-messages route should be mapped to ScheduledMessageListController", function () {
              expect(2).toEqual(2);
              expect(route.routes['/scheduled-messages'].controller).toBe('ScheduledMessageListController');
          });
  
      });
  });
  </code></pre>
  
  <p>This is CommsSignalREventService.ts file:</p>
  
  <pre><code>var servicesModule: ng.IModule = angular.module('forge.communications.services');
  
  servicesModule.factory('commsSignalrEventService', function ($rootScope): CommsSignalrEventService {
      return new CommsSignalrEventService($rootScope);
  });
  
  class CommsSignalrEventService {
  
  private $rootScope: ng.IScope;
  private proxy:any = null;
  
  constructor($rootScope) {
      this.$rootScope = $rootScope;
  }
  
  public initialize(): JQueryPromise&lt;any&gt;{
  
      this.proxy = $.connection['communicationsCenterHub'];
  
      console.log('proxy',this.proxy);
  
      //scheduled messages
      this.proxy.client.broadcastScheduledMessageCreatedEvent = (messageId: number) =&gt; {
          this.$rootScope.$broadcast('comms-message-created', { messageId: messageId });
      };
  
      this.proxy.client.broadcastScheduledMessageUpdatedEvent = (messageId: number) =&gt; {
          this.$rootScope.$broadcast('comms-message-updated', { messageId: messageId });
      };
  
      this.proxy.client.broadcastScheduledMessageStateChangedEvent = (messageId: number) =&gt; {
          this.$rootScope.$broadcast('comms-message-statechanged', { messageId: messageId });
      };
  
      this.proxy.client.broadcastScheduledMessageDeletedEvent = (messageId: number) =&gt; {
          this.$rootScope.$broadcast('comms-message-deleted', { messageId: messageId });
      };
  
      //geotriggered messages
      this.proxy.client.broadcastGeoMessageCreatedEvent = (messageId: number) =&gt; {
          this.$rootScope.$broadcast('comms-geomessage-created', { messageId: messageId });
      };
  
      this.proxy.client.broadcastGeoMessageUpdatedEvent = (messageId: number) =&gt; {
          this.$rootScope.$broadcast('comms-geomessage-updated', { messageId: messageId });
      };
  
      this.proxy.client.broadcastGeoMessageStateChangedEvent = (messageId: number) =&gt; {
          this.$rootScope.$broadcast('comms-geomessage-statechanged', { messageId: messageId });
      };
  
      this.proxy.client.broadcastGeoMessageDeletedEvent = (messageId: number) =&gt; {
          this.$rootScope.$broadcast('comms-geomessage-deleted', { messageId: messageId });
      };
  
      var promise = $.connection.hub.start();
      promise.done(function () {
          //console.log('comms signalr hub started');
      });
      return promise;
  }
  
      public RegisterScheduledMessageCreated(messageId: number): void{
          this.proxy.server.registerScheduledMessageCreated(messageId);
      }
  
      public RegisterScheduledMessageUpdated(messageId: number): void {
          this.proxy.server.registerScheduledMessageUpdated(messageId);
      }
  
      public RegisterScheduledMessageDeleted(messageId: number): void {
          this.proxy.server.registerScheduledMessageDeleted(messageId);
      }
  
      public RegisterScheduledMessageStateChanged(messageId: number): void {
          this.proxy.server.registerScheduledMessageStateChanged(messageId);
      }
  
      public RegisterGeoMessageCreated(messageId: number): void {
          this.proxy.server.registerGeoMessageCreated(messageId);
      }
  
     public RegisterGeoMessageUpdated(messageId: number): void {
         this.proxy.server.registerGeoMessageUpdated(messageId);
      }
  
      public RegisterGeoMessageDeleted(messageId: number): void {
          this.proxy.server.registerGeoMessageDeleted(messageId);
      }
  
      public RegisterGeoMessageStateChanged(messageId: number): void {
          this.proxy.server.registerGeoMessageStateChanged(messageId);
      }
  }
  </code></pre>
  
  <p>The error I am seeing constantly in the command line, whenever I run karma, is forge.communications.CommsApp encountered a declaration exception FAILED
  TypeError: Cannot read property 'client' of undefined at CommsSignalREventService, meaning that the 'proxy' variable in CommsSignalREventService.ts file is undefined: </p>
  
  <pre><code>this.proxy = $.connection['communicationsCenterHub'];
  console.log('proxy', this.proxy); //resolves to UNDEFINED in tests, works fine in the app
  
  this.proxy.client.broadcastScheduledMessageCreatedEvent = function (messageId) {
          _this.$rootScope.$broadcast('comms-message-created', { messageId: messageId });
      };
  </code></pre>
  
  <p>I will appreciate any help, because the amount of time I have put trying to figure it out is beyond ridiculous at this stage.</p>