import { GovukComponentTestHelper } from '../../test-utils/GovukComponentTestHelper'
import { setupComponentTest } from '../../test-utils/setupComponentTest'
import { GovUKSelectInput } from './govukSelectInput'
vi.mock('nunjucks')
describe('govukSelectInput', () => {
setupComponentTest()
const helper = new GovukComponentTestHelper(GovUKSelectInput)
describe('Data transformation', () => {
it('sets default values correctly', async () => {
// Arrange
const block = {
code: 'test-select',
items: [{ value: 'option1', text: 'Option 1' }],
}
// Act
const params = await helper.getParams(block)
// Assert
expect(params.id).toBe('test-select')
expect(params.name).toBe('test-select')
expect(params.items).toEqual([{ value: 'option1', text: 'Option 1' }])
expect(params.value).toBeUndefined()
})
it('uses custom ID over code', async () => {
// Arrange
const block = {
code: 'test-select',
id: 'custom-id',
items: [] as { value: string; text: string }[],
}
// Act
const params = await helper.getParams(block)
// Assert
expect(params.id).toBe('custom-id')
expect(params.name).toBe('test-select')
})
it('passes through value', async () => {
// Arrange
const block = {
code: 'test-select',
value: 'selected-value',
items: [] as { value: string; text: string }[],
}
// Act
const params = await helper.getParams(block)
// Assert
expect(params.value).toBe('selected-value')
})
it('passes through items array', async () => {
// Arrange
const items = [
{ value: '', text: 'Choose an option' },
{ value: 'uk', text: 'United Kingdom' },
{ value: 'fr', text: 'France', disabled: true },
]
const block = {
code: 'test-select',
items,
}
// Act
const params = await helper.getParams(block)
// Assert
expect(params.items).toEqual(items)
})
it('should omit items when visibleWhen evaluates to false', async () => {
// Arrange
const items = [
{ value: '', text: 'Choose an option' },
{ value: 'uk', text: 'United Kingdom', visibleWhen: false },
{ value: 'fr', text: 'France', visibleWhen: true },
]
const block = {
code: 'test-select',
items,
}
// Act
const params = await helper.getParams(block)
// Assert
expect(params.items.map((item: { text: string }) => item.text)).toEqual(['Choose an option', 'France'])
})
})
describe('Label transformation', () => {
it('converts string label to object format', async () => {
// Arrange
const block = {
code: 'test-select',
label: 'Select your country',
items: [] as { value: string; text: string }[],
}
// Act
const params = await helper.getParams(block)
// Assert
expect(params.label).toEqual({
text: 'Select your country',
})
})
it('passes through object label unchanged', async () => {
// Arrange
const labelObj = {
text: 'Country',
classes: 'govuk-label--l',
isPageHeading: true,
}
const block = {
code: 'test-select',
label: labelObj,
items: [] as { value: string; text: string }[],
}
// Act
const params = await helper.getParams(block)
// Assert
expect(params.label).toEqual(labelObj)
})
it('passes through label with HTML', async () => {
// Arrange
const labelObj = {
html: 'Country Required',
}
const block = {
code: 'test-select',
label: labelObj,
items: [] as { value: string; text: string }[],
}
// Act
const params = await helper.getParams(block)
// Assert
expect(params.label).toEqual(labelObj)
})
})
describe('Hint transformation', () => {
it('converts string hint to object format', async () => {
// Arrange
const block = {
code: 'test-select',
hint: 'Select the country where you currently live',
items: [] as { value: string; text: string }[],
}
// Act
const params = await helper.getParams(block)
// Assert
expect(params.hint).toEqual({
text: 'Select the country where you currently live',
})
})
it('passes through object hint unchanged', async () => {
// Arrange
const hintObj = {
text: 'This is the country where you pay tax',
classes: 'custom-hint',
id: 'country-hint',
}
const block = {
code: 'test-select',
hint: hintObj,
items: [] as { value: string; text: string }[],
}
// Act
const params = await helper.getParams(block)
// Assert
expect(params.hint).toEqual(hintObj)
})
it('passes undefined hint when not provided', async () => {
// Arrange
const block = {
code: 'test-select',
hint: undefined as undefined,
items: [] as { value: string; text: string }[],
}
// Act
const params = await helper.getParams(block)
// Assert
expect(params.hint).toBeUndefined()
})
})
describe('Select attributes', () => {
it('passes through disabled state', async () => {
// Arrange
const block = {
code: 'test-select',
disabled: true,
items: [] as { value: string; text: string }[],
}
// Act
const params = await helper.getParams(block)
// Assert
expect(params.disabled).toBe(true)
})
it('passes through describedBy', async () => {
// Arrange
const block = {
code: 'test-select',
describedBy: 'select-guidance',
items: [] as { value: string; text: string }[],
}
// Act
const params = await helper.getParams(block)
// Assert
expect(params.describedBy).toBe('select-guidance')
})
it('passes through classes', async () => {
// Arrange
const block = {
code: 'test-select',
classes: 'govuk-!-width-one-half',
items: [] as { value: string; text: string }[],
}
// Act
const params = await helper.getParams(block)
// Assert
expect(params.classes).toBe('govuk-!-width-one-half')
})
it('passes through attributes', async () => {
// Arrange
const block = {
code: 'test-select',
attributes: {
'data-module': 'accessible-autocomplete',
'aria-describedby': 'help-text',
},
items: [] as { value: string; text: string }[],
}
// Act
const params = await helper.getParams(block)
// Assert
expect(params.attributes).toEqual({
'data-module': 'accessible-autocomplete',
'aria-describedby': 'help-text',
})
})
it('passes through formGroup configuration', async () => {
// Arrange
const formGroup = {
classes: 'custom-form-group',
attributes: { 'data-test': 'value' },
beforeInput: { text: 'Before text' },
afterInput: { html: 'After HTML' },
}
const block = {
code: 'test-select',
formGroup,
items: [] as { value: string; text: string }[],
}
// Act
const params = await helper.getParams(block)
// Assert
expect(params.formGroup).toEqual(formGroup)
})
})
describe('Error message transformation', () => {
it('transforms error array to error message object', async () => {
// Arrange
const block = {
code: 'test-select',
errors: [{ message: 'Select an option' }],
items: [] as { value: string; text: string }[],
}
// Act
const params = await helper.getParams(block)
// Assert
expect(params.errorMessage).toEqual({
text: 'Select an option',
})
})
it('uses first error when multiple provided', async () => {
// Arrange
const block = {
code: 'test-select',
errors: [{ message: 'First error' }, { message: 'Second error' }],
items: [] as { value: string; text: string }[],
}
// Act
const params = await helper.getParams(block)
// Assert
expect(params.errorMessage).toEqual({
text: 'First error',
})
})
it('sets errorMessage to undefined when no errors', async () => {
// Arrange
const block = {
code: 'test-select',
items: [] as { value: string; text: string }[],
}
// Act
const params = await helper.getParams(block)
// Assert
expect(params.errorMessage).toBeUndefined()
})
})
describe('Template and context', () => {
it('calls nunjucks with correct template path', async () => {
// Arrange
const block = {
code: 'test-select',
items: [] as { value: string; text: string }[],
}
// Act
const { template } = await helper.executeComponent(block)
// Assert
expect(template).toBe('govuk/components/select/template.njk')
})
it('wraps params in context object', async () => {
// Arrange
const block = {
code: 'test-select',
items: [] as { value: string; text: string }[],
}
// Act
const { context } = (await helper.executeComponent(block)) as { context: any }
// Assert
expect(context).toHaveProperty('params')
expect(context.params).toHaveProperty('id')
expect(context.params).toHaveProperty('name')
expect(context.params).toHaveProperty('items')
})
})
describe('DOM rendering smoke test', () => {
it('renders a valid select component', async () => {
// Arrange
const block = {
variant: 'govukSelectInput' as const,
code: 'country-select',
label: 'Select your country',
hint: 'Select the country where you currently live',
value: 'uk',
items: [
{ value: '', text: 'Choose an option' },
{ value: 'uk', text: 'United Kingdom' },
{ value: 'fr', text: 'France' },
{ value: 'de', text: 'Germany' },
],
errors: [{ message: 'Select a country' }],
}
// Act
const html = await helper.renderWithNunjucks(block)
// Assert
expect(html).toContainText('govuk-select')
expect(html).toContainText('country-select')
expect(html).toContainText('Select your country')
expect(html).toContainText('Select the country where you currently live')
expect(html).toContainText('Select a country')
expect(html).toContainText('Choose an option')
expect(html).toContainText('United Kingdom')
expect(html).toContainText('France')
expect(html).toContainText('Germany')
})
})
})