feat(FN-5162): merge fusion/fn-5162
This commit is contained in:
@@ -63,7 +63,10 @@
|
||||
.card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
row-gap: var(--space-xs);
|
||||
min-width: 0;
|
||||
margin-bottom: var(--space-xs);
|
||||
}
|
||||
|
||||
@@ -160,6 +163,10 @@
|
||||
.card-no-commits-expected-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
font-size: 0.625rem;
|
||||
font-weight: 600;
|
||||
line-height: 1;
|
||||
@@ -598,6 +605,10 @@
|
||||
.card-agent-created-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
gap: var(--space-xs);
|
||||
font-size: 0.625rem;
|
||||
font-weight: 600;
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { render } from "@testing-library/react";
|
||||
import { TaskCard } from "../TaskCard";
|
||||
import type { Task } from "@fusion/core";
|
||||
import { loadAllAppCss } from "../../test/cssFixture";
|
||||
|
||||
vi.mock("lucide-react", () => ({
|
||||
Link: () => null,
|
||||
GitBranch: () => null,
|
||||
Clock: () => null,
|
||||
Pencil: () => null,
|
||||
Layers: () => null,
|
||||
ChevronDown: () => null,
|
||||
Folder: () => null,
|
||||
GitPullRequest: () => null,
|
||||
CircleDot: () => null,
|
||||
CheckCircle2: () => null,
|
||||
XCircle: () => null,
|
||||
Target: () => null,
|
||||
Bot: () => null,
|
||||
Trash2: () => null,
|
||||
RotateCw: () => null,
|
||||
Zap: () => null,
|
||||
}));
|
||||
|
||||
vi.mock("../ProviderIcon", () => ({
|
||||
ProviderIcon: () => null,
|
||||
}));
|
||||
|
||||
vi.mock("../PluginSlot", () => ({
|
||||
PluginSlot: () => null,
|
||||
}));
|
||||
|
||||
vi.mock("../../hooks/useTaskDiffStats", () => ({
|
||||
useTaskDiffStats: () => ({ stats: null, loading: false }),
|
||||
}));
|
||||
|
||||
const noop = () => {};
|
||||
|
||||
function makeTask(overrides: Partial<Task> = {}): Task {
|
||||
return {
|
||||
id: "FN-5162",
|
||||
title: "Wrap this very long task title without letting the badge row overflow the card boundary",
|
||||
column: "in-progress",
|
||||
status: "planning" as Task["status"],
|
||||
steps: [],
|
||||
dependencies: [],
|
||||
description: "",
|
||||
...overrides,
|
||||
} as Task;
|
||||
}
|
||||
|
||||
describe("TaskCard badge wrapping (FN-5162)", () => {
|
||||
let cleanupCss: (() => void) | undefined;
|
||||
let container: HTMLElement;
|
||||
|
||||
beforeEach(async () => {
|
||||
const style = document.createElement("style");
|
||||
style.textContent = await Promise.resolve(loadAllAppCss());
|
||||
document.head.appendChild(style);
|
||||
cleanupCss = () => style.remove();
|
||||
|
||||
container = render(
|
||||
<TaskCard
|
||||
task={makeTask({
|
||||
priority: "urgent" as Task["priority"],
|
||||
executionMode: "fast",
|
||||
noCommitsExpected: true,
|
||||
sourceType: "agent_heartbeat",
|
||||
sourceAgentId: "agent-badge-wrap",
|
||||
issueInfo: {
|
||||
owner: "owner",
|
||||
repo: "repo",
|
||||
number: 42,
|
||||
state: "open",
|
||||
title: "Tracked issue with a long badge label",
|
||||
url: "https://github.com/owner/repo/issues/42",
|
||||
} as Task["issueInfo"],
|
||||
})}
|
||||
onOpenDetail={noop}
|
||||
addToast={noop}
|
||||
/>,
|
||||
).container;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
cleanupCss?.();
|
||||
cleanupCss = undefined;
|
||||
});
|
||||
|
||||
it("wraps the header row and keeps a non-zero row gap", () => {
|
||||
const header = container.querySelector(".card-header");
|
||||
expect(header).toBeTruthy();
|
||||
|
||||
const styles = getComputedStyle(header!);
|
||||
expect(styles.flexWrap).toBe("wrap");
|
||||
expect(styles.rowGap).toMatch(/^(var\(--space-xs\)|(?!0px$)\d+(?:\.\d+)?px)$/);
|
||||
});
|
||||
|
||||
it.each([
|
||||
".card-status-badge",
|
||||
".card-priority-badge",
|
||||
".card-agent-created-badge",
|
||||
".card-no-commits-expected-badge",
|
||||
".card-github-badge",
|
||||
])("applies truncation constraints to %s when rendered", (selector) => {
|
||||
const badge = container.querySelector(selector);
|
||||
expect(badge, `${selector} should render for the fixture`).toBeTruthy();
|
||||
|
||||
const styles = getComputedStyle(badge as Element);
|
||||
expect(styles.maxWidth).not.toBe("none");
|
||||
expect(styles.whiteSpace).toBe("nowrap");
|
||||
});
|
||||
});
|
||||
@@ -1992,6 +1992,9 @@ input[type="range"]:focus-visible {
|
||||
.card-github-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
gap: var(--space-xs);
|
||||
font-size: 0.6875rem;
|
||||
font-weight: 600;
|
||||
|
||||
@@ -12,7 +12,7 @@ const qualityAppTests = [
|
||||
"app/api/**/*.test.ts",
|
||||
// Representative workflow/component coverage. Exhaustive modal/view suites
|
||||
// stay available in the full `dashboard-app` project.
|
||||
"app/components/__tests__/{ActiveAgentsPanel,ActivityLogModal,AgentMentionPopup,AgentMetricsBar,AgentOnboardingModal,AgentReflectionsTab,AgentTokenStatsPanel,App,AuthTokenRecoveryDialog,Board,board-mobile-view-switch,ChatView,ChatView.autosize,ChatView.chat-input-autosize,ChatView.default-model-icon,ChatView.draft,ChatView.rooms,ChatView.swipe-back,Column,ConfirmDialog,ConversationHistory,DashboardLoader,DevServerView.mobile,DirectoryPicker,DuplicateWarningModal,ErrorBoundary,ExecutorStatusBar,FileBrowser,FileEditor,GitHubBadge,InlineCreateCard,LoginInstructions,MemoryView,MessageComposer,MessageComposer.autosize,MobileNavBar,NewTaskModal,NodeCard,NodeHealthDot,NodeStatusIndicator,PlanningModeModal.autosize,PrChecksList,PrCreateModal,PrCreateModal.layout,ProjectCard,ProjectSelector,ProviderIcon,PrPanel,PrPanel.merge,PrPanel.reviews,QuickChatFAB,ReliabilityView,ResearchView,SecretsView,SettingsModal,SettingsModal.worktrunk,StashRecoveryView,TaskCard,TaskCard.badge-height,TaskChangesTab,TaskComments,TaskDetailModal,TaskDetailModal.github-tracking-header,TaskDetailModal.github-tracking-stale,TaskDetailModal.rebind-banner,TaskDocumentsTab,TaskForm,TaskIdIntegrityBanner,TrackingRepoSelect,WorkflowResultsTab,WorktrunkInstallApprovalDetails}.test.tsx",
|
||||
"app/components/__tests__/{ActiveAgentsPanel,ActivityLogModal,AgentMentionPopup,AgentMetricsBar,AgentOnboardingModal,AgentReflectionsTab,AgentTokenStatsPanel,App,AuthTokenRecoveryDialog,Board,board-mobile-view-switch,ChatView,ChatView.autosize,ChatView.chat-input-autosize,ChatView.default-model-icon,ChatView.draft,ChatView.rooms,ChatView.swipe-back,Column,ConfirmDialog,ConversationHistory,DashboardLoader,DevServerView.mobile,DirectoryPicker,DuplicateWarningModal,ErrorBoundary,ExecutorStatusBar,FileBrowser,FileEditor,GitHubBadge,InlineCreateCard,LoginInstructions,MemoryView,MessageComposer,MessageComposer.autosize,MobileNavBar,NewTaskModal,NodeCard,NodeHealthDot,NodeStatusIndicator,PlanningModeModal.autosize,PrChecksList,PrCreateModal,PrCreateModal.layout,ProjectCard,ProjectSelector,ProviderIcon,PrPanel,PrPanel.merge,PrPanel.reviews,QuickChatFAB,ReliabilityView,ResearchView,SecretsView,SettingsModal,SettingsModal.worktrunk,StashRecoveryView,TaskCard,TaskCard.badge-height,TaskCard.badge-wrap,TaskChangesTab,TaskComments,TaskDetailModal,TaskDetailModal.github-tracking-header,TaskDetailModal.github-tracking-stale,TaskDetailModal.rebind-banner,TaskDocumentsTab,TaskForm,TaskIdIntegrityBanner,TrackingRepoSelect,WorkflowResultsTab,WorktrunkInstallApprovalDetails}.test.tsx",
|
||||
// Hooks and utilities are fast, user-visible state/formatting behavior.
|
||||
"app/context/**/*.test.tsx",
|
||||
"app/hooks/__tests__/{useAgents,useAgentLogs,useAppSettings,useAuthOnboarding,useConfirm,useCurrentProject,useNodes,useNodeSettingsSync,useProjects,useQuickChat,useTasks,useTerminalSessions,useTheme,useToast,useUsageData,useViewState}.test.{ts,tsx}",
|
||||
|
||||
Reference in New Issue
Block a user