Upload
troy-miles
View
334
Download
7
Embed Size (px)
Citation preview
CoWork SouthBay 25 + 26 February 2017
Angular 2.0 Weekend Workshop
Troy Miles• Troy Miles aka the RocknCoder
• Over 38 years of programming experience
• Speaker and author
• bit.ly/rc-jquerybook
• @therockncoder
• Now a lynda.com Author!
Build Mobile Apps!
• Develop mobile apps with Ionic and AngularJS
• Learn the Ionic CLI
• Fetch data via ajax
• Deploy your app to Android & iOS
• bit.ly/ionicvideo
April1&2
–Alejandro (Sicario 2015)
“Nothing will make sense to your American ears, and you will doubt everything that we do,
but in the end you will understand”
Agenda: Day One• Overview
• Angular CLI
• Webpack
• Modern JavaScript
• TypeScript
• Components / Views
• Router
• Data Binding
• Dependency Injection
• Services
Agenda: Day Two• HTTP
• Forms
• Pipes
• Directives
• RxJS
• Unit Testing
• Angular Material
• Summary
Tools• install git
• install node.js
• upgrade npm npm install npm -g
• install RxJS npm install -g rxjs
• install Angular CLI npm install -g @angular/cli
• install Firebase: npm install -g firebase-tools
Check Versionsapp command my version
git git —version 2.11.0
node.js node -v v7.4.0
npm npm —v 4.0.5
angular cli ng -v 1.0.0-beta.32.3
firebase firebase version 3.3.0
Application Root Directory
• All of the commands, for all of the tools are designed work on the application root directory
• If used anywhere else bad things will happen
• be sure you are in the app root
• double check that you are in the app root
Angular CLITool Command
New App ng new <app-name>
Web Server ng serve
Unit Test ng test
End to End Test ng e2e
Dev Build ng build dev
Production Build ng build prod
Create New ComponentsComponent CommandClass ng g class my-new-classComponent ng g component my-new-componentDirective ng g directive my-new-directiveEnum ng g enum my-new-enumInterface ng g interface my-new-interfaceModule ng g module my-modulePipe ng g pipe my-new-pipeService ng g service my-new-service
naming convention• Angular apps are usually built using lowercase
kebab naming convention
• words are lowercase, dash as separator
• final word is the thing’s type, a dot is its separator
• if the thing is a class, no final word
• contact-details.component.ts
Webpack
• Open source module bundler
• Replaces System.JS
• Works with JS, CSS, and HTML
• Minifies, Concatenates, and Bundles
Firebase commandsCommand What?
firebase login logins into your firebase account
firebase init sets up a new firebase project
firebase deploy deploys your app to firebase hosting
firebase list lists all your firebase projects
firebase open open project resources
firebase use —add adds the current
Firebase Steps1. Create project in Firebase
2. Go to application root in terminal/ cmd prompt
3. firebase login
4. firebase init (connects app to firebase project)
5. ng build prod (creates “dist" directory)
6. firebase deploy
7. Refresh cache (Chrome: cmd+shift+R / ctrl+shift+R )
ECMAScript VersionsVersion Date
ES1 June 1997
ES2 June 1998
ES3 December 1999
ES4 DOA 2006
ES5 December 2009
ES6/ES2015 June 2015
ES2016 2016
2009 • ES3 ruled the land, it is 10 years old
• ES4 was abandoned due to infighting
• ES5 was in development, strict mode still a dream
• FireFox 3.5 is the most popular browser
• AngularJS is born
AngularJS
• Created by Miško Hevery and Adam Abrons in 2009
• JavaScript MVC
• Declarative programming for UI
• Imperative programming for business logic
AngularJS Main Parts• Module
• Views/Controllers
• Services
• Directives
• Filters
Since 2009• Two new versions of JavaScript (ES5 & ES6)
• Lots of new browser capabilities
• Transpilers like TypeScript and Babel
• Cool libraries like RxJS and React
• No longer necessary for Angular to do everything
Getting started• npm install typescript -g
• git clone https://github.com/Rockncoder/quizzer-start.git
• cd quizzer-start
• npm install
• npm start
• refresh browser
npm
npm• We need Nodejs for its package manager, npm
• NPM requires a file, package.json, in the app root
• We use npm for a lot of things
• npm officially doesn’t stand for anything
• https://www.npmjs.com/
package.json• name - what this app is called, for npm it must be
• version - the current version number
• description - what this package is all about
• author - who wrote it
• repository - where it lives
package.json
• license - type of license granted to users of the package
• scripts - commands
• dependencies - packages for production
• devDependencies - packages for development
version definitions• “^1.8.9"
• 1 - is the major number
• 8 - is the minor number
• 9 - is the patch number
• patch number is not required
version symbols• "1.8.9" - must exactly match version
• ">1.8.9" - must be greater than version
• ">=1.8.9", "<1.8.9", "<=1.8.9"
• "^1.8.9"- allows changes to the minor & patch
• "~1.8.9" - allows changes to the patch
• "1.8.*" - a wild card which stands for any value here
install• The install adds a package to your app
• npm install <package name> [—save | —save-dev]
• npm i <package name> [-d | -D]
• —save: saves info to dependencies
• —save-dev: saves info to devDependencies
run-script
• npm run-script <command> <args>
• npm run <command> <args> (shortcut)
• to abort use control-c
What’s in our package.json?• angular2 - Needs no explanation
• es6-promise - A polyfill for ES6 promises
• es6-shim - A library that aligns JavaScript more closely to ES6
• reflect-metadata - Polyfill for ES7 decorators
• rxjs - a library for asynchronous and event based programming
• systemjs - a module loading system
• zone.js - for change detection
What’s in our package.json?
• concurrently - runs multiple commands concurrently
• lite-server - a light development node server
• typescript - a language for application scale JS
• typings - the typescript definition manager
Where can you look up npm info?
• https://angular.io/
• https://www.npmjs.com/
• https://angularjs.org/
• https://nodejs.org/
What’s difference between the ‘^’ and the ‘~’ in packages?
A. The ~ means any version greater than this one, while the ^ means any version less than this one
B. The ~ is a wild card but the ^ means only this version
C. The ~ allows different patch number, while the ^ allows changes to both minor and patch numbers
Angular 2
It’s not AngularJS 2• ES5
• ES6
• CoffeeScript
• Dart
• TypeScript
Deleted from Angular 2• $scope
• Data Definition Object
• angular module
• controllers
• jqLite / jQuery
Main Parts• Module
• Component
• Template
• Data binding
• Metadata
• Service
• Directive
• Dependency Injection
ES5
strict mode• 'use strict’; or "use strict;"
• First line of file or function
• Can break working code!!
• More stringent checking
• Enables ES5 features
strict mode• Variables must be declared
• Functions defined only at the top scope level
• “this” is undefined at the global level
• Throws error when you forget the 'new' keyword in constructor
• Can't use the same function parameter twice
Array Functions• .isArray()
• .every()
• .forEach()
• .indexOf()
• .lastIndexOf()
• .some()
• .map()
• .reduce()
• .filter()
forEachlet junk = [1, 2, 3, 4, 'Alpha', 5, {name: 'Jason'}]; let letters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K']; let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]; console.log(nums); // forEach iterates over the array, once for each element, but there is no way to // break outnums.forEach(function (elem, index, arr) { console.log(index + ': ' + elem); });
maplet junk = [1, 2, 3, 4, 'Alpha', 5, {name: 'Jason'}]; let letters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K']; let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]; console.log(nums); // map iterates over all of the elements and returns a new array with the same // number of elementslet nums2 = nums.map((elem) => elem * 2); console.log(nums2);
filterlet junk = [1, 2, 3, 4, 'Alpha', 5, {name: 'Jason'}]; let letters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K']; let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]; console.log(nums); // filter iterates over the array and returns a new array with only the elements // that pass the testlet nums3 = nums.filter((elem) => !!(elem % 2)); console.log(nums3);
reducelet junk = [1, 2, 3, 4, 'Alpha', 5, {name: 'Jason'}]; let letters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K']; let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]; console.log(nums); // reduce iterates over the array passing the previous value and the current// element it is up to you what the reduction does, let's concatenate the stringslet letters2 = letters.reduce((previous, current) => previous + current); console.log(letters2); // reduceRight does the same but goes from right to leftlet letters3 = letters.reduceRight((previous, current) => previous + current); console.log(letters3);
everylet junk = [1, 2, 3, 4, 'Alpha', 5, {name: 'Jason'}]; let letters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K']; let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]; console.log(nums); // every makes sure that all the elements match the expressionlet isEveryNumbers = junk.every((elem) => typeof elem === 'number'); console.log('Are all members of junk numbers: ' + isEveryNumbers);
JSON Object• JSON strings must be double quote
• key/value pairs
• key is any valid JS string
• value is an valid JS data type
• .stringify() - converts object to JSON string
• .parse() - converts JSON string to object
JSON data{ "title": "U.S. Citizenship", "tagLine": "Think you can pass this quiz of basic knowledge of American government, history, and geography?", "added": "2015-07-04T18:25:43.511Z", "rating": 3, "_id": 1, "tags": [ "history", "geography", "United States" ] }
How do you turn a JS object into a JSON string?
A. JSON.parse()
B. Math.obj()
C. .toString()
D. JSON.stringify()
ES6 (ES2015)
ES2015 aka ES6• let
• const
• Template strings
• Arrow functions
• for-of
• Classes
• Promises
• Using ES6 today
let
• let allows us to create a block scoped variables
• they live and die within their curly braces
• best practice is to use let instead of var
let// let allows us to create block scoped variables// they live and die within the curly braceslet val = 2; console.info(`val = ${val}`); { let val = 59; console.info(`val = ${val}`); } console.info(`val = ${val}`);
const
• const creates a variable that can't be changed
• best practice is to make any variable that should not change a constant
• does not apply to object properties or array elements
constconst name = 'Troy'; console.info(`My name is ${name}`); // the line below triggers a type errorname = 'Miles';
Template strings
• Defined by using opening & closing back ticks
• Templates defined by ${JavaScript value}
• The value can be any simple JavaScript expression
• Allows multi-line strings (return is pass thru)
Template strings let state = 'California'; let city = 'Long Beach'; console.info(`This weekend's workshop is in ${city}, ${state}.`); // template strings can run simple expressions like addition let cup_coffee = 4.5; let cup_tea = 2.5; console.info(`coffee: $${cup_coffee} + tea: $${cup_tea} = $${cup_coffee + cup_tea}.`); // they can allow us to create multi-line strings console.info(`This is line #1.this is line #2.`);
Arrow (lambda) functionlet anon_func = function (num1, num2) { return num1 + num2; }; console.info(`Anonymous func: ${anon_func(1, 2)}`); let arrow_func = (num1, num2) => num1 + num2; console.info(`Arrow func: ${arrow_func(3, 4)}`);
In a loop what do the break and continue instructions do?
A. break cause the program to halt all execute and continue resumes execution
B. break goes immediately to the top of the loop and continue exits the loop
C. break exits the loop and continue goes immediately to the top of the loop
for-of• for of lets us iterate over an array
• .entries() gives us the index and the element
• with destructuring we can use as variables
• unlike forEach, continue and break work
• break stop the loop
• continue stops the current iteration
for (let elem of pirateArray) { console.info(elem); } // if we want the element and its index we can get it toofor (let [index, elem] of pirateArray.entries()) { if (index === 5) { break; } console.info(`${index}. ${elem}`); } // unlike forEach, continue and break workfor (let [index, elem] of pirateArray.entries()) { if (index === 5) { continue; } console.info(`${index}. ${elem}`); }
for-of
class// class must exist before usageclass Animal { constructor(name) { this.name = name; this.legs = 2; } showNameAndLegs() { console.info(`${this.name} has ${this.legs} legs.`); } } var myBird = new Animal("Bird"); myBird.showNameAndLegs();
Promisefunction sometimesWorks() { // note: all this function does is return a promise // the promise returns immediately to the caller return new Promise( function (resolve, reject) { // number of milliseconds to delay let delay = getRandomNum(1000, 3000); setTimeout(function(){ // whether it is successful or not let worked = !!Math.floor(getRandomNum(0, 2)); if(worked){ resolve('It worked!'); } else { reject('It failed'); } }, delay); }); }
PromisesometimesWorks().then( // if it is successful, it will come here function (data) { console.info(data); }, // if it fails it will come here function (err) { console.info(err); } ); console.info('Back from promise land');
What is the difference between var and let?
A. var is scoped to blocks and let is scoped to functions
B. let allows you to create a constant, var is for variables
C. let is scoped to blocks and var is scoped to functions
D. Nothing, let is the same as var
Default parameters
• Automatically assign a value to undefined parameters
• Always taken from left to right
Default parameter example
1 var add = (x=1, y=2) => x + y; 2 console.info(add(10));
ES2016 aka ES7
• array.prototype.includes
• Exponentiation operator **
How to use modern JS now?
• Use only the latest browsers
• Use a transpiler: Babel, Traceur, Closure, TypeScript
• Use Node.js
• https://kangax.github.io/compat-table/es6/
TypeScript
JavaScript Problems• No modules, only files
• No linkage
• No static checking
• Hard to refactor
• So Google created AtScript
The death of AtScript• Google forked TypeScript,
• Called it AtScript for @ signed used annotations
• Google and Microsoft engineers met
• Microsoft added some desired functionality to TypeScript
• TypeScript became the preferred language of Angular 2
TypeScript to JavaScript
• Use system.js to compile in browser
• Use typescript command
• Use npm/system.js/typescript to auto-compile
Types• Boolean
• Number
• String
• Array
• Tuple
• Enum
• Any
• Void
Interfaces• Functions
• Properties
• Arrays
• Extends other interfaces
• How to choose interface or class?
Decorators
• A proposed standard for ES2016
• Created by Yehuda Katz (Ember)
• Implemented in TypeScript
• Implement Angular’s Annotation
Annotation• A declarative way to add metadata to an object
• Three types:
• Type
• Field
• Class
Annotation Exampleimport {Component, OnInit} from 'angular2/core'; import {QuizService} from './quiz-service'; import {ROUTER_DIRECTIVES} from 'angular2/router'; @Component({ selector: 'quiz', templateUrl: './templates/quiz.html', directives: [ROUTER_DIRECTIVES], providers: [QuizService]}) export class QuizComponent implements OnInit { quizList:IQuizList[] = []; constructor(private _quizService:QuizService){ } ngOnInit() { this.getQuiz(); } getQuiz() { this._quizService.getQuizzes().then((quiz) => { this.quizList = quiz }, (error)=>console.log(error)); } }
Modules
• Any file containing a top-level import or export is considered a module
• Modules are executed within their own scope
• Modules are declarative
• Modules import one another using a module loader
tsconfig.json{ "compilerOptions": { "target": "es5", "module": "system", "moduleResolution": "node", "sourceMap": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, "removeComments": false, "noImplicitAny": false }, "exclude": [ "node_modules", "typings/main", "typings/main.d.ts" ] }
tsconfig.json
• target: compile to this version of JS
• module: module system to use
• moduleResolution: where modules are loaded
• sourceMap: should a source map be generated
tsconfig.json• emitDecoratorMetadata: set true to include the
decorator metadata, required for Angular 2
• experimentalDecorators: should we use ES7 style decorators
• removeComments: should comments be deleted
• noImplicitAny: set true if you want super strict typing, (you probably don’t want this)
• npm install -g typescript
• git clone https://github.com/Rockncoder/quizzer-start.git
• cd quizzer-start
• npm install
• npm start
Angular 2
Bootstrapping
• Angular apps built with components
• One component is chosen by the developer to kick off the app
• This process is known as bootstrapping
Main Parts• Metadata
• Component
• Template/View
• Data Binding
• Module
• Service
• Directive
• Dependency Injection
Metadata
• Metadata is extra information which gives angular more info
• @Component tells angular the class is a component
• @Directive tells angular the class is a directive
Component• A class with component metadata
• Responsible for a piece of the screen referred to as view.
• Template is a form HTML that tells angular how to render the component.
• Metadata tells Angular how to process a class
Componentimport {Component, OnInit} from 'angular2/core'import {QuizService} from './quiz-service'@Component({ selector: 'quiz', templateUrl: './templates/quiz.html', providers: [QuizService]}) export class QuizComponent implements OnInit { quizList: IQuizList[]; constructor(private _quizService:QuizService) { } ngOnInit() { this.getQuiz(); } getQuiz() { this.quizList = this._quizService.getQuizzes(); } }
Template/View• Is a way to describe a view using HTML
• Templates can be included with the component
• Or as an URL link to an HTML file
• Best practice is to use an HTML file
• The moduleId: module.id property sets the base for module-relative loading of the templateUrl.
moduleId
• The moduleId: module.id
• Sets the base for module-relative loading of the templateUrl.
Service
• “Substitutable objects that are wired together using dependency injection (DI)”
• Used to share code across app
• Lazily instantiated
Directives
Directive• A class with directive metadata
• Two kinds: attribute & structural
• Attribute directives alter the look or behavior of an existing element
• Structural directives alter the layout by adding, removing, and replacing elements in the DOM
• All structural directives begin with “*”
• A component is a directive with a view
Directives
Directive Purpose
*ngIf adds or removes part of the DOM
*ngFor implements a template
*ngSwitchCase teams up with ngSwitch & *ngSwitchDefault
Custom Directiveimport {Directive, ElementRef, Renderer, Input, OnInit} from 'angular2/core'; @Directive({ selector: '[sizer]'}) export class Sizer implements OnInit { @Input() sizer:string; element:ELementRef; renderer:Renderer; constructor(element:ElementRef, renderer:Renderer) { this.element = element; this.renderer = renderer; } ngOnInit() { this.renderer.setElementStyle(this.element.nativeElement, 'fontSize', this.sizer + '%'); } }
Component + Directiveimport {Directive, Component, ElementRef, Renderer} from ‘@angular/core'; import {Sizer} from './sizer'@Component({ selector: 'my-app', providers: [], template: ` <div> <p [sizer]="200">Butter{{name}}</p> </div> `, directives: [Sizer]}) export class App { constructor() { this.name = 'Monkey' } }
Dependency Injection• A way to supply a new instance of a class with the
fully-formed dependencies it needs
• Most dependencies are services
• Angular know which services a components by looking at the types of its constructor parameters
• Services are injected by an Injector which uses a Provider to create the service
Module
• Modules are optional but a best practice
• export tells TypeScript that the resource is a module available for other modules
• import tells TypeScript the resource in a module
• Angular ships a collection library modules
What is the difference between a component and a directive?
• Nothing, they are the same thing.
• A component is a directive with a view.
• A directive is a decorator and a component is an attribute.
• All of the above.
Lifecycle Hooks• ngOnChanges
• ngOnInit
• ngDoCheck
• ngAfterContentInit
• ngAfterContentCheck
• ngAfterViewInit
• ngAfterViewChecked
• ngOnDestroy
Forms
Forms in Angular
• Template-Driven Forms
• Model-Driven Forms
Data Binding
C/D Attribute Binding type
—> {{ value }} one-way
—> [property] = “value” property
<— (event) = “handler” event
<—> [(ng-model)] = “property” two-way
Using Forms
• Forms module must imported
• Forms use two-way binding via [(ngModel)]
• name attribute is required on form tags
NgForm
• Added to the form element automatically
• Holds the forms controls and their validity state
• Also has it own validity
ngModel Change-StateControl State If true If false
Visited ng-touched ng-untouched
Changed ng-dirty ng-pristine
Valid ng-valid ng-invalid
Control Classes
• *.pristine - true if the user has not touched the control
• *.touched - true if the user has left the control
• *.valid - true if the control is valid
template reference variable
• #<name>=“ngModel” (template ref. variable)
• ngModel is required here
• creates a variable named, <name>
• (it relates to the directive’s exportAs property)
t.r.v. properties
• .value
• .valid / .invalid
• .pristine / .dirty
• .touched / .untouched
Firebase
Installing Firebase
• npm i -S firebase angularfire2
• Add to app module and initialize
• Import into code
• Using firebase is different than hosting on it
Firebase settings
• Go to the Firebase console
• Click on Overview
• Click on “Add Firebase to your web app”
• Copy your config settings
Configure Firebase8 import {AngularFireModule} from "angularfire2"; 9 10 export const firebaseConfig = { 11 apiKey: "AxAxAxAxAxAxAxAxAxAxAxAxAxAxAxAxAxAxAxAx", 12 authDomain: “an-app-42.firebaseapp.com”, 13 databaseURL: "https:#//an-app-42.firebaseio.com", 14 storageBucket: "an-app-42.appspot.com", 15 messagingSenderId: "xxxxxxxxxxxx" 16 }; 17 18 @NgModule({ 19 imports: [ 20 BrowserModule, 21 FormsModule, 22 HttpModule, 23 AngularFireModule.initializeApp(firebaseConfig) 24 ], 25 declarations: [ 26 AppComponent 27 ], 28 providers: [], 29 bootstrap: [AppComponent] 30 })
RxJS
Reactive Extensions
• A library for building async and event-based programs using observable data streams
• Data streams can be from a file, web service, or user input
Use Rx for…• UI events like mouse move, button click
• Domain events like property changed, collection updated, etc.
• Infrastructure events like from file watcher, system and WMI events
• Integration events like a broadcast from a message bus or a push event from WebSockets API
Observable
• Emit the next element
• Throw an error
• Send a signal that streaming is finished
Observer
• Handle the next emitted element
• Handle errors
• Handle the end of streaming
Jasmine
Jasmine• Created by Pivotal Labs in 2010
• Current version 2.5.3
• JavaScript testing framework
• The default unit test for Angular
• Can test client and server code
describe() - Test Suite• describe() is a global Jasmine function
• Takes to parameters
• name of the test suite (string)
• implementation of the suite (function)
• Can be nested
describe()describe('App: Quizzer', () => { beforeEach(() => { TestBed.configureTestingModule({ declarations: [ AppComponent ], imports: [ RouterTestingModule ] }); }); });
it() - Test Spec
• it() is a global Jasmine function
• Takes two parameters
• name of the spec (string)
• implementation of the spec (function)
it()
it(`should have as title 'Quizzer'`, async(() => { let fixture = TestBed.createComponent(AppComponent); let app = fixture.debugElement.componentInstance; expect(app.title).toEqual('Quizzer'); }));
expect() - Expectation• expect() is a global Jasmine function
• Jasmine’s version of assert()
• Takes one parameter
• The actual - value generated by code under test
• Is chained to a Matcher
Matcher
• Takes the output of the expect() function
• Takes one parameter
• The expected value
• Compares the expect and actual value using the logic of the matcher
expect()
let app = fixture.debugElement.componentInstance; expect(app).toBeTruthy(); expect(app).not.toBeUndefined(); expect(app.title).toEqual('Quizzer');
Matchers (part 1)Matcher Comparison
toBe() compares using ===
toEqual() works for literal variables and objects
toMatch() for regular expressions
toBeDefined() compares against 'undefined'
toBeUndefined() also compares against ‘undefined'
Matchers (part 2)Matcher Comparison
toBeNull() compares against null
toBeTruthy() truthy boolean casting
toBeFalsy() falsy boolean casting
toContain() finds an item in array
Matchers (part 3)Matcher Comparison
toBeLessThan() mathematical comparison
toBeGreaterThan() mathematical comparison
toBeCloseTo() precision math comparison
toThrow() should throw an exception
Angular’s MatchersMatcher Comparison
toBePromise() the value is a promise
toBeAnInstanceOf() an instance of an object
toHaveText() the element has the given text
toHaveCssClass() the element has the given CSS class
toHaveCssStyle() the element has the given CSS styles
toImplement() the class implements the given interface
Custom Matchersvar customMatchers = { toBeGoofy: function (util, customEqualityTesters) { return { compare: function (actual, expected) { if (expected === undefined) { expected = ''; } var result = {}; result.pass = util.equals(actual.hyuk, "gawrsh" + expected, customEqualityTesters); result.message = result.pass ? "Expected " + actual + " not to be quite so goofy" : "Expected " + actual + " to be goofy, but it was not very goofy"; return result; } }; } };
beforeEach()
• Setup function
• Called before each spec is executed
• A good place to add customer matchers
beforeEach()
beforeEach(function() { jasmine.addMatchers(customMatchers); });
this
• beforeEach sets the this construct to any empty object
• It is passed to each it() and afterEach()
• The modified this doesn’t flow thru from one it() to the next
afterEach()
• Teardown function
• Called after each spec is executed
Disabling suites & specs
• prepend an ‘x’
• to disable a suite change describe() to xdescribe()
• to disable a spec change it() to xit()
• They are not execute but appear in reporting
Dependency Injection is not Magic
• Dependency Injection (DI) is a core component of Angular
• It only means objects are instantiated somewhere else
• And supplied to your code when it needs them
• Angular calls DI a provider
providers@NgModule({ imports: TroyModules, declarations: [ AppComponent, AboutComponent, LoginComponent, QuizComponent, PlayerComponent, MixedPipe, BackcolorDirective, ModelComponent ], providers: [QuizService], bootstrap: [AppComponent] }) export class AppModule { }
Module InitializationKey Value
imports Modules (array)
declarations Components (array)
providers Services and other DI objects (array)
bootstrap the launch component
Unit Test & DI
• When unit testing your app you ask Angular for just enough parts to make it work
• Angular uses DI to do this
Unit Tests & Providersdescribe('Router', () => { beforeEach(() => { // acts like NgModule TestBed.configureTestingModule({ imports: [ RouterTestingModule, AppRoutingModule ], declarations: [ AppComponent, AboutComponent, LoginComponent ], providers: [ {provide: APP_BASE_HREF, useValue: '/'} ] }); });
Links
• https://angular.io/
• https://material.angular.io/
• https://github.com/systemjs/systemjs
• https://github.com/angular/angularfire2
• http://blog.angular-university.io/angular-2-firebase/
Links• http://www.sitepoint.com/angular-2-mockbackend/
• https://auth0.com/blog/2015/09/03/angular2-series-working-with-pipes/
• https://developers.livechatinc.com/blog/testing-angular-2-apps-routeroutlet-and-http/
• https://medium.com/google-developer-experts/angular-2-introduction-to-new-http-module-1278499db2a0#.xey81v6eq
Summary
• Angular 2 is simpler than AngularJS
• TypeScript is the preferred language for Angular 2
• The framework is made to be easily testable