diff --git a/packages/manager/.changeset/pr-10909-tests-1725903174019.md b/packages/manager/.changeset/pr-10909-tests-1725903174019.md new file mode 100644 index 00000000000..3cf118d08bc --- /dev/null +++ b/packages/manager/.changeset/pr-10909-tests-1725903174019.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Tests +--- + +Add unit tests for AttachVolumeDrawer component ([#10909](https://github.com/linode/manager/pull/10909)) diff --git a/packages/manager/.changeset/pr-10909-upcoming-features-1725903122030.md b/packages/manager/.changeset/pr-10909-upcoming-features-1725903122030.md new file mode 100644 index 00000000000..5d3e9651650 --- /dev/null +++ b/packages/manager/.changeset/pr-10909-upcoming-features-1725903122030.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Upcoming Features +--- + +Add 'Encrypt Volume' checkbox in Attach Volume drawer ([#10909](https://github.com/linode/manager/pull/10909)) diff --git a/packages/manager/src/components/Encryption/constants.tsx b/packages/manager/src/components/Encryption/constants.tsx index 0b49c80e40d..4f44f4fd100 100644 --- a/packages/manager/src/components/Encryption/constants.tsx +++ b/packages/manager/src/components/Encryption/constants.tsx @@ -103,7 +103,7 @@ export const BLOCK_STORAGE_USER_SIDE_ENCRYPTION_CAVEAT = 'User-side encryption on top of encryption-enabled volumes is discouraged at this time, as it could severely impact your volume performance.'; export const BLOCK_STORAGE_ENCRYPTION_SETTING_IMMUTABLE_COPY = - 'The encryption setting cannot be changed after creation.'; + 'The encryption setting cannot be modified after a volume has been created.'; export const BLOCK_STORAGE_CLONING_INHERITANCE_CAVEAT = 'Encryption is inherited from the source volume and cannot be changed when cloning volumes.'; diff --git a/packages/manager/src/features/Volumes/AttachVolumeDrawer.test.tsx b/packages/manager/src/features/Volumes/AttachVolumeDrawer.test.tsx new file mode 100644 index 00000000000..0e52af786d5 --- /dev/null +++ b/packages/manager/src/features/Volumes/AttachVolumeDrawer.test.tsx @@ -0,0 +1,83 @@ +import { waitFor } from '@testing-library/react'; +import * as React from 'react'; + +import { accountFactory, volumeFactory } from 'src/factories'; +import { HttpResponse, http, server } from 'src/mocks/testServer'; +import { renderWithTheme } from 'src/utilities/testHelpers'; + +import { AttachVolumeDrawer } from './AttachVolumeDrawer'; + +const accountEndpoint = '*/v4/account'; +const encryptionLabelText = 'Encrypt Volume'; + +describe('AttachVolumeDrawer', () => { + /* @TODO BSE: Remove feature flagging/conditionality once BSE is fully rolled out */ + + it('should display a disabled checkbox for volume encryption if the user has the account capability and the feature flag is on', async () => { + const volume = volumeFactory.build(); + + server.use( + http.get(accountEndpoint, () => { + return HttpResponse.json( + accountFactory.build({ capabilities: ['Block Storage Encryption'] }) + ); + }) + ); + + const { getByLabelText } = renderWithTheme( + , + { + flags: { blockStorageEncryption: true }, + } + ); + + await waitFor(() => { + expect(getByLabelText(encryptionLabelText)).not.toBeNull(); + expect(getByLabelText(encryptionLabelText)).toBeDisabled(); + }); + }); + + it('should not display a checkbox for volume encryption if the user has the account capability but the feature flag is off', async () => { + const volume = volumeFactory.build(); + + server.use( + http.get(accountEndpoint, () => { + return HttpResponse.json( + accountFactory.build({ capabilities: ['Block Storage Encryption'] }) + ); + }) + ); + + const { queryByRole } = renderWithTheme( + , + { + flags: { blockStorageEncryption: false }, + } + ); + + await waitFor(() => { + expect(queryByRole('checkbox')).not.toBeInTheDocument(); + }); + }); + + it('should not display a checkbox for volume encryption if the feature flag is on but the user lacks the account capability', async () => { + const volume = volumeFactory.build(); + + server.use( + http.get(accountEndpoint, () => { + return HttpResponse.json(accountFactory.build({ capabilities: [] })); + }) + ); + + const { queryByRole } = renderWithTheme( + , + { + flags: { blockStorageEncryption: true }, + } + ); + + await waitFor(() => { + expect(queryByRole('checkbox')).not.toBeInTheDocument(); + }); + }); +}); diff --git a/packages/manager/src/features/Volumes/AttachVolumeDrawer.tsx b/packages/manager/src/features/Volumes/AttachVolumeDrawer.tsx index 0204a22f430..9fa0305e7eb 100644 --- a/packages/manager/src/features/Volumes/AttachVolumeDrawer.tsx +++ b/packages/manager/src/features/Volumes/AttachVolumeDrawer.tsx @@ -1,4 +1,3 @@ -import { Volume } from '@linode/api-v4'; import { styled } from '@mui/material/styles'; import { useFormik } from 'formik'; import { useSnackbar } from 'notistack'; @@ -6,7 +5,11 @@ import * as React from 'react'; import { number, object } from 'yup'; import { ActionsPanel } from 'src/components/ActionsPanel/ActionsPanel'; +import { Box } from 'src/components/Box'; +import { Checkbox } from 'src/components/Checkbox'; import { Drawer } from 'src/components/Drawer'; +import { BLOCK_STORAGE_ENCRYPTION_SETTING_IMMUTABLE_COPY } from 'src/components/Encryption/constants'; +import { useIsBlockStorageEncryptionFeatureEnabled } from 'src/components/Encryption/utils'; import { FormHelperText } from 'src/components/FormHelperText'; import { Notice } from 'src/components/Notice/Notice'; import { LinodeSelect } from 'src/features/Linodes/LinodeSelect/LinodeSelect'; @@ -17,6 +20,8 @@ import { getAPIErrorFor } from 'src/utilities/getAPIErrorFor'; import { ConfigSelect } from './VolumeDrawer/ConfigSelect'; +import type { Volume } from '@linode/api-v4'; + interface Props { onClose: () => void; open: boolean; @@ -43,6 +48,10 @@ export const AttachVolumeDrawer = React.memo((props: Props) => { const { error, mutateAsync: attachVolume } = useAttachVolumeMutation(); + const { + isBlockStorageEncryptionFeatureEnabled, + } = useIsBlockStorageEncryptionFeatureEnabled(); + const formik = useFormik({ initialValues: { config_id: -1, linode_id: -1 }, async onSubmit(values) { @@ -142,7 +151,21 @@ export const AttachVolumeDrawer = React.memo((props: Props) => { onBlur={() => null} value={formik.values.config_id} /> - + {isBlockStorageEncryptionFeatureEnabled && ( + + + + )}