@@ -588,4 +588,140 @@ describe('BSON e2e', function () {
588588 shell . assertNoErrors ( ) ;
589589 } ) ;
590590 } ) ;
591+ describe ( 'inspect nesting depth' , function ( ) {
592+ const deepAndNestedDefinition = `({
593+ a: { b: { c: { d: { e: { f: { g: { h: "foundme" } } } } } } },
594+ array: [...Array(100000).keys()].map(i => ({ num: i })),
595+ str: 'All work and no playmakes Jack a dull boy'.repeat(4096) + 'The End'
596+ })` ;
597+ const checkForDeepOutput = ( output : string , wantFullOutput : boolean ) => {
598+ if ( wantFullOutput ) {
599+ expect ( output ) . not . to . include ( '[Object' ) ;
600+ expect ( output ) . not . to . include ( 'more items' ) ;
601+ expect ( output ) . to . include ( 'foundme' ) ;
602+ expect ( output ) . to . include ( 'num: 99999' ) ;
603+ expect ( output ) . to . include ( 'The End' ) ;
604+ } else {
605+ expect ( output ) . to . include ( '[Object' ) ;
606+ expect ( output ) . to . include ( 'more items' ) ;
607+ expect ( output ) . not . to . include ( 'foundme' ) ;
608+ expect ( output ) . not . to . include ( 'num: 99999' ) ;
609+ expect ( output ) . not . to . include ( 'The End' ) ;
610+ }
611+ } ;
612+
613+ beforeEach ( async function ( ) {
614+ await shell . executeLine ( `use ${ dbName } ` ) ;
615+ await shell . executeLine ( `deepAndNested = ${ deepAndNestedDefinition } ` ) ;
616+ await shell . executeLine ( `db.coll.insertOne(deepAndNested)` ) ;
617+ } ) ;
618+
619+ it ( 'inspects a full bson document when it is read from the server (interactive mode)' , async function ( ) {
620+ // Deeply nested object from the server should be fully printed
621+ const output = await shell . executeLine ( 'db.coll.findOne()' ) ;
622+ checkForDeepOutput ( output , true ) ;
623+ // Same object doesn't need to be fully printed if created by the user
624+ const output2 = await shell . executeLine ( 'deepAndNested' ) ;
625+ checkForDeepOutput ( output2 , false ) ;
626+ shell . assertNoErrors ( ) ;
627+ } ) ;
628+
629+ it ( 'can explicitly disable full-depth nesting (interactive mode)' , async function ( ) {
630+ shell . kill ( ) ;
631+ shell = this . startTestShell ( {
632+ args : [ await testServer . connectionString ( ) , '--deepInspect=false' ] ,
633+ } ) ;
634+ await shell . waitForPrompt ( ) ;
635+ await shell . executeLine ( `use ${ dbName } ` ) ;
636+ const output = await shell . executeLine ( 'db.coll.findOne()' ) ;
637+ checkForDeepOutput ( output , false ) ;
638+ shell . assertNoErrors ( ) ;
639+ } ) ;
640+
641+ it ( 'does not deeply inspect objects in non-interactive mode for intermediate output' , async function ( ) {
642+ shell . kill ( ) ;
643+ shell = this . startTestShell ( {
644+ args : [
645+ await testServer . connectionString ( ) ,
646+ '--eval' ,
647+ `use(${ JSON . stringify ( dbName ) } ); print(db.coll.findOne()); 0` ,
648+ ] ,
649+ } ) ;
650+ checkForDeepOutput ( await shell . waitForCleanOutput ( ) , false ) ;
651+ shell = this . startTestShell ( {
652+ args : [
653+ await testServer . connectionString ( ) ,
654+ '--eval' ,
655+ `print(${ deepAndNestedDefinition } ); 0` ,
656+ ] ,
657+ } ) ;
658+ checkForDeepOutput ( await shell . waitForCleanOutput ( ) , false ) ;
659+ } ) ;
660+
661+ it ( 'inspect full objects in non-interactive mode for final output' , async function ( ) {
662+ shell . kill ( ) ;
663+ shell = this . startTestShell ( {
664+ args : [
665+ await testServer . connectionString ( ) ,
666+ '--eval' ,
667+ `use(${ JSON . stringify ( dbName ) } ); db.coll.findOne();` ,
668+ ] ,
669+ } ) ;
670+ checkForDeepOutput ( await shell . waitForCleanOutput ( ) , true ) ;
671+ shell = this . startTestShell ( {
672+ args : [
673+ await testServer . connectionString ( ) ,
674+ '--eval' ,
675+ deepAndNestedDefinition ,
676+ ] ,
677+ } ) ;
678+ checkForDeepOutput ( await shell . waitForCleanOutput ( ) , true ) ;
679+ } ) ;
680+
681+ it ( 'can explicitly disable full-depth nesting (non-interactive mode)' , async function ( ) {
682+ shell . kill ( ) ;
683+ shell = this . startTestShell ( {
684+ args : [
685+ await testServer . connectionString ( ) ,
686+ '--deepInspect=false' ,
687+ '--eval' ,
688+ `use(${ JSON . stringify ( dbName ) } ); db.coll.findOne();` ,
689+ ] ,
690+ } ) ;
691+ checkForDeepOutput ( await shell . waitForCleanOutput ( ) , false ) ;
692+ shell = this . startTestShell ( {
693+ args : [
694+ await testServer . connectionString ( ) ,
695+ '--deepInspect=false' ,
696+ '--eval' ,
697+ deepAndNestedDefinition ,
698+ ] ,
699+ } ) ;
700+ checkForDeepOutput ( await shell . waitForCleanOutput ( ) , false ) ;
701+ } ) ;
702+
703+ it ( 'can parse serverStatus back to its original form' , async function ( ) {
704+ // Dates get special treatment but that doesn't currently apply
705+ // to mongosh's util.inspect that's available to users
706+ // (although maybe it should?).
707+ await shell . executeLine (
708+ `Date.prototype[Symbol.for('nodejs.util.inspect.custom')] = function(){ return 'ISODate("' + this.toISOString() + '")'; };`
709+ ) ;
710+ // 'void 0' to avoid large output in the shell from serverStatus
711+ await shell . executeLine (
712+ 'A = db.adminCommand({ serverStatus: 1 }); void 0'
713+ ) ;
714+ await shell . executeLine ( 'util.inspect(A)' ) ;
715+ await shell . executeLine ( `B = eval('(' + util.inspect(A) + ')'); void 0` ) ;
716+ shell . assertNoErrors ( ) ;
717+ const output1 = await shell . executeLineWithJSONResult ( 'A' , {
718+ parseAsEJSON : false ,
719+ } ) ;
720+ const output2 = await shell . executeLineWithJSONResult ( 'B' , {
721+ parseAsEJSON : false ,
722+ } ) ;
723+ expect ( output1 ) . to . deep . equal ( output2 ) ;
724+ shell . assertNoErrors ( ) ;
725+ } ) ;
726+ } ) ;
591727} ) ;
0 commit comments