Skip to content

Commit

Permalink
feat(chat): show errors if there are issues when getting databases & …
Browse files Browse the repository at this point in the history
…collections to pick VSCODE-610 (#864)
  • Loading branch information
gagik authored Nov 8, 2024
1 parent 9acf251 commit d5a9345
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 20 deletions.
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

0 comments on commit d5a9345

Please sign in to comment.