225 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			225 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
// Based on https://github.com/angular/angular/blob/master/modules/angular2/test/testing/testing_public_spec.ts
 | 
						|
/* tslint:disable:forin */
 | 
						|
import { Component, EventEmitter, Injectable, Input, Output,
 | 
						|
         OnInit, OnChanges, OnDestroy, SimpleChange } from '@angular/core';
 | 
						|
 | 
						|
import { Observable }     from 'rxjs/Rx';
 | 
						|
 | 
						|
////////// The App: Services and Components for the tests. //////////////
 | 
						|
 | 
						|
////////// Services ///////////////
 | 
						|
 | 
						|
@Injectable()
 | 
						|
export class FancyService {
 | 
						|
  value: string = 'real value';
 | 
						|
 | 
						|
  getAsyncValue() { return Promise.resolve('async value'); }
 | 
						|
 | 
						|
  getObservableValue() { return Observable.of('observable value'); }
 | 
						|
 | 
						|
  getTimeoutValue() {
 | 
						|
    return new Promise((resolve, reject) => { setTimeout(() => {resolve('timeout value'); }, 10); });
 | 
						|
  }
 | 
						|
 | 
						|
  getObservableDelayValue() { return Observable.of('observable delay value').delay(10); }
 | 
						|
}
 | 
						|
 | 
						|
@Injectable()
 | 
						|
export class MockFancyService extends FancyService {
 | 
						|
  value: string = 'mocked out value';
 | 
						|
}
 | 
						|
 | 
						|
//////////// Components /////////////
 | 
						|
 | 
						|
@Component({
 | 
						|
  selector: 'button-comp',
 | 
						|
  template: `<button (click)='clicked()'>Click me!</button>`
 | 
						|
})
 | 
						|
export class ButtonComp {
 | 
						|
  wasClicked = false;
 | 
						|
  clicked() { this.wasClicked = true; }
 | 
						|
}
 | 
						|
 | 
						|
@Component({
 | 
						|
  selector: 'input-comp',
 | 
						|
  template: `<input [(ngModel)]="name">`
 | 
						|
})
 | 
						|
export class InputComp {
 | 
						|
  name = 'John';
 | 
						|
}
 | 
						|
 | 
						|
@Component({
 | 
						|
  selector: 'child-comp',
 | 
						|
  template: `<span>Original {{childBinding}}</span>`
 | 
						|
})
 | 
						|
export class ChildComp {
 | 
						|
  childBinding = 'Child';
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
@Component({
 | 
						|
  selector: 'child-comp',
 | 
						|
  template: `<span>Mock</span>`
 | 
						|
})
 | 
						|
export class MockChildComp { }
 | 
						|
 | 
						|
 | 
						|
@Component({
 | 
						|
  selector: 'parent-comp',
 | 
						|
  template: `Parent(<child-comp></child-comp>)`,
 | 
						|
  directives: [ChildComp]
 | 
						|
})
 | 
						|
export class ParentComp { }
 | 
						|
 | 
						|
 | 
						|
@Component({
 | 
						|
  selector: 'my-if-comp',
 | 
						|
  template: `MyIf(<span *ngIf="showMore">More</span>)`
 | 
						|
})
 | 
						|
export class MyIfComp {
 | 
						|
  showMore = false;
 | 
						|
}
 | 
						|
 | 
						|
@Component({
 | 
						|
  selector: 'child-child-comp',
 | 
						|
  template: '<span>ChildChild</span>'
 | 
						|
})
 | 
						|
export class ChildChildComp { }
 | 
						|
 | 
						|
 | 
						|
@Component({
 | 
						|
  selector: 'child-comp',
 | 
						|
  template: `<span>Original {{childBinding}}(<child-child-comp></child-child-comp>)</span>`,
 | 
						|
  directives: [ChildChildComp]
 | 
						|
})
 | 
						|
export class ChildWithChildComp {
 | 
						|
  childBinding = 'Child';
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
@Component({
 | 
						|
  selector: 'child-child-comp',
 | 
						|
  template: `<span>ChildChild Mock</span>`
 | 
						|
})
 | 
						|
export class MockChildChildComp { }
 | 
						|
 | 
						|
 | 
						|
@Component({
 | 
						|
  selector: 'my-service-comp',
 | 
						|
  template: `injected value: {{fancyService.value}}`,
 | 
						|
  providers: [FancyService]
 | 
						|
})
 | 
						|
export class TestProvidersComp {
 | 
						|
  constructor(private fancyService: FancyService) {}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
@Component({
 | 
						|
  selector: 'my-service-comp',
 | 
						|
  template: `injected value: {{fancyService.value}}`,
 | 
						|
  viewProviders: [FancyService]
 | 
						|
})
 | 
						|
export class TestViewProvidersComp {
 | 
						|
  constructor(private fancyService: FancyService) {}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
@Component({
 | 
						|
  moduleId: module.id,
 | 
						|
  selector: 'external-template-comp',
 | 
						|
  templateUrl: 'bag-external-template.html'
 | 
						|
})
 | 
						|
export class ExternalTemplateComp { }
 | 
						|
 | 
						|
 | 
						|
@Component({
 | 
						|
  selector: 'bad-template-comp',
 | 
						|
  templateUrl: 'non-existant.html'
 | 
						|
})
 | 
						|
export class BadTemplateUrl { }
 | 
						|
 | 
						|
 | 
						|
///////// MyIfChildComp ////////
 | 
						|
@Component({
 | 
						|
  selector: 'my-if-child-comp',
 | 
						|
 | 
						|
  template: `
 | 
						|
    <h4>MyIfChildComp</h4>
 | 
						|
    <div>
 | 
						|
      <label>Child value: <input [(ngModel)]="childValue"> </label>
 | 
						|
    </div>
 | 
						|
    <p><i>Change log:</i></p>
 | 
						|
    <div *ngFor="let log of changeLog; let i=index">{{i + 1}} - {{log}}</div>`
 | 
						|
})
 | 
						|
export class MyIfChildComp implements OnInit, OnChanges, OnDestroy {
 | 
						|
  @Input() value = '';
 | 
						|
  @Output() valueChange = new EventEmitter<string>();
 | 
						|
 | 
						|
  get childValue() { return this.value; }
 | 
						|
  set childValue(v: string) {
 | 
						|
    if (this.value === v) { return; }
 | 
						|
    this.value = v;
 | 
						|
    this.valueChange.emit(v);
 | 
						|
  }
 | 
						|
 | 
						|
  changeLog: string[] = [];
 | 
						|
 | 
						|
  ngOnInitCalled = false;
 | 
						|
  ngOnChangesCounter = 0;
 | 
						|
  ngOnDestroyCalled = false;
 | 
						|
 | 
						|
  ngOnInit()    {
 | 
						|
    this.ngOnInitCalled = true;
 | 
						|
    this.changeLog.push('ngOnInit called');
 | 
						|
  }
 | 
						|
 | 
						|
  ngOnDestroy() {
 | 
						|
    this.ngOnDestroyCalled = true;
 | 
						|
    this.changeLog.push('ngOnDestroy called');
 | 
						|
  }
 | 
						|
 | 
						|
  ngOnChanges(changes: {[propertyName: string]: SimpleChange}) {
 | 
						|
    for (let propName in changes) {
 | 
						|
      this.ngOnChangesCounter += 1;
 | 
						|
      let prop = changes[propName];
 | 
						|
      let cur  = JSON.stringify(prop.currentValue);
 | 
						|
      let prev = JSON.stringify(prop.previousValue);
 | 
						|
      this.changeLog.push(`${propName}: currentValue = ${cur}, previousValue = ${prev}`);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
///////// MyIfParentComp ////////
 | 
						|
 | 
						|
@Component({
 | 
						|
  selector: 'my-if-parent-comp',
 | 
						|
  template: `
 | 
						|
    <h3>MyIfParentComp</h3>
 | 
						|
    <label>Parent value:
 | 
						|
      <input [(ngModel)]="parentValue">
 | 
						|
    </label>
 | 
						|
    <button (click)='clicked()'>{{toggleLabel}} Child</button><br>
 | 
						|
    <div *ngIf="showChild"
 | 
						|
         style="margin: 4px; padding: 4px; background-color: aliceblue;">
 | 
						|
      <my-if-child-comp  [(value)]="parentValue"></my-if-child-comp>
 | 
						|
    </div>
 | 
						|
  `,
 | 
						|
  directives: [MyIfChildComp]
 | 
						|
})
 | 
						|
export class MyIfParentComp implements OnInit {
 | 
						|
  ngOnInitCalled = false;
 | 
						|
  parentValue = 'Hello, World';
 | 
						|
  showChild = false;
 | 
						|
  toggleLabel = 'Unknown';
 | 
						|
 | 
						|
  ngOnInit() {
 | 
						|
    this.ngOnInitCalled = true;
 | 
						|
    this.clicked();
 | 
						|
  }
 | 
						|
 | 
						|
  clicked() {
 | 
						|
    this.showChild = !this.showChild;
 | 
						|
    this.toggleLabel = this.showChild ? 'Close' : 'Show';
 | 
						|
  }
 | 
						|
}
 |