@@ -132,22 +132,164 @@ class SystemError extends makeNodeError(Error) {
132
132
}
133
133
}
134
134
135
+ function createErrDiff ( actual , expected , operator ) {
136
+ var other = '' ;
137
+ var res = '' ;
138
+ var lastPos = 0 ;
139
+ var end = '' ;
140
+ var skipped = false ;
141
+ const actualLines = util
142
+ . inspect ( actual , { compact : false } ) . split ( '\n' ) ;
143
+ const expectedLines = util
144
+ . inspect ( expected , { compact : false } ) . split ( '\n' ) ;
145
+ const msg = `Input A expected to ${ operator } input B:\n` +
146
+ '\u001b[32m+ expected\u001b[39m \u001b[31m- actual\u001b[39m' ;
147
+ const skippedMsg = ' ... Lines skipped' ;
148
+
149
+ // Remove all ending lines that match (this optimizes the output for
150
+ // readability by reducing the number of total changed lines).
151
+ var a = actualLines [ actualLines . length - 1 ] ;
152
+ var b = expectedLines [ expectedLines . length - 1 ] ;
153
+ var i = 0 ;
154
+ while ( a === b ) {
155
+ if ( i ++ < 2 ) {
156
+ end = `\n ${ a } ${ end } ` ;
157
+ } else {
158
+ other = a ;
159
+ }
160
+ actualLines . pop ( ) ;
161
+ expectedLines . pop ( ) ;
162
+ a = actualLines [ actualLines . length - 1 ] ;
163
+ b = expectedLines [ expectedLines . length - 1 ] ;
164
+ }
165
+ if ( i > 3 ) {
166
+ end = `\n...${ end } ` ;
167
+ skipped = true ;
168
+ }
169
+ if ( other !== '' ) {
170
+ end = `\n ${ other } ${ end } ` ;
171
+ other = '' ;
172
+ }
173
+
174
+ const maxLines = Math . max ( actualLines . length , expectedLines . length ) ;
175
+ var printedLines = 0 ;
176
+ for ( i = 0 ; i < maxLines ; i ++ ) {
177
+ // Only extra expected lines exist
178
+ const cur = i - lastPos ;
179
+ if ( actualLines . length < i + 1 ) {
180
+ if ( cur > 1 && i > 2 ) {
181
+ if ( cur > 4 ) {
182
+ res += '\n...' ;
183
+ skipped = true ;
184
+ } else if ( cur > 3 ) {
185
+ res += `\n ${ expectedLines [ i - 2 ] } ` ;
186
+ printedLines ++ ;
187
+ }
188
+ res += `\n ${ expectedLines [ i - 1 ] } ` ;
189
+ printedLines ++ ;
190
+ }
191
+ lastPos = i ;
192
+ other += `\n\u001b[32m+\u001b[39m ${ expectedLines [ i ] } ` ;
193
+ printedLines ++ ;
194
+ // Only extra actual lines exist
195
+ } else if ( expectedLines . length < i + 1 ) {
196
+ if ( cur > 1 && i > 2 ) {
197
+ if ( cur > 4 ) {
198
+ res += '\n...' ;
199
+ skipped = true ;
200
+ } else if ( cur > 3 ) {
201
+ res += `\n ${ actualLines [ i - 2 ] } ` ;
202
+ printedLines ++ ;
203
+ }
204
+ res += `\n ${ actualLines [ i - 1 ] } ` ;
205
+ printedLines ++ ;
206
+ }
207
+ lastPos = i ;
208
+ res += `\n\u001b[31m-\u001b[39m ${ actualLines [ i ] } ` ;
209
+ printedLines ++ ;
210
+ // Lines diverge
211
+ } else if ( actualLines [ i ] !== expectedLines [ i ] ) {
212
+ if ( cur > 1 && i > 2 ) {
213
+ if ( cur > 4 ) {
214
+ res += '\n...' ;
215
+ skipped = true ;
216
+ } else if ( cur > 3 ) {
217
+ res += `\n ${ actualLines [ i - 2 ] } ` ;
218
+ printedLines ++ ;
219
+ }
220
+ res += `\n ${ actualLines [ i - 1 ] } ` ;
221
+ printedLines ++ ;
222
+ }
223
+ lastPos = i ;
224
+ res += `\n\u001b[31m-\u001b[39m ${ actualLines [ i ] } ` ;
225
+ other += `\n\u001b[32m+\u001b[39m ${ expectedLines [ i ] } ` ;
226
+ printedLines += 2 ;
227
+ // Lines are identical
228
+ } else {
229
+ res += other ;
230
+ other = '' ;
231
+ if ( cur === 1 || i === 0 ) {
232
+ res += `\n ${ actualLines [ i ] } ` ;
233
+ printedLines ++ ;
234
+ }
235
+ }
236
+ // Inspected object to big (Show ~20 rows max)
237
+ if ( printedLines > 20 && i < maxLines - 2 ) {
238
+ return `${ msg } ${ skippedMsg } \n${ res } \n...${ other } \n...` ;
239
+ }
240
+ }
241
+ return `${ msg } ${ skipped ? skippedMsg : '' } \n${ res } ${ other } ${ end } ` ;
242
+ }
243
+
135
244
class AssertionError extends Error {
136
245
constructor ( options ) {
137
246
if ( typeof options !== 'object' || options === null ) {
138
247
throw new exports . TypeError ( 'ERR_INVALID_ARG_TYPE' , 'options' , 'Object' ) ;
139
248
}
140
- var { actual, expected, message, operator, stackStartFn } = options ;
249
+ var {
250
+ actual,
251
+ expected,
252
+ message,
253
+ operator,
254
+ stackStartFn,
255
+ errorDiff = 0
256
+ } = options ;
257
+
141
258
if ( message != null ) {
142
259
super ( message ) ;
143
260
} else {
261
+ if ( util === null ) util = require ( 'util' ) ;
262
+
144
263
if ( actual && actual . stack && actual instanceof Error )
145
264
actual = `${ actual . name } : ${ actual . message } ` ;
146
265
if ( expected && expected . stack && expected instanceof Error )
147
266
expected = `${ expected . name } : ${ expected . message } ` ;
148
- if ( util === null ) util = require ( 'util' ) ;
149
- super ( `${ util . inspect ( actual ) . slice ( 0 , 128 ) } ` +
150
- `${ operator } ${ util . inspect ( expected ) . slice ( 0 , 128 ) } ` ) ;
267
+
268
+ if ( errorDiff === 0 ) {
269
+ let res = util . inspect ( actual ) ;
270
+ let other = util . inspect ( expected ) ;
271
+ if ( res . length > 128 )
272
+ res = `${ res . slice ( 0 , 125 ) } ...` ;
273
+ if ( other . length > 128 )
274
+ other = `${ other . slice ( 0 , 125 ) } ...` ;
275
+ super ( `${ res } ${ operator } ${ other } ` ) ;
276
+ } else if ( errorDiff === 1 ) {
277
+ // In case the objects are equal but the operator requires unequal, show
278
+ // the first object and say A equals B
279
+ const res = util
280
+ . inspect ( actual , { compact : false } ) . split ( '\n' ) ;
281
+
282
+ if ( res . length > 20 ) {
283
+ res [ 19 ] = '...' ;
284
+ while ( res . length > 20 ) {
285
+ res . pop ( ) ;
286
+ }
287
+ }
288
+ // Only print a single object.
289
+ super ( `Identical input passed to ${ operator } :\n${ res . join ( '\n' ) } ` ) ;
290
+ } else {
291
+ super ( createErrDiff ( actual , expected , operator ) ) ;
292
+ }
151
293
}
152
294
153
295
this . generatedMessage = ! message ;
0 commit comments