From 9b88991ffb75f587f641a4f1bfde8d84f064d24a Mon Sep 17 00:00:00 2001 From: labkey-nicka Date: Mon, 3 Aug 2026 12:46:38 -0700 Subject: [PATCH 1/7] Formsy: isShallowSame --- .../components/forms/formsy/Formsy.test.tsx | 51 ++++++++++++++++++- .../components/forms/formsy/utils.test.ts | 32 +++++++++++- .../internal/components/forms/formsy/utils.ts | 20 ++++++++ .../components/forms/formsy/withFormsy.tsx | 21 +++++++- 4 files changed, 120 insertions(+), 4 deletions(-) diff --git a/packages/components/src/internal/components/forms/formsy/Formsy.test.tsx b/packages/components/src/internal/components/forms/formsy/Formsy.test.tsx index 3a1ce27a63..787d776c92 100644 --- a/packages/components/src/internal/components/forms/formsy/Formsy.test.tsx +++ b/packages/components/src/internal/components/forms/formsy/Formsy.test.tsx @@ -1,7 +1,7 @@ // This file was originally derived from the "formsy-react" package, specifically, v2.3.2. // Credit: Christian Alfoni and the Formsy Authors // Repository: https://github.com/formsy/formsy-react/tree/0226fab133a25 -import React, { act, FC, memo, PropsWithChildren, useCallback, useRef, useState } from 'react'; +import React, { act, FC, memo, PropsWithChildren, useCallback, useMemo, useRef, useState } from 'react'; import { createPortal } from 'react-dom'; import { createEvent, fireEvent, render } from '@testing-library/react'; import { userEvent } from '@testing-library/user-event'; @@ -448,6 +448,55 @@ describe('Formsy', () => { }); }); + describe('validation messages', () => { + // Mirrors an input whose error message is enriched by data that only starts loading once the validation + // failure is known, so the message changes while the rules and the value stay put. + const AsyncMessageForm: FC = () => { + const [isRegistered, setIsRegistered] = useState(false); + const [canAssociate, setCanAssociate] = useState(false); + const validations = useMemo(() => ({ isNotRegistered: isRegistered }), [isRegistered]); + const validationErrors = useMemo( + () => ({ isNotRegistered: canAssociate ? 'Already registered. Associate?' : 'Already registered.' }), + [canAssociate] + ); + const onRegister = useCallback(() => setIsRegistered(true), []); + const onAssociate = useCallback(() => setCanAssociate(true), []); + + return ( + <> + + + +