Angular2 testing: What's the difference between a DebugElement and a NativeElement object in a ComponentFixture?

I'm currently putting together some best practices for testing Angular 2 apps on a component level.

I've seen a few tutorials query a fixture's NativeElement object for selectors and the like, e.g.

it('should render "Hello World!" after click', async(() => {
    builder.createAsync(HelloWorld).then((fixture: ComponentFixture<HelloWorld>) => {
        fixture.detectChanges();
        let el = fixture.nativeElement;
        el.querySelector('h1').click();
        fixture.detectChanges();
            
        expect(el.querySelector('h1')).toHaveText('Hello World!');
    });
}));

However, in juliemr's Angular 2 test seed she accesses the NativeElement through a parent DebugElement object.

it('should render "Hello World!" after click', async(() => {
    builder.createAsync(HelloWorld).then((fixture: ComponentFixture<HelloWorld>) => {
      fixture.detectChanges();
      let compiled = fixture.debugElement.nativeElement;
      compiled.querySelector('h1').click();
      fixture.detectChanges();
            
      expect(compiled.querySelector('h1')).toHaveText('Hello World!');
    });
}));

Are there any specific cases you'd use a fixture's debugElement.nativeElement over its nativeElement?


Solution 1:

  • nativeElement returns a reference to the DOM element
  • DebugElement is an Angular2 class that contains all kinds of references and methods relevant to investigate an element or component (See the source of DebugNode and DebugElement

Solution 2:

to add on to what has been mentioned already :

  abstract class ComponentFixture {
  debugElement;       // test helper 
  componentInstance;  // access properties and methods
  nativeElement;      // access DOM
  detectChanges();    // trigger component change detection
}

source: https://github.com/angular/angular/blob/a7e9bc97f6a19a2b47b962bd021cb91346a44baa/modules/angular2/src/testing/test_component_builder.ts#L31

Solution 3:

Take a look at Angular discussion about this topic and related PR.

Mainly:

fixture.componentInstance == fixture.debugElement.componentInstance;
fixture.nativeElement == fixture.debugElement.nativeElement;

Solution 4:

.nativeElement() returns DOM tree whereas debugElement returns a JS object (debugElement tree). debugElement is a Angular's method.

.nativeElement() is Browser specific API that returns or give access to DOM tree. But what if application is running on non-browser platform (such as server or web-worker), in that case .nativeElement() may throw error.

If we are sure that our application will run on browser only, then unhesitantly we can use let el = fixture.nativeElement. But if we are not sure about the platform then to be on safer side use let le = fixture.debugElement because it returns a plain JS Object.