/**
* Tests for DataProviderContext - data-provider-context.tsx
*
* TDD RED phase: Write failing tests first.
*/
import { describe, it, expect, vi } from 'vitest'
import { render, screen } from '@testing-library/react'
import { DataProviderProvider, useDataProvider } from '../../context/data-provider-context'
import type { DataProvider } from '../../types'
// Helper component to consume data provider context
function DataProviderConsumer({ onProvider }: { onProvider: (dp: DataProvider) => void }) {
const dataProvider = useDataProvider()
onProvider(dataProvider)
return
true
}
function createMockDataProvider(overrides: Partial = {}): DataProvider {
return {
getList: vi.fn().mockResolvedValue({ data: [], total: 0 }),
getOne: vi.fn().mockResolvedValue({ data: { id: '1' } }),
getMany: vi.fn().mockResolvedValue({ data: [] }),
create: vi.fn().mockResolvedValue({ data: { id: '1' } }),
update: vi.fn().mockResolvedValue({ data: { id: '1' } }),
delete: vi.fn().mockResolvedValue({ data: { id: '1' } }),
...overrides,
}
}
describe('DataProviderContext', () => {
describe('DataProviderProvider', () => {
it('should provide the data provider to children', () => {
const mockProvider = createMockDataProvider()
let receivedProvider: DataProvider | undefined
render(
{ receivedProvider = dp }} />
)
expect(screen.getByTestId('has-provider').textContent).toBe('true')
expect(receivedProvider).toBe(mockProvider)
})
it('should allow calling data provider methods', async () => {
const mockGetList = vi.fn().mockResolvedValue({ data: [{ id: '1', name: 'Test' }], total: 1 })
const mockProvider = createMockDataProvider({ getList: mockGetList })
let receivedProvider: DataProvider | undefined
render(
{ receivedProvider = dp }} />
)
const result = await receivedProvider!.getList('users', { pagination: { page: 1, perPage: 10 } })
expect(mockGetList).toHaveBeenCalledWith('users', { pagination: { page: 1, perPage: 10 } })
expect(result.data).toEqual([{ id: '1', name: 'Test' }])
expect(result.total).toBe(1)
})
it('should support all DataProvider methods', async () => {
const mockProvider = createMockDataProvider()
let receivedProvider: DataProvider | undefined
render(
{ receivedProvider = dp }} />
)
// Call all methods
await receivedProvider!.getList('users')
await receivedProvider!.getOne('users', { id: '1' })
await receivedProvider!.getMany('users', { ids: ['1', '2'] })
await receivedProvider!.create('users', { data: { name: 'New' } })
await receivedProvider!.update('users', { id: '1', data: { name: 'Updated' } })
await receivedProvider!.delete('users', { id: '1' })
expect(mockProvider.getList).toHaveBeenCalled()
expect(mockProvider.getOne).toHaveBeenCalled()
expect(mockProvider.getMany).toHaveBeenCalled()
expect(mockProvider.create).toHaveBeenCalled()
expect(mockProvider.update).toHaveBeenCalled()
expect(mockProvider.delete).toHaveBeenCalled()
})
})
describe('useDataProvider', () => {
it('should throw error when used outside DataProviderProvider', () => {
const consoleError = vi.spyOn(console, 'error').mockImplementation(() => {})
expect(() => {
render( {}} />)
}).toThrow('useDataProvider must be used within a DataProviderProvider')
consoleError.mockRestore()
})
})
})