refactor(core): move directives, pipes, and forms into common

BREAKING CHANGE

All private exports from 'angular2/src/core/{directives,pipes,forms}' should be replaced with 'angular2/src/common/{directives,pipes,formis}'

Closes #5153
This commit is contained in:
vsavkin
2015-11-05 14:58:24 -08:00
committed by Victor Savkin
parent 6edd964a83
commit 695923dcd6
82 changed files with 166 additions and 147 deletions
@@ -1,483 +0,0 @@
import {
ComponentFixture,
AsyncTestCompleter,
TestComponentBuilder,
beforeEach,
beforeEachBindings,
ddescribe,
xdescribe,
describe,
el,
expect,
iit,
inject,
it,
xit,
} from 'angular2/testing_internal';
import {ListWrapper, StringMapWrapper, SetWrapper} from 'angular2/src/core/facade/collection';
import {Component, View, NgFor, provide} from 'angular2/angular2';
import {NgClass} from 'angular2/src/core/directives/ng_class';
import {APP_VIEW_POOL_CAPACITY} from 'angular2/src/core/linker/view_pool';
function detectChangesAndCheck(fixture: ComponentFixture, classes: string, elIndex: number = 0) {
fixture.detectChanges();
expect(fixture.debugElement.componentViewChildren[elIndex].nativeElement.className)
.toEqual(classes);
}
export function main() {
describe('binding to CSS class list', () => {
describe('viewpool support', () => {
beforeEachBindings(() => { return [provide(APP_VIEW_POOL_CAPACITY, {useValue: 100})]; });
it('should clean up when the directive is destroyed',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<div *ng-for="var item of items" [ng-class]="item"></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
fixture.debugElement.componentInstance.items = [['0']];
fixture.detectChanges();
fixture.debugElement.componentInstance.items = [['1']];
detectChangesAndCheck(fixture, '1', 1);
async.done();
});
}));
});
describe('expressions evaluating to objects', () => {
it('should add classes specified in an object literal',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<div [ng-class]="{foo: true, bar: false}"></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
detectChangesAndCheck(fixture, 'foo');
async.done();
});
}));
it('should add classes specified in an object literal without change in class names',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = `<div [ng-class]="{'foo-bar': true, 'fooBar': true}"></div>`;
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
detectChangesAndCheck(fixture, 'foo-bar fooBar');
async.done();
});
}));
it('should add and remove classes based on changes in object literal values',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<div [ng-class]="{foo: condition, bar: !condition}"></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
detectChangesAndCheck(fixture, 'foo');
fixture.debugElement.componentInstance.condition = false;
detectChangesAndCheck(fixture, 'bar');
async.done();
});
}));
it('should add and remove classes based on changes to the expression object',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<div [ng-class]="objExpr"></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
detectChangesAndCheck(fixture, 'foo');
StringMapWrapper.set(fixture.debugElement.componentInstance.objExpr, 'bar', true);
detectChangesAndCheck(fixture, 'foo bar');
StringMapWrapper.set(fixture.debugElement.componentInstance.objExpr, 'baz', true);
detectChangesAndCheck(fixture, 'foo bar baz');
StringMapWrapper.delete(fixture.debugElement.componentInstance.objExpr, 'bar');
detectChangesAndCheck(fixture, 'foo baz');
async.done();
});
}));
it('should add and remove classes based on reference changes to the expression object',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<div [ng-class]="objExpr"></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
detectChangesAndCheck(fixture, 'foo');
fixture.debugElement.componentInstance.objExpr = {foo: true, bar: true};
detectChangesAndCheck(fixture, 'foo bar');
fixture.debugElement.componentInstance.objExpr = {baz: true};
detectChangesAndCheck(fixture, 'baz');
async.done();
});
}));
it('should remove active classes when expression evaluates to null',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<div [ng-class]="objExpr"></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
detectChangesAndCheck(fixture, 'foo');
fixture.debugElement.componentInstance.objExpr = null;
detectChangesAndCheck(fixture, '');
fixture.debugElement.componentInstance.objExpr = {'foo': false, 'bar': true};
detectChangesAndCheck(fixture, 'bar');
async.done();
});
}));
});
describe('expressions evaluating to lists', () => {
it('should add classes specified in a list literal',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = `<div [ng-class]="['foo', 'bar', 'foo-bar', 'fooBar']"></div>`;
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
detectChangesAndCheck(fixture, 'foo bar foo-bar fooBar');
async.done();
});
}));
it('should add and remove classes based on changes to the expression',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<div [ng-class]="arrExpr"></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
var arrExpr: string[] = fixture.debugElement.componentInstance.arrExpr;
detectChangesAndCheck(fixture, 'foo');
arrExpr.push('bar');
detectChangesAndCheck(fixture, 'foo bar');
arrExpr[1] = 'baz';
detectChangesAndCheck(fixture, 'foo baz');
ListWrapper.remove(fixture.debugElement.componentInstance.arrExpr, 'baz');
detectChangesAndCheck(fixture, 'foo');
async.done();
});
}));
it('should add and remove classes when a reference changes',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<div [ng-class]="arrExpr"></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
detectChangesAndCheck(fixture, 'foo');
fixture.debugElement.componentInstance.arrExpr = ['bar'];
detectChangesAndCheck(fixture, 'bar');
async.done();
});
}));
it('should take initial classes into account when a reference changes',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<div class="foo" [ng-class]="arrExpr"></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
detectChangesAndCheck(fixture, 'foo');
fixture.debugElement.componentInstance.arrExpr = ['bar'];
detectChangesAndCheck(fixture, 'foo bar');
async.done();
});
}));
it('should ignore empty or blank class names',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<div class="foo" [ng-class]="arrExpr"></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
fixture.debugElement.componentInstance.arrExpr = ['', ' '];
detectChangesAndCheck(fixture, 'foo');
async.done();
});
}));
it('should trim blanks from class names',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<div class="foo" [ng-class]="arrExpr"></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
fixture.debugElement.componentInstance.arrExpr = [' bar '];
detectChangesAndCheck(fixture, 'foo bar');
async.done();
});
}));
});
describe('expressions evaluating to sets', () => {
it('should add and remove classes if the set instance changed',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<div [ng-class]="setExpr"></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
var setExpr = new Set<string>();
setExpr.add('bar');
fixture.debugElement.componentInstance.setExpr = setExpr;
detectChangesAndCheck(fixture, 'bar');
setExpr = new Set<string>();
setExpr.add('baz');
fixture.debugElement.componentInstance.setExpr = setExpr;
detectChangesAndCheck(fixture, 'baz');
async.done();
});
}));
});
describe('expressions evaluating to string', () => {
it('should add classes specified in a string literal',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = `<div [ng-class]="'foo bar foo-bar fooBar'"></div>`;
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
detectChangesAndCheck(fixture, 'foo bar foo-bar fooBar');
async.done();
});
}));
it('should add and remove classes based on changes to the expression',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<div [ng-class]="strExpr"></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
detectChangesAndCheck(fixture, 'foo');
fixture.debugElement.componentInstance.strExpr = 'foo bar';
detectChangesAndCheck(fixture, 'foo bar');
fixture.debugElement.componentInstance.strExpr = 'baz';
detectChangesAndCheck(fixture, 'baz');
async.done();
});
}));
it('should remove active classes when switching from string to null',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = `<div [ng-class]="strExpr"></div>`;
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
detectChangesAndCheck(fixture, 'foo');
fixture.debugElement.componentInstance.strExpr = null;
detectChangesAndCheck(fixture, '');
async.done();
});
}));
it('should take initial classes into account when switching from string to null',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = `<div class="foo" [ng-class]="strExpr"></div>`;
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
detectChangesAndCheck(fixture, 'foo');
fixture.debugElement.componentInstance.strExpr = null;
detectChangesAndCheck(fixture, 'foo');
async.done();
});
}));
it('should ignore empty and blank strings',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = `<div class="foo" [ng-class]="strExpr"></div>`;
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
fixture.debugElement.componentInstance.strExpr = '';
detectChangesAndCheck(fixture, 'foo');
async.done();
});
}));
});
describe('cooperation with other class-changing constructs', () => {
it('should co-operate with the class attribute',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<div [ng-class]="objExpr" class="init foo"></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
StringMapWrapper.set(fixture.debugElement.componentInstance.objExpr, 'bar', true);
detectChangesAndCheck(fixture, 'init foo bar');
StringMapWrapper.set(fixture.debugElement.componentInstance.objExpr, 'foo', false);
detectChangesAndCheck(fixture, 'init bar');
fixture.debugElement.componentInstance.objExpr = null;
detectChangesAndCheck(fixture, 'init foo');
async.done();
});
}));
it('should co-operate with the interpolated class attribute',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = `<div [ng-class]="objExpr" class="{{'init foo'}}"></div>`;
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
StringMapWrapper.set(fixture.debugElement.componentInstance.objExpr, 'bar', true);
detectChangesAndCheck(fixture, `init foo bar`);
StringMapWrapper.set(fixture.debugElement.componentInstance.objExpr, 'foo', false);
detectChangesAndCheck(fixture, `init bar`);
fixture.debugElement.componentInstance.objExpr = null;
detectChangesAndCheck(fixture, `init foo`);
async.done();
});
}));
it('should co-operate with the class attribute and binding to it',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = `<div [ng-class]="objExpr" class="init" [class]="'foo'"></div>`;
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
StringMapWrapper.set(fixture.debugElement.componentInstance.objExpr, 'bar', true);
detectChangesAndCheck(fixture, `init foo bar`);
StringMapWrapper.set(fixture.debugElement.componentInstance.objExpr, 'foo', false);
detectChangesAndCheck(fixture, `init bar`);
fixture.debugElement.componentInstance.objExpr = null;
detectChangesAndCheck(fixture, `init foo`);
async.done();
});
}));
it('should co-operate with the class attribute and class.name binding',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template =
'<div class="init foo" [ng-class]="objExpr" [class.baz]="condition"></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
detectChangesAndCheck(fixture, 'init foo baz');
StringMapWrapper.set(fixture.debugElement.componentInstance.objExpr, 'bar', true);
detectChangesAndCheck(fixture, 'init foo baz bar');
StringMapWrapper.set(fixture.debugElement.componentInstance.objExpr, 'foo', false);
detectChangesAndCheck(fixture, 'init baz bar');
fixture.debugElement.componentInstance.condition = false;
detectChangesAndCheck(fixture, 'init bar');
async.done();
});
}));
it('should co-operate with initial class and class attribute binding when binding changes',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<div class="init" [ng-class]="objExpr" [class]="strExpr"></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
detectChangesAndCheck(fixture, 'init foo');
StringMapWrapper.set(fixture.debugElement.componentInstance.objExpr, 'bar', true);
detectChangesAndCheck(fixture, 'init foo bar');
fixture.debugElement.componentInstance.strExpr = 'baz';
detectChangesAndCheck(fixture, 'init bar baz foo');
fixture.debugElement.componentInstance.objExpr = null;
detectChangesAndCheck(fixture, 'init baz');
async.done();
});
}));
});
})
}
@Component({selector: 'test-cmp'})
@View({directives: [NgClass, NgFor]})
class TestComponent {
condition: boolean = true;
items: any[];
arrExpr: string[] = ['foo'];
setExpr: Set<string> = new Set<string>();
objExpr = {'foo': true, 'bar': false};
strExpr = 'foo';
constructor() { this.setExpr.add('foo'); }
}
@@ -1,352 +0,0 @@
import {
AsyncTestCompleter,
TestComponentBuilder,
beforeEach,
beforeEachBindings,
ddescribe,
describe,
el,
expect,
iit,
inject,
it,
xit,
} from 'angular2/testing_internal';
import {ListWrapper} from 'angular2/src/core/facade/collection';
import {Component, View, TemplateRef, ContentChild} from 'angular2/angular2';
import {NgFor} from 'angular2/src/core/directives/ng_for';
export function main() {
describe('ng-for', () => {
var TEMPLATE =
'<div><copy-me template="ng-for #item of items">{{item.toString()}};</copy-me></div>';
it('should reflect initial elements',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.overrideTemplate(TestComponent, TEMPLATE)
.createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('1;2;');
async.done();
});
}));
it('should reflect added elements',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.overrideTemplate(TestComponent, TEMPLATE)
.createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges();
(<number[]>fixture.debugElement.componentInstance.items).push(3);
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('1;2;3;');
async.done();
});
}));
it('should reflect removed elements',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.overrideTemplate(TestComponent, TEMPLATE)
.createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges();
ListWrapper.removeAt(fixture.debugElement.componentInstance.items, 1);
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('1;');
async.done();
});
}));
it('should reflect moved elements',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.overrideTemplate(TestComponent, TEMPLATE)
.createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges();
ListWrapper.removeAt(fixture.debugElement.componentInstance.items, 0);
(<number[]>fixture.debugElement.componentInstance.items).push(1);
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('2;1;');
async.done();
});
}));
it('should reflect a mix of all changes (additions/removals/moves)',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.overrideTemplate(TestComponent, TEMPLATE)
.createAsync(TestComponent)
.then((fixture) => {
fixture.debugElement.componentInstance.items = [0, 1, 2, 3, 4, 5];
fixture.detectChanges();
fixture.debugElement.componentInstance.items = [6, 2, 7, 0, 4, 8];
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('6;2;7;0;4;8;');
async.done();
});
}));
it('should iterate over an array of objects',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<ul><li template="ng-for #item of items">{{item["name"]}};</li></ul>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
// INIT
fixture.debugElement.componentInstance.items =
[{'name': 'misko'}, {'name': 'shyam'}];
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('misko;shyam;');
// GROW
(<any[]>fixture.debugElement.componentInstance.items).push({'name': 'adam'});
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('misko;shyam;adam;');
// SHRINK
ListWrapper.removeAt(fixture.debugElement.componentInstance.items, 2);
ListWrapper.removeAt(fixture.debugElement.componentInstance.items, 0);
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('shyam;');
async.done();
});
}));
it('should gracefully handle nulls',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<ul><li template="ng-for #item of null">{{item}};</li></ul>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('');
async.done();
});
}));
it('should gracefully handle ref changing to null and back',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.overrideTemplate(TestComponent, TEMPLATE)
.createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('1;2;');
fixture.debugElement.componentInstance.items = null;
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('');
fixture.debugElement.componentInstance.items = [1, 2, 3];
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('1;2;3;');
async.done();
});
}));
it('should throw on ref changing to string',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.overrideTemplate(TestComponent, TEMPLATE)
.createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('1;2;');
fixture.debugElement.componentInstance.items = 'whaaa';
expect(() => fixture.detectChanges()).toThrowError();
async.done();
});
}));
it('should works with duplicates',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.overrideTemplate(TestComponent, TEMPLATE)
.createAsync(TestComponent)
.then((fixture) => {
var a = new Foo();
fixture.debugElement.componentInstance.items = [a, a];
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('foo;foo;');
async.done();
});
}));
it('should repeat over nested arrays',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<div>' +
'<div template="ng-for #item of items">' +
'<div template="ng-for #subitem of item">' +
'{{subitem}}-{{item.length}};' +
'</div>|' +
'</div>' +
'</div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
fixture.debugElement.componentInstance.items = [['a', 'b'], ['c']];
fixture.detectChanges();
fixture.detectChanges();
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('a-2;b-2;|c-1;|');
fixture.debugElement.componentInstance.items = [['e'], ['f', 'g']];
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('e-1;|f-2;g-2;|');
async.done();
});
}));
it('should repeat over nested arrays with no intermediate element',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<div><template ng-for #item [ng-for-of]="items">' +
'<div template="ng-for #subitem of item">' +
'{{subitem}}-{{item.length}};' +
'</div></template></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
fixture.debugElement.componentInstance.items = [['a', 'b'], ['c']];
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('a-2;b-2;c-1;');
fixture.debugElement.componentInstance.items = [['e'], ['f', 'g']];
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('e-1;f-2;g-2;');
async.done();
});
}));
it('should display indices correctly',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template =
'<div><copy-me template="ng-for: var item of items; var i=index">{{i.toString()}}</copy-me></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
fixture.debugElement.componentInstance.items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('0123456789');
fixture.debugElement.componentInstance.items = [1, 2, 6, 7, 4, 3, 5, 8, 9, 0];
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('0123456789');
async.done();
});
}));
it('should display last item correctly',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template =
'<div><copy-me template="ng-for: var item of items; var isLast=last">{{isLast.toString()}}</copy-me></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
fixture.debugElement.componentInstance.items = [0, 1, 2];
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('falsefalsetrue');
fixture.debugElement.componentInstance.items = [2, 1];
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('falsetrue');
async.done();
});
}));
it('should display even items correctly',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template =
'<div><copy-me template="ng-for: var item of items; var isEven=even">{{isEven.toString()}}</copy-me></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
fixture.debugElement.componentInstance.items = [0, 1, 2];
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('truefalsetrue');
fixture.debugElement.componentInstance.items = [2, 1];
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('truefalse');
async.done();
});
}));
it('should display odd items correctly',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template =
'<div><copy-me template="ng-for: var item of items; var isOdd=odd">{{isOdd.toString()}}</copy-me></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
fixture.debugElement.componentInstance.items = [0, 1, 2, 3];
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('falsetruefalsetrue');
fixture.debugElement.componentInstance.items = [2, 1];
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('falsetrue');
async.done();
});
}));
it('should allow to use a custom template',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.overrideTemplate(
TestComponent,
'<ul><template ng-for [ng-for-of]="items" [ng-for-template]="contentTpl"></template></ul>')
.overrideTemplate(
ComponentUsingTestComponent,
'<test-cmp><li template="#item #i=index">{{i}}: {{item}};</li></test-cmp>')
.createAsync(ComponentUsingTestComponent)
.then((fixture) => {
var testComponent = fixture.debugElement.componentViewChildren[0];
testComponent.componentInstance.items = ['a', 'b', 'c'];
fixture.detectChanges();
expect(testComponent.nativeElement).toHaveText('0: a;1: b;2: c;');
async.done();
});
}));
});
}
class Foo {
toString() { return 'foo'; }
}
@Component({selector: 'test-cmp'})
@View({directives: [NgFor]})
class TestComponent {
@ContentChild(TemplateRef) contentTpl: TemplateRef;
items: any;
constructor() { this.items = [1, 2]; }
}
@Component({selector: 'outer-cmp'})
@View({directives: [TestComponent]})
class ComponentUsingTestComponent {
items: any;
constructor() { this.items = [1, 2]; }
}
@@ -1,241 +0,0 @@
import {
AsyncTestCompleter,
TestComponentBuilder,
beforeEach,
ddescribe,
describe,
el,
expect,
iit,
inject,
it,
xit,
} from 'angular2/testing_internal';
import {DOM} from 'angular2/src/core/dom/dom_adapter';
import {Component, View, NgIf} from 'angular2/core';
import {IS_DART} from 'angular2/src/core/facade/lang';
export function main() {
describe('ng-if directive', () => {
it('should work in a template attribute',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var html = '<div><copy-me template="ng-if booleanCondition">hello</copy-me></div>';
tcb.overrideTemplate(TestComponent, html)
.createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges();
expect(DOM.querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length)
.toEqual(1);
expect(fixture.debugElement.nativeElement).toHaveText('hello');
async.done();
});
}));
it('should work in a template element',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var html =
'<div><template [ng-if]="booleanCondition"><copy-me>hello2</copy-me></template></div>';
tcb.overrideTemplate(TestComponent, html)
.createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges();
expect(DOM.querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length)
.toEqual(1);
expect(fixture.debugElement.nativeElement).toHaveText('hello2');
async.done();
});
}));
it('should toggle node when condition changes',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var html = '<div><copy-me template="ng-if booleanCondition">hello</copy-me></div>';
tcb.overrideTemplate(TestComponent, html)
.createAsync(TestComponent)
.then((fixture) => {
fixture.debugElement.componentInstance.booleanCondition = false;
fixture.detectChanges();
expect(DOM.querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length)
.toEqual(0);
expect(fixture.debugElement.nativeElement).toHaveText('');
fixture.debugElement.componentInstance.booleanCondition = true;
fixture.detectChanges();
expect(DOM.querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length)
.toEqual(1);
expect(fixture.debugElement.nativeElement).toHaveText('hello');
fixture.debugElement.componentInstance.booleanCondition = false;
fixture.detectChanges();
expect(DOM.querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length)
.toEqual(0);
expect(fixture.debugElement.nativeElement).toHaveText('');
async.done();
});
}));
it('should handle nested if correctly',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var html =
'<div><template [ng-if]="booleanCondition"><copy-me *ng-if="nestedBooleanCondition">hello</copy-me></template></div>';
tcb.overrideTemplate(TestComponent, html)
.createAsync(TestComponent)
.then((fixture) => {
fixture.debugElement.componentInstance.booleanCondition = false;
fixture.detectChanges();
expect(DOM.querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length)
.toEqual(0);
expect(fixture.debugElement.nativeElement).toHaveText('');
fixture.debugElement.componentInstance.booleanCondition = true;
fixture.detectChanges();
expect(DOM.querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length)
.toEqual(1);
expect(fixture.debugElement.nativeElement).toHaveText('hello');
fixture.debugElement.componentInstance.nestedBooleanCondition = false;
fixture.detectChanges();
expect(DOM.querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length)
.toEqual(0);
expect(fixture.debugElement.nativeElement).toHaveText('');
fixture.debugElement.componentInstance.nestedBooleanCondition = true;
fixture.detectChanges();
expect(DOM.querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length)
.toEqual(1);
expect(fixture.debugElement.nativeElement).toHaveText('hello');
fixture.debugElement.componentInstance.booleanCondition = false;
fixture.detectChanges();
expect(DOM.querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length)
.toEqual(0);
expect(fixture.debugElement.nativeElement).toHaveText('');
async.done();
});
}));
it('should update several nodes with if',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var html =
'<div>' +
'<copy-me template="ng-if numberCondition + 1 >= 2">helloNumber</copy-me>' +
'<copy-me template="ng-if stringCondition == \'foo\'">helloString</copy-me>' +
'<copy-me template="ng-if functionCondition(stringCondition, numberCondition)">helloFunction</copy-me>' +
'</div>';
tcb.overrideTemplate(TestComponent, html)
.createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges();
expect(DOM.querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length)
.toEqual(3);
expect(DOM.getText(fixture.debugElement.nativeElement))
.toEqual('helloNumberhelloStringhelloFunction');
fixture.debugElement.componentInstance.numberCondition = 0;
fixture.detectChanges();
expect(DOM.querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length)
.toEqual(1);
expect(fixture.debugElement.nativeElement).toHaveText('helloString');
fixture.debugElement.componentInstance.numberCondition = 1;
fixture.debugElement.componentInstance.stringCondition = "bar";
fixture.detectChanges();
expect(DOM.querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length)
.toEqual(1);
expect(fixture.debugElement.nativeElement).toHaveText('helloNumber');
async.done();
});
}));
if (!IS_DART) {
it('should not add the element twice if the condition goes from true to true (JS)',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var html = '<div><copy-me template="ng-if numberCondition">hello</copy-me></div>';
tcb.overrideTemplate(TestComponent, html)
.createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges();
expect(DOM.querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length)
.toEqual(1);
expect(fixture.debugElement.nativeElement).toHaveText('hello');
fixture.debugElement.componentInstance.numberCondition = 2;
fixture.detectChanges();
expect(DOM.querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length)
.toEqual(1);
expect(fixture.debugElement.nativeElement).toHaveText('hello');
async.done();
});
}));
it('should not recreate the element if the condition goes from true to true (JS)',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var html = '<div><copy-me template="ng-if numberCondition">hello</copy-me></div>';
tcb.overrideTemplate(TestComponent, html)
.createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges();
DOM.addClass(DOM.querySelector(fixture.debugElement.nativeElement, 'copy-me'),
"foo");
fixture.debugElement.componentInstance.numberCondition = 2;
fixture.detectChanges();
expect(
DOM.hasClass(DOM.querySelector(fixture.debugElement.nativeElement, 'copy-me'),
"foo"))
.toBe(true);
async.done();
});
}));
}
if (IS_DART) {
it('should not create the element if the condition is not a boolean (DART)',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var html = '<div><copy-me template="ng-if numberCondition">hello</copy-me></div>';
tcb.overrideTemplate(TestComponent, html)
.createAsync(TestComponent)
.then((fixture) => {
expect(() => fixture.detectChanges()).toThrowError();
expect(DOM.querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length)
.toEqual(0);
expect(fixture.debugElement.nativeElement).toHaveText('');
async.done();
});
}));
}
});
}
@Component({selector: 'test-cmp'})
@View({directives: [NgIf]})
class TestComponent {
booleanCondition: boolean;
nestedBooleanCondition: boolean;
numberCondition: number;
stringCondition: string;
functionCondition: Function;
constructor() {
this.booleanCondition = true;
this.nestedBooleanCondition = true;
this.numberCondition = 1;
this.stringCondition = "foo";
this.functionCondition = function(s, n) { return s == "foo" && n == 1; };
}
}
@@ -1,157 +0,0 @@
import {
AsyncTestCompleter,
TestComponentBuilder,
beforeEach,
beforeEachBindings,
ddescribe,
xdescribe,
describe,
el,
expect,
iit,
inject,
it,
xit,
} from 'angular2/testing_internal';
import {StringMapWrapper} from 'angular2/src/core/facade/collection';
import {Component, View} from 'angular2/angular2';
import {DOM} from 'angular2/src/core/dom/dom_adapter';
import {NgStyle} from 'angular2/src/core/directives/ng_style';
export function main() {
describe('binding to CSS styles', () => {
it('should add styles specified in an object literal',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = `<div [ng-style]="{'max-width': '40px'}"></div>`;
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges();
expect(DOM.getStyle(fixture.debugElement.componentViewChildren[0].nativeElement,
'max-width'))
.toEqual('40px');
async.done();
});
}));
it('should add and change styles specified in an object expression',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = `<div [ng-style]="expr"></div>`;
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
var expr: Map<string, any>;
fixture.debugElement.componentInstance.expr = {'max-width': '40px'};
fixture.detectChanges();
expect(DOM.getStyle(fixture.debugElement.componentViewChildren[0].nativeElement,
'max-width'))
.toEqual('40px');
expr = fixture.debugElement.componentInstance.expr;
expr['max-width'] = '30%';
fixture.detectChanges();
expect(DOM.getStyle(fixture.debugElement.componentViewChildren[0].nativeElement,
'max-width'))
.toEqual('30%');
async.done();
});
}));
it('should remove styles when deleting a key in an object expression',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = `<div [ng-style]="expr"></div>`;
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
fixture.debugElement.componentInstance.expr = {'max-width': '40px'};
fixture.detectChanges();
expect(DOM.getStyle(fixture.debugElement.componentViewChildren[0].nativeElement,
'max-width'))
.toEqual('40px');
StringMapWrapper.delete(fixture.debugElement.componentInstance.expr, 'max-width');
fixture.detectChanges();
expect(DOM.getStyle(fixture.debugElement.componentViewChildren[0].nativeElement,
'max-width'))
.toEqual('');
async.done();
});
}));
it('should co-operate with the style attribute',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = `<div style="font-size: 12px" [ng-style]="expr"></div>`;
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
fixture.debugElement.componentInstance.expr = {'max-width': '40px'};
fixture.detectChanges();
expect(DOM.getStyle(fixture.debugElement.componentViewChildren[0].nativeElement,
'max-width'))
.toEqual('40px');
expect(DOM.getStyle(fixture.debugElement.componentViewChildren[0].nativeElement,
'font-size'))
.toEqual('12px');
StringMapWrapper.delete(fixture.debugElement.componentInstance.expr, 'max-width');
fixture.detectChanges();
expect(DOM.getStyle(fixture.debugElement.componentViewChildren[0].nativeElement,
'max-width'))
.toEqual('');
expect(DOM.getStyle(fixture.debugElement.componentViewChildren[0].nativeElement,
'font-size'))
.toEqual('12px');
async.done();
});
}));
it('should co-operate with the style.[styleName]="expr" special-case in the compiler',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = `<div [style.font-size.px]="12" [ng-style]="expr"></div>`;
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
fixture.debugElement.componentInstance.expr = {'max-width': '40px'};
fixture.detectChanges();
expect(DOM.getStyle(fixture.debugElement.componentViewChildren[0].nativeElement,
'max-width'))
.toEqual('40px');
expect(DOM.getStyle(fixture.debugElement.componentViewChildren[0].nativeElement,
'font-size'))
.toEqual('12px');
StringMapWrapper.delete(fixture.debugElement.componentInstance.expr, 'max-width');
expect(DOM.getStyle(fixture.debugElement.componentViewChildren[0].nativeElement,
'font-size'))
.toEqual('12px');
fixture.detectChanges();
expect(DOM.getStyle(fixture.debugElement.componentViewChildren[0].nativeElement,
'max-width'))
.toEqual('');
async.done();
});
}));
})
}
@Component({selector: 'test-cmp'})
@View({directives: [NgStyle]})
class TestComponent {
expr;
}
@@ -1,160 +0,0 @@
import {
AsyncTestCompleter,
TestComponentBuilder,
beforeEach,
ddescribe,
describe,
el,
expect,
iit,
inject,
it,
xit,
} from 'angular2/testing_internal';
import {Component, View} from 'angular2/angular2';
import {NgSwitch, NgSwitchWhen, NgSwitchDefault} from 'angular2/src/core/directives/ng_switch';
export function main() {
describe('switch', () => {
describe('switch value changes', () => {
it('should switch amongst when values',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<div>' +
'<ul [ng-switch]="switchValue">' +
'<template ng-switch-when="a"><li>when a</li></template>' +
'<template ng-switch-when="b"><li>when b</li></template>' +
'</ul></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('');
fixture.debugElement.componentInstance.switchValue = 'a';
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('when a');
fixture.debugElement.componentInstance.switchValue = 'b';
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('when b');
async.done();
});
}));
it('should switch amongst when values with fallback to default',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<div>' +
'<ul [ng-switch]="switchValue">' +
'<li template="ng-switch-when \'a\'">when a</li>' +
'<li template="ng-switch-default">when default</li>' +
'</ul></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('when default');
fixture.debugElement.componentInstance.switchValue = 'a';
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('when a');
fixture.debugElement.componentInstance.switchValue = 'b';
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('when default');
async.done();
});
}));
it('should support multiple whens with the same value',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<div>' +
'<ul [ng-switch]="switchValue">' +
'<template ng-switch-when="a"><li>when a1;</li></template>' +
'<template ng-switch-when="b"><li>when b1;</li></template>' +
'<template ng-switch-when="a"><li>when a2;</li></template>' +
'<template ng-switch-when="b"><li>when b2;</li></template>' +
'<template ng-switch-default><li>when default1;</li></template>' +
'<template ng-switch-default><li>when default2;</li></template>' +
'</ul></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges();
expect(fixture.debugElement.nativeElement)
.toHaveText('when default1;when default2;');
fixture.debugElement.componentInstance.switchValue = 'a';
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('when a1;when a2;');
fixture.debugElement.componentInstance.switchValue = 'b';
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('when b1;when b2;');
async.done();
});
}));
});
describe('when values changes', () => {
it('should switch amongst when values',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<div>' +
'<ul [ng-switch]="switchValue">' +
'<template [ng-switch-when]="when1"><li>when 1;</li></template>' +
'<template [ng-switch-when]="when2"><li>when 2;</li></template>' +
'<template ng-switch-default><li>when default;</li></template>' +
'</ul></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
fixture.debugElement.componentInstance.when1 = 'a';
fixture.debugElement.componentInstance.when2 = 'b';
fixture.debugElement.componentInstance.switchValue = 'a';
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('when 1;');
fixture.debugElement.componentInstance.switchValue = 'b';
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('when 2;');
fixture.debugElement.componentInstance.switchValue = 'c';
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('when default;');
fixture.debugElement.componentInstance.when1 = 'c';
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('when 1;');
fixture.debugElement.componentInstance.when1 = 'd';
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('when default;');
async.done();
});
}));
});
});
}
@Component({selector: 'test-cmp'})
@View({directives: [NgSwitch, NgSwitchWhen, NgSwitchDefault]})
class TestComponent {
switchValue: any;
when1: any;
when2: any;
constructor() {
this.switchValue = null;
this.when1 = null;
this.when2 = null;
}
}
@@ -1,73 +0,0 @@
import {
AsyncTestCompleter,
TestComponentBuilder,
beforeEach,
ddescribe,
describe,
el,
expect,
iit,
inject,
it,
xit,
} from 'angular2/testing_internal';
import {DOM} from 'angular2/src/core/dom/dom_adapter';
import {Component, Directive, View} from 'angular2/core';
import {ElementRef} from 'angular2/src/core/linker/element_ref';
export function main() {
describe('non-bindable', () => {
it('should not interpolate children',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<div>{{text}}<span ng-non-bindable>{{text}}</span></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('foo{{text}}');
async.done();
});
}));
it('should ignore directives on child nodes',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<div ng-non-bindable><span id=child test-dec>{{text}}</span></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges();
// We must use DOM.querySelector instead of fixture.query here
// since the elements inside are not compiled.
var span = DOM.querySelector(fixture.debugElement.nativeElement, '#child');
expect(DOM.hasClass(span, 'compiled')).toBeFalsy();
async.done();
});
}));
it('should trigger directives on the same node',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<div><span id=child ng-non-bindable test-dec>{{text}}</span></div>';
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges();
var span = DOM.querySelector(fixture.debugElement.nativeElement, '#child');
expect(DOM.hasClass(span, 'compiled')).toBeTruthy();
async.done();
});
}));
})
}
@Directive({selector: '[test-dec]'})
class TestDirective {
constructor(el: ElementRef) { DOM.addClass(el.nativeElement, 'compiled'); }
}
@Component({selector: 'test-cmp'})
@View({directives: [TestDirective]})
class TestComponent {
text: string;
constructor() { this.text = 'foo'; }
}
@@ -1,104 +0,0 @@
library angular2.test.directives.observable_list_iterable_diff_spec;
import 'package:angular2/testing_internal.dart';
import 'package:observe/observe.dart' show ObservableList;
import 'package:angular2/core.dart'
show ObservableListDiffFactory, ChangeDetectorRef;
@proxy
class SpyChangeDetectorRef extends SpyObject implements ChangeDetectorRef {
noSuchMethod(m) => super.noSuchMethod(m);
}
main() {
describe('ObservableListDiff', () {
var factory, changeDetectorRef;
beforeEach(() {
factory = const ObservableListDiffFactory();
changeDetectorRef = new SpyChangeDetectorRef();
});
describe("supports", () {
it("should be true for ObservableList", () {
expect(factory.supports(new ObservableList())).toBe(true);
});
it("should be false otherwise", () {
expect(factory.supports([1, 2, 3])).toBe(false);
});
});
it("should return itself when called the first time", () {
final d = factory.create(changeDetectorRef);
final c = new ObservableList.from([1, 2]);
expect(d.diff(c)).toBe(d);
});
it("should return itself when no changes between the calls", () {
final d = factory.create(changeDetectorRef);
final c = new ObservableList.from([1, 2]);
d.diff(c);
expect(d.diff(c)).toBe(null);
});
it("should return the wrapped value once a change has been triggered",
fakeAsync(() {
final d = factory.create(changeDetectorRef);
final c = new ObservableList.from([1, 2]);
d.diff(c);
c.add(3);
// same value, because we have not detected the change yet
expect(d.diff(c)).toBe(null);
// now we detect the change
flushMicrotasks();
expect(d.diff(c)).toBe(d);
}));
it("should request a change detection check upon receiving a change",
fakeAsync(() {
final d = factory.create(changeDetectorRef);
final c = new ObservableList.from([1, 2]);
d.diff(c);
c.add(3);
flushMicrotasks();
expect(changeDetectorRef.spy("markForCheck")).toHaveBeenCalledOnce();
}));
it("should return the wrapped value after changing a collection", () {
final d = factory.create(changeDetectorRef);
final c1 = new ObservableList.from([1, 2]);
final c2 = new ObservableList.from([3, 4]);
expect(d.diff(c1)).toBe(d);
expect(d.diff(c2)).toBe(d);
});
it("should not unbsubscribe from the stream of chagnes after changing a collection",
() {
final d = factory.create(changeDetectorRef);
final c1 = new ObservableList.from([1, 2]);
expect(d.diff(c1)).toBe(d);
final c2 = new ObservableList.from([3, 4]);
expect(d.diff(c2)).toBe(d);
// pushing into the first collection has no effect, and we do not see the change
c1.add(3);
expect(d.diff(c2)).toBe(null);
});
});
}
@@ -1,493 +0,0 @@
import {
ddescribe,
describe,
fakeAsync,
flushMicrotasks,
it,
iit,
xit,
expect,
beforeEach,
afterEach,
el,
AsyncTestCompleter,
inject,
tick
} from 'angular2/testing_internal';
import {SpyNgControl, SpyValueAccessor} from '../spies';
import {
ControlGroup,
Control,
NgControlName,
NgControlGroup,
NgFormModel,
ControlValueAccessor,
Validators,
NgForm,
NgModel,
NgFormControl,
NgControl,
DefaultValueAccessor,
CheckboxControlValueAccessor,
SelectControlValueAccessor,
QueryList,
Validator
} from 'angular2/core';
import {selectValueAccessor, composeValidators} from 'angular2/src/core/forms/directives/shared';
import {TimerWrapper} from 'angular2/src/core/facade/async';
import {PromiseWrapper} from 'angular2/src/core/facade/promise';
import {SimpleChange} from 'angular2/src/core/change_detection';
class DummyControlValueAccessor implements ControlValueAccessor {
writtenValue;
registerOnChange(fn) {}
registerOnTouched(fn) {}
writeValue(obj: any): void { this.writtenValue = obj; }
}
class CustomValidatorDirective implements Validator {
validate(c: Control): {[key: string]: any} { return {"custom": true}; }
}
function asyncValidator(expected, timeout = 0) {
return (c) => {
var completer = PromiseWrapper.completer();
var res = c.value != expected ? {"async": true} : null;
if (timeout == 0) {
completer.resolve(res);
} else {
TimerWrapper.setTimeout(() => { completer.resolve(res); }, timeout);
}
return completer.promise;
};
}
export function main() {
describe("Form Directives", () => {
var defaultAccessor;
beforeEach(() => { defaultAccessor = new DefaultValueAccessor(null, null); });
describe("shared", () => {
describe("selectValueAccessor", () => {
var dir: NgControl;
beforeEach(() => { dir = <any>new SpyNgControl(); });
it("should throw when given an empty array",
() => { expect(() => selectValueAccessor(dir, [])).toThrowError(); });
it("should return the default value accessor when no other provided",
() => { expect(selectValueAccessor(dir, [defaultAccessor])).toEqual(defaultAccessor); });
it("should return checkbox accessor when provided", () => {
var checkboxAccessor = new CheckboxControlValueAccessor(null, null);
expect(selectValueAccessor(dir, [defaultAccessor, checkboxAccessor]))
.toEqual(checkboxAccessor);
});
it("should return select accessor when provided", () => {
var selectAccessor = new SelectControlValueAccessor(null, null, new QueryList<any>());
expect(selectValueAccessor(dir, [defaultAccessor, selectAccessor]))
.toEqual(selectAccessor);
});
it("should throw when more than one build-in accessor is provided", () => {
var checkboxAccessor = new CheckboxControlValueAccessor(null, null);
var selectAccessor = new SelectControlValueAccessor(null, null, new QueryList<any>());
expect(() => selectValueAccessor(dir, [checkboxAccessor, selectAccessor])).toThrowError();
});
it("should return custom accessor when provided", () => {
var customAccessor = new SpyValueAccessor();
var checkboxAccessor = new CheckboxControlValueAccessor(null, null);
expect(selectValueAccessor(dir, [defaultAccessor, customAccessor, checkboxAccessor]))
.toEqual(customAccessor);
});
it("should throw when more than one custom accessor is provided", () => {
var customAccessor: ControlValueAccessor = <any>new SpyValueAccessor();
expect(() => selectValueAccessor(dir, [customAccessor, customAccessor])).toThrowError();
});
});
describe("composeValidators", () => {
it("should compose functions", () => {
var dummy1 = (_) => ({"dummy1": true});
var dummy2 = (_) => ({"dummy2": true});
var v = composeValidators([dummy1, dummy2]);
expect(v(new Control(""))).toEqual({"dummy1": true, "dummy2": true});
});
it("should compose validator directives", () => {
var dummy1 = (_) => ({"dummy1": true});
var v = composeValidators([dummy1, new CustomValidatorDirective()]);
expect(v(new Control(""))).toEqual({"dummy1": true, "custom": true});
});
});
});
describe("NgFormModel", () => {
var form;
var formModel;
var loginControlDir;
beforeEach(() => {
form = new NgFormModel([], []);
formModel = new ControlGroup({
"login": new Control(),
"passwords":
new ControlGroup({"password": new Control(), "passwordConfirm": new Control()})
});
form.form = formModel;
loginControlDir = new NgControlName(form, [Validators.required],
[asyncValidator("expected")], [defaultAccessor]);
loginControlDir.name = "login";
loginControlDir.valueAccessor = new DummyControlValueAccessor();
});
it("should reexport control properties", () => {
expect(form.control).toBe(formModel);
expect(form.value).toBe(formModel.value);
expect(form.valid).toBe(formModel.valid);
expect(form.errors).toBe(formModel.errors);
expect(form.pristine).toBe(formModel.pristine);
expect(form.dirty).toBe(formModel.dirty);
expect(form.touched).toBe(formModel.touched);
expect(form.untouched).toBe(formModel.untouched);
});
describe("addControl", () => {
it("should throw when no control found", () => {
var dir = new NgControlName(form, null, null, [defaultAccessor]);
dir.name = "invalidName";
expect(() => form.addControl(dir))
.toThrowError(new RegExp("Cannot find control 'invalidName'"));
});
it("should throw when no value accessor", () => {
var dir = new NgControlName(form, null, null, null);
dir.name = "login";
expect(() => form.addControl(dir))
.toThrowError(new RegExp("No value accessor for 'login'"));
});
it("should set up validators", fakeAsync(() => {
form.addControl(loginControlDir);
// sync validators are set
expect(formModel.hasError("required", ["login"])).toBe(true);
expect(formModel.hasError("async", ["login"])).toBe(false);
formModel.find(["login"]).updateValue("invalid value");
// sync validator passes, running async validators
expect(formModel.pending).toBe(true);
tick();
expect(formModel.hasError("required", ["login"])).toBe(false);
expect(formModel.hasError("async", ["login"])).toBe(true);
}));
it("should write value to the DOM", () => {
formModel.find(["login"]).updateValue("initValue");
form.addControl(loginControlDir);
expect((<any>loginControlDir.valueAccessor).writtenValue).toEqual("initValue");
});
it("should add the directive to the list of directives included in the form", () => {
form.addControl(loginControlDir);
expect(form.directives).toEqual([loginControlDir]);
});
});
describe("addControlGroup", () => {
var matchingPasswordsValidator = (g) => {
if (g.controls["password"].value != g.controls["passwordConfirm"].value) {
return {"differentPasswords": true};
} else {
return null;
}
};
it("should set up validator", fakeAsync(() => {
var group = new NgControlGroup(form, [matchingPasswordsValidator],
[asyncValidator('expected')]);
group.name = "passwords";
form.addControlGroup(group);
formModel.find(["passwords", "password"]).updateValue("somePassword");
formModel.find(["passwords", "passwordConfirm"]).updateValue("someOtherPassword");
// sync validators are set
expect(formModel.hasError("differentPasswords", ["passwords"])).toEqual(true);
formModel.find(["passwords", "passwordConfirm"]).updateValue("somePassword");
// sync validators pass, running async validators
expect(formModel.pending).toBe(true);
tick();
expect(formModel.hasError("async", ["passwords"])).toBe(true);
}));
});
describe("removeControl", () => {
it("should remove the directive to the list of directives included in the form", () => {
form.addControl(loginControlDir);
form.removeControl(loginControlDir);
expect(form.directives).toEqual([]);
});
});
describe("onChanges", () => {
it("should update dom values of all the directives", () => {
form.addControl(loginControlDir);
formModel.find(["login"]).updateValue("new value");
form.onChanges({});
expect((<any>loginControlDir.valueAccessor).writtenValue).toEqual("new value");
});
it("should set up a sync validator", () => {
var formValidator = (c) => ({"custom": true});
var f = new NgFormModel([formValidator], []);
f.form = formModel;
f.onChanges({"form": formModel});
expect(formModel.errors).toEqual({"custom": true});
});
it("should set up an async validator", fakeAsync(() => {
var f = new NgFormModel([], [asyncValidator("expected")]);
f.form = formModel;
f.onChanges({"form": formModel});
tick();
expect(formModel.errors).toEqual({"async": true});
}));
});
});
describe("NgForm", () => {
var form;
var formModel;
var loginControlDir;
var personControlGroupDir;
beforeEach(() => {
form = new NgForm([], []);
formModel = form.form;
personControlGroupDir = new NgControlGroup(form, [], []);
personControlGroupDir.name = "person";
loginControlDir = new NgControlName(personControlGroupDir, null, null, [defaultAccessor]);
loginControlDir.name = "login";
loginControlDir.valueAccessor = new DummyControlValueAccessor();
});
it("should reexport control properties", () => {
expect(form.control).toBe(formModel);
expect(form.value).toBe(formModel.value);
expect(form.valid).toBe(formModel.valid);
expect(form.errors).toBe(formModel.errors);
expect(form.pristine).toBe(formModel.pristine);
expect(form.dirty).toBe(formModel.dirty);
expect(form.touched).toBe(formModel.touched);
expect(form.untouched).toBe(formModel.untouched);
});
describe("addControl & addControlGroup", () => {
it("should create a control with the given name", fakeAsync(() => {
form.addControlGroup(personControlGroupDir);
form.addControl(loginControlDir);
flushMicrotasks();
expect(formModel.find(["person", "login"])).not.toBeNull;
}));
// should update the form's value and validity
});
describe("removeControl & removeControlGroup", () => {
it("should remove control", fakeAsync(() => {
form.addControlGroup(personControlGroupDir);
form.addControl(loginControlDir);
form.removeControlGroup(personControlGroupDir);
form.removeControl(loginControlDir);
flushMicrotasks();
expect(formModel.find(["person"])).toBeNull();
expect(formModel.find(["person", "login"])).toBeNull();
}));
// should update the form's value and validity
});
it("should set up sync validator", fakeAsync(() => {
var formValidator = (c) => ({"custom": true});
var f = new NgForm([formValidator], []);
tick();
expect(f.form.errors).toEqual({"custom": true});
}));
it("should set up async validator", fakeAsync(() => {
var f = new NgForm([], [asyncValidator("expected")]);
tick();
expect(f.form.errors).toEqual({"async": true});
}));
});
describe("NgControlGroup", () => {
var formModel;
var controlGroupDir;
beforeEach(() => {
formModel = new ControlGroup({"login": new Control(null)});
var parent = new NgFormModel([], []);
parent.form = new ControlGroup({"group": formModel});
controlGroupDir = new NgControlGroup(parent, [], []);
controlGroupDir.name = "group";
});
it("should reexport control properties", () => {
expect(controlGroupDir.control).toBe(formModel);
expect(controlGroupDir.value).toBe(formModel.value);
expect(controlGroupDir.valid).toBe(formModel.valid);
expect(controlGroupDir.errors).toBe(formModel.errors);
expect(controlGroupDir.pristine).toBe(formModel.pristine);
expect(controlGroupDir.dirty).toBe(formModel.dirty);
expect(controlGroupDir.touched).toBe(formModel.touched);
expect(controlGroupDir.untouched).toBe(formModel.untouched);
});
});
describe("NgFormControl", () => {
var controlDir;
var control;
var checkProperties = function(control) {
expect(controlDir.control).toBe(control);
expect(controlDir.value).toBe(control.value);
expect(controlDir.valid).toBe(control.valid);
expect(controlDir.errors).toBe(control.errors);
expect(controlDir.pristine).toBe(control.pristine);
expect(controlDir.dirty).toBe(control.dirty);
expect(controlDir.touched).toBe(control.touched);
expect(controlDir.untouched).toBe(control.untouched);
};
beforeEach(() => {
controlDir = new NgFormControl([Validators.required], [], [defaultAccessor]);
controlDir.valueAccessor = new DummyControlValueAccessor();
control = new Control(null);
controlDir.form = control;
});
it("should reexport control properties", () => { checkProperties(control); });
it("should reexport new control properties", () => {
var newControl = new Control(null);
controlDir.form = newControl;
controlDir.onChanges({"form": new SimpleChange(control, newControl)});
checkProperties(newControl);
});
it("should set up validator", () => {
expect(control.valid).toBe(true);
// this will add the required validator and recalculate the validity
controlDir.onChanges({"form": new SimpleChange(null, control)});
expect(control.valid).toBe(false);
});
});
describe("NgModel", () => {
var ngModel;
beforeEach(() => {
ngModel =
new NgModel([Validators.required], [asyncValidator("expected")], [defaultAccessor]);
ngModel.valueAccessor = new DummyControlValueAccessor();
});
it("should reexport control properties", () => {
var control = ngModel.control;
expect(ngModel.control).toBe(control);
expect(ngModel.value).toBe(control.value);
expect(ngModel.valid).toBe(control.valid);
expect(ngModel.errors).toBe(control.errors);
expect(ngModel.pristine).toBe(control.pristine);
expect(ngModel.dirty).toBe(control.dirty);
expect(ngModel.touched).toBe(control.touched);
expect(ngModel.untouched).toBe(control.untouched);
});
it("should set up validator", fakeAsync(() => {
// this will add the required validator and recalculate the validity
ngModel.onChanges({});
tick();
expect(ngModel.control.errors).toEqual({"required": true});
ngModel.control.updateValue("someValue");
tick();
expect(ngModel.control.errors).toEqual({"async": true});
}));
});
describe("NgControlName", () => {
var formModel;
var controlNameDir;
beforeEach(() => {
formModel = new Control("name");
var parent = new NgFormModel([], []);
parent.form = new ControlGroup({"name": formModel});
controlNameDir = new NgControlName(parent, [], [], [defaultAccessor]);
controlNameDir.name = "name";
});
it("should reexport control properties", () => {
expect(controlNameDir.control).toBe(formModel);
expect(controlNameDir.value).toBe(formModel.value);
expect(controlNameDir.valid).toBe(formModel.valid);
expect(controlNameDir.errors).toBe(formModel.errors);
expect(controlNameDir.pristine).toBe(formModel.pristine);
expect(controlNameDir.dirty).toBe(formModel.dirty);
expect(controlNameDir.touched).toBe(formModel.touched);
expect(controlNameDir.untouched).toBe(formModel.untouched);
});
});
});
}
@@ -1,72 +0,0 @@
import {
ddescribe,
describe,
it,
iit,
xit,
expect,
beforeEach,
afterEach,
el
} from 'angular2/testing_internal';
import {Control, FormBuilder} from 'angular2/core';
import {PromiseWrapper} from 'angular2/src/core/facade/promise';
export function main() {
function syncValidator(_) { return null; }
function asyncValidator(_) { return PromiseWrapper.resolve(null); }
describe("Form Builder", () => {
var b;
beforeEach(() => { b = new FormBuilder(); });
it("should create controls from a value", () => {
var g = b.group({"login": "some value"});
expect(g.controls["login"].value).toEqual("some value");
});
it("should create controls from an array", () => {
var g = b.group(
{"login": ["some value"], "password": ["some value", syncValidator, asyncValidator]});
expect(g.controls["login"].value).toEqual("some value");
expect(g.controls["password"].value).toEqual("some value");
expect(g.controls["password"].validator).toEqual(syncValidator);
expect(g.controls["password"].asyncValidator).toEqual(asyncValidator);
});
it("should use controls", () => {
var g = b.group({"login": b.control("some value", syncValidator, asyncValidator)});
expect(g.controls["login"].value).toEqual("some value");
expect(g.controls["login"].validator).toBe(syncValidator);
expect(g.controls["login"].asyncValidator).toBe(asyncValidator);
});
it("should create groups with optional controls", () => {
var g = b.group({"login": "some value"}, {"optionals": {"login": false}});
expect(g.contains("login")).toEqual(false);
});
it("should create groups with a custom validator", () => {
var g = b.group({"login": "some value"},
{"validator": syncValidator, "asyncValidator": asyncValidator});
expect(g.validator).toBe(syncValidator);
expect(g.asyncValidator).toBe(asyncValidator);
});
it("should create control arrays", () => {
var c = b.control("three");
var a = b.array(["one", ["two", syncValidator], c, b.array(['four'])], syncValidator,
asyncValidator);
expect(a.value).toEqual(['one', 'two', 'three', ['four']]);
expect(a.validator).toBe(syncValidator);
expect(a.asyncValidator).toBe(asyncValidator);
});
});
}
File diff suppressed because it is too large Load Diff
@@ -1,823 +0,0 @@
import {
ddescribe,
describe,
it,
iit,
xit,
expect,
beforeEach,
afterEach,
el,
AsyncTestCompleter,
fakeAsync,
tick,
inject
} from 'angular2/testing_internal';
import {ControlGroup, Control, ControlArray, Validators} from 'angular2/core';
import {isPresent, CONST_EXPR} from 'angular2/src/core/facade/lang';
import {PromiseWrapper} from 'angular2/src/core/facade/promise';
import {TimerWrapper, ObservableWrapper} from 'angular2/src/core/facade/async';
import {IS_DART} from 'angular2/src/core/facade/lang';
export function main() {
function asyncValidator(expected, timeouts = CONST_EXPR({})) {
return (c) => {
var completer = PromiseWrapper.completer();
var t = isPresent(timeouts[c.value]) ? timeouts[c.value] : 0;
var res = c.value != expected ? {"async": true} : null;
if (t == 0) {
completer.resolve(res);
} else {
TimerWrapper.setTimeout(() => { completer.resolve(res); }, t);
}
return completer.promise;
};
}
describe("Form Model", () => {
describe("Control", () => {
it("should default the value to null", () => {
var c = new Control();
expect(c.value).toBe(null);
});
describe("validator", () => {
it("should run validator with the initial value", () => {
var c = new Control("value", Validators.required);
expect(c.valid).toEqual(true);
});
it("should rerun the validator when the value changes", () => {
var c = new Control("value", Validators.required);
c.updateValue(null);
expect(c.valid).toEqual(false);
});
it("should return errors", () => {
var c = new Control(null, Validators.required);
expect(c.errors).toEqual({"required": true});
});
});
describe("asyncValidator", () => {
it("should run validator with the initial value", fakeAsync(() => {
var c = new Control("value", null, asyncValidator("expected"));
tick();
expect(c.valid).toEqual(false);
expect(c.errors).toEqual({"async": true});
}));
it("should rerun the validator when the value changes", fakeAsync(() => {
var c = new Control("value", null, asyncValidator("expected"));
c.updateValue("expected");
tick();
expect(c.valid).toEqual(true);
}));
it("should run the async validator only when the sync validator passes", fakeAsync(() => {
var c = new Control("", Validators.required, asyncValidator("expected"));
tick();
expect(c.errors).toEqual({"required": true});
c.updateValue("some value");
tick();
expect(c.errors).toEqual({"async": true});
}));
it("should mark the control as pending while running the async validation",
fakeAsync(() => {
var c = new Control("", null, asyncValidator("expected"));
expect(c.pending).toEqual(true);
tick();
expect(c.pending).toEqual(false);
}));
it("should only use the latest async validation run", fakeAsync(() => {
var c =
new Control("", null, asyncValidator("expected", {"long": 200, "expected": 100}));
c.updateValue("long");
c.updateValue("expected");
tick(300);
expect(c.valid).toEqual(true);
}));
});
describe("dirty", () => {
it("should be false after creating a control", () => {
var c = new Control("value");
expect(c.dirty).toEqual(false);
});
it("should be true after changing the value of the control", () => {
var c = new Control("value");
c.markAsDirty();
expect(c.dirty).toEqual(true);
});
});
describe("updateValue", () => {
var g, c;
beforeEach(() => {
c = new Control("oldValue");
g = new ControlGroup({"one": c});
});
it("should update the value of the control", () => {
c.updateValue("newValue");
expect(c.value).toEqual("newValue");
});
it("should invoke onChanges if it is present", () => {
var onChanges;
c.registerOnChange((v) => onChanges = ["invoked", v]);
c.updateValue("newValue");
expect(onChanges).toEqual(["invoked", "newValue"]);
});
it("should not invoke on change when explicitly specified", () => {
var onChange = null;
c.registerOnChange((v) => onChange = ["invoked", v]);
c.updateValue("newValue", {emitModelToViewChange: false});
expect(onChange).toBeNull();
});
it("should update the parent", () => {
c.updateValue("newValue");
expect(g.value).toEqual({"one": "newValue"});
});
it("should not update the parent when explicitly specified", () => {
c.updateValue("newValue", {onlySelf: true});
expect(g.value).toEqual({"one": "oldValue"});
});
it("should fire an event", fakeAsync(() => {
ObservableWrapper.subscribe(c.valueChanges,
(value) => { expect(value).toEqual("newValue"); });
c.updateValue("newValue");
tick();
}));
it("should not fire an event when explicitly specified", fakeAsync(() => {
ObservableWrapper.subscribe(c.valueChanges, (value) => { throw "Should not happen"; });
c.updateValue("newValue", {emitEvent: false});
tick();
}));
});
describe("valueChanges", () => {
var c;
beforeEach(() => { c = new Control("old", Validators.required); });
it("should fire an event after the value has been updated",
inject([AsyncTestCompleter], (async) => {
ObservableWrapper.subscribe(c.valueChanges, (value) => {
expect(c.value).toEqual('new');
expect(value).toEqual('new');
async.done();
});
c.updateValue("new");
}));
// TODO: remove the if statement after making observable delivery sync
if (!IS_DART) {
it("should update set errors and status before emitting an event",
inject([AsyncTestCompleter], (async) => {
c.valueChanges.subscribe(value => {
expect(c.valid).toEqual(false);
expect(c.errors).toEqual({"required": true});
async.done();
});
c.updateValue("");
}));
}
it("should return a cold observable", inject([AsyncTestCompleter], (async) => {
c.updateValue("will be ignored");
ObservableWrapper.subscribe(c.valueChanges, (value) => {
expect(value).toEqual('new');
async.done();
});
c.updateValue("new");
}));
});
describe("setErrors", () => {
it("should set errors on a control", () => {
var c = new Control("someValue");
c.setErrors({"someError": true});
expect(c.valid).toEqual(false);
expect(c.errors).toEqual({"someError": true});
});
it("should reset the errors and validity when the value changes", () => {
var c = new Control("someValue", Validators.required);
c.setErrors({"someError": true});
c.updateValue("");
expect(c.errors).toEqual({"required": true});
});
it("should update the parent group's validity", () => {
var c = new Control("someValue");
var g = new ControlGroup({"one": c});
expect(g.valid).toEqual(true);
c.setErrors({"someError": true});
expect(g.controlsErrors).toEqual({"one": {"someError": true}});
expect(g.valid).toEqual(false);
});
it("should not reset parent's errors", () => {
var c = new Control("someValue");
var g = new ControlGroup({"one": c});
g.setErrors({"someGroupError": true});
c.setErrors({"someError": true});
expect(g.errors).toEqual({"someGroupError": true});
});
it("should reset errors when updating a value", () => {
var c = new Control("oldValue");
var g = new ControlGroup({"one": c});
g.setErrors({"someGroupError": true});
c.setErrors({"someError": true});
c.updateValue("newValue");
expect(c.errors).toEqual(null);
expect(g.errors).toEqual(null);
});
});
});
describe("ControlGroup", () => {
describe("value", () => {
it("should be the reduced value of the child controls", () => {
var g = new ControlGroup({"one": new Control("111"), "two": new Control("222")});
expect(g.value).toEqual({"one": "111", "two": "222"});
});
it("should be empty when there are no child controls", () => {
var g = new ControlGroup({});
expect(g.value).toEqual({});
});
it("should support nested groups", () => {
var g = new ControlGroup(
{"one": new Control("111"), "nested": new ControlGroup({"two": new Control("222")})});
expect(g.value).toEqual({"one": "111", "nested": {"two": "222"}});
(<Control>(g.controls["nested"].find("two"))).updateValue("333");
expect(g.value).toEqual({"one": "111", "nested": {"two": "333"}});
});
});
describe("controlsErrors", () => {
it("should be null when no errors", () => {
var g = new ControlGroup({"one": new Control('value', Validators.required)});
expect(g.valid).toEqual(true);
expect(g.controlsErrors).toEqual(null);
});
it("should collect errors from the child controls", () => {
var one = new Control(null, Validators.required);
var g = new ControlGroup({"one": one});
expect(g.valid).toEqual(false);
expect(g.controlsErrors).toEqual({"one": {"required": true}});
});
it("should not include controls that have no errors", () => {
var one = new Control(null, Validators.required);
var two = new Control("two");
var g = new ControlGroup({"one": one, "two": two});
expect(g.controlsErrors).toEqual({"one": {"required": true}});
});
it("should run the validator with the value changes", () => {
var c = new Control(null, Validators.required);
var g = new ControlGroup({"one": c});
c.updateValue("some value");
expect(g.valid).toEqual(true);
expect(g.controlsErrors).toEqual(null);
});
});
describe("errors", () => {
it("should run the validator when the value changes", () => {
var simpleValidator = (c) =>
c.controls["one"].value != "correct" ? {"broken": true} : null;
var c = new Control(null);
var g = new ControlGroup({"one": c}, null, simpleValidator);
c.updateValue("correct");
expect(g.valid).toEqual(true);
expect(g.errors).toEqual(null);
c.updateValue("incorrect");
expect(g.valid).toEqual(false);
expect(g.errors).toEqual({"broken": true});
});
});
describe("dirty", () => {
var c, g;
beforeEach(() => {
c = new Control('value');
g = new ControlGroup({"one": c});
});
it("should be false after creating a control", () => { expect(g.dirty).toEqual(false); });
it("should be false after changing the value of the control", () => {
c.markAsDirty();
expect(g.dirty).toEqual(true);
});
});
describe("optional components", () => {
describe("contains", () => {
var group;
beforeEach(() => {
group = new ControlGroup(
{
"required": new Control("requiredValue"),
"optional": new Control("optionalValue")
},
{"optional": false});
});
// rename contains into has
it("should return false when the component is not included",
() => { expect(group.contains("optional")).toEqual(false); })
it("should return false when there is no component with the given name",
() => { expect(group.contains("something else")).toEqual(false); });
it("should return true when the component is included", () => {
expect(group.contains("required")).toEqual(true);
group.include("optional");
expect(group.contains("optional")).toEqual(true);
});
});
it("should not include an inactive component into the group value", () => {
var group = new ControlGroup(
{"required": new Control("requiredValue"), "optional": new Control("optionalValue")},
{"optional": false});
expect(group.value).toEqual({"required": "requiredValue"});
group.include("optional");
expect(group.value).toEqual({"required": "requiredValue", "optional": "optionalValue"});
});
it("should not run Validators on an inactive component", () => {
var group = new ControlGroup(
{
"required": new Control("requiredValue", Validators.required),
"optional": new Control("", Validators.required)
},
{"optional": false});
expect(group.valid).toEqual(true);
group.include("optional");
expect(group.valid).toEqual(false);
});
});
describe("valueChanges", () => {
var g, c1, c2;
beforeEach(() => {
c1 = new Control("old1");
c2 = new Control("old2");
g = new ControlGroup({"one": c1, "two": c2}, {"two": true});
});
it("should fire an event after the value has been updated",
inject([AsyncTestCompleter], (async) => {
ObservableWrapper.subscribe(g.valueChanges, (value) => {
expect(g.value).toEqual({'one': 'new1', 'two': 'old2'});
expect(value).toEqual({'one': 'new1', 'two': 'old2'});
async.done();
});
c1.updateValue("new1");
}));
it("should fire an event after the control's observable fired an event",
inject([AsyncTestCompleter], (async) => {
var controlCallbackIsCalled = false;
ObservableWrapper.subscribe(c1.valueChanges,
(value) => { controlCallbackIsCalled = true; });
ObservableWrapper.subscribe(g.valueChanges, (value) => {
expect(controlCallbackIsCalled).toBe(true);
async.done();
});
c1.updateValue("new1");
}));
it("should fire an event when a control is excluded",
inject([AsyncTestCompleter], (async) => {
ObservableWrapper.subscribe(g.valueChanges, (value) => {
expect(value).toEqual({'one': 'old1'});
async.done();
});
g.exclude("two");
}));
it("should fire an event when a control is included",
inject([AsyncTestCompleter], (async) => {
g.exclude("two");
ObservableWrapper.subscribe(g.valueChanges, (value) => {
expect(value).toEqual({'one': 'old1', 'two': 'old2'});
async.done();
});
g.include("two");
}));
it("should fire an event every time a control is updated",
inject([AsyncTestCompleter], (async) => {
var loggedValues = [];
ObservableWrapper.subscribe(g.valueChanges, (value) => {
loggedValues.push(value);
if (loggedValues.length == 2) {
expect(loggedValues)
.toEqual([{"one": "new1", "two": "old2"}, {"one": "new1", "two": "new2"}]);
async.done();
}
});
c1.updateValue("new1");
c2.updateValue("new2");
}));
xit("should not fire an event when an excluded control is updated",
inject([AsyncTestCompleter], (async) => {
// hard to test without hacking zones
}));
});
describe("getError", () => {
it("should return the error when it is present", () => {
var c = new Control("", Validators.required);
var g = new ControlGroup({"one": c});
expect(c.getError("required")).toEqual(true);
expect(g.getError("required", ["one"])).toEqual(true);
});
it("should return null otherwise", () => {
var c = new Control("not empty", Validators.required);
var g = new ControlGroup({"one": c});
expect(c.getError("invalid")).toEqual(null);
expect(g.getError("required", ["one"])).toEqual(null);
expect(g.getError("required", ["invalid"])).toEqual(null);
});
});
describe("asyncValidator", () => {
it("should run the async validator", fakeAsync(() => {
var c = new Control("value");
var g = new ControlGroup({"one": c}, null, null, asyncValidator("expected"));
expect(g.pending).toEqual(true);
tick(1);
expect(g.errors).toEqual({"async": true});
expect(g.pending).toEqual(false);
}));
it("should set the parent group's status to pending", fakeAsync(() => {
var c = new Control("value", null, asyncValidator("expected"));
var g = new ControlGroup({"one": c});
expect(g.pending).toEqual(true);
tick(1);
expect(g.pending).toEqual(false);
}));
it("should run the parent group's async validator when children are pending",
fakeAsync(() => {
var c = new Control("value", null, asyncValidator("expected"));
var g = new ControlGroup({"one": c}, null, null, asyncValidator("expected"));
tick(1);
expect(g.errors).toEqual({"async": true});
expect(g.find(["one"]).errors).toEqual({"async": true});
}));
})
});
describe("ControlArray", () => {
describe("adding/removing", () => {
var a: ControlArray;
var c1, c2, c3;
beforeEach(() => {
a = new ControlArray([]);
c1 = new Control(1);
c2 = new Control(2);
c3 = new Control(3);
});
it("should support pushing", () => {
a.push(c1);
expect(a.length).toEqual(1);
expect(a.controls).toEqual([c1]);
});
it("should support removing", () => {
a.push(c1);
a.push(c2);
a.push(c3);
a.removeAt(1);
expect(a.controls).toEqual([c1, c3]);
});
it("should support inserting", () => {
a.push(c1);
a.push(c3);
a.insert(1, c2);
expect(a.controls).toEqual([c1, c2, c3]);
});
});
describe("value", () => {
it("should be the reduced value of the child controls", () => {
var a = new ControlArray([new Control(1), new Control(2)]);
expect(a.value).toEqual([1, 2]);
});
it("should be an empty array when there are no child controls", () => {
var a = new ControlArray([]);
expect(a.value).toEqual([]);
});
});
describe("controlsErrors", () => {
it("should return null when no errors", () => {
var a = new ControlArray(
[new Control(1, Validators.required), new Control(2, Validators.required)]);
expect(a.valid).toBe(true);
expect(a.controlsErrors).toBe(null);
});
it("should collect errors from the child controls", () => {
var a = new ControlArray([
new Control(1, Validators.required),
new Control(null, Validators.required),
new Control(2, Validators.required)
]);
expect(a.valid).toBe(false);
expect(a.controlsErrors).toEqual([null, {"required": true}, null]);
});
it("should run the validator when the value changes", () => {
var a = new ControlArray([]);
var c = new Control(null, Validators.required);
a.push(c);
expect(a.valid).toBe(false);
c.updateValue("some value");
expect(a.valid).toBe(true);
expect(a.controlsErrors).toBe(null);
});
});
describe("errors", () => {
it("should run the validator when the value changes", () => {
var simpleValidator = (c) => c.controls[0].value != "correct" ? {"broken": true} : null;
var c = new Control(null);
var g = new ControlArray([c], simpleValidator);
c.updateValue("correct");
expect(g.valid).toEqual(true);
expect(g.errors).toEqual(null);
c.updateValue("incorrect");
expect(g.valid).toEqual(false);
expect(g.errors).toEqual({"broken": true});
});
});
describe("dirty", () => {
var c: Control;
var a: ControlArray;
beforeEach(() => {
c = new Control('value');
a = new ControlArray([c]);
});
it("should be false after creating a control", () => { expect(a.dirty).toEqual(false); });
it("should be false after changing the value of the control", () => {
c.markAsDirty();
expect(a.dirty).toEqual(true);
});
});
describe("pending", () => {
var c: Control;
var a: ControlArray;
beforeEach(() => {
c = new Control('value');
a = new ControlArray([c]);
});
it("should be false after creating a control", () => {
expect(c.pending).toEqual(false);
expect(a.pending).toEqual(false);
});
it("should be true after changing the value of the control", () => {
c.markAsPending();
expect(c.pending).toEqual(true);
expect(a.pending).toEqual(true);
});
it("should not update the parent when onlySelf = true", () => {
c.markAsPending({onlySelf: true});
expect(c.pending).toEqual(true);
expect(a.pending).toEqual(false);
});
});
describe("valueChanges", () => {
var a: ControlArray;
var c1, c2;
beforeEach(() => {
c1 = new Control("old1");
c2 = new Control("old2");
a = new ControlArray([c1, c2]);
});
it("should fire an event after the value has been updated",
inject([AsyncTestCompleter], (async) => {
ObservableWrapper.subscribe(a.valueChanges, (value) => {
expect(a.value).toEqual(['new1', 'old2']);
expect(value).toEqual(['new1', 'old2']);
async.done();
});
c1.updateValue("new1");
}));
it("should fire an event after the control's observable fired an event",
inject([AsyncTestCompleter], (async) => {
var controlCallbackIsCalled = false;
ObservableWrapper.subscribe(c1.valueChanges,
(value) => { controlCallbackIsCalled = true; });
ObservableWrapper.subscribe(a.valueChanges, (value) => {
expect(controlCallbackIsCalled).toBe(true);
async.done();
});
c1.updateValue("new1");
}));
it("should fire an event when a control is removed",
inject([AsyncTestCompleter], (async) => {
ObservableWrapper.subscribe(a.valueChanges, (value) => {
expect(value).toEqual(['old1']);
async.done();
});
a.removeAt(1);
}));
it("should fire an event when a control is added", inject([AsyncTestCompleter], (async) => {
a.removeAt(1);
ObservableWrapper.subscribe(a.valueChanges, (value) => {
expect(value).toEqual(['old1', 'old2']);
async.done();
});
a.push(c2);
}));
});
describe("find", () => {
it("should return null when path is null", () => {
var g = new ControlGroup({});
expect(g.find(null)).toEqual(null);
});
it("should return null when path is empty", () => {
var g = new ControlGroup({});
expect(g.find([])).toEqual(null);
});
it("should return null when path is invalid", () => {
var g = new ControlGroup({});
expect(g.find(["one", "two"])).toEqual(null);
});
it("should return a child of a control group", () => {
var g = new ControlGroup(
{"one": new Control("111"), "nested": new ControlGroup({"two": new Control("222")})});
expect(g.find(["nested", "two"]).value).toEqual("222");
expect(g.find(["one"]).value).toEqual("111");
expect(g.find("nested/two").value).toEqual("222");
expect(g.find("one").value).toEqual("111");
});
it("should return an element of an array", () => {
var g = new ControlGroup({"array": new ControlArray([new Control("111")])});
expect(g.find(["array", 0]).value).toEqual("111");
});
});
describe("asyncValidator", () => {
it("should run the async validator", fakeAsync(() => {
var c = new Control("value");
var g = new ControlArray([c], null, asyncValidator("expected"));
expect(g.pending).toEqual(true);
tick(1);
expect(g.errors).toEqual({"async": true});
expect(g.pending).toEqual(false);
}));
})
});
});
}
@@ -1,147 +0,0 @@
import {
ddescribe,
describe,
it,
iit,
xit,
expect,
beforeEach,
afterEach,
fakeAsync,
tick,
el
} from 'angular2/testing_internal';
import {ControlGroup, Control, Validators, AbstractControl, ControlArray} from 'angular2/core';
import {PromiseWrapper} from 'angular2/src/core/facade/promise';
import {TimerWrapper} from 'angular2/src/core/facade/async';
import {CONST_EXPR} from 'angular2/src/core/facade/lang';
export function main() {
function validator(key: string, error: any) {
return function(c: AbstractControl) {
var r = {};
r[key] = error;
return r;
}
}
describe("Validators", () => {
describe("required", () => {
it("should error on an empty string",
() => { expect(Validators.required(new Control(""))).toEqual({"required": true}); });
it("should error on null",
() => { expect(Validators.required(new Control(null))).toEqual({"required": true}); });
it("should not error on a non-empty string",
() => { expect(Validators.required(new Control("not empty"))).toEqual(null); });
});
describe("minLength", () => {
it("should not error on an empty string",
() => { expect(Validators.minLength(2)(new Control(""))).toEqual(null); });
it("should not error on null",
() => { expect(Validators.minLength(2)(new Control(null))).toEqual(null); });
it("should not error on valid strings",
() => { expect(Validators.minLength(2)(new Control("aa"))).toEqual(null); });
it("should error on short strings", () => {
expect(Validators.minLength(2)(new Control("a")))
.toEqual({"minlength": {"requiredLength": 2, "actualLength": 1}});
});
});
describe("maxLength", () => {
it("should not error on an empty string",
() => { expect(Validators.maxLength(2)(new Control(""))).toEqual(null); });
it("should not error on null",
() => { expect(Validators.maxLength(2)(new Control(null))).toEqual(null); });
it("should not error on valid strings",
() => { expect(Validators.maxLength(2)(new Control("aa"))).toEqual(null); });
it("should error on short strings", () => {
expect(Validators.maxLength(2)(new Control("aaa")))
.toEqual({"maxlength": {"requiredLength": 2, "actualLength": 3}});
});
});
describe("compose", () => {
it("should return null when given null",
() => { expect(Validators.compose(null)).toBe(null); });
it("should collect errors from all the validators", () => {
var c = Validators.compose([validator("a", true), validator("b", true)]);
expect(c(new Control(""))).toEqual({"a": true, "b": true});
});
it("should run validators left to right", () => {
var c = Validators.compose([validator("a", 1), validator("a", 2)]);
expect(c(new Control(""))).toEqual({"a": 2});
});
it("should return null when no errors", () => {
var c = Validators.compose([Validators.nullValidator, Validators.nullValidator]);
expect(c(new Control(""))).toEqual(null);
});
it("should ignore nulls", () => {
var c = Validators.compose([null, Validators.required]);
expect(c(new Control(""))).toEqual({"required": true});
});
});
describe("composeAsync", () => {
function asyncValidator(expected, response, timeout = 0) {
return (c) => {
var completer = PromiseWrapper.completer();
var res = c.value != expected ? response : null;
TimerWrapper.setTimeout(() => { completer.resolve(res); }, timeout);
return completer.promise;
};
}
it("should return null when given null",
() => { expect(Validators.composeAsync(null)).toEqual(null); });
it("should collect errors from all the validators", fakeAsync(() => {
var c = Validators.composeAsync([
asyncValidator("expected", {"one": true}),
asyncValidator("expected", {"two": true})
]);
var value = null;
c(new Control("invalid")).then(v => value = v);
tick(1);
expect(value).toEqual({"one": true, "two": true});
}));
it("should return null when no errors", fakeAsync(() => {
var c = Validators.composeAsync([asyncValidator("expected", {"one": true})]);
var value = null;
c(new Control("expected")).then(v => value = v);
tick(1);
expect(value).toEqual(null);
}));
it("should ignore nulls", fakeAsync(() => {
var c = Validators.composeAsync([asyncValidator("expected", {"one": true}), null]);
var value = null;
c(new Control("invalid")).then(v => value = v);
tick(1);
expect(value).toEqual({"one": true});
}));
});
});
}
@@ -1,220 +0,0 @@
import {
ddescribe,
describe,
it,
iit,
xit,
expect,
beforeEach,
afterEach,
AsyncTestCompleter,
inject,
SpyObject,
browserDetection
} from 'angular2/testing_internal';
import {SpyChangeDetectorRef} from './spies';
import {isBlank} from 'angular2/src/core/facade/lang';
import {AsyncPipe, WrappedValue} from 'angular2/core';
import {
EventEmitter,
ObservableWrapper,
PromiseWrapper,
TimerWrapper
} from 'angular2/src/core/facade/async';
import {DOM} from 'angular2/src/core/dom/dom_adapter';
export function main() {
describe("AsyncPipe", () => {
describe('Observable', () => {
var emitter;
var pipe;
var ref;
var message = new Object();
beforeEach(() => {
emitter = new EventEmitter();
ref = new SpyChangeDetectorRef();
pipe = new AsyncPipe(ref);
});
describe("transform", () => {
it("should return null when subscribing to an observable",
() => { expect(pipe.transform(emitter)).toBe(null); });
it("should return the latest available value wrapped",
inject([AsyncTestCompleter], (async) => {
pipe.transform(emitter);
ObservableWrapper.callNext(emitter, message);
TimerWrapper.setTimeout(() => {
expect(pipe.transform(emitter)).toEqual(new WrappedValue(message));
async.done();
}, 0)
}));
it("should return same value when nothing has changed since the last call",
inject([AsyncTestCompleter], (async) => {
pipe.transform(emitter);
ObservableWrapper.callNext(emitter, message);
TimerWrapper.setTimeout(() => {
pipe.transform(emitter);
expect(pipe.transform(emitter)).toBe(message);
async.done();
}, 0)
}));
it("should dispose of the existing subscription when subscribing to a new observable",
inject([AsyncTestCompleter], (async) => {
pipe.transform(emitter);
var newEmitter = new EventEmitter();
expect(pipe.transform(newEmitter)).toBe(null);
// this should not affect the pipe
ObservableWrapper.callNext(emitter, message);
TimerWrapper.setTimeout(() => {
expect(pipe.transform(newEmitter)).toBe(null);
async.done();
}, 0)
}));
it("should request a change detection check upon receiving a new value",
inject([AsyncTestCompleter], (async) => {
pipe.transform(emitter);
ObservableWrapper.callNext(emitter, message);
TimerWrapper.setTimeout(() => {
expect(ref.spy('markForCheck')).toHaveBeenCalled();
async.done();
}, 0)
}));
});
describe("onDestroy", () => {
it("should do nothing when no subscription",
() => { expect(() => pipe.onDestroy()).not.toThrow(); });
it("should dispose of the existing subscription", inject([AsyncTestCompleter], (async) => {
pipe.transform(emitter);
pipe.onDestroy();
ObservableWrapper.callNext(emitter, message);
TimerWrapper.setTimeout(() => {
expect(pipe.transform(emitter)).toBe(null);
async.done();
}, 0)
}));
});
});
describe("Promise", () => {
var message = new Object();
var pipe;
var completer;
var ref;
// adds longer timers for passing tests in IE
var timer = (!isBlank(DOM) && browserDetection.isIE) ? 50 : 0;
beforeEach(() => {
completer = PromiseWrapper.completer();
ref = new SpyChangeDetectorRef();
pipe = new AsyncPipe(ref);
});
describe("transform", () => {
it("should return null when subscribing to a promise",
() => { expect(pipe.transform(completer.promise)).toBe(null); });
it("should return the latest available value", inject([AsyncTestCompleter], (async) => {
pipe.transform(completer.promise);
completer.resolve(message);
TimerWrapper.setTimeout(() => {
expect(pipe.transform(completer.promise)).toEqual(new WrappedValue(message));
async.done();
}, timer)
}));
it("should return unwrapped value when nothing has changed since the last call",
inject([AsyncTestCompleter], (async) => {
pipe.transform(completer.promise);
completer.resolve(message);
TimerWrapper.setTimeout(() => {
pipe.transform(completer.promise);
expect(pipe.transform(completer.promise)).toBe(message);
async.done();
}, timer)
}));
it("should dispose of the existing subscription when subscribing to a new promise",
inject([AsyncTestCompleter], (async) => {
pipe.transform(completer.promise);
var newCompleter = PromiseWrapper.completer();
expect(pipe.transform(newCompleter.promise)).toBe(null);
// this should not affect the pipe, so it should return WrappedValue
completer.resolve(message);
TimerWrapper.setTimeout(() => {
expect(pipe.transform(newCompleter.promise)).toBe(null);
async.done();
}, timer)
}));
it("should request a change detection check upon receiving a new value",
inject([AsyncTestCompleter], (async) => {
pipe.transform(completer.promise);
completer.resolve(message);
TimerWrapper.setTimeout(() => {
expect(ref.spy('markForCheck')).toHaveBeenCalled();
async.done();
}, timer)
}));
describe("onDestroy", () => {
it("should do nothing when no source",
() => { expect(() => pipe.onDestroy()).not.toThrow(); });
it("should dispose of the existing source", inject([AsyncTestCompleter], (async) => {
pipe.transform(completer.promise);
expect(pipe.transform(completer.promise)).toBe(null);
completer.resolve(message)
TimerWrapper.setTimeout(() => {
expect(pipe.transform(completer.promise)).toEqual(new WrappedValue(message));
pipe.onDestroy();
expect(pipe.transform(completer.promise)).toBe(null);
async.done();
}, timer);
}));
});
});
});
describe('null', () => {
it('should return null when given null', () => {
var pipe = new AsyncPipe(null);
expect(pipe.transform(null, [])).toEqual(null);
});
});
describe('other types', () => {
it('should throw when given an invalid object', () => {
var pipe = new AsyncPipe(null);
expect(() => pipe.transform(<any>"some bogus object", [])).toThrowError();
});
});
});
}
@@ -1,82 +0,0 @@
import {
ddescribe,
describe,
it,
iit,
xit,
expect,
beforeEach,
afterEach,
browserDetection
} from 'angular2/testing_internal';
import {DatePipe} from 'angular2/core';
import {DateWrapper} from 'angular2/src/core/facade/lang';
import {PipeResolver} from 'angular2/src/core/linker/pipe_resolver';
export function main() {
describe("DatePipe", () => {
var date;
var pipe;
beforeEach(() => {
date = DateWrapper.create(2015, 6, 15, 21, 43, 11);
pipe = new DatePipe();
});
it('should be marked as pure',
() => { expect(new PipeResolver().resolve(DatePipe).pure).toEqual(true); });
describe("supports", () => {
it("should support date", () => { expect(pipe.supports(date)).toBe(true); });
it("should support int", () => { expect(pipe.supports(123456789)).toBe(true); });
it("should not support other objects", () => {
expect(pipe.supports(new Object())).toBe(false);
expect(pipe.supports(null)).toBe(false);
});
});
// TODO(mlaval): enable tests when Intl API is no longer used, see
// https://github.com/angular/angular/issues/3333
if (browserDetection.supportsIntlApi) {
describe("transform", () => {
it('should format each component correctly', () => {
expect(pipe.transform(date, ['y'])).toEqual('2015');
expect(pipe.transform(date, ['yy'])).toEqual('15');
expect(pipe.transform(date, ['M'])).toEqual('6');
expect(pipe.transform(date, ['MM'])).toEqual('06');
expect(pipe.transform(date, ['MMM'])).toEqual('Jun');
expect(pipe.transform(date, ['MMMM'])).toEqual('June');
expect(pipe.transform(date, ['d'])).toEqual('15');
expect(pipe.transform(date, ['E'])).toEqual('Mon');
expect(pipe.transform(date, ['EEEE'])).toEqual('Monday');
expect(pipe.transform(date, ['H'])).toEqual('21');
expect(pipe.transform(date, ['j'])).toEqual('9 PM');
expect(pipe.transform(date, ['m'])).toEqual('43');
expect(pipe.transform(date, ['s'])).toEqual('11');
});
it('should format common multi component patterns', () => {
expect(pipe.transform(date, ['yMEd'])).toEqual('Mon, 6/15/2015');
expect(pipe.transform(date, ['MEd'])).toEqual('Mon, 6/15');
expect(pipe.transform(date, ['MMMd'])).toEqual('Jun 15');
expect(pipe.transform(date, ['yMMMMEEEEd'])).toEqual('Monday, June 15, 2015');
expect(pipe.transform(date, ['jms'])).toEqual('9:43:11 PM');
expect(pipe.transform(date, ['ms'])).toEqual('43:11');
});
it('should format with pattern aliases', () => {
expect(pipe.transform(date, ['medium'])).toEqual('Jun 15, 2015, 9:43:11 PM');
expect(pipe.transform(date, ['short'])).toEqual('6/15/2015, 9:43 PM');
expect(pipe.transform(date, ['fullDate'])).toEqual('Monday, June 15, 2015');
expect(pipe.transform(date, ['longDate'])).toEqual('June 15, 2015');
expect(pipe.transform(date, ['mediumDate'])).toEqual('Jun 15, 2015');
expect(pipe.transform(date, ['shortDate'])).toEqual('6/15/2015');
expect(pipe.transform(date, ['mediumTime'])).toEqual('9:43:11 PM');
expect(pipe.transform(date, ['shortTime'])).toEqual('9:43 PM');
});
});
}
});
}
@@ -1,78 +0,0 @@
import {
ddescribe,
describe,
it,
iit,
xit,
expect,
beforeEach,
afterEach,
AsyncTestCompleter,
inject,
proxy,
SpyObject,
TestComponentBuilder
} from 'angular2/testing_internal';
import {Json, RegExp, NumberWrapper, StringWrapper} from 'angular2/src/core/facade/lang';
import {JsonPipe, Component} from 'angular2/core';
export function main() {
describe("JsonPipe", () => {
var regNewLine = '\n';
var inceptionObj;
var inceptionObjString;
var pipe;
function normalize(obj: string): string { return StringWrapper.replace(obj, regNewLine, ''); }
beforeEach(() => {
inceptionObj = {dream: {dream: {dream: 'Limbo'}}};
inceptionObjString = "{\n" + " \"dream\": {\n" + " \"dream\": {\n" +
" \"dream\": \"Limbo\"\n" + " }\n" + " }\n" + "}";
pipe = new JsonPipe();
});
describe("transform", () => {
it("should return JSON-formatted string",
() => { expect(pipe.transform(inceptionObj)).toEqual(inceptionObjString); });
it("should return JSON-formatted string even when normalized", () => {
var dream1 = normalize(pipe.transform(inceptionObj));
var dream2 = normalize(inceptionObjString);
expect(dream1).toEqual(dream2);
});
it("should return JSON-formatted string similar to Json.stringify", () => {
var dream1 = normalize(pipe.transform(inceptionObj));
var dream2 = normalize(Json.stringify(inceptionObj));
expect(dream1).toEqual(dream2);
});
});
describe('integration', () => {
it('should work with mutable objects',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.createAsync(TestComp).then((fixture) => {
let mutable: number[] = [1];
fixture.debugElement.componentInstance.data = mutable;
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText("[\n 1\n]");
mutable.push(2);
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText("[\n 1,\n 2\n]");
async.done();
});
}));
});
});
}
@Component({selector: 'test-comp', template: '{{data | json}}', pipes: [JsonPipe]})
class TestComp {
data: any;
}
@@ -1,44 +0,0 @@
import {
ddescribe,
describe,
it,
iit,
xit,
expect,
beforeEach,
afterEach
} from 'angular2/testing_internal';
import {LowerCasePipe} from 'angular2/core';
export function main() {
describe("LowerCasePipe", () => {
var upper;
var lower;
var pipe;
beforeEach(() => {
lower = 'something';
upper = 'SOMETHING';
pipe = new LowerCasePipe();
});
describe("transform", () => {
it("should return lowercase", () => {
var val = pipe.transform(upper);
expect(val).toEqual(lower);
});
it("should lowercase when there is a new value", () => {
var val = pipe.transform(upper);
expect(val).toEqual(lower);
var val2 = pipe.transform('WAT');
expect(val2).toEqual('wat');
});
it("should not support other objects",
() => { expect(() => pipe.transform(new Object())).toThrowError(); });
});
});
}
@@ -1,72 +0,0 @@
import {
ddescribe,
describe,
it,
iit,
xit,
expect,
beforeEach,
afterEach,
browserDetection
} from 'angular2/testing_internal';
import {DecimalPipe, PercentPipe, CurrencyPipe} from 'angular2/core';
export function main() {
// TODO(mlaval): enable tests when Intl API is no longer used, see
// https://github.com/angular/angular/issues/3333
if (browserDetection.supportsIntlApi) {
describe("DecimalPipe", () => {
var pipe;
beforeEach(() => { pipe = new DecimalPipe(); });
describe("transform", () => {
it('should return correct value for numbers', () => {
expect(pipe.transform(12345, [])).toEqual('12,345');
expect(pipe.transform(123, ['.2'])).toEqual('123.00');
expect(pipe.transform(1, ['3.'])).toEqual('001');
expect(pipe.transform(1.1, ['3.4-5'])).toEqual('001.1000');
expect(pipe.transform(1.123456, ['3.4-5'])).toEqual('001.12346');
expect(pipe.transform(1.1234, [])).toEqual('1.123');
});
it("should not support other objects",
() => { expect(() => pipe.transform(new Object(), [])).toThrowError(); });
});
});
describe("PercentPipe", () => {
var pipe;
beforeEach(() => { pipe = new PercentPipe(); });
describe("transform", () => {
it('should return correct value for numbers', () => {
expect(pipe.transform(1.23, [])).toEqual('123%');
expect(pipe.transform(1.2, ['.2'])).toEqual('120.00%');
});
it("should not support other objects",
() => { expect(() => pipe.transform(new Object(), [])).toThrowError(); });
});
});
describe("CurrencyPipe", () => {
var pipe;
beforeEach(() => { pipe = new CurrencyPipe(); });
describe("transform", () => {
it('should return correct value for numbers', () => {
expect(pipe.transform(123, [])).toEqual('USD123');
expect(pipe.transform(12, ['EUR', false, '.2'])).toEqual('EUR12.00');
});
it("should not support other objects",
() => { expect(() => pipe.transform(new Object(), [])).toThrowError(); });
});
});
}
}
@@ -1,26 +0,0 @@
import {
ddescribe,
xdescribe,
describe,
it,
iit,
xit,
expect,
beforeEach,
afterEach
} from 'angular2/testing_internal';
import {PipeProvider} from 'angular2/src/core/pipes/pipe_provider';
import {Pipe} from 'angular2/src/core/metadata';
class MyPipe {}
export function main() {
describe("PipeProvider", () => {
it('should create a provider out of a type', () => {
var provider = PipeProvider.createFromType(MyPipe, new Pipe({name: 'my-pipe'}));
expect(provider.name).toEqual('my-pipe');
expect(provider.key.token).toEqual(MyPipe);
});
});
}
@@ -1,76 +0,0 @@
import {
ddescribe,
xdescribe,
describe,
it,
iit,
xit,
expect,
beforeEach,
afterEach
} from 'angular2/testing_internal';
import {Injector, Inject, provide, Pipe, PipeTransform} from 'angular2/core';
import {ProtoPipes, Pipes} from 'angular2/src/core/pipes/pipes';
import {PipeProvider} from 'angular2/src/core/pipes/pipe_provider';
class PipeA implements PipeTransform {
transform(a, b) {}
onDestroy() {}
}
class PipeB implements PipeTransform {
dep;
constructor(@Inject("dep") dep: any) { this.dep = dep; }
transform(a, b) {}
onDestroy() {}
}
export function main() {
describe("Pipes", () => {
var injector;
beforeEach(() => {
injector = Injector.resolveAndCreate([provide('dep', {useValue: 'dependency'})]);
});
it('should instantiate a pipe', () => {
var proto =
ProtoPipes.fromProviders([PipeProvider.createFromType(PipeA, new Pipe({name: 'a'}))]);
var pipes = new Pipes(proto, injector);
expect(pipes.get("a").pipe).toBeAnInstanceOf(PipeA);
});
it('should throw when no pipe found', () => {
var proto = ProtoPipes.fromProviders([]);
var pipes = new Pipes(proto, injector);
expect(() => pipes.get("invalid")).toThrowErrorWith("Cannot find pipe 'invalid'");
});
it('should inject dependencies from the provided injector', () => {
var proto =
ProtoPipes.fromProviders([PipeProvider.createFromType(PipeB, new Pipe({name: 'b'}))]);
var pipes = new Pipes(proto, injector);
expect((<any>pipes.get("b").pipe).dep).toEqual("dependency");
});
it('should cache pure pipes', () => {
var proto = ProtoPipes.fromProviders(
[PipeProvider.createFromType(PipeA, new Pipe({name: 'a', pure: true}))]);
var pipes = new Pipes(proto, injector);
expect(pipes.get("a").pure).toEqual(true);
expect(pipes.get("a")).toBe(pipes.get("a"));
});
it('should NOT cache impure pipes', () => {
var proto = ProtoPipes.fromProviders(
[PipeProvider.createFromType(PipeA, new Pipe({name: 'a', pure: false}))]);
var pipes = new Pipes(proto, injector);
expect(pipes.get("a").pure).toEqual(false);
expect(pipes.get("a")).not.toBe(pipes.get("a"));
});
});
}
@@ -1,114 +0,0 @@
import {
ddescribe,
describe,
it,
iit,
xit,
expect,
beforeEach,
afterEach,
browserDetection,
inject,
TestComponentBuilder,
AsyncTestCompleter
} from 'angular2/testing_internal';
import {SlicePipe, Component} from 'angular2/core';
export function main() {
describe("SlicePipe", () => {
var list: number[];
var str;
var pipe;
beforeEach(() => {
list = [1, 2, 3, 4, 5];
str = 'tuvwxyz';
pipe = new SlicePipe();
});
describe("supports", () => {
it("should support strings", () => { expect(pipe.supports(str)).toBe(true); });
it("should support lists", () => { expect(pipe.supports(list)).toBe(true); });
it("should not support other objects", () => {
expect(pipe.supports(new Object())).toBe(false);
expect(pipe.supports(null)).toBe(false);
});
});
describe("transform", () => {
it('should return all items after START index when START is positive and END is omitted',
() => {
expect(pipe.transform(list, [3])).toEqual([4, 5]);
expect(pipe.transform(str, [3])).toEqual('wxyz');
});
it('should return last START items when START is negative and END is omitted', () => {
expect(pipe.transform(list, [-3])).toEqual([3, 4, 5]);
expect(pipe.transform(str, [-3])).toEqual('xyz');
});
it('should return all items between START and END index when START and END are positive',
() => {
expect(pipe.transform(list, [1, 3])).toEqual([2, 3]);
expect(pipe.transform(str, [1, 3])).toEqual('uv');
});
it('should return all items between START and END from the end when START and END are negative',
() => {
expect(pipe.transform(list, [-4, -2])).toEqual([2, 3]);
expect(pipe.transform(str, [-4, -2])).toEqual('wx');
});
it('should return an empty value if START is greater than END', () => {
expect(pipe.transform(list, [4, 2])).toEqual([]);
expect(pipe.transform(str, [4, 2])).toEqual('');
});
it('should return an empty value if START greater than input length', () => {
expect(pipe.transform(list, [99])).toEqual([]);
expect(pipe.transform(str, [99])).toEqual('');
});
// Makes Edge to disconnect when running the full unit test campaign
// TODO: remove when issue is solved: https://github.com/angular/angular/issues/4756
if (!browserDetection.isEdge) {
it('should return entire input if START is negative and greater than input length', () => {
expect(pipe.transform(list, [-99])).toEqual([1, 2, 3, 4, 5]);
expect(pipe.transform(str, [-99])).toEqual('tuvwxyz');
});
it('should not modify the input list', () => {
expect(pipe.transform(list, [2])).toEqual([3, 4, 5]);
expect(list).toEqual([1, 2, 3, 4, 5]);
});
}
});
describe('integration', () => {
it('should work with mutable arrays',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.createAsync(TestComp).then((fixture) => {
let mutable: number[] = [1, 2];
fixture.debugElement.componentInstance.data = mutable;
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('2');
mutable.push(3);
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('2,3');
async.done();
});
}));
});
});
}
@Component({selector: 'test-comp', template: '{{(data | slice:1).join(",") }}', pipes: [SlicePipe]})
class TestComp {
data: any;
}
@@ -1,9 +0,0 @@
library pipes.spies;
import 'package:angular2/src/core/change_detection/change_detection.dart';
import 'package:angular2/testing_internal.dart';
@proxy
class SpyChangeDetectorRef extends SpyObject implements ChangeDetectorRef {
noSuchMethod(m) => super.noSuchMethod(m);
}
@@ -1,7 +0,0 @@
import {ChangeDetectorRef_} from 'angular2/src/core/change_detection/change_detector_ref';
import {SpyObject, proxy} from 'angular2/testing_internal';
export class SpyChangeDetectorRef extends SpyObject {
constructor() { super(ChangeDetectorRef_); }
}
@@ -1,45 +0,0 @@
import {
ddescribe,
describe,
it,
iit,
xit,
expect,
beforeEach,
afterEach
} from 'angular2/testing_internal';
import {UpperCasePipe} from 'angular2/core';
export function main() {
describe("UpperCasePipe", () => {
var upper;
var lower;
var pipe;
beforeEach(() => {
lower = 'something';
upper = 'SOMETHING';
pipe = new UpperCasePipe();
});
describe("transform", () => {
it("should return uppercase", () => {
var val = pipe.transform(lower);
expect(val).toEqual(upper);
});
it("should uppercase when there is a new value", () => {
var val = pipe.transform(lower);
expect(val).toEqual(upper);
var val2 = pipe.transform('wat');
expect(val2).toEqual('WAT');
});
it("should not support other objects",
() => { expect(() => pipe.transform(new Object())).toThrowError(); });
});
});
}
+1 -11
View File
@@ -106,14 +106,4 @@ class SpyDomAdapter extends SpyObject implements DomAdapter {
class SpyRenderEventDispatcher extends SpyObject
implements RenderEventDispatcher {
noSuchMethod(m) => super.noSuchMethod(m);
}
@proxy
class SpyNgControl extends SpyObject implements NgControl {
noSuchMethod(m) => super.noSuchMethod(m);
}
@proxy
class SpyValueAccessor extends SpyObject implements ControlValueAccessor {
noSuchMethod(m) => super.noSuchMethod(m);
}
}
+1 -5
View File
@@ -105,8 +105,4 @@ export class SpyRenderEventDispatcher extends SpyObject {
super();
this.spy('dispatchRenderEvent');
}
}
export class SpyNgControl extends SpyObject {}
export class SpyValueAccessor extends SpyObject {}
}