Files
QuantEngineByItz/oms-wms-erp/tests/integration/products.spec.ts
T
kjh2064 b34b0dd7d6
Validators (Pushes and Pull Requests) / UI & Storage Validation (pull_request) Failing after 12s
Validators (Pushes and Pull Requests) / Database & Schema Validation (pull_request) Successful in 13s
Validators (Pushes and Pull Requests) / Core Validators & Database Setup (pull_request) Failing after 28s
Validators (Pushes and Pull Requests) / WBS & Audit Validations (pull_request) Has been skipped
Validators (Pushes and Pull Requests) / .NET Contracts (pull_request) Has been skipped
Validators (Pushes and Pull Requests) / Calibration & Performance (pull_request) Has been skipped
Validators (Pushes and Pull Requests) / Operational Report & Decision Packet (pull_request) Has been skipped
Validators (Pushes and Pull Requests) / CI Workflow Lint (pull_request) Failing after 10s
Validators (Pushes and Pull Requests) / Security & Secrets (pull_request) Successful in 12s
Validators (Pushes and Pull Requests) / Notify PR Results (pull_request) Successful in 2s
Frontend CI Pipeline / ci-frontend-8-steps (pull_request) Failing after 2m50s
Add OMS WMS ERP platform
2026-07-27 00:45:39 +09:00

298 lines
8.0 KiB
TypeScript

/**
* Integration Tests: Products (ERP) Store
* Tests product catalog management with mocked API
*
* Run: npm run test:integration
*/
import { beforeEach, describe, expect, it } from 'vitest'
import { server } from '@/tests/mocks/server'
import { http, HttpResponse } from 'msw'
/**
* Mock Products Store (placeholder until actual store is created)
*/
class MockProductsStore {
products: any[] = []
loading = false
error: string | null = null
filters: Record<string, any> = {}
async fetchProducts() {
this.loading = true
try {
const response = await fetch(
`${process.env.VITE_API_BASE_URL || 'http://localhost:3000/api'}/products`
)
const data = await response.json()
this.products = data.data || []
} catch (err) {
this.error = (err as Error).message
} finally {
this.loading = false
}
}
async createProduct(payload: any) {
this.loading = true
try {
const response = await fetch(
`${process.env.VITE_API_BASE_URL || 'http://localhost:3000/api'}/products`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
}
)
if (!response.ok) throw new Error('Creation failed')
const data = await response.json()
this.products.push(data)
return data
} catch (err) {
this.error = (err as Error).message
throw err
} finally {
this.loading = false
}
}
async getProduct(productId: string) {
this.loading = true
try {
const response = await fetch(
`${process.env.VITE_API_BASE_URL || 'http://localhost:3000/api'}/products/${productId}`
)
if (!response.ok) throw new Error('Not found')
const data = await response.json()
return data
} catch (err) {
this.error = (err as Error).message
throw err
} finally {
this.loading = false
}
}
setFilter(key: string, value: any) {
this.filters[key] = value
}
clearFilters() {
this.filters = {}
}
}
describe('Products (ERP) Store Integration', () => {
let store: MockProductsStore
beforeEach(() => {
store = new MockProductsStore()
})
describe('fetchProducts', () => {
it('loads products from ERP API', async () => {
await store.fetchProducts()
expect(store.products).toHaveLength(1)
expect(store.products[0].productId).toBe('PROD-001')
expect(store.products[0].productName).toBe('Product A')
expect(store.loading).toBe(false)
})
it('includes product metadata', async () => {
await store.fetchProducts()
const product = store.products[0]
expect(product).toHaveProperty('sku')
expect(product).toHaveProperty('categoryId')
expect(product).toHaveProperty('status')
expect(product).toHaveProperty('createdAt')
})
it('handles empty product list', async () => {
server.use(
http.get('*/api/products', () => {
return HttpResponse.json({ data: [] })
})
)
await store.fetchProducts()
expect(store.products).toHaveLength(0)
expect(store.error).toBeNull()
})
})
describe('createProduct', () => {
it('creates new product with required fields', async () => {
const payload = {
sku: 'SKU-NEW',
productName: 'New Product',
categoryId: 'CAT-002'
}
const created = await store.createProduct(payload)
expect(created.productId).toBe('PROD-NEW')
expect(created.sku).toBe('SKU-NEW')
expect(created.productName).toBe('New Product')
expect(created.status).toBe('ACTIVE')
})
it('adds created product to store', async () => {
const initialCount = store.products.length
await store.createProduct({
sku: 'SKU-NEW-2',
productName: 'Another Product',
categoryId: 'CAT-003'
})
expect(store.products.length).toBeGreaterThan(initialCount)
})
it('validates required fields', async () => {
server.use(
http.post('*/api/products', () => {
return HttpResponse.json(
{ message: 'Product name is required' },
{ status: 400 }
)
})
)
await expect(
store.createProduct({ sku: 'SKU-INVALID' })
).rejects.toThrow()
})
it('ensures unique SKU', async () => {
server.use(
http.post('*/api/products', () => {
return HttpResponse.json(
{ message: 'SKU already exists' },
{ status: 409 }
)
})
)
await expect(
store.createProduct({ sku: 'SKU-001', productName: 'Duplicate' })
).rejects.toThrow()
})
})
describe('getProduct', () => {
it('fetches single product by ID', async () => {
const product = await store.getProduct('PROD-001')
expect(product.productId).toBe('PROD-001')
expect(product.productName).toBe('Product Sample')
})
it('handles product not found', async () => {
server.use(
http.get('*/api/products/:productId', () => {
return HttpResponse.json(
{ message: 'Product not found' },
{ status: 404 }
)
})
)
await expect(store.getProduct('PROD-INVALID')).rejects.toThrow()
expect(store.error).not.toBeNull()
})
})
describe('product filtering', () => {
beforeEach(async () => {
server.use(
http.get('*/api/products', () => {
return HttpResponse.json({
data: [
{ productId: 'PROD-001', categoryId: 'CAT-001', status: 'ACTIVE' },
{ productId: 'PROD-002', categoryId: 'CAT-001', status: 'ACTIVE' },
{ productId: 'PROD-003', categoryId: 'CAT-002', status: 'INACTIVE' },
{ productId: 'PROD-004', categoryId: 'CAT-002', status: 'ACTIVE' }
]
})
})
)
await store.fetchProducts()
})
it('filters by category', () => {
store.setFilter('categoryId', 'CAT-001')
const filtered = store.products.filter((p) => p.categoryId === store.filters.categoryId)
expect(filtered).toHaveLength(2)
})
it('filters by status', () => {
store.setFilter('status', 'ACTIVE')
const filtered = store.products.filter((p) => p.status === store.filters.status)
expect(filtered.length).toBeGreaterThan(0)
})
it('combines multiple filters', () => {
store.setFilter('categoryId', 'CAT-001')
store.setFilter('status', 'ACTIVE')
const filtered = store.products.filter(
(p) =>
p.categoryId === store.filters.categoryId &&
p.status === store.filters.status
)
expect(filtered).toHaveLength(2)
})
it('clears all filters', () => {
store.setFilter('categoryId', 'CAT-001')
store.setFilter('status', 'ACTIVE')
store.clearFilters()
expect(Object.keys(store.filters)).toHaveLength(0)
})
})
describe('bulk operations', () => {
it('handles bulk product creation', async () => {
server.use(
http.post('*/api/products/bulk', async ({ request }) => {
const body = await request.json() as any
return HttpResponse.json(
{
created: body.items.length,
items: body.items.map((item: any, idx: number) => ({
productId: `PROD-BULK-${idx + 1}`,
...item
}))
},
{ status: 201 }
)
})
)
const items = [
{ sku: 'SKU-BULK-1', productName: 'Bulk Product 1' },
{ sku: 'SKU-BULK-2', productName: 'Bulk Product 2' }
]
const response = await fetch(
`${process.env.VITE_API_BASE_URL || 'http://localhost:3000/api'}/products/bulk`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ items })
}
)
const data = await response.json()
expect(data.created).toBe(2)
expect(data.items).toHaveLength(2)
})
})
})