vatsrahul1001 commented on code in PR #60673:
URL: https://github.com/apache/airflow/pull/60673#discussion_r2727288736


##########
airflow-core/src/airflow/ui/tests/e2e/pages/DagCalendarPage.ts:
##########
@@ -0,0 +1,73 @@
+/*!
+ * 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 { expect, type Locator, type Page } from "@playwright/test";
+import { BasePage } from "tests/e2e/pages/BasePage";
+
+export class DagCalendarPage extends BasePage {
+  public readonly calendarGrid: Locator;
+  public readonly calendarTab: Locator;
+  public readonly monthYearHeader: Locator;
+
+  public constructor(page: Page) {
+    super(page);
+    this.calendarTab = page.getByRole("tab", { name: "Calendar" });
+    this.calendarGrid = page
+      .locator(".react-calendar-heatmap")
+      .or(page.getByTestId("calendar-cell").first().locator(".."));
+    this.monthYearHeader = page.getByTestId("calendar-header-date");
+  }
+
+  public async clickDay(date: string): Promise<void> {

Review Comment:
   we are not using this in tests



##########
airflow-core/src/airflow/ui/tests/e2e/pages/DagCalendarPage.ts:
##########
@@ -0,0 +1,73 @@
+/*!
+ * 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 { expect, type Locator, type Page } from "@playwright/test";
+import { BasePage } from "tests/e2e/pages/BasePage";
+
+export class DagCalendarPage extends BasePage {
+  public readonly calendarGrid: Locator;
+  public readonly calendarTab: Locator;
+  public readonly monthYearHeader: Locator;
+
+  public constructor(page: Page) {
+    super(page);
+    this.calendarTab = page.getByRole("tab", { name: "Calendar" });
+    this.calendarGrid = page
+      .locator(".react-calendar-heatmap")
+      .or(page.getByTestId("calendar-cell").first().locator(".."));
+    this.monthYearHeader = page.getByTestId("calendar-header-date");
+  }
+
+  public async clickDay(date: string): Promise<void> {
+    const cell = 
this.page.locator(`[data-testid="calendar-cell"][data-date="${date}"]`);
+
+    await cell.click();
+  }
+
+  public async navigateToCalendar(dagId: string): Promise<void> {
+    await this.page.goto(`/dags/${dagId}/calendar`);
+
+    await this.page.waitForLoadState("networkidle");
+  }
+
+  public async verifyCalendarRender(): Promise<void> {
+    await expect(this.monthYearHeader).toBeVisible();
+
+    await expect(this.page.getByRole("button", { name: "Daily" 
})).toBeVisible();
+
+    await expect(this.page.getByRole("button", { name: "Hourly" 
})).toBeVisible();
+  }
+
+  public async verifyDayRun(date: string, status: "failed" | "running" | 
"success"): Promise<void> {

Review Comment:
   Maybe we can add a test for this
   
   test("verify tooltip shows run details on hover", async () => {
     await dagCalendarPage.navigateToCalendar(testDagId);
     const todayDate = new Date().toISOString().split('T')[0];
     await dagCalendarPage.verifyDayRun(todayDate, "success");
   });



##########
airflow-core/src/airflow/ui/tests/e2e/specs/dag-calendar.spec.ts:
##########
@@ -0,0 +1,110 @@
+/*!
+ * 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 { test, expect } from "@playwright/test";
+import { AUTH_FILE, testConfig } from "playwright.config";
+import { DagCalendarPage } from "tests/e2e/pages/DagCalendarPage";
+
+test.describe("DAG Calendar Page", () => {
+  test.setTimeout(60_000);
+
+  let dagCalendarPage: DagCalendarPage;
+  const testDagId = testConfig.testDag.id;
+
+  test.beforeAll(async ({ browser }) => {
+    const context = await browser.newContext({ storageState: AUTH_FILE });
+    const page = await context.newPage();
+    const baseUrl = process.env.AIRFLOW_UI_BASE_URL ?? "http://localhost:8080";;
+
+    const timestamp = Date.now();
+
+    // Trigger DAG runs to ensure data
+    // Success Run
+    const runId1 = `test_run_cal_success_${timestamp}`;
+    const logicalDate1 = new Date(timestamp).toISOString();
+    const triggerResponse1 = await 
page.request.post(`${baseUrl}/api/v2/dags/${testDagId}/dagRuns`, {
+      data: JSON.stringify({
+        dag_run_id: runId1,
+        logical_date: logicalDate1,
+      }),
+      headers: { "Content-Type": "application/json" },
+    });
+
+    expect(triggerResponse1.ok()).toBeTruthy();
+
+    const runData1 = (await triggerResponse1.json()) as { dag_run_id: string };
+
+    await 
page.request.patch(`${baseUrl}/api/v2/dags/${testDagId}/dagRuns/${runData1.dag_run_id}`,
 {
+      data: JSON.stringify({ state: "success" }),
+      headers: { "Content-Type": "application/json" },
+    });
+
+    // Failed Run
+    const runId2 = `test_run_cal_failed_${timestamp}`;
+    const logicalDate2 = new Date(timestamp + 60 * 1000).toISOString();
+    const triggerResponse2 = await 
page.request.post(`${baseUrl}/api/v2/dags/${testDagId}/dagRuns`, {
+      data: JSON.stringify({
+        dag_run_id: runId2,
+        logical_date: logicalDate2,
+      }),
+      headers: { "Content-Type": "application/json" },
+    });
+
+    expect(triggerResponse2.ok()).toBeTruthy();
+
+    const runData2 = (await triggerResponse2.json()) as { dag_run_id: string };
+
+    await 
page.request.patch(`${baseUrl}/api/v2/dags/${testDagId}/dagRuns/${runData2.dag_run_id}`,
 {
+      data: JSON.stringify({ state: "failed" }),
+      headers: { "Content-Type": "application/json" },
+    });
+
+    await context.close();
+  });
+
+  test.beforeEach(({ page }) => {
+    dagCalendarPage = new DagCalendarPage(page);
+  });
+
+  test("verify calendar renders and displays runs", async () => {
+    await dagCalendarPage.navigateToCalendar(testDagId);
+
+    await dagCalendarPage.verifyCalendarRender();
+
+    // Verify that calendar cells exist (calendar grid rendered)
+    const calendarCells = dagCalendarPage.page.getByTestId("calendar-cell");
+
+    await expect(calendarCells.first()).toBeVisible();
+  });
+
+  test("verify status filtering", async () => {

Review Comment:
   Filter verification is too weak 
   This only checks cells still visible:
   
   1. Should verify filtering actually changed data, e.g.:Count cells 
before/after
   2. Check specific run is no longer visible
   3. Verify URL or UI state changed



##########
airflow-core/src/airflow/ui/tests/e2e/pages/DagCalendarPage.ts:
##########
@@ -0,0 +1,73 @@
+/*!
+ * 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 { expect, type Locator, type Page } from "@playwright/test";
+import { BasePage } from "tests/e2e/pages/BasePage";
+
+export class DagCalendarPage extends BasePage {
+  public readonly calendarGrid: Locator;
+  public readonly calendarTab: Locator;
+  public readonly monthYearHeader: Locator;
+
+  public constructor(page: Page) {
+    super(page);
+    this.calendarTab = page.getByRole("tab", { name: "Calendar" });
+    this.calendarGrid = page
+      .locator(".react-calendar-heatmap")
+      .or(page.getByTestId("calendar-cell").first().locator(".."));
+    this.monthYearHeader = page.getByTestId("calendar-header-date");
+  }
+
+  public async clickDay(date: string): Promise<void> {
+    const cell = 
this.page.locator(`[data-testid="calendar-cell"][data-date="${date}"]`);
+
+    await cell.click();
+  }
+
+  public async navigateToCalendar(dagId: string): Promise<void> {
+    await this.page.goto(`/dags/${dagId}/calendar`);
+
+    await this.page.waitForLoadState("networkidle");
+  }
+
+  public async verifyCalendarRender(): Promise<void> {
+    await expect(this.monthYearHeader).toBeVisible();
+
+    await expect(this.page.getByRole("button", { name: "Daily" 
})).toBeVisible();
+
+    await expect(this.page.getByRole("button", { name: "Hourly" 
})).toBeVisible();
+  }
+
+  public async verifyDayRun(date: string, status: "failed" | "running" | 
"success"): Promise<void> {

Review Comment:
   We are not using this in tests



##########
airflow-core/src/airflow/ui/tests/e2e/pages/DagCalendarPage.ts:
##########
@@ -0,0 +1,73 @@
+/*!
+ * 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 { expect, type Locator, type Page } from "@playwright/test";
+import { BasePage } from "tests/e2e/pages/BasePage";
+
+export class DagCalendarPage extends BasePage {
+  public readonly calendarGrid: Locator;
+  public readonly calendarTab: Locator;
+  public readonly monthYearHeader: Locator;
+
+  public constructor(page: Page) {
+    super(page);
+    this.calendarTab = page.getByRole("tab", { name: "Calendar" });
+    this.calendarGrid = page
+      .locator(".react-calendar-heatmap")
+      .or(page.getByTestId("calendar-cell").first().locator(".."));
+    this.monthYearHeader = page.getByTestId("calendar-header-date");
+  }
+
+  public async clickDay(date: string): Promise<void> {

Review Comment:
   Lets add test for this



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to