UNPKG

prodobit

Version:

Open-core business application development platform

587 lines (495 loc) 15.4 kB
import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest' import { ProdobitClient } from '../client' import type { ProdobitClientConfig } from '../types' import { ProdobitError } from '../types' // Mock fetch globally global.fetch = vi.fn() describe('ProdobitClient - Items Management', () => { let client: ProdobitClient let mockConfig: ProdobitClientConfig beforeEach(() => { vi.clearAllMocks() mockConfig = { baseUrl: 'https://api.prodobit.com', timeout: 5000, autoRefresh: true } client = new ProdobitClient(mockConfig) // Set up authentication const mockTokenInfo = { accessToken: 'access-token-123', expiresAt: new Date(Date.now() + 3600000), csrfToken: 'csrf-token-123', tenantId: '123e4567-e89b-12d3-a456-426614174000' } client.setTokenInfo(mockTokenInfo) }) afterEach(() => { vi.restoreAllMocks() }) describe('getItems', () => { it('should get items successfully without filters', async () => { const mockResponse = { success: true, data: [ { id: 'item-1', name: 'Product 1', code: 'PROD-001', itemType: 'product', tenantId: '123e4567-e89b-12d3-a456-426614174000' }, { id: 'item-2', name: 'Service 1', code: 'SERV-001', itemType: 'service', tenantId: '123e4567-e89b-12d3-a456-426614174000' } ] } ;(global.fetch as any).mockResolvedValueOnce({ ok: true, json: () => Promise.resolve(mockResponse) }) const result = await client.getItems() expect(result).toEqual(mockResponse) expect(global.fetch).toHaveBeenCalledWith( 'https://api.prodobit.com/api/v1/items', expect.objectContaining({ method: 'GET', headers: expect.objectContaining({ 'Authorization': 'Bearer access-token-123' }) }) ) }) it('should get items with filters and pagination', async () => { const mockResponse = { success: true, data: [ { id: 'item-1', name: 'Product 1', itemType: 'product' } ], pagination: { page: 1, limit: 10, total: 1 } } ;(global.fetch as any).mockResolvedValueOnce({ ok: true, json: () => Promise.resolve(mockResponse) }) const result = await client.getItems({ type: 'product', status: 'active', page: 1, limit: 10 }) expect(result).toEqual(mockResponse) expect(global.fetch).toHaveBeenCalledWith( 'https://api.prodobit.com/api/v1/items?type=product&status=active&page=1&limit=10', expect.objectContaining({ method: 'GET' }) ) }) }) describe('getItem', () => { it('should get item by ID successfully', async () => { const mockResponse = { success: true, data: { id: 'item-123', name: 'Test Product', code: 'TEST-001', itemType: 'product', description: 'A test product' } } ;(global.fetch as any).mockResolvedValueOnce({ ok: true, json: () => Promise.resolve(mockResponse) }) const result = await client.getItem('item-123') expect(result).toEqual(mockResponse) expect(global.fetch).toHaveBeenCalledWith( 'https://api.prodobit.com/api/v1/items/item-123', expect.objectContaining({ method: 'GET' }) ) }) it('should handle item not found', async () => { ;(global.fetch as any).mockResolvedValueOnce({ ok: false, status: 404, json: () => Promise.resolve({ error: { message: 'Item not found' } }) }) await expect(client.getItem('nonexistent-item')).rejects.toThrow(ProdobitError) }) }) describe('createItem', () => { it('should create item successfully', async () => { const itemData = { name: 'New Product', code: 'NEW-001', itemType: 'product' as const, description: 'A new product', isInventoryItem: true, isStockItem: true } const mockResponse = { success: true, data: { id: 'item-new', ...itemData, tenantId: '123e4567-e89b-12d3-a456-426614174000', createdAt: '2024-01-01T00:00:00Z' } } ;(global.fetch as any).mockResolvedValueOnce({ ok: true, json: () => Promise.resolve(mockResponse) }) const result = await client.createItem(itemData) expect(result).toEqual(mockResponse) expect(global.fetch).toHaveBeenCalledWith( 'https://api.prodobit.com/api/v1/items', expect.objectContaining({ method: 'POST', body: JSON.stringify(itemData) }) ) }) it('should handle validation errors', async () => { const mockErrorResponse = { error: { code: 'VALIDATION_ERROR', message: 'Invalid item data', details: { name: 'Name is required' } } } ;(global.fetch as any).mockResolvedValueOnce({ ok: false, status: 422, json: () => Promise.resolve(mockErrorResponse) }) await expect(client.createItem({ name: '', itemType: 'product' as const })).rejects.toThrow(ProdobitError) }) }) describe('specialized create methods', () => { it('should create product', async () => { const productData = { name: 'New Product', code: 'PROD-001', itemType: 'product' as const } const mockResponse = { success: true, data: { id: 'product-1', ...productData } } ;(global.fetch as any).mockResolvedValueOnce({ ok: true, json: () => Promise.resolve(mockResponse) }) const result = await client.createProduct(productData) expect(result).toEqual(mockResponse) expect(global.fetch).toHaveBeenCalledWith( 'https://api.prodobit.com/api/v1/items/products', expect.objectContaining({ method: 'POST' }) ) }) it('should create service', async () => { const serviceData = { name: 'Consulting Service', code: 'SERV-001', itemType: 'service' as const } const mockResponse = { success: true, data: { id: 'service-1', ...serviceData } } ;(global.fetch as any).mockResolvedValueOnce({ ok: true, json: () => Promise.resolve(mockResponse) }) const result = await client.createService(serviceData) expect(result).toEqual(mockResponse) expect(global.fetch).toHaveBeenCalledWith( 'https://api.prodobit.com/api/v1/items/services', expect.objectContaining({ method: 'POST' }) ) }) it('should create raw material', async () => { const rawMaterialData = { name: 'Steel Sheet', code: 'RM-001', itemType: 'raw_material' as const } const mockResponse = { success: true, data: { id: 'raw-material-1', ...rawMaterialData } } ;(global.fetch as any).mockResolvedValueOnce({ ok: true, json: () => Promise.resolve(mockResponse) }) const result = await client.createRawMaterial(rawMaterialData) expect(result).toEqual(mockResponse) expect(global.fetch).toHaveBeenCalledWith( 'https://api.prodobit.com/api/v1/items/raw-materials', expect.objectContaining({ method: 'POST' }) ) }) it('should create component', async () => { const componentData = { name: 'Screw M6', code: 'COMP-001', itemType: 'component' as const } const mockResponse = { success: true, data: { id: 'component-1', ...componentData } } ;(global.fetch as any).mockResolvedValueOnce({ ok: true, json: () => Promise.resolve(mockResponse) }) const result = await client.createComponent(componentData) expect(result).toEqual(mockResponse) expect(global.fetch).toHaveBeenCalledWith( 'https://api.prodobit.com/api/v1/items/components', expect.objectContaining({ method: 'POST' }) ) }) }) describe('get specialized items', () => { it('should get products', async () => { const mockResponse = { success: true, data: [ { id: 'prod-1', name: 'Product 1', itemType: 'product' }, { id: 'prod-2', name: 'Product 2', itemType: 'product' } ] } ;(global.fetch as any).mockResolvedValueOnce({ ok: true, json: () => Promise.resolve(mockResponse) }) const result = await client.getProducts() expect(result).toEqual(mockResponse) expect(global.fetch).toHaveBeenCalledWith( 'https://api.prodobit.com/api/v1/items/products', expect.objectContaining({ method: 'GET' }) ) }) it('should get services', async () => { const mockResponse = { success: true, data: [ { id: 'serv-1', name: 'Service 1', itemType: 'service' } ] } ;(global.fetch as any).mockResolvedValueOnce({ ok: true, json: () => Promise.resolve(mockResponse) }) const result = await client.getServices() expect(result).toEqual(mockResponse) }) it('should get raw materials', async () => { const mockResponse = { success: true, data: [ { id: 'rm-1', name: 'Raw Material 1', itemType: 'raw_material' } ] } ;(global.fetch as any).mockResolvedValueOnce({ ok: true, json: () => Promise.resolve(mockResponse) }) const result = await client.getRawMaterials() expect(result).toEqual(mockResponse) }) it('should get components', async () => { const mockResponse = { success: true, data: [ { id: 'comp-1', name: 'Component 1', itemType: 'component' } ] } ;(global.fetch as any).mockResolvedValueOnce({ ok: true, json: () => Promise.resolve(mockResponse) }) const result = await client.getComponents() expect(result).toEqual(mockResponse) }) }) describe('searchItems', () => { it('should search items successfully', async () => { const mockResponse = { success: true, data: [ { id: 'item-1', name: 'Computer Laptop', code: 'COMP-001' }, { id: 'item-2', name: 'Desktop Computer', code: 'COMP-002' } ] } ;(global.fetch as any).mockResolvedValueOnce({ ok: true, json: () => Promise.resolve(mockResponse) }) const result = await client.searchItems('computer') expect(result).toEqual(mockResponse) expect(global.fetch).toHaveBeenCalledWith( 'https://api.prodobit.com/api/v1/items/search?q=computer', expect.objectContaining({ method: 'GET' }) ) }) it('should search items with filters', async () => { const mockResponse = { success: true, data: [ { id: 'item-1', name: 'Computer Laptop', itemType: 'product' } ] } ;(global.fetch as any).mockResolvedValueOnce({ ok: true, json: () => Promise.resolve(mockResponse) }) const result = await client.searchItems('computer', { itemType: 'product' }) expect(result).toEqual(mockResponse) expect(global.fetch).toHaveBeenCalledWith( 'https://api.prodobit.com/api/v1/items/search?q=computer&itemType=product', expect.objectContaining({ method: 'GET' }) ) }) }) describe('deleteItem', () => { it('should delete item successfully', async () => { const mockResponse = { success: true, message: 'Item deleted successfully' } ;(global.fetch as any).mockResolvedValueOnce({ ok: true, json: () => Promise.resolve(mockResponse) }) const result = await client.deleteItem('item-123') expect(result).toEqual(mockResponse) expect(global.fetch).toHaveBeenCalledWith( 'https://api.prodobit.com/api/v1/items/item-123', expect.objectContaining({ method: 'DELETE' }) ) }) it('should handle delete item not found', async () => { ;(global.fetch as any).mockResolvedValueOnce({ ok: false, status: 404, json: () => Promise.resolve({ error: { message: 'Item not found' } }) }) await expect(client.deleteItem('nonexistent')).rejects.toThrow(ProdobitError) }) }) describe('item categories', () => { it('should get item categories', async () => { const mockResponse = { success: true, data: [ { id: 'cat-1', name: 'Electronics', itemType: 'product' }, { id: 'cat-2', name: 'Office Supplies', itemType: 'product' } ] } ;(global.fetch as any).mockResolvedValueOnce({ ok: true, json: () => Promise.resolve(mockResponse) }) const result = await client.getItemCategories() expect(result).toEqual(mockResponse) expect(global.fetch).toHaveBeenCalledWith( 'https://api.prodobit.com/api/v1/items/categories', expect.objectContaining({ method: 'GET' }) ) }) it('should get item categories by item type', async () => { const mockResponse = { success: true, data: [ { id: 'cat-1', name: 'Electronics', itemType: 'product' } ] } ;(global.fetch as any).mockResolvedValueOnce({ ok: true, json: () => Promise.resolve(mockResponse) }) const result = await client.getItemCategories('product') expect(result).toEqual(mockResponse) expect(global.fetch).toHaveBeenCalledWith( 'https://api.prodobit.com/api/v1/items/categories?itemType=product', expect.objectContaining({ method: 'GET' }) ) }) it('should create item category', async () => { const categoryData = { name: 'New Category', itemType: 'product' as const, description: 'A new category for products' } const mockResponse = { success: true, data: { id: 'cat-new', ...categoryData, tenantId: '123e4567-e89b-12d3-a456-426614174000' } } ;(global.fetch as any).mockResolvedValueOnce({ ok: true, json: () => Promise.resolve(mockResponse) }) const result = await client.createItemCategory(categoryData) expect(result).toEqual(mockResponse) expect(global.fetch).toHaveBeenCalledWith( 'https://api.prodobit.com/api/v1/items/categories', expect.objectContaining({ method: 'POST', body: JSON.stringify(categoryData) }) ) }) }) })