import { MojComponentTestHelper } from '../../test-utils/MojComponentTestHelper'
import { setupComponentTest } from '../../test-utils/setupComponentTest'
import { MOJMultiSelect } from './mojMultiSelect'
vi.mock('nunjucks')
describe('mojMultiSelect', () => {
setupComponentTest()
const helper = new MojComponentTestHelper(MOJMultiSelect)
describe('Data transformation', () => {
it('should pass through rows', async () => {
// Arrange
const rows = [
[{ html: '' }, { text: 'John Smith' }, { text: 'Active' }],
[{ html: '' }, { text: 'Jane Doe' }, { text: 'Inactive' }],
]
// Act
const params = await helper.getParams({ rows })
// Assert
expect(params.rows).toEqual(rows)
})
it('should pass through head', async () => {
// Arrange
const head = [{ html: '' }, { text: 'Name' }, { text: 'Status' }]
const rows = [[{ text: 'data' }]]
// Act
const params = await helper.getParams({ rows, head })
// Assert
expect(params.head).toEqual(head)
})
it('should pass through caption', async () => {
// Arrange
const rows = [[{ text: 'data' }]]
// Act
const params = await helper.getParams({
rows,
caption: 'User selection table',
})
// Assert
expect(params.caption).toBe('User selection table')
})
it('should pass through captionClasses', async () => {
// Arrange
const rows = [[{ text: 'data' }]]
// Act
const params = await helper.getParams({
rows,
caption: 'Table caption',
captionClasses: 'govuk-table__caption--m',
})
// Assert
expect(params.captionClasses).toBe('govuk-table__caption--m')
})
it('should pass through firstCellIsHeader', async () => {
// Arrange
const rows = [[{ text: 'data' }]]
// Act
const params = await helper.getParams({
rows,
firstCellIsHeader: true,
})
// Assert
expect(params.firstCellIsHeader).toBe(true)
})
it('should leave optional properties undefined when not provided', async () => {
// Arrange
const rows = [[{ text: 'data' }]]
// Act
const params = await helper.getParams({ rows })
// Assert
expect(params.head).toBeUndefined()
expect(params.caption).toBeUndefined()
expect(params.captionClasses).toBeUndefined()
expect(params.firstCellIsHeader).toBeUndefined()
})
})
describe('Data module attribute', () => {
it('should add data-module attribute with value moj-multi-select', async () => {
// Arrange
const rows = [[{ text: 'data' }]]
// Act
const params = await helper.getParams({ rows })
// Assert
expect(params.attributes).toHaveProperty('data-module', 'moj-multi-select')
})
it('should merge user-provided attributes with data-module', async () => {
// Arrange
const rows = [[{ text: 'data' }]]
const attributes = {
'data-testid': 'my-multi-select',
'data-tracking': 'selection-table',
}
// Act
const params = await helper.getParams({ rows, attributes })
// Assert
expect(params.attributes).toEqual({
'data-testid': 'my-multi-select',
'data-tracking': 'selection-table',
'data-module': 'moj-multi-select',
})
})
it('should override user-provided data-module with moj-multi-select', async () => {
// Arrange
const rows = [[{ text: 'data' }]]
const attributes = {
'data-module': 'custom-module',
'data-other': 'value',
}
// Act
const params = await helper.getParams({ rows, attributes })
// Assert
expect(params.attributes).toEqual({
'data-module': 'moj-multi-select',
'data-other': 'value',
})
})
it('should add data-module when no attributes provided', async () => {
// Arrange
const rows = [[{ text: 'data' }]]
// Act
const params = await helper.getParams({ rows })
// Assert
expect(params.attributes).toEqual({
'data-module': 'moj-multi-select',
})
})
})
describe('Optional attributes', () => {
it('should pass through classes', async () => {
// Arrange
const rows = [[{ text: 'data' }]]
// Act
const params = await helper.getParams({
rows,
classes: 'custom-table-class',
})
// Assert
expect(params.classes).toBe('custom-table-class')
})
it('should pass through multiple custom attributes', async () => {
// Arrange
const rows = [[{ text: 'data' }]]
const attributes = {
'data-testid': 'my-table',
'data-custom': 'value',
'aria-label': 'Selection table',
}
// Act
const params = await helper.getParams({ rows, attributes })
// Assert
expect(params.attributes).toMatchObject(attributes)
})
})
describe('Template and context', () => {
it('should call nunjucks with GOV.UK table template path', async () => {
// Arrange
const rows = [[{ text: 'data' }]]
// Act
const { template } = await helper.executeComponent({ rows })
// Assert
expect(template).toBe('govuk/components/table/template.njk')
})
it('should wrap params in context object', async () => {
// Arrange
const rows = [[{ text: 'data' }]]
// Act
const { context } = await helper.executeComponent({ rows })
// Assert
expect(context).toHaveProperty('params')
expect((context as { params: Record }).params).toHaveProperty('rows')
})
it('should include all params in context', async () => {
// Arrange
const rows = [[{ html: '' }, { text: 'John Smith' }]]
const head = [{ html: '' }, { text: 'Name' }]
// Act
const { context } = await helper.executeComponent({
rows,
head,
caption: 'Users',
captionClasses: 'govuk-table__caption--l',
firstCellIsHeader: false,
classes: 'custom-class',
attributes: { 'data-test': 'value' },
})
// Assert
const params = (context as { params: Record }).params
expect(params).toHaveProperty('rows', rows)
expect(params).toHaveProperty('head', head)
expect(params).toHaveProperty('caption', 'Users')
expect(params).toHaveProperty('captionClasses', 'govuk-table__caption--l')
expect(params).toHaveProperty('firstCellIsHeader', false)
expect(params).toHaveProperty('classes', 'custom-class')
expect(params).toHaveProperty('attributes')
expect(params.attributes).toHaveProperty('data-module', 'moj-multi-select')
})
})
describe('Complex cell configurations', () => {
it('should handle cells with colspan and rowspan', async () => {
// Arrange
const rows = [
[
{ text: 'Cell 1', colspan: 2 },
{ text: 'Cell 2', rowspan: 2 },
],
]
// Act
const params = await helper.getParams({ rows })
// Assert
expect(params.rows).toEqual(rows)
expect(params.rows[0][0]).toHaveProperty('colspan', 2)
expect(params.rows[0][1]).toHaveProperty('rowspan', 2)
})
it('should handle cells with format and classes', async () => {
// Arrange
const rows = [
[{ text: '100', format: 'numeric', classes: 'govuk-table__cell--numeric' }, { text: 'Regular cell' }],
]
// Act
const params = await helper.getParams({ rows })
// Assert
expect(params.rows[0][0]).toHaveProperty('format', 'numeric')
expect(params.rows[0][0]).toHaveProperty('classes', 'govuk-table__cell--numeric')
})
it('should handle cells with custom attributes', async () => {
// Arrange
const rows = [
[
{
text: 'Cell',
attributes: { 'data-cell-id': '123', 'data-sort': 'asc' },
},
],
]
// Act
const params = await helper.getParams({ rows })
// Assert
expect(params.rows[0][0].attributes).toEqual({
'data-cell-id': '123',
'data-sort': 'asc',
})
})
it('should handle head cells with all options', async () => {
// Arrange
const head = [
{
html: '',
classes: 'govuk-table__header--checkbox',
attributes: { scope: 'col' },
},
{
text: 'Name',
format: 'text',
colspan: 2,
attributes: { scope: 'col' },
},
]
const rows = [[{ text: 'data' }]]
// Act
const params = await helper.getParams({ rows, head })
// Assert
expect(params.head).toEqual(head)
})
})
describe('HTML and text content in cells', () => {
it('should handle HTML content in cells', async () => {
// Arrange
const rows = [[{ html: 'Bold text' }, { html: 'Link' }]]
// Act
const params = await helper.getParams({ rows })
// Assert
expect(params.rows[0][0]).toHaveProperty('html', 'Bold text')
expect(params.rows[0][1]).toHaveProperty('html', 'Link')
})
it('should handle text content in cells', async () => {
// Arrange
const rows = [[{ text: 'Plain text 1' }, { text: 'Plain text 2' }]]
// Act
const params = await helper.getParams({ rows })
// Assert
expect(params.rows[0][0]).toHaveProperty('text', 'Plain text 1')
expect(params.rows[0][1]).toHaveProperty('text', 'Plain text 2')
})
it('should handle mixed HTML and text in different cells', async () => {
// Arrange
const rows = [
[
{ html: '' },
{ text: 'John Smith' },
{ html: 'Active' },
],
]
// Act
const params = await helper.getParams({ rows })
// Assert
expect(params.rows[0][0]).toHaveProperty('html')
expect(params.rows[0][1]).toHaveProperty('text', 'John Smith')
expect(params.rows[0][2]).toHaveProperty('html')
})
})
})