Skip to content

Commit 7b4b7a6

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

File tree

5 files changed

+151
-70
lines changed

5 files changed

+151
-70
lines changed

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

Lines changed: 115 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2441,16 +2441,81 @@ describe('CliRepl', function () {
24412441
wantShardDistribution: boolean;
24422442
hasCollectionNames: boolean;
24432443
hasDatabaseNames: boolean;
2444+
}): 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+
2484+
return _verifyAutocompletion({
2485+
testServer,
2486+
wantVersion,
2487+
wantQueryOperators,
2488+
wantWatch,
2489+
wantShardDistribution,
2490+
hasCollectionNames,
2491+
hasDatabaseNames,
2492+
});
2493+
}
2494+
2495+
function _verifyAutocompletion({
2496+
testServer,
2497+
wantVersion,
2498+
wantQueryOperators,
2499+
wantWatch,
2500+
wantShardDistribution,
2501+
hasCollectionNames,
2502+
hasDatabaseNames,
2503+
}: {
2504+
testServer: MongodSetup | null;
2505+
wantVersion: boolean;
2506+
wantQueryOperators: boolean;
2507+
wantWatch: boolean;
2508+
wantShardDistribution: boolean;
2509+
hasCollectionNames: boolean;
2510+
hasDatabaseNames: boolean;
24442511
}): void {
24452512
describe('autocompletion', function () {
24462513
let cliRepl: CliRepl;
2447-
const tab = async () => {
2514+
2515+
const tabCompletion = async () => {
24482516
await tick();
24492517
input.write('\u0009');
2450-
};
2451-
const tabtab = async () => {
2452-
await tab();
2453-
await tab();
2518+
await waitCompletion(cliRepl.bus);
24542519
};
24552520

24562521
beforeEach(async function () {
@@ -2463,6 +2528,13 @@ describe('CliRepl', function () {
24632528
testServer ? await testServer.connectionString() : '',
24642529
{} as any
24652530
);
2531+
2532+
if (!(testServer as any)?._opts.args?.includes('--auth')) {
2533+
// make sure there are some collections we can autocomplete on below
2534+
input.write('db.coll.insertOne({})\n');
2535+
input.write('db.movies.insertOne({})\n');
2536+
await waitEval(cliRepl.bus);
2537+
}
24662538
});
24672539

24682540
afterEach(async function () {
@@ -2479,26 +2551,33 @@ describe('CliRepl', function () {
24792551
if (process.env.MONGOSH_TEST_FORCE_API_STRICT) {
24802552
return this.skip();
24812553
}
2554+
24822555
output = '';
24832556
input.write('db.wat');
2484-
await tabtab();
2485-
await waitCompletion(cliRepl.bus);
2557+
await tabCompletion();
2558+
await tabCompletion();
24862559
if (wantWatch) {
24872560
expect(output).to.include('db.watch');
24882561
} else {
24892562
expect(output).not.to.include('db.watch');
24902563
}
24912564
});
24922565

2493-
it('completes the version method', async function () {
2566+
it(`${
2567+
wantVersion ? 'completes' : 'does not complete'
2568+
} the version method`, async function () {
24942569
if (process.env.MONGOSH_TEST_FORCE_API_STRICT) {
24952570
return this.skip();
24962571
}
24972572
output = '';
24982573
input.write('db.vers');
2499-
await tabtab();
2500-
await waitCompletion(cliRepl.bus);
2501-
expect(output).to.include('db.version');
2574+
await tabCompletion();
2575+
await tabCompletion();
2576+
if (wantVersion) {
2577+
expect(output).to.include('db.version');
2578+
} else {
2579+
expect(output).to.not.include('db.version');
2580+
}
25022581
});
25032582

25042583
it('does not complete legacy JS get/set definitions', async function () {
@@ -2507,8 +2586,8 @@ describe('CliRepl', function () {
25072586
}
25082587
output = '';
25092588
input.write('JSON.');
2510-
await tabtab();
2511-
await waitCompletion(cliRepl.bus);
2589+
await tabCompletion();
2590+
await tabCompletion();
25122591
expect(output).to.include('JSON.__proto__');
25132592
expect(output).not.to.include('JSON.__defineGetter__');
25142593
expect(output).not.to.include('JSON.__defineSetter__');
@@ -2524,8 +2603,8 @@ describe('CliRepl', function () {
25242603
}
25252604
output = '';
25262605
input.write('db.coll.getShardDis');
2527-
await tabtab();
2528-
await waitCompletion(cliRepl.bus);
2606+
await tabCompletion();
2607+
await tabCompletion();
25292608
if (wantShardDistribution) {
25302609
expect(output).to.include('db.coll.getShardDistribution');
25312610
} else {
@@ -2543,8 +2622,8 @@ describe('CliRepl', function () {
25432622

25442623
output = '';
25452624
input.write('db.testcoll');
2546-
await tabtab();
2547-
await waitCompletion(cliRepl.bus);
2625+
await tabCompletion();
2626+
await tabCompletion();
25482627
expect(output).to.include(collname);
25492628

25502629
input.write(`db.${collname}.drop()\n`);
@@ -2553,17 +2632,16 @@ describe('CliRepl', function () {
25532632

25542633
it('completes JS value properties properly (incomplete, double tab)', async function () {
25552634
input.write('JSON.');
2556-
await tabtab();
2557-
await waitCompletion(cliRepl.bus);
2635+
await tabCompletion();
2636+
await tabCompletion();
25582637
expect(output).to.include('JSON.parse');
25592638
expect(output).to.include('JSON.stringify');
25602639
expect(output).not.to.include('rawValue');
25612640
});
25622641

25632642
it('completes JS value properties properly (complete, single tab)', async function () {
25642643
input.write('JSON.pa');
2565-
await tab();
2566-
await waitCompletion(cliRepl.bus);
2644+
await tabCompletion();
25672645
expect(output).to.include('JSON.parse');
25682646
expect(output).not.to.include('JSON.stringify');
25692647
expect(output).not.to.include('rawValue');
@@ -2575,8 +2653,7 @@ describe('CliRepl', function () {
25752653

25762654
output = '';
25772655
input.write('show d');
2578-
await tab();
2579-
await waitCompletion(cliRepl.bus);
2656+
await tabCompletion();
25802657
expect(output).to.include('show databases');
25812658
expect(output).not.to.include('dSomeVariableStartingWithD');
25822659
});
@@ -2587,16 +2664,21 @@ describe('CliRepl', function () {
25872664
await waitEval(cliRepl.bus);
25882665

25892666
input.write('use adm');
2590-
await tab();
2591-
await waitCompletion(cliRepl.bus);
2667+
await tabCompletion();
25922668
expect(output).to.include('use admin');
25932669
});
25942670

2595-
it('completes query operators', async function () {
2671+
it(`${
2672+
wantQueryOperators ? 'completes' : 'does not complete'
2673+
} query operators`, async function () {
25962674
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');
2675+
await tabCompletion();
2676+
await tabCompletion();
2677+
if (wantQueryOperators) {
2678+
expect(output).to.include('db.movies.find({year: {$gte');
2679+
} else {
2680+
expect(output).to.not.include('db.movies.find({year: {$gte');
2681+
}
26002682
});
26012683

26022684
it('completes properties of shell API result types', async function () {
@@ -2614,8 +2696,8 @@ describe('CliRepl', function () {
26142696
expect(output).to.include('DeleteResult');
26152697

26162698
input.write('res.a');
2617-
await tabtab();
2618-
await waitCompletion(cliRepl.bus);
2699+
await tabCompletion();
2700+
await tabCompletion();
26192701
expect(output).to.include('res.acknowledged');
26202702
});
26212703

@@ -2631,8 +2713,8 @@ describe('CliRepl', function () {
26312713

26322714
output = '';
26332715
input.write('db.actestc');
2634-
await tabtab();
2635-
await waitCompletion(cliRepl.bus);
2716+
await tabCompletion();
2717+
await tabCompletion();
26362718
expect(output).to.include('db.actestcoll1');
26372719
expect(output).to.not.include('db.actestcoll2');
26382720
});

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/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)