feat(change_detection): added an experimental support for observables
This commit is contained in:
@ -103,7 +103,14 @@ export function getDefinition(id: string): TestDefinition {
|
||||
let cdDef = new ChangeDetectorDefinition(id, null, [], [], eventRecords,
|
||||
[_DirectiveUpdating.basicRecords[0]], true);
|
||||
testDef = new TestDefinition(id, cdDef, null);
|
||||
|
||||
} else if (id == "onPushObserve") {
|
||||
var records = _createBindingRecords("a");
|
||||
let cdDef = new ChangeDetectorDefinition(id, "ON_PUSH_OBSERVE", [], records, [], [], false);
|
||||
testDef = new TestDefinition(id, cdDef, null);
|
||||
}
|
||||
|
||||
|
||||
if (isBlank(testDef)) {
|
||||
throw `No ChangeDetectorDefinition for ${id} available. Please modify this file if necessary.`;
|
||||
}
|
||||
@ -129,6 +136,7 @@ export function getAllDefinitions(): List<TestDefinition> {
|
||||
ListWrapper.concat(allDefs, StringMapWrapper.keys(_DirectiveUpdating.availableDefinitions));
|
||||
allDefs = ListWrapper.concat(allDefs, _availableEventDefinitions);
|
||||
allDefs = ListWrapper.concat(allDefs, _availableHostEventDefinitions);
|
||||
allDefs = ListWrapper.concat(allDefs, ["onPushObserve"]);
|
||||
return ListWrapper.map(allDefs, (id) => getDefinition(id));
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,16 @@
|
||||
///<reference path="../../src/change_detection/pipe_transform.ts"/>
|
||||
import {ddescribe, describe, it, iit, xit, expect, beforeEach, afterEach} from 'angular2/test_lib';
|
||||
import {
|
||||
ddescribe,
|
||||
describe,
|
||||
it,
|
||||
iit,
|
||||
xit,
|
||||
expect,
|
||||
beforeEach,
|
||||
afterEach,
|
||||
tick,
|
||||
fakeAsync
|
||||
} from 'angular2/test_lib';
|
||||
|
||||
import {
|
||||
CONST_EXPR,
|
||||
@ -40,6 +51,7 @@ import {Pipes} from 'angular2/src/change_detection/pipes';
|
||||
import {JitProtoChangeDetector} from 'angular2/src/change_detection/jit_proto_change_detector';
|
||||
|
||||
import {getDefinition} from './change_detector_config';
|
||||
import {createObservableModel} from './change_detector_spec_util';
|
||||
import {getFactoryById} from './generated/change_detector_classes';
|
||||
import {IS_DART} from '../platform';
|
||||
|
||||
@ -735,6 +747,67 @@ export function main() {
|
||||
|
||||
expect(checkedDetector.mode).toEqual(CHECK_ONCE);
|
||||
});
|
||||
|
||||
if (IS_DART) {
|
||||
it('should mark ON_PUSH_OBSERVE detectors as CHECK_ONCE when an observable fires an event',
|
||||
fakeAsync(() => {
|
||||
var context = new TestDirective();
|
||||
context.a = createObservableModel();
|
||||
|
||||
var cd = _createWithoutHydrate('onPushObserve').changeDetector;
|
||||
cd.hydrate(context, null, directives, null);
|
||||
cd.detectChanges();
|
||||
|
||||
expect(cd.mode).toEqual(CHECKED);
|
||||
|
||||
context.a.pushUpdate();
|
||||
tick();
|
||||
|
||||
expect(cd.mode).toEqual(CHECK_ONCE);
|
||||
}));
|
||||
|
||||
it('should unsubscribe from an old observable when an object changes', fakeAsync(() => {
|
||||
var originalModel = createObservableModel();
|
||||
var context = new TestDirective();
|
||||
context.a = originalModel;
|
||||
|
||||
var cd = _createWithoutHydrate('onPushObserve').changeDetector;
|
||||
cd.hydrate(context, null, directives, null);
|
||||
cd.detectChanges();
|
||||
|
||||
context.a = createObservableModel();
|
||||
cd.mode = CHECK_ONCE;
|
||||
cd.detectChanges();
|
||||
|
||||
// Updating this model will not reenable the detector. This model is not longer
|
||||
// used.
|
||||
originalModel.pushUpdate();
|
||||
tick();
|
||||
expect(cd.mode).toEqual(CHECKED);
|
||||
}));
|
||||
|
||||
it('should unsubscribe from observables when dehydrating', fakeAsync(() => {
|
||||
var originalModel = createObservableModel();
|
||||
var context = new TestDirective();
|
||||
context.a = originalModel;
|
||||
|
||||
var cd = _createWithoutHydrate('onPushObserve').changeDetector;
|
||||
cd.hydrate(context, null, directives, null);
|
||||
cd.detectChanges();
|
||||
|
||||
cd.dehydrate();
|
||||
|
||||
context.a = "not an observable model";
|
||||
cd.hydrate(context, null, directives, null);
|
||||
cd.detectChanges();
|
||||
|
||||
// Updating this model will not reenable the detector. This model is not longer
|
||||
// used.
|
||||
originalModel.pushUpdate();
|
||||
tick();
|
||||
expect(cd.mode).toEqual(CHECKED);
|
||||
}));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -0,0 +1,27 @@
|
||||
library angular.change_detection.change_detector_spec_util;
|
||||
|
||||
import 'package:observe/observe.dart' show Observable;
|
||||
import 'dart:async';
|
||||
|
||||
dynamic createObservableModel() {
|
||||
return new Entity();
|
||||
}
|
||||
|
||||
class Entity implements Observable {
|
||||
Stream changes;
|
||||
StreamController controller;
|
||||
|
||||
Entity() {
|
||||
controller = new StreamController.broadcast();
|
||||
changes = controller.stream;
|
||||
}
|
||||
|
||||
pushUpdate() {
|
||||
controller.add("new");
|
||||
}
|
||||
|
||||
bool get hasObservers => null;
|
||||
bool deliverChanges() => null;
|
||||
notifyPropertyChange(Symbol field, Object oldValue, Object newValue) => null;
|
||||
void notifyChange(record) {}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
export function createObservableModel(): any {
|
||||
return null;
|
||||
}
|
@ -36,7 +36,7 @@ main() {
|
||||
|
||||
d.diff(c);
|
||||
|
||||
expect(d.diff(c)).toBe(d);
|
||||
expect(d.diff(c)).toBe(null);
|
||||
});
|
||||
|
||||
it("should return the wrapped value once a change has been triggered",
|
||||
@ -50,7 +50,7 @@ main() {
|
||||
c.add(3);
|
||||
|
||||
// same value, because we have not detected the change yet
|
||||
expect(d.diff(c)).toBe(d);
|
||||
expect(d.diff(c)).toBe(null);
|
||||
|
||||
// now we detect the change
|
||||
flushMicrotasks();
|
||||
@ -92,7 +92,7 @@ main() {
|
||||
|
||||
// pushing into the first collection has no effect, and we do not see the change
|
||||
c1.add(3);
|
||||
expect(d.diff(c2)).toBe(d);
|
||||
expect(d.diff(c2)).toBe(null);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
Reference in New Issue
Block a user