| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | include ../../../../_includes/_util-fns | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |  | :marked | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   We’ll test an Angular pipe in this chapter | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   An Angular pipe is a declarative way in HTML to transform some input into some displayable output. | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   We’ll look at our app’s custom `InitCapsPipe` that converts a string of words into a string of capitalized words. | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   We use it our `hero-detail.component.html` template to turn a hero name like “eeny weenie” into “Eeny Weenie” | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-16 01:06:56 -07:00
										 |  |  |  | code-example(format="linenums" language="html" escape="html"). | 
					
						
							|  |  |  |  |   <h2>{{hero.name  | initCaps}} is {{userName}}'s current super hero!</h2> | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |  | :marked | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   The code for `InitCapsPipe` in `init-caps-pipe.ts` is quite brief: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   ``` | 
					
						
							|  |  |  |  |   import {Pipe} from 'angular2/angular2'; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   @Pipe({ name: 'initCaps' }) | 
					
						
							|  |  |  |  |   export class InitCapsPipe { | 
					
						
							|  |  |  |  |     transform(value: string) { | 
					
						
							|  |  |  |  |       return value.toLowerCase().replace(/(?:^|\s)[a-z]/g, function(m) { | 
					
						
							|  |  |  |  |         return m.toUpperCase(); | 
					
						
							|  |  |  |  |       }); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  |   ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   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 | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-10 03:29:34 -07:00
										 |  |  |  | .callout.is-helpful | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   header Prior Knowledge | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |  |   :marked | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |     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 | 
					
						
							| 
									
										
										
										
											2015-10-14 23:04:58 -07:00
										 |  |  |  |     the [Tour of Heroes](../tutorial/) tutorial | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |     such as <code>npm</code>, <code>gulp</code>, and <code>live-server</code>. | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |  | :marked | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   ## Add the Angular library | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |  |   Looking back at `unit-tests.html` we realize that we have not loaded the Angular library. | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   Yet we were able to load and test the application’s `Hero` class. | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |  |   **We were lucky!**  The `Hero` class has no dependence on Angular. | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   If it had depended on Angular, we’d still be staring at the Jasmine “big-time fail” screen: | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | figure.image-display | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |  |   img(src='/resources/images/devguide/testing-an-angular-pipe/big-time-fail-screen.png' | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |       style="width:400px;" alt="Jasmine's' big time fail screen") | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |  | :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 | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   tried to load Angular and couldn't find it. | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-16 01:06:56 -07:00
										 |  |  |  | code-example(format="" language="html" escape="html"). | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |  |   GET http://127.0.0.1:8080/src/angular2/angular2 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. | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   The `InitCapsPiep` clearly depends on Angular as is clear in the first few lines: | 
					
						
							|  |  |  |  |   ``` | 
					
						
							|  |  |  |  |   import {Pipe} from 'angular2/angular2'; | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   @Pipe({ name: 'initCaps' }) | 
					
						
							|  |  |  |  |   export class InitCapsPipe { | 
					
						
							|  |  |  |  |   ``` | 
					
						
							|  |  |  |  |   **Open** `unit-tests.html` | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   **Find** the `src="../node_modules/systemjs/dist/system.src.js"></script>` | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   **Replace** Step #1  with these two scripts: | 
					
						
							|  |  |  |  |   ``` | 
					
						
							|  |  |  |  |   <!-- #1. add the system.js and angular libraries --> | 
					
						
							|  |  |  |  |   <script src="../node_modules/systemjs/dist/system.src.js"></script> | 
					
						
							|  |  |  |  |   <script src="../node_modules/angular2/bundles/angular2.dev.js"></script> | 
					
						
							|  |  |  |  |   ``` | 
					
						
							|  |  |  |  |   ## Add another spec file | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   **Create** an *`init-caps-pipe.spec.ts`** next to `init-caps-pipes.ts` in `src/app` | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   **Stop and restart the TypeScript compiler** to ensure we compile the new file. | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   **Add** the following lines of rather obvious Jasmine test code | 
					
						
							|  |  |  |  |   ``` | 
					
						
							|  |  |  |  |   import {InitCapsPipe} from './init-caps-pipe'; | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   describe('InitCapsPipe', () => { | 
					
						
							|  |  |  |  |     let pipe:InitCapsPipe; | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |     beforeEach(() => { | 
					
						
							|  |  |  |  |       pipe = new InitCapsPipe(); | 
					
						
							|  |  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |     it('transforms "abc" to "Abc"', () => { | 
					
						
							|  |  |  |  |       expect(pipe.transform('abc')).toEqual('Abc'); | 
					
						
							|  |  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |     it('transforms "abc def" to "Abc Def"', () => { | 
					
						
							|  |  |  |  |       expect(pipe.transform('abc def')).toEqual('Abc Def'); | 
					
						
							|  |  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |     it('leaves "Abc Def" unchanged', () => { | 
					
						
							|  |  |  |  |       expect(pipe.transform('Abc Def')).toEqual('Abc Def'); | 
					
						
							|  |  |  |  |     }); | 
					
						
							|  |  |  |  |   }); | 
					
						
							|  |  |  |  |   ``` | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |  |   Note that each test is short (one line in our case). | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   It has a clear label that accurately describes the test. And it makes exactly one expectation. | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |  |   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. | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   We’ll have little trouble maintaining these tests and adding more like them as we encounter new conditions to explore. | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   That’s the way we like our tests! | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   ## Add this spec to `unit-tests.html` | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   Now let’s wire our new spec file into the HTML test harness. | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   Open `unit-tests.html`. Find `System.import('app/hero.spec')`. | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   Hmm. We can’t just add `System.import('app/init-caps-pipe.spec')`. | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |  |   The first `System.import` returns a promise as does this second import. | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   We can’t run any of the Jasmine tests until **both imports are finished**. | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |  |   Fortunately, we can create a new `Promise` that wraps both import promises and waits | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   for both to finish loading. | 
					
						
							|  |  |  |  |   ``` | 
					
						
							|  |  |  |  |   // #3. Import the spec files explicitly | 
					
						
							|  |  |  |  |   Promise.all([ | 
					
						
							|  |  |  |  |     System.import('app/hero.spec'), | 
					
						
							|  |  |  |  |     System.import('app/init-caps-pipe.spec') | 
					
						
							|  |  |  |  |   ]) | 
					
						
							|  |  |  |  |   ``` | 
					
						
							|  |  |  |  |   Try it. The browser should refresh and show | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | figure.image-display | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |  |   img(src='/resources/images/devguide/testing-an-angular-pipe/5-specs-0-failures.png' | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   style="width:400px;" alt="import promises 5 specs, 0 failures") | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |  | :marked | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   We have a pattern for adding new tests. | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |  |   In future, when we add a new spec, we add another `System.import('app/some.spec')` to | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   the array argument passed to `Promise.all`. | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   ## What’s Next? | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   Now we can test parts of our application that we *load* asynchronously with system.js. | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   What about testing parts that *are themselves asynchronous*? | 
					
						
							| 
									
										
										
										
											2015-10-09 10:33:12 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-10 18:31:46 +00:00
										 |  |  |  |   In the next chapter we’ll test a service with a public asynchronous method that fetches heroes | 
					
						
							| 
									
										
										
										
											2015-10-14 20:25:19 -07:00
										 |  |  |  |   from a remote server. |