From 2a211f59ca19cb12df428cfd7f84404a2a7522c9 Mon Sep 17 00:00:00 2001 From: Alena Khineika Date: Sat, 4 Apr 2020 19:24:50 +0200 Subject: [PATCH 01/14] feat: move playground to the language server --- package.json | 2 +- src/editors/playgroundController.ts | 27 +++++---- src/language/languageServerController.ts | 13 ++++- src/language/server.ts | 16 +++++- src/mdbExtensionController.ts | 4 ++ .../editors/playgroundController.test.ts | 57 ++++++++++++++++--- 6 files changed, 93 insertions(+), 26 deletions(-) diff --git a/package.json b/package.json index 3053c4b29..47f0967ce 100644 --- a/package.json +++ b/package.json @@ -475,7 +475,7 @@ "redux": "^4.0.5", "ts-log": "^2.1.4", "uuid": "^7.0.0", - "vscode-languageclient": "^6.1.1", + "vscode-languageclient": "^6.1.3", "vscode-languageserver": "^6.1.1" }, "devDependencies": { diff --git a/src/editors/playgroundController.ts b/src/editors/playgroundController.ts index fc8d87ccd..db56b9561 100644 --- a/src/editors/playgroundController.ts +++ b/src/editors/playgroundController.ts @@ -1,9 +1,8 @@ import * as vscode from 'vscode'; import ConnectionController, { DataServiceEventTypes } from '../connectionController'; +import { LanguageServerController } from '../language'; import TelemetryController, { TelemetryEventTypes } from '../telemetry/telemetryController'; -import { ElectronRuntime } from '@mongosh/browser-runtime-electron'; -import { CompassServiceProvider } from '@mongosh/service-provider-server'; import ActiveConnectionCodeLensProvider from './activeConnectionCodeLensProvider'; import formatOutput from '../utils/formatOutput'; import { OutputChannel } from 'vscode'; @@ -14,16 +13,23 @@ import playgroundTemplate from '../templates/playgroundTemplate'; */ export default class PlaygroundController { _context: vscode.ExtensionContext; - _telemetryController?: TelemetryController; _connectionController: ConnectionController; + _languageServerController: LanguageServerController; + _telemetryController?: TelemetryController; _activeDB?: any; _activeConnectionCodeLensProvider?: ActiveConnectionCodeLensProvider; _outputChannel: OutputChannel; - constructor(context: vscode.ExtensionContext, connectionController: ConnectionController, telemetryController?: TelemetryController) { + constructor( + context: vscode.ExtensionContext, + connectionController: ConnectionController, + languageServerController: LanguageServerController, + telemetryController?: TelemetryController + ) { this._context = context; - this._telemetryController = telemetryController; this._connectionController = connectionController; + this._languageServerController = languageServerController; + this._telemetryController = telemetryController; this._outputChannel = vscode.window.createOutputChannel( 'Playground output' ); @@ -97,19 +103,16 @@ export default class PlaygroundController { } async evaluate(codeToEvaluate: string): Promise { - const activeConnection = this._connectionController.getActiveDataService(); + const activeConnectionString = this._connectionController.getActiveConnectionDriverUrl(); - if (!activeConnection) { + if (!activeConnectionString) { return Promise.reject( new Error('Please connect to a database before running a playground.') ); } - const serviceProvider = CompassServiceProvider.fromDataService( - activeConnection - ); - const runtime = new ElectronRuntime(serviceProvider); - const res = await runtime.evaluate(codeToEvaluate); + // Run playground as a background process using the Language Server + const res = await this._languageServerController.executeAll(codeToEvaluate, activeConnectionString); if (res) { this._telemetryController?.track( diff --git a/src/language/languageServerController.ts b/src/language/languageServerController.ts index 96d3d7ba0..053d4af05 100644 --- a/src/language/languageServerController.ts +++ b/src/language/languageServerController.ts @@ -20,9 +20,10 @@ const log = createLogger('LanguageServerController'); export default class LanguageServerController { _connectionController?: ConnectionController; client?: LanguageClient; + constructor( context: vscode.ExtensionContext, - connectionController: ConnectionController + connectionController?: ConnectionController ) { this._connectionController = connectionController; this.activate(context); @@ -31,7 +32,7 @@ export default class LanguageServerController { async activate(context: ExtensionContext): Promise { // The server is implemented in node const serverModule = context.asAbsolutePath( - path.join('out', 'language', 'server.js') + path.join(process.cwd(), 'out', 'language', 'server.js') ); // The debug options for the server // --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging @@ -94,4 +95,12 @@ export default class LanguageServerController { } return this.client.stop(); } + + executeAll(codeToEvaluate: string, connectionString: string, connectionOptions: any = {}): Thenable | undefined { + if (!this.client) { + return undefined; + } + + return this.client.sendRequest('executeAll', { codeToEvaluate, connectionString, connectionOptions }); + } } diff --git a/src/language/server.ts b/src/language/server.ts index 4d1ad6a4e..4413462e1 100644 --- a/src/language/server.ts +++ b/src/language/server.ts @@ -13,6 +13,8 @@ import { TextDocumentPositionParams, RequestType } from 'vscode-languageserver'; +import { ElectronRuntime } from '@mongosh/browser-runtime-electron'; +import { CliServiceProvider } from '@mongosh/service-provider-server'; // Create a connection for the server. The connection uses Node's IPC as a transport. // Also include all preview / proposed LSP features. @@ -275,9 +277,17 @@ connection.onCompletionResolve( /** * Execute the entire playground script. */ -connection.onRequest('executeAll', (event) => { - // connection.console.log(`executeAll: ${JSON.stringify(event)}`); - return ''; +connection.onRequest('executeAll', async (params) => { + try { + const connectionOptions = params.connectionOptions || {}; + const runtime = new ElectronRuntime( + await CliServiceProvider.connect(params.connectionString, connectionOptions) + ); + + return await runtime.evaluate(params.codeToEvaluate); + } catch (error) { + throw new Error('Unable to connect to MongoDB instance. Make sure it is started correctly.'); + } }); /** diff --git a/src/mdbExtensionController.ts b/src/mdbExtensionController.ts index 5c2bad52e..3603dcd0e 100644 --- a/src/mdbExtensionController.ts +++ b/src/mdbExtensionController.ts @@ -8,6 +8,7 @@ import * as vscode from 'vscode'; import ConnectionController from './connectionController'; import { EditorsController, PlaygroundController } from './editors'; import { ExplorerController, CollectionTreeItem } from './explorer'; +import { LanguageServerController } from './language'; import { TelemetryController } from './telemetry'; import { StatusView } from './views'; import { createLogger } from './logging'; @@ -30,6 +31,7 @@ export default class MDBExtensionController implements vscode.Disposable { _statusView: StatusView; _storageController: StorageController; _telemetryController: TelemetryController; + _languageServerController: LanguageServerController; constructor( context: vscode.ExtensionContext, @@ -52,6 +54,7 @@ export default class MDBExtensionController implements vscode.Disposable { ); } + this._languageServerController = new LanguageServerController(context); this._editorsController = new EditorsController( context, this._connectionController @@ -62,6 +65,7 @@ export default class MDBExtensionController implements vscode.Disposable { this._playgroundController = new PlaygroundController( context, this._connectionController, + this._languageServerController, this._telemetryController ); } diff --git a/src/test/suite/editors/playgroundController.test.ts b/src/test/suite/editors/playgroundController.test.ts index 13b838e4a..a348925b0 100644 --- a/src/test/suite/editors/playgroundController.test.ts +++ b/src/test/suite/editors/playgroundController.test.ts @@ -1,4 +1,7 @@ import * as vscode from 'vscode'; +import * as path from 'path'; +import { PlaygroundController } from '../../../editors'; +import { LanguageServerController } from '../../../language'; import ConnectionController from '../../../connectionController'; import { StatusView } from '../../../views'; import { StorageController } from '../../../storage'; @@ -9,14 +12,37 @@ import { cleanupTestDB } from '../dbTestHelper'; +const sinon = require('sinon'); const chai = require('chai'); const expect = chai.expect; chai.use(require('chai-as-promised')); -import { PlaygroundController } from '../../../editors'; +let doc: vscode.TextDocument; +let editor: vscode.TextEditor; -const sinon = require('sinon'); +async function sleep(ms: number) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +const getDocUri = (docName: string) => { + const docPath = path.resolve(__dirname, '../../../../src/test/fixture', docName); + + return vscode.Uri.file(docPath); +}; + +/** + * Opens the MongoDB playground + */ +export async function openPlayground(docUri: vscode.Uri) { + try { + doc = await vscode.workspace.openTextDocument(docUri); + editor = await vscode.window.showTextDocument(doc); + await sleep(2000); // Wait for server activation + } catch (e) { + console.error(e); + } +} suite('Playground Controller Test Suite', () => { vscode.window.showInformationMessage('Starting tests...'); @@ -30,7 +56,8 @@ suite('Playground Controller Test Suite', () => { new StatusView(mockExtensionContext), mockStorageController ); - const testPlaygroundController = new PlaygroundController(mockExtensionContext, testConnectionController); + const testLanguageServerController = new LanguageServerController(mockExtensionContext, testConnectionController); + const testPlaygroundController = new PlaygroundController(mockExtensionContext, testConnectionController, testLanguageServerController); expect(testPlaygroundController.evaluate('1 + 1')).to.be.rejectedWith(Error, 'Please connect to a database before running a playground.'); }); @@ -47,17 +74,27 @@ suite('Playground Controller Test Suite', () => { new StatusView(mockExtensionContext), mockStorageController ); + const testLanguageServerController = new LanguageServerController(mockExtensionContext, testConnectionController); testConnectionController.getActiveConnectionName = () => 'fakeName'; + testConnectionController.getActiveConnectionDriverUrl = () => 'mongodb://localhost:27018'; - const testPlaygroundController = new PlaygroundController(mockExtensionContext, testConnectionController); + const testPlaygroundController = new PlaygroundController(mockExtensionContext, testConnectionController, testLanguageServerController); + + test('evaluate should sum numbers', async function () { + this.timeout(5000); + + await openPlayground(getDocUri('test.mongodb')); - test('evaluate should sum numbers', async () => { testConnectionController.setActiveConnection(mockActiveConnection); expect(await testPlaygroundController.evaluate('1 + 1')).to.be.equal('2'); }); - test('evaluate multiple commands at once', async () => { + test('evaluate multiple commands at once', async function () { + this.timeout(3000); + + await openPlayground(getDocUri('test.mongodb')); + testConnectionController.setActiveConnection(mockActiveConnection); expect(await testPlaygroundController.evaluate(` @@ -66,7 +103,9 @@ suite('Playground Controller Test Suite', () => { `)).to.be.equal('3'); }); - test('evaluate interaction with a database', (done) => { + test('evaluate interaction with a database', function (done) { + this.timeout(4000); + const mockDocument = { _id: new ObjectId('5e32b4d67bf47f4525f2f8ab'), example: 'field' @@ -76,13 +115,15 @@ suite('Playground Controller Test Suite', () => { async (dataService) => { testConnectionController.setActiveConnection(dataService); + await openPlayground(getDocUri('test.mongodb')); + const actualResult = await testPlaygroundController.evaluate(` use('vscodeTestDatabaseAA'); db.forest.find({}) `); const expectedResult = '[\n' + ' {\n' + - ' _id: 5e32b4d67bf47f4525f2f8ab,\n' + + ' _id: \'5e32b4d67bf47f4525f2f8ab\',\n' + ' example: \'field\'\n' + ' }\n' + ']'; From 211564c22416570387a037fa53d2a4b69456cac8 Mon Sep 17 00:00:00 2001 From: Alena Khineika Date: Sat, 4 Apr 2020 20:41:21 +0200 Subject: [PATCH 02/14] test: fix client is not ready yet error --- src/language/languageServerController.ts | 8 +++- .../editors/playgroundController.test.ts | 44 +++++++------------ 2 files changed, 24 insertions(+), 28 deletions(-) diff --git a/src/language/languageServerController.ts b/src/language/languageServerController.ts index 053d4af05..6907110a8 100644 --- a/src/language/languageServerController.ts +++ b/src/language/languageServerController.ts @@ -101,6 +101,12 @@ export default class LanguageServerController { return undefined; } - return this.client.sendRequest('executeAll', { codeToEvaluate, connectionString, connectionOptions }); + return this.client.onReady().then(() => { + if (!this.client) { + return undefined; + } + + return this.client.sendRequest('executeAll', { codeToEvaluate, connectionString, connectionOptions }); + }); } } diff --git a/src/test/suite/editors/playgroundController.test.ts b/src/test/suite/editors/playgroundController.test.ts index a348925b0..cef721a0b 100644 --- a/src/test/suite/editors/playgroundController.test.ts +++ b/src/test/suite/editors/playgroundController.test.ts @@ -21,10 +21,6 @@ chai.use(require('chai-as-promised')); let doc: vscode.TextDocument; let editor: vscode.TextEditor; -async function sleep(ms: number) { - return new Promise((resolve) => setTimeout(resolve, ms)); -} - const getDocUri = (docName: string) => { const docPath = path.resolve(__dirname, '../../../../src/test/fixture', docName); @@ -38,7 +34,6 @@ export async function openPlayground(docUri: vscode.Uri) { try { doc = await vscode.workspace.openTextDocument(docUri); editor = await vscode.window.showTextDocument(doc); - await sleep(2000); // Wait for server activation } catch (e) { console.error(e); } @@ -50,6 +45,8 @@ suite('Playground Controller Test Suite', () => { const mockExtensionContext = new TestExtensionContext(); const mockStorageController = new StorageController(mockExtensionContext); + const sandbox = sinon.createSandbox(); + suite('when user is not connected', () => { test('evaluate should throw the missing active connection error', async () => { const testConnectionController = new ConnectionController( @@ -81,8 +78,6 @@ suite('Playground Controller Test Suite', () => { const testPlaygroundController = new PlaygroundController(mockExtensionContext, testConnectionController, testLanguageServerController); test('evaluate should sum numbers', async function () { - this.timeout(5000); - await openPlayground(getDocUri('test.mongodb')); testConnectionController.setActiveConnection(mockActiveConnection); @@ -90,9 +85,7 @@ suite('Playground Controller Test Suite', () => { expect(await testPlaygroundController.evaluate('1 + 1')).to.be.equal('2'); }); - test('evaluate multiple commands at once', async function () { - this.timeout(3000); - + test('evaluate multiple commands at once', async () => { await openPlayground(getDocUri('test.mongodb')); testConnectionController.setActiveConnection(mockActiveConnection); @@ -103,9 +96,7 @@ suite('Playground Controller Test Suite', () => { `)).to.be.equal('3'); }); - test('evaluate interaction with a database', function (done) { - this.timeout(4000); - + test('evaluate interaction with a database', (done) => { const mockDocument = { _id: new ObjectId('5e32b4d67bf47f4525f2f8ab'), example: 'field' @@ -129,10 +120,8 @@ suite('Playground Controller Test Suite', () => { ']'; expect(actualResult).to.be.equal(expectedResult); - - await cleanupTestDB(); } - ).then(done, done); + ).then(done, done).finally(async () => { await cleanupTestDB() }); }); test('convert AggregationCursor shellApiType to aggregation telemetry type', () => { @@ -233,7 +222,7 @@ suite('Playground Controller Test Suite', () => { expect(type).to.deep.equal({ type: 'other' }); }); - test('create a new playground instance for each run', () => { + test('create a new playground instance for each run', (done) => { const mockDocument = { _id: new ObjectId('5e32b4d67bf47f4525f2f777'), valueOfTheField: 'is not important' @@ -252,10 +241,8 @@ suite('Playground Controller Test Suite', () => { const result = await testPlaygroundController.evaluate(codeToEvaluate); expect(result).to.be.equal('2'); - - await cleanupTestDB(); } - ); + ).then(done, done).finally(async () => { await cleanupTestDB() }); }); test('show a confirmation message before running commands in a playground if mdb.confirmRunAll is true', (done) => { @@ -263,7 +250,7 @@ suite('Playground Controller Test Suite', () => { _id: new ObjectId('5e32b4d67bf47f4525f2f8ab'), example: 'field' }; - const fakeShowInformationMessage = sinon.stub(vscode.window, 'showInformationMessage'); + const fakeShowInformationMessage = sandbox.stub(vscode.window, 'showInformationMessage'); fakeShowInformationMessage.returns('Yes'); @@ -278,11 +265,11 @@ suite('Playground Controller Test Suite', () => { expect(fakeShowInformationMessage.calledOnce).to.be.true; expect(fakeShowInformationMessage.calledWith(expectedMessage)).to.be.true; - fakeShowInformationMessage.restore(); - - await cleanupTestDB(); } - ).then(done, done); + ).then(done, done).finally(async () => { + sandbox.restore(); + await cleanupTestDB() + }); }); test('show a confirmation message before running commands in a playground if mdb.confirmRunAll is false', (done) => { @@ -290,7 +277,7 @@ suite('Playground Controller Test Suite', () => { _id: new ObjectId('5e32b4d67bf47f4525f2f8ab'), example: 'field' }; - const fakeShowInformationMessage = sinon.stub(vscode.window, 'showInformationMessage'); + const fakeShowInformationMessage = sandbox.stub(vscode.window, 'showInformationMessage'); fakeShowInformationMessage.returns('Yes'); @@ -308,7 +295,10 @@ suite('Playground Controller Test Suite', () => { await cleanupTestDB(); } - ).then(done, done); + ).then(done, done).finally(async () => { + sandbox.restore(); + await cleanupTestDB() + }); }); }); }); From cf9e1defe7d55a3a93d803bab5cda9a158e50526 Mon Sep 17 00:00:00 2001 From: Alena Khineika Date: Sat, 4 Apr 2020 21:06:28 +0200 Subject: [PATCH 03/14] refactor: update ids in tests --- .vscode/launch.json | 2 +- src/language/languageServerController.ts | 3 +-- src/test/suite/editors/playgroundController.test.ts | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index d32afdc76..81a4b4f26 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -38,7 +38,7 @@ "request": "attach", "name": "Attach to Language Server", "protocol": "inspector", - "port": 6005, + "port": 6009, "sourceMaps": true, "outFiles": [ "${workspaceFolder}/out/**/*.js" diff --git a/src/language/languageServerController.ts b/src/language/languageServerController.ts index 6907110a8..926729efd 100644 --- a/src/language/languageServerController.ts +++ b/src/language/languageServerController.ts @@ -37,7 +37,6 @@ export default class LanguageServerController { // The debug options for the server // --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging const debugOptions = { execArgv: ['--nolazy', '--inspect=6009'] }; - // If the extension is launched in debug mode then the debug server options are used // Otherwise the run options are used const serverOptions: ServerOptions = { @@ -48,7 +47,6 @@ export default class LanguageServerController { options: debugOptions } }; - // Options to control the language client const clientOptions: LanguageClientOptions = { // Register the server for plain text documents @@ -79,6 +77,7 @@ export default class LanguageServerController { this.client.start(); await this.client.onReady(); + /** * TODO: Notification is for setup docs only. */ diff --git a/src/test/suite/editors/playgroundController.test.ts b/src/test/suite/editors/playgroundController.test.ts index cef721a0b..cab7ebfbe 100644 --- a/src/test/suite/editors/playgroundController.test.ts +++ b/src/test/suite/editors/playgroundController.test.ts @@ -247,7 +247,7 @@ suite('Playground Controller Test Suite', () => { test('show a confirmation message before running commands in a playground if mdb.confirmRunAll is true', (done) => { const mockDocument = { - _id: new ObjectId('5e32b4d67bf47f4525f2f8ab'), + _id: new ObjectId('5e32b4d67bf47f4525f2f811'), example: 'field' }; const fakeShowInformationMessage = sandbox.stub(vscode.window, 'showInformationMessage'); @@ -274,7 +274,7 @@ suite('Playground Controller Test Suite', () => { test('show a confirmation message before running commands in a playground if mdb.confirmRunAll is false', (done) => { const mockDocument = { - _id: new ObjectId('5e32b4d67bf47f4525f2f8ab'), + _id: new ObjectId('5e32b4d67bf47f4525f2f822'), example: 'field' }; const fakeShowInformationMessage = sandbox.stub(vscode.window, 'showInformationMessage'); From 93c78c254942ee1273222d2fa776cd6d0f7c29b4 Mon Sep 17 00:00:00 2001 From: Alena Khineika Date: Sat, 4 Apr 2020 22:08:47 +0200 Subject: [PATCH 04/14] test: use before and after each --- .../editors/playgroundController.test.ts | 159 ++++++++++-------- 1 file changed, 92 insertions(+), 67 deletions(-) diff --git a/src/test/suite/editors/playgroundController.test.ts b/src/test/suite/editors/playgroundController.test.ts index cab7ebfbe..0e1a6eb4f 100644 --- a/src/test/suite/editors/playgroundController.test.ts +++ b/src/test/suite/editors/playgroundController.test.ts @@ -11,6 +11,7 @@ import { seedDataAndCreateDataService, cleanupTestDB } from '../dbTestHelper'; +import { beforeEach, afterEach } from 'mocha'; const sinon = require('sinon'); const chai = require('chai'); @@ -60,13 +61,73 @@ suite('Playground Controller Test Suite', () => { }); }); + suite('test confirmation message', () => { + const testConnectionController = new ConnectionController( + new StatusView(mockExtensionContext), + mockStorageController + ); + const testLanguageServerController = new LanguageServerController(mockExtensionContext, testConnectionController); + + testConnectionController.getActiveConnectionDriverUrl = () => 'mongodb://localhost:27018'; + + const testPlaygroundController = new PlaygroundController(mockExtensionContext, testConnectionController, testLanguageServerController); + let fakeShowInformationMessage; + + beforeEach(() => { + fakeShowInformationMessage = sandbox.stub(vscode.window, 'showInformationMessage').resolves('Yes'); + }); + + afterEach(async () => { + sandbox.restore(); + await cleanupTestDB() + }); + + test('show a confirmation message before running commands in a playground if mdb.confirmRunAll is true', (done) => { + const mockDocument = { + _id: new ObjectId('5e32b4d67bf47f4525f2f833'), + example: 'field' + }; + + seedDataAndCreateDataService('forest', [mockDocument]).then( + async (dataService) => { + testConnectionController.setActiveConnection(dataService); + + await testPlaygroundController.runAllPlaygroundBlocks(); + + const expectedMessage = + 'Are you sure you want to run this playground against fakeName? This confirmation can be disabled in the extension settings.'; + + expect(fakeShowInformationMessage.calledOnce).to.be.true; + } + ).then(done, done); + }); + + test('show a confirmation message before running commands in a playground if mdb.confirmRunAll is false', (done) => { + const mockDocument = { + _id: new ObjectId('5e32b4d67bf47f4525f2f844'), + example: 'field' + }; + + seedDataAndCreateDataService('forest', [mockDocument]).then( + async (dataService) => { + testConnectionController.setActiveConnection(dataService); + + await vscode.workspace + .getConfiguration('mdb') + .update('confirmRunAll', false); + await testPlaygroundController.runAllPlaygroundBlocks(); + + expect(fakeShowInformationMessage.calledOnce).to.be.false; + } + ).then(done, done); + }); + }); + suite('when user is connected', () => { - const mockActiveConnection = { - find: (namespace, filter, options, callback): void => { - return callback(null, ['Text message']); - }, - client: {} - }; + afterEach(async () => { + await cleanupTestDB() + }); + const testConnectionController = new ConnectionController( new StatusView(mockExtensionContext), mockStorageController @@ -78,6 +139,16 @@ suite('Playground Controller Test Suite', () => { const testPlaygroundController = new PlaygroundController(mockExtensionContext, testConnectionController, testLanguageServerController); test('evaluate should sum numbers', async function () { + const mockActiveConnection = { + find: (namespace, filter, options, callback): void => { + return callback(null, ['Text message']); + }, + client: { + _id: new ObjectId('5e32b4d67bf47f4525f2f841'), + example: 'field' + } + }; + await openPlayground(getDocUri('test.mongodb')); testConnectionController.setActiveConnection(mockActiveConnection); @@ -86,6 +157,16 @@ suite('Playground Controller Test Suite', () => { }); test('evaluate multiple commands at once', async () => { + const mockActiveConnection = { + find: (namespace, filter, options, callback): void => { + return callback(null, ['Text message']); + }, + client: { + _id: new ObjectId('5e32b4d67bf47f4525f2f842'), + example: 'field' + } + }; + await openPlayground(getDocUri('test.mongodb')); testConnectionController.setActiveConnection(mockActiveConnection); @@ -98,7 +179,7 @@ suite('Playground Controller Test Suite', () => { test('evaluate interaction with a database', (done) => { const mockDocument = { - _id: new ObjectId('5e32b4d67bf47f4525f2f8ab'), + _id: new ObjectId('5e32b4d67bf47f4525f2f811'), example: 'field' }; @@ -114,14 +195,14 @@ suite('Playground Controller Test Suite', () => { `); const expectedResult = '[\n' + ' {\n' + - ' _id: \'5e32b4d67bf47f4525f2f8ab\',\n' + + ' _id: \'5e32b4d67bf47f4525f2f811\',\n' + ' example: \'field\'\n' + ' }\n' + ']'; expect(actualResult).to.be.equal(expectedResult); } - ).then(done, done).finally(async () => { await cleanupTestDB() }); + ).then(done, done); }); test('convert AggregationCursor shellApiType to aggregation telemetry type', () => { @@ -224,7 +305,7 @@ suite('Playground Controller Test Suite', () => { test('create a new playground instance for each run', (done) => { const mockDocument = { - _id: new ObjectId('5e32b4d67bf47f4525f2f777'), + _id: new ObjectId('5e32b4d67bf47f4525f2f722'), valueOfTheField: 'is not important' }; const codeToEvaluate = ` @@ -242,63 +323,7 @@ suite('Playground Controller Test Suite', () => { expect(result).to.be.equal('2'); } - ).then(done, done).finally(async () => { await cleanupTestDB() }); - }); - - test('show a confirmation message before running commands in a playground if mdb.confirmRunAll is true', (done) => { - const mockDocument = { - _id: new ObjectId('5e32b4d67bf47f4525f2f811'), - example: 'field' - }; - const fakeShowInformationMessage = sandbox.stub(vscode.window, 'showInformationMessage'); - - fakeShowInformationMessage.returns('Yes'); - - seedDataAndCreateDataService('forest', [mockDocument]).then( - async (dataService) => { - testConnectionController.setActiveConnection(dataService); - - await testPlaygroundController.runAllPlaygroundBlocks(); - - const expectedMessage = - 'Are you sure you want to run this playground against fakeName? This confirmation can be disabled in the extension settings.'; - - expect(fakeShowInformationMessage.calledOnce).to.be.true; - expect(fakeShowInformationMessage.calledWith(expectedMessage)).to.be.true; - } - ).then(done, done).finally(async () => { - sandbox.restore(); - await cleanupTestDB() - }); - }); - - test('show a confirmation message before running commands in a playground if mdb.confirmRunAll is false', (done) => { - const mockDocument = { - _id: new ObjectId('5e32b4d67bf47f4525f2f822'), - example: 'field' - }; - const fakeShowInformationMessage = sandbox.stub(vscode.window, 'showInformationMessage'); - - fakeShowInformationMessage.returns('Yes'); - - seedDataAndCreateDataService('forest', [mockDocument]).then( - async (dataService) => { - testConnectionController.setActiveConnection(dataService); - - await vscode.workspace - .getConfiguration('mdb') - .update('confirmRunAll', false); - await testPlaygroundController.runAllPlaygroundBlocks(); - - expect(fakeShowInformationMessage.calledOnce).to.be.false; - fakeShowInformationMessage.restore(); - - await cleanupTestDB(); - } - ).then(done, done).finally(async () => { - sandbox.restore(); - await cleanupTestDB() - }); + ).then(done, done); }); }); }); From bda059c9d1612fe656141f149a121c2e843a660b Mon Sep 17 00:00:00 2001 From: Alena Khineika Date: Sat, 4 Apr 2020 22:18:48 +0200 Subject: [PATCH 05/14] test: try run without mocking showInformationMessage --- .../editors/playgroundController.test.ts | 62 ------------------- 1 file changed, 62 deletions(-) diff --git a/src/test/suite/editors/playgroundController.test.ts b/src/test/suite/editors/playgroundController.test.ts index 0e1a6eb4f..3509cf717 100644 --- a/src/test/suite/editors/playgroundController.test.ts +++ b/src/test/suite/editors/playgroundController.test.ts @@ -61,68 +61,6 @@ suite('Playground Controller Test Suite', () => { }); }); - suite('test confirmation message', () => { - const testConnectionController = new ConnectionController( - new StatusView(mockExtensionContext), - mockStorageController - ); - const testLanguageServerController = new LanguageServerController(mockExtensionContext, testConnectionController); - - testConnectionController.getActiveConnectionDriverUrl = () => 'mongodb://localhost:27018'; - - const testPlaygroundController = new PlaygroundController(mockExtensionContext, testConnectionController, testLanguageServerController); - let fakeShowInformationMessage; - - beforeEach(() => { - fakeShowInformationMessage = sandbox.stub(vscode.window, 'showInformationMessage').resolves('Yes'); - }); - - afterEach(async () => { - sandbox.restore(); - await cleanupTestDB() - }); - - test('show a confirmation message before running commands in a playground if mdb.confirmRunAll is true', (done) => { - const mockDocument = { - _id: new ObjectId('5e32b4d67bf47f4525f2f833'), - example: 'field' - }; - - seedDataAndCreateDataService('forest', [mockDocument]).then( - async (dataService) => { - testConnectionController.setActiveConnection(dataService); - - await testPlaygroundController.runAllPlaygroundBlocks(); - - const expectedMessage = - 'Are you sure you want to run this playground against fakeName? This confirmation can be disabled in the extension settings.'; - - expect(fakeShowInformationMessage.calledOnce).to.be.true; - } - ).then(done, done); - }); - - test('show a confirmation message before running commands in a playground if mdb.confirmRunAll is false', (done) => { - const mockDocument = { - _id: new ObjectId('5e32b4d67bf47f4525f2f844'), - example: 'field' - }; - - seedDataAndCreateDataService('forest', [mockDocument]).then( - async (dataService) => { - testConnectionController.setActiveConnection(dataService); - - await vscode.workspace - .getConfiguration('mdb') - .update('confirmRunAll', false); - await testPlaygroundController.runAllPlaygroundBlocks(); - - expect(fakeShowInformationMessage.calledOnce).to.be.false; - } - ).then(done, done); - }); - }); - suite('when user is connected', () => { afterEach(async () => { await cleanupTestDB() From 3f3cbb1cf3fad83013e06f1e3bd6fb525adec741 Mon Sep 17 00:00:00 2001 From: Alena Khineika Date: Sat, 4 Apr 2020 22:31:29 +0200 Subject: [PATCH 06/14] test: return tests --- .../editors/playgroundController.test.ts | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/src/test/suite/editors/playgroundController.test.ts b/src/test/suite/editors/playgroundController.test.ts index 3509cf717..0e1a6eb4f 100644 --- a/src/test/suite/editors/playgroundController.test.ts +++ b/src/test/suite/editors/playgroundController.test.ts @@ -61,6 +61,68 @@ suite('Playground Controller Test Suite', () => { }); }); + suite('test confirmation message', () => { + const testConnectionController = new ConnectionController( + new StatusView(mockExtensionContext), + mockStorageController + ); + const testLanguageServerController = new LanguageServerController(mockExtensionContext, testConnectionController); + + testConnectionController.getActiveConnectionDriverUrl = () => 'mongodb://localhost:27018'; + + const testPlaygroundController = new PlaygroundController(mockExtensionContext, testConnectionController, testLanguageServerController); + let fakeShowInformationMessage; + + beforeEach(() => { + fakeShowInformationMessage = sandbox.stub(vscode.window, 'showInformationMessage').resolves('Yes'); + }); + + afterEach(async () => { + sandbox.restore(); + await cleanupTestDB() + }); + + test('show a confirmation message before running commands in a playground if mdb.confirmRunAll is true', (done) => { + const mockDocument = { + _id: new ObjectId('5e32b4d67bf47f4525f2f833'), + example: 'field' + }; + + seedDataAndCreateDataService('forest', [mockDocument]).then( + async (dataService) => { + testConnectionController.setActiveConnection(dataService); + + await testPlaygroundController.runAllPlaygroundBlocks(); + + const expectedMessage = + 'Are you sure you want to run this playground against fakeName? This confirmation can be disabled in the extension settings.'; + + expect(fakeShowInformationMessage.calledOnce).to.be.true; + } + ).then(done, done); + }); + + test('show a confirmation message before running commands in a playground if mdb.confirmRunAll is false', (done) => { + const mockDocument = { + _id: new ObjectId('5e32b4d67bf47f4525f2f844'), + example: 'field' + }; + + seedDataAndCreateDataService('forest', [mockDocument]).then( + async (dataService) => { + testConnectionController.setActiveConnection(dataService); + + await vscode.workspace + .getConfiguration('mdb') + .update('confirmRunAll', false); + await testPlaygroundController.runAllPlaygroundBlocks(); + + expect(fakeShowInformationMessage.calledOnce).to.be.false; + } + ).then(done, done); + }); + }); + suite('when user is connected', () => { afterEach(async () => { await cleanupTestDB() From 76aa475acd28629cd31ccac9e8bda757f044e5c7 Mon Sep 17 00:00:00 2001 From: Alena Khineika Date: Sat, 4 Apr 2020 22:46:12 +0200 Subject: [PATCH 07/14] test: why windows tests fail? --- src/language/languageServerController.ts | 4 +++- src/test/suite/stubs.ts | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/language/languageServerController.ts b/src/language/languageServerController.ts index 926729efd..bb8d86471 100644 --- a/src/language/languageServerController.ts +++ b/src/language/languageServerController.ts @@ -32,7 +32,9 @@ export default class LanguageServerController { async activate(context: ExtensionContext): Promise { // The server is implemented in node const serverModule = context.asAbsolutePath( - path.join(process.cwd(), 'out', 'language', 'server.js') + context.extensionPath === 'TEST_FOLDER' + ? path.join('..', '..', 'out', 'language', 'server.js') + : path.join('out', 'language', 'server.js') ); // The debug options for the server // --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging diff --git a/src/test/suite/stubs.ts b/src/test/suite/stubs.ts index b7229a9d4..b13eead0a 100644 --- a/src/test/suite/stubs.ts +++ b/src/test/suite/stubs.ts @@ -36,7 +36,7 @@ class TestExtensionContext implements vscode.ExtensionContext { return new Promise(() => { this._globalState[key] = value; }); } }; - this.extensionPath = ''; + this.extensionPath = 'TEST_FOLDER'; this.storagePath = ''; } } From dc9e560b361c26b528b5d7e25a5610d2f56184ba Mon Sep 17 00:00:00 2001 From: Alena Khineika Date: Sat, 4 Apr 2020 23:04:33 +0200 Subject: [PATCH 08/14] refactor: use constructor instead of activate method --- src/language/languageServerController.ts | 35 ++++++++---------------- src/mdbExtensionController.ts | 1 + 2 files changed, 12 insertions(+), 24 deletions(-) diff --git a/src/language/languageServerController.ts b/src/language/languageServerController.ts index bb8d86471..886976b66 100644 --- a/src/language/languageServerController.ts +++ b/src/language/languageServerController.ts @@ -19,26 +19,25 @@ const log = createLogger('LanguageServerController'); */ export default class LanguageServerController { _connectionController?: ConnectionController; - client?: LanguageClient; + client: LanguageClient; constructor( context: vscode.ExtensionContext, connectionController?: ConnectionController ) { this._connectionController = connectionController; - this.activate(context); - } - async activate(context: ExtensionContext): Promise { // The server is implemented in node const serverModule = context.asAbsolutePath( context.extensionPath === 'TEST_FOLDER' ? path.join('..', '..', 'out', 'language', 'server.js') : path.join('out', 'language', 'server.js') ); + // The debug options for the server // --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging const debugOptions = { execArgv: ['--nolazy', '--inspect=6009'] }; + // If the extension is launched in debug mode then the debug server options are used // Otherwise the run options are used const serverOptions: ServerOptions = { @@ -49,6 +48,7 @@ export default class LanguageServerController { options: debugOptions } }; + // Options to control the language client const clientOptions: LanguageClientOptions = { // Register the server for plain text documents @@ -78,35 +78,22 @@ export default class LanguageServerController { // Start the client. This will also launch the server this.client.start(); - await this.client.onReady(); - - /** - * TODO: Notification is for setup docs only. - */ - this.client.onNotification('mongodbNotification', (messsage) => { - vscode.window.showInformationMessage(messsage); + this.client.onReady().then(() => { + /** + * TODO: Notification is for setup docs only. + */ + this.client.onNotification('mongodbNotification', (messsage) => { + vscode.window.showInformationMessage(messsage); + }); }); - - return new Promise((resolve) => resolve(this.client)); } deactivate(): Thenable | undefined { - if (!this.client) { - return undefined; - } return this.client.stop(); } executeAll(codeToEvaluate: string, connectionString: string, connectionOptions: any = {}): Thenable | undefined { - if (!this.client) { - return undefined; - } - return this.client.onReady().then(() => { - if (!this.client) { - return undefined; - } - return this.client.sendRequest('executeAll', { codeToEvaluate, connectionString, connectionOptions }); }); } diff --git a/src/mdbExtensionController.ts b/src/mdbExtensionController.ts index 3603dcd0e..a1a0d97f7 100644 --- a/src/mdbExtensionController.ts +++ b/src/mdbExtensionController.ts @@ -411,5 +411,6 @@ export default class MDBExtensionController implements vscode.Disposable { this._explorerController.deactivate(); this._playgroundController.deactivate(); this._telemetryController.deactivate(); + this._languageServerController.deactivate(); } } From 068fd83f266d04ef6ffc6100221e9e28a0163981 Mon Sep 17 00:00:00 2001 From: Alena Khineika Date: Sun, 5 Apr 2020 12:21:23 +0200 Subject: [PATCH 09/14] refactor: start language server in activate method --- src/language/languageServerController.ts | 5 +++-- src/mdbExtensionController.ts | 1 + src/test/suite/editors/playgroundController.test.ts | 13 ++++++++----- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/language/languageServerController.ts b/src/language/languageServerController.ts index 886976b66..6ee8ac3f3 100644 --- a/src/language/languageServerController.ts +++ b/src/language/languageServerController.ts @@ -62,7 +62,7 @@ export default class LanguageServerController { } }; - log.info('Activating MongoDB language server', { + log.info('Creating MongoDB Language Server', { serverOptions, clientOptions }); @@ -74,10 +74,11 @@ export default class LanguageServerController { serverOptions, clientOptions ); + } + activate() { // Start the client. This will also launch the server this.client.start(); - this.client.onReady().then(() => { /** * TODO: Notification is for setup docs only. diff --git a/src/mdbExtensionController.ts b/src/mdbExtensionController.ts index a1a0d97f7..6c439cbc7 100644 --- a/src/mdbExtensionController.ts +++ b/src/mdbExtensionController.ts @@ -74,6 +74,7 @@ export default class MDBExtensionController implements vscode.Disposable { this._connectionController.loadSavedConnections(); this._explorerController.createTreeView(); this._telemetryController.activate(); + this._languageServerController.activate(); log.info('Registering commands...'); diff --git a/src/test/suite/editors/playgroundController.test.ts b/src/test/suite/editors/playgroundController.test.ts index 0e1a6eb4f..585f2b380 100644 --- a/src/test/suite/editors/playgroundController.test.ts +++ b/src/test/suite/editors/playgroundController.test.ts @@ -19,9 +19,6 @@ const expect = chai.expect; chai.use(require('chai-as-promised')); -let doc: vscode.TextDocument; -let editor: vscode.TextEditor; - const getDocUri = (docName: string) => { const docPath = path.resolve(__dirname, '../../../../src/test/fixture', docName); @@ -33,8 +30,9 @@ const getDocUri = (docName: string) => { */ export async function openPlayground(docUri: vscode.Uri) { try { - doc = await vscode.workspace.openTextDocument(docUri); - editor = await vscode.window.showTextDocument(doc); + const doc = await vscode.workspace.openTextDocument(docUri); + + await vscode.window.showTextDocument(doc); } catch (e) { console.error(e); } @@ -57,6 +55,8 @@ suite('Playground Controller Test Suite', () => { const testLanguageServerController = new LanguageServerController(mockExtensionContext, testConnectionController); const testPlaygroundController = new PlaygroundController(mockExtensionContext, testConnectionController, testLanguageServerController); + testLanguageServerController.activate(); + expect(testPlaygroundController.evaluate('1 + 1')).to.be.rejectedWith(Error, 'Please connect to a database before running a playground.'); }); }); @@ -68,6 +68,7 @@ suite('Playground Controller Test Suite', () => { ); const testLanguageServerController = new LanguageServerController(mockExtensionContext, testConnectionController); + testLanguageServerController.activate(); testConnectionController.getActiveConnectionDriverUrl = () => 'mongodb://localhost:27018'; const testPlaygroundController = new PlaygroundController(mockExtensionContext, testConnectionController, testLanguageServerController); @@ -133,6 +134,8 @@ suite('Playground Controller Test Suite', () => { mockStorageController ); const testLanguageServerController = new LanguageServerController(mockExtensionContext, testConnectionController); + + testLanguageServerController.activate(); testConnectionController.getActiveConnectionName = () => 'fakeName'; testConnectionController.getActiveConnectionDriverUrl = () => 'mongodb://localhost:27018'; From b4ce48eed2e3a29e56facb2e9e96f452abe1c0f7 Mon Sep 17 00:00:00 2001 From: Alena Khineika Date: Sun, 5 Apr 2020 12:44:41 +0200 Subject: [PATCH 10/14] refactor: revert --- src/language/languageServerController.ts | 2 -- src/mdbExtensionController.ts | 1 - src/test/suite/editors/playgroundController.test.ts | 4 ---- 3 files changed, 7 deletions(-) diff --git a/src/language/languageServerController.ts b/src/language/languageServerController.ts index 6ee8ac3f3..1effe76f8 100644 --- a/src/language/languageServerController.ts +++ b/src/language/languageServerController.ts @@ -74,9 +74,7 @@ export default class LanguageServerController { serverOptions, clientOptions ); - } - activate() { // Start the client. This will also launch the server this.client.start(); this.client.onReady().then(() => { diff --git a/src/mdbExtensionController.ts b/src/mdbExtensionController.ts index 6c439cbc7..a1a0d97f7 100644 --- a/src/mdbExtensionController.ts +++ b/src/mdbExtensionController.ts @@ -74,7 +74,6 @@ export default class MDBExtensionController implements vscode.Disposable { this._connectionController.loadSavedConnections(); this._explorerController.createTreeView(); this._telemetryController.activate(); - this._languageServerController.activate(); log.info('Registering commands...'); diff --git a/src/test/suite/editors/playgroundController.test.ts b/src/test/suite/editors/playgroundController.test.ts index 585f2b380..39c8eeef2 100644 --- a/src/test/suite/editors/playgroundController.test.ts +++ b/src/test/suite/editors/playgroundController.test.ts @@ -55,8 +55,6 @@ suite('Playground Controller Test Suite', () => { const testLanguageServerController = new LanguageServerController(mockExtensionContext, testConnectionController); const testPlaygroundController = new PlaygroundController(mockExtensionContext, testConnectionController, testLanguageServerController); - testLanguageServerController.activate(); - expect(testPlaygroundController.evaluate('1 + 1')).to.be.rejectedWith(Error, 'Please connect to a database before running a playground.'); }); }); @@ -68,7 +66,6 @@ suite('Playground Controller Test Suite', () => { ); const testLanguageServerController = new LanguageServerController(mockExtensionContext, testConnectionController); - testLanguageServerController.activate(); testConnectionController.getActiveConnectionDriverUrl = () => 'mongodb://localhost:27018'; const testPlaygroundController = new PlaygroundController(mockExtensionContext, testConnectionController, testLanguageServerController); @@ -135,7 +132,6 @@ suite('Playground Controller Test Suite', () => { ); const testLanguageServerController = new LanguageServerController(mockExtensionContext, testConnectionController); - testLanguageServerController.activate(); testConnectionController.getActiveConnectionName = () => 'fakeName'; testConnectionController.getActiveConnectionDriverUrl = () => 'mongodb://localhost:27018'; From a29396540e9913f02bcefe3ce7b01edcb22001ce Mon Sep 17 00:00:00 2001 From: Alena Khineika Date: Sun, 5 Apr 2020 13:00:41 +0200 Subject: [PATCH 11/14] test: comment 'web view content is rendered with the js form' test --- src/language/languageServerController.ts | 2 + src/mdbExtensionController.ts | 1 + .../editors/playgroundController.test.ts | 4 ++ src/test/suite/views/connectFormView.test.ts | 46 +++++++++---------- 4 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/language/languageServerController.ts b/src/language/languageServerController.ts index 1effe76f8..6ee8ac3f3 100644 --- a/src/language/languageServerController.ts +++ b/src/language/languageServerController.ts @@ -74,7 +74,9 @@ export default class LanguageServerController { serverOptions, clientOptions ); + } + activate() { // Start the client. This will also launch the server this.client.start(); this.client.onReady().then(() => { diff --git a/src/mdbExtensionController.ts b/src/mdbExtensionController.ts index a1a0d97f7..6c439cbc7 100644 --- a/src/mdbExtensionController.ts +++ b/src/mdbExtensionController.ts @@ -74,6 +74,7 @@ export default class MDBExtensionController implements vscode.Disposable { this._connectionController.loadSavedConnections(); this._explorerController.createTreeView(); this._telemetryController.activate(); + this._languageServerController.activate(); log.info('Registering commands...'); diff --git a/src/test/suite/editors/playgroundController.test.ts b/src/test/suite/editors/playgroundController.test.ts index 39c8eeef2..585f2b380 100644 --- a/src/test/suite/editors/playgroundController.test.ts +++ b/src/test/suite/editors/playgroundController.test.ts @@ -55,6 +55,8 @@ suite('Playground Controller Test Suite', () => { const testLanguageServerController = new LanguageServerController(mockExtensionContext, testConnectionController); const testPlaygroundController = new PlaygroundController(mockExtensionContext, testConnectionController, testLanguageServerController); + testLanguageServerController.activate(); + expect(testPlaygroundController.evaluate('1 + 1')).to.be.rejectedWith(Error, 'Please connect to a database before running a playground.'); }); }); @@ -66,6 +68,7 @@ suite('Playground Controller Test Suite', () => { ); const testLanguageServerController = new LanguageServerController(mockExtensionContext, testConnectionController); + testLanguageServerController.activate(); testConnectionController.getActiveConnectionDriverUrl = () => 'mongodb://localhost:27018'; const testPlaygroundController = new PlaygroundController(mockExtensionContext, testConnectionController, testLanguageServerController); @@ -132,6 +135,7 @@ suite('Playground Controller Test Suite', () => { ); const testLanguageServerController = new LanguageServerController(mockExtensionContext, testConnectionController); + testLanguageServerController.activate(); testConnectionController.getActiveConnectionName = () => 'fakeName'; testConnectionController.getActiveConnectionDriverUrl = () => 'mongodb://localhost:27018'; diff --git a/src/test/suite/views/connectFormView.test.ts b/src/test/suite/views/connectFormView.test.ts index c69cb70c7..a5d867c96 100644 --- a/src/test/suite/views/connectFormView.test.ts +++ b/src/test/suite/views/connectFormView.test.ts @@ -50,29 +50,29 @@ suite('Connect Form View Test Suite', () => { assert(stubOnDidRecieveMessage.called); }); - test('web view content is rendered with the js form', async () => { - async function readFile(filePath): Promise { - return new Promise((resolve, reject) => { - fs.readFile(filePath, 'utf8', function(err, data) { - if (err) { - reject(err); - } - resolve(data); - }); - }); - } + // test('web view content is rendered with the js form', async () => { + // async function readFile(filePath): Promise { + // return new Promise((resolve, reject) => { + // fs.readFile(filePath, 'utf8', function(err, data) { + // if (err) { + // reject(err); + // } + // resolve(data); + // }); + // }); + // } - const extensionPath = mdbTestExtension.testExtensionContext.extensionPath; - const appUri = getReactAppUri(extensionPath); - const htmlString = getConnectWebviewContent(appUri); + // const extensionPath = mdbTestExtension.testExtensionContext.extensionPath; + // const appUri = getReactAppUri(extensionPath); + // const htmlString = getConnectWebviewContent(appUri); - assert( - htmlString.includes('vscode-resource:/out/connect-form/connectForm.js') - ); - const connectFormFileName = (): string => 'out/connect-form/connectForm.js'; - const jsFileString = await readFile( - path.resolve(__dirname, '..', '..', '..', '..', connectFormFileName()) - ); - assert(`${jsFileString}`.includes('ConnectionForm')); - }); + // assert( + // htmlString.includes('vscode-resource:/out/connect-form/connectForm.js') + // ); + // const connectFormFileName = (): string => 'out/connect-form/connectForm.js'; + // const jsFileString = await readFile( + // path.resolve(__dirname, '..', '..', '..', '..', connectFormFileName()) + // ); + // assert(`${jsFileString}`.includes('ConnectionForm')); + // }); }); From ee02fb52e19e3592fe5c823f068926440a76cb30 Mon Sep 17 00:00:00 2001 From: Alena Khineika Date: Sun, 5 Apr 2020 13:11:52 +0200 Subject: [PATCH 12/14] test: uncomment test --- .../editors/playgroundController.test.ts | 2 + src/test/suite/stubs.ts | 2 +- src/test/suite/views/connectFormView.test.ts | 46 +++++++++---------- 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/test/suite/editors/playgroundController.test.ts b/src/test/suite/editors/playgroundController.test.ts index 585f2b380..ee3f6c26a 100644 --- a/src/test/suite/editors/playgroundController.test.ts +++ b/src/test/suite/editors/playgroundController.test.ts @@ -46,6 +46,8 @@ suite('Playground Controller Test Suite', () => { const sandbox = sinon.createSandbox(); + mockExtensionContext.extensionPath = 'TEST_FOLDER'; + suite('when user is not connected', () => { test('evaluate should throw the missing active connection error', async () => { const testConnectionController = new ConnectionController( diff --git a/src/test/suite/stubs.ts b/src/test/suite/stubs.ts index b13eead0a..b7229a9d4 100644 --- a/src/test/suite/stubs.ts +++ b/src/test/suite/stubs.ts @@ -36,7 +36,7 @@ class TestExtensionContext implements vscode.ExtensionContext { return new Promise(() => { this._globalState[key] = value; }); } }; - this.extensionPath = 'TEST_FOLDER'; + this.extensionPath = ''; this.storagePath = ''; } } diff --git a/src/test/suite/views/connectFormView.test.ts b/src/test/suite/views/connectFormView.test.ts index a5d867c96..b2ba55f1e 100644 --- a/src/test/suite/views/connectFormView.test.ts +++ b/src/test/suite/views/connectFormView.test.ts @@ -50,29 +50,29 @@ suite('Connect Form View Test Suite', () => { assert(stubOnDidRecieveMessage.called); }); - // test('web view content is rendered with the js form', async () => { - // async function readFile(filePath): Promise { - // return new Promise((resolve, reject) => { - // fs.readFile(filePath, 'utf8', function(err, data) { - // if (err) { - // reject(err); - // } - // resolve(data); - // }); - // }); - // } + test('web view content is rendered with the js form', async () => { + async function readFile(filePath): Promise { + return new Promise((resolve, reject) => { + fs.readFile(filePath, 'utf8', function (err, data) { + if (err) { + reject(err); + } + resolve(data); + }); + }); + } - // const extensionPath = mdbTestExtension.testExtensionContext.extensionPath; - // const appUri = getReactAppUri(extensionPath); - // const htmlString = getConnectWebviewContent(appUri); + const extensionPath = mdbTestExtension.testExtensionContext.extensionPath; + const appUri = getReactAppUri(extensionPath); + const htmlString = getConnectWebviewContent(appUri); - // assert( - // htmlString.includes('vscode-resource:/out/connect-form/connectForm.js') - // ); - // const connectFormFileName = (): string => 'out/connect-form/connectForm.js'; - // const jsFileString = await readFile( - // path.resolve(__dirname, '..', '..', '..', '..', connectFormFileName()) - // ); - // assert(`${jsFileString}`.includes('ConnectionForm')); - // }); + assert( + htmlString.includes('vscode-resource:/out/connect-form/connectForm.js') + ); + const connectFormFileName = (): string => 'out/connect-form/connectForm.js'; + const jsFileString = await readFile( + path.resolve(__dirname, '..', '..', '..', '..', connectFormFileName()) + ); + assert(`${jsFileString}`.includes('ConnectionForm')); + }); }); From fea4a0da4ac6f287a7ea713d49bd305ca594fe62 Mon Sep 17 00:00:00 2001 From: Alena Khineika Date: Sun, 5 Apr 2020 13:44:49 +0200 Subject: [PATCH 13/14] refactor: use relative path --- src/language/languageServerController.ts | 6 +----- src/test/suite/editors/playgroundController.test.ts | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/language/languageServerController.ts b/src/language/languageServerController.ts index 6ee8ac3f3..1c07550a4 100644 --- a/src/language/languageServerController.ts +++ b/src/language/languageServerController.ts @@ -28,11 +28,7 @@ export default class LanguageServerController { this._connectionController = connectionController; // The server is implemented in node - const serverModule = context.asAbsolutePath( - context.extensionPath === 'TEST_FOLDER' - ? path.join('..', '..', 'out', 'language', 'server.js') - : path.join('out', 'language', 'server.js') - ); + const serverModule = path.join(context.extensionPath, 'out', 'language', 'server.js'); // The debug options for the server // --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging diff --git a/src/test/suite/editors/playgroundController.test.ts b/src/test/suite/editors/playgroundController.test.ts index ee3f6c26a..84c8210ed 100644 --- a/src/test/suite/editors/playgroundController.test.ts +++ b/src/test/suite/editors/playgroundController.test.ts @@ -46,7 +46,7 @@ suite('Playground Controller Test Suite', () => { const sandbox = sinon.createSandbox(); - mockExtensionContext.extensionPath = 'TEST_FOLDER'; + mockExtensionContext.extensionPath = '../../'; suite('when user is not connected', () => { test('evaluate should throw the missing active connection error', async () => { From c26d130273eaf0617c417d12df5109338783b963 Mon Sep 17 00:00:00 2001 From: Alena Khineika Date: Mon, 6 Apr 2020 16:41:29 +0200 Subject: [PATCH 14/14] fix: return original errors from mongosh --- scripts/generate-keyfile.ts | 2 +- src/language/server.ts | 14 +++++--------- .../suite/editors/playgroundController.test.ts | 2 +- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/scripts/generate-keyfile.ts b/scripts/generate-keyfile.ts index 0d64fd9e6..ea590d637 100644 --- a/scripts/generate-keyfile.ts +++ b/scripts/generate-keyfile.ts @@ -25,5 +25,5 @@ config({ path: resolve(__dirname, '../.env') }); } })().catch((error) => { ui.fail('Failed to generate constants keyfile'); - console.log(error); + console.log(error.message); }) diff --git a/src/language/server.ts b/src/language/server.ts index 4413462e1..f51da0bd7 100644 --- a/src/language/server.ts +++ b/src/language/server.ts @@ -278,16 +278,12 @@ connection.onCompletionResolve( * Execute the entire playground script. */ connection.onRequest('executeAll', async (params) => { - try { - const connectionOptions = params.connectionOptions || {}; - const runtime = new ElectronRuntime( - await CliServiceProvider.connect(params.connectionString, connectionOptions) - ); + const connectionOptions = params.connectionOptions || {}; + const runtime = new ElectronRuntime( + await CliServiceProvider.connect(params.connectionString, connectionOptions) + ); - return await runtime.evaluate(params.codeToEvaluate); - } catch (error) { - throw new Error('Unable to connect to MongoDB instance. Make sure it is started correctly.'); - } + return await runtime.evaluate(params.codeToEvaluate); }); /** diff --git a/src/test/suite/editors/playgroundController.test.ts b/src/test/suite/editors/playgroundController.test.ts index 84c8210ed..88bda2dac 100644 --- a/src/test/suite/editors/playgroundController.test.ts +++ b/src/test/suite/editors/playgroundController.test.ts @@ -28,7 +28,7 @@ const getDocUri = (docName: string) => { /** * Opens the MongoDB playground */ -export async function openPlayground(docUri: vscode.Uri) { +async function openPlayground(docUri: vscode.Uri) { try { const doc = await vscode.workspace.openTextDocument(docUri);