import React from 'react'; import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { MemoryRouter } from 'react-router-dom'; /** * Create Order → Order Summary: driving distance and duration for short legs. * * Pickup and drop on the same address showed "1 km" and "15 mins". OSRM rounds * to whole km (a 120 m leg is 0 km), the page then did `Math.max(1, d || 1)` * and `minutes || 15`, so every leg under 500 m read as 1 km / 15 mins. The * card must show the real road length in metres and "< 1 min". */ jest.mock('lucide-react', () => new Proxy({}, { get: (_t, prop) => (prop === '__esModule' ? true : (props) => ), }) ); jest.mock('leaflet', () => ({ __esModule: true, default: { DivIcon: function DivIcon() {} } })); jest.mock('react-leaflet', () => ({ MapContainer: () => null, Marker: () => null, Polyline: () => null, TileLayer: () => null, useMap: () => ({}), })); // The autocomplete is replaced by a button that "selects" one fixed place, so // the test drives the real handlePlaceSelect → route effect → summary card. const RS_PURAM = { latitude: 11.0086, longitude: 76.9502, formatted_address: 'RS Puram, Coimbatore, Tamil Nadu, 641002' }; jest.mock('@/components/doormile/AddressAutocomplete', () => ({ __esModule: true, default: ({ id, onPlaceSelected }) => ( ), })); jest.mock('@/components/doormile/MapPinPickerModal', () => ({ __esModule: true, default: () => null })); jest.mock('@/components/doormile/HubLocationSelect', () => ({ HubLocationSelect: () => null })); jest.mock('@/lib/doormileHooks', () => ({ useHubs: () => ({ data: [] }) })); jest.mock('@/lib/geocodingService', () => ({ buildCityScope: () => null, geocodeAddress: jest.fn(), saveRecentAddress: jest.fn() })); jest.mock('@/components/third-party/OpenToast', () => ({ OpenToast: jest.fn() })); jest.mock('@/api/doormile/endpoints', () => ({ createExpressBooking: jest.fn(), createTenantCustomer: jest.fn(), getAdminCustomers: jest.fn(() => Promise.resolve([])), getAdminPricing: jest.fn(() => Promise.resolve([])), getAdminTenants: jest.fn(() => Promise.resolve([])), getTenantCustomers: jest.fn(() => Promise.resolve([])), getTenantLocations: jest.fn(() => Promise.resolve([])), })); import CreateOrder from '@/pages/doormile/orders/CreateOrder'; const osrm = (meters, seconds) => ({ ok: true, json: async () => ({ routes: [{ distance: meters, duration: seconds, geometry: { coordinates: [] } }] }), }); const renderPage = () => { const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } }); return render( ); }; // The value box sits directly under its label in the summary card. const metric = (label) => screen.getByText(label).nextElementSibling.textContent; const pinBothEnds = () => { fireEvent.click(screen.getByTestId('select-pickup-address')); fireEvent.click(screen.getByTestId('select-drop-address')); }; describe('Create Order — route summary for short legs', () => { beforeEach(() => { global.fetch = jest.fn(); }); it('shows 0 m and "< 1 min" when pickup and drop are the same address — not 1 km / 15 mins', async () => { global.fetch.mockResolvedValue(osrm(0, 0)); renderPage(); pinBothEnds(); await waitFor(() => expect(metric('Driving Dist.')).toBe('0 m')); expect(metric('Est. Duration')).toBe('< 1 min'); expect(screen.getByText('0 m road path')).toBeInTheDocument(); expect(screen.queryByText('1 km')).not.toBeInTheDocument(); expect(screen.queryByText('15 mins')).not.toBeInTheDocument(); }); it('shows a ~140 m leg in metres', async () => { global.fetch.mockResolvedValue(osrm(142, 25)); renderPage(); pinBothEnds(); await waitFor(() => expect(metric('Driving Dist.')).toBe('140 m')); expect(metric('Est. Duration')).toBe('< 1 min'); }); it('still shows longer legs in km with one decimal and real minutes', async () => { global.fetch.mockResolvedValue(osrm(1908, 130)); renderPage(); pinBothEnds(); await waitFor(() => expect(metric('Driving Dist.')).toBe('1.9 km')); expect(metric('Est. Duration')).toBe('2 mins'); }); });