Converting native Karma, Jasmine tests to use Angular-Testing-Library
John Peters
Posted on February 19, 2020
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;
});
});
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
The RenderResult object has everything needed to access the DOM.
How do we access the DOM?
temp.fixture.componentInstance.element.nativeElement.innerHTML
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>
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:
{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.
Posted on February 19, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.