veza/apps/web/src/services/marketplaceService.test.ts
senke 5b0a333bad [FE-TEST-001] fe-test: Add unit tests for API services
- Created comprehensive unit tests for marketplaceService (11 tests)
- Created comprehensive unit tests for profileService (12 tests)
- Created comprehensive unit tests for avatarService (9 tests)
- Created comprehensive unit tests for 2fa-service (8 tests)
- All 40 tests pass successfully
- Tests cover success cases, error handling, edge cases, and validation scenarios

Files modified:
- apps/web/src/services/marketplaceService.test.ts (new)
- apps/web/src/features/profile/services/profileService.test.ts (new)
- apps/web/src/features/profile/services/avatarService.test.ts (new)
- apps/web/src/services/2fa-service.test.ts (new)
- VEZA_COMPLETE_MVP_TODOLIST.json
2025-12-25 15:55:53 +01:00

274 lines
7.4 KiB
TypeScript

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { AxiosError } from 'axios';
import { marketplaceService } from './marketplaceService';
import { apiClient } from './api/client';
import type { Product, Order, ProductStatus } from '../types/marketplace';
// Mock apiClient
vi.mock('./api/client', () => ({
apiClient: {
get: vi.fn(),
post: vi.fn(),
},
}));
const mockedApiClient = apiClient as {
get: ReturnType<typeof vi.fn>;
post: ReturnType<typeof vi.fn>;
};
describe('marketplaceService', () => {
beforeEach(() => {
vi.clearAllMocks();
});
describe('fetchProducts', () => {
it('should fetch products without filters', async () => {
const mockProducts: Product[] = [
{
id: '1',
name: 'Test Product',
description: 'Test Description',
price: 10.99,
status: 'active' as ProductStatus,
seller_id: 'seller-1',
created_at: '2024-01-01T00:00:00Z',
},
];
mockedApiClient.get.mockResolvedValue({
data: {
products: mockProducts,
total: 1,
page: 1,
limit: 20,
total_pages: 1,
},
});
const result = await marketplaceService.fetchProducts();
expect(result.products).toEqual(mockProducts);
expect(result.total).toBe(1);
expect(mockedApiClient.get).toHaveBeenCalledWith('/marketplace/products');
});
it('should fetch products with filters', async () => {
const mockProducts: Product[] = [];
mockedApiClient.get.mockResolvedValue({
data: {
products: mockProducts,
total: 0,
page: 1,
limit: 20,
total_pages: 0,
},
});
await marketplaceService.fetchProducts(
{
status: 'active' as ProductStatus,
seller_id: 'seller-1',
min_price: 10,
max_price: 100,
search: 'test',
},
{ page: 1, limit: 20 },
);
expect(mockedApiClient.get).toHaveBeenCalledWith(
'/marketplace/products?status=active&seller_id=seller-1&min_price=10&max_price=100&search=test&page=1&limit=20',
);
});
it('should handle array response format (backward compatibility)', async () => {
const mockProducts: Product[] = [
{
id: '1',
name: 'Test Product',
description: 'Test Description',
price: 10.99,
status: 'active' as ProductStatus,
seller_id: 'seller-1',
created_at: '2024-01-01T00:00:00Z',
},
];
mockedApiClient.get.mockResolvedValue({
data: mockProducts,
});
const result = await marketplaceService.fetchProducts();
expect(result.products).toEqual(mockProducts);
expect(result.total).toBe(1);
expect(result.page).toBe(1);
});
it('should throw error on fetch failure', async () => {
const mockError = new AxiosError('Fetch failed');
mockError.response = {
status: 500,
data: { error: 'Internal server error' },
} as any;
mockedApiClient.get.mockRejectedValue(mockError);
await expect(marketplaceService.fetchProducts()).rejects.toThrow();
});
});
describe('createProduct', () => {
it('should create a product successfully', async () => {
const mockProduct: Product = {
id: '1',
name: 'New Product',
description: 'New Description',
price: 19.99,
status: 'active' as ProductStatus,
seller_id: 'seller-1',
created_at: '2024-01-01T00:00:00Z',
};
mockedApiClient.post.mockResolvedValue({
data: mockProduct,
});
const result = await marketplaceService.createProduct({
name: 'New Product',
description: 'New Description',
price: 19.99,
product_type: 'track',
});
expect(result).toEqual(mockProduct);
expect(mockedApiClient.post).toHaveBeenCalledWith(
'/marketplace/products',
{
name: 'New Product',
description: 'New Description',
price: 19.99,
product_type: 'track',
},
);
});
it('should throw error on creation failure', async () => {
const mockError = new AxiosError('Creation failed');
mockError.response = {
status: 403,
data: { error: 'Permission denied' },
} as any;
mockedApiClient.post.mockRejectedValue(mockError);
await expect(
marketplaceService.createProduct({
name: 'New Product',
description: 'New Description',
price: 19.99,
product_type: 'track',
}),
).rejects.toThrow();
});
});
describe('createOrder', () => {
it('should create an order successfully', async () => {
const mockOrder: Order = {
id: 'order-1',
user_id: 'user-1',
items: [{ product_id: 'product-1', quantity: 1 }],
total: 19.99,
status: 'pending',
created_at: '2024-01-01T00:00:00Z',
};
mockedApiClient.post.mockResolvedValue({
data: mockOrder,
});
const result = await marketplaceService.createOrder([
{ product_id: 'product-1' },
]);
expect(result).toEqual(mockOrder);
expect(mockedApiClient.post).toHaveBeenCalledWith(
'/marketplace/orders',
{ items: [{ product_id: 'product-1' }] },
);
});
it('should throw error on order creation failure', async () => {
const mockError = new AxiosError('Order creation failed');
mockError.response = {
status: 400,
data: { error: 'Invalid product' },
} as any;
mockedApiClient.post.mockRejectedValue(mockError);
await expect(
marketplaceService.createOrder([{ product_id: 'invalid-product' }]),
).rejects.toThrow();
});
});
describe('purchaseProduct', () => {
it('should purchase a single product successfully', async () => {
const mockOrder: Order = {
id: 'order-1',
user_id: 'user-1',
items: [{ product_id: 'product-1', quantity: 1 }],
total: 19.99,
status: 'pending',
created_at: '2024-01-01T00:00:00Z',
};
mockedApiClient.post.mockResolvedValue({
data: mockOrder,
});
const result = await marketplaceService.purchaseProduct('product-1');
expect(result).toEqual(mockOrder);
expect(mockedApiClient.post).toHaveBeenCalledWith(
'/marketplace/orders',
{ items: [{ product_id: 'product-1' }] },
);
});
});
describe('getDownloadLink', () => {
it('should get download link successfully', async () => {
const mockResponse = { url: 'https://example.com/download/product-1' };
mockedApiClient.get.mockResolvedValue({
data: mockResponse,
});
const result = await marketplaceService.getDownloadLink('product-1');
expect(result).toBe('https://example.com/download/product-1');
expect(mockedApiClient.get).toHaveBeenCalledWith(
'/marketplace/download/product-1',
);
});
it('should throw error on download link failure', async () => {
const mockError = new AxiosError('Download link failed');
mockError.response = {
status: 403,
data: { error: 'No license found' },
} as any;
mockedApiClient.get.mockRejectedValue(mockError);
await expect(
marketplaceService.getDownloadLink('product-1'),
).rejects.toThrow();
});
});
});