Test Angular Components with Jasmine, Karma, and the Test Wrapper Pattern

Cam Dziurgot
JavaScript in Plain English
6 min readApr 25, 2021

--

Automated testing has become a great way protect applications from new bugs. Let’s look at a pattern that can be used to test components.

Photo by Clay Banks on Unsplash

Prerequisites/Assumptions

You have at least a boilerplate Angular application (one generated using ng new <app-name> will work), set up with Jasmine and Karma. The code was written using Angular 11 and Angular CLI - the Test Wrapper pattern should work with any supported version of Angular. It is also expected that you will have Node and Git bash, set up on your machine.

Example Component

First step is to generate a simple component using the command ng generate component simple-sample. When the component is generated, you can delete the HTML and CSS (or whatever style file) is generated. Style won’t be used and the template will be in the Typescript file itself.

The component will be, like the name suggests, simple. It will have two Inputs, a boolean and a string, and an output emitter, which will emit a string. The component will show a title passed in by the input, and have a default title when no input is provided. It will also have two buttons that are enabled/disabled based on the input boolean. When a button is clicked an output will be emitted to the parent component. Here is the component’s Typescript file.

Simple component Typescript file.

Test Wrapper Component

When you run the generate command, you’ll get a boilerplate spec file to build tests. The file is set up with a component and fixture variable. The component variable is the component being tested. The fixture variable is a testing tool used to apply changes to the component and see how the changes affect the state of the component. Here is what the spec file looks like when it is created by the generate command.

Initial test file generated.

The first addition to the spec file you’ll want to do is create the TestWrapperComponent. The wrapper component is just that, it is a container that wraps the component we are testing with all the inputs, handled outputs, and a flag the acts as a switch that will show and hide the component (default value to not show).

TestWrapper for the SimpleSample component.

At the beginning of each test case the show flag defaults to false. This means the component that is being tested will not be shown. The first thing done in each test case is set the input values that will be required for the tests. This includes turning on the show flag. Once everything is set, then detectChanges() is called using the fixture tool in order to refresh the component. This will cause every test to initial the component being tested, with ngOnInit and the constructor run for each test case.

The show/hide switch is key to this pattern. It will allow the component being tested to be reset before each test case so that the component will run through the life cycle functions.

Test Cases

Before starting to write actual tests, there should be several test cases (scenarios), in which to test on the SimpleSampleComponent. Since the component does not have a lot going on, there is not a lot of to test.

The following aspects can be tested; default behavior of the component when the Wrapper shows the testing component, clicking buttons will emit the expected values, disabled buttons being clicked do not emit events, and changing inputs after the component is initialized will update the component accordingly.

With these as scenarios to test, here are the list of test cases to go over.

#01 - undefined inputs, show default title
#02 - someBoolean true, click right button, event is "right"
#03 - default inputs, try click right button, event is ""
#04 - some title updated, span displays specific title
#05 - default inputs, click left button, event is "left"
#06 - update someTitle input after first shown, show updated title

Update Test Configuration

Now that there is a TestWrapperComponent, and a list of test cases, we can configure the spec file for testing. When Angular generates a spec file, the component and fixture variables are set to be type of a SimpleSampleComponent.

For the Test Wrapper pattern, we will set the type to be the TestWrapperComponent. In the beforeEach()function, the function that is called before each test case, the fixture is recreated using the TestBed class. That reset will also have to be updated to use the TestWrapperComponent instead of the SimpleSampleComponent. The TestWrapperComponent will have to be declared in the test configuration set through the TestBed configureTestingModule() function.

Writing Test Cases

Once you have the configurations set, the test cases can be written. There are essentially two types of test cases for the SimpleSampleComponent. One testing the title being displayed in the component, the other testing the events resulting from a button click based on the state of the component.

In both types of cases, the fixture is debugging property, nativeElement, is used to query the Wrapper component element for what will be rendered in the DOM. The nativeElement can be queried using either querySelector() or querySelectorAll() functions, just like a document on a page in a browser.

When testing for a specific title to appear in the DOM, a CSS selector is used in the querySelector() to grab an Element. Then the innerHTML string value of the queried Element is trimmed and checked against the expected value.

For the button tests, the CSS selector will be used to grab a ButtonElement. The that button element has a click() performed on it, and there is a value that will be emitted out and handled by the TestWrapperComponent.

Here is the full spec file, with the TestWrapperComponent, configuration set, and all the test cases implemented.

Completed spec file with Test Wrapper pattern.

Results

Karma Browser

Now the tests can be run with the npm test command. Running this command from a boilerplate Angular project will start the Karma test runner and open a browser. The browser will display the following.

Karma test runner in Chrome Browser.

Code Coverage

The test coverage for the tests can also be check using the command, ng test --no-watch --code-coverage. When the command is run in the command line, the component has 100% statement coverage.

Code coverage report for tests.

Conclusion

Writing unit tests is a good way to protect you application from introducing bugs when refactoring. Angular provides a good boilerplate for writing testings with both Jasmine framework and Karma test runner. Using the Test Wrapper pattern in your tests is a good way to fully test the life cycle of a component and easily test how changes in a parent will effect the component you are testing.

Try using the pattern next time you generate a component. Good luck, and happy coding!

More content at plainenglish.io

--

--

Full stack web developer interested in designing cloud based software systems.