🚀 Spectator V4: A Powerful Tool to Simplify Your Angular Tests!

Dirk Luijk
Netanel Basal
Published in
6 min readAug 27, 2019

We are proud to release the next major version of Spectator. In this version, we make Angular testing easier than ever before.

We believe that its simple API is what makes Spectator great. It is easy to learn and saves you a lot of boilerplate code. In Spectator v4, we wanted to improve this experience by making the API even more consistent and make every feature easily accessible.

With Spectator, unit testing your Angular app is enjoyable again

Internally, we did quite some refactoring to enforce the internal code reuse. This makes Spectator more robust and predictable. This also allowed us to add some awesome features easily.

Why Spectator?

Spectator helps you get rid of all the boilerplate grunt work, leaving you with readable, sleek and streamlined unit tests.

It allows you to write tests for components, directives, services, and more, without having to learn TestBed, ComponentFixture, and DebugElement APIs.

Installation

$ npm install @ngneat/spectator --save-dev

Spectator V4 Overview

In Spectator v4, we provide the following factory functions to unit test Angular building blocks:

Every factory supports a wide range of features, including:

  • Auto-mocking services for both Jasmine and Jest
  • Access injected services in a type-safe way
  • Support for entry components
  • Override providers easily
  • Powerful DOM querying
  • Event dispatching, like click, focus, blur and other (custom) events
  • Global injections to reduce boilerplate code even more
  • Awesome matchers for Jasmine/Jest

On top of that, some factories provide additional specific features. Let’s take a look at some of them:

Spectator Improvements

Spectator loves component testing. In v4 we added some new features on top of the existing ones.

Basic Spectator Example

For a reference, this is how a simple Spectator test looks like:

You can also pass additional options to the factory.

Please find all the possible options in our documentation.

Global Queries

Sometimes, we don’t want to query within your component, but on a global level. For example, when we are testing an overlay.

In Spectator v4, we can simple do a global query using the root key:

const element = spectator.query('.some-overlay', {
root: true
})

This is useful if we want to access the element itself. If we wish to perform some tests right away, we can also use the power of Spectator matchers:

expect('.some-overlay').toHaveText('Lorem ipsum');

This will perform a global query as well.

Global Injections

It is now possible to add global configuration for Spectator. Use the defineGlobalsInjections() helper in your test setup to share some options across all Spectator tests:

This is very useful if you have modules, providers, or declarations that you need for (almost) every component. This way, you don’t have to repeat yourself.

Additional Helpers

We added the following helper functions to make DOM interaction easier:

  • spectator.blur()
  • spectator.focus()
  • spectator.keyboard.pressKey('a')

In addition to that, we still provide all the existing helpers of Spectator 3.x. Every helper accepts an optional selector. If not provided, the component host element is targeted.

Factory Overrides

In every Spectator v4 factory, we can now consistently override the following options:

  • providers: override providers for a specific test case
  • detectChanges: disable initial change detection if needed
  • props: override component/directive properties
  • hostProps: override host component properties
  • Route options (see Routing support)

Mock Providers

We can auto-mock providers by using the mocks option. Based on the class definition, it will automatically create a mock object by using Jasmine or Jest spies.

To mock components, directives, or pipes, we recommend you to use the library ng-mocks. For example, if you want to replace any child component with a dummy implementation, you can do the following:

Advanced Spectator Example

Check out some of the advanced features in the snippet below:

Spectator with Host Improvements

With Spectator, it is also possible to test a component together with a host component. By using an additional host component as a parent, it is easier to test the interaction of a component with its outside world (inputs, outputs).

Basic Example

Please find a basic example below:

What’s New?

In Spectator v4, the SpectatorHost API shares all the mentioned features of Spectator, with on top of that:

  • Defining a default template for the host component
  • Overriding this template
  • Overriding the host component properties
  • Using a custom host component (with complete type-safety)

Using a Custom Host Component

For more advanced cases, it might be useful to use a custom host component. For example, when you want to define specific host properties or methods:

🎉 New! Spectator for Directives

In Spectator v4, we added a new SpectatorDirective API for testing directives. A directive always needs a host component, so it looks a lot like the SpectatorHost API, with some small differences:

  • All queries are relative from the host element
  • For event dispatching, if no query is provided, the directive’s element is the default target

See its beauty in the example below:

🎉 New! Spectator for Routing

Spectator v4 introduces a new factory for routed components: components that are associated with a route (from @angular/router). They usually respond to routing changes (e.g., they rely on an ActivatedRoute).

The new SpectatorRouting API provides all the features of Spectator, with additionally:

  • It automatically provides a stub implementation for ActivatedRoute
  • You can configure the params, queryParams, fragments, and data. You can also update them to test how your component reacts to changes.
  • It provides a stub for RouterLink directives

Additional options

We can use the following additional options (they are all optional):

  • params: Params - a map of initial route parameters
  • queryParams: Params - a map of initial route query parameters
  • fragment: string - an initial route fragment
  • data: Data - a map of initial route data

SpectatorRouting API

We can update the route options and trigger navigation using the following methods:

  • triggerNavigation(options?: RouteOptions): void
  • setRouteParam(name: string, value: string): void
  • setRouteQueryParam(name: string, value: string): void
  • setRouteData(name: string, value: string): void
  • setRouteFragment(fragment: string | null): void

Basic Routing Example

Spectator for Services

Testing services with Spectator is easy. In Spectator v4 we added a special factory for creating services: createServiceFactory which returns a factory for SpectatorService.

Of course, we can stick to plain-old class testing, but if we want to benefit from dependency injection and Spectator features, this is an easy alternative.
We can access the created service using the spectator.service property.

Basic example

Advanced Example

In the following example, we can see that we can define imports, providers mocks and overrides for SpectatorService as well.

Spectator for HTTP

Data services are services that perform HTTP requests. In Spectator, there is a special factory for creating data services: createHttpFactory. It returns a factory for SpectatorHttp, which has the following members:

  • service — returns the created service
  • expectOne(URL: string, method: HttpMethod) — to assert a request and returning the TestRequest
  • httpClient — to access the HttpClient from Angular
  • controller — to access the HttpTestingController from Angular

Basic HTTP example

Additional Improvements

  • Improved general type-safety
  • Jasmine 3 support
  • Removed deprecated APIs from v3
  • Added support for mocking component providers
  • Added VSCode snippets package

🦊 New Docs

We wrote our documentation from scratch, detailing everything the spectator has to give. We also migrate from Gitbook to Github so it will be easier to contribute and track docs changes.

We also created an online testing playground in ng-run. Thanks to Alexey Zuev for the cooperation.

⭐️ We are Now Part of @ngneat!

As of v4, Spectator has moved to the @ngneat organization. ngneat provides neat Angular libraries with high-quality standards.

Please check out some of our other projects!

Migrating from 3.x

We wrote a migration guide to make updating to Spectator 4 as easy as possible.

What’s Next?

Spectator v4 is a very stable release, and we don’t expect to have any breaking changes soon.

We might add some additional features to support edge cases even better. Please let us know if you miss a feature.

--

--

Dirk Luijk
Dirk Luijk

Written by Dirk Luijk

Frontend engineer, Angular expert, blogger and open source maintainer.

Responses (7)