92 lines
3.7 KiB
TypeScript
92 lines
3.7 KiB
TypeScript
import { cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||
import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from 'vitest'
|
||
|
||
import { ConfigField } from '@/app/settings/config-field'
|
||
import { FIELD_DESCRIPTIONS, FIELD_LABELS, SECTIONS } from '@/app/settings/constants'
|
||
|
||
import { I18nProvider } from './context'
|
||
import { en } from './en'
|
||
import { trOverrides } from './tr'
|
||
import { TR_FIELD_DESCRIPTIONS, TR_FIELD_LABELS } from './tr-fields'
|
||
|
||
afterEach(cleanup)
|
||
const scrollDescriptor = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'scrollIntoView')
|
||
beforeAll(() => Object.defineProperty(HTMLElement.prototype, 'scrollIntoView', { configurable: true, value: vi.fn() }))
|
||
afterAll(() => {
|
||
if (scrollDescriptor) {
|
||
Object.defineProperty(HTMLElement.prototype, 'scrollIntoView', scrollDescriptor)
|
||
} else {
|
||
Reflect.deleteProperty(HTMLElement.prototype, 'scrollIntoView')
|
||
}
|
||
})
|
||
|
||
describe('Turkish settings contents', () => {
|
||
it('covers every registered settings section, including sections absent from the English dictionary', () => {
|
||
for (const section of SECTIONS) {
|
||
expect(trOverrides.settings?.sections?.[section.id], section.id).toBeTruthy()
|
||
}
|
||
})
|
||
it('supplies every desktop message explicitly without English fallback', () => {
|
||
function check(reference: Record<string, unknown>, actual: Record<string, unknown>, prefix: string) {
|
||
for (const [key, value] of Object.entries(reference)) {
|
||
expect(actual[key], prefix + '.' + key).toBeDefined()
|
||
|
||
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
||
check(value as Record<string, unknown>, actual[key] as Record<string, unknown>, prefix + '.' + key)
|
||
}
|
||
}
|
||
}
|
||
|
||
check(en as unknown as Record<string, unknown>, trOverrides as Record<string, unknown>, 'tr')
|
||
})
|
||
it('covers every curated field label and description without English fallback', () => {
|
||
for (const [key, value] of Object.entries(FIELD_LABELS)) {
|
||
expect(TR_FIELD_LABELS[key], key).toBeTruthy()
|
||
expect(TR_FIELD_LABELS[key], key).not.toBe(value)
|
||
}
|
||
|
||
for (const [key, value] of Object.entries(FIELD_DESCRIPTIONS)) {
|
||
expect(TR_FIELD_DESCRIPTIONS[key], key).toBeTruthy()
|
||
expect(TR_FIELD_DESCRIPTIONS[key], key).not.toBe(value)
|
||
}
|
||
})
|
||
|
||
it('renders translated field contents and retains the stored boolean value', async () => {
|
||
const onChange = vi.fn()
|
||
render(
|
||
<I18nProvider>
|
||
<ConfigField
|
||
onChange={onChange}
|
||
schema={{ type: 'boolean', description: 'Hide secrets' }}
|
||
schemaKey="security.redact_secrets"
|
||
value={true}
|
||
/>
|
||
</I18nProvider>
|
||
)
|
||
expect(screen.getByText('Gizli bilgileri maskele')).toBeTruthy()
|
||
expect(screen.getByText(TR_FIELD_DESCRIPTIONS['security.redactSecrets'])).toBeTruthy()
|
||
expect(screen.queryByText('Hide secrets')).toBeNull()
|
||
fireEvent.click(screen.getByRole('switch'))
|
||
await waitFor(() => expect(onChange).toHaveBeenCalledWith(false))
|
||
})
|
||
|
||
it('translates option labels without changing the backend enum value', async () => {
|
||
const onChange = vi.fn()
|
||
render(
|
||
<I18nProvider>
|
||
<ConfigField
|
||
onChange={onChange}
|
||
schema={{ type: 'select', options: ['manual', 'smart', 'off'] }}
|
||
schemaKey="approvals.mode"
|
||
value="manual"
|
||
/>
|
||
</I18nProvider>
|
||
)
|
||
expect(screen.getByText('Onay modu')).toBeTruthy()
|
||
expect(screen.getByRole('combobox').textContent).toContain('Elle onayla')
|
||
fireEvent.keyDown(screen.getByRole('combobox'), { key: 'ArrowDown' })
|
||
fireEvent.click(await screen.findByRole('option', { name: 'Akıllı onay' }))
|
||
expect(onChange).toHaveBeenCalledWith('smart')
|
||
})
|
||
})
|