fix(marketplace): fix duplicate /api in URLs and add adminService tests

- Fix adminService URLs from /api/v1 to /v1 (base URL already includes /api)
- Add adminService.test.ts with 17 unit tests for all CRUD operations
- Update productService.test.ts and auth.test.ts for new apiClient format
- All 31 frontend tests passing
This commit is contained in:
Tiago Yamamoto 2025-12-22 08:04:27 -03:00
parent 460303e90e
commit 00685f7b26
4 changed files with 240 additions and 31 deletions

View file

@ -0,0 +1,208 @@
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { adminService } from './adminService'
import { apiClient } from './apiClient'
// Mock apiClient
vi.mock('./apiClient', () => ({
apiClient: {
get: vi.fn(),
post: vi.fn(),
put: vi.fn(),
patch: vi.fn(),
delete: vi.fn(),
}
}))
describe('adminService', () => {
beforeEach(() => {
vi.clearAllMocks()
})
describe('Users', () => {
it('listUsers should call correct endpoint with pagination', async () => {
const mockResponse = { users: [], total: 0, page: 1, page_size: 10 }
vi.mocked(apiClient.get).mockResolvedValue(mockResponse)
const result = await adminService.listUsers(1, 10)
expect(apiClient.get).toHaveBeenCalledWith('/v1/users?page=1&page_size=10')
expect(result).toEqual(mockResponse)
})
it('getUser should call correct endpoint with id', async () => {
const mockUser = { id: 'abc123', name: 'Test User' }
vi.mocked(apiClient.get).mockResolvedValue(mockUser)
const result = await adminService.getUser('abc123')
expect(apiClient.get).toHaveBeenCalledWith('/v1/users/abc123')
expect(result).toEqual(mockUser)
})
it('createUser should POST user data', async () => {
const userData = {
company_id: 'comp1',
role: 'Colaborador',
name: 'New User',
username: 'newuser',
email: 'new@test.com',
password: '123456'
}
const mockResponse = { id: 'new123', ...userData }
vi.mocked(apiClient.post).mockResolvedValue(mockResponse)
const result = await adminService.createUser(userData)
expect(apiClient.post).toHaveBeenCalledWith('/v1/users', userData)
expect(result).toEqual(mockResponse)
})
it('updateUser should PUT user data with id', async () => {
const updateData = { name: 'Updated Name' }
const mockResponse = { id: 'abc123', name: 'Updated Name' }
vi.mocked(apiClient.put).mockResolvedValue(mockResponse)
const result = await adminService.updateUser('abc123', updateData)
expect(apiClient.put).toHaveBeenCalledWith('/v1/users/abc123', updateData)
expect(result).toEqual(mockResponse)
})
it('deleteUser should DELETE user by id', async () => {
vi.mocked(apiClient.delete).mockResolvedValue({})
await adminService.deleteUser('abc123')
expect(apiClient.delete).toHaveBeenCalledWith('/v1/users/abc123')
})
})
describe('Companies', () => {
it('listCompanies should call correct endpoint', async () => {
const mockResponse = { tenants: [], total: 0, page: 1, page_size: 20 }
vi.mocked(apiClient.get).mockResolvedValue(mockResponse)
const result = await adminService.listCompanies(1, 20)
expect(apiClient.get).toHaveBeenCalledWith('/v1/companies?page=1&page_size=20')
expect(result).toEqual(mockResponse)
})
it('createCompany should POST company data', async () => {
const companyData = {
cnpj: '12345678000100',
corporate_name: 'Test Company',
category: 'farmacia',
license_number: 'LIC123',
latitude: -16.32,
longitude: -48.95,
city: 'Anápolis',
state: 'GO'
}
vi.mocked(apiClient.post).mockResolvedValue({ id: 'comp1', ...companyData })
await adminService.createCompany(companyData)
expect(apiClient.post).toHaveBeenCalledWith('/v1/companies', companyData)
})
it('updateCompany should PATCH company data', async () => {
const updateData = { corporate_name: 'Updated Name' }
vi.mocked(apiClient.patch).mockResolvedValue({ id: 'comp1', ...updateData })
await adminService.updateCompany('comp1', updateData)
expect(apiClient.patch).toHaveBeenCalledWith('/v1/companies/comp1', updateData)
})
it('verifyCompany should PATCH verify endpoint', async () => {
vi.mocked(apiClient.patch).mockResolvedValue({ id: 'comp1', is_verified: true })
await adminService.verifyCompany('comp1')
expect(apiClient.patch).toHaveBeenCalledWith('/v1/companies/comp1/verify', {})
})
it('deleteCompany should DELETE company by id', async () => {
vi.mocked(apiClient.delete).mockResolvedValue({})
await adminService.deleteCompany('comp1')
expect(apiClient.delete).toHaveBeenCalledWith('/v1/companies/comp1')
})
})
describe('Products', () => {
it('listProducts should call correct endpoint', async () => {
const mockResponse = { products: [], total: 0, page: 1, page_size: 20 }
vi.mocked(apiClient.get).mockResolvedValue(mockResponse)
const result = await adminService.listProducts(1, 20)
expect(apiClient.get).toHaveBeenCalledWith('/v1/products?page=1&page_size=20')
expect(result).toEqual(mockResponse)
})
it('createProduct should POST product data', async () => {
const productData = {
seller_id: 'seller1',
name: 'Dipirona 500mg',
description: 'Analgésico',
batch: 'L2024001',
expires_at: '2025-12-31',
price_cents: 1299,
stock: 100
}
vi.mocked(apiClient.post).mockResolvedValue({ id: 'prod1', ...productData })
await adminService.createProduct(productData)
expect(apiClient.post).toHaveBeenCalledWith('/v1/products', productData)
})
it('updateProduct should PATCH product data', async () => {
const updateData = { price_cents: 1599, stock: 50 }
vi.mocked(apiClient.patch).mockResolvedValue({ id: 'prod1', ...updateData })
await adminService.updateProduct('prod1', updateData)
expect(apiClient.patch).toHaveBeenCalledWith('/v1/products/prod1', updateData)
})
it('deleteProduct should DELETE product by id', async () => {
vi.mocked(apiClient.delete).mockResolvedValue({})
await adminService.deleteProduct('prod1')
expect(apiClient.delete).toHaveBeenCalledWith('/v1/products/prod1')
})
})
describe('Orders', () => {
it('listOrders should call correct endpoint', async () => {
const mockResponse = { orders: [], total: 0, page: 1, page_size: 20 }
vi.mocked(apiClient.get).mockResolvedValue(mockResponse)
const result = await adminService.listOrders(1, 20)
expect(apiClient.get).toHaveBeenCalledWith('/v1/orders?page=1&page_size=20')
expect(result).toEqual(mockResponse)
})
it('updateOrderStatus should PATCH status endpoint', async () => {
vi.mocked(apiClient.patch).mockResolvedValue({})
await adminService.updateOrderStatus('order1', 'Pago')
expect(apiClient.patch).toHaveBeenCalledWith('/v1/orders/order1/status', { status: 'Pago' })
})
it('deleteOrder should DELETE order by id', async () => {
vi.mocked(apiClient.delete).mockResolvedValue({})
await adminService.deleteOrder('order1')
expect(apiClient.delete).toHaveBeenCalledWith('/v1/orders/order1')
})
})
})

View file

@ -162,35 +162,35 @@ export const adminService = {
// Users
listUsers: async (page = 1, pageSize = 20) => {
log('listUsers', { page, pageSize })
const result = await apiClient.get<UserPage>(`/api/v1/users?page=${page}&page_size=${pageSize}`)
const result = await apiClient.get<UserPage>(`/v1/users?page=${page}&page_size=${pageSize}`)
log('listUsers result', result)
return result
},
getUser: async (id: string) => {
log('getUser', { id })
const result = await apiClient.get<User>(`/api/v1/users/${id}`)
const result = await apiClient.get<User>(`/v1/users/${id}`)
log('getUser result', result)
return result
},
createUser: async (data: CreateUserRequest) => {
log('createUser', data)
const result = await apiClient.post<User>('/api/v1/users', data)
const result = await apiClient.post<User>('/v1/users', data)
log('createUser result', result)
return result
},
updateUser: async (id: string, data: UpdateUserRequest) => {
log('updateUser', { id, data })
const result = await apiClient.put<User>(`/api/v1/users/${id}`, data)
const result = await apiClient.put<User>(`/v1/users/${id}`, data)
log('updateUser result', result)
return result
},
deleteUser: async (id: string) => {
log('deleteUser', { id })
const result = await apiClient.delete(`/api/v1/users/${id}`)
const result = await apiClient.delete(`/v1/users/${id}`)
log('deleteUser done')
return result
},
@ -198,42 +198,42 @@ export const adminService = {
// Companies
listCompanies: async (page = 1, pageSize = 20) => {
log('listCompanies', { page, pageSize })
const result = await apiClient.get<CompanyPage>(`/api/v1/companies?page=${page}&page_size=${pageSize}`)
const result = await apiClient.get<CompanyPage>(`/v1/companies?page=${page}&page_size=${pageSize}`)
log('listCompanies result', result)
return result
},
getCompany: async (id: string) => {
log('getCompany', { id })
const result = await apiClient.get<Company>(`/api/v1/companies/${id}`)
const result = await apiClient.get<Company>(`/v1/companies/${id}`)
log('getCompany result', result)
return result
},
createCompany: async (data: CreateCompanyRequest) => {
log('createCompany', data)
const result = await apiClient.post<Company>('/api/v1/companies', data)
const result = await apiClient.post<Company>('/v1/companies', data)
log('createCompany result', result)
return result
},
updateCompany: async (id: string, data: UpdateCompanyRequest) => {
log('updateCompany', { id, data })
const result = await apiClient.patch<Company>(`/api/v1/companies/${id}`, data)
const result = await apiClient.patch<Company>(`/v1/companies/${id}`, data)
log('updateCompany result', result)
return result
},
deleteCompany: async (id: string) => {
log('deleteCompany', { id })
const result = await apiClient.delete(`/api/v1/companies/${id}`)
const result = await apiClient.delete(`/v1/companies/${id}`)
log('deleteCompany done')
return result
},
verifyCompany: async (id: string) => {
log('verifyCompany', { id })
const result = await apiClient.patch<Company>(`/api/v1/companies/${id}/verify`, {})
const result = await apiClient.patch<Company>(`/v1/companies/${id}/verify`, {})
log('verifyCompany result', result)
return result
},
@ -241,35 +241,35 @@ export const adminService = {
// Products
listProducts: async (page = 1, pageSize = 20) => {
log('listProducts', { page, pageSize })
const result = await apiClient.get<ProductPage>(`/api/v1/products?page=${page}&page_size=${pageSize}`)
const result = await apiClient.get<ProductPage>(`/v1/products?page=${page}&page_size=${pageSize}`)
log('listProducts result', result)
return result
},
getProduct: async (id: string) => {
log('getProduct', { id })
const result = await apiClient.get<Product>(`/api/v1/products/${id}`)
const result = await apiClient.get<Product>(`/v1/products/${id}`)
log('getProduct result', result)
return result
},
createProduct: async (data: CreateProductRequest) => {
log('createProduct', data)
const result = await apiClient.post<Product>('/api/v1/products', data)
const result = await apiClient.post<Product>('/v1/products', data)
log('createProduct result', result)
return result
},
updateProduct: async (id: string, data: UpdateProductRequest) => {
log('updateProduct', { id, data })
const result = await apiClient.patch<Product>(`/api/v1/products/${id}`, data)
const result = await apiClient.patch<Product>(`/v1/products/${id}`, data)
log('updateProduct result', result)
return result
},
deleteProduct: async (id: string) => {
log('deleteProduct', { id })
const result = await apiClient.delete(`/api/v1/products/${id}`)
const result = await apiClient.delete(`/v1/products/${id}`)
log('deleteProduct done')
return result
},
@ -277,28 +277,28 @@ export const adminService = {
// Orders
listOrders: async (page = 1, pageSize = 20) => {
log('listOrders', { page, pageSize })
const result = await apiClient.get<OrderPage>(`/api/v1/orders?page=${page}&page_size=${pageSize}`)
const result = await apiClient.get<OrderPage>(`/v1/orders?page=${page}&page_size=${pageSize}`)
log('listOrders result', result)
return result
},
getOrder: async (id: string) => {
log('getOrder', { id })
const result = await apiClient.get<Order>(`/api/v1/orders/${id}`)
const result = await apiClient.get<Order>(`/v1/orders/${id}`)
log('getOrder result', result)
return result
},
updateOrderStatus: async (id: string, status: string) => {
log('updateOrderStatus', { id, status })
const result = await apiClient.patch(`/api/v1/orders/${id}/status`, { status })
const result = await apiClient.patch(`/v1/orders/${id}/status`, { status })
log('updateOrderStatus done')
return result
},
deleteOrder: async (id: string) => {
log('deleteOrder', { id })
const result = await apiClient.delete(`/api/v1/orders/${id}`)
const result = await apiClient.delete(`/v1/orders/${id}`)
log('deleteOrder done')
return result
},

View file

@ -21,13 +21,12 @@ describe('authService', () => {
describe('login', () => {
it('should login successfully with valid credentials', async () => {
const mockResponse = {
data: {
token: 'jwt-token-123',
expires_at: '2024-12-23T00:00:00Z'
}
// apiClient now returns data directly, not response.data
const mockData = {
token: 'jwt-token-123',
expires_at: '2024-12-23T00:00:00Z'
}
vi.mocked(apiClient.post).mockResolvedValue(mockResponse)
vi.mocked(apiClient.post).mockResolvedValue(mockData)
const result = await authService.login({
username: 'admin',

View file

@ -15,8 +15,9 @@ describe('productService', () => {
})
it('search calls api with correct params', async () => {
const mockResponse = { data: { products: [], total: 0, page: 1, page_size: 20 } }
vi.mocked(apiClient.get).mockResolvedValue(mockResponse)
// apiClient now returns data directly, not response.data
const mockData = { products: [], total: 0, page: 1, page_size: 20 }
vi.mocked(apiClient.get).mockResolvedValue(mockData)
const filters: ProductSearchFilters = {
lat: -16.32,
@ -37,12 +38,12 @@ describe('productService', () => {
expect(callArgs).toContain('lng=-48.95')
expect(callArgs).toContain('search=dipirona')
expect(result).toEqual(mockResponse.data)
expect(result).toEqual(mockData)
})
it('search handles optional filters', async () => {
const mockResponse = { data: { products: [], total: 0 } }
vi.mocked(apiClient.get).mockResolvedValue(mockResponse)
const mockData = { products: [], total: 0 }
vi.mocked(apiClient.get).mockResolvedValue(mockData)
const filters: ProductSearchFilters = {
lat: -16.32,
@ -60,3 +61,4 @@ describe('productService', () => {
expect(callArgs).toContain('max_distance=10')
})
})