简体   繁体   English

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

[英]Access DebugElement of nested component when using native view encapsulation

I'm testing a component like the following 我正在测试如下组件

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

When unit testing my component, I want to obtain a reference to the nested component MyOtherComponent . 单元测试我的组件时,我想获得对嵌套组件MyOtherComponent的引用。 If my-component used no encapsulation, or if it used emulated encapsulation, I could use: 如果my-component没有使用封装,或者它使用了模拟封装,我可以使用:

let fixture = TestBed.createComponent(MyComponent);
let nestedComponent = fixture.debugElement.query(By.directive(MyNestedComponent))

to obtain a reference to the component. 获取对组件的引用。

But in this case, query just queries the light DOM children of the component (mimicking the behaviour of querySelector ), so nestedComponent is null when using native view encapsulation. 但在这种情况下, query只是查询组件的轻DOM子项(模仿querySelector的行为),因此当使用本机视图封装时, nestedComponentnull

How are you supposed to get a reference to the DebugElement (and therefore the component instance) of the nested component? 你应该如何获得嵌套组件的DebugElement (以及组件实例)的引用?

Let's say we have the following components: 假设我们有以下组件:

@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;
}

So i would write test like this: 所以我会写这样的测试:

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');

You can also try this test as a live example in plunker 您也可以尝试这个测试作为一个活生生的例子在plunker

Let me update the correct answer based on newer versions of used tools: 让我根据更新版本的旧工具更新正确答案:

Here's how it worked for me, using "@angular/core": "^5.2.6" , "typescript": "~2.4.2" and "jasmine-core": "2.5.2" 以下是它对我有用的方法,使用"@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")

With Angular v6.1.8 and component with Shadow root . 使用Angular v6.1.8和具有Shadow root的组件。 Example: 例:

  const fixture = TestBed.createComponent(AppComponent);
  const app = fixture.debugElement.componentInstance as AppComponent;
  const shadowRoot: DocumentFragment = fixture.debugElement.nativeElement.shadowRoot;

  app.active = true;
  app.title = 'Title';
  fixture.detectChanges();

  expect(shadowRoot.querySelector('.bz-modal__header_title').textContent).toEqual('Title');

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM