Files
doormilxpress_astryx/tests/integration/bookingsDatePicker.test.jsx

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();
});
});