Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(chat): show errors if there are issues when getting databases & collections to pick VSCODE-610 #864

Merged
merged 42 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
ff0c1cc
WIP
gagik Oct 31, 2024
f9dd536
Move around dependencies
gagik Nov 1, 2024
09c7414
Remove grep
gagik Nov 1, 2024
aada8e1
Use firstCall
gagik Nov 1, 2024
eb2c7dc
Add test filtering
gagik Nov 1, 2024
bcd260b
Update CONTRIBUTING.md
gagik Nov 1, 2024
a9beef1
Escape the environment variable
gagik Nov 1, 2024
2e4bd70
Merge branch 'gagik/add-test-filtering' of github.com:mongodb-js/vsco…
gagik Nov 1, 2024
33c995e
Fix wording
gagik Nov 1, 2024
8582193
Add schema tests
gagik Nov 1, 2024
a8bc30d
align tests and use a stub
gagik Nov 1, 2024
5ddc7fb
Add saving to metadata
gagik Nov 1, 2024
06435e8
Move things
gagik Nov 3, 2024
5a58171
Better org
gagik Nov 3, 2024
fdbabfc
Merge branch 'gagik/add-test-filtering' of github.com:mongodb-js/vsco…
gagik Nov 3, 2024
f23e19f
simplify tests and picking logic
gagik Nov 3, 2024
274fe17
typos
gagik Nov 3, 2024
54885d6
Align with broken test
gagik Nov 4, 2024
cfb9d61
Add error info and tests
gagik Nov 4, 2024
f080016
wrap l10n
gagik Nov 4, 2024
190f4f6
Merge branch 'gagik/one-no-collection-handling' of github.com:mongodb…
gagik Nov 5, 2024
182dc15
wrap in l10n
gagik Nov 5, 2024
a341e45
remove settings change
gagik Nov 5, 2024
c1b6534
Merge branch 'main' of github.com:mongodb-js/vscode into gagik/no-dat…
gagik Nov 5, 2024
378b202
Merge branch 'main' of github.com:mongodb-js/vscode into gagik/one-no…
gagik Nov 5, 2024
62c07ef
Apply suggestions from code review
gagik Nov 6, 2024
f2b54ea
changes from review
gagik Nov 6, 2024
bf2a0c7
switch to parametrized tests
gagik Nov 6, 2024
02f45dc
Merge branch 'gagik/one-no-collection-handling' into gagik/no-databas…
gagik Nov 6, 2024
a1765ef
remove patched vscode
gagik Nov 6, 2024
ccacb8a
remove vscode
gagik Nov 6, 2024
886aa45
better comments
gagik Nov 6, 2024
52dbdf6
fix potential CI discrepancy
gagik Nov 7, 2024
686c7cd
Merge branch 'main' of github.com:mongodb-js/vscode into gagik/one-no…
gagik Nov 7, 2024
fee668e
combine message text
gagik Nov 7, 2024
e1d12bf
add explicit undefined returns
gagik Nov 7, 2024
c92cdcb
Merge branch 'gagik/one-no-collection-handling' into gagik/no-databas…
gagik Nov 7, 2024
985ed49
Move tests to parameterized
gagik Nov 7, 2024
853eccf
Merge branch 'main' of github.com:mongodb-js/vscode into gagik/no-dat…
gagik Nov 8, 2024
0162400
propagate the error
gagik Nov 8, 2024
378179c
fix test and error instead of markdown
gagik Nov 8, 2024
ec67467
use l10tn in errors
gagik Nov 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 29 additions & 16 deletions src/participant/participant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -793,11 +793,10 @@ export default class ParticipantController {
_id: string;
name: string;
}[]
| undefined
> {
const dataService = this._connectionController.getActiveDataService();
if (!dataService) {
return undefined;
throw new Error(vscode.l10n.t('Failed to get the data service'));
}

stream.push(
Expand All @@ -811,7 +810,11 @@ export default class ParticipantController {
} catch (error) {
log.error('Unable to fetch databases:', error);

return undefined;
throw new Error(
vscode.l10n.t(
`Unable to fetch database names: ${formatError(error).message}.`
)
);
}
}

Expand All @@ -821,11 +824,11 @@ export default class ParticipantController {
}: {
stream: vscode.ChatResponseStream;
databaseName: string;
}): Promise<ReturnType<DataService['listCollections']> | undefined> {
}): Promise<ReturnType<DataService['listCollections']>> {
const dataService = this._connectionController.getActiveDataService();

if (!dataService) {
return undefined;
throw new Error(vscode.l10n.t('Failed to get the data service'));
}

stream.push(
Expand All @@ -835,9 +838,15 @@ export default class ParticipantController {
try {
return await dataService.listCollections(databaseName);
} catch (error) {
log.error('Unable to fetch collections:', error);
log.error('Unable to fetch collection names:', error);

return undefined;
throw new Error(
vscode.l10n.t(
`Unable to fetch collection names from ${databaseName}: ${
formatError(error).message
}.`
)
);
}
}

Expand All @@ -856,9 +865,12 @@ export default class ParticipantController {
}): Promise<string | undefined> {
const collections = await this._getCollections({ stream, databaseName });

if (collections === undefined) {
log.error('No collections found');
return undefined;
if (collections.length === 0) {
throw new Error(
vscode.l10n.t(
`No collections were found in the database ${databaseName}.`
)
);
}
if (collections.length === 1) {
return collections[0].name;
Expand Down Expand Up @@ -894,9 +906,8 @@ export default class ParticipantController {
}): Promise<string | undefined> {
const databases = await this._getDatabases({ stream });

if (databases === undefined || databases.length === 0) {
log.error('No databases found');
return undefined;
if (databases.length === 0) {
throw new Error(vscode.l10n.t('No databases were found.'));
}

if (databases.length === 1) {
Expand All @@ -908,9 +919,11 @@ export default class ParticipantController {
// Users can then select a value by clicking on an item in the list
// or typing the name manually.
stream.markdown(
`Which database would you like ${
command === '/query' ? 'this query to run against' : 'to use'
}? Select one by either clicking on an item in the list or typing the name manually in the chat.\n\n`
vscode.l10n.t(
`Which database would you like ${
command === '/query' ? 'this query to run against' : 'to use'
}? Select one by either clicking on an item in the list or typing the name manually in the chat.\n\n`
)
);

this.renderDatabasesTree({
Expand Down
82 changes: 78 additions & 4 deletions src/test/suite/participant/participant.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as vscode from 'vscode';
import { beforeEach, afterEach } from 'mocha';
import { expect } from 'chai';
import type { SinonSpy } from 'sinon';
import type { SinonSpy, SinonStub } from 'sinon';
import sinon from 'sinon';
import type { DataService } from 'mongodb-data-service';
import { ObjectId, Int32 } from 'bson';
Expand Down Expand Up @@ -404,9 +404,9 @@ suite('Participant Controller Test Suite', function () {
});

suite('when connected', function () {
let sampleStub;
let listCollectionsStub;
let listDatabasesStub;
let sampleStub: SinonStub;
let listCollectionsStub: SinonStub;
let listDatabasesStub: SinonStub;

beforeEach(function () {
sampleStub = sinon.stub();
Expand Down Expand Up @@ -1790,6 +1790,43 @@ Schema:
sinon.restore();
});

test('shows an error if something goes wrong with getting databases', async function () {
listDatabasesStub.rejects(new Error('Something went wrong'));

let caughtError: Error | undefined;
try {
await invokeChatHandler({
prompt: 'find all docs by a name example',
command,
references: [],
});
} catch (error) {
caughtError = error as Error;
}

expect(caughtError?.message).equals(
'Unable to fetch database names: Something went wrong.'
);
});

test('shows an error if there are no databases found', async function () {
// No databases
listDatabasesStub.resolves([]);

let caughtError: Error | undefined;
try {
await invokeChatHandler({
prompt: 'find all docs by a name example',
command,
references: [],
});
} catch (error) {
caughtError = error as Error;
}

expect(caughtError?.message).equals('No databases were found.');
});

test('database name gets picked automatically if there is only 1', async function () {
listDatabasesStub.resolves([{ name: 'onlyOneDb' }]);

Expand Down Expand Up @@ -1859,6 +1896,43 @@ Schema:
);
});

test('shows an error if something goes wrong with getting collections', async function () {
listCollectionsStub.rejects(new Error('Something went wrong'));

let caughtError: Error | undefined;
try {
await invokeChatHandler({
prompt: 'find all docs by a name example',
command,
references: [],
});
} catch (error) {
caughtError = error as Error;
}

expect(caughtError?.message).equals(
'Unable to fetch collection names from dbOne: Something went wrong.'
);
});

test('shows an error if there are no collections found', async function () {
listCollectionsStub.resolves([]);
let caughtError: Error | undefined;
try {
await invokeChatHandler({
prompt: 'find all docs by a name example',
command,
references: [],
});
} catch (error) {
caughtError = error as Error;
}

expect(caughtError?.message).equals(
'No collections were found in the database dbOne.'
);
});

test('collection name gets picked automatically if there is only 1', async function () {
listCollectionsStub.resolves([{ name: 'onlyOneColl' }]);
const renderCollectionsTreeSpy = sinon.spy(
Expand Down
Loading