使用本机视图封装时访问嵌套组件的DebugElement

ova*_*gle 5 unit-testing shadow-dom typescript angular

我正在测试如下组件

@Component({
  selector: 'my-component',
  template: `
    <my-nested-component [state]="state"></my-nested-component>
  `,
  encapsulation: ViewEncapsulation.Native
})
export class MyComponent {}
Run Code Online (Sandbox Code Playgroud)

单元测试我的组件时,我想获得对嵌套组件的引用MyOtherComponent.如果my-component没有使用封装,或者它使用了模拟封装,我可以使用:

let fixture = TestBed.createComponent(MyComponent);
let nestedComponent = fixture.debugElement.query(By.directive(MyNestedComponent))
Run Code Online (Sandbox Code Playgroud)

获取对组件的引用.

但在这种情况下,query只需查询组件的轻DOM子项(模仿行为querySelector),因此使用本机视图封装时nestedComponent也是如此null.

你应该如何获得DebugElement嵌套组件的(以及组件实例)的引用?

yur*_*zui 6

假设我们有以下组件:

@Component({
  selector: 'my-nested-component',
  template: `
    <h1>Nested component - {{ state }}</h1> 
  `,
})
export class NesterComponent {
  @Input() state: number;
}

@Component({
  selector: 'my-app',
  template: `
    <my-nested-component [state]="state"></my-nested-component> 
  `,
  encapsulation: ViewEncapsulation.Native
})
export class TestComponent {
  state = 1;
}
Run Code Online (Sandbox Code Playgroud)

所以我会写这样的测试:

let fixture = TestBed.createComponent(TestComponent);
let component = fixture.componentInstance;

const shadowRoot: DocumentFragment = fixture.debugElement.nativeElement.shadowRoot;
const nestedComponentNativeElement = shadowRoot.querySelector('my-nested-component');

const nestedComponentDebugElement = <DebugElement>getDebugNode(nestedComponentNativeElement);

var nestedComponentInstance: NesterComponent = nestedComponentDebugElement.componentInstance;
// here can be your code

component.state = 2;
fixture.detectChanges();

de = nestedComponentDebugElement.query(By.css('h1'));

expect(de.nativeElement.textContent).toBe('Nested component - 2');
Run Code Online (Sandbox Code Playgroud)

您也可以尝试这个测试作为一个活生生的例子在plunker


小智 5

让我根据使用过的工具的较新版本更新正确答案:

这是它对我的工作方式,使用"@angular/core": "^5.2.6","typescript": "~2.4.2""jasmine-core": "2.5.2"

const shadowRoot: DocumentFragment = fixture.debugElement.nativeElement
const nativeElement = shadowRoot.querySelector("html-element")
const debugElement = getDebugNode(nativeElement) as DebugElement
const instance: NestedComponent = debugElement.componentInstance
expect(debugElement.query(By.css("h1")).nativeElement.textContent).toBe("ExpectedText")
Run Code Online (Sandbox Code Playgroud)