@wise/dynamic-flow-client 5.8.1 → 5.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/DynamicFlowCore.js +5 -0
- package/build/common/errorBoundary/ErrorBoundary.js +26 -0
- package/build/common/errorBoundary/ErrorBoundary.test.js +29 -0
- package/build/common/errorBoundary/ErrorBoundaryAlert.js +11 -0
- package/build/common/makeHttpClient/api-utils.js +3 -0
- package/build/common/makeHttpClient/index.js +1 -0
- package/build/common/makeHttpClient/makeHttpClient.js +10 -0
- package/build/common/makeHttpClient/makeHttpClient.test.js +186 -0
- package/build/common/messages/external-confirmation.messages.js +23 -0
- package/build/common/messages/file-upload.messages.js +13 -0
- package/build/common/messages/generic-error.messages.js +18 -0
- package/build/common/messages/help.messages.js +8 -0
- package/build/common/messages/multi-file-upload.messages.js +18 -0
- package/build/common/messages/multi-select.messages.js +8 -0
- package/build/common/messages/paragraph.messages.js +13 -0
- package/build/common/messages/repeatable.messages.js +23 -0
- package/build/common/messages/search.messages.js +8 -0
- package/build/common/messages/validation.array.messages.js +13 -0
- package/build/common/messages/validation.messages.js +53 -0
- package/build/controller/FlowController.js +368 -0
- package/build/controller/executePoll.js +49 -0
- package/build/controller/executeRefresh.js +39 -0
- package/build/controller/executeRequest.js +77 -0
- package/build/controller/executeSubmission.js +69 -0
- package/build/controller/getErrorMessage.js +7 -0
- package/build/controller/getRequestAbortController.js +13 -0
- package/build/controller/getResponseType.js +35 -0
- package/build/controller/getSafeHttpClient.js +8 -0
- package/build/controller/getStepCounter.js +16 -0
- package/build/controller/handleErrorResponse.js +26 -0
- package/build/controller/makeSafeHttpClient.js +8 -0
- package/build/controller/response-utils.js +72 -0
- package/build/domain/components/AlertComponent.js +1 -0
- package/build/domain/components/AllOfComponent.js +40 -0
- package/build/domain/components/BooleanInputComponent.js +50 -0
- package/build/domain/components/BoxComponent.js +3 -0
- package/build/domain/components/ButtonComponent.js +1 -0
- package/build/domain/components/ColumnsComponent.js +3 -0
- package/build/domain/components/ConstComponent.js +18 -0
- package/build/domain/components/ContainerComponent.js +3 -0
- package/build/domain/components/DateInputComponent.js +75 -0
- package/build/domain/components/DecisionComponent.js +1 -0
- package/build/domain/components/DividerComponent.js +1 -0
- package/build/domain/components/FormComponent.js +3 -0
- package/build/domain/components/FormattedValueComponent.js +44 -0
- package/build/domain/components/HeadingComponent.js +1 -0
- package/build/domain/components/ImageComponent.js +1 -0
- package/build/domain/components/InstructionsComponent.js +1 -0
- package/build/domain/components/IntegerInputComponent.js +74 -0
- package/build/domain/components/ListComponent.js +1 -0
- package/build/domain/components/LoadingIndicatorComponent.js +1 -0
- package/build/domain/components/MarkdownComponent.js +1 -0
- package/build/domain/components/MediaComponent.js +1 -0
- package/build/domain/components/ModalComponent.js +16 -0
- package/build/domain/components/ModalLayoutComponent.js +3 -0
- package/build/domain/components/MoneyInputComponent.js +57 -0
- package/build/domain/components/MultiSelectInputComponent.js +81 -0
- package/build/domain/components/MultiUploadInputComponent.js +88 -0
- package/build/domain/components/NumberInputComponent.js +73 -0
- package/build/domain/components/ObjectComponent.js +45 -0
- package/build/domain/components/ParagraphComponent.js +1 -0
- package/build/domain/components/PersistAsyncComponent.js +92 -0
- package/build/domain/components/ProgressComponent.js +1 -0
- package/build/domain/components/RepeatableComponent.js +103 -0
- package/build/domain/components/ReviewComponent.js +1 -0
- package/build/domain/components/RootDomainComponent.js +173 -0
- package/build/domain/components/SectionComponent.js +5 -0
- package/build/domain/components/SelectInputComponent.js +88 -0
- package/build/domain/components/StatusListComponent.js +1 -0
- package/build/domain/components/SubflowDomainComponent.js +9 -0
- package/build/domain/components/TabsComponent.js +1 -0
- package/build/domain/components/TextInputComponent.js +76 -0
- package/build/domain/components/TupleComponent.js +41 -0
- package/build/domain/components/UploadInputComponent.js +83 -0
- package/build/domain/components/UpsellComponent.js +25 -0
- package/build/domain/components/searchComponent/SearchComponent.js +92 -0
- package/build/domain/components/searchComponent/SearchComponent.test.js +190 -0
- package/build/domain/components/step/ExternalConfirmationComponent.js +28 -0
- package/build/domain/components/step/StepDomainComponent.js +73 -0
- package/build/domain/components/step/ToolbarComponent.js +1 -0
- package/build/domain/components/utils/WithUpdate.js +1 -0
- package/build/domain/components/utils/component-utils.js +12 -0
- package/build/domain/components/utils/debounce.js +34 -0
- package/build/domain/components/utils/debounce.test.js +67 -0
- package/build/domain/components/utils/file-utils.js +21 -0
- package/build/domain/components/utils/file-utils.test.js +27 -0
- package/build/domain/components/utils/getRandomId.js +1 -0
- package/build/domain/components/utils/isExactLocalValueMatch.js +14 -0
- package/build/domain/components/utils/isOrWasValid.js +5 -0
- package/build/domain/components/utils/isPartialModelMatch.js +18 -0
- package/build/domain/components/utils/isPartialModelMatch.test.js +74 -0
- package/build/domain/features/eventNames.js +24 -0
- package/build/domain/features/events.js +1 -0
- package/build/domain/features/persistAsync/getComponentMultiPersistAsync.js +50 -0
- package/build/domain/features/persistAsync/getInitialPersistedState.js +7 -0
- package/build/domain/features/persistAsync/getPerformPersistAsync.js +43 -0
- package/build/domain/features/persistAsync/getPerformPersistAsync.test.js +139 -0
- package/build/domain/features/polling/getStepPolling.js +43 -0
- package/build/domain/features/polling/getStepPolling.test.js +90 -0
- package/build/domain/features/prefetch/getStepPrefetch.js +43 -0
- package/build/domain/features/prefetch/request-cache.js +49 -0
- package/build/domain/features/prefetch/request-cache.test.js +70 -0
- package/build/domain/features/refreshAfter/getStepRefreshAfter.js +24 -0
- package/build/domain/features/refreshAfter/getStepRefreshAfter.test.js +40 -0
- package/build/domain/features/schema-on-change/getDebouncedSchemaOnChange.js +50 -0
- package/build/domain/features/schema-on-change/getSchemaOnChange.js +34 -0
- package/build/domain/features/search/getPerformSearchFunction.js +75 -0
- package/build/domain/features/search/getPerformSearchFunction.test.js +301 -0
- package/build/domain/features/summary/summary-utils.js +40 -0
- package/build/domain/features/summary/summary-utils.test.js +125 -0
- package/build/domain/features/utils/http-utils.js +21 -0
- package/build/domain/features/utils/response-utils.js +9 -0
- package/build/domain/features/validation/spec-utils.js +19 -0
- package/build/domain/features/validation/validateStringPattern.js +24 -0
- package/build/domain/features/validation/validation-functions.js +6 -0
- package/build/domain/features/validation/validation-functions.test.js +108 -0
- package/build/domain/features/validation/value-checks.js +125 -0
- package/build/domain/features/validation/value-checks.test.js +262 -0
- package/build/domain/features/validationAsync/getComponentValidationAsync.js +53 -0
- package/build/domain/features/validationAsync/getComponentValidationAsync.test.js +67 -0
- package/build/domain/features/validationAsync/getInitialValidationAsyncState.js +5 -0
- package/build/domain/features/validationAsync/getPerformValidationAsync.js +45 -0
- package/build/domain/features/validationAsync/getPerformValidationAsync.test.js +143 -0
- package/build/domain/mappers/layout/alertLayoutToComponent.js +16 -0
- package/build/domain/mappers/layout/boxLayoutToComponent.js +13 -0
- package/build/domain/mappers/layout/buttonLayoutToComponent.js +77 -0
- package/build/domain/mappers/layout/columnsLayoutToComponent.js +13 -0
- package/build/domain/mappers/layout/decisionLayoutToComponent.js +22 -0
- package/build/domain/mappers/layout/deprecatedListLayoutToComponent.js +30 -0
- package/build/domain/mappers/layout/dividerLayoutToComponent.js +2 -0
- package/build/domain/mappers/layout/formLayoutToComponent.js +19 -0
- package/build/domain/mappers/layout/headingLayoutToComponent.js +12 -0
- package/build/domain/mappers/layout/imageLayoutToComponent.js +20 -0
- package/build/domain/mappers/layout/infoLayoutToComponent.js +12 -0
- package/build/domain/mappers/layout/instructionsLayoutToComponent.js +12 -0
- package/build/domain/mappers/layout/listLayoutToComponent.js +39 -0
- package/build/domain/mappers/layout/loadingIndicatorLayoutToComponent.js +9 -0
- package/build/domain/mappers/layout/markdownLayoutToComponent.js +12 -0
- package/build/domain/mappers/layout/mediaLayoutToComponent.js +12 -0
- package/build/domain/mappers/layout/modalLayoutToComponent.js +17 -0
- package/build/domain/mappers/layout/modalToComponent.js +8 -0
- package/build/domain/mappers/layout/paragraphLayoutToComponent.js +12 -0
- package/build/domain/mappers/layout/progressLayoutToComponent.js +15 -0
- package/build/domain/mappers/layout/reviewLayoutToComponent.js +48 -0
- package/build/domain/mappers/layout/searchLayoutToComponent.js +44 -0
- package/build/domain/mappers/layout/sectionLayoutToComponent.js +15 -0
- package/build/domain/mappers/layout/statusListLayoutToComponent.js +15 -0
- package/build/domain/mappers/layout/tabsLayoutToComponent.js +16 -0
- package/build/domain/mappers/layout/upsellLayoutToComponent.js +25 -0
- package/build/domain/mappers/mapLayoutToComponent.js +81 -0
- package/build/domain/mappers/mapSchemaToComponent.js +61 -0
- package/build/domain/mappers/mapSchemaToComponent.test.js +112 -0
- package/build/domain/mappers/mapStepSchemas.js +17 -0
- package/build/domain/mappers/mapStepToComponent.js +132 -0
- package/build/domain/mappers/mapStepToComponent.test.js +221 -0
- package/build/domain/mappers/mapToolbarToComponent.js +15 -0
- package/build/domain/mappers/schema/allOfSchemaToComponent.js +16 -0
- package/build/domain/mappers/schema/arraySchemaToComponent/arraySchemaToComponent.js +26 -0
- package/build/domain/mappers/schema/arraySchemaToComponent/arraySchemaToMultiSelectComponent.js +55 -0
- package/build/domain/mappers/schema/arraySchemaToComponent/arraySchemaToMultiUploadComponent.js +67 -0
- package/build/domain/mappers/schema/arraySchemaToComponent/arraySchemaToRepeatableComponent.js +57 -0
- package/build/domain/mappers/schema/arraySchemaToComponent/arraySchemaToTupleComponent.js +20 -0
- package/build/domain/mappers/schema/blobSchemaToComponent.js +15 -0
- package/build/domain/mappers/schema/booleanSchemaToComponent.js +29 -0
- package/build/domain/mappers/schema/constSchemaToComponent.js +23 -0
- package/build/domain/mappers/schema/integerSchemaToComponent.js +28 -0
- package/build/domain/mappers/schema/numberSchemaToComponent.js +26 -0
- package/build/domain/mappers/schema/objectSchemaToComponent/assertDisplayOrder.js +23 -0
- package/build/domain/mappers/schema/objectSchemaToComponent/objectSchemaToFormattedValueComponent.js +9 -0
- package/build/domain/mappers/schema/objectSchemaToComponent/objectSchemaToMoneyInputComponent.js +119 -0
- package/build/domain/mappers/schema/objectSchemaToComponent/objectSchemaToMoneyInputComponent.test.js +96 -0
- package/build/domain/mappers/schema/objectSchemaToComponent/objectSchemaToObjectComponent.js +31 -0
- package/build/domain/mappers/schema/objectSchemaToComponent/objectSchemaToObjectComponent.test.js +99 -0
- package/build/domain/mappers/schema/oneOfSchemaToComponent/oneOfSchemaToComponent.js +76 -0
- package/build/domain/mappers/schema/oneOfSchemaToComponent/oneOfSchemaToComponent.test.js +265 -0
- package/build/domain/mappers/schema/persistAsyncSchemaToComponent.js +29 -0
- package/build/domain/mappers/schema/stringSchemaToComponent/stringSchemaToComponent.js +18 -0
- package/build/domain/mappers/schema/stringSchemaToComponent/stringSchemaToComponent.test.js +133 -0
- package/build/domain/mappers/schema/stringSchemaToComponent/stringSchemaToDateInputComponent.js +48 -0
- package/build/domain/mappers/schema/stringSchemaToComponent/stringSchemaToTextInputComponent.js +37 -0
- package/build/domain/mappers/schema/stringSchemaToComponent/stringSchemaToUploadInputComponent.js +28 -0
- package/build/domain/mappers/schema/tests/test-utils.js +16 -0
- package/build/domain/mappers/schema/types.js +1 -0
- package/build/domain/mappers/schema/utils/getPerformPersistAsyncFn.js +19 -0
- package/build/domain/mappers/schema/utils/getValidationAsyncInitialState.js +23 -0
- package/build/domain/mappers/schema/utils/mapCommonSchemaProps.js +16 -0
- package/build/domain/mappers/types.js +1 -0
- package/build/domain/mappers/utils/FeatureFlags.js +22 -0
- package/build/domain/mappers/utils/behavior-utils.js +44 -0
- package/build/domain/mappers/utils/call-to-action-utils.js +21 -0
- package/build/domain/mappers/utils/getAutocompleteString.js +76 -0
- package/build/domain/mappers/utils/getAutocompleteString.test.js +21 -0
- package/build/domain/mappers/utils/groupLayoutByPinned.js +38 -0
- package/build/domain/mappers/utils/groupLayoutByPinned.test.js +166 -0
- package/build/domain/mappers/utils/image.js +9 -0
- package/build/domain/mappers/utils/layout-utils.js +11 -0
- package/build/domain/mappers/utils/legacy-utils.js +49 -0
- package/build/domain/mappers/utils/media-utils.js +14 -0
- package/build/domain/mappers/utils/suggestions-utils.js +26 -0
- package/build/domain/mappers/utils/suggestions-utils.test.js +36 -0
- package/build/domain/mappers/utils/tags-utils.js +1 -0
- package/build/domain/mappers/utils/utils.js +35 -0
- package/build/domain/types.js +1 -0
- package/build/getSubflowCallbacks.js +38 -0
- package/build/i18n/index.js +40 -0
- package/build/index.js +8 -0
- package/build/main.js +112 -54
- package/build/main.mjs +111 -53
- package/build/renderers/CoreContainerRenderer.js +5 -0
- package/build/renderers/CoreRootRenderer.js +12 -0
- package/build/renderers/EmptyLoadingStateRenderer.js +5 -0
- package/build/renderers/getRenderFunction.js +24 -0
- package/build/renderers/getSchemaErrorMessageFunction.js +97 -0
- package/build/renderers/mappers/alertComponentToProps.js +2 -0
- package/build/renderers/mappers/allOfComponentToProps.js +6 -0
- package/build/renderers/mappers/booleanInputComponentToProps.js +5 -0
- package/build/renderers/mappers/boxComponentToProps.js +13 -0
- package/build/renderers/mappers/buttonComponentToProps.js +4 -0
- package/build/renderers/mappers/columnsComponentToProps.js +11 -0
- package/build/renderers/mappers/componentToRendererProps.js +164 -0
- package/build/renderers/mappers/constComponentToProps.js +5 -0
- package/build/renderers/mappers/containerComponentToProps.js +7 -0
- package/build/renderers/mappers/dateInputComponentToProps.js +2 -0
- package/build/renderers/mappers/decisionComponentToProps.js +16 -0
- package/build/renderers/mappers/dividerComponentToProps.js +2 -0
- package/build/renderers/mappers/externalComponentToProps.js +3 -0
- package/build/renderers/mappers/formComponentToProps.js +12 -0
- package/build/renderers/mappers/formattedValueComponentToProps.js +5 -0
- package/build/renderers/mappers/headingComponentToProps.js +2 -0
- package/build/renderers/mappers/hiddenComponentToProps.js +4 -0
- package/build/renderers/mappers/imageComponentToProps.js +2 -0
- package/build/renderers/mappers/instructionsComponentToProps.js +2 -0
- package/build/renderers/mappers/integerInputComponentToProps.js +2 -0
- package/build/renderers/mappers/listComponentToProps.js +2 -0
- package/build/renderers/mappers/loadingIndicatorComponentToProps.js +2 -0
- package/build/renderers/mappers/markdownComponentToProps.js +2 -0
- package/build/renderers/mappers/mediaComponentToProps.js +2 -0
- package/build/renderers/mappers/modalComponentToProps.js +11 -0
- package/build/renderers/mappers/modalLayoutComponentToProps.js +16 -0
- package/build/renderers/mappers/moneyInputComponentToProps.js +36 -0
- package/build/renderers/mappers/multiSelectComponentToProps.js +23 -0
- package/build/renderers/mappers/multiUploadInputComponentToProps.js +12 -0
- package/build/renderers/mappers/numberInputComponentToProps.js +2 -0
- package/build/renderers/mappers/objectComponentToProps.js +8 -0
- package/build/renderers/mappers/paragraphComponentToProps.js +2 -0
- package/build/renderers/mappers/persistAsyncComponentToProps.js +8 -0
- package/build/renderers/mappers/progressComponentToProps.js +2 -0
- package/build/renderers/mappers/repeatableComponentToProps.js +30 -0
- package/build/renderers/mappers/reviewComponentToProps.js +2 -0
- package/build/renderers/mappers/rootComponentToProps.js +21 -0
- package/build/renderers/mappers/searchComponentToProps.js +57 -0
- package/build/renderers/mappers/sectionComponentToProps.js +6 -0
- package/build/renderers/mappers/selectInputComponentToProps.js +26 -0
- package/build/renderers/mappers/statusListComponentToProps.js +2 -0
- package/build/renderers/mappers/subflowComponentToRendererProps.js +4 -0
- package/build/renderers/mappers/tabsComponentToProps.js +14 -0
- package/build/renderers/mappers/textInputComponentToProps.js +2 -0
- package/build/renderers/mappers/tupleComponentToProps.js +8 -0
- package/build/renderers/mappers/uploadInputComponentToProps.js +8 -0
- package/build/renderers/mappers/upsellComponentToProps.js +2 -0
- package/build/renderers/mappers/utils/getValidationState.js +12 -0
- package/build/renderers/mappers/utils/inputComponentToProps.js +26 -0
- package/build/renderers/mappers/utils/mapErrorsToValidationState.js +9 -0
- package/build/renderers/mappers/utils/pick.js +8 -0
- package/build/renderers/mappers/utils/selectInputOptionsToProps.js +11 -0
- package/build/renderers/stepComponentToProps.js +32 -0
- package/build/renderers/utils.js +69 -0
- package/build/renderers/utils.test.js +70 -0
- package/build/stories/dev-tools/ContainerQueries.story.js +66 -0
- package/build/stories/dev-tools/Debugger.story.js +38 -0
- package/build/stories/dev-tools/FixtureSelect.story.js +23 -0
- package/build/stories/dev-tools/TestServer.story.js +32 -0
- package/build/stories/examples/NativeFlow.story.js +80 -0
- package/build/stories/examples/Recipients.story.js +568 -0
- package/build/stories/spec/behavior/Copy.story.js +59 -0
- package/build/stories/spec/behavior/Modal.story.js +76 -0
- package/build/stories/spec/behavior/Subflow.story.js +267 -0
- package/build/stories/spec/layouts/Decision.story.js +241 -0
- package/build/stories/spec/layouts/Image.story.js +42 -0
- package/build/stories/spec/layouts/Modal.story.js +81 -0
- package/build/stories/spec/layouts/Search.story.js +325 -0
- package/build/stories/spec/layouts/Upsell.story.js +55 -0
- package/build/stories/spec/layouts/button/Button.story.js +100 -0
- package/build/stories/spec/layouts/button/PinnedButton.story.js +81 -0
- package/build/stories/spec/response/ActionResponse.story.js +66 -0
- package/build/stories/spec/schemas/MultiSelect.story.js +148 -0
- package/build/stories/spec/schemas/Upload.story.js +168 -0
- package/build/stories/spec/schemas/const/ConstLayout.story.js +159 -0
- package/build/stories/spec/schemas/const/ObjectConst.story.js +94 -0
- package/build/stories/spec/schemas/features/PersistAsync.story.js +176 -0
- package/build/stories/spec/schemas/features/ValidationAsync.story.js +103 -0
- package/build/stories/spec/schemas/object/FormattedValue.story.js +92 -0
- package/build/stories/spec/schemas/object/MoneyInput.story.js +240 -0
- package/build/stories/spec/schemas/oneOf/OneOfInitialisation.story.js +55 -0
- package/build/stories/spec/step/Controls.story.js +109 -0
- package/build/stories/spec/step/DFModal.story.js +58 -0
- package/build/stories/spec/step/Footer.story.js +70 -0
- package/build/stories/spec/step/Navigation.story.js +20 -0
- package/build/stories/spec/step/Tags.story.js +39 -0
- package/build/stories/spec/step/ToolBar.story.js +60 -0
- package/build/stories/spec/step/features/ErrorHandling.story.js +92 -0
- package/build/stories/spec/step/features/External.story.js +44 -0
- package/build/stories/spec/step/features/Polling.story.js +108 -0
- package/build/stories/spec/step/features/RefreshAfter.story.js +92 -0
- package/build/stories/spec/step/features/refresh/Refresh.story.js +258 -0
- package/build/stories/spec/step/features/refresh/RefreshWithPersistAsync.story.js +958 -0
- package/build/stories/types.js +1 -0
- package/build/stories/utils/fixtureHttpClient.js +70 -0
- package/build/stories/utils/getBasicStep.js +223 -0
- package/build/stories/utils/mockSearchHandler.js +71 -0
- package/build/stories/utils/render-utils.js +41 -0
- package/build/stories/visual-tests/layouts/NotUsingListItem.story.js +17 -0
- package/build/test-utils/DynamicFlowWise.js +32 -0
- package/build/test-utils/DynamicFlowWiseModal.js +34 -0
- package/build/test-utils/NeptuneProviders.js +11 -0
- package/build/test-utils/component-utils.js +5 -0
- package/build/test-utils/fetch-utils.js +45 -0
- package/build/test-utils/getMergedTestRenderers.js +34 -0
- package/build/test-utils/getRandomId.js +1 -0
- package/build/test-utils/index.js +3 -0
- package/build/test-utils/rtl-utils.js +7 -0
- package/build/test-utils/step-utils.js +6 -0
- package/build/test-utils/wait.js +3 -0
- package/build/tests/AlertLayout.test.js +78 -0
- package/build/tests/ArrayTuple.test.js +118 -0
- package/build/tests/ButtonLayout.test.js +308 -0
- package/build/tests/ConstLayout.test.js +95 -0
- package/build/tests/DateInput.test.js +163 -0
- package/build/tests/DecisionLayout.test.js +146 -0
- package/build/tests/DynamicFlow.test.js +147 -0
- package/build/tests/External.test.js +169 -0
- package/build/tests/Flow.test.js +328 -0
- package/build/tests/FormLayout.test.js +28 -0
- package/build/tests/FormattedValue.test.js +107 -0
- package/build/tests/ImageRenderer.test.js +78 -0
- package/build/tests/InitialAction.test.js +179 -0
- package/build/tests/InitialStep.test.js +168 -0
- package/build/tests/InstructionsLayout.test.js +45 -0
- package/build/tests/ListLayout.test.js +145 -0
- package/build/tests/Logging.test.js +53 -0
- package/build/tests/ModalBehavior.test.js +149 -0
- package/build/tests/MoneyInput.test.js +316 -0
- package/build/tests/MultiUpload.test.js +293 -0
- package/build/tests/NativeBack.test.js +267 -0
- package/build/tests/OneOfInitialisation.test.js +571 -0
- package/build/tests/PersistAsync.test.js +653 -0
- package/build/tests/Polling.test.js +617 -0
- package/build/tests/Prefetching.test.js +230 -0
- package/build/tests/RefreshAfter.test.js +63 -0
- package/build/tests/RefreshOnChange.ResponseHandling.test.js +205 -0
- package/build/tests/RefreshOnChange.test.js +233 -0
- package/build/tests/RefreshOnChange.with.Segmented.test.js +348 -0
- package/build/tests/RefreshOnChange.with.Tabs.test.js +358 -0
- package/build/tests/RefreshOnChangePreserve.test.js +224 -0
- package/build/tests/RendererProps.test.js +342 -0
- package/build/tests/Repeatable.test.js +107 -0
- package/build/tests/Rerendering.test.js +67 -0
- package/build/tests/ReviewLayout.test.js +274 -0
- package/build/tests/SchemaOnChange.test.js +133 -0
- package/build/tests/ScrollToError.test.js +217 -0
- package/build/tests/SegmentedControl.test.js +49 -0
- package/build/tests/SingleFileUpload.test.js +88 -0
- package/build/tests/StatusList.test.js +85 -0
- package/build/tests/Subflow.test.js +710 -0
- package/build/tests/Submission.ResponseHandling.test.js +557 -0
- package/build/tests/Submission.merging.test.js +202 -0
- package/build/tests/Submission.test.js +523 -0
- package/build/tests/Tags.test.js +475 -0
- package/build/tests/Upsell.test.js +126 -0
- package/build/tests/ValidationAsync.test.js +295 -0
- package/build/tests/legacy/Actions.test.js +158 -0
- package/build/tests/legacy/BackButton.test.js +114 -0
- package/build/tests/legacy/HiddenSchemas.test.js +246 -0
- package/build/tests/legacy/MultiSelect.test.js +497 -0
- package/build/tests/legacy/MultipleFileUploadSchema.test.js +341 -0
- package/build/tests/legacy/PersistAsync.blob-schema.test.js +224 -0
- package/build/tests/legacy/PersistAsync.string-schema.test.js +211 -0
- package/build/tests/legacy/RefreshStepOnChange.debouncing.test.js +209 -0
- package/build/tests/legacy/RefreshStepOnChange.test.js +424 -0
- package/build/tests/legacy/Search.test.js +437 -0
- package/build/tests/renderers/MultiSelectInputRendererProps.test.js +58 -0
- package/build/tests/renderers/SelectInputRendererProps.test.js +42 -0
- package/build/tests/renderers/TextInputRenderer.test.js +51 -0
- package/build/types/domain/components/UpsellComponent.d.ts +2 -3
- package/build/types/domain/components/UpsellComponent.d.ts.map +1 -1
- package/build/types/domain/components/searchComponent/SearchComponent.d.ts +5 -4
- package/build/types/domain/components/searchComponent/SearchComponent.d.ts.map +1 -1
- package/build/types/domain/features/search/getPerformSearchFunction.d.ts +1 -1
- package/build/types/domain/features/search/getPerformSearchFunction.d.ts.map +1 -1
- package/build/types/domain/mappers/layout/searchLayoutToComponent.d.ts +2 -1
- package/build/types/domain/mappers/layout/searchLayoutToComponent.d.ts.map +1 -1
- package/build/types/domain/mappers/layout/upsellLayoutToComponent.d.ts +1 -1
- package/build/types/domain/mappers/layout/upsellLayoutToComponent.d.ts.map +1 -1
- package/build/types/renderers/EmptyLoadingStateRenderer.d.ts +3 -0
- package/build/types/renderers/EmptyLoadingStateRenderer.d.ts.map +1 -0
- package/build/types/renderers/mappers/rootComponentToProps.d.ts.map +1 -1
- package/build/types/renderers/mappers/searchComponentToProps.d.ts +1 -1
- package/build/types/renderers/mappers/searchComponentToProps.d.ts.map +1 -1
- package/build/types/renderers/mappers/upsellComponentToProps.d.ts +2 -2
- package/build/types/renderers/mappers/upsellComponentToProps.d.ts.map +1 -1
- package/build/types/test-utils/getMergedTestRenderers.d.ts +1 -1
- package/build/types/test-utils/getMergedTestRenderers.d.ts.map +1 -1
- package/build/types/useDynamicFlow.d.ts.map +1 -1
- package/build/types.js +1 -0
- package/build/useDynamicFlow.js +104 -0
- package/build/useDynamicFlowModal.js +58 -0
- package/build/utils/analyse-step.js +14 -0
- package/build/utils/component-utils.js +8 -0
- package/build/utils/component-utils.test.js +113 -0
- package/build/utils/getScrollToTop.js +12 -0
- package/build/utils/normalise-flow-id.js +1 -0
- package/build/utils/normalise-flow-id.test.js +24 -0
- package/build/utils/openLinkInNewTab.js +10 -0
- package/build/utils/recursiveMerge.js +40 -0
- package/build/utils/recursiveMerge.test.js +93 -0
- package/build/utils/type-utils.js +21 -0
- package/build/utils/type-validators.js +11 -0
- package/build/utils/type-validators.test.js +180 -0
- package/build/utils/useStableCallback.js +15 -0
- package/package.json +4 -4
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { isArray, isNullish, isNumber, isString, isValidDate, } from '../../../utils/type-validators';
|
|
2
|
+
import { validateStringPattern } from './validateStringPattern';
|
|
3
|
+
export const getAboveMaxItemsCheck = ({ maxItems }, messageFunctions) => (value) => {
|
|
4
|
+
if (isNumber(maxItems) && isArray(value) && value.length > maxItems) {
|
|
5
|
+
return messageFunctions.maxItems(maxItems);
|
|
6
|
+
}
|
|
7
|
+
return null;
|
|
8
|
+
};
|
|
9
|
+
export const getBelowMinFilesCheck = ({ minItems }, messageFunctions) => (value) => {
|
|
10
|
+
if (isNumber(minItems) && isArray(value) && value.length > 0 && value.length < minItems) {
|
|
11
|
+
return messageFunctions.minFiles(minItems);
|
|
12
|
+
}
|
|
13
|
+
return null;
|
|
14
|
+
};
|
|
15
|
+
export const getAboveMaxFilesCheck = ({ maxItems }, messageFunctions) => (value) => {
|
|
16
|
+
if (isNumber(maxItems) && isArray(value) && value.length > maxItems) {
|
|
17
|
+
return messageFunctions.maxFiles(maxItems);
|
|
18
|
+
}
|
|
19
|
+
return null;
|
|
20
|
+
};
|
|
21
|
+
export const getFileSizeCheck = (schema, messageFunctions) => (value) => {
|
|
22
|
+
const maxSize = 'persistAsync' in schema ? schema.persistAsync.schema.maxSize : schema.maxSize;
|
|
23
|
+
if (maxSize && value && value.size > maxSize) {
|
|
24
|
+
return messageFunctions.maxSize();
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
};
|
|
28
|
+
export const getFileTypeCheck = (schema, messageFunctions) => (value) => {
|
|
29
|
+
const accepts = 'persistAsync' in schema ? schema.persistAsync.schema.accepts : schema.accepts;
|
|
30
|
+
if (accepts && value && !accepts.includes(value.type)) {
|
|
31
|
+
return messageFunctions.accepts();
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
};
|
|
35
|
+
export const getBelowMinItemsCheck = ({ minItems }, messageFunctions) => (value) => {
|
|
36
|
+
if (isNumber(minItems) && isArray(value) && value.length > 0 && value.length < minItems) {
|
|
37
|
+
return messageFunctions.minItems(minItems);
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
};
|
|
41
|
+
export const getAboveMaxLengthCheck = ({ maxLength }, messageFunctions) => (value) => {
|
|
42
|
+
if (isNumber(maxLength) && isString(value) && value.length > maxLength) {
|
|
43
|
+
return messageFunctions.maxLength(maxLength);
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
};
|
|
47
|
+
export const getBelowMinLengthCheck = ({ minLength }, messageFunctions) => (value) => {
|
|
48
|
+
if (isNumber(minLength) && isString(value) && value && value.length < minLength) {
|
|
49
|
+
return messageFunctions.minLength(minLength);
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
};
|
|
53
|
+
export const getAboveMaximumCheck = ({ maximum }, messageFunctions) => (value) => {
|
|
54
|
+
if (isNumber(maximum) && isNumber(value) && value > maximum) {
|
|
55
|
+
return messageFunctions.maximum(maximum);
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
};
|
|
59
|
+
export const getBelowMinimumCheck = ({ minimum }, messageFunctions) => (value) => {
|
|
60
|
+
if (isNumber(minimum) && isNumber(value) && value < minimum) {
|
|
61
|
+
return messageFunctions.minimum(minimum);
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
};
|
|
65
|
+
export const getAboveMaximumMoneyAmountCheck = ({ maximum }, messageFunctions) => (value) => {
|
|
66
|
+
const numericValue = value != null ? Number.parseFloat(value) : null;
|
|
67
|
+
const numericMax = maximum != null ? Number.parseFloat(maximum) : null;
|
|
68
|
+
if (maximum != null &&
|
|
69
|
+
isNumber(numericMax) &&
|
|
70
|
+
isNumber(numericValue) &&
|
|
71
|
+
numericValue > numericMax) {
|
|
72
|
+
return messageFunctions.maximum(maximum);
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
};
|
|
76
|
+
export const getBelowMinimumMoneyAmountCheck = ({ minimum }, messageFunctions) => (value) => {
|
|
77
|
+
const numericValue = value != null ? Number.parseFloat(value) : null;
|
|
78
|
+
const numericMin = minimum != null ? Number.parseFloat(minimum) : null;
|
|
79
|
+
if (minimum != null &&
|
|
80
|
+
isNumber(numericMin) &&
|
|
81
|
+
isNumber(numericValue) &&
|
|
82
|
+
numericValue < numericMin) {
|
|
83
|
+
return messageFunctions.minimum(minimum);
|
|
84
|
+
}
|
|
85
|
+
return null;
|
|
86
|
+
};
|
|
87
|
+
export const getAboveMaximumDateCheck = ({ maximum }, messageFunctions) => (value) => {
|
|
88
|
+
if (isString(maximum) && isString(value) && value > maximum) {
|
|
89
|
+
return messageFunctions.maximumDate(maximum);
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
};
|
|
93
|
+
export const getBelowMinimumDateCheck = ({ minimum }, messageFunctions) => (value) => {
|
|
94
|
+
if (isString(minimum) && isString(value) && value && value < minimum) {
|
|
95
|
+
return messageFunctions.minimumDate(minimum);
|
|
96
|
+
}
|
|
97
|
+
return null;
|
|
98
|
+
};
|
|
99
|
+
export const getNotAdheringToPatternCheck = ({ pattern }, messageFunctions, options) => {
|
|
100
|
+
validateStringPattern(pattern, options === null || options === void 0 ? void 0 : options.logEvent);
|
|
101
|
+
return (value) => {
|
|
102
|
+
if (isString(pattern) && isString(value) && value) {
|
|
103
|
+
return new RegExp(pattern).test(value) ? null : messageFunctions.pattern();
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
export const getRequiredCheck = (required, messageFunctions) => (value) => {
|
|
109
|
+
if (!required) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
if (isArray(value) && value.length === 0) {
|
|
113
|
+
return messageFunctions.required();
|
|
114
|
+
}
|
|
115
|
+
if (value === '') {
|
|
116
|
+
return messageFunctions.required();
|
|
117
|
+
}
|
|
118
|
+
return isNullish(value) ? messageFunctions.required() : null;
|
|
119
|
+
};
|
|
120
|
+
export const getValidDateCheck = (required, messageFunctions) => (value) => {
|
|
121
|
+
if (required && !isValidDate(value)) {
|
|
122
|
+
return messageFunctions.required();
|
|
123
|
+
}
|
|
124
|
+
return null;
|
|
125
|
+
};
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { getAboveMaxLengthCheck, getBelowMinLengthCheck, getAboveMaximumCheck, getBelowMinimumCheck, getAboveMaximumDateCheck, getBelowMinimumDateCheck, getNotAdheringToPatternCheck, getAboveMaxItemsCheck, getBelowMinItemsCheck, getAboveMaxFilesCheck, getBelowMinFilesCheck, getValidDateCheck, } from './value-checks';
|
|
2
|
+
import { mockErrorMessageFunctions } from './spec-utils';
|
|
3
|
+
import { vi } from 'vitest';
|
|
4
|
+
describe('value checks', () => {
|
|
5
|
+
describe('getAboveMaxLengthCheck', () => {
|
|
6
|
+
it('should return null if the string length is below or equal to the maxLength', () => {
|
|
7
|
+
const schema = { type: 'string', maxLength: 5 };
|
|
8
|
+
const check = getAboveMaxLengthCheck(schema, mockErrorMessageFunctions);
|
|
9
|
+
const belowLength = check('0');
|
|
10
|
+
const atLength = check('01234');
|
|
11
|
+
expect(belowLength).toBeNull();
|
|
12
|
+
expect(atLength).toBeNull();
|
|
13
|
+
});
|
|
14
|
+
it('should return an error message if the string length is above the maxLength', () => {
|
|
15
|
+
const schema = { type: 'string', maxLength: 5 };
|
|
16
|
+
const check = getAboveMaxLengthCheck(schema, mockErrorMessageFunctions);
|
|
17
|
+
expect(check('012345')).toBe('maxLength');
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
describe('getBelowMinLengthCheck', () => {
|
|
21
|
+
it('should return null if the string length is above or equal to the minLength', () => {
|
|
22
|
+
const schema = { type: 'string', minLength: 5 };
|
|
23
|
+
const check = getBelowMinLengthCheck(schema, mockErrorMessageFunctions);
|
|
24
|
+
const atLength = check('01234');
|
|
25
|
+
const aboveLength = check('0123456789');
|
|
26
|
+
expect(atLength).toBeNull();
|
|
27
|
+
expect(aboveLength).toBeNull();
|
|
28
|
+
});
|
|
29
|
+
it('should return null if the string is empty', () => {
|
|
30
|
+
const schema = { type: 'string', minLength: 5 };
|
|
31
|
+
const check = getBelowMinLengthCheck(schema, mockErrorMessageFunctions);
|
|
32
|
+
expect(check('')).toBeNull();
|
|
33
|
+
});
|
|
34
|
+
it('should return an error message if the string length is below the minLength', () => {
|
|
35
|
+
const schema = { type: 'string', minLength: 5 };
|
|
36
|
+
const check = getBelowMinLengthCheck(schema, mockErrorMessageFunctions);
|
|
37
|
+
expect(check('0')).toBe('minLength');
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
describe('getAboveMaximumCheck', () => {
|
|
41
|
+
it('should return null if the number is below or equal to the maximum', () => {
|
|
42
|
+
const schema = { type: 'number', maximum: 10 };
|
|
43
|
+
const check = getAboveMaximumCheck(schema, mockErrorMessageFunctions);
|
|
44
|
+
const atMax = check(5);
|
|
45
|
+
const belowMax = check(10);
|
|
46
|
+
expect(atMax).toBeNull();
|
|
47
|
+
expect(belowMax).toBeNull();
|
|
48
|
+
});
|
|
49
|
+
it('should return an error message if the number is above the maximum', () => {
|
|
50
|
+
const schema = { type: 'number', maximum: 10 };
|
|
51
|
+
const check = getAboveMaximumCheck(schema, mockErrorMessageFunctions);
|
|
52
|
+
expect(check(15)).toBe('maximum');
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
describe('getBelowMinimumCheck', () => {
|
|
56
|
+
it('should return null if the number is above or equal to the minimum', () => {
|
|
57
|
+
const schema = { type: 'integer', minimum: 5 };
|
|
58
|
+
const check = getBelowMinimumCheck(schema, mockErrorMessageFunctions);
|
|
59
|
+
const atMinimum = check(5);
|
|
60
|
+
const aboveMinimum = check(10);
|
|
61
|
+
expect(atMinimum).toBeNull();
|
|
62
|
+
expect(aboveMinimum).toBeNull();
|
|
63
|
+
});
|
|
64
|
+
it('should return an error message if the number is below the minimum', () => {
|
|
65
|
+
const schema = { type: 'integer', minimum: 10 };
|
|
66
|
+
const check = getBelowMinimumCheck(schema, mockErrorMessageFunctions);
|
|
67
|
+
expect(check(5)).toBe('minimum');
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
describe('getAboveMaximumDateCheck', () => {
|
|
71
|
+
it('should return null if the date is below or equal to the maximum', () => {
|
|
72
|
+
const schema = { type: 'string', format: 'date', maximum: '2022-01-01' };
|
|
73
|
+
const check = getAboveMaximumDateCheck(schema, mockErrorMessageFunctions);
|
|
74
|
+
const atDate = check('2022-01-01');
|
|
75
|
+
const belowDate = check('2021-12-31');
|
|
76
|
+
expect(atDate).toBeNull();
|
|
77
|
+
expect(belowDate).toBeNull();
|
|
78
|
+
});
|
|
79
|
+
it('should return an error message if the date is above the maximum', () => {
|
|
80
|
+
const schema = { type: 'string', format: 'date', maximum: '2022-01-01' };
|
|
81
|
+
const check = getAboveMaximumDateCheck(schema, mockErrorMessageFunctions);
|
|
82
|
+
expect(check('2022-01-02')).toBe('maximumDate');
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
describe('getBelowMinimumDateCheck', () => {
|
|
86
|
+
it('should return null if the date is above or equal to the minimum', () => {
|
|
87
|
+
const schema = { type: 'string', format: 'date', minimum: '2022-01-01' };
|
|
88
|
+
const check = getBelowMinimumDateCheck(schema, mockErrorMessageFunctions);
|
|
89
|
+
const atDate = check('2022-01-01');
|
|
90
|
+
const aboveDate = check('2022-01-02');
|
|
91
|
+
expect(atDate).toBeNull();
|
|
92
|
+
expect(aboveDate).toBeNull();
|
|
93
|
+
});
|
|
94
|
+
it('should return an error message if the date is below the minimum', () => {
|
|
95
|
+
const schema = { type: 'string', format: 'date', minimum: '2022-01-01' };
|
|
96
|
+
const check = getBelowMinimumDateCheck(schema, mockErrorMessageFunctions);
|
|
97
|
+
expect(check('2021-12-31')).toBe('minimumDate');
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
describe('getNotAdheringToPatternCheck', () => {
|
|
101
|
+
it('should return null if the string adheres to the pattern', () => {
|
|
102
|
+
const schema = { type: 'string', pattern: '[A-Za-z]+' };
|
|
103
|
+
const check = getNotAdheringToPatternCheck(schema, mockErrorMessageFunctions);
|
|
104
|
+
expect(check('Hello')).toBeNull();
|
|
105
|
+
});
|
|
106
|
+
it('should return null if the string is empty', () => {
|
|
107
|
+
const schema = { type: 'string', pattern: '[A-Za-z]+' };
|
|
108
|
+
const check = getNotAdheringToPatternCheck(schema, mockErrorMessageFunctions);
|
|
109
|
+
expect(check('')).toBeNull();
|
|
110
|
+
});
|
|
111
|
+
it('should return an error message if the string does not adhere to the pattern', () => {
|
|
112
|
+
const schema = { type: 'string', pattern: '[A-Za-z]+' };
|
|
113
|
+
const check = getNotAdheringToPatternCheck(schema, mockErrorMessageFunctions);
|
|
114
|
+
expect(check('01234')).toBe('pattern');
|
|
115
|
+
});
|
|
116
|
+
// Unicode support has been disabled for now
|
|
117
|
+
describe('unicode support (temporarily disabled)', () => {
|
|
118
|
+
it.skip('should return null if string adheres to the pattern', () => {
|
|
119
|
+
const schema = { type: 'string', pattern: '^[A-Za-z0-9\\s\\p{P}]*$' };
|
|
120
|
+
const check = getNotAdheringToPatternCheck(schema, mockErrorMessageFunctions);
|
|
121
|
+
expect(check('23 Bananas!')).toBeNull();
|
|
122
|
+
});
|
|
123
|
+
it.skip('should return an error message if the string does not adhere to the pattern', () => {
|
|
124
|
+
const schema = { type: 'string', pattern: '^[A-Za-z0-9\\s\\p{P}]*$' };
|
|
125
|
+
const check = getNotAdheringToPatternCheck(schema, mockErrorMessageFunctions);
|
|
126
|
+
expect(check('é')).toBe('pattern');
|
|
127
|
+
expect(check('ñ')).toBe('pattern');
|
|
128
|
+
expect(check('❌')).toBe('pattern');
|
|
129
|
+
});
|
|
130
|
+
describe('when a pattern is valid without Unicode support but invalid with Unicode support', () => {
|
|
131
|
+
const logEvent = vi.fn();
|
|
132
|
+
const schema = { type: 'string', pattern: '^\\d{3}\\-?\\d{3}$' };
|
|
133
|
+
it('a logging event should be emitted', () => {
|
|
134
|
+
const check = getNotAdheringToPatternCheck(schema, mockErrorMessageFunctions, {
|
|
135
|
+
logEvent,
|
|
136
|
+
});
|
|
137
|
+
expect(logEvent).toHaveBeenCalledWith('warning', expect.stringMatching(/Failed to instantiate RegExp with Unicode support/), expect.any(Object));
|
|
138
|
+
});
|
|
139
|
+
it(`the check function still works, because it doesn't use Unicode support`, () => {
|
|
140
|
+
const check = getNotAdheringToPatternCheck(schema, mockErrorMessageFunctions, {
|
|
141
|
+
logEvent,
|
|
142
|
+
});
|
|
143
|
+
expect(check('123-123')).toBeNull();
|
|
144
|
+
expect(check('123123')).toBeNull();
|
|
145
|
+
expect(check('123')).toBe('pattern');
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
describe('getAboveMaxItemsCheck', () => {
|
|
151
|
+
const arraySchema = {
|
|
152
|
+
type: 'array',
|
|
153
|
+
items: { type: 'string' },
|
|
154
|
+
addItemTitle: '',
|
|
155
|
+
editItemTitle: '',
|
|
156
|
+
maxItems: 5,
|
|
157
|
+
};
|
|
158
|
+
it('should return null if the array length is below or equal to the maxItems', () => {
|
|
159
|
+
const check = getAboveMaxItemsCheck(arraySchema, mockErrorMessageFunctions);
|
|
160
|
+
const belowLength = check(['0']);
|
|
161
|
+
const atLength = check(['0', '1', '2', '3', '4']);
|
|
162
|
+
expect(belowLength).toBeNull();
|
|
163
|
+
expect(atLength).toBeNull();
|
|
164
|
+
});
|
|
165
|
+
it('should return an error message if the array length is above the maxItems', () => {
|
|
166
|
+
const check = getAboveMaxItemsCheck(arraySchema, mockErrorMessageFunctions);
|
|
167
|
+
expect(check(['0', '1', '2', '3', '4', '5'])).toBe('maxItems');
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
describe('getBelowMinItemsCheck', () => {
|
|
171
|
+
const arraySchema = {
|
|
172
|
+
type: 'array',
|
|
173
|
+
items: { type: 'string' },
|
|
174
|
+
addItemTitle: '',
|
|
175
|
+
editItemTitle: '',
|
|
176
|
+
minItems: 3,
|
|
177
|
+
};
|
|
178
|
+
it('should return null if the array length is above or equal to the minItems', () => {
|
|
179
|
+
const check = getBelowMinItemsCheck(arraySchema, mockErrorMessageFunctions);
|
|
180
|
+
const atLength = check(['0', '1', '2']);
|
|
181
|
+
const aboveLength = check(['0', '1', '2', '3']);
|
|
182
|
+
expect(atLength).toBeNull();
|
|
183
|
+
expect(aboveLength).toBeNull();
|
|
184
|
+
});
|
|
185
|
+
it('should return null if the array is empty', () => {
|
|
186
|
+
const check = getBelowMinItemsCheck(arraySchema, mockErrorMessageFunctions);
|
|
187
|
+
const empty = check([]);
|
|
188
|
+
expect(empty).toBeNull();
|
|
189
|
+
});
|
|
190
|
+
it('should return an error message if the array length is below the minItems', () => {
|
|
191
|
+
const check = getBelowMinItemsCheck(arraySchema, mockErrorMessageFunctions);
|
|
192
|
+
expect(check(['0', '1'])).toBe('minItems');
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
describe('getAboveMaxFilesCheck', () => {
|
|
196
|
+
const arraySchema = {
|
|
197
|
+
type: 'array',
|
|
198
|
+
items: { type: 'string' },
|
|
199
|
+
addItemTitle: '',
|
|
200
|
+
editItemTitle: '',
|
|
201
|
+
maxItems: 2,
|
|
202
|
+
};
|
|
203
|
+
it('should return null if the array length is below or equal to the maxItems', () => {
|
|
204
|
+
const check = getAboveMaxFilesCheck(arraySchema, mockErrorMessageFunctions);
|
|
205
|
+
const belowLength = check([new File([new Blob()], '0')]);
|
|
206
|
+
const atLength = check([new File([new Blob()], '0'), new File([new Blob()], '1')]);
|
|
207
|
+
expect(belowLength).toBeNull();
|
|
208
|
+
expect(atLength).toBeNull();
|
|
209
|
+
});
|
|
210
|
+
it('should return an error message if the array length is above the maxItems', () => {
|
|
211
|
+
const check = getAboveMaxFilesCheck(arraySchema, mockErrorMessageFunctions);
|
|
212
|
+
expect(check([
|
|
213
|
+
new File([new Blob()], '0'),
|
|
214
|
+
new File([new Blob()], '1'),
|
|
215
|
+
new File([new Blob()], '2'),
|
|
216
|
+
])).toBe('maxFiles');
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
describe('getBelowMinFilesCheck', () => {
|
|
220
|
+
const arraySchema = {
|
|
221
|
+
type: 'array',
|
|
222
|
+
items: { type: 'string' },
|
|
223
|
+
addItemTitle: '',
|
|
224
|
+
editItemTitle: '',
|
|
225
|
+
minItems: 2,
|
|
226
|
+
};
|
|
227
|
+
it('should return null if the array length is above or equal to the minItems', () => {
|
|
228
|
+
const check = getBelowMinFilesCheck(arraySchema, mockErrorMessageFunctions);
|
|
229
|
+
const atLength = check([new File([new Blob()], '0'), new File([new Blob()], '1')]);
|
|
230
|
+
const aboveLength = check([
|
|
231
|
+
new File([new Blob()], '0'),
|
|
232
|
+
new File([new Blob()], '1'),
|
|
233
|
+
new File([new Blob()], '2'),
|
|
234
|
+
]);
|
|
235
|
+
expect(atLength).toBeNull();
|
|
236
|
+
expect(aboveLength).toBeNull();
|
|
237
|
+
});
|
|
238
|
+
it('should return null if the array is empty', () => {
|
|
239
|
+
const check = getBelowMinFilesCheck(arraySchema, mockErrorMessageFunctions);
|
|
240
|
+
const empty = check([]);
|
|
241
|
+
expect(empty).toBeNull();
|
|
242
|
+
});
|
|
243
|
+
it('should return an error message if the array length is below the minItems', () => {
|
|
244
|
+
const check = getBelowMinFilesCheck(arraySchema, mockErrorMessageFunctions);
|
|
245
|
+
expect(check([new File([new Blob()], '0')])).toBe('minFiles');
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
describe('getValidDateCheck', () => {
|
|
249
|
+
it('should return null for partial date strings when not required', () => {
|
|
250
|
+
const check = getValidDateCheck(false, mockErrorMessageFunctions);
|
|
251
|
+
expect(check('2012-01')).toBeNull();
|
|
252
|
+
});
|
|
253
|
+
it('should return null for valid date strings when required', () => {
|
|
254
|
+
const check = getValidDateCheck(true, mockErrorMessageFunctions);
|
|
255
|
+
expect(check('2012-01-01')).toBeNull();
|
|
256
|
+
});
|
|
257
|
+
it('should return a validation for partial date strings when required', () => {
|
|
258
|
+
const check = getValidDateCheck(true, mockErrorMessageFunctions);
|
|
259
|
+
expect(check('2012-01')).not.toBeNull();
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { isNullish } from '../../../utils/type-validators';
|
|
2
|
+
import { debounce } from '../../components/utils/debounce';
|
|
3
|
+
import { abortAndResetController } from '../utils/http-utils';
|
|
4
|
+
/**
|
|
5
|
+
* Creates an onValidateAsync handler for a component.
|
|
6
|
+
*/
|
|
7
|
+
export const getComponentValidationAsync = (update, performValidationAsync) =>
|
|
8
|
+
/**
|
|
9
|
+
* Will update the validationAsyncState when a new request is made, and will update
|
|
10
|
+
* the description or set errors when the request completes.
|
|
11
|
+
*/
|
|
12
|
+
async (component, currentValue) => {
|
|
13
|
+
const { abortController } = component.validationAsyncState;
|
|
14
|
+
const newAbortController = abortAndResetController(abortController);
|
|
15
|
+
if (isNullish(currentValue)) {
|
|
16
|
+
update(component, (draft) => {
|
|
17
|
+
draft.validationAsyncState = {
|
|
18
|
+
abortController: newAbortController,
|
|
19
|
+
lastSubmitted: currentValue,
|
|
20
|
+
messages: {},
|
|
21
|
+
};
|
|
22
|
+
});
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const { signal } = newAbortController;
|
|
26
|
+
const newSubmission = performValidationAsync({ value: currentValue, signal })
|
|
27
|
+
.then((message) => {
|
|
28
|
+
update(component, (draft) => {
|
|
29
|
+
if (message) {
|
|
30
|
+
draft.validationAsyncState.messages.success = message;
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
return message;
|
|
34
|
+
})
|
|
35
|
+
.catch((error) => {
|
|
36
|
+
if (error instanceof DOMException && error.name === 'AbortError') {
|
|
37
|
+
// No op, the request was aborted
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
update(component, (draft) => {
|
|
41
|
+
draft.validationAsyncState.messages.error = error.message;
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
update(component, (draft) => {
|
|
45
|
+
draft.validationAsyncState = {
|
|
46
|
+
abortController: newAbortController,
|
|
47
|
+
lastSubmitted: currentValue,
|
|
48
|
+
messages: {},
|
|
49
|
+
};
|
|
50
|
+
});
|
|
51
|
+
return newSubmission;
|
|
52
|
+
};
|
|
53
|
+
export const getDebouncedComponentValidationAsync = (update, performValidationAsync) => debounce(getComponentValidationAsync(update, performValidationAsync), 1000);
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { waitFor } from '@testing-library/react';
|
|
2
|
+
import { vi } from 'vitest';
|
|
3
|
+
import { abortableDelay } from '../../../test-utils/fetch-utils';
|
|
4
|
+
import { createTextInputComponent } from '../../components/TextInputComponent';
|
|
5
|
+
import { getInputUpdateFunction } from '../../components/utils/component-utils';
|
|
6
|
+
import { getUpdateFunctionMock } from '../../mappers/schema/tests/test-utils';
|
|
7
|
+
import { getComponentValidationAsync } from './getComponentValidationAsync';
|
|
8
|
+
import { getInitialValidationAsyncState } from './getInitialValidationAsyncState';
|
|
9
|
+
const defaultProps = {
|
|
10
|
+
uid: '123',
|
|
11
|
+
checks: [],
|
|
12
|
+
analyticsId: 'analyticsId',
|
|
13
|
+
autoComplete: 'off',
|
|
14
|
+
disabled: true,
|
|
15
|
+
errors: [],
|
|
16
|
+
hidden: false,
|
|
17
|
+
id: 'id',
|
|
18
|
+
required: false,
|
|
19
|
+
validationAsyncState: getInitialValidationAsyncState(),
|
|
20
|
+
value: '',
|
|
21
|
+
onPersistAsync: undefined,
|
|
22
|
+
performRefresh: undefined,
|
|
23
|
+
schemaOnChange: undefined,
|
|
24
|
+
onValueChange: () => { },
|
|
25
|
+
summariser: () => ({}),
|
|
26
|
+
};
|
|
27
|
+
describe('getComponentValidationAsync', () => {
|
|
28
|
+
it('should make request and update message if response is ok', async () => {
|
|
29
|
+
const performValidationAsync = vi.fn().mockResolvedValue('Everything is ok');
|
|
30
|
+
const mockUpdateFunction = getUpdateFunctionMock(() => inputComponent);
|
|
31
|
+
const inputComponent = createTextInputComponent(Object.assign(Object.assign({}, defaultProps), { performValidationAsync, value: 'test' }), mockUpdateFunction);
|
|
32
|
+
const update = getInputUpdateFunction(mockUpdateFunction);
|
|
33
|
+
const validate = getComponentValidationAsync(update, performValidationAsync);
|
|
34
|
+
void validate(inputComponent, inputComponent.getLocalValue());
|
|
35
|
+
expect(performValidationAsync).toHaveBeenCalledWith(expect.objectContaining({ value: 'test' }));
|
|
36
|
+
await waitFor(() => expect(inputComponent.validationAsyncState.messages.success).toBe('Everything is ok'));
|
|
37
|
+
});
|
|
38
|
+
it('should set component errors if validation fails', async () => {
|
|
39
|
+
const errorMessage = 'This field is invalid';
|
|
40
|
+
const performValidationAsync = vi.fn().mockRejectedValue(new Error(errorMessage));
|
|
41
|
+
const mockUpdateFunction = getUpdateFunctionMock(() => inputComponent);
|
|
42
|
+
const inputComponent = createTextInputComponent(Object.assign(Object.assign({}, defaultProps), { performValidationAsync, value: 'test' }), mockUpdateFunction);
|
|
43
|
+
const update = getInputUpdateFunction(mockUpdateFunction);
|
|
44
|
+
const validate = getComponentValidationAsync(update, performValidationAsync);
|
|
45
|
+
void validate(inputComponent, inputComponent.getLocalValue());
|
|
46
|
+
await waitFor(() => expect(inputComponent.validationAsyncState.messages.error).toEqual(errorMessage));
|
|
47
|
+
});
|
|
48
|
+
it('should ignore previous responses if a second persist has been triggered', async () => {
|
|
49
|
+
const performValidationAsync = vi
|
|
50
|
+
.fn()
|
|
51
|
+
.mockImplementationOnce(async ({ signal }) => abortableDelay(200, signal).then(() => 'response-1'))
|
|
52
|
+
.mockImplementationOnce(async ({ signal }) => abortableDelay(10, signal).then(() => 'response-2'));
|
|
53
|
+
const mockUpdateFunction = getUpdateFunctionMock(() => inputComponent);
|
|
54
|
+
const inputComponent = createTextInputComponent(Object.assign(Object.assign({}, defaultProps), { performValidationAsync, value: 'test' }), mockUpdateFunction);
|
|
55
|
+
const update = getInputUpdateFunction(mockUpdateFunction);
|
|
56
|
+
const validate = getComponentValidationAsync(update, performValidationAsync);
|
|
57
|
+
void validate(inputComponent, inputComponent.getLocalValue());
|
|
58
|
+
inputComponent.onChange('new-value');
|
|
59
|
+
void validate(inputComponent, inputComponent.getLocalValue());
|
|
60
|
+
// Second callback has resolved
|
|
61
|
+
await vi.advanceTimersByTimeAsync(100);
|
|
62
|
+
await waitFor(() => expect(inputComponent.validationAsyncState.messages.success).toBe('response-2'));
|
|
63
|
+
// First callback has resolved, but value is ignored
|
|
64
|
+
await vi.advanceTimersByTimeAsync(100);
|
|
65
|
+
await waitFor(() => expect(inputComponent.validationAsyncState.messages.success).toBe('response-2'));
|
|
66
|
+
});
|
|
67
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { isObject, isString } from '../../../utils/type-validators';
|
|
2
|
+
import { constructPayload } from '../utils/http-utils';
|
|
3
|
+
import { getAnalyticsFromErrorResponse } from '../utils/response-utils';
|
|
4
|
+
/**
|
|
5
|
+
* Takes an httpClient and schema validation async config and returns a function that can
|
|
6
|
+
* execute a validation async request.
|
|
7
|
+
*/
|
|
8
|
+
export const getPerformValidationAsync = ({ httpClient, validationAsyncConfig, schemaId, trackEvent, }) => {
|
|
9
|
+
const { method, param, url } = validationAsyncConfig;
|
|
10
|
+
const trackFailureAndReturn = (json) => {
|
|
11
|
+
const analytics = getAnalyticsFromErrorResponse(json);
|
|
12
|
+
trackEvent('ValidationAsync Failed', Object.assign({ schema: schemaId }, analytics));
|
|
13
|
+
return null;
|
|
14
|
+
};
|
|
15
|
+
return async function performValidationAsync({ value, signal }) {
|
|
16
|
+
let response;
|
|
17
|
+
trackEvent('ValidationAsync Triggered', { schema: schemaId });
|
|
18
|
+
try {
|
|
19
|
+
response = await httpClient(url, constructPayload({ value, signal, requestConfig: { method, param } }));
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
return trackFailureAndReturn();
|
|
23
|
+
}
|
|
24
|
+
const json = (await response.json().catch(() => null));
|
|
25
|
+
const message = getValidationMessage(json);
|
|
26
|
+
if (response.ok) {
|
|
27
|
+
trackEvent('ValidationAsync Succeeded', { schema: schemaId });
|
|
28
|
+
return message;
|
|
29
|
+
}
|
|
30
|
+
if (response.status === 422) {
|
|
31
|
+
if (message) {
|
|
32
|
+
trackEvent('ValidationAsync Succeeded', { schema: schemaId });
|
|
33
|
+
throw new Error(message);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return trackFailureAndReturn(json);
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
const getValidationMessage = (json) => {
|
|
40
|
+
if (!isObject(json)) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
const { message } = json;
|
|
44
|
+
return isString(message) ? message : null;
|
|
45
|
+
};
|