如何使用@input alias对Angular指令进行单元测试

如何使用@input alias对Angular指令进行单元测试,angular,unit-testing,karma-jasmine,angular-directive,Angular,Unit Testing,Karma Jasmine,Angular Directive,我想根据用户的角色显示/隐藏元素(例如,一些按钮应该只对管理员可见)。这可以通过*ngIf实现,但我相信更好的方法是一种指导: import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core'; import { AuthService } from '../services/auth.service'; @Directive({ selector: '[appHasRole]', }) ex

我想根据用户的角色显示/隐藏元素(例如,一些按钮应该只对管理员可见)。这可以通过*ngIf实现,但我相信更好的方法是一种指导:

import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
import { AuthService } from '../services/auth.service';

@Directive({
    selector: '[appHasRole]',
})
export class HasRoleDirective {
    constructor(private auth: AuthService, private templateRef: TemplateRef<any>, private viewContainer: ViewContainerRef) {}

    @Input() set appHasRole(role: string) {
        if (this.checkRole(role)) {
            this.viewContainer.createEmbeddedView(this.templateRef);
        } else {
            this.viewContainer.clear();
        }
    }

    checkRole(role: string): boolean {
        return this.auth.getRole() === role;
    }
}
用这种方法

尝试2:

<div *appHasRole="'admin'">
@Component({
    template: `<div *appHasRole="'admin'" class="test"></div>`,
})
class TestComponent {
    @ViewChild(HasRoleDirective) directive: HasRoleDirective;
}

beforeEach(async(() => {
    fixture = TestBed.configureTestingModule({
        declarations: [HasRoleDirective, TestComponent],
        providers: [AuthService, HasRoleDirective, TemplateRef, ViewContainerRef],
    }).createComponent(TestComponent);
    testDirective = new HasRoleDirective(new AuthService(), new TemplateRef(), new ViewContainerRef());
}))
@Component({
    template: `<div *appHasRole="'admin'"></div>`,
})
class TestComponent {
    @ViewChild(HasRoleDirective) directive: HasRoleDirective;
}

let directive: DebugElement;
let testComponent: TestComponent;

beforeEach(() => {
    fixture = TestBed.configureTestingModule({
        declarations: [HasRoleDirective, TestComponent],
        imports: [HttpClientModule, RouterTestingModule],
        providers: [HasRoleDirective, TemplateRef, ViewContainerRef],
    }).createComponent(TestComponent);

    fixture.detectChanges();
    testComponent = fixture.componentInstance;
    directive = fixture.debugElement.query(By.directive(HasRoleDirective));
    console.log(directive);
});
@Component({
    template: `<div *appHasRole="'admin'" class="test"></div>`,
})
class TestComponent {
    @ViewChild(HasRoleDirective) directive: HasRoleDirective;
}

let directive: DebugElement;
let testComponent: TestComponent;

beforeEach(() => {
    fixture = TestBed.configureTestingModule({
        declarations: [HasRoleDirective, TestComponent],
        imports: [HttpClientModule, RouterTestingModule],
        providers: [HasRoleDirective, TemplateRef, ViewContainerRef],
    }).createComponent(TestComponent);

    fixture.detectChanges();
    testComponent = fixture.componentInstance;
    directive = fixture.debugElement.query(By.css('.test'));
    console.log(directive);
});
@组件({
模板:``,
})
类TestComponent{
@ViewChild(HasRoleDirective)指令:HasRoleDirective;
}
let指令:DebugElement;
let testComponent:testComponent;
在每个之前(()=>{
fixture=TestBed.configureTestingModule({
声明:[HasRoleDirective,TestComponent],
导入:[HttpClientModule,RouterTestingModule],
提供者:[HasRoleDirective、TemplateRef、ViewContainerRef],
}).createComponent(TestComponent);
fixture.detectChanges();
testComponent=fixture.componentInstance;
directive=fixture.debugElement.query(By.directive(HasRoleDirective));
console.log(指令);
});
该指令始终为空,这会阻止进一步的测试。即使我尝试使用助手类访问它:

尝试3:

<div *appHasRole="'admin'">
@Component({
    template: `<div *appHasRole="'admin'" class="test"></div>`,
})
class TestComponent {
    @ViewChild(HasRoleDirective) directive: HasRoleDirective;
}

beforeEach(async(() => {
    fixture = TestBed.configureTestingModule({
        declarations: [HasRoleDirective, TestComponent],
        providers: [AuthService, HasRoleDirective, TemplateRef, ViewContainerRef],
    }).createComponent(TestComponent);
    testDirective = new HasRoleDirective(new AuthService(), new TemplateRef(), new ViewContainerRef());
}))
@Component({
    template: `<div *appHasRole="'admin'"></div>`,
})
class TestComponent {
    @ViewChild(HasRoleDirective) directive: HasRoleDirective;
}

let directive: DebugElement;
let testComponent: TestComponent;

beforeEach(() => {
    fixture = TestBed.configureTestingModule({
        declarations: [HasRoleDirective, TestComponent],
        imports: [HttpClientModule, RouterTestingModule],
        providers: [HasRoleDirective, TemplateRef, ViewContainerRef],
    }).createComponent(TestComponent);

    fixture.detectChanges();
    testComponent = fixture.componentInstance;
    directive = fixture.debugElement.query(By.directive(HasRoleDirective));
    console.log(directive);
});
@Component({
    template: `<div *appHasRole="'admin'" class="test"></div>`,
})
class TestComponent {
    @ViewChild(HasRoleDirective) directive: HasRoleDirective;
}

let directive: DebugElement;
let testComponent: TestComponent;

beforeEach(() => {
    fixture = TestBed.configureTestingModule({
        declarations: [HasRoleDirective, TestComponent],
        imports: [HttpClientModule, RouterTestingModule],
        providers: [HasRoleDirective, TemplateRef, ViewContainerRef],
    }).createComponent(TestComponent);

    fixture.detectChanges();
    testComponent = fixture.componentInstance;
    directive = fixture.debugElement.query(By.css('.test'));
    console.log(directive);
});
@组件({
模板:``,
})
类TestComponent{
@ViewChild(HasRoleDirective)指令:HasRoleDirective;
}
let指令:DebugElement;
let testComponent:testComponent;
在每个之前(()=>{
fixture=TestBed.configureTestingModule({
声明:[HasRoleDirective,TestComponent],
导入:[HttpClientModule,RouterTestingModule],
提供者:[HasRoleDirective、TemplateRef、ViewContainerRef],
}).createComponent(TestComponent);
fixture.detectChanges();
testComponent=fixture.componentInstance;
directive=fixture.debugElement.query(By.css('.test'));
console.log(指令);
});

谁能给我一个提示吗?

你想测试什么?指令还是组件?也可能有帮助,dom在我尝试测试指令时,在
ngAfterViewInit
之后才会初始化。我不知道ngAfterViewInit能帮我什么忙?不应该考虑DOM中的更改吗?非常感谢你的帮助!