@nocobase/flow-engine 2.0.0-alpha.7 → 2.0.0-alpha.71
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/lib/BlockScopedFlowEngine.d.ts +23 -0
- package/lib/BlockScopedFlowEngine.js +91 -0
- package/lib/FlowContextProvider.d.ts +2 -2
- package/lib/FlowContextProvider.js +3 -3
- package/lib/FlowDefinition.d.ts +6 -4
- package/lib/JSRunner.d.ts +6 -0
- package/lib/JSRunner.js +27 -1
- package/lib/ViewScopedFlowEngine.d.ts +1 -1
- package/lib/ViewScopedFlowEngine.js +18 -1
- package/lib/acl/Acl.d.ts +12 -12
- package/lib/acl/Acl.js +88 -30
- package/lib/components/DynamicFlowsEditor.js +2 -4
- package/lib/components/FieldModelRenderer.js +17 -9
- package/lib/components/FieldSkeleton.d.ts +10 -0
- package/lib/components/FieldSkeleton.js +64 -0
- package/lib/components/FlowContextSelector.js +19 -3
- package/lib/components/FlowModelRenderer.d.ts +4 -6
- package/lib/components/FlowModelRenderer.js +35 -53
- package/lib/components/FormItem.js +5 -1
- package/lib/components/MobilePopup.d.ts +20 -0
- package/lib/components/MobilePopup.js +102 -0
- package/lib/components/MobilePopup.style.d.ts +17 -0
- package/lib/components/MobilePopup.style.js +186 -0
- package/lib/components/common/withFlowDesignMode.d.ts +1 -1
- package/lib/components/common/withFlowDesignMode.js +5 -5
- package/lib/components/dnd/gridDragPlanner.d.ts +1 -0
- package/lib/components/dnd/gridDragPlanner.js +53 -1
- package/lib/components/index.d.ts +1 -0
- package/lib/components/index.js +3 -1
- package/lib/components/settings/independents/dropdown/FlowsDropdownButton.js +71 -53
- package/lib/components/settings/wrappers/component/SelectWithTitle.d.ts +19 -0
- package/lib/components/settings/wrappers/component/SelectWithTitle.js +136 -0
- package/lib/components/settings/wrappers/component/SwitchWithTitle.d.ts +10 -0
- package/lib/components/settings/wrappers/component/SwitchWithTitle.js +111 -0
- package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +233 -97
- package/lib/components/settings/wrappers/contextual/FlowsContextMenu.js +71 -54
- package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.d.ts +2 -2
- package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.js +63 -23
- package/lib/components/settings/wrappers/contextual/StepSettingsDialog.js +13 -2
- package/lib/components/settings/wrappers/embedded/FlowSettings.js +42 -28
- package/lib/components/settings/wrappers/embedded/FlowsSettings.js +3 -3
- package/lib/components/settings/wrappers/embedded/FlowsSettingsContent.js +52 -32
- package/lib/components/subModel/AddSubModelButton.d.ts +7 -0
- package/lib/components/subModel/AddSubModelButton.js +78 -8
- package/lib/components/subModel/LazyDropdown.js +14 -15
- package/lib/components/subModel/utils.d.ts +1 -1
- package/lib/components/subModel/utils.js +21 -11
- package/lib/components/variables/VariableInput.js +26 -6
- package/lib/components/variables/VariableTag.js +43 -2
- package/lib/components/variables/types.d.ts +2 -0
- package/lib/components/variables/utils.js +4 -2
- package/lib/data-source/index.d.ts +23 -4
- package/lib/data-source/index.js +135 -14
- package/lib/data-source/jioToJoiSchema.js +1 -0
- package/lib/emitter.d.ts +6 -0
- package/lib/emitter.js +12 -0
- package/lib/executor/FlowExecutor.d.ts +6 -6
- package/lib/executor/FlowExecutor.js +302 -99
- package/lib/flow-registry/GlobalFlowRegistry.d.ts +1 -0
- package/lib/flow-registry/GlobalFlowRegistry.js +3 -0
- package/lib/flow-registry/InstanceFlowRegistry.d.ts +1 -0
- package/lib/flow-registry/InstanceFlowRegistry.js +3 -0
- package/lib/flowContext.d.ts +105 -6
- package/lib/flowContext.js +447 -139
- package/lib/flowEngine.d.ts +71 -1
- package/lib/flowEngine.js +319 -16
- package/lib/flowSettings.d.ts +4 -3
- package/lib/flowSettings.js +45 -21
- package/lib/hooks/useApplyAutoFlows.d.ts +1 -0
- package/lib/hooks/useApplyAutoFlows.js +3 -2
- package/lib/index.d.ts +14 -3
- package/lib/index.js +54 -7
- package/lib/locale/de-DE.json +62 -0
- package/lib/locale/en-US.json +57 -45
- package/lib/locale/es-ES.json +62 -0
- package/lib/locale/fr-FR.json +62 -0
- package/lib/locale/hu-HU.json +62 -0
- package/lib/locale/id-ID.json +62 -0
- package/lib/locale/index.d.ts +114 -90
- package/lib/locale/it-IT.json +62 -0
- package/lib/locale/ja-JP.json +62 -0
- package/lib/locale/ko-KR.json +62 -0
- package/lib/locale/nl-NL.json +62 -0
- package/lib/locale/pt-BR.json +62 -0
- package/lib/locale/ru-RU.json +62 -0
- package/lib/locale/tr-TR.json +62 -0
- package/lib/locale/uk-UA.json +62 -0
- package/lib/locale/vi-VN.json +62 -0
- package/lib/locale/zh-CN.json +58 -46
- package/lib/locale/zh-TW.json +62 -0
- package/lib/models/CollectionFieldModel.d.ts +7 -2
- package/lib/models/CollectionFieldModel.js +63 -16
- package/lib/models/flowModel.d.ts +76 -32
- package/lib/models/flowModel.js +300 -112
- package/lib/models/forkFlowModel.d.ts +8 -4
- package/lib/models/forkFlowModel.js +38 -8
- package/lib/provider.d.ts +3 -1
- package/lib/provider.js +14 -11
- package/lib/reactive/index.d.ts +10 -0
- package/lib/{runjs-context/snippets/global/api-request-post.snippet.js → reactive/index.js} +14 -15
- package/lib/reactive/observer.d.ts +19 -0
- package/lib/reactive/observer.js +109 -0
- package/lib/resources/baseRecordResource.d.ts +6 -0
- package/lib/resources/baseRecordResource.js +38 -3
- package/lib/resources/multiRecordResource.d.ts +5 -2
- package/lib/resources/multiRecordResource.js +26 -10
- package/lib/resources/singleRecordResource.js +8 -3
- package/lib/resources/sqlResource.d.ts +5 -3
- package/lib/resources/sqlResource.js +30 -28
- package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.d.ts +1 -6
- package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.js +37 -20
- package/lib/runjs-context/contexts/JSBlockRunJSContext.d.ts +1 -6
- package/lib/runjs-context/contexts/JSBlockRunJSContext.js +46 -33
- package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.d.ts +1 -2
- package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.js +14 -15
- package/lib/runjs-context/contexts/{LinkageRunJSContext.d.ts → JSColumnRunJSContext.d.ts} +6 -3
- package/lib/runjs-context/contexts/JSColumnRunJSContext.js +78 -0
- package/lib/runjs-context/contexts/JSEditableFieldRunJSContext.d.ts +16 -0
- package/lib/runjs-context/contexts/JSEditableFieldRunJSContext.js +125 -0
- package/lib/runjs-context/contexts/JSFieldRunJSContext.d.ts +1 -6
- package/lib/runjs-context/contexts/JSFieldRunJSContext.js +28 -24
- package/lib/runjs-context/contexts/JSItemRunJSContext.d.ts +1 -6
- package/lib/runjs-context/contexts/JSItemRunJSContext.js +34 -20
- package/lib/runjs-context/contexts/JSRecordActionRunJSContext.d.ts +1 -2
- package/lib/runjs-context/contexts/JSRecordActionRunJSContext.js +16 -17
- package/lib/runjs-context/contexts/base.d.ts +9 -0
- package/lib/runjs-context/contexts/base.js +879 -0
- package/lib/runjs-context/contributions.d.ts +33 -0
- package/lib/runjs-context/contributions.js +88 -0
- package/lib/runjs-context/helpers.d.ts +5 -2
- package/lib/runjs-context/helpers.js +36 -27
- package/lib/runjs-context/registry.d.ts +7 -4
- package/lib/runjs-context/registry.js +10 -42
- package/lib/runjs-context/setup.d.ts +9 -0
- package/lib/runjs-context/setup.js +88 -0
- package/lib/runjs-context/snippets/global/{copy-record-json.snippet.js → api-request.snippet.js} +25 -10
- package/lib/runjs-context/snippets/global/clipboard-copy-text.snippet.js +61 -0
- package/lib/runjs-context/snippets/global/{view-navigation-push.snippet.js → import-esm.snippet.js} +26 -12
- package/lib/runjs-context/snippets/global/message-error.snippet.js +6 -0
- package/lib/runjs-context/snippets/global/message-success.snippet.js +6 -0
- package/lib/runjs-context/snippets/global/notification-open.snippet.d.ts +3 -8
- package/lib/runjs-context/snippets/global/notification-open.snippet.js +8 -1
- package/lib/runjs-context/snippets/global/open-view-dialog.snippet.js +10 -3
- package/lib/runjs-context/snippets/global/open-view-drawer.snippet.js +10 -3
- package/lib/runjs-context/snippets/global/query-selector.snippet.js +53 -0
- package/lib/runjs-context/snippets/global/require-amd.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/{requireAsync.snippet.js → require-amd.snippet.js} +16 -13
- package/lib/runjs-context/snippets/global/window-open.snippet.d.ts +3 -8
- package/lib/runjs-context/snippets/global/window-open.snippet.js +8 -1
- package/lib/runjs-context/snippets/index.d.ts +24 -3
- package/lib/runjs-context/snippets/index.js +183 -40
- package/lib/runjs-context/snippets/scene/block/add-event-listener.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{jsblock → block}/add-event-listener.snippet.js +11 -2
- package/lib/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.js +64 -0
- package/lib/runjs-context/snippets/scene/block/chartjs-bar.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/chartjs-bar.snippet.js +99 -0
- package/lib/runjs-context/snippets/{libs → scene/block}/echarts-init.snippet.js +24 -7
- package/lib/runjs-context/snippets/scene/block/render-antd-icons.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/render-antd-icons.snippet.js +65 -0
- package/lib/runjs-context/snippets/scene/block/render-button-handler.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{jsblock → block}/render-button-handler.snippet.js +17 -9
- package/lib/runjs-context/snippets/scene/block/render-iframe.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/render-iframe.snippet.js +57 -0
- package/lib/runjs-context/snippets/scene/block/render-info-card.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/render-info-card.snippet.js +71 -0
- package/lib/runjs-context/snippets/scene/block/render-react-jsx.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{jsblock/render-card.snippet.js → block/render-react-jsx.snippet.js} +26 -13
- package/lib/runjs-context/snippets/scene/block/render-react.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{jsblock → block}/render-react.snippet.js +18 -17
- package/lib/runjs-context/snippets/scene/block/render-statistics.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/render-statistics.snippet.js +95 -0
- package/lib/runjs-context/snippets/scene/block/render-timeline.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/render-timeline.snippet.js +84 -0
- package/lib/runjs-context/snippets/scene/block/resource-example.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/resource-example.snippet.js +60 -0
- package/lib/runjs-context/snippets/scene/block/three-users-orbit.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/three-users-orbit.snippet.js +283 -0
- package/lib/runjs-context/snippets/scene/block/vue-component.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/vue-component.snippet.js +124 -0
- package/lib/runjs-context/snippets/scene/detail/color-by-value.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{jsfield → detail}/color-by-value.snippet.js +13 -3
- package/lib/runjs-context/snippets/scene/detail/copy-to-clipboard.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/{global → scene/detail}/copy-to-clipboard.snippet.js +28 -6
- package/lib/runjs-context/snippets/scene/detail/format-number.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{jsfield → detail}/format-number.snippet.js +13 -3
- package/lib/runjs-context/snippets/scene/detail/innerHTML-value.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{jsfield → detail}/innerHTML-value.snippet.js +13 -3
- package/lib/runjs-context/snippets/scene/detail/percentage-bar.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/detail/percentage-bar.snippet.js +82 -0
- package/lib/runjs-context/snippets/scene/detail/relative-time.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/detail/relative-time.snippet.js +80 -0
- package/lib/runjs-context/snippets/scene/detail/status-tag.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/detail/status-tag.snippet.js +74 -0
- package/lib/runjs-context/snippets/scene/form/calculate-total.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/form/calculate-total.snippet.js +63 -0
- package/lib/runjs-context/snippets/scene/form/cascade-select.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/form/cascade-select.snippet.js +81 -0
- package/lib/runjs-context/snippets/scene/form/conditional-required.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/form/conditional-required.snippet.js +64 -0
- package/lib/runjs-context/snippets/scene/form/copy-field-values.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/form/copy-field-values.snippet.js +74 -0
- package/lib/runjs-context/snippets/scene/form/render-basic.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{jsitem → form}/render-basic.snippet.js +11 -2
- package/lib/runjs-context/snippets/scene/form/set-disabled.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{linkage → form}/set-disabled.snippet.js +12 -3
- package/lib/runjs-context/snippets/scene/form/set-field-value.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{linkage → form}/set-field-value.snippet.js +12 -3
- package/lib/runjs-context/snippets/scene/form/set-required.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{linkage → form}/set-required.snippet.js +12 -3
- package/lib/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.js +67 -0
- package/lib/runjs-context/snippets/scene/form/toggle-visible.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{linkage → form}/toggle-visible.snippet.js +12 -3
- package/lib/runjs-context/snippets/scene/table/cell-open-dialog.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/table/cell-open-dialog.snippet.js +64 -0
- package/lib/runjs-context/snippets/scene/table/collection-selected-count.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{actions → table}/collection-selected-count.snippet.js +11 -2
- package/lib/runjs-context/snippets/scene/table/concat-fields.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/table/concat-fields.snippet.js +79 -0
- package/lib/runjs-context/snippets/scene/table/destroy-selected.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/{global/log-json-record.snippet.js → scene/table/destroy-selected.snippet.js} +24 -11
- package/lib/runjs-context/snippets/scene/table/export-selected-json.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/table/export-selected-json.snippet.js +64 -0
- package/lib/runjs-context/snippets/scene/table/iterate-selected-rows.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{actions → table}/iterate-selected-rows.snippet.js +11 -2
- package/lib/runjs-context/snippets/types.d.ts +9 -1
- package/lib/runjsLibs.d.ts +28 -0
- package/lib/runjsLibs.js +532 -0
- package/lib/scheduler/ModelOperationScheduler.d.ts +53 -0
- package/lib/scheduler/ModelOperationScheduler.js +262 -0
- package/lib/types.d.ts +66 -7
- package/lib/types.js +4 -3
- package/lib/utils/associationObjectVariable.d.ts +32 -0
- package/lib/utils/associationObjectVariable.js +157 -0
- package/lib/utils/createCollectionContextMeta.d.ts +1 -1
- package/lib/utils/createCollectionContextMeta.js +9 -4
- package/lib/utils/createEphemeralContext.d.ts +13 -0
- package/lib/utils/createEphemeralContext.js +140 -0
- package/lib/utils/flows.d.ts +10 -0
- package/lib/{runjs-context/snippets/global/console-log-ctx.snippet.js → utils/flows.js} +21 -14
- package/lib/utils/index.d.ts +9 -3
- package/lib/utils/index.js +30 -2
- package/lib/utils/jsxTransform.d.ts +15 -0
- package/lib/utils/jsxTransform.js +68 -0
- package/lib/utils/params-resolvers.js +19 -12
- package/lib/utils/parsePathnameToViewParams.d.ts +1 -1
- package/lib/utils/parsePathnameToViewParams.js +41 -5
- package/lib/utils/pruneFilter.d.ts +21 -0
- package/lib/{runjs-context/snippets/global/try-catch-async.snippet.js → utils/pruneFilter.js} +24 -16
- package/lib/utils/resolveModuleUrl.d.ts +58 -0
- package/lib/utils/resolveModuleUrl.js +65 -0
- package/lib/utils/runjsModuleLoader.d.ts +58 -0
- package/lib/utils/runjsModuleLoader.js +422 -0
- package/lib/utils/runjsTemplateCompat.d.ts +35 -0
- package/lib/utils/runjsTemplateCompat.js +743 -0
- package/lib/utils/safeGlobals.d.ts +6 -8
- package/lib/utils/safeGlobals.js +169 -14
- package/lib/utils/schema-utils.d.ts +6 -0
- package/lib/utils/schema-utils.js +71 -6
- package/lib/utils/serverContextParams.d.ts +4 -0
- package/lib/utils/serverContextParams.js +2 -0
- package/lib/utils/translation.d.ts +4 -1
- package/lib/utils/translation.js +6 -2
- package/lib/utils/variablesParams.d.ts +22 -5
- package/lib/utils/variablesParams.js +141 -61
- package/lib/views/DialogComponent.js +1 -5
- package/lib/views/DrawerComponent.js +18 -9
- package/lib/views/PageComponent.js +5 -5
- package/lib/views/ViewNavigation.d.ts +11 -15
- package/lib/views/ViewNavigation.js +37 -19
- package/lib/views/createViewMeta.d.ts +27 -5
- package/lib/views/createViewMeta.js +338 -72
- package/lib/views/index.d.ts +1 -1
- package/lib/views/index.js +4 -0
- package/lib/views/useDialog.d.ts +10 -9
- package/lib/views/useDialog.js +46 -34
- package/lib/views/useDrawer.d.ts +10 -9
- package/lib/views/useDrawer.js +74 -48
- package/lib/views/usePage.d.ts +14 -9
- package/lib/views/usePage.js +82 -33
- package/lib/views/usePopover.js +4 -1
- package/lib/views/viewEvents.d.ts +17 -0
- package/lib/views/viewEvents.js +90 -0
- package/package.json +6 -3
- package/src/BlockScopedFlowEngine.ts +85 -0
- package/src/FlowContextProvider.tsx +4 -2
- package/src/JSRunner.ts +39 -1
- package/src/ViewScopedFlowEngine.ts +21 -1
- package/src/__tests__/JSRunner.test.ts +125 -52
- package/src/__tests__/blockScopedFlowEngine.test.ts +154 -0
- package/src/__tests__/createViewMeta.popup.test.ts +203 -0
- package/src/__tests__/flow-engine.test.ts +3 -0
- package/src/__tests__/flowContext.test.ts +160 -0
- package/src/__tests__/flowContextCreateJSRunner.test.ts +163 -0
- package/src/__tests__/flowEngine.dataSourceDirty.test.ts +63 -0
- package/src/__tests__/flowEngine.destroyModel.test.ts +74 -0
- package/src/__tests__/flowEngine.moveModel.test.ts +43 -0
- package/src/__tests__/flowEngine.removeModel.test.ts +72 -0
- package/src/__tests__/flowEngine.saveModel.test.ts +4 -0
- package/src/__tests__/flowModel.openView.navigation.test.ts +31 -2
- package/src/__tests__/flowRunJSContextDefine.test.ts +508 -0
- package/src/__tests__/flowSettings.open.test.tsx +71 -15
- package/src/__tests__/flowSettings.test.ts +2 -0
- package/src/__tests__/globalFlowRegistry.test.ts +1 -1
- package/src/__tests__/modelOperationScheduler.test.ts +346 -0
- package/src/__tests__/objectVariable.test.ts +464 -0
- package/src/__tests__/provider.test.tsx +0 -5
- package/src/__tests__/runjsContext.test.ts +219 -35
- package/src/__tests__/runjsContextImplementations.test.ts +217 -0
- package/src/__tests__/runjsContextRuntime.test.ts +269 -0
- package/src/__tests__/runjsEdgeCases.test.ts +281 -0
- package/src/__tests__/runjsExternalLibs.test.ts +242 -0
- package/src/__tests__/runjsLibsLazyLoading.test.ts +44 -0
- package/src/__tests__/runjsLocales.test.ts +39 -0
- package/src/__tests__/runjsPreprocessDefault.test.ts +49 -0
- package/src/__tests__/runjsRuntimeFeatures.test.ts +461 -0
- package/src/__tests__/runjsSnippets.test.ts +140 -0
- package/src/__tests__/viewScopedFlowEngine.test.ts +101 -3
- package/src/acl/Acl.tsx +85 -31
- package/src/acl/__tests__/Acl.test.tsx +43 -1
- package/src/components/DynamicFlowsEditor.tsx +0 -10
- package/src/components/FieldModelRenderer.tsx +22 -9
- package/src/components/FieldSkeleton.tsx +27 -0
- package/src/components/FlowContextSelector.tsx +20 -2
- package/src/components/FlowModelRenderer.tsx +52 -84
- package/src/components/FormItem.tsx +8 -1
- package/src/components/MobilePopup.style.ts +220 -0
- package/src/components/MobilePopup.tsx +86 -0
- package/src/components/__tests__/FlowModelRenderer.test.tsx +89 -0
- package/src/components/__tests__/flow-model-render-error-fallback.test.tsx +6 -6
- package/src/components/__tests__/gridDragPlanner.test.ts +141 -1
- package/src/components/common/withFlowDesignMode.tsx +5 -5
- package/src/components/dnd/gridDragPlanner.ts +60 -0
- package/src/components/index.ts +1 -0
- package/src/components/settings/independents/dropdown/FlowsDropdownButton.tsx +34 -17
- package/src/components/settings/wrappers/component/SelectWithTitle.tsx +110 -0
- package/src/components/settings/wrappers/component/SwitchWithTitle.tsx +83 -0
- package/src/components/settings/wrappers/component/__tests__/InlineControls.test.tsx +74 -0
- package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +272 -125
- package/src/components/settings/wrappers/contextual/FlowsContextMenu.tsx +34 -18
- package/src/components/settings/wrappers/contextual/FlowsFloatContextMenu.tsx +56 -18
- package/src/components/settings/wrappers/contextual/StepSettings.tsx +1 -2
- package/src/components/settings/wrappers/contextual/StepSettingsDialog.tsx +13 -1
- package/src/components/settings/wrappers/contextual/__tests__/DefaultSettingsIcon.test.tsx +624 -0
- package/src/components/settings/wrappers/embedded/FlowSettings.tsx +47 -35
- package/src/components/settings/wrappers/embedded/FlowsSettings.tsx +1 -1
- package/src/components/settings/wrappers/embedded/FlowsSettingsContent.tsx +64 -42
- package/src/components/subModel/AddSubModelButton.tsx +104 -9
- package/src/components/subModel/LazyDropdown.tsx +14 -14
- package/src/components/subModel/__tests__/AddSubModelButton.test.tsx +168 -7
- package/src/components/subModel/__tests__/utils.test.ts +12 -12
- package/src/components/subModel/utils.ts +25 -6
- package/src/components/variables/VariableInput.tsx +32 -6
- package/src/components/variables/VariableTag.tsx +54 -2
- package/src/components/variables/types.ts +2 -0
- package/src/components/variables/utils.ts +7 -3
- package/src/data-source/index.ts +143 -12
- package/src/data-source/jioToJoiSchema.ts +1 -0
- package/src/emitter.ts +14 -0
- package/src/executor/FlowExecutor.ts +383 -119
- package/src/executor/__tests__/ctx-defs-injection.test.ts +197 -0
- package/src/executor/__tests__/flowExecutor.test.ts +217 -5
- package/src/flow-registry/GlobalFlowRegistry.ts +1 -0
- package/src/flow-registry/InstanceFlowRegistry.ts +1 -0
- package/src/flow-registry/__tests__/globalFlowRegistry.test.ts +54 -0
- package/src/flowContext.ts +646 -158
- package/src/flowEngine.ts +385 -14
- package/src/flowSettings.ts +59 -30
- package/src/hooks/useApplyAutoFlows.ts +5 -3
- package/src/index.ts +26 -3
- package/src/locale/de-DE.json +62 -0
- package/src/locale/en-US.json +57 -45
- package/src/locale/es-ES.json +62 -0
- package/src/locale/fr-FR.json +62 -0
- package/src/locale/hu-HU.json +62 -0
- package/src/locale/id-ID.json +62 -0
- package/src/locale/it-IT.json +62 -0
- package/src/locale/ja-JP.json +62 -0
- package/src/locale/ko-KR.json +62 -0
- package/src/locale/nl-NL.json +62 -0
- package/src/locale/pt-BR.json +62 -0
- package/src/locale/ru-RU.json +62 -0
- package/src/locale/tr-TR.json +62 -0
- package/src/locale/uk-UA.json +62 -0
- package/src/locale/vi-VN.json +62 -0
- package/src/locale/zh-CN.json +58 -46
- package/src/locale/zh-TW.json +62 -0
- package/src/models/CollectionFieldModel.tsx +82 -18
- package/src/models/__tests__/dispatchEvent.behavior.test.ts +169 -0
- package/src/models/__tests__/dispatchEvent.when.test.ts +356 -0
- package/src/models/__tests__/flowEngine.resolveUse.test.ts +170 -0
- package/src/models/__tests__/flowModel.clone.test.ts +416 -0
- package/src/models/__tests__/flowModel.getFlows.sort.test.ts +33 -9
- package/src/models/__tests__/flowModel.scheduleModelOperation.test.tsx +129 -0
- package/src/models/__tests__/flowModel.test.ts +296 -119
- package/src/models/__tests__/forkFlowModel.test.ts +40 -7
- package/src/models/flowModel.tsx +426 -148
- package/src/models/forkFlowModel.ts +48 -8
- package/src/provider.tsx +18 -14
- package/src/reactive/__tests__/observer.test.tsx +211 -0
- package/src/reactive/index.ts +11 -0
- package/src/reactive/observer.tsx +101 -0
- package/src/resources/__tests__/multiRecordResource.test.ts +44 -0
- package/src/resources/__tests__/sqlResource.test.ts +60 -0
- package/src/resources/baseRecordResource.ts +46 -3
- package/src/resources/multiRecordResource.ts +28 -12
- package/src/resources/singleRecordResource.ts +9 -3
- package/src/resources/sqlResource.ts +33 -32
- package/src/runjs-context/contexts/FormJSFieldItemRunJSContext.ts +38 -21
- package/src/runjs-context/contexts/JSBlockRunJSContext.ts +50 -34
- package/src/runjs-context/contexts/JSCollectionActionRunJSContext.ts +15 -16
- package/src/runjs-context/contexts/JSColumnRunJSContext.ts +58 -0
- package/src/runjs-context/contexts/JSEditableFieldRunJSContext.ts +106 -0
- package/src/runjs-context/contexts/JSFieldRunJSContext.ts +30 -25
- package/src/runjs-context/contexts/JSItemRunJSContext.ts +35 -21
- package/src/runjs-context/contexts/JSRecordActionRunJSContext.ts +17 -18
- package/src/runjs-context/contexts/base.ts +871 -0
- package/src/runjs-context/contributions.ts +88 -0
- package/src/runjs-context/helpers.ts +32 -30
- package/src/runjs-context/registry.ts +16 -47
- package/src/runjs-context/setup.ts +57 -0
- package/src/runjs-context/snippets/global/api-request.snippet.ts +38 -0
- package/src/runjs-context/snippets/global/clipboard-copy-text.snippet.ts +42 -0
- package/src/runjs-context/snippets/global/import-esm.snippet.ts +39 -0
- package/src/runjs-context/snippets/global/message-error.snippet.ts +6 -0
- package/src/runjs-context/snippets/global/message-success.snippet.ts +6 -0
- package/src/runjs-context/snippets/global/notification-open.snippet.ts +11 -1
- package/src/runjs-context/snippets/global/open-view-dialog.snippet.ts +10 -3
- package/src/runjs-context/snippets/global/open-view-drawer.snippet.ts +10 -3
- package/src/runjs-context/snippets/global/query-selector.snippet.ts +34 -0
- package/src/runjs-context/snippets/global/require-amd.snippet.ts +30 -0
- package/src/runjs-context/snippets/global/window-open.snippet.ts +11 -1
- package/src/runjs-context/snippets/index.ts +212 -39
- package/src/runjs-context/snippets/scene/{jsblock → block}/add-event-listener.snippet.ts +14 -2
- package/src/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.ts +45 -0
- package/src/runjs-context/snippets/scene/block/chartjs-bar.snippet.ts +80 -0
- package/src/runjs-context/snippets/scene/block/echarts-init.snippet.ts +44 -0
- package/src/runjs-context/snippets/scene/block/render-antd-icons.snippet.ts +46 -0
- package/src/runjs-context/snippets/scene/block/render-button-handler.snippet.ts +35 -0
- package/src/runjs-context/snippets/scene/block/render-iframe.snippet.ts +38 -0
- package/src/runjs-context/snippets/scene/block/render-info-card.snippet.ts +52 -0
- package/src/runjs-context/snippets/scene/block/render-react-jsx.snippet.ts +39 -0
- package/src/runjs-context/snippets/scene/block/render-react.snippet.ts +38 -0
- package/src/runjs-context/snippets/scene/block/render-statistics.snippet.ts +76 -0
- package/src/runjs-context/snippets/scene/block/render-timeline.snippet.ts +65 -0
- package/src/runjs-context/snippets/scene/block/resource-example.snippet.ts +46 -0
- package/src/runjs-context/snippets/scene/block/three-users-orbit.snippet.ts +264 -0
- package/src/runjs-context/snippets/scene/block/vue-component.snippet.ts +105 -0
- package/src/runjs-context/snippets/scene/detail/color-by-value.snippet.ts +33 -0
- package/src/runjs-context/snippets/scene/detail/copy-to-clipboard.snippet.ts +45 -0
- package/src/runjs-context/snippets/scene/detail/format-number.snippet.ts +32 -0
- package/src/runjs-context/snippets/scene/detail/innerHTML-value.snippet.ts +31 -0
- package/src/runjs-context/snippets/scene/detail/percentage-bar.snippet.ts +63 -0
- package/src/runjs-context/snippets/scene/detail/relative-time.snippet.ts +61 -0
- package/src/runjs-context/snippets/scene/detail/status-tag.snippet.ts +55 -0
- package/src/runjs-context/snippets/scene/form/calculate-total.snippet.ts +44 -0
- package/src/runjs-context/snippets/scene/form/cascade-select.snippet.ts +62 -0
- package/src/runjs-context/snippets/scene/form/conditional-required.snippet.ts +45 -0
- package/src/runjs-context/snippets/scene/form/copy-field-values.snippet.ts +55 -0
- package/src/runjs-context/snippets/scene/{jsitem → form}/render-basic.snippet.ts +14 -2
- package/src/runjs-context/snippets/scene/{linkage → form}/set-disabled.snippet.ts +15 -3
- package/src/runjs-context/snippets/scene/{linkage → form}/set-field-value.snippet.ts +15 -3
- package/src/runjs-context/snippets/scene/{linkage → form}/set-required.snippet.ts +15 -3
- package/src/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.ts +48 -0
- package/src/runjs-context/snippets/scene/{linkage → form}/toggle-visible.snippet.ts +15 -3
- package/src/runjs-context/snippets/scene/table/cell-open-dialog.snippet.ts +45 -0
- package/src/runjs-context/snippets/scene/{actions → table}/collection-selected-count.snippet.ts +14 -2
- package/src/runjs-context/snippets/scene/table/concat-fields.snippet.ts +60 -0
- package/src/runjs-context/snippets/scene/table/destroy-selected.snippet.ts +36 -0
- package/src/runjs-context/snippets/scene/table/export-selected-json.snippet.ts +45 -0
- package/src/runjs-context/snippets/scene/{actions → table}/iterate-selected-rows.snippet.ts +14 -2
- package/src/runjs-context/snippets/types.ts +5 -1
- package/src/runjsLibs.ts +622 -0
- package/src/scheduler/ModelOperationScheduler.ts +306 -0
- package/src/types.ts +86 -5
- package/src/utils/__tests__/createCollectionContextMeta.test.ts +51 -0
- package/src/utils/__tests__/flows.test.ts +65 -0
- package/src/utils/__tests__/jsxTransform.test.ts +38 -0
- package/src/utils/__tests__/params-resolvers.test.ts +40 -0
- package/src/utils/__tests__/parsePathnameToViewParams.test.ts +25 -0
- package/src/utils/__tests__/pruneFilter.test.ts +38 -0
- package/src/utils/__tests__/runjsRequireAsyncAutoWhitelist.test.ts +38 -0
- package/src/utils/__tests__/runjsTemplateCompat.test.ts +159 -0
- package/src/utils/__tests__/safeGlobals.test.ts +79 -2
- package/src/utils/__tests__/utils.test.ts +114 -15
- package/src/utils/__tests__/variablesParams.test.ts +120 -0
- package/src/utils/associationObjectVariable.ts +180 -0
- package/src/utils/createCollectionContextMeta.ts +9 -3
- package/src/utils/createEphemeralContext.ts +142 -0
- package/src/utils/flows.ts +23 -0
- package/src/utils/index.ts +17 -3
- package/src/utils/jsxTransform.ts +39 -0
- package/src/utils/params-resolvers.ts +25 -11
- package/src/utils/parsePathnameToViewParams.ts +50 -6
- package/src/utils/pruneFilter.ts +41 -0
- package/src/utils/resolveModuleUrl.ts +91 -0
- package/src/utils/runjsModuleLoader.ts +553 -0
- package/src/utils/runjsTemplateCompat.ts +828 -0
- package/src/utils/safeGlobals.ts +181 -15
- package/src/utils/schema-utils.ts +81 -3
- package/src/utils/serverContextParams.ts +6 -0
- package/src/utils/translation.ts +7 -2
- package/src/utils/variablesParams.ts +164 -72
- package/src/views/DialogComponent.tsx +1 -4
- package/src/views/DrawerComponent.tsx +19 -7
- package/src/views/PageComponent.tsx +3 -5
- package/src/views/ViewNavigation.ts +49 -43
- package/src/views/__tests__/FlowView.usePage.test.tsx +186 -0
- package/src/views/__tests__/ViewNavigation.test.ts +54 -34
- package/src/views/__tests__/useDialog.closeDestroy.test.tsx +159 -0
- package/src/views/__tests__/viewEvents.resolveOpenerEngine.test.ts +28 -0
- package/src/views/createViewMeta.ts +402 -73
- package/src/views/index.tsx +1 -1
- package/src/views/useDialog.tsx +52 -31
- package/src/views/useDrawer.tsx +99 -55
- package/src/views/usePage.tsx +101 -33
- package/src/views/usePopover.tsx +4 -1
- package/src/views/viewEvents.ts +55 -0
- package/lib/runjs-context/contexts/FlowRunJSContext.d.ts +0 -38
- package/lib/runjs-context/contexts/FlowRunJSContext.js +0 -217
- package/lib/runjs-context/contexts/LinkageRunJSContext.js +0 -62
- package/lib/runjs-context/index.d.ts +0 -19
- package/lib/runjs-context/index.js +0 -57
- package/lib/runjs-context/snippets/global/api-request-get.snippet.d.ts +0 -16
- package/lib/runjs-context/snippets/global/api-request-get.snippet.js +0 -42
- package/lib/runjs-context/snippets/global/api-request-post.snippet.d.ts +0 -16
- package/lib/runjs-context/snippets/global/console-log-ctx.snippet.d.ts +0 -16
- package/lib/runjs-context/snippets/global/requireAsync.snippet.d.ts +0 -16
- package/lib/runjs-context/snippets/global/sleep.snippet.d.ts +0 -16
- package/lib/runjs-context/snippets/global/sleep.snippet.js +0 -43
- package/lib/runjs-context/snippets/global/try-catch-async.snippet.d.ts +0 -16
- package/lib/runjs-context/snippets/libs/echarts-init.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/actions/collection-selected-count.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/actions/iterate-selected-rows.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.js +0 -43
- package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.js +0 -40
- package/lib/runjs-context/snippets/scene/jsblock/add-event-listener.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.js +0 -42
- package/lib/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.js +0 -46
- package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.js +0 -41
- package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.js +0 -41
- package/lib/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsblock/render-react.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsfield/color-by-value.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsfield/format-number.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsitem/render-basic.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/linkage/set-disabled.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/linkage/set-field-value.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/linkage/set-required.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/linkage/toggle-visible.snippet.d.ts +0 -15
- package/src/runjs-context/contexts/FlowRunJSContext.ts +0 -190
- package/src/runjs-context/contexts/LinkageRunJSContext.ts +0 -35
- package/src/runjs-context/index.ts +0 -20
- package/src/runjs-context/snippets/global/api-request-get.snippet.ts +0 -20
- package/src/runjs-context/snippets/global/api-request-post.snippet.ts +0 -20
- package/src/runjs-context/snippets/global/console-log-ctx.snippet.ts +0 -19
- package/src/runjs-context/snippets/global/copy-record-json.snippet.ts +0 -21
- package/src/runjs-context/snippets/global/copy-to-clipboard.snippet.ts +0 -21
- package/src/runjs-context/snippets/global/log-json-record.snippet.ts +0 -21
- package/src/runjs-context/snippets/global/requireAsync.snippet.ts +0 -24
- package/src/runjs-context/snippets/global/sleep.snippet.ts +0 -21
- package/src/runjs-context/snippets/global/try-catch-async.snippet.ts +0 -22
- package/src/runjs-context/snippets/global/view-navigation-push.snippet.ts +0 -23
- package/src/runjs-context/snippets/libs/echarts-init.snippet.ts +0 -24
- package/src/runjs-context/snippets/scene/actions/record-id-message.snippet.ts +0 -21
- package/src/runjs-context/snippets/scene/actions/run-action-basic.snippet.ts +0 -18
- package/src/runjs-context/snippets/scene/jsblock/append-style.snippet.ts +0 -20
- package/src/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.ts +0 -24
- package/src/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.ts +0 -19
- package/src/runjs-context/snippets/scene/jsblock/render-basic.snippet.ts +0 -24
- package/src/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.ts +0 -24
- package/src/runjs-context/snippets/scene/jsblock/render-card.snippet.ts +0 -30
- package/src/runjs-context/snippets/scene/jsblock/render-react.snippet.ts +0 -34
- package/src/runjs-context/snippets/scene/jsfield/color-by-value.snippet.ts +0 -20
- package/src/runjs-context/snippets/scene/jsfield/format-number.snippet.ts +0 -19
- package/src/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.ts +0 -18
- /package/lib/runjs-context/snippets/global/{copy-record-json.snippet.d.ts → api-request.snippet.d.ts} +0 -0
- /package/lib/runjs-context/snippets/global/{copy-to-clipboard.snippet.d.ts → clipboard-copy-text.snippet.d.ts} +0 -0
- /package/lib/runjs-context/snippets/global/{log-json-record.snippet.d.ts → import-esm.snippet.d.ts} +0 -0
- /package/lib/runjs-context/snippets/global/{view-navigation-push.snippet.d.ts → query-selector.snippet.d.ts} +0 -0
- /package/lib/runjs-context/snippets/scene/{jsblock/render-card.snippet.d.ts → block/echarts-init.snippet.d.ts} +0 -0
|
@@ -7,18 +7,17 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import {
|
|
11
|
-
import { APIClient } from '@nocobase/sdk';
|
|
10
|
+
import { reaction } from '@nocobase/flow-engine';
|
|
12
11
|
import { render, waitFor } from '@testing-library/react';
|
|
13
12
|
import React from 'react';
|
|
14
13
|
import { vi } from 'vitest';
|
|
15
14
|
import { FlowModelRenderer } from '../../components/FlowModelRenderer';
|
|
15
|
+
import { FlowEngineProvider } from '../../provider';
|
|
16
16
|
import { FlowEngine } from '../../flowEngine';
|
|
17
|
-
import type { DefaultStructure, FlowDefinitionOptions, FlowModelOptions
|
|
17
|
+
import type { DefaultStructure, FlowDefinitionOptions, FlowModelOptions } from '../../types';
|
|
18
18
|
import { FlowExitException } from '../../utils';
|
|
19
19
|
import { FlowExitAllException } from '../../utils/exceptions';
|
|
20
|
-
import {
|
|
21
|
-
import { ForkFlowModel } from '../forkFlowModel';
|
|
20
|
+
import { FlowModel, ModelRenderMode } from '../flowModel';
|
|
22
21
|
|
|
23
22
|
// 全局处理测试中的未处理 Promise rejection
|
|
24
23
|
const originalUnhandledRejection = process.listeners('unhandledRejection');
|
|
@@ -134,6 +133,14 @@ let modelOptions: FlowModelOptions;
|
|
|
134
133
|
|
|
135
134
|
beforeEach(() => {
|
|
136
135
|
flowEngine = createMockFlowEngine();
|
|
136
|
+
// Mock api for FlowEngineContext
|
|
137
|
+
(flowEngine.context as any).api = {
|
|
138
|
+
auth: {
|
|
139
|
+
role: 'admin',
|
|
140
|
+
locale: 'en-US',
|
|
141
|
+
token: 'mock-token',
|
|
142
|
+
},
|
|
143
|
+
};
|
|
137
144
|
modelOptions = {
|
|
138
145
|
uid: 'test-model-uid',
|
|
139
146
|
flowEngine,
|
|
@@ -295,6 +302,17 @@ describe('FlowModel', () => {
|
|
|
295
302
|
model.setStepParams(null as any);
|
|
296
303
|
expect(model.stepParams).toEqual(originalParams);
|
|
297
304
|
});
|
|
305
|
+
|
|
306
|
+
test('should emit onStepParamsChanged when params updated', () => {
|
|
307
|
+
const listener = vi.fn();
|
|
308
|
+
model.emitter.on('onStepParamsChanged', listener);
|
|
309
|
+
|
|
310
|
+
model.setStepParams('flow1', 'step1', { foo: 'bar' });
|
|
311
|
+
|
|
312
|
+
expect(listener).toHaveBeenCalledTimes(1);
|
|
313
|
+
|
|
314
|
+
model.emitter.off('onStepParamsChanged', listener);
|
|
315
|
+
});
|
|
298
316
|
});
|
|
299
317
|
});
|
|
300
318
|
|
|
@@ -392,7 +410,7 @@ describe('FlowModel', () => {
|
|
|
392
410
|
TestFlowModel.registerFlow(exitFlow2);
|
|
393
411
|
const loggerSpy = vi.spyOn(model.context.logger, 'info').mockImplementation(() => {});
|
|
394
412
|
|
|
395
|
-
await model.
|
|
413
|
+
await model.dispatchEvent('beforeRender');
|
|
396
414
|
|
|
397
415
|
expect(exitFlow.steps.step2.handler).not.toHaveBeenCalled();
|
|
398
416
|
expect(exitFlow2.steps.step2.handler).toHaveBeenCalled();
|
|
@@ -430,7 +448,7 @@ describe('FlowModel', () => {
|
|
|
430
448
|
TestFlowModel.registerFlow(exitFlow2);
|
|
431
449
|
const loggerSpy = vi.spyOn(model.context.logger, 'info').mockImplementation(() => {});
|
|
432
450
|
|
|
433
|
-
await model.
|
|
451
|
+
await model.dispatchEvent('beforeRender');
|
|
434
452
|
|
|
435
453
|
expect(exitFlow.steps.step2.handler).not.toHaveBeenCalled();
|
|
436
454
|
expect(exitFlow2.steps.step2.handler).not.toHaveBeenCalled();
|
|
@@ -530,7 +548,7 @@ describe('FlowModel', () => {
|
|
|
530
548
|
});
|
|
531
549
|
});
|
|
532
550
|
|
|
533
|
-
describe('
|
|
551
|
+
describe('beforeRender flows', () => {
|
|
534
552
|
test('should execute all auto flows', async () => {
|
|
535
553
|
const autoFlow1 = { ...createAutoFlowDefinition(), key: 'auto1', sort: 1 };
|
|
536
554
|
const autoFlow2 = { ...createAutoFlowDefinition(), key: 'auto2', sort: 2 };
|
|
@@ -540,7 +558,7 @@ describe('FlowModel', () => {
|
|
|
540
558
|
TestFlowModel.registerFlow(autoFlow2);
|
|
541
559
|
TestFlowModel.registerFlow(manualFlow);
|
|
542
560
|
|
|
543
|
-
const results = await model.
|
|
561
|
+
const results = await model.dispatchEvent('beforeRender');
|
|
544
562
|
|
|
545
563
|
expect(results).toHaveLength(2);
|
|
546
564
|
expect(autoFlow1.steps.autoStep.handler).toHaveBeenCalled();
|
|
@@ -594,13 +612,13 @@ describe('FlowModel', () => {
|
|
|
594
612
|
TestFlowModel.registerFlow(autoFlow2);
|
|
595
613
|
TestFlowModel.registerFlow(autoFlow3);
|
|
596
614
|
|
|
597
|
-
await model.
|
|
615
|
+
await model.dispatchEvent('beforeRender');
|
|
598
616
|
|
|
599
617
|
expect(executionOrder).toEqual(['auto2', 'auto3', 'auto1']);
|
|
600
618
|
});
|
|
601
619
|
|
|
602
620
|
test('should no results when no auto flows found', async () => {
|
|
603
|
-
const results = await model.
|
|
621
|
+
const results = await model.dispatchEvent('beforeRender');
|
|
604
622
|
|
|
605
623
|
expect(results).toEqual([]);
|
|
606
624
|
// Note: Log output may be captured in stderr, not console.log
|
|
@@ -617,16 +635,14 @@ describe('FlowModel', () => {
|
|
|
617
635
|
afterHookSpy = vi.fn();
|
|
618
636
|
errorHookSpy = vi.fn();
|
|
619
637
|
TestFlowModelWithHooks = class extends TestFlowModel {
|
|
620
|
-
async
|
|
621
|
-
beforeHookSpy(inputArgs);
|
|
638
|
+
async onDispatchEventStart(eventName: string, _opts?: any, inputArgs?: Record<string, any>) {
|
|
639
|
+
if (eventName === 'beforeRender') beforeHookSpy(inputArgs);
|
|
622
640
|
}
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
afterHookSpy(results, inputArgs);
|
|
641
|
+
async onDispatchEventEnd(eventName: string, _opts?: any, inputArgs?: Record<string, any>, results?: any[]) {
|
|
642
|
+
if (eventName === 'beforeRender') afterHookSpy(results, inputArgs);
|
|
626
643
|
}
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
errorHookSpy(error, inputArgs);
|
|
644
|
+
async onDispatchEventError(eventName: string, _opts?: any, inputArgs?: Record<string, any>, error?: Error) {
|
|
645
|
+
if (eventName === 'beforeRender') errorHookSpy(error, inputArgs);
|
|
630
646
|
}
|
|
631
647
|
};
|
|
632
648
|
});
|
|
@@ -638,7 +654,7 @@ describe('FlowModel', () => {
|
|
|
638
654
|
const modelWithHooks = new TestFlowModelWithHooks(modelOptions);
|
|
639
655
|
const inputArgs = { test: 'value' };
|
|
640
656
|
|
|
641
|
-
const results = await modelWithHooks.
|
|
657
|
+
const results = await modelWithHooks.dispatchEvent('beforeRender', inputArgs);
|
|
642
658
|
|
|
643
659
|
// Verify hooks were called
|
|
644
660
|
expect(beforeHookSpy).toHaveBeenCalledTimes(1);
|
|
@@ -654,22 +670,22 @@ describe('FlowModel', () => {
|
|
|
654
670
|
);
|
|
655
671
|
});
|
|
656
672
|
|
|
657
|
-
test(
|
|
673
|
+
test("should allow onDispatchEventStart('beforeRender') to terminate flow via ctx.exit()", async () => {
|
|
658
674
|
const autoFlow1 = { ...createAutoFlowDefinition(), key: 'auto1' };
|
|
659
675
|
const autoFlow2 = { ...createAutoFlowDefinition(), key: 'auto2' };
|
|
660
676
|
|
|
661
677
|
const TestFlowModelWithExitHooks = class extends TestFlowModel {
|
|
662
|
-
async
|
|
663
|
-
|
|
664
|
-
|
|
678
|
+
async onDispatchEventStart(eventName: string, _opts?: any, inputArgs?: Record<string, any>) {
|
|
679
|
+
if (eventName === 'beforeRender') {
|
|
680
|
+
beforeHookSpy(inputArgs);
|
|
681
|
+
throw new FlowExitException('beforeRender', this.uid);
|
|
682
|
+
}
|
|
665
683
|
}
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
afterHookSpy(results, inputArgs);
|
|
684
|
+
async onDispatchEventEnd(eventName: string, _o?: any, _i?: any, _r?: any[]) {
|
|
685
|
+
if (eventName === 'beforeRender') afterHookSpy(_r, _i);
|
|
669
686
|
}
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
errorHookSpy(error, inputArgs);
|
|
687
|
+
async onDispatchEventError(eventName: string, _o?: any, i?: any, e?: Error) {
|
|
688
|
+
if (eventName === 'beforeRender') errorHookSpy(e, i);
|
|
673
689
|
}
|
|
674
690
|
};
|
|
675
691
|
|
|
@@ -678,9 +694,9 @@ describe('FlowModel', () => {
|
|
|
678
694
|
TestFlowModelWithExitHooks.registerFlow(autoFlow2);
|
|
679
695
|
|
|
680
696
|
const modelWithHooks = new TestFlowModelWithExitHooks(modelOptions);
|
|
681
|
-
const results = await modelWithHooks.
|
|
697
|
+
const results = await modelWithHooks.dispatchEvent('beforeRender');
|
|
682
698
|
|
|
683
|
-
// Should have called
|
|
699
|
+
// Should have called onDispatchEventStart but not onDispatchEventEnd
|
|
684
700
|
expect(beforeHookSpy).toHaveBeenCalledTimes(1);
|
|
685
701
|
expect(afterHookSpy).not.toHaveBeenCalled();
|
|
686
702
|
expect(errorHookSpy).not.toHaveBeenCalled();
|
|
@@ -688,12 +704,12 @@ describe('FlowModel', () => {
|
|
|
688
704
|
// Should return empty results since flow was terminated early
|
|
689
705
|
expect(results).toEqual([]);
|
|
690
706
|
|
|
691
|
-
//
|
|
707
|
+
// flows should not have been executed
|
|
692
708
|
expect(autoFlow1.steps.autoStep.handler).not.toHaveBeenCalled();
|
|
693
709
|
expect(autoFlow2.steps.autoStep.handler).not.toHaveBeenCalled();
|
|
694
710
|
});
|
|
695
711
|
|
|
696
|
-
test(
|
|
712
|
+
test("should call onDispatchEventError('beforeRender') when flow execution fails", async () => {
|
|
697
713
|
const errorFlow = {
|
|
698
714
|
key: 'errorFlow',
|
|
699
715
|
|
|
@@ -708,11 +724,8 @@ describe('FlowModel', () => {
|
|
|
708
724
|
TestFlowModelWithHooks.registerFlow(errorFlow);
|
|
709
725
|
|
|
710
726
|
const modelWithHooks = new TestFlowModelWithHooks(modelOptions);
|
|
711
|
-
|
|
712
|
-
//
|
|
713
|
-
await expect(modelWithHooks.applyAutoFlows()).rejects.toThrow('Test error');
|
|
714
|
-
|
|
715
|
-
// Verify hooks were called
|
|
727
|
+
await expect(modelWithHooks.dispatchEvent('beforeRender')).rejects.toThrow('Test error');
|
|
728
|
+
// Verify hooks were called (error path)
|
|
716
729
|
expect(beforeHookSpy).toHaveBeenCalledTimes(1);
|
|
717
730
|
expect(afterHookSpy).not.toHaveBeenCalled();
|
|
718
731
|
expect(errorHookSpy).toHaveBeenCalledTimes(1);
|
|
@@ -726,14 +739,14 @@ describe('FlowModel', () => {
|
|
|
726
739
|
);
|
|
727
740
|
});
|
|
728
741
|
|
|
729
|
-
test('should provide access to step results in
|
|
742
|
+
test('should provide access to step results in onDispatchEventEnd(beforeRender)', async () => {
|
|
730
743
|
const autoFlow1 = { ...createAutoFlowDefinition(), key: 'auto1' };
|
|
731
744
|
const autoFlow2 = { ...createAutoFlowDefinition(), key: 'auto2' };
|
|
732
745
|
TestFlowModelWithHooks.registerFlow(autoFlow1);
|
|
733
746
|
TestFlowModelWithHooks.registerFlow(autoFlow2);
|
|
734
747
|
|
|
735
748
|
const modelWithHooks = new TestFlowModelWithHooks(modelOptions);
|
|
736
|
-
await modelWithHooks.
|
|
749
|
+
await modelWithHooks.dispatchEvent('beforeRender');
|
|
737
750
|
|
|
738
751
|
expect(afterHookSpy).toHaveBeenCalledTimes(1);
|
|
739
752
|
|
|
@@ -777,6 +790,82 @@ describe('FlowModel', () => {
|
|
|
777
790
|
}
|
|
778
791
|
});
|
|
779
792
|
|
|
793
|
+
test('getFlows includes beforeRender and no-on flows; excludes manual and other events', async () => {
|
|
794
|
+
const TestM = class extends FlowModel {};
|
|
795
|
+
const beforeHandler = vi.fn();
|
|
796
|
+
const noOnHandler = vi.fn();
|
|
797
|
+
const manualHandler = vi.fn();
|
|
798
|
+
|
|
799
|
+
TestM.registerFlow({ key: 'beforeA', on: 'beforeRender', sort: 2, steps: { s: { handler: beforeHandler } } });
|
|
800
|
+
TestM.registerFlow({ key: 'noOnB', sort: 1, steps: { s: { handler: noOnHandler } } });
|
|
801
|
+
TestM.registerFlow({ key: 'manualSkip', manual: true, steps: { s: { handler: manualHandler } } });
|
|
802
|
+
TestM.registerFlow({ key: 'otherEvent', on: 'click', steps: { s: { handler: vi.fn() } } });
|
|
803
|
+
|
|
804
|
+
const m = new TestM(modelOptions);
|
|
805
|
+
const autoKeys = m.getEventFlows('beforeRender').map((f) => f.key);
|
|
806
|
+
|
|
807
|
+
// sort 按 1,2 排序:noOnB -> beforeA
|
|
808
|
+
expect(autoKeys).toEqual(['noOnB', 'beforeA']);
|
|
809
|
+
|
|
810
|
+
// beforeRender 会运行两者
|
|
811
|
+
await m.dispatchEvent('beforeRender');
|
|
812
|
+
expect(beforeHandler).toHaveBeenCalledTimes(1);
|
|
813
|
+
expect(noOnHandler).toHaveBeenCalledTimes(1);
|
|
814
|
+
expect(manualHandler).not.toHaveBeenCalled();
|
|
815
|
+
});
|
|
816
|
+
|
|
817
|
+
test('beforeRender executes in sort order mixing no-on and beforeRender', async () => {
|
|
818
|
+
const TestM = class extends FlowModel {};
|
|
819
|
+
const calls: string[] = [];
|
|
820
|
+
TestM.registerFlow({ key: 'noOn1', sort: 1, steps: { s: { handler: () => calls.push('noOn1') } } });
|
|
821
|
+
TestM.registerFlow({
|
|
822
|
+
key: 'before2',
|
|
823
|
+
on: 'beforeRender',
|
|
824
|
+
sort: 2,
|
|
825
|
+
steps: { s: { handler: () => calls.push('before2') } },
|
|
826
|
+
});
|
|
827
|
+
TestM.registerFlow({ key: 'noOn3', sort: 3, steps: { s: { handler: () => calls.push('noOn3') } } });
|
|
828
|
+
|
|
829
|
+
const m = new TestM(modelOptions);
|
|
830
|
+
await m.dispatchEvent('beforeRender');
|
|
831
|
+
expect(calls).toEqual(['noOn1', 'before2', 'noOn3']);
|
|
832
|
+
});
|
|
833
|
+
|
|
834
|
+
test("model.dispatchEvent('beforeRender') uses cache keyed by eventName", async () => {
|
|
835
|
+
const TestM = class extends FlowModel {};
|
|
836
|
+
const handler = vi.fn();
|
|
837
|
+
TestM.registerFlow({ key: 'autoA', steps: { s: { handler } } });
|
|
838
|
+
|
|
839
|
+
const m = new TestM(modelOptions);
|
|
840
|
+
await m.dispatchEvent('beforeRender');
|
|
841
|
+
await m.dispatchEvent('beforeRender');
|
|
842
|
+
expect(handler).toHaveBeenCalledTimes(1);
|
|
843
|
+
});
|
|
844
|
+
|
|
845
|
+
test('invalidFlowCache should clear specific event cache', async () => {
|
|
846
|
+
const TestM = class extends FlowModel {};
|
|
847
|
+
const h1 = vi.fn();
|
|
848
|
+
const h2 = vi.fn();
|
|
849
|
+
TestM.registerFlow({ key: 'onFoo', on: 'foo', steps: { s: { handler: h1 } } });
|
|
850
|
+
TestM.registerFlow({ key: 'onBar', on: 'bar', steps: { s: { handler: h2 } } });
|
|
851
|
+
|
|
852
|
+
const m = new TestM(modelOptions);
|
|
853
|
+
await m.dispatchEvent('foo', {}, { useCache: true });
|
|
854
|
+
await m.dispatchEvent('bar', {}, { useCache: true });
|
|
855
|
+
|
|
856
|
+
// cached
|
|
857
|
+
await m.dispatchEvent('foo', {}, { useCache: true });
|
|
858
|
+
await m.dispatchEvent('bar', {}, { useCache: true });
|
|
859
|
+
expect(h1).toHaveBeenCalledTimes(1);
|
|
860
|
+
expect(h2).toHaveBeenCalledTimes(1);
|
|
861
|
+
|
|
862
|
+
// invalidate foo only
|
|
863
|
+
m.invalidateFlowCache('foo');
|
|
864
|
+
await m.dispatchEvent('foo', {}, { useCache: true });
|
|
865
|
+
await m.dispatchEvent('bar', {}, { useCache: true });
|
|
866
|
+
expect(h1).toHaveBeenCalledTimes(2);
|
|
867
|
+
expect(h2).toHaveBeenCalledTimes(1);
|
|
868
|
+
});
|
|
780
869
|
test('should handle multiple flows for same event', async () => {
|
|
781
870
|
const eventFlow1 = { ...createEventFlowDefinition('sharedEvent'), key: 'event1' };
|
|
782
871
|
const eventFlow2 = { ...createEventFlowDefinition('sharedEvent'), key: 'event2' };
|
|
@@ -802,10 +891,17 @@ describe('FlowModel', () => {
|
|
|
802
891
|
const _dispatchEventWithDebounceSpy = vi.spyOn(model as any, '_dispatchEventWithDebounce');
|
|
803
892
|
|
|
804
893
|
// Test with debounce enabled
|
|
805
|
-
await model.dispatchEvent('debouncedEvent', { data: 'test' }, { debounce: true });
|
|
894
|
+
await model.dispatchEvent('debouncedEvent', { data: 'test' }, { debounce: true, sequential: true });
|
|
806
895
|
|
|
807
|
-
expect(_dispatchEventWithDebounceSpy).toHaveBeenCalledWith(
|
|
808
|
-
|
|
896
|
+
expect(_dispatchEventWithDebounceSpy).toHaveBeenCalledWith(
|
|
897
|
+
'debouncedEvent',
|
|
898
|
+
{ data: 'test' },
|
|
899
|
+
expect.objectContaining({ sequential: true }),
|
|
900
|
+
);
|
|
901
|
+
// _dispatchEvent is called by _dispatchEventWithDebounce after debounce
|
|
902
|
+
// So we check it's called at least once eventually
|
|
903
|
+
await new Promise((resolve) => setTimeout(resolve, 150));
|
|
904
|
+
expect(_dispatchEventSpy).toHaveBeenCalledTimes(1);
|
|
809
905
|
|
|
810
906
|
_dispatchEventSpy.mockRestore();
|
|
811
907
|
_dispatchEventWithDebounceSpy.mockRestore();
|
|
@@ -821,7 +917,11 @@ describe('FlowModel', () => {
|
|
|
821
917
|
// Test with debounce disabled
|
|
822
918
|
await model.dispatchEvent('normalEvent', { data: 'test' }, { debounce: false });
|
|
823
919
|
|
|
824
|
-
expect(_dispatchEventSpy).toHaveBeenCalledWith(
|
|
920
|
+
expect(_dispatchEventSpy).toHaveBeenCalledWith(
|
|
921
|
+
'normalEvent',
|
|
922
|
+
{ data: 'test' },
|
|
923
|
+
expect.objectContaining({ sequential: true }),
|
|
924
|
+
);
|
|
825
925
|
expect(_dispatchEventWithDebounceSpy).not.toHaveBeenCalled();
|
|
826
926
|
|
|
827
927
|
_dispatchEventSpy.mockRestore();
|
|
@@ -838,7 +938,11 @@ describe('FlowModel', () => {
|
|
|
838
938
|
// Test without debounce option
|
|
839
939
|
await model.dispatchEvent('defaultEvent', { data: 'test' });
|
|
840
940
|
|
|
841
|
-
expect(_dispatchEventSpy).toHaveBeenCalledWith(
|
|
941
|
+
expect(_dispatchEventSpy).toHaveBeenCalledWith(
|
|
942
|
+
'defaultEvent',
|
|
943
|
+
{ data: 'test' },
|
|
944
|
+
expect.objectContaining({ sequential: true }),
|
|
945
|
+
);
|
|
842
946
|
expect(_dispatchEventWithDebounceSpy).not.toHaveBeenCalled();
|
|
843
947
|
|
|
844
948
|
_dispatchEventSpy.mockRestore();
|
|
@@ -855,7 +959,11 @@ describe('FlowModel', () => {
|
|
|
855
959
|
// Test with undefined options
|
|
856
960
|
await model.dispatchEvent('undefinedOptionsEvent', { data: 'test' }, undefined);
|
|
857
961
|
|
|
858
|
-
expect(_dispatchEventSpy).toHaveBeenCalledWith(
|
|
962
|
+
expect(_dispatchEventSpy).toHaveBeenCalledWith(
|
|
963
|
+
'undefinedOptionsEvent',
|
|
964
|
+
{ data: 'test' },
|
|
965
|
+
expect.objectContaining({ sequential: true }),
|
|
966
|
+
);
|
|
859
967
|
expect(_dispatchEventWithDebounceSpy).not.toHaveBeenCalled();
|
|
860
968
|
|
|
861
969
|
_dispatchEventSpy.mockRestore();
|
|
@@ -881,7 +989,7 @@ describe('FlowModel', () => {
|
|
|
881
989
|
expect(handlerSpy).toHaveBeenCalledTimes(1);
|
|
882
990
|
expect(handlerSpy).toHaveBeenLastCalledWith(
|
|
883
991
|
expect.objectContaining({
|
|
884
|
-
inputArgs: { call:
|
|
992
|
+
inputArgs: expect.objectContaining({ call: 1 }),
|
|
885
993
|
}),
|
|
886
994
|
expect.any(Object),
|
|
887
995
|
);
|
|
@@ -904,21 +1012,21 @@ describe('FlowModel', () => {
|
|
|
904
1012
|
expect(handlerSpy).toHaveBeenNthCalledWith(
|
|
905
1013
|
1,
|
|
906
1014
|
expect.objectContaining({
|
|
907
|
-
inputArgs: { call: 1 },
|
|
1015
|
+
inputArgs: expect.objectContaining({ call: 1 }),
|
|
908
1016
|
}),
|
|
909
1017
|
expect.any(Object),
|
|
910
1018
|
);
|
|
911
1019
|
expect(handlerSpy).toHaveBeenNthCalledWith(
|
|
912
1020
|
2,
|
|
913
1021
|
expect.objectContaining({
|
|
914
|
-
inputArgs: { call: 2 },
|
|
1022
|
+
inputArgs: expect.objectContaining({ call: 2 }),
|
|
915
1023
|
}),
|
|
916
1024
|
expect.any(Object),
|
|
917
1025
|
);
|
|
918
1026
|
expect(handlerSpy).toHaveBeenNthCalledWith(
|
|
919
1027
|
3,
|
|
920
1028
|
expect.objectContaining({
|
|
921
|
-
inputArgs: { call: 3 },
|
|
1029
|
+
inputArgs: expect.objectContaining({ call: 3 }),
|
|
922
1030
|
}),
|
|
923
1031
|
expect.any(Object),
|
|
924
1032
|
);
|
|
@@ -946,14 +1054,14 @@ describe('FlowModel', () => {
|
|
|
946
1054
|
expect(handlerSpy).toHaveBeenNthCalledWith(
|
|
947
1055
|
1,
|
|
948
1056
|
expect.objectContaining({
|
|
949
|
-
inputArgs: { type: 'immediate' },
|
|
1057
|
+
inputArgs: expect.objectContaining({ type: 'immediate' }),
|
|
950
1058
|
}),
|
|
951
1059
|
expect.any(Object),
|
|
952
1060
|
);
|
|
953
1061
|
expect(handlerSpy).toHaveBeenNthCalledWith(
|
|
954
1062
|
2,
|
|
955
1063
|
expect.objectContaining({
|
|
956
|
-
inputArgs: { type: 'debounced', call:
|
|
1064
|
+
inputArgs: expect.objectContaining({ type: 'debounced', call: 1 }),
|
|
957
1065
|
}),
|
|
958
1066
|
expect.any(Object),
|
|
959
1067
|
);
|
|
@@ -981,7 +1089,7 @@ describe('FlowModel', () => {
|
|
|
981
1089
|
expect(handlerSpy).toHaveBeenCalledTimes(1);
|
|
982
1090
|
expect(handlerSpy).toHaveBeenCalledWith(
|
|
983
1091
|
expect.objectContaining({
|
|
984
|
-
inputArgs,
|
|
1092
|
+
inputArgs: expect.objectContaining(inputArgs),
|
|
985
1093
|
}),
|
|
986
1094
|
expect.any(Object),
|
|
987
1095
|
);
|
|
@@ -1265,41 +1373,63 @@ describe('FlowModel', () => {
|
|
|
1265
1373
|
});
|
|
1266
1374
|
});
|
|
1267
1375
|
|
|
1268
|
-
describe('
|
|
1376
|
+
describe('applySubModelsBeforeRenderFlows', () => {
|
|
1269
1377
|
test('should apply auto flows to all array subModels', async () => {
|
|
1270
1378
|
const child1 = new FlowModel({ uid: 'child1', flowEngine });
|
|
1271
1379
|
const child2 = new FlowModel({ uid: 'child2', flowEngine });
|
|
1272
1380
|
|
|
1273
|
-
child1.
|
|
1274
|
-
child2.
|
|
1381
|
+
child1.dispatchEvent = vi.fn().mockResolvedValue(undefined) as any;
|
|
1382
|
+
child2.dispatchEvent = vi.fn().mockResolvedValue(undefined) as any;
|
|
1275
1383
|
|
|
1276
1384
|
parentModel.addSubModel('children', child1);
|
|
1277
1385
|
parentModel.addSubModel('children', child2);
|
|
1278
1386
|
|
|
1279
1387
|
const runtimeData = { test: 'extra' };
|
|
1280
1388
|
|
|
1281
|
-
await parentModel.
|
|
1389
|
+
await parentModel.applySubModelsBeforeRenderFlows('children', runtimeData);
|
|
1282
1390
|
|
|
1283
|
-
expect(child1.
|
|
1284
|
-
expect(child2.
|
|
1391
|
+
expect(child1.dispatchEvent).toHaveBeenCalledWith('beforeRender', runtimeData);
|
|
1392
|
+
expect(child2.dispatchEvent).toHaveBeenCalledWith('beforeRender', runtimeData);
|
|
1285
1393
|
});
|
|
1286
1394
|
|
|
1287
1395
|
test('should apply auto flows to single subModel', async () => {
|
|
1288
1396
|
const child = new FlowModel({ uid: 'child', flowEngine });
|
|
1289
1397
|
|
|
1290
|
-
child.
|
|
1398
|
+
child.dispatchEvent = vi.fn().mockResolvedValue(undefined) as any;
|
|
1291
1399
|
|
|
1292
1400
|
parentModel.setSubModel('child', child);
|
|
1293
1401
|
|
|
1294
1402
|
const runtimeData = { test: 'extra' };
|
|
1295
1403
|
|
|
1296
|
-
await parentModel.
|
|
1404
|
+
await parentModel.applySubModelsBeforeRenderFlows('child', runtimeData);
|
|
1297
1405
|
|
|
1298
|
-
expect(child.
|
|
1406
|
+
expect(child.dispatchEvent).toHaveBeenCalledWith('beforeRender', runtimeData);
|
|
1299
1407
|
});
|
|
1300
1408
|
|
|
1301
1409
|
test('should handle empty subModels gracefully', async () => {
|
|
1302
|
-
await expect(parentModel.
|
|
1410
|
+
await expect(parentModel.applySubModelsBeforeRenderFlows('nonExistent')).resolves.not.toThrow();
|
|
1411
|
+
});
|
|
1412
|
+
});
|
|
1413
|
+
|
|
1414
|
+
describe('beforeRender cache invalidation on inputArgs change', () => {
|
|
1415
|
+
test('should rerun when inputArgs changed and reuse when equal', async () => {
|
|
1416
|
+
const TestM = class extends FlowModel {};
|
|
1417
|
+
const handler = vi.fn();
|
|
1418
|
+
TestM.registerFlow({ key: 'auto1', steps: { s: { handler } } });
|
|
1419
|
+
|
|
1420
|
+
const m = new TestM(modelOptions);
|
|
1421
|
+
|
|
1422
|
+
// First run with {a:1}
|
|
1423
|
+
await m.dispatchEvent('beforeRender', { a: 1 });
|
|
1424
|
+
expect(handler).toHaveBeenCalledTimes(1);
|
|
1425
|
+
|
|
1426
|
+
// Second run with same args should hit cache -> no extra handler calls
|
|
1427
|
+
await m.dispatchEvent('beforeRender', { a: 1 });
|
|
1428
|
+
expect(handler).toHaveBeenCalledTimes(1);
|
|
1429
|
+
|
|
1430
|
+
// Different args invalidate cache -> handler called again
|
|
1431
|
+
await m.dispatchEvent('beforeRender', { a: 2 });
|
|
1432
|
+
expect(handler).toHaveBeenCalledTimes(2);
|
|
1303
1433
|
});
|
|
1304
1434
|
});
|
|
1305
1435
|
|
|
@@ -1415,8 +1545,6 @@ describe('FlowModel', () => {
|
|
|
1415
1545
|
const fork1 = model.createFork();
|
|
1416
1546
|
const fork2 = model.createFork();
|
|
1417
1547
|
|
|
1418
|
-
expect(fork1.forkId).toBe(0);
|
|
1419
|
-
expect(fork2.forkId).toBe(1);
|
|
1420
1548
|
expect(model.forks.size).toBe(2);
|
|
1421
1549
|
expect(model.forks.has(fork1)).toBe(true);
|
|
1422
1550
|
expect(model.forks.has(fork2)).toBe(true);
|
|
@@ -1430,13 +1558,27 @@ describe('FlowModel', () => {
|
|
|
1430
1558
|
expect(model.forks.size).toBe(1);
|
|
1431
1559
|
});
|
|
1432
1560
|
|
|
1561
|
+
test('should recreate cached fork after dispose to avoid state leakage', () => {
|
|
1562
|
+
const fork1 = model.createFork({ foo: 'bar' }, 'cacheKey');
|
|
1563
|
+
fork1.hidden = true;
|
|
1564
|
+
fork1.setProps({ disabled: true });
|
|
1565
|
+
|
|
1566
|
+
fork1.dispose();
|
|
1567
|
+
|
|
1568
|
+
expect(model.getFork('cacheKey')).toBeUndefined();
|
|
1569
|
+
|
|
1570
|
+
const fork2 = model.createFork({}, 'cacheKey');
|
|
1571
|
+
|
|
1572
|
+
expect(fork2).not.toBe(fork1);
|
|
1573
|
+
expect(fork2.hidden).toBe(false);
|
|
1574
|
+
expect(fork2.localProps).toEqual({});
|
|
1575
|
+
});
|
|
1576
|
+
|
|
1433
1577
|
test('should create different instances for different keys', () => {
|
|
1434
1578
|
const fork1 = model.createFork({}, 'key1');
|
|
1435
1579
|
const fork2 = model.createFork({}, 'key2');
|
|
1436
1580
|
|
|
1437
1581
|
expect(fork1).not.toBe(fork2);
|
|
1438
|
-
expect(fork1.forkId).toBe(0);
|
|
1439
|
-
expect(fork2.forkId).toBe(1);
|
|
1440
1582
|
});
|
|
1441
1583
|
|
|
1442
1584
|
test('should create fork with local props', () => {
|
|
@@ -1627,7 +1769,7 @@ describe('FlowModel', () => {
|
|
|
1627
1769
|
});
|
|
1628
1770
|
|
|
1629
1771
|
describe('rendering operations', () => {
|
|
1630
|
-
test('should not pre-call render for RenderFunction mode and call exactly once on render', () => {
|
|
1772
|
+
test('should not pre-call render for RenderFunction mode and call exactly once on render', async () => {
|
|
1631
1773
|
const renderSpy = vi.fn(() => vi.fn());
|
|
1632
1774
|
|
|
1633
1775
|
class CallbackRenderModel extends FlowModel {
|
|
@@ -1645,17 +1787,20 @@ describe('FlowModel', () => {
|
|
|
1645
1787
|
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
|
1646
1788
|
try {
|
|
1647
1789
|
const { unmount } = render(
|
|
1648
|
-
React.createElement(
|
|
1790
|
+
React.createElement(
|
|
1791
|
+
FlowEngineProvider,
|
|
1792
|
+
{ engine: callbackModel.flowEngine },
|
|
1793
|
+
React.createElement(FlowModelRenderer, { model: callbackModel }),
|
|
1794
|
+
),
|
|
1649
1795
|
);
|
|
1650
|
-
|
|
1651
|
-
expect(renderSpy).toHaveBeenCalledTimes(1);
|
|
1796
|
+
await waitFor(() => expect(renderSpy).toHaveBeenCalledTimes(1));
|
|
1652
1797
|
unmount();
|
|
1653
1798
|
} finally {
|
|
1654
1799
|
warnSpy.mockRestore();
|
|
1655
1800
|
}
|
|
1656
1801
|
});
|
|
1657
1802
|
|
|
1658
|
-
test('should not pre-call render for ReactElement mode and call exactly once on actual render', () => {
|
|
1803
|
+
test('should not pre-call render for ReactElement mode and call exactly once on actual render', async () => {
|
|
1659
1804
|
const renderSpy = vi.fn(() => React.createElement('div', { 'data-testid': 'elt' }, 'Elt'));
|
|
1660
1805
|
|
|
1661
1806
|
class ElementRenderModel extends FlowModel {
|
|
@@ -1670,11 +1815,15 @@ describe('FlowModel', () => {
|
|
|
1670
1815
|
expect(renderSpy).toHaveBeenCalledTimes(0);
|
|
1671
1816
|
|
|
1672
1817
|
const { getByTestId, unmount } = render(
|
|
1673
|
-
React.createElement(
|
|
1818
|
+
React.createElement(
|
|
1819
|
+
FlowEngineProvider,
|
|
1820
|
+
{ engine: elementModel.flowEngine },
|
|
1821
|
+
React.createElement(FlowModelRenderer, { model: elementModel }),
|
|
1822
|
+
),
|
|
1674
1823
|
);
|
|
1675
1824
|
|
|
1676
1825
|
// Render should be called exactly once during mount
|
|
1677
|
-
expect(renderSpy).toHaveBeenCalledTimes(1);
|
|
1826
|
+
await waitFor(() => expect(renderSpy).toHaveBeenCalledTimes(1));
|
|
1678
1827
|
expect(getByTestId('elt')).toBeTruthy();
|
|
1679
1828
|
|
|
1680
1829
|
unmount();
|
|
@@ -1690,13 +1839,15 @@ describe('FlowModel', () => {
|
|
|
1690
1839
|
expect(result.type.displayName).toBe('ReactiveWrapper(FlowModel)');
|
|
1691
1840
|
});
|
|
1692
1841
|
|
|
1693
|
-
test('should rerender
|
|
1842
|
+
test('should rerender triggers beforeRender without cache', async () => {
|
|
1694
1843
|
const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
|
|
1695
|
-
model.
|
|
1844
|
+
model.dispatchEvent = vi.fn().mockResolvedValue(undefined) as any;
|
|
1696
1845
|
|
|
1697
1846
|
try {
|
|
1698
1847
|
await expect(model.rerender()).resolves.not.toThrow();
|
|
1699
|
-
expect(model.
|
|
1848
|
+
expect(model.dispatchEvent).toHaveBeenCalledWith('beforeRender', undefined, {
|
|
1849
|
+
useCache: false,
|
|
1850
|
+
});
|
|
1700
1851
|
} finally {
|
|
1701
1852
|
consoleSpy.mockRestore();
|
|
1702
1853
|
}
|
|
@@ -1713,12 +1864,14 @@ describe('FlowModel', () => {
|
|
|
1713
1864
|
|
|
1714
1865
|
const serialized = model.serialize();
|
|
1715
1866
|
|
|
1716
|
-
expect(serialized).toEqual(
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1867
|
+
expect(serialized).toEqual(
|
|
1868
|
+
expect.objectContaining({
|
|
1869
|
+
uid: model.uid,
|
|
1870
|
+
stepParams: expect.objectContaining({ flow1: { step1: { param1: 'value1' } } }),
|
|
1871
|
+
sortIndex: 5,
|
|
1872
|
+
subModels: expect.any(Object),
|
|
1873
|
+
}),
|
|
1874
|
+
);
|
|
1722
1875
|
// props should be excluded from serialization
|
|
1723
1876
|
expect(serialized.props).toBeUndefined();
|
|
1724
1877
|
expect(serialized.flowEngine).toBeUndefined();
|
|
@@ -1736,12 +1889,14 @@ describe('FlowModel', () => {
|
|
|
1736
1889
|
|
|
1737
1890
|
const serialized = emptyModel.serialize();
|
|
1738
1891
|
|
|
1739
|
-
expect(serialized).toEqual(
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1892
|
+
expect(serialized).toEqual(
|
|
1893
|
+
expect.objectContaining({
|
|
1894
|
+
uid: 'empty-model',
|
|
1895
|
+
stepParams: expect.any(Object),
|
|
1896
|
+
sortIndex: expect.any(Number),
|
|
1897
|
+
subModels: expect.any(Object),
|
|
1898
|
+
}),
|
|
1899
|
+
);
|
|
1745
1900
|
expect(serialized.flowEngine).toBeUndefined();
|
|
1746
1901
|
});
|
|
1747
1902
|
});
|
|
@@ -1861,6 +2016,22 @@ describe('FlowModel', () => {
|
|
|
1861
2016
|
expect(model.title).toBe('Custom Title');
|
|
1862
2017
|
});
|
|
1863
2018
|
|
|
2019
|
+
test('should be reactive when title changes', () => {
|
|
2020
|
+
const seen: string[] = [];
|
|
2021
|
+
const dispose = reaction(
|
|
2022
|
+
() => model.title,
|
|
2023
|
+
(next) => {
|
|
2024
|
+
if (typeof next === 'string') seen.push(next);
|
|
2025
|
+
},
|
|
2026
|
+
);
|
|
2027
|
+
|
|
2028
|
+
model.setTitle('First Title');
|
|
2029
|
+
model.setTitle('Second Title');
|
|
2030
|
+
|
|
2031
|
+
dispose();
|
|
2032
|
+
expect(seen).toEqual(['First Title', 'Second Title']);
|
|
2033
|
+
});
|
|
2034
|
+
|
|
1864
2035
|
test('should update title when called multiple times', () => {
|
|
1865
2036
|
model.setTitle('First Title');
|
|
1866
2037
|
expect(model.title).toBe('First Title');
|
|
@@ -2039,16 +2210,16 @@ describe('FlowModel', () => {
|
|
|
2039
2210
|
vi.restoreAllMocks();
|
|
2040
2211
|
});
|
|
2041
2212
|
|
|
2042
|
-
describe('
|
|
2213
|
+
describe('invalidateFlowCache', () => {
|
|
2043
2214
|
test('should delete auto flow cache for current model', () => {
|
|
2044
|
-
const expectedCacheKey = '
|
|
2215
|
+
const expectedCacheKey = 'event:beforeRender-beforeRender-test-model-uid';
|
|
2045
2216
|
realFlowEngine.applyFlowCache.set(expectedCacheKey, {
|
|
2046
2217
|
status: 'resolved',
|
|
2047
2218
|
data: [],
|
|
2048
2219
|
promise: Promise.resolve([]),
|
|
2049
2220
|
});
|
|
2050
2221
|
|
|
2051
|
-
model.
|
|
2222
|
+
model.invalidateFlowCache('beforeRender');
|
|
2052
2223
|
|
|
2053
2224
|
expect(deleteSpy).toHaveBeenCalledWith(expectedCacheKey);
|
|
2054
2225
|
});
|
|
@@ -2057,8 +2228,8 @@ describe('FlowModel', () => {
|
|
|
2057
2228
|
const fork1 = model.createFork();
|
|
2058
2229
|
const fork2 = model.createFork();
|
|
2059
2230
|
|
|
2060
|
-
const fork1CacheKey =
|
|
2061
|
-
const fork2CacheKey =
|
|
2231
|
+
const fork1CacheKey = `event:beforeRender:${fork1.forkId}-beforeRender-test-model-uid`;
|
|
2232
|
+
const fork2CacheKey = `event:beforeRender:${fork2.forkId}-beforeRender-test-model-uid`;
|
|
2062
2233
|
|
|
2063
2234
|
realFlowEngine.applyFlowCache.set(fork1CacheKey, {
|
|
2064
2235
|
status: 'resolved',
|
|
@@ -2071,7 +2242,7 @@ describe('FlowModel', () => {
|
|
|
2071
2242
|
promise: Promise.resolve([]),
|
|
2072
2243
|
});
|
|
2073
2244
|
|
|
2074
|
-
model.
|
|
2245
|
+
model.invalidateFlowCache('beforeRender');
|
|
2075
2246
|
|
|
2076
2247
|
expect(deleteSpy).toHaveBeenCalledWith(fork1CacheKey);
|
|
2077
2248
|
expect(deleteSpy).toHaveBeenCalledWith(fork2CacheKey);
|
|
@@ -2081,27 +2252,27 @@ describe('FlowModel', () => {
|
|
|
2081
2252
|
const childModel1 = new FlowModel({ uid: 'child1', flowEngine: realFlowEngine });
|
|
2082
2253
|
const childModel2 = new FlowModel({ uid: 'child2', flowEngine: realFlowEngine });
|
|
2083
2254
|
|
|
2084
|
-
const child1Spy = vi.spyOn(childModel1, '
|
|
2085
|
-
const child2Spy = vi.spyOn(childModel2, '
|
|
2255
|
+
const child1Spy = vi.spyOn(childModel1, 'invalidateFlowCache');
|
|
2256
|
+
const child2Spy = vi.spyOn(childModel2, 'invalidateFlowCache');
|
|
2086
2257
|
|
|
2087
2258
|
model.addSubModel('children', childModel1);
|
|
2088
2259
|
model.addSubModel('children', childModel2);
|
|
2089
2260
|
|
|
2090
|
-
model.
|
|
2261
|
+
model.invalidateFlowCache('beforeRender', true);
|
|
2091
2262
|
|
|
2092
|
-
expect(child1Spy).toHaveBeenCalledWith(true);
|
|
2093
|
-
expect(child2Spy).toHaveBeenCalledWith(true);
|
|
2263
|
+
expect(child1Spy).toHaveBeenCalledWith('beforeRender', true);
|
|
2264
|
+
expect(child2Spy).toHaveBeenCalledWith('beforeRender', true);
|
|
2094
2265
|
});
|
|
2095
2266
|
|
|
2096
2267
|
test('should recursively invalidate cache for object subModels', () => {
|
|
2097
2268
|
const childModel = new FlowModel({ uid: 'child', flowEngine: realFlowEngine });
|
|
2098
|
-
const childSpy = vi.spyOn(childModel, '
|
|
2269
|
+
const childSpy = vi.spyOn(childModel, 'invalidateFlowCache');
|
|
2099
2270
|
|
|
2100
2271
|
model.setSubModel('child', childModel);
|
|
2101
2272
|
|
|
2102
|
-
model.
|
|
2273
|
+
model.invalidateFlowCache('beforeRender', true);
|
|
2103
2274
|
|
|
2104
|
-
expect(childSpy).toHaveBeenCalledWith(true);
|
|
2275
|
+
expect(childSpy).toHaveBeenCalledWith('beforeRender', true);
|
|
2105
2276
|
});
|
|
2106
2277
|
|
|
2107
2278
|
test('should handle mixed array and object subModels', () => {
|
|
@@ -2109,25 +2280,31 @@ describe('FlowModel', () => {
|
|
|
2109
2280
|
const arrayChild2 = new FlowModel({ uid: 'arrayChild2', flowEngine: realFlowEngine });
|
|
2110
2281
|
const objectChild = new FlowModel({ uid: 'objectChild', flowEngine: realFlowEngine });
|
|
2111
2282
|
|
|
2112
|
-
const array1Spy = vi.spyOn(arrayChild1, '
|
|
2113
|
-
const array2Spy = vi.spyOn(arrayChild2, '
|
|
2114
|
-
const objectSpy = vi.spyOn(objectChild, '
|
|
2283
|
+
const array1Spy = vi.spyOn(arrayChild1, 'invalidateFlowCache');
|
|
2284
|
+
const array2Spy = vi.spyOn(arrayChild2, 'invalidateFlowCache');
|
|
2285
|
+
const objectSpy = vi.spyOn(objectChild, 'invalidateFlowCache');
|
|
2115
2286
|
|
|
2116
2287
|
model.addSubModel('arrayChildren', arrayChild1);
|
|
2117
2288
|
model.addSubModel('arrayChildren', arrayChild2);
|
|
2118
2289
|
model.setSubModel('objectChild', objectChild);
|
|
2119
2290
|
|
|
2120
|
-
model.
|
|
2291
|
+
model.invalidateFlowCache('beforeRender', true);
|
|
2121
2292
|
|
|
2122
|
-
expect(array1Spy).toHaveBeenCalledWith(true);
|
|
2123
|
-
expect(array2Spy).toHaveBeenCalledWith(true);
|
|
2124
|
-
expect(objectSpy).toHaveBeenCalledWith(true);
|
|
2293
|
+
expect(array1Spy).toHaveBeenCalledWith('beforeRender', true);
|
|
2294
|
+
expect(array2Spy).toHaveBeenCalledWith('beforeRender', true);
|
|
2295
|
+
expect(objectSpy).toHaveBeenCalledWith('beforeRender', true);
|
|
2125
2296
|
});
|
|
2126
2297
|
|
|
2127
2298
|
test('should handle empty subModels without error', () => {
|
|
2128
|
-
|
|
2299
|
+
realFlowEngine.applyFlowCache.set('event:beforeRender-beforeRender-test-model-uid', {
|
|
2300
|
+
status: 'resolved',
|
|
2301
|
+
data: [],
|
|
2302
|
+
promise: Promise.resolve([]),
|
|
2303
|
+
});
|
|
2304
|
+
|
|
2305
|
+
model.invalidateFlowCache('beforeRender');
|
|
2129
2306
|
|
|
2130
|
-
expect(deleteSpy).toHaveBeenCalledWith('
|
|
2307
|
+
expect(deleteSpy).toHaveBeenCalledWith('event:beforeRender-beforeRender-test-model-uid');
|
|
2131
2308
|
});
|
|
2132
2309
|
|
|
2133
2310
|
test('should handle null flowEngine gracefully', () => {
|
|
@@ -2135,19 +2312,19 @@ describe('FlowModel', () => {
|
|
|
2135
2312
|
modelWithValidEngine.flowEngine = null;
|
|
2136
2313
|
|
|
2137
2314
|
expect(() => {
|
|
2138
|
-
modelWithValidEngine.
|
|
2315
|
+
modelWithValidEngine.invalidateFlowCache('beforeRender');
|
|
2139
2316
|
}).not.toThrow();
|
|
2140
2317
|
});
|
|
2141
2318
|
|
|
2142
2319
|
test('should pass deep parameter to recursive calls', () => {
|
|
2143
2320
|
const childModel = new FlowModel({ uid: 'child', flowEngine: realFlowEngine });
|
|
2144
|
-
const childSpy = vi.spyOn(childModel, '
|
|
2321
|
+
const childSpy = vi.spyOn(childModel, 'invalidateFlowCache');
|
|
2145
2322
|
|
|
2146
2323
|
model.setSubModel('child', childModel);
|
|
2147
2324
|
|
|
2148
|
-
model.
|
|
2325
|
+
model.invalidateFlowCache('beforeRender', true);
|
|
2149
2326
|
|
|
2150
|
-
expect(childSpy).toHaveBeenCalledWith(true);
|
|
2327
|
+
expect(childSpy).toHaveBeenCalledWith('beforeRender', true);
|
|
2151
2328
|
});
|
|
2152
2329
|
});
|
|
2153
2330
|
});
|
|
@@ -2198,7 +2375,7 @@ describe('FlowModel', () => {
|
|
|
2198
2375
|
});
|
|
2199
2376
|
|
|
2200
2377
|
const handlerSpy = flow.steps.testStep.handler as any;
|
|
2201
|
-
await model.
|
|
2378
|
+
await model.dispatchEvent('beforeRender');
|
|
2202
2379
|
expect(handlerSpy).toHaveBeenCalled();
|
|
2203
2380
|
});
|
|
2204
2381
|
|
|
@@ -2245,7 +2422,7 @@ describe('FlowModel', () => {
|
|
|
2245
2422
|
});
|
|
2246
2423
|
|
|
2247
2424
|
const handlerSpy = flow.steps.nestedStep.handler as any;
|
|
2248
|
-
await model.
|
|
2425
|
+
await model.dispatchEvent('beforeRender');
|
|
2249
2426
|
expect(handlerSpy).toHaveBeenCalled();
|
|
2250
2427
|
});
|
|
2251
2428
|
});
|