feat: add MSW for integration test mocking
Install Mock Service Worker (MSW) and configure it for vitest. Write one integration test for usePurchases hook using MSW. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
committed by
Barcode Betty
parent
d7cfc00a8d
commit
cf26dd3049
Generated
+680
-462
File diff suppressed because it is too large
Load Diff
@@ -34,6 +34,7 @@
|
||||
"eslint-plugin-react-refresh": "^0.5.2",
|
||||
"globals": "^17.4.0",
|
||||
"jsdom": "^25.0.1",
|
||||
"msw": "^2.12.14",
|
||||
"tailwindcss": "^4.0.0",
|
||||
"typescript": "^5.7.3",
|
||||
"typescript-eslint": "^8.56.1",
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import { renderHook, waitFor } from '@testing-library/react'
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
||||
import { usePurchases } from '../useApi'
|
||||
import { http, HttpResponse } from 'msw'
|
||||
import { server } from '../../test/mocks/server'
|
||||
|
||||
function createWrapper() {
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: { queries: { retry: false } },
|
||||
})
|
||||
return function Wrapper({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
{children}
|
||||
</QueryClientProvider>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
describe('useApi hooks', () => {
|
||||
describe('usePurchases', () => {
|
||||
it('fetches and returns purchases', async () => {
|
||||
const { result } = renderHook(() => usePurchases(), { wrapper: createWrapper() })
|
||||
|
||||
await waitFor(() => expect(result.current.isSuccess).toBe(true))
|
||||
|
||||
expect(result.current.data).toHaveLength(1)
|
||||
expect(result.current.data![0]).toMatchObject({
|
||||
id: 'pur_1',
|
||||
storeName: 'Kroger',
|
||||
total: 42.5,
|
||||
})
|
||||
})
|
||||
|
||||
it('returns an error when the endpoint fails', async () => {
|
||||
server.use(
|
||||
http.get('/api/v1/purchases', () => HttpResponse.error()),
|
||||
)
|
||||
|
||||
const { result } = renderHook(() => usePurchases(), { wrapper: createWrapper() })
|
||||
|
||||
await waitFor(() => expect(result.current.isError).toBe(true))
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,65 @@
|
||||
import { http, HttpResponse } from 'msw'
|
||||
import type { Purchase, Product, Coupon, PriceAlert } from '../../types/api.ts'
|
||||
|
||||
const mockPurchases: Purchase[] = [
|
||||
{
|
||||
id: 'pur_1',
|
||||
storeId: 'store_1',
|
||||
storeName: 'Kroger',
|
||||
date: '2024-01-15',
|
||||
total: 42.5,
|
||||
items: [
|
||||
{ id: 'item_1', productId: 'prod_1', name: 'Milk', quantity: 1, price: 3.99, unitPrice: 3.99 },
|
||||
{ id: 'item_2', productId: 'prod_2', name: 'Bread', quantity: 2, price: 5.98, unitPrice: 2.99 },
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
const mockProducts: Product[] = [
|
||||
{
|
||||
id: 'prod_1',
|
||||
name: 'Whole Milk',
|
||||
brand: 'Kroger',
|
||||
category: 'Dairy',
|
||||
prices: [{ storeId: 'store_1', storeName: 'Kroger', price: 3.99, lastUpdated: '2024-01-15' }],
|
||||
},
|
||||
{
|
||||
id: 'prod_2',
|
||||
name: 'Whole Wheat Bread',
|
||||
brand: 'Nature\'s Own',
|
||||
category: 'Bakery',
|
||||
prices: [{ storeId: 'store_1', storeName: 'Kroger', price: 2.99, lastUpdated: '2024-01-15' }],
|
||||
},
|
||||
]
|
||||
|
||||
const mockCoupons: Coupon[] = [
|
||||
{
|
||||
id: 'coupon_1',
|
||||
productId: 'prod_1',
|
||||
storeName: 'Kroger',
|
||||
description: '$1 off milk',
|
||||
discount: '$1.00',
|
||||
expiresAt: '2024-12-31',
|
||||
code: 'MILK1',
|
||||
},
|
||||
]
|
||||
|
||||
const mockAlerts: PriceAlert[] = [
|
||||
{
|
||||
id: 'alert_1',
|
||||
productId: 'prod_1',
|
||||
productName: 'Whole Milk',
|
||||
targetPrice: 2.99,
|
||||
currentPrice: 3.99,
|
||||
triggered: false,
|
||||
},
|
||||
]
|
||||
|
||||
export const handlers = [
|
||||
http.get('/api/v1/health', () => HttpResponse.json({ status: 'ok' })),
|
||||
http.get('/api/v1/purchases', () => HttpResponse.json(mockPurchases)),
|
||||
http.get('/api/v1/products', () => HttpResponse.json(mockProducts)),
|
||||
http.get('/api/v1/products/prod_1', () => HttpResponse.json(mockProducts[0])),
|
||||
http.get('/api/v1/coupons', () => HttpResponse.json(mockCoupons)),
|
||||
http.get('/api/v1/price-alerts', () => HttpResponse.json(mockAlerts)),
|
||||
]
|
||||
@@ -0,0 +1,4 @@
|
||||
import { setupServer } from 'msw/node'
|
||||
import { handlers } from './handlers'
|
||||
|
||||
export const server = setupServer(...handlers)
|
||||
@@ -1 +1,6 @@
|
||||
import '@testing-library/jest-dom/vitest'
|
||||
import { server } from './mocks/server'
|
||||
|
||||
beforeAll(() => server.listen())
|
||||
afterEach(() => server.resetHandlers())
|
||||
afterAll(() => server.close())
|
||||
|
||||
Reference in New Issue
Block a user