import React from 'react'; import { render, screen, waitFor } from '@testing-library/react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import dayjs from 'dayjs'; jest.mock('@/components/ui/dropdown-menu', () => ({ DropdownMenu: ({ children }) =>
{children}
, DropdownMenuTrigger: ({ children }) =>
{children}
, DropdownMenuContent: ({ children }) =>
{children}
, DropdownMenuItem: ({ children, onClick }) => , DropdownMenuLabel: ({ children }) =>
{children}
, DropdownMenuSeparator: () =>
, })); jest.mock('lucide-react', () => new Proxy({}, { get: (_t, prop) => (prop === '__esModule' ? true : (props) => ), }) ); const today = dayjs().format('YYYY-MM-DD'); const lastWeek = dayjs().subtract(7, 'day').format('YYYY-MM-DD'); // Two customer-app bookings: one placed today, one a week ago. jest.mock('@/lib/assistant/scan', () => ({ __esModule: true, drainBookings: jest.fn(), })); jest.mock('@/lib/doormileHooks', () => ({ __esModule: true, useBooking: () => ({ data: null, isLoading: false, refetch: jest.fn() }), useAssignMilerToBooking: () => ({ mutateAsync: jest.fn(), isPending: false }), useRiderOptions: () => ({ data: [] }), })); import Bookings from '@/pages/doormile/bookings/Bookings'; import { drainBookings } from '@/lib/assistant/scan'; const booking = (bookingno, createdat) => ({ bookingid: bookingno, bookingno, createdat, status: 'Pending_Pickup', bookingsource: 'Customer_App', pickupaddress: 'Somewhere', pickuppincode: '641001', deliveryaddress: 'Elsewhere', deliverypincode: '641002', }); const renderPage = () => { const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } }); return render( ); }; /** * The Bookings list had no date control at all: it drained every page of * `/admin/bookings` and showed the lot, so the newest booking sat wherever the * scan happened to put it and there was no way to ask "what came in today". * * The picker defaults to today, and every number on the page is scoped to it — * which is the part worth pinning. A KPI that keeps counting the whole account * while the table shows one day reads as a broken page, not as a filter. */ describe('the Bookings date picker', () => { beforeEach(() => { drainBookings.mockResolvedValue({ rows: [booking('DM-TODAY', `${today} 09:00:00`), booking('DM-OLD', `${lastWeek} 09:00:00`)], truncated: false, scanned: 2, pagesFetched: 1, total: 2, }); }); it('renders a date control, defaulted to today', async () => { const { container } = renderPage(); await waitFor(() => expect(drainBookings).toHaveBeenCalled()); // The trigger carries the calendar icon and labels itself with the active // range. Asserted on the container's text rather than a single node because // the label and its "Today" badge are two sibling text nodes. expect(container.querySelector('[data-testid="icon-Calendar"]')).toBeTruthy(); expect(container.textContent).toMatch(/Today/); }); it("shows today's booking and hides the one from last week", async () => { renderPage(); expect(await screen.findByText('DM-TODAY')).toBeInTheDocument(); expect(screen.queryByText('DM-OLD')).not.toBeInTheDocument(); }); it('the KPI counts the same day the table shows', async () => { // Was the whole account before the filter existed. A "Customer bookings 2" // over a one-row table is the failure this pins. renderPage(); await screen.findByText('DM-TODAY'); expect(screen.getByText(/Customer bookings · today/i)).toBeInTheDocument(); }); it('says a date is filtering when the day is empty, not just "no bookings"', async () => { drainBookings.mockResolvedValue({ rows: [booking('DM-OLD', `${lastWeek} 09:00:00`)], truncated: false, scanned: 1, pagesFetched: 1, total: 1, }); renderPage(); // "Nothing was booked" and "a filter is hiding it" are different facts and // an operator has to be able to tell which one they are looking at. expect(await screen.findByText(/date picker to widen the range/i)).toBeInTheDocument(); }); });