From c6e7633090c6ac768536393fc41f9f2854613a22 Mon Sep 17 00:00:00 2001 From: Rhys Date: Thu, 18 Jan 2024 13:45:16 -0500 Subject: [PATCH 1/7] chore: cancel connection attempt when removing connection, update assert to expect in webview and connection controller tests (#667) --- src/connectionController.ts | 7 + src/test/suite/connectionController.test.ts | 375 +++++------- .../suite/views/webviewController.test.ts | 577 +++++++----------- 3 files changed, 400 insertions(+), 559 deletions(-) diff --git a/src/connectionController.ts b/src/connectionController.ts index 259c03387..1572fd834 100644 --- a/src/connectionController.ts +++ b/src/connectionController.ts @@ -618,6 +618,13 @@ export default class ConnectionController { } async removeSavedConnection(connectionId: string): Promise { + if ( + this._connectionAttempt && + connectionId === this._connectingConnectionId + ) { + this.cancelConnectionAttempt(); + } + delete this._connections[connectionId]; await this._connectionStorage.removeConnection(connectionId); diff --git a/src/test/suite/connectionController.test.ts b/src/test/suite/connectionController.test.ts index 7c9df1db2..ca06ae39e 100644 --- a/src/test/suite/connectionController.test.ts +++ b/src/test/suite/connectionController.test.ts @@ -3,7 +3,6 @@ import type { SinonStub } from 'sinon'; import util from 'util'; import * as vscode from 'vscode'; import { afterEach, beforeEach } from 'mocha'; -import assert from 'assert'; import * as mongodbDataService from 'mongodb-data-service'; import { expect } from 'chai'; import ConnectionString from 'mongodb-connection-string-url'; @@ -89,15 +88,12 @@ suite('Connection Controller Test Suite', function () { const name = testConnectionController._connections[connnectionId].name; const dataService = testConnectionController.getActiveDataService(); - assert.strictEqual(succesfullyConnected, true); - assert.strictEqual( - testConnectionController.getSavedConnections().length, - 1 - ); - assert.strictEqual(name, 'localhost:27088'); - assert.strictEqual(testConnectionController.isCurrentlyConnected(), true); + expect(succesfullyConnected).to.be.true; + expect(testConnectionController.getSavedConnections().length).to.equal(1); + expect(name).to.equal('localhost:27088'); + expect(testConnectionController.isCurrentlyConnected()).to.be.true; - assert.notStrictEqual(dataService, null); + expect(dataService).to.not.equal(null); }); test('"disconnect()" disconnects from the active connection', async () => { @@ -106,9 +102,8 @@ suite('Connection Controller Test Suite', function () { TEST_DATABASE_URI ); - assert.strictEqual(succesfullyConnected, true); - assert.strictEqual( - testConnectionController.getConnectionStatus(), + expect(succesfullyConnected).to.be.true; + expect(testConnectionController.getConnectionStatus()).to.equal( 'CONNECTED' ); @@ -121,15 +116,14 @@ suite('Connection Controller Test Suite', function () { const connnectionId = testConnectionController.getActiveConnectionId(); const dataService = testConnectionController.getActiveDataService(); - assert.strictEqual( - testConnectionController.getConnectionStatus(), + expect(testConnectionController.getConnectionStatus()).to.equal( 'DISCONNECTED' ); - assert.strictEqual(successfullyDisconnected, true); - assert.strictEqual(connectionsCount, 1); - assert.strictEqual(connnectionId, null); - assert.strictEqual(testConnectionController.isCurrentlyConnected(), false); - assert.strictEqual(dataService, null); + expect(successfullyDisconnected).to.be.true; + expect(connectionsCount).to.equal(1); + expect(connnectionId).to.equal(null); + expect(testConnectionController.isCurrentlyConnected()).to.be.false; + expect(dataService).to.equal(null); }); test('"removeMongoDBConnection()" returns a reject promise when there is no active connection', async () => { @@ -137,8 +131,8 @@ suite('Connection Controller Test Suite', function () { const successfullyRemovedMongoDBConnection = await testConnectionController.onRemoveMongoDBConnection(); - assert.strictEqual(showErrorMessageStub.firstCall.args[0], expectedMessage); - assert.strictEqual(successfullyRemovedMongoDBConnection, false); + expect(showErrorMessageStub.firstCall.args[0]).to.equal(expectedMessage); + expect(successfullyRemovedMongoDBConnection).to.be.false; }); test('"disconnect()" fails when there is no active connection', async () => { @@ -146,8 +140,8 @@ suite('Connection Controller Test Suite', function () { const successfullyDisconnected = await testConnectionController.disconnect(); - assert.strictEqual(showErrorMessageStub.firstCall.args[0], expectedMessage); - assert.strictEqual(successfullyDisconnected, false); + expect(showErrorMessageStub.firstCall.args[0]).to.equal(expectedMessage); + expect(successfullyDisconnected).to.be.false; }); test('when adding a new connection it disconnects from the current connection', async () => { @@ -156,7 +150,7 @@ suite('Connection Controller Test Suite', function () { TEST_DATABASE_URI ); - assert.strictEqual(succesfullyConnected, true); + expect(succesfullyConnected).to.be.true; try { await testConnectionController.addNewConnectionStringAndConnect( @@ -165,15 +159,9 @@ suite('Connection Controller Test Suite', function () { } catch (error) { const expectedError = 'Failed to connect'; - assert.strictEqual( - formatError(error).message.includes(expectedError), - true - ); - assert.strictEqual(testConnectionController.getActiveDataService(), null); - assert.strictEqual( - testConnectionController.getActiveConnectionId(), - null - ); + expect(formatError(error).message.includes(expectedError)).to.be.true; + expect(testConnectionController.getActiveDataService()).to.equal(null); + expect(testConnectionController.getActiveConnectionId()).to.equal(null); } }); @@ -183,7 +171,7 @@ suite('Connection Controller Test Suite', function () { TEST_DATABASE_URI ); - assert.strictEqual(succesfullyConnected, true); + expect(succesfullyConnected).to.be.true; let wasSetToConnectingWhenDisconnecting = false; sandbox.replace(testConnectionController, 'disconnect', () => { @@ -197,26 +185,25 @@ suite('Connection Controller Test Suite', function () { TEST_DATABASE_URI ); - assert.strictEqual(succesfullyConnected2, true); - assert.strictEqual(wasSetToConnectingWhenDisconnecting, true); + expect(succesfullyConnected2).to.be.true; + expect(wasSetToConnectingWhenDisconnecting).to.be.true; }); - test('"connect()" should fire a CONNECTIONS_DID_CHANGE event', async () => { - let isConnectionChanged = false; - + test('"connect()" should fire 3 CONNECTIONS_DID_CHANGE event', (done) => { + let eventCounter = 0; testConnectionController.addEventListener( DataServiceEventTypes.CONNECTIONS_DID_CHANGE, () => { - isConnectionChanged = true; + eventCounter++; + if (eventCounter === 3) { + done(); + } } ); - await testConnectionController.addNewConnectionStringAndConnect( + void testConnectionController.addNewConnectionStringAndConnect( TEST_DATABASE_URI ); - await sleep(50); - - assert.strictEqual(isConnectionChanged, true); }); const expectedTimesToFire = 4; @@ -237,16 +224,13 @@ suite('Connection Controller Test Suite', function () { await testConnectionController.disconnect(); await sleep(100); - assert.strictEqual(connectionEventFiredCount, expectedTimesToFire); + expect(connectionEventFiredCount).to.equal(expectedTimesToFire); }); test('when there are no existing connections in the store and the connection controller loads connections', async () => { await testConnectionController.loadSavedConnections(); - const connectionsCount = - testConnectionController.getSavedConnections().length; - - assert.strictEqual(connectionsCount, 0); + expect(testConnectionController.getSavedConnections().length).to.equal(0); }); test('the connection model loads both global and workspace stored connection models', async () => { @@ -303,12 +287,11 @@ suite('Connection Controller Test Suite', function () { StorageLocation.GLOBAL ); - assert.strictEqual(Object.keys(globalStoreConnections).length, 1); + expect(Object.keys(globalStoreConnections).length).to.equal(1); const id = Object.keys(globalStoreConnections)[0]; - assert.strictEqual( - globalStoreConnections[id].name, + expect(globalStoreConnections[id].name).to.equal( testDatabaseConnectionName ); @@ -316,7 +299,7 @@ suite('Connection Controller Test Suite', function () { StorageVariables.WORKSPACE_SAVED_CONNECTIONS ); - assert.strictEqual(workspaceStoreConnections, undefined); + expect(workspaceStoreConnections).to.equal(undefined); }); test('when a connection is added it is saved to the workspace store', async () => { @@ -336,12 +319,11 @@ suite('Connection Controller Test Suite', function () { StorageLocation.WORKSPACE ); - assert.strictEqual(Object.keys(workspaceStoreConnections).length, 1); + expect(Object.keys(workspaceStoreConnections).length).to.equal(1); const id = Object.keys(workspaceStoreConnections)[0]; - assert.strictEqual( - workspaceStoreConnections[id].name, + expect(workspaceStoreConnections[id].name).to.equal( testDatabaseConnectionName ); @@ -350,7 +332,7 @@ suite('Connection Controller Test Suite', function () { StorageLocation.GLOBAL ); - assert.strictEqual(globalStoreConnections, undefined); + expect(globalStoreConnections).to.equal(undefined); }); test('a connection can be connected to by id', async () => { @@ -367,8 +349,8 @@ suite('Connection Controller Test Suite', function () { const connectionResult = await testConnectionController.connectWithConnectionId('25'); - assert.strictEqual(connectionResult.successfullyConnected, true); - assert.strictEqual(testConnectionController.getActiveConnectionId(), '25'); + expect(connectionResult.successfullyConnected).to.be.true; + expect(testConnectionController.getActiveConnectionId()).to.equal('25'); }); test('a saved connection can be loaded and connected to workspace store', async () => { @@ -388,23 +370,17 @@ suite('Connection Controller Test Suite', function () { StorageLocation.WORKSPACE ); - assert.strictEqual(Object.keys(workspaceStoreConnections).length, 1); + expect(Object.keys(workspaceStoreConnections).length).to.equal(1); await testConnectionController.disconnect(); testConnectionController.clearAllConnections(); - assert.strictEqual( - testConnectionController.getSavedConnections().length, - 0 - ); + expect(testConnectionController.getSavedConnections().length).to.equal(0); // Activate (which will load the past connection). await testConnectionController.loadSavedConnections(); - assert.strictEqual( - testConnectionController.getSavedConnections().length, - 1 - ); + expect(testConnectionController.getSavedConnections().length).to.equal(1); const id = testConnectionController.getSavedConnections()[0].id; @@ -413,8 +389,8 @@ suite('Connection Controller Test Suite', function () { const activeId = testConnectionController.getActiveConnectionId(); const name = testConnectionController._connections[activeId || ''].name; - assert.strictEqual(activeId, id); - assert.strictEqual(name, 'localhost:27088'); + expect(activeId).to.equal(id); + expect(name).to.equal('localhost:27088'); }); test('"copyConnectionStringByConnectionId" returns the driver uri of a connection', async () => { @@ -427,14 +403,14 @@ suite('Connection Controller Test Suite', function () { const activeConnectionId = testConnectionController.getActiveConnectionId(); - assert.notStrictEqual(activeConnectionId, null); + expect(activeConnectionId).to.not.equal(null); const testDriverUrl = testConnectionController.copyConnectionStringByConnectionId( activeConnectionId || '' ); - assert.strictEqual(testDriverUrl, expectedDriverUrl); + expect(testDriverUrl).to.equal(expectedDriverUrl); }); test('when a connection is added and the user has set it to not save on default it is not saved', async () => { @@ -457,14 +433,14 @@ suite('Connection Controller Test Suite', function () { StorageLocation.GLOBAL ); - assert.strictEqual(JSON.stringify(globalStoreConnections), objectString); + expect(JSON.stringify(globalStoreConnections)).to.equal(objectString); const workspaceStoreConnections = testStorageController.get( StorageVariables.WORKSPACE_SAVED_CONNECTIONS, StorageLocation.WORKSPACE ); - assert.strictEqual(JSON.stringify(workspaceStoreConnections), objectString); + expect(JSON.stringify(workspaceStoreConnections)).to.equal(objectString); }); test('getNotifyDeviceFlowForConnectionAttempt returns a function that shows a message with the url when oidc is set', function () { @@ -474,7 +450,7 @@ suite('Connection Controller Test Suite', function () { } ); - assert.strictEqual(expectedUndefinedDeviceFlow, undefined); + expect(expectedUndefinedDeviceFlow).to.equal(undefined); const oidcConnectionString = new ConnectionString(TEST_DATABASE_URI); oidcConnectionString.searchParams.set('authMechanism', 'MONGODB-OIDC'); @@ -482,8 +458,8 @@ suite('Connection Controller Test Suite', function () { const expectedFunction = getNotifyDeviceFlowForConnectionAttempt({ connectionString: oidcConnectionString.toString(), }); - assert.notStrictEqual(expectedFunction, undefined); - assert.strictEqual(showInformationMessageStub.called, false); + expect(expectedFunction).to.not.equal(undefined); + expect(showInformationMessageStub.called).to.equal(false); ( expectedFunction as (deviceFlowInformation: { @@ -495,15 +471,9 @@ suite('Connection Controller Test Suite', function () { userCode: 'testabc', }); - assert.strictEqual(showInformationMessageStub.called, true); - assert.strictEqual( - showInformationMessageStub.firstCall.args[0].includes('test123'), - true - ); - assert.strictEqual( - showInformationMessageStub.firstCall.args[0].includes('testabc'), - true - ); + expect(showInformationMessageStub.called).to.be.true; + expect(showInformationMessageStub.firstCall.args[0]).to.include('test123'); + expect(showInformationMessageStub.firstCall.args[0]).to.include('testabc'); }); test('when a connection is removed it is also removed from workspace store', async () => { @@ -523,7 +493,7 @@ suite('Connection Controller Test Suite', function () { StorageLocation.WORKSPACE ); - assert.strictEqual(Object.keys(workspaceStoreConnections).length, 1); + expect(Object.keys(workspaceStoreConnections).length).to.equal(1); const connectionId = testConnectionController.getActiveConnectionId() || 'a'; @@ -536,7 +506,7 @@ suite('Connection Controller Test Suite', function () { StorageLocation.WORKSPACE ); - assert.strictEqual(Object.keys(postWorkspaceStoreConnections).length, 0); + expect(Object.keys(postWorkspaceStoreConnections).length).to.equal(0); }); test('when a connection is removed it is also removed from global storage', async () => { @@ -553,7 +523,7 @@ suite('Connection Controller Test Suite', function () { StorageLocation.GLOBAL ); - assert.strictEqual(Object.keys(globalStoreConnections).length, 1); + expect(Object.keys(globalStoreConnections).length).to.equal(1); const connectionId = testConnectionController.getActiveConnectionId() || 'a'; @@ -564,7 +534,7 @@ suite('Connection Controller Test Suite', function () { StorageLocation.GLOBAL ); - assert.strictEqual(Object.keys(postGlobalStoreConnections).length, 0); + expect(Object.keys(postGlobalStoreConnections).length).to.equal(0); }); test('when a connection is removed, the secrets for that connection are also removed', async () => { @@ -579,7 +549,7 @@ suite('Connection Controller Test Suite', function () { const [connection] = testConnectionController.getSavedConnections(); await testConnectionController.removeSavedConnection(connection.id); - assert.strictEqual(secretStorageDeleteSpy.calledOnce, true); + expect(secretStorageDeleteSpy.calledOnce).to.be.true; }); test('a saved to workspace connection can be renamed and loaded', async () => { @@ -599,7 +569,7 @@ suite('Connection Controller Test Suite', function () { StorageLocation.WORKSPACE ); - assert.strictEqual(Object.keys(workspaceStoreConnections).length, 1); + expect(Object.keys(workspaceStoreConnections).length).to.equal(1); const connectionId = testConnectionController.getActiveConnectionId() || 'zz'; @@ -612,29 +582,23 @@ suite('Connection Controller Test Suite', function () { connectionId ); - assert.strictEqual(renameSuccess, true); + expect(renameSuccess).to.be.true; await testConnectionController.disconnect(); testConnectionController.clearAllConnections(); - assert.strictEqual( - testConnectionController.getSavedConnections().length, - 0 - ); + expect(testConnectionController.getSavedConnections().length).to.equal(0); // Activate (which will load the past connection). await testConnectionController.loadSavedConnections(); - assert.strictEqual( - testConnectionController.getSavedConnections().length, - 1 - ); + expect(testConnectionController.getSavedConnections().length).to.equal(1); const id = testConnectionController.getSavedConnections()[0].id; const name = testConnectionController._connections[id || 'x'].name; - assert.strictEqual(name, 'new connection name'); + expect(name, 'new connection name'); }); test('a saved to workspace connection can be updated and loaded', async () => { @@ -654,7 +618,7 @@ suite('Connection Controller Test Suite', function () { StorageLocation.WORKSPACE ); - assert.strictEqual(Object.keys(workspaceStoreConnections).length, 1); + expect(Object.keys(workspaceStoreConnections).length).to.equal(1); const connectionId = testConnectionController.getActiveConnectionId() || 'zz'; @@ -669,24 +633,18 @@ suite('Connection Controller Test Suite', function () { }, }); - assert.strictEqual(updateSuccess.successfullyConnected, true); + expect(updateSuccess.successfullyConnected).to.be.true; await testConnectionController.disconnect(); testConnectionController.clearAllConnections(); - assert.strictEqual( - testConnectionController.getSavedConnections().length, - 0 - ); + expect(testConnectionController.getSavedConnections().length).to.equal(0); // Activate (which will load the past connection). await testConnectionController.loadSavedConnections(); - assert.strictEqual( - testConnectionController.getSavedConnections().length, - 1 - ); + expect(testConnectionController.getSavedConnections().length).to.equal(1); const id = testConnectionController.getSavedConnections()[0].id; const connectTimeoutMS = new ConnectionString( @@ -694,9 +652,9 @@ suite('Connection Controller Test Suite', function () { ).searchParams.get('connectTimeoutMS'); const name = testConnectionController._connections[id || 'x'].name; - assert.strictEqual(name, 'localhost:27088'); + expect(name).to.equal('localhost:27088'); // Ensure it's updated. - assert.strictEqual(connectTimeoutMS, '5000'); + expect(connectTimeoutMS).to.equal('5000'); }); test('close connection string input calls to cancel the cancellation token', function (done) { @@ -704,11 +662,11 @@ suite('Connection Controller Test Suite', function () { inputBoxResolvesStub.callsFake(() => { try { const cancellationToken = inputBoxResolvesStub.firstCall.args[1]; - assert.strictEqual(cancellationToken.isCancellationRequested, false); + expect(cancellationToken.isCancellationRequested).to.be.false; testConnectionController.closeConnectionStringInput(); - assert.strictEqual(cancellationToken.isCancellationRequested, true); + expect(cancellationToken.isCancellationRequested).to.be.true; } catch (err) { done(err); } @@ -742,9 +700,9 @@ suite('Connection Controller Test Suite', function () { const connections = testConnectionController._connections; const connectionIds = Object.keys(connections); - assert.strictEqual(connectionIds.length, 2); - assert.strictEqual(connections[connectionIds[0]].name, 'localhost:27088'); - assert.strictEqual(connections[connectionIds[1]].name, 'localhost:27088'); + expect(connectionIds.length).to.equal(2); + expect(connections[connectionIds[0]].name).to.equal('localhost:27088'); + expect(connections[connectionIds[1]].name).to.equal('localhost:27088'); const inputBoxResolvesStub = sandbox.stub(); inputBoxResolvesStub.onCall(0).resolves('Lynx'); @@ -754,39 +712,36 @@ suite('Connection Controller Test Suite', function () { connectionIds[0] ); - assert.strictEqual(renameSuccess, true); + expect(renameSuccess).to.be.true; await testConnectionController.loadSavedConnections(); - assert.strictEqual(connectionIds.length, 2); + expect(connectionIds.length).to.equal(2); const connectionQuickPicks = testConnectionController.getConnectionQuickPicks(); - assert.strictEqual(connectionQuickPicks.length, 3); - assert.strictEqual(connectionQuickPicks[0].label, 'Add new connection'); - assert.strictEqual(connectionQuickPicks[1].label, 'localhost:27088'); - assert.strictEqual(connectionQuickPicks[2].label, 'Lynx'); + expect(connectionQuickPicks.length).to.equal(3); + expect(connectionQuickPicks[0].label).to.equal('Add new connection'); + expect(connectionQuickPicks[1].label).to.equal('localhost:27088'); + expect(connectionQuickPicks[2].label).to.equal('Lynx'); }); suite('connecting to a new connection when already connecting', () => { test('connects to the new connection', async () => { - void testConnectionController.addNewConnectionStringAndConnect( - testDatabaseURI2WithTimeout - ); - - await testConnectionController.addNewConnectionStringAndConnect( - TEST_DATABASE_URI - ); - - assert(!testConnectionController.isConnecting()); + await Promise.all([ + testConnectionController.addNewConnectionStringAndConnect( + testDatabaseURI2WithTimeout + ), + testConnectionController.addNewConnectionStringAndConnect( + TEST_DATABASE_URI + ), + ]); - // Ensure the first connection completes. - await sleep(1050); + expect(testConnectionController.isConnecting()).to.be.false; - assert.strictEqual(testConnectionController.isCurrentlyConnected(), true); - assert.strictEqual( - testConnectionController.getActiveConnectionName(), + expect(testConnectionController.isCurrentlyConnected()).to.be.true; + expect(testConnectionController.getActiveConnectionName()).to.equal( 'localhost:27088' ); }); @@ -803,43 +758,55 @@ suite('Connection Controller Test Suite', function () { }; } + const connectPromises: Promise[] = []; for (let i = 0; i < 5; i++) { const id = `${i}`; - void testConnectionController.connectWithConnectionId(id); + connectPromises.push( + testConnectionController.connectWithConnectionId(id) + ); } // Ensure the connections complete. - await sleep(1000); + await Promise.all(connectPromises); - assert.strictEqual(testConnectionController.isConnecting(), false); - assert.strictEqual(testConnectionController.isCurrentlyConnected(), true); - assert.strictEqual( - testConnectionController.getActiveConnectionName(), + expect(testConnectionController.isConnecting()).to.be.false; + expect(testConnectionController.isCurrentlyConnected()).to.be.true; + expect(testConnectionController.getActiveConnectionName()).to.equal( 'test4' ); }); }); - test('two disconnects on one connection at once', async () => { - await testConnectionController.addNewConnectionStringAndConnect( - TEST_DATABASE_URI - ); - - try { - void testConnectionController.disconnect(); - void testConnectionController.disconnect(); - } catch (err) { - assert( - false, - `Expected not to error when disconnecting multiple times, received: ${err}` + suite('when connected', function () { + beforeEach(async function () { + await testConnectionController.addNewConnectionStringAndConnect( + TEST_DATABASE_URI ); - } + }); - // Ensure the disconnects complete. - await sleep(100); + test('two disconnects on one connection at once complete without erroring', (done) => { + let disconnectsCompleted = 0; + async function disconnect() { + try { + await testConnectionController.disconnect(); + + ++disconnectsCompleted; + if (disconnectsCompleted === 2) { + expect(testConnectionController.isCurrentlyConnected()).to.be.false; + expect(testConnectionController.getActiveDataService()).to.equal( + null + ); + + done(); + } + } catch (err) { + return done(err); + } + } - assert.strictEqual(testConnectionController.isCurrentlyConnected(), false); - assert.strictEqual(testConnectionController.getActiveDataService(), null); + void disconnect(); + void disconnect(); + }); }); test('a connection which fails can be removed while it is being connected to', async () => { @@ -854,17 +821,16 @@ suite('Connection Controller Test Suite', function () { void testConnectionController.connectWithConnectionId(connectionId); - assert.strictEqual(testConnectionController.isConnecting(), true); - assert.strictEqual( - testConnectionController.getConnectionStatus(), + expect(testConnectionController.isConnecting()).to.be.true; + expect(testConnectionController.getConnectionStatus()).to.equal( 'CONNECTING' ); - try { - await testConnectionController.removeSavedConnection(connectionId); - } catch (error) { - assert.strictEqual(formatError(error), false); - } + await testConnectionController.removeSavedConnection(connectionId); + + // Check that it's removed. + expect(testConnectionController.isConnecting()).to.be.false; + expect(testConnectionController._connections[connectionId]).to.be.undefined; }); test('a successfully connecting connection can be removed while it is being connected to', async () => { @@ -883,25 +849,21 @@ suite('Connection Controller Test Suite', function () { async (connectionOptions) => { await sleep(50); + expect(testConnectionController.isConnecting()).to.be.true; + return mongodbDataService.connect({ connectionOptions: connectionOptions.connectionOptions, }); } ); - void testConnectionController.connectWithConnectionId(connectionId); - - // Ensure the connection attempt has started. - await sleep(10); + await Promise.all([ + testConnectionController.connectWithConnectionId(connectionId), - assert.strictEqual(testConnectionController.isConnecting(), true); + testConnectionController.removeSavedConnection(connectionId), + ]); - await testConnectionController.removeSavedConnection(connectionId); - - // Wait for the connection to timeout and complete (and not error in the process). - await sleep(250); - - assert.strictEqual(testConnectionController.isCurrentlyConnected(), false); + expect(testConnectionController.isCurrentlyConnected()).to.be.false; }); test('_getConnectionInfoWithSecrets returns the connection info with secrets', async () => { @@ -922,14 +884,14 @@ suite('Connection Controller Test Suite', function () { const connections = testConnectionController.getSavedConnections(); - assert.strictEqual(connections.length, 1); + expect(connections.length).to.equal(1); const newSavedConnectionInfoWithSecrets = await testConnectionController._connectionStorage._getConnectionInfoWithSecrets( connections[0] ); - assert.deepStrictEqual(newSavedConnectionInfoWithSecrets, connectionInfo); + expect(newSavedConnectionInfoWithSecrets).to.deep.equal(connectionInfo); }); test('addNewConnectionStringAndConnect saves connection without secrets to the global storage', async () => { @@ -979,12 +941,14 @@ suite('Connection Controller Test Suite', function () { const mongoClientConnectionOptions = testConnectionController.getMongoClientConnectionOptions(); - assert(mongoClientConnectionOptions !== undefined); + expect(mongoClientConnectionOptions).to.not.equal(undefined); - delete mongoClientConnectionOptions.options.parentHandle; - delete mongoClientConnectionOptions.options.oidc?.openBrowser; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + delete mongoClientConnectionOptions!.options.parentHandle; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + delete mongoClientConnectionOptions!.options.oidc?.openBrowser; - assert.deepStrictEqual(mongoClientConnectionOptions, { + expect(mongoClientConnectionOptions).to.deep.equal({ url: `mongodb://localhost:27088/?appname=mongodb-vscode+${version}`, options: { autoEncryption: undefined, @@ -1011,7 +975,7 @@ suite('Connection Controller Test Suite', function () { proxyUsername: 'test', }, }); - assert.strictEqual(connectionString, expectedConnectionStringWithProxy); + expect(connectionString).to.equal(expectedConnectionStringWithProxy); }); suite('loadSavedConnections', () => { @@ -1047,13 +1011,12 @@ suite('Connection Controller Test Suite', function () { // By default the connection secrets are already stored in SecretStorage const savedConnections = testConnectionController.getSavedConnections(); - assert.strictEqual( + expect( savedConnections.every( ({ secretStorageLocation }) => secretStorageLocation === SecretStorageLocation.SecretStorage - ), - true - ); + ) + ).to.be.true; await testConnectionController.disconnect(); testConnectionController.clearAllConnections(); @@ -1061,18 +1024,14 @@ suite('Connection Controller Test Suite', function () { await testConnectionController.loadSavedConnections(); const savedConnectionsAfterFreshLoad = testConnectionController.getSavedConnections(); - assert.deepStrictEqual( - savedConnections, + expect(savedConnections).to.deep.equal( testConnectionController.getSavedConnections() ); // Additionally make sure that we are retrieving secrets properly - assert.strictEqual( - savedConnectionsAfterFreshLoad[1].connectionOptions?.connectionString.includes( - TEST_USER_PASSWORD - ), - true - ); + expect( + savedConnectionsAfterFreshLoad[1].connectionOptions?.connectionString + ).to.include(TEST_USER_PASSWORD); }); }); @@ -1093,7 +1052,7 @@ suite('Connection Controller Test Suite', function () { ); await testConnectionController.loadSavedConnections(); - assert.strictEqual(isConnectionChanged, true); + expect(isConnectionChanged).to.be.true; }); test('should ignore older unsupported secrets', async () => { @@ -1153,12 +1112,10 @@ suite('Connection Controller Test Suite', function () { testConnectionController.clearAllConnections(); await testConnectionController.loadSavedConnections(); - assert.strictEqual( - Object.keys(testConnectionController._connections).length, - 1 - ); - assert.strictEqual( - Object.values(testConnectionController._connections)[0], + expect( + Object.keys(testConnectionController._connections).length + ).to.equal(1); + expect(Object.values(testConnectionController._connections)[0]).to.equal( loadedConnection ); }); @@ -1232,8 +1189,8 @@ suite('Connection Controller Test Suite', function () { // Load connections tracked. Called once because in the current load of // migration there were no errors and hence the error tracking event won't // be called. - assert.strictEqual(trackStub.calledOnce, true); - assert.deepStrictEqual(trackStub.lastCall.args, [ + expect(trackStub.calledOnce).to.be.true; + expect(trackStub.lastCall.args).to.deep.equal([ { connections_with_secrets_in_keytar: 2, connections_with_secrets_in_secret_storage: 2, diff --git a/src/test/suite/views/webviewController.test.ts b/src/test/suite/views/webviewController.test.ts index b2b340612..3672f4566 100644 --- a/src/test/suite/views/webviewController.test.ts +++ b/src/test/suite/views/webviewController.test.ts @@ -1,6 +1,6 @@ import sinon from 'sinon'; import * as vscode from 'vscode'; -import assert from 'assert'; +import { expect } from 'chai'; import { before, after, beforeEach, afterEach } from 'mocha'; import fs from 'fs'; import path from 'path'; @@ -18,6 +18,17 @@ import WebviewController, { } from '../../../views/webviewController'; import * as linkHelper from '../../../utils/linkHelper'; +function waitFor(condition: () => boolean, timeout = 10) { + return new Promise((resolve) => { + const testInterval = setInterval(() => { + if (condition()) { + clearInterval(testInterval); + resolve(); + } + }, timeout); + }); +} + suite('Webview Test Suite', () => { const sandbox = sinon.createSandbox(); let extensionContextStub: ExtensionContextStub; @@ -47,6 +58,7 @@ suite('Webview Test Suite', () => { mdbTestExtension.testExtensionController._telemetryService, 'trackNewConnection' ); + sandbox.stub(testTelemetryService, 'trackNewConnection'); }); afterEach(() => { @@ -54,22 +66,18 @@ suite('Webview Test Suite', () => { }); test('it creates a web view panel and sets the html content', () => { - const stubOnDidRecieveMessage = sandbox.stub(); + const stubOnDidReceiveMessage = sandbox.stub(); const fakeWebview = { html: '', - onDidReceiveMessage: stubOnDidRecieveMessage, - asWebviewUri: sandbox.fake.returns(''), - }; - const fakeVSCodeCreateWebviewPanel = sandbox.fake.returns({ - webview: fakeWebview, - onDidDispose: sandbox.fake.returns(''), - }); - - sandbox.replace( - vscode.window, - 'createWebviewPanel', - fakeVSCodeCreateWebviewPanel - ); + onDidReceiveMessage: stubOnDidReceiveMessage, + asWebviewUri: sandbox.stub().returns(''), + } as unknown as vscode.Webview; + const fakeVSCodeCreateWebviewPanel = sandbox + .stub(vscode.window, 'createWebviewPanel') + .returns({ + webview: fakeWebview, + onDidDispose: sandbox.stub().returns(''), + } as unknown as vscode.WebviewPanel); const testWebviewController = new WebviewController({ connectionController: @@ -84,12 +92,9 @@ suite('Webview Test Suite', () => { mdbTestExtension.extensionContextStub ); - assert(fakeVSCodeCreateWebviewPanel.called); - assert(fakeWebview.html !== ''); - assert( - stubOnDidRecieveMessage.called, - 'Ensure it starts listening for messages from the webview.' - ); + expect(fakeVSCodeCreateWebviewPanel).to.be.calledOnce; + expect(fakeWebview.html).to.not.equal(''); + expect(stubOnDidReceiveMessage).to.be.calledOnce; }); test('web view content is rendered with the js form', async () => { @@ -104,68 +109,58 @@ suite('Webview Test Suite', () => { }); } - const webviewStub: any = { - asWebviewUri: (jsUri) => { - return jsUri; - }, - }; - const extensionPath = mdbTestExtension.extensionContextStub.extensionPath; const htmlString = getWebviewContent({ extensionPath, telemetryUserId: '', - webview: webviewStub, + webview: { + asWebviewUri: (jsUri) => { + return jsUri; + }, + } as unknown as vscode.Webview, }); - assert(htmlString.includes('dist/webviewApp.js')); + expect(htmlString).to.include('dist/webviewApp.js'); const webviewAppFileName = (): string => 'dist/webviewApp.js'; const jsFileString = await readFile( path.join(extensionPath, webviewAppFileName()) ); - assert(`${jsFileString}`.includes('OverviewPage')); + expect(`${jsFileString}`).to.include('OverviewPage'); }); test('web view content sets the segment anonymous id globally', () => { - const fakeWebview: any = { - asWebviewUri: (jsUri) => { - return jsUri; - }, - }; - const extensionPath = mdbTestExtension.extensionContextStub.extensionPath; const htmlString = getWebviewContent({ extensionPath, telemetryUserId: 'MOCK_ANONYMOU_ID', - webview: fakeWebview, + webview: { + asWebviewUri: (jsUri) => { + return jsUri; + }, + } as unknown as vscode.Webview, }); - assert( - htmlString.includes( - ">window['VSCODE_EXTENSION_SEGMENT_ANONYMOUS_ID'] = 'MOCK_ANONYMOU_ID';" - ) + expect(htmlString).to.include( + ">window['VSCODE_EXTENSION_SEGMENT_ANONYMOUS_ID'] = 'MOCK_ANONYMOU_ID';" ); }); test('web view content sets the oidc device auth id globally', () => { - const fakeWebview: any = { - asWebviewUri: (jsUri) => { - return jsUri; - }, - }; - const extensionPath = mdbTestExtension.extensionContextStub.extensionPath; const htmlString = getWebviewContent({ extensionPath, telemetryUserId: 'test', - webview: fakeWebview, + webview: { + asWebviewUri: (jsUri) => { + return jsUri; + }, + } as unknown as vscode.Webview, }); - assert( - htmlString.includes( - ">window['VSCODE_EXTENSION_OIDC_DEVICE_AUTH_ID'] = false;" - ) + expect(htmlString).to.include( + ">window['VSCODE_EXTENSION_OIDC_DEVICE_AUTH_ID'] = false;" ); }); @@ -187,23 +182,19 @@ suite('Webview Test Suite', () => { }); test('web view content sets the oidc device auth id globally', () => { - const fakeWebview: any = { - asWebviewUri: (jsUri) => { - return jsUri; - }, - }; - const extensionPath = mdbTestExtension.extensionContextStub.extensionPath; const htmlString = getWebviewContent({ extensionPath, telemetryUserId: 'test', - webview: fakeWebview, + webview: { + asWebviewUri: (jsUri) => { + return jsUri; + }, + } as unknown as vscode.Webview, }); - assert( - htmlString.includes( - ">window['VSCODE_EXTENSION_OIDC_DEVICE_AUTH_ID'] = true;" - ) + expect(htmlString).to.include( + ">window['VSCODE_EXTENSION_OIDC_DEVICE_AUTH_ID'] = true;" ); }); }); @@ -211,47 +202,34 @@ suite('Webview Test Suite', () => { test('web view listens for a connect message and adds the connection', (done) => { let messageReceivedSet = false; let messageReceived; - - sandbox.stub(testTelemetryService, 'trackNewConnection'); - - const fakeWebview = { - html: '', - postMessage: async (): Promise => { - assert(testConnectionController.isCurrentlyConnected()); - assert( - testConnectionController.getActiveConnectionName() === + sandbox.stub(vscode.window, 'createWebviewPanel').returns({ + webview: { + html: '', + postMessage: async (): Promise => { + expect(testConnectionController.isCurrentlyConnected()).to.equal( + true + ); + expect(testConnectionController.getActiveConnectionName()).to.include( 'localhost:27088' - ); + ); - await testConnectionController.disconnect(); - done(); - }, - onDidReceiveMessage: (callback): void => { - messageReceived = callback; - messageReceivedSet = true; + await testConnectionController.disconnect(); + done(); + }, + onDidReceiveMessage: (callback): void => { + messageReceived = callback; + messageReceivedSet = true; + }, + asWebviewUri: () => '', }, - asWebviewUri: sandbox.fake.returns(''), - }; - - const fakeVSCodeCreateWebviewPanel = sandbox.fake.returns({ - webview: fakeWebview, - onDidDispose: sandbox.fake.returns(''), - }); - - sandbox.replace( - vscode.window, - 'createWebviewPanel', - fakeVSCodeCreateWebviewPanel - ); + onDidDispose: () => '', + } as unknown as vscode.WebviewPanel); void testWebviewController.openWebview( mdbTestExtension.extensionContextStub ); - assert( - messageReceivedSet, - 'Ensure it starts listening for messages from the webview.' - ); + expect(messageReceivedSet).to.be.true; // Mock a connection call. messageReceived({ @@ -268,47 +246,31 @@ suite('Webview Test Suite', () => { test('web view sends a successful connect result on a successful connection', (done) => { let messageReceivedSet = false; let messageReceived; + sandbox.stub(vscode.window, 'createWebviewPanel').returns({ + webview: { + html: '', + postMessage: async (message): Promise => { + expect(message.connectionSuccess).to.be.true; + const expectedMessage = 'Successfully connected to localhost:27088.'; + expect(message.connectionMessage).to.equal(expectedMessage); - sandbox.stub(testTelemetryService, 'trackNewConnection'); - - const fakeWebview = { - html: '', - postMessage: async (message): Promise => { - assert(message.connectionSuccess); - const expectedMessage = 'Successfully connected to localhost:27088.'; - assert( - message.connectionMessage === expectedMessage, - `Expected connection message "${message.connectionMessage}" to equal ${expectedMessage}` - ); - - await testConnectionController.disconnect(); - done(); - }, - onDidReceiveMessage: (callback): void => { - messageReceived = callback; - messageReceivedSet = true; + await testConnectionController.disconnect(); + done(); + }, + onDidReceiveMessage: (callback): void => { + messageReceived = callback; + messageReceivedSet = true; + }, + asWebviewUri: () => '', }, - asWebviewUri: sandbox.fake.returns(''), - }; - const fakeVSCodeCreateWebviewPanel = sandbox.fake.returns({ - webview: fakeWebview, - onDidDispose: sandbox.fake.returns(''), - }); - - sandbox.replace( - vscode.window, - 'createWebviewPanel', - fakeVSCodeCreateWebviewPanel - ); + onDidDispose: () => '', + } as unknown as vscode.WebviewPanel); void testWebviewController.openWebview( mdbTestExtension.extensionContextStub ); - assert( - messageReceivedSet, - 'Ensure it starts listening for messages from the webview.' - ); + expect(messageReceivedSet).to.be.true; // Mock a connection call. messageReceived({ @@ -324,33 +286,25 @@ suite('Webview Test Suite', () => { test('web view sends an unsuccessful connect result on an unsuccessful connection', (done) => { let messageReceived; + sandbox.stub(vscode.window, 'createWebviewPanel').returns({ + webview: { + html: '', + postMessage: async (message): Promise => { + expect(message.connectionSuccess).to.be.false; + expect(message.connectionMessage).to.include( + 'Unable to load connection' + ); - sandbox.stub(testTelemetryService, 'trackNewConnection'); - - const fakeWebview = { - html: '', - postMessage: async (message): Promise => { - assert(!message.connectionSuccess); - assert(message.connectionMessage.includes('Unable to load connection')); - - await testConnectionController.disconnect(); - done(); - }, - onDidReceiveMessage: (callback): void => { - messageReceived = callback; + await testConnectionController.disconnect(); + done(); + }, + onDidReceiveMessage: (callback): void => { + messageReceived = callback; + }, + asWebviewUri: () => '', }, - asWebviewUri: sandbox.fake.returns(''), - }; - const fakeVSCodeCreateWebviewPanel = sandbox.fake.returns({ - webview: fakeWebview, - onDidDispose: sandbox.fake.returns(''), - }); - - sandbox.replace( - vscode.window, - 'createWebviewPanel', - fakeVSCodeCreateWebviewPanel - ); + onDidDispose: () => '', + } as unknown as vscode.WebviewPanel); void testWebviewController.openWebview( mdbTestExtension.extensionContextStub @@ -373,39 +327,29 @@ suite('Webview Test Suite', () => { this.timeout(5000); let messageReceived; - - sandbox.stub(testTelemetryService, 'trackNewConnection'); - - const fakeWebview = { - html: '', - postMessage: (message): void => { - try { - assert.strictEqual(message.connectionSuccess, false); - assert.strictEqual( - message.connectionMessage, - 'connection attempt cancelled' - ); - - void testConnectionController.disconnect(); - done(); - } catch (err) { - done(err); - } - }, - onDidReceiveMessage: (callback): void => { - messageReceived = callback; + sandbox.stub(vscode.window, 'createWebviewPanel').returns({ + webview: { + html: '', + postMessage: (message): void => { + try { + expect(message.connectionSuccess).to.be.false; + expect(message.connectionMessage).to.include( + 'connection attempt cancelled' + ); + + void testConnectionController.disconnect(); + done(); + } catch (err) { + done(err); + } + }, + onDidReceiveMessage: (callback): void => { + messageReceived = callback; + }, + asWebviewUri: sandbox.fake.returns(''), }, - asWebviewUri: sandbox.fake.returns(''), - }; - const fakeVSCodeCreateWebviewPanel = sandbox.fake.returns({ - webview: fakeWebview, onDidDispose: sandbox.fake.returns(''), - }); - sandbox.replace( - vscode.window, - 'createWebviewPanel', - fakeVSCodeCreateWebviewPanel - ); + } as unknown as vscode.WebviewPanel); void testWebviewController.openWebview( mdbTestExtension.extensionContextStub ); @@ -427,36 +371,23 @@ suite('Webview Test Suite', () => { ); }); - test('web view runs the "connectWithURI" command when open connection string input is received', (done) => { + test('web view runs the "connectWithURI" command when open connection string input is received', async () => { let messageReceived; - - sandbox.stub(testTelemetryService, 'trackNewConnection'); - const fakeWebview = { html: '', onDidReceiveMessage: (callback): void => { messageReceived = callback; }, - asWebviewUri: sandbox.fake.returns(''), + asWebviewUri: () => '', }; - const fakeVSCodeExecuteCommand = sandbox.fake.resolves(false); + const fakeVSCodeExecuteCommand = sandbox + .stub(vscode.commands, 'executeCommand') + .resolves(false); - sandbox.replace( - vscode.commands, - 'executeCommand', - fakeVSCodeExecuteCommand - ); - - const fakeVSCodeCreateWebviewPanel = sandbox.fake.returns({ + sandbox.stub(vscode.window, 'createWebviewPanel').returns({ webview: fakeWebview, - onDidDispose: sandbox.fake.returns(''), - }); - - sandbox.replace( - vscode.window, - 'createWebviewPanel', - fakeVSCodeCreateWebviewPanel - ); + onDidDispose: () => '', + } as unknown as vscode.WebviewPanel); void testWebviewController.openWebview( mdbTestExtension.extensionContextStub @@ -466,45 +397,36 @@ suite('Webview Test Suite', () => { command: MESSAGE_TYPES.OPEN_CONNECTION_STRING_INPUT, }); - setTimeout(() => { - assert(fakeVSCodeExecuteCommand.called); - assert( - fakeVSCodeExecuteCommand.firstCall.args[0] === 'mdb.connectWithURI' - ); + await waitFor(() => { + return fakeVSCodeExecuteCommand.called; + }); - done(); - }, 50); + expect(fakeVSCodeExecuteCommand).to.be.called; + expect(fakeVSCodeExecuteCommand.firstCall.args[0]).to.equal( + 'mdb.connectWithURI' + ); }); test('webview returns the connection status on a connection status request', (done) => { let messageReceived; - sandbox.stub(testTelemetryService, 'trackNewConnection'); - - const fakeWebview = { - html: '', - postMessage: (message): void => { - assert(message.command === 'CONNECTION_STATUS_MESSAGE'); - assert(message.connectionStatus === 'DISCONNECTED'); - assert(message.activeConnectionName === ''); + sandbox.stub(vscode.window, 'createWebviewPanel').returns({ + webview: { + html: '', + postMessage: (message): void => { + expect(message.command).to.equal('CONNECTION_STATUS_MESSAGE'); + expect(message.connectionStatus).to.equal('DISCONNECTED'); + expect(message.activeConnectionName).to.equal(''); - done(); - }, - onDidReceiveMessage: (callback): void => { - messageReceived = callback; + done(); + }, + onDidReceiveMessage: (callback): void => { + messageReceived = callback; + }, + asWebviewUri: sandbox.fake.returns(''), }, - asWebviewUri: sandbox.fake.returns(''), - }; - const fakeVSCodeCreateWebviewPanel = sandbox.fake.returns({ - webview: fakeWebview, onDidDispose: sandbox.fake.returns(''), - }); - - sandbox.replace( - vscode.window, - 'createWebviewPanel', - fakeVSCodeCreateWebviewPanel - ); + } as unknown as vscode.WebviewPanel); void testWebviewController.openWebview( mdbTestExtension.extensionContextStub @@ -519,33 +441,24 @@ suite('Webview Test Suite', () => { test('webview returns the connection status on a connection status request', (done) => { let messageReceived; - sandbox.stub(testTelemetryService, 'trackNewConnection'); - - const fakeWebview = { - html: '', - postMessage: async (message): Promise => { - assert(message.command === 'CONNECTION_STATUS_MESSAGE'); - assert(message.connectionStatus === 'CONNECTED'); - assert(message.activeConnectionName === 'localhost:27088'); - await testConnectionController.disconnect(); + sandbox.stub(vscode.window, 'createWebviewPanel').returns({ + webview: { + html: '', + postMessage: async (message): Promise => { + expect(message.command).to.equal('CONNECTION_STATUS_MESSAGE'); + expect(message.connectionStatus).to.equal('CONNECTED'); + expect(message.activeConnectionName).to.equal('localhost:27088'); + await testConnectionController.disconnect(); - done(); - }, - onDidReceiveMessage: (callback): void => { - messageReceived = callback; + done(); + }, + onDidReceiveMessage: (callback): void => { + messageReceived = callback; + }, + asWebviewUri: sandbox.fake.returns(''), }, - asWebviewUri: sandbox.fake.returns(''), - }; - const fakeVSCodeCreateWebviewPanel = sandbox.fake.returns({ - webview: fakeWebview, onDidDispose: sandbox.fake.returns(''), - }); - - sandbox.replace( - vscode.window, - 'createWebviewPanel', - fakeVSCodeCreateWebviewPanel - ); + } as unknown as vscode.WebviewPanel); void testWebviewController.openWebview( mdbTestExtension.extensionContextStub @@ -564,26 +477,17 @@ suite('Webview Test Suite', () => { test('calls to rename the active connection when a rename active connection message is passed', async () => { let messageReceived; - sandbox.stub(testTelemetryService, 'trackNewConnection'); - - const fakeWebview = { - html: '', - postMessage: (): void => {}, - onDidReceiveMessage: (callback): void => { - messageReceived = callback; + sandbox.stub(vscode.window, 'createWebviewPanel').returns({ + webview: { + html: '', + postMessage: (): void => {}, + onDidReceiveMessage: (callback): void => { + messageReceived = callback; + }, + asWebviewUri: sandbox.fake.returns(''), }, - asWebviewUri: sandbox.fake.returns(''), - }; - const fakeVSCodeCreateWebviewPanel = sandbox.fake.returns({ - webview: fakeWebview, onDidDispose: sandbox.fake.returns(''), - }); - - sandbox.replace( - vscode.window, - 'createWebviewPanel', - fakeVSCodeCreateWebviewPanel - ); + } as unknown as vscode.WebviewPanel); const mockRenameConnectionOnConnectionController = sandbox.fake.returns(null); @@ -607,18 +511,15 @@ suite('Webview Test Suite', () => { command: MESSAGE_TYPES.RENAME_ACTIVE_CONNECTION, }); - assert(mockRenameConnectionOnConnectionController.called); - assert.strictEqual( - mockRenameConnectionOnConnectionController.firstCall.args[0], - testConnectionController.getActiveConnectionId() - ); + expect(mockRenameConnectionOnConnectionController).to.be.calledOnce; + expect( + mockRenameConnectionOnConnectionController.firstCall.args[0] + ).to.equal(testConnectionController.getActiveConnectionId()); await testConnectionController.disconnect(); }); test('calls to edit a connection when an edit connection message is passed', async () => { - sandbox.stub(testTelemetryService, 'trackNewConnection'); - let messageReceived; sandbox.stub(vscode.window, 'createWebviewPanel').returns({ webview: { @@ -656,52 +557,42 @@ suite('Webview Test Suite', () => { }, }); - assert(mockEditConnectionOnConnectionController.called); - assert.deepStrictEqual( - mockEditConnectionOnConnectionController.firstCall.args[0], - { - connectionId: 'pineapple', - connectionOptions: { - connectionString: 'test', - }, - } - ); + expect(mockEditConnectionOnConnectionController).to.be.calledOnce; + expect( + mockEditConnectionOnConnectionController.firstCall.args[0] + ).to.deep.equal({ + connectionId: 'pineapple', + connectionOptions: { + connectionString: 'test', + }, + }); await testConnectionController.disconnect(); }); test('it notifies all the webviews of the change of current theme and gulps the error if any', function (done) { - sandbox.stub(testTelemetryService, 'trackNewConnection'); - const totalExpectedPostMessageCalls = 3; let callsSoFar = 0; - const fakeWebview = { - html: '', - // eslint-disable-next-line @typescript-eslint/require-await - postMessage: async (message): Promise => { - assert(message.command === 'THEME_CHANGED'); - assert(message.darkMode === true); - if (++callsSoFar === 1) { - // This should be fine since we catch the rejection and proceed ahead silently - throw new Error('BAM'); - } - if (++callsSoFar === totalExpectedPostMessageCalls) { - done(); - } + sandbox.stub(vscode.window, 'createWebviewPanel').returns({ + webview: { + html: '', + // eslint-disable-next-line @typescript-eslint/require-await + postMessage: async (message): Promise => { + expect(message.command).to.equal('THEME_CHANGED'); + expect(message.darkMode).to.be.true; + if (++callsSoFar === 1) { + // This should be fine since we catch the rejection and proceed ahead silently + throw new Error('BAM'); + } + if (++callsSoFar === totalExpectedPostMessageCalls) { + done(); + } + }, + onDidReceiveMessage: (): void => {}, + asWebviewUri: sandbox.fake.returns(''), }, - onDidReceiveMessage: (): void => {}, - asWebviewUri: sandbox.fake.returns(''), - }; - const fakeVSCodeCreateWebviewPanel = sandbox.fake.returns({ - webview: fakeWebview, onDidDispose: sandbox.fake.returns(''), - }); - - sandbox.replace( - vscode.window, - 'createWebviewPanel', - fakeVSCodeCreateWebviewPanel - ); + } as unknown as vscode.WebviewPanel); void testWebviewController.openWebview( mdbTestExtension.extensionContextStub @@ -728,47 +619,34 @@ suite('Webview Test Suite', () => { testStorageController, extensionContextStub ); - let testConnectionController; - let messageReceived; - let fakeWebview; - - let testWebviewController; beforeEach(() => { - testConnectionController = new ConnectionController({ + const testConnectionController = new ConnectionController({ statusView: new StatusView(extensionContextStub), storageController: testStorageController, telemetryService: testTelemetryService, }); - fakeWebview = { - html: '', - postMessage: (): void => {}, - onDidReceiveMessage: (callback): void => { - messageReceived = callback; + sandbox.stub(vscode.window, 'createWebviewPanel').returns({ + webview: { + html: '', + postMessage: (): void => {}, + onDidReceiveMessage: (callback): void => { + messageReceived = callback; + }, + asWebviewUri: sandbox.fake.returns(''), }, - asWebviewUri: sandbox.fake.returns(''), - }; - - const fakeVSCodeCreateWebviewPanel = sandbox.fake.returns({ - webview: fakeWebview, onDidDispose: sandbox.fake.returns(''), - }); - sandbox.replace( - vscode.window, - 'createWebviewPanel', - fakeVSCodeCreateWebviewPanel - ); + } as unknown as vscode.WebviewPanel); - testWebviewController = new WebviewController({ + const testWebviewController = new WebviewController({ connectionController: testConnectionController, storageController: testStorageController, telemetryService: testTelemetryService, }); testWebviewController.openWebview(mdbTestExtension.extensionContextStub); - sandbox.stub(testTelemetryService, 'trackNewConnection'); }); test('it should handle opening trusted links', () => { @@ -780,9 +658,8 @@ suite('Webview Test Suite', () => { linkTo: 'https://mongodb.com/test', }); - assert(stubOpenLink.called); - assert.strictEqual( - stubOpenLink.firstCall.args[0], + expect(stubOpenLink).to.be.calledOnce; + expect(stubOpenLink.firstCall.args[0]).to.equal( 'https://mongodb.com/test' ); }); From 2e28a5190d825c359ae8a67abe00b73245e0f999 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 23 Jan 2024 03:04:01 +0000 Subject: [PATCH 2/7] Update changelog (#671) Co-authored-by: mcasimir --- CHANGELOG.md | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0caad78ba..9e7b572d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## [v1.5.0](https://github.com/mongodb-js/vscode/releases/tag/untagged-bf7d742ca55d7b3fe4c6) - null + +Edit the release notes before publishing. + + ## [v1.4.0](https://github.com/mongodb-js/vscode/releases/tag/v1.4.0) - 2024-01-09 ## What's Changed @@ -431,21 +436,3 @@ To dig deeper please feel free to follow the links mentioned below: - Fixed an issue with the tree explorer freezing when double clicking an open schema -## [v0.0.4](https://github.com/mongodb-js/vscode/releases/tag/v0.0.4) - 2020-06-17 - -### Added - -- Added `Launch MongoDB Shell` right click action for the active connection in the tree view - -### Fixed - -- Fixed an issue with connecting to ssl with the launch shell command -- Fixed an issue with the launch shell command on windows -- Fixed playgrounds not being able to run in WSL environments -- Updated our connection model dependency to pull in a fix for connection strings with `readPreferenceTags` - -### Changed - -- Connections in the tree view are now alphabetically sorted - - From d64604333f0d134b7c572c593d66a0da1a553b9d Mon Sep 17 00:00:00 2001 From: Rhys Date: Wed, 24 Jan 2024 09:54:13 -0500 Subject: [PATCH 3/7] chore: remove unused less in webpack and deps (#674) --- .depcheckrc | 5 - package-lock.json | 765 ---------------------------------------------- package.json | 5 - webpack.config.js | 28 -- 4 files changed, 803 deletions(-) diff --git a/.depcheckrc b/.depcheckrc index 97d6c0453..238406eb2 100644 --- a/.depcheckrc +++ b/.depcheckrc @@ -14,11 +14,6 @@ ignores: - "vscode" - "webpack-cli" - "@mongodb-js/oidc-plugin" - - css-loader - - less - - less-loader - node-loader - - postcss-loader - - style-loader - ts-loader - mongodb-runner diff --git a/package-lock.json b/package-lock.json index 26e0b72d2..bf3007bfe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -78,7 +78,6 @@ "chai-as-promised": "^7.1.1", "cross-env": "^7.0.3", "crypto-browserify": "^3.12.0", - "css-loader": "^6.8.1", "depcheck": "^1.4.3", "duplicate-package-checker-webpack-plugin": "^3.0.0", "enzyme": "^3.11.0", @@ -90,8 +89,6 @@ "jest": "^26.6.3", "jest-junit": "^12.3.0", "jest-transform-stub": "^2.0.0", - "less": "^3.13.1", - "less-loader": "^5.0.0", "mkdirp": "^1.0.4", "mocha": "^10.2.0", "mocha-junit-reporter": "^2.2.0", @@ -103,14 +100,12 @@ "npm-run-all": "^4.1.5", "ora": "^5.4.1", "path-browserify": "^1.0.1", - "postcss-loader": "^7.3.3", "pre-commit": "^1.2.2", "prettier": "^2.8.8", "process": "^0.11.10", "sinon": "^9.2.4", "sinon-chai": "^3.7.0", "stream-browserify": "^3.0.0", - "style-loader": "^1.3.0", "ts-jest": "^26.5.6", "ts-loader": "^9.4.4", "ts-node": "^10.9.1", @@ -7897,15 +7892,6 @@ "node": ">=0.6" } }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true, - "engines": { - "node": "*" - } - }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -8823,15 +8809,6 @@ "wrap-ansi": "^7.0.0" } }, - "node_modules/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, "node_modules/clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", @@ -9061,18 +9038,6 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, - "node_modules/copy-anything": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", - "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", - "dev": true, - "dependencies": { - "is-what": "^3.14.1" - }, - "funding": { - "url": "https://github.com/sponsors/mesqueeb" - } - }, "node_modules/copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", @@ -9240,32 +9205,6 @@ "node": "*" } }, - "node_modules/css-loader": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.8.1.tgz", - "integrity": "sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g==", - "dev": true, - "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.21", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.3", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.3.8" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, "node_modules/css-select": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", @@ -9294,18 +9233,6 @@ "url": "https://github.com/sponsors/fb55" } }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/cssom": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", @@ -10438,15 +10365,6 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "devOptional": true }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -10556,19 +10474,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/errno": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", - "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", - "dev": true, - "optional": true, - "dependencies": { - "prr": "~1.0.1" - }, - "bin": { - "errno": "cli.js" - } - }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -13587,18 +13492,6 @@ "node": ">=0.10.0" } }, - "node_modules/icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -13627,19 +13520,6 @@ "node": ">= 4" } }, - "node_modules/image-size": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", - "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", - "dev": true, - "optional": true, - "bin": { - "image-size": "bin/image-size.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/immediate": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", @@ -14524,12 +14404,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-what": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", - "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", - "dev": true - }, "node_modules/is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -15536,15 +15410,6 @@ "node": ">= 10.13.0" } }, - "node_modules/jiti": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", - "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", - "dev": true, - "bin": { - "jiti": "bin/jiti.js" - } - }, "node_modules/jose": { "version": "4.14.4", "resolved": "https://registry.npmjs.org/jose/-/jose-4.14.4.tgz", @@ -15848,65 +15713,6 @@ "node": ">=0.10.0" } }, - "node_modules/less": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/less/-/less-3.13.1.tgz", - "integrity": "sha512-SwA1aQXGUvp+P5XdZslUOhhLnClSLIjWvJhmd+Vgib5BFIr9lMNlQwmwUNOjXThF/A0x+MCYYPeWEfeWiLRnTw==", - "dev": true, - "dependencies": { - "copy-anything": "^2.0.1", - "tslib": "^1.10.0" - }, - "bin": { - "lessc": "bin/lessc" - }, - "engines": { - "node": ">=6" - }, - "optionalDependencies": { - "errno": "^0.1.1", - "graceful-fs": "^4.1.2", - "image-size": "~0.5.0", - "make-dir": "^2.1.0", - "mime": "^1.4.1", - "native-request": "^1.0.5", - "source-map": "~0.6.0" - } - }, - "node_modules/less-loader": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-5.0.0.tgz", - "integrity": "sha512-bquCU89mO/yWLaUq0Clk7qCsKhsF/TZpJUzETRvJa9KSVEL9SO3ovCvdEHISBhrC81OwC8QSVX7E0bzElZj9cg==", - "dev": true, - "dependencies": { - "clone": "^2.1.1", - "loader-utils": "^1.1.0", - "pify": "^4.0.1" - }, - "engines": { - "node": ">= 4.8.0" - }, - "peerDependencies": { - "less": "^2.3.1 || ^3.0.0", - "webpack": "^2.0.0 || ^3.0.0 || ^4.0.0" - } - }, - "node_modules/less/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/less/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -16007,32 +15813,6 @@ "node": ">=6.11.5" } }, - "node_modules/loader-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", - "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/loader-utils/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, "node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -16184,30 +15964,6 @@ "node": ">=12" } }, - "node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "optional": true, - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "optional": true, - "bin": { - "semver": "bin/semver" - } - }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -17492,13 +17248,6 @@ "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", "devOptional": true }, - "node_modules/native-request": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/native-request/-/native-request-1.1.0.tgz", - "integrity": "sha512-uZ5rQaeRn15XmpgE0xoPL8YWqcX90VtCFglYwAgkvKM5e8fog+vePLAhHxuuv/gRkrQxIeh5U3q9sMNUrENqWw==", - "dev": true, - "optional": true - }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -18723,15 +18472,6 @@ "node": ">=0.10" } }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", @@ -18837,144 +18577,6 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/postcss-loader": { - "version": "7.3.3", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.3.tgz", - "integrity": "sha512-YgO/yhtevGO/vJePCQmTxiaEwER94LABZN0ZMT4A0vsak9TpO+RvKRs7EmJ8peIlB9xfXCsS7M8LjqncsUZ5HA==", - "dev": true, - "dependencies": { - "cosmiconfig": "^8.2.0", - "jiti": "^1.18.2", - "semver": "^7.3.8" - }, - "engines": { - "node": ">= 14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "postcss": "^7.0.0 || ^8.0.1", - "webpack": "^5.0.0" - } - }, - "node_modules/postcss-loader/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/postcss-loader/node_modules/cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dev": true, - "dependencies": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/postcss-loader/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-local-by-default": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz", - "integrity": "sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==", - "dev": true, - "dependencies": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-scope": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", - "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.4" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, - "dependencies": { - "icss-utils": "^5.0.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.0.13", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", - "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", @@ -19218,13 +18820,6 @@ "node": ">= 0.10" } }, - "node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", - "dev": true, - "optional": true - }, "node_modules/pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -20401,24 +19996,6 @@ "object-assign": "^4.1.1" } }, - "node_modules/schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/scss-parser": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/scss-parser/-/scss-parser-1.0.6.tgz", @@ -21740,40 +21317,6 @@ "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" }, - "node_modules/style-loader": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz", - "integrity": "sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q==", - "dev": true, - "dependencies": { - "loader-utils": "^2.0.0", - "schema-utils": "^2.7.0" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/style-loader/node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, "node_modules/style-mod": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.0.tgz", @@ -30253,12 +29796,6 @@ "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==" }, - "big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true - }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -30971,12 +30508,6 @@ "wrap-ansi": "^7.0.0" } }, - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", - "dev": true - }, "clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", @@ -31165,15 +30696,6 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, - "copy-anything": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", - "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", - "dev": true, - "requires": { - "is-what": "^3.14.1" - } - }, "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", @@ -31315,22 +30837,6 @@ "randomfill": "^1.0.3" } }, - "css-loader": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.8.1.tgz", - "integrity": "sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g==", - "dev": true, - "requires": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.21", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.3", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.3.8" - } - }, "css-select": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", @@ -31350,12 +30856,6 @@ "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", "dev": true }, - "cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true - }, "cssom": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", @@ -32223,12 +31723,6 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "devOptional": true }, - "emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true - }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -32311,16 +31805,6 @@ "object-is": "^1.1.5" } }, - "errno": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", - "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", - "dev": true, - "optional": true, - "requires": { - "prr": "~1.0.1" - } - }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -34650,12 +34134,6 @@ "safer-buffer": ">= 2.1.2 < 3" } }, - "icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true - }, "ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -34667,13 +34145,6 @@ "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true }, - "image-size": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", - "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", - "dev": true, - "optional": true - }, "immediate": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", @@ -35317,12 +34788,6 @@ "get-intrinsic": "^1.1.1" } }, - "is-what": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", - "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", - "dev": true - }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -36129,12 +35594,6 @@ "supports-color": "^7.0.0" } }, - "jiti": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", - "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", - "dev": true - }, "jose": { "version": "4.14.4", "resolved": "https://registry.npmjs.org/jose/-/jose-4.14.4.tgz", @@ -36395,49 +35854,6 @@ "invert-kv": "^1.0.0" } }, - "less": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/less/-/less-3.13.1.tgz", - "integrity": "sha512-SwA1aQXGUvp+P5XdZslUOhhLnClSLIjWvJhmd+Vgib5BFIr9lMNlQwmwUNOjXThF/A0x+MCYYPeWEfeWiLRnTw==", - "dev": true, - "requires": { - "copy-anything": "^2.0.1", - "errno": "^0.1.1", - "graceful-fs": "^4.1.2", - "image-size": "~0.5.0", - "make-dir": "^2.1.0", - "mime": "^1.4.1", - "native-request": "^1.0.5", - "source-map": "~0.6.0", - "tslib": "^1.10.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "less-loader": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-5.0.0.tgz", - "integrity": "sha512-bquCU89mO/yWLaUq0Clk7qCsKhsF/TZpJUzETRvJa9KSVEL9SO3ovCvdEHISBhrC81OwC8QSVX7E0bzElZj9cg==", - "dev": true, - "requires": { - "clone": "^2.1.1", - "loader-utils": "^1.1.0", - "pify": "^4.0.1" - } - }, "leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -36519,28 +35935,6 @@ "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", "dev": true }, - "loader-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", - "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "dependencies": { - "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - } - } - }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -36667,26 +36061,6 @@ "@jridgewell/sourcemap-codec": "^1.4.15" } }, - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "optional": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "dependencies": { - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "optional": true - } - } - }, "make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -37649,13 +37023,6 @@ "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", "devOptional": true }, - "native-request": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/native-request/-/native-request-1.1.0.tgz", - "integrity": "sha512-uZ5rQaeRn15XmpgE0xoPL8YWqcX90VtCFglYwAgkvKM5e8fog+vePLAhHxuuv/gRkrQxIeh5U3q9sMNUrENqWw==", - "dev": true, - "optional": true - }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -38591,12 +37958,6 @@ "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", "dev": true }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, "pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", @@ -38672,91 +38033,6 @@ } } }, - "postcss-loader": { - "version": "7.3.3", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.3.tgz", - "integrity": "sha512-YgO/yhtevGO/vJePCQmTxiaEwER94LABZN0ZMT4A0vsak9TpO+RvKRs7EmJ8peIlB9xfXCsS7M8LjqncsUZ5HA==", - "dev": true, - "requires": { - "cosmiconfig": "^8.2.0", - "jiti": "^1.18.2", - "semver": "^7.3.8" - }, - "dependencies": { - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dev": true, - "requires": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - } - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - } - } - }, - "postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true - }, - "postcss-modules-local-by-default": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz", - "integrity": "sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==", - "dev": true, - "requires": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - } - }, - "postcss-modules-scope": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", - "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.4" - } - }, - "postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, - "requires": { - "icss-utils": "^5.0.0" - } - }, - "postcss-selector-parser": { - "version": "6.0.13", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", - "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - } - }, "postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", @@ -38939,13 +38215,6 @@ } } }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", - "dev": true, - "optional": true - }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -39846,17 +39115,6 @@ "object-assign": "^4.1.1" } }, - "schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" - } - }, "scss-parser": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/scss-parser/-/scss-parser-1.0.6.tgz", @@ -40918,29 +40176,6 @@ "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" }, - "style-loader": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz", - "integrity": "sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q==", - "dev": true, - "requires": { - "loader-utils": "^2.0.0", - "schema-utils": "^2.7.0" - }, - "dependencies": { - "loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - } - } - }, "style-mod": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.0.tgz", diff --git a/package.json b/package.json index a943b2444..c2f053b24 100644 --- a/package.json +++ b/package.json @@ -1129,7 +1129,6 @@ "chai-as-promised": "^7.1.1", "cross-env": "^7.0.3", "crypto-browserify": "^3.12.0", - "css-loader": "^6.8.1", "depcheck": "^1.4.3", "duplicate-package-checker-webpack-plugin": "^3.0.0", "enzyme": "^3.11.0", @@ -1141,8 +1140,6 @@ "jest": "^26.6.3", "jest-junit": "^12.3.0", "jest-transform-stub": "^2.0.0", - "less": "^3.13.1", - "less-loader": "^5.0.0", "mkdirp": "^1.0.4", "mocha": "^10.2.0", "mocha-junit-reporter": "^2.2.0", @@ -1154,14 +1151,12 @@ "npm-run-all": "^4.1.5", "ora": "^5.4.1", "path-browserify": "^1.0.1", - "postcss-loader": "^7.3.3", "pre-commit": "^1.2.2", "prettier": "^2.8.8", "process": "^0.11.10", "sinon": "^9.2.4", "sinon-chai": "^3.7.0", "stream-browserify": "^3.0.0", - "style-loader": "^1.3.0", "ts-jest": "^26.5.6", "ts-loader": "^9.4.4", "ts-node": "^10.9.1", diff --git a/webpack.config.js b/webpack.config.js index d5f4c7cd6..3fca92511 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -175,34 +175,6 @@ module.exports = (env, argv) => { exclude: /node_modules/, options: {}, }, - { - test: /\.less$/, - exclude: [/\.global/, /bootstrap/, /node_modules/, /global\.less/], - use: [ - { loader: 'style-loader' }, - { - loader: 'css-loader', - options: { - modules: true, - importLoaders: 1, - }, - }, - { - loader: 'postcss-loader', - options: { - postcssOptions: { - plugins: [autoprefixer()], - }, - }, - }, - { - loader: 'less-loader', - options: { - noIeCompat: true, - }, - }, - ], - }, ], }, plugins: [ From 4e7c08b10cc64cfad0b8edbd16930d5df2d49dd4 Mon Sep 17 00:00:00 2001 From: Rhys Date: Wed, 24 Jan 2024 10:00:43 -0500 Subject: [PATCH 4/7] chore: set browser auth without github actions for mongosh int tests (#672) --- .github/workflows/actions/test-and-build/action.yaml | 8 -------- src/test/suite/oidc.test.ts | 4 ++-- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/.github/workflows/actions/test-and-build/action.yaml b/.github/workflows/actions/test-and-build/action.yaml index ee400fdd7..07f558515 100644 --- a/.github/workflows/actions/test-and-build/action.yaml +++ b/.github/workflows/actions/test-and-build/action.yaml @@ -69,15 +69,7 @@ runs: if: ${{ runner.os != 'Windows' }} shell: bash - - name: Set BROWSER_AUTH_COMMAND - run: | - BROWSER_AUTH_COMMAND=$(echo "$(which node) $(pwd)/src/test/fixture/curl.js") - echo "BROWSER_AUTH_COMMAND=$BROWSER_AUTH_COMMAND" >> $GITHUB_ENV - shell: bash - - name: Run Tests - env: - BROWSER_AUTH_COMMAND: ${{ env.BROWSER_AUTH_COMMAND }} run: | npm run test shell: bash diff --git a/src/test/suite/oidc.test.ts b/src/test/suite/oidc.test.ts index 2fef7f337..bd5b520ca 100644 --- a/src/test/suite/oidc.test.ts +++ b/src/test/suite/oidc.test.ts @@ -31,8 +31,8 @@ function hash(input: string): string { } // Need to be provided via CI env because we can't get a hold for node.js exec -// path in our tests - they run inside a vscode process -const browserShellCommand = process.env.BROWSER_AUTH_COMMAND; +// path in our tests - they run inside a vscode process in the built dir. +const browserShellCommand = `$(echo "$(which node) ${__dirname}/../../../src/test/fixture/curl.js")`; const UNIQUE_TASK_ID = process.env.GITHUB_RUN_ID && process.env.GITHUB_RUN_NUMBER From 6c3273938223f00ab6585d64ee7148f5677a8d7e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 24 Jan 2024 16:07:47 +0000 Subject: [PATCH 5/7] Update changelog (#675) Co-authored-by: Anemy --- CHANGELOG.md | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e7b572d7..1a1fa4a2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,22 @@ # Change Log -## [v1.5.0](https://github.com/mongodb-js/vscode/releases/tag/untagged-bf7d742ca55d7b3fe4c6) - null +## [v1.5.0](https://github.com/mongodb-js/vscode/releases/tag/v1.5.0) - 2024-01-24 -Edit the release notes before publishing. +## What's Changed +* VSCODE-505: stream support in UI by @shaketbaby in https://github.com/mongodb-js/vscode/pull/643 +* feat(webview): use new connection form, remove old form VSCODE-491 by @Anemy in https://github.com/mongodb-js/vscode/pull/636 +* fix: add explicit ordering for stream processor context menu actions by @pulkitkalra-mdb in https://github.com/mongodb-js/vscode/pull/654 +* chore: close connection string input when opening form VSCODE-507 by @Anemy in https://github.com/mongodb-js/vscode/pull/656 +* fix: ensure extension output populates ObjectIds in stream by @pulkitkalra-mdb in https://github.com/mongodb-js/vscode/pull/657 +* feat(connect-form): add OIDC device auth flow with preference VSCODE-503 by @Anemy in https://github.com/mongodb-js/vscode/pull/658 +* feat(connections): add edit connection context menu action VSCODE-406 by @Anemy in https://github.com/mongodb-js/vscode/pull/655 +* chore(deps): update mongodb and devtools dependencies by @Anemy in https://github.com/mongodb-js/vscode/pull/662 +* chore: cancel connection attempt when removing connection, update assert to expect in webview and connection controller tests by @Anemy in https://github.com/mongodb-js/vscode/pull/667 + +## New Contributors +* @pulkitkalra-mdb made their first contribution in https://github.com/mongodb-js/vscode/pull/654 + +**Full Changelog**: https://github.com/mongodb-js/vscode/compare/v1.4.0...v1.5.0 ## [v1.4.0](https://github.com/mongodb-js/vscode/releases/tag/v1.4.0) - 2024-01-09 From 4606982fef69c382e1655a83ebe3c93cdf2eb11c Mon Sep 17 00:00:00 2001 From: Paula Stachova Date: Thu, 25 Jan 2024 09:16:46 +0100 Subject: [PATCH 6/7] feat: add export to Rust and PHP VSCODE-411 (#676) * feat: add export to Rust and PHP VSCODE-411 * test: update playgroundSelectedCodeActionProvider tests --- README.md | 2 + package.json | 16 ++ src/commands/index.ts | 2 + .../playgroundSelectedCodeActionProvider.ts | 22 +++ src/mdbExtensionController.ts | 6 + ...aygroundSelectedCodeActionProvider.test.ts | 163 +++++++++++++++++- src/types/playgroundType.ts | 2 + 7 files changed, 207 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index bf7a289cf..82e101b9b 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,8 @@ Select queries and aggregations within your Playground files and translate them * Python 3 * Ruby * Go + * Rust + * PHP ![Export to language](resources/screenshots/export-to-language.gif) diff --git a/package.json b/package.json index c2f053b24..e21f6cf35 100644 --- a/package.json +++ b/package.json @@ -246,6 +246,14 @@ "command": "mdb.exportToGo", "title": "MongoDB: Export To Go" }, + { + "command": "mdb.exportToRust", + "title": "MongoDB: Export To Rust" + }, + { + "command": "mdb.exportToPHP", + "title": "MongoDB: Export To PHP" + }, { "command": "mdb.addConnection", "title": "Add MongoDB Connection", @@ -720,6 +728,14 @@ "command": "mdb.exportToGo", "when": "mdb.isPlayground == true && mdb.connectedToMongoDB == true && mdb.isAtlasStreams == false" }, + { + "command": "mdb.exportToRust", + "when": "mdb.isPlayground == true && mdb.connectedToMongoDB == true && mdb.isAtlasStreams == false" + }, + { + "command": "mdb.exportToPHP", + "when": "mdb.isPlayground == true && mdb.connectedToMongoDB == true && mdb.isAtlasStreams == false" + }, { "command": "mdb.refreshPlaygroundsFromTreeView", "when": "false" diff --git a/src/commands/index.ts b/src/commands/index.ts index 8e5e3c989..ebef4dec1 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -23,6 +23,8 @@ enum EXTENSION_COMMANDS { MDB_EXPORT_TO_NODE = 'mdb.exportToNode', MDB_EXPORT_TO_RUBY = 'mdb.exportToRuby', MDB_EXPORT_TO_GO = 'mdb.exportToGo', + MDB_EXPORT_TO_RUST = 'mdb.exportToRust', + MDB_EXPORT_TO_PHP = 'mdb.exportToPHP', MDB_CHANGE_EXPORT_TO_LANGUAGE_ADDONS = 'mdb.changeExportToLanguageAddons', MDB_OPEN_MONGODB_DOCUMENT_FROM_CODE_LENS = 'mdb.openMongoDBDocumentFromCodeLens', diff --git a/src/editors/playgroundSelectedCodeActionProvider.ts b/src/editors/playgroundSelectedCodeActionProvider.ts index 2784d5c58..f12d4de45 100644 --- a/src/editors/playgroundSelectedCodeActionProvider.ts +++ b/src/editors/playgroundSelectedCodeActionProvider.ts @@ -133,6 +133,28 @@ export default class PlaygroundSelectedCodeActionProvider tooltip: 'Export To Go', }; codeActions.push(exportToGoCommand); + + const exportToRustCommand = new vscode.CodeAction( + 'Export To Rust', + vscode.CodeActionKind.Empty + ); + exportToRustCommand.command = { + command: EXTENSION_COMMANDS.MDB_EXPORT_TO_RUST, + title: 'Export To Rust', + tooltip: 'Export To Rust', + }; + codeActions.push(exportToRustCommand); + + const exportToPHPCommand = new vscode.CodeAction( + 'Export To PHP', + vscode.CodeActionKind.Empty + ); + exportToPHPCommand.command = { + command: EXTENSION_COMMANDS.MDB_EXPORT_TO_PHP, + title: 'Export To PHP', + tooltip: 'Export To PHP', + }; + codeActions.push(exportToPHPCommand); } return codeActions; diff --git a/src/mdbExtensionController.ts b/src/mdbExtensionController.ts index 8319bb77e..791d85287 100644 --- a/src/mdbExtensionController.ts +++ b/src/mdbExtensionController.ts @@ -235,6 +235,12 @@ export default class MDBExtensionController implements vscode.Disposable { this.registerCommand(EXTENSION_COMMANDS.MDB_EXPORT_TO_GO, () => this._playgroundController.exportToLanguage(ExportToLanguages.GO) ); + this.registerCommand(EXTENSION_COMMANDS.MDB_EXPORT_TO_RUST, () => + this._playgroundController.exportToLanguage(ExportToLanguages.RUST) + ); + this.registerCommand(EXTENSION_COMMANDS.MDB_EXPORT_TO_PHP, () => + this._playgroundController.exportToLanguage(ExportToLanguages.PHP) + ); this.registerCommand( EXTENSION_COMMANDS.MDB_CHANGE_EXPORT_TO_LANGUAGE_ADDONS, diff --git a/src/test/suite/editors/playgroundSelectedCodeActionProvider.test.ts b/src/test/suite/editors/playgroundSelectedCodeActionProvider.test.ts index cc09fb127..3950d7dc7 100644 --- a/src/test/suite/editors/playgroundSelectedCodeActionProvider.test.ts +++ b/src/test/suite/editors/playgroundSelectedCodeActionProvider.test.ts @@ -24,6 +24,9 @@ suite('Playground Selected CodeAction Provider Test Suite', function () { const extensionContextStub = new ExtensionContextStub(); + const EXPORT_LANGUAGES_CODEACTIONS_COUNT = 8; + const TOTAL_CODEACTIONS_COUNT = EXPORT_LANGUAGES_CODEACTIONS_COUNT + 1; + // The test extension runner. extensionContextStub.extensionPath = '../../'; @@ -182,7 +185,7 @@ suite('Playground Selected CodeAction Provider Test Suite', function () { expect(codeActions).to.exist; if (codeActions) { - expect(codeActions.length).to.be.equal(7); + expect(codeActions.length).to.be.equal(TOTAL_CODEACTIONS_COUNT); const actionCommand = codeActions[2].command; if (actionCommand) { @@ -218,7 +221,7 @@ suite('Playground Selected CodeAction Provider Test Suite', function () { expect(codeActions).to.exist; if (codeActions) { - expect(codeActions.length).to.be.equal(7); + expect(codeActions.length).to.be.equal(TOTAL_CODEACTIONS_COUNT); const actionCommand = codeActions[2].command; if (actionCommand) { @@ -283,7 +286,7 @@ suite('Playground Selected CodeAction Provider Test Suite', function () { expect(codeActions).to.exist; if (codeActions) { - expect(codeActions.length).to.be.equal(7); + expect(codeActions.length).to.be.equal(TOTAL_CODEACTIONS_COUNT); const actionCommand = codeActions[3].command; if (actionCommand) { @@ -352,7 +355,7 @@ suite('Playground Selected CodeAction Provider Test Suite', function () { expect(codeActions).to.exist; if (codeActions) { - expect(codeActions.length).to.be.equal(7); + expect(codeActions.length).to.be.equal(TOTAL_CODEACTIONS_COUNT); const actionCommand = codeActions[1].command; if (actionCommand) { @@ -426,7 +429,7 @@ suite('Playground Selected CodeAction Provider Test Suite', function () { expect(codeActions).to.exist; if (codeActions) { - expect(codeActions.length).to.be.equal(7); + expect(codeActions.length).to.be.equal(TOTAL_CODEACTIONS_COUNT); const actionCommand = codeActions[5].command; if (actionCommand) { @@ -500,7 +503,7 @@ suite('Playground Selected CodeAction Provider Test Suite', function () { expect(codeActions).to.exist; if (codeActions) { - expect(codeActions.length).to.be.equal(7); + expect(codeActions.length).to.be.equal(TOTAL_CODEACTIONS_COUNT); const actionCommand = codeActions[6].command; if (actionCommand) { @@ -547,6 +550,154 @@ suite('Playground Selected CodeAction Provider Test Suite', function () { } } }); + + test('exports to rust and includes driver syntax', async () => { + const textFromEditor = "use('db'); db.coll.find({ name: '22' })"; + const selection = { + start: { line: 0, character: 24 }, + end: { line: 0, character: 38 }, + } as vscode.Selection; + const mode = ExportToLanguageMode.QUERY; + const activeTextEditor = { + document: { getText: () => textFromEditor }, + } as vscode.TextEditor; + + mdbTestExtension.testExtensionController._playgroundController._selectedText = + "{ name: '22' }"; + mdbTestExtension.testExtensionController._playgroundController._playgroundSelectedCodeActionProvider.selection = + selection; + mdbTestExtension.testExtensionController._playgroundController._playgroundSelectedCodeActionProvider.mode = + mode; + mdbTestExtension.testExtensionController._playgroundController._activeTextEditor = + activeTextEditor; + + testCodeActionProvider.refresh({ selection, mode }); + + const codeActions = testCodeActionProvider.provideCodeActions(); + expect(codeActions).to.exist; + + if (codeActions) { + expect(codeActions.length).to.be.equal(TOTAL_CODEACTIONS_COUNT); + const actionCommand = codeActions[7].command; + + if (actionCommand) { + expect(actionCommand.command).to.be.equal('mdb.exportToRust'); + expect(actionCommand.title).to.be.equal('Export To Rust'); + + await vscode.commands.executeCommand(actionCommand.command); + + let expectedResult: PlaygroundResult = { + namespace: 'DATABASE_NAME.COLLECTION_NAME', + type: null, + content: 'doc! {\n "name": "22"\n}', + language: 'rust', + }; + expect( + mdbTestExtension.testExtensionController._playgroundController + ._playgroundResult + ).to.be.deep.equal(expectedResult); + + const codeLenses = + mdbTestExtension.testExtensionController._playgroundController._exportToLanguageCodeLensProvider.provideCodeLenses(); + expect(codeLenses.length).to.be.equal(2); + + await vscode.commands.executeCommand( + 'mdb.changeExportToLanguageAddons', + { + ...mdbTestExtension.testExtensionController._playgroundController + ._exportToLanguageCodeLensProvider._exportToLanguageAddons, + driverSyntax: true, + } + ); + + expectedResult = { + namespace: 'db.coll', + type: null, + content: `// Requires the MongoDB crate.\n// https://crates.io/crates/mongodb\n\nlet client = Client::with_uri_str(\"mongodb://localhost:27088/?appname=mongodb-vscode+${version}\").await?;\nlet result = client.database(\"db\").collection::(\"coll\").find(doc! {\n \"name\": \"22\"\n}, None).await?;`, + language: 'rust', + }; + + expect( + mdbTestExtension.testExtensionController._playgroundController + ._playgroundResult + ).to.be.deep.equal(expectedResult); + } + } + }); + + test('exports to php and includes driver syntax', async () => { + const textFromEditor = "use('db'); db.coll.find({ name: '22' })"; + const selection = { + start: { line: 0, character: 24 }, + end: { line: 0, character: 38 }, + } as vscode.Selection; + const mode = ExportToLanguageMode.QUERY; + const activeTextEditor = { + document: { getText: () => textFromEditor }, + } as vscode.TextEditor; + + mdbTestExtension.testExtensionController._playgroundController._selectedText = + "{ name: '22' }"; + mdbTestExtension.testExtensionController._playgroundController._playgroundSelectedCodeActionProvider.selection = + selection; + mdbTestExtension.testExtensionController._playgroundController._playgroundSelectedCodeActionProvider.mode = + mode; + mdbTestExtension.testExtensionController._playgroundController._activeTextEditor = + activeTextEditor; + + testCodeActionProvider.refresh({ selection, mode }); + + const codeActions = testCodeActionProvider.provideCodeActions(); + expect(codeActions).to.exist; + + if (codeActions) { + expect(codeActions.length).to.be.equal(TOTAL_CODEACTIONS_COUNT); + const actionCommand = codeActions[8].command; + + if (actionCommand) { + expect(actionCommand.command).to.be.equal('mdb.exportToPHP'); + expect(actionCommand.title).to.be.equal('Export To PHP'); + + await vscode.commands.executeCommand(actionCommand.command); + + let expectedResult: PlaygroundResult = { + namespace: 'DATABASE_NAME.COLLECTION_NAME', + type: null, + content: "['name' => '22']", + language: 'php', + }; + expect( + mdbTestExtension.testExtensionController._playgroundController + ._playgroundResult + ).to.be.deep.equal(expectedResult); + + const codeLenses = + mdbTestExtension.testExtensionController._playgroundController._exportToLanguageCodeLensProvider.provideCodeLenses(); + expect(codeLenses.length).to.be.equal(2); + + await vscode.commands.executeCommand( + 'mdb.changeExportToLanguageAddons', + { + ...mdbTestExtension.testExtensionController._playgroundController + ._exportToLanguageCodeLensProvider._exportToLanguageAddons, + driverSyntax: true, + } + ); + + expectedResult = { + namespace: 'db.coll', + type: null, + content: `// Requires the MongoDB PHP Driver\n// https://www.mongodb.com/docs/drivers/php/\n\n$client = new Client('mongodb://localhost:27088/?appname=mongodb-vscode+${version}');\n$collection = $client->selectCollection('db', 'coll');\n$cursor = $collection->find(['name' => '22']);`, + language: 'php', + }; + + expect( + mdbTestExtension.testExtensionController._playgroundController + ._playgroundResult + ).to.be.deep.equal(expectedResult); + } + } + }); }); suite('the regular JS file', () => { diff --git a/src/types/playgroundType.ts b/src/types/playgroundType.ts index b2728c71b..350a7d890 100644 --- a/src/types/playgroundType.ts +++ b/src/types/playgroundType.ts @@ -46,6 +46,8 @@ export enum ExportToLanguages { JAVASCRIPT = 'javascript', RUBY = 'ruby', GO = 'go', + RUST = 'rust', + PHP = 'php', } export enum ExportToLanguageMode { From b03533f13b6ba20752cde21ff4ae883b18535c41 Mon Sep 17 00:00:00 2001 From: Basit <1305718+mabaasit@users.noreply.github.com> Date: Fri, 26 Jan 2024 18:16:21 +0100 Subject: [PATCH 7/7] chore(ci): sign using package (#678) --- .../actions/test-and-build/action.yaml | 9 ++- package-lock.json | 65 ++++++++++++++++++- package.json | 1 + scripts/sign-vsix.js | 13 ++++ scripts/sign-vsix.sh | 45 ------------- 5 files changed, 84 insertions(+), 49 deletions(-) create mode 100644 scripts/sign-vsix.js delete mode 100644 scripts/sign-vsix.sh diff --git a/.github/workflows/actions/test-and-build/action.yaml b/.github/workflows/actions/test-and-build/action.yaml index 07f558515..f69e43675 100644 --- a/.github/workflows/actions/test-and-build/action.yaml +++ b/.github/workflows/actions/test-and-build/action.yaml @@ -89,13 +89,18 @@ runs: - name: Sign .vsix if: runner.os == 'Linux' env: - ARTIFACTORY_HOST: ${{ inputs.ARTIFACTORY_HOST }} ARTIFACTORY_PASSWORD: ${{ inputs.ARTIFACTORY_PASSWORD }} ARTIFACTORY_USERNAME: ${{ inputs.ARTIFACTORY_USERNAME }} GARASIGN_PASSWORD: ${{ inputs.GARASIGN_PASSWORD }} GARASIGN_USERNAME: ${{ inputs.GARASIGN_USERNAME }} run: | - bash scripts/sign-vsix.sh + set -e + FILE_TO_SIGN=$(find . -maxdepth 1 -name '*.vsix' -print -quit) + if [ -z "$FILE_TO_SIGN" ]; then + echo "Error: No .vsix file found in the current directory." >&2 + exit 1 + fi + node scripts/sign-vsix.js "${FILE_TO_SIGN}" ls *.vsix.sig shell: bash diff --git a/package-lock.json b/package-lock.json index bf3007bfe..e981e8c50 100644 --- a/package-lock.json +++ b/package-lock.json @@ -50,6 +50,7 @@ "@mongodb-js/oidc-plugin": "^0.3.0", "@mongodb-js/prettier-config-devtools": "^1.0.1", "@mongodb-js/sbom-tools": "^0.5.4", + "@mongodb-js/signing-utils": "^0.3.1", "@mongosh/service-provider-core": "^2.0.2", "@testing-library/react": "^12.1.5", "@types/babel__core": "^7.20.1", @@ -4961,6 +4962,17 @@ "mongodb-sbom-tools": "bin/mongodb-sbom-tools.js" } }, + "node_modules/@mongodb-js/signing-utils": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@mongodb-js/signing-utils/-/signing-utils-0.3.1.tgz", + "integrity": "sha512-/zAg9vdxTQstu6kNkfOPr9WvLodz88k7egetKw8c5eZyPLBQgm3JfTaH7vQe/iSCuCwvXSk0tNcgo+6AdQNbTw==", + "dev": true, + "dependencies": { + "@types/ssh2": "^1.11.19", + "debug": "^4.3.4", + "ssh2": "^1.15.0" + } + }, "node_modules/@mongodb-js/ssh-tunnel": { "version": "2.1.10", "resolved": "https://registry.npmjs.org/@mongodb-js/ssh-tunnel/-/ssh-tunnel-2.1.10.tgz", @@ -6434,6 +6446,24 @@ "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz", "integrity": "sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==" }, + "node_modules/@types/ssh2": { + "version": "1.11.19", + "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-1.11.19.tgz", + "integrity": "sha512-ydbQAqEcdNVy2t1w7dMh6eWMr+iOgtEkqM/3K9RMijMaok/ER7L8GW6PwsOypHCN++M+c8S/UR9SgMqNIFstbA==", + "dev": true, + "dependencies": { + "@types/node": "^18.11.18" + } + }, + "node_modules/@types/ssh2/node_modules/@types/node": { + "version": "18.19.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.10.tgz", + "integrity": "sha512-IZD8kAM02AW1HRDTPOlz3npFava678pr8Ie9Vp8uRhBROXAv8MXT2pCnGZZAKYdromsNQLHQcfWQ6EOatVLtqA==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, "node_modules/@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", @@ -22322,7 +22352,7 @@ "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "optional": true + "devOptional": true }, "node_modules/union-value": { "version": "1.0.1", @@ -27482,6 +27512,17 @@ "spdx-satisfies": "^5.0.1" } }, + "@mongodb-js/signing-utils": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@mongodb-js/signing-utils/-/signing-utils-0.3.1.tgz", + "integrity": "sha512-/zAg9vdxTQstu6kNkfOPr9WvLodz88k7egetKw8c5eZyPLBQgm3JfTaH7vQe/iSCuCwvXSk0tNcgo+6AdQNbTw==", + "dev": true, + "requires": { + "@types/ssh2": "^1.11.19", + "debug": "^4.3.4", + "ssh2": "^1.15.0" + } + }, "@mongodb-js/ssh-tunnel": { "version": "2.1.10", "resolved": "https://registry.npmjs.org/@mongodb-js/ssh-tunnel/-/ssh-tunnel-2.1.10.tgz", @@ -28704,6 +28745,26 @@ "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz", "integrity": "sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==" }, + "@types/ssh2": { + "version": "1.11.19", + "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-1.11.19.tgz", + "integrity": "sha512-ydbQAqEcdNVy2t1w7dMh6eWMr+iOgtEkqM/3K9RMijMaok/ER7L8GW6PwsOypHCN++M+c8S/UR9SgMqNIFstbA==", + "dev": true, + "requires": { + "@types/node": "^18.11.18" + }, + "dependencies": { + "@types/node": { + "version": "18.19.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.10.tgz", + "integrity": "sha512-IZD8kAM02AW1HRDTPOlz3npFava678pr8Ie9Vp8uRhBROXAv8MXT2pCnGZZAKYdromsNQLHQcfWQ6EOatVLtqA==", + "dev": true, + "requires": { + "undici-types": "~5.26.4" + } + } + } + }, "@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", @@ -40952,7 +41013,7 @@ "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "optional": true + "devOptional": true }, "union-value": { "version": "1.0.1", diff --git a/package.json b/package.json index e21f6cf35..38997d53e 100644 --- a/package.json +++ b/package.json @@ -1117,6 +1117,7 @@ "@mongodb-js/oidc-plugin": "^0.3.0", "@mongodb-js/prettier-config-devtools": "^1.0.1", "@mongodb-js/sbom-tools": "^0.5.4", + "@mongodb-js/signing-utils": "^0.3.1", "@mongosh/service-provider-core": "^2.0.2", "@testing-library/react": "^12.1.5", "@types/babel__core": "^7.20.1", diff --git a/scripts/sign-vsix.js b/scripts/sign-vsix.js new file mode 100644 index 000000000..5a45f7c1f --- /dev/null +++ b/scripts/sign-vsix.js @@ -0,0 +1,13 @@ +const { sign } = require('@mongodb-js/signing-utils'); + +(async () => { + const file = process.argv[2]; + if (!file) { + throw new Error('File is required.'); + } + console.log(`Signing vsix: ${file}`); + await sign(file, { + client: 'local', + signingMethod: 'gpg', + }); +})(); diff --git a/scripts/sign-vsix.sh b/scripts/sign-vsix.sh deleted file mode 100644 index 5cf417adb..000000000 --- a/scripts/sign-vsix.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash - -FILE_TO_SIGN=$(find . -maxdepth 1 -name '*.vsix' -print -quit) - -if [ -z "$FILE_TO_SIGN" ]; then - echo "Error: No .vsix file found in the current directory." >&2 - exit 1 -fi - -required_vars=("ARTIFACTORY_PASSWORD" "ARTIFACTORY_HOST" "ARTIFACTORY_USERNAME" "GARASIGN_USERNAME" "GARASIGN_PASSWORD") -for var in "${required_vars[@]}"; do - if [ -z "${!var}" ]; then - echo "Error: Environment variable $var is not set." >&2 - exit 1 - fi -done - -logout_artifactory() { - docker logout "${ARTIFACTORY_HOST}" > /dev/null 2>&1 - echo "logged out from artifactory" -} - -trap logout_artifactory EXIT - - -echo "${ARTIFACTORY_PASSWORD}" | docker login "${ARTIFACTORY_HOST}" -u "${ARTIFACTORY_USERNAME}" --password-stdin > /dev/null 2>&1 - -if [ $? -ne 0 ]; then - echo "Docker login failed" >&2 - exit 1 -fi - -docker run \ - --rm \ - -e GRS_CONFIG_USER1_USERNAME="${GARASIGN_USERNAME}" \ - -e GRS_CONFIG_USER1_PASSWORD="${GARASIGN_PASSWORD}" \ - -v "$(pwd):/tmp/workdir" \ - -w /tmp/workdir \ - ${ARTIFACTORY_HOST}/release-tools-container-registry-local/garasign-gpg \ - /bin/bash -c "gpgloader && gpg --yes -v --armor -o /tmp/workdir/${FILE_TO_SIGN}.sig --detach-sign /tmp/workdir/${FILE_TO_SIGN}" - -if [ $? -ne 0 ]; then - echo "Signing failed" >&2 - exit 1 -fi