diff --git a/src/core/client/admin/routes/Configure/sections/General/FlairBadgeConfigContainer.tsx b/src/core/client/admin/routes/Configure/sections/General/FlairBadgeConfigContainer.tsx index c21ab87307..2f7444d8dc 100644 --- a/src/core/client/admin/routes/Configure/sections/General/FlairBadgeConfigContainer.tsx +++ b/src/core/client/admin/routes/Configure/sections/General/FlairBadgeConfigContainer.tsx @@ -6,7 +6,7 @@ import { graphql } from "react-relay"; import { colorFromMeta } from "coral-framework/lib/form"; import { ExternalLink } from "coral-framework/lib/i18n/components"; import { useMutation, withFragmentContainer } from "coral-framework/lib/relay"; -import { validateImageURL } from "coral-framework/lib/validation"; +import { validateImageURLFunc } from "coral-framework/lib/validation"; import { AddIcon, BinIcon, ButtonSvgIcon } from "coral-ui/components/icons"; import { Button, @@ -56,9 +56,11 @@ const FlairBadgeConfigContainer: FunctionComponent = ({ }) => { const addFlairBadge = useMutation(CreateFlairBadgeMutation); const deleteFlairBadge = useMutation(DeleteFlairBadgeMutation); + const [flairBadgeNameInput, setFlairBadgeNameInput] = useState(""); const [flairBadgeURLInput, setFlairBadgeURLInput] = useState(""); const [submitError, setSubmitError] = useState(null); + const onSubmit = useCallback(async () => { try { await addFlairBadge({ @@ -71,21 +73,24 @@ const FlairBadgeConfigContainer: FunctionComponent = ({ setSubmitError(e.message); } }, [addFlairBadge, flairBadgeURLInput, flairBadgeNameInput]); + const onDelete = useCallback( async (name: string) => { await deleteFlairBadge({ name }); }, [deleteFlairBadge] ); - const validFlairURL = useCallback( - (values: string) => { - const nameInvalid = - !flairBadgeNameInput || flairBadgeNameInput.length === 0; - const urlValidation = validateImageURL(flairBadgeURLInput, values); - return !nameInvalid && !(urlValidation === undefined); + + const validFlairInput = useCallback( + (value: string) => { + const nameIsValid = + flairBadgeNameInput && flairBadgeNameInput.length !== 0; + const urlValidationResult = validateImageURLFunc(flairBadgeURLInput); + return nameIsValid && urlValidationResult; }, [flairBadgeURLInput, flairBadgeNameInput] ); + return ( = ({ = ({ = ({ className={styles.addButton} size="large" onClick={() => onSubmit()} - disabled={validFlairURL(flairBadgeURLInput)} + disabled={!validFlairInput(flairBadgeURLInput)} > Add diff --git a/src/core/client/admin/test/configure/general.spec.tsx b/src/core/client/admin/test/configure/general.spec.tsx index cda968ea89..321b9eacaf 100644 --- a/src/core/client/admin/test/configure/general.spec.tsx +++ b/src/core/client/admin/test/configure/general.spec.tsx @@ -640,6 +640,7 @@ it("enable, add, and delete custom flair badges", async () => { const resolvers = createResolversStub({ Mutation: { createFlairBadge: ({ variables }) => { + expectAndFail(variables.name).toEqual("subscriber"); expectAndFail(variables.url).toEqual( "https://www.example.com/image.jpg" ); @@ -649,7 +650,7 @@ it("enable, add, and delete custom flair badges", async () => { flairBadgesEnabled: true, badges: [ { - name: variables.name, + name: "subscriber", url: "https://www.example.com/image.jpg", }, ], @@ -711,8 +712,17 @@ it("enable, add, and delete custom flair badges", async () => { ) ).toBeVisible(); + // Add URL button should still be disabled while we have a name but are still missing a url + const flairNameInput = within(customFlairBadgeConfig).getByTestId( + "flairBadgeNameInput" + ); + userEvent.type(flairNameInput, "subscriber"); + expect(addURLButton).toBeDisabled(); + // Add URL button should still be disabled when entering url that's not valid image url yet - const flairURLInput = within(customFlairBadgeConfig).getByRole("textbox"); + const flairURLInput = within(customFlairBadgeConfig).getByTestId( + "flairBadgeURLInput" + ); userEvent.type(flairURLInput, "https://www.example.com"); expect(addURLButton).toBeDisabled(); diff --git a/src/core/client/admin/test/fixtures.ts b/src/core/client/admin/test/fixtures.ts index 95635e3f7a..0eb008e38d 100644 --- a/src/core/client/admin/test/fixtures.ts +++ b/src/core/client/admin/test/fixtures.ts @@ -225,6 +225,10 @@ export const settings = createFixture({ embeddedComments: { allowReplies: true, }, + flairBadges: { + flairBadgesEnabled: false, + badges: [], + }, }); export const settingsWithMultisite = createFixture( diff --git a/src/core/client/framework/lib/validation.tsx b/src/core/client/framework/lib/validation.tsx index 0a3056af8b..f94a7818c6 100644 --- a/src/core/client/framework/lib/validation.tsx +++ b/src/core/client/framework/lib/validation.tsx @@ -97,7 +97,7 @@ export const validateUsernameCharacters = createValidator( INVALID_CHARACTERS() ); -export const validateImageURL = createValidator((v) => { +export const validateImageURLFunc = (v: any) => { if (!v || typeof v !== "string" || !URL_REGEX.test(v)) { return false; } @@ -108,7 +108,12 @@ export const validateImageURL = createValidator((v) => { } catch (err) { return false; } -}, INVALID_MEDIA_URL()); +}; + +export const validateImageURL = createValidator( + validateImageURLFunc, + INVALID_MEDIA_URL() +); /** * validateURL is a Validator that checks that the URL only contains valid characters.