From 8a8e7b19af22e38c4e09a6c3943451e186b5d4d6 Mon Sep 17 00:00:00 2001 From: Thomas Kosiewski Date: Mon, 13 Jan 2025 17:54:21 +0100 Subject: [PATCH] fix(site): validate group name before submitting to the backend (#16115) --- .gitignore | 1 + .../pages/GroupsPage/CreateGroupPageView.stories.tsx | 11 +++++++++++ site/src/pages/GroupsPage/CreateGroupPageView.tsx | 11 +++++++++-- .../GroupsPage/CreateGroupPageView.stories.tsx | 10 ++++++++++ .../GroupsPage/CreateGroupPageView.tsx | 11 +++++++++-- 5 files changed, 40 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 16607eacaa..0316611195 100644 --- a/.gitignore +++ b/.gitignore @@ -54,6 +54,7 @@ site/stats/ # direnv .envrc +.direnv *.test # Loadtesting diff --git a/site/src/pages/GroupsPage/CreateGroupPageView.stories.tsx b/site/src/pages/GroupsPage/CreateGroupPageView.stories.tsx index d6b3dbdb57..735c4160c9 100644 --- a/site/src/pages/GroupsPage/CreateGroupPageView.stories.tsx +++ b/site/src/pages/GroupsPage/CreateGroupPageView.stories.tsx @@ -1,4 +1,5 @@ import type { Meta, StoryObj } from "@storybook/react"; +import { userEvent, within } from "@storybook/test"; import { mockApiError } from "testHelpers/entities"; import { CreateGroupPageView } from "./CreateGroupPageView"; @@ -21,3 +22,13 @@ export const WithError: Story = { initialTouched: { name: true }, }, }; + +export const InvalidName: Story = { + play: async ({ canvasElement }) => { + const user = userEvent.setup(); + const body = within(canvasElement.ownerDocument.body); + const input = await body.findByLabelText("Name"); + await user.type(input, "$om3 !nv@lid Name"); + input.blur(); + }, +}; diff --git a/site/src/pages/GroupsPage/CreateGroupPageView.tsx b/site/src/pages/GroupsPage/CreateGroupPageView.tsx index fe2ed5158f..e1432d78e2 100644 --- a/site/src/pages/GroupsPage/CreateGroupPageView.tsx +++ b/site/src/pages/GroupsPage/CreateGroupPageView.tsx @@ -12,11 +12,15 @@ import { Stack } from "components/Stack/Stack"; import { type FormikTouched, useFormik } from "formik"; import type { FC } from "react"; import { useNavigate } from "react-router-dom"; -import { getFormHelpers, onChangeTrimmed } from "utils/formUtils"; +import { + getFormHelpers, + nameValidator, + onChangeTrimmed, +} from "utils/formUtils"; import * as Yup from "yup"; const validationSchema = Yup.object({ - name: Yup.string().required().label("Name"), + name: nameValidator("Name"), }); export type CreateGroupPageViewProps = { @@ -62,6 +66,8 @@ export const CreateGroupPageView: FC = ({ autoFocus fullWidth label="Name" + onChange={onChangeTrimmed(form)} + autoComplete="name" /> = ({ })} fullWidth label="Display Name" + autoComplete="display_name" /> { + const user = userEvent.setup(); + const body = within(canvasElement.ownerDocument.body); + const input = await body.findByLabelText("Name"); + await user.type(input, "$om3 !nv@lid Name"); + input.blur(); + }, +}; diff --git a/site/src/pages/ManagementSettingsPage/GroupsPage/CreateGroupPageView.tsx b/site/src/pages/ManagementSettingsPage/GroupsPage/CreateGroupPageView.tsx index 050a428909..3f695020d2 100644 --- a/site/src/pages/ManagementSettingsPage/GroupsPage/CreateGroupPageView.tsx +++ b/site/src/pages/ManagementSettingsPage/GroupsPage/CreateGroupPageView.tsx @@ -15,11 +15,15 @@ import { Spinner } from "components/Spinner/Spinner"; import { useFormik } from "formik"; import type { FC } from "react"; import { useNavigate } from "react-router-dom"; -import { getFormHelpers, onChangeTrimmed } from "utils/formUtils"; +import { + getFormHelpers, + nameValidator, + onChangeTrimmed, +} from "utils/formUtils"; import * as Yup from "yup"; const validationSchema = Yup.object({ - name: Yup.string().required().label("Name"), + name: nameValidator("Name"), }); export type CreateGroupPageViewProps = { @@ -69,6 +73,8 @@ export const CreateGroupPageView: FC = ({ autoFocus fullWidth label="Name" + onChange={onChangeTrimmed(form)} + autoComplete="name" /> = ({ })} fullWidth label="Display Name" + autoComplete="display_name" />