Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,18 @@ export const CalendarCell = ({
const hasData = Boolean(cellData && relevantCount > 0);
const hasTooltip = Boolean(cellData);

// States present in this cell, computed with the same view-mode-aware logic the
// tooltip uses (see CalendarTooltip). Exposed as a `data-states` attribute so e2e
// tests can read run states from the DOM instead of hovering — the tooltip does
// not open reliably under synthetic pointer events in headless Firefox.
Comment thread
potiuk marked this conversation as resolved.
const runStates = cellData
? Object.entries(cellData.counts)
.filter(
([key, value]) => key !== "total" && value > 0 && (viewMode === "failed" ? key === "failed" : true),
)
.map(([key]) => key)
: [];

const isMixedState =
typeof backgroundColor === "object" && "planned" in backgroundColor && "actual" in backgroundColor;

Expand All @@ -60,6 +72,7 @@ export const CalendarCell = ({
borderRadius="2px"
cursor={hasData ? "pointer" : "default"}
data-has-data={hasData ? "true" : "false"}
data-states={runStates.join(" ")}
data-testid="calendar-cell"
data-view-mode={viewMode}
height="14px"
Expand Down Expand Up @@ -90,6 +103,7 @@ export const CalendarCell = ({
borderRadius="2px"
cursor={hasData ? "pointer" : "default"}
data-has-data={hasData ? "true" : "false"}
data-states={runStates.join(" ")}
data-testid="calendar-cell"
data-view-mode={viewMode}
height="14px"
Expand Down
28 changes: 10 additions & 18 deletions airflow-core/src/airflow/ui/tests/e2e/pages/DagCalendarTab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@ export class DagCalendarTab extends BasePage {
return this.page.getByTestId("calendar-cell");
}

public get tooltip(): Locator {
return this.page.getByTestId("calendar-tooltip");
}

public constructor(page: Page) {
super(page);

Expand Down Expand Up @@ -92,22 +88,18 @@ export class DagCalendarTab extends BasePage {
const count = await this.activeCells.count();
const states: Array<string> = [];

// Read run states from the cell's `data-states` attribute rather than hovering to
// read the tooltip. The tooltip (BasicTooltip) opens on a `mouseenter` after a
// 500ms delay and renders through a portal; synthetic pointer events do not open
// it reliably in headless Firefox, which made these tests flaky. `data-states` is
// populated with the same view-mode-aware logic the tooltip uses (see
// CalendarCell), so the assertions are unchanged and now backend-independent.
for (let i = 0; i < count; i++) {
const cell = this.activeCells.nth(i);
const raw = (await this.activeCells.nth(i).getAttribute("data-states")) ?? "";

// Firefox sometimes fails to trigger tooltips on hover.
// Retry the hover + tooltip visibility check to handle this.
let text = "";

await expect(async () => {
await cell.hover({ force: true });
await expect(this.tooltip).toBeVisible({ timeout: 3000 });
text = ((await this.tooltip.textContent()) ?? "").toLowerCase();
}).toPass({ intervals: [1000], timeout: 20_000 });

if (text.includes("success")) states.push("success");
if (text.includes("failed")) states.push("failed");
if (text.includes("running")) states.push("running");
for (const state of raw.split(" ").filter(Boolean)) {
states.push(state);
}
}

return states;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ test.describe("Dag Calendar Tab", () => {
expect(states.length).toBeGreaterThanOrEqual(2);
});

test("verify hover shows correct run states", async ({ dagCalendarTab }) => {
test("verify success and failed run states are detected", async ({ dagCalendarTab }) => {
await dagCalendarTab.switchToHourly();

const states = await dagCalendarTab.getManualRunStates();
Expand Down
Loading