1

I recently have start using Jasmine, and I have a weird situation. I am testing a function which does a DOM manipulation with another function call. Jasmine is throwing an error by saying that elem.className is not a constructor. Here is the structure of my code:

Controller code:

function resetElem(elem) {
  elem.classList.remove(/some string/);
}

function a() {
  resetElem(document.getElementsByClassName('xx')[0])
}

Jasmine:

var elem;

beforeEach(inject(function($rootScope, $controller, $q) {
  deferred = $q.defer();
  scope = $rootScope.$new();

  mockHTMLElements(); 
  createController($controller);
}));

function mockHTMLElements() {
  /* //This was the other method that I tried.
    jasmine.spyOn(document, 
    'getElementsByClassName').and.CallFake(function(name) {
      var el;
      if (!elems[name]) {
        el = document.createElement('div');
        el.className = name;

        elems[name] = el;
      }

      return [elems[name]];
    });
  */

  elems['preview-promo'] = document.createElement('div');
  elems['preview-promo'].className="preview-promo";

  elems['create-promo'] = document.createElement('div');
  elems['create-promo'].className="create-promo";

  elem = {
    classList : { 
      add : jasmine.createSpy('add'),
      remove : jasmine.createSpy('remove'),
    },
    className : 'test'
  };
}

it('tests the a function', function() {
  // vm is ref of this of controller
  vm.a(true);
  ...some other tests
});

Console returns

TypeError: undefined is not an object (evaluating 'elem.classList')

Not sure how to make this right.

1 Answer 1

1

It's difficult to give you a good answer with the information provided.

As a general rule avoid manipulating the DOM from a controller. Create a directive instead, that way you'll have access to the DOM element and it will make your tests easier/more natural to write.

Sign up to request clarification or add additional context in comments.

5 Comments

I am conditionally adding a class progress when network request is made. I am not sure if making a directive will work. How will I call directive's link function conditionally?
You won't. Using bindings you could control the CSS class from the current scope.
will give it a shot.
so, directive is more like event binders in angular?
Nope, please refer to the angularJS docs for more info: docs.angularjs.org/guide/directive

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.