107 lines
4.3 KiB
JavaScript
107 lines
4.3 KiB
JavaScript
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 }) => <div>{children}</div>,
|
|
DropdownMenuTrigger: ({ children }) => <div>{children}</div>,
|
|
DropdownMenuContent: ({ children }) => <div>{children}</div>,
|
|
DropdownMenuItem: ({ children, onClick }) => <button type="button" onClick={onClick}>{children}</button>,
|
|
DropdownMenuLabel: ({ children }) => <div>{children}</div>,
|
|
DropdownMenuSeparator: () => <hr />,
|
|
}));
|
|
|
|
jest.mock('lucide-react', () =>
|
|
new Proxy({}, {
|
|
get: (_t, prop) => (prop === '__esModule' ? true : (props) => <span data-testid={`icon-${String(prop)}`} {...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(
|
|
<QueryClientProvider client={qc}>
|
|
<Bookings />
|
|
</QueryClientProvider>
|
|
);
|
|
};
|
|
|
|
/**
|
|
* 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();
|
|
});
|
|
});
|