fix(tests): fix failing tests and increase coverage
Backend: - Fix TestCreateCompany (added Phone, OperatingHours, Is24Hours) - Fix TestCreateProduct (added EANCode, Manufacturer, Category, etc) - Add TestCreateUser, TestListUsers, TestListOrders, TestGetShippingSettings - All 9 repository tests now pass Frontend: - Add shippingService.test.ts (4 tests) - Add ordersService.test.ts (5 tests) - Add format.test.ts (9 tests) - Total tests increased from 54 to 72
This commit is contained in:
parent
630bcc9da5
commit
f0d64d1801
4 changed files with 428 additions and 19 deletions
|
|
@ -28,18 +28,21 @@ func TestCreateCompany(t *testing.T) {
|
|||
defer repo.db.Close()
|
||||
|
||||
company := &domain.Company{
|
||||
ID: uuid.Must(uuid.NewV7()),
|
||||
CNPJ: "12345678901234",
|
||||
CorporateName: "Test Pharmacy",
|
||||
Category: "farmacia",
|
||||
LicenseNumber: "123",
|
||||
IsVerified: false,
|
||||
Latitude: -10.0,
|
||||
Longitude: -20.0,
|
||||
City: "Test City",
|
||||
State: "TS",
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
ID: uuid.Must(uuid.NewV7()),
|
||||
CNPJ: "12345678901234",
|
||||
CorporateName: "Test Pharmacy",
|
||||
Category: "farmacia",
|
||||
LicenseNumber: "123",
|
||||
IsVerified: false,
|
||||
Latitude: -10.0,
|
||||
Longitude: -20.0,
|
||||
City: "Test City",
|
||||
State: "TS",
|
||||
Phone: "(11) 99999-9999",
|
||||
OperatingHours: "08:00-18:00",
|
||||
Is24Hours: false,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
|
||||
query := `INSERT INTO companies`
|
||||
|
|
@ -55,6 +58,9 @@ func TestCreateCompany(t *testing.T) {
|
|||
company.Longitude,
|
||||
company.City,
|
||||
company.State,
|
||||
company.Phone,
|
||||
company.OperatingHours,
|
||||
company.Is24Hours,
|
||||
sqlmock.AnyArg(), // CreatedAt
|
||||
sqlmock.AnyArg(), // UpdatedAt
|
||||
).
|
||||
|
|
@ -97,13 +103,19 @@ func TestCreateProduct(t *testing.T) {
|
|||
defer repo.db.Close()
|
||||
|
||||
product := &domain.Product{
|
||||
ID: uuid.Must(uuid.NewV7()),
|
||||
SellerID: uuid.Must(uuid.NewV7()),
|
||||
Name: "Test Product",
|
||||
Description: "Desc",
|
||||
Batch: "B1",
|
||||
PriceCents: 1000,
|
||||
Stock: 10,
|
||||
ID: uuid.Must(uuid.NewV7()),
|
||||
SellerID: uuid.Must(uuid.NewV7()),
|
||||
EANCode: "7891234567890",
|
||||
Name: "Test Product",
|
||||
Description: "Desc",
|
||||
Manufacturer: "Test Manufacturer",
|
||||
Category: "medicamento",
|
||||
Subcategory: "analgésico",
|
||||
Batch: "B1",
|
||||
ExpiresAt: time.Now().AddDate(1, 0, 0),
|
||||
PriceCents: 1000,
|
||||
Stock: 10,
|
||||
Observations: "Test observations",
|
||||
}
|
||||
|
||||
query := `INSERT INTO products`
|
||||
|
|
@ -113,12 +125,17 @@ func TestCreateProduct(t *testing.T) {
|
|||
WithArgs(
|
||||
product.ID,
|
||||
product.SellerID,
|
||||
product.EANCode,
|
||||
product.Name,
|
||||
product.Description,
|
||||
product.Manufacturer,
|
||||
product.Category,
|
||||
product.Subcategory,
|
||||
product.Batch,
|
||||
product.ExpiresAt,
|
||||
product.PriceCents,
|
||||
product.Stock,
|
||||
product.Observations,
|
||||
).
|
||||
WillReturnRows(rows)
|
||||
|
||||
|
|
@ -141,3 +158,126 @@ func TestListProducts(t *testing.T) {
|
|||
assert.Equal(t, int64(1), count)
|
||||
assert.Len(t, list, 1)
|
||||
}
|
||||
|
||||
func TestCreateUser(t *testing.T) {
|
||||
repo, mock := newMockRepo(t)
|
||||
defer repo.db.Close()
|
||||
|
||||
user := &domain.User{
|
||||
ID: uuid.Must(uuid.NewV7()),
|
||||
CompanyID: uuid.Must(uuid.NewV7()),
|
||||
Role: "Colaborador",
|
||||
Name: "Test User",
|
||||
Username: "testuser",
|
||||
Email: "test@example.com",
|
||||
PasswordHash: "hashed_password",
|
||||
}
|
||||
|
||||
query := `INSERT INTO users`
|
||||
mock.ExpectExec(regexp.QuoteMeta(query)).
|
||||
WithArgs(
|
||||
user.ID,
|
||||
user.CompanyID,
|
||||
user.Role,
|
||||
user.Name,
|
||||
user.Username,
|
||||
user.Email,
|
||||
user.EmailVerified, // email_verified
|
||||
user.PasswordHash, // password_hash
|
||||
sqlmock.AnyArg(), // CreatedAt
|
||||
sqlmock.AnyArg(), // UpdatedAt
|
||||
).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
|
||||
err := repo.CreateUser(context.Background(), user)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestListUsers(t *testing.T) {
|
||||
repo, mock := newMockRepo(t)
|
||||
defer repo.db.Close()
|
||||
|
||||
companyID := uuid.Must(uuid.NewV7())
|
||||
userID := uuid.Must(uuid.NewV7())
|
||||
|
||||
rows := sqlmock.NewRows([]string{
|
||||
"id", "company_id", "role", "name", "username", "email",
|
||||
"email_verified", "password_hash", "created_at", "updated_at",
|
||||
}).AddRow(
|
||||
userID, companyID, "Owner", "Test", "test", "test@test.com",
|
||||
true, "hash", time.Now(), time.Now(),
|
||||
)
|
||||
|
||||
mock.ExpectQuery(`SELECT count\(\*\) FROM users`).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1))
|
||||
mock.ExpectQuery(`SELECT .* FROM users`).
|
||||
WithArgs(20, 0).
|
||||
WillReturnRows(rows)
|
||||
|
||||
list, count, err := repo.ListUsers(context.Background(), domain.UserFilter{Limit: 20})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(1), count)
|
||||
assert.Len(t, list, 1)
|
||||
}
|
||||
|
||||
func TestListOrders(t *testing.T) {
|
||||
repo, mock := newMockRepo(t)
|
||||
defer repo.db.Close()
|
||||
|
||||
orderID := uuid.Must(uuid.NewV7())
|
||||
buyerID := uuid.Must(uuid.NewV7())
|
||||
sellerID := uuid.Must(uuid.NewV7())
|
||||
|
||||
rows := sqlmock.NewRows([]string{
|
||||
"id", "buyer_id", "seller_id", "status", "total_cents", "payment_method",
|
||||
"shipping_recipient_name", "shipping_street", "shipping_number", "shipping_complement",
|
||||
"shipping_district", "shipping_city", "shipping_state", "shipping_zip_code",
|
||||
"shipping_country", "created_at", "updated_at",
|
||||
}).AddRow(
|
||||
orderID, buyerID, sellerID, "Pendente", 10000, "pix",
|
||||
"Test User", "Test Street", "123", "", "Centro", "City", "ST", "12345-678", "Brasil",
|
||||
time.Now(), time.Now(),
|
||||
)
|
||||
|
||||
mock.ExpectQuery(`SELECT count\(\*\) FROM orders`).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1))
|
||||
mock.ExpectQuery(`SELECT .* FROM orders`).
|
||||
WithArgs(20, 0).
|
||||
WillReturnRows(rows)
|
||||
|
||||
// Expect query for order items
|
||||
mock.ExpectQuery(`SELECT .* FROM order_items WHERE order_id`).
|
||||
WithArgs(orderID).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id", "order_id", "product_id", "quantity", "unit_cents", "batch", "expires_at"}))
|
||||
|
||||
list, count, err := repo.ListOrders(context.Background(), domain.OrderFilter{Limit: 20})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(1), count)
|
||||
assert.Len(t, list, 1)
|
||||
}
|
||||
|
||||
func TestGetShippingSettings(t *testing.T) {
|
||||
repo, mock := newMockRepo(t)
|
||||
defer repo.db.Close()
|
||||
|
||||
vendorID := uuid.Must(uuid.NewV7())
|
||||
|
||||
rows := sqlmock.NewRows([]string{
|
||||
"vendor_id", "active", "max_radius_km", "price_per_km_cents", "min_fee_cents",
|
||||
"free_shipping_threshold_cents", "pickup_active", "pickup_address", "pickup_hours",
|
||||
"latitude", "longitude", "created_at", "updated_at",
|
||||
}).AddRow(
|
||||
vendorID, true, 50.0, 150, 1000, nil, true, "Rua Test, 123", "08:00-18:00",
|
||||
-23.55, -46.63, time.Now(), time.Now(),
|
||||
)
|
||||
|
||||
mock.ExpectQuery(`SELECT \* FROM shipping_settings WHERE vendor_id`).
|
||||
WithArgs(vendorID).
|
||||
WillReturnRows(rows)
|
||||
|
||||
settings, err := repo.GetShippingSettings(context.Background(), vendorID)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, settings)
|
||||
assert.Equal(t, vendorID, settings.VendorID)
|
||||
assert.True(t, settings.Active)
|
||||
}
|
||||
|
|
|
|||
122
marketplace/src/services/ordersService.test.ts
Normal file
122
marketplace/src/services/ordersService.test.ts
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
||||
import { ordersService, CreateOrderRequest } from './ordersService'
|
||||
import { apiClient } from './apiClient'
|
||||
|
||||
// Mock apiClient
|
||||
vi.mock('./apiClient', () => ({
|
||||
apiClient: {
|
||||
get: vi.fn(),
|
||||
post: vi.fn()
|
||||
}
|
||||
}))
|
||||
|
||||
describe('ordersService', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
describe('listOrders', () => {
|
||||
it('should fetch orders list', async () => {
|
||||
const mockOrders = {
|
||||
orders: [
|
||||
{ id: 'order-1', buyer_id: 'buyer-1', seller_id: 'seller-1', status: 'Pendente', total_cents: 10000 },
|
||||
{ id: 'order-2', buyer_id: 'buyer-1', seller_id: 'seller-2', status: 'Pago', total_cents: 25000 }
|
||||
],
|
||||
total: 2,
|
||||
page: 1,
|
||||
page_size: 20
|
||||
}
|
||||
|
||||
vi.mocked(apiClient.get).mockResolvedValue(mockOrders)
|
||||
|
||||
const result = await ordersService.listOrders()
|
||||
|
||||
expect(apiClient.get).toHaveBeenCalledWith('/v1/orders')
|
||||
expect(result).toEqual(mockOrders)
|
||||
})
|
||||
|
||||
it('should handle empty orders list', async () => {
|
||||
const mockOrders = {
|
||||
orders: [],
|
||||
total: 0,
|
||||
page: 1,
|
||||
page_size: 20
|
||||
}
|
||||
|
||||
vi.mocked(apiClient.get).mockResolvedValue(mockOrders)
|
||||
|
||||
const result = await ordersService.listOrders()
|
||||
|
||||
expect(result).toEqual(mockOrders)
|
||||
})
|
||||
|
||||
it('should handle API error', async () => {
|
||||
vi.mocked(apiClient.get).mockRejectedValue(new Error('Internal Server Error'))
|
||||
|
||||
await expect(ordersService.listOrders())
|
||||
.rejects.toThrow('Internal Server Error')
|
||||
})
|
||||
})
|
||||
|
||||
describe('createOrder', () => {
|
||||
it('should create an order successfully', async () => {
|
||||
const orderData: CreateOrderRequest = {
|
||||
buyer_id: 'buyer-1',
|
||||
seller_id: 'seller-1',
|
||||
items: [
|
||||
{ product_id: 'prod-1', quantity: 2, unit_cents: 1500, batch: 'L001', expires_at: '2025-12-31' }
|
||||
],
|
||||
shipping: {
|
||||
recipient_name: 'Test User',
|
||||
street: 'Rua Test',
|
||||
number: '123',
|
||||
district: 'Centro',
|
||||
city: 'City',
|
||||
state: 'ST',
|
||||
zip_code: '12345-678',
|
||||
country: 'Brasil'
|
||||
},
|
||||
payment_method: 'pix'
|
||||
}
|
||||
|
||||
const mockOrder = {
|
||||
id: 'new-order-1',
|
||||
...orderData,
|
||||
status: 'Pendente',
|
||||
total_cents: 3000,
|
||||
created_at: new Date().toISOString()
|
||||
}
|
||||
|
||||
vi.mocked(apiClient.post).mockResolvedValue(mockOrder)
|
||||
|
||||
const result = await ordersService.createOrder(orderData)
|
||||
|
||||
expect(apiClient.post).toHaveBeenCalledWith('/v1/orders', orderData)
|
||||
expect(result).toEqual(mockOrder)
|
||||
})
|
||||
|
||||
it('should handle order creation failure', async () => {
|
||||
vi.mocked(apiClient.post).mockRejectedValue(new Error('Insufficient stock'))
|
||||
|
||||
const orderData: CreateOrderRequest = {
|
||||
buyer_id: 'buyer-1',
|
||||
seller_id: 'seller-1',
|
||||
items: [],
|
||||
shipping: {
|
||||
recipient_name: '',
|
||||
street: '',
|
||||
number: '',
|
||||
district: '',
|
||||
city: '',
|
||||
state: '',
|
||||
zip_code: '',
|
||||
country: ''
|
||||
},
|
||||
payment_method: 'pix'
|
||||
}
|
||||
|
||||
await expect(ordersService.createOrder(orderData))
|
||||
.rejects.toThrow('Insufficient stock')
|
||||
})
|
||||
})
|
||||
})
|
||||
96
marketplace/src/services/shippingService.test.ts
Normal file
96
marketplace/src/services/shippingService.test.ts
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
||||
import { shippingService } from './shippingService'
|
||||
import { apiClient } from './apiClient'
|
||||
import type { ShippingSettings } from '../types/shipping'
|
||||
|
||||
// Mock apiClient
|
||||
vi.mock('./apiClient', () => ({
|
||||
apiClient: {
|
||||
get: vi.fn(),
|
||||
post: vi.fn()
|
||||
}
|
||||
}))
|
||||
|
||||
describe('shippingService', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
describe('getSettings', () => {
|
||||
it('should fetch shipping settings for a vendor', async () => {
|
||||
const mockSettings: ShippingSettings = {
|
||||
vendor_id: 'vendor-123',
|
||||
active: true,
|
||||
max_radius_km: 50,
|
||||
price_per_km_cents: 150,
|
||||
min_fee_cents: 1000,
|
||||
pickup_active: true,
|
||||
pickup_address: 'Rua Test, 123',
|
||||
pickup_hours: '08:00-18:00',
|
||||
latitude: -23.55,
|
||||
longitude: -46.63
|
||||
}
|
||||
|
||||
vi.mocked(apiClient.get).mockResolvedValue(mockSettings)
|
||||
|
||||
const result = await shippingService.getSettings('vendor-123')
|
||||
|
||||
expect(apiClient.get).toHaveBeenCalledWith('/v1/shipping/settings/vendor-123')
|
||||
expect(result).toEqual(mockSettings)
|
||||
expect(result.active).toBe(true)
|
||||
expect(result.pickup_active).toBe(true)
|
||||
})
|
||||
|
||||
it('should handle vendor not found', async () => {
|
||||
vi.mocked(apiClient.get).mockRejectedValue(new Error('Vendor not found'))
|
||||
|
||||
await expect(shippingService.getSettings('invalid-vendor'))
|
||||
.rejects.toThrow('Vendor not found')
|
||||
})
|
||||
})
|
||||
|
||||
describe('calculate', () => {
|
||||
it('should calculate shipping cost', async () => {
|
||||
const mockCalculation = {
|
||||
options: [
|
||||
{
|
||||
seller_id: 'seller-1',
|
||||
delivery_fee_cents: 2500,
|
||||
distance_km: 15.5,
|
||||
estimated_days: 2,
|
||||
pickup_available: true,
|
||||
pickup_address: 'Rua Test, 123',
|
||||
pickup_hours: '08:00-18:00'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
vi.mocked(apiClient.post).mockResolvedValue(mockCalculation)
|
||||
|
||||
const result = await shippingService.calculate({
|
||||
buyer_id: 'buyer-123',
|
||||
order_total_cents: 15000,
|
||||
items: [
|
||||
{ seller_id: 'seller-1', product_id: 'prod-1', quantity: 2, price_cents: 7500 }
|
||||
]
|
||||
})
|
||||
|
||||
expect(apiClient.post).toHaveBeenCalledWith('/v1/shipping/calculate', expect.objectContaining({
|
||||
buyer_id: 'buyer-123',
|
||||
order_total_cents: 15000
|
||||
}))
|
||||
expect(result.options).toHaveLength(1)
|
||||
expect(result.options[0].delivery_fee_cents).toBe(2500)
|
||||
})
|
||||
|
||||
it('should handle API error', async () => {
|
||||
vi.mocked(apiClient.post).mockRejectedValue(new Error('Server error'))
|
||||
|
||||
await expect(shippingService.calculate({
|
||||
buyer_id: 'buyer-123',
|
||||
order_total_cents: 15000,
|
||||
items: []
|
||||
})).rejects.toThrow('Server error')
|
||||
})
|
||||
})
|
||||
})
|
||||
51
marketplace/src/utils/format.test.ts
Normal file
51
marketplace/src/utils/format.test.ts
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
import { describe, it, expect } from 'vitest'
|
||||
import { formatCents, formatCurrency } from './format'
|
||||
|
||||
describe('format utilities', () => {
|
||||
describe('formatCurrency', () => {
|
||||
it('should format number to comma-separated string', () => {
|
||||
expect(formatCurrency(10.00)).toBe('10,00')
|
||||
expect(formatCurrency(15.99)).toBe('15,99')
|
||||
expect(formatCurrency(1000.50)).toBe('1000,50')
|
||||
})
|
||||
|
||||
it('should handle zero', () => {
|
||||
expect(formatCurrency(0)).toBe('0,00')
|
||||
})
|
||||
|
||||
it('should handle undefined/null', () => {
|
||||
expect(formatCurrency(undefined)).toBe('0,00')
|
||||
expect(formatCurrency(null)).toBe('0,00')
|
||||
})
|
||||
|
||||
it('should handle NaN', () => {
|
||||
expect(formatCurrency(NaN)).toBe('0,00')
|
||||
})
|
||||
})
|
||||
|
||||
describe('formatCents', () => {
|
||||
it('should format cents to BRL currency', () => {
|
||||
expect(formatCents(1000)).toBe('R$ 10,00')
|
||||
expect(formatCents(1599)).toBe('R$ 15,99')
|
||||
expect(formatCents(100000)).toBe('R$ 1000,00')
|
||||
})
|
||||
|
||||
it('should handle zero', () => {
|
||||
expect(formatCents(0)).toBe('R$ 0,00')
|
||||
})
|
||||
|
||||
it('should handle undefined/null', () => {
|
||||
expect(formatCents(undefined)).toBe('R$ 0,00')
|
||||
expect(formatCents(null)).toBe('R$ 0,00')
|
||||
})
|
||||
|
||||
it('should handle NaN', () => {
|
||||
expect(formatCents(NaN)).toBe('R$ 0,00')
|
||||
})
|
||||
|
||||
it('should handle small amounts', () => {
|
||||
expect(formatCents(50)).toBe('R$ 0,50')
|
||||
expect(formatCents(1)).toBe('R$ 0,01')
|
||||
})
|
||||
})
|
||||
})
|
||||
Loading…
Reference in a new issue