From 237f66ac8ea67ee4e7415ac26d82b3cecebfad3e Mon Sep 17 00:00:00 2001 From: Omri Rosner Date: Wed, 11 Feb 2026 12:23:29 +0200 Subject: [PATCH 1/3] toggle remains active when workflow YAML has validation errors --- .../workflows/store/workflow_detail/selectors.ts | 8 +++++++- .../entities/workflows/store/workflow_detail/slice.ts | 6 ++++++ .../entities/workflows/store/workflow_detail/types.ts | 2 ++ .../workflow_detail/ui/workflow_detail_header.tsx | 1 + .../workflow_yaml_editor/ui/workflow_yaml_editor.tsx | 11 ++++++++++- 5 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/selectors.ts b/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/selectors.ts index 364fcfe613caf..2e4efbf71ff1f 100644 --- a/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/selectors.ts +++ b/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/selectors.ts @@ -49,11 +49,17 @@ export const selectWorkflowDefinition = createSelector( (computed) => computed?.workflowDefinition ); -// Only checks if the current workflow yaml can be parses, does check the schema, only the yaml syntax +// Only checks if the current workflow yaml can be parsed, does not check the schema, only the yaml syntax export const selectIsYamlSyntaxValid = createSelector(selectYamlComputed, (computed): boolean => Boolean(computed?.workflowDefinition) ); +// Checks whether validation errors (from strict schema + custom validations) are present +export const selectHasValidationErrors = createSelector( + selectDetail, + (detail): boolean => detail.validationErrorCount > 0 +); + export const selectFocusedStepId = createSelector(selectDetail, (detail) => detail.focusedStepId); export const selectHighlightedStepId = createSelector( diff --git a/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/slice.ts b/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/slice.ts index 994e06c2b9d71..27645092f26d1 100644 --- a/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/slice.ts +++ b/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/slice.ts @@ -28,6 +28,7 @@ const initialState: WorkflowDetailState = { highlightedStepId: undefined, isTestModalOpen: false, loading: initialLoadingState, + validationErrorCount: 0, connectorFlyout: { isOpen: false, connectorType: undefined, @@ -82,6 +83,10 @@ const workflowDetailSlice = createSlice({ state.activeTab = action.payload; }, + setValidationErrorCount: (state, action: { payload: number }) => { + state.validationErrorCount = action.payload; + }, + // Connector flyout actions openCreateConnectorFlyout: ( state, @@ -133,6 +138,7 @@ export const { setExecution, clearExecution, setActiveTab, + setValidationErrorCount, openCreateConnectorFlyout, openEditConnectorFlyout, closeConnectorFlyout, diff --git a/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/types.ts b/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/types.ts index 0107c37de535a..73dfaad34e77c 100644 --- a/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/types.ts +++ b/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/types.ts @@ -41,6 +41,8 @@ export interface WorkflowDetailState { schema: WorkflowZodSchemaType; /** Loading states for async operations */ loading: LoadingStates; + /** Number of validation errors reported by Monaco markers (strict schema + custom validations) */ + validationErrorCount: number; /** Connector flyout state */ connectorFlyout: { isOpen: boolean; diff --git a/src/platform/plugins/shared/workflows_management/public/pages/workflow_detail/ui/workflow_detail_header.tsx b/src/platform/plugins/shared/workflows_management/public/pages/workflow_detail/ui/workflow_detail_header.tsx index be57bb9ad52a9..efdf4c5c85e37 100644 --- a/src/platform/plugins/shared/workflows_management/public/pages/workflow_detail/ui/workflow_detail_header.tsx +++ b/src/platform/plugins/shared/workflows_management/public/pages/workflow_detail/ui/workflow_detail_header.tsx @@ -37,6 +37,7 @@ import { useSaveYaml } from '../../../entities/workflows/model/use_save_yaml'; import { useUpdateWorkflow } from '../../../entities/workflows/model/use_update_workflow'; import { selectHasChanges, + selectHasValidationErrors, selectIsExecutionsTab, selectIsSavingYaml, selectIsYamlSyntaxValid, diff --git a/src/platform/plugins/shared/workflows_management/public/widgets/workflow_yaml_editor/ui/workflow_yaml_editor.tsx b/src/platform/plugins/shared/workflows_management/public/widgets/workflow_yaml_editor/ui/workflow_yaml_editor.tsx index 26db5e824056a..6dc9f1fa6acb0 100644 --- a/src/platform/plugins/shared/workflows_management/public/widgets/workflow_yaml_editor/ui/workflow_yaml_editor.tsx +++ b/src/platform/plugins/shared/workflows_management/public/widgets/workflow_yaml_editor/ui/workflow_yaml_editor.tsx @@ -52,7 +52,10 @@ import { selectStepExecutions, selectWorkflow, } from '../../../entities/workflows/store/workflow_detail/selectors'; -import { setIsTestModalOpen } from '../../../entities/workflows/store/workflow_detail/slice'; +import { + setIsTestModalOpen, + setValidationErrorCount, +} from '../../../entities/workflows/store/workflow_detail/slice'; import { ActionsMenuPopover } from '../../../features/actions_menu_popover'; import type { ActionOptionData } from '../../../features/actions_menu_popover/types'; import { useMonacoMarkersChangedInterceptor } from '../../../features/validate_workflow_yaml/lib/use_monaco_markers_changed_interceptor'; @@ -248,6 +251,12 @@ export const WorkflowYAMLEditor = ({ workflowYamlSchema: workflowYamlSchema as z.ZodSchema, }); + // Sync validation error count to Redux so sibling components (e.g. header toggle) can react + useEffect(() => { + const errorCount = validationErrors.filter((e) => e.severity === 'error').length; + dispatch(setValidationErrorCount(errorCount)); + }, [validationErrors, dispatch]); + const handleErrorClick = useCallback((error: YamlValidationResult) => { if (!editorRef.current) { return; From ebe66fc4ceaf95dd18b5734cb6f62599a593edfe Mon Sep 17 00:00:00 2001 From: Omri Rosner Date: Wed, 11 Feb 2026 13:50:33 +0200 Subject: [PATCH 2/3] toggle remains active when workflow YAML has validation errors --- .../store/workflow_detail/selectors.ts | 2 +- .../workflows/store/workflow_detail/slice.ts | 8 +-- .../workflows/store/workflow_detail/types.ts | 4 +- .../ui/workflow_detail_header.test.tsx | 71 +++++++++++++------ .../ui/workflow_detail_header.tsx | 17 +++-- .../ui/workflow_yaml_editor.tsx | 8 +-- 6 files changed, 73 insertions(+), 37 deletions(-) diff --git a/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/selectors.ts b/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/selectors.ts index 2e4efbf71ff1f..f95e7263899d6 100644 --- a/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/selectors.ts +++ b/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/selectors.ts @@ -57,7 +57,7 @@ export const selectIsYamlSyntaxValid = createSelector(selectYamlComputed, (compu // Checks whether validation errors (from strict schema + custom validations) are present export const selectHasValidationErrors = createSelector( selectDetail, - (detail): boolean => detail.validationErrorCount > 0 + (detail): boolean => detail.hasValidationErrors ); export const selectFocusedStepId = createSelector(selectDetail, (detail) => detail.focusedStepId); diff --git a/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/slice.ts b/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/slice.ts index 27645092f26d1..3354e0c44b1f6 100644 --- a/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/slice.ts +++ b/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/slice.ts @@ -28,7 +28,7 @@ const initialState: WorkflowDetailState = { highlightedStepId: undefined, isTestModalOpen: false, loading: initialLoadingState, - validationErrorCount: 0, + hasValidationErrors: false, connectorFlyout: { isOpen: false, connectorType: undefined, @@ -83,8 +83,8 @@ const workflowDetailSlice = createSlice({ state.activeTab = action.payload; }, - setValidationErrorCount: (state, action: { payload: number }) => { - state.validationErrorCount = action.payload; + setHasValidationErrors: (state, action: { payload: boolean }) => { + state.hasValidationErrors = action.payload; }, // Connector flyout actions @@ -138,7 +138,7 @@ export const { setExecution, clearExecution, setActiveTab, - setValidationErrorCount, + setHasValidationErrors, openCreateConnectorFlyout, openEditConnectorFlyout, closeConnectorFlyout, diff --git a/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/types.ts b/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/types.ts index 73dfaad34e77c..8a93ed37161b8 100644 --- a/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/types.ts +++ b/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/types.ts @@ -41,8 +41,8 @@ export interface WorkflowDetailState { schema: WorkflowZodSchemaType; /** Loading states for async operations */ loading: LoadingStates; - /** Number of validation errors reported by Monaco markers (strict schema + custom validations) */ - validationErrorCount: number; + /** Whether the editor has validation errors (strict schema + custom validations) */ + hasValidationErrors: boolean; /** Connector flyout state */ connectorFlyout: { isOpen: boolean; diff --git a/src/platform/plugins/shared/workflows_management/public/pages/workflow_detail/ui/workflow_detail_header.test.tsx b/src/platform/plugins/shared/workflows_management/public/pages/workflow_detail/ui/workflow_detail_header.test.tsx index 865421b7eea96..e4f97197f9703 100644 --- a/src/platform/plugins/shared/workflows_management/public/pages/workflow_detail/ui/workflow_detail_header.test.tsx +++ b/src/platform/plugins/shared/workflows_management/public/pages/workflow_detail/ui/workflow_detail_header.test.tsx @@ -13,7 +13,8 @@ import type { WorkflowDetailHeaderProps } from './workflow_detail_header'; import { WorkflowDetailHeader } from './workflow_detail_header'; import { createMockStore } from '../../../entities/workflows/store/__mocks__/store.mock'; import { - _setComputedDataInternal, + _clearComputedData, + setHasValidationErrors, setWorkflow, setYamlString, } from '../../../entities/workflows/store/workflow_detail/slice'; @@ -72,27 +73,33 @@ describe('WorkflowDetailHeader', () => { const renderWithProviders = ( component: React.ReactElement, - { isValid = true, hasChanges = false }: { isValid?: boolean; hasChanges?: boolean } = {} + { + isValid = true, + hasChanges = false, + hasValidationErrors = false, + serverValid = true, + }: { + isValid?: boolean; + hasChanges?: boolean; + hasValidationErrors?: boolean; + serverValid?: boolean; + } = {} ) => { const store = createMockStore(); - // Set up the workflow in the store - store.dispatch(setWorkflow(mockWorkflow)); + // Set up the workflow in the store (with server-side valid flag) + store.dispatch(setWorkflow({ ...mockWorkflow, valid: serverValid })); store.dispatch(setYamlString(hasChanges ? 'modified yaml' : mockWorkflow.yaml)); - // Set computed data to control syntax validation - if (isValid) { - store.dispatch( - _setComputedDataInternal({ - workflowDefinition: { - version: '1', - name: 'Test Workflow', - enabled: true, - triggers: [], - steps: [], - }, - }) - ); + if (!isValid) { + // Clear the computed data that the middleware auto-generated from the yaml, + // so that selectIsYamlSyntaxValid returns false + store.dispatch(_clearComputedData()); + } + + // Simulate strict validation errors from Monaco + if (hasValidationErrors) { + store.dispatch(setHasValidationErrors(true)); } const wrapper = ({ children }: { children: React.ReactNode }) => { @@ -158,15 +165,39 @@ describe('WorkflowDetailHeader', () => { expect(container).toBeTruthy(); }); - // We shouldn't rely on parseResult to determine if the yaml is valid now - // instead we should move validationErrors to the store and use it to determine it - it.skip('disables run workflow button when yaml is invalid', () => { + it('disables run workflow button when yaml has syntax errors', () => { const result = renderWithProviders(, { isValid: false, }); expect(result.getByTestId('runWorkflowHeaderButton')).toBeDisabled(); }); + it('disables run workflow button when yaml has validation errors', () => { + const result = renderWithProviders(, { + isValid: true, + hasValidationErrors: true, + }); + expect(result.getByTestId('runWorkflowHeaderButton')).toBeDisabled(); + }); + + it('disables enabled toggle when yaml has validation errors', () => { + const result = renderWithProviders(, { + isValid: true, + hasValidationErrors: true, + }); + const toggle = result.getByRole('switch'); + expect(toggle).toBeDisabled(); + }); + + it('disables enabled toggle when server reports workflow as invalid (e.g. initial page load)', () => { + const result = renderWithProviders(, { + isValid: true, + serverValid: false, + }); + const toggle = result.getByRole('switch'); + expect(toggle).toBeDisabled(); + }); + it('enables run workflow button when yaml is valid', () => { const result = renderWithProviders(); const button = result.getByTestId('runWorkflowHeaderButton'); diff --git a/src/platform/plugins/shared/workflows_management/public/pages/workflow_detail/ui/workflow_detail_header.tsx b/src/platform/plugins/shared/workflows_management/public/pages/workflow_detail/ui/workflow_detail_header.tsx index efdf4c5c85e37..b40d1f141c306 100644 --- a/src/platform/plugins/shared/workflows_management/public/pages/workflow_detail/ui/workflow_detail_header.tsx +++ b/src/platform/plugins/shared/workflows_management/public/pages/workflow_detail/ui/workflow_detail_header.tsx @@ -105,6 +105,7 @@ export const WorkflowDetailHeader = React.memo( const workflow = useSelector(selectWorkflow); const isSyntaxValid = useSelector(selectIsYamlSyntaxValid); + const hasValidationErrors = useSelector(selectHasValidationErrors); const hasUnsavedChanges = useSelector(selectHasChanges); const isExecutionsTab = useSelector(selectIsExecutionsTab); @@ -134,13 +135,17 @@ export const WorkflowDetailHeader = React.memo( const [showRunConfirmation, setShowRunConfirmation] = useState(false); + // Combined validity: syntax must parse AND no strict validation errors AND server considers it valid. + // workflow?.valid !== false covers the initial page load before Monaco validates. + const isValid = isSyntaxValid && !hasValidationErrors && workflow?.valid !== false; + const runWorkflowTooltipContent = useMemo(() => { return getTestRunTooltipContent({ isExecutionsTab, - isValid: isSyntaxValid, + isValid, canRunWorkflow: canExecuteWorkflow, }); - }, [isSyntaxValid, canExecuteWorkflow, isExecutionsTab]); + }, [isValid, canExecuteWorkflow, isExecutionsTab]); const saveWorkflowTooltipContent = useMemo(() => { const isCreate = !workflowId; @@ -261,9 +266,9 @@ export const WorkflowDetailHeader = React.memo( ? i18n.translate('workflows.workflowDetailHeader.unsaved', { defaultMessage: 'Save changes to enable/disable workflow', }) - : !isSyntaxValid + : !isValid ? i18n.translate('workflows.workflowDetailHeader.invalid', { - defaultMessage: 'Fix errors to enable workflow', + defaultMessage: 'Fix validation errors to enable workflow', }) : undefined } @@ -273,7 +278,7 @@ export const WorkflowDetailHeader = React.memo( !workflowId || isLoading || !canUpdateWorkflow || - !isSyntaxValid || + !isValid || hasUnsavedChanges } checked={isEnabled} @@ -291,7 +296,7 @@ export const WorkflowDetailHeader = React.memo( iconType="play" size="s" onClick={handleRunClickWithUnsavedCheck} - disabled={isExecutionsTab || !canExecuteWorkflow || isLoading || !isSyntaxValid} + disabled={isExecutionsTab || !canExecuteWorkflow || isLoading || !isValid} aria-label={Translations.runWorkflow} data-test-subj="runWorkflowHeaderButton" /> diff --git a/src/platform/plugins/shared/workflows_management/public/widgets/workflow_yaml_editor/ui/workflow_yaml_editor.tsx b/src/platform/plugins/shared/workflows_management/public/widgets/workflow_yaml_editor/ui/workflow_yaml_editor.tsx index 6dc9f1fa6acb0..9f113cf0daae6 100644 --- a/src/platform/plugins/shared/workflows_management/public/widgets/workflow_yaml_editor/ui/workflow_yaml_editor.tsx +++ b/src/platform/plugins/shared/workflows_management/public/widgets/workflow_yaml_editor/ui/workflow_yaml_editor.tsx @@ -53,8 +53,8 @@ import { selectWorkflow, } from '../../../entities/workflows/store/workflow_detail/selectors'; import { + setHasValidationErrors, setIsTestModalOpen, - setValidationErrorCount, } from '../../../entities/workflows/store/workflow_detail/slice'; import { ActionsMenuPopover } from '../../../features/actions_menu_popover'; import type { ActionOptionData } from '../../../features/actions_menu_popover/types'; @@ -251,10 +251,10 @@ export const WorkflowYAMLEditor = ({ workflowYamlSchema: workflowYamlSchema as z.ZodSchema, }); - // Sync validation error count to Redux so sibling components (e.g. header toggle) can react + // Sync validation error state to Redux so sibling components (e.g. header toggle) can react useEffect(() => { - const errorCount = validationErrors.filter((e) => e.severity === 'error').length; - dispatch(setValidationErrorCount(errorCount)); + const hasErrors = validationErrors.some((e) => e.severity === 'error'); + dispatch(setHasValidationErrors(hasErrors)); }, [validationErrors, dispatch]); const handleErrorClick = useCallback((error: YamlValidationResult) => { From 39455c01515bb9d7caee4c62a148b694183c9049 Mon Sep 17 00:00:00 2001 From: Omri Rosner Date: Thu, 19 Feb 2026 11:59:47 +0200 Subject: [PATCH 3/3] hasValidationErrors -> hasYamlSchemaValidationErrors --- .../workflows/store/workflow_detail/selectors.ts | 4 ++-- .../workflows/store/workflow_detail/slice.ts | 8 ++++---- .../workflows/store/workflow_detail/types.ts | 2 +- .../ui/workflow_detail_header.test.tsx | 14 +++++++------- .../workflow_detail/ui/workflow_detail_header.tsx | 6 +++--- .../ui/workflow_yaml_editor.tsx | 4 ++-- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/selectors.ts b/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/selectors.ts index 9563350bce0a9..47c00dc7e93b3 100644 --- a/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/selectors.ts +++ b/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/selectors.ts @@ -57,9 +57,9 @@ export const selectIsYamlSyntaxValid = createSelector(selectYamlComputed, (compu ); // Checks whether validation errors (from strict schema + custom validations) are present -export const selectHasValidationErrors = createSelector( +export const selectHasYamlSchemaValidationErrors = createSelector( selectDetail, - (detail): boolean => detail.hasValidationErrors + (detail): boolean => detail.hasYamlSchemaValidationErrors ); export const selectFocusedStepId = createSelector(selectDetail, (detail) => detail.focusedStepId); diff --git a/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/slice.ts b/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/slice.ts index 8e1c02e5d1375..88aad8972d9e8 100644 --- a/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/slice.ts +++ b/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/slice.ts @@ -31,7 +31,7 @@ const initialState: WorkflowDetailState = { highlightedStepId: undefined, isTestModalOpen: false, loading: initialLoadingState, - hasValidationErrors: false, + hasYamlSchemaValidationErrors: false, connectorFlyout: { isOpen: false, connectorType: undefined, @@ -90,8 +90,8 @@ const workflowDetailSlice = createSlice({ state.activeTab = action.payload; }, - setHasValidationErrors: (state, action: { payload: boolean }) => { - state.hasValidationErrors = action.payload; + setHasYamlSchemaValidationErrors: (state, action: { payload: boolean }) => { + state.hasYamlSchemaValidationErrors = action.payload; }, // Connector flyout actions @@ -156,7 +156,7 @@ export const { setExecution, clearExecution, setActiveTab, - setHasValidationErrors, + setHasYamlSchemaValidationErrors, openCreateConnectorFlyout, openEditConnectorFlyout, closeConnectorFlyout, diff --git a/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/types.ts b/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/types.ts index fa9a7c0c2a6d3..7312ad9c68666 100644 --- a/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/types.ts +++ b/src/platform/plugins/shared/workflows_management/public/entities/workflows/store/workflow_detail/types.ts @@ -50,7 +50,7 @@ export interface WorkflowDetailState { /** Loading states for async operations */ loading: LoadingStates; /** Whether the editor has validation errors (strict schema + custom validations) */ - hasValidationErrors: boolean; + hasYamlSchemaValidationErrors: boolean; /** Connector flyout state */ connectorFlyout: { isOpen: boolean; diff --git a/src/platform/plugins/shared/workflows_management/public/pages/workflow_detail/ui/workflow_detail_header.test.tsx b/src/platform/plugins/shared/workflows_management/public/pages/workflow_detail/ui/workflow_detail_header.test.tsx index e4f97197f9703..dc019721d3619 100644 --- a/src/platform/plugins/shared/workflows_management/public/pages/workflow_detail/ui/workflow_detail_header.test.tsx +++ b/src/platform/plugins/shared/workflows_management/public/pages/workflow_detail/ui/workflow_detail_header.test.tsx @@ -14,7 +14,7 @@ import { WorkflowDetailHeader } from './workflow_detail_header'; import { createMockStore } from '../../../entities/workflows/store/__mocks__/store.mock'; import { _clearComputedData, - setHasValidationErrors, + setHasYamlSchemaValidationErrors, setWorkflow, setYamlString, } from '../../../entities/workflows/store/workflow_detail/slice'; @@ -76,12 +76,12 @@ describe('WorkflowDetailHeader', () => { { isValid = true, hasChanges = false, - hasValidationErrors = false, + hasYamlSchemaValidationErrors = false, serverValid = true, }: { isValid?: boolean; hasChanges?: boolean; - hasValidationErrors?: boolean; + hasYamlSchemaValidationErrors?: boolean; serverValid?: boolean; } = {} ) => { @@ -98,8 +98,8 @@ describe('WorkflowDetailHeader', () => { } // Simulate strict validation errors from Monaco - if (hasValidationErrors) { - store.dispatch(setHasValidationErrors(true)); + if (hasYamlSchemaValidationErrors) { + store.dispatch(setHasYamlSchemaValidationErrors(true)); } const wrapper = ({ children }: { children: React.ReactNode }) => { @@ -175,7 +175,7 @@ describe('WorkflowDetailHeader', () => { it('disables run workflow button when yaml has validation errors', () => { const result = renderWithProviders(, { isValid: true, - hasValidationErrors: true, + hasYamlSchemaValidationErrors: true, }); expect(result.getByTestId('runWorkflowHeaderButton')).toBeDisabled(); }); @@ -183,7 +183,7 @@ describe('WorkflowDetailHeader', () => { it('disables enabled toggle when yaml has validation errors', () => { const result = renderWithProviders(, { isValid: true, - hasValidationErrors: true, + hasYamlSchemaValidationErrors: true, }); const toggle = result.getByRole('switch'); expect(toggle).toBeDisabled(); diff --git a/src/platform/plugins/shared/workflows_management/public/pages/workflow_detail/ui/workflow_detail_header.tsx b/src/platform/plugins/shared/workflows_management/public/pages/workflow_detail/ui/workflow_detail_header.tsx index c0818fc1f6ee4..afb35966b37e2 100644 --- a/src/platform/plugins/shared/workflows_management/public/pages/workflow_detail/ui/workflow_detail_header.tsx +++ b/src/platform/plugins/shared/workflows_management/public/pages/workflow_detail/ui/workflow_detail_header.tsx @@ -37,7 +37,7 @@ import { useSaveYaml } from '../../../entities/workflows/model/use_save_yaml'; import { useUpdateWorkflow } from '../../../entities/workflows/model/use_update_workflow'; import { selectHasChanges, - selectHasValidationErrors, + selectHasYamlSchemaValidationErrors, selectIsExecutionsTab, selectIsSavingYaml, selectIsYamlSynced, @@ -106,7 +106,7 @@ export const WorkflowDetailHeader = React.memo( const workflow = useSelector(selectWorkflow); const isSyntaxValid = useSelector(selectIsYamlSyntaxValid); - const hasValidationErrors = useSelector(selectHasValidationErrors); + const hasYamlSchemaValidationErrors = useSelector(selectHasYamlSchemaValidationErrors); const hasUnsavedChanges = useSelector(selectHasChanges); const isExecutionsTab = useSelector(selectIsExecutionsTab); const isYamlSynced = useSelector(selectIsYamlSynced); @@ -139,7 +139,7 @@ export const WorkflowDetailHeader = React.memo( // Combined validity: syntax must parse AND no strict validation errors AND server considers it valid. // workflow?.valid !== false covers the initial page load before Monaco validates. - const isValid = isSyntaxValid && !hasValidationErrors && workflow?.valid !== false; + const isValid = isSyntaxValid && !hasYamlSchemaValidationErrors && workflow?.valid !== false; const runWorkflowTooltipContent = useMemo(() => { return getTestRunTooltipContent({ diff --git a/src/platform/plugins/shared/workflows_management/public/widgets/workflow_yaml_editor/ui/workflow_yaml_editor.tsx b/src/platform/plugins/shared/workflows_management/public/widgets/workflow_yaml_editor/ui/workflow_yaml_editor.tsx index 848a0d74f1121..b63787a3646e9 100644 --- a/src/platform/plugins/shared/workflows_management/public/widgets/workflow_yaml_editor/ui/workflow_yaml_editor.tsx +++ b/src/platform/plugins/shared/workflows_management/public/widgets/workflow_yaml_editor/ui/workflow_yaml_editor.tsx @@ -54,7 +54,7 @@ import { selectWorkflow, } from '../../../entities/workflows/store/workflow_detail/selectors'; import { - setHasValidationErrors, + setHasYamlSchemaValidationErrors, setIsTestModalOpen, } from '../../../entities/workflows/store/workflow_detail/slice'; import { ActionsMenuPopover } from '../../../features/actions_menu_popover'; @@ -262,7 +262,7 @@ export const WorkflowYAMLEditor = ({ // Sync validation error state to Redux so sibling components (e.g. header toggle) can react useEffect(() => { const hasErrors = validationErrors.some((e) => e.severity === 'error'); - dispatch(setHasValidationErrors(hasErrors)); + dispatch(setHasYamlSchemaValidationErrors(hasErrors)); }, [validationErrors, dispatch]); const handleErrorClick = useCallback((error: YamlValidationResult) => {