DEV Community

JWP
JWP

Posted on • Edited on

4 1

Converting native Karma, Jasmine tests to use Angular-Testing-Library

A great suggestion by John O. was to try Angular-Testing-Library in response to this post.

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
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:


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;
   });
});
Enter fullscreen mode Exit fullscreen mode

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


{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
Enter fullscreen mode Exit fullscreen mode

The RenderResult object has everything needed to access the DOM.

How do we access the DOM?

temp.fixture.componentInstance.element.nativeElement.innerHTML
Enter fullscreen mode Exit fullscreen mode

Shows this:

<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>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

It's expanded value looks like this:

{GroupName: "", PropertyName: "", Type: "", CurrentValue: "", Checked: ""}
GroupName: ""
PropertyName: ""
Type: ""
CurrentValue: ""
Checked: ""
__proto__: Object
Enter fullscreen mode Exit fullscreen mode

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

Thanks to John O.

Top comments (1)

Collapse
 
joerter profile image
John Oerter

I'm glad you like it! You'll have to let me know how it goes with testing some complex forms, I haven't had a chance to dive into that too much yet. I've only looked at the examples here.

👋 Kindness is contagious

Explore a trove of insights in this engaging article, celebrated within our welcoming DEV Community. Developers from every background are invited to join and enhance our shared wisdom.

A genuine "thank you" can truly uplift someone’s day. Feel free to express your gratitude in the comments below!

On DEV, our collective exchange of knowledge lightens the road ahead and strengthens our community bonds. Found something valuable here? A small thank you to the author can make a big difference.

Okay