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 0000000000..c893a336ea
--- /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 7c842ffac4..99b93248cf 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 23dfd58dbe..95fa0b6fd2 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 925d35be86..71ed62ce9b 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,