@@ -13,11 +13,12 @@ const { SourceCode } = eslint;
13
13
const ruleFixer = require ( 'eslint/lib/util/rule-fixer' ) ;
14
14
const Traverser = require ( 'eslint/lib/util/traverser' ) ;
15
15
const SourceCodeFixer = require ( 'eslint/lib/util/source-code-fixer' ) ;
16
- const { encode, decode } = require ( '../lib/stringSnapshot' ) ;
16
+ const indentString = require ( './indentString' ) ;
17
+ const isSimpleObjectTree = require ( './isSimpleObjectTree' ) ;
17
18
18
19
function stringify ( obj , indentationWidth , expectForRendering ) {
19
- if ( typeof obj === 'string' ) {
20
- return `\`${ encode ( obj , indentationWidth ) } \`` ;
20
+ if ( obj . includes ( '\n' ) ) {
21
+ return `expect.unindent \`${ indentString ( obj , indentationWidth ) } \`` ;
21
22
} else {
22
23
expectForRendering . output . indentationWidth = indentationWidth ;
23
24
return expectForRendering . inspect ( obj ) . toString ( 'text' ) ;
@@ -173,7 +174,8 @@ function ensureAfterBlockIsRegistered() {
173
174
columnNumber,
174
175
status,
175
176
subject,
176
- expectForRendering
177
+ expectForRendering,
178
+ assertionName
177
179
} of topLevelFixes ) {
178
180
const sourceCode = getSourceCode ( fileName ) ;
179
181
if ( ! sourceCode ) {
@@ -209,7 +211,6 @@ function ensureAfterBlockIsRegistered() {
209
211
return '' ;
210
212
}
211
213
}
212
-
213
214
new Traverser ( ) . traverse ( sourceCode . ast , {
214
215
enter ( node , parent ) {
215
216
if (
@@ -230,29 +231,63 @@ function ensureAfterBlockIsRegistered() {
230
231
} else {
231
232
indent = getNodeIndent ( node . arguments [ 1 ] ) ;
232
233
}
233
- const stringifiedSubject = stringify (
234
- subject ,
235
- indentationWidth ,
236
- expectForRendering
237
- ) . replace ( / \n ^ (? = [ ^ \n ] ) / gm, `\n${ indent } ` ) ;
238
-
239
- let fix ;
234
+ const fixes = [ ] ;
235
+ let stringifiedSubject ;
236
+ let newAssertionName = 'to equal snapshot' ;
237
+ if ( typeof subject === 'string' ) {
238
+ stringifiedSubject = stringify (
239
+ subject ,
240
+ indentationWidth ,
241
+ expectForRendering
242
+ ) . replace ( / \n ^ (? = [ ^ \n ] ) / gm, `\n${ indent } ` ) ;
243
+ } else if ( isSimpleObjectTree ( subject , expectForRendering ) ) {
244
+ expectForRendering . output . indentationWidth = indentationWidth ;
245
+ stringifiedSubject = expectForRendering
246
+ . inspect ( subject )
247
+ . toString ( 'text' ) ;
248
+ } else {
249
+ newAssertionName = 'to inspect as snapshot' ;
250
+ stringifiedSubject = stringify (
251
+ expectForRendering . inspect ( subject ) . toString ( 'text' ) ,
252
+ indentationWidth ,
253
+ expectForRendering
254
+ ) . replace ( / \n ^ (? = [ ^ \n ] ) / gm, `\n${ indent } ` ) ;
255
+ }
240
256
if ( status === 'missing' ) {
241
- fix = ruleFixer . insertTextAfter (
242
- node . arguments [ node . arguments . length - 1 ] ,
243
- `, ${ stringifiedSubject } `
244
- ) ;
257
+ if ( newAssertionName !== assertionName ) {
258
+ fixes . unshift (
259
+ ruleFixer . replaceText (
260
+ node . arguments [ 1 ] ,
261
+ `'${ newAssertionName } ', ${ stringifiedSubject } `
262
+ )
263
+ ) ;
264
+ } else {
265
+ fixes . unshift (
266
+ ruleFixer . insertTextAfter (
267
+ node . arguments [ node . arguments . length - 1 ] ,
268
+ `, ${ stringifiedSubject } `
269
+ )
270
+ ) ;
271
+ }
245
272
} else if ( status === 'mismatch' ) {
246
- fix = ruleFixer . replaceText (
247
- node . arguments [ node . arguments . length - 1 ] ,
248
- stringifiedSubject
273
+ if ( newAssertionName !== assertionName ) {
274
+ fixes . unshift (
275
+ ruleFixer . replaceText (
276
+ node . arguments [ 1 ] ,
277
+ `'${ newAssertionName } '`
278
+ )
279
+ ) ;
280
+ }
281
+ fixes . unshift (
282
+ ruleFixer . replaceText (
283
+ node . arguments [ node . arguments . length - 1 ] ,
284
+ stringifiedSubject
285
+ )
249
286
) ;
250
287
}
251
- if ( fix ) {
288
+ if ( fixes . length > 0 ) {
252
289
( fixesByFileName [ fileName ] =
253
- fixesByFileName [ fileName ] || [ ] ) . push ( {
254
- fix
255
- } ) ;
290
+ fixesByFileName [ fileName ] || [ ] ) . push ( ...fixes ) ;
256
291
}
257
292
}
258
293
}
@@ -263,7 +298,7 @@ function ensureAfterBlockIsRegistered() {
263
298
for ( const fileName of Object . keys ( fixesByFileName ) ) {
264
299
var fixResult = SourceCodeFixer . applyFixes (
265
300
getSourceCode ( fileName ) . text ,
266
- fixesByFileName [ fileName ]
301
+ fixesByFileName [ fileName ] . map ( fix => ( { fix } ) )
267
302
) ;
268
303
if ( fixResult . fixed ) {
269
304
fixedSourceTextByFileName [ fileName ] = fixResult . output ;
@@ -394,52 +429,6 @@ module.exports = {
394
429
installInto ( expect ) {
395
430
const expectForRendering = expect . child ( ) ;
396
431
397
- // Copy of https://github.com/unexpectedjs/unexpected/blob/bf9bb959b85459eee43e550f8dfea43bead2e7b1/lib/createTopLevelExpect.js#L274
398
- // so that we get to control the handling of circular references
399
- const defaultDepth = 3 ;
400
- expectForRendering . inspect = function ( obj , depth , outputOrFormat ) {
401
- let seen = [ ] ;
402
- let printOutput = ( obj , currentDepth , output ) => {
403
- const objType = this . findTypeOf ( obj ) ;
404
- if (
405
- currentDepth <= 0 &&
406
- objType . is ( 'object' ) &&
407
- ! objType . is ( 'expect.it' )
408
- ) {
409
- return output . text ( '...' ) ;
410
- }
411
-
412
- seen = seen || [ ] ;
413
- if ( seen . indexOf ( obj ) !== - 1 ) {
414
- throw new Error ( 'Circular references not supported in snapshots' ) ;
415
- }
416
-
417
- return objType . inspect ( obj , currentDepth , output , ( v , childDepth ) => {
418
- output = output . clone ( ) ;
419
- seen . push ( obj ) ;
420
- if ( typeof childDepth === 'undefined' ) {
421
- childDepth = currentDepth - 1 ;
422
- }
423
- output = printOutput ( v , childDepth , output ) || output ;
424
- seen . pop ( ) ;
425
- return output ;
426
- } ) ;
427
- } ;
428
-
429
- let output =
430
- typeof outputOrFormat === 'string'
431
- ? this . createOutput ( outputOrFormat )
432
- : outputOrFormat ;
433
- output = output || this . createOutput ( ) ;
434
- return (
435
- printOutput (
436
- obj ,
437
- typeof depth === 'number' ? depth : defaultDepth ,
438
- output
439
- ) || output
440
- ) ;
441
- } ;
442
-
443
432
expectForRendering . addType ( {
444
433
name : 'infiniteBuffer' ,
445
434
base : 'Buffer' ,
@@ -523,21 +512,22 @@ module.exports = {
523
512
const symbol = Symbol ( 'unexpectedSnapshot' ) ;
524
513
525
514
expect . addAssertion (
526
- '<any> to equal snapshot <any?>' ,
515
+ '<any> to ( equal|inspect as) snapshot <any?>' ,
527
516
( expect , subject , ...args ) => {
517
+ const assertionName = `to ${ expect . alternations [ 0 ] } snapshot` ;
518
+ if ( expect . alternations [ 0 ] === 'inspect as' ) {
519
+ subject = expectForRendering . inspect ( subject ) . toString ( 'text' ) ;
520
+ }
528
521
if ( args . length === 1 ) {
529
- let value = args [ 0 ] ;
530
- if ( typeof value === 'string' ) {
531
- value = decode ( value ) ;
532
- }
533
522
return expect . withError (
534
523
( ) => {
535
- expect ( subject , 'to equal' , value ) ;
524
+ expect ( subject , 'to equal' , args [ 0 ] ) ;
536
525
} ,
537
526
err => {
538
527
topLevelFixes . push ( {
539
528
...expect . context [ symbol ] ,
540
529
subject,
530
+ assertionName,
541
531
status : 'mismatch'
542
532
} ) ;
543
533
ensureAfterBlockIsRegistered ( ) ;
@@ -549,6 +539,7 @@ module.exports = {
549
539
topLevelFixes . push ( {
550
540
...expect . context [ symbol ] ,
551
541
subject,
542
+ assertionName,
552
543
status : 'missing'
553
544
} ) ;
554
545
ensureAfterBlockIsRegistered ( ) ;
@@ -562,6 +553,8 @@ module.exports = {
562
553
}
563
554
) ;
564
555
556
+ expect . unindent = require ( '@gustavnikolaj/string-utils' ) . deindent ;
557
+
565
558
expect . hook ( function ( next ) {
566
559
return function unexpectedSnapshot ( context , ...rest ) {
567
560
if ( ! context [ symbol ] ) {
0 commit comments