HomeAgenda.test.tsx4.8 KBView on GitHub /**
* "Daily agenda" on the home hero — today's TASKS, in one always-expanded card.
*
* Three things are pinned here:
*
* 1. TASKS ONLY. The meetings that used to share this card live in the home widget rail
* now, so a meetings column reappearing here is a regression.
* 2. NO FOLD AND NO CLAMP. The card folded back when it competed for the single column
* with the meetings and the agent list; both have moved out, so a clamp now only hides
* the tasks the screen exists for.
* 3. THE TITLE IS THE LAYOUT'S, not the editor's — the document's own date heading renders
* empty on this surface.
*/
import { fireEvent, render, screen } from '@testing-library/react';
import type { ReactNode } from 'react';
jest.mock('@/modules/auth/utils/auth-client', () => ({
useSession: () => ({ data: { user: { id: 'user-1', name: 'Jesse Li' } }, isPending: false }),
}));
// The agenda's own fetch rides on its MOUNT, so the spy fires from a mount-only
// effect rather than from the render body — a re-render is free, a remount is the bug.
const mockAgendaDocumentMounted = jest.fn();
jest.mock('@/modules/agentCanvas/components/AgendaDocument', () => {
const { useEffect } = require('react');
return {
AgendaDocument: () => {
useEffect(() => {
mockAgendaDocumentMounted();
}, []);
return <div data-testid="agenda-document">AGENDA</div>;
},
};
});
// Left UNMOCKED deliberately: if the agenda ever reaches for the meetings column again, this
// sentinel is not here to catch it — the import itself would pull the whole calendar stack in
// and the suite would fail loudly rather than quietly rendering a stub.
jest.mock('@/modules/agentCanvas/context/MultiDayEditorRegistry', () => ({
MultiDayEditorRegistryProvider: ({ children }: { children: ReactNode }) => <>{children}</>,
}));
jest.mock('@/modules/agentCanvas/context/CrossEditorDragBus', () => ({
CrossEditorDragBusProvider: ({ children }: { children: ReactNode }) => <>{children}</>,
}));
const mockNavigate = jest.fn();
jest.mock('react-router', () => ({ useNavigate: () => mockNavigate }));
jest.mock('@/providers/query-provider', () => ({
useTRPC: () => ({
aopAgents: { getAgendaInstructions: { queryOptions: () => ({ queryKey: ['agendaInstructions'] }) } },
}),
}));
jest.mock('@tanstack/react-query', () => ({
useQuery: () => ({ data: { agentId: 'agent-1' } }),
}));
import { HomeAgenda } from '@/modules/home/components/HomeAgenda';
const body = () => screen.getByTestId('home-agenda-body');
const card = () => screen.getByTestId('home-agenda');
beforeEach(() => {
mockAgendaDocumentMounted.mockClear();
});
describe('HomeAgenda', () => {
it('holds the tasks document and NOT the meetings', () => {
render(<HomeAgenda />);
expect(body()).toContainElement(screen.getByTestId('agenda-document'));
// The meetings moved to the home widget rail. A two-column agenda card is the old shape.
expect(screen.queryByTestId('meetings')).not.toBeInTheDocument();
expect(body().className).not.toContain('grid-cols');
});
it('carries the "Daily agenda" title INSIDE the container, above the document', () => {
render(<HomeAgenda />);
const title = screen.getByRole('heading', { name: 'Daily agenda' });
// Inside the card it controls, but outside the editor: the document's own date
// heading renders empty on this surface (see DateHeadingNode's `surface` option).
expect(card()).toContainElement(title);
expect(body()).not.toContainElement(title);
expect(title.compareDocumentPosition(body()) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();
});
it('is always expanded — no toggle, no clamp, no fade', () => {
render(<HomeAgenda />);
// The fold existed to keep the agent list below reachable; that list is gone from the
// hero, so a clamp here would only hide the tasks the screen exists for.
expect(screen.queryByRole('button', { expanded: false })).not.toBeInTheDocument();
expect(screen.queryByRole('button', { expanded: true })).not.toBeInTheDocument();
expect(body().className).not.toContain('max-h-');
expect(body().className).not.toContain('overflow-hidden');
expect(body()).toBeVisible();
});
it('mounts the agenda document, so its query and Y.Doc sync are live', () => {
render(<HomeAgenda />);
expect(mockAgendaDocumentMounted).toHaveBeenCalled();
expect(screen.getByTestId('agenda-document')).toBeInTheDocument();
});
it('sends the instructions button to the agent\'s own config page', () => {
// The instructions ARE the agent's config, so a dialog showing the prose on
// its own left the reader one click short of every question it raised.
render(<HomeAgenda />);
fireEvent.click(screen.getByRole('button', { name: /Agenda Agent Instructions/i }));
expect(mockNavigate).toHaveBeenCalledWith('/agents/agent-1?tab=config');
});
});