Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 1.5 unit testing component while ignoring child components

I am trying to write a unit test for a component in Angular 1.5. I want to unit test that component and its dom nodes. This component contains a child component that is quite complex.

My goal is to unit test the outer component without compiling the child component.

Since I want to test the DOM as well, it is not sufficient to use $componentController for this test.

Here is a short example of what I would like to achieve:

Component code:

angular.module('app').component('myComponent', {
  bindings: {
    username: '<',
  },
  template: `
    <span>{{ $ctrl.username }}</span>
    <my-complex-component />
  `
  controller: function () {}
});

Unit test for my-component:

it('my-component should render username', function () {
  var template = '<my-component username="username"></my-component>',
    element,
    scope,
    date;

  scope = $rootScope.$new();
  scope.username = 'John';

  element = $compile(template)(scope);
  scope.$digest();

  username = element.find('span');
  expect(username.text()).to.be.equal('John');
});

my-complex-component should not be instantiated. It should resist in the template as it is. Creating the element in the unit test should result in

<span>John</span>
<my-complex-component />

Is there any way to do this?

like image 365
Pascal Chorus Avatar asked Dec 20 '16 12:12

Pascal Chorus


People also ask

What is fixture detectChanges ()?

fixture is a wrapper for our component's environment so we can control things like change detection. To trigger change detection we call the function fixture.detectChanges() , now we can update our test spec to: Copy it('login button hidden when the user is authenticated', () => { expect(el. nativeElement.

What is beforeEach in Angular testing?

beforeEach is a global function in Jasmine that runs some setup code before each spec in the test suite. In this test suite, beforeEach is used to create a testing module using the TestBed object and declares any components that would be used in this testing module.


1 Answers

Here is a very good explanation of how to test a component without rendering the whole tree under the current component.

What you want is called

shallow rendering (avoid rendering the whole template of the child component)

and Angular 1.5 doesn’t offer it out-of-the-box.

If you take a look at the link above, Wojciech Zawistowski shows how to use the helper below in order to achieve shallow rendering.

export function componentSpyOn(name) {
  function componentSpy($provide) {
    componentSpy.bindings = [];

    $provide.decorator(name + 'Directive', ($delegate) => {
      let component = $delegate[0];

      component.template = '';
      component.controller = class {
        constructor() {
          componentSpy.bindings.push(this);
        }
      };

      return $delegate;
    });
  }

  return componentSpy;
}
like image 181
tottomotto Avatar answered Jan 01 '23 21:01

tottomotto