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

109 lines
4.4 KiB
JavaScript

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) => <span data-testid={`icon-${String(prop)}`} {...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 }) => (
<button type="button" data-testid={`select-${id}`} onClick={() => onPlaceSelected(RS_PURAM)}>select</button>
),
}));
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(
<QueryClientProvider client={qc}>
<MemoryRouter>
<CreateOrder />
</MemoryRouter>
</QueryClientProvider>
);
};
// 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');
});
});