From 96e0be26d8e4502068ce2046a8131b65336a6882 Mon Sep 17 00:00:00 2001 From: Mikhail Shatikhin Date: Thu, 16 May 2024 14:40:28 +0500 Subject: [PATCH 1/4] fix: when immediate validation, show error always --- .../react-ui-validations/src/ValidationWrapperInternal.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/react-ui-validations/src/ValidationWrapperInternal.tsx b/packages/react-ui-validations/src/ValidationWrapperInternal.tsx index 399213e8546..7e1ffd01003 100644 --- a/packages/react-ui-validations/src/ValidationWrapperInternal.tsx +++ b/packages/react-ui-validations/src/ValidationWrapperInternal.tsx @@ -110,11 +110,12 @@ export class ValidationWrapperInternal extends React.Component< const { children, 'data-tid': dataTid } = this.props; const { validation } = this.state; + const immediate = validation?.behaviour === 'immediate'; let clonedChild: React.ReactElement = children ? ( React.cloneElement(children, { ref: this.customRef, - error: !this.isChanging && getLevel(validation) === 'error', - warning: !this.isChanging && getLevel(validation) === 'warning', + error: (!this.isChanging || immediate) && getLevel(validation) === 'error', + warning: (!this.isChanging || immediate) && getLevel(validation) === 'warning', onBlur: (...args: any[]) => { this.handleBlur(); if (children.props && children.props.onBlur) { From 2a104b181e3cd7fee266bd34f083f1c79f46499c Mon Sep 17 00:00:00 2001 From: Mikhail Shatikhin Date: Thu, 16 May 2024 15:13:15 +0500 Subject: [PATCH 2/4] chore: update .net version selenium validation --- .gitignore | 2 ++ .../selenium-tests/Common.DotSettings | 1 + .../selenium-tests/ValidationTests/App.config | 14 +++++++++++++ .../ValidationTests/ValidationTests.csproj | 9 ++++++--- .../ValidationTests/packages.config | 20 +++++++++---------- 5 files changed, 33 insertions(+), 13 deletions(-) create mode 100644 packages/react-ui-validations/selenium-tests/ValidationTests/App.config diff --git a/.gitignore b/.gitignore index d7bb8fd4309..e6f0e9e985e 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,5 @@ browsers/ .scannerwork /packages/react-ui-validations/.creevey/report /packages/react-ui-validations/.storybook/build/ + +.vs diff --git a/packages/react-ui-validations/selenium-tests/Common.DotSettings b/packages/react-ui-validations/selenium-tests/Common.DotSettings index 673a80936f7..d5b403cc521 100644 --- a/packages/react-ui-validations/selenium-tests/Common.DotSettings +++ b/packages/react-ui-validations/selenium-tests/Common.DotSettings @@ -170,6 +170,7 @@ True True True + True True True True diff --git a/packages/react-ui-validations/selenium-tests/ValidationTests/App.config b/packages/react-ui-validations/selenium-tests/ValidationTests/App.config new file mode 100644 index 00000000000..be292451cc7 --- /dev/null +++ b/packages/react-ui-validations/selenium-tests/ValidationTests/App.config @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/react-ui-validations/selenium-tests/ValidationTests/ValidationTests.csproj b/packages/react-ui-validations/selenium-tests/ValidationTests/ValidationTests.csproj index 7058775addd..79d8a43e2b1 100644 --- a/packages/react-ui-validations/selenium-tests/ValidationTests/ValidationTests.csproj +++ b/packages/react-ui-validations/selenium-tests/ValidationTests/ValidationTests.csproj @@ -9,8 +9,9 @@ Properties SKBKontur.ValidationTests ValidationTests - v4.5 + v4.8 512 + true @@ -43,13 +44,14 @@ ..\packages\Kontur.Selone.0.0.6-alpha\lib\net45\Kontur.Selone.dll + ..\packages\NUnit.3.6.1\lib\net45\nunit.framework.dll - - ..\packages\System.ValueTuple.4.4.0\lib\netstandard1.0\System.ValueTuple.dll + + ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll ..\packages\Selenium.WebDriver.3.13.1\lib\net45\WebDriver.dll @@ -76,6 +78,7 @@ + diff --git a/packages/react-ui-validations/selenium-tests/ValidationTests/packages.config b/packages/react-ui-validations/selenium-tests/ValidationTests/packages.config index 1ef0894ce9b..7a2dfb88bdd 100644 --- a/packages/react-ui-validations/selenium-tests/ValidationTests/packages.config +++ b/packages/react-ui-validations/selenium-tests/ValidationTests/packages.config @@ -1,12 +1,12 @@  - - - - - - - - - - \ No newline at end of file + + + + + + + + + + From 523e1914e6c4e18f790b8843db2d562d5f0a25cb Mon Sep 17 00:00:00 2001 From: Mikhail Shatikhin Date: Fri, 17 May 2024 12:21:31 +0500 Subject: [PATCH 3/4] fix: program validation on multi fields IF-1719 --- .../tests/ValidationContainer.test.tsx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/react-ui-validations/tests/ValidationContainer.test.tsx b/packages/react-ui-validations/tests/ValidationContainer.test.tsx index 39f7a0935f7..b90947bbbba 100644 --- a/packages/react-ui-validations/tests/ValidationContainer.test.tsx +++ b/packages/react-ui-validations/tests/ValidationContainer.test.tsx @@ -188,7 +188,7 @@ describe('ValidationContainer', () => { - + ); }; @@ -196,7 +196,8 @@ describe('ValidationContainer', () => { const onValidationUpdated = jest.fn(); const containerRef = renderValidationContainer(, { onValidationUpdated }); await containerRef.current?.submit(); - expect(onValidationUpdated).toBeCalledWith(false); + const errors = await screen.findAllByText('Ошибка'); + expect(errors.length).toBe(1); screen.getByRole('button', { name: 'Repair' }).click(); expect(onValidationUpdated).toBeCalledWith(true); @@ -216,15 +217,15 @@ describe('ValidationContainer', () => { - - + + ); @@ -234,7 +235,8 @@ describe('ValidationContainer', () => { const containerRef = renderValidationContainer(, { onValidationUpdated }); await containerRef.current?.submit(); - expect(onValidationUpdated).toBeCalledWith(false); + const errors = await screen.findAllByText('Ошибка'); + expect(errors.length).toBe(1); screen.getByRole('button', { name: 'Partial Repair' }).click(); expect(onValidationUpdated).toBeCalledWith(false); From 87569f9c4959a367ef921e9971c5046713c54043 Mon Sep 17 00:00:00 2001 From: Mikhail Shatikhin Date: Fri, 17 May 2024 15:15:29 +0500 Subject: [PATCH 4/4] fix: w3c validation + position text validation IF-1684 --- contributing.md | 2 +- .../FeatureFlags/FeatureFlagsContext.md | 8 +-- ...ampleValidationsRemoveDivWrapper.demo.tsx} | 6 +- .../src/ValidationContextWrapper.tsx | 5 +- .../src/ValidationText.tsx | 19 ++---- .../src/ValidationTooltip.tsx | 34 +++------- .../src/ValidationWrapperInternal.tsx | 27 +------- .../src/utils/InlineDiv.tsx | 8 +++ .../ValidationsFeatureFlagsContext.tsx | 2 +- .../stories/Checkbox.stories.tsx | 28 ++++---- .../stories/Input.stories.tsx | 68 ++++++++----------- .../tests/ValidationContainer.test.tsx | 10 +-- 12 files changed, 82 insertions(+), 135 deletions(-) rename packages/react-ui-validations/docs/Pages/Displaying/FeatureFlags/{FeatureFlagsExampleValidationsRemoveExtraSpans.demo.tsx => FeatureFlagsExampleValidationsRemoveDivWrapper.demo.tsx} (90%) create mode 100644 packages/react-ui-validations/src/utils/InlineDiv.tsx diff --git a/contributing.md b/contributing.md index e53b6efaea3..085c8d11939 100644 --- a/contributing.md +++ b/contributing.md @@ -350,7 +350,7 @@ function foo() {} Стоит избегать общих слов, таких как "change". Вместо этого опишите в чем конкретно произошло изменение. Примеры: - - validationsRemoveExtraSpans - Избавиться от обертки span в ValidationContainer, ValidationWrapper и ValidationText + - validationsDivWrapper - Поменять обертку span на div c 'display: inline' чтобы соответсвовать w3c стандарту в ValidationContainer, ValidationWrapper и ValidationText - tokenInputRemoveWhitespaceFromDefaultDelimiters - В TokenInput изменили разделитель по умолчанию 2) Добавьте флаг в ReactUIFeatureFlags в файл ReactUIFeatureFlagsContext.tsx и в документацию FEATUREFLAGSCONTEXT.md diff --git a/packages/react-ui-validations/docs/Pages/Displaying/FeatureFlags/FeatureFlagsContext.md b/packages/react-ui-validations/docs/Pages/Displaying/FeatureFlags/FeatureFlagsContext.md index 3fe05a91875..7e9ad8a9d40 100644 --- a/packages/react-ui-validations/docs/Pages/Displaying/FeatureFlags/FeatureFlagsContext.md +++ b/packages/react-ui-validations/docs/Pages/Displaying/FeatureFlags/FeatureFlagsContext.md @@ -3,7 +3,7 @@ ## Доступные флаги export interface ValidationsFeatureFlags { - validationsRemoveExtraSpans?: boolean; + validationsDivWrapper?: boolean; fixedValidationTextColors?: boolean; darkTheme?: boolean; } @@ -14,16 +14,16 @@ import { ValidationsFeatureFlagsContext } from '@skbkontur/react-ui-validations' - {/* ... */}; + {/* ... */}; ## Использование -### validationsRemoveExtraSpans +### validationsDivWrapper В ValidationContainer, ValidationWrapper и ValidationText из корня удалён лишний span. В Validations 2.0 фича будет применена по умолчанию. - !!DemoWithCode!!FeatureFlagsExamplevalidationsRemoveExtraSpans + !!DemoWithCode!!FeatureFlagsExampleValidationsRemoveDivWrapper ### fixedValidationTextColors diff --git a/packages/react-ui-validations/docs/Pages/Displaying/FeatureFlags/FeatureFlagsExampleValidationsRemoveExtraSpans.demo.tsx b/packages/react-ui-validations/docs/Pages/Displaying/FeatureFlags/FeatureFlagsExampleValidationsRemoveDivWrapper.demo.tsx similarity index 90% rename from packages/react-ui-validations/docs/Pages/Displaying/FeatureFlags/FeatureFlagsExampleValidationsRemoveExtraSpans.demo.tsx rename to packages/react-ui-validations/docs/Pages/Displaying/FeatureFlags/FeatureFlagsExampleValidationsRemoveDivWrapper.demo.tsx index 15db394f1e7..919e290cd97 100644 --- a/packages/react-ui-validations/docs/Pages/Displaying/FeatureFlags/FeatureFlagsExampleValidationsRemoveExtraSpans.demo.tsx +++ b/packages/react-ui-validations/docs/Pages/Displaying/FeatureFlags/FeatureFlagsExampleValidationsRemoveDivWrapper.demo.tsx @@ -13,7 +13,7 @@ interface CheckboxState { checked: boolean; } -export default class FeatureFlagsExampleValidationsWrapperAndContainerRemoveExtraSpan extends React.Component { +export default class FeatureFlagsExampleValidationsWrapperAndContainerDivWrapper extends React.Component { public state: CheckboxState = { checked: false, }; @@ -31,9 +31,7 @@ export default class FeatureFlagsExampleValidationsWrapperAndContainerRemoveExtr render() { return ( - + { - if (flags.validationsRemoveExtraSpans) { - return this.props.children; + if (flags.validationsDivWrapper) { + return {this.props.children}; } return {this.props.children}; diff --git a/packages/react-ui-validations/src/ValidationText.tsx b/packages/react-ui-validations/src/ValidationText.tsx index 6fe19c89920..42bb70acab5 100644 --- a/packages/react-ui-validations/src/ValidationText.tsx +++ b/packages/react-ui-validations/src/ValidationText.tsx @@ -21,19 +21,13 @@ export const ValidationText = ({ pos, children, validation, 'data-tid': dataTid const color = getValidationTextColor(featureFlags, theme, validation?.level); if (pos === 'right') { - const childrenAndValidationText = ( - <> + return ( + {children} {(validation && validation.message) || ''} - - ); - - return featureFlags.validationsRemoveExtraSpans ? ( - childrenAndValidationText - ) : ( - {childrenAndValidationText} + ); } @@ -54,12 +48,7 @@ export const ValidationText = ({ pos, children, validation, 'data-tid': dataTid ); - return featureFlags.validationsRemoveExtraSpans ? ( - <> - {children} - {validationText} - - ) : ( + return ( {children} {validationText} diff --git a/packages/react-ui-validations/src/ValidationTooltip.tsx b/packages/react-ui-validations/src/ValidationTooltip.tsx index 0d78675eee4..bf462de8bb9 100644 --- a/packages/react-ui-validations/src/ValidationTooltip.tsx +++ b/packages/react-ui-validations/src/ValidationTooltip.tsx @@ -1,10 +1,5 @@ import React from 'react'; -import { - ValidationsFeatureFlags, - ValidationsFeatureFlagsContext, - getFullValidationsFlagsContext, -} from './utils/featureFlagsContext'; import { ReactUiDetection, Tooltip } from './ReactUiDetection'; export type TooltipPosition = @@ -33,31 +28,22 @@ export class ValidationTooltip extends React.Component { public static __KONTUR_REACT_UI__ = 'ValidationTooltip'; public static displayName = 'ValidationTooltip'; - private featureFlags!: ValidationsFeatureFlags; public render() { const { children, pos, error, render, ...rest } = this.props; const onlyChild = React.Children.only(children); const child = onlyChild && onlyChild.props ? onlyChild.props.children : null; - return ( - - {(flags) => { - this.featureFlags = getFullValidationsFlagsContext(flags); - return !this.featureFlags.validationsRemoveExtraSpans && - (ReactUiDetection.isRadioGroup(child) || - ReactUiDetection.isTokenInput(child) || - ReactUiDetection.isSwitcher(child)) ? ( - - {child} - - ) : ( - - {children} - - ); - }} - + return ReactUiDetection.isRadioGroup(child) || + ReactUiDetection.isTokenInput(child) || + ReactUiDetection.isSwitcher(child) ? ( + + {child} + + ) : ( + + {children} + ); } } diff --git a/packages/react-ui-validations/src/ValidationWrapperInternal.tsx b/packages/react-ui-validations/src/ValidationWrapperInternal.tsx index 7e1ffd01003..1d1ff85d3ae 100644 --- a/packages/react-ui-validations/src/ValidationWrapperInternal.tsx +++ b/packages/react-ui-validations/src/ValidationWrapperInternal.tsx @@ -3,11 +3,6 @@ import warning from 'warning'; import { Nullable } from '../typings/Types'; -import { - ValidationsFeatureFlags, - ValidationsFeatureFlagsContext, - getFullValidationsFlagsContext, -} from './utils/featureFlagsContext'; import { getRootNode } from './utils/getRootNode'; import { isBrowser } from './utils/utils'; import { smoothScrollIntoView } from './smoothScrollIntoView'; @@ -70,8 +65,6 @@ export class ValidationWrapperInternal extends React.Component< public static contextType = ValidationContext; public context: ValidationContextType = this.context; - private featureFlags!: ValidationsFeatureFlags; - public componentDidMount() { warning( this.context, @@ -150,23 +143,9 @@ export class ValidationWrapperInternal extends React.Component< }); } - return ( - - {(flags) => { - this.featureFlags = getFullValidationsFlagsContext(flags); - return React.cloneElement( - this.props.errorMessage( - this.featureFlags.validationsRemoveExtraSpans ? clonedChild : {clonedChild}, - !!validation, - validation, - ), - { - 'data-tid': dataTid, - }, - ); - }} - - ); + return React.cloneElement(this.props.errorMessage(clonedChild, !!validation, validation), { + 'data-tid': dataTid, + }); } private customRef = (instance: Nullable) => { diff --git a/packages/react-ui-validations/src/utils/InlineDiv.tsx b/packages/react-ui-validations/src/utils/InlineDiv.tsx new file mode 100644 index 00000000000..b57ecf8dbf1 --- /dev/null +++ b/packages/react-ui-validations/src/utils/InlineDiv.tsx @@ -0,0 +1,8 @@ +import React from 'react'; +import type { FC, PropsWithChildren } from 'react'; + +export const InlineDiv: FC>> = ({ children, ...rest }) => ( +
+ {children} +
+); diff --git a/packages/react-ui-validations/src/utils/featureFlagsContext/ValidationsFeatureFlagsContext.tsx b/packages/react-ui-validations/src/utils/featureFlagsContext/ValidationsFeatureFlagsContext.tsx index 4d6c0151b61..79ae11a5145 100644 --- a/packages/react-ui-validations/src/utils/featureFlagsContext/ValidationsFeatureFlagsContext.tsx +++ b/packages/react-ui-validations/src/utils/featureFlagsContext/ValidationsFeatureFlagsContext.tsx @@ -5,7 +5,7 @@ export type FeatureFlags = 'validationsRemoveExtraSpans' | 'fixedValidationTextC export type ValidationsFeatureFlags = Partial>; export const validationsFeatureFlagsDefault: ValidationsFeatureFlags = { - validationsRemoveExtraSpans: false, + validationsDivWrapper: false, fixedValidationTextColors: false, }; diff --git a/packages/react-ui-validations/stories/Checkbox.stories.tsx b/packages/react-ui-validations/stories/Checkbox.stories.tsx index dbf49a66cab..42a34078075 100644 --- a/packages/react-ui-validations/stories/Checkbox.stories.tsx +++ b/packages/react-ui-validations/stories/Checkbox.stories.tsx @@ -3,7 +3,7 @@ import { Meta } from '@storybook/react'; import { Button } from '@skbkontur/react-ui/components/Button'; import { Checkbox } from '@skbkontur/react-ui/components/Checkbox/Checkbox'; -import { ValidationContainer, ValidationInfo, ValidationWrapper, ValidationsFeatureFlagsContext } from '../src'; +import { ValidationContainer, ValidationInfo, ValidationWrapper } from '../src'; import { Nullable } from '../typings/Types'; export default { @@ -22,19 +22,17 @@ export const Required = () => { }; return ( - -
- - - - Checkbox - - -
- -
-
-
-
+
+ + + + Checkbox + + +
+ +
+
+
); }; diff --git a/packages/react-ui-validations/stories/Input.stories.tsx b/packages/react-ui-validations/stories/Input.stories.tsx index fb1cc828712..04f9a94b107 100644 --- a/packages/react-ui-validations/stories/Input.stories.tsx +++ b/packages/react-ui-validations/stories/Input.stories.tsx @@ -6,15 +6,7 @@ import { Select } from '@skbkontur/react-ui/components/Select'; import { Gapped } from '@skbkontur/react-ui'; import { Story } from '@skbkontur/react-ui/typings/stories'; -import { - text, - tooltip, - ValidationBehaviour, - ValidationContainer, - ValidationInfo, - ValidationWrapper, - ValidationsFeatureFlagsContext, -} from '../src'; +import { text, tooltip, ValidationBehaviour, ValidationContainer, ValidationInfo, ValidationWrapper } from '../src'; import { Nullable } from '../typings/Types'; export default { @@ -179,23 +171,21 @@ export const SelectFirstControlForValidation = () => { }; return ( - - -
-
- - - -
-
- - - -
+ +
+
+ + +
- - - +
+ + + +
+
+ +
); }; @@ -382,21 +372,19 @@ export const SetPercentageWidth = () => { refContainer.current?.submit(); }} > - - - - - -
-
- - - -
-
+ + + + +
+
+ + + +



diff --git a/packages/react-ui-validations/tests/ValidationContainer.test.tsx b/packages/react-ui-validations/tests/ValidationContainer.test.tsx index b90947bbbba..d611930ade0 100644 --- a/packages/react-ui-validations/tests/ValidationContainer.test.tsx +++ b/packages/react-ui-validations/tests/ValidationContainer.test.tsx @@ -33,9 +33,9 @@ describe('ValidationContainer', () => { expect(screen.getByTestId('passed-container')).toBeInTheDocument(); }); - it('renders passed data-tid on container when validationsRemoveExtraSpans enabled', () => { + it('renders passed data-tid on container when validationsDivWrapper enabled', () => { render( - +
@@ -45,9 +45,9 @@ describe('ValidationContainer', () => { expect(screen.getByTestId('passed-container')).toBeInTheDocument(); }); - it('not renders passed data-tid on container when validationsRemoveExtraSpans enabled', () => { + it('renders passed data-tid on container when validationsDivWrapper enabled', () => { render( - +
@@ -55,7 +55,7 @@ describe('ValidationContainer', () => { , ); - expect(screen.queryByTestId('passed-container')).toBeNull(); + expect(screen.queryByTestId('passed-container')).toBeInTheDocument(); }); it('renders passed children', () => {