├── Chapter 01 ├── .DS_Store ├── Builder Pattern │ ├── builder.js │ └── index.html ├── README.md └── calculator │ ├── calculator.js │ └── testRunner.html ├── Chapter 02 ├── .DS_Store ├── MIT.LICENSE ├── README.md ├── SpecRunner.html ├── lib │ └── jasmine-2.4.1 │ │ ├── boot.js │ │ ├── console.js │ │ ├── jasmine-html.js │ │ ├── jasmine.css │ │ ├── jasmine.js │ │ └── jasmine_favicon.png ├── spec │ └── mySpec.js └── src │ └── mySource.js ├── Chapter 03 ├── .editorconfig ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── app │ ├── app.component.spec.ts │ ├── app.component.ts │ ├── app.module.ts │ └── main.ts ├── e2e │ └── app.e2e-spec.ts ├── favicon.ico ├── index.html ├── karma-test-shim.js ├── karma.conf.js ├── package.json ├── protractor.config.js ├── styles.css ├── systemjs.config.extras.js ├── systemjs.config.js ├── tsconfig.json └── tslint.json ├── Chapter 04 ├── .editorconfig ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── app │ ├── app.component.spec.ts │ ├── app.component.ts │ ├── app.module.ts │ └── main.ts ├── e2e │ └── app.e2e-spec.ts ├── favicon.ico ├── index.html ├── karma-test-shim.js ├── karma.conf.js ├── package.json ├── protractor.config.js ├── styles.css ├── systemjs.config.extras.js ├── systemjs.config.js ├── tsconfig.json └── tslint.json ├── Chapter 05 ├── .editorconfig ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── app │ ├── app.component.spec.ts │ ├── app.component.ts │ ├── app.module.ts │ └── main.ts ├── debug │ ├── app.debug.e2e.ts │ └── debugConf.js ├── e2e │ └── app.e2e-spec.ts ├── favicon.ico ├── index.html ├── karma-test-shim.js ├── karma.conf.js ├── package.json ├── protractor.config.js ├── styles.css ├── systemjs.config.extras.js ├── systemjs.config.js ├── tsconfig.json └── tslint.json ├── Chapter 06 ├── .dockerignore ├── .editorconfig ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── Dockerfile ├── LICENSE ├── README.md ├── app │ ├── app.component.ts │ ├── app.module.ts │ └── main.ts ├── favicon.ico ├── index.html ├── karma-test-shim.js ├── karma.conf.js ├── package.json ├── protractor.config.js ├── spec │ ├── e2e │ │ └── app.e2e-spec.ts │ └── unit │ │ └── app.component.spec.ts ├── styles.css ├── systemjs.config.extras.js ├── systemjs.config.js ├── tsconfig.json ├── tslint.json └── wallaby.js ├── Chapter 07 ├── .editorconfig ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── app │ ├── app.component.html │ ├── app.component.ts │ ├── app.module.ts │ ├── app.routes.ts │ ├── data │ │ └── people.json │ ├── main.ts │ ├── members │ │ ├── members.component.css │ │ ├── members.component.html │ │ ├── members.component.ts │ │ └── person │ │ │ ├── person.component.html │ │ │ └── person.component.ts │ ├── nav │ │ ├── navbar.component.css │ │ ├── navbar.component.html │ │ └── navbar.component.ts │ └── view │ │ ├── view1.component.ts │ │ └── view2.component.ts ├── favicon.ico ├── index.html ├── karma-test-shim.js ├── karma.conf.js ├── package.json ├── protractor-results.txt ├── protractor.config.js ├── spec │ └── e2e │ │ ├── app.e2e-spec.ts │ │ ├── members.component.e2e-spec.ts │ │ ├── person.component.e2e-spec.ts │ │ └── view.e2e-spec.ts ├── styles.css ├── systemjs.config.extras.js ├── systemjs.config.js ├── tsconfig.json ├── tslint.json └── typing.json ├── Chapter 08 ├── .editorconfig ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── app │ ├── app.component.html │ ├── app.component.ts │ ├── app.module.ts │ ├── app.routes.ts │ ├── data │ │ └── people.json │ ├── main.ts │ ├── members │ │ ├── members.component.css │ │ ├── members.component.html │ │ ├── members.component.ts │ │ └── person │ │ │ ├── person.component.html │ │ │ └── person.component.ts │ ├── nav │ │ ├── navbar.component.css │ │ ├── navbar.component.html │ │ └── navbar.component.ts │ ├── search │ │ ├── search.component.html │ │ └── search.component.ts │ ├── services │ │ └── members.service.ts │ └── view │ │ ├── view1.component.ts │ │ └── view2.component.ts ├── favicon.ico ├── index.html ├── karma-test-shim.js ├── karma.conf.js ├── package.json ├── protractor-results.txt ├── protractor.config.js ├── spec │ ├── e2e │ │ ├── app.e2e-spec.ts │ │ ├── members.component.e2e-spec.ts │ │ ├── person.component.e2e-spec.ts │ │ └── view.e2e-spec.ts │ └── unit │ │ ├── app.component.spec.ts │ │ ├── members.service.spec.ts │ │ └── stub │ │ ├── members.service.stub.ts │ │ └── router-stubs.ts ├── styles.css ├── systemjs.config.extras.js ├── systemjs.config.js ├── tsconfig.json ├── tslint.json └── typing.json ├── LICENSE └── README.md /Chapter 01/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Angular-Test-Driven-Development-Second-Edition/306153dc7400dd7c063d3494d17d5d14e3c1c41a/Chapter 01/.DS_Store -------------------------------------------------------------------------------- /Chapter 01/Builder Pattern/builder.js: -------------------------------------------------------------------------------- 1 | 2 | var bookBuilder = function() { 3 | var _resultBook = { 4 | id: 1, 5 | author: 'Any Author', 6 | dateTime: new Date() 7 | }; 8 | 9 | this.build = function() { 10 | return _resultBook; 11 | }; 12 | 13 | this.setAuthor = function(author) { 14 | _resultBook.author = author; 15 | return this; 16 | }; 17 | 18 | this.setDateTime = function(dateTime) { 19 | _resultBook.dateTime = dateTime; 20 | return this; 21 | }; 22 | }; 23 | 24 | var validate = function(builtBookToValidate){ 25 | if(!builtBookToValidate.author) { 26 | return false; 27 | } 28 | if(!builtBookToValidate.dateTime) { 29 | return false; 30 | } 31 | return true; 32 | }; 33 | 34 | var builtBook = new bookBuilder().setAuthor('Ziaul Haq') 35 | .setDateTime(new Date()) 36 | .build(); 37 | 38 | console.log(builtBook.author); // Ziaul Haq 39 | 40 | 41 | var validBuilder = new bookBuilder().setAuthor('Ziaul Haq') 42 | .setDateTime(new Date()) 43 | .build(); 44 | 45 | // Validate the object with validate() method 46 | if (validate(validBuilder)) { 47 | console.log('Valid Book created'); 48 | } 49 | 50 | var invalidBuilder = new bookBuilder().setAuthor(null).build(); 51 | 52 | if (!validate(invalidBuilder)) { 53 | console.log('Invalid Book created as author is null'); 54 | } 55 | 56 | var invalidBuilder = new bookBuilder().setDateTime(null).build(); 57 | 58 | if (!validate(invalidBuilder)) { 59 | console.log('Invalid Book created as dateTime is null'); 60 | } 61 | -------------------------------------------------------------------------------- /Chapter 01/Builder Pattern/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Test Runner 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Chapter 01/README.md: -------------------------------------------------------------------------------- 1 | # Angular TDD Chapter1 Source 2 | 3 | This repository is for 2 simple test projects. 4 | 5 | 1. Simple calculator testing 6 | 2. Builder pattern 7 | -------------------------------------------------------------------------------- /Chapter 01/calculator/calculator.js: -------------------------------------------------------------------------------- 1 | 2 | var calculator = { 3 | multiply : function(amount1, amount2) { 4 | return amount1 * amount2; 5 | } 6 | }; 7 | 8 | function multipleTest1() { 9 | // Test 10 | var result = calculator.multiply(3, 3); 11 | 12 | // Assert Result is expected 13 | if (result === 9) { 14 | console.log('Test Passed'); 15 | } else { 16 | console.log('Test Failed'); 17 | } 18 | }; 19 | 20 | multipleTest1(); 21 | -------------------------------------------------------------------------------- /Chapter 01/calculator/testRunner.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Test Runner 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Chapter 02/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Angular-Test-Driven-Development-Second-Edition/306153dc7400dd7c063d3494d17d5d14e3c1c41a/Chapter 02/.DS_Store -------------------------------------------------------------------------------- /Chapter 02/MIT.LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008-2011 Pivotal Labs 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Chapter 02/README.md: -------------------------------------------------------------------------------- 1 | # Angular TDD Chapter2 Source 2 | 3 | This repository is for Jasmine v2.4.1 sample test suite with some very basic test case. 4 | -------------------------------------------------------------------------------- /Chapter 02/SpecRunner.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Jasmine Spec Runner v2.4.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Chapter 02/lib/jasmine-2.4.1/jasmine_favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Angular-Test-Driven-Development-Second-Edition/306153dc7400dd7c063d3494d17d5d14e3c1c41a/Chapter 02/lib/jasmine-2.4.1/jasmine_favicon.png -------------------------------------------------------------------------------- /Chapter 02/spec/mySpec.js: -------------------------------------------------------------------------------- 1 | 2 | describe("A sample test suite to test jasmine assertion", function() { 3 | var fetchA; 4 | beforeEach(function() { 5 | spyOn(myObj, "getA").and.returnValue(789); 6 | myObj.setA(123); 7 | fetchA = myObj.getA(); 8 | }); 9 | 10 | it("tracks that the spy was called", function() { 11 | expect(myObj.getA).toHaveBeenCalled(); 12 | }); 13 | 14 | it("should not affect other functions", function() { 15 | expect(a).toEqual(123); 16 | }); 17 | 18 | it("when called returns the requested value", function() { 19 | expect(fetchA).toEqual(789); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /Chapter 02/src/mySource.js: -------------------------------------------------------------------------------- 1 | 2 | var a, 3 | myObj = { 4 | setA: function(value) { 5 | a = value; 6 | }, 7 | getA: function(value) { 8 | return a; 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /Chapter 03/.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | 12 | [*.md] 13 | max_line_length = 0 14 | trim_trailing_whitespace = false 15 | 16 | # Indentation override 17 | #[lib/**.js] 18 | #[{package.json,.travis.yml}] 19 | #[**/**.js] 20 | -------------------------------------------------------------------------------- /Chapter 03/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | node_modules 3 | jspm_packages 4 | npm-debug.* 5 | link-checker-results.txt 6 | app/**/*.js 7 | *.js.map 8 | e2e/**/*.js 9 | e2e/**/*.js.map 10 | _test-output 11 | _temp 12 | -------------------------------------------------------------------------------- /Chapter 03/.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | sudo: required 3 | language: node_js 4 | node_js: 5 | - "5" 6 | os: 7 | - linux 8 | env: 9 | global: 10 | - DBUS_SESSION_BUS_ADDRESS=/dev/null 11 | - DISPLAY=:99.0 12 | - CHROME_BIN=chromium-browser 13 | before_script: 14 | - sh -e /etc/init.d/xvfb start 15 | install: 16 | - npm install 17 | script: 18 | - npm run lint 19 | - npm run test-once 20 | - npm run e2e 21 | -------------------------------------------------------------------------------- /Chapter 03/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## Angular Documentation QuickStart Changelog 2 | Upgraders: for a fresh start, consider running these commands 3 | * `git clean -xdf` 4 | * `npm install` 5 | 6 | 7 | # 0.2.17 (2016-11-16) 8 | * Conform to updated QuickStart advice 9 | * removed docker everywhere (was nice but not necessary) 10 | * removed wallaby 11 | * shrink styles.css 12 | * refine tsconfig.json 13 | * `AppComponent` uses interpolation 14 | 15 | 16 | # 0.2.16 (2016-11-14) 17 | * Update to Angular 2.2.0 18 | 19 | 20 | # 0.2.15 (2016-10-29) 21 | * Revert to Jasmine 2.4.1 because bug in 2.5.x (see [jasmine issue #1231](https://github.com/jasmine/jasmine/issues/1231)) 22 | 23 | 24 | # 0.2.14 (2016-10-29) 25 | * Remove bootstrap.css install 26 | * Angular v2.1.2 27 | 28 | 29 | # 0.2.13 (2016-10-20) 30 | * Protractor 4 31 | * Move from `typings` to `@types`. See `tsconfig.json` changes. 32 | * Angular v2.1.1 33 | 34 | 35 | # 0.2.12 (2016-10-06) 36 | * Angular v2.1.0 37 | 38 | 39 | # 0.2.11 (2016-10-06) 40 | * Angular v2.0.2 41 | * License is MIT 42 | * Current testing configuration 43 | * No code changes 44 | 45 | 46 | # 0.2.10 (2016-09-19) 47 | * All "Angular 2" references become just "Angular" 48 | * No code changes 49 | 50 | 51 | # 0.2.9 (2016-09-14) 52 | * Angular 2.0.0 version 53 | * Update to Typescript 2.0.2 54 | * Fix e2e test missing dir 55 | 56 | 57 | # 0.2.8 (2016-09-01) 58 | * remove @angular test libraries from system.js (now in shim) 59 | * update test related files 60 | * wallaby doesn't completely work. Researching. 61 | 62 | 63 | # 0.2.7 (2016-08-31) 64 | * Angular 2 RC6 version 65 | * Updated new forms, router, angular2-in-memory-web-api, karma, core-js, rxjs and zone.js packages 66 | * Removed router-deprecated package 67 | * Updated karma.conf.js and systemjs.config.js 68 | 69 | 70 | # 0.2.6 (2016-08-09) 71 | * Angular 2 RC5 version 72 | * Updated new forms, router and angular2-in-memory-web-api 73 | 74 | 75 | # 0.2.5 (2016-06-30) 76 | * Angular 2 RC4 version 77 | * Updated new forms and router 78 | 79 | 80 | # 0.2.4 (2016-06-21) 81 | * Angular 2 RC3 version 82 | * Add new forms and router 83 | * Add support for TS e2e tests 84 | 85 | 86 | # 0.2.3 (2016-06-15) 87 | * Angular 2 RC2 version 88 | 89 | 90 | # 0.2.2 (2016-05-21) 91 | * Update to Typings 1.x 92 | 93 | 94 | # 0.2.1 (2016-05-03) 95 | * Angular 2 RC01 version 96 | 97 | 98 | # 0.2.0 (2016-05-02) 99 | * Angular 2 RC0 version 100 | 101 | 102 | # 0.1.17 (2016-04-29) 103 | * update packages 104 | * Angular 2 beta 17 105 | * RxJS 5.0.0-beta.6 106 | * a2-in-memory-web-api 0.1.17 107 | 108 | 109 | # 0.1.16 (2016-04-26) 110 | * update packages 111 | * Angular 2 beta 16 112 | * a2-in-memory-web-api 0.1.6 113 | * protractor 3.3.0 114 | * typings 0.8.1 115 | * zone.js 0.6.12 116 | 117 | * added favicon.ico 118 | 119 | * testing 120 | - updated wallaby.js and karma.conf.js 121 | - updated app.component.spec.ts 122 | 123 | 124 | 125 | # 0.1.15 (2016-04-13) 126 | * Add testing support 127 | * npm scripts 128 | * karma/jasmine 129 | * protractor 130 | 131 | * update packages 132 | * Angular 2 beta 15 133 | * lite-server 2.2.0 134 | * systemjs 0.19.26 135 | * typescript 1.8.10 136 | * typings 0.7.12 137 | 138 | * add run packages 139 | * a2-in-memory-web-api 140 | 141 | * add testing dev-dependency packages 142 | * canonical-path: 0.0.2, 143 | * http-server: ^0.9.0, 144 | * jasmine-core: ~2.4.1, 145 | * karma: ^0.13.22, 146 | * karma-chrome-launcher: ^0.2.3, 147 | * karma-cli: ^0.1.2, 148 | * karma-htmlfile-reporter: ^0.2.2, 149 | * karma-jasmine: ^0.3.8, 150 | * protractor: ^3.2.2, 151 | * rimraf: ^2.5.2 152 | 153 | 154 | # 0.1.14 (2016-04-07) 155 | * update packages 156 | * Angular 2 beta 14 157 | * lite-server 2.2.0 158 | * typings 0.7.12 159 | 160 | 161 | # 0.1.13 (2016-03-31) 162 | * update packages 163 | * Angular 2 beta 13 164 | 165 | 166 | # 0.1.12 (2016-03-23) 167 | * update packages 168 | * Angular 2 beta 12 169 | * zones 0.6.6 170 | * remove es6-promise because no longer needed. 171 | 172 | 173 | # 0.1.11 (2016-03-18) 174 | * update packages 175 | * Angular 2 beta 11 176 | * zones 0.6.4 177 | * typescript 1.8.9 178 | * typings 0.7.9 179 | -------------------------------------------------------------------------------- /Chapter 03/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2014-2016 Google, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Chapter 03/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { AppComponent } from './app.component'; 2 | 3 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 4 | 5 | describe('AppComponent', function () { 6 | let comp: AppComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ AppComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(AppComponent); 18 | comp = fixture.componentInstance; 19 | }); 20 | 21 | it('Should define a list object', () => { 22 | expect(comp.items).toBeDefined(); 23 | }); 24 | 25 | it('Should have 3 items in list', () => { 26 | expect(comp.items.length).toBe(3); 27 | }); 28 | 29 | it('List items should be as expected', () => { 30 | expect(comp.items).toEqual(['test','execute','refactor']); 31 | }); 32 | 33 | describe('Testing add method', () => { 34 | 35 | beforeEach(() => { 36 | comp.add('new-item'); 37 | }); 38 | 39 | it('Should have 4 items in list', () => { 40 | expect(comp.items.length).toBe(4); 41 | }); 42 | 43 | it('Should add a new item at the end of list', () => { 44 | var lastIndexOfList = comp.items.length - 1; 45 | expect(comp.items[lastIndexOfList]).toEqual('new-item'); 46 | }); 47 | }); 48 | 49 | }); 50 | -------------------------------------------------------------------------------- /Chapter 03/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'my-app', 5 | template: `

MY Items

` 6 | }) 7 | export class AppComponent { 8 | items:Array; 9 | 10 | constructor() { 11 | this.items = ['test','execute','refactor']; 12 | } 13 | 14 | add(item) { 15 | this.items.push(item); 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /Chapter 03/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | 4 | import { AppComponent } from './app.component'; 5 | 6 | @NgModule({ 7 | imports: [ BrowserModule ], 8 | declarations: [ AppComponent ], 9 | bootstrap: [ AppComponent ] 10 | }) 11 | export class AppModule { } 12 | -------------------------------------------------------------------------------- /Chapter 03/app/main.ts: -------------------------------------------------------------------------------- 1 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 2 | 3 | import { AppModule } from './app.module'; 4 | 5 | platformBrowserDynamic().bootstrapModule(AppModule); 6 | -------------------------------------------------------------------------------- /Chapter 03/e2e/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { browser, element, by } from 'protractor'; 2 | 3 | describe('AppComponent Tests', () => { 4 | 5 | beforeEach(() => { 6 | browser.get('/'); 7 | }); 8 | 9 | it('Browser should have a defined title', () => { 10 | expect(browser.getTitle()).toEqual('Angular Karma'); 11 | }); 12 | 13 | }); 14 | -------------------------------------------------------------------------------- /Chapter 03/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Angular-Test-Driven-Development-Second-Edition/306153dc7400dd7c063d3494d17d5d14e3c1c41a/Chapter 03/favicon.ico -------------------------------------------------------------------------------- /Chapter 03/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Angular Karma 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 21 | 22 | 23 | Loading AppComponent content here ... 24 | 25 | 26 | -------------------------------------------------------------------------------- /Chapter 03/karma-test-shim.js: -------------------------------------------------------------------------------- 1 | // #docregion 2 | // /*global jasmine, __karma__, window*/ 3 | Error.stackTraceLimit = 0; // "No stacktrace"" is usually best for app testing. 4 | 5 | // Uncomment to get full stacktrace output. Sometimes helpful, usually not. 6 | // Error.stackTraceLimit = Infinity; // 7 | 8 | jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000; 9 | 10 | var builtPath = '/base/app/'; 11 | 12 | __karma__.loaded = function () { }; 13 | 14 | function isJsFile(path) { 15 | return path.slice(-3) == '.js'; 16 | } 17 | 18 | function isSpecFile(path) { 19 | return /\.spec\.(.*\.)?js$/.test(path); 20 | } 21 | 22 | function isBuiltFile(path) { 23 | return isJsFile(path) && (path.substr(0, builtPath.length) == builtPath); 24 | } 25 | 26 | var allSpecFiles = Object.keys(window.__karma__.files) 27 | .filter(isSpecFile) 28 | .filter(isBuiltFile); 29 | 30 | System.config({ 31 | baseURL: 'base', 32 | // Extend usual application package list with test folder 33 | packages: { 'testing': { main: 'index.js', defaultExtension: 'js' } }, 34 | 35 | // Assume npm: is set in `paths` in systemjs.config 36 | // Map the angular testing umd bundles 37 | map: { 38 | '@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js', 39 | '@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js', 40 | '@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js', 41 | '@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js', 42 | '@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js', 43 | '@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js', 44 | '@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js', 45 | '@angular/forms/testing': 'npm:@angular/forms/bundles/forms-testing.umd.js', 46 | }, 47 | }); 48 | 49 | System.import('systemjs.config.js') 50 | .then(importSystemJsExtras) 51 | .then(initTestBed) 52 | .then(initTesting); 53 | 54 | /** Optional SystemJS configuration extras. Keep going w/o it */ 55 | function importSystemJsExtras(){ 56 | return System.import('systemjs.config.extras.js') 57 | .catch(function(reason) { 58 | console.log( 59 | 'Warning: System.import could not load the optional "systemjs.config.extras.js". Did you omit it by accident? Continuing without it.' 60 | ); 61 | console.log(reason); 62 | }); 63 | } 64 | 65 | function initTestBed(){ 66 | return Promise.all([ 67 | System.import('@angular/core/testing'), 68 | System.import('@angular/platform-browser-dynamic/testing') 69 | ]) 70 | 71 | .then(function (providers) { 72 | var coreTesting = providers[0]; 73 | var browserTesting = providers[1]; 74 | 75 | coreTesting.TestBed.initTestEnvironment( 76 | browserTesting.BrowserDynamicTestingModule, 77 | browserTesting.platformBrowserDynamicTesting()); 78 | }) 79 | } 80 | 81 | // Import all spec files and start karma 82 | function initTesting () { 83 | return Promise.all( 84 | allSpecFiles.map(function (moduleName) { 85 | return System.import(moduleName); 86 | }) 87 | ) 88 | .then(__karma__.start, __karma__.error); 89 | } 90 | -------------------------------------------------------------------------------- /Chapter 03/karma.conf.js: -------------------------------------------------------------------------------- 1 | // #docregion 2 | module.exports = function(config) { 3 | 4 | config.set({ 5 | basePath: '', 6 | frameworks: ['jasmine'], 7 | plugins: [ 8 | require('karma-jasmine'), 9 | require('karma-chrome-launcher') 10 | ], 11 | 12 | files: [ 13 | // System.js for module loading 14 | 'node_modules/systemjs/dist/system.src.js', 15 | 16 | // Polyfills 17 | 'node_modules/core-js/client/shim.js', 18 | 'node_modules/reflect-metadata/Reflect.js', 19 | 20 | // zone.js 21 | 'node_modules/zone.js/dist/zone.js', 22 | 'node_modules/zone.js/dist/long-stack-trace-zone.js', 23 | 'node_modules/zone.js/dist/proxy.js', 24 | 'node_modules/zone.js/dist/sync-test.js', 25 | 'node_modules/zone.js/dist/jasmine-patch.js', 26 | 'node_modules/zone.js/dist/async-test.js', 27 | 'node_modules/zone.js/dist/fake-async-test.js', 28 | 29 | // RxJs 30 | { pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false }, 31 | { pattern: 'node_modules/rxjs/**/*.js.map', included: false, watched: false }, 32 | 33 | // Paths loaded via module imports: 34 | // Angular itself 35 | { pattern: 'node_modules/@angular/**/*.js', included: false, watched: false }, 36 | { pattern: 'node_modules/@angular/**/*.js.map', included: false, watched: false }, 37 | 38 | { pattern: 'systemjs.config.js', included: false, watched: false }, 39 | { pattern: 'systemjs.config.extras.js', included: false, watched: false }, 40 | 'karma-test-shim.js', 41 | 42 | { pattern: 'app/**/*.js', included: false, watched: true } 43 | ], 44 | 45 | port: 9876, 46 | colors: true, 47 | autoWatch: true, 48 | browsers: ['Chrome'], 49 | singleRun: false 50 | }) 51 | } 52 | -------------------------------------------------------------------------------- /Chapter 03/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-TDD-chapter-3", 3 | "version": "1.0.0", 4 | "description": "QuickStart package.json from the documentation, supplemented with testing support", 5 | "scripts": { 6 | "start": "tsc && concurrently \"tsc -w\" \"lite-server\" ", 7 | "e2e": "tsc && concurrently \"http-server -s\" \"protractor protractor.config.js\" --kill-others --success first", 8 | "lint": "tslint ./app/**/*.ts -t verbose", 9 | "lite": "lite-server", 10 | "pree2e": "webdriver-manager update", 11 | "test": "tsc && concurrently \"tsc -w\" \"karma start karma.conf.js\"", 12 | "test-once": "tsc && karma start karma.conf.js --single-run", 13 | "tsc": "tsc", 14 | "tsc:w": "tsc -w" 15 | }, 16 | "keywords": [], 17 | "author": "", 18 | "license": "MIT", 19 | "dependencies": { 20 | "@angular/common": "~2.2.0", 21 | "@angular/compiler": "~2.2.0", 22 | "@angular/core": "~2.2.0", 23 | "@angular/forms": "~2.2.0", 24 | "@angular/http": "~2.2.0", 25 | "@angular/platform-browser": "~2.2.0", 26 | "@angular/platform-browser-dynamic": "~2.2.0", 27 | "@angular/router": "~3.2.0", 28 | 29 | "angular-in-memory-web-api": "~0.1.15", 30 | "systemjs": "0.19.40", 31 | "core-js": "^2.4.1", 32 | "reflect-metadata": "^0.1.8", 33 | "rxjs": "5.0.0-beta.12", 34 | "zone.js": "^0.6.26" 35 | }, 36 | "devDependencies": { 37 | "concurrently": "^3.1.0", 38 | "lite-server": "^2.2.2", 39 | "typescript": "^2.0.10", 40 | 41 | "canonical-path": "0.0.2", 42 | "http-server": "^0.9.0", 43 | "tslint": "^3.15.1", 44 | "lodash": "^4.16.4", 45 | "jasmine-core": "~2.4.1", 46 | "karma": "^1.3.0", 47 | "karma-chrome-launcher": "^2.0.0", 48 | "karma-cli": "^1.0.1", 49 | "karma-htmlfile-reporter": "^0.3.4", 50 | "karma-jasmine": "^1.0.2", 51 | "karma-jasmine-html-reporter": "^0.2.2", 52 | "protractor": "4.0.14", 53 | "webdriver-manager": "10.2.5", 54 | "rimraf": "^2.5.4", 55 | 56 | "@types/node": "^6.0.46", 57 | "@types/jasmine": "^2.5.36", 58 | "@types/selenium-webdriver": "^2.53.33" 59 | }, 60 | "repository": {} 61 | } 62 | -------------------------------------------------------------------------------- /Chapter 03/styles.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | color: #369; 3 | font-family: Arial, Helvetica, sans-serif; 4 | font-size: 250%; 5 | } 6 | -------------------------------------------------------------------------------- /Chapter 03/systemjs.config.extras.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Add barrels and stuff 3 | * Adjust as necessary for your application needs. 4 | */ 5 | // (function (global) { 6 | // System.config({ 7 | // packages: { 8 | // // add packages here 9 | // } 10 | // }); 11 | // })(this); 12 | -------------------------------------------------------------------------------- /Chapter 03/systemjs.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * System configuration for Angular samples 3 | * Adjust as necessary for your application needs. 4 | */ 5 | (function (global) { 6 | System.config({ 7 | paths: { 8 | // paths serve as alias 9 | 'npm:': 'node_modules/' 10 | }, 11 | // map tells the System loader where to look for things 12 | map: { 13 | // our app is within the app folder 14 | app: 'app', 15 | 16 | // angular bundles 17 | '@angular/core': 'npm:@angular/core/bundles/core.umd.js', 18 | '@angular/common': 'npm:@angular/common/bundles/common.umd.js', 19 | '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js', 20 | '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js', 21 | '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js', 22 | '@angular/http': 'npm:@angular/http/bundles/http.umd.js', 23 | '@angular/router': 'npm:@angular/router/bundles/router.umd.js', 24 | '@angular/router/upgrade': 'npm:@angular/router/bundles/router-upgrade.umd.js', 25 | '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js', 26 | '@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.js', 27 | '@angular/upgrade/static': 'npm:@angular/upgrade/bundles/upgrade-static.umd.js', 28 | 29 | // other libraries 30 | 'rxjs': 'npm:rxjs', 31 | 'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js' 32 | }, 33 | // packages tells the System loader how to load when no filename and/or no extension 34 | packages: { 35 | app: { 36 | main: './main.js', 37 | defaultExtension: 'js' 38 | }, 39 | rxjs: { 40 | defaultExtension: 'js' 41 | } 42 | } 43 | }); 44 | })(this); 45 | -------------------------------------------------------------------------------- /Chapter 03/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "emitDecoratorMetadata": true, 8 | "experimentalDecorators": true, 9 | "lib": [ "es2015", "dom" ], 10 | "noImplicitAny": false, 11 | "suppressImplicitAnyIndexErrors": true 12 | }, 13 | "exclude": [ 14 | "node_modules/*", 15 | "**/*-aot.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /Chapter 03/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "class-name": true, 4 | "comment-format": [ 5 | true, 6 | "check-space" 7 | ], 8 | "curly": true, 9 | "eofline": true, 10 | "forin": true, 11 | "indent": [ 12 | true, 13 | "spaces" 14 | ], 15 | "label-position": true, 16 | "label-undefined": true, 17 | "max-line-length": [ 18 | true, 19 | 140 20 | ], 21 | "member-access": false, 22 | "member-ordering": [ 23 | true, 24 | "static-before-instance", 25 | "variables-before-functions" 26 | ], 27 | "no-arg": true, 28 | "no-bitwise": true, 29 | "no-console": [ 30 | true, 31 | "debug", 32 | "info", 33 | "time", 34 | "timeEnd", 35 | "trace" 36 | ], 37 | "no-construct": true, 38 | "no-debugger": true, 39 | "no-duplicate-key": true, 40 | "no-duplicate-variable": true, 41 | "no-empty": false, 42 | "no-eval": true, 43 | "no-inferrable-types": true, 44 | "no-shadowed-variable": true, 45 | "no-string-literal": false, 46 | "no-switch-case-fall-through": true, 47 | "no-trailing-whitespace": true, 48 | "no-unused-expression": true, 49 | "no-unused-variable": true, 50 | "no-unreachable": true, 51 | "no-use-before-declare": true, 52 | "no-var-keyword": true, 53 | "object-literal-sort-keys": false, 54 | "one-line": [ 55 | true, 56 | "check-open-brace", 57 | "check-catch", 58 | "check-else", 59 | "check-whitespace" 60 | ], 61 | "quotemark": [ 62 | true, 63 | "single" 64 | ], 65 | "radix": true, 66 | "semicolon": [ 67 | "always" 68 | ], 69 | "triple-equals": [ 70 | true, 71 | "allow-null-check" 72 | ], 73 | "typedef-whitespace": [ 74 | true, 75 | { 76 | "call-signature": "nospace", 77 | "index-signature": "nospace", 78 | "parameter": "nospace", 79 | "property-declaration": "nospace", 80 | "variable-declaration": "nospace" 81 | } 82 | ], 83 | "variable-name": false, 84 | "whitespace": [ 85 | true, 86 | "check-branch", 87 | "check-decl", 88 | "check-operator", 89 | "check-separator", 90 | "check-type" 91 | ] 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Chapter 04/.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | 12 | [*.md] 13 | max_line_length = 0 14 | trim_trailing_whitespace = false 15 | 16 | # Indentation override 17 | #[lib/**.js] 18 | #[{package.json,.travis.yml}] 19 | #[**/**.js] 20 | -------------------------------------------------------------------------------- /Chapter 04/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | node_modules 3 | jspm_packages 4 | npm-debug.* 5 | link-checker-results.txt 6 | app/**/*.js 7 | *.js.map 8 | e2e/**/*.js 9 | e2e/**/*.js.map 10 | _test-output 11 | _temp 12 | -------------------------------------------------------------------------------- /Chapter 04/.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | sudo: required 3 | language: node_js 4 | node_js: 5 | - "5" 6 | os: 7 | - linux 8 | env: 9 | global: 10 | - DBUS_SESSION_BUS_ADDRESS=/dev/null 11 | - DISPLAY=:99.0 12 | - CHROME_BIN=chromium-browser 13 | before_script: 14 | - sh -e /etc/init.d/xvfb start 15 | install: 16 | - npm install 17 | script: 18 | - npm run lint 19 | - npm run test-once 20 | - npm run e2e 21 | -------------------------------------------------------------------------------- /Chapter 04/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## Angular Documentation QuickStart Changelog 2 | Upgraders: for a fresh start, consider running these commands 3 | * `git clean -xdf` 4 | * `npm install` 5 | 6 | 7 | # 0.2.17 (2016-11-16) 8 | * Conform to updated QuickStart advice 9 | * removed docker everywhere (was nice but not necessary) 10 | * removed wallaby 11 | * shrink styles.css 12 | * refine tsconfig.json 13 | * `AppComponent` uses interpolation 14 | 15 | 16 | # 0.2.16 (2016-11-14) 17 | * Update to Angular 2.2.0 18 | 19 | 20 | # 0.2.15 (2016-10-29) 21 | * Revert to Jasmine 2.4.1 because bug in 2.5.x (see [jasmine issue #1231](https://github.com/jasmine/jasmine/issues/1231)) 22 | 23 | 24 | # 0.2.14 (2016-10-29) 25 | * Remove bootstrap.css install 26 | * Angular v2.1.2 27 | 28 | 29 | # 0.2.13 (2016-10-20) 30 | * Protractor 4 31 | * Move from `typings` to `@types`. See `tsconfig.json` changes. 32 | * Angular v2.1.1 33 | 34 | 35 | # 0.2.12 (2016-10-06) 36 | * Angular v2.1.0 37 | 38 | 39 | # 0.2.11 (2016-10-06) 40 | * Angular v2.0.2 41 | * License is MIT 42 | * Current testing configuration 43 | * No code changes 44 | 45 | 46 | # 0.2.10 (2016-09-19) 47 | * All "Angular 2" references become just "Angular" 48 | * No code changes 49 | 50 | 51 | # 0.2.9 (2016-09-14) 52 | * Angular 2.0.0 version 53 | * Update to Typescript 2.0.2 54 | * Fix e2e test missing dir 55 | 56 | 57 | # 0.2.8 (2016-09-01) 58 | * remove @angular test libraries from system.js (now in shim) 59 | * update test related files 60 | * wallaby doesn't completely work. Researching. 61 | 62 | 63 | # 0.2.7 (2016-08-31) 64 | * Angular 2 RC6 version 65 | * Updated new forms, router, angular2-in-memory-web-api, karma, core-js, rxjs and zone.js packages 66 | * Removed router-deprecated package 67 | * Updated karma.conf.js and systemjs.config.js 68 | 69 | 70 | # 0.2.6 (2016-08-09) 71 | * Angular 2 RC5 version 72 | * Updated new forms, router and angular2-in-memory-web-api 73 | 74 | 75 | # 0.2.5 (2016-06-30) 76 | * Angular 2 RC4 version 77 | * Updated new forms and router 78 | 79 | 80 | # 0.2.4 (2016-06-21) 81 | * Angular 2 RC3 version 82 | * Add new forms and router 83 | * Add support for TS e2e tests 84 | 85 | 86 | # 0.2.3 (2016-06-15) 87 | * Angular 2 RC2 version 88 | 89 | 90 | # 0.2.2 (2016-05-21) 91 | * Update to Typings 1.x 92 | 93 | 94 | # 0.2.1 (2016-05-03) 95 | * Angular 2 RC01 version 96 | 97 | 98 | # 0.2.0 (2016-05-02) 99 | * Angular 2 RC0 version 100 | 101 | 102 | # 0.1.17 (2016-04-29) 103 | * update packages 104 | * Angular 2 beta 17 105 | * RxJS 5.0.0-beta.6 106 | * a2-in-memory-web-api 0.1.17 107 | 108 | 109 | # 0.1.16 (2016-04-26) 110 | * update packages 111 | * Angular 2 beta 16 112 | * a2-in-memory-web-api 0.1.6 113 | * protractor 3.3.0 114 | * typings 0.8.1 115 | * zone.js 0.6.12 116 | 117 | * added favicon.ico 118 | 119 | * testing 120 | - updated wallaby.js and karma.conf.js 121 | - updated app.component.spec.ts 122 | 123 | 124 | 125 | # 0.1.15 (2016-04-13) 126 | * Add testing support 127 | * npm scripts 128 | * karma/jasmine 129 | * protractor 130 | 131 | * update packages 132 | * Angular 2 beta 15 133 | * lite-server 2.2.0 134 | * systemjs 0.19.26 135 | * typescript 1.8.10 136 | * typings 0.7.12 137 | 138 | * add run packages 139 | * a2-in-memory-web-api 140 | 141 | * add testing dev-dependency packages 142 | * canonical-path: 0.0.2, 143 | * http-server: ^0.9.0, 144 | * jasmine-core: ~2.4.1, 145 | * karma: ^0.13.22, 146 | * karma-chrome-launcher: ^0.2.3, 147 | * karma-cli: ^0.1.2, 148 | * karma-htmlfile-reporter: ^0.2.2, 149 | * karma-jasmine: ^0.3.8, 150 | * protractor: ^3.2.2, 151 | * rimraf: ^2.5.2 152 | 153 | 154 | # 0.1.14 (2016-04-07) 155 | * update packages 156 | * Angular 2 beta 14 157 | * lite-server 2.2.0 158 | * typings 0.7.12 159 | 160 | 161 | # 0.1.13 (2016-03-31) 162 | * update packages 163 | * Angular 2 beta 13 164 | 165 | 166 | # 0.1.12 (2016-03-23) 167 | * update packages 168 | * Angular 2 beta 12 169 | * zones 0.6.6 170 | * remove es6-promise because no longer needed. 171 | 172 | 173 | # 0.1.11 (2016-03-18) 174 | * update packages 175 | * Angular 2 beta 11 176 | * zones 0.6.4 177 | * typescript 1.8.9 178 | * typings 0.7.9 179 | -------------------------------------------------------------------------------- /Chapter 04/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2014-2016 Google, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Chapter 04/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { AppComponent } from './app.component'; 2 | 3 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 4 | 5 | describe('AppComponent', function () { 6 | let comp: AppComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ AppComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(AppComponent); 18 | comp = fixture.componentInstance; 19 | }); 20 | 21 | it('Should define a list object', () => { 22 | expect(comp.items).toBeDefined(); 23 | }); 24 | 25 | it('Should have 3 items in list', () => { 26 | expect(comp.items.length).toBe(3); 27 | }); 28 | 29 | it('List items should be as expected', () => { 30 | expect(comp.items).toEqual(['test','execute','refactor']); 31 | }); 32 | 33 | describe('Testing add method', () => { 34 | 35 | beforeEach(() => { 36 | comp.add('new-item'); 37 | }); 38 | 39 | it('Should have 4 items in list', () => { 40 | expect(comp.items.length).toBe(4); 41 | }); 42 | 43 | it('Should add a new item at the end of list', () => { 44 | var lastIndexOfList = comp.items.length - 1; 45 | expect(comp.items[lastIndexOfList]).toEqual('new-item'); 46 | }); 47 | }); 48 | 49 | }); 50 | -------------------------------------------------------------------------------- /Chapter 04/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'my-app', 5 | template: `

MY Items

  • {{ item }}
` 6 | }) 7 | export class AppComponent { 8 | items:Array; 9 | 10 | constructor() { 11 | this.items = ['test','execute','refactor']; 12 | } 13 | 14 | add(item) { 15 | this.items.push(item); 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /Chapter 04/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | 4 | import { AppComponent } from './app.component'; 5 | 6 | @NgModule({ 7 | imports: [ BrowserModule ], 8 | declarations: [ AppComponent ], 9 | bootstrap: [ AppComponent ] 10 | }) 11 | export class AppModule { } 12 | -------------------------------------------------------------------------------- /Chapter 04/app/main.ts: -------------------------------------------------------------------------------- 1 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 2 | 3 | import { AppModule } from './app.module'; 4 | 5 | platformBrowserDynamic().bootstrapModule(AppModule); 6 | -------------------------------------------------------------------------------- /Chapter 04/e2e/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { browser, element, by } from 'protractor'; 2 | 3 | describe('AppComponent Tests', () => { 4 | 5 | var todoListItems = element.all(by.css('li')); 6 | 7 | beforeEach(() => { 8 | browser.get('/'); 9 | }); 10 | 11 | it('Browser should have a defined title', () => { 12 | expect(browser.getTitle()).toEqual('Angular Protractor'); 13 | }); 14 | 15 | it('Should get the number of items as defined in item object', () => { 16 | expect(todoListItems.count()).toBe(3); 17 | }); 18 | 19 | it('Should get the first item text as defined', () => { 20 | expect(todoListItems.first().getText()).toEqual('test'); 21 | }); 22 | 23 | it('Should get the last item text as defined', () => { 24 | expect(todoListItems.last().getText()).toEqual('refactor'); 25 | }); 26 | 27 | }); 28 | -------------------------------------------------------------------------------- /Chapter 04/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Angular-Test-Driven-Development-Second-Edition/306153dc7400dd7c063d3494d17d5d14e3c1c41a/Chapter 04/favicon.ico -------------------------------------------------------------------------------- /Chapter 04/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Angular Protractor 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 21 | 22 | 23 | Loading AppComponent content here ... 24 | 25 | 26 | -------------------------------------------------------------------------------- /Chapter 04/karma-test-shim.js: -------------------------------------------------------------------------------- 1 | // #docregion 2 | // /*global jasmine, __karma__, window*/ 3 | Error.stackTraceLimit = 0; // "No stacktrace"" is usually best for app testing. 4 | 5 | // Uncomment to get full stacktrace output. Sometimes helpful, usually not. 6 | // Error.stackTraceLimit = Infinity; // 7 | 8 | jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000; 9 | 10 | var builtPath = '/base/app/'; 11 | 12 | __karma__.loaded = function () { }; 13 | 14 | function isJsFile(path) { 15 | return path.slice(-3) == '.js'; 16 | } 17 | 18 | function isSpecFile(path) { 19 | return /\.spec\.(.*\.)?js$/.test(path); 20 | } 21 | 22 | function isBuiltFile(path) { 23 | return isJsFile(path) && (path.substr(0, builtPath.length) == builtPath); 24 | } 25 | 26 | var allSpecFiles = Object.keys(window.__karma__.files) 27 | .filter(isSpecFile) 28 | .filter(isBuiltFile); 29 | 30 | System.config({ 31 | baseURL: 'base', 32 | // Extend usual application package list with test folder 33 | packages: { 'testing': { main: 'index.js', defaultExtension: 'js' } }, 34 | 35 | // Assume npm: is set in `paths` in systemjs.config 36 | // Map the angular testing umd bundles 37 | map: { 38 | '@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js', 39 | '@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js', 40 | '@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js', 41 | '@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js', 42 | '@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js', 43 | '@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js', 44 | '@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js', 45 | '@angular/forms/testing': 'npm:@angular/forms/bundles/forms-testing.umd.js', 46 | }, 47 | }); 48 | 49 | System.import('systemjs.config.js') 50 | .then(importSystemJsExtras) 51 | .then(initTestBed) 52 | .then(initTesting); 53 | 54 | /** Optional SystemJS configuration extras. Keep going w/o it */ 55 | function importSystemJsExtras(){ 56 | return System.import('systemjs.config.extras.js') 57 | .catch(function(reason) { 58 | console.log( 59 | 'Warning: System.import could not load the optional "systemjs.config.extras.js". Did you omit it by accident? Continuing without it.' 60 | ); 61 | console.log(reason); 62 | }); 63 | } 64 | 65 | function initTestBed(){ 66 | return Promise.all([ 67 | System.import('@angular/core/testing'), 68 | System.import('@angular/platform-browser-dynamic/testing') 69 | ]) 70 | 71 | .then(function (providers) { 72 | var coreTesting = providers[0]; 73 | var browserTesting = providers[1]; 74 | 75 | coreTesting.TestBed.initTestEnvironment( 76 | browserTesting.BrowserDynamicTestingModule, 77 | browserTesting.platformBrowserDynamicTesting()); 78 | }) 79 | } 80 | 81 | // Import all spec files and start karma 82 | function initTesting () { 83 | return Promise.all( 84 | allSpecFiles.map(function (moduleName) { 85 | return System.import(moduleName); 86 | }) 87 | ) 88 | .then(__karma__.start, __karma__.error); 89 | } 90 | -------------------------------------------------------------------------------- /Chapter 04/karma.conf.js: -------------------------------------------------------------------------------- 1 | // #docregion 2 | module.exports = function(config) { 3 | 4 | config.set({ 5 | basePath: '', 6 | frameworks: ['jasmine'], 7 | plugins: [ 8 | require('karma-jasmine'), 9 | require('karma-chrome-launcher') 10 | ], 11 | 12 | files: [ 13 | // System.js for module loading 14 | 'node_modules/systemjs/dist/system.src.js', 15 | 16 | // Polyfills 17 | 'node_modules/core-js/client/shim.js', 18 | 'node_modules/reflect-metadata/Reflect.js', 19 | 20 | // zone.js 21 | 'node_modules/zone.js/dist/zone.js', 22 | 'node_modules/zone.js/dist/long-stack-trace-zone.js', 23 | 'node_modules/zone.js/dist/proxy.js', 24 | 'node_modules/zone.js/dist/sync-test.js', 25 | 'node_modules/zone.js/dist/jasmine-patch.js', 26 | 'node_modules/zone.js/dist/async-test.js', 27 | 'node_modules/zone.js/dist/fake-async-test.js', 28 | 29 | // RxJs 30 | { pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false }, 31 | { pattern: 'node_modules/rxjs/**/*.js.map', included: false, watched: false }, 32 | 33 | // Paths loaded via module imports: 34 | // Angular itself 35 | { pattern: 'node_modules/@angular/**/*.js', included: false, watched: false }, 36 | { pattern: 'node_modules/@angular/**/*.js.map', included: false, watched: false }, 37 | 38 | { pattern: 'systemjs.config.js', included: false, watched: false }, 39 | { pattern: 'systemjs.config.extras.js', included: false, watched: false }, 40 | 'karma-test-shim.js', 41 | 42 | { pattern: 'app/**/*.js', included: false, watched: true } 43 | ], 44 | 45 | port: 9876, 46 | colors: true, 47 | autoWatch: true, 48 | browsers: ['Chrome'], 49 | singleRun: false 50 | }) 51 | } 52 | -------------------------------------------------------------------------------- /Chapter 04/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-TDD-chapter-4", 3 | "version": "1.0.0", 4 | "description": "QuickStart package.json from the documentation, supplemented with testing support", 5 | "scripts": { 6 | "start": "tsc && concurrently \"tsc -w\" \"lite-server\" ", 7 | "e2e": "tsc && concurrently \"http-server -s\" \"protractor protractor.config.js\" --kill-others --success first", 8 | "lint": "tslint ./app/**/*.ts -t verbose", 9 | "lite": "lite-server", 10 | "pree2e": "webdriver-manager update", 11 | "test": "tsc && concurrently \"tsc -w\" \"karma start karma.conf.js\"", 12 | "test-once": "tsc && karma start karma.conf.js --single-run", 13 | "tsc": "tsc", 14 | "tsc:w": "tsc -w" 15 | }, 16 | "keywords": [], 17 | "author": "", 18 | "license": "MIT", 19 | "dependencies": { 20 | "@angular/common": "~2.2.0", 21 | "@angular/compiler": "~2.2.0", 22 | "@angular/core": "~2.2.0", 23 | "@angular/forms": "~2.2.0", 24 | "@angular/http": "~2.2.0", 25 | "@angular/platform-browser": "~2.2.0", 26 | "@angular/platform-browser-dynamic": "~2.2.0", 27 | "@angular/router": "~3.2.0", 28 | 29 | "angular-in-memory-web-api": "~0.1.15", 30 | "systemjs": "0.19.40", 31 | "core-js": "^2.4.1", 32 | "reflect-metadata": "^0.1.8", 33 | "rxjs": "5.0.0-beta.12", 34 | "zone.js": "^0.6.26" 35 | }, 36 | "devDependencies": { 37 | "concurrently": "^3.1.0", 38 | "lite-server": "^2.2.2", 39 | "typescript": "^2.0.10", 40 | 41 | "canonical-path": "0.0.2", 42 | "http-server": "^0.9.0", 43 | "tslint": "^3.15.1", 44 | "lodash": "^4.16.4", 45 | "jasmine-core": "~2.4.1", 46 | "karma": "^1.3.0", 47 | "karma-chrome-launcher": "^2.0.0", 48 | "karma-cli": "^1.0.1", 49 | "karma-htmlfile-reporter": "^0.3.4", 50 | "karma-jasmine": "^1.0.2", 51 | "karma-jasmine-html-reporter": "^0.2.2", 52 | "protractor": "4.0.14", 53 | "webdriver-manager": "10.2.5", 54 | "rimraf": "^2.5.4", 55 | 56 | "@types/node": "^6.0.46", 57 | "@types/jasmine": "^2.5.36", 58 | "@types/selenium-webdriver": "^2.53.33" 59 | }, 60 | "repository": {} 61 | } 62 | -------------------------------------------------------------------------------- /Chapter 04/protractor.config.js: -------------------------------------------------------------------------------- 1 | // FIRST TIME ONLY- run: 2 | // ./node_modules/.bin/webdriver-manager update 3 | // 4 | // Try: `npm run webdriver:update` 5 | // 6 | // AND THEN EVERYTIME ... 7 | // 1. Compile with `tsc` 8 | // 2. Make sure the test server (e.g., http-server: localhost:8080) is running. 9 | // 3. ./node_modules/.bin/protractor protractor.config.js 10 | // 11 | // To do all steps, try: `npm run e2e` 12 | 13 | var fs = require('fs'); 14 | var path = require('canonical-path'); 15 | var _ = require('lodash'); 16 | 17 | 18 | exports.config = { 19 | directConnect: true, 20 | 21 | // Capabilities to be passed to the webdriver instance. 22 | capabilities: { 23 | 'browserName': 'chrome' 24 | }, 25 | 26 | // Framework to use. Jasmine is recommended. 27 | framework: 'jasmine', 28 | 29 | // Spec patterns are relative to this config file 30 | specs: ['**/*e2e-spec.js' ], 31 | 32 | 33 | // For angular tests 34 | useAllAngular2AppRoots: true, 35 | 36 | // Base URL for application server 37 | baseUrl: 'http://localhost:8080', 38 | 39 | 40 | jasmineNodeOpts: { 41 | // defaultTimeoutInterval: 60000, 42 | defaultTimeoutInterval: 10000, 43 | showTiming: true, 44 | print: function() {} 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /Chapter 04/styles.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | color: #369; 3 | font-family: Arial, Helvetica, sans-serif; 4 | font-size: 250%; 5 | } 6 | -------------------------------------------------------------------------------- /Chapter 04/systemjs.config.extras.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Add barrels and stuff 3 | * Adjust as necessary for your application needs. 4 | */ 5 | // (function (global) { 6 | // System.config({ 7 | // packages: { 8 | // // add packages here 9 | // } 10 | // }); 11 | // })(this); 12 | -------------------------------------------------------------------------------- /Chapter 04/systemjs.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * System configuration for Angular samples 3 | * Adjust as necessary for your application needs. 4 | */ 5 | (function (global) { 6 | System.config({ 7 | paths: { 8 | // paths serve as alias 9 | 'npm:': 'node_modules/' 10 | }, 11 | // map tells the System loader where to look for things 12 | map: { 13 | // our app is within the app folder 14 | app: 'app', 15 | 16 | // angular bundles 17 | '@angular/core': 'npm:@angular/core/bundles/core.umd.js', 18 | '@angular/common': 'npm:@angular/common/bundles/common.umd.js', 19 | '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js', 20 | '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js', 21 | '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js', 22 | '@angular/http': 'npm:@angular/http/bundles/http.umd.js', 23 | '@angular/router': 'npm:@angular/router/bundles/router.umd.js', 24 | '@angular/router/upgrade': 'npm:@angular/router/bundles/router-upgrade.umd.js', 25 | '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js', 26 | '@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.js', 27 | '@angular/upgrade/static': 'npm:@angular/upgrade/bundles/upgrade-static.umd.js', 28 | 29 | // other libraries 30 | 'rxjs': 'npm:rxjs', 31 | 'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js' 32 | }, 33 | // packages tells the System loader how to load when no filename and/or no extension 34 | packages: { 35 | app: { 36 | main: './main.js', 37 | defaultExtension: 'js' 38 | }, 39 | rxjs: { 40 | defaultExtension: 'js' 41 | } 42 | } 43 | }); 44 | })(this); 45 | -------------------------------------------------------------------------------- /Chapter 04/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "emitDecoratorMetadata": true, 8 | "experimentalDecorators": true, 9 | "lib": [ "es2015", "dom" ], 10 | "noImplicitAny": false, 11 | "suppressImplicitAnyIndexErrors": true 12 | }, 13 | "exclude": [ 14 | "node_modules/*", 15 | "**/*-aot.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /Chapter 04/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "class-name": true, 4 | "comment-format": [ 5 | true, 6 | "check-space" 7 | ], 8 | "curly": true, 9 | "eofline": true, 10 | "forin": true, 11 | "indent": [ 12 | true, 13 | "spaces" 14 | ], 15 | "label-position": true, 16 | "label-undefined": true, 17 | "max-line-length": [ 18 | true, 19 | 140 20 | ], 21 | "member-access": false, 22 | "member-ordering": [ 23 | true, 24 | "static-before-instance", 25 | "variables-before-functions" 26 | ], 27 | "no-arg": true, 28 | "no-bitwise": true, 29 | "no-console": [ 30 | true, 31 | "debug", 32 | "info", 33 | "time", 34 | "timeEnd", 35 | "trace" 36 | ], 37 | "no-construct": true, 38 | "no-debugger": true, 39 | "no-duplicate-key": true, 40 | "no-duplicate-variable": true, 41 | "no-empty": false, 42 | "no-eval": true, 43 | "no-inferrable-types": true, 44 | "no-shadowed-variable": true, 45 | "no-string-literal": false, 46 | "no-switch-case-fall-through": true, 47 | "no-trailing-whitespace": true, 48 | "no-unused-expression": true, 49 | "no-unused-variable": true, 50 | "no-unreachable": true, 51 | "no-use-before-declare": true, 52 | "no-var-keyword": true, 53 | "object-literal-sort-keys": false, 54 | "one-line": [ 55 | true, 56 | "check-open-brace", 57 | "check-catch", 58 | "check-else", 59 | "check-whitespace" 60 | ], 61 | "quotemark": [ 62 | true, 63 | "single" 64 | ], 65 | "radix": true, 66 | "semicolon": [ 67 | "always" 68 | ], 69 | "triple-equals": [ 70 | true, 71 | "allow-null-check" 72 | ], 73 | "typedef-whitespace": [ 74 | true, 75 | { 76 | "call-signature": "nospace", 77 | "index-signature": "nospace", 78 | "parameter": "nospace", 79 | "property-declaration": "nospace", 80 | "variable-declaration": "nospace" 81 | } 82 | ], 83 | "variable-name": false, 84 | "whitespace": [ 85 | true, 86 | "check-branch", 87 | "check-decl", 88 | "check-operator", 89 | "check-separator", 90 | "check-type" 91 | ] 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Chapter 05/.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | 12 | [*.md] 13 | max_line_length = 0 14 | trim_trailing_whitespace = false 15 | 16 | # Indentation override 17 | #[lib/**.js] 18 | #[{package.json,.travis.yml}] 19 | #[**/**.js] 20 | -------------------------------------------------------------------------------- /Chapter 05/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | node_modules 3 | jspm_packages 4 | npm-debug.* 5 | link-checker-results.txt 6 | app/**/*.js 7 | *.js.map 8 | debug/**/*.e2e.js 9 | debug/**/*.js.map 10 | e2e/**/*.js 11 | e2e/**/*.js.map 12 | _test-output 13 | _temp 14 | -------------------------------------------------------------------------------- /Chapter 05/.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | sudo: required 3 | language: node_js 4 | node_js: 5 | - "5" 6 | os: 7 | - linux 8 | env: 9 | global: 10 | - DBUS_SESSION_BUS_ADDRESS=/dev/null 11 | - DISPLAY=:99.0 12 | - CHROME_BIN=chromium-browser 13 | before_script: 14 | - sh -e /etc/init.d/xvfb start 15 | install: 16 | - npm install 17 | script: 18 | - npm run lint 19 | - npm run test-once 20 | - npm run e2e 21 | -------------------------------------------------------------------------------- /Chapter 05/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## Angular Documentation QuickStart Changelog 2 | Upgraders: for a fresh start, consider running these commands 3 | * `git clean -xdf` 4 | * `npm install` 5 | 6 | 7 | # 0.2.17 (2016-11-16) 8 | * Conform to updated QuickStart advice 9 | * removed docker everywhere (was nice but not necessary) 10 | * removed wallaby 11 | * shrink styles.css 12 | * refine tsconfig.json 13 | * `AppComponent` uses interpolation 14 | 15 | 16 | # 0.2.16 (2016-11-14) 17 | * Update to Angular 2.2.0 18 | 19 | 20 | # 0.2.15 (2016-10-29) 21 | * Revert to Jasmine 2.4.1 because bug in 2.5.x (see [jasmine issue #1231](https://github.com/jasmine/jasmine/issues/1231)) 22 | 23 | 24 | # 0.2.14 (2016-10-29) 25 | * Remove bootstrap.css install 26 | * Angular v2.1.2 27 | 28 | 29 | # 0.2.13 (2016-10-20) 30 | * Protractor 4 31 | * Move from `typings` to `@types`. See `tsconfig.json` changes. 32 | * Angular v2.1.1 33 | 34 | 35 | # 0.2.12 (2016-10-06) 36 | * Angular v2.1.0 37 | 38 | 39 | # 0.2.11 (2016-10-06) 40 | * Angular v2.0.2 41 | * License is MIT 42 | * Current testing configuration 43 | * No code changes 44 | 45 | 46 | # 0.2.10 (2016-09-19) 47 | * All "Angular 2" references become just "Angular" 48 | * No code changes 49 | 50 | 51 | # 0.2.9 (2016-09-14) 52 | * Angular 2.0.0 version 53 | * Update to Typescript 2.0.2 54 | * Fix e2e test missing dir 55 | 56 | 57 | # 0.2.8 (2016-09-01) 58 | * remove @angular test libraries from system.js (now in shim) 59 | * update test related files 60 | * wallaby doesn't completely work. Researching. 61 | 62 | 63 | # 0.2.7 (2016-08-31) 64 | * Angular 2 RC6 version 65 | * Updated new forms, router, angular2-in-memory-web-api, karma, core-js, rxjs and zone.js packages 66 | * Removed router-deprecated package 67 | * Updated karma.conf.js and systemjs.config.js 68 | 69 | 70 | # 0.2.6 (2016-08-09) 71 | * Angular 2 RC5 version 72 | * Updated new forms, router and angular2-in-memory-web-api 73 | 74 | 75 | # 0.2.5 (2016-06-30) 76 | * Angular 2 RC4 version 77 | * Updated new forms and router 78 | 79 | 80 | # 0.2.4 (2016-06-21) 81 | * Angular 2 RC3 version 82 | * Add new forms and router 83 | * Add support for TS e2e tests 84 | 85 | 86 | # 0.2.3 (2016-06-15) 87 | * Angular 2 RC2 version 88 | 89 | 90 | # 0.2.2 (2016-05-21) 91 | * Update to Typings 1.x 92 | 93 | 94 | # 0.2.1 (2016-05-03) 95 | * Angular 2 RC01 version 96 | 97 | 98 | # 0.2.0 (2016-05-02) 99 | * Angular 2 RC0 version 100 | 101 | 102 | # 0.1.17 (2016-04-29) 103 | * update packages 104 | * Angular 2 beta 17 105 | * RxJS 5.0.0-beta.6 106 | * a2-in-memory-web-api 0.1.17 107 | 108 | 109 | # 0.1.16 (2016-04-26) 110 | * update packages 111 | * Angular 2 beta 16 112 | * a2-in-memory-web-api 0.1.6 113 | * protractor 3.3.0 114 | * typings 0.8.1 115 | * zone.js 0.6.12 116 | 117 | * added favicon.ico 118 | 119 | * testing 120 | - updated wallaby.js and karma.conf.js 121 | - updated app.component.spec.ts 122 | 123 | 124 | 125 | # 0.1.15 (2016-04-13) 126 | * Add testing support 127 | * npm scripts 128 | * karma/jasmine 129 | * protractor 130 | 131 | * update packages 132 | * Angular 2 beta 15 133 | * lite-server 2.2.0 134 | * systemjs 0.19.26 135 | * typescript 1.8.10 136 | * typings 0.7.12 137 | 138 | * add run packages 139 | * a2-in-memory-web-api 140 | 141 | * add testing dev-dependency packages 142 | * canonical-path: 0.0.2, 143 | * http-server: ^0.9.0, 144 | * jasmine-core: ~2.4.1, 145 | * karma: ^0.13.22, 146 | * karma-chrome-launcher: ^0.2.3, 147 | * karma-cli: ^0.1.2, 148 | * karma-htmlfile-reporter: ^0.2.2, 149 | * karma-jasmine: ^0.3.8, 150 | * protractor: ^3.2.2, 151 | * rimraf: ^2.5.2 152 | 153 | 154 | # 0.1.14 (2016-04-07) 155 | * update packages 156 | * Angular 2 beta 14 157 | * lite-server 2.2.0 158 | * typings 0.7.12 159 | 160 | 161 | # 0.1.13 (2016-03-31) 162 | * update packages 163 | * Angular 2 beta 13 164 | 165 | 166 | # 0.1.12 (2016-03-23) 167 | * update packages 168 | * Angular 2 beta 12 169 | * zones 0.6.6 170 | * remove es6-promise because no longer needed. 171 | 172 | 173 | # 0.1.11 (2016-03-18) 174 | * update packages 175 | * Angular 2 beta 11 176 | * zones 0.6.4 177 | * typescript 1.8.9 178 | * typings 0.7.9 179 | -------------------------------------------------------------------------------- /Chapter 05/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2014-2016 Google, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Chapter 05/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { AppComponent } from './app.component'; 2 | 3 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 4 | 5 | describe('AppComponent', function () { 6 | let comp: AppComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ AppComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(AppComponent); 18 | comp = fixture.componentInstance; 19 | }); 20 | 21 | it('Should define a list object', () => { 22 | expect(comp.items).toBeDefined(); 23 | }); 24 | 25 | it('Should have 3 items in list', () => { 26 | expect(comp.items.length).toBe(3); 27 | }); 28 | 29 | it('List items should be as expected', () => { 30 | expect(comp.items).toEqual(['test','execute','refactor']); 31 | }); 32 | 33 | describe('Testing add method', () => { 34 | 35 | beforeEach(() => { 36 | comp.add('new-item'); 37 | }); 38 | 39 | it('Should have 4 items in list', () => { 40 | expect(comp.items.length).toBe(4); 41 | }); 42 | 43 | it('Should add a new item at the end of list', () => { 44 | var lastIndexOfList = comp.items.length - 1; 45 | expect(comp.items[lastIndexOfList]).toEqual('new-item'); 46 | }); 47 | }); 48 | 49 | }); 50 | -------------------------------------------------------------------------------- /Chapter 05/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'my-app', 5 | template: `

MY Items

  • {{ item }}
` 6 | }) 7 | export class AppComponent { 8 | items:Array; 9 | 10 | constructor() { 11 | this.items = ['test','execute','refactor']; 12 | } 13 | 14 | add(item) { 15 | this.items.push(item); 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /Chapter 05/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | 4 | import { AppComponent } from './app.component'; 5 | 6 | @NgModule({ 7 | imports: [ BrowserModule ], 8 | declarations: [ AppComponent ], 9 | bootstrap: [ AppComponent ] 10 | }) 11 | export class AppModule { } 12 | -------------------------------------------------------------------------------- /Chapter 05/app/main.ts: -------------------------------------------------------------------------------- 1 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 2 | 3 | import { AppModule } from './app.module'; 4 | 5 | platformBrowserDynamic().bootstrapModule(AppModule); 6 | -------------------------------------------------------------------------------- /Chapter 05/debug/app.debug.e2e.ts: -------------------------------------------------------------------------------- 1 | import { browser, element, by } from 'protractor'; 2 | 3 | describe('AppComponent Tests', () => { 4 | 5 | beforeEach(() => { 6 | browser.get('/'); 7 | }); 8 | 9 | it('Test spec for debug and play', () => { 10 | browser.pause(); 11 | //browser.debugger(); 12 | 13 | // There is not element with the id=“my_id”, so this will fail the test 14 | expect(element(by.id('my_id')).getText()).toEqual('my text') 15 | }); 16 | 17 | }); 18 | -------------------------------------------------------------------------------- /Chapter 05/debug/debugConf.js: -------------------------------------------------------------------------------- 1 | 2 | var fs = require('fs'); 3 | var path = require('canonical-path'); 4 | var _ = require('lodash'); 5 | 6 | 7 | exports.config = { 8 | directConnect: true, 9 | 10 | // Capabilities to be passed to the webdriver instance. 11 | capabilities: { 12 | 'browserName': 'chrome' 13 | }, 14 | 15 | // Framework to use. Jasmine is recommended. 16 | framework: 'jasmine', 17 | 18 | // Spec patterns are relative to this config file 19 | specs: [ 20 | 'app.debug.e2e.js' 21 | ], 22 | 23 | 24 | // For angular tests 25 | useAllAngular2AppRoots: true, 26 | 27 | // Base URL for application server 28 | baseUrl: 'http://localhost:3000/', 29 | 30 | 31 | jasmineNodeOpts: { 32 | // defaultTimeoutInterval: 60000, 33 | defaultTimeoutInterval: 300000, 34 | showTiming: true, 35 | print: function() {} 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /Chapter 05/e2e/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { browser, element, by } from 'protractor'; 2 | 3 | describe('AppComponent Tests', () => { 4 | 5 | var todoListItems = element.all(by.css('li')); 6 | 7 | beforeEach(() => { 8 | browser.get('/'); 9 | }); 10 | 11 | it('Browser should have a defined title', () => { 12 | expect(browser.getTitle()).toEqual('Angular Protractor'); 13 | }); 14 | 15 | it('Should get the number of items as defined in item object', () => { 16 | expect(todoListItems.count()).toBe(3); 17 | }); 18 | 19 | it('Should get the first item text as defined', () => { 20 | expect(todoListItems.first().getText()).toEqual('test'); 21 | }); 22 | 23 | it('Should get the last item text as defined', () => { 24 | expect(todoListItems.last().getText()).toEqual('refactor'); 25 | }); 26 | 27 | }); 28 | -------------------------------------------------------------------------------- /Chapter 05/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Angular-Test-Driven-Development-Second-Edition/306153dc7400dd7c063d3494d17d5d14e3c1c41a/Chapter 05/favicon.ico -------------------------------------------------------------------------------- /Chapter 05/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Angular Protractor 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 21 | 22 | 23 | Loading AppComponent content here ... 24 | 25 | 26 | -------------------------------------------------------------------------------- /Chapter 05/karma-test-shim.js: -------------------------------------------------------------------------------- 1 | // #docregion 2 | // /*global jasmine, __karma__, window*/ 3 | Error.stackTraceLimit = 0; // "No stacktrace"" is usually best for app testing. 4 | 5 | // Uncomment to get full stacktrace output. Sometimes helpful, usually not. 6 | // Error.stackTraceLimit = Infinity; // 7 | 8 | jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000; 9 | 10 | var builtPath = '/base/app/'; 11 | 12 | __karma__.loaded = function () { }; 13 | 14 | function isJsFile(path) { 15 | return path.slice(-3) == '.js'; 16 | } 17 | 18 | function isSpecFile(path) { 19 | return /\.spec\.(.*\.)?js$/.test(path); 20 | } 21 | 22 | function isBuiltFile(path) { 23 | return isJsFile(path) && (path.substr(0, builtPath.length) == builtPath); 24 | } 25 | 26 | var allSpecFiles = Object.keys(window.__karma__.files) 27 | .filter(isSpecFile) 28 | .filter(isBuiltFile); 29 | 30 | System.config({ 31 | baseURL: 'base', 32 | // Extend usual application package list with test folder 33 | packages: { 'testing': { main: 'index.js', defaultExtension: 'js' } }, 34 | 35 | // Assume npm: is set in `paths` in systemjs.config 36 | // Map the angular testing umd bundles 37 | map: { 38 | '@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js', 39 | '@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js', 40 | '@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js', 41 | '@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js', 42 | '@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js', 43 | '@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js', 44 | '@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js', 45 | '@angular/forms/testing': 'npm:@angular/forms/bundles/forms-testing.umd.js', 46 | }, 47 | }); 48 | 49 | System.import('systemjs.config.js') 50 | .then(importSystemJsExtras) 51 | .then(initTestBed) 52 | .then(initTesting); 53 | 54 | /** Optional SystemJS configuration extras. Keep going w/o it */ 55 | function importSystemJsExtras(){ 56 | return System.import('systemjs.config.extras.js') 57 | .catch(function(reason) { 58 | console.log( 59 | 'Warning: System.import could not load the optional "systemjs.config.extras.js". Did you omit it by accident? Continuing without it.' 60 | ); 61 | console.log(reason); 62 | }); 63 | } 64 | 65 | function initTestBed(){ 66 | return Promise.all([ 67 | System.import('@angular/core/testing'), 68 | System.import('@angular/platform-browser-dynamic/testing') 69 | ]) 70 | 71 | .then(function (providers) { 72 | var coreTesting = providers[0]; 73 | var browserTesting = providers[1]; 74 | 75 | coreTesting.TestBed.initTestEnvironment( 76 | browserTesting.BrowserDynamicTestingModule, 77 | browserTesting.platformBrowserDynamicTesting()); 78 | }) 79 | } 80 | 81 | // Import all spec files and start karma 82 | function initTesting () { 83 | return Promise.all( 84 | allSpecFiles.map(function (moduleName) { 85 | return System.import(moduleName); 86 | }) 87 | ) 88 | .then(__karma__.start, __karma__.error); 89 | } 90 | -------------------------------------------------------------------------------- /Chapter 05/karma.conf.js: -------------------------------------------------------------------------------- 1 | // #docregion 2 | module.exports = function(config) { 3 | 4 | config.set({ 5 | basePath: '', 6 | frameworks: ['jasmine'], 7 | plugins: [ 8 | require('karma-jasmine'), 9 | require('karma-chrome-launcher') 10 | ], 11 | 12 | files: [ 13 | // System.js for module loading 14 | 'node_modules/systemjs/dist/system.src.js', 15 | 16 | // Polyfills 17 | 'node_modules/core-js/client/shim.js', 18 | 'node_modules/reflect-metadata/Reflect.js', 19 | 20 | // zone.js 21 | 'node_modules/zone.js/dist/zone.js', 22 | 'node_modules/zone.js/dist/long-stack-trace-zone.js', 23 | 'node_modules/zone.js/dist/proxy.js', 24 | 'node_modules/zone.js/dist/sync-test.js', 25 | 'node_modules/zone.js/dist/jasmine-patch.js', 26 | 'node_modules/zone.js/dist/async-test.js', 27 | 'node_modules/zone.js/dist/fake-async-test.js', 28 | 29 | // RxJs 30 | { pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false }, 31 | { pattern: 'node_modules/rxjs/**/*.js.map', included: false, watched: false }, 32 | 33 | // Paths loaded via module imports: 34 | // Angular itself 35 | { pattern: 'node_modules/@angular/**/*.js', included: false, watched: false }, 36 | { pattern: 'node_modules/@angular/**/*.js.map', included: false, watched: false }, 37 | 38 | { pattern: 'systemjs.config.js', included: false, watched: false }, 39 | { pattern: 'systemjs.config.extras.js', included: false, watched: false }, 40 | 'karma-test-shim.js', 41 | 42 | { pattern: 'app/**/*.js', included: false, watched: true } 43 | ], 44 | 45 | port: 9876, 46 | colors: true, 47 | autoWatch: true, 48 | browsers: ['Chrome'], 49 | singleRun: false 50 | }) 51 | } 52 | -------------------------------------------------------------------------------- /Chapter 05/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-TDD-chapter-5", 3 | "version": "1.0.0", 4 | "description": "QuickStart package.json from the documentation, supplemented with testing support", 5 | "scripts": { 6 | "start": "tsc && concurrently \"tsc -w\" \"lite-server\" ", 7 | "e2e": "tsc && concurrently \"http-server -s\" \"protractor protractor.config.js\" --kill-others --success first", 8 | "lint": "tslint ./app/**/*.ts -t verbose", 9 | "lite": "lite-server", 10 | "pree2e": "webdriver-manager update", 11 | "test": "tsc && concurrently \"tsc -w\" \"karma start karma.conf.js\"", 12 | "test-once": "tsc && karma start karma.conf.js --single-run", 13 | "tsc": "tsc", 14 | "tsc:w": "tsc -w" 15 | }, 16 | "keywords": [], 17 | "author": "", 18 | "license": "MIT", 19 | "dependencies": { 20 | "@angular/common": "~2.2.0", 21 | "@angular/compiler": "~2.2.0", 22 | "@angular/core": "~2.2.0", 23 | "@angular/forms": "~2.2.0", 24 | "@angular/http": "~2.2.0", 25 | "@angular/platform-browser": "~2.2.0", 26 | "@angular/platform-browser-dynamic": "~2.2.0", 27 | "@angular/router": "~3.2.0", 28 | 29 | "angular-in-memory-web-api": "~0.1.15", 30 | "systemjs": "0.19.40", 31 | "core-js": "^2.4.1", 32 | "reflect-metadata": "^0.1.8", 33 | "rxjs": "5.0.0-beta.12", 34 | "zone.js": "^0.6.26" 35 | }, 36 | "devDependencies": { 37 | "concurrently": "^3.1.0", 38 | "lite-server": "^2.2.2", 39 | "typescript": "^2.0.10", 40 | 41 | "canonical-path": "0.0.2", 42 | "http-server": "^0.9.0", 43 | "tslint": "^3.15.1", 44 | "lodash": "^4.16.4", 45 | "jasmine-core": "~2.4.1", 46 | "karma": "^1.3.0", 47 | "karma-chrome-launcher": "^2.0.0", 48 | "karma-cli": "^1.0.1", 49 | "karma-htmlfile-reporter": "^0.3.4", 50 | "karma-jasmine": "^1.0.2", 51 | "karma-jasmine-html-reporter": "^0.2.2", 52 | "protractor": "4.0.14", 53 | "webdriver-manager": "10.2.5", 54 | "rimraf": "^2.5.4", 55 | 56 | "@types/node": "^6.0.46", 57 | "@types/jasmine": "^2.5.36", 58 | "@types/selenium-webdriver": "^2.53.33" 59 | }, 60 | "repository": {} 61 | } 62 | -------------------------------------------------------------------------------- /Chapter 05/protractor.config.js: -------------------------------------------------------------------------------- 1 | // FIRST TIME ONLY- run: 2 | // ./node_modules/.bin/webdriver-manager update 3 | // 4 | // Try: `npm run webdriver:update` 5 | // 6 | // AND THEN EVERYTIME ... 7 | // 1. Compile with `tsc` 8 | // 2. Make sure the test server (e.g., http-server: localhost:8080) is running. 9 | // 3. ./node_modules/.bin/protractor protractor.config.js 10 | // 11 | // To do all steps, try: `npm run e2e` 12 | 13 | var fs = require('fs'); 14 | var path = require('canonical-path'); 15 | var _ = require('lodash'); 16 | 17 | 18 | exports.config = { 19 | directConnect: true, 20 | 21 | // Capabilities to be passed to the webdriver instance. 22 | capabilities: { 23 | 'browserName': 'chrome' 24 | }, 25 | 26 | // Framework to use. Jasmine is recommended. 27 | framework: 'jasmine', 28 | 29 | // Spec patterns are relative to this config file 30 | specs: ['**/*e2e-spec.js' ], 31 | 32 | 33 | // For angular tests 34 | useAllAngular2AppRoots: true, 35 | 36 | // Base URL for application server 37 | baseUrl: 'http://localhost:3000/', 38 | 39 | 40 | jasmineNodeOpts: { 41 | // defaultTimeoutInterval: 60000, 42 | defaultTimeoutInterval: 10000, 43 | showTiming: true, 44 | print: function() {} 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /Chapter 05/styles.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | color: #369; 3 | font-family: Arial, Helvetica, sans-serif; 4 | font-size: 250%; 5 | } 6 | -------------------------------------------------------------------------------- /Chapter 05/systemjs.config.extras.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Add barrels and stuff 3 | * Adjust as necessary for your application needs. 4 | */ 5 | // (function (global) { 6 | // System.config({ 7 | // packages: { 8 | // // add packages here 9 | // } 10 | // }); 11 | // })(this); 12 | -------------------------------------------------------------------------------- /Chapter 05/systemjs.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * System configuration for Angular samples 3 | * Adjust as necessary for your application needs. 4 | */ 5 | (function (global) { 6 | System.config({ 7 | paths: { 8 | // paths serve as alias 9 | 'npm:': 'node_modules/' 10 | }, 11 | // map tells the System loader where to look for things 12 | map: { 13 | // our app is within the app folder 14 | app: 'app', 15 | 16 | // angular bundles 17 | '@angular/core': 'npm:@angular/core/bundles/core.umd.js', 18 | '@angular/common': 'npm:@angular/common/bundles/common.umd.js', 19 | '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js', 20 | '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js', 21 | '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js', 22 | '@angular/http': 'npm:@angular/http/bundles/http.umd.js', 23 | '@angular/router': 'npm:@angular/router/bundles/router.umd.js', 24 | '@angular/router/upgrade': 'npm:@angular/router/bundles/router-upgrade.umd.js', 25 | '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js', 26 | '@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.js', 27 | '@angular/upgrade/static': 'npm:@angular/upgrade/bundles/upgrade-static.umd.js', 28 | 29 | // other libraries 30 | 'rxjs': 'npm:rxjs', 31 | 'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js' 32 | }, 33 | // packages tells the System loader how to load when no filename and/or no extension 34 | packages: { 35 | app: { 36 | main: './main.js', 37 | defaultExtension: 'js' 38 | }, 39 | rxjs: { 40 | defaultExtension: 'js' 41 | } 42 | } 43 | }); 44 | })(this); 45 | -------------------------------------------------------------------------------- /Chapter 05/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "emitDecoratorMetadata": true, 8 | "experimentalDecorators": true, 9 | "lib": [ "es2015", "dom" ], 10 | "noImplicitAny": false, 11 | "suppressImplicitAnyIndexErrors": true 12 | }, 13 | "exclude": [ 14 | "node_modules/*", 15 | "**/*-aot.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /Chapter 05/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "class-name": true, 4 | "comment-format": [ 5 | true, 6 | "check-space" 7 | ], 8 | "curly": true, 9 | "eofline": true, 10 | "forin": true, 11 | "indent": [ 12 | true, 13 | "spaces" 14 | ], 15 | "label-position": true, 16 | "label-undefined": true, 17 | "max-line-length": [ 18 | true, 19 | 140 20 | ], 21 | "member-access": false, 22 | "member-ordering": [ 23 | true, 24 | "static-before-instance", 25 | "variables-before-functions" 26 | ], 27 | "no-arg": true, 28 | "no-bitwise": true, 29 | "no-console": [ 30 | true, 31 | "debug", 32 | "info", 33 | "time", 34 | "timeEnd", 35 | "trace" 36 | ], 37 | "no-construct": true, 38 | "no-debugger": true, 39 | "no-duplicate-key": true, 40 | "no-duplicate-variable": true, 41 | "no-empty": false, 42 | "no-eval": true, 43 | "no-inferrable-types": true, 44 | "no-shadowed-variable": true, 45 | "no-string-literal": false, 46 | "no-switch-case-fall-through": true, 47 | "no-trailing-whitespace": true, 48 | "no-unused-expression": true, 49 | "no-unused-variable": true, 50 | "no-unreachable": true, 51 | "no-use-before-declare": true, 52 | "no-var-keyword": true, 53 | "object-literal-sort-keys": false, 54 | "one-line": [ 55 | true, 56 | "check-open-brace", 57 | "check-catch", 58 | "check-else", 59 | "check-whitespace" 60 | ], 61 | "quotemark": [ 62 | true, 63 | "single" 64 | ], 65 | "radix": true, 66 | "semicolon": [ 67 | "always" 68 | ], 69 | "triple-equals": [ 70 | true, 71 | "allow-null-check" 72 | ], 73 | "typedef-whitespace": [ 74 | true, 75 | { 76 | "call-signature": "nospace", 77 | "index-signature": "nospace", 78 | "parameter": "nospace", 79 | "property-declaration": "nospace", 80 | "variable-declaration": "nospace" 81 | } 82 | ], 83 | "variable-name": false, 84 | "whitespace": [ 85 | true, 86 | "check-branch", 87 | "check-decl", 88 | "check-operator", 89 | "check-separator", 90 | "check-type" 91 | ] 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Chapter 06/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /Chapter 06/.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | 12 | [*.md] 13 | max_line_length = 0 14 | trim_trailing_whitespace = false 15 | 16 | # Indentation override 17 | #[lib/**.js] 18 | #[{package.json,.travis.yml}] 19 | #[**/**.js] 20 | -------------------------------------------------------------------------------- /Chapter 06/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .DS_Store 3 | node_modules 4 | jspm_packages 5 | npm-debug.* 6 | link-checker-results.txt 7 | app/**/*.js 8 | *.js.map 9 | spec/e2e/**/*.js 10 | spec/e2e/**/*.js.map 11 | spec/unit/**/*.js 12 | spec/unit/**/*.js.map 13 | _test-output 14 | _temp 15 | -------------------------------------------------------------------------------- /Chapter 06/.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | sudo: required 3 | language: node_js 4 | node_js: 5 | - "5" 6 | os: 7 | - linux 8 | env: 9 | global: 10 | - DBUS_SESSION_BUS_ADDRESS=/dev/null 11 | - DISPLAY=:99.0 12 | - CHROME_BIN=chromium-browser 13 | before_script: 14 | - sh -e /etc/init.d/xvfb start 15 | install: 16 | - npm install 17 | script: 18 | - npm run lint 19 | - npm run test-once 20 | - npm run e2e 21 | -------------------------------------------------------------------------------- /Chapter 06/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## Angular Documentation QuickStart Changelog 2 | Upgraders: to be sure of a fresh start, consider running these commands 3 | * `git clean -xdf` 4 | * `npm install` 5 | * `npm run webdriver:update` 6 | 7 | 8 | # 0.2.16 (2016-11-14) 9 | * Update to Angular 2.2.0 10 | 11 | 12 | # 0.2.15 (2016-10-29) 13 | * Revert to Jasmine 2.4.1 because bug in 2.5.x (see [jasmine issue #1231](https://github.com/jasmine/jasmine/issues/1231)) 14 | 15 | 16 | # 0.2.14 (2016-10-29) 17 | * Remove bootstrap.css install 18 | * Angular v2.1.2 19 | 20 | 21 | # 0.2.13 (2016-10-20) 22 | * Protractor 4 23 | * Move from `typings` to `@types`. See `tsconfig.json` changes. 24 | * Angular v2.1.1 25 | 26 | 27 | # 0.2.12 (2016-10-06) 28 | * Angular v2.1.0 29 | 30 | 31 | # 0.2.11 (2016-10-06) 32 | * Angular v2.0.2 33 | * License is MIT 34 | * Current testing configuration 35 | * No code changes 36 | 37 | 38 | # 0.2.10 (2016-09-19) 39 | * All "Angular 2" references become just "Angular" 40 | * No code changes 41 | 42 | 43 | # 0.2.9 (2016-09-14) 44 | * Angular 2.0.0 version 45 | * Update to Typescript 2.0.2 46 | * Fix e2e test missing dir 47 | 48 | 49 | # 0.2.8 (2016-09-01) 50 | * remove @angular test libraries from system.js (now in shim) 51 | * update test related files 52 | * wallaby doesn't completely work. Researching. 53 | 54 | 55 | # 0.2.7 (2016-08-31) 56 | * Angular 2 RC6 version 57 | * Updated new forms, router, angular2-in-memory-web-api, karma, core-js, rxjs and zone.js packages 58 | * Removed router-deprecated package 59 | * Updated karma.conf.js and systemjs.config.js 60 | 61 | 62 | # 0.2.6 (2016-08-09) 63 | * Angular 2 RC5 version 64 | * Updated new forms, router and angular2-in-memory-web-api 65 | 66 | 67 | # 0.2.5 (2016-06-30) 68 | * Angular 2 RC4 version 69 | * Updated new forms and router 70 | 71 | 72 | # 0.2.4 (2016-06-21) 73 | * Angular 2 RC3 version 74 | * Add new forms and router 75 | * Add support for TS e2e tests 76 | 77 | 78 | # 0.2.3 (2016-06-15) 79 | * Angular 2 RC2 version 80 | 81 | 82 | # 0.2.2 (2016-05-21) 83 | * Update to Typings 1.x 84 | 85 | 86 | # 0.2.1 (2016-05-03) 87 | * Angular 2 RC01 version 88 | 89 | 90 | # 0.2.0 (2016-05-02) 91 | * Angular 2 RC0 version 92 | 93 | 94 | # 0.1.17 (2016-04-29) 95 | * update packages 96 | * Angular 2 beta 17 97 | * RxJS 5.0.0-beta.6 98 | * a2-in-memory-web-api 0.1.17 99 | 100 | 101 | # 0.1.16 (2016-04-26) 102 | * update packages 103 | * Angular 2 beta 16 104 | * a2-in-memory-web-api 0.1.6 105 | * protractor 3.3.0 106 | * typings 0.8.1 107 | * zone.js 0.6.12 108 | 109 | * added favicon.ico 110 | 111 | * testing 112 | - updated wallaby.js and karma.conf.js 113 | - updated app.component.spec.ts 114 | 115 | 116 | 117 | # 0.1.15 (2016-04-13) 118 | * Add testing support 119 | * npm scripts 120 | * karma/jasmine 121 | * protractor 122 | 123 | * update packages 124 | * Angular 2 beta 15 125 | * lite-server 2.2.0 126 | * systemjs 0.19.26 127 | * typescript 1.8.10 128 | * typings 0.7.12 129 | 130 | * add run packages 131 | * a2-in-memory-web-api 132 | 133 | * add testing dev-dependency packages 134 | * canonical-path: 0.0.2, 135 | * http-server: ^0.9.0, 136 | * jasmine-core: ~2.4.1, 137 | * karma: ^0.13.22, 138 | * karma-chrome-launcher: ^0.2.3, 139 | * karma-cli: ^0.1.2, 140 | * karma-htmlfile-reporter: ^0.2.2, 141 | * karma-jasmine: ^0.3.8, 142 | * protractor: ^3.2.2, 143 | * rimraf: ^2.5.2 144 | 145 | 146 | # 0.1.14 (2016-04-07) 147 | * update packages 148 | * Angular 2 beta 14 149 | * lite-server 2.2.0 150 | * typings 0.7.12 151 | 152 | 153 | # 0.1.13 (2016-03-31) 154 | * update packages 155 | * Angular 2 beta 13 156 | 157 | 158 | # 0.1.12 (2016-03-23) 159 | * update packages 160 | * Angular 2 beta 12 161 | * zones 0.6.6 162 | * remove es6-promise because no longer needed. 163 | 164 | 165 | # 0.1.11 (2016-03-18) 166 | * update packages 167 | * Angular 2 beta 11 168 | * zones 0.6.4 169 | * typescript 1.8.9 170 | * typings 0.7.9 171 | -------------------------------------------------------------------------------- /Chapter 06/Dockerfile: -------------------------------------------------------------------------------- 1 | # To build and run with Docker: 2 | # 3 | # $ docker build -t ng-quickstart . 4 | # $ docker run -it --rm -p 3000:3000 -p 3001:3001 ng-quickstart 5 | # 6 | FROM node:latest 7 | 8 | RUN mkdir -p /quickstart /home/nodejs && \ 9 | groupadd -r nodejs && \ 10 | useradd -r -g nodejs -d /home/nodejs -s /sbin/nologin nodejs && \ 11 | chown -R nodejs:nodejs /home/nodejs 12 | 13 | WORKDIR /quickstart 14 | COPY package.json /quickstart/ 15 | RUN npm install --unsafe-perm=true 16 | 17 | COPY . /quickstart 18 | RUN chown -R nodejs:nodejs /quickstart 19 | USER nodejs 20 | 21 | CMD npm start 22 | -------------------------------------------------------------------------------- /Chapter 06/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2014-2016 Google, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Chapter 06/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'my-app', 5 | template: `

My First Angular 2 App

6 | 7 | 8 |
    9 |
  • 10 | {{comment.title}} 11 | 12 | {{comment.likes}} 13 |
  • 14 |
` 15 | }) 16 | export class AppComponent { 17 | comments:Array; 18 | 19 | constructor() { 20 | this.comments = [ 21 | {title: 'First commemnt', likes: 0} 22 | ]; 23 | } 24 | 25 | add(comment) { 26 | var commentObj = {title: comment, likes: 0}; 27 | this.comments.unshift(commentObj); 28 | } 29 | 30 | like(comment) { 31 | comment.likes++ 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Chapter 06/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | import { FormsModule } from '@angular/forms'; 4 | 5 | import { AppComponent } from './app.component'; 6 | 7 | @NgModule({ 8 | imports: [ BrowserModule, FormsModule ], 9 | declarations: [ AppComponent ], 10 | bootstrap: [ AppComponent ] 11 | }) 12 | export class AppModule { } 13 | -------------------------------------------------------------------------------- /Chapter 06/app/main.ts: -------------------------------------------------------------------------------- 1 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 2 | 3 | import { AppModule } from './app.module'; 4 | 5 | platformBrowserDynamic().bootstrapModule(AppModule); 6 | -------------------------------------------------------------------------------- /Chapter 06/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Angular-Test-Driven-Development-Second-Edition/306153dc7400dd7c063d3494d17d5d14e3c1c41a/Chapter 06/favicon.ico -------------------------------------------------------------------------------- /Chapter 06/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Angular QuickStart 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 21 | 22 | 23 | Loading... 24 | 25 | 26 | -------------------------------------------------------------------------------- /Chapter 06/karma-test-shim.js: -------------------------------------------------------------------------------- 1 | // #docregion 2 | // /*global jasmine, __karma__, window*/ 3 | Error.stackTraceLimit = 0; // "No stacktrace"" is usually best for app testing. 4 | 5 | // Uncomment to get full stacktrace output. Sometimes helpful, usually not. 6 | // Error.stackTraceLimit = Infinity; // 7 | 8 | jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000; 9 | 10 | var builtPath = '/base/'; 11 | 12 | __karma__.loaded = function () { }; 13 | 14 | function isJsFile(path) { 15 | return path.slice(-3) == '.js'; 16 | } 17 | 18 | function isSpecFile(path) { 19 | return /\.spec\.(.*\.)?js$/.test(path); 20 | } 21 | 22 | function isBuiltFile(path) { 23 | return isJsFile(path) && (path.substr(0, builtPath.length) == builtPath); 24 | } 25 | 26 | var allSpecFiles = Object.keys(window.__karma__.files) 27 | .filter(isSpecFile) 28 | .filter(isBuiltFile); 29 | 30 | System.config({ 31 | baseURL: 'base', 32 | // Extend usual application package list with test folder 33 | packages: { 'testing': { main: 'index.js', defaultExtension: 'js' } }, 34 | 35 | // Assume npm: is set in `paths` in systemjs.config 36 | // Map the angular testing umd bundles 37 | map: { 38 | '@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js', 39 | '@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js', 40 | '@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js', 41 | '@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js', 42 | '@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js', 43 | '@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js', 44 | '@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js', 45 | '@angular/forms/testing': 'npm:@angular/forms/bundles/forms-testing.umd.js', 46 | }, 47 | }); 48 | 49 | System.import('systemjs.config.js') 50 | .then(importSystemJsExtras) 51 | .then(initTestBed) 52 | .then(initTesting); 53 | 54 | /** Optional SystemJS configuration extras. Keep going w/o it */ 55 | function importSystemJsExtras(){ 56 | return System.import('systemjs.config.extras.js') 57 | .catch(function(reason) { 58 | console.log( 59 | 'Warning: System.import could not load the optional "systemjs.config.extras.js". Did you omit it by accident? Continuing without it.' 60 | ); 61 | console.log(reason); 62 | }); 63 | } 64 | 65 | function initTestBed(){ 66 | return Promise.all([ 67 | System.import('@angular/core/testing'), 68 | System.import('@angular/platform-browser-dynamic/testing') 69 | ]) 70 | 71 | .then(function (providers) { 72 | var coreTesting = providers[0]; 73 | var browserTesting = providers[1]; 74 | 75 | coreTesting.TestBed.initTestEnvironment( 76 | browserTesting.BrowserDynamicTestingModule, 77 | browserTesting.platformBrowserDynamicTesting()); 78 | }) 79 | } 80 | 81 | // Import all spec files and start karma 82 | function initTesting () { 83 | return Promise.all( 84 | allSpecFiles.map(function (moduleName) { 85 | return System.import(moduleName); 86 | }) 87 | ) 88 | .then(__karma__.start, __karma__.error); 89 | } 90 | -------------------------------------------------------------------------------- /Chapter 06/karma.conf.js: -------------------------------------------------------------------------------- 1 | // #docregion 2 | module.exports = function(config) { 3 | 4 | var appBase = 'app/'; // transpiled app JS and map files 5 | var appSrcBase = 'app/'; // app source TS files 6 | var appAssets = 'base/app/'; // component assets fetched by Angular's compiler 7 | 8 | var testBase = 'spec/unit/'; // transpiled test JS and map files 9 | var testSrcBase = 'spec/unit/'; // test source TS files 10 | 11 | config.set({ 12 | basePath: '', 13 | frameworks: ['jasmine'], 14 | plugins: [ 15 | require('karma-jasmine'), 16 | require('karma-chrome-launcher'), 17 | require('karma-jasmine-html-reporter'), // click "Debug" in browser to see it 18 | require('karma-htmlfile-reporter') // crashing w/ strange socket error 19 | ], 20 | 21 | customLaunchers: { 22 | // From the CLI. Not used here but interesting 23 | // chrome setup for travis CI using chromium 24 | Chrome_travis_ci: { 25 | base: 'Chrome', 26 | flags: ['--no-sandbox'] 27 | } 28 | }, 29 | files: [ 30 | // System.js for module loading 31 | 'node_modules/systemjs/dist/system.src.js', 32 | 33 | // Polyfills 34 | 'node_modules/core-js/client/shim.js', 35 | 'node_modules/reflect-metadata/Reflect.js', 36 | 37 | // zone.js 38 | 'node_modules/zone.js/dist/zone.js', 39 | 'node_modules/zone.js/dist/long-stack-trace-zone.js', 40 | 'node_modules/zone.js/dist/proxy.js', 41 | 'node_modules/zone.js/dist/sync-test.js', 42 | 'node_modules/zone.js/dist/jasmine-patch.js', 43 | 'node_modules/zone.js/dist/async-test.js', 44 | 'node_modules/zone.js/dist/fake-async-test.js', 45 | 46 | // RxJs 47 | { pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false }, 48 | { pattern: 'node_modules/rxjs/**/*.js.map', included: false, watched: false }, 49 | 50 | // Paths loaded via module imports: 51 | // Angular itself 52 | { pattern: 'node_modules/@angular/**/*.js', included: false, watched: false }, 53 | { pattern: 'node_modules/@angular/**/*.js.map', included: false, watched: false }, 54 | 55 | { pattern: 'systemjs.config.js', included: false, watched: false }, 56 | { pattern: 'systemjs.config.extras.js', included: false, watched: false }, 57 | 'karma-test-shim.js', 58 | 59 | // transpiled application & spec code paths loaded via module imports 60 | { pattern: appBase + '**/*.js', included: false, watched: true }, 61 | { pattern: testBase + '**/*.spec.js', included: false, watched: true }, 62 | 63 | // Asset (HTML & CSS) paths loaded via Angular's component compiler 64 | // (these paths need to be rewritten, see proxies section) 65 | //{ pattern: appBase + '**/*.html', included: false, watched: true }, 66 | //{ pattern: appBase + '**/*.css', included: false, watched: true }, 67 | 68 | // Paths for debugging with source maps in dev tools 69 | { pattern: appSrcBase + '**/*.ts', included: false, watched: false }, 70 | { pattern: appBase + '**/*.js.map', included: false, watched: false }, 71 | { pattern: testSrcBase + '**/*.ts', included: false, watched: false }, 72 | { pattern: testBase + '**/*.js.map', included: false, watched: false } 73 | ], 74 | 75 | // Proxied base paths for loading assets 76 | // proxies: { 77 | // // required for component assets fetched by Angular's compiler 78 | // "/app/": appAssets 79 | // }, 80 | 81 | exclude: [], 82 | preprocessors: {}, 83 | // disabled HtmlReporter; suddenly crashing w/ strange socket error 84 | reporters: ['progress', 'kjhtml'],//'html'], 85 | 86 | // HtmlReporter configuration 87 | htmlReporter: { 88 | // Open this file to see results in browser 89 | outputFile: '_test-output/tests.html', 90 | 91 | // Optional 92 | pageTitle: 'Unit Tests', 93 | subPageTitle: __dirname 94 | }, 95 | 96 | port: 9876, 97 | colors: true, 98 | logLevel: config.LOG_INFO, 99 | autoWatch: true, 100 | browsers: ['Chrome'], 101 | singleRun: true 102 | }) 103 | } 104 | -------------------------------------------------------------------------------- /Chapter 06/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-TDD-chapter-6", 3 | "version": "1.0.0", 4 | "description": "QuickStart package.json from the documentation, supplemented with testing support", 5 | "scripts": { 6 | "start": "tsc && concurrently \"tsc -w\" \"lite-server\" ", 7 | "docker-build": "docker build -t ng2-quickstart .", 8 | "docker": "npm run docker-build && docker run -it --rm -p 3000:3000 -p 3001:3001 ng2-quickstart", 9 | "pree2e": "npm run webdriver:update", 10 | "e2e": "tsc && concurrently \"http-server -s\" \"protractor protractor.config.js\" --kill-others --success first", 11 | "lint": "tslint ./app/**/*.ts -t verbose", 12 | "lite": "lite-server", 13 | "test": "tsc && concurrently \"tsc -w\" \"karma start karma.conf.js\"", 14 | "test-once": "tsc && karma start karma.conf.js --single-run", 15 | "tsc": "tsc", 16 | "tsc:w": "tsc -w", 17 | "webdriver:update": "webdriver-manager update" 18 | }, 19 | "keywords": [], 20 | "author": "", 21 | "licenses": [ 22 | { 23 | "type": "MIT", 24 | "url": "https://github.com/angular/angular.io/blob/master/LICENSE" 25 | } 26 | ], 27 | "dependencies": { 28 | "@angular/common": "~2.2.0", 29 | "@angular/compiler": "~2.2.0", 30 | "@angular/core": "~2.2.0", 31 | "@angular/forms": "~2.2.0", 32 | "@angular/http": "~2.2.0", 33 | "@angular/platform-browser": "~2.2.0", 34 | "@angular/platform-browser-dynamic": "~2.2.0", 35 | "@angular/router": "~3.2.0", 36 | "@angular/upgrade": "~2.2.0", 37 | 38 | "angular-in-memory-web-api": "~0.1.15", 39 | "systemjs": "0.19.40", 40 | "core-js": "^2.4.1", 41 | "reflect-metadata": "^0.1.8", 42 | "rxjs": "5.0.0-beta.12", 43 | "zone.js": "^0.6.26" 44 | }, 45 | "devDependencies": { 46 | "concurrently": "^3.1.0", 47 | "lite-server": "^2.2.2", 48 | "typescript": "^2.0.3", 49 | 50 | "canonical-path": "0.0.2", 51 | "http-server": "^0.9.0", 52 | "tslint": "^3.15.1", 53 | "lodash": "^4.16.4", 54 | "jasmine-core": "~2.4.1", 55 | "karma": "^1.3.0", 56 | "karma-chrome-launcher": "^2.0.0", 57 | "karma-cli": "^1.0.1", 58 | "karma-htmlfile-reporter": "^0.3.4", 59 | "karma-jasmine": "^1.0.2", 60 | "karma-jasmine-html-reporter": "^0.2.2", 61 | "protractor": "4.0.14", 62 | "webdriver-manager": "10.2.5", 63 | "rimraf": "^2.5.4", 64 | 65 | "@types/core-js": "^0.9.34", 66 | "@types/node": "^6.0.46", 67 | "@types/jasmine": "^2.5.36", 68 | "@types/selenium-webdriver": "^2.53.33" 69 | }, 70 | "repository": {} 71 | } 72 | -------------------------------------------------------------------------------- /Chapter 06/spec/e2e/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { browser, element, by } from 'protractor'; 2 | 3 | describe('Given I am posting a new comment', () => { 4 | describe('When I push the submit button', () => { 5 | beforeEach(() => { 6 | //Assemble 7 | browser.get(''); 8 | var commentInput = element(by.css('input')); 9 | commentInput.sendKeys('a sample comment'); 10 | //Act 11 | var submitButton = element(by.buttonText('Submit')).click(); 12 | }); 13 | 14 | //Assert 15 | it('Should then add the comment', () => { 16 | var comment = element.all(by.css('li')).first(); 17 | expect(comment.getText()).toBe('a sample comment like 0'); 18 | }); 19 | }); 20 | 21 | describe('When I like a comment', () => { 22 | var firstComment = null; 23 | 24 | beforeEach(() => { 25 | browser.get(''); 26 | 27 | //Assemble 28 | firstComment = element.all(by.css('li')).first(); 29 | var likeButton = firstComment.element(by.buttonText('like')); 30 | 31 | //Act 32 | likeButton.click(); 33 | }); 34 | 35 | //Assert 36 | it('Should increase the number of likes to one', () => { 37 | var commentLikes = firstComment.element(by.css('#likes')); 38 | expect(commentLikes.getText()).toEqual('1'); 39 | }); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /Chapter 06/spec/unit/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | 2 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 3 | import { By } from '@angular/platform-browser'; 4 | import { DebugElement } from '@angular/core'; 5 | import { FormsModule } from '@angular/forms'; 6 | 7 | import { AppComponent } from '../../app/app.component'; 8 | 9 | describe('AppComponent', function () { 10 | let comp: AppComponent; 11 | let fixture: ComponentFixture; 12 | 13 | beforeEach(async(() => { 14 | TestBed.configureTestingModule({ 15 | imports: [ FormsModule ], 16 | declarations: [ AppComponent ] 17 | }) 18 | .compileComponents(); 19 | })); 20 | 21 | beforeEach(() => { 22 | fixture = TestBed.createComponent(AppComponent); 23 | comp = fixture.componentInstance; 24 | 25 | comp.add('a sample comment'); 26 | comp.like(comp.comments[0]); 27 | }); 28 | 29 | it('should create component', () => { 30 | expect(comp).toBeDefined(); 31 | }); 32 | 33 | it('First item in the item should match', () => { 34 | expect(comp.comments[0].title).toBe('a sample comment'); 35 | }); 36 | 37 | it('Number of likes should increase on like', () => { 38 | expect(comp.comments[0].likes).toEqual(1); 39 | }); 40 | 41 | }); 42 | -------------------------------------------------------------------------------- /Chapter 06/styles.css: -------------------------------------------------------------------------------- 1 | /* Master Styles */ 2 | h1 { 3 | color: #369; 4 | font-family: Arial, Helvetica, sans-serif; 5 | font-size: 250%; 6 | } 7 | h2, h3 { 8 | color: #444; 9 | font-family: Arial, Helvetica, sans-serif; 10 | font-weight: lighter; 11 | } 12 | body { 13 | margin: 2em; 14 | } 15 | body, input[text], button { 16 | color: #888; 17 | font-family: Cambria, Georgia; 18 | } 19 | a { 20 | cursor: pointer; 21 | cursor: hand; 22 | } 23 | button { 24 | font-family: Arial; 25 | background-color: #eee; 26 | border: none; 27 | padding: 5px 10px; 28 | border-radius: 4px; 29 | cursor: pointer; 30 | cursor: hand; 31 | } 32 | button:hover { 33 | background-color: #cfd8dc; 34 | } 35 | button:disabled { 36 | background-color: #eee; 37 | color: #aaa; 38 | cursor: auto; 39 | } 40 | 41 | /* Navigation link styles */ 42 | nav a { 43 | padding: 5px 10px; 44 | text-decoration: none; 45 | margin-top: 10px; 46 | display: inline-block; 47 | background-color: #eee; 48 | border-radius: 4px; 49 | } 50 | nav a:visited, a:link { 51 | color: #607D8B; 52 | } 53 | nav a:hover { 54 | color: #039be5; 55 | background-color: #CFD8DC; 56 | } 57 | nav a.router-link-active { 58 | color: #039be5; 59 | } 60 | 61 | /* items class */ 62 | .items { 63 | margin: 0 0 2em 0; 64 | list-style-type: none; 65 | padding: 0; 66 | width: 24em; 67 | } 68 | .items li { 69 | cursor: pointer; 70 | position: relative; 71 | left: 0; 72 | background-color: #EEE; 73 | margin: .5em; 74 | padding: .3em 0; 75 | height: 1.6em; 76 | border-radius: 4px; 77 | } 78 | .items li:hover { 79 | color: #607D8B; 80 | background-color: #DDD; 81 | left: .1em; 82 | } 83 | .items li.selected:hover { 84 | background-color: #BBD8DC; 85 | color: white; 86 | } 87 | .items .text { 88 | position: relative; 89 | top: -3px; 90 | } 91 | .items { 92 | margin: 0 0 2em 0; 93 | list-style-type: none; 94 | padding: 0; 95 | width: 24em; 96 | } 97 | .items li { 98 | cursor: pointer; 99 | position: relative; 100 | left: 0; 101 | background-color: #EEE; 102 | margin: .5em; 103 | padding: .3em 0; 104 | height: 1.6em; 105 | border-radius: 4px; 106 | } 107 | .items li:hover { 108 | color: #607D8B; 109 | background-color: #DDD; 110 | left: .1em; 111 | } 112 | .items li.selected { 113 | background-color: #CFD8DC; 114 | color: white; 115 | } 116 | 117 | .items li.selected:hover { 118 | background-color: #BBD8DC; 119 | } 120 | .items .text { 121 | position: relative; 122 | top: -3px; 123 | } 124 | .items .badge { 125 | display: inline-block; 126 | font-size: small; 127 | color: white; 128 | padding: 0.8em 0.7em 0 0.7em; 129 | background-color: #607D8B; 130 | line-height: 1em; 131 | position: relative; 132 | left: -1px; 133 | top: -4px; 134 | height: 1.8em; 135 | margin-right: .8em; 136 | border-radius: 4px 0 0 4px; 137 | } 138 | 139 | /* everywhere else */ 140 | * { 141 | font-family: Arial, Helvetica, sans-serif; 142 | } 143 | -------------------------------------------------------------------------------- /Chapter 06/systemjs.config.extras.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Add barrels and stuff 3 | * Adjust as necessary for your application needs. 4 | */ 5 | // (function (global) { 6 | // System.config({ 7 | // packages: { 8 | // // add packages here 9 | // } 10 | // }); 11 | // })(this); 12 | -------------------------------------------------------------------------------- /Chapter 06/systemjs.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * System configuration for Angular samples 3 | * Adjust as necessary for your application needs. 4 | */ 5 | (function (global) { 6 | System.config({ 7 | paths: { 8 | // paths serve as alias 9 | 'npm:': 'node_modules/' 10 | }, 11 | // map tells the System loader where to look for things 12 | map: { 13 | // our app is within the app folder 14 | app: 'app', 15 | 16 | // angular bundles 17 | '@angular/core': 'npm:@angular/core/bundles/core.umd.js', 18 | '@angular/common': 'npm:@angular/common/bundles/common.umd.js', 19 | '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js', 20 | '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js', 21 | '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js', 22 | '@angular/http': 'npm:@angular/http/bundles/http.umd.js', 23 | '@angular/router': 'npm:@angular/router/bundles/router.umd.js', 24 | '@angular/router/upgrade': 'npm:@angular/router/bundles/router-upgrade.umd.js', 25 | '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js', 26 | '@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.js', 27 | '@angular/upgrade/static': 'npm:@angular/upgrade/bundles/upgrade-static.umd.js', 28 | 29 | // other libraries 30 | 'rxjs': 'npm:rxjs', 31 | 'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js' 32 | }, 33 | // packages tells the System loader how to load when no filename and/or no extension 34 | packages: { 35 | app: { 36 | main: './main.js', 37 | defaultExtension: 'js' 38 | }, 39 | rxjs: { 40 | defaultExtension: 'js' 41 | } 42 | } 43 | }); 44 | })(this); 45 | -------------------------------------------------------------------------------- /Chapter 06/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "emitDecoratorMetadata": true, 8 | "experimentalDecorators": true, 9 | "removeComments": false, 10 | "noImplicitAny": false, 11 | "suppressImplicitAnyIndexErrors": true, 12 | "typeRoots": [ 13 | "./node_modules/@types/" 14 | ] 15 | }, 16 | "compileOnSave": true, 17 | "exclude": [ 18 | "node_modules/*", 19 | "**/*-aot.ts" 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /Chapter 06/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "class-name": true, 4 | "comment-format": [ 5 | true, 6 | "check-space" 7 | ], 8 | "curly": true, 9 | "eofline": true, 10 | "forin": true, 11 | "indent": [ 12 | true, 13 | "spaces" 14 | ], 15 | "label-position": true, 16 | "label-undefined": true, 17 | "max-line-length": [ 18 | true, 19 | 140 20 | ], 21 | "member-access": false, 22 | "member-ordering": [ 23 | true, 24 | "static-before-instance", 25 | "variables-before-functions" 26 | ], 27 | "no-arg": true, 28 | "no-bitwise": true, 29 | "no-console": [ 30 | true, 31 | "debug", 32 | "info", 33 | "time", 34 | "timeEnd", 35 | "trace" 36 | ], 37 | "no-construct": true, 38 | "no-debugger": true, 39 | "no-duplicate-key": true, 40 | "no-duplicate-variable": true, 41 | "no-empty": false, 42 | "no-eval": true, 43 | "no-inferrable-types": true, 44 | "no-shadowed-variable": true, 45 | "no-string-literal": false, 46 | "no-switch-case-fall-through": true, 47 | "no-trailing-whitespace": true, 48 | "no-unused-expression": true, 49 | "no-unused-variable": true, 50 | "no-unreachable": true, 51 | "no-use-before-declare": true, 52 | "no-var-keyword": true, 53 | "object-literal-sort-keys": false, 54 | "one-line": [ 55 | true, 56 | "check-open-brace", 57 | "check-catch", 58 | "check-else", 59 | "check-whitespace" 60 | ], 61 | "quotemark": [ 62 | true, 63 | "single" 64 | ], 65 | "radix": true, 66 | "semicolon": [ 67 | "always" 68 | ], 69 | "triple-equals": [ 70 | true, 71 | "allow-null-check" 72 | ], 73 | "typedef-whitespace": [ 74 | true, 75 | { 76 | "call-signature": "nospace", 77 | "index-signature": "nospace", 78 | "parameter": "nospace", 79 | "property-declaration": "nospace", 80 | "variable-declaration": "nospace" 81 | } 82 | ], 83 | "variable-name": false, 84 | "whitespace": [ 85 | true, 86 | "check-branch", 87 | "check-decl", 88 | "check-operator", 89 | "check-separator", 90 | "check-type" 91 | ] 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Chapter 06/wallaby.js: -------------------------------------------------------------------------------- 1 | // Configuration for the Wallaby Visual Studio Code testing extension 2 | // https://marketplace.visualstudio.com/items?itemName=WallabyJs.wallaby-vscode 3 | // Note: Wallaby is not open source and costs money 4 | 5 | module.exports = function () { 6 | return { 7 | files: [ 8 | // System.js for module loading 9 | {pattern: 'node_modules/systemjs/dist/system.js', instrument: false}, 10 | {pattern: 'systemjs.config.js', instrument: false}, 11 | {pattern: 'systemjs.config.extras.js', instrument: false}, 12 | 13 | // Polyfills 14 | {pattern: 'node_modules/core-js/client/shim.min.js', instrument: false}, 15 | {pattern: 'node_modules/reflect-metadata/Reflect.js', instrument: false}, 16 | 17 | // zone.js 18 | {pattern: 'node_modules/zone.js/dist/zone.js', instrument: false}, 19 | {pattern: 'node_modules/zone.js/dist/long-stack-trace-zone.js', instrument: false}, 20 | {pattern: 'node_modules/zone.js/dist/proxy.js', instrument: false}, 21 | {pattern: 'node_modules/zone.js/dist/sync-test.js', instrument: false}, 22 | {pattern: 'node_modules/zone.js/dist/jasmine-patch.js', instrument: false}, 23 | {pattern: 'node_modules/zone.js/dist/async-test.js', instrument: false}, 24 | {pattern: 'node_modules/zone.js/dist/fake-async-test.js', instrument: false}, 25 | 26 | // application (but not specs) loaded via module imports 27 | {pattern: 'app/**/*+(ts|html|css)', load: false}, 28 | {pattern: 'app/**/*.spec.ts', ignore: true}, 29 | 30 | {pattern: 'testing/**/*+(ts|html|css)', load: false}, 31 | ], 32 | 33 | tests: [ 34 | {pattern: 'app/**/*.spec.ts', load: false} 35 | ], 36 | 37 | middleware: function (app, express) { 38 | app.use('/node_modules', express.static(require('path').join(__dirname, 'node_modules'))); 39 | }, 40 | 41 | testFramework: 'jasmine', 42 | 43 | debug: true, 44 | 45 | bootstrap: bootstrap 46 | }; 47 | }; 48 | 49 | // Like karma-test-shim.js 50 | function bootstrap (wallaby) { 51 | wallaby.delayStart(); 52 | 53 | System.config({ 54 | // Extend usual application package list with test folder 55 | packages: { 'testing': { main: 'index.js', defaultExtension: 'js' } }, 56 | 57 | // Assume npm: is set in `paths` in systemjs.config 58 | // Map the angular testing umd bundles 59 | map: { 60 | '@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js', 61 | '@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js', 62 | '@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js', 63 | '@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js', 64 | '@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js', 65 | '@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js', 66 | '@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js', 67 | '@angular/forms/testing': 'npm:@angular/forms/bundles/forms-testing.umd.js', 68 | }, 69 | }); 70 | 71 | System.import('systemjs.config.js') 72 | .then(importSystemJsExtras) 73 | .then(initTestBed) 74 | .then(initTesting); 75 | 76 | /** Optional SystemJS configuration extras. Keep going w/o it */ 77 | function importSystemJsExtras(){ 78 | return System.import('systemjs.config.extras.js') 79 | .catch(function(reason) { 80 | console.log( 81 | 'Warning: System.import could not load the optional "systemjs.config.extras.js". Did you omit it by accident? Continuing without it.' 82 | ); 83 | console.log(reason); 84 | }); 85 | } 86 | 87 | function initTestBed(){ 88 | return Promise.all([ 89 | System.import('@angular/core/testing'), 90 | System.import('@angular/platform-browser-dynamic/testing') 91 | ]) 92 | 93 | .then(function (providers) { 94 | var coreTesting = providers[0]; 95 | var browserTesting = providers[1]; 96 | 97 | coreTesting.TestBed.initTestEnvironment( 98 | browserTesting.BrowserDynamicTestingModule, 99 | browserTesting.platformBrowserDynamicTesting()); 100 | }) 101 | } 102 | 103 | // Load all spec files and start wallaby 104 | function initTesting () { 105 | return Promise.all( 106 | wallaby.tests.map(function (specFile) { 107 | return System.import(specFile); 108 | }) 109 | ) 110 | .then(function () { 111 | wallaby.start(); 112 | }) 113 | .catch(function (e) { 114 | setTimeout(function () { 115 | throw e; 116 | }, 0); 117 | }); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /Chapter 07/.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | 12 | [*.md] 13 | max_line_length = 0 14 | trim_trailing_whitespace = false 15 | 16 | # Indentation override 17 | #[lib/**.js] 18 | #[{package.json,.travis.yml}] 19 | #[**/**.js] 20 | -------------------------------------------------------------------------------- /Chapter 07/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .DS_Store 3 | node_modules 4 | jspm_packages 5 | npm-debug.* 6 | link-checker-results.txt 7 | app/**/*.js 8 | *.js.map 9 | spec/e2e/**/*.js 10 | spec/e2e/**/*.js.map 11 | spec/unit/**/*.js 12 | spec/unit/**/*.js.map 13 | _test-output 14 | _temp 15 | -------------------------------------------------------------------------------- /Chapter 07/.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | sudo: required 3 | language: node_js 4 | node_js: 5 | - "5" 6 | os: 7 | - linux 8 | env: 9 | global: 10 | - DBUS_SESSION_BUS_ADDRESS=/dev/null 11 | - DISPLAY=:99.0 12 | - CHROME_BIN=chromium-browser 13 | before_script: 14 | - sh -e /etc/init.d/xvfb start 15 | install: 16 | - npm install 17 | script: 18 | - npm run lint 19 | - npm run test-once 20 | - npm run e2e 21 | -------------------------------------------------------------------------------- /Chapter 07/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## Angular Documentation QuickStart Changelog 2 | Upgraders: for a fresh start, consider running these commands 3 | * `git clean -xdf` 4 | * `npm install` 5 | 6 | 7 | # 0.2.19 (2016-11-30) 8 | * remove upgrade mappings from `systemjs.config.js` PR #301 9 | 10 | 11 | # 0.2.18 (2016-11-30) 12 | * remove `exclude` clause from `tsconfig.json`; it was just confusing people 13 | * karma.config + karma-test-shim can handle multiple spec source paths (issue #294) 14 | * cosmetic `app.component.spec.ts` changes 15 | * cosmetic `karma.config.js` changes 16 | 17 | 18 | # 0.2.17 (2016-11-16) 19 | * Conform to updated QuickStart advice 20 | * removed docker everywhere (was nice but not necessary) 21 | * removed wallaby 22 | * shrink styles.css 23 | * refine tsconfig.json 24 | * `AppComponent` uses interpolation 25 | 26 | 27 | # 0.2.16 (2016-11-14) 28 | * Update to Angular 2.2.0 29 | 30 | 31 | # 0.2.15 (2016-10-29) 32 | * Revert to Jasmine 2.4.1 because bug in 2.5.x (see [jasmine issue #1231](https://github.com/jasmine/jasmine/issues/1231)) 33 | 34 | 35 | # 0.2.14 (2016-10-29) 36 | * Remove bootstrap.css install 37 | * Angular v2.1.2 38 | 39 | 40 | # 0.2.13 (2016-10-20) 41 | * Protractor 4 42 | * Move from `typings` to `@types`. See `tsconfig.json` changes. 43 | * Angular v2.1.1 44 | 45 | 46 | # 0.2.12 (2016-10-06) 47 | * Angular v2.1.0 48 | 49 | 50 | # 0.2.11 (2016-10-06) 51 | * Angular v2.0.2 52 | * License is MIT 53 | * Current testing configuration 54 | * No code changes 55 | 56 | 57 | # 0.2.10 (2016-09-19) 58 | * All "Angular 2" references become just "Angular" 59 | * No code changes 60 | 61 | 62 | # 0.2.9 (2016-09-14) 63 | * Angular 2.0.0 version 64 | * Update to Typescript 2.0.2 65 | * Fix e2e test missing dir 66 | 67 | 68 | # 0.2.8 (2016-09-01) 69 | * remove @angular test libraries from system.js (now in shim) 70 | * update test related files 71 | * wallaby doesn't completely work. Researching. 72 | 73 | 74 | # 0.2.7 (2016-08-31) 75 | * Angular 2 RC6 version 76 | * Updated new forms, router, angular2-in-memory-web-api, karma, core-js, rxjs and zone.js packages 77 | * Removed router-deprecated package 78 | * Updated karma.conf.js and systemjs.config.js 79 | 80 | 81 | # 0.2.6 (2016-08-09) 82 | * Angular 2 RC5 version 83 | * Updated new forms, router and angular2-in-memory-web-api 84 | 85 | 86 | # 0.2.5 (2016-06-30) 87 | * Angular 2 RC4 version 88 | * Updated new forms and router 89 | 90 | 91 | # 0.2.4 (2016-06-21) 92 | * Angular 2 RC3 version 93 | * Add new forms and router 94 | * Add support for TS e2e tests 95 | 96 | 97 | # 0.2.3 (2016-06-15) 98 | * Angular 2 RC2 version 99 | 100 | 101 | # 0.2.2 (2016-05-21) 102 | * Update to Typings 1.x 103 | 104 | 105 | # 0.2.1 (2016-05-03) 106 | * Angular 2 RC01 version 107 | 108 | 109 | # 0.2.0 (2016-05-02) 110 | * Angular 2 RC0 version 111 | 112 | 113 | # 0.1.17 (2016-04-29) 114 | * update packages 115 | * Angular 2 beta 17 116 | * RxJS 5.0.0-beta.6 117 | * a2-in-memory-web-api 0.1.17 118 | 119 | 120 | # 0.1.16 (2016-04-26) 121 | * update packages 122 | * Angular 2 beta 16 123 | * a2-in-memory-web-api 0.1.6 124 | * protractor 3.3.0 125 | * typings 0.8.1 126 | * zone.js 0.6.12 127 | 128 | * added favicon.ico 129 | 130 | * testing 131 | - updated wallaby.js and karma.conf.js 132 | - updated app.component.spec.ts 133 | 134 | 135 | 136 | # 0.1.15 (2016-04-13) 137 | * Add testing support 138 | * npm scripts 139 | * karma/jasmine 140 | * protractor 141 | 142 | * update packages 143 | * Angular 2 beta 15 144 | * lite-server 2.2.0 145 | * systemjs 0.19.26 146 | * typescript 1.8.10 147 | * typings 0.7.12 148 | 149 | * add run packages 150 | * a2-in-memory-web-api 151 | 152 | * add testing dev-dependency packages 153 | * canonical-path: 0.0.2, 154 | * http-server: ^0.9.0, 155 | * jasmine-core: ~2.4.1, 156 | * karma: ^0.13.22, 157 | * karma-chrome-launcher: ^0.2.3, 158 | * karma-cli: ^0.1.2, 159 | * karma-htmlfile-reporter: ^0.2.2, 160 | * karma-jasmine: ^0.3.8, 161 | * protractor: ^3.2.2, 162 | * rimraf: ^2.5.2 163 | 164 | 165 | # 0.1.14 (2016-04-07) 166 | * update packages 167 | * Angular 2 beta 14 168 | * lite-server 2.2.0 169 | * typings 0.7.12 170 | 171 | 172 | # 0.1.13 (2016-03-31) 173 | * update packages 174 | * Angular 2 beta 13 175 | 176 | 177 | # 0.1.12 (2016-03-23) 178 | * update packages 179 | * Angular 2 beta 12 180 | * zones 0.6.6 181 | * remove es6-promise because no longer needed. 182 | 183 | 184 | # 0.1.11 (2016-03-18) 185 | * update packages 186 | * Angular 2 beta 11 187 | * zones 0.6.4 188 | * typescript 1.8.9 189 | * typings 0.7.9 190 | -------------------------------------------------------------------------------- /Chapter 07/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2014-2016 Google, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Chapter 07/app/app.component.html: -------------------------------------------------------------------------------- 1 |

My First Angular 2 App

2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter 07/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | moduleId: module.id, 5 | selector: 'my-app', 6 | templateUrl: 'app.component.html' 7 | }) 8 | export class AppComponent { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /Chapter 07/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core' 2 | import {BrowserModule} from "@angular/platform-browser"; 3 | import {RouterModule} from "@angular/router"; 4 | import {FormsModule} from "@angular/forms"; 5 | import {HttpModule} from "@angular/http"; 6 | 7 | 8 | import {rootRouterConfig} from "./app.routes"; 9 | import {AppComponent} from "./app.component"; 10 | import {NavbarComponent} from './nav/navbar.component'; 11 | import {View1Component} from './view/view1.component'; 12 | import {View2Component} from './view/view2.component'; 13 | import {MembersComponent} from './members/members.component'; 14 | import {PersonComponent} from './members/person/person.component'; 15 | 16 | @NgModule({ 17 | declarations: [AppComponent, NavbarComponent, View1Component, View2Component, MembersComponent, PersonComponent], 18 | imports : [BrowserModule, FormsModule, HttpModule, RouterModule.forRoot(rootRouterConfig)], 19 | bootstrap : [AppComponent] 20 | }) 21 | export class AppModule { 22 | 23 | } 24 | -------------------------------------------------------------------------------- /Chapter 07/app/app.routes.ts: -------------------------------------------------------------------------------- 1 | import {Routes} from '@angular/router'; 2 | import {View1Component} from './view/view1.component'; 3 | import {View2Component} from './view/view2.component'; 4 | import {MembersComponent} from './members/members.component'; 5 | import {PersonComponent} from './members/person/person.component'; 6 | 7 | 8 | export const rootRouterConfig: Routes = [ 9 | {path: '', redirectTo: 'view1', pathMatch: 'full'}, 10 | {path: 'view1', component: View1Component}, 11 | {path: 'view2', component: View2Component}, 12 | {path: 'members', component: MembersComponent}, 13 | {path: 'person/:id', component: PersonComponent} 14 | ]; 15 | -------------------------------------------------------------------------------- /Chapter 07/app/data/people.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "name": "Peyton Manning", 5 | "phone": "(303) 567-8910", 6 | "address": { 7 | "street": "1234 Main Street", 8 | "city": "Greenwood Village", 9 | "state": "CO", 10 | "zip": "80111" 11 | } 12 | }, 13 | { 14 | "id": 2, 15 | "name": "Demaryius Thomas", 16 | "phone": "(720) 213-9876", 17 | "address": { 18 | "street": "5555 Marion Street", 19 | "city": "Denver", 20 | "state": "CO", 21 | "zip": "80202" 22 | } 23 | }, 24 | { 25 | "id": 3, 26 | "name": "Von Miller", 27 | "phone": "(917) 323-2333", 28 | "address": { 29 | "street": "14 Mountain Way", 30 | "city": "Vail", 31 | "state": "CO", 32 | "zip": "81657" 33 | } 34 | } 35 | ] 36 | -------------------------------------------------------------------------------- /Chapter 07/app/main.ts: -------------------------------------------------------------------------------- 1 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 2 | import { AppModule } from './app.module'; 3 | 4 | platformBrowserDynamic().bootstrapModule(AppModule); 5 | -------------------------------------------------------------------------------- /Chapter 07/app/members/members.component.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | padding: 0 16px; 4 | } 5 | 6 | table { 7 | margin-top: 10px; 8 | border-collapse: collapse; 9 | } 10 | 11 | th { 12 | text-align: left; 13 | border-bottom: 2px solid #ddd; 14 | padding: 8px; 15 | } 16 | 17 | td { 18 | border-top: 1px solid #ddd; 19 | padding: 8px; 20 | } 21 | -------------------------------------------------------------------------------- /Chapter 07/app/members/members.component.html: -------------------------------------------------------------------------------- 1 |

Members

2 | 3 |
4 | 5 | 6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
NamePhone
{{member.name}}{{member.phone}}
22 | -------------------------------------------------------------------------------- /Chapter 07/app/members/members.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Http, Response } from '@angular/http'; 3 | import { Router } from '@angular/router'; 4 | 5 | import 'rxjs/add/operator/toPromise'; 6 | import { Person } from './person/person.component'; 7 | 8 | @Component({ 9 | selector: 'app-member', 10 | moduleId: module.id, 11 | templateUrl: 'members.component.html', 12 | styleUrls: ['members.component.css'] 13 | }) 14 | export class MembersComponent implements OnInit { 15 | memberList: Array = []; 16 | query: string; 17 | 18 | constructor(private http:Http, private router:Router) { 19 | 20 | } 21 | 22 | ngOnInit() { 23 | //this.getMembers(); 24 | this.search(); 25 | } 26 | 27 | viewDetails(id:number) { 28 | this.router.navigate(['/person', id]); 29 | } 30 | 31 | getMembers() { 32 | this.getData() 33 | .then(data => { 34 | data.map(item => { 35 | this.memberList.push(item); 36 | }); 37 | }) 38 | return this.memberList; 39 | } 40 | 41 | getData() { 42 | return this.http.get('app/data/people.json') 43 | .toPromise() 44 | .then(response => response.json()); 45 | } 46 | 47 | search(): void { 48 | this.searchQuery(this.query) 49 | .then(results => this.memberList = results); 50 | } 51 | 52 | searchQuery(q:string) { 53 | if (!q || q === '*') { 54 | q = ''; 55 | } else { 56 | q = q.toLowerCase(); 57 | } 58 | return this.getData() 59 | .then(data => { 60 | let results:Array = []; 61 | data.map(item => { 62 | if (JSON.stringify(item).toLowerCase().includes(q)) { 63 | results.push(item); 64 | } 65 | }); 66 | return results; 67 | }); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Chapter 07/app/members/person/person.component.html: -------------------------------------------------------------------------------- 1 |

Member Details

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
Name :{{person.name}}
Phone: {{person.phone}}
Street: {{person.address.street}}
City: {{person.address.city}}
State: {{person.address.state}}
Zip: {{person.address.zip}}
31 | -------------------------------------------------------------------------------- /Chapter 07/app/members/person/person.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Http, Response } from '@angular/http'; 3 | import { Router, ActivatedRoute, Params } from '@angular/router'; 4 | import 'rxjs/add/operator/toPromise'; 5 | 6 | @Component({ 7 | selector: 'app-person', 8 | moduleId: module.id, 9 | templateUrl: 'person.component.html', 10 | styleUrls: ['../members.component.css'] 11 | }) 12 | export class PersonComponent implements OnInit { 13 | person: Person; 14 | constructor(private http:Http, private route: ActivatedRoute, private router: Router) { 15 | 16 | } 17 | 18 | ngOnInit() { 19 | this.route.params.forEach((params: Params) => { 20 | let id = +params['id']; 21 | this.getPerson(id).then(person => { 22 | this.person = person; 23 | }); 24 | }); 25 | } 26 | 27 | getPerson(id:number) { 28 | return this.getData().then(data => data.find(member => member.id === id)); 29 | } 30 | 31 | getData() { 32 | return this.http.get('app/data/people.json') 33 | .toPromise() 34 | .then(response => response.json()); 35 | } 36 | 37 | } 38 | 39 | export class Person { 40 | id:number; 41 | name:string; 42 | phone:string; 43 | address:Address; 44 | 45 | constructor(obj?:any) { 46 | this.id = obj && Number(obj.id) || null; 47 | this.name = obj && obj.name || null; 48 | this.phone = obj && obj.phone || null; 49 | this.address = obj && obj.address || null; 50 | } 51 | } 52 | 53 | export class Address { 54 | street:string; 55 | city:string; 56 | state:string; 57 | zip:string; 58 | 59 | constructor(obj?:any) { 60 | this.street = obj && obj.street || null; 61 | this.city = obj && obj.city || null; 62 | this.state = obj && obj.state || null; 63 | this.zip = obj && obj.zip || null; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Chapter 07/app/nav/navbar.component.css: -------------------------------------------------------------------------------- 1 | :host { 2 | border-color: #e1e1e1; 3 | border-style: solid; 4 | border-width: 0 0 1px; 5 | display: block; 6 | height: 48px; 7 | padding: 0 16px; 8 | } 9 | 10 | nav a { 11 | color: #8f8f8f; 12 | font-size: 14px; 13 | font-weight: 500; 14 | margin-right: 20px; 15 | text-decoration: none; 16 | vertical-align: middle; 17 | } 18 | 19 | nav a.router-link-active { 20 | color: #106cc8; 21 | } 22 | -------------------------------------------------------------------------------- /Chapter 07/app/nav/navbar.component.html: -------------------------------------------------------------------------------- 1 |
2 | 7 |
8 | -------------------------------------------------------------------------------- /Chapter 07/app/nav/navbar.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-navbar', 5 | moduleId: module.id, 6 | templateUrl: 'navbar.component.html', 7 | styleUrls: ['navbar.component.css'] 8 | }) 9 | export class NavbarComponent {} 10 | -------------------------------------------------------------------------------- /Chapter 07/app/view/view1.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-view1', 5 | template: '
I am view one component
' 6 | }) 7 | export class View1Component { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /Chapter 07/app/view/view2.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-view2', 5 | template: '
I am view two component
' 6 | }) 7 | export class View2Component { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /Chapter 07/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Angular-Test-Driven-Development-Second-Edition/306153dc7400dd7c063d3494d17d5d14e3c1c41a/Chapter 07/favicon.ico -------------------------------------------------------------------------------- /Chapter 07/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Angular 2 QuickStart 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 21 | 22 | 23 | 24 | Loading AppComponent content here ... 25 | 26 | 27 | -------------------------------------------------------------------------------- /Chapter 07/karma-test-shim.js: -------------------------------------------------------------------------------- 1 | // /*global jasmine, __karma__, window*/ 2 | Error.stackTraceLimit = 0; // "No stacktrace"" is usually best for app testing. 3 | 4 | // Uncomment to get full stacktrace output. Sometimes helpful, usually not. 5 | // Error.stackTraceLimit = Infinity; // 6 | 7 | jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000; 8 | 9 | // builtPaths: root paths for output ("built") files 10 | // get from karma.config.js, then prefix with '/base/' (default is 'app/') 11 | var builtPaths = (__karma__.config.builtPaths || ['app/']) 12 | .map(function(p) { return '/base/'+p;}); 13 | 14 | __karma__.loaded = function () { }; 15 | 16 | function isJsFile(path) { 17 | return path.slice(-3) == '.js'; 18 | } 19 | 20 | function isSpecFile(path) { 21 | return /\.spec\.(.*\.)?js$/.test(path); 22 | } 23 | 24 | // Is a "built" file if is JavaScript file in one of the "built" folders 25 | function isBuiltFile(path) { 26 | return isJsFile(path) && 27 | builtPaths.reduce(function(keep, bp) { 28 | return keep || (path.substr(0, bp.length) === bp); 29 | }, false); 30 | } 31 | 32 | var allSpecFiles = Object.keys(window.__karma__.files) 33 | .filter(isSpecFile) 34 | .filter(isBuiltFile); 35 | 36 | System.config({ 37 | baseURL: 'base', 38 | // Extend usual application package list with test folder 39 | packages: { 'testing': { main: 'index.js', defaultExtension: 'js' } }, 40 | 41 | // Assume npm: is set in `paths` in systemjs.config 42 | // Map the angular testing umd bundles 43 | map: { 44 | '@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js', 45 | '@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js', 46 | '@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js', 47 | '@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js', 48 | '@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js', 49 | '@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js', 50 | '@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js', 51 | '@angular/forms/testing': 'npm:@angular/forms/bundles/forms-testing.umd.js', 52 | }, 53 | }); 54 | 55 | System.import('systemjs.config.js') 56 | .then(importSystemJsExtras) 57 | .then(initTestBed) 58 | .then(initTesting); 59 | 60 | /** Optional SystemJS configuration extras. Keep going w/o it */ 61 | function importSystemJsExtras(){ 62 | return System.import('systemjs.config.extras.js') 63 | .catch(function(reason) { 64 | console.log( 65 | 'Warning: System.import could not load the optional "systemjs.config.extras.js". Did you omit it by accident? Continuing without it.' 66 | ); 67 | console.log(reason); 68 | }); 69 | } 70 | 71 | function initTestBed(){ 72 | return Promise.all([ 73 | System.import('@angular/core/testing'), 74 | System.import('@angular/platform-browser-dynamic/testing') 75 | ]) 76 | 77 | .then(function (providers) { 78 | var coreTesting = providers[0]; 79 | var browserTesting = providers[1]; 80 | 81 | coreTesting.TestBed.initTestEnvironment( 82 | browserTesting.BrowserDynamicTestingModule, 83 | browserTesting.platformBrowserDynamicTesting()); 84 | }) 85 | } 86 | 87 | // Import all spec files and start karma 88 | function initTesting () { 89 | return Promise.all( 90 | allSpecFiles.map(function (moduleName) { 91 | return System.import(moduleName); 92 | }) 93 | ) 94 | .then(__karma__.start, __karma__.error); 95 | } 96 | -------------------------------------------------------------------------------- /Chapter 07/karma.conf.js: -------------------------------------------------------------------------------- 1 | module.exports = function(config) { 2 | 3 | var appBase = 'app/'; // transpiled app JS and map files 4 | var appSrcBase = 'app/'; // app source TS files 5 | var appAssets = 'base/app/'; // component assets fetched by Angular's compiler 6 | 7 | var testBase = 'spec/unit/'; // transpiled test JS and map files 8 | var testSrcBase = 'spec/unit/'; // test source TS files 9 | 10 | config.set({ 11 | basePath: '', 12 | frameworks: ['jasmine'], 13 | 14 | plugins: [ 15 | require('karma-jasmine'), 16 | require('karma-chrome-launcher'), 17 | require('karma-phantomjs-launcher'), 18 | require('karma-jasmine-html-reporter') // click "Debug" in browser to see it 19 | ], 20 | 21 | client: { 22 | builtPaths: [appBase, testBase], // add more spec base paths as needed 23 | clearContext: false // leave Jasmine Spec Runner output visible in browser 24 | }, 25 | 26 | customLaunchers: { 27 | // From the CLI. Not used here but interesting 28 | // chrome setup for travis CI using chromium 29 | Chrome_travis_ci: { 30 | base: 'Chrome', 31 | flags: ['--no-sandbox'] 32 | } 33 | }, 34 | 35 | files: [ 36 | // System.js for module loading 37 | 'node_modules/systemjs/dist/system.src.js', 38 | 39 | // Polyfills 40 | 'node_modules/core-js/client/shim.js', 41 | 'node_modules/reflect-metadata/Reflect.js', 42 | 43 | // zone.js 44 | 'node_modules/zone.js/dist/zone.js', 45 | 'node_modules/zone.js/dist/long-stack-trace-zone.js', 46 | 'node_modules/zone.js/dist/proxy.js', 47 | 'node_modules/zone.js/dist/sync-test.js', 48 | 'node_modules/zone.js/dist/jasmine-patch.js', 49 | 'node_modules/zone.js/dist/async-test.js', 50 | 'node_modules/zone.js/dist/fake-async-test.js', 51 | 52 | // RxJs 53 | { pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false }, 54 | { pattern: 'node_modules/rxjs/**/*.js.map', included: false, watched: false }, 55 | 56 | // Paths loaded via module imports: 57 | // Angular itself 58 | { pattern: 'node_modules/@angular/**/*.js', included: false, watched: false }, 59 | { pattern: 'node_modules/@angular/**/*.js.map', included: false, watched: false }, 60 | 61 | { pattern: 'systemjs.config.js', included: false, watched: false }, 62 | { pattern: 'systemjs.config.extras.js', included: false, watched: false }, 63 | 'karma-test-shim.js', // optionally extend SystemJS mapping e.g., with barrels 64 | 65 | // transpiled application & spec code paths loaded via module imports 66 | { pattern: appBase + '**/*.js', included: false, watched: true }, 67 | { pattern: testBase + '**/*.js', included: false, watched: true }, 68 | 69 | 70 | // Asset (HTML & CSS) paths loaded via Angular's component compiler 71 | // (these paths need to be rewritten, see proxies section) 72 | { pattern: appBase + '**/*.html', included: false, watched: true }, 73 | { pattern: appBase + '**/*.css', included: false, watched: true }, 74 | 75 | // Paths for debugging with source maps in dev tools 76 | { pattern: appSrcBase + '**/*.ts', included: false, watched: false }, 77 | { pattern: appBase + '**/*.js.map', included: false, watched: false }, 78 | { pattern: testSrcBase + '**/*.ts', included: false, watched: false }, 79 | { pattern: testBase + '**/*.js.map', included: false, watched: false} 80 | ], 81 | 82 | // Proxied base paths for loading assets 83 | proxies: { 84 | // required for component assets fetched by Angular's compiler 85 | "/app/": appAssets 86 | }, 87 | 88 | exclude: [], 89 | preprocessors: {}, 90 | reporters: ['progress', 'kjhtml'], 91 | 92 | port: 9876, 93 | colors: true, 94 | logLevel: config.LOG_INFO, 95 | autoWatch: true, 96 | browsers: ['Chrome'], 97 | singleRun: false 98 | }) 99 | } 100 | -------------------------------------------------------------------------------- /Chapter 07/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-TDD-chapter-7", 3 | "version": "1.0.0", 4 | "description": "QuickStart package.json from the documentation, supplemented with testing support", 5 | "scripts": { 6 | "start": "tsc && concurrently \"tsc -w\" \"lite-server\" ", 7 | "e2e": "tsc && concurrently \"http-server -s\" \"protractor protractor.config.js\" --kill-others --success first", 8 | "lint": "tslint ./app/**/*.ts -t verbose", 9 | "lite": "lite-server", 10 | "pree2e": "webdriver-manager update", 11 | "test": "tsc && concurrently \"tsc -w\" \"karma start karma.conf.js\"", 12 | "test-once": "tsc && karma start karma.conf.js --single-run", 13 | "tsc": "tsc", 14 | "tsc:w": "tsc -w" 15 | }, 16 | "keywords": [], 17 | "author": "", 18 | "license": "MIT", 19 | "dependencies": { 20 | "@angular/common": "~2.2.0", 21 | "@angular/compiler": "~2.2.0", 22 | "@angular/core": "~2.2.0", 23 | "@angular/forms": "~2.2.0", 24 | "@angular/http": "~2.2.0", 25 | "@angular/platform-browser": "~2.2.0", 26 | "@angular/platform-browser-dynamic": "~2.2.0", 27 | "@angular/router": "~3.2.0", 28 | "angular-in-memory-web-api": "~0.1.15", 29 | "core-js": "^2.4.1", 30 | "reflect-metadata": "^0.1.8", 31 | "rxjs": "5.0.0-beta.12", 32 | "systemjs": "0.19.40", 33 | "zone.js": "^0.6.26" 34 | }, 35 | "devDependencies": { 36 | "concurrently": "^3.1.0", 37 | "lite-server": "^2.2.2", 38 | "typescript": "^2.0.10", 39 | "canonical-path": "0.0.2", 40 | "http-server": "^0.9.0", 41 | "tslint": "^3.15.1", 42 | "lodash": "^4.16.4", 43 | "jasmine-core": "~2.4.1", 44 | "karma": "^1.3.0", 45 | "karma-chrome-launcher": "^2.0.0", 46 | "karma-cli": "^1.0.1", 47 | "karma-jasmine": "^1.0.2", 48 | "karma-jasmine-html-reporter": "^0.2.2", 49 | "karma-phantomjs-launcher": "^1.0.2", 50 | "protractor": "4.0.14", 51 | "webdriver-manager": "10.2.5", 52 | "rimraf": "^2.5.4", 53 | "@types/node": "^6.0.46", 54 | "@types/jasmine": "^2.5.36", 55 | "@types/selenium-webdriver": "^2.53.33" 56 | }, 57 | "repository": {} 58 | } 59 | -------------------------------------------------------------------------------- /Chapter 07/protractor-results.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Chapter 07/spec/e2e/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { browser, element, by } from 'protractor'; 2 | 3 | // describe('Given page has a page title and navigation menu', () => { 4 | // beforeEach( () => { 5 | // browser.get(''); 6 | // }); 7 | // 8 | // it('Page should have a header title as expected ', function () { 9 | // expect(element(by.css('h1')).getText()).toEqual('My First Angular 2 App'); 10 | // }); 11 | // 12 | // it('should have