Skip to content

Commit 4516723

Browse files
committed
fix tests for new autocomplete
1 parent 23ea819 commit 4516723

File tree

6 files changed

+138
-70
lines changed

6 files changed

+138
-70
lines changed

packages/cli-repl/src/cli-repl.spec.ts

Lines changed: 97 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2442,15 +2442,52 @@ describe('CliRepl', function () {
24422442
hasCollectionNames: boolean;
24432443
hasDatabaseNames: boolean;
24442444
}): void {
2445+
let wantVersion = true;
2446+
let wantQueryOperators = true;
2447+
2448+
if (process.env.USE_NEW_AUTOCOMPLETE && !testServer) {
2449+
// mongodb-ts-autocomplete does not support noDb mode. It wouldn't be able
2450+
// to list collections anyway, and since the collections don't exist it
2451+
// wouldn't autocomplete methods on those collections.
2452+
wantVersion = false;
2453+
wantQueryOperators = false;
2454+
wantWatch = false;
2455+
wantShardDistribution = false;
2456+
hasCollectionNames = false;
2457+
hasDatabaseNames = false;
2458+
}
2459+
2460+
if (process.env.USE_NEW_AUTOCOMPLETE && testServer) {
2461+
if ((testServer as any)?._opts.args?.includes('--auth')) {
2462+
// mongodb-ts-autocomplete does not take into account the server version
2463+
// or capabilities, so it always completes db.watch
2464+
wantWatch = true;
2465+
// db.collection.getShardDistribution won't be autocompleted because we
2466+
// can't list the collections due to to auth being required
2467+
wantShardDistribution = false;
2468+
// we can't get the document schema because auth is required
2469+
wantQueryOperators = false;
2470+
} else {
2471+
// mongodb-ts-autocomplete does not take into account the server version
2472+
// or capabilities, so it always completes db.watch and
2473+
// db.collection.getShardDistribution assuming collection exists and can
2474+
// be listed
2475+
wantWatch = true;
2476+
wantShardDistribution = true;
2477+
2478+
// TODO: we need MQL support in mongodb-ts-autocomplete in order for it
2479+
// to autocomplete collection field names
2480+
wantQueryOperators = false;
2481+
}
2482+
}
2483+
24452484
describe('autocompletion', function () {
24462485
let cliRepl: CliRepl;
2447-
const tab = async () => {
2486+
2487+
const tabCompletion = async () => {
24482488
await tick();
24492489
input.write('\u0009');
2450-
};
2451-
const tabtab = async () => {
2452-
await tab();
2453-
await tab();
2490+
await waitCompletion(cliRepl.bus);
24542491
};
24552492

24562493
beforeEach(async function () {
@@ -2463,6 +2500,13 @@ describe('CliRepl', function () {
24632500
testServer ? await testServer.connectionString() : '',
24642501
{} as any
24652502
);
2503+
2504+
if (!(testServer as any)?._opts.args?.includes('--auth')) {
2505+
// make sure there are some collections we can autocomplete on below
2506+
input.write('db.coll.insertOne({})\n');
2507+
input.write('db.movies.insertOne({})\n');
2508+
await waitEval(cliRepl.bus);
2509+
}
24662510
});
24672511

24682512
afterEach(async function () {
@@ -2479,26 +2523,33 @@ describe('CliRepl', function () {
24792523
if (process.env.MONGOSH_TEST_FORCE_API_STRICT) {
24802524
return this.skip();
24812525
}
2526+
24822527
output = '';
24832528
input.write('db.wat');
2484-
await tabtab();
2485-
await waitCompletion(cliRepl.bus);
2529+
await tabCompletion();
2530+
await tabCompletion();
24862531
if (wantWatch) {
24872532
expect(output).to.include('db.watch');
24882533
} else {
24892534
expect(output).not.to.include('db.watch');
24902535
}
24912536
});
24922537

2493-
it('completes the version method', async function () {
2538+
it(`${
2539+
wantVersion ? 'completes' : 'does not complete'
2540+
} the version method`, async function () {
24942541
if (process.env.MONGOSH_TEST_FORCE_API_STRICT) {
24952542
return this.skip();
24962543
}
24972544
output = '';
24982545
input.write('db.vers');
2499-
await tabtab();
2500-
await waitCompletion(cliRepl.bus);
2501-
expect(output).to.include('db.version');
2546+
await tabCompletion();
2547+
await tabCompletion();
2548+
if (wantVersion) {
2549+
expect(output).to.include('db.version');
2550+
} else {
2551+
expect(output).to.not.include('db.version');
2552+
}
25022553
});
25032554

25042555
it('does not complete legacy JS get/set definitions', async function () {
@@ -2507,8 +2558,8 @@ describe('CliRepl', function () {
25072558
}
25082559
output = '';
25092560
input.write('JSON.');
2510-
await tabtab();
2511-
await waitCompletion(cliRepl.bus);
2561+
await tabCompletion();
2562+
await tabCompletion();
25122563
expect(output).to.include('JSON.__proto__');
25132564
expect(output).not.to.include('JSON.__defineGetter__');
25142565
expect(output).not.to.include('JSON.__defineSetter__');
@@ -2524,8 +2575,8 @@ describe('CliRepl', function () {
25242575
}
25252576
output = '';
25262577
input.write('db.coll.getShardDis');
2527-
await tabtab();
2528-
await waitCompletion(cliRepl.bus);
2578+
await tabCompletion();
2579+
await tabCompletion();
25292580
if (wantShardDistribution) {
25302581
expect(output).to.include('db.coll.getShardDistribution');
25312582
} else {
@@ -2543,8 +2594,8 @@ describe('CliRepl', function () {
25432594

25442595
output = '';
25452596
input.write('db.testcoll');
2546-
await tabtab();
2547-
await waitCompletion(cliRepl.bus);
2597+
await tabCompletion();
2598+
await tabCompletion();
25482599
expect(output).to.include(collname);
25492600

25502601
input.write(`db.${collname}.drop()\n`);
@@ -2553,50 +2604,63 @@ describe('CliRepl', function () {
25532604

25542605
it('completes JS value properties properly (incomplete, double tab)', async function () {
25552606
input.write('JSON.');
2556-
await tabtab();
2557-
await waitCompletion(cliRepl.bus);
2607+
await tabCompletion();
2608+
await tabCompletion();
25582609
expect(output).to.include('JSON.parse');
25592610
expect(output).to.include('JSON.stringify');
25602611
expect(output).not.to.include('rawValue');
25612612
});
25622613

25632614
it('completes JS value properties properly (complete, single tab)', async function () {
25642615
input.write('JSON.pa');
2565-
await tab();
2566-
await waitCompletion(cliRepl.bus);
2616+
await tabCompletion();
25672617
expect(output).to.include('JSON.parse');
25682618
expect(output).not.to.include('JSON.stringify');
25692619
expect(output).not.to.include('rawValue');
25702620
});
25712621

25722622
it('completes shell commands', async function () {
2623+
if (process.env.USE_NEW_AUTOCOMPLETE) {
2624+
// TODO(MONGOSH-2035): not supported yet
2625+
this.skip();
2626+
}
2627+
25732628
input.write('const dSomeVariableStartingWithD = 10;\n');
25742629
await waitEval(cliRepl.bus);
25752630

25762631
output = '';
25772632
input.write('show d');
2578-
await tab();
2579-
await waitCompletion(cliRepl.bus);
2633+
await tabCompletion();
25802634
expect(output).to.include('show databases');
25812635
expect(output).not.to.include('dSomeVariableStartingWithD');
25822636
});
25832637

25842638
it('completes use <db>', async function () {
2639+
if (process.env.USE_NEW_AUTOCOMPLETE) {
2640+
// TODO(MONGOSH-2035): not supported yet
2641+
this.skip();
2642+
}
2643+
25852644
if (!hasDatabaseNames) return this.skip();
25862645
input.write('db.getMongo()._listDatabases()\n'); // populate database cache
25872646
await waitEval(cliRepl.bus);
25882647

25892648
input.write('use adm');
2590-
await tab();
2591-
await waitCompletion(cliRepl.bus);
2649+
await tabCompletion();
25922650
expect(output).to.include('use admin');
25932651
});
25942652

2595-
it('completes query operators', async function () {
2653+
it(`${
2654+
wantQueryOperators ? 'completes' : 'does not complete'
2655+
} query operators`, async function () {
25962656
input.write('db.movies.find({year: {$g');
2597-
await tabtab();
2598-
await waitCompletion(cliRepl.bus);
2599-
expect(output).to.include('db.movies.find({year: {$gte');
2657+
await tabCompletion();
2658+
await tabCompletion();
2659+
if (wantQueryOperators) {
2660+
expect(output).to.include('db.movies.find({year: {$gte');
2661+
} else {
2662+
expect(output).to.not.include('db.movies.find({year: {$gte');
2663+
}
26002664
});
26012665

26022666
it('completes properties of shell API result types', async function () {
@@ -2614,8 +2678,8 @@ describe('CliRepl', function () {
26142678
expect(output).to.include('DeleteResult');
26152679

26162680
input.write('res.a');
2617-
await tabtab();
2618-
await waitCompletion(cliRepl.bus);
2681+
await tabCompletion();
2682+
await tabCompletion();
26192683
expect(output).to.include('res.acknowledged');
26202684
});
26212685

@@ -2631,8 +2695,8 @@ describe('CliRepl', function () {
26312695

26322696
output = '';
26332697
input.write('db.actestc');
2634-
await tabtab();
2635-
await waitCompletion(cliRepl.bus);
2698+
await tabCompletion();
2699+
await tabCompletion();
26362700
expect(output).to.include('db.actestcoll1');
26372701
expect(output).to.not.include('db.actestcoll2');
26382702
});

packages/cli-repl/src/mongosh-repl.spec.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ import {
1919
fakeTTYProps,
2020
tick,
2121
useTmpdir,
22+
waitCompletion,
2223
waitEval,
23-
waitMongoshCompletionResults,
2424
} from '../test/repl-helpers';
2525
import type { MongoshIOProvider, MongoshNodeReplOptions } from './mongosh-repl';
2626
import MongoshNodeRepl from './mongosh-repl';
@@ -364,9 +364,6 @@ describe('MongoshNodeRepl', function () {
364364
};
365365
const tabtab = async () => {
366366
await tab();
367-
if (process.env.USE_NEW_AUTOCOMPLETE) {
368-
await waitMongoshCompletionResults(bus);
369-
}
370367
await tab();
371368
};
372369

@@ -406,6 +403,7 @@ describe('MongoshNodeRepl', function () {
406403
output = '';
407404
input.write('db.');
408405
await tabtab();
406+
await waitCompletion(bus);
409407
await tick();
410408
input.write('version()\n');
411409
input.write('\u0004'); // Ctrl+D
@@ -479,29 +477,30 @@ describe('MongoshNodeRepl', function () {
479477
it('autocompletes collection methods', async function () {
480478
input.write('db.coll.');
481479
await tabtab();
480+
await waitCompletion(bus);
482481
await tick();
483482
expect(output, output).to.include('db.coll.updateOne');
484483
});
485-
it('autocompletes collection schema fields', async function () {
486-
if (!process.env.USE_NEW_AUTOCOMPLETE) {
487-
// not supported in the old autocomplete
488-
this.skip();
489-
}
484+
// this will eventually be supported in the new autocomplete
485+
it.skip('autocompletes collection schema fields', async function () {
490486
input.write('db.coll.find({');
491487
await tabtab();
488+
await waitCompletion(bus);
492489
await tick();
493490
expect(output, output).to.include('db.coll.find({foo');
494491
});
495492
it('autocompletes shell-api methods (once)', async function () {
496493
input.write('vers');
497494
await tabtab();
495+
await waitCompletion(bus);
498496
await tick();
499497
expect(output, output).to.include('version');
500498
expect(output, output).to.not.match(/version[ \t]+version/);
501499
});
502500
it('autocompletes async shell api methods', async function () {
503501
input.write('db.coll.find().');
504502
await tabtab();
503+
await waitCompletion(bus);
505504
await tick();
506505
expect(output, output).to.include('db.coll.find().toArray');
507506
});
@@ -511,19 +510,22 @@ describe('MongoshNodeRepl', function () {
511510
output = '';
512511
input.write('somelong');
513512
await tabtab();
513+
await waitCompletion(bus);
514514
await tick();
515515
expect(output, output).to.include('somelongvariable');
516516
});
517517
it('autocompletes partial repl commands', async function () {
518518
input.write('.e');
519519
await tabtab();
520+
await waitCompletion(bus);
520521
await tick();
521522
expect(output, output).to.include('editor');
522523
expect(output, output).to.include('exit');
523524
});
524525
it('autocompletes full repl commands', async function () {
525526
input.write('.ed');
526527
await tabtab();
528+
await waitCompletion(bus);
527529
await tick();
528530
expect(output, output).to.include('.editor');
529531
expect(output, output).not.to.include('exit');
@@ -535,6 +537,7 @@ describe('MongoshNodeRepl', function () {
535537
expect((mongoshRepl.runtimeState().repl as any)._prompt).to.equal('');
536538
input.write('db.');
537539
await tabtab();
540+
await waitCompletion(bus);
538541
await tick();
539542
input.write('foo\nbar\n');
540543
expect((mongoshRepl.runtimeState().repl as any)._prompt).to.equal('');

packages/cli-repl/src/mongosh-repl.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,11 @@ class MongoshNodeRepl implements EvaluationListener {
482482
});
483483
}
484484

485+
// mongodb-ts-autocomplete requires a connection and a schema
486+
if (this.shellCliOptions.nodb) {
487+
return [[], text];
488+
}
489+
485490
const results = await newMongoshCompleter.autocomplete(text);
486491
const transformed = transformAutocompleteResults(text, results);
487492
return transformed;

packages/cli-repl/test/repl-helpers.ts

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -71,26 +71,10 @@ async function waitEval(bus: MongoshBus) {
7171
}
7272

7373
async function waitCompletion(bus: MongoshBus) {
74-
await waitBus(bus, 'mongosh:autocompletion-complete');
75-
await tick();
76-
}
77-
78-
async function waitMongoshCompletionResults(bus: MongoshBus) {
79-
// Waiting for the completion results can "time out" if an async action such
80-
// as listing the databases or collections or loading the schema takes longer
81-
// than 200ms (at the time of writing), but by the next try or at least
82-
// eventually the action should complete and then the next autocomplete call
83-
// will return the cached result.
84-
let found = false;
85-
while (!found) {
86-
const [, mongoshResults] = await waitBus(
87-
bus,
88-
'mongosh:autocompletion-complete'
89-
);
90-
if (mongoshResults.length === 0) {
91-
found = true;
92-
}
93-
}
74+
await Promise.race([
75+
waitBus(bus, 'mongosh:autocompletion-complete'),
76+
new Promise((resolve) => setTimeout(resolve, 5000)?.unref?.()),
77+
]);
9478
await tick();
9579
}
9680

@@ -125,7 +109,6 @@ export {
125109
waitBus,
126110
waitEval,
127111
waitCompletion,
128-
waitMongoshCompletionResults,
129112
fakeTTYProps,
130113
readReplLogFile,
131114
};

0 commit comments

Comments
 (0)