@@ -361,30 +361,64 @@ export function main() {
|
||||
});
|
||||
}));
|
||||
|
||||
it('should use custom track by if function is provided',
|
||||
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
|
||||
var template =
|
||||
`<template ngFor #item [ngForOf]="items" [ngForTrackBy]="customTrackBy" #i="index">
|
||||
describe('track by', function() {
|
||||
it('should not replace tracked items',
|
||||
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
|
||||
var template =
|
||||
`<template ngFor #item [ngForOf]="items" [ngForTrackBy]="customTrackBy" #i="index">
|
||||
<p>{{items[i]}}</p>
|
||||
</template>`;
|
||||
tcb.overrideTemplate(TestComponent, template)
|
||||
.createAsync(TestComponent)
|
||||
.then((fixture) => {
|
||||
var buildItemList =
|
||||
() => {
|
||||
fixture.debugElement.componentInstance.items = [{'id': 'a'}];
|
||||
fixture.detectChanges();
|
||||
return fixture.debugElement.queryAll(By.css('p'))[0];
|
||||
}
|
||||
|
||||
var firstP = buildItemList();
|
||||
var finalP = buildItemList();
|
||||
expect(finalP.nativeElement).toBe(firstP.nativeElement);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
tcb.overrideTemplate(TestComponent, template)
|
||||
.createAsync(TestComponent)
|
||||
.then((fixture) => {
|
||||
var buildItemList =
|
||||
() => {
|
||||
fixture.debugElement.componentInstance.items = [{'id': 'a'}];
|
||||
fixture.detectChanges();
|
||||
return fixture.debugElement.queryAll(By.css('p'))[0];
|
||||
}
|
||||
|
||||
var firstP = buildItemList();
|
||||
var finalP = buildItemList();
|
||||
expect(finalP.nativeElement).toBe(firstP.nativeElement);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
it('should update implicit local variable on view',
|
||||
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
|
||||
var template =
|
||||
`<div><template ngFor #item [ngForOf]="items" [ngForTrackBy]="customTrackBy">{{item['color']}}</template></div>`;
|
||||
tcb.overrideTemplate(TestComponent, template)
|
||||
.createAsync(TestComponent)
|
||||
.then((fixture) => {
|
||||
fixture.debugElement.componentInstance.items = [{'id': 'a', 'color': 'blue'}];
|
||||
fixture.detectChanges();
|
||||
expect(fixture.debugElement.nativeElement).toHaveText('blue');
|
||||
fixture.debugElement.componentInstance.items = [{'id': 'a', 'color': 'red'}];
|
||||
fixture.detectChanges();
|
||||
expect(fixture.debugElement.nativeElement).toHaveText('red');
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
it('should move items around and keep them updated ',
|
||||
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
|
||||
var template =
|
||||
`<div><template ngFor #item [ngForOf]="items" [ngForTrackBy]="customTrackBy">{{item['color']}}</template></div>`;
|
||||
tcb.overrideTemplate(TestComponent, template)
|
||||
.createAsync(TestComponent)
|
||||
.then((fixture) => {
|
||||
fixture.debugElement.componentInstance.items =
|
||||
[{'id': 'a', 'color': 'blue'}, {'id': 'b', 'color': 'yellow'}];
|
||||
fixture.detectChanges();
|
||||
expect(fixture.debugElement.nativeElement).toHaveText('blueyellow');
|
||||
fixture.debugElement.componentInstance.items =
|
||||
[{'id': 'b', 'color': 'orange'}, {'id': 'a', 'color': 'red'}];
|
||||
fixture.detectChanges();
|
||||
expect(fixture.debugElement.nativeElement).toHaveText('orangered');
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+31
-4
@@ -25,6 +25,12 @@ class ItemWithId {
|
||||
toString() { return `{id: ${this.id}}` }
|
||||
}
|
||||
|
||||
class ComplexItem {
|
||||
constructor(private id: string, private color: string) {}
|
||||
|
||||
toString() { return `{id: ${this.id}, color: ${this.color}}` }
|
||||
}
|
||||
|
||||
// todo(vicb): UnmodifiableListView / frozen object when implemented
|
||||
export function main() {
|
||||
describe('iterable differ', function() {
|
||||
@@ -342,8 +348,12 @@ export function main() {
|
||||
|
||||
beforeEach(() => { differ = new DefaultIterableDiffer(trackByItemId); });
|
||||
|
||||
it('should not treat maps as new with track by function', () => {
|
||||
it('should treat the collection as dirty if identity changes', () => {
|
||||
differ.diff(buildItemList(['a']));
|
||||
expect(differ.diff(buildItemList(['a']))).toBe(differ);
|
||||
});
|
||||
|
||||
it('should treat seen records as identity changes, not additions', () => {
|
||||
let l = buildItemList(['a', 'b', 'c']);
|
||||
differ.check(l);
|
||||
expect(differ.toString())
|
||||
@@ -357,11 +367,26 @@ export function main() {
|
||||
expect(differ.toString())
|
||||
.toEqual(iterableChangesAsString({
|
||||
collection: [`{id: a}`, `{id: b}`, `{id: c}`],
|
||||
identityChanges: [`{id: a}`, `{id: b}`, `{id: c}`],
|
||||
previous: [`{id: a}`, `{id: b}`, `{id: c}`]
|
||||
}));
|
||||
});
|
||||
|
||||
it('should track moves normally with track by function', () => {
|
||||
it('should have updated properties in identity change collection', () => {
|
||||
let l = [new ComplexItem('a', 'blue'), new ComplexItem('b', 'yellow')];
|
||||
differ.check(l);
|
||||
|
||||
l = [new ComplexItem('a', 'orange'), new ComplexItem('b', 'red')];
|
||||
differ.check(l);
|
||||
expect(differ.toString())
|
||||
.toEqual(iterableChangesAsString({
|
||||
collection: [`{id: a, color: orange}`, `{id: b, color: red}`],
|
||||
identityChanges: [`{id: a, color: orange}`, `{id: b, color: red}`],
|
||||
previous: [`{id: a, color: orange}`, `{id: b, color: red}`]
|
||||
}));
|
||||
});
|
||||
|
||||
it('should track moves normally', () => {
|
||||
let l = buildItemList(['a', 'b', 'c']);
|
||||
differ.check(l);
|
||||
|
||||
@@ -370,13 +395,14 @@ export function main() {
|
||||
expect(differ.toString())
|
||||
.toEqual(iterableChangesAsString({
|
||||
collection: ['{id: b}[1->0]', '{id: a}[0->1]', '{id: c}'],
|
||||
identityChanges: ['{id: b}[1->0]', '{id: a}[0->1]', '{id: c}'],
|
||||
previous: ['{id: a}[0->1]', '{id: b}[1->0]', '{id: c}'],
|
||||
moves: ['{id: b}[1->0]', '{id: a}[0->1]']
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
it('should track duplicate reinsertion normally with track by function', () => {
|
||||
it('should track duplicate reinsertion normally', () => {
|
||||
let l = buildItemList(['a', 'a']);
|
||||
differ.check(l);
|
||||
|
||||
@@ -385,6 +411,7 @@ export function main() {
|
||||
expect(differ.toString())
|
||||
.toEqual(iterableChangesAsString({
|
||||
collection: ['{id: b}[null->0]', '{id: a}[0->1]', '{id: a}[1->2]'],
|
||||
identityChanges: ['{id: a}[0->1]', '{id: a}[1->2]'],
|
||||
previous: ['{id: a}[0->1]', '{id: a}[1->2]'],
|
||||
moves: ['{id: a}[0->1]', '{id: a}[1->2]'],
|
||||
additions: ['{id: b}[null->0]']
|
||||
@@ -392,7 +419,7 @@ export function main() {
|
||||
|
||||
});
|
||||
|
||||
it('should track removals normally with track by function', () => {
|
||||
it('should track removals normally', () => {
|
||||
let l = buildItemList(['a', 'b', 'c']);
|
||||
differ.check(l);
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import {isBlank, CONST_EXPR} from 'angular2/src/facade/lang';
|
||||
|
||||
export function iterableChangesAsString({collection = CONST_EXPR([]), previous = CONST_EXPR([]),
|
||||
additions = CONST_EXPR([]), moves = CONST_EXPR([]),
|
||||
removals = CONST_EXPR([])}) {
|
||||
export function iterableChangesAsString(
|
||||
{collection = CONST_EXPR([]), previous = CONST_EXPR([]), additions = CONST_EXPR([]),
|
||||
moves = CONST_EXPR([]), removals = CONST_EXPR([]), identityChanges = CONST_EXPR([])}) {
|
||||
return "collection: " + collection.join(', ') + "\n" + "previous: " + previous.join(', ') + "\n" +
|
||||
"additions: " + additions.join(', ') + "\n" + "moves: " + moves.join(', ') + "\n" +
|
||||
"removals: " + removals.join(', ') + "\n";
|
||||
"removals: " + removals.join(', ') + "\n" + "identityChanges: " +
|
||||
identityChanges.join(', ') + "\n";
|
||||
}
|
||||
|
||||
export function kvChangesAsString(
|
||||
|
||||
@@ -419,6 +419,7 @@ var NG_COMMON = [
|
||||
'ObservableListDiff.forEachMovedItem():dart',
|
||||
'ObservableListDiff.forEachPreviousItem():dart',
|
||||
'ObservableListDiff.forEachRemovedItem():dart',
|
||||
'ObservableListDiff.forEachIdentityChange():dart',
|
||||
'ObservableListDiff.isDirty:dart',
|
||||
'ObservableListDiff.length:dart',
|
||||
'ObservableListDiff.onDestroy():dart',
|
||||
|
||||
Reference in New Issue
Block a user