diff --git a/packages/compass-connections/src/components/legacy-connections.tsx b/packages/compass-connections/src/components/legacy-connections.tsx index b47138d32bb..5da0cd144c2 100644 --- a/packages/compass-connections/src/components/legacy-connections.tsx +++ b/packages/compass-connections/src/components/legacy-connections.tsx @@ -191,8 +191,8 @@ function Connections({ onSaveClicked={saveEditedConnection} initialConnectionInfo={activeConnectionInfo} connectionErrorMessage={connectionErrorMessage} - preferences={connectionFormPreferences} openSettingsModal={openSettingsModal} + {...connectionFormPreferences} /> diff --git a/packages/compass-sidebar/src/components/multiple-connections/sidebar.tsx b/packages/compass-sidebar/src/components/multiple-connections/sidebar.tsx index 3ad5238b987..3189961eda0 100644 --- a/packages/compass-sidebar/src/components/multiple-connections/sidebar.tsx +++ b/packages/compass-sidebar/src/components/multiple-connections/sidebar.tsx @@ -248,8 +248,8 @@ export function MultipleConnectionSidebar({ connectionErrorMessage={ connectionErrors[editingConnectionInfo.id]?.message } - preferences={formPreferences} openSettingsModal={openSettingsModal} + {...formPreferences} /> )} { - screen.getByTestId('home'); - }, - { timeout: 1_000_000 } - ); - } - afterEach(() => { cleanup(); sinon.restore(); }); describe('is not connected', function () { - it('renders the connect screen', function () { - renderHome(); - expect(() => screen.getByTestId('home')).to.throw; - expect(screen.getByTestId('connections-wrapper')).to.be.displayed; - }); - it('renders welcome modal and hides it', async function () { renderHome({ showWelcomeModal: true }); const modal = screen.getByTestId('welcome-modal'); @@ -137,58 +118,4 @@ describe('Home [Component]', function () { }); }); }); - - describe('is connected', function () { - describe('when UI status is complete', function () { - let dataServiceDisconnectedSpy: sinon.SinonSpy; - - let onDisconnectSpy: sinon.SinonSpy; - let hideCollectionSubMenuSpy: sinon.SinonSpy; - - beforeEach(async function () { - dataServiceDisconnectedSpy = sinon.fake.resolves(true); - hideCollectionSubMenuSpy = sinon.spy(); - onDisconnectSpy = sinon.spy(); - const dataService = { - ...createDataService(), - disconnect: dataServiceDisconnectedSpy, - addReauthenticationHandler: sinon.stub(), - }; - renderHome( - { - hideCollectionSubMenu: hideCollectionSubMenuSpy, - onDisconnect: onDisconnectSpy, - }, - [], - dataService - ); - await waitForConnect(); - }); - - afterEach(function () { - sinon.restore(); - }); - - it('renders only the workspaces', function () { - expect(screen.getByTestId('home')).to.be.displayed; - expect(() => screen.getByTestId('connections-wrapper')).to.throw; - }); - - it('on `app:disconnect`', async function () { - hadronIpc.ipcRenderer?.emit('app:disconnect'); - await waitFor(() => { - expect(onDisconnectSpy.called, 'it calls onDisconnect').to.be.true; - expect( - hideCollectionSubMenuSpy.called, - 'it calls hideCollectionSubMenu' - ).to.be.true; - }); - - await waitFor(() => { - expect(screen.queryByTestId('connections-wrapper')).to.be.visible; - }); - expect(dataServiceDisconnectedSpy.callCount).to.equal(1); - }); - }); - }); }); diff --git a/packages/connection-form/src/components/advanced-options-tabs/advanced-options-tabs.spec.tsx b/packages/connection-form/src/components/advanced-options-tabs/advanced-options-tabs.spec.tsx index 38f415c878d..4f33c2ba3df 100644 --- a/packages/connection-form/src/components/advanced-options-tabs/advanced-options-tabs.spec.tsx +++ b/packages/connection-form/src/components/advanced-options-tabs/advanced-options-tabs.spec.tsx @@ -4,7 +4,7 @@ import { expect } from 'chai'; import sinon from 'sinon'; import AdvancedOptionsTabs from './advanced-options-tabs'; -import { ConnectionFormPreferencesContext } from '../../hooks/use-connect-form-preferences'; +import { ConnectionFormSettingsContext } from '../../hooks/use-connect-form-settings'; const testUrl = 'mongodb+srv://0ranges:p!neapp1es@localhost/?ssl=true'; @@ -110,7 +110,7 @@ describe('AdvancedOptionsTabs Component', function () { it('should not render CSFLE when its set to false in the preferences', function () { render( - + - + ); const csfleTabName = tabs.find((tab) => tab.id === 'csfle')?.name; diff --git a/packages/connection-form/src/components/advanced-options-tabs/advanced-options-tabs.tsx b/packages/connection-form/src/components/advanced-options-tabs/advanced-options-tabs.tsx index f247914e132..bb09a5c5c9a 100644 --- a/packages/connection-form/src/components/advanced-options-tabs/advanced-options-tabs.tsx +++ b/packages/connection-form/src/components/advanced-options-tabs/advanced-options-tabs.tsx @@ -20,7 +20,7 @@ import type { UpdateConnectionFormField } from '../../hooks/use-connect-form'; import type { ConnectionFormError, TabId } from '../../utils/validation'; import { errorsByFieldTab } from '../../utils/validation'; import { defaultConnectionString } from '../../constants/default-connection'; -import { useConnectionFormPreference } from '../../hooks/use-connect-form-preferences'; +import { useConnectionFormSetting } from '../../hooks/use-connect-form-settings'; const tabsStyles = css({ marginTop: spacing[2], @@ -72,7 +72,7 @@ function AdvancedOptionsTabs({ openSettingsModal?: (tab?: string) => void; }): React.ReactElement { const [activeTab, setActiveTab] = useState(0); - const showCSFLE = useConnectionFormPreference('showCSFLE'); + const showCSFLE = useConnectionFormSetting('showCSFLE'); const tabs: TabObject[] = [ { name: 'General', id: 'general', component: GeneralTab }, diff --git a/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-gssapi.spec.tsx b/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-gssapi.spec.tsx index a3e7cf69533..3c3eecb8dd6 100644 --- a/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-gssapi.spec.tsx +++ b/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-gssapi.spec.tsx @@ -12,7 +12,7 @@ import ConnectionStringUrl from 'mongodb-connection-string-url'; import AuthenticationGssapi from './authentication-gssapi'; import type { ConnectionFormError } from '../../../utils/validation'; import type { UpdateConnectionFormField } from '../../../hooks/use-connect-form'; -import { ConnectionFormPreferencesContext } from '../../../hooks/use-connect-form-preferences'; +import { ConnectionFormSettingsContext } from '../../../hooks/use-connect-form-settings'; function renderComponent({ errors = [], @@ -24,7 +24,7 @@ function renderComponent({ updateConnectionFormField: UpdateConnectionFormField; }) { render( - - + ); } diff --git a/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-gssapi.tsx b/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-gssapi.tsx index 88c9feecb44..1d4d803011f 100644 --- a/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-gssapi.tsx +++ b/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-gssapi.tsx @@ -17,7 +17,7 @@ import { getConnectionStringUsername, parseAuthMechanismProperties, } from '../../../utils/connection-string-helpers'; -import { useConnectionFormPreference } from '../../../hooks/use-connect-form-preferences'; +import { useConnectionFormSetting } from '../../../hooks/use-connect-form-settings'; const GSSAPI_CANONICALIZE_HOST_NAME_OPTIONS: Record< string, @@ -56,7 +56,7 @@ function AuthenticationGSSAPI({ const [showPassword, setShowPassword] = useState(false); - const showKerberosPasswordField = !!useConnectionFormPreference( + const showKerberosPasswordField = !!useConnectionFormSetting( 'showKerberosPasswordField' ); diff --git a/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-oidc.spec.tsx b/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-oidc.spec.tsx index 85a16e897cf..27bfda46557 100644 --- a/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-oidc.spec.tsx +++ b/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-oidc.spec.tsx @@ -31,7 +31,8 @@ async function renderConnectionForm( onSaveAndConnectClicked={(connectionInfo) => { void connectSpy(connectionInfo.connectionOptions); }} - preferences={{ enableOidc: true, showOIDCDeviceAuthFlow }} + enableOidc={true} + showOIDCDeviceAuthFlow={showOIDCDeviceAuthFlow} onSaveClicked={() => { return Promise.resolve(); }} diff --git a/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-oidc.tsx b/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-oidc.tsx index 97a805c29fd..e4a8698593a 100644 --- a/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-oidc.tsx +++ b/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-oidc.tsx @@ -16,7 +16,7 @@ import type { ConnectionFormError } from '../../../utils/validation'; import { errorMessageByFieldName } from '../../../utils/validation'; import { getConnectionStringUsername } from '../../../utils/connection-string-helpers'; import type { OIDCOptions } from '../../../utils/oidc-handler'; -import { useConnectionFormPreference } from '../../../hooks/use-connect-form-preferences'; +import { useConnectionFormSetting } from '../../../hooks/use-connect-form-settings'; type AuthFlowType = NonNullable[number]; @@ -50,7 +50,7 @@ function AuthenticationOIDC({ const hasEnabledDeviceAuthFlow = !!connectionOptions.oidc?.allowedFlows?.includes?.('device-auth'); - const showOIDCDeviceAuthFlow = !!useConnectionFormPreference( + const showOIDCDeviceAuthFlow = !!useConnectionFormSetting( 'showOIDCDeviceAuthFlow' ); @@ -59,7 +59,7 @@ function AuthenticationOIDC({ [openSettingsModal] ); const showProxySettings = - useConnectionFormPreference('showProxySettings') && openSettingsModal; + useConnectionFormSetting('showProxySettings') && openSettingsModal; return ( <> diff --git a/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-tab.spec.tsx b/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-tab.spec.tsx index 6d317bf4733..cec0f60c13c 100644 --- a/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-tab.spec.tsx +++ b/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-tab.spec.tsx @@ -8,26 +8,24 @@ import type { AuthMechanism } from 'mongodb'; import AuthenticationTab from './authentication-tab'; import type { ConnectionFormError } from '../../../utils/validation'; import type { UpdateConnectionFormField } from '../../../hooks/use-connect-form'; -import { ConnectionFormPreferencesContext } from '../../../hooks/use-connect-form-preferences'; -import type { ConnectionFormPreferences } from '../../../hooks/use-connect-form-preferences'; +import { ConnectionFormSettingsContext } from '../../../hooks/use-connect-form-settings'; +import type { ConnectionFormSettings } from '../../../hooks/use-connect-form-settings'; function renderComponent({ errors = [], connectionStringUrl = new ConnectionStringUrl('mongodb://localhost:27017'), - connectionFormPreferences = { + connectionFormSettings = { enableOidc: true, }, updateConnectionFormField, }: { connectionStringUrl?: ConnectionStringUrl; - connectionFormPreferences?: Partial; + connectionFormSettings?: Partial; errors?: ConnectionFormError[]; updateConnectionFormField: UpdateConnectionFormField; }) { render( - + - + ); } @@ -142,7 +140,7 @@ describe('AuthenticationTab Component', function () { it('should not render OIDC auth when its set to false in the preferences', function () { renderComponent({ - connectionFormPreferences: { showOIDCAuth: false }, + connectionFormSettings: { showOIDCAuth: false }, updateConnectionFormField: updateConnectionFormFieldSpy, }); @@ -155,7 +153,7 @@ describe('AuthenticationTab Component', function () { it('should not render Kerberos auth when its set to false in the preferences', function () { renderComponent({ - connectionFormPreferences: { showKerberosAuth: false }, + connectionFormSettings: { showKerberosAuth: false }, updateConnectionFormField: updateConnectionFormFieldSpy, }); diff --git a/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-tab.tsx b/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-tab.tsx index a3b63287974..7a8b5343cd7 100644 --- a/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-tab.tsx +++ b/packages/connection-form/src/components/advanced-options-tabs/authentication-tab/authentication-tab.tsx @@ -20,7 +20,7 @@ import AuthenticationGSSAPI from './authentication-gssapi'; import AuthenticationPlain from './authentication-plain'; import AuthenticationAWS from './authentication-aws'; import AuthenticationOidc from './authentication-oidc'; -import { useConnectionFormPreference } from '../../../hooks/use-connect-form-preferences'; +import { useConnectionFormSetting } from '../../../hooks/use-connect-form-settings'; interface TabOption { id: AuthMechanism; @@ -100,9 +100,9 @@ function AuthenticationTab({ openSettingsModal?: (tab?: string) => void; }): React.ReactElement { // enableOIDC is the feature flag, showOIDC is the connection form preference. - const enableOIDC = !!useConnectionFormPreference('enableOidc'); - const showOIDC = useConnectionFormPreference('showOIDCAuth'); - const showKerberos = useConnectionFormPreference('showKerberosAuth'); + const enableOIDC = !!useConnectionFormSetting('enableOidc'); + const showOIDC = useConnectionFormSetting('showOIDCAuth'); + const showKerberos = useConnectionFormSetting('showKerberosAuth'); const enabledAuthOptions = useMemo( () => options.filter((option) => { diff --git a/packages/connection-form/src/components/advanced-options-tabs/csfle-tab/csfle-tab.tsx b/packages/connection-form/src/components/advanced-options-tabs/csfle-tab/csfle-tab.tsx index 81372d65138..9eeb1829a15 100644 --- a/packages/connection-form/src/components/advanced-options-tabs/csfle-tab/csfle-tab.tsx +++ b/packages/connection-form/src/components/advanced-options-tabs/csfle-tab/csfle-tab.tsx @@ -35,7 +35,7 @@ import type { KMSProviderName, } from '../../../utils/csfle-kms-fields'; import { KMSProviderFields } from '../../../utils/csfle-kms-fields'; -import { useConnectionFormPreference } from '../../../hooks/use-connect-form-preferences'; +import { useConnectionFormSetting } from '../../../hooks/use-connect-form-settings'; const kmsProviderComponentWrapperStyles = css({ paddingLeft: spacing[3], @@ -96,7 +96,7 @@ function CSFLETab({ const autoEncryptionOptions = connectionOptions.fleOptions?.autoEncryption ?? {}; - const enableSchemaMapDebugFlag = useConnectionFormPreference( + const enableSchemaMapDebugFlag = useConnectionFormSetting( 'enableDebugUseCsfleSchemaMap' ); diff --git a/packages/connection-form/src/components/advanced-options-tabs/ssh-tunnel-tab/proxy-and-ssh-tunnel-tab.tsx b/packages/connection-form/src/components/advanced-options-tabs/ssh-tunnel-tab/proxy-and-ssh-tunnel-tab.tsx index 62ea137f0fa..ec8a0782d0c 100644 --- a/packages/connection-form/src/components/advanced-options-tabs/ssh-tunnel-tab/proxy-and-ssh-tunnel-tab.tsx +++ b/packages/connection-form/src/components/advanced-options-tabs/ssh-tunnel-tab/proxy-and-ssh-tunnel-tab.tsx @@ -22,7 +22,7 @@ import SshTunnelPassword from './ssh-tunnel-password'; import Socks from './socks'; import { AppProxy } from './app-proxy'; import type { ConnectionFormError } from '../../../utils/validation'; -import { useConnectionFormPreference } from '../../../hooks/use-connect-form-preferences'; +import { useConnectionFormSetting } from '../../../hooks/use-connect-form-settings'; interface TabOption { id: string; @@ -127,7 +127,7 @@ function ProxyAndSshTunnelTab({ ); const options = [...tabOptions]; - const showProxySettings = useConnectionFormPreference('showProxySettings'); + const showProxySettings = useConnectionFormSetting('showProxySettings'); if (showProxySettings) { options.push({ title: 'Application-level Proxy', diff --git a/packages/connection-form/src/components/connection-form-actions.spec.tsx b/packages/connection-form/src/components/connection-form-actions.spec.tsx index 3fb75a3ab22..03434261762 100644 --- a/packages/connection-form/src/components/connection-form-actions.spec.tsx +++ b/packages/connection-form/src/components/connection-form-actions.spec.tsx @@ -1,12 +1,54 @@ import React from 'react'; -import { render, screen, fireEvent } from '@mongodb-js/testing-library-compass'; +import { render, screen, userEvent } from '@mongodb-js/testing-library-compass'; import { expect } from 'chai'; import sinon from 'sinon'; import { ConnectionFormModalActions } from './connection-form-actions'; describe('', function () { + it('should show warnings', function () { + render( + undefined} + onSaveAndConnect={() => undefined} + > + ); + expect(screen.getByText('Warning!')).to.be.visible; + }); + + it('should show errors', function () { + render( + undefined} + onSaveAndConnect={() => undefined} + > + ); + expect(screen.getByText('Error!')).to.be.visible; + }); + describe('Connect Button', function () { + it('should call onSaveAndConnect function', function () { + const onSaveAndConnectSpy = sinon.spy(); + render( + undefined} + onSaveAndConnect={onSaveAndConnectSpy} + > + ); + const connectButton = screen.getByRole('button', { name: 'Connect' }); + userEvent.click(connectButton); + + expect(onSaveAndConnectSpy).to.have.been.calledOnce; + }); + }); + + describe('Save Button', function () { it('should call onSave function', function () { const onSaveSpy = sinon.spy(); render( @@ -17,38 +59,24 @@ describe('', function () { onSaveAndConnect={() => undefined} > ); - const saveButton = screen.getByText('Save'); - fireEvent( - saveButton, - new MouseEvent('click', { - bubbles: true, - cancelable: true, - }) - ); + const saveButton = screen.getByRole('button', { name: 'Save' }); + userEvent.click(saveButton); expect(onSaveSpy).to.have.been.calledOnce; }); - it('should call onSaveAndConnect function', function () { - const onSaveAndConnectSpy = sinon.spy(); + it('should hide "save" button if there is no callback', function () { render( undefined} - onSaveAndConnect={onSaveAndConnectSpy} + onSaveAndConnect={() => undefined} > ); - const saveButton = screen.getByText('Connect'); - fireEvent( - saveButton, - new MouseEvent('click', { - bubbles: true, - cancelable: true, - }) - ); - expect(onSaveAndConnectSpy).to.have.been.calledOnce; + expect(screen.queryByRole('button', { name: 'Save' })).to.not.exist; }); + }); + describe('Cancel Button', function () { it('should call onCancel function', function () { const onCancelSpy = sinon.spy(); render( @@ -60,39 +88,22 @@ describe('', function () { onCancel={onCancelSpy} > ); - const saveButton = screen.getByText('Cancel'); - fireEvent( - saveButton, - new MouseEvent('click', { - bubbles: true, - cancelable: true, - }) - ); + const cancelButton = screen.getByRole('button', { name: 'Cancel' }); + userEvent.click(cancelButton); + expect(onCancelSpy).to.have.been.calledOnce; }); - it('should show warnings', function () { + it('should hide onCancel button if there is no callback', function () { render( undefined} - onSaveAndConnect={() => undefined} - > - ); - expect(screen.getByText('Warning!')).to.be.visible; - }); - - it('should show errors', function () { - render( - undefined} onSaveAndConnect={() => undefined} > ); - expect(screen.getByText('Error!')).to.be.visible; + expect(screen.queryByRole('button', { name: 'Cancel' })).to.not.exist; }); }); }); diff --git a/packages/connection-form/src/components/connection-form-actions.tsx b/packages/connection-form/src/components/connection-form-actions.tsx index dd32358a213..86de081c126 100644 --- a/packages/connection-form/src/components/connection-form-actions.tsx +++ b/packages/connection-form/src/components/connection-form-actions.tsx @@ -12,7 +12,7 @@ import type { ConnectionFormError, ConnectionFormWarning, } from '../utils/validation'; -import { useConnectionFormPreference } from '../hooks/use-connect-form-preferences'; +import { useConnectionFormSetting } from '../hooks/use-connect-form-settings'; const formActionStyles = css({ paddingLeft: spacing[4], @@ -38,99 +38,15 @@ const saveAndConnectStyles = css({ justifyContent: 'flex-end', }); -export function LegacyConnectionFormActions({ - errors, - warnings, - onConnectClicked, - onSaveClicked, - onSaveAndConnectClicked, - saveButton, - saveAndConnectButton, -}: { - errors: ConnectionFormError[]; - warnings: ConnectionFormWarning[]; - onConnectClicked: () => void; - onSaveClicked: () => void; - onSaveAndConnectClicked: () => void; - saveButton: 'enabled' | 'disabled' | 'hidden'; - saveAndConnectButton: 'enabled' | 'disabled' | 'hidden'; -}): React.ReactElement { - const showFavoriteActions = useConnectionFormPreference( - 'showFavoriteActions' - ); - - return ( -
- {warnings.length > 0 && ( -
- warning.message)} - /> -
- )} - {errors.length > 0 && ( -
- error.message)} - /> -
- )} -
- {showFavoriteActions && ( - <> - {saveButton !== 'hidden' && ( - - )} - - {saveAndConnectButton !== 'hidden' && ( -
- -
- )} - - )} - - -
-
- ); -} - export type ConnectionFormModalActionsProps = { errors: ConnectionFormError[]; warnings: ConnectionFormWarning[]; onCancel?(): void; - onSave(): void; + onSave?(): void; onSaveAndConnect(): void; }; -// TODO(COMPASS-8098): Make sure these work for VSCode, for example add: -// saveButton: 'enabled' | 'disabled' | 'hidden'; -// saveAndConnectButton: 'enabled' | 'disabled' | 'hidden'; -// cancelButton: 'enabled' | 'disabled' | 'hidden'; export function ConnectionFormModalActions({ errors, warnings, @@ -138,6 +54,7 @@ export function ConnectionFormModalActions({ onSave, onSaveAndConnect, }: ConnectionFormModalActionsProps): React.ReactElement { + const saveAndConnectLabel = useConnectionFormSetting('saveAndConnectLabel'); return (
{warnings.length > 0 && ( @@ -168,23 +85,25 @@ export function ConnectionFormModalActions({ )} -
- -
+ {onSave && ( +
+ +
+ )}
diff --git a/packages/connection-form/src/components/connection-form.spec.tsx b/packages/connection-form/src/components/connection-form.spec.tsx index e915862dc51..0620a892e00 100644 --- a/packages/connection-form/src/components/connection-form.spec.tsx +++ b/packages/connection-form/src/components/connection-form.spec.tsx @@ -11,7 +11,6 @@ import { import { expect } from 'chai'; import type { PreferencesAccess } from 'compass-preferences-model'; import { createSandboxFromDefaultPreferences } from 'compass-preferences-model'; -import { PreferencesProvider } from 'compass-preferences-model/provider'; import ConnectionForm from './connection-form'; import type { ConnectionFormProps } from './connection-form'; import Sinon from 'sinon'; @@ -36,19 +35,16 @@ describe('ConnectionForm Component', function () { let preferences: PreferencesAccess; function renderForm(props: Partial = {}) { return render( - - - + ); } @@ -73,7 +69,7 @@ describe('ConnectionForm Component', function () { it('should render the connection string textbox', function () { renderForm(); - const textArea = screen.getByTestId('connectionString'); + const textArea = screen.getByTestId('connectionString'); expect(textArea).to.have.text('mongodb://pineapple:*****@localhost:27019/'); }); @@ -97,10 +93,8 @@ describe('ConnectionForm Component', function () { it('should render the toggle button in the off state for default connection', function () { renderForm({ initialConnectionInfo: DEFAULT_CONNECTION, - preferences: { - protectConnectionStringsForNewConnections: true, - protectConnectionStrings: false, - }, + protectConnectionStringsForNewConnections: true, + protectConnectionStrings: false, }); expect(screen.queryByTestId('toggle-edit-connection-string')).to @@ -114,10 +108,8 @@ describe('ConnectionForm Component', function () { it('should render the toggle button in the off state for existing connection', function () { renderForm({ - preferences: { - protectConnectionStringsForNewConnections: true, - protectConnectionStrings: false, - }, + protectConnectionStringsForNewConnections: true, + protectConnectionStrings: false, }); expect(screen.queryByTestId('toggle-edit-connection-string')).to .not.be.null; @@ -136,10 +128,8 @@ describe('ConnectionForm Component', function () { it('should render the toggle button in the off state for default connection', function () { renderForm({ initialConnectionInfo: DEFAULT_CONNECTION, - preferences: { - protectConnectionStringsForNewConnections: true, - protectConnectionStrings: true, - }, + protectConnectionStringsForNewConnections: true, + protectConnectionStrings: true, }); expect(screen.queryByTestId('toggle-edit-connection-string')).to .not.be.null; @@ -152,10 +142,8 @@ describe('ConnectionForm Component', function () { it('should not render the toggle button for existing connection', function () { renderForm({ - preferences: { - protectConnectionStringsForNewConnections: true, - protectConnectionStrings: true, - }, + protectConnectionStringsForNewConnections: true, + protectConnectionStrings: true, }); expect(screen.queryByTestId('toggle-edit-connection-string')).to .be.null; @@ -174,10 +162,8 @@ describe('ConnectionForm Component', function () { it('should render the toggle button in the on state for default connection', function () { renderForm({ initialConnectionInfo: DEFAULT_CONNECTION, - preferences: { - protectConnectionStringsForNewConnections: false, - protectConnectionStrings: false, - }, + protectConnectionStringsForNewConnections: false, + protectConnectionStrings: false, }); expect(screen.queryByTestId('toggle-edit-connection-string')).to .not.be.null; @@ -190,10 +176,8 @@ describe('ConnectionForm Component', function () { it('should render the toggle button in the off state for existing connection', function () { renderForm({ - preferences: { - protectConnectionStringsForNewConnections: false, - protectConnectionStrings: false, - }, + protectConnectionStringsForNewConnections: false, + protectConnectionStrings: false, }); expect(screen.queryByTestId('toggle-edit-connection-string')).to .not.be.null; @@ -212,10 +196,8 @@ describe('ConnectionForm Component', function () { it('should render the toggle button in the on state for default connection', function () { renderForm({ initialConnectionInfo: DEFAULT_CONNECTION, - preferences: { - protectConnectionStringsForNewConnections: false, - protectConnectionStrings: true, - }, + protectConnectionStringsForNewConnections: false, + protectConnectionStrings: true, }); expect(screen.queryByTestId('toggle-edit-connection-string')).to .not.be.null; @@ -228,10 +210,8 @@ describe('ConnectionForm Component', function () { it('should not render the toggle button for existing connection', function () { renderForm({ - preferences: { - protectConnectionStringsForNewConnections: false, - protectConnectionStrings: true, - }, + protectConnectionStringsForNewConnections: false, + protectConnectionStrings: true, }); expect(screen.queryByTestId('toggle-edit-connection-string')).to .be.null; @@ -246,9 +226,7 @@ describe('ConnectionForm Component', function () { context.skip('when preferences.showFavoriteActions === false', function () { it('should not render the favorite button', function () { renderForm({ - preferences: { - showFavoriteActions: false, - }, + showFavoriteActions: false, }); expect(screen.queryByText(favoriteText)).to.not.exist; }); @@ -388,10 +366,8 @@ describe('ConnectionForm Component', function () { }); renderForm({ initialConnectionInfo: DEFAULT_CONNECTION, - preferences: { - protectConnectionStringsForNewConnections: false, - protectConnectionStrings: false, - }, + protectConnectionStringsForNewConnections: false, + protectConnectionStrings: false, onCancel, }); }); @@ -417,9 +393,8 @@ describe('ConnectionForm Component', function () { describe('name input', function () { it('should sync with the href of the connection string unless it has been edited', async function () { - const connectionString = screen.getByTestId( - 'connectionString' - ) as HTMLInputElement; + const connectionString = + screen.getByTestId('connectionString'); userEvent.clear(connectionString); await waitFor(() => expect(connectionString.value).to.equal('')); @@ -430,19 +405,18 @@ describe('ConnectionForm Component', function () { expect(connectionString.value).to.equal('mongodb://myserver:27017/') ); - const personalizationName = screen.getByTestId( + const personalizationName = screen.getByTestId( 'personalization-name-input' - ) as HTMLInputElement; + ); expect(personalizationName.value).to.equal('myserver:27017'); }); it('should not sync with the href of the connection string when it has been edited', async function () { - const connectionString = screen.getByTestId( - 'connectionString' - ) as HTMLInputElement; - const personalizationName = screen.getByTestId( + const connectionString = + screen.getByTestId('connectionString'); + const personalizationName = screen.getByTestId( 'personalization-name-input' - ) as HTMLInputElement; + ); userEvent.clear(personalizationName); userEvent.clear(connectionString); diff --git a/packages/connection-form/src/components/connection-form.tsx b/packages/connection-form/src/components/connection-form.tsx index a0896967c72..ff5b278edc4 100644 --- a/packages/connection-form/src/components/connection-form.tsx +++ b/packages/connection-form/src/components/connection-form.tsx @@ -8,10 +8,6 @@ import { BannerVariant, Checkbox, Description, - FavoriteIcon, - Icon, - IconButton, - Overline, H3, spacing, Select, @@ -25,25 +21,20 @@ import { useDarkMode, } from '@mongodb-js/compass-components'; import { cloneDeep } from 'lodash'; -import { usePreference } from 'compass-preferences-model/provider'; import ConnectionStringInput from './connection-string-input'; import AdvancedConnectionOptions from './advanced-connection-options'; -import { - ConnectionFormModalActions, - LegacyConnectionFormActions, -} from './connection-form-actions'; +import { ConnectionFormModalActions } from './connection-form-actions'; import { useConnectForm, type ConnectionPersonalizationOptions, type UpdateConnectionFormField, } from '../hooks/use-connect-form'; import { validateConnectionOptionsErrors } from '../utils/validation'; -import SaveConnectionModal from './save-connection-modal'; -import type { ConnectionFormPreferences } from '../hooks/use-connect-form-preferences'; +import type { ConnectionFormSettings } from '../hooks/use-connect-form-settings'; import { - ConnectionFormPreferencesContext, - useConnectionFormPreference, -} from '../hooks/use-connect-form-preferences'; + ConnectionFormSettingsContext, + useConnectionFormSetting, +} from '../hooks/use-connect-form-settings'; import { useConnectionColor } from '../hooks/use-connection-color'; import FormHelp from './form-help/form-help'; @@ -125,22 +116,6 @@ const formFooterBorderLightModeStyles = css({ borderTop: `1px solid ${palette.gray.light2}`, }); -const favoriteButtonStyles = css({ - position: 'absolute', - top: -spacing[400], - right: 0, - cursor: 'pointer', - width: spacing[7], - height: spacing[7], -}); - -const favoriteButtonContentStyles = css({ - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - justifyContent: 'center', -}); - const headingWithHiddenButtonStyles = css({ button: { visibility: 'hidden', @@ -152,14 +127,6 @@ const headingWithHiddenButtonStyles = css({ }, }); -const editFavoriteButtonStyles = css({ - verticalAlign: 'text-top', -}); - -const favoriteButtonLabelStyles = css({ - paddingTop: spacing[1], -}); - const connectionStringErrorStyles = css({ marginBottom: spacing[3], }); @@ -243,9 +210,7 @@ function ConnectionPersonalizationForm({ updateConnectionFormField, personalizationOptions, }: ConnectionPersonalizationFormProps): React.ReactElement { - const showFavoriteActions = useConnectionFormPreference( - 'showFavoriteActions' - ); + const showFavoriteActions = useConnectionFormSetting('showFavoriteActions'); const onChangeName = useCallback( (ev: React.ChangeEvent) => { @@ -334,37 +299,32 @@ function ConnectionPersonalizationForm({ ); } -type ConnectionFormPropsWithoutPreferences = { +type ConnectionFormPropsWithoutSettings = { darkMode?: boolean; initialConnectionInfo: ConnectionInfo; connectionErrorMessage?: string | null; onCancel?: () => void; onConnectClicked?: (connectionInfo: ConnectionInfo) => void; onSaveAndConnectClicked?: (connectionInfo: ConnectionInfo) => void; - onSaveClicked: (connectionInfo: ConnectionInfo) => Promise; + onSaveClicked?: (connectionInfo: ConnectionInfo) => Promise; onAdvancedOptionsToggle?: (newState: boolean) => void; openSettingsModal?: (tab?: string) => void; }; -export type ConnectionFormProps = ConnectionFormPropsWithoutPreferences & { - preferences?: Partial; -}; +export type ConnectionFormProps = ConnectionFormPropsWithoutSettings & + Partial; function ConnectionForm({ initialConnectionInfo, connectionErrorMessage, - onConnectClicked, onSaveAndConnectClicked, onSaveClicked, onCancel, onAdvancedOptionsToggle, openSettingsModal, -}: ConnectionFormPropsWithoutPreferences): React.ReactElement { +}: ConnectionFormPropsWithoutSettings): React.ReactElement { const [advancedOpen, setAdvancedOpen] = useState(false); const isDarkMode = useDarkMode(); - const isMultiConnectionEnabled = usePreference( - 'enableMultipleConnectionSystem' - ); const onAdvancedChange = useCallback( (newState: boolean) => { @@ -377,7 +337,6 @@ function ConnectionForm({ const [ { enableEditingConnectionString: _enableEditingConnectionString, - isDirty, errors, warnings: _warnings, connectionOptions, @@ -387,17 +346,13 @@ function ConnectionForm({ { setEnableEditingConnectionString, updateConnectionFormField, setErrors }, ] = useConnectForm(initialConnectionInfo, connectionErrorMessage); - type SaveConnectionModalState = 'hidden' | 'save' | 'saveAndConnect'; - - const [saveConnectionModal, setSaveConnectionModal] = - useState('hidden'); const protectConnectionStrings = - !!useConnectionFormPreference('protectConnectionStrings') && + !!useConnectionFormSetting('protectConnectionStrings') && !allowEditingIfProtected; const enableEditingConnectionString = _enableEditingConnectionString && !protectConnectionStrings; - const forceConnectionOptions = useConnectionFormPreference( + const forceConnectionOptions = useConnectionFormSetting( 'forceConnectionOptions' ); const warnings = useMemo(() => { @@ -419,75 +374,43 @@ function ConnectionForm({ ); const getConnectionInfoToSave = useCallback( - (favoriteInfo?: ConnectionFavoriteOptions): ConnectionInfo => { - if (isMultiConnectionEnabled) { - return { - ...cloneDeep(initialConnectionInfo), - connectionOptions: cloneDeep(connectionOptions), - savedConnectionType: personalizationOptions.isFavorite - ? 'favorite' - : 'recent', - favorite: { - ...(favoriteInfo || {}), - name: personalizationOptions.name, - color: personalizationOptions.color, - }, - }; - } else { - return { - ...cloneDeep(initialConnectionInfo), - connectionOptions: cloneDeep(connectionOptions), - savedConnectionType: 'favorite', - favorite: { - name: '', - color: undefined, - ...favoriteInfo, - }, - }; - } - }, - [ - isMultiConnectionEnabled, - initialConnectionInfo, - connectionOptions, - personalizationOptions, - ] - ); - const onSubmitForm = useCallback( - (action: 'saveAndConnect' | 'connect') => { - // TODO(COMPASS-7906): cleanup - const updatedConnectionOptions = cloneDeep(connectionOptions); - // TODO: this method throws on malformed connection strings instead of - // returning errors - const formErrors = validateConnectionOptionsErrors( - updatedConnectionOptions - ); - if (formErrors.length) { - setErrors(formErrors); - return; - } - if (action === 'saveAndConnect') { - onSaveAndConnectClicked?.({ - ...initialConnectionInfo, - ...getConnectionInfoToSave(), - connectionOptions: updatedConnectionOptions, - }); - } else { - onConnectClicked?.({ - ...initialConnectionInfo, - connectionOptions: updatedConnectionOptions, - }); - } - }, - [ - initialConnectionInfo, - onSaveAndConnectClicked, - onConnectClicked, - setErrors, - connectionOptions, - getConnectionInfoToSave, - ] + (favoriteInfo?: ConnectionFavoriteOptions): ConnectionInfo => ({ + ...cloneDeep(initialConnectionInfo), + connectionOptions: cloneDeep(connectionOptions), + savedConnectionType: personalizationOptions.isFavorite + ? 'favorite' + : 'recent', + favorite: { + ...(favoriteInfo || {}), + name: personalizationOptions.name, + color: personalizationOptions.color, + }, + }), + [initialConnectionInfo, connectionOptions, personalizationOptions] ); + const onSubmitForm = useCallback(() => { + const updatedConnectionOptions = cloneDeep(connectionOptions); + // TODO: this method throws on malformed connection strings instead of + // returning errors + const formErrors = validateConnectionOptionsErrors( + updatedConnectionOptions + ); + if (formErrors.length) { + setErrors(formErrors); + return; + } + onSaveAndConnectClicked?.({ + ...initialConnectionInfo, + ...getConnectionInfoToSave(), + connectionOptions: updatedConnectionOptions, + }); + }, [ + initialConnectionInfo, + onSaveAndConnectClicked, + setErrors, + connectionOptions, + getConnectionInfoToSave, + ]); const callOnSaveConnectionClickedAndStoreErrors = useCallback( async (connectionInfo: ConnectionInfo): Promise => { @@ -507,13 +430,11 @@ function ConnectionForm({ [onSaveClicked, setErrors] ); - const showFavoriteActions = useConnectionFormPreference( - 'showFavoriteActions' + const showPersonalisationForm = useConnectionFormSetting( + 'showPersonalisationForm' ); - const showFooterBorder = !!isMultiConnectionEnabled; - - const showHelpCardsInForm = !!isMultiConnectionEnabled; + const showHelpCardsInForm = useConnectionFormSetting('showHelpCardsInForm'); return ( @@ -522,7 +443,7 @@ function ConnectionForm({ onSubmit={(e) => { // Prevent default html page refresh. e.preventDefault(); - onSubmitForm(isMultiConnectionEnabled ? 'saveAndConnect' : 'connect'); + onSubmitForm(); }} // Prevent default html tooltip popups. noValidate @@ -531,47 +452,10 @@ function ConnectionForm({

{initialConnectionInfo.favorite?.name ?? 'New Connection'} - {!isMultiConnectionEnabled && showFavoriteActions && ( - { - setSaveConnectionModal('save'); - }} - > - - - )}

- {!isMultiConnectionEnabled && 'Connect to a MongoDB deployment'} - {isMultiConnectionEnabled && 'Manage your connection settings'} + Manage your connection settings - - {!isMultiConnectionEnabled && showFavoriteActions && ( - { - setSaveConnectionModal('save'); - }} - > -
- - - FAVORITE - -
-
- )}
@@ -583,11 +467,7 @@ function ConnectionForm({ setEnableEditingConnectionString={ setEnableEditingConnectionString } - onSubmit={() => - onSubmitForm( - isMultiConnectionEnabled ? 'saveAndConnect' : 'connect' - ) - } + onSubmit={onSubmitForm} updateConnectionFormField={updateConnectionFormField} protectConnectionStrings={protectConnectionStrings} /> @@ -599,7 +479,7 @@ function ConnectionForm({ {connectionStringInvalidError.message} )} - {isMultiConnectionEnabled && ( + {showPersonalisationForm && (
- {isMultiConnectionEnabled && ( - + void callOnSaveConnectionClickedAndStoreErrors?.( getConnectionInfoToSave() - ) - } - onSaveAndConnect={() => onSubmitForm('saveAndConnect')} - /> - )} - {!isMultiConnectionEnabled && ( - { - if (initialConnectionInfo.favorite) { - void callOnSaveConnectionClickedAndStoreErrors({ - ...cloneDeep(initialConnectionInfo), - connectionOptions: cloneDeep(connectionOptions), - }); - } else { - setSaveConnectionModal('save'); - } - }} - onSaveAndConnectClicked={() => { - setSaveConnectionModal('saveAndConnect'); - }} - onConnectClicked={() => onSubmitForm('connect')} - /> - )} + )) + } + onSaveAndConnect={onSubmitForm} + />
- - {showFavoriteActions && ( - { - setSaveConnectionModal('hidden'); - }} - onSaveClicked={async (favoriteInfo: ConnectionFavoriteOptions) => { - setSaveConnectionModal('hidden'); - - const connectionInfo = getConnectionInfoToSave(favoriteInfo); - await callOnSaveConnectionClickedAndStoreErrors(connectionInfo); - - if (saveConnectionModal === 'saveAndConnect') { - // Connect to the newly created favorite - onSubmitForm('connect'); - } - }} - key={initialConnectionInfo.id} - initialFavoriteInfo={initialConnectionInfo.favorite} - /> - )}
); } -const ConnectionFormWithPreferences = ( - props: ConnectionFormPropsWithoutPreferences & { - preferences?: Partial; - } -) => { - const { preferences, ...rest } = props; +const ConnectionFormWithSettings: React.FunctionComponent< + ConnectionFormPropsWithoutSettings & Partial +> = ({ + showFavoriteActions, + showHelpCardsInForm, + showPersonalisationForm, + protectConnectionStrings, + forceConnectionOptions, + showKerberosPasswordField, + showOIDCDeviceAuthFlow, + enableOidc, + enableDebugUseCsfleSchemaMap, + protectConnectionStringsForNewConnections, + showOIDCAuth, + showKerberosAuth, + showCSFLE, + showProxySettings, + saveAndConnectLabel, + ...rest +}) => { + const value = useMemo( + () => ({ + showFavoriteActions, + showHelpCardsInForm, + showPersonalisationForm, + protectConnectionStrings, + forceConnectionOptions, + showKerberosPasswordField, + showOIDCDeviceAuthFlow, + enableOidc, + enableDebugUseCsfleSchemaMap, + protectConnectionStringsForNewConnections, + showOIDCAuth, + showKerberosAuth, + showCSFLE, + showProxySettings, + saveAndConnectLabel, + }), + [ + showFavoriteActions, + showHelpCardsInForm, + showPersonalisationForm, + protectConnectionStrings, + forceConnectionOptions, + showKerberosPasswordField, + showOIDCDeviceAuthFlow, + enableOidc, + enableDebugUseCsfleSchemaMap, + protectConnectionStringsForNewConnections, + showOIDCAuth, + showKerberosAuth, + showCSFLE, + showProxySettings, + saveAndConnectLabel, + ] + ); return ( - + - + ); }; -export default ConnectionFormWithPreferences; +export default ConnectionFormWithSettings; diff --git a/packages/connection-form/src/hooks/use-connect-form-preferences.tsx b/packages/connection-form/src/hooks/use-connect-form-settings.tsx similarity index 59% rename from packages/connection-form/src/hooks/use-connect-form-preferences.tsx rename to packages/connection-form/src/hooks/use-connect-form-settings.tsx index 0a2367841bf..c0803853253 100644 --- a/packages/connection-form/src/hooks/use-connect-form-preferences.tsx +++ b/packages/connection-form/src/hooks/use-connect-form-settings.tsx @@ -1,8 +1,9 @@ import { createContext, useContext } from 'react'; -// Not all of these preference map to Compass preferences. -export type ConnectionFormPreferences = { +export type ConnectionFormSettings = { showFavoriteActions: boolean; + showHelpCardsInForm: boolean; + showPersonalisationForm: boolean; protectConnectionStrings: boolean; forceConnectionOptions: [key: string, value: string][]; showKerberosPasswordField: boolean; @@ -14,10 +15,13 @@ export type ConnectionFormPreferences = { showKerberosAuth: boolean; showCSFLE: boolean; showProxySettings: boolean; + saveAndConnectLabel: string; }; -const defaultPreferences = { +const defaultSettings = { showFavoriteActions: true, + showPersonalisationForm: true, + showHelpCardsInForm: true, protectConnectionStrings: false, forceConnectionOptions: [], showKerberosPasswordField: false, @@ -29,18 +33,19 @@ const defaultPreferences = { showKerberosAuth: true, showCSFLE: true, showProxySettings: true, + saveAndConnectLabel: 'Connect', }; -export const ConnectionFormPreferencesContext = createContext< - Partial +export const ConnectionFormSettingsContext = createContext< + Partial >({}); -export const useConnectionFormPreference = < - K extends keyof ConnectionFormPreferences +export const useConnectionFormSetting = < + K extends keyof ConnectionFormSettings >( preferenceKey: K -): ConnectionFormPreferences[K] => { - const preferences = useContext(ConnectionFormPreferencesContext); +): ConnectionFormSettings[K] => { + const settings = useContext(ConnectionFormSettingsContext); - return preferences[preferenceKey] ?? defaultPreferences[preferenceKey]; + return settings[preferenceKey] ?? defaultSettings[preferenceKey]; }; diff --git a/packages/connection-form/src/hooks/use-connect-form.ts b/packages/connection-form/src/hooks/use-connect-form.ts index 6df2cad09d5..117e546265b 100644 --- a/packages/connection-form/src/hooks/use-connect-form.ts +++ b/packages/connection-form/src/hooks/use-connect-form.ts @@ -67,7 +67,7 @@ import { import type { UpdateOIDCAction } from '../utils/oidc-handler'; import { setAppNameParamIfMissing } from '../utils/set-app-name-if-missing'; import { applyForceConnectionOptions } from '../utils/force-connection-options'; -import { useConnectionFormPreference } from './use-connect-form-preferences'; +import { useConnectionFormSetting } from './use-connect-form-settings'; import ConnectionString from 'mongodb-connection-string-url'; export type ConnectionPersonalizationOptions = { @@ -723,9 +723,8 @@ export function useConnectForm( const initialFormState: ConnectFormState = { ...derivedFormState, enableEditingConnectionString: - !useConnectionFormPreference( - 'protectConnectionStringsForNewConnections' - ) && derivedFormState.enableEditingConnectionString, + !useConnectionFormSetting('protectConnectionStringsForNewConnections') && + derivedFormState.enableEditingConnectionString, }; const [state, dispatch] = useReducer(connectFormReducer, initialFormState); @@ -802,7 +801,7 @@ function setInitialState({ setErrors: (errors: ConnectionFormError[]) => void; dispatch: Dispatch; }) { - const protectConnectionStringsForNewConnections = useConnectionFormPreference( + const protectConnectionStringsForNewConnections = useConnectionFormSetting( 'protectConnectionStringsForNewConnections' ); useEffect(() => {