Testing directives

The last leg of our journey into the world of unit testing Angular elements will cover directives. Directives will usually be quite straightforward in their overall shape, being pretty much components with no view attached. The fact that directives usually work with components gives us a very good idea of how to proceed when testing them.

A directive can be simple in the sense that it has no external dependencies. It looks something like this:

@Directive({
selector: 'some-directive'
})
export class SomeDirective {
someMethod() {}
}

Testing is easy, you just need to instantiate an object from the SomeDirective class. However, it is likely that your directive will have dependencies and in those cases, we need to test the directive implicitly through it being attached to the component. Let's have a look at such an example. Let's first define the directive, like so:

import { 
Directive,
ElementRef,
HostListener
}
from '@angular/core';

@Directive({ selector: '[banana]' })
export class BananaDirective {
constructor(private elementRef: ElementRef) { }

@HostListener('mouseover') onMouseOver() {
this.elementRef.nativeElement.style.color = 'yellow';
}

@HostListener('mouseout') onMouseOut() {
this.elementRef.nativeElement.style.color = 'inherit';
}
}

What you see here is a simple directive that shifts the font color to yellow if we hover over it. We need to attach it to a component. Let us define an element next, like so:

import { Component } from '@angular/core';

@Component({
selector: 'banana',
template: `
<p class="banana" banana>hover me</p>
`
})
export class BananaComponent {}

Here we can see that we added the element as an attribute to the p-tag that we defined in the components template.

Next, let's go over to our test. We now know how to write tests, and especially how to test elements, so the following test code should come as no surprise:

import { By } from '@angular/platform-browser';
import { TestBed } from "@angular/core/testing";
import { BananaComponent } from './banana.component';
import { BananaDirective } from './banana.directive';

describe('A banana directive', () => {
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [BananaDirective, BananaComponent]
}).compileComponents();
});

it('should set color property to yellow when mouseover event happens', () => {
const fixture = TestBed.createComponent(BananaComponent);
const element = fixture.debugElement.query(By.css('.banana'));
element.triggerEventHandler('mouseover', null);
fixture.detectChanges();

expect(element.nativeElement.style.color).toBe('yellow');
});
})

In the beforeEach() method, we talk to TestBed to configure our testing module and tell it about the BananaDirective as well as the BananaComponent, with this code:

 beforeEach(() => {
TestBed.configureTestingModule({
declarations: [ BananaDirective, BananaComponent ]
}).compileComponents();
});

In the test itself, we use TestBed yet again to create a component. Thereafter, we find our element by its CSS class. We find the element so that we are able to trigger an event, a mouseover. Triggering a mouseover event will trigger code in the directive that will make the font color yellow. With the event triggered, then we are able to assert the element's font color with this line:

expect(element.nativeElement.style.color).toBe('yellow');

Now, this is how simple it can be to test a directive, even if it has dependencies. The key takeaway is that if that is the case, you need an element to place the directive on, and that you implicitly test the directive through the element.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset