/** * Network-layer mocks for the user-ui tests. * * Everything the home page fetches goes through one of two doors: * - tRPC -> global.fetch (common.essentialConsts, ...) * - axios -> the assets CDN (products.json, stores.json, slots.json, availability.json) * * Both are stubbed here and both fail loudly on an unmocked URL, so a new * dependency introduced by app code surfaces as a test failure instead of a * silent empty render. * * The tRPC URL is matched on the procedure path rather than the host, because * BASE_API_URL (packages/ui/index.ts) is a local address during development. * `jest.mock('axios')` lives in tests/setup.ts so it is registered before any * app module imports axios. * * Fixtures are imported as JSON rather than read with `fs`: importing a Node * builtin pulls @types/node into the typecheck program, which flips * `setTimeout` from `number` to `NodeJS.Timeout` and breaks unrelated app types. * * NOTE: mock-slots-response.json is a snapshot of a real day (see the * deliveryTime values). The home page drops past slots, so those fixtures need * refreshing once their dates fall behind. */ import essentialConsts from '../__fixtures__/essentialConsts.json' import availability from './mock-availability-response.json' import products from './mock-products-response.json' import slots from './mock-slots-response.json' import stores from './mock-stores-response.json' export const ESSENTIAL_CONSTS_URL = 'https://worker.freshyo.in/api/trpc/common.essentialConsts?batch=1&input=%7B%220%22%3A%7B%22json%22%3Anull%2C%22meta%22%3A%7B%22values%22%3A%5B%22undefined%22%5D%7D%7D%7D' // Derived by useCacheUrl / useAvailabilityCacheUrl / useSlotsCacheUrl from the // essentialConsts payload above (assetsDomain, apiCacheKey, cacheVersion, // availabilityVersionNum, slotsVersionNum). export const PRODUCTS_URL = 'https://assets.freshyo.in/api-cache/v-755/products.json' export const AVAILABILITY_URL = 'https://assets.freshyo.in/av-72/availability.json' export const STORES_URL = 'https://assets.freshyo.in/api-cache/v-755/stores.json' export const SLOTS_URL = 'https://assets.freshyo.in/slots/v-401/slots.json?v=123' /** Route a CDN file name to its mock response. */ const mockForCacheFile = (url: string): unknown => { if (url.includes('products.json')) return products if (url.includes('stores.json')) return stores if (url.includes('slots.json')) return slots if (url.includes('availability.json')) return availability throw new Error(`[tests] unmocked assets request: ${url}`) } const jsonResponse = (body: unknown) => ({ ok: true, status: 200, statusText: 'OK', headers: new Map(), url: '', json: async () => body, text: async () => JSON.stringify(body), }) /** * Install the fetch + axios stubs and return the handles for assertions. * Call from beforeEach so each test starts from a clean call history. */ export function setupApiMocks() { const axios = require('axios') axios.get.mockImplementation(async (url: string) => ({ data: mockForCacheFile(url), status: 200, statusText: 'OK', headers: {}, config: {}, })) const fetchMock = jest.fn(async (url: string) => { if (url.includes('common.essentialConsts')) { return jsonResponse(essentialConsts) } throw new Error(`[tests] unmocked fetch: ${url}`) }) ;(global as unknown as { fetch: unknown }).fetch = fetchMock return { fetchMock, axiosGet: axios.get } }