Skip to content

Commit e163eb2

Browse files
tboschmhevery
authored andcommitted
fix(test_lib): support deep compare of objects with private/static fields
1 parent 6748486 commit e163eb2

2 files changed

Lines changed: 73 additions & 3 deletions

File tree

modules/angular2/src/test_lib/test_lib.dart

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import 'dart:async';
88
import 'package:angular2/src/reflection/reflection.dart';
99
import 'package:angular2/src/facade/dom.dart';
1010
import 'package:angular2/src/reflection/reflection_capabilities.dart';
11+
import 'package:collection/equality.dart';
1112

1213
bool IS_DARTIUM = true;
1314

@@ -22,7 +23,9 @@ class Expect extends gns.Expect {
2223

2324
NotExpect get not => new NotExpect(actual);
2425

25-
void toEqual(expected) => toHaveSameProps(expected);
26+
// TODO(tbosch) change back when https://github.com/vsavkin/guinness/issues/41 is fixed
27+
// void toEqual(expected) => toHaveSameProps(expected);
28+
void toEqual(expected) => _expect(actual, new FixedSamePropsMatcher(expected));
2629
void toThrowError([message=""]) => this.toThrowWith(message: message);
2730
void toBePromise() => _expect(actual is Future, equals(true));
2831
void toImplement(expected) => toBeA(expected);
@@ -33,7 +36,10 @@ class Expect extends gns.Expect {
3336
class NotExpect extends gns.NotExpect {
3437
NotExpect(actual) : super(actual);
3538

36-
void toEqual(expected) => toHaveSameProps(expected);
39+
// TODO(tbosch) change back when https://github.com/vsavkin/guinness/issues/41 is fixed
40+
// void toEqual(expected) => toHaveSameProps(expected);
41+
void toEqual(expected) => _expect(actual, isNot(new FixedSamePropsMatcher(expected)));
42+
Function get _expect => gns.guinness.matchers.expect;
3743
}
3844

3945
beforeEach(fn) {
@@ -70,4 +76,64 @@ _handleAsync(fn) {
7076
}
7177

7278
return fn;
79+
}
80+
81+
// TODO(tbosch): remove when https://github.com/vsavkin/guinness/issues/41
82+
// is fixed
83+
class FixedSamePropsMatcher extends Matcher {
84+
final Object _expected;
85+
86+
const FixedSamePropsMatcher(this._expected);
87+
88+
bool matches(actual, Map matchState) {
89+
return compare(toData(_expected), toData(actual));
90+
}
91+
92+
Description describeMismatch(item, Description mismatchDescription,
93+
Map matchState, bool verbose) =>
94+
mismatchDescription.add('is equal to ${toData(item)}. Expected: ${toData(_expected)}');
95+
96+
Description describe(Description description) =>
97+
description.add('has different properties');
98+
99+
toData(obj) => new _FixedObjToData().call(obj);
100+
compare(d1, d2) => new DeepCollectionEquality().equals(d1, d2);
101+
}
102+
103+
// TODO(tbosch): remove when https://github.com/vsavkin/guinness/issues/41
104+
// is fixed
105+
class _FixedObjToData {
106+
final visitedObjects = new Set();
107+
108+
call(obj) {
109+
if (visitedObjects.contains(obj)) return null;
110+
visitedObjects.add(obj);
111+
112+
if (obj is num || obj is String || obj is bool) return obj;
113+
if (obj is Iterable) return obj.map(call).toList();
114+
if (obj is Map) return mapToData(obj);
115+
return toDataUsingReflection(obj);
116+
}
117+
118+
mapToData(obj) {
119+
var res = {};
120+
obj.forEach((k,v) {
121+
res[call(k)] = call(v);
122+
});
123+
return res;
124+
}
125+
126+
toDataUsingReflection(obj) {
127+
final clazz = reflectClass(obj.runtimeType);
128+
final instance = reflect(obj);
129+
130+
return clazz.declarations.values.fold({}, (map, decl) {
131+
if (decl is VariableMirror && !decl.isPrivate && !decl.isStatic) {
132+
final field = instance.getField(decl.simpleName);
133+
final name = MirrorSystem.getName(decl.simpleName);
134+
map[name] = call(field.reflectee);
135+
}
136+
return map;
137+
});
138+
}
73139
}

modules/angular2/test/test_lib/test_lib_spec.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {describe, it, iit, ddescribe, expect, tick, async, SpyObject, beforeEach, proxy} from 'angular2/test_lib';
22
import {MapWrapper, ListWrapper} from 'angular2/src/facade/collection';
33
import {PromiseWrapper} from 'angular2/src/facade/async';
4-
import {IMPLEMENTS} from 'angular2/src/facade/lang';
4+
import {IMPLEMENTS, Date, DateWrapper} from 'angular2/src/facade/lang';
55

66
class TestObj {
77
prop;
@@ -26,6 +26,10 @@ export function main() {
2626
expect(falseActual).not.toEqual(expected);
2727
});
2828

29+
it('should structurally compare objects with private and static fields', () => {
30+
expect(DateWrapper.fromMillis(1)).toEqual(DateWrapper.fromMillis(1));
31+
});
32+
2933
it('should work for arrays of string maps', () => {
3034
expect([{'a':'b'}]).toEqual([{'a':'b'}]);
3135
});

0 commit comments

Comments
 (0)