How to test a host directive in Angular application
Let's imagine we have a component with a host directive which adds the name
attribute.
The code of the directive:
@Directive({
selector: 'host',
standalone: true,
})
class HostDirective {
@HostBinding('attr.name') @Input() input?: string;
}
The code of the component:
@Component({
selector: 'target',
hostDirectives: [
{
directive: HostDirective,
inputs: ['input'],
},
],
template: 'target',
})
class TargetComponent {
// tons of logic we want to ignore
}
The component can be heavy, and, in an ideal test, the logic of the component should be ignored, so the focus would stay on the directive and how it behaves.
MockBuilder
knows how to mock the component
and how to keep one or some of its host directives as they are.
In order to do so, the host directive should be kept, and its component should be mocked:
beforeEach(() => MockBuilder(HostDirective, TargetComponent));
Profit!
To access the directive in a test, ngMocks.findInstnace
can be used.
it('keeps host directives', () => {
const fixture = MockRender(TargetComponent, { input: 'test' });
const directive = ngMocks.findInstance(HostDirective);
expect(directive.input).toEqual('test');
expect(ngMocks.formatHtml(fixture)).toContain(' name="test"');
});
Live example
https://github.com/help-me-mom/ng-mocks/blob/master/examples/TestHostDirective/test.spec.ts
import {
Component,
Directive,
HostBinding,
Input,
} from '@angular/core';
import { MockBuilder, MockRender, ngMocks } from 'ng-mocks';
@Directive({
selector: 'host',
standalone: true,
})
class HostDirective {
@HostBinding('attr.name') @Input() input?: string;
public hostTestHostDirective() {}
}
@Component({
selector: 'target',
hostDirectives: [
{
directive: HostDirective,
inputs: ['input'],
},
],
template: 'target',
})
class TargetComponent {
public targetTestHostDirective() {}
}
describe('TestHostDirective', () => {
beforeEach(() => MockBuilder(HostDirective, TargetComponent));
it('keeps host directives', () => {
const fixture = MockRender(TargetComponent, { input: 'test' });
const directive = ngMocks.findInstance(HostDirective);
expect(directive.input).toEqual('test');
expect(ngMocks.formatHtml(fixture)).toContain(' name="test"');
});
});