import React from 'react'
import { render, screen } from '@testing-library/react'
import { describe, it, expect, beforeEach, vi } from 'vitest'
import {
ReadOnlyDateField,
ReadOnlyDurationField,
ReadOnlyNumberField,
ReadOnlySizeField,
ReadOnlyTextField,
} from './ReadOnlyFields'
vi.mock('react-admin', async (importOriginal) => ({
...(await importOriginal()),
useLocale: vi.fn(),
}))
describe('ReadOnlyFields', () => {
const record = {
id: '1',
client: 'NavidromeUI',
createdAt: '2026-09-17T14:30:00Z',
lastVisitedAt: '0001-01-01T00:00:00Z',
count: 1234567,
zero: 0,
size: 1536000,
duration: 3725,
}
beforeEach(async () => {
vi.clearAllMocks()
vi.spyOn(navigator, 'languages', 'get').mockReturnValue([])
const { useLocale } = await import('react-admin')
vi.mocked(useLocale).mockReturnValue('de')
})
const renderField = (Field, props) =>
render()
describe('', () => {
it('shows the record value with the translated field label', () => {
renderField(ReadOnlyTextField, { source: 'client' })
const input = screen.getByLabelText('resources.player.fields.client')
expect(input).toHaveValue('NavidromeUI')
})
it('cannot be edited or reached with the Tab key', () => {
renderField(ReadOnlyTextField, { source: 'client' })
const input = screen.getByRole('textbox')
expect(input).toHaveAttribute('readonly')
expect(input).toHaveAttribute('tabindex', '-1')
})
it('shows an empty value when the record has no value', () => {
renderField(ReadOnlyTextField, { source: 'userName' })
expect(screen.getByRole('textbox')).toHaveValue('')
})
it('uses an explicit label when given', () => {
renderField(ReadOnlyTextField, { source: 'client', label: 'Custom' })
expect(screen.getByLabelText('Custom')).toBeInTheDocument()
})
it('applies a custom format', () => {
renderField(ReadOnlyTextField, {
source: 'client',
format: (v) => v.toUpperCase(),
})
expect(screen.getByRole('textbox')).toHaveValue('NAVIDROMEUI')
})
it('exposes theme-overridable class names', () => {
const { container } = renderField(ReadOnlyTextField, {
source: 'client',
})
expect(
container.querySelector('[class*="NDReadOnlyField-inputRoot"]'),
).toBeInTheDocument()
expect(
container.querySelector('[class*="NDReadOnlyField-notchedOutline"]'),
).toBeInTheDocument()
})
})
describe('', () => {
it('formats the date using the selected language', () => {
renderField(ReadOnlyDateField, { source: 'createdAt' })
expect(screen.getByRole('textbox').value).toMatch(/^17\.9\.2026, /)
})
it('shows an empty value when the date is not set', () => {
renderField(ReadOnlyDateField, { source: 'lastVisitedAt' })
expect(screen.getByRole('textbox')).toHaveValue('')
})
})
describe('', () => {
it('formats the number using the selected language', () => {
renderField(ReadOnlyNumberField, { source: 'count' })
expect(screen.getByRole('textbox')).toHaveValue('1.234.567')
})
it('shows zero', () => {
renderField(ReadOnlyNumberField, { source: 'zero' })
expect(screen.getByRole('textbox')).toHaveValue('0')
})
})
describe('', () => {
it('formats bytes as a human-readable size', () => {
renderField(ReadOnlySizeField, { source: 'size' })
expect(screen.getByRole('textbox')).toHaveValue('1.46 MB')
})
})
describe('', () => {
it('formats seconds as a human-readable duration', () => {
renderField(ReadOnlyDurationField, { source: 'duration' })
expect(screen.getByRole('textbox')).toHaveValue('1h 2m 5s')
})
})
})