I recently discovered the HostAttributeToken
in Angular (see docs) to provide static attributes for a component.
The following example works fine:
import { Component, HostAttributeToken, inject } from '@angular/core';
@Component({
selector: 'demo-component',
template: `<div [class]="styleClass">Hello world</div>`,
})
export class DemoComponent {
styleClass = inject(new HostAttributeToken('style-class'));
}
usage
<demo-component style-class="bla" />
My question: How can provide the HostAttributeToken
in a test with jasmine/karma?
I want to make this attribute required (there is also a flag to make the HostAttributeToken
optional).
It is of course easy if there is a host component, but how can I achieve the same thing with the TestBed
Api?
A basic test setup without providing an HostAttributeToken
would look like this:
import { TestBed } from '@angular/core/testing';
import { DemoComponent } from './demo.component';
describe('DemoComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [DemoComponent],
}).compileComponents();
});
it('should create', () => {
const fixture = TestBed.createComponent(DemoComponent);
expect(fixture.componentInstance).toBeTruthy();
});
});
which errors with
Error: NG0201: No provider for HostAttributeToken style-class found. Find more at https://angular.dev/errors/NG0201
When you have that kind of question, it is often interesting how the feature itself is unit-testing inside the angular repo.
Here is the relevant test file.
Long story short, there is no other way than having a fake host component to test that feature.
// The directive you're testing
@Directive({selector: '[dir]', standalone: true})
class Dir {
value = inject(new HostAttributeToken('some-attr'));
}
// The "fake" host component
@Component({
standalone: true,
template: '<div dir some-attr="foo" other="ignore"></div>',
imports: [Dir],
})
class TestCmp {
@ViewChild(Dir) dir!: Dir;
}
const fixture = TestBed.createComponent(TestCmp);
fixture.detectChanges();
expect(fixture.componentInstance.dir.value).toBe('foo');