diff --git a/modules/angular2/src/test_lib/test_lib.dart b/modules/angular2/src/test_lib/test_lib.dart index 38b6c6cfe8..08fca30daf 100644 --- a/modules/angular2/src/test_lib/test_lib.dart +++ b/modules/angular2/src/test_lib/test_lib.dart @@ -8,6 +8,7 @@ import 'dart:async'; import 'package:angular2/src/reflection/reflection.dart'; import 'package:angular2/src/facade/dom.dart'; import 'package:angular2/src/reflection/reflection_capabilities.dart'; +import 'package:collection/equality.dart'; bool IS_DARTIUM = true; @@ -22,7 +23,9 @@ class Expect extends gns.Expect { NotExpect get not => new NotExpect(actual); - void toEqual(expected) => toHaveSameProps(expected); + // TODO(tbosch) change back when https://github.com/vsavkin/guinness/issues/41 is fixed + // void toEqual(expected) => toHaveSameProps(expected); + void toEqual(expected) => _expect(actual, new FixedSamePropsMatcher(expected)); void toThrowError([message=""]) => this.toThrowWith(message: message); void toBePromise() => _expect(actual is Future, equals(true)); void toImplement(expected) => toBeA(expected); @@ -33,7 +36,10 @@ class Expect extends gns.Expect { class NotExpect extends gns.NotExpect { NotExpect(actual) : super(actual); - void toEqual(expected) => toHaveSameProps(expected); + // TODO(tbosch) change back when https://github.com/vsavkin/guinness/issues/41 is fixed + // void toEqual(expected) => toHaveSameProps(expected); + void toEqual(expected) => _expect(actual, isNot(new FixedSamePropsMatcher(expected))); + Function get _expect => gns.guinness.matchers.expect; } beforeEach(fn) { @@ -70,4 +76,64 @@ _handleAsync(fn) { } return fn; +} + +// TODO(tbosch): remove when https://github.com/vsavkin/guinness/issues/41 +// is fixed +class FixedSamePropsMatcher extends Matcher { + final Object _expected; + + const FixedSamePropsMatcher(this._expected); + + bool matches(actual, Map matchState) { + return compare(toData(_expected), toData(actual)); + } + + Description describeMismatch(item, Description mismatchDescription, + Map matchState, bool verbose) => + mismatchDescription.add('is equal to ${toData(item)}. Expected: ${toData(_expected)}'); + + Description describe(Description description) => + description.add('has different properties'); + + toData(obj) => new _FixedObjToData().call(obj); + compare(d1, d2) => new DeepCollectionEquality().equals(d1, d2); +} + +// TODO(tbosch): remove when https://github.com/vsavkin/guinness/issues/41 +// is fixed +class _FixedObjToData { + final visitedObjects = new Set(); + + call(obj) { + if (visitedObjects.contains(obj)) return null; + visitedObjects.add(obj); + + if (obj is num || obj is String || obj is bool) return obj; + if (obj is Iterable) return obj.map(call).toList(); + if (obj is Map) return mapToData(obj); + return toDataUsingReflection(obj); + } + + mapToData(obj) { + var res = {}; + obj.forEach((k,v) { + res[call(k)] = call(v); + }); + return res; + } + + toDataUsingReflection(obj) { + final clazz = reflectClass(obj.runtimeType); + final instance = reflect(obj); + + return clazz.declarations.values.fold({}, (map, decl) { + if (decl is VariableMirror && !decl.isPrivate && !decl.isStatic) { + final field = instance.getField(decl.simpleName); + final name = MirrorSystem.getName(decl.simpleName); + map[name] = call(field.reflectee); + } + return map; + }); + } } \ No newline at end of file diff --git a/modules/angular2/test/test_lib/test_lib_spec.js b/modules/angular2/test/test_lib/test_lib_spec.js index d87de7a325..a3c06bb539 100644 --- a/modules/angular2/test/test_lib/test_lib_spec.js +++ b/modules/angular2/test/test_lib/test_lib_spec.js @@ -1,7 +1,7 @@ import {describe, it, iit, ddescribe, expect, tick, async, SpyObject, beforeEach, proxy} from 'angular2/test_lib'; import {MapWrapper, ListWrapper} from 'angular2/src/facade/collection'; import {PromiseWrapper} from 'angular2/src/facade/async'; -import {IMPLEMENTS} from 'angular2/src/facade/lang'; +import {IMPLEMENTS, Date, DateWrapper} from 'angular2/src/facade/lang'; class TestObj { prop; @@ -26,6 +26,10 @@ export function main() { expect(falseActual).not.toEqual(expected); }); + it('should structurally compare objects with private and static fields', () => { + expect(DateWrapper.fromMillis(1)).toEqual(DateWrapper.fromMillis(1)); + }); + it('should work for arrays of string maps', () => { expect([{'a':'b'}]).toEqual([{'a':'b'}]); });