128 lines
4.7 KiB
Plaintext
128 lines
4.7 KiB
Plaintext
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 <code>npm</code>, <code>gulp</code>, and <code>live-server</code>.
|
||
|
||
: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"></script>`
|
||
|
||
**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.
|