Skip to content

Commit ae20849

Browse files
authored
chore: Prompt user to connect when running a playground VSCODE-686 (#1185)
1 parent cd9ae51 commit ae20849

File tree

2 files changed

+108
-49
lines changed

2 files changed

+108
-49
lines changed

src/editors/playgroundController.ts

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -375,10 +375,12 @@ export default class PlaygroundController {
375375
},
376376
token: vscode.CancellationToken,
377377
): Promise<ShellEvaluateResult> {
378-
const connectionId = this._connectionController.getActiveConnectionId();
378+
let connectionId = this._connectionController.getActiveConnectionId();
379379

380380
if (!connectionId) {
381-
throw new Error(connectBeforeRunningMessage);
381+
await this._ensureConnection();
382+
connectionId = this._connectionController.getActiveConnectionId();
383+
if (!connectionId) throw new Error(connectBeforeRunningMessage);
382384
}
383385

384386
this._statusView.showMessage('Getting results...');
@@ -420,10 +422,9 @@ export default class PlaygroundController {
420422
codeToEvaluate: string;
421423
filePath?: string;
422424
}): Promise<ShellEvaluateResult> {
423-
if (!this._connectionController.isCurrentlyConnected()) {
425+
if (!(await this._ensureConnection())) {
424426
throw new Error(connectBeforeRunningMessage);
425427
}
426-
427428
return await vscode.window.withProgress(
428429
{
429430
location: ProgressLocation.Notification,
@@ -493,14 +494,8 @@ export default class PlaygroundController {
493494
.getConfiguration('mdb')
494495
.get('confirmRunCopilotCode');
495496

496-
if (!this._connectionController.isCurrentlyConnected()) {
497-
const successfullyConnected =
498-
await this._connectionController.changeActiveConnection();
499-
500-
if (!successfullyConnected) {
501-
void vscode.window.showErrorMessage(connectBeforeRunningMessage);
502-
return false;
503-
}
497+
if (!(await this._ensureConnection())) {
498+
return false;
504499
}
505500

506501
if (shouldConfirmRunCopilotCode === true) {
@@ -537,6 +532,26 @@ export default class PlaygroundController {
537532
return true;
538533
}
539534

535+
async _ensureConnection(): Promise<boolean> {
536+
if (this._connectionController.isCurrentlyConnected()) {
537+
return true;
538+
}
539+
const action = await vscode.window.showInformationMessage(
540+
'Please connect to a database before running a playground.',
541+
{ modal: true },
542+
'Connect now',
543+
);
544+
if (action === 'Connect now') {
545+
const successfullyConnected =
546+
await this._connectionController.changeActiveConnection();
547+
if (!successfullyConnected) {
548+
void vscode.window.showErrorMessage(connectBeforeRunningMessage);
549+
}
550+
return successfullyConnected;
551+
}
552+
return false;
553+
}
554+
540555
async _evaluatePlayground({
541556
codeToEvaluate,
542557
filePath,
@@ -548,9 +563,7 @@ export default class PlaygroundController {
548563
.getConfiguration('mdb')
549564
.get('confirmRunAll');
550565

551-
if (!this._connectionController.isCurrentlyConnected()) {
552-
void vscode.window.showErrorMessage(connectBeforeRunningMessage);
553-
566+
if (!(await this._ensureConnection())) {
554567
return false;
555568
}
556569

src/test/suite/editors/playgroundController.test.ts

Lines changed: 80 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ suite('Playground Controller Test Suite', function () {
4242
let languageServerControllerStub: LanguageServerController;
4343
let testPlaygroundController: PlaygroundController;
4444
let showErrorMessageStub: SinonStub;
45+
let showInformationMessageStub: SinonStub;
4546
let sandbox: sinon.SinonSandbox;
4647

4748
beforeEach(() => {
@@ -82,6 +83,10 @@ suite('Playground Controller Test Suite', function () {
8283
exportToLanguageCodeLensProvider: testExportToLanguageCodeLensProvider,
8384
});
8485
showErrorMessageStub = sandbox.stub(vscode.window, 'showErrorMessage');
86+
showInformationMessageStub = sandbox.stub(
87+
vscode.window,
88+
'showInformationMessage',
89+
);
8590
sandbox.stub(testTelemetryService, 'trackNewConnection');
8691
});
8792

@@ -117,7 +122,6 @@ suite('Playground Controller Test Suite', function () {
117122
'activeConnectionChanged',
118123
fakeConnectToServiceProvider,
119124
);
120-
sandbox.stub(vscode.window, 'showInformationMessage');
121125

122126
testPlaygroundController._connectionController.setActiveDataService(
123127
mockActiveDataService,
@@ -154,13 +158,7 @@ suite('Playground Controller Test Suite', function () {
154158
});
155159

156160
suite('playground is not open', () => {
157-
let showInformationMessageStub: SinonStub;
158-
159161
beforeEach(() => {
160-
showInformationMessageStub = sandbox.stub(
161-
vscode.window,
162-
'showInformationMessage',
163-
);
164162
sandbox.stub(vscode.window, 'activeTextEditor').get(function getterFn() {
165163
return undefined;
166164
});
@@ -195,13 +193,7 @@ suite('Playground Controller Test Suite', function () {
195193
});
196194

197195
suite('playground is open', () => {
198-
let showInformationMessageStub: SinonStub;
199-
200196
beforeEach(() => {
201-
showInformationMessageStub = sandbox.stub(
202-
vscode.window,
203-
'showInformationMessage',
204-
);
205197
const activeTextEditor = mockTextEditor;
206198
activeTextEditor.document.uri = vscode.Uri.parse('test.mongodb.js');
207199
activeTextEditor.document.getText = (): string => '123';
@@ -211,39 +203,101 @@ suite('Playground Controller Test Suite', function () {
211203
});
212204

213205
suite('user is not connected', () => {
206+
let changeActiveConnectionStub: SinonStub;
207+
let isCurrentlyConnectedStub: SinonStub;
208+
214209
beforeEach(() => {
215-
sandbox.replace(
210+
isCurrentlyConnectedStub = sandbox
211+
.stub(
212+
testPlaygroundController._connectionController,
213+
'isCurrentlyConnected',
214+
)
215+
.returns(false);
216+
changeActiveConnectionStub = sandbox.stub(
216217
testPlaygroundController._connectionController,
217-
'isCurrentlyConnected',
218-
() => false,
218+
'changeActiveConnection',
219219
);
220220
});
221221

222-
test('run all playground blocks shows please connect to a database error', async () => {
222+
test('run all playground blocks shows please connect to a database modal', async () => {
223223
const expectedMessage =
224224
'Please connect to a database before running a playground.';
225225
await testPlaygroundController.runAllPlaygroundBlocks();
226-
expect(showErrorMessageStub.firstCall.args[0]).to.be.equal(
226+
expect(showInformationMessageStub.firstCall.args[0]).to.be.equal(
227227
expectedMessage,
228228
);
229229
});
230230

231-
test('run selected playground blocks shows please connect to a database error', async () => {
231+
test('run selected playground blocks shows please connect to a database modal', async () => {
232232
const expectedMessage =
233233
'Please connect to a database before running a playground.';
234234
await testPlaygroundController.runSelectedPlaygroundBlocks();
235-
expect(showErrorMessageStub.firstCall.args[0]).to.be.equal(
235+
expect(showInformationMessageStub.firstCall.args[0]).to.be.equal(
236236
expectedMessage,
237237
);
238238
});
239239

240-
test('run all or selected playground blocks shows please connect to a database error', async () => {
240+
test('run all or selected playground blocks shows please connect to a database modal', async () => {
241241
const expectedMessage =
242242
'Please connect to a database before running a playground.';
243243
await testPlaygroundController.runAllOrSelectedPlaygroundBlocks();
244-
expect(showErrorMessageStub.firstCall.args[0]).to.be.equal(
244+
expect(showInformationMessageStub.firstCall.args[0]).to.be.equal(
245+
expectedMessage,
246+
);
247+
});
248+
249+
test('run all playground blocks shows please connect to a database modal, user dismisses', async () => {
250+
const expectedMessage =
251+
'Please connect to a database before running a playground.';
252+
await testPlaygroundController.runAllPlaygroundBlocks();
253+
expect(showInformationMessageStub.firstCall.args[0]).to.be.equal(
254+
expectedMessage,
255+
);
256+
// User cancels the connection modal
257+
showInformationMessageStub.resolves(undefined);
258+
259+
expect(changeActiveConnectionStub.notCalled).to.be.true;
260+
const result = await testPlaygroundController.runAllPlaygroundBlocks();
261+
expect(result).to.be.false;
262+
});
263+
264+
test('run all playground blocks shows please connect to a database modal, user connects', async () => {
265+
const getConfigurationStub = sandbox.stub(
266+
vscode.workspace,
267+
'getConfiguration',
268+
);
269+
getConfigurationStub.returns({
270+
get: (key: string) => {
271+
if (key === 'confirmRunAll') {
272+
return false;
273+
}
274+
return undefined;
275+
},
276+
} as any);
277+
278+
sandbox
279+
.stub(testPlaygroundController, '_evaluateWithCancelModal')
280+
.resolves({ result: '123' } as any);
281+
sandbox.stub(testPlaygroundController, '_openInResultPane').resolves();
282+
283+
const expectedMessage =
284+
'Please connect to a database before running a playground.';
285+
const beforeConnectResult =
286+
await testPlaygroundController.runAllPlaygroundBlocks();
287+
expect(showInformationMessageStub.firstCall.args[0]).to.be.equal(
245288
expectedMessage,
246289
);
290+
expect(showInformationMessageStub.firstCall.args[2]).to.be.equal(
291+
'Connect now',
292+
);
293+
expect(beforeConnectResult).to.be.false;
294+
295+
changeActiveConnectionStub.resolves(true);
296+
isCurrentlyConnectedStub.returns(true);
297+
298+
const afterConnectResult =
299+
await testPlaygroundController.runAllPlaygroundBlocks();
300+
expect(afterConnectResult).to.be.true;
247301
});
248302

249303
suite('running code from the participant', function () {
@@ -252,18 +306,13 @@ suite('Playground Controller Test Suite', function () {
252306
.stub(testPlaygroundController, '_evaluateWithCancelModal')
253307
.resolves({ result: '123' } as any);
254308
sinon.stub(testPlaygroundController, '_openInResultPane').resolves();
255-
256-
showInformationMessageStub.resolves('Yes');
257309
});
258310

259311
afterEach(() => sinon.restore());
260312

261313
test('prompts to connect to a database and succeeds with selection', async () => {
262-
const changeActiveConnectionStub = sinon.stub(
263-
testPlaygroundController._connectionController,
264-
'changeActiveConnection',
265-
);
266-
// Mocks the user selecting a connection.
314+
showInformationMessageStub.onFirstCall().resolves('Connect now');
315+
showInformationMessageStub.onSecondCall().resolves('Yes');
267316
changeActiveConnectionStub.resolves(true);
268317

269318
const result = await testPlaygroundController.evaluateParticipantCode(
@@ -278,11 +327,8 @@ suite('Playground Controller Test Suite', function () {
278327
});
279328

280329
test('prompts to connect to a database and errors if not selected', async () => {
281-
const changeActiveConnectionStub = sinon.stub(
282-
testPlaygroundController._connectionController,
283-
'changeActiveConnection',
284-
);
285-
// Mocks the user selecting a connection.
330+
showInformationMessageStub.onFirstCall().resolves('Connect now');
331+
showInformationMessageStub.onSecondCall().resolves('Yes');
286332
changeActiveConnectionStub.resolves(false);
287333

288334
const result = await testPlaygroundController.evaluateParticipantCode(

0 commit comments

Comments
 (0)