I have a directive that highlights text:
import { Directive, ElementRef, HostListener, Input } from '@angular/core';
@Directive({ selector: '[appHighlight]' })
export class HighlightDirective {
@Input('appHighlight') // tslint:disable-line no-input-rename
highlightColor: string;
constructor(private el: ElementRef) { }
@HostListener('mouseenter')
onMouseEnter() {
this.highlight(this.highlightColor || 'yellow');
}
@HostListener('mouseleave')
onMouseLeave() {
this.highlight(null);
}
private highlight(color: string) {
this.el.nativeElement.style.backgroundColor = color;
}
}
On my app HTML I have:
This <span [appHighlight]="'pink'">is nice</span>!
And it works
Then I started to build some tests, and in one test I try to bind a different color (just like the example above), but it doesn't bind the value, the field is undefined
.
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { Component } from '@angular/core';
import { HighlightDirective } from './highlight.directive';
@Component({
selector: 'app-test-container',
template: `
<div>
<span id="red" appHighlight>red text</span>
<span id="green" [appHighlight]="'green'">green text</span>
<span id="no">no color</span>
</div>
`
})
class ContainerComponent { }
const mouseEvents = {
get enter() {
const mouseenter = document.createEvent('MouseEvent');
mouseenter.initEvent('mouseenter', true, true);
return mouseenter;
},
get leave() {
const mouseleave = document.createEvent('MouseEvent');
mouseleave.initEvent('mouseleave', true, true);
return mouseleave;
},
};
fdescribe('HighlightDirective', () => {
let fixture: ComponentFixture<ContainerComponent>;
let container: ContainerComponent;
let element: HTMLElement;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [ContainerComponent, HighlightDirective],
});
fixture = TestBed.createComponent(ContainerComponent);
container = fixture.componentInstance;
element = fixture.nativeElement;
});
fit('should set background-color green when passing green parameter', () => {
const targetElement = <HTMLSpanElement>element.querySelector('#green');
targetElement.dispatchEvent(mouseEvents.enter);
expect(targetElement.style.backgroundColor).toEqual('green');
});
});
The test output shows
Am I doing something wrong? Why it doesn't it bind the green
color?
This error often means that you haven't declared the directive "x" or haven't imported the NgModule to which "x" belongs. Perhaps you declared "x" in an application sub-module but forgot to export it. The "x" class isn't visible to other modules until you add it to the exports list.
A mock directive in Angular tests can be created by MockDirective function. The mock directive has the same interface as its original directive, but all its methods are dummies. In order to create a mock directive, pass the original directive into MockDirective function.
To create a custom directive we have to replace @Component decorator with @Directive decorator. So, let's get started with creating our first Custom Attribute directive. In this directive, we are going to highlight the selected DOM element by setting an element's background color. Create an app-highlight.
The solution is actually pretty simple. You have to register CommonModule in the module that you are using. And that's it! The error should disappear.
I found out that by default Angular doesn't run bindings on templates during tests. Even a simple {{ myVar }}
will not work unless you make it run bindings and lifecycle events, as described in Angular detectchanges
documentation.
There are two options in this scenario, I can manually call
fixture.detectChanges();
Just after I get my fixture.
Or I can include a provider that sets it to run things automatically
providers: [
{ provide: ComponentFixtureAutoDetect, useValue: true },
],
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With