/** * Integration Tests: Inventory (WMS) Store * Tests warehouse inventory management with mocked API * * Run: npm run test:integration */ import { beforeEach, describe, expect, it } from 'vitest' import { setActivePinia, createPinia } from 'pinia' import { server } from '@/tests/mocks/server' import { http, HttpResponse } from 'msw' /** * Mock Inventory Store (placeholder until actual store is created) */ class MockInventoryStore { inventory: any[] = [] loading = false error: string | null = null async fetchInventory() { this.loading = true try { const response = await fetch(`${process.env.VITE_API_BASE_URL || 'http://localhost:3000/api'}/inventory`) const data = await response.json() this.inventory = data.data || [] } catch (err) { this.error = (err as Error).message } finally { this.loading = false } } async updateInventory(inventoryId: string, payload: any) { this.loading = true try { const response = await fetch( `${process.env.VITE_API_BASE_URL || 'http://localhost:3000/api'}/inventory/${inventoryId}`, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) } ) if (!response.ok) throw new Error('Update failed') const data = await response.json() const index = this.inventory.findIndex((i) => i.inventoryId === inventoryId) if (index !== -1) this.inventory[index] = data return data } catch (err) { this.error = (err as Error).message throw err } finally { this.loading = false } } } describe('Inventory (WMS) Store Integration', () => { let store: MockInventoryStore beforeEach(() => { store = new MockInventoryStore() }) describe('fetchInventory', () => { it('loads inventory from WMS API', async () => { await store.fetchInventory() expect(store.inventory).toHaveLength(1) expect(store.inventory[0].inventoryId).toBe('INV-001') expect(store.inventory[0].qtyOnHand).toBe(1000) expect(store.loading).toBe(false) expect(store.error).toBeNull() }) it('calculates available quantity correctly', async () => { await store.fetchInventory() const inv = store.inventory[0] const available = inv.qtyOnHand - inv.qtyReserved expect(available).toBe(900) expect(inv.qtyAvailable).toBe(available) }) it('handles API errors gracefully', async () => { server.use( http.get('*/api/inventory', () => { return HttpResponse.json( { message: 'Database connection failed' }, { status: 500 } ) }) ) await store.fetchInventory() expect(store.error).not.toBeNull() expect(store.inventory).toHaveLength(0) }) }) describe('updateInventory', () => { beforeEach(async () => { await store.fetchInventory() }) it('updates inventory quantities', async () => { const updates = { qtyOnHand: 1200, qtyReserved: 150 } const updated = await store.updateInventory('INV-001', updates) expect(updated.qtyOnHand).toBe(1200) expect(updated.qtyReserved).toBe(150) expect(updated.qtyAvailable).toBe(1050) }) it('reflects updates in store', async () => { const updates = { qtyOnHand: 800, qtyReserved: 100 } await store.updateInventory('INV-001', updates) const inv = store.inventory.find((i) => i.inventoryId === 'INV-001') expect(inv?.qtyOnHand).toBe(800) }) it('handles update validation errors', async () => { server.use( http.patch('*/api/inventory/:inventoryId', () => { return HttpResponse.json( { message: 'Quantity cannot be negative' }, { status: 400 } ) }) ) await expect( store.updateInventory('INV-001', { qtyOnHand: -100 }) ).rejects.toThrow() }) }) describe('stock availability checks', () => { beforeEach(async () => { await store.fetchInventory() }) it('reserves stock correctly', async () => { const initial = store.inventory[0] const reservation = 100 const updated = await store.updateInventory('INV-001', { qtyOnHand: initial.qtyOnHand, qtyReserved: initial.qtyReserved + reservation }) expect(updated.qtyAvailable).toBe(initial.qtyAvailable - reservation) }) it('prevents over-reservation', async () => { const current = store.inventory[0] // Try to reserve more than available server.use( http.patch('*/api/inventory/:inventoryId', () => { return HttpResponse.json( { message: 'Cannot reserve more than available quantity' }, { status: 422 } ) }) ) await expect( store.updateInventory('INV-001', { qtyOnHand: current.qtyOnHand, qtyReserved: 10000 // Exceed available }) ).rejects.toThrow() }) }) describe('multi-warehouse scenarios', () => { it('handles inventory across multiple warehouses', async () => { server.use( http.get('*/api/inventory', () => { return HttpResponse.json({ data: [ { inventoryId: 'INV-001', warehouseId: 'WH-SEOUL', qtyOnHand: 1000 }, { inventoryId: 'INV-002', warehouseId: 'WH-BUSAN', qtyOnHand: 500 }, { inventoryId: 'INV-003', warehouseId: 'WH-DAEGU', qtyOnHand: 300 } ] }) }) ) const tempStore = new MockInventoryStore() await tempStore.fetchInventory() expect(tempStore.inventory).toHaveLength(3) const totalQty = tempStore.inventory.reduce((sum, inv) => sum + inv.qtyOnHand, 0) expect(totalQty).toBe(1800) }) }) })