151 lines
5.0 KiB
JavaScript
151 lines
5.0 KiB
JavaScript
import React from 'react';
|
|
import dayjs from 'dayjs';
|
|
|
|
jest.mock('lucide-react', () =>
|
|
new Proxy({}, { get: (_t, prop) => (prop === '__esModule' ? true : (props) => <span data-testid={`icon-${String(prop)}`} {...props} />) })
|
|
);
|
|
|
|
import {
|
|
rtoActionsFor,
|
|
RETURN_WINDOW_DAYS,
|
|
getDeliveryAgeDays,
|
|
RTO_STARTABLE,
|
|
} from '@/components/doormile/RtoDialogs';
|
|
import { RTO_REASONS } from '@/api/doormile/endpoints';
|
|
|
|
describe('7-Day Amazon-Style Reverse Logistics', () => {
|
|
it('defines RETURN_WINDOW_DAYS as 7', () => {
|
|
expect(RETURN_WINDOW_DAYS).toBe(7);
|
|
});
|
|
|
|
it('allows in-transit orders to initiate RTO', () => {
|
|
RTO_STARTABLE.forEach((status) => {
|
|
const actions = rtoActionsFor({ consignmentid: 123, orderstatus: status });
|
|
expect(actions.canStart).toBe(true);
|
|
expect(actions.isPostDelivery).toBe(false);
|
|
expect(actions.windowExpired).toBe(false);
|
|
});
|
|
});
|
|
|
|
it('allows orders delivered within 7 days to initiate customer return', () => {
|
|
// Delivered 2 days ago
|
|
const twoDaysAgo = dayjs().subtract(2, 'day').toISOString();
|
|
const actions = rtoActionsFor({
|
|
consignmentid: 101,
|
|
orderstatus: 'delivered',
|
|
deliveredat: twoDaysAgo,
|
|
});
|
|
|
|
expect(actions.canStart).toBe(true);
|
|
expect(actions.isPostDelivery).toBe(true);
|
|
expect(actions.windowExpired).toBe(false);
|
|
expect(actions.daysRemaining).toBe(5);
|
|
});
|
|
|
|
it('allows orders delivered 6 days ago (near boundary) to initiate return', () => {
|
|
const sixDaysAgo = dayjs().subtract(6, 'day').toISOString();
|
|
const actions = rtoActionsFor({
|
|
consignmentid: 102,
|
|
orderstatus: 'delivered',
|
|
deliveredat: sixDaysAgo,
|
|
});
|
|
|
|
expect(actions.canStart).toBe(true);
|
|
expect(actions.isPostDelivery).toBe(true);
|
|
expect(actions.windowExpired).toBe(false);
|
|
expect(actions.daysRemaining).toBe(1);
|
|
});
|
|
|
|
it('HIDES/DISABLES return for orders delivered MORE than 7 days ago', () => {
|
|
// Delivered 8 days ago
|
|
const eightDaysAgo = dayjs().subtract(8, 'day').toISOString();
|
|
const actions = rtoActionsFor({
|
|
consignmentid: 103,
|
|
orderstatus: 'delivered',
|
|
deliveredat: eightDaysAgo,
|
|
});
|
|
|
|
// canStart is false -> button is hidden in Deliveries table
|
|
expect(actions.canStart).toBe(false);
|
|
expect(actions.isPostDelivery).toBe(true);
|
|
expect(actions.windowExpired).toBe(true);
|
|
expect(actions.daysRemaining).toBe(0);
|
|
});
|
|
|
|
it('falls back to updatedat if deliveredat is missing on delivered order', () => {
|
|
const threeDaysAgo = dayjs().subtract(3, 'day').toISOString();
|
|
const actions = rtoActionsFor({
|
|
consignmentid: 104,
|
|
orderstatus: 'delivered',
|
|
updatedat: threeDaysAgo,
|
|
});
|
|
|
|
expect(actions.canStart).toBe(true);
|
|
expect(actions.daysRemaining).toBe(4);
|
|
});
|
|
|
|
it('rejects cancelled or invalid rows', () => {
|
|
expect(rtoActionsFor({ consignmentid: 105, orderstatus: 'cancelled' }).canStart).toBe(false);
|
|
expect(rtoActionsFor({ consignmentid: null, orderstatus: 'delivered' }).canStart).toBe(false);
|
|
expect(rtoActionsFor(null).canStart).toBe(false);
|
|
});
|
|
|
|
it('includes post-delivery customer return reasons', () => {
|
|
const values = RTO_REASONS.map((r) => r.value);
|
|
expect(values).toContain('wrong_item');
|
|
expect(values).toContain('defective');
|
|
expect(values).toContain('quality_issue');
|
|
expect(values).toContain('size_mismatch');
|
|
expect(values).toContain('not_needed');
|
|
});
|
|
|
|
it('BLOCKS returns for Food items (canStart is false, button is hidden)', () => {
|
|
const foodRow = {
|
|
consignmentid: 201,
|
|
orderstatus: 'delivered',
|
|
deliverycategory: 'Food',
|
|
deliveredat: dayjs().subtract(1, 'day').toISOString(),
|
|
};
|
|
const actions = rtoActionsFor(foodRow);
|
|
expect(actions.canStart).toBe(false);
|
|
expect(actions.isPerishable).toBe(true);
|
|
});
|
|
|
|
it('BLOCKS returns for Meat items (canStart is false, button is hidden)', () => {
|
|
const meatRow = {
|
|
consignmentid: 202,
|
|
orderstatus: 'delivered',
|
|
itemcategory: 'Raw Meat',
|
|
deliveredat: dayjs().subtract(1, 'day').toISOString(),
|
|
};
|
|
const actions = rtoActionsFor(meatRow);
|
|
expect(actions.canStart).toBe(false);
|
|
expect(actions.isPerishable).toBe(true);
|
|
});
|
|
|
|
it('BLOCKS returns for Fresh Produce items (canStart is false, button is hidden)', () => {
|
|
const freshRow = {
|
|
consignmentid: 203,
|
|
orderstatus: 'delivered',
|
|
parcels: [{ itemcategory: 'Fresh Vegetables' }],
|
|
deliveredat: dayjs().subtract(1, 'day').toISOString(),
|
|
};
|
|
const actions = rtoActionsFor(freshRow);
|
|
expect(actions.canStart).toBe(false);
|
|
expect(actions.isPerishable).toBe(true);
|
|
});
|
|
|
|
it('ALLOWS returns for Steel and durable goods within 7 days', () => {
|
|
const steelRow = {
|
|
consignmentid: 204,
|
|
orderstatus: 'delivered',
|
|
deliverycategory: 'Steel',
|
|
deliveredat: dayjs().subtract(2, 'day').toISOString(),
|
|
};
|
|
const actions = rtoActionsFor(steelRow);
|
|
expect(actions.canStart).toBe(true);
|
|
expect(actions.isPerishable).toBeUndefined();
|
|
expect(actions.daysRemaining).toBe(5);
|
|
});
|
|
});
|