include ../_util-fns
:marked
We’ll test an Angular pipe in this chapter
An Angular pipe is a declarative way in HTML to transform some input into some displayable output.
We’ll look at our app’s custom `InitCapsPipe` that converts a string of words into a string of capitalized words.
We use it our `hero-detail.component.html` template to turn a hero name like “eeny weenie” into “Eeny Weenie”
+makeExample('testing/ts/app/hero-detail.component.html', 'pipe-usage')
:marked
The code for `InitCapsPipe` in `init-caps-pipe.ts` is quite brief:
+makeExample('testing/ts/app/init-caps-pipe.ts')
:marked
In this chapter we will:
- add the Angular 2 library to our test harness
- test this custom Angular pipe class
- load multiple test files in our test harness, using system.js
.callout.is-helpful
header Prior Knowledge
:marked
The Unit Testing chapters build upon each other. We recommend reading them in order.
We're also assuming that you're already comfortable with basic Angular 2 concepts and the tools
we introduced in the [QuickStart](../quickstart.html) and
the [Tour of Heroes](../tutorial/) tutorial
such as npm
, gulp
, and live-server
.
:marked
## Add the Angular library
Looking back at `unit-tests.html` we realize that we have not loaded the Angular library.
Yet we were able to load and test the application’s `Hero` class.
**We were lucky!** The `Hero` class has no dependence on Angular.
If it had depended on Angular, we’d still be staring at the Jasmine “big-time fail” screen:
figure.image-display
img(src='/resources/images/devguide/testing-an-angular-pipe/big-time-fail-screen.png'
style="width:400px;" alt="Jasmine's' big time fail screen")
:marked
If we then opened the browser’s Developer Tools (F12, Ctrl-Shift-I) and looked
in the console window, we would see that SystemJS
tried to load Angular and couldn't find it.
code-example(format="" language="html" escape="html").
GET http://127.0.0.1:8080/src/angular2/core 404 (Not Found)
:marked
We are writing an Angular application afterall and
we were going to need Angular sooner or later. That time has come.
The `InitCapsPipe` depends on Angular as is clear in the first few lines:
+makeExample('testing/ts/app/init-caps-pipe.ts', 'depends-on-angular')(format=".")
:marked
**Open** `unit-tests.html`
**Find** the `src="../node_modules/systemjs/dist/system.src.js">`
**Replace** Step #1 with these two scripts:
+makeExample('testing/ts/unit-tests-4.html', 'import-angular')(format=".")
:marked
## Add another spec file
**Create** an `init-caps-pipe.spec.ts` next to `init-caps-pipes.ts` in `src/app`
**Stop and restart the TypeScript compiler** to ensure we compile the new file.
**Add** the following lines of rather obvious Jasmine test code
+makeExample('testing/ts/app/init-caps-pipe.spec.ts', 'base-pipe-spec')
:marked
Note that each test is short (one line in our case).
It has a clear label that accurately describes the test. And it makes exactly one expectation.
Anyone can read these tests and understand quickly what the test does and what the pipe does.
If one of the tests fails, we know which expected behavior is no longer true.
We’ll have little trouble maintaining these tests and adding more like them as we encounter new conditions to explore.
That’s the way we like our tests!
## Add this spec to `unit-tests.html`
Now let’s wire our new spec file into the HTML test harness.
Open `unit-tests.html`. Find `System.import('app/hero.spec')`.
Hmm. We can’t just add `System.import('app/init-caps-pipe.spec')`.
The first `System.import` returns a promise as does this second import.
We can’t run any of the Jasmine tests until **both imports are finished**.
Fortunately, we can create a new `Promise` that wraps both import promises and waits
for both to finish loading.
+makeExample('testing/ts/unit-tests-4.html', 'promise-all')(format=".")
:marked
Try it. The browser should refresh and show
figure.image-display
img(src='/resources/images/devguide/testing-an-angular-pipe/5-specs-0-failures.png'
style="width:400px;" alt="import promises 5 specs, 0 failures")
:marked
We have a pattern for adding new tests.
In future, when we add a new spec, we add another `System.import('app/some.spec')` to
the array argument passed to `Promise.all`.
## What’s Next?
Now we can test parts of our application that we *load* asynchronously with system.js.
What about testing parts that *are themselves asynchronous*?
Let's test a service with a public asynchronous method that fetches heroes from a remote server.