feat(FN-4712): complete Step 4 — autosize planning chat textareas
Fusion-Task-Id: FN-4712 Fusion-Task-Lineage: 92ef2161-7ce2-4277-9921-7fe1dd204e98
This commit is contained in:
committed by
gsxdsm
parent
a7859ccef3
commit
ef5f7bbdfb
@@ -0,0 +1,134 @@
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { render, screen, waitFor } from "@testing-library/react";
|
||||
import { userEvent } from "@testing-library/user-event";
|
||||
import { PlanningModeModal } from "../PlanningModeModal";
|
||||
import {
|
||||
mockStartPlanningStreaming,
|
||||
mockCreatePlanningDraft,
|
||||
mockConnectPlanningStream,
|
||||
mockRespondToPlanning,
|
||||
mockRetryPlanningSession,
|
||||
mockCancelPlanning,
|
||||
mockStopPlanningGeneration,
|
||||
mockUpdatePlanningSessionDraft,
|
||||
mockCreateTaskFromPlanning,
|
||||
mockStartPlanningBreakdown,
|
||||
mockCreateTasksFromPlanning,
|
||||
mockFetchAiSession,
|
||||
mockParseConversationHistory,
|
||||
mockFetchModels,
|
||||
mockAcquireSessionLock,
|
||||
mockReleaseSessionLock,
|
||||
mockForceAcquireSessionLock,
|
||||
mockFetchAiSessions,
|
||||
mockConfirm,
|
||||
mockUseViewportMode,
|
||||
mockUseMobileKeyboard,
|
||||
mockTasks,
|
||||
mockModels,
|
||||
} from "./PlanningModeModal.test-helpers";
|
||||
|
||||
vi.mock("../../hooks/useNavigationHistory", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../hooks/useNavigationHistory")>();
|
||||
return {
|
||||
...actual,
|
||||
useNavigationHistoryContext: () => ({ pushNav: vi.fn(), replaceCurrent: vi.fn() }),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../../api", () => ({
|
||||
startPlanningStreaming: (...args: any[]) => mockStartPlanningStreaming(...args),
|
||||
createPlanningDraft: (...args: any[]) => mockCreatePlanningDraft(...args),
|
||||
connectPlanningStream: (...args: any[]) => mockConnectPlanningStream(...args),
|
||||
respondToPlanning: (...args: any[]) => mockRespondToPlanning(...args),
|
||||
retryPlanningSession: (...args: any[]) => mockRetryPlanningSession(...args),
|
||||
cancelPlanning: (...args: any[]) => mockCancelPlanning(...args),
|
||||
stopPlanningGeneration: (...args: any[]) => mockStopPlanningGeneration(...args),
|
||||
updatePlanningSessionDraft: (...args: any[]) => mockUpdatePlanningSessionDraft(...args),
|
||||
createTaskFromPlanning: (...args: any[]) => mockCreateTaskFromPlanning(...args),
|
||||
startPlanningBreakdown: (...args: any[]) => mockStartPlanningBreakdown(...args),
|
||||
createTasksFromPlanning: (...args: any[]) => mockCreateTasksFromPlanning(...args),
|
||||
fetchAiSession: (...args: any[]) => mockFetchAiSession(...args),
|
||||
parseConversationHistory: (...args: any[]) => mockParseConversationHistory(...args),
|
||||
fetchSettings: vi.fn().mockResolvedValue({ modelPresets: [], autoSelectModelPreset: false, defaultPresetBySize: {} }),
|
||||
fetchModels: (...args: any[]) => mockFetchModels(...args),
|
||||
fetchWorkflowSteps: vi.fn().mockResolvedValue([]),
|
||||
updateGlobalSettings: vi.fn().mockResolvedValue({}),
|
||||
duplicateTask: vi.fn().mockResolvedValue({}),
|
||||
fetchAiSessions: (...args: any[]) => mockFetchAiSessions(...args),
|
||||
archiveAiSession: vi.fn(),
|
||||
unarchiveAiSession: vi.fn(),
|
||||
deleteAiSession: vi.fn(),
|
||||
summarizePlanningDraftTitle: vi.fn().mockResolvedValue({ title: "Draft" }),
|
||||
fetchModelsWithFallback: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("../../hooks/useConfirm", () => ({
|
||||
useConfirm: () => ({ confirm: mockConfirm }),
|
||||
}));
|
||||
|
||||
vi.mock("../../hooks/useViewportMode", () => ({
|
||||
useViewportMode: () => mockUseViewportMode(),
|
||||
}));
|
||||
|
||||
vi.mock("../../hooks/useMobileKeyboard", () => ({
|
||||
useMobileKeyboard: (...args: any[]) => mockUseMobileKeyboard(...args),
|
||||
}));
|
||||
|
||||
vi.mock("../../hooks/useSessionLock", () => ({
|
||||
useSessionLock: () => ({ isLockedByOther: false, takeControl: vi.fn(), isLoading: false }),
|
||||
}));
|
||||
|
||||
describe("PlanningModeModal autosize", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
mockConfirm.mockResolvedValue(true);
|
||||
mockStartPlanningStreaming.mockResolvedValue({ sessionId: "session-123" });
|
||||
mockCreatePlanningDraft.mockResolvedValue({ sessionId: "draft-123", title: "New planning session" });
|
||||
mockRetryPlanningSession.mockResolvedValue({ success: true, sessionId: "session-123" });
|
||||
mockStartPlanningBreakdown.mockResolvedValue({ sessionId: "session-123", subtasks: [] });
|
||||
mockFetchAiSession.mockResolvedValue(null);
|
||||
mockFetchAiSessions.mockResolvedValue([]);
|
||||
mockParseConversationHistory.mockReturnValue([]);
|
||||
mockFetchModels.mockResolvedValue({
|
||||
models: mockModels,
|
||||
favoriteProviders: [],
|
||||
favoriteModels: [],
|
||||
resolvedPlanningProvider: "openai",
|
||||
resolvedPlanningModelId: "gpt-4o",
|
||||
});
|
||||
mockAcquireSessionLock.mockResolvedValue({ acquired: true, currentHolder: null });
|
||||
mockReleaseSessionLock.mockResolvedValue(undefined);
|
||||
mockForceAcquireSessionLock.mockResolvedValue(undefined);
|
||||
mockCancelPlanning.mockResolvedValue(undefined);
|
||||
mockUpdatePlanningSessionDraft.mockResolvedValue({ ok: true });
|
||||
mockStopPlanningGeneration.mockResolvedValue({ success: true });
|
||||
mockConnectPlanningStream.mockReturnValue({ close: vi.fn(), isConnected: vi.fn().mockReturnValue(true) } as any);
|
||||
});
|
||||
|
||||
it("grows initial planning textarea and caps at max", async () => {
|
||||
render(<PlanningModeModal isOpen={true} onClose={vi.fn()} onTaskCreated={vi.fn()} onTasksCreated={vi.fn()} tasks={mockTasks} />);
|
||||
|
||||
const textarea = screen.getByPlaceholderText(/Build a user authentication/i) as HTMLTextAreaElement;
|
||||
Object.defineProperty(HTMLTextAreaElement.prototype, "scrollHeight", {
|
||||
configurable: true,
|
||||
get() {
|
||||
const value = (this as HTMLTextAreaElement).value;
|
||||
if (!value) return 24;
|
||||
if (value.split("\n").length > 5) return 800;
|
||||
return 180;
|
||||
},
|
||||
});
|
||||
|
||||
await userEvent.type(textarea, "line 1\nline 2");
|
||||
await waitFor(() => {
|
||||
expect(Number.parseInt(textarea.style.height, 10)).toBeGreaterThanOrEqual(120);
|
||||
expect(Number.parseInt(textarea.style.height, 10)).toBeLessThanOrEqual(320);
|
||||
});
|
||||
|
||||
await userEvent.type(textarea, "\nline 3\nline 4\nline 5\nline 6");
|
||||
await waitFor(() => {
|
||||
expect(textarea.style.height).toBe("320px");
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user