user3897395
user3897395

Reputation: 113

Cannot get the scope os a controller in anugular.js

I am trying to test a javascript file which has in it a controller and some HTML DOM elements which it interacts with.

The class under test is:

function BaseConceptMenu(options) {
 var baseConceptMenu = new BaseMenu(options);

   //Public function -->Method under Test
   function showCodeConceptToolbar() {
    var scope = angular.element('#toolbar').scope();
    scope.$apply(function() {
        scope.toolbarController.show(baseConceptMenu.someObject);
    });
}

I am trying to mock the controller and create the HTML DOM element "toolbar" on the fly without trying to create an external HTML template just for the sake of testing.

I am trying to create the div "toolbar" inside the before each and mocking the "CodeConceptToolbarController" controller

beforeEach(inject(function ($rootScope, $compile) {
      elm = document.createElement('div');
      elm.id = 'toolbar';

        scope = $rootScope.$new();
        createController = function() {
            return $controller('CodeConceptToolbarController', {
                $scope: scope
            });
        };
        $compile(elm)(scope);
        scope.$digest();
    }));

However when I try to test it as below

it('Test Code ConeptToolbarContoller', function() {
//   var toolbar = angular.element('#toolbar');

    document.getElementById("toolbar").scope().toolbarController = createController();
   //As of now,not doing any-idepth testing
   //Just a base test call
    var menu = new BaseConceptMenu({});
    expect(menu.show()).toBe(true);
});

I get this error

 TypeError: Cannot read property 'scope' of null

Could anyone provide a way to test this? or is there a better way to test this? currently I am using Maven-jasmine plugin

Upvotes: 0

Views: 827

Answers (1)

Chad Robinson
Chad Robinson

Reputation: 4623

Two problems:

  1. As per https://developer.mozilla.org/en-US/docs/Web/API/document.getElementById, "Elements not in the document are not searched by getElementById." $compile doesn't insert the element into the DOM - it just sets up appropriate bindings (and does smart things like handling nested directives inside your template string). Your getElementById will fail to find a match. You need to insert the element into the DOM somewhere.

  2. getElementById returns a raw HTML DOM element. To get the Angular scope from it, the docs call for wrapping it in angular.element():

    var element = document.getElementById(id);
    angular.element(element).scope()...
    

This pattern will provide the Angular wrapper around the element to do the rest of the magic. It's all based on jqLite, which isn't jQuery but does follow a lot of the same patterns. For those used to jQuery, think of it like writing $(element).

Upvotes: 0

Related Questions