@nocobase/flow-engine 2.0.0-alpha.2
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/LICENSE +661 -0
- package/README.md +30 -0
- package/lib/ContextPathProxy.d.ts +17 -0
- package/lib/ContextPathProxy.js +65 -0
- package/lib/ElementProxy.d.ts +17 -0
- package/lib/ElementProxy.js +93 -0
- package/lib/FlowContextProvider.d.ts +24 -0
- package/lib/FlowContextProvider.js +82 -0
- package/lib/FlowDefinition.d.ts +423 -0
- package/lib/FlowDefinition.js +257 -0
- package/lib/JSRunner.d.ts +32 -0
- package/lib/JSRunner.js +95 -0
- package/lib/ReactView.d.ts +20 -0
- package/lib/ReactView.js +120 -0
- package/lib/ViewScopedFlowEngine.d.ts +23 -0
- package/lib/ViewScopedFlowEngine.js +81 -0
- package/lib/acl/Acl.d.ts +31 -0
- package/lib/acl/Acl.js +115 -0
- package/lib/action-registry/BaseActionRegistry.d.ts +23 -0
- package/lib/action-registry/BaseActionRegistry.js +57 -0
- package/lib/action-registry/EngineActionRegistry.d.ts +20 -0
- package/lib/action-registry/EngineActionRegistry.js +47 -0
- package/lib/action-registry/ModelActionRegistry.d.ts +34 -0
- package/lib/action-registry/ModelActionRegistry.js +79 -0
- package/lib/components/DynamicFlowsEditor.d.ts +17 -0
- package/lib/components/DynamicFlowsEditor.js +49 -0
- package/lib/components/FieldModelRenderer.d.ts +10 -0
- package/lib/components/FieldModelRenderer.js +94 -0
- package/lib/components/FlowContextSelector.d.ts +11 -0
- package/lib/components/FlowContextSelector.js +221 -0
- package/lib/components/FlowErrorFallback.d.ts +25 -0
- package/lib/components/FlowErrorFallback.js +264 -0
- package/lib/components/FlowModelRenderer.d.ts +64 -0
- package/lib/components/FlowModelRenderer.js +254 -0
- package/lib/components/FormItem.d.ts +18 -0
- package/lib/components/FormItem.js +147 -0
- package/lib/components/common/FlowSettingsButton.d.ts +11 -0
- package/lib/components/common/FlowSettingsButton.js +66 -0
- package/lib/components/common/index.d.ts +9 -0
- package/lib/components/common/index.js +30 -0
- package/lib/components/common/withFlowDesignMode.d.ts +26 -0
- package/lib/components/common/withFlowDesignMode.js +61 -0
- package/lib/components/dnd/getMousePositionOnElement.d.ts +50 -0
- package/lib/components/dnd/getMousePositionOnElement.js +95 -0
- package/lib/components/dnd/index.d.ts +24 -0
- package/lib/components/dnd/index.js +164 -0
- package/lib/components/dnd/moveBlock.d.ts +33 -0
- package/lib/components/dnd/moveBlock.js +302 -0
- package/lib/components/index.d.ts +18 -0
- package/lib/components/index.js +48 -0
- package/lib/components/settings/independents/dropdown/FlowsDropdownButton.d.ts +46 -0
- package/lib/components/settings/independents/dropdown/FlowsDropdownButton.js +225 -0
- package/lib/components/settings/independents/dropdown/index.d.ts +9 -0
- package/lib/components/settings/independents/dropdown/index.js +30 -0
- package/lib/components/settings/independents/index.d.ts +1 -0
- package/lib/components/settings/independents/index.js +30 -0
- package/lib/components/settings/index.d.ts +10 -0
- package/lib/components/settings/index.js +32 -0
- package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.d.ts +24 -0
- package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +501 -0
- package/lib/components/settings/wrappers/contextual/FlowsContextMenu.d.ts +45 -0
- package/lib/components/settings/wrappers/contextual/FlowsContextMenu.js +231 -0
- package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.d.ts +111 -0
- package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.js +484 -0
- package/lib/components/settings/wrappers/contextual/StepRequiredSettingsDialog.d.ts +26 -0
- package/lib/components/settings/wrappers/contextual/StepRequiredSettingsDialog.js +342 -0
- package/lib/components/settings/wrappers/contextual/StepSettings.d.ts +23 -0
- package/lib/components/settings/wrappers/contextual/StepSettings.js +110 -0
- package/lib/components/settings/wrappers/contextual/StepSettingsDialog.d.ts +20 -0
- package/lib/components/settings/wrappers/contextual/StepSettingsDialog.js +206 -0
- package/lib/components/settings/wrappers/contextual/StepSettingsDrawer.d.ts +20 -0
- package/lib/components/settings/wrappers/contextual/StepSettingsDrawer.js +47 -0
- package/lib/components/settings/wrappers/contextual/index.d.ts +14 -0
- package/lib/components/settings/wrappers/contextual/index.js +40 -0
- package/lib/components/settings/wrappers/embedded/FlowSettings.d.ts +33 -0
- package/lib/components/settings/wrappers/embedded/FlowSettings.js +207 -0
- package/lib/components/settings/wrappers/embedded/FlowsSettings.d.ts +41 -0
- package/lib/components/settings/wrappers/embedded/FlowsSettings.js +84 -0
- package/lib/components/settings/wrappers/embedded/FlowsSettingsContent.d.ts +16 -0
- package/lib/components/settings/wrappers/embedded/FlowsSettingsContent.js +88 -0
- package/lib/components/settings/wrappers/embedded/index.d.ts +10 -0
- package/lib/components/settings/wrappers/embedded/index.js +32 -0
- package/lib/components/settings/wrappers/index.d.ts +2 -0
- package/lib/components/settings/wrappers/index.js +32 -0
- package/lib/components/subModel/AddSubModelButton.d.ts +62 -0
- package/lib/components/subModel/AddSubModelButton.js +415 -0
- package/lib/components/subModel/LazyDropdown.d.ts +55 -0
- package/lib/components/subModel/LazyDropdown.js +524 -0
- package/lib/components/subModel/index.d.ts +10 -0
- package/lib/components/subModel/index.js +32 -0
- package/lib/components/subModel/utils.d.ts +34 -0
- package/lib/components/subModel/utils.js +287 -0
- package/lib/components/variables/InlineVariableTag.d.ts +21 -0
- package/lib/components/variables/InlineVariableTag.js +123 -0
- package/lib/components/variables/SlateVariableEditor.d.ts +46 -0
- package/lib/components/variables/SlateVariableEditor.js +302 -0
- package/lib/components/variables/VariableInput.d.ts +11 -0
- package/lib/components/variables/VariableInput.js +322 -0
- package/lib/components/variables/VariableTag.d.ts +11 -0
- package/lib/components/variables/VariableTag.js +148 -0
- package/lib/components/variables/VariableTrigger.d.ts +20 -0
- package/lib/components/variables/VariableTrigger.js +136 -0
- package/lib/components/variables/index.d.ts +15 -0
- package/lib/components/variables/index.js +53 -0
- package/lib/components/variables/types.d.ts +93 -0
- package/lib/components/variables/types.js +24 -0
- package/lib/components/variables/useResolvedMetaTree.d.ts +19 -0
- package/lib/components/variables/useResolvedMetaTree.js +91 -0
- package/lib/components/variables/utils.d.ts +22 -0
- package/lib/components/variables/utils.js +177 -0
- package/lib/data-source/index.d.ts +180 -0
- package/lib/data-source/index.js +733 -0
- package/lib/data-source/jioToJoiSchema.d.ts +19 -0
- package/lib/data-source/jioToJoiSchema.js +114 -0
- package/lib/decorators/index.d.ts +9 -0
- package/lib/decorators/index.js +36 -0
- package/lib/decorators/largeField.d.ts +9 -0
- package/lib/decorators/largeField.js +42 -0
- package/lib/emitter.d.ts +16 -0
- package/lib/emitter.js +58 -0
- package/lib/event-registry/BaseEventRegistry.d.ts +22 -0
- package/lib/event-registry/BaseEventRegistry.js +57 -0
- package/lib/event-registry/EngineEventRegistry.d.ts +19 -0
- package/lib/event-registry/EngineEventRegistry.js +47 -0
- package/lib/event-registry/ModelEventRegistry.d.ts +33 -0
- package/lib/event-registry/ModelEventRegistry.js +79 -0
- package/lib/executor/FlowExecutor.d.ts +26 -0
- package/lib/executor/FlowExecutor.js +262 -0
- package/lib/flow-registry/BaseFlowRegistry.d.ts +46 -0
- package/lib/flow-registry/BaseFlowRegistry.js +86 -0
- package/lib/flow-registry/GlobalFlowRegistry.d.ts +22 -0
- package/lib/flow-registry/GlobalFlowRegistry.js +95 -0
- package/lib/flow-registry/InstanceFlowRegistry.d.ts +21 -0
- package/lib/flow-registry/InstanceFlowRegistry.js +59 -0
- package/lib/flow-registry/index.d.ts +11 -0
- package/lib/flow-registry/index.js +34 -0
- package/lib/flowContext.d.ts +215 -0
- package/lib/flowContext.js +1266 -0
- package/lib/flowEngine.d.ts +340 -0
- package/lib/flowEngine.js +781 -0
- package/lib/flowI18n.d.ts +46 -0
- package/lib/flowI18n.js +117 -0
- package/lib/flowSettings.d.ts +266 -0
- package/lib/flowSettings.js +850 -0
- package/lib/hooks/index.d.ts +14 -0
- package/lib/hooks/index.js +40 -0
- package/lib/hooks/useApplyAutoFlows.d.ts +21 -0
- package/lib/hooks/useApplyAutoFlows.js +62 -0
- package/lib/hooks/useFlowModel.d.ts +29 -0
- package/lib/hooks/useFlowModel.js +72 -0
- package/lib/hooks/useFlowModelById.d.ts +11 -0
- package/lib/hooks/useFlowModelById.js +61 -0
- package/lib/hooks/useFlowSettingsContext.d.ts +20 -0
- package/lib/hooks/useFlowSettingsContext.js +61 -0
- package/lib/hooks/useFlowStep.d.ts +17 -0
- package/lib/hooks/useFlowStep.js +56 -0
- package/lib/hooks/useNiceDropdownMaxHeight.d.ts +13 -0
- package/lib/hooks/useNiceDropdownMaxHeight.js +52 -0
- package/lib/index.d.ts +27 -0
- package/lib/index.js +73 -0
- package/lib/locale/en-US.json +61 -0
- package/lib/locale/index.d.ts +141 -0
- package/lib/locale/index.js +70 -0
- package/lib/locale/zh-CN.json +61 -0
- package/lib/models/CollectionFieldModel.d.ts +50 -0
- package/lib/models/CollectionFieldModel.js +242 -0
- package/lib/models/DisplayItemModel.d.ts +12 -0
- package/lib/models/DisplayItemModel.js +41 -0
- package/lib/models/EditableItemModel.d.ts +12 -0
- package/lib/models/EditableItemModel.js +41 -0
- package/lib/models/FilterableItemModel.d.ts +12 -0
- package/lib/models/FilterableItemModel.js +41 -0
- package/lib/models/flowModel.d.ts +344 -0
- package/lib/models/flowModel.js +1133 -0
- package/lib/models/forkFlowModel.d.ts +83 -0
- package/lib/models/forkFlowModel.js +257 -0
- package/lib/models/index.d.ts +14 -0
- package/lib/models/index.js +40 -0
- package/lib/provider.d.ts +22 -0
- package/lib/provider.js +114 -0
- package/lib/resources/apiResource.d.ts +34 -0
- package/lib/resources/apiResource.js +153 -0
- package/lib/resources/baseRecordResource.d.ts +61 -0
- package/lib/resources/baseRecordResource.js +264 -0
- package/lib/resources/filterItem.d.ts +33 -0
- package/lib/resources/filterItem.js +93 -0
- package/lib/resources/flowResource.d.ts +45 -0
- package/lib/resources/flowResource.js +146 -0
- package/lib/resources/index.d.ts +15 -0
- package/lib/resources/index.js +42 -0
- package/lib/resources/multiRecordResource.d.ts +53 -0
- package/lib/resources/multiRecordResource.js +230 -0
- package/lib/resources/singleRecordResource.d.ts +23 -0
- package/lib/resources/singleRecordResource.js +111 -0
- package/lib/resources/sqlResource.d.ts +73 -0
- package/lib/resources/sqlResource.js +294 -0
- package/lib/runjs-context/contexts/FlowRunJSContext.d.ts +38 -0
- package/lib/runjs-context/contexts/FlowRunJSContext.js +217 -0
- package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.d.ts +16 -0
- package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.js +66 -0
- package/lib/runjs-context/contexts/JSBlockRunJSContext.d.ts +16 -0
- package/lib/runjs-context/contexts/JSBlockRunJSContext.js +78 -0
- package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.d.ts +12 -0
- package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.js +59 -0
- package/lib/runjs-context/contexts/JSFieldRunJSContext.d.ts +16 -0
- package/lib/runjs-context/contexts/JSFieldRunJSContext.js +70 -0
- package/lib/runjs-context/contexts/JSItemRunJSContext.d.ts +16 -0
- package/lib/runjs-context/contexts/JSItemRunJSContext.js +66 -0
- package/lib/runjs-context/contexts/JSRecordActionRunJSContext.d.ts +12 -0
- package/lib/runjs-context/contexts/JSRecordActionRunJSContext.js +61 -0
- package/lib/runjs-context/contexts/LinkageRunJSContext.d.ts +12 -0
- package/lib/runjs-context/contexts/LinkageRunJSContext.js +62 -0
- package/lib/runjs-context/helpers.d.ts +17 -0
- package/lib/runjs-context/helpers.js +79 -0
- package/lib/runjs-context/index.d.ts +19 -0
- package/lib/runjs-context/index.js +57 -0
- package/lib/runjs-context/registry.d.ts +17 -0
- package/lib/runjs-context/registry.js +93 -0
- package/lib/runjs-context/snippets/global/api-request-get.snippet.d.ts +16 -0
- package/lib/runjs-context/snippets/global/api-request-get.snippet.js +42 -0
- package/lib/runjs-context/snippets/global/api-request-post.snippet.d.ts +16 -0
- package/lib/runjs-context/snippets/global/api-request-post.snippet.js +42 -0
- package/lib/runjs-context/snippets/global/console-log-ctx.snippet.d.ts +16 -0
- package/lib/runjs-context/snippets/global/console-log-ctx.snippet.js +41 -0
- package/lib/runjs-context/snippets/global/copy-record-json.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/copy-record-json.snippet.js +42 -0
- package/lib/runjs-context/snippets/global/copy-to-clipboard.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/copy-to-clipboard.snippet.js +42 -0
- package/lib/runjs-context/snippets/global/log-json-record.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/log-json-record.snippet.js +42 -0
- package/lib/runjs-context/snippets/global/message-error.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/message-error.snippet.js +41 -0
- package/lib/runjs-context/snippets/global/message-success.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/message-success.snippet.js +41 -0
- package/lib/runjs-context/snippets/global/notification-open.snippet.d.ts +16 -0
- package/lib/runjs-context/snippets/global/notification-open.snippet.js +43 -0
- package/lib/runjs-context/snippets/global/open-view-dialog.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/open-view-dialog.snippet.js +47 -0
- package/lib/runjs-context/snippets/global/open-view-drawer.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/open-view-drawer.snippet.js +47 -0
- package/lib/runjs-context/snippets/global/requireAsync.snippet.d.ts +16 -0
- package/lib/runjs-context/snippets/global/requireAsync.snippet.js +46 -0
- package/lib/runjs-context/snippets/global/sleep.snippet.d.ts +16 -0
- package/lib/runjs-context/snippets/global/sleep.snippet.js +43 -0
- package/lib/runjs-context/snippets/global/try-catch-async.snippet.d.ts +16 -0
- package/lib/runjs-context/snippets/global/try-catch-async.snippet.js +44 -0
- package/lib/runjs-context/snippets/global/view-navigation-push.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/view-navigation-push.snippet.js +44 -0
- package/lib/runjs-context/snippets/global/window-open.snippet.d.ts +16 -0
- package/lib/runjs-context/snippets/global/window-open.snippet.js +41 -0
- package/lib/runjs-context/snippets/index.d.ts +11 -0
- package/lib/runjs-context/snippets/index.js +94 -0
- package/lib/runjs-context/snippets/libs/echarts-init.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/libs/echarts-init.snippet.js +46 -0
- package/lib/runjs-context/snippets/scene/actions/collection-selected-count.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/actions/collection-selected-count.snippet.js +44 -0
- package/lib/runjs-context/snippets/scene/actions/iterate-selected-rows.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/actions/iterate-selected-rows.snippet.js +43 -0
- package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.js +43 -0
- package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.js +40 -0
- package/lib/runjs-context/snippets/scene/jsblock/add-event-listener.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsblock/add-event-listener.snippet.js +46 -0
- package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.js +42 -0
- package/lib/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.js +46 -0
- package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.js +41 -0
- package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.js +41 -0
- package/lib/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.js +46 -0
- package/lib/runjs-context/snippets/scene/jsblock/render-card.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/jsblock/render-card.snippet.js +45 -0
- package/lib/runjs-context/snippets/scene/jsblock/render-react.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsblock/render-react.snippet.js +56 -0
- package/lib/runjs-context/snippets/scene/jsfield/color-by-value.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsfield/color-by-value.snippet.js +42 -0
- package/lib/runjs-context/snippets/scene/jsfield/format-number.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsfield/format-number.snippet.js +41 -0
- package/lib/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.js +40 -0
- package/lib/runjs-context/snippets/scene/jsitem/render-basic.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsitem/render-basic.snippet.js +44 -0
- package/lib/runjs-context/snippets/scene/linkage/set-disabled.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/linkage/set-disabled.snippet.js +60 -0
- package/lib/runjs-context/snippets/scene/linkage/set-field-value.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/linkage/set-field-value.snippet.js +59 -0
- package/lib/runjs-context/snippets/scene/linkage/set-required.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/linkage/set-required.snippet.js +60 -0
- package/lib/runjs-context/snippets/scene/linkage/toggle-visible.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/linkage/toggle-visible.snippet.js +60 -0
- package/lib/runjs-context/snippets/types.d.ts +16 -0
- package/lib/runjs-context/snippets/types.js +24 -0
- package/lib/types.d.ts +398 -0
- package/lib/types.js +43 -0
- package/lib/utils/autoFlowError.d.ts +16 -0
- package/lib/utils/autoFlowError.js +53 -0
- package/lib/utils/constants.d.ts +29 -0
- package/lib/utils/constants.js +77 -0
- package/lib/utils/context.d.ts +40 -0
- package/lib/utils/context.js +63 -0
- package/lib/utils/createCollectionContextMeta.d.ts +11 -0
- package/lib/utils/createCollectionContextMeta.js +117 -0
- package/lib/utils/exceptions.d.ts +22 -0
- package/lib/utils/exceptions.js +62 -0
- package/lib/utils/flow-definitions.d.ts +11 -0
- package/lib/utils/flow-definitions.js +40 -0
- package/lib/utils/index.d.ts +22 -0
- package/lib/utils/index.js +117 -0
- package/lib/utils/inheritance.d.ts +16 -0
- package/lib/utils/inheritance.js +53 -0
- package/lib/utils/params-resolvers.d.ts +51 -0
- package/lib/utils/params-resolvers.js +309 -0
- package/lib/utils/parsePathnameToViewParams.d.ts +34 -0
- package/lib/utils/parsePathnameToViewParams.js +84 -0
- package/lib/utils/safeGlobals.d.ts +16 -0
- package/lib/utils/safeGlobals.js +179 -0
- package/lib/utils/schema-utils.d.ts +40 -0
- package/lib/utils/schema-utils.js +161 -0
- package/lib/utils/serverContextParams.d.ts +28 -0
- package/lib/utils/serverContextParams.js +106 -0
- package/lib/utils/setupRuntimeContextSteps.d.ts +19 -0
- package/lib/utils/setupRuntimeContextSteps.js +88 -0
- package/lib/utils/translation.d.ts +18 -0
- package/lib/utils/translation.js +58 -0
- package/lib/utils/variablesParams.d.ts +51 -0
- package/lib/utils/variablesParams.js +150 -0
- package/lib/views/DialogComponent.d.ts +22 -0
- package/lib/views/DialogComponent.js +98 -0
- package/lib/views/DrawerComponent.d.ts +11 -0
- package/lib/views/DrawerComponent.js +101 -0
- package/lib/views/FlowView.d.ts +76 -0
- package/lib/views/FlowView.js +81 -0
- package/lib/views/PageComponent.d.ts +10 -0
- package/lib/views/PageComponent.js +167 -0
- package/lib/views/ViewNavigation.d.ts +45 -0
- package/lib/views/ViewNavigation.js +97 -0
- package/lib/views/createViewMeta.d.ts +16 -0
- package/lib/views/createViewMeta.js +171 -0
- package/lib/views/index.d.ts +13 -0
- package/lib/views/index.js +48 -0
- package/lib/views/useDialog.d.ts +32 -0
- package/lib/views/useDialog.js +199 -0
- package/lib/views/useDrawer.d.ts +33 -0
- package/lib/views/useDrawer.js +206 -0
- package/lib/views/usePage.d.ts +32 -0
- package/lib/views/usePage.js +193 -0
- package/lib/views/usePatchElement.d.ts +10 -0
- package/lib/views/usePatchElement.js +54 -0
- package/lib/views/usePopover.d.ts +17 -0
- package/lib/views/usePopover.js +159 -0
- package/package.json +37 -0
- package/src/ContextPathProxy.ts +45 -0
- package/src/ElementProxy.ts +69 -0
- package/src/FlowContextProvider.tsx +40 -0
- package/src/FlowDefinition.ts +275 -0
- package/src/JSRunner.ts +84 -0
- package/src/ReactView.tsx +104 -0
- package/src/ViewScopedFlowEngine.ts +75 -0
- package/src/__tests__/ElementProxy.test.ts +51 -0
- package/src/__tests__/JSRunner.test.ts +92 -0
- package/src/__tests__/ReactView.test.tsx +63 -0
- package/src/__tests__/context-path-proxy.test.ts +35 -0
- package/src/__tests__/flow-engine.test.ts +189 -0
- package/src/__tests__/flowContext.test.ts +2012 -0
- package/src/__tests__/flowEngine.saveModel.test.ts +171 -0
- package/src/__tests__/flowI18n.test.ts +28 -0
- package/src/__tests__/flowModel.getFlows.test.ts +61 -0
- package/src/__tests__/flowModel.openView.navigation.test.ts +78 -0
- package/src/__tests__/flowRuntimeContext.test.ts +187 -0
- package/src/__tests__/flowSettings.open.test.tsx +1920 -0
- package/src/__tests__/flowSettings.test.ts +566 -0
- package/src/__tests__/globalFlowRegistry.test.ts +77 -0
- package/src/__tests__/isFieldInterfaceMatch.test.ts +51 -0
- package/src/__tests__/metaTreeNodeCache.test.ts +234 -0
- package/src/__tests__/path-aggregation.test.ts +85 -0
- package/src/__tests__/provider.test.tsx +28 -0
- package/src/__tests__/renderHiddenInConfig.test.tsx +91 -0
- package/src/__tests__/runjsContext.test.ts +60 -0
- package/src/__tests__/viewScopedFlowEngine.test.ts +212 -0
- package/src/acl/Acl.tsx +109 -0
- package/src/acl/__tests__/Acl.test.tsx +72 -0
- package/src/action-registry/BaseActionRegistry.ts +46 -0
- package/src/action-registry/EngineActionRegistry.ts +32 -0
- package/src/action-registry/ModelActionRegistry.ts +75 -0
- package/src/action-registry/__tests__/engineActionRegistry.test.ts +43 -0
- package/src/action-registry/__tests__/modelActionRegistry.test.ts +107 -0
- package/src/components/DynamicFlowsEditor.tsx +318 -0
- package/src/components/FieldModelRenderer.tsx +62 -0
- package/src/components/FlowContextSelector.tsx +255 -0
- package/src/components/FlowErrorFallback.tsx +316 -0
- package/src/components/FlowModelRenderer.tsx +428 -0
- package/src/components/FormItem.tsx +130 -0
- package/src/components/__tests__/flow-model-render-error-fallback.test.tsx +226 -0
- package/src/components/common/FlowSettingsButton.tsx +30 -0
- package/src/components/common/index.ts +10 -0
- package/src/components/common/withFlowDesignMode.tsx +49 -0
- package/src/components/dnd/getMousePositionOnElement.ts +115 -0
- package/src/components/dnd/index.tsx +128 -0
- package/src/components/dnd/moveBlock.ts +379 -0
- package/src/components/index.ts +20 -0
- package/src/components/settings/independents/dropdown/FlowsDropdownButton.tsx +279 -0
- package/src/components/settings/independents/dropdown/index.ts +10 -0
- package/src/components/settings/independents/index.ts +2 -0
- package/src/components/settings/index.ts +11 -0
- package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +617 -0
- package/src/components/settings/wrappers/contextual/FlowsContextMenu.tsx +292 -0
- package/src/components/settings/wrappers/contextual/FlowsFloatContextMenu.tsx +655 -0
- package/src/components/settings/wrappers/contextual/StepRequiredSettingsDialog.tsx +446 -0
- package/src/components/settings/wrappers/contextual/StepSettings.tsx +109 -0
- package/src/components/settings/wrappers/contextual/StepSettingsDialog.tsx +217 -0
- package/src/components/settings/wrappers/contextual/StepSettingsDrawer.tsx +32 -0
- package/src/components/settings/wrappers/contextual/index.ts +15 -0
- package/src/components/settings/wrappers/embedded/FlowSettings.tsx +258 -0
- package/src/components/settings/wrappers/embedded/FlowsSettings.tsx +111 -0
- package/src/components/settings/wrappers/embedded/FlowsSettingsContent.tsx +96 -0
- package/src/components/settings/wrappers/embedded/index.ts +11 -0
- package/src/components/settings/wrappers/index.ts +5 -0
- package/src/components/subModel/AddSubModelButton.tsx +575 -0
- package/src/components/subModel/LazyDropdown.tsx +714 -0
- package/src/components/subModel/__tests__/AddSubModelButton.test.tsx +1185 -0
- package/src/components/subModel/__tests__/buildWrapperFieldChildren.test.ts +192 -0
- package/src/components/subModel/__tests__/utils.test.ts +425 -0
- package/src/components/subModel/index.ts +12 -0
- package/src/components/subModel/utils.ts +278 -0
- package/src/components/variables/InlineVariableTag.tsx +97 -0
- package/src/components/variables/SlateVariableEditor.tsx +384 -0
- package/src/components/variables/VariableInput.tsx +342 -0
- package/src/components/variables/VariableTag.tsx +123 -0
- package/src/components/variables/VariableTrigger.tsx +116 -0
- package/src/components/variables/__tests__/FlowContextSelector.test.tsx +553 -0
- package/src/components/variables/__tests__/VariableInput.test.tsx +550 -0
- package/src/components/variables/__tests__/VariableTag.test.tsx +347 -0
- package/src/components/variables/__tests__/test-utils.tsx +62 -0
- package/src/components/variables/__tests__/utils.test.ts +310 -0
- package/src/components/variables/index.ts +16 -0
- package/src/components/variables/types.ts +100 -0
- package/src/components/variables/useResolvedMetaTree.ts +76 -0
- package/src/components/variables/utils.ts +192 -0
- package/src/data-source/__tests__/collection.test.ts +58 -0
- package/src/data-source/__tests__/index.test.ts +82 -0
- package/src/data-source/__tests__/jioToJoiSchema.test.ts +56 -0
- package/src/data-source/index.ts +812 -0
- package/src/data-source/jioToJoiSchema.ts +103 -0
- package/src/decorators/index.ts +10 -0
- package/src/decorators/largeField.ts +14 -0
- package/src/emitter.ts +33 -0
- package/src/event-registry/BaseEventRegistry.ts +40 -0
- package/src/event-registry/EngineEventRegistry.ts +26 -0
- package/src/event-registry/ModelEventRegistry.ts +69 -0
- package/src/event-registry/__tests__/engineEventRegistry.test.ts +48 -0
- package/src/executor/FlowExecutor.ts +256 -0
- package/src/executor/__tests__/eventStep.test.ts +157 -0
- package/src/executor/__tests__/flowExecutor.test.ts +163 -0
- package/src/flow-registry/BaseFlowRegistry.ts +91 -0
- package/src/flow-registry/GlobalFlowRegistry.ts +82 -0
- package/src/flow-registry/InstanceFlowRegistry.ts +39 -0
- package/src/flow-registry/__tests__/globalFlowRegistry.test.ts +141 -0
- package/src/flow-registry/__tests__/instance-and-global-registry.test.ts +67 -0
- package/src/flow-registry/__tests__/instanceFlowRegistry.test.ts +83 -0
- package/src/flow-registry/index.ts +12 -0
- package/src/flowContext.ts +1639 -0
- package/src/flowEngine.ts +905 -0
- package/src/flowI18n.ts +96 -0
- package/src/flowSettings.ts +1045 -0
- package/src/hooks/index.ts +15 -0
- package/src/hooks/useApplyAutoFlows.ts +51 -0
- package/src/hooks/useFlowModel.tsx +59 -0
- package/src/hooks/useFlowModelById.ts +37 -0
- package/src/hooks/useFlowSettingsContext.tsx +37 -0
- package/src/hooks/useFlowStep.tsx +19 -0
- package/src/hooks/useNiceDropdownMaxHeight.ts +34 -0
- package/src/index.ts +38 -0
- package/src/locale/en-US.json +61 -0
- package/src/locale/index.ts +38 -0
- package/src/locale/zh-CN.json +61 -0
- package/src/models/CollectionFieldModel.tsx +269 -0
- package/src/models/DisplayItemModel.tsx +13 -0
- package/src/models/EditableItemModel.tsx +13 -0
- package/src/models/FilterableItemModel.tsx +13 -0
- package/src/models/__tests__/CollectionFieldModel.test.ts +122 -0
- package/src/models/__tests__/defaultParams-on-create.test.ts +83 -0
- package/src/models/__tests__/flow-model-oninit.test.ts +44 -0
- package/src/models/__tests__/flowModel.actions.integration.test.ts +100 -0
- package/src/models/__tests__/flowModel.getFlows.sort.test.ts +100 -0
- package/src/models/__tests__/flowModel.test.ts +2746 -0
- package/src/models/__tests__/flowRegistry.test.ts +512 -0
- package/src/models/__tests__/forkFlowModel.test.ts +1047 -0
- package/src/models/__tests__/model-actions.test.ts +70 -0
- package/src/models/__tests__/model-events.test.ts +69 -0
- package/src/models/flowModel.tsx +1398 -0
- package/src/models/forkFlowModel.ts +287 -0
- package/src/models/index.ts +17 -0
- package/src/provider.tsx +101 -0
- package/src/resources/__tests__/apiResource.test.ts +201 -0
- package/src/resources/__tests__/baseRecordResource.test.ts +262 -0
- package/src/resources/__tests__/filterItem.test.ts +260 -0
- package/src/resources/__tests__/flowResource.test.ts +127 -0
- package/src/resources/apiResource.ts +148 -0
- package/src/resources/baseRecordResource.ts +279 -0
- package/src/resources/filterItem.ts +74 -0
- package/src/resources/flowResource.ts +143 -0
- package/src/resources/index.ts +17 -0
- package/src/resources/multiRecordResource.ts +219 -0
- package/src/resources/singleRecordResource.ts +83 -0
- package/src/resources/sqlResource.ts +299 -0
- package/src/runjs-context/contexts/FlowRunJSContext.ts +190 -0
- package/src/runjs-context/contexts/FormJSFieldItemRunJSContext.ts +39 -0
- package/src/runjs-context/contexts/JSBlockRunJSContext.ts +52 -0
- package/src/runjs-context/contexts/JSCollectionActionRunJSContext.ts +32 -0
- package/src/runjs-context/contexts/JSFieldRunJSContext.ts +43 -0
- package/src/runjs-context/contexts/JSItemRunJSContext.ts +39 -0
- package/src/runjs-context/contexts/JSRecordActionRunJSContext.ts +34 -0
- package/src/runjs-context/contexts/LinkageRunJSContext.ts +35 -0
- package/src/runjs-context/helpers.ts +56 -0
- package/src/runjs-context/index.ts +20 -0
- package/src/runjs-context/registry.ts +65 -0
- package/src/runjs-context/snippets/global/api-request-get.snippet.ts +20 -0
- package/src/runjs-context/snippets/global/api-request-post.snippet.ts +20 -0
- package/src/runjs-context/snippets/global/console-log-ctx.snippet.ts +19 -0
- package/src/runjs-context/snippets/global/copy-record-json.snippet.ts +21 -0
- package/src/runjs-context/snippets/global/copy-to-clipboard.snippet.ts +21 -0
- package/src/runjs-context/snippets/global/log-json-record.snippet.ts +21 -0
- package/src/runjs-context/snippets/global/message-error.snippet.ts +20 -0
- package/src/runjs-context/snippets/global/message-success.snippet.ts +20 -0
- package/src/runjs-context/snippets/global/notification-open.snippet.ts +21 -0
- package/src/runjs-context/snippets/global/open-view-dialog.snippet.ts +26 -0
- package/src/runjs-context/snippets/global/open-view-drawer.snippet.ts +26 -0
- package/src/runjs-context/snippets/global/requireAsync.snippet.ts +24 -0
- package/src/runjs-context/snippets/global/sleep.snippet.ts +21 -0
- package/src/runjs-context/snippets/global/try-catch-async.snippet.ts +22 -0
- package/src/runjs-context/snippets/global/view-navigation-push.snippet.ts +23 -0
- package/src/runjs-context/snippets/global/window-open.snippet.ts +19 -0
- package/src/runjs-context/snippets/index.ts +59 -0
- package/src/runjs-context/snippets/libs/echarts-init.snippet.ts +24 -0
- package/src/runjs-context/snippets/scene/actions/collection-selected-count.snippet.ts +22 -0
- package/src/runjs-context/snippets/scene/actions/iterate-selected-rows.snippet.ts +21 -0
- package/src/runjs-context/snippets/scene/actions/record-id-message.snippet.ts +21 -0
- package/src/runjs-context/snippets/scene/actions/run-action-basic.snippet.ts +18 -0
- package/src/runjs-context/snippets/scene/jsblock/add-event-listener.snippet.ts +29 -0
- package/src/runjs-context/snippets/scene/jsblock/append-style.snippet.ts +20 -0
- package/src/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.ts +24 -0
- package/src/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.ts +19 -0
- package/src/runjs-context/snippets/scene/jsblock/render-basic.snippet.ts +24 -0
- package/src/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.ts +24 -0
- package/src/runjs-context/snippets/scene/jsblock/render-card.snippet.ts +30 -0
- package/src/runjs-context/snippets/scene/jsblock/render-react.snippet.ts +34 -0
- package/src/runjs-context/snippets/scene/jsfield/color-by-value.snippet.ts +20 -0
- package/src/runjs-context/snippets/scene/jsfield/format-number.snippet.ts +19 -0
- package/src/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.ts +18 -0
- package/src/runjs-context/snippets/scene/jsitem/render-basic.snippet.ts +27 -0
- package/src/runjs-context/snippets/scene/linkage/set-disabled.snippet.ts +38 -0
- package/src/runjs-context/snippets/scene/linkage/set-field-value.snippet.ts +37 -0
- package/src/runjs-context/snippets/scene/linkage/set-required.snippet.ts +38 -0
- package/src/runjs-context/snippets/scene/linkage/toggle-visible.snippet.ts +38 -0
- package/src/runjs-context/snippets/types.ts +17 -0
- package/src/types.ts +474 -0
- package/src/utils/__tests__/context.test.ts +93 -0
- package/src/utils/__tests__/params-resolvers.test.ts +652 -0
- package/src/utils/__tests__/parsePathnameToViewParams.test.ts +104 -0
- package/src/utils/__tests__/safeGlobals.test.ts +29 -0
- package/src/utils/__tests__/utils.test.ts +1021 -0
- package/src/utils/__tests__/variablesParams.test.ts +52 -0
- package/src/utils/autoFlowError.ts +29 -0
- package/src/utils/constants.ts +60 -0
- package/src/utils/context.ts +70 -0
- package/src/utils/createCollectionContextMeta.ts +122 -0
- package/src/utils/exceptions.ts +36 -0
- package/src/utils/flow-definitions.ts +16 -0
- package/src/utils/index.ts +63 -0
- package/src/utils/inheritance.ts +39 -0
- package/src/utils/params-resolvers.ts +482 -0
- package/src/utils/parsePathnameToViewParams.ts +103 -0
- package/src/utils/safeGlobals.ts +188 -0
- package/src/utils/schema-utils.ts +201 -0
- package/src/utils/serverContextParams.ts +111 -0
- package/src/utils/setupRuntimeContextSteps.ts +89 -0
- package/src/utils/translation.ts +37 -0
- package/src/utils/variablesParams.ts +175 -0
- package/src/views/DialogComponent.tsx +79 -0
- package/src/views/DrawerComponent.tsx +72 -0
- package/src/views/FlowView.tsx +103 -0
- package/src/views/PageComponent.tsx +150 -0
- package/src/views/ViewNavigation.ts +122 -0
- package/src/views/__tests__/FlowView.test.ts +31 -0
- package/src/views/__tests__/ViewNavigation.test.ts +191 -0
- package/src/views/__tests__/usePatchElement.test.tsx +28 -0
- package/src/views/createViewMeta.ts +157 -0
- package/src/views/index.tsx +14 -0
- package/src/views/useDialog.tsx +192 -0
- package/src/views/useDrawer.tsx +205 -0
- package/src/views/usePage.tsx +182 -0
- package/src/views/usePatchElement.tsx +27 -0
- package/src/views/usePopover.tsx +131 -0
|
@@ -0,0 +1,1021 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { describe, test, expect, beforeEach, vi } from 'vitest';
|
|
11
|
+
import {
|
|
12
|
+
getT,
|
|
13
|
+
isInheritedFrom,
|
|
14
|
+
resolveDefaultParams,
|
|
15
|
+
resolveStepUiSchema,
|
|
16
|
+
FlowExitException,
|
|
17
|
+
defineAction,
|
|
18
|
+
compileUiSchema,
|
|
19
|
+
resolveCreateModelOptions as resolveDefaultOptions,
|
|
20
|
+
FLOW_ENGINE_NAMESPACE,
|
|
21
|
+
} from '../index';
|
|
22
|
+
import { FlowModel } from '../../models/flowModel';
|
|
23
|
+
import { FlowEngine } from '../../flowEngine';
|
|
24
|
+
import type {
|
|
25
|
+
FlowDefinitionOptions,
|
|
26
|
+
ActionDefinition,
|
|
27
|
+
DeepPartial,
|
|
28
|
+
ModelConstructor,
|
|
29
|
+
StepParams,
|
|
30
|
+
StepDefinition,
|
|
31
|
+
} from '../../types';
|
|
32
|
+
import { FlowRuntimeContext } from '../../flowContext';
|
|
33
|
+
|
|
34
|
+
// Helper functions
|
|
35
|
+
const createMockFlowEngine = (): FlowEngine => {
|
|
36
|
+
return new FlowEngine();
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
interface MockFlowModelOptions {
|
|
40
|
+
uid?: string;
|
|
41
|
+
flowEngine?: FlowEngine;
|
|
42
|
+
stepParams?: StepParams;
|
|
43
|
+
sortIndex?: number;
|
|
44
|
+
subModels?: Record<string, FlowModel | FlowModel[]>;
|
|
45
|
+
use?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const createMockFlowModel = (overrides: MockFlowModelOptions = {}): FlowModel => {
|
|
49
|
+
const flowEngine = overrides.flowEngine || createMockFlowEngine();
|
|
50
|
+
const options = {
|
|
51
|
+
uid: 'test-model-uid',
|
|
52
|
+
use: 'FlowModel',
|
|
53
|
+
stepParams: {},
|
|
54
|
+
sortIndex: 0,
|
|
55
|
+
subModels: {},
|
|
56
|
+
...overrides,
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const model = flowEngine.createModel(options);
|
|
60
|
+
|
|
61
|
+
// Mock additional methods for testing
|
|
62
|
+
flowEngine.translate = vi.fn((key: string, options?: Record<string, unknown>) => {
|
|
63
|
+
if (options?.returnOriginal) return key;
|
|
64
|
+
return `translated_${key}`;
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
flowEngine.getAction = vi.fn().mockReturnValue(null);
|
|
68
|
+
|
|
69
|
+
return model;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// Test setup
|
|
73
|
+
let mockModel: FlowModel;
|
|
74
|
+
let mockFlowEngine: FlowEngine;
|
|
75
|
+
|
|
76
|
+
beforeEach(() => {
|
|
77
|
+
mockFlowEngine = createMockFlowEngine();
|
|
78
|
+
mockModel = createMockFlowModel({ flowEngine: mockFlowEngine });
|
|
79
|
+
vi.clearAllMocks();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
describe('Utils', () => {
|
|
83
|
+
// ==================== getT() FUNCTION ====================
|
|
84
|
+
describe('getT()', () => {
|
|
85
|
+
describe('basic translation functionality', () => {
|
|
86
|
+
test('should return translation function when flowEngine.translate exists', () => {
|
|
87
|
+
const translateFn = getT(mockModel);
|
|
88
|
+
|
|
89
|
+
expect(typeof translateFn).toBe('function');
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test('should call flowEngine.translate with correct parameters', () => {
|
|
93
|
+
const translateFn = getT(mockModel);
|
|
94
|
+
|
|
95
|
+
translateFn('test.key', { custom: 'option' });
|
|
96
|
+
|
|
97
|
+
expect(mockModel.flowEngine.translate).toHaveBeenCalledWith('test.key', {
|
|
98
|
+
ns: [FLOW_ENGINE_NAMESPACE, 'client'],
|
|
99
|
+
nsMode: 'fallback',
|
|
100
|
+
custom: 'option',
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test('should return translated result from flowEngine', () => {
|
|
105
|
+
const translateFn = getT(mockModel);
|
|
106
|
+
|
|
107
|
+
const result = translateFn('hello.world');
|
|
108
|
+
|
|
109
|
+
expect(result).toBe('translated_hello.world');
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
describe('namespace handling', () => {
|
|
114
|
+
test('should add flow-engine namespace by default', () => {
|
|
115
|
+
const translateFn = getT(mockModel);
|
|
116
|
+
|
|
117
|
+
translateFn('key');
|
|
118
|
+
|
|
119
|
+
expect(mockModel.flowEngine.translate).toHaveBeenCalledWith('key', {
|
|
120
|
+
ns: [FLOW_ENGINE_NAMESPACE, 'client'],
|
|
121
|
+
nsMode: 'fallback',
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test('should merge with existing options', () => {
|
|
126
|
+
const translateFn = getT(mockModel);
|
|
127
|
+
|
|
128
|
+
translateFn('key', { ns: ['custom'], extraOption: 'value' });
|
|
129
|
+
|
|
130
|
+
// The implementation spreads options after defaults, so options override defaults
|
|
131
|
+
expect(mockModel.flowEngine.translate).toHaveBeenCalledWith('key', {
|
|
132
|
+
ns: ['custom'], // options.ns overrides default ns
|
|
133
|
+
nsMode: 'fallback',
|
|
134
|
+
extraOption: 'value',
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
test('should allow nsMode override', () => {
|
|
139
|
+
const translateFn = getT(mockModel);
|
|
140
|
+
|
|
141
|
+
translateFn('key', { nsMode: 'strict' });
|
|
142
|
+
|
|
143
|
+
// The implementation spreads options after defaults, so options override defaults
|
|
144
|
+
expect(mockModel.flowEngine.translate).toHaveBeenCalledWith('key', {
|
|
145
|
+
ns: [FLOW_ENGINE_NAMESPACE, 'client'],
|
|
146
|
+
nsMode: 'strict', // options.nsMode overrides default nsMode
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
describe('fallback mechanism', () => {
|
|
152
|
+
test('should return fallback function when no flowEngine', () => {
|
|
153
|
+
const modelWithoutEngine = { flowEngine: null } as unknown as FlowModel;
|
|
154
|
+
|
|
155
|
+
const translateFn = getT(modelWithoutEngine);
|
|
156
|
+
|
|
157
|
+
expect(typeof translateFn).toBe('function');
|
|
158
|
+
expect(translateFn('test.key')).toBe('test.key');
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
test('should return fallback function when no translate method', () => {
|
|
162
|
+
const modelWithoutTranslate = {
|
|
163
|
+
flowEngine: { translate: null },
|
|
164
|
+
} as unknown as FlowModel;
|
|
165
|
+
|
|
166
|
+
const translateFn = getT(modelWithoutTranslate);
|
|
167
|
+
|
|
168
|
+
expect(translateFn('test.key')).toBe('test.key');
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
describe('error handling', () => {
|
|
173
|
+
test('should handle translate method throwing errors', () => {
|
|
174
|
+
mockModel.flowEngine.translate = vi.fn(() => {
|
|
175
|
+
throw new Error('Translation error');
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
expect(() => {
|
|
179
|
+
const translateFn = getT(mockModel);
|
|
180
|
+
translateFn('test.key');
|
|
181
|
+
}).toThrow('Translation error');
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
test('should handle null options parameter', () => {
|
|
185
|
+
const translateFn = getT(mockModel);
|
|
186
|
+
|
|
187
|
+
translateFn('key', null);
|
|
188
|
+
|
|
189
|
+
expect(mockModel.flowEngine.translate).toHaveBeenCalledWith('key', {
|
|
190
|
+
ns: [FLOW_ENGINE_NAMESPACE, 'client'],
|
|
191
|
+
nsMode: 'fallback',
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
test('should handle undefined options parameter', () => {
|
|
196
|
+
const translateFn = getT(mockModel);
|
|
197
|
+
|
|
198
|
+
translateFn('key');
|
|
199
|
+
|
|
200
|
+
expect(mockModel.flowEngine.translate).toHaveBeenCalledWith('key', {
|
|
201
|
+
ns: [FLOW_ENGINE_NAMESPACE, 'client'],
|
|
202
|
+
nsMode: 'fallback',
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// ==================== isInheritedFrom() FUNCTION ====================
|
|
209
|
+
describe('isInheritedFrom()', () => {
|
|
210
|
+
let BaseClass: ModelConstructor;
|
|
211
|
+
let MiddleClass: ModelConstructor;
|
|
212
|
+
let DerivedClass: ModelConstructor;
|
|
213
|
+
let UnrelatedClass: ModelConstructor;
|
|
214
|
+
|
|
215
|
+
beforeEach(() => {
|
|
216
|
+
BaseClass = class extends FlowModel {} as ModelConstructor;
|
|
217
|
+
MiddleClass = class MiddleClass extends BaseClass {} as ModelConstructor;
|
|
218
|
+
DerivedClass = class DerivedClass extends MiddleClass {} as ModelConstructor;
|
|
219
|
+
UnrelatedClass = class extends FlowModel {} as ModelConstructor;
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
describe('basic inheritance checking', () => {
|
|
223
|
+
test('should return true for direct inheritance', () => {
|
|
224
|
+
const result = isInheritedFrom(MiddleClass, BaseClass);
|
|
225
|
+
|
|
226
|
+
expect(result).toBe(true);
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
test('should return false for same class', () => {
|
|
230
|
+
const result = isInheritedFrom(BaseClass, BaseClass);
|
|
231
|
+
|
|
232
|
+
expect(result).toBe(false);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
test('should return false for unrelated classes', () => {
|
|
236
|
+
const result = isInheritedFrom(UnrelatedClass, BaseClass);
|
|
237
|
+
|
|
238
|
+
expect(result).toBe(false);
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
describe('multi-level inheritance', () => {
|
|
243
|
+
test('should return true for multi-level inheritance', () => {
|
|
244
|
+
const result = isInheritedFrom(DerivedClass, BaseClass);
|
|
245
|
+
|
|
246
|
+
expect(result).toBe(true);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
test('should return true for immediate parent', () => {
|
|
250
|
+
const result = isInheritedFrom(DerivedClass, MiddleClass);
|
|
251
|
+
|
|
252
|
+
expect(result).toBe(true);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
test('should handle deep inheritance chains', () => {
|
|
256
|
+
class Level1 extends DerivedClass {}
|
|
257
|
+
class Level2 extends Level1 {}
|
|
258
|
+
class Level3 extends Level2 {}
|
|
259
|
+
|
|
260
|
+
expect(isInheritedFrom(Level3 as unknown as ModelConstructor, BaseClass)).toBe(true);
|
|
261
|
+
expect(isInheritedFrom(Level3 as unknown as ModelConstructor, MiddleClass)).toBe(true);
|
|
262
|
+
expect(isInheritedFrom(Level3 as unknown as ModelConstructor, DerivedClass)).toBe(true);
|
|
263
|
+
expect(isInheritedFrom(Level3 as unknown as ModelConstructor, Level2 as unknown as ModelConstructor)).toBe(
|
|
264
|
+
true,
|
|
265
|
+
);
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
describe('prototype chain validation', () => {
|
|
270
|
+
test('should traverse prototype chain correctly', () => {
|
|
271
|
+
// Create a complex inheritance chain
|
|
272
|
+
const A = class extends FlowModel {} as ModelConstructor;
|
|
273
|
+
const B = class B extends A {} as ModelConstructor;
|
|
274
|
+
const C = class C extends B {} as ModelConstructor;
|
|
275
|
+
const D = class D extends C {} as ModelConstructor;
|
|
276
|
+
|
|
277
|
+
expect(isInheritedFrom(D, C)).toBe(true);
|
|
278
|
+
expect(isInheritedFrom(D, B)).toBe(true);
|
|
279
|
+
expect(isInheritedFrom(D, A)).toBe(true);
|
|
280
|
+
expect(isInheritedFrom(C, A)).toBe(true);
|
|
281
|
+
expect(isInheritedFrom(B, A)).toBe(true);
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
test('should handle null prototype correctly', () => {
|
|
285
|
+
const NullProtoClass = function () {} as unknown as ModelConstructor;
|
|
286
|
+
Object.setPrototypeOf((NullProtoClass as unknown as { prototype: unknown }).prototype, null);
|
|
287
|
+
|
|
288
|
+
expect(() => {
|
|
289
|
+
isInheritedFrom(NullProtoClass, BaseClass);
|
|
290
|
+
}).not.toThrow();
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
// ==================== resolveDefaultParams() FUNCTION ====================
|
|
296
|
+
describe('resolveDefaultParams()', () => {
|
|
297
|
+
let mockContext: FlowRuntimeContext<FlowModel>;
|
|
298
|
+
|
|
299
|
+
beforeEach(() => {
|
|
300
|
+
mockContext = new FlowRuntimeContext(mockModel, 'testFlow', 'runtime');
|
|
301
|
+
mockContext.defineProperty('inputArgs', { value: { testExtra: 'testExtra' } });
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
describe('static parameter resolution', () => {
|
|
305
|
+
test('should return static object directly', async () => {
|
|
306
|
+
const staticParams = { param1: 'value1', param2: 'value2' };
|
|
307
|
+
|
|
308
|
+
const result = await resolveDefaultParams(staticParams, mockContext);
|
|
309
|
+
|
|
310
|
+
expect(result).toEqual(staticParams);
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
test('should return empty object for undefined params', async () => {
|
|
314
|
+
const result = await resolveDefaultParams(undefined, mockContext);
|
|
315
|
+
|
|
316
|
+
expect(result).toEqual({});
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
test('should return empty object for null params', async () => {
|
|
320
|
+
const result = await resolveDefaultParams(null, mockContext);
|
|
321
|
+
|
|
322
|
+
expect(result).toEqual({});
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
test('should handle complex static objects', async () => {
|
|
326
|
+
const complexParams = {
|
|
327
|
+
user: { name: 'John', age: 30 },
|
|
328
|
+
settings: { theme: 'dark', notifications: true },
|
|
329
|
+
array: [1, 2, 3],
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
const result = await resolveDefaultParams(complexParams, mockContext);
|
|
333
|
+
|
|
334
|
+
expect(result).toEqual(complexParams);
|
|
335
|
+
});
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
describe('function parameter resolution', () => {
|
|
339
|
+
test('should call function with context and return result', async () => {
|
|
340
|
+
const paramsFn = vi.fn().mockReturnValue({ dynamic: 'value' });
|
|
341
|
+
|
|
342
|
+
const result = await resolveDefaultParams(paramsFn, mockContext);
|
|
343
|
+
|
|
344
|
+
expect(paramsFn).toHaveBeenCalledWith(mockContext);
|
|
345
|
+
expect(result).toEqual({ dynamic: 'value' });
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
test('should handle function accessing context properties', async () => {
|
|
349
|
+
const paramsFn = vi.fn((ctx: FlowRuntimeContext<FlowModel>) => ({
|
|
350
|
+
modelUid: ctx.model.uid,
|
|
351
|
+
extraData: ctx.inputArgs.testExtra,
|
|
352
|
+
}));
|
|
353
|
+
|
|
354
|
+
const result = await resolveDefaultParams(paramsFn, mockContext);
|
|
355
|
+
|
|
356
|
+
expect(result).toEqual({
|
|
357
|
+
modelUid: mockModel.uid,
|
|
358
|
+
extraData: 'testExtra',
|
|
359
|
+
});
|
|
360
|
+
});
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
describe('async processing', () => {
|
|
364
|
+
test('should handle async function correctly', async () => {
|
|
365
|
+
const asyncParamsFn = vi.fn().mockResolvedValue({ async: 'result' });
|
|
366
|
+
|
|
367
|
+
const result = await resolveDefaultParams(asyncParamsFn, mockContext);
|
|
368
|
+
|
|
369
|
+
expect(asyncParamsFn).toHaveBeenCalledWith(mockContext);
|
|
370
|
+
expect(result).toEqual({ async: 'result' });
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
test('should handle async function with delay', async () => {
|
|
374
|
+
const asyncParamsFn = vi.fn(
|
|
375
|
+
() => new Promise((resolve) => setTimeout(() => resolve({ delayed: 'value' }), 10)),
|
|
376
|
+
);
|
|
377
|
+
|
|
378
|
+
const result = await resolveDefaultParams(asyncParamsFn, mockContext);
|
|
379
|
+
|
|
380
|
+
expect(result).toEqual({ delayed: 'value' });
|
|
381
|
+
});
|
|
382
|
+
});
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
// ==================== FlowExitException CLASS ====================
|
|
386
|
+
describe('FlowExitException', () => {
|
|
387
|
+
describe('constructor', () => {
|
|
388
|
+
test('should create exception with all parameters', () => {
|
|
389
|
+
const exception = new FlowExitException('testFlow', 'model-123', 'Custom exit message');
|
|
390
|
+
|
|
391
|
+
expect(exception.flowKey).toBe('testFlow');
|
|
392
|
+
expect(exception.modelUid).toBe('model-123');
|
|
393
|
+
expect(exception.message).toBe('Custom exit message');
|
|
394
|
+
expect(exception.name).toBe('FlowExitException');
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
test('should create exception with default message', () => {
|
|
398
|
+
const exception = new FlowExitException('testFlow', 'model-123');
|
|
399
|
+
|
|
400
|
+
expect(exception.flowKey).toBe('testFlow');
|
|
401
|
+
expect(exception.modelUid).toBe('model-123');
|
|
402
|
+
expect(exception.message).toBe("Flow 'testFlow' on model 'model-123' exited via ctx.exit().");
|
|
403
|
+
expect(exception.name).toBe('FlowExitException');
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
test('should create exception with empty string message', () => {
|
|
407
|
+
const exception = new FlowExitException('testFlow', 'model-123', '');
|
|
408
|
+
|
|
409
|
+
// Empty string is falsy, so the default message is used in the constructor
|
|
410
|
+
expect(exception.message).toBe("Flow 'testFlow' on model 'model-123' exited via ctx.exit().");
|
|
411
|
+
});
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
describe('property access', () => {
|
|
415
|
+
test('should have readonly properties accessible', () => {
|
|
416
|
+
const exception = new FlowExitException('flowKey', 'modelUid');
|
|
417
|
+
|
|
418
|
+
expect(exception.flowKey).toBe('flowKey');
|
|
419
|
+
expect(exception.modelUid).toBe('modelUid');
|
|
420
|
+
});
|
|
421
|
+
});
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
// ==================== defineAction() FUNCTION ====================
|
|
425
|
+
describe('defineAction()', () => {
|
|
426
|
+
describe('basic functionality', () => {
|
|
427
|
+
test('should return action definition unchanged', () => {
|
|
428
|
+
const actionDef: ActionDefinition = {
|
|
429
|
+
name: 'testAction',
|
|
430
|
+
handler: vi.fn(),
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
const result = defineAction(actionDef);
|
|
434
|
+
|
|
435
|
+
expect(result).toBe(actionDef);
|
|
436
|
+
expect(result).toEqual(actionDef);
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
test('should handle complex action definition', () => {
|
|
440
|
+
const complexAction: ActionDefinition = {
|
|
441
|
+
name: 'complexAction',
|
|
442
|
+
handler: vi.fn().mockResolvedValue('result'),
|
|
443
|
+
defaultParams: { param1: 'value1' },
|
|
444
|
+
uiSchema: {
|
|
445
|
+
field1: { type: 'string', title: 'Field 1' },
|
|
446
|
+
},
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
const result = defineAction(complexAction);
|
|
450
|
+
|
|
451
|
+
expect(result).toBe(complexAction);
|
|
452
|
+
expect(result.name).toBe('complexAction');
|
|
453
|
+
expect(result.defaultParams).toEqual({ param1: 'value1' });
|
|
454
|
+
expect(result.uiSchema).toEqual({
|
|
455
|
+
field1: { type: 'string', title: 'Field 1' },
|
|
456
|
+
});
|
|
457
|
+
});
|
|
458
|
+
});
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
// ==================== compileUiSchema() FUNCTION ====================
|
|
462
|
+
describe('compileUiSchema()', () => {
|
|
463
|
+
let mockScope: Record<string, unknown>;
|
|
464
|
+
|
|
465
|
+
beforeEach(() => {
|
|
466
|
+
mockScope = {
|
|
467
|
+
t: vi.fn((key: string) => `translated_${key}`),
|
|
468
|
+
randomString: vi.fn(() => 'random123'),
|
|
469
|
+
user: { name: 'John', role: 'admin' },
|
|
470
|
+
};
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
describe('expression compilation', () => {
|
|
474
|
+
test('should compile simple expressions', () => {
|
|
475
|
+
const result = compileUiSchema(mockScope, "{{ t('Hello World') }}");
|
|
476
|
+
|
|
477
|
+
expect(mockScope.t).toHaveBeenCalledWith('Hello World');
|
|
478
|
+
expect(typeof result).toBe('string');
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
test('should compile expressions with variables', () => {
|
|
482
|
+
const result = compileUiSchema(mockScope, '{{ user.name }}');
|
|
483
|
+
|
|
484
|
+
expect(result).toBe('John');
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
test('should compile complex expressions', () => {
|
|
488
|
+
const result = compileUiSchema(mockScope, "{{ user.role === 'admin' ? 'Administrator' : 'User' }}");
|
|
489
|
+
|
|
490
|
+
expect(result).toBe('Administrator');
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
test('should handle non-expression strings', () => {
|
|
494
|
+
const result = compileUiSchema(mockScope, 'Plain string without expressions');
|
|
495
|
+
|
|
496
|
+
expect(result).toBe('Plain string without expressions');
|
|
497
|
+
});
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
describe('caching mechanism', () => {
|
|
501
|
+
test('should cache compiled results', () => {
|
|
502
|
+
const schema = "{{ t('Cached Test') }}";
|
|
503
|
+
|
|
504
|
+
const result1 = compileUiSchema(mockScope, schema);
|
|
505
|
+
const result2 = compileUiSchema(mockScope, schema);
|
|
506
|
+
|
|
507
|
+
expect(result1).toBe(result2);
|
|
508
|
+
// Schema.compile should be called once and then cached
|
|
509
|
+
expect(mockScope.t).toHaveBeenCalledTimes(1);
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
test('should bypass cache when noCache option is true', () => {
|
|
513
|
+
const schema = "{{ t('No Cache Test') }}";
|
|
514
|
+
|
|
515
|
+
compileUiSchema(mockScope, schema, { noCache: false });
|
|
516
|
+
compileUiSchema(mockScope, schema, { noCache: true });
|
|
517
|
+
|
|
518
|
+
// t function should be called twice when bypassing cache
|
|
519
|
+
expect(mockScope.t).toHaveBeenCalledTimes(2);
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
test('should cache object compilations', () => {
|
|
523
|
+
const schema = {
|
|
524
|
+
title: "{{ t('Object Title') }}",
|
|
525
|
+
description: 'Static description',
|
|
526
|
+
};
|
|
527
|
+
|
|
528
|
+
const result1 = compileUiSchema(mockScope, schema);
|
|
529
|
+
const result2 = compileUiSchema(mockScope, schema);
|
|
530
|
+
|
|
531
|
+
expect(result1).toBe(result2);
|
|
532
|
+
expect(result1.title).toBeDefined();
|
|
533
|
+
expect(result1.description).toBe('Static description');
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
test('should cache array compilations', () => {
|
|
537
|
+
const schema = [{ title: "{{ t('Item 1') }}" }, { title: "{{ t('Item 2') }}" }];
|
|
538
|
+
|
|
539
|
+
const result1 = compileUiSchema(mockScope, schema);
|
|
540
|
+
const result2 = compileUiSchema(mockScope, schema);
|
|
541
|
+
|
|
542
|
+
expect(result1).toBe(result2);
|
|
543
|
+
expect(Array.isArray(result1)).toBe(true);
|
|
544
|
+
expect(result1).toHaveLength(2);
|
|
545
|
+
});
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
describe('object compilation', () => {
|
|
549
|
+
test('should compile objects with template strings', () => {
|
|
550
|
+
const schema = {
|
|
551
|
+
title: "{{ t('Form Title') }}",
|
|
552
|
+
description: 'Static description',
|
|
553
|
+
user: '{{ user.name }}',
|
|
554
|
+
role: '{{ user.role }}',
|
|
555
|
+
};
|
|
556
|
+
|
|
557
|
+
const result = compileUiSchema(mockScope, schema);
|
|
558
|
+
|
|
559
|
+
expect(typeof result.title).toBe('string');
|
|
560
|
+
expect(result.description).toBe('Static description');
|
|
561
|
+
expect(result.user).toBe('John');
|
|
562
|
+
expect(result.role).toBe('admin');
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
test('should handle nested objects', () => {
|
|
566
|
+
const schema = {
|
|
567
|
+
form: {
|
|
568
|
+
title: "{{ t('Nested Form') }}",
|
|
569
|
+
fields: {
|
|
570
|
+
username: {
|
|
571
|
+
label: "{{ t('Username') }}",
|
|
572
|
+
placeholder: "{{ t('Enter username') }}",
|
|
573
|
+
},
|
|
574
|
+
},
|
|
575
|
+
},
|
|
576
|
+
};
|
|
577
|
+
|
|
578
|
+
const result = compileUiSchema(mockScope, schema);
|
|
579
|
+
|
|
580
|
+
expect(typeof result.form.title).toBe('string');
|
|
581
|
+
expect(typeof result.form.fields.username.label).toBe('string');
|
|
582
|
+
expect(typeof result.form.fields.username.placeholder).toBe('string');
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
test('should handle arrays within objects', () => {
|
|
586
|
+
const schema = {
|
|
587
|
+
items: [
|
|
588
|
+
{ title: "{{ t('Item 1') }}", value: 1 },
|
|
589
|
+
{ title: "{{ t('Item 2') }}", value: 2 },
|
|
590
|
+
],
|
|
591
|
+
metadata: {
|
|
592
|
+
count: "{{ user.role === 'admin' ? 'unlimited' : '10' }}",
|
|
593
|
+
},
|
|
594
|
+
};
|
|
595
|
+
|
|
596
|
+
const result = compileUiSchema(mockScope, schema);
|
|
597
|
+
|
|
598
|
+
expect(Array.isArray(result.items)).toBe(true);
|
|
599
|
+
expect(result.items).toHaveLength(2);
|
|
600
|
+
expect(result.items[0].value).toBe(1);
|
|
601
|
+
expect(result.items[1].value).toBe(2);
|
|
602
|
+
expect(result.metadata.count).toBe('unlimited');
|
|
603
|
+
});
|
|
604
|
+
|
|
605
|
+
test('should preserve non-template properties', () => {
|
|
606
|
+
const schema = {
|
|
607
|
+
type: 'object',
|
|
608
|
+
properties: {
|
|
609
|
+
name: {
|
|
610
|
+
type: 'string',
|
|
611
|
+
title: "{{ t('Name Field') }}",
|
|
612
|
+
maxLength: 100,
|
|
613
|
+
},
|
|
614
|
+
},
|
|
615
|
+
};
|
|
616
|
+
|
|
617
|
+
const result = compileUiSchema(mockScope, schema);
|
|
618
|
+
|
|
619
|
+
expect(result.type).toBe('object');
|
|
620
|
+
expect(result.properties.name.type).toBe('string');
|
|
621
|
+
expect(typeof result.properties.name.title).toBe('string');
|
|
622
|
+
expect(result.properties.name.maxLength).toBe(100);
|
|
623
|
+
});
|
|
624
|
+
});
|
|
625
|
+
});
|
|
626
|
+
|
|
627
|
+
// ==================== resolveDefaultOptions() FUNCTION ====================
|
|
628
|
+
describe('resolveDefaultOptions()', () => {
|
|
629
|
+
describe('static options resolution', () => {
|
|
630
|
+
test('should return static object directly', async () => {
|
|
631
|
+
const staticOptions = { option1: 'value1', option2: 'value2' };
|
|
632
|
+
|
|
633
|
+
const result = await resolveDefaultOptions(staticOptions, mockModel.context);
|
|
634
|
+
|
|
635
|
+
expect(result).toEqual(staticOptions);
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
test('should return empty object for undefined options', async () => {
|
|
639
|
+
const result = await resolveDefaultOptions(undefined, mockModel.context);
|
|
640
|
+
|
|
641
|
+
expect(result).toEqual({});
|
|
642
|
+
});
|
|
643
|
+
|
|
644
|
+
test('should return empty object for null options', async () => {
|
|
645
|
+
const result = await resolveDefaultOptions(null, mockModel.context);
|
|
646
|
+
|
|
647
|
+
expect(result).toEqual({});
|
|
648
|
+
});
|
|
649
|
+
|
|
650
|
+
test('should handle complex static objects', async () => {
|
|
651
|
+
const complexOptions = {
|
|
652
|
+
use: 'TableModel',
|
|
653
|
+
config: {
|
|
654
|
+
columns: ['id', 'name'],
|
|
655
|
+
pagination: true,
|
|
656
|
+
},
|
|
657
|
+
stepParams: {
|
|
658
|
+
default: {
|
|
659
|
+
step1: { dataSourceKey: 'main' },
|
|
660
|
+
},
|
|
661
|
+
},
|
|
662
|
+
};
|
|
663
|
+
|
|
664
|
+
const result = await resolveDefaultOptions(complexOptions, mockModel.context);
|
|
665
|
+
|
|
666
|
+
expect(result).toEqual(complexOptions);
|
|
667
|
+
});
|
|
668
|
+
});
|
|
669
|
+
|
|
670
|
+
describe('function options resolution', () => {
|
|
671
|
+
test('should call function with parent model and return result', async () => {
|
|
672
|
+
const optionsFn = vi.fn().mockReturnValue({ dynamic: 'value' });
|
|
673
|
+
|
|
674
|
+
const result = await resolveDefaultOptions(optionsFn, mockModel.context);
|
|
675
|
+
|
|
676
|
+
expect(optionsFn).toHaveBeenCalledWith(mockModel.context, undefined);
|
|
677
|
+
expect(result).toEqual({ dynamic: 'value' });
|
|
678
|
+
});
|
|
679
|
+
|
|
680
|
+
test('should handle function accessing model properties', async () => {
|
|
681
|
+
const optionsFn = vi.fn((parentContext: any) => ({
|
|
682
|
+
use: 'DynamicModel',
|
|
683
|
+
parentUid: parentContext.model.uid,
|
|
684
|
+
sortIndex: parentContext.model.sortIndex || 0,
|
|
685
|
+
}));
|
|
686
|
+
|
|
687
|
+
const result = await resolveDefaultOptions(optionsFn, mockModel.context);
|
|
688
|
+
|
|
689
|
+
expect(result).toEqual({
|
|
690
|
+
use: 'DynamicModel',
|
|
691
|
+
parentUid: mockModel.uid,
|
|
692
|
+
sortIndex: 0,
|
|
693
|
+
});
|
|
694
|
+
});
|
|
695
|
+
|
|
696
|
+
test('should handle async function correctly', async () => {
|
|
697
|
+
const asyncOptionsFn = vi.fn().mockResolvedValue({ async: 'result' });
|
|
698
|
+
|
|
699
|
+
const result = await resolveDefaultOptions(asyncOptionsFn, mockModel.context);
|
|
700
|
+
|
|
701
|
+
expect(asyncOptionsFn).toHaveBeenCalledWith(mockModel.context, undefined);
|
|
702
|
+
expect(result).toEqual({ async: 'result' });
|
|
703
|
+
});
|
|
704
|
+
|
|
705
|
+
test('should handle async function with delay', async () => {
|
|
706
|
+
const asyncOptionsFn = vi.fn(
|
|
707
|
+
() => new Promise((resolve) => setTimeout(() => resolve({ delayed: 'value' }), 10)),
|
|
708
|
+
);
|
|
709
|
+
|
|
710
|
+
const result = await resolveDefaultOptions(asyncOptionsFn, mockModel.context);
|
|
711
|
+
|
|
712
|
+
expect(result).toEqual({ delayed: 'value' });
|
|
713
|
+
});
|
|
714
|
+
});
|
|
715
|
+
|
|
716
|
+
describe('error handling', () => {
|
|
717
|
+
test('should handle function throwing errors and return empty object', async () => {
|
|
718
|
+
const errorFn = vi.fn(() => {
|
|
719
|
+
throw new Error('Options generation error');
|
|
720
|
+
});
|
|
721
|
+
|
|
722
|
+
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
723
|
+
|
|
724
|
+
const result = await resolveDefaultOptions(errorFn, mockModel.context);
|
|
725
|
+
|
|
726
|
+
expect(result).toEqual({});
|
|
727
|
+
expect(consoleSpy).toHaveBeenCalledWith('Error resolving createModelOptions function:', expect.any(Error));
|
|
728
|
+
|
|
729
|
+
consoleSpy.mockRestore();
|
|
730
|
+
});
|
|
731
|
+
|
|
732
|
+
test('should handle async function rejection and return empty object', async () => {
|
|
733
|
+
const rejectFn = vi.fn().mockRejectedValue(new Error('Async error'));
|
|
734
|
+
|
|
735
|
+
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
736
|
+
|
|
737
|
+
const result = await resolveDefaultOptions(rejectFn, mockModel.context);
|
|
738
|
+
|
|
739
|
+
expect(result).toEqual({});
|
|
740
|
+
expect(consoleSpy).toHaveBeenCalledWith('Error resolving createModelOptions function:', expect.any(Error));
|
|
741
|
+
|
|
742
|
+
consoleSpy.mockRestore();
|
|
743
|
+
});
|
|
744
|
+
|
|
745
|
+
test('should handle function returning null and convert to empty object', async () => {
|
|
746
|
+
const nullFn = vi.fn().mockReturnValue(null);
|
|
747
|
+
|
|
748
|
+
const result = await resolveDefaultOptions(nullFn, mockModel.context);
|
|
749
|
+
|
|
750
|
+
expect(result).toEqual({});
|
|
751
|
+
});
|
|
752
|
+
|
|
753
|
+
test('should handle function returning undefined and convert to empty object', async () => {
|
|
754
|
+
const undefinedFn = vi.fn().mockReturnValue(undefined);
|
|
755
|
+
|
|
756
|
+
const result = await resolveDefaultOptions(undefinedFn, mockModel.context);
|
|
757
|
+
|
|
758
|
+
expect(result).toEqual({});
|
|
759
|
+
});
|
|
760
|
+
});
|
|
761
|
+
});
|
|
762
|
+
|
|
763
|
+
// ==================== resolveStepUiSchema() FUNCTION ====================
|
|
764
|
+
describe('resolveStepUiSchema()', () => {
|
|
765
|
+
let mockFlow: any;
|
|
766
|
+
let mockStep: StepDefinition;
|
|
767
|
+
let mockAction: any;
|
|
768
|
+
|
|
769
|
+
beforeEach(() => {
|
|
770
|
+
mockFlow = {
|
|
771
|
+
key: 'testFlow',
|
|
772
|
+
title: 'Test Flow',
|
|
773
|
+
steps: {
|
|
774
|
+
testStep: {
|
|
775
|
+
handler: vi.fn(),
|
|
776
|
+
},
|
|
777
|
+
},
|
|
778
|
+
};
|
|
779
|
+
|
|
780
|
+
mockStep = {
|
|
781
|
+
handler: vi.fn().mockResolvedValue('step-result'),
|
|
782
|
+
title: 'Test Step',
|
|
783
|
+
};
|
|
784
|
+
|
|
785
|
+
mockAction = {
|
|
786
|
+
name: 'testAction',
|
|
787
|
+
handler: vi.fn().mockResolvedValue('action-result'),
|
|
788
|
+
title: 'Test Action',
|
|
789
|
+
};
|
|
790
|
+
});
|
|
791
|
+
|
|
792
|
+
describe('basic functionality', () => {
|
|
793
|
+
test('should return null when no uiSchema is available', async () => {
|
|
794
|
+
// Step with no uiSchema and no action
|
|
795
|
+
const result = await resolveStepUiSchema(mockModel, mockFlow, mockStep);
|
|
796
|
+
|
|
797
|
+
expect(result).toBeNull();
|
|
798
|
+
});
|
|
799
|
+
|
|
800
|
+
test('should return null when step and action both have empty uiSchema', async () => {
|
|
801
|
+
mockStep.uiSchema = {};
|
|
802
|
+
mockAction.uiSchema = {};
|
|
803
|
+
mockStep.use = 'testAction';
|
|
804
|
+
mockModel.flowEngine.getAction = vi.fn().mockReturnValue(mockAction);
|
|
805
|
+
|
|
806
|
+
const result = await resolveStepUiSchema(mockModel, mockFlow, mockStep);
|
|
807
|
+
|
|
808
|
+
expect(result).toBeNull();
|
|
809
|
+
});
|
|
810
|
+
|
|
811
|
+
test('should return step uiSchema when only step has uiSchema', async () => {
|
|
812
|
+
const stepUiSchema = {
|
|
813
|
+
field1: { type: 'string', title: 'Field 1' },
|
|
814
|
+
field2: { type: 'number', title: 'Field 2' },
|
|
815
|
+
};
|
|
816
|
+
mockStep.uiSchema = stepUiSchema;
|
|
817
|
+
|
|
818
|
+
const result = await resolveStepUiSchema(mockModel, mockFlow, mockStep);
|
|
819
|
+
|
|
820
|
+
expect(result).toEqual(stepUiSchema);
|
|
821
|
+
});
|
|
822
|
+
|
|
823
|
+
test('should return action uiSchema when only action has uiSchema', async () => {
|
|
824
|
+
const actionUiSchema = {
|
|
825
|
+
actionField: { type: 'string', title: 'Action Field' },
|
|
826
|
+
};
|
|
827
|
+
mockAction.uiSchema = actionUiSchema;
|
|
828
|
+
mockStep.use = 'testAction';
|
|
829
|
+
mockModel.flowEngine.getAction = vi.fn().mockReturnValue(mockAction);
|
|
830
|
+
|
|
831
|
+
const result = await resolveStepUiSchema(mockModel, mockFlow, mockStep);
|
|
832
|
+
|
|
833
|
+
expect(result).toEqual(actionUiSchema);
|
|
834
|
+
});
|
|
835
|
+
});
|
|
836
|
+
|
|
837
|
+
describe('merging behavior', () => {
|
|
838
|
+
test('should return step uiSchema when both step and action have uiSchema', async () => {
|
|
839
|
+
const actionUiSchema = {
|
|
840
|
+
field1: { type: 'string', title: 'Action Field 1' },
|
|
841
|
+
field2: { type: 'number', title: 'Action Field 2' },
|
|
842
|
+
};
|
|
843
|
+
const stepUiSchema = {
|
|
844
|
+
field1: { type: 'string', title: 'Step Field 1' }, // Should override action
|
|
845
|
+
field3: { type: 'boolean', title: 'Step Field 3' }, // Should be added
|
|
846
|
+
};
|
|
847
|
+
|
|
848
|
+
mockAction.uiSchema = actionUiSchema;
|
|
849
|
+
mockStep.uiSchema = stepUiSchema;
|
|
850
|
+
mockStep.use = 'testAction';
|
|
851
|
+
mockModel.flowEngine.getAction = vi.fn().mockReturnValue(mockAction);
|
|
852
|
+
|
|
853
|
+
const result = await resolveStepUiSchema(mockModel, mockFlow, mockStep);
|
|
854
|
+
|
|
855
|
+
expect(result).toEqual({
|
|
856
|
+
field1: { type: 'string', title: 'Step Field 1' },
|
|
857
|
+
field3: { type: 'boolean', title: 'Step Field 3' },
|
|
858
|
+
});
|
|
859
|
+
});
|
|
860
|
+
});
|
|
861
|
+
|
|
862
|
+
describe('dynamic uiSchema resolution', () => {
|
|
863
|
+
test('should resolve function-based step uiSchema', async () => {
|
|
864
|
+
const dynamicStepUiSchema = vi.fn().mockResolvedValue({
|
|
865
|
+
dynamicField: { type: 'string', title: 'Dynamic Field' },
|
|
866
|
+
});
|
|
867
|
+
mockStep.uiSchema = dynamicStepUiSchema;
|
|
868
|
+
|
|
869
|
+
const result = await resolveStepUiSchema(mockModel, mockFlow, mockStep);
|
|
870
|
+
|
|
871
|
+
expect(dynamicStepUiSchema).toHaveBeenCalled();
|
|
872
|
+
expect(result).toEqual({
|
|
873
|
+
dynamicField: { type: 'string', title: 'Dynamic Field' },
|
|
874
|
+
});
|
|
875
|
+
});
|
|
876
|
+
|
|
877
|
+
test('should resolve function-based action uiSchema', async () => {
|
|
878
|
+
const dynamicActionUiSchema = vi.fn().mockResolvedValue({
|
|
879
|
+
actionDynamicField: { type: 'number', title: 'Action Dynamic Field' },
|
|
880
|
+
});
|
|
881
|
+
mockAction.uiSchema = dynamicActionUiSchema;
|
|
882
|
+
mockStep.use = 'testAction';
|
|
883
|
+
mockModel.flowEngine.getAction = vi.fn().mockReturnValue(mockAction);
|
|
884
|
+
|
|
885
|
+
const result = await resolveStepUiSchema(mockModel, mockFlow, mockStep);
|
|
886
|
+
|
|
887
|
+
expect(dynamicActionUiSchema).toHaveBeenCalled();
|
|
888
|
+
expect(result).toEqual({
|
|
889
|
+
actionDynamicField: { type: 'number', title: 'Action Dynamic Field' },
|
|
890
|
+
});
|
|
891
|
+
});
|
|
892
|
+
|
|
893
|
+
test('should resolve both dynamic step and action uiSchemas', async () => {
|
|
894
|
+
const dynamicActionUiSchema = vi.fn().mockResolvedValue({
|
|
895
|
+
actionField: { type: 'string', title: 'Action Field' },
|
|
896
|
+
sharedField: { type: 'string', title: 'Action Shared' },
|
|
897
|
+
});
|
|
898
|
+
const dynamicStepUiSchema = vi.fn().mockResolvedValue({
|
|
899
|
+
stepField: { type: 'number', title: 'Step Field' },
|
|
900
|
+
sharedField: { type: 'string', title: 'Step Shared' }, // Should override
|
|
901
|
+
});
|
|
902
|
+
|
|
903
|
+
mockAction.uiSchema = dynamicActionUiSchema;
|
|
904
|
+
mockStep.uiSchema = dynamicStepUiSchema;
|
|
905
|
+
mockStep.use = 'testAction';
|
|
906
|
+
mockModel.flowEngine.getAction = vi.fn().mockReturnValue(mockAction);
|
|
907
|
+
|
|
908
|
+
const result = await resolveStepUiSchema(mockModel, mockFlow, mockStep);
|
|
909
|
+
|
|
910
|
+
expect(dynamicActionUiSchema).not.toHaveBeenCalled();
|
|
911
|
+
expect(dynamicStepUiSchema).toHaveBeenCalled();
|
|
912
|
+
expect(result).toEqual({
|
|
913
|
+
stepField: { type: 'number', title: 'Step Field' },
|
|
914
|
+
sharedField: { type: 'string', title: 'Step Shared' },
|
|
915
|
+
});
|
|
916
|
+
});
|
|
917
|
+
|
|
918
|
+
test('should return null when dynamic uiSchemas resolve to empty objects', async () => {
|
|
919
|
+
const emptyActionUiSchema = vi.fn().mockResolvedValue({});
|
|
920
|
+
const emptyStepUiSchema = vi.fn().mockResolvedValue({});
|
|
921
|
+
|
|
922
|
+
mockAction.uiSchema = emptyActionUiSchema;
|
|
923
|
+
mockStep.uiSchema = emptyStepUiSchema;
|
|
924
|
+
mockStep.use = 'testAction';
|
|
925
|
+
mockModel.flowEngine.getAction = vi.fn().mockReturnValue(mockAction);
|
|
926
|
+
|
|
927
|
+
const result = await resolveStepUiSchema(mockModel, mockFlow, mockStep);
|
|
928
|
+
|
|
929
|
+
expect(result).toBeNull();
|
|
930
|
+
});
|
|
931
|
+
|
|
932
|
+
test('should return null when dynamic uiSchemas resolve to null/undefined', async () => {
|
|
933
|
+
const nullActionUiSchema = vi.fn().mockResolvedValue(null);
|
|
934
|
+
const undefinedStepUiSchema = vi.fn().mockResolvedValue(undefined);
|
|
935
|
+
|
|
936
|
+
mockAction.uiSchema = nullActionUiSchema;
|
|
937
|
+
mockStep.uiSchema = undefinedStepUiSchema;
|
|
938
|
+
mockStep.use = 'testAction';
|
|
939
|
+
mockModel.flowEngine.getAction = vi.fn().mockReturnValue(mockAction);
|
|
940
|
+
|
|
941
|
+
const result = await resolveStepUiSchema(mockModel, mockFlow, mockStep);
|
|
942
|
+
|
|
943
|
+
expect(result).toBeNull();
|
|
944
|
+
});
|
|
945
|
+
});
|
|
946
|
+
|
|
947
|
+
describe('action handling', () => {
|
|
948
|
+
test('should handle missing action gracefully', async () => {
|
|
949
|
+
mockStep.use = 'nonExistentAction';
|
|
950
|
+
mockStep.uiSchema = {
|
|
951
|
+
field1: { type: 'string', title: 'Field 1' },
|
|
952
|
+
};
|
|
953
|
+
mockModel.flowEngine.getAction = vi.fn().mockReturnValue(null);
|
|
954
|
+
|
|
955
|
+
const result = await resolveStepUiSchema(mockModel, mockFlow, mockStep);
|
|
956
|
+
|
|
957
|
+
expect(result).toEqual({
|
|
958
|
+
field1: { type: 'string', title: 'Field 1' },
|
|
959
|
+
});
|
|
960
|
+
});
|
|
961
|
+
|
|
962
|
+
test('should handle action without uiSchema', async () => {
|
|
963
|
+
mockStep.use = 'testAction';
|
|
964
|
+
mockStep.uiSchema = {
|
|
965
|
+
field1: { type: 'string', title: 'Field 1' },
|
|
966
|
+
};
|
|
967
|
+
mockModel.flowEngine.getAction = vi.fn().mockReturnValue({
|
|
968
|
+
...mockAction,
|
|
969
|
+
uiSchema: undefined,
|
|
970
|
+
});
|
|
971
|
+
|
|
972
|
+
const result = await resolveStepUiSchema(mockModel, mockFlow, mockStep);
|
|
973
|
+
|
|
974
|
+
expect(result).toEqual({
|
|
975
|
+
field1: { type: 'string', title: 'Field 1' },
|
|
976
|
+
});
|
|
977
|
+
});
|
|
978
|
+
|
|
979
|
+
test('should handle getAction throwing error', async () => {
|
|
980
|
+
const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
|
981
|
+
|
|
982
|
+
mockStep.use = 'errorAction';
|
|
983
|
+
mockStep.uiSchema = {
|
|
984
|
+
field1: { type: 'string', title: 'Field 1' },
|
|
985
|
+
};
|
|
986
|
+
mockModel.flowEngine.getAction = vi.fn(() => {
|
|
987
|
+
throw new Error('Action retrieval error');
|
|
988
|
+
});
|
|
989
|
+
|
|
990
|
+
const result = await resolveStepUiSchema(mockModel, mockFlow, mockStep);
|
|
991
|
+
|
|
992
|
+
expect(consoleSpy).toHaveBeenCalledWith('Failed to get action errorAction:', expect.any(Error));
|
|
993
|
+
expect(result).toEqual({
|
|
994
|
+
field1: { type: 'string', title: 'Field 1' },
|
|
995
|
+
});
|
|
996
|
+
|
|
997
|
+
consoleSpy.mockRestore();
|
|
998
|
+
});
|
|
999
|
+
|
|
1000
|
+
test('should handle missing getAction method', async () => {
|
|
1001
|
+
// Mock a flowEngine without getAction method
|
|
1002
|
+
const originalGetAction = mockModel.flowEngine.getAction;
|
|
1003
|
+
mockModel.flowEngine.getAction = undefined;
|
|
1004
|
+
|
|
1005
|
+
mockStep.use = 'testAction';
|
|
1006
|
+
mockStep.uiSchema = {
|
|
1007
|
+
field1: { type: 'string', title: 'Field 1' },
|
|
1008
|
+
};
|
|
1009
|
+
|
|
1010
|
+
const result = await resolveStepUiSchema(mockModel, mockFlow, mockStep);
|
|
1011
|
+
|
|
1012
|
+
expect(result).toEqual({
|
|
1013
|
+
field1: { type: 'string', title: 'Field 1' },
|
|
1014
|
+
});
|
|
1015
|
+
|
|
1016
|
+
// Restore the original method
|
|
1017
|
+
mockModel.flowEngine.getAction = originalGetAction;
|
|
1018
|
+
});
|
|
1019
|
+
});
|
|
1020
|
+
});
|
|
1021
|
+
});
|