Getting to know fixture.debugElement : Angular Unit Testing

Shashank Vivek
3 min readOct 17, 2020

--

In the Angular world of Unit testing, we often overlook some concepts unless we actually need them to serve specific purpose. After answering a lot of questions on stackoverflow , one of such concept is related to accessing HTML elements using fixture .

Before we begin, if you are new to unit testing then I would recommend you to start from the intro article. You can more article links below this link, which contain more use cases for unit testing in Angular.

In this article, I’ll discuss 3 ways to access an HTML element and how are they different. For below element with an id as shan:

<div id="shan">Hey there</div>

We can use below ways to get it in unit testing:

  • fixture.debugElement.query(By.css('#shan'))
  • fixture.debugElement.nativeElement.querySelector('#shan')
  • document.getElementById('#shan')

1. fixture.debugElement.query(By.css(‘#hello’))

It is used to get “DebugElement” for a DOM object. More detailed info can be found here on offical Angular doc.

In brief, you can pass id as By.css('#shan') , class as By.css('.shan') , or you can also elements with ways such as By.css('div') or By.css('some-app-component')

DebugElement is an Angular class that contains all kinds of references and methods relevant to investigate an element as well as component

fixture.debugElement.query(By.css('#shan'))

will return

DebugElement__PRE_R3__{listeners: [], parent: DebugElement__PRE_R3__{listeners: [], parent: null, debugContext: DebugContext{view: …, nodeIndex: …, nodeDef: …, elDef: …, elView: …}, nativeNode: Hey there, properties: Object{}, attributes: Object{ng-version: …}, classes: Object{}, styles: Object{}, childNodes: […], nativeElement: Hey there}, debugContext: DebugContext{view: Object{def: …, parent: …, viewContainerParent: …, parentNodeDef: …, context: …, component: …, nodes: …, state: …, root: …, renderer: …, oldValues: …, disposables: …, initIndex: …}, nodeIndex: 0, nodeDef: Object{nodeIndex: …, parent: …, renderParent: …, bindingIndex: …, outputIndex: …, checkIndex: …, flags: …, childFlags: …, directChildFlags: …, childMatchedQueries: …, matchedQueries: …, matchedQueryIds: …, references: …, ngContentIndex: …, childCount: …, bindings: …, bindingFlags: …, outputs: …, element: …, provider: …, text: …, query: …, ngContent: …}, elDef: Object{nodeIndex: …, parent: …, renderParent: …, bindingIndex: …, outputIndex: …, checkIndex: …, flags: …, childFlags: …, directChildFlags: …, childMatchedQueries: …, matchedQueries: …, matchedQueryIds: …, references: …, ngContentIndex: …, childCount: …, bindings: …, bindingFlags: …, outputs: …, element: …, provider: …, text: …, query: …, ngContent: …}, elView: Object{def: …, parent: …, viewContainerParent: …, parentNodeDef: …, context: …, component: …, nodes: …, state: …, root: …, renderer: …, oldValues: …, disposables: …, initIndex: …}}, nativeNode: Hey there, properties: Object{}, attributes: Object{id: ‘shan’}, classes: Object{}, styles: Object{}, childNodes:[DebugNode__PRE_R3__{listeners: …, parent: …, _debugContext: …, ..nativeNode: …}], nativeElement: Hey there, name: ‘div’}

2. fixture.debugElement.nativeElement.querySelector(‘#shan’)

nativeElement returns a reference to the DOM element which can also come under debugElement as stated above.You can use it do actions such as click() event in test cases.

fixture.debugElement.nativeElement.querySelector('#shan').click(); // this will create a click event over this element.

It works for querying both class something like (fixture.debugElement.nativeElement.querySelector('.shan')) as well as id.

fixture.debugElement.nativeElement.querySelector('#shan')

will return

<div _ngcontent-a-c0="" id="shan">Hey there</div>

3. document.getElementById(‘shan’)

This is our good old way to access an id (not a class). You can't access class by doing something like

document.getElementById('.shan') // will return null

Also, note that you don’t need to pass # in this function argument.

document.getElementById('#shan') // will return null

It should be avoided while working with angular because angular has its own ChangeDetection which requires it to be worked with fixtures. By directly calling document , you'll end up banging your head on the wall , trying to figure out why is the element coming as null

document.getElementById('shan')

will return

<div _ngcontent-a-c0="" id="shan">Hey there</div>

If you like this article, please 👏 clap 👏 few times & encourage me 🐼 to write more.

--

--