import * as React from 'react' import { render, screen, cleanup } from '@testing-library/react' import { LibrarySelectionField } from './LibrarySelectionField' import { useInput, useTranslate, useRecordContext } from 'react-admin' import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { SelectLibraryInput } from '../common/SelectLibraryInput' // Mock the react-admin hooks vi.mock('react-admin', () => ({ useInput: vi.fn(), useTranslate: vi.fn(), useRecordContext: vi.fn(), })) // Mock the SelectLibraryInput component vi.mock('../common/SelectLibraryInput.jsx', () => ({ SelectLibraryInput: vi.fn(() =>
), })) describe('', () => { const defaultProps = { input: { name: 'libraryIds', value: [], onChange: vi.fn(), }, meta: { touched: false, error: undefined, }, } const mockTranslate = vi.fn((key) => key) beforeEach(() => { useInput.mockReturnValue(defaultProps) useTranslate.mockReturnValue(mockTranslate) useRecordContext.mockReturnValue({}) SelectLibraryInput.mockClear() }) afterEach(cleanup) it('should render field label from translations', () => { render() expect(screen.getByText('resources.user.fields.libraries')).not.toBeNull() }) it('should render helper text from translations', () => { render() expect( screen.getByText('resources.user.helperTexts.libraries'), ).not.toBeNull() }) it('should render SelectLibraryInput with correct props', () => { render() expect(screen.getByTestId('select-library-input')).not.toBeNull() expect(SelectLibraryInput).toHaveBeenCalledWith( expect.objectContaining({ onChange: defaultProps.input.onChange, value: defaultProps.input.value, }), expect.anything(), ) }) it('should render error message when touched and has error', () => { useInput.mockReturnValue({ ...defaultProps, meta: { touched: true, error: 'This field is required', }, }) render() expect(screen.getByText('This field is required')).not.toBeNull() }) it('should not render error message when not touched', () => { useInput.mockReturnValue({ ...defaultProps, meta: { touched: false, error: 'This field is required', }, }) render() expect(screen.queryByText('This field is required')).toBeNull() }) it('should initialize with empty array when value is null', () => { useInput.mockReturnValue({ ...defaultProps, input: { ...defaultProps.input, value: null, }, }) render() expect(SelectLibraryInput).toHaveBeenCalledWith( expect.objectContaining({ value: [], }), expect.anything(), ) }) it('should extract library IDs from record libraries array when editing user', () => { // Mock a record with libraries array (from backend during edit) useRecordContext.mockReturnValue({ id: 'user123', name: 'John Doe', libraries: [ { id: 1, name: 'Music Library 1', path: '/music1' }, { id: 3, name: 'Music Library 3', path: '/music3' }, ], }) // Mock input without libraryIds (edit mode scenario) useInput.mockReturnValue({ ...defaultProps, input: { ...defaultProps.input, value: undefined, }, }) render() expect(SelectLibraryInput).toHaveBeenCalledWith( expect.objectContaining({ value: [1, 3], // Should extract IDs from libraries array }), expect.anything(), ) }) it('should prefer libraryIds when both libraryIds and libraries are present', () => { // Mock a record with libraries array useRecordContext.mockReturnValue({ id: 'user123', libraries: [ { id: 1, name: 'Music Library 1', path: '/music1' }, { id: 3, name: 'Music Library 3', path: '/music3' }, ], }) // Mock input with explicit libraryIds (create mode or already transformed) useInput.mockReturnValue({ ...defaultProps, input: { ...defaultProps.input, value: [2, 4], // Different IDs than in libraries }, }) render() expect(SelectLibraryInput).toHaveBeenCalledWith( expect.objectContaining({ value: [2, 4], // Should prefer libraryIds over libraries }), expect.anything(), ) }) })