From 963d051632bea12fa097bf1ce3687863c1fad6db Mon Sep 17 00:00:00 2001 From: Mateusz Kwasniewski Date: Fri, 5 Jul 2024 13:03:51 +0200 Subject: [PATCH] feat: Limit environments component (#7548) --- .../CreateEnvironment.test.tsx | 57 +++++++++++++++++++ .../CreateEnvironment/CreateEnvironment.tsx | 23 +++++++- .../EnvironmentForm/EnvironmentForm.tsx | 15 ++++- .../FeatureOverviewEnvironment.test.tsx | 4 -- 4 files changed, 92 insertions(+), 7 deletions(-) create mode 100644 frontend/src/component/environments/CreateEnvironment/CreateEnvironment.test.tsx diff --git a/frontend/src/component/environments/CreateEnvironment/CreateEnvironment.test.tsx b/frontend/src/component/environments/CreateEnvironment/CreateEnvironment.test.tsx new file mode 100644 index 000000000000..c893a336ea15 --- /dev/null +++ b/frontend/src/component/environments/CreateEnvironment/CreateEnvironment.test.tsx @@ -0,0 +1,57 @@ +import { screen } from '@testing-library/react'; +import { render } from 'utils/testRenderer'; +import { testServerRoute, testServerSetup } from '../../../utils/testServer'; +import CreateEnvironment from './CreateEnvironment'; +import { ADMIN } from '../../providers/AccessProvider/permissions'; + +const server = testServerSetup(); + +const setupApi = ({ + resourceLimits, + limit, + environments, +}: { resourceLimits: boolean; limit: number; environments: number }) => { + testServerRoute(server, '/api/admin/ui-config', { + flags: { + resourceLimits, + }, + resourceLimits: { + environments: limit, + }, + }); + + testServerRoute(server, '/api/admin/environments', { + environments: [...Array(environments).keys()].map((i) => ({ + name: `environment${i}`, + })), + }); +}; + +test('show limit reached info', async () => { + setupApi({ environments: 1, limit: 1, resourceLimits: true }); + render(, { permissions: [{ permission: ADMIN }] }); + + await screen.findByText('You have reached the limit for environments'); + const createButton = await screen.findByText('Create environment', { + selector: 'button', + }); + expect(createButton).toBeDisabled(); +}); + +test('show approaching limit info', async () => { + setupApi({ environments: 9, limit: 10, resourceLimits: true }); + render(, { permissions: [{ permission: ADMIN }] }); + + await screen.findByText('You are nearing the limit for environments'); + const createButton = await screen.findByText('Create environment', { + selector: 'button', + }); + expect(createButton).toBeEnabled(); +}); + +test('show limit reached info - no resource limits component', async () => { + setupApi({ environments: 1, limit: 1, resourceLimits: false }); + render(); + + await screen.findByText('Go back'); +}); diff --git a/frontend/src/component/environments/CreateEnvironment/CreateEnvironment.tsx b/frontend/src/component/environments/CreateEnvironment/CreateEnvironment.tsx index 7c842ffac40c..99b93248cfcf 100644 --- a/frontend/src/component/environments/CreateEnvironment/CreateEnvironment.tsx +++ b/frontend/src/component/environments/CreateEnvironment/CreateEnvironment.tsx @@ -16,10 +16,13 @@ import { ADMIN } from 'component/providers/AccessProvider/permissions'; import { PageHeader } from 'component/common/PageHeader/PageHeader'; import { formatUnknownError } from 'utils/formatUnknownError'; import { GO_BACK } from 'constants/navigate'; +import { Limit } from 'component/common/Limit/Limit'; +import { useUiFlag } from 'hooks/useUiFlag'; const CreateEnvironment = () => { const { setToastApiError, setToastData } = useToast(); const { uiConfig } = useUiConfig(); + const resourceLimitsEnabled = useUiFlag('resourceLimits'); const environmentLimit = uiConfig.resourceLimits.environments; const navigate = useNavigate(); const { environments } = useEnvironments(); @@ -71,7 +74,7 @@ const CreateEnvironment = () => { return ( { setType={setType} mode='Create' clearErrors={clearErrors} + Limit={ + + } + /> + } > - + } diff --git a/frontend/src/component/environments/EnvironmentForm/EnvironmentForm.tsx b/frontend/src/component/environments/EnvironmentForm/EnvironmentForm.tsx index 23dfd58dbe79..95fa0b6fd296 100644 --- a/frontend/src/component/environments/EnvironmentForm/EnvironmentForm.tsx +++ b/frontend/src/component/environments/EnvironmentForm/EnvironmentForm.tsx @@ -1,4 +1,4 @@ -import { Button, styled } from '@mui/material'; +import { Box, Button, styled } from '@mui/material'; import type React from 'react'; import Input from 'component/common/Input/Input'; import EnvironmentTypeSelector from './EnvironmentTypeSelector/EnvironmentTypeSelector'; @@ -16,6 +16,7 @@ interface IEnvironmentForm { mode: 'Create' | 'Edit'; clearErrors: () => void; children?: React.ReactNode; + Limit?: React.ReactNode; } const StyledForm = styled('form')({ @@ -52,6 +53,14 @@ const StyledCancelButton = styled(Button)(({ theme }) => ({ marginLeft: theme.spacing(3), })); +const LimitContainer = styled(Box)(({ theme }) => ({ + flex: 1, + display: 'flex', + alignItems: 'flex-end', + marginTop: theme.spacing(3), + marginBottom: theme.spacing(3), +})); + const EnvironmentForm: React.FC = ({ children, handleSubmit, @@ -64,6 +73,7 @@ const EnvironmentForm: React.FC = ({ errors, mode, clearErrors, + Limit, }) => { return ( @@ -93,6 +103,9 @@ const EnvironmentForm: React.FC = ({ value={type} /> + + {Limit} + {children} diff --git a/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/FeatureOverviewEnvironment.test.tsx b/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/FeatureOverviewEnvironment.test.tsx index 925d35be86da..71ed62ce9b88 100644 --- a/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/FeatureOverviewEnvironment.test.tsx +++ b/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/FeatureOverviewEnvironment.test.tsx @@ -3,11 +3,7 @@ import { render } from 'utils/testRenderer'; import FeatureOverviewEnvironment from './FeatureOverviewEnvironment'; import { Route, Routes } from 'react-router-dom'; import { CREATE_FEATURE_STRATEGY } from 'component/providers/AccessProvider/permissions'; -import type { IFeatureStrategy } from 'interfaces/strategy'; -const strategy = { - name: 'default', -} as IFeatureStrategy; const environmentWithoutStrategies = { name: 'production', enabled: true,