@@ -6,7 +6,6 @@ const MATRIX = [
6
6
{ name : 'string' , object : 'test' , serialized : '"test"' } ,
7
7
{ name : 'array' , object : [ 1 , 'test' ] , serialized : '[1,"test"]' } ,
8
8
{ name : 'object' , object : { a : 'test' } , serialized : '{"a":"test"}' } ,
9
- // TODO: Add tests for cyclic and deep objects
10
9
] ;
11
10
12
11
describe ( 'clone()' , ( ) => {
@@ -18,11 +17,207 @@ describe('clone()', () => {
18
17
} ) ;
19
18
20
19
describe ( 'serialize()' , ( ) => {
20
+ function jsonify ( obj : object ) : string {
21
+ return JSON . stringify ( obj ) ;
22
+ }
23
+
21
24
for ( const entry of MATRIX ) {
22
25
test ( `serializes a ${ entry . name } ` , ( ) => {
23
26
expect ( serialize ( entry . object ) ) . toEqual ( entry . serialized ) ;
24
27
} ) ;
25
28
}
29
+
30
+ describe ( 'cyclical structures' , ( ) => {
31
+ it ( 'must stringify circular objects' , ( ) => {
32
+ const obj = { name : 'Alice' } ;
33
+ // @ts -ignore
34
+ obj . self = obj ;
35
+
36
+ const json = serialize ( obj ) ;
37
+ expect ( json ) . toEqual ( jsonify ( { name : 'Alice' , self : '[Circular ~]' } ) ) ;
38
+ } ) ;
39
+
40
+ it ( 'must stringify circular objects with intermediaries' , ( ) => {
41
+ const obj = { name : 'Alice' } ;
42
+ // @ts -ignore
43
+ obj . identity = { self : obj } ;
44
+ const json = serialize ( obj ) ;
45
+ expect ( json ) . toEqual (
46
+ jsonify ( { name : 'Alice' , identity : { self : '[Circular ~]' } } ) ,
47
+ ) ;
48
+ } ) ;
49
+
50
+ it ( 'must stringify circular objects deeper' , ( ) => {
51
+ const obj = { name : 'Alice' , child : { name : 'Bob' } } ;
52
+ // @ts -ignore
53
+ obj . child . self = obj . child ;
54
+
55
+ expect ( serialize ( obj ) ) . toEqual (
56
+ jsonify ( {
57
+ name : 'Alice' ,
58
+ child : { name : 'Bob' , self : '[Circular ~.child]' } ,
59
+ } ) ,
60
+ ) ;
61
+ } ) ;
62
+
63
+ it ( 'must stringify circular objects deeper with intermediaries' , ( ) => {
64
+ const obj = { name : 'Alice' , child : { name : 'Bob' } } ;
65
+ // @ts -ignore
66
+ obj . child . identity = { self : obj . child } ;
67
+
68
+ expect ( serialize ( obj ) ) . toEqual (
69
+ jsonify ( {
70
+ name : 'Alice' ,
71
+ child : { name : 'Bob' , identity : { self : '[Circular ~.child]' } } ,
72
+ } ) ,
73
+ ) ;
74
+ } ) ;
75
+
76
+ it ( 'must stringify circular objects in an array' , ( ) => {
77
+ const obj = { name : 'Alice' } ;
78
+ // @ts -ignore
79
+ obj . self = [ obj , obj ] ;
80
+
81
+ expect ( serialize ( obj ) ) . toEqual (
82
+ jsonify ( {
83
+ name : 'Alice' ,
84
+ self : [ '[Circular ~]' , '[Circular ~]' ] ,
85
+ } ) ,
86
+ ) ;
87
+ } ) ;
88
+
89
+ it ( 'must stringify circular objects deeper in an array' , ( ) => {
90
+ const obj = {
91
+ name : 'Alice' ,
92
+ children : [ { name : 'Bob' } , { name : 'Eve' } ] ,
93
+ } ;
94
+ // @ts -ignore
95
+ obj . children [ 0 ] . self = obj . children [ 0 ] ;
96
+ // @ts -ignore
97
+ obj . children [ 1 ] . self = obj . children [ 1 ] ;
98
+
99
+ expect ( serialize ( obj ) ) . toEqual (
100
+ jsonify ( {
101
+ name : 'Alice' ,
102
+ children : [
103
+ { name : 'Bob' , self : '[Circular ~.children.0]' } ,
104
+ { name : 'Eve' , self : '[Circular ~.children.1]' } ,
105
+ ] ,
106
+ } ) ,
107
+ ) ;
108
+ } ) ;
109
+
110
+ it ( 'must stringify circular arrays' , ( ) => {
111
+ const obj : object [ ] = [ ] ;
112
+ obj . push ( obj ) ;
113
+ obj . push ( obj ) ;
114
+ const json = serialize ( obj ) ;
115
+ expect ( json ) . toEqual ( jsonify ( [ '[Circular ~]' , '[Circular ~]' ] ) ) ;
116
+ } ) ;
117
+
118
+ it ( 'must stringify circular arrays with intermediaries' , ( ) => {
119
+ const obj : object [ ] = [ ] ;
120
+ obj . push ( { name : 'Alice' , self : obj } ) ;
121
+ obj . push ( { name : 'Bob' , self : obj } ) ;
122
+
123
+ expect ( serialize ( obj ) ) . toEqual (
124
+ jsonify ( [
125
+ { name : 'Alice' , self : '[Circular ~]' } ,
126
+ { name : 'Bob' , self : '[Circular ~]' } ,
127
+ ] ) ,
128
+ ) ;
129
+ } ) ;
130
+
131
+ it ( 'must stringify repeated objects in objects' , ( ) => {
132
+ const obj = { } ;
133
+ const alice = { name : 'Alice' } ;
134
+ // @ts -ignore
135
+ obj . alice1 = alice ;
136
+ // @ts -ignore
137
+ obj . alice2 = alice ;
138
+
139
+ expect ( serialize ( obj ) ) . toEqual (
140
+ jsonify ( {
141
+ alice1 : { name : 'Alice' } ,
142
+ alice2 : { name : 'Alice' } ,
143
+ } ) ,
144
+ ) ;
145
+ } ) ;
146
+
147
+ it ( 'must stringify repeated objects in arrays' , ( ) => {
148
+ const alice = { name : 'Alice' } ;
149
+ const obj = [ alice , alice ] ;
150
+ const json = serialize ( obj ) ;
151
+ expect ( json ) . toEqual ( jsonify ( [ { name : 'Alice' } , { name : 'Alice' } ] ) ) ;
152
+ } ) ;
153
+
154
+ it ( 'must stringify error objects, including extra properties' , ( ) => {
155
+ const obj = new Error ( 'Wubba Lubba Dub Dub' ) ;
156
+ // @ts -ignore
157
+ obj . reason = new TypeError ( "I'm pickle Riiick!" ) ;
158
+ // @ts -ignore
159
+ obj . extra = 'some extra prop' ;
160
+
161
+ // Stack is inconsistent across browsers, so override it and just make sure its stringified
162
+ obj . stack = 'x' ;
163
+ // @ts -ignore
164
+ obj . reason . stack = 'x' ;
165
+
166
+ // IE 10/11
167
+ // @ts -ignore
168
+ delete obj . description ;
169
+ // @ts -ignore
170
+ delete obj . reason . description ;
171
+
172
+ // Safari doesn't allow deleting those properties from error object, yet only it provides them
173
+ const result = serialize ( obj )
174
+ . replace ( / + " ( l i n e | c o l u m n | s o u r c e U R L ) " : .+ , ? \n / g, '' )
175
+ . replace ( / , \n ( + ) } / g, '\n$1}' ) ; // make sure to strip trailing commas as well
176
+
177
+ expect ( result ) . toEqual (
178
+ jsonify ( {
179
+ message : 'Wubba Lubba Dub Dub' ,
180
+ name : 'Error' ,
181
+ stack : 'x' ,
182
+ reason : {
183
+ message : "I'm pickle Riiick!" ,
184
+ name : 'TypeError' ,
185
+ stack : 'x' ,
186
+ } ,
187
+ extra : 'some extra prop' ,
188
+ } ) ,
189
+ ) ;
190
+ } ) ;
191
+ } ) ;
192
+
193
+ it ( 'must stringify error objects with circular references' , ( ) => {
194
+ const obj = new Error ( 'Wubba Lubba Dub Dub' ) ;
195
+ // @ts -ignore
196
+ obj . reason = obj ;
197
+
198
+ // Stack is inconsistent across browsers, so override it and just make sure its stringified
199
+ obj . stack = 'x' ;
200
+ // @ts -ignore
201
+ obj . reason . stack = 'x' ;
202
+
203
+ // IE 10/11
204
+ // @ts -ignore
205
+ delete obj . description ;
206
+
207
+ // Safari doesn't allow deleting those properties from error object, yet only it provides them
208
+ const result = serialize ( obj )
209
+ . replace ( / + " ( l i n e | c o l u m n | s o u r c e U R L ) " : .+ , ? \n / g, '' )
210
+ . replace ( / , \n ( + ) } / g, '\n$1}' ) ; // make sure to strip trailing commas as well
211
+
212
+ expect ( result ) . toEqual (
213
+ jsonify ( {
214
+ message : 'Wubba Lubba Dub Dub' ,
215
+ name : 'Error' ,
216
+ stack : 'x' ,
217
+ reason : '[Circular ~]' ,
218
+ } ) ,
219
+ ) ;
220
+ } ) ;
26
221
} ) ;
27
222
28
223
describe ( 'deserialize()' , ( ) => {
0 commit comments