From d7e39fd723693d7f4a73663561066437bcfbab27 Mon Sep 17 00:00:00 2001 From: Le Roux Bodenstein Date: Tue, 1 Oct 2024 14:13:14 +0100 Subject: [PATCH] split out connectionSupports into a function that we can use outside of hooks --- .../src/hooks/use-connection-supports.ts | 47 +---- packages/compass-connections/src/index.tsx | 2 + .../src/utils/connection-supports.spec.ts | 199 ++++++++++++++++++ .../src/utils/connection-supports.ts | 49 +++++ 4 files changed, 253 insertions(+), 44 deletions(-) create mode 100644 packages/compass-connections/src/utils/connection-supports.spec.ts create mode 100644 packages/compass-connections/src/utils/connection-supports.ts diff --git a/packages/compass-connections/src/hooks/use-connection-supports.ts b/packages/compass-connections/src/hooks/use-connection-supports.ts index 7006c9c33eb..27ffd75809b 100644 --- a/packages/compass-connections/src/hooks/use-connection-supports.ts +++ b/packages/compass-connections/src/hooks/use-connection-supports.ts @@ -1,39 +1,6 @@ import { useSelector } from '../stores/store-context'; -import type { ConnectionState } from '../stores/connections-store-redux'; - -type ConnectionFeature = 'rollingIndexCreation' | 'globalWrites'; - -function isFreeOrSharedTierCluster(instanceSize: string | undefined): boolean { - if (!instanceSize) { - return false; - } - - return ['M0', 'M2', 'M5'].includes(instanceSize); -} - -function supportsRollingIndexCreation(connection: ConnectionState) { - const atlasMetadata = connection.info?.atlasMetadata; - - if (!atlasMetadata) { - return false; - } - - const { metricsType, instanceSize } = atlasMetadata; - return ( - !isFreeOrSharedTierCluster(instanceSize) && - (metricsType === 'cluster' || metricsType === 'replicaSet') - ); -} - -function supportsGlobalWrites(connection: ConnectionState) { - const atlasMetadata = connection.info?.atlasMetadata; - - if (!atlasMetadata) { - return false; - } - - return atlasMetadata.clusterType === 'GEOSHARDED'; -} +import type { ConnectionFeature } from '../utils/connection-supports'; +import { connectionSupports } from '../utils/connection-supports'; export function useConnectionSupports( connectionId: string, @@ -46,14 +13,6 @@ export function useConnectionSupports( return false; } - if (connectionFeature === 'rollingIndexCreation') { - return supportsRollingIndexCreation(connection); - } - - if (connectionFeature === 'globalWrites') { - return supportsGlobalWrites(connection); - } - - return false; + return connectionSupports(connection.info, connectionFeature); }); } diff --git a/packages/compass-connections/src/index.tsx b/packages/compass-connections/src/index.tsx index f24a5758529..daf8203eccb 100644 --- a/packages/compass-connections/src/index.tsx +++ b/packages/compass-connections/src/index.tsx @@ -22,6 +22,8 @@ export { LegacyConnectionsModal } from './components/legacy-connections-modal'; export { useConnectionFormPreferences } from './hooks/use-connection-form-preferences'; import type { connect as devtoolsConnect } from 'mongodb-data-service'; import type { ExtraConnectionData as ExtraConnectionDataForTelemetry } from '@mongodb-js/compass-telemetry'; +export type { ConnectionFeature } from './utils/connection-supports'; +export { connectionSupports } from './utils/connection-supports'; const ConnectionsComponent: React.FunctionComponent<{ appName: string; diff --git a/packages/compass-connections/src/utils/connection-supports.spec.ts b/packages/compass-connections/src/utils/connection-supports.spec.ts new file mode 100644 index 00000000000..de32f2abbcd --- /dev/null +++ b/packages/compass-connections/src/utils/connection-supports.spec.ts @@ -0,0 +1,199 @@ +import { connectionSupports } from './connection-supports'; +import { type ConnectionInfo } from '@mongodb-js/connection-storage/provider'; +import { expect } from 'chai'; + +const mockConnections: ConnectionInfo[] = [ + { + id: 'no-atlasMetadata', + connectionOptions: { + connectionString: 'mongodb://foo', + }, + }, + { + id: 'host-cluster', + connectionOptions: { + connectionString: 'mongodb://foo', + }, + atlasMetadata: { + orgId: 'orgId', + projectId: 'projectId', + clusterName: 'clusterName', + regionalBaseUrl: 'https://example.com', + metricsId: 'metricsId', + metricsType: 'host', + instanceSize: 'M10', + clusterType: 'REPLICASET', + clusterUniqueId: 'clusterUniqueId', + }, + }, + { + id: 'free-cluster', + connectionOptions: { + connectionString: 'mongodb://foo', + }, + atlasMetadata: { + orgId: 'orgId', + projectId: 'projectId', + clusterName: 'clusterName', + regionalBaseUrl: 'https://example.com', + metricsId: 'metricsId', + metricsType: 'replicaSet', + instanceSize: 'M0', + clusterType: 'REPLICASET', + clusterUniqueId: 'clusterUniqueId', + }, + }, + { + id: 'serverless-cluster', + connectionOptions: { + connectionString: 'mongodb://foo', + }, + atlasMetadata: { + orgId: 'orgId', + projectId: 'projectId', + clusterName: 'clusterName', + regionalBaseUrl: 'https://example.com', + metricsId: 'metricsId', + metricsType: 'serverless', + instanceSize: 'SERVERLESS_V2', + clusterType: 'REPLICASET', + clusterUniqueId: 'clusterUniqueId', + }, + }, + { + id: 'dedicated-replicaSet', + connectionOptions: { + connectionString: 'mongodb://foo', + }, + atlasMetadata: { + orgId: 'orgId', + projectId: 'projectId', + clusterName: 'clusterName', + regionalBaseUrl: 'https://example.com', + metricsId: 'metricsId', + metricsType: 'replicaSet', + instanceSize: 'M10', + clusterType: 'REPLICASET', + clusterUniqueId: 'clusterUniqueId', + }, + }, + { + id: 'dedicated-sharded', + connectionOptions: { + connectionString: 'mongodb://foo', + }, + atlasMetadata: { + orgId: 'orgId', + projectId: 'projectId', + clusterName: 'clusterName', + regionalBaseUrl: 'https://example.com', + metricsId: 'metricsId', + metricsType: 'cluster', + instanceSize: 'M10', + clusterType: 'SHARDED', + clusterUniqueId: 'clusterUniqueId', + }, + }, + { + id: 'dedicated-geo-sharded', + connectionOptions: { + connectionString: 'mongodb://foo', + }, + atlasMetadata: { + orgId: 'orgId', + projectId: 'projectId', + clusterName: 'clusterName', + regionalBaseUrl: 'https://example.com', + metricsId: 'metricsId', + metricsType: 'cluster', + instanceSize: 'M30', + clusterType: 'GEOSHARDED', + clusterUniqueId: 'clusterUniqueId', + }, + }, +]; + +function connectionInfoById(connectionId: string): ConnectionInfo { + const connectionInfo = mockConnections.find(({ id }) => id === connectionId); + if (!connectionInfo) { + throw new Error(`No connection for id "${connectionId}"`); + } + return connectionInfo; +} + +describe('connectionSupports', function () { + context('rollingIndexCreation', function () { + it('should return false if the connection has no atlasMetadata', function () { + expect( + connectionSupports( + connectionInfoById('no-atlasMetadata'), + 'rollingIndexCreation' + ) + ).to.be.false; + }); + + it('should return false for host cluster type', function () { + expect( + connectionSupports( + connectionInfoById('host-cluster'), + 'rollingIndexCreation' + ) + ).to.be.false; + }); + + it('should return false for serverless cluster type', function () { + expect( + connectionSupports( + connectionInfoById('serverless-cluster'), + 'rollingIndexCreation' + ) + ).to.be.false; + }); + + it('should return false for free/shared tier clusters', function () { + expect( + connectionSupports( + connectionInfoById('free-cluster'), + 'rollingIndexCreation' + ) + ).to.be.false; + }); + + it('should return true for dedicated replicaSet clusters', function () { + expect( + connectionSupports( + connectionInfoById('dedicated-replicaSet'), + 'rollingIndexCreation' + ) + ).to.be.true; + }); + + it('should return true for dedicated sharded clusters', function () { + expect( + connectionSupports( + connectionInfoById('dedicated-sharded'), + 'rollingIndexCreation' + ) + ).to.be.true; + }); + }); + context('globalWrites', function () { + it('should return false if the connection has no atlasMetadata', function () { + expect( + connectionSupports( + connectionInfoById('no-atlasMetadata'), + 'globalWrites' + ) + ).to.be.false; + }); + + it('should return true if the cluster type is geosharded', function () { + expect( + connectionSupports( + connectionInfoById('dedicated-geo-sharded'), + 'globalWrites' + ) + ).to.be.true; + }); + }); +}); diff --git a/packages/compass-connections/src/utils/connection-supports.ts b/packages/compass-connections/src/utils/connection-supports.ts new file mode 100644 index 00000000000..cec5c564462 --- /dev/null +++ b/packages/compass-connections/src/utils/connection-supports.ts @@ -0,0 +1,49 @@ +import type { ConnectionInfo } from '@mongodb-js/connection-info'; +export type ConnectionFeature = 'rollingIndexCreation' | 'globalWrites'; + +function isFreeOrSharedTierCluster(instanceSize: string | undefined): boolean { + if (!instanceSize) { + return false; + } + + return ['M0', 'M2', 'M5'].includes(instanceSize); +} + +function supportsRollingIndexCreation(connectionInfo: ConnectionInfo) { + const atlasMetadata = connectionInfo.atlasMetadata; + + if (!atlasMetadata) { + return false; + } + + const { metricsType, instanceSize } = atlasMetadata; + return ( + !isFreeOrSharedTierCluster(instanceSize) && + (metricsType === 'cluster' || metricsType === 'replicaSet') + ); +} + +function supportsGlobalWrites(connectionInfo: ConnectionInfo) { + const atlasMetadata = connectionInfo.atlasMetadata; + + if (!atlasMetadata) { + return false; + } + + return atlasMetadata.clusterType === 'GEOSHARDED'; +} + +export function connectionSupports( + connectionInfo: ConnectionInfo, + connectionFeature: ConnectionFeature +): boolean { + if (connectionFeature === 'rollingIndexCreation') { + return supportsRollingIndexCreation(connectionInfo); + } + + if (connectionFeature === 'globalWrites') { + return supportsGlobalWrites(connectionInfo); + } + + return false; +}