From a7588b76001ed2690063aabbe9edd60778cc27b9 Mon Sep 17 00:00:00 2001
From: Tymoteusz Czech <2625371+Tymek@users.noreply.github.com>
Date: Thu, 10 Oct 2024 19:57:24 +0200
Subject: [PATCH] feat($env): api integration
---
.../OrderEnvironments.test.tsx | 42 ++++++++++++++++
.../OrderEnvironments/OrderEnvironments.tsx | 31 ++++++++++--
.../OrderEnvironmentsDialog.tsx | 48 ++++++++++++-------
3 files changed, 100 insertions(+), 21 deletions(-)
create mode 100644 frontend/src/component/environments/EnvironmentTable/OrderEnvironments/OrderEnvironments.test.tsx
diff --git a/frontend/src/component/environments/EnvironmentTable/OrderEnvironments/OrderEnvironments.test.tsx b/frontend/src/component/environments/EnvironmentTable/OrderEnvironments/OrderEnvironments.test.tsx
new file mode 100644
index 000000000000..49e7d9513192
--- /dev/null
+++ b/frontend/src/component/environments/EnvironmentTable/OrderEnvironments/OrderEnvironments.test.tsx
@@ -0,0 +1,42 @@
+import { screen, fireEvent, waitFor } from '@testing-library/react';
+import { render } from 'utils/testRenderer';
+import { OrderEnvironments } from './OrderEnvironments';
+import { testServerRoute, testServerSetup } from 'utils/testServer';
+
+const server = testServerSetup();
+
+const setupServerRoutes = (changeRequestsEnabled = true) => {
+ testServerRoute(server, '/api/admin/ui-config', {
+ environment: 'Pro',
+ flags: {
+ purchaseAdditionalEnvironments: true,
+ },
+ });
+};
+
+describe('OrderEnvironmentsDialog Component', () => {
+ test('should show error if environment name is empty', async () => {
+ setupServerRoutes();
+ render();
+
+ await waitFor(async () => {
+ const openDialogButton = await screen.queryByRole('button', {
+ name: /view pricing/i,
+ });
+ expect(openDialogButton).toBeInTheDocument();
+ fireEvent.click(openDialogButton!);
+ });
+
+ const checkbox = screen.getByRole('checkbox', {
+ name: /i understand adding environments/i,
+ });
+ fireEvent.click(checkbox);
+
+ const submitButton = screen.getByRole('button', { name: /order/i });
+ fireEvent.click(submitButton);
+
+ expect(
+ screen.getByText(/environment name is required/i),
+ ).toBeInTheDocument();
+ });
+});
diff --git a/frontend/src/component/environments/EnvironmentTable/OrderEnvironments/OrderEnvironments.tsx b/frontend/src/component/environments/EnvironmentTable/OrderEnvironments/OrderEnvironments.tsx
index c03cc1234209..5111b72e99f7 100644
--- a/frontend/src/component/environments/EnvironmentTable/OrderEnvironments/OrderEnvironments.tsx
+++ b/frontend/src/component/environments/EnvironmentTable/OrderEnvironments/OrderEnvironments.tsx
@@ -4,6 +4,8 @@ import { useUiFlag } from 'hooks/useUiFlag';
import { PurchasableFeature } from './PurchasableFeature/PurchasableFeature';
import { OrderEnvironmentsDialog } from './OrderEnvironmentsDialog/OrderEnvironmentsDialog';
import { OrderEnvironmentsConfirmation } from './OrderEnvironmentsConfirmation/OrderEnvironmentsConfirmation';
+import { useFormErrors } from 'hooks/useFormErrors';
+import useToast from 'hooks/useToast';
type OrderEnvironmentsProps = {};
@@ -17,18 +19,36 @@ export const OrderEnvironments: FC = () => {
const isPurchaseAdditionalEnvironmentsEnabled = useUiFlag(
'purchaseAdditionalEnvironments',
);
+ const errors = useFormErrors();
+ const { setToastData, setToastApiError } = useToast();
if (!isPro() || !isPurchaseAdditionalEnvironmentsEnabled) {
return null;
}
const onSubmit = (environments: string[]) => {
- setPurchaseDialogOpen(false);
- // TODO: API call
- setConfirmationState({
- isOpen: true,
- environmentsCount: environments.length,
+ let hasErrors = false;
+ environments.forEach((environment, index) => {
+ const field = `environment-${index}`;
+ if (environment.trim() === '') {
+ errors.setFormError(field, 'Environment name is required');
+ hasErrors = true;
+ } else {
+ errors.removeFormError(field);
+ }
});
+
+ if (hasErrors) {
+ return;
+ } else {
+ // TODO: API call
+
+ setPurchaseDialogOpen(false);
+ setConfirmationState({
+ isOpen: true,
+ environmentsCount: environments.length,
+ });
+ }
};
return (
@@ -42,6 +62,7 @@ export const OrderEnvironments: FC = () => {
open={purchaseDialogOpen}
onClose={() => setPurchaseDialogOpen(false)}
onSubmit={onSubmit}
+ errors={errors}
/>
void;
onSubmit: (environments: string[]) => void;
+ errors?: IFormErrors;
};
const StyledDialog = styled(Dialog)(({ theme }) => ({
@@ -74,10 +76,13 @@ export const OrderEnvironmentsDialog: FC = ({
open,
onClose,
onSubmit,
+ errors,
}) => {
const [selectedOption, setSelectedOption] = useState(OPTIONS[0]);
const [costCheckboxChecked, setCostCheckboxChecked] = useState(false);
- const [environmentNames, setEnvironmentNames] = useState([]);
+ const [environmentNames, setEnvironmentNames] = useState(['']);
+
+ console.log({ environmentNames });
return (
@@ -133,7 +138,10 @@ export const OrderEnvironmentsDialog: FC = ({
const value = Number.parseInt(option, 10);
setSelectedOption(value);
setEnvironmentNames((names) =>
- names.slice(0, value),
+ [...names, ...Array(value).fill('')].slice(
+ 0,
+ value,
+ ),
);
}}
/>
@@ -143,20 +151,28 @@ export const OrderEnvironmentsDialog: FC = ({
How would you like the environment
{selectedOption > 1 ? 's' : ''} to be named?
- {[...Array(selectedOption)].map((_, i) => (
- {
- setEnvironmentNames((names) => {
- const newValues = [...names];
- newValues[i] = event.target.value;
- return newValues;
- });
- }}
- />
- ))}
+ {[...Array(selectedOption)].map((_, i) => {
+ const error = errors?.getFormError(
+ `environment-${i}`,
+ );
+
+ return (
+ {
+ setEnvironmentNames((names) => {
+ const newValues = [...names];
+ newValues[i] = event.target.value;
+ return newValues;
+ });
+ }}
+ error={Boolean(error)}
+ errorText={error}
+ />
+ );
+ })}