angular
angular copied to clipboard
Unit testing: directives on ng-template present but not detectable with By.directive
Which @angular/* package(s) are the source of the bug?
core
Is this a regression?
No
Description
Directives added to ng-template (as describe in Angular's guide to dynamic components) don't seem to be detectable using DebugElement.query(By.directive([directive])).
For example:
@Directive({
selector: '[fooHost]',
})
class FooDirective {
constructor(public viewContainerRef: ViewContainerRef) {}
}
@Component({
template: '<ng-template fooHost></ng-template>',
})
class TestHostComponent {
@ViewChild(FooDirective, { static: true }) fooDirective!: FooDirective;
}
describe('injected directive', () => {
let fixture: ComponentFixture<TestHostComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [FooDirective, TestHostComponent],
}).compileComponents();
fixture = TestBed.createComponent(TestHostComponent);
});
afterEach(() => {
fixture.nativeElement.remove();
// Get a fresh TestBed configuration between tests.
TestBed.resetTestingModule();
});
...
If the directive is queried, no directive will be found:
it('FooDirective undetectable using query(By.directive)', () => {
fixture.detectChanges();
const fooDirective = fixture.debugElement.query(By.directive(FooDirective));
expect(fooDirective).toBeNull();
});
Yet if we check the TestHostComponent's fooDirective, we can see that FooDirective was correctly added, and properties like its viewContainerRef have been defined:
it('FooDirective gets viewContainerRef', () => {
const fooDirective = fixture.componentInstance.fooDirective;
expect(fooDirective.viewContainerRef).toBeDefined();
});
(Notice that fixture.detectChanges() was not necessary.)
Please provide a link to a minimal reproduction of the bug
https://stackblitz.com/edit/angular-unit-testing-examples-tpfzzf?file=src%2Fapp%2Fdemo.cmpnt.spec.ts
Please provide the exception or error you saw
Not applicable
Please provide the environment you discovered this bug in (run ng version)
This was documented in Stackblitz, where no console is available to run Angular's `ng version`. See the Dependencies in Stackblitz. Angular 14.0.6 was installed. It also appears locally in my older Angular setup:
Angular CLI: 13.3.3
Node: 16.13.0
Package Manager: npm 8.3.0
OS: darwin x64
Angular: 13.3.3
... animations, cli, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, router
Package Version
---------------------------------------------------------
@angular-devkit/architect 0.1303.3
@angular-devkit/build-angular 13.3.3
@angular-devkit/core 13.3.3
@angular-devkit/schematics 13.3.3
@angular/fire 7.3.0
@schematics/angular 13.3.3
rxjs 6.6.7
typescript 4.5.5
Anything else?
No response
same problem, any solutions?
Isn't that pretty much expected ? Your component has no children.
Your ng-template points to nothing, it will not exist in the dom. But if you add a div with the directive, instantiate your template (with ngTemplateOutlet for example) it will work.