270 lines
6.6 KiB
TypeScript
270 lines
6.6 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
import {
|
|
getArtists,
|
|
getArtistWithPortfolio,
|
|
getPublicArtists,
|
|
getArtistBySlug,
|
|
updateArtist,
|
|
addPortfolioImage,
|
|
updatePortfolioImage,
|
|
deletePortfolioImage,
|
|
} from '@/lib/db'
|
|
|
|
// Mock D1 database
|
|
const createMockD1 = () => ({
|
|
prepare: vi.fn().mockReturnThis(),
|
|
bind: vi.fn().mockReturnThis(),
|
|
first: vi.fn(),
|
|
all: vi.fn(),
|
|
run: vi.fn(),
|
|
})
|
|
|
|
describe('Database Functions', () => {
|
|
let mockEnv: { DB: ReturnType<typeof createMockD1> }
|
|
|
|
beforeEach(() => {
|
|
mockEnv = {
|
|
DB: createMockD1(),
|
|
}
|
|
vi.clearAllMocks()
|
|
})
|
|
|
|
describe('getArtists', () => {
|
|
it('should fetch all artists and parse JSON fields', async () => {
|
|
const mockArtists = [
|
|
{
|
|
id: '1',
|
|
name: 'Test Artist',
|
|
bio: 'Test bio',
|
|
specialties: '["Traditional","Realism"]',
|
|
isActive: 1,
|
|
},
|
|
]
|
|
|
|
mockEnv.DB.all.mockResolvedValue({
|
|
results: mockArtists,
|
|
success: true,
|
|
})
|
|
|
|
const result = await getArtists(mockEnv)
|
|
|
|
expect(result).toHaveLength(1)
|
|
expect(result[0].specialties).toEqual(['Traditional', 'Realism'])
|
|
expect(result[0].isActive).toBe(true)
|
|
})
|
|
|
|
it('should handle empty results', async () => {
|
|
mockEnv.DB.all.mockResolvedValue({
|
|
results: [],
|
|
success: true,
|
|
})
|
|
|
|
const result = await getArtists(mockEnv)
|
|
expect(result).toEqual([])
|
|
})
|
|
|
|
it('should handle database errors', async () => {
|
|
mockEnv.DB.all.mockRejectedValue(new Error('Database error'))
|
|
|
|
await expect(getArtists(mockEnv)).rejects.toThrow('Database error')
|
|
})
|
|
})
|
|
|
|
describe('getArtistWithPortfolio', () => {
|
|
it('should fetch artist with portfolio images', async () => {
|
|
const mockArtist = {
|
|
id: '1',
|
|
name: 'Test Artist',
|
|
bio: 'Test bio',
|
|
specialties: '["Traditional"]',
|
|
isActive: 1,
|
|
}
|
|
|
|
const mockImages = [
|
|
{
|
|
id: '1',
|
|
artistId: '1',
|
|
url: 'https://example.com/image.jpg',
|
|
caption: 'Test image',
|
|
tags: '["Traditional","Portrait"]',
|
|
isPublic: 1,
|
|
orderIndex: 0,
|
|
},
|
|
]
|
|
|
|
mockEnv.DB.first.mockResolvedValueOnce(mockArtist)
|
|
mockEnv.DB.all.mockResolvedValueOnce({
|
|
results: mockImages,
|
|
success: true,
|
|
})
|
|
|
|
const result = await getArtistWithPortfolio('1', mockEnv)
|
|
|
|
expect(result).toBeDefined()
|
|
expect(result?.name).toBe('Test Artist')
|
|
expect(result?.portfolioImages).toHaveLength(1)
|
|
expect(result?.portfolioImages[0].tags).toEqual(['Traditional', 'Portrait'])
|
|
})
|
|
|
|
it('should return null for non-existent artist', async () => {
|
|
mockEnv.DB.first.mockResolvedValue(null)
|
|
|
|
const result = await getArtistWithPortfolio('999', mockEnv)
|
|
expect(result).toBeNull()
|
|
})
|
|
})
|
|
|
|
describe('getPublicArtists', () => {
|
|
it('should return only active artists with public images', async () => {
|
|
const mockArtists = [
|
|
{
|
|
id: '1',
|
|
name: 'Active Artist',
|
|
specialties: '["Traditional"]',
|
|
isActive: 1,
|
|
},
|
|
{
|
|
id: '2',
|
|
name: 'Inactive Artist',
|
|
specialties: '["Realism"]',
|
|
isActive: 0,
|
|
},
|
|
]
|
|
|
|
mockEnv.DB.all.mockResolvedValue({
|
|
results: mockArtists.filter(a => a.isActive),
|
|
success: true,
|
|
})
|
|
|
|
const result = await getPublicArtists({}, mockEnv)
|
|
|
|
expect(result).toHaveLength(1)
|
|
expect(result[0].name).toBe('Active Artist')
|
|
})
|
|
|
|
it('should filter by specialty', async () => {
|
|
const mockArtists = [
|
|
{
|
|
id: '1',
|
|
name: 'Traditional Artist',
|
|
specialties: '["Traditional"]',
|
|
isActive: 1,
|
|
},
|
|
]
|
|
|
|
mockEnv.DB.all.mockResolvedValue({
|
|
results: mockArtists,
|
|
success: true,
|
|
})
|
|
|
|
await getPublicArtists({ specialty: 'Traditional' }, mockEnv)
|
|
|
|
// Verify the bind was called (specialty filter applied)
|
|
expect(mockEnv.DB.bind).toHaveBeenCalled()
|
|
})
|
|
})
|
|
|
|
describe('getArtistBySlug', () => {
|
|
it('should fetch artist by slug', async () => {
|
|
const mockArtist = {
|
|
id: '1',
|
|
slug: 'test-artist',
|
|
name: 'Test Artist',
|
|
specialties: '["Traditional"]',
|
|
}
|
|
|
|
mockEnv.DB.first.mockResolvedValue(mockArtist)
|
|
mockEnv.DB.all.mockResolvedValue({
|
|
results: [],
|
|
success: true,
|
|
})
|
|
|
|
const result = await getArtistBySlug('test-artist', mockEnv)
|
|
|
|
expect(result).toBeDefined()
|
|
expect(result?.slug).toBe('test-artist')
|
|
expect(mockEnv.DB.bind).toHaveBeenCalledWith('test-artist')
|
|
})
|
|
})
|
|
|
|
describe('updateArtist', () => {
|
|
it('should update artist and stringify JSON fields', async () => {
|
|
const updateData = {
|
|
id: '1',
|
|
name: 'Updated Name',
|
|
bio: 'Updated bio',
|
|
specialties: ['Traditional', 'Realism'],
|
|
hourlyRate: 150,
|
|
}
|
|
|
|
mockEnv.DB.run.mockResolvedValue({
|
|
success: true,
|
|
meta: { changes: 1 },
|
|
})
|
|
|
|
await updateArtist('1', updateData, mockEnv)
|
|
|
|
// Verify the update was called
|
|
expect(mockEnv.DB.run).toHaveBeenCalled()
|
|
expect(mockEnv.DB.bind).toHaveBeenCalled()
|
|
})
|
|
})
|
|
|
|
describe('Portfolio Image Operations', () => {
|
|
it('should add portfolio image', async () => {
|
|
const imageData = {
|
|
url: 'https://example.com/image.jpg',
|
|
caption: 'Test caption',
|
|
tags: ['Traditional'],
|
|
isPublic: true,
|
|
orderIndex: 0,
|
|
}
|
|
|
|
mockEnv.DB.run.mockResolvedValue({
|
|
success: true,
|
|
meta: { last_row_id: 1 },
|
|
})
|
|
|
|
mockEnv.DB.first.mockResolvedValue({
|
|
id: '1',
|
|
...imageData,
|
|
artistId: '1',
|
|
tags: JSON.stringify(imageData.tags),
|
|
})
|
|
|
|
const result = await addPortfolioImage('1', imageData, mockEnv)
|
|
|
|
expect(result).toBeDefined()
|
|
expect(result.caption).toBe('Test caption')
|
|
})
|
|
|
|
it('should update portfolio image', async () => {
|
|
const updateData = {
|
|
caption: 'Updated caption',
|
|
tags: ['Traditional', 'Portrait'],
|
|
isPublic: false,
|
|
}
|
|
|
|
mockEnv.DB.run.mockResolvedValue({
|
|
success: true,
|
|
meta: { changes: 1 },
|
|
})
|
|
|
|
await updatePortfolioImage('1', updateData, mockEnv)
|
|
|
|
expect(mockEnv.DB.run).toHaveBeenCalled()
|
|
})
|
|
|
|
it('should delete portfolio image', async () => {
|
|
mockEnv.DB.run.mockResolvedValue({
|
|
success: true,
|
|
meta: { changes: 1 },
|
|
})
|
|
|
|
await deletePortfolioImage('1', mockEnv)
|
|
|
|
expect(mockEnv.DB.run).toHaveBeenCalled()
|
|
})
|
|
})
|
|
})
|