0

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

user3897395
  • 103
  • 1
  • 1
  • 9
  • Likely your getElementById is not returning anything. You have a reference to the element already when you generate/compile. Why not use that reference to get the scope? It could also be that your angular.element.scope() is failing as well. Do longs of each one before you do the scope() call to see. Your code also does not appear to be written in a testable way. Consider using a directive for the toolbar. – ryanlutgen Dec 06 '14 at 03:03

1 Answers1

0

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).

Chad Robinson
  • 4,575
  • 22
  • 27