|
1 | 1 | /* eslint-disable no-control-regex */
|
2 | 2 | import { MongoshCommandFailed } from '@mongosh/errors';
|
3 |
| -import type { ServiceProvider } from '@mongosh/service-provider-core'; |
| 3 | +import type { |
| 4 | + AggregationCursor, |
| 5 | + ServiceProvider, |
| 6 | +} from '@mongosh/service-provider-core'; |
4 | 7 | import { bson } from '@mongosh/service-provider-core';
|
5 | 8 | import { ADMIN_DB } from '@mongosh/shell-api/lib/enums';
|
6 | 9 | import { CliUserConfig } from '@mongosh/types';
|
@@ -89,6 +92,14 @@ describe('MongoshNodeRepl', function () {
|
89 | 92 | },
|
90 | 93 | });
|
91 | 94 | sp.runCommandWithCheck.resolves({ ok: 1 });
|
| 95 | + |
| 96 | + if (process.env.USE_NEW_AUTOCOMPLETE) { |
| 97 | + sp.listCollections.resolves([{ name: 'coll' }]); |
| 98 | + const aggCursor = stubInterface<AggregationCursor>(); |
| 99 | + aggCursor.toArray.resolves([{ foo: 1, bar: 2 }]); |
| 100 | + sp.aggregate.returns(aggCursor); |
| 101 | + } |
| 102 | + |
92 | 103 | serviceProvider = sp;
|
93 | 104 | calledServiceProviderFunctions = () =>
|
94 | 105 | Object.fromEntries(
|
@@ -352,6 +363,14 @@ describe('MongoshNodeRepl', function () {
|
352 | 363 | };
|
353 | 364 | const tabtab = async () => {
|
354 | 365 | await tab();
|
| 366 | + if (process.env.USE_NEW_AUTOCOMPLETE) { |
| 367 | + // TODO: This is because autocomplete() is async and will either list |
| 368 | + // databases or collections or sample documents, any of which takes time |
| 369 | + // to complete and can time out. There is probably a better way. |
| 370 | + await new Promise((resolve) => { |
| 371 | + setTimeout(resolve, 210); |
| 372 | + }); |
| 373 | + } |
355 | 374 | await tab();
|
356 | 375 | };
|
357 | 376 |
|
@@ -379,19 +398,28 @@ describe('MongoshNodeRepl', function () {
|
379 | 398 | expect(output).to.include('65537');
|
380 | 399 | });
|
381 | 400 |
|
382 |
| - it('does not stop input when autocompleting during .editor', async function () { |
383 |
| - input.write('.editor\n'); |
384 |
| - await tick(); |
385 |
| - expect(output).to.include('Entering editor mode'); |
386 |
| - output = ''; |
387 |
| - input.write('db.'); |
388 |
| - await tabtab(); |
389 |
| - await tick(); |
390 |
| - input.write('version()\n'); |
391 |
| - input.write('\u0004'); // Ctrl+D |
392 |
| - await waitEval(bus); |
393 |
| - expect(output).to.include('Error running command serverBuildInfo'); |
394 |
| - }); |
| 401 | + context( |
| 402 | + `autocompleting during .editor [${ |
| 403 | + process.env.USE_NEW_AUTOCOMPLETE ?? 'old' |
| 404 | + }]`, |
| 405 | + function () { |
| 406 | + it('does not stop input when autocompleting during .editor', async function () { |
| 407 | + input.write('.editor\n'); |
| 408 | + await tick(); |
| 409 | + expect(output).to.include('Entering editor mode'); |
| 410 | + output = ''; |
| 411 | + input.write('db.'); |
| 412 | + await tabtab(); |
| 413 | + await tick(); |
| 414 | + input.write('version()\n'); |
| 415 | + input.write('\u0004'); // Ctrl+D |
| 416 | + await waitEval(bus); |
| 417 | + expect(output, output).to.include( |
| 418 | + 'Error running command serverBuildInfo' |
| 419 | + ); |
| 420 | + }); |
| 421 | + } |
| 422 | + ); |
395 | 423 |
|
396 | 424 | it('can enter multiline code', async function () {
|
397 | 425 | for (const line of multilineCode.split('\n')) {
|
@@ -449,73 +477,86 @@ describe('MongoshNodeRepl', function () {
|
449 | 477 | expect(code).to.equal(undefined);
|
450 | 478 | });
|
451 | 479 |
|
452 |
| - context('autocompletion', function () { |
453 |
| - it('autocompletes collection methods', async function () { |
454 |
| - input.write('db.coll.'); |
455 |
| - await tabtab(); |
456 |
| - await tick(); |
457 |
| - expect(output).to.include('db.coll.updateOne'); |
458 |
| - }); |
459 |
| - it('autocompletes shell-api methods (once)', async function () { |
460 |
| - input.write('vers'); |
461 |
| - await tabtab(); |
462 |
| - await tick(); |
463 |
| - expect(output).to.include('version'); |
464 |
| - expect(output).to.not.match(/version[ \t]+version/); |
465 |
| - }); |
466 |
| - it('autocompletes async shell api methods', async function () { |
467 |
| - input.write('db.coll.find().'); |
468 |
| - await tabtab(); |
469 |
| - await tick(); |
470 |
| - expect(output).to.include('db.coll.find().close'); |
471 |
| - }); |
472 |
| - it('autocompletes local variables', async function () { |
473 |
| - input.write('let somelongvariable = 0\n'); |
474 |
| - await waitEval(bus); |
475 |
| - output = ''; |
476 |
| - input.write('somelong'); |
477 |
| - await tabtab(); |
478 |
| - await tick(); |
479 |
| - expect(output).to.include('somelongvariable'); |
480 |
| - }); |
481 |
| - it('autocompletes partial repl commands', async function () { |
482 |
| - input.write('.e'); |
483 |
| - await tabtab(); |
484 |
| - await tick(); |
485 |
| - expect(output).to.include('editor'); |
486 |
| - expect(output).to.include('exit'); |
487 |
| - }); |
488 |
| - it('autocompletes full repl commands', async function () { |
489 |
| - input.write('.ed'); |
490 |
| - await tabtab(); |
491 |
| - await tick(); |
492 |
| - expect(output).to.include('.editor'); |
493 |
| - expect(output).not.to.include('exit'); |
494 |
| - }); |
495 |
| - it('autocompletion during .editor does not reset the prompt', async function () { |
496 |
| - input.write('.editor\n'); |
497 |
| - await tick(); |
498 |
| - output = ''; |
499 |
| - expect((mongoshRepl.runtimeState().repl as any)._prompt).to.equal(''); |
500 |
| - input.write('db.'); |
501 |
| - await tabtab(); |
502 |
| - await tick(); |
503 |
| - input.write('foo\nbar\n'); |
504 |
| - expect((mongoshRepl.runtimeState().repl as any)._prompt).to.equal(''); |
505 |
| - input.write('\u0003'); // Ctrl+C for abort |
506 |
| - await tick(); |
507 |
| - expect((mongoshRepl.runtimeState().repl as any)._prompt).to.equal( |
508 |
| - 'test> ' |
509 |
| - ); |
510 |
| - expect(stripAnsi(output)).to.equal('db.foo\r\nbar\r\n\r\ntest> '); |
511 |
| - }); |
512 |
| - it('does not autocomplete tab-indented code', async function () { |
513 |
| - output = ''; |
514 |
| - input.write('\t\tfoo'); |
515 |
| - await tick(); |
516 |
| - expect(output).to.equal('\t\tfoo'); |
517 |
| - }); |
518 |
| - }); |
| 480 | + context( |
| 481 | + `autocompletion [${process.env.USE_NEW_AUTOCOMPLETE ?? 'old'}]`, |
| 482 | + function () { |
| 483 | + it('autocompletes collection methods', async function () { |
| 484 | + input.write('db.coll.'); |
| 485 | + await tabtab(); |
| 486 | + await tick(); |
| 487 | + expect(output, output).to.include('db.coll.updateOne'); |
| 488 | + }); |
| 489 | + it('autocompletes collection schema fields', async function () { |
| 490 | + if (!process.env.USE_NEW_AUTOCOMPLETE) { |
| 491 | + // not supported in the old autocomplete |
| 492 | + this.skip(); |
| 493 | + } |
| 494 | + input.write('db.coll.find({'); |
| 495 | + await tabtab(); |
| 496 | + await tick(); |
| 497 | + expect(output, output).to.include('db.coll.find({foo'); |
| 498 | + }); |
| 499 | + it('autocompletes shell-api methods (once)', async function () { |
| 500 | + input.write('vers'); |
| 501 | + await tabtab(); |
| 502 | + await tick(); |
| 503 | + expect(output, output).to.include('version'); |
| 504 | + expect(output, output).to.not.match(/version[ \t]+version/); |
| 505 | + }); |
| 506 | + it('autocompletes async shell api methods', async function () { |
| 507 | + input.write('db.coll.find().'); |
| 508 | + await tabtab(); |
| 509 | + await tick(); |
| 510 | + expect(output, output).to.include('db.coll.find().toArray'); |
| 511 | + }); |
| 512 | + it('autocompletes local variables', async function () { |
| 513 | + input.write('let somelongvariable = 0\n'); |
| 514 | + await waitEval(bus); |
| 515 | + output = ''; |
| 516 | + input.write('somelong'); |
| 517 | + await tabtab(); |
| 518 | + await tick(); |
| 519 | + expect(output, output).to.include('somelongvariable'); |
| 520 | + }); |
| 521 | + it('autocompletes partial repl commands', async function () { |
| 522 | + input.write('.e'); |
| 523 | + await tabtab(); |
| 524 | + await tick(); |
| 525 | + expect(output, output).to.include('editor'); |
| 526 | + expect(output, output).to.include('exit'); |
| 527 | + }); |
| 528 | + it('autocompletes full repl commands', async function () { |
| 529 | + input.write('.ed'); |
| 530 | + await tabtab(); |
| 531 | + await tick(); |
| 532 | + expect(output, output).to.include('.editor'); |
| 533 | + expect(output, output).not.to.include('exit'); |
| 534 | + }); |
| 535 | + it('autocompletion during .editor does not reset the prompt', async function () { |
| 536 | + input.write('.editor\n'); |
| 537 | + await tick(); |
| 538 | + output = ''; |
| 539 | + expect((mongoshRepl.runtimeState().repl as any)._prompt).to.equal(''); |
| 540 | + input.write('db.'); |
| 541 | + await tabtab(); |
| 542 | + await tick(); |
| 543 | + input.write('foo\nbar\n'); |
| 544 | + expect((mongoshRepl.runtimeState().repl as any)._prompt).to.equal(''); |
| 545 | + input.write('\u0003'); // Ctrl+C for abort |
| 546 | + await tick(); |
| 547 | + expect((mongoshRepl.runtimeState().repl as any)._prompt).to.equal( |
| 548 | + 'test> ' |
| 549 | + ); |
| 550 | + expect(stripAnsi(output)).to.equal('db.foo\r\nbar\r\n\r\ntest> '); |
| 551 | + }); |
| 552 | + it('does not autocomplete tab-indented code', async function () { |
| 553 | + output = ''; |
| 554 | + input.write('\t\tfoo'); |
| 555 | + await tick(); |
| 556 | + expect(output, output).to.equal('\t\tfoo'); |
| 557 | + }); |
| 558 | + } |
| 559 | + ); |
519 | 560 |
|
520 | 561 | context('history support', function () {
|
521 | 562 | const arrowUp = '\x1b[A';
|
|
0 commit comments