This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 2a3feb98506 Fix retrigger form config sync (#65749)
2a3feb98506 is described below

commit 2a3feb98506169663a4d3c43b12d7faafb0f32b0
Author: Paul <[email protected]>
AuthorDate: Mon Apr 27 15:39:35 2026 -0700

    Fix retrigger form config sync (#65749)
    
    * UI: Fix re-trigger form config sync
    
    * UI: Clean up re-trigger regression test
    
    * Simplify Trigger DAG form prefill test data
    
    * Fix retrigger form UI test selector
    
    * Fix Trigger DAG form test lint
---
 .../components/TriggerDag/TriggerDAGForm.test.tsx  | 131 +++++++++++++++++++++
 .../src/components/TriggerDag/TriggerDAGForm.tsx   |   8 +-
 2 files changed, 137 insertions(+), 2 deletions(-)

diff --git 
a/airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGForm.test.tsx 
b/airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGForm.test.tsx
new file mode 100644
index 00000000000..c739b058a87
--- /dev/null
+++ 
b/airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGForm.test.tsx
@@ -0,0 +1,131 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import "@testing-library/jest-dom";
+import { fireEvent, render, screen, waitFor } from "@testing-library/react";
+import { describe, expect, it, vi } from "vitest";
+
+import { Wrapper } from "src/utils/Wrapper";
+
+import TriggerDAGForm from "./TriggerDAGForm";
+
+const dagParams = vi.hoisted(() => ({
+  paramsDict: {
+    message: {
+      description: "Message",
+      schema: {
+        title: "Message",
+        type: "string",
+      },
+      value: "Hello",
+    },
+  },
+}));
+
+vi.mock("react-i18next", () => ({
+  useTranslation: () => ({
+    // eslint-disable-next-line id-length
+    t: (translationKey: string) =>
+      ({
+        "configForm.advancedOptions": "Advanced Options",
+      })[translationKey] ?? translationKey,
+  }),
+}));
+
+vi.mock("src/queries/useDagParams", () => ({
+  useDagParams: () => dagParams,
+}));
+
+vi.mock("src/queries/useTogglePause", () => ({
+  useTogglePause: () => ({
+    mutate: vi.fn(),
+  }),
+}));
+
+vi.mock("../DateTimeInput", () => ({
+  DateTimeInput: ({ value = "" }: { readonly value?: string }) => (
+    <input aria-label="Logical Date" readOnly value={value} />
+  ),
+}));
+
+vi.mock("../JsonEditor", () => ({
+  JsonEditor: ({
+    onBlur,
+    onChange,
+    value = "",
+  }: {
+    readonly onBlur?: () => void;
+    readonly onChange?: (value: string) => void;
+    readonly value?: string;
+  }) => (
+    <textarea
+      aria-label="Configuration JSON"
+      onBlur={onBlur}
+      onChange={(event) => onChange?.(event.target.value)}
+      value={value}
+    />
+  ),
+}));
+
+describe("TriggerDAGForm", () => {
+  it("syncs Advanced Options JSON after Run Parameters edits in prefilled 
re-trigger mode", async () => {
+    const { container } = render(
+      <TriggerDAGForm
+        dagDisplayName="Params Trigger UI"
+        dagId="example_params_trigger_ui"
+        error={undefined}
+        hasSchedule={false}
+        isPartitioned={false}
+        isPaused={false}
+        isPending={false}
+        onSubmitTrigger={vi.fn()}
+        open
+        prefillConfig={{
+          conf: {
+            message: "Original message",
+          },
+          logicalDate: undefined,
+          runId: "manual__test",
+        }}
+      />,
+      { wrapper: Wrapper },
+    );
+
+    await waitFor(() =>
+      
expect(container.querySelector<HTMLInputElement>('input[name="element_message"]')).toBeInTheDocument(),
+    );
+    const messageField = 
container.querySelector<HTMLInputElement>('input[name="element_message"]');
+
+    if (messageField === null) {
+      throw new Error("Expected message input to be rendered");
+    }
+
+    fireEvent.change(messageField, { target: { value: "Updated message" } });
+    fireEvent.click(screen.getByText("Advanced Options"));
+
+    await waitFor(() => {
+      const configJson = screen.getByLabelText("Configuration JSON");
+
+      if (!(configJson instanceof HTMLTextAreaElement)) {
+        throw new TypeError("Expected Configuration JSON to render as a 
textarea");
+      }
+
+      expect(configJson.value).toContain('"Updated message"');
+    });
+  });
+});
diff --git 
a/airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGForm.tsx 
b/airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGForm.tsx
index 91b2cd1daa0..a324bf4d7df 100644
--- a/airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGForm.tsx
+++ b/airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGForm.tsx
@@ -73,6 +73,7 @@ const TriggerDAGForm = ({
   const initialParamsDict = useDagParams(dagId, open);
   const { conf, initialParamDict, setConf, setInitialParamDict } = 
useParamStore();
   const [unpause, setUnpause] = useState(true);
+  const [hasAppliedPrefill, setHasAppliedPrefill] = useState(false);
   const { mutate: togglePause } = useTogglePause({ dagId });
 
   const { control, handleSubmit, reset, watch } = 
useForm<DagRunTriggerParams>({
@@ -114,6 +115,9 @@ const TriggerDAGForm = ({
         }
         setConf(confString);
       }
+      setHasAppliedPrefill(true);
+    } else if (!open) {
+      setHasAppliedPrefill(false);
     }
   }, [
     prefillConfig,
@@ -128,10 +132,10 @@ const TriggerDAGForm = ({
 
   // Automatically reset form when conf is fetched (only if no prefillConfig)
   useEffect(() => {
-    if (conf && !prefillConfig && open) {
+    if (conf && open && (!prefillConfig || hasAppliedPrefill)) {
       reset((prevValues) => ({ ...prevValues, conf }));
     }
-  }, [conf, prefillConfig, open, reset]);
+  }, [conf, hasAppliedPrefill, prefillConfig, open, reset]);
 
   const resetDateError = () => setErrors((prev) => ({ ...prev, date: undefined 
}));
 

Reply via email to