Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to unit test a structural directive the way we test an attribute directive in angular 2

I have both attribute and structural directives in my project. I am able to test the attribute directive by creating a test component and using the attribute directive in it's template.

@Component({
    template: `<input [myAttrDir]="{prop1: val1, prop2: val2}"/>`
})
export class TestComponent {
}

@Directive({
    selector: '[myAttrDir]'
})
export class MyAttrDirective {
    @Input('myAttrDir') testProp;
}

The testing module looks like:

TestBed.configureTestingModule({
    declarations: [MyAttrDirective, TestComponent]
})

I get hold of directive this way:

fixture = TestBed.createComponent(TestComponent)
directive = fixture.debugElement.query(By.directive(MyAttrDirective))

I am able to get the instance of attribute directive. However when I try this same way to test structural directive, I get null value of directive. I have checked out official documentation as well and only found the unit testing of attribute directive. The structural directive testing methodology is not given anywhere.

@Component({
    template: `<input *myStrucDir="{prop1: val1, prop2: val2}"/>`
})
export class TestComponent {
}
@Directive({
    selector: '[myStrucDir]'
})
export class MyStrucDirective {
    @Input set myStrucDir(data);
    constructor(
        private templateRef: TemplateRef<any>,
        private vcr: ViewContainerRef,
        private cfr: ComponentFactoryResolver,
        private el: ElementRef) {

    }
}
TestBed.configureTestingModule({
    declarations: [MyStrucDirective, TestComponent]
})
fixture = TestBed.createComponent(TestComponent)
directive = fixture.debugElement.query(By.directive(MyStrucDirective))

Is it possible to test structural directive in any way?

like image 942
user Avatar asked Aug 14 '18 10:08

user


People also ask

What is the difference between structural directive and attribute directive?

There are two types of directives in Angular. Attribute directives modify the appearance or behavior of DOM elements. Structural directives add or remove elements from the DOM.

Can we use two structural directive in a single HTML element?

we cannot use two structural directives on same element. Structural directives like ngfor can do complex things with the host element and its childrens. When two directives placed on same element we cannot decide which one takes precedence i.e., which should execute first *ngIf or *ngFor?

What is attribute directive in Angular?

Angular attribute directives are a number of built-in directives that we can add to our HTML elements that give them a dynamic behavior. In summary, an attribute directive changes the appearance or behavior of a DOM element.


1 Answers

I had the same issue, but I figured out why debugElement.query(By.directive(MyStrucDirective)) does NOT work for structural directives.

Structural directives are applied to templates (<ng-template>) instead of elements. This means, that they are not bound to any DebugElement, but rather to a DebugNode. That is a small difference, but explains why it is not found.

To find the instance, you have to query differently:

# Angular 8.1 or below
debugElement.queryAllNodes(debugNode => debugNode.providerTokens.includes(MyStrucDirective))[0];

# Angular 8.2
debugElement.queryAllNodes(By.directive(MyStrucDirective))[0];
like image 136
Dirk Luijk Avatar answered Oct 06 '22 00:10

Dirk Luijk