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

pierrejeambrun 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 d1df638bfb1 Fix dashboard stats cards navigating to a 404 page (#73178)
d1df638bfb1 is described below

commit d1df638bfb123ea14409e384d66d83167c7bd87b
Author: Yeonguk Choo <[email protected]>
AuthorDate: Tue Sep 15 21:35:50 2026 +0900

    Fix dashboard stats cards navigating to a 404 page (#73178)
---
 .../ui/src/pages/Dashboard/Stats/Stats.test.tsx    | 37 ++++++++++++++++------
 .../airflow/ui/src/pages/Dashboard/Stats/Stats.tsx |  8 ++---
 2 files changed, 31 insertions(+), 14 deletions(-)

diff --git 
a/airflow-core/src/airflow/ui/src/pages/Dashboard/Stats/Stats.test.tsx 
b/airflow-core/src/airflow/ui/src/pages/Dashboard/Stats/Stats.test.tsx
index c653e4f6eb4..930974bd617 100644
--- a/airflow-core/src/airflow/ui/src/pages/Dashboard/Stats/Stats.test.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Dashboard/Stats/Stats.test.tsx
@@ -16,11 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+import type { PropsWithChildren } from "react";
+
 import "@testing-library/jest-dom";
 import { render, screen } from "@testing-library/react";
+import { MemoryRouter, Route, Routes } from "react-router-dom";
 import { describe, expect, it, vi } from "vitest";
 
-import { Wrapper } from "src/utils/Wrapper";
+import { BaseWrapper } from "src/utils/Wrapper";
 
 import { Stats } from "./Stats";
 
@@ -28,9 +31,9 @@ vi.mock("openapi/queries", () => ({
   useDashboardServiceDagStats: () => ({
     data: {
       active_dag_count: 1,
-      failed_dag_count: 0,
-      queued_dag_count: 0,
-      running_dag_count: 0,
+      failed_dag_count: 2,
+      queued_dag_count: 3,
+      running_dag_count: 4,
     },
     isLoading: false,
   }),
@@ -49,13 +52,27 @@ vi.mock("src/utils", () => ({ useAutoRefresh: () => false 
}));
 vi.mock("./DagImportErrors", () => ({ DagImportErrors: () => null }));
 vi.mock("./PluginImportErrors", () => ({ PluginImportErrors: () => null }));
 
+// Dashboard renders under the /home route. Mount Stats as that route's 
element so relative links
+// would resolve against /home (producing /home/dags -> 404) unless the links 
are absolute.
+const wrapperAtHome = ({ children }: PropsWithChildren) => (
+  <BaseWrapper>
+    <MemoryRouter initialEntries={["/home"]}>
+      <Routes>
+        <Route element={children} path="home" />
+      </Routes>
+    </MemoryRouter>
+  </BaseWrapper>
+);
+
 describe("Dashboard stats", () => {
-  it("links the active Dag count to the exact active scheduling state", () => {
-    render(<Stats />, { wrapper: Wrapper });
+  it.each([
+    { href: "/dags?last_dag_run_state=failed", label: "stats.failedDags" },
+    { href: "/dags?dag_run_state=queued", label: "stats.queuedDags" },
+    { href: "/dags?dag_run_state=running", label: "stats.runningDags" },
+    { href: "/dags?scheduling_state=active", label: "stats.activeDags" },
+  ])("links $label to the absolute $href from the /home route", ({ href, label 
}) => {
+    render(<Stats />, { wrapper: wrapperAtHome });
 
-    expect(screen.getByText("stats.activeDags").closest("a")).toHaveAttribute(
-      "href",
-      "/dags?scheduling_state=active",
-    );
+    expect(screen.getByText(label).closest("a")).toHaveAttribute("href", href);
   });
 });
diff --git a/airflow-core/src/airflow/ui/src/pages/Dashboard/Stats/Stats.tsx 
b/airflow-core/src/airflow/ui/src/pages/Dashboard/Stats/Stats.tsx
index b3d7173dc7c..612dc1d2f73 100644
--- a/airflow-core/src/airflow/ui/src/pages/Dashboard/Stats/Stats.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Dashboard/Stats/Stats.tsx
@@ -62,7 +62,7 @@ export const Stats = () => {
           isLoading={isStatsLoading}
           isRTL={isRTL}
           label={translate("stats.failedDags")}
-          link="dags?last_dag_run_state=failed"
+          link="/dags?last_dag_run_state=failed"
           state="failed"
         />
 
@@ -77,7 +77,7 @@ export const Stats = () => {
             isLoading={isStatsLoading}
             isRTL={isRTL}
             label={translate("stats.queuedDags")}
-            link="dags?dag_run_state=queued"
+            link="/dags?dag_run_state=queued"
             state="queued"
           />
         ) : undefined}
@@ -88,7 +88,7 @@ export const Stats = () => {
           isLoading={isStatsLoading}
           isRTL={isRTL}
           label={translate("stats.runningDags")}
-          link="dags?dag_run_state=running"
+          link="/dags?dag_run_state=running"
           state="running"
         />
 
@@ -99,7 +99,7 @@ export const Stats = () => {
           isLoading={isStatsLoading}
           isRTL={isRTL}
           label={translate("stats.activeDags")}
-          link="dags?scheduling_state=active"
+          link="/dags?scheduling_state=active"
         />
       </Flex>
     </Box>

Reply via email to