Converting native Karma, Jasmine tests to use Angular-Testing-Library
Tags: angular, testing, typescript, javascript
Published: 2020-02-19 22:36:02

[A great suggestion by John O. was to try Angular-Testing-Library in response to this post.]  (https://dev.to/jwp/karma-jasmine-are-dead-1ifn)

Here's the results:

1) It can still run using Jasmine and Karma per the common Angular application.
2) [Here's how to install it](https://testing-library.com/docs/angular-testing-library/intro)
3) It is way more easy to use and it handled more dependencies automatically than Karma.
4) Create a simple test.spec.ts like this:

```javascript

import { render } from "@testing-library/angular";
import { CheckboxComponent } from "./checkbox.component";
import { ReactiveFormsModule } from "@angular/forms";

describe("CheckboxComponent", () => {
   it("testing checkbox", async () => {
      let temp = await render(CheckboxComponent, {
         imports: [ReactiveFormsModule]
      });
      debugger;
   });
});
```
4) Type in 'ng test', and make sure the spec is picked up by Karma/Jasmine.
5) Press F12 when the test starts to run then take a look at the variable "temp".

**Temp is the RenderResult**

```javascript 

{fixture: ComponentFixture, debugElement: null, detectChanges: ƒ, navigate: ƒ, rerender: ƒ, …}
fixture: ComponentFixture {componentRef: ComponentRef_, ngZone: NgZone, _autoDetect: false, _isStable: true, _isDestroyed: false, …}
detectChanges: ƒ detectChanges()
navigate: (elementOrPath, basePath = '') => {…}
rerender: (rerenderedProperties) => {…}
debugElement: null
container: div#root0
debug: (element = fixture.nativeElement) => {…}
type: ƒ type(element, value, options)
selectOptions: ƒ selectOptions(element, matcher, matcherOptions)
waitForDomChange: ƒ componentWaitForDomChange(options)
waitForElement: ƒ componentWaitForElement(callback, options)
waitForElementToBeRemoved: ƒ componentWaitForElementToBeRemoved(callback, options)
queryAllByLabelText: ƒ ()
queryByLabelText: ƒ ()
getAllByLabelText: ƒ ()
getByLabelText: ƒ ()
findAllByLabelText: ƒ ()
findByLabelText: ƒ ()
queryByPlaceholderText: ƒ ()
queryAllByPlaceholderText: ƒ ()
getByPlaceholderText: ƒ ()
getAllByPlaceholderText: ƒ ()
findAllByPlaceholderText: ƒ ()
findByPlaceholderText: ƒ ()
queryByText: ƒ ()
queryAllByText: ƒ ()
getByText: ƒ ()
getAllByText: ƒ ()
findAllByText: ƒ ()
findByText: ƒ ()
queryByDisplayValue: ƒ ()
queryAllByDisplayValue: ƒ ()
getByDisplayValue: ƒ ()
getAllByDisplayValue: ƒ ()
findAllByDisplayValue: ƒ ()
findByDisplayValue: ƒ ()
queryByAltText: ƒ ()
queryAllByAltText: ƒ ()
getByAltText: ƒ ()
getAllByAltText: ƒ ()
findAllByAltText: ƒ ()
findByAltText: ƒ ()
queryByTitle: ƒ ()
queryAllByTitle: ƒ ()
getByTitle: ƒ ()
getAllByTitle: ƒ ()
findAllByTitle: ƒ ()
findByTitle: ƒ ()
queryByRole: ƒ ()
queryAllByRole: ƒ ()
getAllByRole: ƒ ()
getByRole: ƒ ()
findAllByRole: ƒ ()
findByRole: ƒ ()
queryByTestId: ƒ ()
queryAllByTestId: ƒ ()
getByTestId: ƒ ()
getAllByTestId: ƒ ()
findAllByTestId: ƒ ()
findByTestId: ƒ ()
copy: (element, options) => {…}
cut: (element, options) => {…}
paste: (element, options) => {…}
compositionEnd: (element, options) => {…}
compositionStart: (element, options) => {…}
compositionUpdate: (element, options) => {…}
keyDown: (element, options) => {…}
keyPress: (element, options) => {…}
keyUp: (element, options) => {…}
focus: (element, options) => {…}
blur: (element, options) => {…}
focusIn: (element, options) => {…}
focusOut: (element, options) => {…}
change: (element, options) => {…}
input: (element, options) => {…}
invalid: (element, options) => {…}
submit: (element, options) => {…}
click: (element, options) => {…}
contextMenu: (element, options) => {…}
dblClick: (element, options) => {…}
drag: (element, options) => {…}
dragEnd: (element, options) => {…}
dragEnter: (element, options) => {…}
dragExit: (element, options) => {…}
dragLeave: (element, options) => {…}
dragOver: (element, options) => {…}
dragStart: (element, options) => {…}
drop: (element, options) => {…}
mouseDown: (element, options) => {…}
mouseEnter: (element, options) => {…}
mouseLeave: (element, options) => {…}
mouseMove: (element, options) => {…}
mouseOut: (element, options) => {…}
mouseOver: (element, options) => {…}
mouseUp: (element, options) => {…}
select: (element, options) => {…}
touchCancel: (element, options) => {…}
touchEnd: (element, options) => {…}
touchMove: (element, options) => {…}
touchStart: (element, options) => {…}
scroll: (element, options) => {…}
wheel: (element, options) => {…}
abort: (element, options) => {…}
canPlay: (element, options) => {…}
canPlayThrough: (element, options) => {…}
durationChange: (element, options) => {…}
emptied: (element, options) => {…}
encrypted: (element, options) => {…}
ended: (element, options) => {…}
loadedData: (element, options) => {…}
loadedMetadata: (element, options) => {…}
loadStart: (element, options) => {…}
pause: (element, options) => {…}
play: (element, options) => {…}
playing: (element, options) => {…}
progress: (element, options) => {…}
rateChange: (element, options) => {…}
seeked: (element, options) => {…}
seeking: (element, options) => {…}
stalled: (element, options) => {…}
suspend: (element, options) => {…}
timeUpdate: (element, options) => {…}
volumeChange: (element, options) => {…}
waiting: (element, options) => {…}
load: (element, options) => {…}
error: (element, options) => {…}
animationStart: (element, options) => {…}
animationEnd: (element, options) => {…}
animationIteration: (element, options) => {…}
transitionEnd: (element, options) => {…}
pointerOver: (element, options) => {…}
pointerEnter: (element, options) => {…}
pointerDown: (element, options) => {…}
pointerMove: (element, options) => {…}
pointerUp: (element, options) => {…}
pointerCancel: (element, options) => {…}
pointerOut: (element, options) => {…}
pointerLeave: (element, options) => {…}
gotPointerCapture: (element, options) => {…}
lostPointerCapture: (element, options) => {…}
doubleClick: (element, options) => {…}
__proto__: Object
```
The RenderResult object has everything needed to access the DOM.


**How do we access the DOM?**

```javascript
temp.fixture.componentInstance.element.nativeElement.innerHTML
```
Shows this:
```html
<form _ngcontent-a-c0="" novalidate="" ng-reflect-form="[object Object]" class="ng-untouched ng-pristine ng-valid"><label _ngcontent-a-c0=""></label><!--bindings={
  "ng-reflect-ng-if": "false"
}--></form>
```

Or, we can pull values out of the component itself, like this; where control is an input property of the component.

```
temp.fixture.componentInstance.control
```
It's expanded value looks like this:

```javascript 
{GroupName: "", PropertyName: "", Type: "", CurrentValue: "", Checked: ""}
GroupName: ""
PropertyName: ""
Type: ""
CurrentValue: ""
Checked: ""
__proto__: Object
```

**Take Away**
This library seems to make configuration of dependencies much more simple.

Thanks to John O.