1 | 'use strict'
|
2 |
|
3 | var EventEmitter = require('events').EventEmitter
|
4 | var test = require('tap').test
|
5 | var d = require('../')
|
6 |
|
7 | function functionA (a) { return a }
|
8 | var heinous = {
|
9 | nothin: null,
|
10 | nope: undefined,
|
11 | number: 0,
|
12 | funky: functionA,
|
13 | stringer: 'heya',
|
14 | then: new Date('1981-03-30'),
|
15 | rexpy: /^(pi|π)$/,
|
16 | granular: {
|
17 | stuff: [0, 1, 2]
|
18 | }
|
19 | }
|
20 | heinous.granular.self = heinous
|
21 |
|
22 | var awful = {
|
23 | nothin: null,
|
24 | nope: undefined,
|
25 | number: 0,
|
26 | funky: functionA,
|
27 | stringer: 'heya',
|
28 | then: new Date('1981-03-30'),
|
29 | rexpy: /^(pi|π)$/,
|
30 | granular: {
|
31 | stuff: [0, 1, 2]
|
32 | }
|
33 | }
|
34 | awful.granular.self = awful
|
35 |
|
36 | test('deeper handles all the edge cases', function (t) {
|
37 | |
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 | var functionB = functionA
|
44 |
|
45 |
|
46 | t.ok(d(null, null), 'null is the same as itself')
|
47 | t.ok(d(undefined, undefined), 'undefined is the same as itself')
|
48 | t.ok(d(0, 0), 'numbers check out')
|
49 | t.ok(d(1 / 0, 1 / 0), "it's a travesty that 1 / 0 = Infinity, but Infinities are equal")
|
50 | t.ok(d('ok', 'ok'), 'strings check out')
|
51 | t.ok(d(functionA, functionB), 'references to the same function are equal')
|
52 |
|
53 |
|
54 | var bufferA = new Buffer('abc')
|
55 | var bufferB = new Buffer('abc')
|
56 | t.ok(d(bufferA, bufferB), 'buffers are compared by value')
|
57 |
|
58 |
|
59 | var dateA = new Date('2001-01-11')
|
60 | var dateB = new Date('2001-01-11')
|
61 | t.ok(d(dateA, dateB), 'dates are compared by time value')
|
62 |
|
63 |
|
64 | var rexpA = /^h[oe][wl][dl][oy]$/
|
65 | var rexpB = /^h[oe][wl][dl][oy]$/
|
66 | t.ok(d(rexpA, rexpB), 'regexps are compared by their properties')
|
67 |
|
68 |
|
69 | t.ok(d({}, {}), 'bare objects check out')
|
70 | var a = { a: 'a' }
|
71 | var b = a
|
72 | t.ok(d(a, b), 'identical object references check out')
|
73 | b = { a: 'a' }
|
74 | t.ok(d(a, b), 'identical simple object values check out')
|
75 |
|
76 | t.ok(d([0, 1], [0, 1]), 'arrays check out')
|
77 |
|
78 | function onerror (error) { console.err(error.stack) }
|
79 | var eeA = new EventEmitter()
|
80 | eeA.on('error', onerror)
|
81 | var eeB = new EventEmitter()
|
82 | eeB.on('error', onerror)
|
83 | t.ok(d(eeA, eeB), 'more complex objects check out')
|
84 |
|
85 | var cyclicA = {}
|
86 | cyclicA.x = cyclicA
|
87 | var cyclicB = {}
|
88 | cyclicB.x = cyclicB
|
89 | t.ok(d(cyclicA, cyclicB), 'can handle cyclic data structures')
|
90 |
|
91 | var y = {v: {v: {v: {v: {v: {v: {v: {v: {v: {v: {v: {v: {v: {v: {v: {}}}}}}}}}}}}}}}}
|
92 | y.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v = y
|
93 | var z = {v: {v: {v: {v: {v: {v: {v: {v: {v: {v: {v: {v: {v: {v: {v: {}}}}}}}}}}}}}}}}
|
94 | z.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v = z
|
95 | t.ok(d(y, z), 'deeply recursive data structures also work')
|
96 |
|
97 | t.ok(d(heinous, awful), 'more complex objects also check out')
|
98 |
|
99 | awful.granular.self = heinous
|
100 | heinous.granular.self = awful
|
101 | t.ok(d(heinous, awful),
|
102 | 'mutual recursion with otherwise identical structures fools deepEquals')
|
103 |
|
104 | |
105 |
|
106 |
|
107 |
|
108 |
|
109 |
|
110 |
|
111 | t.notOk(d(NaN, NaN), 'NaN is the only JavaScript value not equal to itself')
|
112 | t.notOk(d(1 / 0, -1 / 0), 'opposite infinities are different')
|
113 | t.notOk(d(1, '1'), 'strict equality, no coercion between strings and numbers')
|
114 | t.notOk(d('ok', 'nok'), 'different strings are different')
|
115 | t.notOk(d(0, '0'), 'strict equality, no coercion between strings and numbers')
|
116 | t.notOk(d(undefined, null), 'so many kinds of nothingness!')
|
117 | t.notOk(d(function nop () {},
|
118 | function nop () {}), 'functions are only the same by reference')
|
119 |
|
120 |
|
121 | t.notOk(d(undefined, {}), "if both aren't objects, not the same")
|
122 |
|
123 |
|
124 | t.notOk(d({}, null), 'null is of type object')
|
125 |
|
126 |
|
127 | bufferB = new Buffer('abcd')
|
128 | t.notOk(d(bufferA, bufferB), 'Buffers are checked for length')
|
129 | bufferB = new Buffer('abd')
|
130 | t.notOk(d(bufferA, bufferB), 'Buffers are also checked for value')
|
131 |
|
132 |
|
133 | dateB = new Date('2001-01-12')
|
134 | t.notOk(d(dateA, dateB), 'different dates are not the same')
|
135 |
|
136 |
|
137 | rexpB = /^(howdy|hello)$/
|
138 | t.notOk(d(rexpA, rexpB), 'different regexps are not the same')
|
139 |
|
140 |
|
141 | var outer = arguments
|
142 | ;(function inner (tt) {
|
143 | var inner = arguments
|
144 | t.ok(d(outer, outer))
|
145 | t.ok(d(outer, inner))
|
146 | t.notOk(d(outer, [t]))
|
147 | }(t))
|
148 |
|
149 |
|
150 | t.notOk(d([], {}), "different object types shouldn't match")
|
151 |
|
152 | var nullstructor = Object.create(null)
|
153 | t.notOk(d({}, nullstructor), 'Object.create(null).constructor === undefined')
|
154 |
|
155 | b = { b: 'b' }
|
156 | t.notOk(d(a, b), "different object values aren't the same")
|
157 |
|
158 | var c = { b: 'b', c: undefined }
|
159 | t.notOk(d(b, c), "different object values aren't the same")
|
160 |
|
161 | function ondata (data) { console.log(data) }
|
162 | eeB.on('data', ondata)
|
163 | t.notOk(d(eeA, eeB), "changed objects don't match")
|
164 |
|
165 | awful.granular.stuff[2] = 3
|
166 | t.notOk(d(heinous, awful), 'small changes should be found')
|
167 |
|
168 | awful.granular.stuff[2] = 2
|
169 | t.ok(d(heinous, awful), 'small changes should be fixable')
|
170 |
|
171 | t.end()
|
172 | })
|