FN-7780: move agent-created badge to bottom row on task cards
Moves the agent-created badge out of the task card header's meta-badges row into its own bottom row so it no longer causes header wrapping. - Moved .card-agent-created-badge out of .card-meta-badges into a new .card-agent-badge-row in TaskCard.tsx - Updated hasCardMetaBadges guard logic and TaskCard.css to support the new bottom row layout - Added TaskCard.badge-wrap.test.tsx regression coverage and extended TaskCard.test.tsx - Updated docs/dashboard-guide.md - Added changeset fn-7780-agent-badge-bottom-row.md (patch, fix category) Files changed: .changeset/fn-7780-agent-badge-bottom-row.md | 7 +++ docs/dashboard-guide.md | 3 +- packages/dashboard/app/components/TaskCard.css | 12 ++++ packages/dashboard/app/components/TaskCard.tsx | 29 ++++++---- .../__tests__/TaskCard.badge-wrap.test.tsx | 66 ++++++++++++++++++++++ .../app/components/__tests__/TaskCard.test.tsx | 34 ++++++++--- 6 files changed, 131 insertions(+), 20 deletions(-) Fusion-Task-Id: FN-7780 Fusion-Task-Lineage: 6a6cd9f6-a9ce-488f-969d-520459c8631b Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
7
.changeset/fn-7780-agent-badge-bottom-row.md
Normal file
7
.changeset/fn-7780-agent-badge-bottom-row.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
"@runfusion/fusion": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
summary: Task cards no longer wrap the header when a task was created by an agent — the agent badge moved to a bottom row.
|
||||||
|
category: fix
|
||||||
|
dev: Moved `.card-agent-created-badge` out of `.card-meta-badges` into a new `.card-agent-badge-row` in TaskCard; updated the `hasCardMetaBadges` guard.
|
||||||
@@ -193,7 +193,8 @@ Features:
|
|||||||
- PR/issue badges with live updates
|
- PR/issue badges with live updates
|
||||||
- GitLab tracking badges on task cards for linked GitLab project issues, group issues, and merge requests; stale GitLab metadata uses a warning-colored badge while GitHub badges remain unchanged.
|
- GitLab tracking badges on task cards for linked GitLab project issues, group issues, and merge requests; stale GitLab metadata uses a warning-colored badge while GitHub badges remain unchanged.
|
||||||
- GitHub provenance marker on task cards imported from GitHub (`sourceType: github_import`), shown in the footer with other external-source metadata
|
- GitHub provenance marker on task cards imported from GitHub (`sourceType: github_import`), shown in the footer with other external-source metadata
|
||||||
- Task card header meta badges group priority, fast mode, agent-created provenance, workflow identity, and elapsed/created-time chips into one wrapping row; agent labels prefer `sourceMetadata.agentName` over raw agent IDs
|
- Task card header meta badges group priority and fast mode in the header; agent-created provenance renders in a dedicated bottom-left row ahead of workflow identity so the ID/status/actions header does not wrap on narrow cards. Agent labels prefer `sourceMetadata.agentName` over raw agent IDs.
|
||||||
|
<!-- FNXC:TaskCardLayout 2026-07-10-00:00: FN-7780 moved agent-created provenance out of the header meta-badge cluster into a bottom row. Keep dashboard docs aligned so operators do not expect the agent chip to participate in header wrapping. -->
|
||||||
<!-- FNXC:PlannerOversight 2026-07-04-00:00: FN-7516 adds a read-only effective oversight-level badge plus an active-overseer-state indicator to the card-meta-badges cluster. The overseer-state indicator is derived card-locally from already-on-Task fields (mirroring the engine's stage-resolution precedence) rather than a new engine-plumbed field, since @fusion/engine's in-memory monitor state is not persisted onto Task/exposed via API. -->
|
<!-- FNXC:PlannerOversight 2026-07-04-00:00: FN-7516 adds a read-only effective oversight-level badge plus an active-overseer-state indicator to the card-meta-badges cluster. The overseer-state indicator is derived card-locally from already-on-Task fields (mirroring the engine's stage-resolution precedence) rather than a new engine-plumbed field, since @fusion/engine's in-memory monitor state is not persisted onto Task/exposed via API. -->
|
||||||
<!-- FNXC:PlannerOversight 2026-07-04-16:00: round-2 code-review fix — when a card must fetch the workflow's effective oversight tier (no synchronous per-task override), neither badge below renders until that fetch resolves; the schema default must never render as a guess while the true workflow tier is unknown. -->
|
<!-- FNXC:PlannerOversight 2026-07-04-16:00: round-2 code-review fix — when a card must fetch the workflow's effective oversight tier (no synchronous per-task override), neither badge below renders until that fetch resolves; the schema default must never render as a guess while the true workflow tier is unknown. -->
|
||||||
<!-- FNXC:PlannerOversight 2026-07-04-19:10: FN-7539 fix — the badge was rendering on virtually every card because the schema default `autonomous` tier was treated as "meaningfully configured". Narrowed the gate so an inherited (no per-task-override, no non-default workflow tier) `autonomous` level renders no badge; only an explicit per-task override or a resolved workflow/effective tier that is not the plain inherited default surfaces the badge. -->
|
<!-- FNXC:PlannerOversight 2026-07-04-19:10: FN-7539 fix — the badge was rendering on virtually every card because the schema default `autonomous` tier was treated as "meaningfully configured". Narrowed the gate so an inherited (no per-task-override, no non-default workflow tier) `autonomous` level renders no badge; only an explicit per-task override or a resolved workflow/effective tier that is not the plain inherited default surfaces the badge. -->
|
||||||
|
|||||||
@@ -234,6 +234,18 @@ All workflows cards need workflow identity at the bottom-left below every other
|
|||||||
FNXC:WorkflowBadges 2026-06-30-00:00:
|
FNXC:WorkflowBadges 2026-06-30-00:00:
|
||||||
Workflow badges need a slight token-based gap between icon and label so compact workflow identity remains readable without changing placement, clickability, or truncation behavior.
|
Workflow badges need a slight token-based gap between icon and label so compact workflow identity remains readable without changing placement, clickability, or truncation behavior.
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
|
FNXC:TaskCardLayout 2026-07-10-00:00:
|
||||||
|
FN-7780 anchors the created-by-agent badge in its own bottom-left row before workflow identity, matching the existing workflow-row layout so the header ID/status/action row no longer wraps because of the agent chip on narrow/mobile cards.
|
||||||
|
*/
|
||||||
|
.card-agent-badge-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
min-width: 0;
|
||||||
|
margin-top: var(--space-xs);
|
||||||
|
}
|
||||||
|
|
||||||
.card-workflow-badge-row {
|
.card-workflow-badge-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -2704,7 +2704,6 @@ function TaskCardComponent({
|
|||||||
*/
|
*/
|
||||||
const hasCardMetaBadges = showPriorityBadge
|
const hasCardMetaBadges = showPriorityBadge
|
||||||
|| task.executionMode === "fast"
|
|| task.executionMode === "fast"
|
||||||
|| isAgentCreated
|
|
||||||
// FNXC:PlannerOversight 2026-07-04-00:00: the oversight badge is opt-in
|
// FNXC:PlannerOversight 2026-07-04-00:00: the oversight badge is opt-in
|
||||||
// metadata (absent for the common "off" default) — include it in the wrapper
|
// metadata (absent for the common "off" default) — include it in the wrapper
|
||||||
// guard so `.card-meta-badges` only renders when it has a real child.
|
// guard so `.card-meta-badges` only renders when it has a real child.
|
||||||
@@ -2983,17 +2982,6 @@ function TaskCardComponent({
|
|||||||
<span className="visually-hidden">{t("tasks.fastMode", "Fast mode")}</span>
|
<span className="visually-hidden">{t("tasks.fastMode", "Fast mode")}</span>
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{isAgentCreated && (
|
|
||||||
<span
|
|
||||||
className="card-agent-created-badge"
|
|
||||||
title={agentCreatedTitle}
|
|
||||||
aria-label={agentCreatedTitle}
|
|
||||||
>
|
|
||||||
<Bot size={11} aria-hidden="true" />
|
|
||||||
<span className="visually-hidden">{agentCreatedTitle}</span>
|
|
||||||
<span aria-hidden="true">{agentCreatedVisibleLabel}</span>
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
{showOversightBadge && (
|
{showOversightBadge && (
|
||||||
<span
|
<span
|
||||||
className={`card-oversight-badge card-oversight-badge--${OVERSIGHT_BADGE_MODIFIER[effectiveOversightLevel as Exclude<PlannerOversightLevel, "off">]}`}
|
className={`card-oversight-badge card-oversight-badge--${OVERSIGHT_BADGE_MODIFIER[effectiveOversightLevel as Exclude<PlannerOversightLevel, "off">]}`}
|
||||||
@@ -3544,6 +3532,23 @@ function TaskCardComponent({
|
|||||||
{showInReviewMoveControl && !metaRowVisible && renderInReviewMoveControl()}
|
{showInReviewMoveControl && !metaRowVisible && renderInReviewMoveControl()}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{isAgentCreated && (
|
||||||
|
<div className="card-agent-badge-row" data-testid="card-agent-badge-row">
|
||||||
|
{/**
|
||||||
|
* FNXC:TaskCardLayout 2026-07-10-00:00:
|
||||||
|
* FN-7780 moves the created-by-agent chip below the task content and before the workflow identity row so the header keeps only ID/status/actions metadata and no longer wraps on narrow/mobile cards. The badge content, tooltip, and accessible name remain unchanged.
|
||||||
|
*/}
|
||||||
|
<span
|
||||||
|
className="card-agent-created-badge"
|
||||||
|
title={agentCreatedTitle}
|
||||||
|
aria-label={agentCreatedTitle}
|
||||||
|
>
|
||||||
|
<Bot size={11} aria-hidden="true" />
|
||||||
|
<span className="visually-hidden">{agentCreatedTitle}</span>
|
||||||
|
<span aria-hidden="true">{agentCreatedVisibleLabel}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{hasWorkflowBadge && (
|
{hasWorkflowBadge && (
|
||||||
<div className="card-workflow-badge-row" data-testid="card-workflow-badge-row">
|
<div className="card-workflow-badge-row" data-testid="card-workflow-badge-row">
|
||||||
{/*
|
{/*
|
||||||
|
|||||||
@@ -123,15 +123,81 @@ describe("TaskCard badge wrapping (FN-5162)", () => {
|
|||||||
expect(styles.whiteSpace).toBe("nowrap");
|
expect(styles.whiteSpace).toBe("nowrap");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("places the agent badge in a left-aligned bottom row outside the header badge cluster", () => {
|
||||||
|
const agentRow = container.querySelector(".card-agent-badge-row") as HTMLElement;
|
||||||
|
const agentBadge = container.querySelector(".card-agent-created-badge") as HTMLElement;
|
||||||
|
const header = container.querySelector(".card-header") as HTMLElement;
|
||||||
|
const metaBadges = container.querySelector(".card-meta-badges") as HTMLElement;
|
||||||
|
|
||||||
|
expect(agentRow).toBeTruthy();
|
||||||
|
expect(agentBadge).toBeTruthy();
|
||||||
|
expect(agentRow.contains(agentBadge)).toBe(true);
|
||||||
|
expect(header.contains(agentBadge)).toBe(false);
|
||||||
|
expect(metaBadges.contains(agentBadge)).toBe(false);
|
||||||
|
expect(agentBadge.getAttribute("title")).toBe("Created by agent: agent-badge-wrap");
|
||||||
|
expect(agentBadge.getAttribute("aria-label")).toBe("Created by agent: agent-badge-wrap");
|
||||||
|
expect(agentBadge.querySelector(".visually-hidden")?.textContent).toBe("Created by agent: agent-badge-wrap");
|
||||||
|
expect(agentBadge.querySelector("span[aria-hidden='true']")?.textContent).toBe("agent-badge-...");
|
||||||
|
|
||||||
|
const styles = getComputedStyle(agentRow);
|
||||||
|
expect(styles.display).toBe("flex");
|
||||||
|
expect(styles.justifyContent).toBe("flex-start");
|
||||||
|
expect(styles.minWidth).toBe("0px");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not render an empty header badge shell when the agent badge is the only grouped affordance", () => {
|
||||||
|
const { container: agentOnlyContainer } = render(
|
||||||
|
<TaskCard
|
||||||
|
task={makeTask({
|
||||||
|
priority: "normal" as Task["priority"],
|
||||||
|
executionMode: "standard",
|
||||||
|
sourceType: "agent_heartbeat",
|
||||||
|
sourceAgentId: "agent-only",
|
||||||
|
plannerOversightLevel: "off",
|
||||||
|
})}
|
||||||
|
onOpenDetail={noop}
|
||||||
|
addToast={noop}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
const agentBadge = agentOnlyContainer.querySelector(".card-agent-created-badge");
|
||||||
|
expect(agentBadge).not.toBeNull();
|
||||||
|
expect(agentBadge?.closest(".card-agent-badge-row")).not.toBeNull();
|
||||||
|
expect(agentBadge?.closest(".card-header")).toBeNull();
|
||||||
|
expect(agentOnlyContainer.querySelector(".card-meta-badges")).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("omits the agent bottom row for non-agent-created tasks", () => {
|
||||||
|
const { container: nonAgentContainer } = render(
|
||||||
|
<TaskCard
|
||||||
|
task={makeTask({
|
||||||
|
priority: "normal" as Task["priority"],
|
||||||
|
executionMode: "standard",
|
||||||
|
sourceType: "dashboard_ui",
|
||||||
|
sourceAgentId: undefined,
|
||||||
|
plannerOversightLevel: "off",
|
||||||
|
})}
|
||||||
|
onOpenDetail={noop}
|
||||||
|
addToast={noop}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(nonAgentContainer.querySelector(".card-agent-created-badge")).toBeNull();
|
||||||
|
expect(nonAgentContainer.querySelector(".card-agent-badge-row")).toBeNull();
|
||||||
|
expect(nonAgentContainer.querySelector(".card-meta-badges")).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
it("places the workflow badge in a left-aligned bottom row outside the header badge cluster", () => {
|
it("places the workflow badge in a left-aligned bottom row outside the header badge cluster", () => {
|
||||||
const workflowRow = container.querySelector(".card-workflow-badge-row") as HTMLElement;
|
const workflowRow = container.querySelector(".card-workflow-badge-row") as HTMLElement;
|
||||||
const workflowBadge = container.querySelector(".card-workflow-badge") as HTMLElement;
|
const workflowBadge = container.querySelector(".card-workflow-badge") as HTMLElement;
|
||||||
const metaBadges = container.querySelector(".card-meta-badges") as HTMLElement;
|
const metaBadges = container.querySelector(".card-meta-badges") as HTMLElement;
|
||||||
|
const agentRow = container.querySelector(".card-agent-badge-row") as HTMLElement;
|
||||||
|
|
||||||
expect(workflowRow).toBeTruthy();
|
expect(workflowRow).toBeTruthy();
|
||||||
expect(workflowBadge).toBeTruthy();
|
expect(workflowBadge).toBeTruthy();
|
||||||
expect(workflowRow.contains(workflowBadge)).toBe(true);
|
expect(workflowRow.contains(workflowBadge)).toBe(true);
|
||||||
expect(metaBadges.contains(workflowBadge)).toBe(false);
|
expect(metaBadges.contains(workflowBadge)).toBe(false);
|
||||||
|
expect(agentRow.compareDocumentPosition(workflowRow) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();
|
||||||
|
|
||||||
const styles = getComputedStyle(workflowRow);
|
const styles = getComputedStyle(workflowRow);
|
||||||
expect(styles.display).toBe("flex");
|
expect(styles.display).toBe("flex");
|
||||||
|
|||||||
@@ -2594,7 +2594,7 @@ describe("TaskCard", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it("keeps priority, fast mode, and agent-created in meta while time moves to footer", () => {
|
it("keeps priority and fast mode in meta while agent-created and time move to bottom rows", () => {
|
||||||
|
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
<TaskCard
|
<TaskCard
|
||||||
@@ -2618,7 +2618,6 @@ describe("TaskCard", () => {
|
|||||||
const expectedMetaSelectors = [
|
const expectedMetaSelectors = [
|
||||||
".card-priority-badge",
|
".card-priority-badge",
|
||||||
".card-execution-mode-badge",
|
".card-execution-mode-badge",
|
||||||
".card-agent-created-badge",
|
|
||||||
];
|
];
|
||||||
expectedMetaSelectors.forEach((selector) => {
|
expectedMetaSelectors.forEach((selector) => {
|
||||||
|
|
||||||
@@ -2637,10 +2636,15 @@ describe("TaskCard", () => {
|
|||||||
// longer renders a per-card badge (FN-7539) — an inherited default is not
|
// longer renders a per-card badge (FN-7539) — an inherited default is not
|
||||||
// meaningfully-configured oversight, so it does not appear among the
|
// meaningfully-configured oversight, so it does not appear among the
|
||||||
// opt-in meta badges here.
|
// opt-in meta badges here.
|
||||||
|
const agentBadge = container.querySelector(".card-agent-created-badge");
|
||||||
|
expect(agentBadge).not.toBeNull();
|
||||||
|
expect(agentBadge?.closest(".card-agent-badge-row")).not.toBeNull();
|
||||||
|
expect(agentBadge?.closest(".card-meta-badges")).toBeNull();
|
||||||
|
expect(agentBadge?.closest(".card-header")).toBeNull();
|
||||||
|
|
||||||
expect(Array.from(group?.children ?? []).map((child) => child.className)).toEqual([
|
expect(Array.from(group?.children ?? []).map((child) => child.className)).toEqual([
|
||||||
"card-priority-badge card-priority-badge--high",
|
"card-priority-badge card-priority-badge--high",
|
||||||
"card-execution-mode-badge card-execution-mode-badge--fast",
|
"card-execution-mode-badge card-execution-mode-badge--fast",
|
||||||
"card-agent-created-badge",
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -2663,7 +2667,8 @@ describe("TaskCard", () => {
|
|||||||
expect(group).not.toBeNull();
|
expect(group).not.toBeNull();
|
||||||
expect(group?.querySelector(".card-priority-badge")).not.toBeNull();
|
expect(group?.querySelector(".card-priority-badge")).not.toBeNull();
|
||||||
expect(group?.querySelector(".card-execution-mode-badge")).not.toBeNull();
|
expect(group?.querySelector(".card-execution-mode-badge")).not.toBeNull();
|
||||||
expect(group?.querySelector(".card-agent-created-badge")).not.toBeNull();
|
expect(group?.querySelector(".card-agent-created-badge")).toBeNull();
|
||||||
|
expect(container.querySelector(".card-agent-created-badge")?.closest(".card-agent-badge-row")).not.toBeNull();
|
||||||
expect(group?.querySelector(".card-time-indicator")).toBeNull();
|
expect(group?.querySelector(".card-time-indicator")).toBeNull();
|
||||||
expect(container.querySelector(".card-footer-row")).toBeNull();
|
expect(container.querySelector(".card-footer-row")).toBeNull();
|
||||||
expect(container.querySelector(".card-footer-row-right")).toBeNull();
|
expect(container.querySelector(".card-footer-row-right")).toBeNull();
|
||||||
@@ -2706,6 +2711,7 @@ describe("TaskCard", () => {
|
|||||||
expect(container.querySelector(".card-priority-badge")).toBeNull();
|
expect(container.querySelector(".card-priority-badge")).toBeNull();
|
||||||
expect(container.querySelector(".card-execution-mode-badge")).toBeNull();
|
expect(container.querySelector(".card-execution-mode-badge")).toBeNull();
|
||||||
expect(container.querySelector(".card-agent-created-badge")).toBeNull();
|
expect(container.querySelector(".card-agent-created-badge")).toBeNull();
|
||||||
|
expect(container.querySelector(".card-agent-badge-row")).toBeNull();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -4497,7 +4503,10 @@ describe("TaskCard", () => {
|
|||||||
|
|
||||||
const badge = container.querySelector(".card-agent-created-badge");
|
const badge = container.querySelector(".card-agent-created-badge");
|
||||||
expect(badge).not.toBeNull();
|
expect(badge).not.toBeNull();
|
||||||
|
expect(badge?.closest(".card-agent-badge-row")).not.toBeNull();
|
||||||
|
expect(badge?.closest(".card-header")).toBeNull();
|
||||||
expect(badge?.getAttribute("title")).toBe("Created by agent: Task Robot");
|
expect(badge?.getAttribute("title")).toBe("Created by agent: Task Robot");
|
||||||
|
expect(badge?.getAttribute("aria-label")).toBe("Created by agent: Task Robot");
|
||||||
expect(badge?.querySelector("span[aria-hidden='true']")?.textContent).toBe("Task Robot");
|
expect(badge?.querySelector("span[aria-hidden='true']")?.textContent).toBe("Task Robot");
|
||||||
expect(badge?.querySelector(".visually-hidden")?.textContent).toBe("Created by agent: Task Robot");
|
expect(badge?.querySelector(".visually-hidden")?.textContent).toBe("Created by agent: Task Robot");
|
||||||
});
|
});
|
||||||
@@ -4518,6 +4527,8 @@ describe("TaskCard", () => {
|
|||||||
|
|
||||||
const badge = container.querySelector(".card-agent-created-badge");
|
const badge = container.querySelector(".card-agent-created-badge");
|
||||||
expect(badge).not.toBeNull();
|
expect(badge).not.toBeNull();
|
||||||
|
expect(badge?.closest(".card-agent-badge-row")).not.toBeNull();
|
||||||
|
expect(badge?.closest(".card-meta-badges")).toBeNull();
|
||||||
expect(badge?.getAttribute("title")).toBe("Created by agent: Scheduler Bot");
|
expect(badge?.getAttribute("title")).toBe("Created by agent: Scheduler Bot");
|
||||||
expect(badge?.getAttribute("aria-label")).toBe("Created by agent: Scheduler Bot");
|
expect(badge?.getAttribute("aria-label")).toBe("Created by agent: Scheduler Bot");
|
||||||
});
|
});
|
||||||
@@ -4539,6 +4550,7 @@ describe("TaskCard", () => {
|
|||||||
|
|
||||||
const badge = container.querySelector(".card-agent-created-badge");
|
const badge = container.querySelector(".card-agent-created-badge");
|
||||||
expect(badge).not.toBeNull();
|
expect(badge).not.toBeNull();
|
||||||
|
expect(badge?.closest(".card-agent-badge-row")).not.toBeNull();
|
||||||
expect(badge?.getAttribute("title")).toBe("Created by agent: Legacy Robot");
|
expect(badge?.getAttribute("title")).toBe("Created by agent: Legacy Robot");
|
||||||
expect(badge?.querySelector("span[aria-hidden='true']")?.textContent).toBe("Legacy Robot");
|
expect(badge?.querySelector("span[aria-hidden='true']")?.textContent).toBe("Legacy Robot");
|
||||||
});
|
});
|
||||||
@@ -4559,7 +4571,9 @@ describe("TaskCard", () => {
|
|||||||
|
|
||||||
const badge = container.querySelector(".card-agent-created-badge");
|
const badge = container.querySelector(".card-agent-created-badge");
|
||||||
expect(badge).not.toBeNull();
|
expect(badge).not.toBeNull();
|
||||||
|
expect(badge?.closest(".card-agent-badge-row")).not.toBeNull();
|
||||||
expect(badge?.getAttribute("title")).toBe("Created by agent");
|
expect(badge?.getAttribute("title")).toBe("Created by agent");
|
||||||
|
expect(badge?.getAttribute("aria-label")).toBe("Created by agent");
|
||||||
expect(badge?.querySelector("span[aria-hidden='true']")?.textContent).toBe("Agent");
|
expect(badge?.querySelector("span[aria-hidden='true']")?.textContent).toBe("Agent");
|
||||||
expect(badge?.querySelector(".visually-hidden")?.textContent).toBe("Created by agent");
|
expect(badge?.querySelector(".visually-hidden")?.textContent).toBe("Created by agent");
|
||||||
});
|
});
|
||||||
@@ -4579,6 +4593,7 @@ describe("TaskCard", () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(container.querySelector(".card-agent-created-badge")).toBeNull();
|
expect(container.querySelector(".card-agent-created-badge")).toBeNull();
|
||||||
|
expect(container.querySelector(".card-agent-badge-row")).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("coexists with GitHub badge and timer metadata", () => {
|
it("coexists with GitHub badge and timer metadata", () => {
|
||||||
@@ -4606,7 +4621,7 @@ describe("TaskCard", () => {
|
|||||||
|
|
||||||
expect(container.querySelector(".card-github-badge")).not.toBeNull();
|
expect(container.querySelector(".card-github-badge")).not.toBeNull();
|
||||||
expect(container.querySelector(".card-source-provenance")).not.toBeNull();
|
expect(container.querySelector(".card-source-provenance")).not.toBeNull();
|
||||||
expect(container.querySelector(".card-agent-created-badge")).not.toBeNull();
|
expect(container.querySelector(".card-agent-created-badge")?.closest(".card-agent-badge-row")).not.toBeNull();
|
||||||
expect(container.querySelector(".card-time-indicator")).not.toBeNull();
|
expect(container.querySelector(".card-time-indicator")).not.toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -5813,7 +5828,7 @@ describe("TaskCard workflow badges", () => {
|
|||||||
expect(screen.queryByTestId("card-workflow-badge-row")).toBeNull();
|
expect(screen.queryByTestId("card-workflow-badge-row")).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("keeps top badges in the meta cluster while rendering workflow identity below card rows", () => {
|
it("keeps top badges in the meta cluster while rendering agent and workflow identity below card rows", () => {
|
||||||
vi.useFakeTimers();
|
vi.useFakeTimers();
|
||||||
vi.setSystemTime(new Date("2026-06-30T12:10:00.000Z"));
|
vi.setSystemTime(new Date("2026-06-30T12:10:00.000Z"));
|
||||||
|
|
||||||
@@ -5839,11 +5854,16 @@ describe("TaskCard workflow badges", () => {
|
|||||||
const metaBadges = screen.getByTestId("card-meta-badges");
|
const metaBadges = screen.getByTestId("card-meta-badges");
|
||||||
const badge = screen.getByTestId("card-workflow-badge");
|
const badge = screen.getByTestId("card-workflow-badge");
|
||||||
const workflowRow = screen.getByTestId("card-workflow-badge-row");
|
const workflowRow = screen.getByTestId("card-workflow-badge-row");
|
||||||
|
const agentRow = screen.getByTestId("card-agent-badge-row");
|
||||||
|
const agentBadge = container.querySelector(".card-agent-created-badge");
|
||||||
expect(metaBadges.querySelector(".card-priority-badge")).not.toBeNull();
|
expect(metaBadges.querySelector(".card-priority-badge")).not.toBeNull();
|
||||||
expect(metaBadges.querySelector(".card-execution-mode-badge")).not.toBeNull();
|
expect(metaBadges.querySelector(".card-execution-mode-badge")).not.toBeNull();
|
||||||
expect(metaBadges.querySelector(".card-agent-created-badge")).not.toBeNull();
|
expect(metaBadges.querySelector(".card-agent-created-badge")).toBeNull();
|
||||||
expect(metaBadges.querySelector(".card-workflow-badge")).toBeNull();
|
expect(metaBadges.querySelector(".card-workflow-badge")).toBeNull();
|
||||||
|
expect(agentRow).toContainElement(agentBadge as HTMLElement);
|
||||||
|
expect(agentBadge?.closest(".card-header")).toBeNull();
|
||||||
expect(workflowRow).toContainElement(badge);
|
expect(workflowRow).toContainElement(badge);
|
||||||
|
expect(agentRow.compareDocumentPosition(workflowRow) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();
|
||||||
|
|
||||||
[".card-footer-row", ".card-meta", ".card-agent-row"].forEach((selector) => {
|
[".card-footer-row", ".card-meta", ".card-agent-row"].forEach((selector) => {
|
||||||
const row = container.querySelector(selector);
|
const row = container.querySelector(selector);
|
||||||
|
|||||||
Reference in New Issue
Block a user