From 5e50b2ef10d48d8fc7cb952ee89bbe2ec4f6e1f3 Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Tue, 31 May 2016 15:25:59 -0700 Subject: [PATCH 01/13] chore(util-fns): minor cleanup and refactoring (#1562) This only impacts language dependent variable and path definitions: - Removed deprecated variable. - Hoisted useful variable definitions from quickstart into _util-fns. - Minor fix in regexp of path translation function --- public/_includes/_util-fns.jade | 9 +++++++-- public/docs/dart/latest/_util-fns.jade | 8 ++++++-- public/docs/dart/latest/quickstart.jade | 2 -- public/docs/ts/latest/guide/component-styles.jade | 2 +- public/docs/ts/latest/quickstart.jade | 2 -- 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/public/_includes/_util-fns.jade b/public/_includes/_util-fns.jade index 5b46d869bb..f9ad971b95 100644 --- a/public/_includes/_util-fns.jade +++ b/public/_includes/_util-fns.jade @@ -23,13 +23,18 @@ //- TS arrays vs. Dart lists - var _Array = 'Array'; - var _array = 'array'; -//- Deprecate now that we have the articles _a and _an -- var _an_array = 'an array'; //- Promise vs. Future, etc - var _Promise = 'Promise'; +- var _PromiseUrl = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise'; +- var _PromiseLinked = '' + _Promise + ''; - var _Observable = 'Observable'; +//- Directories & folders +- var _appDir = 'app'; +- var _indexHtmlDir = 'project root'; +- var _mainDir = _appDir; + //- Location of sample code - var _liveLink = 'live link'; diff --git a/public/docs/dart/latest/_util-fns.jade b/public/docs/dart/latest/_util-fns.jade index 432da3b7fd..9bd0289b4a 100644 --- a/public/docs/dart/latest/_util-fns.jade +++ b/public/docs/dart/latest/_util-fns.jade @@ -5,16 +5,20 @@ include ../../../_includes/_util-fns - var _decorator = 'annotation'; - var _Array = 'List'; - var _array = 'list'; -- var _an_array = 'a list'; //- Deprecate now that we have the articles - var _a = 'an'; - var _an = 'a'; - var _priv = '_'; - var _Lang = 'Dart'; - var _Promise = 'Future'; +- var _FutureUrl = 'https://api.dartlang.org/dart_async/Future.html'; +- var _PromiseLinked = '' + _Promise + ''; - var _Observable = 'Stream'; - var _liveLink = 'sample repo'; - var _truthy = 'true'; - var _falsey = 'false'; +- var _appDir = 'lib'; +- var _indexHtmlDir = 'web'; +- var _mainDir = 'web'; mixin liveExampleLink(linkText, exampleUrlPartName) - var text = linkText || 'live example'; @@ -36,7 +40,7 @@ mixin liveExampleLink2(linkText, exampleUrlPartName) - // if(extn == 'dart') return path; - var baseName = getBaseFileName(path) || path; // TODO: have getBaseFileName() return path - var baseNameNoExt = baseName.substr(0,baseName.length - (extn.length + 1)); -- var inWebFolder = baseNameNoExt.match(/^(main|index(\.\d)?)$/); +- var inWebFolder = baseNameNoExt.match(/^(main|index)(\.\d)?$/); - // Adjust the folder path, e.g., ts -> dart - folder = folder.replace(/(^|\/)ts($|\/)/, '$1dart$2').replace(/(^|\/)app($|\/)/, inWebFolder ? '$1web$2' : '$1lib$2'); - // Special case not handled above: e.g., index.html -> web/index.html diff --git a/public/docs/dart/latest/quickstart.jade b/public/docs/dart/latest/quickstart.jade index 46424744ab..10955b42f5 100644 --- a/public/docs/dart/latest/quickstart.jade +++ b/public/docs/dart/latest/quickstart.jade @@ -6,8 +6,6 @@ block includes - var _prereq = 'the Dart SDK' - var _angular_browser_uri = 'package:angular2/platform/browser.dart' - var _angular_core_uri = 'package:angular2/core.dart' - - var _appDir = 'lib' - - var _indexHtmlDir = 'web' block setup-tooling :marked diff --git a/public/docs/ts/latest/guide/component-styles.jade b/public/docs/ts/latest/guide/component-styles.jade index 4d090a2e9c..baca8c401d 100644 --- a/public/docs/ts/latest/guide/component-styles.jade +++ b/public/docs/ts/latest/guide/component-styles.jade @@ -31,7 +31,7 @@ p Run the #[+liveExampleLink2()] of the code shown in this chapter. specifying any selectors, rules, and media queries that we need. One way to do this is to set the `styles` property in the component metadata. - The `styles` property takes #{_an_array} of strings that contain CSS code. + The `styles` property takes #{_an} #{_array} of strings that contain CSS code. Usually we give it one string as in this example: +makeExample('component-styles/ts/app/hero-app.component.ts')(format='.') diff --git a/public/docs/ts/latest/quickstart.jade b/public/docs/ts/latest/quickstart.jade index 1d0ad35a80..a77ae3a0b3 100644 --- a/public/docs/ts/latest/quickstart.jade +++ b/public/docs/ts/latest/quickstart.jade @@ -4,8 +4,6 @@ block includes - var _prereq = 'Node.js' - var _angular_browser_uri = '@angular/platform-browser-dynamic' - var _angular_core_uri = '@angular/core' - - var _appDir = 'app' - - var _indexHtmlDir = 'project root' :marked Our QuickStart goal is to build and run a super-simple From ae2d8f27306c940bc127560649eb7fda8c10f291 Mon Sep 17 00:00:00 2001 From: Ward Bell Date: Tue, 31 May 2016 18:36:22 -0700 Subject: [PATCH 02/13] docs(template-syntax): add brief example of HTML sanitization in binding. Also clarified interpolation v. property binding example for PR #1564 --- .../template-syntax/ts/app/app.component.html | 13 +- .../template-syntax/ts/app/app.component.ts | 123 +++++++++--------- .../docs/ts/latest/guide/template-syntax.jade | 20 ++- .../devguide/template-syntax/evil-title.png | Bin 0 -> 32206 bytes 4 files changed, 92 insertions(+), 64 deletions(-) create mode 100644 public/resources/images/devguide/template-syntax/evil-title.png diff --git a/public/docs/_examples/template-syntax/ts/app/app.component.html b/public/docs/_examples/template-syntax/ts/app/app.component.html index ed43a2ff33..57f73c4cb2 100644 --- a/public/docs/_examples/template-syntax/ts/app/app.component.html +++ b/public/docs/_examples/template-syntax/ts/app/app.component.html @@ -197,13 +197,18 @@ button -Interpolated:
-Property bound: +

is the interpolated image.

+

is the property bound image.

-
The interpolated title is {{title}}
-
+

"{{title}}" is the interpolated title.

+

"" is the property bound title.

+ +

"{{evilTitle}}" is the interpolated evil title.

+

"" is the property bound evil title.

+ + top diff --git a/public/docs/_examples/template-syntax/ts/app/app.component.ts b/public/docs/_examples/template-syntax/ts/app/app.component.ts index 33ddaa9bf1..c4e32c74d1 100644 --- a/public/docs/_examples/template-syntax/ts/app/app.component.ts +++ b/public/docs/_examples/template-syntax/ts/app/app.component.ts @@ -1,4 +1,5 @@ -//#docplaster +/* tslint:disable:member-ordering forin */ +// #docplaster import { AfterViewInit, Component, ElementRef, OnInit, QueryList, ViewChildren } from '@angular/core'; import { NgForm } from '@angular/common'; @@ -8,7 +9,7 @@ import { HeroDetailComponent, BigHeroDetailComponent } from './hero-detail.compo import { MyClickDirective, MyClickDirective2 } from './my-click.directive'; // Alerter fn: monkey patch during test -export function alerter(msg?:string) { +export function alerter(msg?: string) { window.alert(msg); } @@ -27,7 +28,7 @@ export enum Color {Red, Green, Blue}; }) export class AppComponent implements AfterViewInit, OnInit { - ngOnInit(){ + ngOnInit() { this.refreshHeroes(); } @@ -40,43 +41,48 @@ export class AppComponent implements AfterViewInit, OnInit { badCurly = 'bad curly'; classes = 'special'; - callFax(value:string) {this.alert(`Faxing ${value} ...`)} - callPhone(value:string) {this.alert(`Calling ${value} ...`)} + callFax(value: string) {this.alert(`Faxing ${value} ...`); } + callPhone(value: string) {this.alert(`Calling ${value} ...`); } canSave = true; Color = Color; color = Color.Red; - colorToggle() {this.color = (this.color === Color.Red)? Color.Blue : Color.Red} + colorToggle() {this.color = (this.color === Color.Red) ? Color.Blue : Color.Red; } currentHero = Hero.MockHeroes[0]; - deleteHero(hero:Hero){ - this.alert('Deleted hero: '+ (hero && hero.firstName)) + deleteHero(hero: Hero) { + this.alert('Deleted hero: ' + (hero && hero.firstName)); } - // DevMode memoization fields - private priorClasses:{}; - private _priorStyles:{}; - private _priorStyles2:{}; + // #docregion evil-title + evilTitle = 'Template Syntax'; + // #enddocregion evil-title - getStyles(el:Element){ + title = 'Template Syntax'; + + // DevMode memoization fields + private priorClasses: {}; + private _priorStyles: {}; + + getStyles(el: Element) { let styles = window.getComputedStyle(el); let showStyles = {}; - for (var p in this.setStyles()){ + for (let p in this.setStyles()) { showStyles[p] = styles[p]; } return JSON.stringify(showStyles); } - getVal() {return this.val}; + getVal() { return this.val; } - heroes:Hero[]; + heroes: Hero[]; // heroImageUrl = 'http://www.wpclipart.com/cartoon/people/hero/hero_silhoutte_T.png'; // Public Domain terms of use: http://www.wpclipart.com/terms.html heroImageUrl = 'images/hero.png'; - //iconUrl = 'https://angular.io/resources/images/logos/standard/shield-large.png'; + // iconUrl = 'https://angular.io/resources/images/logos/standard/shield-large.png'; clicked = ''; clickMessage = ''; clickMessage2 = ''; @@ -85,28 +91,28 @@ export class AppComponent implements AfterViewInit, OnInit { isSpecial = true; isUnchanged = true; - nullHero:Hero = null; // or undefined + nullHero: Hero = null; // or undefined - onCancel(event:KeyboardEvent){ - let evtMsg = event ? ' Event target is '+ (event.target).innerHTML : ''; - this.alert('Canceled.'+evtMsg) + onCancel(event: KeyboardEvent) { + let evtMsg = event ? ' Event target is ' + (event.target).innerHTML : ''; + this.alert('Canceled.' + evtMsg); } - onClickMe(event:KeyboardEvent){ - let evtMsg = event ? ' Event target class is '+ (event.target).className : ''; - this.alert('Click me.'+evtMsg) + onClickMe(event: KeyboardEvent) { + let evtMsg = event ? ' Event target class is ' + (event.target).className : ''; + this.alert('Click me.' + evtMsg); } - onSave(event:KeyboardEvent){ - let evtMsg = event ? ' Event target is '+ (event.target).innerText : ''; - this.alert('Saved.'+evtMsg) + onSave(event: KeyboardEvent) { + let evtMsg = event ? ' Event target is ' + (event.target).innerText : ''; + this.alert('Saved.' + evtMsg); } - onSubmit(form:NgForm){ + onSubmit(form: NgForm) { let evtMsg = form.valid ? - ' Form value is '+ JSON.stringify(form.value) : + ' Form value is ' + JSON.stringify(form.value) : ' Form is invalid'; - this.alert('Form submitted.'+evtMsg) + this.alert('Form submitted.' + evtMsg); } product = { @@ -123,10 +129,10 @@ export class AppComponent implements AfterViewInit, OnInit { // #docregion same-as-it-ever-was private samenessCount = 5; - moreOfTheSame() {this.samenessCount++;}; + moreOfTheSame() { this.samenessCount++; }; get sameAsItEverWas() { - var result:string[] = Array(this.samenessCount); - for (var i=result.length; i-- > 0;){result[i]='same as it ever was ...'} + let result: string[] = Array(this.samenessCount); + for ( let i = result.length; i-- > 0; ) { result[i] = 'same as it ever was ...'; } return result; // return [1,2,3,4,5].map(id => { // return {id:id, text: 'same as it ever was ...'}; @@ -134,8 +140,8 @@ export class AppComponent implements AfterViewInit, OnInit { } // #enddocregion same-as-it-ever-was - setUpperCaseFirstName(firstName:string){ - //console.log(firstName); + setUpperCaseFirstName(firstName: string) { + // console.log(firstName); this.currentHero.firstName = firstName.toUpperCase(); } @@ -145,10 +151,10 @@ export class AppComponent implements AfterViewInit, OnInit { saveable: this.canSave, // true modified: !this.isUnchanged, // false special: this.isSpecial, // true - } + }; // #enddocregion setClasses // compensate for DevMode (sigh) - if (JSON.stringify(classes) === JSON.stringify(this.priorClasses)){ + if (JSON.stringify(classes) === JSON.stringify(this.priorClasses)) { return this.priorClasses; } this.priorClasses = classes; @@ -165,10 +171,10 @@ export class AppComponent implements AfterViewInit, OnInit { 'font-style': this.canSave ? 'italic' : 'normal', // italic 'font-weight': !this.isUnchanged ? 'bold' : 'normal', // normal 'font-size': this.isSpecial ? '24px' : '8px', // 24px - } + }; // #enddocregion setStyles // compensate for DevMode (sigh) - if (JSON.stringify(styles) === JSON.stringify(this._priorStyles)){ + if (JSON.stringify(styles) === JSON.stringify(this._priorStyles)) { return this._priorStyles; } this._priorStyles = styles; @@ -178,15 +184,14 @@ export class AppComponent implements AfterViewInit, OnInit { // #enddocregion setStyles toeChoice = ''; - toeChooser(picker:HTMLFieldSetElement){ + toeChooser(picker: HTMLFieldSetElement) { let choices = picker.children; - for (let i=0; ichoices[i]; - if (choice.checked) {return this.toeChoice = choice.value} + for (let i = 0; i < choices.length; i++) { + let choice = choices[i]; + if (choice.checked) {return this.toeChoice = choice.value; } } } - title = 'Template Syntax'; // #docregion trackByHeroes trackByHeroes(index: number, hero: Hero) { return hero.id; } @@ -196,18 +201,18 @@ export class AppComponent implements AfterViewInit, OnInit { trackById(index: number, item: any): string { return item['id']; } // #enddocregion trackById - val=2; - // villainImageUrl = 'http://www.clker.com/cliparts/u/s/y/L/x/9/villain-man-hi.png' + val = 2; + // villainImageUrl = 'http://www.clker.com/cliparts/u/s/y/L/x/9/villain-man-hi.png' // Public Domain terms of use http://www.clker.com/disclaimer.html - villainImageUrl = 'images/villain.png' + villainImageUrl = 'images/villain.png'; //////// Detect effects of NgForTrackBy /////////////// - @ViewChildren('noTrackBy') childrenNoTrackBy:QueryList; - @ViewChildren('withTrackBy') childrenWithTrackBy:QueryList; + @ViewChildren('noTrackBy') childrenNoTrackBy: QueryList; + @ViewChildren('withTrackBy') childrenWithTrackBy: QueryList; - private _oldNoTrackBy:HTMLElement[]; - private _oldWithTrackBy:HTMLElement[]; + private _oldNoTrackBy: HTMLElement[]; + private _oldWithTrackBy: HTMLElement[]; heroesNoTrackByChangeCount = 0; heroesWithTrackByChangeCount = 0; @@ -216,32 +221,32 @@ export class AppComponent implements AfterViewInit, OnInit { this._oldNoTrackBy = toArray(this.childrenNoTrackBy); this._oldWithTrackBy = toArray(this.childrenWithTrackBy); - this.childrenNoTrackBy.changes.subscribe((changes:any) => { + this.childrenNoTrackBy.changes.subscribe((changes: any) => { let newNoTrackBy = toArray(changes); - let isSame = this._oldNoTrackBy.every((v:any, i:number) => v === newNoTrackBy[i]); + let isSame = this._oldNoTrackBy.every((v: any, i: number) => v === newNoTrackBy[i]); if (!isSame) { this._oldNoTrackBy = newNoTrackBy; this.heroesNoTrackByChangeCount++; } - }) + }); - this.childrenWithTrackBy.changes.subscribe((changes:any) => { + this.childrenWithTrackBy.changes.subscribe((changes: any) => { let newWithTrackBy = toArray(changes); - let isSame = this._oldWithTrackBy.every((v:any, i:number) => v === newWithTrackBy[i]); + let isSame = this._oldWithTrackBy.every((v: any, i: number) => v === newWithTrackBy[i]); if (!isSame) { this._oldWithTrackBy = newWithTrackBy; this.heroesWithTrackByChangeCount++; } - }) + }); } /////////////////// } // helper to convert viewChildren to an array of HTMLElements -function toArray(viewChildren:QueryList) { +function toArray(viewChildren: QueryList) { let result: HTMLElement[] = []; let children = viewChildren.toArray()[0].nativeElement.children; - for (var i = 0; i < children.length; i++) { result.push(children[i]); } + for (let i = 0; i < children.length; i++) { result.push(children[i]); } return result; } diff --git a/public/docs/ts/latest/guide/template-syntax.jade b/public/docs/ts/latest/guide/template-syntax.jade index 9f1e008a79..dbf8281515 100644 --- a/public/docs/ts/latest/guide/template-syntax.jade +++ b/public/docs/ts/latest/guide/template-syntax.jade @@ -568,7 +568,8 @@ a(id="one-time-initialization") The `[hero]` binding, on the other hand, remains a live binding to the component's `currentHero` property. ### Property binding or interpolation? - We often have a choice between interpolation and property binding. The following binding pairs do the same thing: + We often have a choice between interpolation and property binding. + The following binding pairs do the same thing: +makeExample('template-syntax/ts/app/app.component.html', 'property-binding-vs-interpolation')(format=".") :marked Interpolation is a convenient alternative for property binding in many cases. @@ -580,6 +581,23 @@ a(id="one-time-initialization") We suggest establishing coding style rules and choosing the form that both conforms to the rules and feels most natural for the task at hand. + +:marked + #### Content Security + Imagine the following *malicious content*. ++makeExample('template-syntax/ts/app/app.component.ts', 'evil-title')(format=".") +:marked + Fortunately, Angular data binding is on alert for dangerous HTML. + It *sanitizes* the values before displaying them. + It **will not** allow HTML with script tags to leak into the browser, neither with interpolation + nor property binding. ++makeExample('template-syntax/ts/app/app.component.html', 'property-binding-vs-interpolation-sanitization')(format=".") +:marked + Interpolation handles the script tags differently than property binding but both approaches render the + content harmlessly. +figure.image-display + img(src='/resources/images/devguide/template-syntax/evil-title.png' alt="evil title made safe" width='500px') + .l-main-section :marked diff --git a/public/resources/images/devguide/template-syntax/evil-title.png b/public/resources/images/devguide/template-syntax/evil-title.png new file mode 100644 index 0000000000000000000000000000000000000000..9c67d7189457aff7d8750ed1bef3f191fd34d637 GIT binary patch literal 32206 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 literal 0 HcmV?d00001 From 8a5df4cfa9b19da77ac87184ab2217fd1fc1259f Mon Sep 17 00:00:00 2001 From: Ward Bell Date: Mon, 30 May 2016 11:05:09 -0700 Subject: [PATCH 03/13] chore: support e2e-specs written in TypeScript Update gulpfile and project to add a tsconfig to protractor test folders Change all sample e2e-spec.js -> e2e-spec.ts Split typings between e2e-spec & app code Use same config for all e2e tests Only 1/3 e2e specs truly converted. Most don't pass because they fail TS transpile by Protractor due to missing type annotations --- .travis.yml | 3 +- gulpfile.js | 157 ++++++++----- public/docs/_examples/_protractor/e2e.d.ts | 14 ++ .../docs/_examples/_protractor/package.json | 19 ++ .../{ => _protractor}/protractor.config.js | 15 +- .../docs/_examples/_protractor/tsconfig.json | 16 ++ .../docs/_examples/_protractor/typings.json | 9 + .../architecture/{e2e-spec.js => e2e-spec.ts} | 27 ++- .../{e2e-spec.js => e2e-spec.ts} | 14 +- .../{e2e-spec.js => e2e-spec.ts} | 49 ++-- .../{e2e-spec.js => e2e-spec.ts} | 121 +++++----- .../{e2e-spec.js => e2e-spec.ts} | 9 +- .../{e2e-spec.js => e2e-spec.ts} | 115 ++++----- .../{e2e-spec.js => e2e-spec.ts} | 18 +- .../{e2e-spec.js => e2e-spec.ts} | 3 +- .../cb-ts-to-js/{e2e-spec.js => e2e-spec.ts} | 25 +- .../{e2e-spec.js => e2e-spec.ts} | 27 ++- .../{e2e-spec.js => e2e-spec.ts} | 37 +-- .../{e2e-spec.js => e2e-spec.ts} | 7 +- .../forms/{e2e-spec.js => e2e-spec.ts} | 27 ++- .../{e2e-spec.js => e2e-spec.ts} | 13 +- .../{e2e-spec.js => e2e-spec.ts} | 12 +- .../{e2e-spec.js => e2e-spec.ts} | 4 +- .../{e2e-spec.js => e2e-spec.ts} | 4 +- .../{e2e-spec.js => e2e-spec.ts} | 75 +++--- public/docs/_examples/package.json | 1 + .../pipes/{e2e-spec.js => e2e-spec.ts} | 37 +-- .../quickstart/{e2e-spec.js => e2e-spec.ts} | 4 +- .../_examples/router-deprecated/e2e-spec.js | 222 +++++++++--------- .../_examples/router-deprecated/e2e-spec.ts | 124 ++++++++++ .../router/{e2e-spec.js => e2e-spec.ts} | 25 +- .../{e2e-spec.js => e2e-spec.ts} | 33 +-- .../{e2e-spec.js => e2e-spec.ts} | 27 ++- .../style-guide/{e2e-spec.js => e2e-spec.ts} | 59 ++--- public/docs/_examples/styleguide/e2e-spec.js | 27 --- public/docs/_examples/styleguide/e2e-spec.ts | 28 +++ .../{e2e-spec.js => e2e-spec.ts} | 9 +- .../toh-5/{e2e-spec.js => e2e-spec.ts} | 27 ++- .../toh-6/{e2e-spec.js => e2e-spec.ts} | 83 +++---- .../{e2e-spec.js => e2e-spec.ts} | 1 + .../{e2e-spec.js => e2e-spec.ts} | 21 +- .../{e2e-spec.js => e2e-spec.ts} | 21 +- .../{e2e-spec.js => e2e-spec.ts} | 25 +- .../user-input/{e2e-spec.js => e2e-spec.ts} | 53 +++-- 44 files changed, 954 insertions(+), 693 deletions(-) create mode 100644 public/docs/_examples/_protractor/e2e.d.ts create mode 100644 public/docs/_examples/_protractor/package.json rename public/docs/_examples/{ => _protractor}/protractor.config.js (96%) create mode 100644 public/docs/_examples/_protractor/tsconfig.json create mode 100644 public/docs/_examples/_protractor/typings.json rename public/docs/_examples/architecture/{e2e-spec.js => e2e-spec.ts} (70%) rename public/docs/_examples/attribute-directives/{e2e-spec.js => e2e-spec.ts} (54%) rename public/docs/_examples/cb-a1-a2-quick-reference/{e2e-spec.js => e2e-spec.ts} (66%) rename public/docs/_examples/cb-component-communication/{e2e-spec.js => e2e-spec.ts} (57%) rename public/docs/_examples/cb-component-relative-paths/{e2e-spec.js => e2e-spec.ts} (81%) rename public/docs/_examples/cb-dependency-injection/{e2e-spec.js => e2e-spec.ts} (56%) rename public/docs/_examples/cb-dynamic-form/{e2e-spec.js => e2e-spec.ts} (65%) rename public/docs/_examples/cb-set-document-title/{e2e-spec.js => e2e-spec.ts} (88%) rename public/docs/_examples/cb-ts-to-js/{e2e-spec.js => e2e-spec.ts} (73%) rename public/docs/_examples/component-styles/{e2e-spec.js => e2e-spec.ts} (69%) rename public/docs/_examples/dependency-injection/{e2e-spec.js => e2e-spec.ts} (89%) rename public/docs/_examples/displaying-data/{e2e-spec.js => e2e-spec.ts} (80%) rename public/docs/_examples/forms/{e2e-spec.js => e2e-spec.ts} (69%) rename public/docs/_examples/hierarchical-dependency-injection/{e2e-spec.js => e2e-spec.ts} (79%) rename public/docs/_examples/homepage-hello-world/{e2e-spec.js => e2e-spec.ts} (77%) rename public/docs/_examples/homepage-tabs/{e2e-spec.js => e2e-spec.ts} (75%) rename public/docs/_examples/homepage-todo/{e2e-spec.js => e2e-spec.ts} (76%) rename public/docs/_examples/lifecycle-hooks/{e2e-spec.js => e2e-spec.ts} (76%) rename public/docs/_examples/pipes/{e2e-spec.js => e2e-spec.ts} (78%) rename public/docs/_examples/quickstart/{e2e-spec.js => e2e-spec.ts} (71%) create mode 100644 public/docs/_examples/router-deprecated/e2e-spec.ts rename public/docs/_examples/router/{e2e-spec.js => e2e-spec.ts} (88%) rename public/docs/_examples/server-communication/{e2e-spec.js => e2e-spec.ts} (80%) rename public/docs/_examples/structural-directives/{e2e-spec.js => e2e-spec.ts} (76%) rename public/docs/_examples/style-guide/{e2e-spec.js => e2e-spec.ts} (69%) delete mode 100644 public/docs/_examples/styleguide/e2e-spec.js create mode 100644 public/docs/_examples/styleguide/e2e-spec.ts rename public/docs/_examples/template-syntax/{e2e-spec.js => e2e-spec.ts} (74%) rename public/docs/_examples/toh-5/{e2e-spec.js => e2e-spec.ts} (87%) rename public/docs/_examples/toh-6/{e2e-spec.js => e2e-spec.ts} (77%) rename public/docs/_examples/upgrade-adapter/{e2e-spec.js => e2e-spec.ts} (99%) rename public/docs/_examples/upgrade-phonecat-1-typescript/{e2e-spec.js => e2e-spec.ts} (79%) rename public/docs/_examples/upgrade-phonecat-2-hybrid/{e2e-spec.js => e2e-spec.ts} (80%) rename public/docs/_examples/upgrade-phonecat-3-final/{e2e-spec.js => e2e-spec.ts} (79%) rename public/docs/_examples/user-input/{e2e-spec.js => e2e-spec.ts} (65%) diff --git a/.travis.yml b/.travis.yml index 7142337909..f09411f763 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,7 +18,8 @@ before_script: install: - npm install --no-optional - npm install --prefix public/docs/_examples - - npm run webdriver:update --prefix public/docs/_examples + - npm install --prefix public/docs/_examples/_protractor + - npm run webdriver:update --prefix public/docs/_examples/_protractor - gulp add-example-boilerplate script: - gulp $SCRIPT \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index d79372c5b0..1939310352 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -38,6 +38,7 @@ var TEMP_PATH = './_temp'; var DOCS_PATH = path.join(PUBLIC_PATH, 'docs'); var EXAMPLES_PATH = path.join(DOCS_PATH, '_examples'); +var EXAMPLES_PROTRACTOR_PATH = path.join(EXAMPLES_PATH, '_protractor'); var NOT_API_DOCS_GLOB = path.join(PUBLIC_PATH, './{docs/*/latest/!(api),!(docs)}/**/*'); var RESOURCES_PATH = path.join(PUBLIC_PATH, 'resources'); var LIVE_EXAMPLES_PATH = path.join(RESOURCES_PATH, 'live-examples'); @@ -86,107 +87,134 @@ var _exampleBoilerplateFiles = [ var _exampleDartWebBoilerPlateFiles = ['styles.css']; +var _exampleProtractorBoilerplateFiles = [ + 'tsconfig.json' +]; + +/** + * Run Protractor End-to-End Specs for Doc Samples + * Alias for 'run-e2e-tests' + */ +gulp.task('e2e', runE2e); + +gulp.task('run-e2e-tests', runE2e); + /** * Run Protractor End-to-End Tests for Doc Samples * * Flags * --filter to filter/select _example app subdir names - * e.g. gulp run-e2e-tests --filter=foo // all example apps with 'foo' in their folder names. + * e.g. gulp e2e --filter=foo // all example apps with 'foo' in their folder names. * * --fast by-passes the npm install and webdriver update * Use it for repeated test runs (but not the FIRST run) - * e.g. gulp run-e2e-tests --fast + * e.g. gulp e2e --fast * * --lang to filter by code language - * e.g. gulp run-e2e-tests --lang=ts // only TypeScript apps + * e.g. gulp e2e --lang=ts // only TypeScript apps * default is (ts|js) * all means (ts|js|dart) */ -gulp.task('run-e2e-tests', function() { +function runE2e() { var promise; if (argv.fast) { // fast; skip all setup promise = Promise.resolve(true); } else { - // Not 'fast'; do full setup + /* + // Not 'fast'; do full setup var spawnInfo = spawnExt('npm', ['install'], { cwd: EXAMPLES_PATH}); promise = spawnInfo.promise.then(function() { copyExampleBoilerplate(); spawnInfo = spawnExt('npm', ['run', 'webdriver:update'], {cwd: EXAMPLES_PATH}); return spawnInfo.promise; }); - } + */ + // Not 'fast'; do full setup + gutil.log('runE2e: install _protractor stuff'); + var spawnInfo = spawnExt('npm', ['install'], { cwd: EXAMPLES_PROTRACTOR_PATH}); + promise = spawnInfo.promise + .then(function() { + gutil.log('runE2e: install _examples stuff'); + spawnInfo = spawnExt('npm', ['install'], { cwd: EXAMPLES_PATH}) + return spawnInfo.promise; + }) + .then(function() { + copyExampleBoilerplate(); + gutil.log('runE2e: update webdriver'); + spawnInfo = spawnExt('npm', ['run', 'webdriver:update'], {cwd: EXAMPLES_PROTRACTOR_PATH}); + return spawnInfo.promise; + }); + }; + + var outputFile = path.join(process.cwd(), 'protractor-results.txt'); promise.then(function() { - return findAndRunE2eTests(argv.filter); + return findAndRunE2eTests(argv.filter, outputFile); }).then(function(status) { - reportStatus(status); + reportStatus(status, outputFile); if (status.failed.length > 0){ return Promise.reject('Some test suites failed'); } }).catch(function(e) { gutil.log(e); - process.exit(1); + process.exitCode = 1; }); -}); + return promise; +} // finds all of the *e2e-spec.tests under the _examples folder along // with the corresponding apps that they should run under. Then run // each app/spec collection sequentially. -function findAndRunE2eTests(filter) { +function findAndRunE2eTests(filter, outputFile) { + + // create an output file with header. var lang = (argv.lang || '(ts|js)').toLowerCase(); if (lang === 'all') { lang = '(ts|js|dart)'; } var startTime = new Date().getTime(); - // create an output file with header. - var outputFile = path.join(process.cwd(), 'protractor-results.txt'); - var header = `Doc Sample Protractor Results for ${lang} on ${new Date().toLocaleString()}\n`; header += argv.fast ? ' Fast Mode (--fast): no npm install, webdriver update, or boilerplate copy\n' : ' Slow Mode: npm install, webdriver update, and boilerplate copy\n'; header += ` Filter: ${filter ? filter : 'All tests'}\n\n`; - fs.writeFileSync(outputFile, header); // create an array of combos where each // combo consists of { examplePath: ... , protractorConfigFilename: ... } - var exeConfigs = []; + var examplePaths = []; var e2eSpecPaths = getE2eSpecPaths(EXAMPLES_PATH); - var srcConfig = path.join(EXAMPLES_PATH, 'protractor.config.js'); - e2eSpecPaths.forEach(function(specPath) { + e2eSpecPaths.forEach(function(specPath) { var destConfig = path.join(specPath, 'protractor.config.js'); - fsExtra.copySync(srcConfig, destConfig); // get all of the examples under each dir where a pcFilename is found - examplePaths = getExamplePaths(specPath, true); + localExamplePaths = getExamplePaths(specPath, true); // Filter by language - examplePaths = examplePaths.filter(function (fn) { + localExamplePaths = localExamplePaths.filter(function (fn) { return fn.match('/'+lang+'$') != null; }); if (filter) { - examplePaths = examplePaths.filter(function (fn) { + localExamplePaths = localExamplePaths.filter(function (fn) { return fn.match(filter) != null; }) } - examplePaths.forEach(function(exPath) { - exeConfigs.push( { examplePath: exPath, protractorConfigFilename: destConfig }); + localExamplePaths.forEach(function(examplePath) { + examplePaths.push(examplePath); }) }); // run the tests sequentially var status = { passed: [], failed: [] }; - return exeConfigs.reduce(function (promise, combo) { + return examplePaths.reduce(function (promise, examplePath) { return promise.then(function () { - var isDart = combo.examplePath.indexOf('/dart') > -1; + var isDart = examplePath.indexOf('/dart') > -1; var runTests = isDart ? runE2eDartTests : runE2eTsTests; - return runTests(combo.examplePath, combo.protractorConfigFilename, outputFile).then(function(ok) { + return runTests(examplePath, outputFile).then(function(ok) { var arr = ok ? status.passed : status.failed; - arr.push(combo.examplePath); + arr.push(examplePath); }) }); }, Q.resolve()).then(function() { var stopTime = new Date().getTime(); status.elapsedTime = (stopTime - startTime)/1000; - fs.appendFileSync(outputFile, '\nElaped Time: ' + status.elapsedTime + ' seconds'); return status; }); } @@ -194,15 +222,15 @@ function findAndRunE2eTests(filter) { // start the example in appDir; then run protractor with the specified // fileName; then shut down the example. All protractor output is appended // to the outputFile. -function runE2eTsTests(appDir, protractorConfigFilename, outputFile) { +function runE2eTsTests(appDir, outputFile) { // start the app var appRunSpawnInfo = spawnExt('npm',['run','http-server:e2e', '--', '-s' ], { cwd: appDir }); var tscRunSpawnInfo = spawnExt('npm',['run','tsc'], { cwd: appDir }); - return runProtractor(tscRunSpawnInfo.promise, appDir, appRunSpawnInfo, protractorConfigFilename, outputFile); + return runProtractor(tscRunSpawnInfo.promise, appDir, appRunSpawnInfo, outputFile); } -function runProtractor(prepPromise, appDir, appRunSpawnInfo, protractorConfigFilename, outputFile) { +function runProtractor(prepPromise, appDir, appRunSpawnInfo, outputFile) { return prepPromise .catch(function(){ var emsg = `AppDir failed during compile: ${appDir}\n\n`; @@ -212,10 +240,10 @@ function runProtractor(prepPromise, appDir, appRunSpawnInfo, protractorConfigFil }) .then(function (data) { // start protractor - var pcFilename = path.resolve(protractorConfigFilename); // need to resolve because we are going to be running from a different dir - var spawnInfo = spawnExt('npm', [ 'run', 'protractor', '--', pcFilename, - '--params.appDir=' + appDir, '--params.outputFile=' + outputFile], { cwd: EXAMPLES_PATH }); - return spawnInfo.promise + var specFilename = path.resolve(`${appDir}/../e2e-spec.ts`); + var spawnInfo = spawnExt('npm', [ 'run', 'protractor', '--', 'protractor.config.js', + `--specs=${specFilename}`, '--params.appDir=' + appDir, '--params.outputFile=' + outputFile], { cwd: EXAMPLES_PROTRACTOR_PATH }); + return spawnInfo.promise; }) .then( function() { return finish(true);}, @@ -233,7 +261,7 @@ function runProtractor(prepPromise, appDir, appRunSpawnInfo, protractorConfigFil // start the server in appDir/build/web; then run protractor with the specified // fileName; then shut down the example. All protractor output is appended // to the outputFile. -function runE2eDartTests(appDir, protractorConfigFilename, outputFile) { +function runE2eDartTests(appDir, outputFile) { var deployDir = path.resolve(path.join(appDir, 'build/web')); gutil.log('AppDir for Dart e2e: ' + appDir); gutil.log('Deploying from: ' + deployDir); @@ -247,24 +275,28 @@ function runE2eDartTests(appDir, protractorConfigFilename, outputFile) { var prepPromise = pubUpgradeSpawnInfo.promise.then(function (data) { return spawnExt('pub', ['build'], { cwd: appDir }).promise; }); - return runProtractor(prepPromise, appDir, appRunSpawnInfo, protractorConfigFilename, outputFile); + return runProtractor(prepPromise, appDir, appRunSpawnInfo, outputFile); } -function reportStatus(status) { - gutil.log('Suites passed:'); +function reportStatus(status, outputFile) { + var log = ['']; + log.push('Suites passed:'); status.passed.forEach(function(val) { - gutil.log(' ' + val); + log.push(' ' + val); }); if (status.failed.length == 0) { - gutil.log('All tests passed'); + log.push('All tests passed'); } else { - gutil.log('Suites failed:'); + log.push('Suites failed:'); status.failed.forEach(function (val) { - gutil.log(' ' + val); + log.push(' ' + val); }); } - gutil.log('Elapsed time: ' + status.elapsedTime + ' seconds'); + log.push('\nElapsed time: ' + status.elapsedTime + ' seconds'); + var log = log.join('\n'); + gutil.log(log); + fs.appendFileSync(outputFile, log); } // returns both a promise and the spawned process so that it can be killed if needed. @@ -312,7 +344,7 @@ gulp.task('help', taskListing.withFilters(function(taskName) { return shouldRemove; })); -// requires admin access +// requires admin access because it adds symlinks gulp.task('add-example-boilerplate', function() { var realPath = path.join(EXAMPLES_PATH, '/node_modules'); var nodeModulesPaths = getNodeModulesPaths(EXAMPLES_PATH); @@ -332,11 +364,18 @@ gulp.task('add-example-boilerplate', function() { return copyExampleBoilerplate(); }); + +// copies boilerplate files to locations +// where an example app is found +gulp.task('_copy-example-boilerplate', copyExampleBoilerplate); + + // copies boilerplate files to locations // where an example app is found // also copies certain web files (e.g., styles.css) to ~/_examples/**/dart/**/web // also copies protractor.config.js file function copyExampleBoilerplate() { + gutil.log('Copying example boilerplate files'); var sourceFiles = _exampleBoilerplateFiles.map(function(fn) { return path.join(EXAMPLES_PATH, fn); }); @@ -351,12 +390,14 @@ function copyExampleBoilerplate() { .then(function() { return copyFiles(dartWebSourceFiles, dartExampleWebPaths); }) - // copy protractor.config.js from _examples dir to each subdir that + // copy files from _examples/_protractor dir to each subdir that // contains a e2e-spec file. .then(function() { - var sourceFiles = [ path.join(EXAMPLES_PATH, 'protractor.config.js') ]; + var protractorSourceFiles = + _exampleProtractorBoilerplateFiles + .map(function(name) {return path.join(EXAMPLES_PROTRACTOR_PATH, name);});; var e2eSpecPaths = getE2eSpecPaths(EXAMPLES_PATH); - return copyFiles(sourceFiles, e2eSpecPaths); + return copyFiles(protractorSourceFiles, e2eSpecPaths); }); } @@ -371,6 +412,15 @@ gulp.task('remove-example-boilerplate', function() { fsUtils.removeSymlink(linkPath); }); + deleteExampleBoilerPlate(); +}); + +// deletes boilerplate files that were added by copyExampleBoilerplate +// from locations where an example app is found +gulp.task('_delete-example-boilerplate', deleteExampleBoilerPlate); + +function deleteExampleBoilerPlate() { + gutil.log('Deleting example boilerplate files'); var examplePaths = getExamplePaths(EXAMPLES_PATH); var dartExampleWebPaths = getDartExampleWebPaths(EXAMPLES_PATH); @@ -379,10 +429,11 @@ gulp.task('remove-example-boilerplate', function() { return deleteFiles(_exampleDartWebBoilerPlateFiles, dartExampleWebPaths); }) .then(function() { + var protractorFiles = _exampleProtractorBoilerplateFiles; var e2eSpecPaths = getE2eSpecPaths(EXAMPLES_PATH); - return deleteFiles(['protractor.config.js'], e2eSpecPaths); - }) -}); + return deleteFiles(protractorFiles, e2eSpecPaths); + }); +} gulp.task('serve-and-sync', ['build-docs'], function (cb) { // watchAndSync({devGuide: true, apiDocs: true, apiExamples: true, localFiles: true}, cb); @@ -744,7 +795,7 @@ function deleteFiles(baseFileNames, destPaths) { // TODO: filter out all paths that are subdirs of another // path in the result. function getE2eSpecPaths(basePath) { - var paths = getPaths(basePath, '*e2e-spec.js', true); + var paths = getPaths(basePath, '*e2e-spec.+(js|ts)', true); return _.uniq(paths); } diff --git a/public/docs/_examples/_protractor/e2e.d.ts b/public/docs/_examples/_protractor/e2e.d.ts new file mode 100644 index 0000000000..ab91658443 --- /dev/null +++ b/public/docs/_examples/_protractor/e2e.d.ts @@ -0,0 +1,14 @@ +/// + +// Defined in protractor.config.js +declare function setProtractorToNg1Mode(): void; +declare function sendKeys(element: protractor.ElementFinder, str: string): webdriver.promise.Promise; +declare function describeIf(cond: boolean, name: string, func: Function): void; +declare function itIf(cond: boolean, name: string, func: Function): void; + +declare namespace protractor { + interface IBrowser { + appIsTs: boolean; + appIsJs: boolean; + } +} diff --git a/public/docs/_examples/_protractor/package.json b/public/docs/_examples/_protractor/package.json new file mode 100644 index 0000000000..eca5cae41f --- /dev/null +++ b/public/docs/_examples/_protractor/package.json @@ -0,0 +1,19 @@ +{ + "name": "angular2-examples-protractor", + "version": "1.0.0", + "description": "Manage _protractor folder installations", + "scripts": { + "postinstall": "typings install", + "typings": "typings", + "protractor": "protractor", + "webdriver:update": "webdriver-manager update" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "protractor": "^3.3.0", + "typings": "^1.0.4" + }, + "repository": {} +} diff --git a/public/docs/_examples/protractor.config.js b/public/docs/_examples/_protractor/protractor.config.js similarity index 96% rename from public/docs/_examples/protractor.config.js rename to public/docs/_examples/_protractor/protractor.config.js index 060c8d9040..6955d05e6b 100644 --- a/public/docs/_examples/protractor.config.js +++ b/public/docs/_examples/_protractor/protractor.config.js @@ -26,10 +26,6 @@ exports.config = { // Framework to use. Jasmine is recommended. framework: 'jasmine', - // Spec patterns are relative to this config file - specs: ['**/*e2e-spec.js' ], - - // For angular2 tests useAllAngular2AppRoots: true, @@ -71,7 +67,7 @@ exports.config = { global.setProtractorToNg1Mode = function() { browser.useAllAngular2AppRoots = false; browser.rootEl = 'body'; - + var disableNgAnimate = function() { angular.module('disableNgAnimate', []).run(['$animate', function($animate) { $animate.enabled(false); @@ -87,6 +83,11 @@ exports.config = { defaultTimeoutInterval: 10000, showTiming: true, print: function() {} + }, + + beforeLaunch: function() { + // add TS support for specs + require('ts-node').register(); } }; @@ -118,7 +119,7 @@ function sendKeys(element, str) { } function Reporter(options) { - var _defaultOutputFile = path.resolve(process.cwd(), "../../", 'protractor-results.txt'); + var _defaultOutputFile = path.resolve(process.cwd(), "../../../../", 'protractor-results.txt'); options.outputFile = options.outputFile || _defaultOutputFile; var _root = { appDir: options.appDir, suites: [] }; @@ -142,7 +143,7 @@ function Reporter(options) { }; this.specStarted = function(spec) { - + }; this.specDone = function(spec) { diff --git a/public/docs/_examples/_protractor/tsconfig.json b/public/docs/_examples/_protractor/tsconfig.json new file mode 100644 index 0000000000..eab9c24f92 --- /dev/null +++ b/public/docs/_examples/_protractor/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "commonjs", + "moduleResolution": "node", + "sourceMap": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "removeComments": false, + "noImplicitAny": true, + "suppressImplicitAnyIndexErrors": true + }, + "files": [ + "e2e-spec.ts" + ] +} diff --git a/public/docs/_examples/_protractor/typings.json b/public/docs/_examples/_protractor/typings.json new file mode 100644 index 0000000000..6962cc930f --- /dev/null +++ b/public/docs/_examples/_protractor/typings.json @@ -0,0 +1,9 @@ +{ + "globalDependencies": { + "angular-protractor": "registry:dt/angular-protractor#1.5.0+20160425143459", + "core-js": "registry:dt/core-js#0.0.0+20160317120654", + "jasmine": "registry:dt/jasmine#2.2.0+20160505161446", + "node": "registry:dt/node#4.0.0+20160509154515", + "selenium-webdriver": "registry:dt/selenium-webdriver#2.44.0+20160317120654" + } +} diff --git a/public/docs/_examples/architecture/e2e-spec.js b/public/docs/_examples/architecture/e2e-spec.ts similarity index 70% rename from public/docs/_examples/architecture/e2e-spec.js rename to public/docs/_examples/architecture/e2e-spec.ts index a8818ad019..a99f24e177 100644 --- a/public/docs/_examples/architecture/e2e-spec.js +++ b/public/docs/_examples/architecture/e2e-spec.ts @@ -1,48 +1,49 @@ +/// describe('Architecture', function () { - var _title = "Hero List"; + let title = 'Hero List'; beforeAll(function () { browser.get(''); }); - function itReset(name, func) { + function itReset(name: string, func: (v: void) => any) { it(name, function() { browser.get('').then(func); }); } - it('should display correct title: ' + _title, function () { - expect(element(by.css('h2')).getText()).toEqual(_title); + it('should display correct title: ' + title, function () { + expect(element(by.css('h2')).getText()).toEqual(title); }); it('should display correct detail after selection', function() { - var detailView = element(by.css('hero-detail')); + let detailView = element(by.css('hero-detail')); expect(detailView.isPresent()).toBe(false); // select the 2nd element - var selectEle = element.all(by.css('hero-list > div')).get(1); + let selectEle = element.all(by.css('hero-list > div')).get(1); selectEle.click().then(function() { return selectEle.getText(); }).then(function(selectedHeroName) { // works but too specific if we change the app // expect(selectedHeroName).toEqual('Mr. Nice'); expect(detailView.isDisplayed()).toBe(true); - var detailTitleEle = element(by.css('hero-detail > h4')); + let detailTitleEle = element(by.css('hero-detail > h4')); expect(detailTitleEle.getText()).toContain(selectedHeroName); }); - }) + }); itReset('should display correct detail after modification', function() { - var detailView = element(by.css('hero-detail')); + let detailView = element(by.css('hero-detail')); expect(detailView.isPresent()).toBe(false); // select the 2nd element - var selectEle = element.all(by.css('hero-list > div')).get(1); + let selectEle = element.all(by.css('hero-list > div')).get(1); selectEle.click().then(function () { return selectEle.getText(); }).then(function (selectedHeroName) { - var detailTitleEle = element(by.css('hero-detail > h4')); + let detailTitleEle = element(by.css('hero-detail > h4')); expect(detailTitleEle.getText()).toContain(selectedHeroName); - var heroNameEle = element.all(by.css('hero-detail input')).get(0); + let heroNameEle = element.all(by.css('hero-detail input')).get(0); // check that both the initial selected item and the detail title reflect changes // made to the input box. @@ -56,6 +57,6 @@ describe('Architecture', function () { // expect(heroNameEle.getText()).toEqual(selectedHeroName); expect(heroNameEle.getAttribute('value')).toEqual(selectedHeroName + 'foo'); }); - }) + }); }); diff --git a/public/docs/_examples/attribute-directives/e2e-spec.js b/public/docs/_examples/attribute-directives/e2e-spec.ts similarity index 54% rename from public/docs/_examples/attribute-directives/e2e-spec.js rename to public/docs/_examples/attribute-directives/e2e-spec.ts index 16fa374c75..54d6a90eea 100644 --- a/public/docs/_examples/attribute-directives/e2e-spec.js +++ b/public/docs/_examples/attribute-directives/e2e-spec.ts @@ -1,6 +1,7 @@ +/// describe('Attribute directives', function () { - var _title = "My First Attribute Directive"; + let _title = 'My First Attribute Directive'; beforeAll(function () { browser.get(''); @@ -11,14 +12,15 @@ describe('Attribute directives', function () { }); it('should be able to select green highlight', function () { - var highlightedEle = element(by.cssContainingText('p', 'Highlight me')); - var lightGreen = "rgba(144, 238, 144, 1)"; + let highlightedEle = element(by.cssContainingText('p', 'Highlight me')); + let lightGreen = 'rgba(144, 238, 144, 1)'; expect(highlightedEle.getCssValue('background-color')).not.toEqual(lightGreen); - // var greenRb = element(by.cssContainingText('input', 'Green')); - var greenRb = element.all(by.css('input')).get(0); + // let greenRb = element(by.cssContainingText('input', 'Green')); + let greenRb = element.all(by.css('input')).get(0); greenRb.click().then(function() { - browser.actions().mouseMove(highlightedEle).perform(); + // TypeScript Todo: find the right type for highlightedEle + browser.actions().mouseMove(highlightedEle as any).perform(); expect(highlightedEle.getCssValue('background-color')).toEqual(lightGreen); }); diff --git a/public/docs/_examples/cb-a1-a2-quick-reference/e2e-spec.js b/public/docs/_examples/cb-a1-a2-quick-reference/e2e-spec.ts similarity index 66% rename from public/docs/_examples/cb-a1-a2-quick-reference/e2e-spec.js rename to public/docs/_examples/cb-a1-a2-quick-reference/e2e-spec.ts index 01e4e57c6c..f75a17ee6e 100644 --- a/public/docs/_examples/cb-a1-a2-quick-reference/e2e-spec.js +++ b/public/docs/_examples/cb-a1-a2-quick-reference/e2e-spec.ts @@ -1,3 +1,4 @@ +/// describe('Angular 1 to 2 Quick Reference Tests', function () { beforeAll(function () { @@ -10,7 +11,7 @@ describe('Angular 1 to 2 Quick Reference Tests', function () { it('should display proper movie data', function () { // We check only a few samples - var expectedSamples = [ + let expectedSamples: any[] = [ {row: 0, column: 0, element: 'img', attr: 'src', value: 'images/hero.png', contains: true}, {row: 0, column: 2, value: 'Celeritas'}, {row: 1, column: 3, matches: /Dec 1[678], 2015/}, // absorb timezone dif; we care about date format @@ -21,18 +22,18 @@ describe('Angular 1 to 2 Quick Reference Tests', function () { ]; // Go through the samples - var movieRows = getMovieRows(); - for (var i = 0; i < expectedSamples.length; i++) { - var sample = expectedSamples[i]; - var tableCell = movieRows.get(sample.row) + let movieRows = getMovieRows(); + for (let i = 0; i < expectedSamples.length; i++) { + let sample = expectedSamples[i]; + let tableCell = movieRows.get(sample.row) .all(by.tagName('td')).get(sample.column); // Check the cell or its nested element - var elementToCheck = sample.element + let elementToCheck = sample.element ? tableCell.element(by.tagName(sample.element)) : tableCell; // Check element attribute or text - var valueToCheck = sample.attr + let valueToCheck = sample.attr ? elementToCheck.getAttribute(sample.attr) : elementToCheck.getText(); @@ -48,38 +49,38 @@ describe('Angular 1 to 2 Quick Reference Tests', function () { }); it('should display images after Show Poster', function () { - testPosterButtonClick("Show Poster", true); + testPosterButtonClick('Show Poster', true); }); it('should hide images after Hide Poster', function () { - testPosterButtonClick("Hide Poster", false); + testPosterButtonClick('Hide Poster', false); }); it('should display no movie when no favorite hero is specified', function () { - testFavoriteHero(null, "Please enter your favorite hero."); + testFavoriteHero(null, 'Please enter your favorite hero.'); }); it('should display no movie for Magneta', function () { - testFavoriteHero("Magneta", "No movie, sorry!"); + testFavoriteHero('Magneta', 'No movie, sorry!'); }); it('should display a movie for Mr. Nice', function () { - testFavoriteHero("Mr. Nice", "Excellent choice!"); + testFavoriteHero('Mr. Nice', 'Excellent choice!'); }); - function testImagesAreDisplayed(isDisplayed) { - var expectedMovieCount = 3; + function testImagesAreDisplayed(isDisplayed: boolean) { + let expectedMovieCount = 3; - var movieRows = getMovieRows(); + let movieRows = getMovieRows(); expect(movieRows.count()).toBe(expectedMovieCount); - for (var i = 0; i < expectedMovieCount; i++) { - var movieImage = movieRows.get(i).element(by.css('td > img')); + for (let i = 0; i < expectedMovieCount; i++) { + let movieImage = movieRows.get(i).element(by.css('td > img')); expect(movieImage.isDisplayed()).toBe(isDisplayed); } } - function testPosterButtonClick(expectedButtonText, isDisplayed) { - var posterButton = element(by.css('movie-list tr > th > button')); + function testPosterButtonClick(expectedButtonText: string, isDisplayed: boolean) { + let posterButton = element(by.css('movie-list tr > th > button')); expect(posterButton.getText()).toBe(expectedButtonText); posterButton.click().then(function () { @@ -91,11 +92,11 @@ describe('Angular 1 to 2 Quick Reference Tests', function () { return element.all(by.css('movie-list tbody > tr')); } - function testFavoriteHero(heroName, expectedLabel) { - var movieListComp = element(by.tagName('movie-list')); - var heroInput = movieListComp.element(by.tagName('input')); - var favoriteHeroLabel = movieListComp.element(by.tagName('h3')); - var resultLabel = movieListComp.element(by.css('span > p')); + function testFavoriteHero(heroName: string, expectedLabel: string) { + let movieListComp = element(by.tagName('movie-list')); + let heroInput = movieListComp.element(by.tagName('input')); + let favoriteHeroLabel = movieListComp.element(by.tagName('h3')); + let resultLabel = movieListComp.element(by.css('span > p')); heroInput.clear().then(function () { sendKeys(heroInput, heroName || '').then(function () { diff --git a/public/docs/_examples/cb-component-communication/e2e-spec.js b/public/docs/_examples/cb-component-communication/e2e-spec.ts similarity index 57% rename from public/docs/_examples/cb-component-communication/e2e-spec.js rename to public/docs/_examples/cb-component-communication/e2e-spec.ts index ed00a5c7cb..fc2566662d 100644 --- a/public/docs/_examples/cb-component-communication/e2e-spec.js +++ b/public/docs/_examples/cb-component-communication/e2e-spec.ts @@ -1,3 +1,4 @@ +/// describe('Component Communication Cookbook Tests', function () { // Note: '?e2e' which app can read to know it is running in protractor @@ -9,16 +10,16 @@ describe('Component Communication Cookbook Tests', function () { describe('Parent-to-child communication', function() { // #docregion parent-to-child // ... - var _heroNames = ['Mr. IQ', 'Magneta', 'Bombasto']; - var _masterName = 'Master'; + let _heroNames = ['Mr. IQ', 'Magneta', 'Bombasto']; + let _masterName = 'Master'; it('should pass properties to children properly', function () { - var parent = element.all(by.tagName('hero-parent')).get(0); - var heroes = parent.all(by.tagName('hero-child')); + let parent = element.all(by.tagName('hero-parent')).get(0); + let heroes = parent.all(by.tagName('hero-child')); - for (var i = 0; i < _heroNames.length; i++) { - var childTitle = heroes.get(i).element(by.tagName('h3')).getText(); - var childDetail = heroes.get(i).element(by.tagName('p')).getText(); + for (let i = 0; i < _heroNames.length; i++) { + let childTitle = heroes.get(i).element(by.tagName('h3')).getText(); + let childDetail = heroes.get(i).element(by.tagName('p')).getText(); expect(childTitle).toEqual(_heroNames[i] + ' says:') expect(childDetail).toContain(_masterName) } @@ -31,22 +32,22 @@ describe('Component Communication Cookbook Tests', function () { // #docregion parent-to-child-setter // ... it('should display trimmed, non-empty names', function () { - var _nonEmptyNameIndex = 0; - var _nonEmptyName = '"Mr. IQ"'; - var parent = element.all(by.tagName('name-parent')).get(0); - var hero = parent.all(by.tagName('name-child')).get(_nonEmptyNameIndex); + let _nonEmptyNameIndex = 0; + let _nonEmptyName = '"Mr. IQ"'; + let parent = element.all(by.tagName('name-parent')).get(0); + let hero = parent.all(by.tagName('name-child')).get(_nonEmptyNameIndex); - var displayName = hero.element(by.tagName('h3')).getText(); + let displayName = hero.element(by.tagName('h3')).getText(); expect(displayName).toEqual(_nonEmptyName) }); it('should replace empty name with default name', function () { - var _emptyNameIndex = 1; - var _defaultName = '""'; - var parent = element.all(by.tagName('name-parent')).get(0); - var hero = parent.all(by.tagName('name-child')).get(_emptyNameIndex); + let _emptyNameIndex = 1; + let _defaultName = '""'; + let parent = element.all(by.tagName('name-parent')).get(0); + let hero = parent.all(by.tagName('name-child')).get(_emptyNameIndex); - var displayName = hero.element(by.tagName('h3')).getText(); + let displayName = hero.element(by.tagName('h3')).getText(); expect(displayName).toEqual(_defaultName) }); // ... @@ -58,26 +59,26 @@ describe('Component Communication Cookbook Tests', function () { // ... // Test must all execute in this exact order it('should set expected initial values', function () { - var actual = getActual(); + let actual = getActual(); - var initialLabel = "Version 1.23"; - var initialLog = 'major changed from {} to 1, minor changed from {} to 23'; + let initialLabel = 'Version 1.23'; + let initialLog = 'major changed from {} to 1, minor changed from {} to 23'; expect(actual.label).toBe(initialLabel); expect(actual.count).toBe(1); expect(actual.logs.get(0).getText()).toBe(initialLog); }); - it('should set expected values after clicking "Minor" twice', function () { - var repoTag = element(by.tagName('version-parent')); - var newMinorButton = repoTag.all(by.tagName('button')).get(0); + it('should set expected values after clicking \'Minor\' twice', function () { + let repoTag = element(by.tagName('version-parent')); + let newMinorButton = repoTag.all(by.tagName('button')).get(0); newMinorButton.click().then(function() { newMinorButton.click().then(function() { - var actual = getActual(); + let actual = getActual(); - var labelAfter2Minor = "Version 1.25"; - var logAfter2Minor = 'minor changed from 24 to 25'; + let labelAfter2Minor = 'Version 1.25'; + let logAfter2Minor = 'minor changed from 24 to 25'; expect(actual.label).toBe(labelAfter2Minor); expect(actual.count).toBe(3); @@ -86,15 +87,15 @@ describe('Component Communication Cookbook Tests', function () { }); }); - it('should set expected values after clicking "Major" once', function () { - var repoTag = element(by.tagName('version-parent')); - var newMajorButton = repoTag.all(by.tagName('button')).get(1); + it('should set expected values after clicking \'Major\' once', function () { + let repoTag = element(by.tagName('version-parent')); + let newMajorButton = repoTag.all(by.tagName('button')).get(1); newMajorButton.click().then(function() { - var actual = getActual(); + let actual = getActual(); - var labelAfterMajor = "Version 2.0"; - var logAfterMajor = 'major changed from 1 to 2, minor changed from 25 to 0'; + let labelAfterMajor = 'Version 2.0'; + let logAfterMajor = 'major changed from 1 to 2, minor changed from 25 to 0'; expect(actual.label).toBe(labelAfterMajor); expect(actual.count).toBe(4); @@ -103,10 +104,10 @@ describe('Component Communication Cookbook Tests', function () { }); function getActual() { - var versionTag = element(by.tagName('version-child')); - var label = versionTag.element(by.tagName('h3')).getText(); - var ul = versionTag.element((by.tagName('ul'))); - var logs = ul.all(by.tagName('li')); + let versionTag = element(by.tagName('version-child')); + let label = versionTag.element(by.tagName('h3')).getText(); + let ul = versionTag.element((by.tagName('ul'))); + let logs = ul.all(by.tagName('li')); return { label: label, @@ -123,28 +124,28 @@ describe('Component Communication Cookbook Tests', function () { // #docregion child-to-parent // ... it('should not emit the event initially', function () { - var voteLabel = element(by.tagName('vote-taker')) + let voteLabel = element(by.tagName('vote-taker')) .element(by.tagName('h3')).getText(); - expect(voteLabel).toBe("Agree: 0, Disagree: 0"); + expect(voteLabel).toBe('Agree: 0, Disagree: 0'); }); it('should process Agree vote', function () { - var agreeButton1 = element.all(by.tagName('my-voter')).get(0) + let agreeButton1 = element.all(by.tagName('my-voter')).get(0) .all(by.tagName('button')).get(0); agreeButton1.click().then(function() { - var voteLabel = element(by.tagName('vote-taker')) + let voteLabel = element(by.tagName('vote-taker')) .element(by.tagName('h3')).getText(); - expect(voteLabel).toBe("Agree: 1, Disagree: 0"); + expect(voteLabel).toBe('Agree: 1, Disagree: 0'); }); }); it('should process Disagree vote', function () { - var agreeButton1 = element.all(by.tagName('my-voter')).get(1) + let agreeButton1 = element.all(by.tagName('my-voter')).get(1) .all(by.tagName('button')).get(1); agreeButton1.click().then(function() { - var voteLabel = element(by.tagName('vote-taker')) + let voteLabel = element(by.tagName('vote-taker')) .element(by.tagName('h3')).getText(); - expect(voteLabel).toBe("Agree: 1, Disagree: 1"); + expect(voteLabel).toBe('Agree: 1, Disagree: 1'); }); }); // ... @@ -161,23 +162,23 @@ describe('Component Communication Cookbook Tests', function () { countDownTimerTests('countdown-parent-vc') }); - function countDownTimerTests(parentTag) { + function countDownTimerTests(parentTag: string) { // #docregion countdown-timer-tests // ... it('timer and parent seconds should match', function () { - var parent = element(by.tagName(parentTag)); - var message = parent.element(by.tagName('countdown-timer')).getText(); + let parent = element(by.tagName(parentTag)); + let message = parent.element(by.tagName('countdown-timer')).getText(); browser.sleep(10); // give `seconds` a chance to catchup with `message` - var seconds = parent.element(by.className('seconds')).getText(); + let seconds = parent.element(by.className('seconds')).getText(); expect(message).toContain(seconds); }); it('should stop the countdown', function () { - var parent = element(by.tagName(parentTag)); - var stopButton = parent.all(by.tagName('button')).get(1); + let parent = element(by.tagName(parentTag)); + let stopButton = parent.all(by.tagName('button')).get(1); stopButton.click().then(function() { - var message = parent.element(by.tagName('countdown-timer')).getText(); + let message = parent.element(by.tagName('countdown-timer')).getText(); expect(message).toContain('Holding'); }); }); @@ -190,10 +191,10 @@ describe('Component Communication Cookbook Tests', function () { // #docregion bidirectional-service // ... it('should announce a mission', function () { - var missionControl = element(by.tagName('mission-control')); - var announceButton = missionControl.all(by.tagName('button')).get(0); + let missionControl = element(by.tagName('mission-control')); + let announceButton = missionControl.all(by.tagName('button')).get(0); announceButton.click().then(function () { - var history = missionControl.all(by.tagName('li')); + let history = missionControl.all(by.tagName('li')); expect(history.count()).toBe(1); expect(history.get(0).getText()).toMatch(/Mission.* announced/); }); @@ -211,14 +212,14 @@ describe('Component Communication Cookbook Tests', function () { testConfirmMission(2, 4, 'Swigert'); }); - function testConfirmMission(buttonIndex, expectedLogCount, astronaut) { - var _confirmedLog = ' confirmed the mission'; - var missionControl = element(by.tagName('mission-control')); - var confirmButton = missionControl.all(by.tagName('button')).get(buttonIndex); + function testConfirmMission(buttonIndex: number, expectedLogCount: number, astronaut: string) { + let _confirmedLog = ' confirmed the mission'; + let missionControl = element(by.tagName('mission-control')); + let confirmButton = missionControl.all(by.tagName('button')).get(buttonIndex); confirmButton.click().then(function () { - var history = missionControl.all(by.tagName('li')); + let history = missionControl.all(by.tagName('li')); expect(history.count()).toBe(expectedLogCount); - expect(history.get(expectedLogCount-1).getText()).toBe(astronaut + _confirmedLog); + expect(history.get(expectedLogCount - 1).getText()).toBe(astronaut + _confirmedLog); }); } // ... diff --git a/public/docs/_examples/cb-component-relative-paths/e2e-spec.js b/public/docs/_examples/cb-component-relative-paths/e2e-spec.ts similarity index 81% rename from public/docs/_examples/cb-component-relative-paths/e2e-spec.js rename to public/docs/_examples/cb-component-relative-paths/e2e-spec.ts index 6646bd0b4f..e39dfdb8a9 100644 --- a/public/docs/_examples/cb-component-relative-paths/e2e-spec.js +++ b/public/docs/_examples/cb-component-relative-paths/e2e-spec.ts @@ -1,5 +1,12 @@ +/// describe('Cookbook: component-relative paths', function () { + interface Page { + title: protractor.ElementFinder; + absComp: protractor.ElementFinder; + relComp: protractor.ElementFinder; + + } function getPageStruct() { return { title: element( by.tagName( 'h1' )), @@ -8,7 +15,7 @@ describe('Cookbook: component-relative paths', function () { } } - var page; + let page: Page; beforeAll(function () { browser.get(''); page = getPageStruct(); diff --git a/public/docs/_examples/cb-dependency-injection/e2e-spec.js b/public/docs/_examples/cb-dependency-injection/e2e-spec.ts similarity index 56% rename from public/docs/_examples/cb-dependency-injection/e2e-spec.js rename to public/docs/_examples/cb-dependency-injection/e2e-spec.ts index 14f1f0994b..2beb08af94 100644 --- a/public/docs/_examples/cb-dependency-injection/e2e-spec.js +++ b/public/docs/_examples/cb-dependency-injection/e2e-spec.ts @@ -1,3 +1,4 @@ +/// describe('Dependency Injection Cookbook', function () { beforeAll(function () { @@ -5,104 +6,104 @@ describe('Dependency Injection Cookbook', function () { }); it('should render Logged in User example', function () { - var loggedInUser = element.all(by.xpath('//h3[text()="Logged in user"]')).get(0); + let loggedInUser = element.all(by.xpath('//h3[text()="Logged in user"]')).get(0); expect(loggedInUser).toBeDefined(); }); - - it('"Bombasto" should be the logged in user', function () { - loggedInUser = element.all(by.xpath('//div[text()="Name: Bombasto"]')).get(0); + + it('"Bombasto" should be the logged in user', function () { + let loggedInUser = element.all(by.xpath('//div[text()="Name: Bombasto"]')).get(0); expect(loggedInUser).toBeDefined(); }); - - it('should render sorted heroes', function () { - var sortedHeroes = element.all(by.xpath('//h3[text()="Sorted Heroes" and position()=1]')).get(0); + + it('should render sorted heroes', function () { + let sortedHeroes = element.all(by.xpath('//h3[text()="Sorted Heroes" and position()=1]')).get(0); expect(sortedHeroes).toBeDefined(); - }); - + }); + it('Mr. Nice should be in sorted heroes', function () { - var sortedHero = element.all(by.xpath('//sorted-heroes/[text()="Mr. Nice" and position()=2]')).get(0); + let sortedHero = element.all(by.xpath('//sorted-heroes/[text()="Mr. Nice" and position()=2]')).get(0); expect(sortedHero).toBeDefined(); }); - - it('RubberMan should be in sorted heroes', function () { - sortedHero = element.all(by.xpath('//sorted-heroes/[text()="RubberMan" and position()=3]')).get(0); + + it('RubberMan should be in sorted heroes', function () { + let sortedHero = element.all(by.xpath('//sorted-heroes/[text()="RubberMan" and position()=3]')).get(0); expect(sortedHero).toBeDefined(); }); - + it('Magma should be in sorted heroes', function () { - sortedHero = element.all(by.xpath('//sorted-heroes/[text()="Magma"]')).get(0); + let sortedHero = element.all(by.xpath('//sorted-heroes/[text()="Magma"]')).get(0); expect(sortedHero).toBeDefined(); }); - - it('should render Hero of the Month when DI deps are defined using provide()', function () { - var heroOfTheMonth = element.all(by.xpath('//h3[text()="Hero of the month"]')).get(0); + + it('should render Hero of the Month when DI deps are defined using provide()', function () { + let heroOfTheMonth = element.all(by.xpath('//h3[text()="Hero of the month"]')).get(0); expect(heroOfTheMonth).toBeDefined(); }); - - it('should render Hero of the Month when DI deps are defined using provide object literal', function () { - var heroOfTheMonth = element.all(by.xpath('//h3[text()="Hero of the month 2"]')).get(0); + + it('should render Hero of the Month when DI deps are defined using provide object literal', function () { + let heroOfTheMonth = element.all(by.xpath('//h3[text()="Hero of the month 2"]')).get(0); expect(heroOfTheMonth).toBeDefined(); }); - - it('should render Hero Bios', function () { - var heroBios = element.all(by.xpath('//h3[text()="Hero Bios"]')).get(0); + + it('should render Hero Bios', function () { + let heroBios = element.all(by.xpath('//h3[text()="Hero Bios"]')).get(0); expect(heroBios).toBeDefined(); }); - - it('should render Magma\'s description in Hero Bios', function () { - var magmaText = element.all(by.xpath('//textarea[text()="Hero of all trades"]')).get(0); + + it('should render Magma\'s description in Hero Bios', function () { + let magmaText = element.all(by.xpath('//textarea[text()="Hero of all trades"]')).get(0); expect(magmaText).toBeDefined(); }); - - it('should render Magma\'s phone in Hero Bios and Contacts', function () { - var magmaPhone = element.all(by.xpath('//div[text()="Phone #: 555-555-5555"]')).get(0); + + it('should render Magma\'s phone in Hero Bios and Contacts', function () { + let magmaPhone = element.all(by.xpath('//div[text()="Phone #: 555-555-5555"]')).get(0); expect(magmaPhone).toBeDefined(); }); - - it('should render Hero-of-the-Month runner-ups when DI deps are defined using provide()', function () { - var runnersUp = element(by.id('rups1')).getText(); + + it('should render Hero-of-the-Month runner-ups when DI deps are defined using provide()', function () { + let runnersUp = element(by.id('rups1')).getText(); expect(runnersUp).toContain('RubberMan, Mr. Nice'); }); - - it('should render Hero-of-the-Month runner-ups when DI deps are defined using provide object literal', function () { - var runnersUp = element(by.id('rups2')).getText(); + + it('should render Hero-of-the-Month runner-ups when DI deps are defined using provide object literal', function () { + let runnersUp = element(by.id('rups2')).getText(); expect(runnersUp).toContain('RubberMan, Mr. Nice'); }); - - it('should render DateLogger log entry in Hero-of-the-Month', function () { - var logs = element.all(by.id('logs')).get(0).getText(); + + it('should render DateLogger log entry in Hero-of-the-Month', function () { + let logs = element.all(by.id('logs')).get(0).getText(); expect(logs).toContain('INFO: starting up at'); }); - + it('should highlight Hero Bios and Contacts container when mouseover', function () { - var target = element(by.css('div[myHighlight="yellow"]')) - var yellow = "rgba(255, 255, 0, 1)"; - + let target = element(by.css('div[myHighlight="yellow"]')) + let yellow = 'rgba(255, 255, 0, 1)'; + expect(target.getCssValue('background-color')).not.toEqual(yellow); - browser.actions().mouseMove(target).perform(); + browser.actions().mouseMove(target as any as webdriver.WebElement).perform(); expect(target.getCssValue('background-color')).toEqual(yellow); }); describe('in Parent Finder', function () { - var cathy1 = element(by.css('alex cathy')); - var craig1 = element(by.css('alex craig')); - var carol1 = element(by.css('alex carol p')); - var carol2 = element(by.css('barry carol p')); - - it('"Cathy" should find "Alex" via the component class', function () { + let cathy1 = element(by.css('alex cathy')); + let craig1 = element(by.css('alex craig')); + let carol1 = element(by.css('alex carol p')); + let carol2 = element(by.css('barry carol p')); + + it('"Cathy" should find "Alex" via the component class', function () { expect(cathy1.getText()).toContain('Found Alex via the component'); }); - - it('"Craig" should not find "Alex" via the base class', function () { + + it('"Craig" should not find "Alex" via the base class', function () { expect(craig1.getText()).toContain('Did not find Alex via the base'); }); - - it('"Carol" within "Alex" should have "Alex" parent', function () { + + it('"Carol" within "Alex" should have "Alex" parent', function () { expect(carol1.getText()).toContain('Alex'); }); - - it('"Carol" within "Barry" should have "Barry" parent', function () { + + it('"Carol" within "Barry" should have "Barry" parent', function () { expect(carol2.getText()).toContain('Barry'); }); - }) + }); }); diff --git a/public/docs/_examples/cb-dynamic-form/e2e-spec.js b/public/docs/_examples/cb-dynamic-form/e2e-spec.ts similarity index 65% rename from public/docs/_examples/cb-dynamic-form/e2e-spec.js rename to public/docs/_examples/cb-dynamic-form/e2e-spec.ts index 9254c86717..d526626b24 100644 --- a/public/docs/_examples/cb-dynamic-form/e2e-spec.js +++ b/public/docs/_examples/cb-dynamic-form/e2e-spec.ts @@ -1,3 +1,5 @@ +/// +/* tslint:disable:quotemark */ describe('Dynamic Form', function () { beforeAll(function () { @@ -5,17 +7,17 @@ describe('Dynamic Form', function () { }); it('should submit form', function () { - var firstNameElement = element.all(by.css('input[id=firstName]')).get(0); + let firstNameElement = element.all(by.css('input[id=firstName]')).get(0); expect(firstNameElement.getAttribute('value')).toEqual('Bombasto'); - - var emailElement = element.all(by.css('input[id=emailAddress]')).get(0); - var email = 'test@test.com'; + + let emailElement = element.all(by.css('input[id=emailAddress]')).get(0); + let email = 'test@test.com'; emailElement.sendKeys(email); - expect(emailElement.getAttribute('value')).toEqual(email); - + expect(emailElement.getAttribute('value')).toEqual(email); + element(by.css('select option[value="solid"]')).click() - - var saveButton = element.all(by.css('button')).get(0); + + let saveButton = element.all(by.css('button')).get(0); saveButton.click().then(function(){ expect(element(by.xpath("//strong[contains(text(),'Saved the following values')]")).isPresent()).toBe(true); }); diff --git a/public/docs/_examples/cb-set-document-title/e2e-spec.js b/public/docs/_examples/cb-set-document-title/e2e-spec.ts similarity index 88% rename from public/docs/_examples/cb-set-document-title/e2e-spec.js rename to public/docs/_examples/cb-set-document-title/e2e-spec.ts index 52516f4d4b..9029c164e0 100644 --- a/public/docs/_examples/cb-set-document-title/e2e-spec.js +++ b/public/docs/_examples/cb-set-document-title/e2e-spec.ts @@ -1,3 +1,4 @@ +/// // gulp run-e2e-tests --filter=cb-set-document-title describe('Set Document Title', function () { @@ -7,7 +8,7 @@ describe('Set Document Title', function () { it('should set the document title', function () { - var titles = [ + let titles = [ 'Good morning!', 'Good afternoon!', 'Good evening!' diff --git a/public/docs/_examples/cb-ts-to-js/e2e-spec.js b/public/docs/_examples/cb-ts-to-js/e2e-spec.ts similarity index 73% rename from public/docs/_examples/cb-ts-to-js/e2e-spec.js rename to public/docs/_examples/cb-ts-to-js/e2e-spec.ts index 27b332e99e..dbb308fbf7 100644 --- a/public/docs/_examples/cb-ts-to-js/e2e-spec.js +++ b/public/docs/_examples/cb-ts-to-js/e2e-spec.ts @@ -1,3 +1,4 @@ +/// describe('TypeScript to Javascript tests', function () { beforeAll(function () { @@ -21,9 +22,9 @@ describe('TypeScript to Javascript tests', function () { }); it('should support optional, attribute, and query injections', function () { - var app = element(by.css('hero-di-inject-additional')); - var h1 = app.element(by.css('h1')); - var okMsg = app.element(by.css('.ok-msg')); + let app = element(by.css('hero-di-inject-additional')); + let h1 = app.element(by.css('h1')); + let okMsg = app.element(by.css('.ok-msg')); expect(h1.getText()).toBe('Tour of Heroes'); app.element(by.buttonText('OK')).click(); @@ -31,8 +32,8 @@ describe('TypeScript to Javascript tests', function () { }); it('should support component with inputs and outputs', function () { - var app = element(by.css('hero-io')); - var confirmComponent = app.element(by.css('my-confirm')); + let app = element(by.css('hero-io')); + let confirmComponent = app.element(by.css('my-confirm')); confirmComponent.element(by.buttonText('OK')).click(); expect(app.element(by.cssContainingText('span', 'OK clicked')).isPresent()).toBe(true); @@ -42,8 +43,8 @@ describe('TypeScript to Javascript tests', function () { }); it('should support host bindings and host listeners', function() { - var app = element(by.css('heroes-bindings')); - var h1 = app.element(by.css('h1')); + let app = element(by.css('heroes-bindings')); + let h1 = app.element(by.css('h1')); expect(app.getAttribute('class')).toBe('heading'); expect(app.getAttribute('title')).toBe('Tooltip content'); @@ -52,21 +53,21 @@ describe('TypeScript to Javascript tests', function () { expect(h1.getAttribute('class')).toBe('active'); h1.click(); - browser.actions().doubleClick(h1).perform(); + browser.actions().doubleClick(h1 as any as webdriver.WebElement).perform(); expect(h1.getAttribute('class')).toBe('active'); }); it('should support content and view queries', function() { - var app = element(by.css('heroes-queries')); - var windstorm = app.element(by.css('hero:first-child')); + let app = element(by.css('heroes-queries')); + let windstorm = app.element(by.css('hero:first-child')); app.element(by.buttonText('Activate')).click(); expect(windstorm.element(by.css('h2')).getAttribute('class')).toBe('active'); expect(windstorm.element(by.css('active-label')).getText()).toBe('Active'); }); - function testTag(selector, expectedText) { - var component = element(by.css(selector)); + function testTag(selector: string, expectedText: string) { + let component = element(by.css(selector)); expect(component.getText()).toBe(expectedText); } diff --git a/public/docs/_examples/component-styles/e2e-spec.js b/public/docs/_examples/component-styles/e2e-spec.ts similarity index 69% rename from public/docs/_examples/component-styles/e2e-spec.js rename to public/docs/_examples/component-styles/e2e-spec.ts index e667260f99..dac3cd55a2 100644 --- a/public/docs/_examples/component-styles/e2e-spec.js +++ b/public/docs/_examples/component-styles/e2e-spec.ts @@ -1,3 +1,4 @@ +/// describe('Component Style Tests', function () { beforeAll(function () { @@ -5,8 +6,8 @@ describe('Component Style Tests', function () { }); it('scopes component styles to component view', function() { - var componentH1 = element(by.css('hero-app > h1')); - var externalH1 = element(by.css('body > h1')); + let componentH1 = element(by.css('hero-app > h1')); + let externalH1 = element(by.css('body > h1')); expect(componentH1.getCssValue('fontWeight')).toEqual('normal'); expect(externalH1.getCssValue('fontWeight')).not.toEqual('normal'); @@ -14,55 +15,55 @@ describe('Component Style Tests', function () { it('allows styling :host element', function() { - var host = element(by.css('hero-details')); + let host = element(by.css('hero-details')); expect(host.getCssValue('borderWidth')).toEqual('1px'); }); it('supports :host() in function form', function() { - var host = element(by.css('hero-details')); + let host = element(by.css('hero-details')); host.element(by.buttonText('Activate')).click(); expect(host.getCssValue('borderWidth')).toEqual('3px'); }); it('allows conditional :host-context() styling', function() { - var h2 = element(by.css('hero-details h2')); + let h2 = element(by.css('hero-details h2')); expect(h2.getCssValue('backgroundColor')).toEqual('rgba(238, 238, 255, 1)'); // #eeeeff }); it('styles both view and content children with /deep/', function() { - var viewH3 = element(by.css('hero-team h3')); - var contentH3 = element(by.css('hero-controls h3')); + let viewH3 = element(by.css('hero-team h3')); + let contentH3 = element(by.css('hero-controls h3')); expect(viewH3.getCssValue('fontStyle')).toEqual('italic'); expect(contentH3.getCssValue('fontStyle')).toEqual('italic'); }); it('includes styles loaded with CSS @import', function() { - var host = element(by.css('hero-details')); + let host = element(by.css('hero-details')); expect(host.getCssValue('padding')).toEqual('10px'); }); it('processes template inline styles', function() { - var button = element(by.css('hero-controls button')); - var externalButton = element(by.css('body > button')); + let button = element(by.css('hero-controls button')); + let externalButton = element(by.css('body > button')); expect(button.getCssValue('backgroundColor')).toEqual('rgba(255, 255, 255, 1)'); // #ffffff expect(externalButton.getCssValue('backgroundColor')).not.toEqual('rgba(255, 255, 255, 1)'); }); it('processes template s', function() { - var li = element(by.css('hero-team li:first-child')); - var externalLi = element(by.css('body > ul li')); + let li = element(by.css('hero-team li:first-child')); + let externalLi = element(by.css('body > ul li')); expect(li.getCssValue('listStyleType')).toEqual('square'); expect(externalLi.getCssValue('listStyleType')).not.toEqual('square'); }); it('supports relative loading with moduleId', function() { - var host = element(by.css('quest-summary')); + let host = element(by.css('quest-summary')); expect(host.getCssValue('color')).toEqual('rgba(255, 255, 255, 1)'); // #ffffff }); diff --git a/public/docs/_examples/dependency-injection/e2e-spec.js b/public/docs/_examples/dependency-injection/e2e-spec.ts similarity index 89% rename from public/docs/_examples/dependency-injection/e2e-spec.js rename to public/docs/_examples/dependency-injection/e2e-spec.ts index effdc1111f..5656bddc6d 100644 --- a/public/docs/_examples/dependency-injection/e2e-spec.js +++ b/public/docs/_examples/dependency-injection/e2e-spec.ts @@ -1,8 +1,9 @@ - +/// describe('Dependency Injection Tests', function () { - var expectedMsg; + let expectedMsg: string; + let expectedMsgRx: RegExp; beforeAll(function () { browser.get(''); @@ -66,8 +67,8 @@ describe('Dependency Injection Tests', function () { describe('Tests:', function() { it('Tests display as expected', function () { - expectedMsg = /Tests passed/; - expect(element(by.css('#tests')).getText()).toMatch(expectedMsg); + expectedMsgRx = /Tests passed/; + expect(element(by.css('#tests')).getText()).toMatch(expectedMsgRx); }); }); @@ -88,7 +89,7 @@ describe('Dependency Injection Tests', function () { expectedMsg = 'Hello from logger provided with useClass'; expect(element(by.css('#p3')).getText()).toEqual(expectedMsg); }); - + it('P3a (provide) displays as expected', function () { expectedMsg = 'Hello from logger provided with {provide: Logger, useClass: Logger}'; expect(element(by.css('#p3a')).getText()).toEqual(expectedMsg); @@ -147,22 +148,22 @@ describe('Dependency Injection Tests', function () { describe('User/Heroes:', function() { it('User is Bob - unauthorized', function () { - expectedMsg = /Bob, is not authorized/; - expect(element(by.css('#user')).getText()).toMatch(expectedMsg); + expectedMsgRx = /Bob, is not authorized/; + expect(element(by.css('#user')).getText()).toMatch(expectedMsgRx); }); it('should have button', function () { - expect(element.all(by.cssContainingText('button','Next User')) - .get(0).isDisplayed()).toBe(true, "'Next User' button should be displayed"); + expect(element.all(by.cssContainingText('button', 'Next User')) + .get(0).isDisplayed()).toBe(true, '\'Next User\' button should be displayed'); }); it('unauthorized user should have multiple unauthorized heroes', function () { - var heroes = element.all(by.css('#unauthorized hero-list div')); + let heroes = element.all(by.css('#unauthorized hero-list div')); expect(heroes.count()).toBeGreaterThan(0); }); it('unauthorized user should have no secret heroes', function () { - var heroes = element.all(by.css('#unauthorized hero-list div')); + let heroes = element.all(by.css('#unauthorized hero-list div')); expect(heroes.count()).toBeGreaterThan(0); heroes.filter(function(elem, index){ @@ -170,7 +171,7 @@ describe('Dependency Injection Tests', function () { return /secret/.test(text); }); }).then(function(filteredElements) { - //console.log("******Secret heroes count: "+filteredElements.length); + // console.log("******Secret heroes count: "+filteredElements.length); expect(filteredElements.length).toEqual(0); }); }); @@ -182,22 +183,22 @@ describe('Dependency Injection Tests', function () { describe('after button click', function() { beforeAll(function (done) { - var buttonEle = element.all(by.cssContainingText('button','Next User')).get(0); + let buttonEle = element.all(by.cssContainingText('button','Next User')).get(0); buttonEle.click().then(done,done); }); it('User is Alice - authorized', function () { - expectedMsg = /Alice, is authorized/; - expect(element(by.css('#user')).getText()).toMatch(expectedMsg); + expectedMsgRx = /Alice, is authorized/; + expect(element(by.css('#user')).getText()).toMatch(expectedMsgRx); }); it('authorized user should have multiple authorized heroes ', function () { - var heroes = element.all(by.css('#authorized hero-list div')); + let heroes = element.all(by.css('#authorized hero-list div')); expect(heroes.count()).toBeGreaterThan(0); }); it('authorized user should have secret heroes', function () { - var heroes = element.all(by.css('#authorized hero-list div')); + let heroes = element.all(by.css('#authorized hero-list div')); expect(heroes.count()).toBeGreaterThan(0); heroes.filter(function(elem, index){ @@ -205,7 +206,7 @@ describe('Dependency Injection Tests', function () { return /secret/.test(text); }); }).then(function(filteredElements) { - //console.log("******Secret heroes count: "+filteredElements.length); + // console.log("******Secret heroes count: "+filteredElements.length); expect(filteredElements.length).toBeGreaterThan(0); }); }); diff --git a/public/docs/_examples/displaying-data/e2e-spec.js b/public/docs/_examples/displaying-data/e2e-spec.ts similarity index 80% rename from public/docs/_examples/displaying-data/e2e-spec.js rename to public/docs/_examples/displaying-data/e2e-spec.ts index 0f01977bb1..9e4e4a9df1 100644 --- a/public/docs/_examples/displaying-data/e2e-spec.js +++ b/public/docs/_examples/displaying-data/e2e-spec.ts @@ -1,6 +1,7 @@ +/// describe('Displaying Data Tests', function () { - var _title = "Tour of Heroes"; - var _defaultHero = 'Windstorm' + let _title = 'Tour of Heroes'; + let _defaultHero = 'Windstorm'; beforeAll(function () { browser.get(''); @@ -15,7 +16,7 @@ describe('Displaying Data Tests', function () { }); it('should have heroes', function () { - var heroEls = element.all(by.css('li')); + let heroEls = element.all(by.css('li')); expect(heroEls.count()).not.toBe(0, 'should have heroes'); }); diff --git a/public/docs/_examples/forms/e2e-spec.js b/public/docs/_examples/forms/e2e-spec.ts similarity index 69% rename from public/docs/_examples/forms/e2e-spec.js rename to public/docs/_examples/forms/e2e-spec.ts index a90138b744..5e68d6e657 100644 --- a/public/docs/_examples/forms/e2e-spec.js +++ b/public/docs/_examples/forms/e2e-spec.ts @@ -1,3 +1,4 @@ +/// describeIf(browser.appIsTs || browser.appIsJs, 'Forms Tests', function () { beforeEach(function () { @@ -10,51 +11,51 @@ describeIf(browser.appIsTs || browser.appIsJs, 'Forms Tests', function () { it('should not display message before submit', function () { - var ele = element(by.css('h2')); + let ele = element(by.css('h2')); expect(ele.isDisplayed()).toBe(false); }); it('should hide form after submit', function () { - var ele = element.all(by.css('h1')).get(0); + let ele = element.all(by.css('h1')).get(0); expect(ele.isDisplayed()).toBe(true); - var b = element.all(by.css('button[type=submit]')).get(0); + let b = element.all(by.css('button[type=submit]')).get(0); b.click().then(function() { expect(ele.isDisplayed()).toBe(false); }); }); it('should display message after submit', function () { - var b = element.all(by.css('button[type=submit]')).get(0); + let b = element.all(by.css('button[type=submit]')).get(0); b.click().then(function() { expect(element(by.css('h2')).getText()).toContain('You submitted the following'); }); }); it('should hide form after submit', function () { - var alterEgoEle = element.all(by.css('input[ngcontrol=alterEgo]')).get(0); + let alterEgoEle = element.all(by.css('input[ngcontrol=alterEgo]')).get(0); expect(alterEgoEle.isDisplayed()).toBe(true); - var submitButtonEle = element.all(by.css('button[type=submit]')).get(0); + let submitButtonEle = element.all(by.css('button[type=submit]')).get(0); submitButtonEle.click().then(function() { expect(alterEgoEle.isDisplayed()).toBe(false); - }) + }); }); it('should reflect submitted data after submit', function () { - var test = 'testing 1 2 3'; - var newValue; - var alterEgoEle = element.all(by.css('input[ngcontrol=alterEgo]')).get(0); + let test = 'testing 1 2 3'; + let newValue: string; + let alterEgoEle = element.all(by.css('input[ngcontrol=alterEgo]')).get(0); alterEgoEle.getAttribute('value').then(function(value) { // alterEgoEle.sendKeys(test); sendKeys(alterEgoEle, test); newValue = value + test; expect(alterEgoEle.getAttribute('value')).toEqual(newValue); }).then(function() { - var b = element.all(by.css('button[type=submit]')).get(0); + let b = element.all(by.css('button[type=submit]')).get(0); return b.click(); }).then(function() { - var alterEgoTextEle = element(by.cssContainingText('div', 'Alter Ego')); + let alterEgoTextEle = element(by.cssContainingText('div', 'Alter Ego')); expect(alterEgoTextEle.isPresent()).toBe(true, 'cannot locate "Alter Ego" label'); - var divEle = element(by.cssContainingText('div', newValue)); + let divEle = element(by.cssContainingText('div', newValue)); expect(divEle.isPresent()).toBe(true, 'cannot locate div with this text: ' + newValue); }); }); diff --git a/public/docs/_examples/hierarchical-dependency-injection/e2e-spec.js b/public/docs/_examples/hierarchical-dependency-injection/e2e-spec.ts similarity index 79% rename from public/docs/_examples/hierarchical-dependency-injection/e2e-spec.js rename to public/docs/_examples/hierarchical-dependency-injection/e2e-spec.ts index a642a74825..57f782de49 100644 --- a/public/docs/_examples/hierarchical-dependency-injection/e2e-spec.js +++ b/public/docs/_examples/hierarchical-dependency-injection/e2e-spec.ts @@ -1,3 +1,4 @@ +/// describe('Hierarchical dependency injection', function () { beforeEach(function () { @@ -14,7 +15,7 @@ describe('Hierarchical dependency injection', function () { }); it('should change to editor view after selection', function () { - var editButtonEle = element.all(by.cssContainingText('button','edit')).get(0); + let editButtonEle = element.all(by.cssContainingText('button','edit')).get(0); editButtonEle.click().then(function() { expect(editButtonEle.isDisplayed()).toBe(false, "edit button should be hidden after selection"); }) @@ -29,19 +30,19 @@ describe('Hierarchical dependency injection', function () { }); function testEdit(shouldSave) { - var inputEle; + let inputEle; // select 2nd ele - var heroEle = element.all(by.css('heroes-list li')).get(1); + let heroEle = element.all(by.css('heroes-list li')).get(1); // get the 2nd span which is the name of the hero - var heroNameEle = heroEle.all(by.css('hero-card span')).get(1); - var editButtonEle = heroEle.element(by.cssContainingText('button','edit')); + let heroNameEle = heroEle.all(by.css('hero-card span')).get(1); + let editButtonEle = heroEle.element(by.cssContainingText('button','edit')); editButtonEle.click().then(function() { inputEle = heroEle.element(by.css('hero-editor input')); // return inputEle.sendKeys("foo"); return sendKeys(inputEle, "foo"); }).then(function() { buttonName = shouldSave ? 'save' : 'cancel'; - var buttonEle = heroEle.element(by.cssContainingText('button', buttonName)); + let buttonEle = heroEle.element(by.cssContainingText('button', buttonName)); return buttonEle.click(); }).then(function() { if (shouldSave) { diff --git a/public/docs/_examples/homepage-hello-world/e2e-spec.js b/public/docs/_examples/homepage-hello-world/e2e-spec.ts similarity index 77% rename from public/docs/_examples/homepage-hello-world/e2e-spec.js rename to public/docs/_examples/homepage-hello-world/e2e-spec.ts index 4cccdfa4e3..fd18afadc5 100644 --- a/public/docs/_examples/homepage-hello-world/e2e-spec.js +++ b/public/docs/_examples/homepage-hello-world/e2e-spec.ts @@ -1,4 +1,4 @@ - +/// describe('Homepage Hello World', function () { beforeAll(function () { @@ -6,15 +6,15 @@ describe('Homepage Hello World', function () { }); // Does it even launch? - var expectedLabel = 'Name:'; + let expectedLabel = 'Name:'; it('should display the label: ' + expectedLabel, function () { expect(element(by.css('label')).getText()).toEqual(expectedLabel); }); it('should display entered name', function () { - var testName = 'Bobby Joe'; - var newValue; - var nameEle = element.all(by.css('input')).get(0); + let testName = 'Bobby Joe'; + let newValue; + let nameEle = element.all(by.css('input')).get(0); nameEle.getAttribute('value').then(function(value) { // nameEle.sendKeys(testName); // should work but doesn't sendKeys(nameEle, testName); // utility that does work @@ -22,7 +22,7 @@ describe('Homepage Hello World', function () { expect(nameEle.getAttribute('value')).toEqual(newValue); }).then(function() { // Check the interpolated message built from name - var helloEle = element.all(by.css('h1')).get(0); + let helloEle = element.all(by.css('h1')).get(0); expect(helloEle.getText()).toEqual('Hello ' + testName + '!'); }); }); diff --git a/public/docs/_examples/homepage-tabs/e2e-spec.js b/public/docs/_examples/homepage-tabs/e2e-spec.ts similarity index 75% rename from public/docs/_examples/homepage-tabs/e2e-spec.js rename to public/docs/_examples/homepage-tabs/e2e-spec.ts index 12f4f4bf53..a481b5c74c 100644 --- a/public/docs/_examples/homepage-tabs/e2e-spec.js +++ b/public/docs/_examples/homepage-tabs/e2e-spec.ts @@ -1,4 +1,4 @@ - +/// describe('Homepage Tabs', function () { beforeAll(function () { @@ -6,7 +6,7 @@ describe('Homepage Tabs', function () { }); // Does it even launch? - var expectedAppTitle = 'Tabs Demo'; + let expectedAppTitle = 'Tabs Demo'; it('should display app title: ' + expectedAppTitle, function () { expect(element(by.css('h4')).getText()).toEqual(expectedAppTitle); }); diff --git a/public/docs/_examples/homepage-todo/e2e-spec.js b/public/docs/_examples/homepage-todo/e2e-spec.ts similarity index 76% rename from public/docs/_examples/homepage-todo/e2e-spec.js rename to public/docs/_examples/homepage-todo/e2e-spec.ts index 4bc9b5f6a6..4776f653a8 100644 --- a/public/docs/_examples/homepage-todo/e2e-spec.js +++ b/public/docs/_examples/homepage-todo/e2e-spec.ts @@ -1,4 +1,4 @@ - +/// describe('Homepage Todo', function () { beforeAll(function () { @@ -6,7 +6,7 @@ describe('Homepage Todo', function () { }); // Does it even launch? - var expectedAppTitle = 'Todo'; + let expectedAppTitle = 'Todo'; it('should display app title: ' + expectedAppTitle, function () { expect(element(by.css('h2')).getText()).toEqual(expectedAppTitle); }); diff --git a/public/docs/_examples/lifecycle-hooks/e2e-spec.js b/public/docs/_examples/lifecycle-hooks/e2e-spec.ts similarity index 76% rename from public/docs/_examples/lifecycle-hooks/e2e-spec.js rename to public/docs/_examples/lifecycle-hooks/e2e-spec.ts index 253efba6b5..a1e9a098a1 100644 --- a/public/docs/_examples/lifecycle-hooks/e2e-spec.js +++ b/public/docs/_examples/lifecycle-hooks/e2e-spec.ts @@ -1,3 +1,4 @@ +/// describe('Lifecycle hooks', function () { beforeAll(function () { @@ -9,10 +10,10 @@ describe('Lifecycle hooks', function () { }); it('should support peek-a-boo', function () { - var pabComp = element(by.css('peek-a-boo-parent peek-a-boo')); + let pabComp = element(by.css('peek-a-boo-parent peek-a-boo')); expect(pabComp.isPresent()).toBe(false, "should not be able to find the 'peek-a-boo' component"); - var pabButton = element.all(by.css('peek-a-boo-parent button')).get(0); - var updateHeroButton = element.all(by.css('peek-a-boo-parent button')).get(1); + let pabButton = element.all(by.css('peek-a-boo-parent button')).get(0); + let updateHeroButton = element.all(by.css('peek-a-boo-parent button')).get(1); expect(pabButton.getText()).toContain('Create Peek'); pabButton.click().then(function () { expect(pabButton.getText()).toContain('Destroy Peek'); @@ -30,12 +31,12 @@ describe('Lifecycle hooks', function () { }); it('should support OnChanges hook', function () { - var onChangesViewEle = element.all(by.css('on-changes div')).get(0); - var inputEles = element.all(by.css('on-changes-parent input')); - var heroNameInputEle = inputEles.get(1); - var powerInputEle = inputEles.get(0); - var titleEle = onChangesViewEle.element(by.css('p')); - var changeLogEles = onChangesViewEle.all(by.css('div')); + let onChangesViewEle = element.all(by.css('on-changes div')).get(0); + let inputEles = element.all(by.css('on-changes-parent input')); + let heroNameInputEle = inputEles.get(1); + let powerInputEle = inputEles.get(0); + let titleEle = onChangesViewEle.element(by.css('p')); + let changeLogEles = onChangesViewEle.all(by.css('div')); expect(titleEle.getText()).toContain('Windstorm can sing'); expect(changeLogEles.count()).toEqual(2, "should start with 2 messages"); @@ -54,13 +55,13 @@ describe('Lifecycle hooks', function () { }); it('should support DoCheck hook', function () { - var doCheckViewEle = element.all(by.css('do-check div')).get(0); - var inputEles = element.all(by.css('do-check-parent input')); - var heroNameInputEle = inputEles.get(1); - var powerInputEle = inputEles.get(0); - var titleEle = doCheckViewEle.element(by.css('p')); - var changeLogEles = doCheckViewEle.all(by.css('div')); - var logCount; + let doCheckViewEle = element.all(by.css('do-check div')).get(0); + let inputEles = element.all(by.css('do-check-parent input')); + let heroNameInputEle = inputEles.get(1); + let powerInputEle = inputEles.get(0); + let titleEle = doCheckViewEle.element(by.css('p')); + let changeLogEles = doCheckViewEle.all(by.css('div')); + let logCount; expect(titleEle.getText()).toContain('Windstorm can sing'); changeLogEles.count().then(function(count) { @@ -86,12 +87,12 @@ describe('Lifecycle hooks', function () { }); it('should support AfterView hooks', function () { - var parentEle = element(by.tagName('after-view-parent')); - var buttonEle = parentEle.element(by.tagName('button')); // Reset - var commentEle = parentEle.element(by.className('comment')); - var logEles = parentEle.all(by.css('h4 ~ div')); - var childViewInputEle = parentEle.element(by.css('my-child input')); - var logCount; + let parentEle = element(by.tagName('after-view-parent')); + let buttonEle = parentEle.element(by.tagName('button')); // Reset + let commentEle = parentEle.element(by.className('comment')); + let logEles = parentEle.all(by.css('h4 ~ div')); + let childViewInputEle = parentEle.element(by.css('my-child input')); + let logCount; expect(childViewInputEle.getAttribute('value')).toContain('Magneta'); expect(commentEle.isPresent()).toBe(false, 'comment should not be in DOM'); @@ -115,12 +116,12 @@ describe('Lifecycle hooks', function () { it('should support AfterContent hooks', function () { - var parentEle = element(by.tagName('after-content-parent')); - var buttonEle = parentEle.element(by.tagName('button')); // Reset - var commentEle = parentEle.element(by.className('comment')); - var logEles = parentEle.all(by.css('h4 ~ div')); - var childViewInputEle = parentEle.element(by.css('my-child input')); - var logCount; + let parentEle = element(by.tagName('after-content-parent')); + let buttonEle = parentEle.element(by.tagName('button')); // Reset + let commentEle = parentEle.element(by.className('comment')); + let logEles = parentEle.all(by.css('h4 ~ div')); + let childViewInputEle = parentEle.element(by.css('my-child input')); + let logCount; expect(childViewInputEle.getAttribute('value')).toContain('Magneta'); expect(commentEle.isPresent()).toBe(false, 'comment should not be in DOM'); @@ -143,11 +144,11 @@ describe('Lifecycle hooks', function () { }); it('should support spy\'s OnInit & OnDestroy hooks', function () { - var inputEle = element(by.css('spy-parent input')); - var addHeroButtonEle = element(by.cssContainingText('spy-parent button','Add Hero')); - var resetHeroesButtonEle = element(by.cssContainingText('spy-parent button','Reset Heroes')); - var heroEles = element.all(by.css('spy-parent div[mySpy')); - var logEles = element.all(by.css('spy-parent h4 ~ div')); + let inputEle = element(by.css('spy-parent input')); + let addHeroButtonEle = element(by.cssContainingText('spy-parent button','Add Hero')); + let resetHeroesButtonEle = element(by.cssContainingText('spy-parent button','Reset Heroes')); + let heroEles = element.all(by.css('spy-parent div[mySpy')); + let logEles = element.all(by.css('spy-parent h4 ~ div')); expect(heroEles.count()).toBe(2, 'should have two heroes displayed'); expect(logEles.count()).toBe(2, 'should have two log entries'); sendKeys(inputEle, "-test-").then(function() { @@ -164,10 +165,10 @@ describe('Lifecycle hooks', function () { }); it('should support "spy counter"', function () { - var updateCounterButtonEle = element(by.cssContainingText('counter-parent button','Update')); - var resetCounterButtonEle = element(by.cssContainingText('counter-parent button','Reset')); - var textEle = element(by.css('counter-parent my-counter > div')); - var logEles = element.all(by.css('counter-parent h4 ~ div')); + let updateCounterButtonEle = element(by.cssContainingText('counter-parent button','Update')); + let resetCounterButtonEle = element(by.cssContainingText('counter-parent button','Reset')); + let textEle = element(by.css('counter-parent my-counter > div')); + let logEles = element.all(by.css('counter-parent h4 ~ div')); expect(textEle.getText()).toContain('Counter = 0'); expect(logEles.count()).toBe(2, 'should start with two log entries'); updateCounterButtonEle.click().then(function() { diff --git a/public/docs/_examples/package.json b/public/docs/_examples/package.json index 7e625af6e6..a4cbe17705 100644 --- a/public/docs/_examples/package.json +++ b/public/docs/_examples/package.json @@ -69,6 +69,7 @@ "rimraf": "^2.5.2", "style-loader": "^0.13.1", "ts-loader": "^0.8.2", + "ts-node": "^0.7.3", "typescript": "^1.8.10", "typings": "^1.0.4", "webpack": "^1.13.0", diff --git a/public/docs/_examples/pipes/e2e-spec.js b/public/docs/_examples/pipes/e2e-spec.ts similarity index 78% rename from public/docs/_examples/pipes/e2e-spec.js rename to public/docs/_examples/pipes/e2e-spec.ts index ae8327dd0d..560791671b 100644 --- a/public/docs/_examples/pipes/e2e-spec.js +++ b/public/docs/_examples/pipes/e2e-spec.ts @@ -1,3 +1,4 @@ +/// describe('Pipes', function () { beforeAll(function () { @@ -23,9 +24,9 @@ describe('Pipes', function () { }); it('should be able to toggle birthday formats', function () { - var birthDayEle = element(by.css('hero-birthday2 > p')); + let birthDayEle = element(by.css('hero-birthday2 > p')); expect(birthDayEle.getText()).toEqual("The hero's birthday is 4/15/1988"); - var buttonEle = element(by.cssContainingText('hero-birthday2 > button', "Toggle Format")); + let buttonEle = element(by.cssContainingText('hero-birthday2 > button', "Toggle Format")); expect(buttonEle.isDisplayed()).toBe(true); buttonEle.click().then(function() { expect(birthDayEle.getText()).toEqual("The hero's birthday is Friday, April 15, 1988"); @@ -33,7 +34,7 @@ describe('Pipes', function () { }); it('should be able to chain and compose pipes', function () { - var chainedPipeEles = element.all(by.cssContainingText('my-app p', "The chained hero's")); + let chainedPipeEles = element.all(by.cssContainingText('my-app p', "The chained hero's")); expect(chainedPipeEles.count()).toBe(3, "should have 3 chained pipe examples"); expect(chainedPipeEles.get(0).getText()).toContain('APR 15, 1988'); expect(chainedPipeEles.get(1).getText()).toContain('FRIDAY, APRIL 15, 1988'); @@ -41,15 +42,15 @@ describe('Pipes', function () { }); it('should be able to use ExponentialStrengthPipe pipe', function () { - var ele = element(by.css('power-booster p')); + let ele = element(by.css('power-booster p')); expect(ele.getText()).toContain('Super power boost: 1024'); }); it('should be able to use the exponential calculator', function () { - var eles = element.all(by.css('power-boost-calculator input')); - var baseInputEle = eles.get(0); - var factorInputEle = eles.get(1); - var outputEle = element(by.css('power-boost-calculator p')); + let eles = element.all(by.css('power-boost-calculator input')); + let baseInputEle = eles.get(0); + let factorInputEle = eles.get(1); + let outputEle = element(by.css('power-boost-calculator p')); baseInputEle.clear().then(function() { return sendKeys(baseInputEle, "7"); }).then(function() { @@ -63,11 +64,11 @@ describe('Pipes', function () { it('should support flying heroes (pure) ', function () { - var nameEle = element(by.css('flying-heroes input[type="text"]')); - var canFlyCheckEle = element(by.css('flying-heroes #can-fly')); - var mutateCheckEle = element(by.css('flying-heroes #mutate')); - var resetEle = element(by.css('flying-heroes button')); - var flyingHeroesEle = element.all(by.css('flying-heroes #flyers div')); + let nameEle = element(by.css('flying-heroes input[type="text"]')); + let canFlyCheckEle = element(by.css('flying-heroes #can-fly')); + let mutateCheckEle = element(by.css('flying-heroes #mutate')); + let resetEle = element(by.css('flying-heroes button')); + let flyingHeroesEle = element.all(by.css('flying-heroes #flyers div')); expect(canFlyCheckEle.getAttribute('checked')).toEqual('true', 'should default to "can fly"'); expect(mutateCheckEle.getAttribute('checked')).toEqual('true', 'should default to mutating array'); @@ -94,11 +95,11 @@ describe('Pipes', function () { it('should support flying heroes (impure) ', function () { - var nameEle = element(by.css('flying-heroes-impure input[type="text"]')); - var canFlyCheckEle = element(by.css('flying-heroes-impure #can-fly')); - var mutateCheckEle = element(by.css('flying-heroes-impure #mutate')); - var resetEle = element(by.css('flying-heroes-impure button')); - var flyingHeroesEle = element.all(by.css('flying-heroes-impure #flyers div')); + let nameEle = element(by.css('flying-heroes-impure input[type="text"]')); + let canFlyCheckEle = element(by.css('flying-heroes-impure #can-fly')); + let mutateCheckEle = element(by.css('flying-heroes-impure #mutate')); + let resetEle = element(by.css('flying-heroes-impure button')); + let flyingHeroesEle = element.all(by.css('flying-heroes-impure #flyers div')); expect(canFlyCheckEle.getAttribute('checked')).toEqual('true', 'should default to "can fly"'); expect(mutateCheckEle.getAttribute('checked')).toEqual('true', 'should default to mutating array'); diff --git a/public/docs/_examples/quickstart/e2e-spec.js b/public/docs/_examples/quickstart/e2e-spec.ts similarity index 71% rename from public/docs/_examples/quickstart/e2e-spec.js rename to public/docs/_examples/quickstart/e2e-spec.ts index 52bb8ec7af..53f587645e 100644 --- a/public/docs/_examples/quickstart/e2e-spec.js +++ b/public/docs/_examples/quickstart/e2e-spec.ts @@ -1,7 +1,7 @@ - +/// describe('QuickStart E2E Tests', function () { - var expectedMsg = 'My First Angular 2 App'; + let expectedMsg = 'My First Angular 2 App'; beforeEach(function () { diff --git a/public/docs/_examples/router-deprecated/e2e-spec.js b/public/docs/_examples/router-deprecated/e2e-spec.js index 4e3018b5c2..1cb536b53e 100644 --- a/public/docs/_examples/router-deprecated/e2e-spec.js +++ b/public/docs/_examples/router-deprecated/e2e-spec.js @@ -1,123 +1,111 @@ +/// describe('Router', function () { - - beforeAll(function () { - browser.get(''); - }); - - function getPageStruct() { - hrefEles = element.all(by.css('my-app a')); - - return { - hrefs: hrefEles, - routerParent: element(by.css('my-app > undefined')), - routerTitle: element(by.css('my-app > undefined > h2')), - - crisisHref: hrefEles.get(0), - crisisList: element.all(by.css('my-app > undefined > undefined li')), - crisisDetail: element(by.css('my-app > undefined > undefined > div')), - crisisDetailTitle: element(by.css('my-app > undefined > undefined > div > h3')), - - heroesHref: hrefEles.get(1), - heroesList: element.all(by.css('my-app > undefined li')), - heroDetail: element(by.css('my-app > undefined > div')), - heroDetailTitle: element(by.css('my-app > undefined > div > h3')), - + beforeAll(function () { + browser.get(''); + }); + function getPageStruct() { + hrefEles = element.all(by.css('my-app a')); + return { + hrefs: hrefEles, + routerParent: element(by.css('my-app > undefined')), + routerTitle: element(by.css('my-app > undefined > h2')), + crisisHref: hrefEles.get(0), + crisisList: element.all(by.css('my-app > undefined > undefined li')), + crisisDetail: element(by.css('my-app > undefined > undefined > div')), + crisisDetailTitle: element(by.css('my-app > undefined > undefined > div > h3')), + heroesHref: hrefEles.get(1), + heroesList: element.all(by.css('my-app > undefined li')), + heroDetail: element(by.css('my-app > undefined > div')), + heroDetailTitle: element(by.css('my-app > undefined > div > h3')), + }; } - } - - it('should be able to see the start screen', function () { - var page = getPageStruct(); - expect(page.hrefs.count()).toEqual(2, 'should be two dashboard choices'); - expect(page.crisisHref.getText()).toEqual("Crisis Center"); - expect(page.heroesHref.getText()).toEqual("Heroes"); - }); - - it('should be able to see crises center items', function () { - var page = getPageStruct(); - expect(page.crisisList.count()).toBe(4, "should be 4 crisis center entries at start"); - }); - - it('should be able to see hero items', function () { - var page = getPageStruct(); - page.heroesHref.click().then(function() { - expect(page.routerTitle.getText()).toContain('HEROES'); - expect(page.heroesList.count()).toBe(6, "should be 6 heroes"); + it('should be able to see the start screen', function () { + var page = getPageStruct(); + expect(page.hrefs.count()).toEqual(2, 'should be two dashboard choices'); + expect(page.crisisHref.getText()).toEqual("Crisis Center"); + expect(page.heroesHref.getText()).toEqual("Heroes"); }); - }); - - it('should be able to toggle the views', function () { - var page = getPageStruct(); - page.crisisHref.click().then(function() { - expect(page.crisisList.count()).toBe(4, "should be 4 crisis center entries"); - return page.heroesHref.click(); - }).then(function() { - expect(page.heroesList.count()).toBe(6, "should be 6 heroes"); + it('should be able to see crises center items', function () { + var page = getPageStruct(); + expect(page.crisisList.count()).toBe(4, "should be 4 crisis center entries at start"); }); - }); - - it('should be able to edit and save details from the crisis center view', function () { - crisisCenterEdit(2, true); - }); - - it('should be able to edit and cancel details from the crisis center view', function () { - crisisCenterEdit(3, false); - }); - - it('should be able to edit and save details from the heroes view', function () { - var page = getPageStruct(); - var heroEle, heroText; - page.heroesHref.click().then(function() { - heroEle = page.heroesList.get(4); - return heroEle.getText(); - }).then(function(text) { - expect(text.length).toBeGreaterThan(0, 'should have some text'); - // remove leading id from text - heroText = text.substr(text.indexOf(' ')).trim(); - return heroEle.click(); - }).then(function() { - expect(page.heroesList.count()).toBe(0, "should no longer see crisis center entries"); - expect(page.heroDetail.isPresent()).toBe(true, 'should be able to see crisis detail'); - expect(page.heroDetailTitle.getText()).toContain(heroText); - var inputEle = page.heroDetail.element(by.css('input')); - return sendKeys(inputEle, '-foo'); - }).then(function() { - expect(page.heroDetailTitle.getText()).toContain(heroText + '-foo'); - var buttonEle = page.heroDetail.element(by.css('button')); - return buttonEle.click(); - }).then(function() { - expect(heroEle.getText()).toContain(heroText + '-foo'); - }) - }); - - function crisisCenterEdit(index, shouldSave) { - var page = getPageStruct(); - var crisisEle, crisisText; - page.crisisHref.click() - .then(function () { - crisisEle = page.crisisList.get(index); - return crisisEle.getText(); - }).then(function (text) { - expect(text.length).toBeGreaterThan(0, 'should have some text'); - // remove leading id from text - crisisText = text.substr(text.indexOf(' ')).trim(); - return crisisEle.click(); - }).then(function () { - expect(page.crisisList.count()).toBe(0, "should no longer see crisis center entries"); - expect(page.crisisDetail.isPresent()).toBe(true, 'should be able to see crisis detail'); - expect(page.crisisDetailTitle.getText()).toContain(crisisText); - var inputEle = page.crisisDetail.element(by.css('input')); - return sendKeys(inputEle, '-foo'); - }).then(function () { - expect(page.crisisDetailTitle.getText()).toContain(crisisText + '-foo'); - var buttonEle = page.crisisDetail.element(by.cssContainingText('button', shouldSave ? 'Save' : 'Cancel')); - return buttonEle.click(); - }).then(function () { - if (shouldSave) { - expect(crisisEle.getText()).toContain(crisisText + '-foo'); - } else { - expect(crisisEle.getText()).not.toContain(crisisText + '-foo'); - } + it('should be able to see hero items', function () { + var page = getPageStruct(); + page.heroesHref.click().then(function () { + expect(page.routerTitle.getText()).toContain('HEROES'); + expect(page.heroesList.count()).toBe(6, "should be 6 heroes"); + }); }); - } - + it('should be able to toggle the views', function () { + var page = getPageStruct(); + page.crisisHref.click().then(function () { + expect(page.crisisList.count()).toBe(4, "should be 4 crisis center entries"); + return page.heroesHref.click(); + }).then(function () { + expect(page.heroesList.count()).toBe(6, "should be 6 heroes"); + }); + }); + it('should be able to edit and save details from the crisis center view', function () { + crisisCenterEdit(2, true); + }); + it('should be able to edit and cancel details from the crisis center view', function () { + crisisCenterEdit(3, false); + }); + it('should be able to edit and save details from the heroes view', function () { + var page = getPageStruct(); + var heroEle, heroText; + page.heroesHref.click().then(function () { + heroEle = page.heroesList.get(4); + return heroEle.getText(); + }).then(function (text) { + expect(text.length).toBeGreaterThan(0, 'should have some text'); + // remove leading id from text + heroText = text.substr(text.indexOf(' ')).trim(); + return heroEle.click(); + }).then(function () { + expect(page.heroesList.count()).toBe(0, "should no longer see crisis center entries"); + expect(page.heroDetail.isPresent()).toBe(true, 'should be able to see crisis detail'); + expect(page.heroDetailTitle.getText()).toContain(heroText); + var inputEle = page.heroDetail.element(by.css('input')); + return sendKeys(inputEle, '-foo'); + }).then(function () { + expect(page.heroDetailTitle.getText()).toContain(heroText + '-foo'); + var buttonEle = page.heroDetail.element(by.css('button')); + return buttonEle.click(); + }).then(function () { + expect(heroEle.getText()).toContain(heroText + '-foo'); + }); + }); + function crisisCenterEdit(index, shouldSave) { + var page = getPageStruct(); + var crisisEle, crisisText; + page.crisisHref.click() + .then(function () { + crisisEle = page.crisisList.get(index); + return crisisEle.getText(); + }).then(function (text) { + expect(text.length).toBeGreaterThan(0, 'should have some text'); + // remove leading id from text + crisisText = text.substr(text.indexOf(' ')).trim(); + return crisisEle.click(); + }).then(function () { + expect(page.crisisList.count()).toBe(0, "should no longer see crisis center entries"); + expect(page.crisisDetail.isPresent()).toBe(true, 'should be able to see crisis detail'); + expect(page.crisisDetailTitle.getText()).toContain(crisisText); + var inputEle = page.crisisDetail.element(by.css('input')); + return sendKeys(inputEle, '-foo'); + }).then(function () { + expect(page.crisisDetailTitle.getText()).toContain(crisisText + '-foo'); + var buttonEle = page.crisisDetail.element(by.cssContainingText('button', shouldSave ? 'Save' : 'Cancel')); + return buttonEle.click(); + }).then(function () { + if (shouldSave) { + expect(crisisEle.getText()).toContain(crisisText + '-foo'); + } + else { + expect(crisisEle.getText()).not.toContain(crisisText + '-foo'); + } + }); + } }); +//# sourceMappingURL=e2e-spec.js.map \ No newline at end of file diff --git a/public/docs/_examples/router-deprecated/e2e-spec.ts b/public/docs/_examples/router-deprecated/e2e-spec.ts new file mode 100644 index 0000000000..241074ec8f --- /dev/null +++ b/public/docs/_examples/router-deprecated/e2e-spec.ts @@ -0,0 +1,124 @@ +/// +describe('Router', function () { + + beforeAll(function () { + browser.get(''); + }); + + function getPageStruct() { + hrefEles = element.all(by.css('my-app a')); + + return { + hrefs: hrefEles, + routerParent: element(by.css('my-app > undefined')), + routerTitle: element(by.css('my-app > undefined > h2')), + + crisisHref: hrefEles.get(0), + crisisList: element.all(by.css('my-app > undefined > undefined li')), + crisisDetail: element(by.css('my-app > undefined > undefined > div')), + crisisDetailTitle: element(by.css('my-app > undefined > undefined > div > h3')), + + heroesHref: hrefEles.get(1), + heroesList: element.all(by.css('my-app > undefined li')), + heroDetail: element(by.css('my-app > undefined > div')), + heroDetailTitle: element(by.css('my-app > undefined > div > h3')), + + } + } + + it('should be able to see the start screen', function () { + let page = getPageStruct(); + expect(page.hrefs.count()).toEqual(2, 'should be two dashboard choices'); + expect(page.crisisHref.getText()).toEqual("Crisis Center"); + expect(page.heroesHref.getText()).toEqual("Heroes"); + }); + + it('should be able to see crises center items', function () { + let page = getPageStruct(); + expect(page.crisisList.count()).toBe(4, "should be 4 crisis center entries at start"); + }); + + it('should be able to see hero items', function () { + let page = getPageStruct(); + page.heroesHref.click().then(function() { + expect(page.routerTitle.getText()).toContain('HEROES'); + expect(page.heroesList.count()).toBe(6, "should be 6 heroes"); + }); + }); + + it('should be able to toggle the views', function () { + let page = getPageStruct(); + page.crisisHref.click().then(function() { + expect(page.crisisList.count()).toBe(4, "should be 4 crisis center entries"); + return page.heroesHref.click(); + }).then(function() { + expect(page.heroesList.count()).toBe(6, "should be 6 heroes"); + }); + }); + + it('should be able to edit and save details from the crisis center view', function () { + crisisCenterEdit(2, true); + }); + + it('should be able to edit and cancel details from the crisis center view', function () { + crisisCenterEdit(3, false); + }); + + it('should be able to edit and save details from the heroes view', function () { + let page = getPageStruct(); + let heroEle, heroText; + page.heroesHref.click().then(function() { + heroEle = page.heroesList.get(4); + return heroEle.getText(); + }).then(function(text) { + expect(text.length).toBeGreaterThan(0, 'should have some text'); + // remove leading id from text + heroText = text.substr(text.indexOf(' ')).trim(); + return heroEle.click(); + }).then(function() { + expect(page.heroesList.count()).toBe(0, "should no longer see crisis center entries"); + expect(page.heroDetail.isPresent()).toBe(true, 'should be able to see crisis detail'); + expect(page.heroDetailTitle.getText()).toContain(heroText); + let inputEle = page.heroDetail.element(by.css('input')); + return sendKeys(inputEle, '-foo'); + }).then(function() { + expect(page.heroDetailTitle.getText()).toContain(heroText + '-foo'); + let buttonEle = page.heroDetail.element(by.css('button')); + return buttonEle.click(); + }).then(function() { + expect(heroEle.getText()).toContain(heroText + '-foo'); + }) + }); + + function crisisCenterEdit(index, shouldSave) { + let page = getPageStruct(); + let crisisEle, crisisText; + page.crisisHref.click() + .then(function () { + crisisEle = page.crisisList.get(index); + return crisisEle.getText(); + }).then(function (text) { + expect(text.length).toBeGreaterThan(0, 'should have some text'); + // remove leading id from text + crisisText = text.substr(text.indexOf(' ')).trim(); + return crisisEle.click(); + }).then(function () { + expect(page.crisisList.count()).toBe(0, "should no longer see crisis center entries"); + expect(page.crisisDetail.isPresent()).toBe(true, 'should be able to see crisis detail'); + expect(page.crisisDetailTitle.getText()).toContain(crisisText); + let inputEle = page.crisisDetail.element(by.css('input')); + return sendKeys(inputEle, '-foo'); + }).then(function () { + expect(page.crisisDetailTitle.getText()).toContain(crisisText + '-foo'); + let buttonEle = page.crisisDetail.element(by.cssContainingText('button', shouldSave ? 'Save' : 'Cancel')); + return buttonEle.click(); + }).then(function () { + if (shouldSave) { + expect(crisisEle.getText()).toContain(crisisText + '-foo'); + } else { + expect(crisisEle.getText()).not.toContain(crisisText + '-foo'); + } + }); + } + +}); diff --git a/public/docs/_examples/router/e2e-spec.js b/public/docs/_examples/router/e2e-spec.ts similarity index 88% rename from public/docs/_examples/router/e2e-spec.js rename to public/docs/_examples/router/e2e-spec.ts index 73bf120d0c..e0749f1d0f 100644 --- a/public/docs/_examples/router/e2e-spec.js +++ b/public/docs/_examples/router/e2e-spec.ts @@ -1,3 +1,4 @@ +/// describe('Router', function () { beforeAll(function () { @@ -26,19 +27,19 @@ describe('Router', function () { } it('should be able to see the start screen', function () { - var page = getPageStruct(); + let page = getPageStruct(); expect(page.hrefs.count()).toEqual(2, 'should be two dashboard choices'); expect(page.crisisHref.getText()).toEqual("Crisis Center"); expect(page.heroesHref.getText()).toEqual("Heroes"); }); it('should be able to see crises center items', function () { - var page = getPageStruct(); + let page = getPageStruct(); expect(page.crisisList.count()).toBe(4, "should be 4 crisis center entries at start"); }); it('should be able to see hero items', function () { - var page = getPageStruct(); + let page = getPageStruct(); page.heroesHref.click().then(function() { expect(page.routerTitle.getText()).toContain('HEROES'); expect(page.heroesList.count()).toBe(6, "should be 6 heroes"); @@ -46,7 +47,7 @@ describe('Router', function () { }); it('should be able to toggle the views', function () { - var page = getPageStruct(); + let page = getPageStruct(); page.crisisHref.click().then(function() { expect(page.crisisList.count()).toBe(4, "should be 4 crisis center entries"); return page.heroesHref.click(); @@ -64,8 +65,8 @@ describe('Router', function () { }); it('should be able to edit and save details from the heroes view', function () { - var page = getPageStruct(); - var heroEle, heroText; + let page = getPageStruct(); + let heroEle, heroText; page.heroesHref.click().then(function() { heroEle = page.heroesList.get(4); return heroEle.getText(); @@ -78,11 +79,11 @@ describe('Router', function () { expect(page.heroesList.count()).toBe(0, "should no longer see crisis center entries"); expect(page.heroDetail.isPresent()).toBe(true, 'should be able to see crisis detail'); expect(page.heroDetailTitle.getText()).toContain(heroText); - var inputEle = page.heroDetail.element(by.css('input')); + let inputEle = page.heroDetail.element(by.css('input')); return sendKeys(inputEle, '-foo'); }).then(function() { expect(page.heroDetailTitle.getText()).toContain(heroText + '-foo'); - var buttonEle = page.heroDetail.element(by.css('button')); + let buttonEle = page.heroDetail.element(by.css('button')); return buttonEle.click(); }).then(function() { expect(heroEle.getText()).toContain(heroText + '-foo'); @@ -90,8 +91,8 @@ describe('Router', function () { }); function crisisCenterEdit(index, shouldSave) { - var page = getPageStruct(); - var crisisEle, crisisText; + let page = getPageStruct(); + let crisisEle, crisisText; page.crisisHref.click() .then(function () { crisisEle = page.crisisList.get(index); @@ -105,11 +106,11 @@ describe('Router', function () { expect(page.crisisList.count()).toBe(0, "should no longer see crisis center entries"); expect(page.crisisDetail.isPresent()).toBe(true, 'should be able to see crisis detail'); expect(page.crisisDetailTitle.getText()).toContain(crisisText); - var inputEle = page.crisisDetail.element(by.css('input')); + let inputEle = page.crisisDetail.element(by.css('input')); return sendKeys(inputEle, '-foo'); }).then(function () { expect(page.crisisDetailTitle.getText()).toContain(crisisText + '-foo'); - var buttonEle = page.crisisDetail.element(by.cssContainingText('button', shouldSave ? 'Save' : 'Cancel')); + let buttonEle = page.crisisDetail.element(by.cssContainingText('button', shouldSave ? 'Save' : 'Cancel')); return buttonEle.click(); }).then(function () { if (shouldSave) { diff --git a/public/docs/_examples/server-communication/e2e-spec.js b/public/docs/_examples/server-communication/e2e-spec.ts similarity index 80% rename from public/docs/_examples/server-communication/e2e-spec.js rename to public/docs/_examples/server-communication/e2e-spec.ts index 98a3f1e03a..ef1dc3e304 100644 --- a/public/docs/_examples/server-communication/e2e-spec.js +++ b/public/docs/_examples/server-communication/e2e-spec.ts @@ -1,3 +1,4 @@ +/// describe('Server Communication', function () { beforeAll(function () { @@ -6,14 +7,14 @@ describe('Server Communication', function () { describe('Tour of Heroes (Observable)', function () { - var initialHeroCount = 4; - var newHeroName = 'Mr. IQ'; - var heroCountAfterAdd = 5; + let initialHeroCount = 4; + let newHeroName = 'Mr. IQ'; + let heroCountAfterAdd = 5; - var heroListComp = element(by.tagName('hero-list')); - var addButton = heroListComp.element(by.tagName('button')); - var heroTags = heroListComp.all(by.tagName('li')); - var heroNameInput = heroListComp.element(by.tagName('input')); + let heroListComp = element(by.tagName('hero-list')); + let addButton = heroListComp.element(by.tagName('button')); + let heroTags = heroListComp.all(by.tagName('li')); + let heroNameInput = heroListComp.element(by.tagName('input')); it('should exist', function() { expect(heroListComp).toBeDefined(' must exist'); @@ -36,7 +37,7 @@ describe('Server Communication', function () { sendKeys(heroNameInput, newHeroName); addButton.click().then(function() { expect(heroTags.count()).toBe(heroCountAfterAdd, 'A new hero should be added'); - var newHeroInList = heroTags.get(heroCountAfterAdd - 1).getText(); + let newHeroInList = heroTags.get(heroCountAfterAdd - 1).getText(); expect(newHeroInList).toBe(newHeroName, 'The hero should be added to the end of the list'); }); }) @@ -45,9 +46,9 @@ describe('Server Communication', function () { describe('Wikipedia Demo', function () { it('should initialize the demo with empty result list', function () { - var myWikiComp = element(by.tagName('my-wiki')); + let myWikiComp = element(by.tagName('my-wiki')); expect(myWikiComp).toBeDefined(' must exist'); - var resultList = myWikiComp.all(by.tagName('li')); + let resultList = myWikiComp.all(by.tagName('li')); expect(resultList.count()).toBe(0, 'result list must be empty'); }); @@ -77,9 +78,9 @@ describe('Server Communication', function () { describe('Smarter Wikipedia Demo', function () { it('should initialize the demo with empty result list', function () { - var myWikiSmartComp = element(by.tagName('my-wiki-smart')); + let myWikiSmartComp = element(by.tagName('my-wiki-smart')); expect(myWikiSmartComp).toBeDefined(' must exist'); - var resultList = myWikiSmartComp.all(by.tagName('li')); + let resultList = myWikiSmartComp.all(by.tagName('li')); expect(resultList.count()).toBe(0, 'result list must be empty'); }); @@ -111,14 +112,14 @@ describe('Server Communication', function () { }); function testForResult(componentTagName, keyPressed, hasListBeforeSearch, done) { - var searchWait = 1000; // Wait for wikipedia but not so long that tests timeout - var wikiComponent = element(by.tagName(componentTagName)); + let searchWait = 1000; // Wait for wikipedia but not so long that tests timeout + let wikiComponent = element(by.tagName(componentTagName)); expect(wikiComponent).toBeDefined('<' + componentTagName + '> must exist'); - var searchBox = wikiComponent.element(by.tagName('input')); + let searchBox = wikiComponent.element(by.tagName('input')); expect(searchBox).toBeDefined(' for search must exist'); searchBox.sendKeys(keyPressed).then(function () { - var resultList = wikiComponent.all(by.tagName('li')); + let resultList = wikiComponent.all(by.tagName('li')); if (hasListBeforeSearch) { expect(resultList.count()).toBeGreaterThan(0, 'result list should not be empty before search'); diff --git a/public/docs/_examples/structural-directives/e2e-spec.js b/public/docs/_examples/structural-directives/e2e-spec.ts similarity index 76% rename from public/docs/_examples/structural-directives/e2e-spec.js rename to public/docs/_examples/structural-directives/e2e-spec.ts index a2ed0455b9..032b923f60 100644 --- a/public/docs/_examples/structural-directives/e2e-spec.js +++ b/public/docs/_examples/structural-directives/e2e-spec.ts @@ -1,3 +1,4 @@ +/// describe('Structural Directives', function () { // tests interact - so we need beforeEach instead of beforeAll @@ -6,16 +7,16 @@ describe('Structural Directives', function () { }); it('should be able to use ngFor, ngIf and ngWhen together', function () { - var allDivEles = element.all(by.css('structural-directives > div')); + let allDivEles = element.all(by.css('structural-directives > div')); expect(allDivEles.get(0).getText()).toEqual('Mr. Nice'); expect(allDivEles.get(1).getText()).toEqual('Mr. Nice'); expect(allDivEles.get(4).getText()).toEqual('Ready'); }); it('should be able to toggle ngIf with a button', function () { - var setConditionButtonEle = element.all(by.css('button')).get(0); - var conditionTrueEles = element.all(by.cssContainingText('p', 'condition is true')); - var conditionFalseEles = element.all(by.cssContainingText('p', 'condition is false')); + let setConditionButtonEle = element.all(by.css('button')).get(0); + let conditionTrueEles = element.all(by.cssContainingText('p', 'condition is true')); + let conditionFalseEles = element.all(by.cssContainingText('p', 'condition is false')); expect(conditionTrueEles.count()).toBe(2, 'should be two condition true elements'); expect(conditionFalseEles.count()).toBe(0, 'should be no condition false elements'); setConditionButtonEle.click().then(function() { @@ -25,13 +26,13 @@ describe('Structural Directives', function () { }); it('should be able to compare use of ngIf with changing css visibility', function () { - var setConditionButtonEle = element.all(by.css('button')).get(0); - var ngIfButtonEle = element(by.cssContainingText('button', 'if | !if')); - var ngIfParentEle = ngIfButtonEle.element(by.xpath('..')); - var ngIfSiblingEle = ngIfParentEle.element(by.css('heavy-loader')); - var cssButtonEle = element(by.cssContainingText('button', 'show | hide')); - var cssSiblingEle = cssButtonEle.element(by.xpath('..')).element(by.css('heavy-loader')); - var setConditionText; + let setConditionButtonEle = element.all(by.css('button')).get(0); + let ngIfButtonEle = element(by.cssContainingText('button', 'if | !if')); + let ngIfParentEle = ngIfButtonEle.element(by.xpath('..')); + let ngIfSiblingEle = ngIfParentEle.element(by.css('heavy-loader')); + let cssButtonEle = element(by.cssContainingText('button', 'show | hide')); + let cssSiblingEle = cssButtonEle.element(by.xpath('..')).element(by.css('heavy-loader')); + let setConditionText; setConditionButtonEle.getText().then(function(text) { setConditionText = text; expect(ngIfButtonEle.isPresent()).toBe(true, 'should be able to find ngIfButton'); @@ -54,8 +55,8 @@ describe('Structural Directives', function () { }); it('should be able to use *ngIf ', function () { - var setConditionButtonEle = element.all(by.css('button')).get(0); - var displayEles = element.all(by.cssContainingText('p', 'Our heroes are true!')); + let setConditionButtonEle = element.all(by.css('button')).get(0); + let displayEles = element.all(by.cssContainingText('p', 'Our heroes are true!')); expect(displayEles.count()).toBe(2, "should be displaying two ngIf elements"); setConditionButtonEle.click().then(function() { expect(displayEles.count()).toBe(0, "should nog longer be displaying ngIf elements"); diff --git a/public/docs/_examples/style-guide/e2e-spec.js b/public/docs/_examples/style-guide/e2e-spec.ts similarity index 69% rename from public/docs/_examples/style-guide/e2e-spec.js rename to public/docs/_examples/style-guide/e2e-spec.ts index dcd5f2af20..1a64dd1598 100644 --- a/public/docs/_examples/style-guide/e2e-spec.js +++ b/public/docs/_examples/style-guide/e2e-spec.ts @@ -1,8 +1,9 @@ +/// describe('Style Guide', function () { it('01-01', function () { browser.get('#/01-01'); - var pre = element(by.tagName('toh-heroes > pre')); + let pre = element(by.tagName('toh-heroes > pre')); expect(pre.getText()).toContain('Bombasto'); expect(pre.getText()).toContain('Tornado'); expect(pre.getText()).toContain('Magneta'); @@ -11,8 +12,8 @@ describe('Style Guide', function () { it('02-07', function () { browser.get('#/02-07'); - var hero = element(by.tagName('toh-hero > div')); - var users = element(by.tagName('admin-users > div')); + let hero = element(by.tagName('toh-hero > div')); + let users = element(by.tagName('admin-users > div')); expect(hero.getText()).toBe('hero component'); expect(users.getText()).toBe('users component'); @@ -21,21 +22,21 @@ describe('Style Guide', function () { it('02-08', function () { browser.get('#/02-08'); - var input = element(by.tagName('input[tohvalidate]')); + let input = element(by.tagName('input[tohvalidate]')); expect(input.isPresent()).toBe(true); }); it('03-01', function () { browser.get('#/03-01'); - var div = element(by.tagName('sg-app > div')); + let div = element(by.tagName('sg-app > div')); expect(div.getText()).toBe('The expected error is 42'); }); it('03-02', function () { browser.get('#/03-02'); - var divs = element.all(by.tagName('sg-app > div')); + let divs = element.all(by.tagName('sg-app > div')); expect(divs.get(0).getText()).toBe('Heroes url: api/heroes'); expect(divs.get(1).getText()).toBe('Villains url: api/villains'); }); @@ -43,14 +44,14 @@ describe('Style Guide', function () { it('03-03', function () { browser.get('#/03-03'); - var div = element(by.tagName('sg-app > div')); + let div = element(by.tagName('sg-app > div')); expect(div.getText()).toBe('Our hero is RubberMan and He is so elastic'); }); it('03-04', function () { browser.get('#/03-04'); - var buttons = element.all(by.tagName('sg-app > button')); + let buttons = element.all(by.tagName('sg-app > button')); expect(buttons.get(0).getText()).toBe('Show toast'); expect(buttons.get(1).getText()).toBe('Hide toast'); }); @@ -58,10 +59,10 @@ describe('Style Guide', function () { it('03-05', function () { browser.get('#/03-05'); - var div = element(by.tagName('sg-app > div')); + let div = element(by.tagName('sg-app > div')); expect(div.getText()).toBe('Actual favorite: Windstorm'); - var lis = element.all(by.tagName('sg-app > ul > li')); + let lis = element.all(by.tagName('sg-app > ul > li')); expect(lis.get(0).getText()).toBe('Windstorm'); expect(lis.get(1).getText()).toBe('Bombasto'); expect(lis.get(2).getText()).toBe('Magneta'); @@ -71,10 +72,10 @@ describe('Style Guide', function () { it('03-06', function () { browser.get('#/03-06'); - var div = element(by.tagName('sg-app > div')); + let div = element(by.tagName('sg-app > div')); expect(div.getText()).toBe('Actual favorite: Windstorm'); - var lis = element.all(by.tagName('sg-app > ul > li')); + let lis = element.all(by.tagName('sg-app > ul > li')); expect(lis.get(0).getText()).toBe('Windstorm'); expect(lis.get(1).getText()).toBe('Bombasto'); expect(lis.get(2).getText()).toBe('Magneta'); @@ -84,77 +85,77 @@ describe('Style Guide', function () { it('04-10', function () { browser.get('#/04-10'); - var div = element(by.tagName('sg-app > toh-heroes > div')); + let div = element(by.tagName('sg-app > toh-heroes > div')); expect(div.getText()).toBe('This is heroes component'); }); it('04-14', function () { browser.get('#/04-14'); - var h2 = element(by.tagName('sg-app > toh-heroes > div > h2')); + let h2 = element(by.tagName('sg-app > toh-heroes > div > h2')); expect(h2.getText()).toBe('My Heroes'); }); it('05-02', function () { browser.get('#/05-02'); - var button = element(by.tagName('sg-app > toh-hero-button > button')); + let button = element(by.tagName('sg-app > toh-hero-button > button')); expect(button.getText()).toBe('Hero button'); }); it('05-03', function () { browser.get('#/05-03'); - var button = element(by.tagName('sg-app > toh-hero-button > button')); + let button = element(by.tagName('sg-app > toh-hero-button > button')); expect(button.getText()).toBe('Hero button'); }); it('05-04', function () { browser.get('#/05-04'); - var h2 = element(by.tagName('sg-app > toh-heroes > div > h2')); + let h2 = element(by.tagName('sg-app > toh-heroes > div > h2')); expect(h2.getText()).toBe('My Heroes'); }); it('05-12', function () { browser.get('#/05-12'); - var button = element(by.tagName('sg-app > toh-hero-button > button')); + let button = element(by.tagName('sg-app > toh-hero-button > button')); expect(button.getText()).toBe('OK'); }); it('05-13', function () { browser.get('#/05-13'); - var button = element(by.tagName('sg-app > toh-hero-button > button')); + let button = element(by.tagName('sg-app > toh-hero-button > button')); expect(button.getText()).toBe('OK'); }); it('05-14', function () { browser.get('#/05-14'); - var toast = element(by.tagName('sg-app > toh-toast')); + let toast = element(by.tagName('sg-app > toh-toast')); expect(toast.getText()).toBe('...'); }); it('05-15', function () { browser.get('#/05-15'); - var heroList = element(by.tagName('sg-app > toh-hero-list')); + let heroList = element(by.tagName('sg-app > toh-hero-list')); expect(heroList.getText()).toBe('...'); }); it('05-16', function () { browser.get('#/05-16'); - var hero = element(by.tagName('sg-app > toh-hero')); + let hero = element(by.tagName('sg-app > toh-hero')); expect(hero.getText()).toBe('...'); }); it('05-17', function () { browser.get('#/05-17'); - var section = element(by.tagName('sg-app > toh-hero-list > section')); + let section = element(by.tagName('sg-app > toh-hero-list > section')); expect(section.getText()).toContain('Our list of heroes'); expect(section.getText()).toContain('Total powers'); expect(section.getText()).toContain('Average power'); @@ -163,21 +164,21 @@ describe('Style Guide', function () { it('06-01', function () { browser.get('#/06-01'); - var div = element(by.tagName('sg-app > div[tohhighlight]')); + let div = element(by.tagName('sg-app > div[tohhighlight]')); expect(div.getText()).toBe('Bombasta'); }); it('06-03', function () { browser.get('#/06-03'); - var input = element(by.tagName('input[tohvalidator]')); + let input = element(by.tagName('input[tohvalidator]')); expect(input.isPresent()).toBe(true); }); it('07-01', function () { browser.get('#/07-01'); - var lis = element.all(by.tagName('sg-app > ul > li')); + let lis = element.all(by.tagName('sg-app > ul > li')); expect(lis.get(0).getText()).toBe('Windstorm'); expect(lis.get(1).getText()).toBe('Bombasto'); expect(lis.get(2).getText()).toBe('Magneta'); @@ -187,21 +188,21 @@ describe('Style Guide', function () { it('07-03', function () { browser.get('#/07-03'); - var pre = element(by.tagName('toh-heroes > pre')); + let pre = element(by.tagName('toh-heroes > pre')); expect(pre.getText()).toContain('[]'); }); it('07-04', function () { browser.get('#/07-04'); - var pre = element(by.tagName('toh-app > pre')); + let pre = element(by.tagName('toh-app > pre')); expect(pre.getText()).toContain('[]'); }); it('09-01', function () { browser.get('#/09-01'); - var button = element(by.tagName('sg-app > toh-hero-button > button')); + let button = element(by.tagName('sg-app > toh-hero-button > button')); expect(button.getText()).toBe('OK'); }); }); diff --git a/public/docs/_examples/styleguide/e2e-spec.js b/public/docs/_examples/styleguide/e2e-spec.js deleted file mode 100644 index 14edeb17ef..0000000000 --- a/public/docs/_examples/styleguide/e2e-spec.js +++ /dev/null @@ -1,27 +0,0 @@ -/*global browser, element, by */ -describe('Getting Started E2E Tests', function() { - - // #docregion shared - var expectedMsg = 'My First Angular 2 App'; - - // tests shared across languages - function sharedTests(basePath) { - beforeEach(function () { - browser.get(basePath + 'index.html'); - }); - - it('should display: '+ expectedMsg, function() { - expect(element(by.id('output')).getText()).toEqual(expectedMsg); - }); - } - // #enddocregion - - describe('Getting Started in JavaScript', function() { - sharedTests('gettingstarted/js/'); - }); - - describe('Getting Started in TypeScript', function() { - sharedTests('gettingstarted/ts/'); - }); - -}); diff --git a/public/docs/_examples/styleguide/e2e-spec.ts b/public/docs/_examples/styleguide/e2e-spec.ts new file mode 100644 index 0000000000..b936b9fd23 --- /dev/null +++ b/public/docs/_examples/styleguide/e2e-spec.ts @@ -0,0 +1,28 @@ +/// +/*global browser, element, by */ +describe('Getting Started E2E Tests', function() { + + // #docregion shared + let expectedMsg = 'My First Angular 2 App'; + + // tests shared across languages + function sharedTests(basePath) { + beforeEach(function () { + browser.get(basePath + 'index.html'); + }); + + it('should display: '+ expectedMsg, function() { + expect(element(by.id('output')).getText()).toEqual(expectedMsg); + }); + } + // #enddocregion + + describe('Getting Started in JavaScript', function() { + sharedTests('gettingstarted/js/'); + }); + + describe('Getting Started in TypeScript', function() { + sharedTests('gettingstarted/ts/'); + }); + +}); diff --git a/public/docs/_examples/template-syntax/e2e-spec.js b/public/docs/_examples/template-syntax/e2e-spec.ts similarity index 74% rename from public/docs/_examples/template-syntax/e2e-spec.js rename to public/docs/_examples/template-syntax/e2e-spec.ts index 8aa140eb5c..48f69ba051 100644 --- a/public/docs/_examples/template-syntax/e2e-spec.js +++ b/public/docs/_examples/template-syntax/e2e-spec.ts @@ -1,3 +1,4 @@ +/// // Not yet complete describe('Template Syntax', function () { @@ -6,24 +7,24 @@ describe('Template Syntax', function () { }); it('should be able to use interpolation with a hero', function () { - var heroInterEle = element.all(by.css('h2+p')).get(0); + let heroInterEle = element.all(by.css('h2+p')).get(0); expect(heroInterEle.getText()).toEqual('My current hero is Hercules'); }); it('should be able to use interpolation with a calculation', function () { - var theSumEles = element.all(by.cssContainingText('h3~p','The sum of')); + let theSumEles = element.all(by.cssContainingText('h3~p','The sum of')); expect(theSumEles.count()).toBe(2); expect(theSumEles.get(0).getText()).toEqual('The sum of 1 + 1 is 2'); expect(theSumEles.get(1).getText()).toEqual('The sum of 1 + 1 is not 4'); }); it('should be able to use class binding syntax', function () { - var specialEle = element(by.cssContainingText('div','Special')); + let specialEle = element(by.cssContainingText('div','Special')); expect(specialEle.getAttribute('class')).toMatch('special'); }); it('should be able to use style binding syntax', function () { - var specialButtonEle = element(by.cssContainingText('div.special~button', 'button')); + let specialButtonEle = element(by.cssContainingText('div.special~button', 'button')); expect(specialButtonEle.getAttribute('style')).toMatch('color: red'); }); }); diff --git a/public/docs/_examples/toh-5/e2e-spec.js b/public/docs/_examples/toh-5/e2e-spec.ts similarity index 87% rename from public/docs/_examples/toh-5/e2e-spec.js rename to public/docs/_examples/toh-5/e2e-spec.ts index f35fcd1287..f3955097b4 100644 --- a/public/docs/_examples/toh-5/e2e-spec.js +++ b/public/docs/_examples/toh-5/e2e-spec.ts @@ -1,3 +1,4 @@ +/// describe('Tutorial', function () { beforeAll(function () { @@ -23,19 +24,19 @@ describe('Tutorial', function () { } it('should be able to see the start screen', function () { - var page = getPageStruct(); + let page = getPageStruct(); expect(page.hrefs.count()).toEqual(2, 'should be two dashboard choices'); expect(page.myDashboardHref.getText()).toEqual("Dashboard"); expect(page.myHeroesHref.getText()).toEqual("Heroes"); }); it('should be able to see dashboard choices', function () { - var page = getPageStruct(); + let page = getPageStruct(); expect(page.topHeroes.count()).toBe(4, "should be 4 dashboard hero choices"); }); it('should be able to toggle the views', function () { - var page = getPageStruct(); + let page = getPageStruct(); expect(page.myDashboardParent.element(by.css('h3')).getText()).toEqual('Top Heroes'); page.myHeroesHref.click().then(function() { @@ -49,11 +50,11 @@ describe('Tutorial', function () { }); it('should be able to edit details from "Dashboard" view', function () { - var page = getPageStruct(); + let page = getPageStruct(); expect(page.myDashboardParent.isPresent()).toBe(true, 'dashboard element should be available'); - var heroEle = page.topHeroes.get(3); - var heroDescrEle = heroEle.element(by.css('h4')); - var heroDescr; + let heroEle = page.topHeroes.get(3); + let heroDescrEle = heroEle.element(by.css('h4')); + let heroDescr; return heroDescrEle.getText().then(function(text) { heroDescr = text; return heroEle.click(); @@ -66,10 +67,10 @@ describe('Tutorial', function () { }); it('should be able to edit details from "Heroes" view', function () { - var page = getPageStruct(); + let page = getPageStruct(); expect(page.myDashboardParent.isPresent()).toBe(true, 'dashboard element should be present'); - var viewDetailsButtonEle = page.myHeroesParent.element(by.cssContainingText('button', 'View Details')); - var heroEle, heroDescr; + let viewDetailsButtonEle = page.myHeroesParent.element(by.cssContainingText('button', 'View Details')); + let heroEle, heroDescr; page.myHeroesHref.click().then(function() { expect(page.myDashboardParent.isPresent()).toBe(false, 'dashboard element should NOT be present'); expect(page.myHeroesParent.isPresent()).toBe(true, 'myHeroes element should be present'); @@ -96,11 +97,11 @@ describe('Tutorial', function () { expect(page.myDashboardParent.isPresent()).toBe(false, 'dashboard element should NOT be present'); expect(page.myHeroesParent.isPresent()).toBe(false, 'myHeroes element should NOT be present'); expect(page.heroDetail.isDisplayed()).toBe(true, 'should be able to see hero-details'); - var inputEle = page.heroDetail.element(by.css('input')); + let inputEle = page.heroDetail.element(by.css('input')); expect(inputEle.isDisplayed()).toBe(true, 'should be able to see the input box'); - var backButtonEle = page.heroDetail.element(by.css('button')); + let backButtonEle = page.heroDetail.element(by.css('button')); expect(backButtonEle.isDisplayed()).toBe(true, 'should be able to see the back button'); - var detailTextEle = page.heroDetail.element(by.css('div h2')); + let detailTextEle = page.heroDetail.element(by.css('div h2')); expect(detailTextEle.getText()).toContain(origValue); return sendKeys(inputEle, textToAdd).then(function () { expect(detailTextEle.getText()).toContain(origValue + textToAdd); diff --git a/public/docs/_examples/toh-6/e2e-spec.js b/public/docs/_examples/toh-6/e2e-spec.ts similarity index 77% rename from public/docs/_examples/toh-6/e2e-spec.js rename to public/docs/_examples/toh-6/e2e-spec.ts index d5823b9add..bec10800b4 100644 --- a/public/docs/_examples/toh-6/e2e-spec.js +++ b/public/docs/_examples/toh-6/e2e-spec.ts @@ -1,3 +1,4 @@ +/// describe('TOH Http Chapter', function () { beforeEach(function () { @@ -5,7 +6,7 @@ describe('TOH Http Chapter', function () { }); function getPageStruct() { - hrefEles = element.all(by.css('my-app a')); + let hrefEles = element.all(by.css('my-app a')); return { hrefs: hrefEles, @@ -22,12 +23,12 @@ describe('TOH Http Chapter', function () { addButton: element.all(by.buttonText('Add New Hero')).get(0), heroDetail: element(by.css('my-app my-hero-detail')) - } + }; } it('should be able to add a hero from the "Heroes" view', function(){ - var page = getPageStruct(); - var heroCount; + let page = getPageStruct(); + let heroCount: webdriver.promise.Promise; page.myHeroesHref.click().then(function() { browser.waitForAngular(); @@ -43,14 +44,14 @@ describe('TOH Http Chapter', function () { heroCount = page.allHeroes.count(); expect(heroCount).toBe(11, 'should show 11'); - var newHero = element(by.xpath('//span[@class="hero-element" and contains(text(),"The New Hero")]')); + let newHero = element(by.xpath('//span[@class="hero-element" and contains(text(),"The New Hero")]')); expect(newHero).toBeDefined(); }); }); it('should be able to delete hero from "Heroes" view', function(){ - var page = getPageStruct(); - var heroCount; + let page = getPageStruct(); + let heroCount: webdriver.promise.Promise; page.myHeroesHref.click().then(function() { browser.waitForAngular(); @@ -66,11 +67,11 @@ describe('TOH Http Chapter', function () { }); it('should be able to save details from "Dashboard" view', function () { - var page = getPageStruct(); + let page = getPageStruct(); expect(page.myDashboardParent.isPresent()).toBe(true, 'dashboard element should be available'); - var heroEle = page.topHeroes.get(2); - var heroDescrEle = heroEle.element(by.css('h4')); - var heroDescr; + let heroEle = page.topHeroes.get(2); + let heroDescrEle = heroEle.element(by.css('h4')); + let heroDescr: string; return heroDescrEle.getText().then(function(text) { heroDescr = text; @@ -88,10 +89,10 @@ describe('TOH Http Chapter', function () { }); it('should be able to save details from "Heroes" view', function () { - var page = getPageStruct(); + let page = getPageStruct(); - var viewDetailsButtonEle = page.myHeroesParent.element(by.cssContainingText('button', 'View Details')); - var heroEle, heroDescr; + let viewDetailsButtonEle = page.myHeroesParent.element(by.cssContainingText('button', 'View Details')); + let heroEle: protractor.ElementFinder, heroDescr: string; page.myHeroesHref.click().then(function() { expect(page.myDashboardParent.isPresent()).toBe(false, 'dashboard element should NOT be present'); @@ -101,7 +102,7 @@ describe('TOH Http Chapter', function () { return heroEle.getText(); }).then(function(text) { // remove leading 'id' from the element - heroDescr = text.substr(text.indexOf(' ')+1); + heroDescr = text.substr(text.indexOf(' ') + 1); return heroEle.click(); }).then(function() { expect(viewDetailsButtonEle.isDisplayed()).toBe(true, 'viewDetails button should now be visible'); @@ -117,13 +118,13 @@ describe('TOH Http Chapter', function () { }); }); - function save(page, origValue, textToAdd) { - var inputEle = page.heroDetail.element(by.css('input')); + function save(page: any, origValue: string, textToAdd: string) { + let inputEle = page.heroDetail.element(by.css('input')); expect(inputEle.isDisplayed()).toBe(true, 'should be able to see the input box'); - var saveButtonEle = page.heroDetail.element(by.buttonText('Save')); - var backButtonEle = page.heroDetail.element(by.buttonText('Back')); + let saveButtonEle = page.heroDetail.element(by.buttonText('Save')); + let backButtonEle = page.heroDetail.element(by.buttonText('Back')); expect(backButtonEle.isDisplayed()).toBe(true, 'should be able to see the back button'); - var detailTextEle = page.heroDetail.element(by.css('div h2')); + let detailTextEle = page.heroDetail.element(by.css('div h2')); expect(detailTextEle.getText()).toContain(origValue); return sendKeys(inputEle, textToAdd).then(function () { expect(detailTextEle.getText()).toContain(origValue + textToAdd); @@ -132,24 +133,24 @@ describe('TOH Http Chapter', function () { } it('should be able to see the start screen', function () { - var page = getPageStruct(); + let page = getPageStruct(); expect(page.hrefs.count()).toEqual(2, 'should be two dashboard choices'); - expect(page.myDashboardHref.getText()).toEqual("Dashboard"); - expect(page.myHeroesHref.getText()).toEqual("Heroes"); + expect(page.myDashboardHref.getText()).toEqual('Dashboard'); + expect(page.myHeroesHref.getText()).toEqual('Heroes'); }); it('should be able to see dashboard choices', function () { - var page = getPageStruct(); - expect(page.topHeroes.count()).toBe(4, "should be 4 dashboard hero choices"); + let page = getPageStruct(); + expect(page.topHeroes.count()).toBe(4, 'should be 4 dashboard hero choices'); }); it('should be able to toggle the views', function () { - var page = getPageStruct(); + let page = getPageStruct(); expect(page.myDashboardParent.element(by.css('h3')).getText()).toEqual('Top Heroes'); page.myHeroesHref.click().then(function() { expect(page.myDashboardParent.isPresent()).toBe(false, 'should no longer see dashboard element'); - expect(page.allHeroes.count()).toBeGreaterThan(4, "should be more than 4 heroes shown"); + expect(page.allHeroes.count()).toBeGreaterThan(4, 'should be more than 4 heroes shown'); return page.myDashboardHref.click(); }).then(function() { expect(page.myDashboardParent.isPresent()).toBe(true, 'should once again see the dashboard element'); @@ -158,11 +159,11 @@ describe('TOH Http Chapter', function () { }); it('should be able to edit details from "Dashboard" view', function () { - var page = getPageStruct(); + let page = getPageStruct(); expect(page.myDashboardParent.isPresent()).toBe(true, 'dashboard element should be available'); - var heroEle = page.topHeroes.get(3); - var heroDescrEle = heroEle.element(by.css('h4')); - var heroDescr; + let heroEle = page.topHeroes.get(3); + let heroDescrEle = heroEle.element(by.css('h4')); + let heroDescr: string; return heroDescrEle.getText().then(function(text) { heroDescr = text; return heroEle.click(); @@ -175,10 +176,10 @@ describe('TOH Http Chapter', function () { }); it('should be able to edit details from "Heroes" view', function () { - var page = getPageStruct(); + let page = getPageStruct(); expect(page.myDashboardParent.isPresent()).toBe(true, 'dashboard element should be present'); - var viewDetailsButtonEle = page.myHeroesParent.element(by.cssContainingText('button', 'View Details')); - var heroEle, heroDescr; + let viewDetailsButtonEle = page.myHeroesParent.element(by.cssContainingText('button', 'View Details')); + let heroEle: protractor.ElementFinder, heroDescr: string; page.myHeroesHref.click().then(function() { expect(page.myDashboardParent.isPresent()).toBe(false, 'dashboard element should NOT be present'); expect(page.myHeroesParent.isPresent()).toBe(true, 'myHeroes element should be present'); @@ -187,7 +188,7 @@ describe('TOH Http Chapter', function () { return heroEle.getText(); }).then(function(text) { // remove leading 'id' from the element - heroDescr = text.substr(text.indexOf(' ')+1); + heroDescr = text.substr(text.indexOf(' ') + 1); return heroEle.click(); }).then(function() { expect(viewDetailsButtonEle.isDisplayed()).toBe(true, 'viewDetails button should now be visible'); @@ -201,18 +202,18 @@ describe('TOH Http Chapter', function () { }); }); - function editDetails(page, origValue, textToAdd) { + function editDetails(page: any, origValue: string, textToAdd: string) { expect(page.myDashboardParent.isPresent()).toBe(false, 'dashboard element should NOT be present'); expect(page.myHeroesParent.isPresent()).toBe(false, 'myHeroes element should NOT be present'); expect(page.heroDetail.isDisplayed()).toBe(true, 'should be able to see hero-details'); - var inputEle = page.heroDetail.element(by.css('input')); + let inputEle = page.heroDetail.element(by.css('input')); expect(inputEle.isDisplayed()).toBe(true, 'should be able to see the input box'); - var buttons = page.heroDetail.all(by.css('button')); - var backButtonEle = buttons.get(0); - var saveButtonEle = buttons.get(1); + let buttons = page.heroDetail.all(by.css('button')); + let backButtonEle = buttons.get(0); + let saveButtonEle = buttons.get(1); expect(backButtonEle.isDisplayed()).toBe(true, 'should be able to see the back button'); expect(saveButtonEle.isDisplayed()).toBe(true, 'should be able to see the save button'); - var detailTextEle = page.heroDetail.element(by.css('div h2')); + let detailTextEle = page.heroDetail.element(by.css('div h2')); expect(detailTextEle.getText()).toContain(origValue); return sendKeys(inputEle, textToAdd).then(function () { expect(detailTextEle.getText()).toContain(origValue + textToAdd); diff --git a/public/docs/_examples/upgrade-adapter/e2e-spec.js b/public/docs/_examples/upgrade-adapter/e2e-spec.ts similarity index 99% rename from public/docs/_examples/upgrade-adapter/e2e-spec.js rename to public/docs/_examples/upgrade-adapter/e2e-spec.ts index 6e00bfafef..eb4706137c 100644 --- a/public/docs/_examples/upgrade-adapter/e2e-spec.js +++ b/public/docs/_examples/upgrade-adapter/e2e-spec.ts @@ -1,3 +1,4 @@ +/// describe('Upgrade Tests', function () { // Protractor doesn't support the UpgradeAdapter's asynchronous diff --git a/public/docs/_examples/upgrade-phonecat-1-typescript/e2e-spec.js b/public/docs/_examples/upgrade-phonecat-1-typescript/e2e-spec.ts similarity index 79% rename from public/docs/_examples/upgrade-phonecat-1-typescript/e2e-spec.js rename to public/docs/_examples/upgrade-phonecat-1-typescript/e2e-spec.ts index d001711436..ced4fbfbd5 100644 --- a/public/docs/_examples/upgrade-phonecat-1-typescript/e2e-spec.js +++ b/public/docs/_examples/upgrade-phonecat-1-typescript/e2e-spec.ts @@ -1,3 +1,4 @@ +/// 'use strict'; // Angular E2E Testing Guide: @@ -22,8 +23,8 @@ describe('PhoneCat Application', function() { }); it('should filter the phone list as a user types into the search box', function() { - var phoneList = element.all(by.repeater('phone in $ctrl.phones')); - var query = element(by.model('$ctrl.query')); + let phoneList = element.all(by.repeater('phone in $ctrl.phones')); + let query = element(by.model('$ctrl.query')); expect(phoneList.count()).toBe(20); @@ -36,10 +37,10 @@ describe('PhoneCat Application', function() { }); it('should be possible to control phone order via the drop-down menu', function() { - var queryField = element(by.model('$ctrl.query')); - var orderSelect = element(by.model('$ctrl.orderProp')); - var nameOption = orderSelect.element(by.css('option[value="name"]')); - var phoneNameColumn = element.all(by.repeater('phone in $ctrl.phones').column('phone.name')); + let queryField = element(by.model('$ctrl.query')); + let orderSelect = element(by.model('$ctrl.orderProp')); + let nameOption = orderSelect.element(by.css('option[value="name"]')); + let phoneNameColumn = element.all(by.repeater('phone in $ctrl.phones').column('phone.name')); function getNames() { return phoneNameColumn.map(function(elem) { @@ -63,7 +64,7 @@ describe('PhoneCat Application', function() { }); it('should render phone specific links', function() { - var query = element(by.model('$ctrl.query')); + let query = element(by.model('$ctrl.query')); query.sendKeys('nexus'); element.all(by.css('.phones li a')).first().click(); @@ -83,14 +84,14 @@ describe('PhoneCat Application', function() { }); it('should display the first phone image as the main phone image', function() { - var mainImage = element(by.css('img.phone.selected')); + let mainImage = element(by.css('img.phone.selected')); expect(mainImage.getAttribute('src')).toMatch(/img\/phones\/nexus-s.0.jpg/); }); it('should swap the main image when clicking on a thumbnail image', function() { - var mainImage = element(by.css('img.phone.selected')); - var thumbnails = element.all(by.css('.phone-thumbs img')); + let mainImage = element(by.css('img.phone.selected')); + let thumbnails = element.all(by.css('.phone-thumbs img')); thumbnails.get(2).click(); expect(mainImage.getAttribute('src')).toMatch(/img\/phones\/nexus-s.2.jpg/); diff --git a/public/docs/_examples/upgrade-phonecat-2-hybrid/e2e-spec.js b/public/docs/_examples/upgrade-phonecat-2-hybrid/e2e-spec.ts similarity index 80% rename from public/docs/_examples/upgrade-phonecat-2-hybrid/e2e-spec.js rename to public/docs/_examples/upgrade-phonecat-2-hybrid/e2e-spec.ts index 627c684d69..09f9bc6b7e 100644 --- a/public/docs/_examples/upgrade-phonecat-2-hybrid/e2e-spec.js +++ b/public/docs/_examples/upgrade-phonecat-2-hybrid/e2e-spec.ts @@ -1,3 +1,4 @@ +/// 'use strict'; // Angular E2E Testing Guide: @@ -21,8 +22,8 @@ describe('PhoneCat Application', function() { }); it('should filter the phone list as a user types into the search box', function() { - var phoneList = element.all(by.css('.phones li')); - var query = element(by.css('input')); + let phoneList = element.all(by.css('.phones li')); + let query = element(by.css('input')); expect(phoneList.count()).toBe(20); @@ -35,10 +36,10 @@ describe('PhoneCat Application', function() { }); it('should be possible to control phone order via the drop-down menu', function() { - var queryField = element(by.css('input')); - var orderSelect = element(by.css('select')); - var nameOption = orderSelect.element(by.css('option[value="name"]')); - var phoneNameColumn = element.all(by.css('.phones .name')); + let queryField = element(by.css('input')); + let orderSelect = element(by.css('select')); + let nameOption = orderSelect.element(by.css('option[value="name"]')); + let phoneNameColumn = element.all(by.css('.phones .name')); function getNames() { return phoneNameColumn.map(function(elem) { @@ -62,7 +63,7 @@ describe('PhoneCat Application', function() { }); it('should render phone specific links', function() { - var query = element(by.css('input')); + let query = element(by.css('input')); sendKeys(query, 'nexus'); element.all(by.css('.phones li a')).first().click(); @@ -83,14 +84,14 @@ describe('PhoneCat Application', function() { }); it('should display the first phone image as the main phone image', function() { - var mainImage = element(by.css('img.phone.selected')); + let mainImage = element(by.css('img.phone.selected')); expect(mainImage.getAttribute('src')).toMatch(/img\/phones\/nexus-s.0.jpg/); }); it('should swap the main image when clicking on a thumbnail image', function() { - var mainImage = element(by.css('img.phone.selected')); - var thumbnails = element.all(by.css('.phone-thumbs img')); + let mainImage = element(by.css('img.phone.selected')); + let thumbnails = element.all(by.css('.phone-thumbs img')); thumbnails.get(2).click(); expect(mainImage.getAttribute('src')).toMatch(/img\/phones\/nexus-s.2.jpg/); diff --git a/public/docs/_examples/upgrade-phonecat-3-final/e2e-spec.js b/public/docs/_examples/upgrade-phonecat-3-final/e2e-spec.ts similarity index 79% rename from public/docs/_examples/upgrade-phonecat-3-final/e2e-spec.js rename to public/docs/_examples/upgrade-phonecat-3-final/e2e-spec.ts index 6b1f78bb9a..3622210403 100644 --- a/public/docs/_examples/upgrade-phonecat-3-final/e2e-spec.js +++ b/public/docs/_examples/upgrade-phonecat-3-final/e2e-spec.ts @@ -1,3 +1,4 @@ +/// 'use strict'; // Angular E2E Testing Guide: @@ -22,8 +23,8 @@ describe('PhoneCat Application', function() { }); it('should filter the phone list as a user types into the search box', function() { - var phoneList = element.all(by.css('.phones li')); - var query = element(by.css('input')); + let phoneList = element.all(by.css('.phones li')); + let query = element(by.css('input')); expect(phoneList.count()).toBe(20); @@ -36,10 +37,10 @@ describe('PhoneCat Application', function() { }); it('should be possible to control phone order via the drop-down menu', function() { - var queryField = element(by.css('input')); - var orderSelect = element(by.css('select')); - var nameOption = orderSelect.element(by.css('option[value="name"]')); - var phoneNameColumn = element.all(by.css('.phones .name')); + let queryField = element(by.css('input')); + let orderSelect = element(by.css('select')); + let nameOption = orderSelect.element(by.css('option[value="name"]')); + let phoneNameColumn = element.all(by.css('.phones .name')); function getNames() { return phoneNameColumn.map(function(elem) { @@ -64,10 +65,10 @@ describe('PhoneCat Application', function() { // #docregion links it('should render phone specific links', function() { - var query = element(by.css('input')); + let query = element(by.css('input')); // https://github.com/angular/protractor/issues/2019 - var str = 'nexus'; - for (var i = 0; i < str.length; i++) { + let str = 'nexus'; + for (let i = 0; i < str.length; i++) { query.sendKeys(str.charAt(i)); } element.all(by.css('.phones li a')).first().click(); @@ -90,14 +91,14 @@ describe('PhoneCat Application', function() { }); it('should display the first phone image as the main phone image', function() { - var mainImage = element(by.css('img.phone.selected')); + let mainImage = element(by.css('img.phone.selected')); expect(mainImage.getAttribute('src')).toMatch(/img\/phones\/nexus-s.0.jpg/); }); it('should swap the main image when clicking on a thumbnail image', function() { - var mainImage = element(by.css('img.phone.selected')); - var thumbnails = element.all(by.css('.phone-thumbs img')); + let mainImage = element(by.css('img.phone.selected')); + let thumbnails = element.all(by.css('.phone-thumbs img')); thumbnails.get(2).click(); expect(mainImage.getAttribute('src')).toMatch(/img\/phones\/nexus-s.2.jpg/); diff --git a/public/docs/_examples/user-input/e2e-spec.js b/public/docs/_examples/user-input/e2e-spec.ts similarity index 65% rename from public/docs/_examples/user-input/e2e-spec.js rename to public/docs/_examples/user-input/e2e-spec.ts index c0d4fa0c1f..7ef2dcec24 100644 --- a/public/docs/_examples/user-input/e2e-spec.js +++ b/public/docs/_examples/user-input/e2e-spec.ts @@ -1,3 +1,4 @@ +/// describe('User Input Tests', function () { beforeAll(function () { @@ -5,8 +6,8 @@ describe('User Input Tests', function () { }); it('should support the click event', function () { - var mainEle = element(by.css('click-me')); - var buttonEle =element(by.css('click-me button')); + let mainEle = element(by.css('click-me')); + let buttonEle =element(by.css('click-me button')); expect(mainEle.getText()).not.toContain('You are my hero!'); buttonEle.click().then(function() { expect(mainEle.getText()).toContain('You are my hero!'); @@ -14,8 +15,8 @@ describe('User Input Tests', function () { }); it('should support the click event with an event payload', function () { - var mainEle = element(by.css('click-me2')); - var buttonEle =element(by.css('click-me2 button')); + let mainEle = element(by.css('click-me2')); + let buttonEle =element(by.css('click-me2 button')); expect(mainEle.getText()).not.toContain('Event target is '); buttonEle.click().then(function() { expect(mainEle.getText()).toContain('Event target is BUTTON'); @@ -23,19 +24,19 @@ describe('User Input Tests', function () { }); it('should support the keyup event ', function () { - var mainEle = element(by.css('key-up1')); - var inputEle = mainEle.element(by.css('input')); - var outputTextEle = mainEle.element(by.css('p')); + let mainEle = element(by.css('key-up1')); + let inputEle = mainEle.element(by.css('input')); + let outputTextEle = mainEle.element(by.css('p')); expect(outputTextEle.getText()).toEqual(''); return sendKeys(inputEle,'abc').then(function() { expect(outputTextEle.getText()).toEqual('a | ab | abc |'); }); }); - it('should support user input from a local template var (loopback)', function () { - var mainEle = element(by.css('loop-back')); - var inputEle = mainEle.element(by.css('input')); - var outputTextEle = mainEle.element(by.css('p')); + it('should support user input from a local template let (loopback)', function () { + let mainEle = element(by.css('loop-back')); + let inputEle = mainEle.element(by.css('input')); + let outputTextEle = mainEle.element(by.css('p')); expect(outputTextEle.getText()).toEqual(''); return sendKeys(inputEle,'abc').then(function() { expect(outputTextEle.getText()).toEqual('abc'); @@ -43,9 +44,9 @@ describe('User Input Tests', function () { }); it('should be able to combine click event with a local template var', function () { - var mainEle = element(by.css('key-up2')); - var inputEle = mainEle.element(by.css('input')); - var outputTextEle = mainEle.element(by.css('p')); + let mainEle = element(by.css('key-up2')); + let inputEle = mainEle.element(by.css('input')); + let outputTextEle = mainEle.element(by.css('p')); expect(outputTextEle.getText()).toEqual(''); return sendKeys(inputEle,'abc').then(function() { expect(outputTextEle.getText()).toEqual('a | ab | abc |'); @@ -53,9 +54,9 @@ describe('User Input Tests', function () { }); it('should be able to filter key events', function () { - var mainEle = element(by.css('key-up3')); - var inputEle = mainEle.element(by.css('input')); - var outputTextEle = mainEle.element(by.css('p')); + let mainEle = element(by.css('key-up3')); + let inputEle = mainEle.element(by.css('input')); + let outputTextEle = mainEle.element(by.css('p')); expect(outputTextEle.getText()).toEqual(''); return sendKeys(inputEle,'abc').then(function() { expect(outputTextEle.getText()).toEqual('', 'should be blank - have not sent enter yet'); @@ -66,10 +67,10 @@ describe('User Input Tests', function () { }); it('should be able to filter blur events', function () { - var prevInputEle = element(by.css('key-up3 input')); - var mainEle = element(by.css('key-up4')); - var inputEle = mainEle.element(by.css('input')); - var outputTextEle = mainEle.element(by.css('p')); + let prevInputEle = element(by.css('key-up3 input')); + let mainEle = element(by.css('key-up4')); + let inputEle = mainEle.element(by.css('input')); + let outputTextEle = mainEle.element(by.css('p')); expect(outputTextEle.getText()).toEqual(''); return sendKeys(inputEle,'abc').then(function() { expect(outputTextEle.getText()).toEqual('', 'should be blank - have not sent enter yet'); @@ -81,11 +82,11 @@ describe('User Input Tests', function () { }); it('should be able to compose little tour of heroes', function () { - var mainEle = element(by.css('little-tour')); - var inputEle = mainEle.element(by.css('input')); - var addButtonEle = mainEle.element(by.css('button')); - var heroEles = mainEle.all(by.css('li')); - var numHeroes; + let mainEle = element(by.css('little-tour')); + let inputEle = mainEle.element(by.css('input')); + let addButtonEle = mainEle.element(by.css('button')); + let heroEles = mainEle.all(by.css('li')); + let numHeroes; expect(heroEles.count()).toBeGreaterThan(0); heroEles.count().then(function(count) { numHeroes = count; From a979c71089112362636eff372add8e432f684fce Mon Sep 17 00:00:00 2001 From: Dan Caddigan Date: Sun, 29 May 2016 20:29:28 -0400 Subject: [PATCH 04/13] chore(typo): harp.json typo closes #1552 --- harp.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/harp.json b/harp.json index 5c2478685e..e79fb92241 100644 --- a/harp.json +++ b/harp.json @@ -322,7 +322,7 @@ "name": "Elad Bezalel", "picture": "/resources/images/bios/eladbezalel.jpg", "website": "https://github.com/EladBezalel", - "bio": "Elad is a fullstack developer with a very storng love for design. Since 8 years old, he's been designing in Photoshop and later on fell in love with programing. This strong bond between design and computer programming gave birth to a new kind of love. And he is currently doing the combination of both, as a core member of the ngMaterial project.", + "bio": "Elad is a fullstack developer with a very strong love for design. Since 8 years old, he's been designing in Photoshop and later on fell in love with programing. This strong bond between design and computer programming gave birth to a new kind of love. And he is currently doing the combination of both, as a core member of the ngMaterial project.", "type": "Community" }, From 3d868da4b79e818d79cc658b22e06cf5be0bad4d Mon Sep 17 00:00:00 2001 From: Christopher Thorne Date: Sun, 29 May 2016 22:09:06 +0100 Subject: [PATCH 05/13] docs(toh-pt5): change getHero to match toh-pt6 getHero closes #1551 --- public/docs/_examples/toh-5/ts/app/hero.service.ts | 5 ++--- public/docs/ts/latest/tutorial/toh-pt5.jade | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/public/docs/_examples/toh-5/ts/app/hero.service.ts b/public/docs/_examples/toh-5/ts/app/hero.service.ts index fd6d5bb128..efc348509b 100644 --- a/public/docs/_examples/toh-5/ts/app/hero.service.ts +++ b/public/docs/_examples/toh-5/ts/app/hero.service.ts @@ -19,9 +19,8 @@ export class HeroService { //#docregion get-hero getHero(id: number) { - return Promise.resolve(HEROES).then( - heroes => heroes.filter(hero => hero.id === id)[0] - ); + return this.getHeroes() + .then(heroes => heroes.filter(hero => hero.id === id)[0]); } //#enddocregion get-hero } diff --git a/public/docs/ts/latest/tutorial/toh-pt5.jade b/public/docs/ts/latest/tutorial/toh-pt5.jade index 9d7f43629e..113c2f94db 100644 --- a/public/docs/ts/latest/tutorial/toh-pt5.jade +++ b/public/docs/ts/latest/tutorial/toh-pt5.jade @@ -427,7 +427,7 @@ code-example(format=''). The problem with this bit of code is that `HeroService` doesn't have a `getHero` method! We better fix that quickly before someone notices that we broke the app. - Open `HeroService` and add the `getHero` method. It's trivial given that we're still faking data access: + Open `HeroService` and add a `getHero` method that filters the heroes list from `getHeroes` by `id`: +makeExample('toh-5/ts/app/hero.service.ts', 'get-hero', 'app/hero.service.ts (getHero)')(format=".") :marked Return to the `HeroDetailComponent` to clean up loose ends. From 2d27097d55b256a47d677f0fea1da8e47472d653 Mon Sep 17 00:00:00 2001 From: Christopher Thorne Date: Sun, 29 May 2016 20:52:25 +0100 Subject: [PATCH 06/13] docs(toh-pt6): correct DetailHeroComponent to HeroDetailComponent closes #1550 --- public/docs/ts/latest/tutorial/toh-pt6.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/docs/ts/latest/tutorial/toh-pt6.jade b/public/docs/ts/latest/tutorial/toh-pt6.jade index a35ba9c98b..42a6e44db4 100644 --- a/public/docs/ts/latest/tutorial/toh-pt6.jade +++ b/public/docs/ts/latest/tutorial/toh-pt6.jade @@ -218,7 +218,7 @@ code-example(format="." language="bash"). In the following section we will update our components to use our new methods to add, edit and delete heroes. ### Add/Edit in the *HeroDetailComponent* - We already have `HeroDetailComponent` for viewing details about a specific hero. Add and Edit are natural extensions of the detail view, so we are able to reuse `DetailHeroComponent` with a few tweaks. The original component was created to render existing data, but to add new data we have to initialize the `hero` property to an empty `Hero` object. + We already have `HeroDetailComponent` for viewing details about a specific hero. Add and Edit are natural extensions of the detail view, so we are able to reuse `HeroDetailComponent` with a few tweaks. The original component was created to render existing data, but to add new data we have to initialize the `hero` property to an empty `Hero` object. +makeExample('toh-6/ts/app/hero-detail.component.ts', 'ngOnInit', 'app/hero-detail.component.ts (ngOnInit)')(format=".") From 613d53e1522eb0d5b096c71fecd524f74e90e030 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maksims=20Mui=C5=BEininkas?= Date: Fri, 27 May 2016 13:09:56 +0300 Subject: [PATCH 07/13] docs(architecture): correct link to testing closes #1536 --- firebase.json | 4 ++++ public/docs/ts/latest/guide/architecture.jade | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/firebase.json b/firebase.json index 957cd5fc28..069b61f208 100644 --- a/firebase.json +++ b/firebase.json @@ -22,6 +22,10 @@ "source": "/docs/ts/latest/guide/setup.html", "destination": "/docs/ts/latest/index.html" }, + { + "source": "/docs/ts/latest/testing", + "destination": "/docs/ts/latest/guide/testing.html" + }, { "source": "/cheatsheet", "destination": "/docs/ts/latest/guide/cheatsheet.html" diff --git a/public/docs/ts/latest/guide/architecture.jade b/public/docs/ts/latest/guide/architecture.jade index 2dd8de74a4..11031aff02 100644 --- a/public/docs/ts/latest/guide/architecture.jade +++ b/public/docs/ts/latest/guide/architecture.jade @@ -538,5 +538,5 @@ code-example(language="javascript" linenumbers="."). :marked >displays a price of "42.33" as `$42.33`. - >**[Testing](../testing/index.html)** - Angular provides a testing library for "unit testing" our application parts as they + >**[Testing](testing.html)** - Angular provides a testing library for "unit testing" our application parts as they interact with the Angular framework. From b2262c2bc9357509de4de616cf1d64202213472c Mon Sep 17 00:00:00 2001 From: Ward Bell Date: Wed, 1 Jun 2016 00:12:51 -0700 Subject: [PATCH 08/13] chore: updated broken-link-checker package and tweaked logging. --- gulpfile.js | 9 ++++++--- package.json | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 1939310352..93a24c4883 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -691,7 +691,7 @@ function linkChecker(options) { var handlers = { robots: function(robots, customData){}, html: function(tree, robots, response, pageUrl, customData){ - //gutil.log('Scanning ' + pageUrl);docs/ts/latest/api/core/ + // gutil.log('Scanning ' + pageUrl); }, junk: function(result, customData){}, @@ -708,8 +708,8 @@ function linkChecker(options) { } var msg = '\n [' + result.html.location.line + ', ' + result.brokenReason + '] ' + result.url.resolved; fs.appendFileSync(outputFile, msg); - //gutil.log(msg); - //gutil.log(result); + // gutil.log(msg); + // gutil.log(result); }, page: function(error, pageUrl, customData){}, @@ -737,8 +737,11 @@ function linkChecker(options) { var startTime = new Date().getTime(); try { + gutil.log('link checker started'); siteChecker.enqueue(siteUrl, customData); } catch (err) { + gutil.log('link checker died'); + console.error('link checker died', err); deferred.reject(err); } return deferred.promise; diff --git a/package.json b/package.json index e1a34a4754..fd0083db03 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "devDependencies": { "archiver": "^0.16.0", "assert-plus": "^0.1.5", - "broken-link-checker": "0.7.0", + "broken-link-checker": "0.7.1", "browser-sync": "^2.9.3", "canonical-path": "0.0.2", "cross-spawn": "^2.1.0", From 2f115a342522c59c93286af71d72795a01b793d4 Mon Sep 17 00:00:00 2001 From: Ward Bell Date: Wed, 1 Jun 2016 00:51:10 -0700 Subject: [PATCH 09/13] chore: fix broken devguide links as of May 31 Did not fix broken Dart and API links --- public/contribute.jade | 2 +- .../{dynamic-forms.jade => dynamic-form.jade} | 0 public/docs/dart/latest/tutorial/_data.json | 5 +++ public/docs/dart/latest/tutorial/toh-pt6.jade | 1 + public/docs/js/latest/tutorial/_data.json | 5 +++ public/docs/js/latest/tutorial/toh-pt6.jade | 1 + public/docs/ts/latest/glossary.jade | 43 +++++++++---------- public/docs/ts/latest/guide/npm-packages.jade | 3 +- public/docs/ts/latest/tutorial/toh-pt5.jade | 2 +- 9 files changed, 36 insertions(+), 26 deletions(-) rename public/docs/dart/latest/cookbook/{dynamic-forms.jade => dynamic-form.jade} (100%) create mode 100644 public/docs/dart/latest/tutorial/toh-pt6.jade create mode 100644 public/docs/js/latest/tutorial/toh-pt6.jade diff --git a/public/contribute.jade b/public/contribute.jade index 3e439abfcb..451269dd40 100644 --- a/public/contribute.jade +++ b/public/contribute.jade @@ -23,7 +23,7 @@ p Our goal is to deliver a lean, lightweight set of Angular-based UI elements that implement the material design specification for use in Angular single-page applications (SPAs). - a(href="https://github.com/angular/material/blob/master/CONTRIBUTING.md" class="button" md-button) Contribute to Angular Material + a(href="https://github.com/angular/material/blob/master/.github/CONTRIBUTING.md" class="button" md-button) Contribute to Angular Material .l-sub-section h3 AngularFire diff --git a/public/docs/dart/latest/cookbook/dynamic-forms.jade b/public/docs/dart/latest/cookbook/dynamic-form.jade similarity index 100% rename from public/docs/dart/latest/cookbook/dynamic-forms.jade rename to public/docs/dart/latest/cookbook/dynamic-form.jade diff --git a/public/docs/dart/latest/tutorial/_data.json b/public/docs/dart/latest/tutorial/_data.json index fd9b910d46..b292070557 100644 --- a/public/docs/dart/latest/tutorial/_data.json +++ b/public/docs/dart/latest/tutorial/_data.json @@ -29,5 +29,10 @@ "title": "Routing", "intro": "We add the Angular Component Router and learn to navigate among the views", "nextable": true + }, + "toh-pt6": { + "title": "Http", + "intro": "We convert our service and components to use Http", + "nextable": true } } diff --git a/public/docs/dart/latest/tutorial/toh-pt6.jade b/public/docs/dart/latest/tutorial/toh-pt6.jade new file mode 100644 index 0000000000..6778b6af28 --- /dev/null +++ b/public/docs/dart/latest/tutorial/toh-pt6.jade @@ -0,0 +1 @@ +!= partial("../../../_includes/_ts-temp") diff --git a/public/docs/js/latest/tutorial/_data.json b/public/docs/js/latest/tutorial/_data.json index bf52bf1c4e..0e5cc1661d 100644 --- a/public/docs/js/latest/tutorial/_data.json +++ b/public/docs/js/latest/tutorial/_data.json @@ -29,5 +29,10 @@ "title": "Routing", "intro": "We add the Angular Component Router and learn to navigate among the views", "nextable": true + }, + "toh-pt6": { + "title": "Http", + "intro": "We convert our service and components to use Http", + "nextable": true } } diff --git a/public/docs/js/latest/tutorial/toh-pt6.jade b/public/docs/js/latest/tutorial/toh-pt6.jade new file mode 100644 index 0000000000..6778b6af28 --- /dev/null +++ b/public/docs/js/latest/tutorial/toh-pt6.jade @@ -0,0 +1 @@ +!= partial("../../../_includes/_ts-temp") diff --git a/public/docs/ts/latest/glossary.jade b/public/docs/ts/latest/glossary.jade index 6a10b6ebf1..0aa98fcf49 100644 --- a/public/docs/ts/latest/glossary.jade +++ b/public/docs/ts/latest/glossary.jade @@ -176,16 +176,16 @@ include _util-fns operations and supporting declaration syntax. The many forms of binding include: - * [Interpolation](guide/template-syntax.html#interpolation) - * [Property Binding](guide/template-syntax.html#property-binding) - * [Event Binding](guide/template-syntax.html#event-binding) - * [Attribute Binding](guide/template-syntax.html#attribute-binding) - * [Class Binding](guide/template-syntax.html#class-binding) - * [Style Binding](guide/template-syntax.html#style-binding) - * [Two-way data binding with ngModel](guide/template-syntax.html#ng-model) + * [Interpolation](/docs/ts/latest/guide/template-syntax.html#interpolation) + * [Property Binding](/docs/ts/latest/guide/template-syntax.html#property-binding) + * [Event Binding](/docs/ts/latest/guide/template-syntax.html#event-binding) + * [Attribute Binding](/docs/ts/latest/guide/template-syntax.html#attribute-binding) + * [Class Binding](/docs/ts/latest/guide/template-syntax.html#class-binding) + * [Style Binding](/docs/ts/latest/guide/template-syntax.html#style-binding) + * [Two-way data binding with ngModel](/docs/ts/latest/guide/template-syntax.html#ng-model) Learn more about data binding in the - [Template Syntax](guide/template-syntax.html#data-binding) chapter. + [Template Syntax](/docs/ts/latest/guide/template-syntax.html#data-binding) chapter. // #enddocregion d1 @@ -275,7 +275,7 @@ include _util-fns is when we [bootstrap](#bootstrap) the application. There are other opportunities to register as well. - Learn more in the [Dependency Injection](guide/dependency-injection.html) chapter. + Learn more in the [Dependency Injection](/docs/ts/latest/guide/dependency-injection.html) chapter. :marked ## Directive .l-sub-section @@ -376,11 +376,11 @@ include _util-fns .l-sub-section :marked A directive property that can be the ***target*** of a - [Property Binding](guide/template-syntax.html#property-binding). + [Property Binding](/docs/ts/latest/guide/template-syntax.html#property-binding). Data values flow *into* this property from the data source identified in the template expression to the right of the equal sign. - See the [Template Syntax](guide/template-syntax.html#inputs-outputs) chapter. + See the [Template Syntax](/docs/ts/latest/guide/template-syntax.html#inputs-outputs) chapter. :marked ## Interpolation @@ -397,7 +397,7 @@ include _util-fns :marked Learn more about interpolation in the - [Template Syntax](guide/template-syntax.html#interpolation) chapter. + [Template Syntax](/docs/ts/latest/guide/template-syntax.html#interpolation) chapter. @@ -439,7 +439,7 @@ include _util-fns * `ngAfterViewChecked` - after every check of a component's view(s) * `ngOnDestroy` - just before the directive is destroyed. - Learn more in the [Lifecycle Hooks](guide/lifecycle-hooks.html) chapter. + Learn more in the [Lifecycle Hooks](/docs/ts/latest/guide/lifecycle-hooks.html) chapter. // #enddocregion f-l // #docregion m1 @@ -472,7 +472,7 @@ include _util-fns Application developers may pick any module library that conforms to the standard Modules are typically named after the file in which the exported thing is defined. - The Angular [DatePipe](https://github.com/angular/angular/blob/master/modules/angular2/src/common/pipes/date_pipe.ts) + The Angular [DatePipe](https://github.com/angular/angular/blob/master/modules/@angular/common/src/pipes/date_pipe.ts) class belongs to a feature module named `date_pipe` in the file `date_pipe.ts`. Developers rarely access Angular feature modules directly. @@ -492,11 +492,11 @@ include _util-fns .l-sub-section :marked A directive property that can be the ***target*** of an - [Event Binding](guide/template-syntax.html#property-binding). + [Event Binding](/docs/ts/latest/guide/template-syntax.html#property-binding). Events stream *out* of this property to the receiver identified in the template expression to the right of the equal sign. - See the [Template Syntax](guide/template-syntax.html#inputs-outputs) chapter. + See the [Template Syntax](/docs/ts/latest/guide/template-syntax.html#inputs-outputs) chapter. .l-main-section @@ -525,7 +525,7 @@ include _util-fns code-example(language="html" escape="html"). {{product.price | currency}} :marked - Learn more in the chapter on [pipes](guide/pipes.html) . + Learn more in the chapter on [pipes](/docs/ts/latest/guide/pipes.html) . :marked ## Provider @@ -552,7 +552,7 @@ include _util-fns and taking other similar actions that cause the application to replace one view with another. - The Angular [Component Router](guide/router.html) is a richly featured mechanism for configuring + The Angular [Component Router](/docs/ts/latest/guide/router.html) is a richly featured mechanism for configuring and managing the entire view navigation process including the creation and destruction of views. :marked @@ -609,7 +609,7 @@ include _util-fns the support and continuing guidance of an Angular [Directive](#directive), most notably a [Component](#component). - We write templates in a special [Template Syntax](guide/template-syntax.html). + We write templates in a special [Template Syntax](/docs/ts/latest/guide/template-syntax.html). :marked ## Template Expression @@ -617,7 +617,7 @@ include _util-fns :marked An expression in a JavaScript-like syntax that Angular evaluates within a [data binding](#data-binding). Learn how to write template expressions - in the [Template Syntax](guide/template-syntax.html#template-expressions) chapter. + in the [Template Syntax](/docs/ts/latest/guide/template-syntax.html#template-expressions) chapter. // #enddocregion t1 // #docregion t2 @@ -683,8 +683,7 @@ include _util-fns The browser DOM and JavaScript have a limited number of asynchronous activities, activities such as DOM events (e.g., clicks), - [promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ - Promise), and + [promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), and [XHR](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) calls to remote servers. diff --git a/public/docs/ts/latest/guide/npm-packages.jade b/public/docs/ts/latest/guide/npm-packages.jade index 063b1aeaba..281b17511a 100644 --- a/public/docs/ts/latest/guide/npm-packages.jade +++ b/public/docs/ts/latest/guide/npm-packages.jade @@ -172,8 +172,7 @@ a(id="why-peer-dependencies") We don't have a *peerDependencies* section in the QuickStart `package.json`. But Angular itself has a *peerDependencies* section in - [*its* package.json](https://github.com/angular/angular/blob/master/modules/angular2/package.json) - and that has important consequences for our application. + *its* package.json and that has important consequences for our application. It explains why we load the [polyfill](#polyfills) *dependency* packages in the QuickStart `package.json`, and why we'll need those packages in our own applications. diff --git a/public/docs/ts/latest/tutorial/toh-pt5.jade b/public/docs/ts/latest/tutorial/toh-pt5.jade index 113c2f94db..79d61f7211 100644 --- a/public/docs/ts/latest/tutorial/toh-pt5.jade +++ b/public/docs/ts/latest/tutorial/toh-pt5.jade @@ -284,7 +284,7 @@ code-example(format="." language="bash"). :marked We specify the path _all the way back to the application root_ — `app/` in this case — because Angular doesn't support relative paths _by default_. - We _can_ switch to [component-relative paths](../cookbook/component-relative-paths) if we prefer. + We _can_ switch to [component-relative paths](../cookbook/component-relative-paths.html) if we prefer. :marked Create that file with these contents: +makeExample('toh-5/ts/app/dashboard.component.html', null, 'dashboard.component.html')(format=".") From 4b4c8dc0fd9132773e03f0e901cd3a4c70269ba3 Mon Sep 17 00:00:00 2001 From: Jesse Palmer Date: Wed, 25 May 2016 11:30:43 -0400 Subject: [PATCH 10/13] docs(readme): typo fixed - Angular.io -> angular.io --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5e1c55b7bd..59732e1d95 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ if not install [nvm](https://github.com/creationix/nvm) to get node going on you 1. clone this repo and the [angular source code repo](https://github.com/angular/angular) to the same parent directory. The two cloned repo directories must be sibling. -1. cd into root directory `Angular.io/` +1. cd into root directory `angular.io/` 1. install the *all-docs* local packages by running `npm install` > If running node v.5+, you probably must rebuild `node-sass` in a separate step: `npm rebuild node-sass` @@ -54,7 +54,7 @@ For example, all of the TypeScript docs are in `public/docs/ts/latest`, e.g. - `public/docs/ts/latest/tutorial/toh-pt5.jade` ### Local server with watches and browser reload - 1. cd into root directory `Angular.io/` + 1. cd into root directory `angular.io/` 1. run `gulp serve-and-sync` 1. browser will launch on localhost:3000 and stay refreshed automatically. @@ -82,7 +82,7 @@ take the following extra steps to prepare the environment: 1. install the canonical node packages for all samples by running `npm install` -1. cd back up to `Angular.io` root: `cd ../../..` +1. cd back up to `angular.io` root: `cd ../../..` 1. run `gulp add-example-boilerplate` (elevate to admin on Windows) to copy canonical files to the sample directories and create symlinks there for node_modules and typings. From eb48a71351b88115e73540aa829e3a979e6f235e Mon Sep 17 00:00:00 2001 From: "Zhimin YE(Rex)" Date: Wed, 25 May 2016 16:14:29 +0100 Subject: [PATCH 11/13] docs(architecture): fixed missing `` mark. closes #1514 --- public/docs/ts/latest/guide/architecture.jade | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/public/docs/ts/latest/guide/architecture.jade b/public/docs/ts/latest/guide/architecture.jade index 11031aff02..e7ee02863b 100644 --- a/public/docs/ts/latest/guide/architecture.jade +++ b/public/docs/ts/latest/guide/architecture.jade @@ -286,13 +286,13 @@ figure We saw three forms of data binding in our [example](#template) template: +makeExample('architecture/ts/app/hero-list.component.1.html', 'binding', 'app/hero-list.component.html (excerpt)')(format=".") :marked - * The {{hero.name}} "[interpolation](displaying-data.html#interpolation)" + * The `{{hero.name}}` [*interpolation*](displaying-data.html#interpolation) displays the component's `hero.name` property value within the `
` tags. - * The `[hero]` [property binding](template-syntax.html#property-binding) passes the `selectedHero` from + * The `[hero]` [*property binding*](template-syntax.html#property-binding) passes the `selectedHero` from the parent `HeroListComponent` to the `hero` property of the child `HeroDetailComponent`. - * The `(click)` [event binding](user-input.html#click) calls the Component's `selectHero` method when the user clicks + * The `(click)` [*event binding*](user-input.html#click) calls the Component's `selectHero` method when the user clicks on a hero's name **Two-way data binding** is an important fourth form From 856947942330656fc634b04eaec5dabd1d89d574 Mon Sep 17 00:00:00 2001 From: Vikash Date: Wed, 25 May 2016 19:47:23 +0530 Subject: [PATCH 12/13] docs: fix numerous typos in many doc files. closes #1509 --- .../docs/_examples/router-deprecated/ts/app/dialog.service.ts | 2 +- public/docs/_examples/router/ts/app/dialog.service.ts | 2 +- .../heroes/shared/hero-button/hero-button.component.avoid.ts | 2 +- public/docs/_includes/styleguide/_aside.jade | 4 ++-- public/docs/_includes/styleguide/_code-examples.jade | 4 ++-- public/docs/_includes/styleguide/_layouts.jade | 4 ++-- public/docs/_includes/styleguide/_tables.jade | 4 ++-- public/docs/dart/latest/tutorial/toh-pt3.jade | 2 +- public/docs/js/latest/guide/forms.jade | 4 ++-- public/docs/js/latest/quickstart.jade | 2 +- public/docs/ts/latest/cookbook/set-document-title.jade | 2 +- public/docs/ts/latest/glossary.jade | 2 +- public/docs/ts/latest/guide/dependency-injection.jade | 2 +- public/docs/ts/latest/guide/forms.jade | 2 +- public/docs/ts/latest/guide/npm-packages.jade | 2 +- public/docs/ts/latest/guide/webpack.jade | 4 ++-- public/docs/ts/latest/tutorial/toh-pt3.jade | 2 +- tools/doc-shredder/doc-shredder.js | 2 +- 18 files changed, 24 insertions(+), 24 deletions(-) diff --git a/public/docs/_examples/router-deprecated/ts/app/dialog.service.ts b/public/docs/_examples/router-deprecated/ts/app/dialog.service.ts index 5d6160c59f..3f5ceba475 100644 --- a/public/docs/_examples/router-deprecated/ts/app/dialog.service.ts +++ b/public/docs/_examples/router-deprecated/ts/app/dialog.service.ts @@ -3,7 +3,7 @@ import { Injectable } from '@angular/core'; /** * Async modal dialog service * DialogService makes this app easier to test by faking this service. - * TODO: better modal implemenation that doesn't use window.confirm + * TODO: better modal implementation that doesn't use window.confirm */ @Injectable() export class DialogService { diff --git a/public/docs/_examples/router/ts/app/dialog.service.ts b/public/docs/_examples/router/ts/app/dialog.service.ts index b6e234b6ea..71a342cbe8 100644 --- a/public/docs/_examples/router/ts/app/dialog.service.ts +++ b/public/docs/_examples/router/ts/app/dialog.service.ts @@ -3,7 +3,7 @@ import { Injectable } from '@angular/core'; /** * Async modal dialog service * DialogService makes this app easier to test by faking this service. - * TODO: better modal implemenation that doesn't use window.confirm + * TODO: better modal implementation that doesn't use window.confirm */ @Injectable() export class DialogService { diff --git a/public/docs/_examples/style-guide/ts/09-01/app/heroes/shared/hero-button/hero-button.component.avoid.ts b/public/docs/_examples/style-guide/ts/09-01/app/heroes/shared/hero-button/hero-button.component.avoid.ts index d451d41be0..7dc42c2f40 100644 --- a/public/docs/_examples/style-guide/ts/09-01/app/heroes/shared/hero-button/hero-button.component.avoid.ts +++ b/public/docs/_examples/style-guide/ts/09-01/app/heroes/shared/hero-button/hero-button.component.avoid.ts @@ -8,7 +8,7 @@ import { Component } from '@angular/core'; template: `