| // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| library node_model_test; |
| import 'dart:async'; |
| import 'dart:html'; |
| import '../../pkg/unittest/lib/unittest.dart'; |
| import '../../pkg/unittest/lib/html_config.dart'; |
| |
| var stepDuration; |
| Future get nextStep { |
| return new Future.delayed(stepDuration); |
| } |
| |
| class ModelTracker { |
| Element element = new DivElement(); |
| List models = []; |
| |
| ModelTracker() { |
| element.onModelChanged.listen((node) { |
| models.add(node.model); |
| }); |
| } |
| |
| void append(ModelTracker other) { |
| element.append(other.element); |
| } |
| |
| get model => element.model; |
| void set model(value) { |
| element.model = value; |
| } |
| |
| void clearModel() { |
| element.clearModel(); |
| } |
| |
| void remove() { |
| element.remove(); |
| } |
| } |
| |
| main() { |
| useHtmlConfiguration(); |
| |
| if (MutationObserver.supported) { |
| stepDuration = new Duration(); |
| } else { |
| // Need to step after the tree update notifications, but on IE9 these may |
| // get polyfilled to use setTimeout(0). So use a longer timer to try to |
| // get a later callback. |
| stepDuration = new Duration(milliseconds: 15); |
| } |
| |
| test('basic top down', () { |
| var a = new DivElement(); |
| var b = new SpanElement(); |
| var c = new DivElement(); |
| var d = new DivElement(); |
| var e = new DivElement(); |
| var model = {}; |
| var model2 = {}; |
| var model3 = {}; |
| |
| document.body.append(a); |
| a.append(b); |
| |
| a.model = model; |
| expect(a.model, model); |
| expect(b.model, model); |
| |
| b.append(c); |
| |
| return nextStep.then((_) { |
| expect(c.model, model); |
| |
| d.append(e); |
| c.append(d); |
| |
| return nextStep; |
| }).then((_) { |
| expect(e.model, model); |
| |
| b.remove(); |
| return nextStep; |
| }).then((_) { |
| expect(b.model, isNull); |
| expect(e.model, isNull); |
| |
| return nextStep; |
| }).then((_) { |
| a.append(b); |
| a.model = model2; |
| |
| return nextStep; |
| }).then((_) { |
| expect(e.model, model2); |
| |
| c.model = model3; |
| expect(c.model, model3); |
| expect(b.model, model2); |
| expect(e.model, model3); |
| |
| return nextStep; |
| }).then((_) { |
| d.remove(); |
| c.append(d); |
| |
| return nextStep; |
| }).then((_) { |
| expect(d.model, model3); |
| |
| c.clearModel(); |
| expect(d.model, model2); |
| |
| a.remove(); |
| return nextStep; |
| }); |
| }); |
| |
| test('changes', () { |
| var a = new ModelTracker(); |
| var b = new ModelTracker(); |
| var c = new ModelTracker(); |
| var d = new ModelTracker(); |
| |
| var model = {}; |
| var cModel = {}; |
| |
| document.body.append(a.element); |
| |
| a.append(b); |
| |
| return nextStep.then((_) { |
| expect(a.models, []); |
| expect(b.models.length, 0); |
| |
| a.model = model; |
| |
| expect(a.models, [model]); |
| expect(b.models, [model]); |
| |
| b.append(c); |
| return nextStep; |
| }).then((_) { |
| expect(c.models, [model]); |
| |
| c.append(d); |
| return nextStep; |
| }).then((_) { |
| c.model = cModel; |
| expect(b.models, [model]); |
| expect(c.models, [model, cModel]); |
| expect(d.models, [model, cModel]); |
| |
| c.clearModel(); |
| expect(c.models, [model, cModel, model]); |
| expect(d.models, [model, cModel, model]); |
| |
| a.remove(); |
| return nextStep; |
| }); |
| }); |
| |
| test('bottom up', () { |
| var a = new ModelTracker(); |
| var b = new ModelTracker(); |
| var c = new ModelTracker(); |
| var d = new ModelTracker(); |
| |
| var aModel = {}; |
| var cModel = {}; |
| |
| c.append(d); |
| c.model = cModel; |
| b.append(c); |
| a.append(b); |
| a.model = aModel; |
| document.body.append(a.element); |
| |
| return nextStep.then((_) { |
| expect(a.models, [aModel]); |
| expect(b.models, [aModel]); |
| expect(c.models, [cModel]); |
| expect(d.models, [cModel]); |
| |
| a.remove(); |
| return nextStep; |
| }); |
| }); |
| } |