Question

My question is quite simple but hard to answer... how to inject a $scope to an AngularJs controller under test using google closure tools.

The controller is quite simple, basically it performs a http request to the server through the _getOrganisations function

Here is the actual controller:

goog.provide 'MyModule.controllers.Menu'

MyModule.controllers.Menu = ($scope, $http, $location, SomeService) ->
  _getOrganisations = () ->

    $http({SomeRequestOptions})
      .success(_handleGetOrganisationsSuccessCallback)
      .error(_handleGetOrganisationsErrorCallback)

  _handleGetOrganisationsSuccessCallback = (result, status) ->
    $scope.organisations = result

  _handleGetOrganisationsErrorCallback = (err, status) ->
    [...]

  $scope.toggleMenu = () ->
    angular.element('.nav-collapse').collapse('toggle')

  _getOrganisations()

Here is how I tried to test my controller

describe 'menu controller', () =>

    result=
        org1 : ''
        org2 : ''
        org3 : ''

    beforeEach () ->
        goog.require 'MyModule.controllers.Menu'

        inject ($rootScope, $controller, $http, $httpBackend) ->
            scope = $rootScope.$new()
            httpBackend = $httpBackend
            httpBackend.whenGET({SomeRequestOptions}).respond result
            menuController = $controller new MyModule.controllers.Menu(), {$scope : scope, $http : $http}

    it 'should get organisations properly', () ->
        expect(scope.organisations).toEqual(result)

When I'm trying to assign my actual controller to the menuController, $scope is undefined... What am I missing here ?

Was it helpful?

Solution

I can see a scope problem with the code in your test. I commented directly in the code.

describe 'menu controller', () =>

    result=
        org1 : ''
        org2 : ''
        org3 : ''

    beforeEach () ->
        goog.require 'MyModule.controllers.Menu'

        inject ($rootScope, $controller, $http, $httpBackend) ->
            # here you define a variable inside a function...
            scope = $rootScope.$new()
            httpBackend = $httpBackend
            httpBackend.whenGET({SomeRequestOptions}).respond result
            menuController = $controller new MyModule.controllers.Menu(), {$scope : scope, $http : $http}

    it 'should get organisations properly', () ->
        # here you try to access the variable from outside the function
        expect(scope.organisations).toEqual(result)

I haven't tested the code but I'm quite sure something like this would solve it. According to this post. http://odetocode.com/blogs/scott/archive/2013/06/10/simple-unit-tests-with-angularjs.aspx

describe 'menu controller', () =>
    scope = null
    result=
        org1 : ''
        org2 : ''
        org3 : ''

    beforeEach () ->
        goog.require 'MyModule.controllers.Menu'

        inject ($rootScope, $controller, $http, $httpBackend) =>
            scope = $rootScope.$new()
            httpBackend = $httpBackend
            httpBackend.whenGET({SomeRequestOptions}).respond result
            menuController = $controller new MyModule.controllers.Menu(), {$scope : scope, $http : $http}

    it 'should get organisations properly', () ->
        expect(scope.organisations).toEqual(result)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top