import { GovukComponentTestHelper } from '../../test-utils/GovukComponentTestHelper' import { setupComponentTest } from '../../test-utils/setupComponentTest' import { GovUKTaskList } from './govukTaskList' vi.mock('nunjucks') describe('GOV.UK Task List Component', () => { setupComponentTest() const helper = new GovukComponentTestHelper(GovUKTaskList) describe('Item data transformation', () => { it('sets single item with title and status correctly', async () => { // Arrange & Act const params = await helper.getParams({ items: [ { title: { text: 'Company information' }, status: { tag: { text: 'Completed' }, }, }, ], }) // Assert expect(params.items).toHaveLength(1) expect(params.items[0]).toEqual({ title: { text: 'Company information' }, status: { tag: { text: 'Completed' }, }, }) }) it('sets item with href correctly', async () => { // Arrange & Act const params = await helper.getParams({ items: [ { title: { text: 'Company information' }, href: '/company-info', status: { tag: { text: 'Completed' }, }, }, ], }) // Assert expect(params.items[0].href).toBe('/company-info') }) it('sets multiple items correctly', async () => { // Arrange & Act const params = await helper.getParams({ items: [ { title: { text: 'Company information' }, href: '/company-info', status: { tag: { text: 'Completed', classes: 'govuk-tag--blue' }, }, }, { title: { text: 'Contact details' }, href: '/contact-details', status: { tag: { text: 'In progress', classes: 'govuk-tag--blue' }, }, }, { title: { text: 'Submit application' }, status: { text: 'Cannot start yet', }, }, ], }) // Assert expect(params.items).toHaveLength(3) expect(params.items[0].title.text).toBe('Company information') expect(params.items[0].href).toBe('/company-info') expect(params.items[1].title.text).toBe('Contact details') expect(params.items[1].href).toBe('/contact-details') expect(params.items[2].title.text).toBe('Submit application') expect(params.items[2].href).toBeUndefined() }) it('sets item classes correctly', async () => { // Arrange & Act const params = await helper.getParams({ items: [ { title: { text: 'Company information' }, status: { tag: { text: 'Completed' } }, classes: 'app-task-list__item--custom', }, ], }) // Assert expect(params.items[0].classes).toBe('app-task-list__item--custom') }) }) describe('Title options', () => { it('sets title with text content', async () => { // Arrange & Act const params = await helper.getParams({ items: [ { title: { text: 'Company information' }, status: { tag: { text: 'Completed' } }, }, ], }) // Assert expect(params.items[0].title.text).toBe('Company information') expect(params.items[0].title.html).toBeUndefined() }) it('sets title with html content', async () => { // Arrange & Act const params = await helper.getParams({ items: [ { title: { html: 'Company information' }, status: { tag: { text: 'Completed' } }, }, ], }) // Assert expect(params.items[0].title.html).toBe('Company information') expect(params.items[0].title.text).toBeUndefined() }) it('sets title with classes', async () => { // Arrange & Act const params = await helper.getParams({ items: [ { title: { text: 'Company information', classes: 'app-task-list__title--custom' }, status: { tag: { text: 'Completed' } }, }, ], }) // Assert expect(params.items[0].title.classes).toBe('app-task-list__title--custom') }) }) describe('Hint', () => { it('sets hint with text content', async () => { // Arrange & Act const params = await helper.getParams({ items: [ { title: { text: 'Contact details' }, hint: { text: 'Include email and phone number' }, status: { tag: { text: 'In progress' } }, }, ], }) // Assert expect(params.items[0].hint).toBeDefined() expect(params.items[0].hint?.text).toBe('Include email and phone number') expect(params.items[0].hint?.html).toBeUndefined() }) it('sets hint with html content', async () => { // Arrange & Act const params = await helper.getParams({ items: [ { title: { text: 'Contact details' }, hint: { html: 'Include email and phone number' }, status: { tag: { text: 'In progress' } }, }, ], }) // Assert expect(params.items[0].hint?.html).toBe('Include email and phone number') expect(params.items[0].hint?.text).toBeUndefined() }) it('handles item without hint', async () => { // Arrange & Act const params = await helper.getParams({ items: [ { title: { text: 'Company information' }, status: { tag: { text: 'Completed' } }, }, ], }) // Assert expect(params.items[0].hint).toBeUndefined() }) }) describe('Status', () => { it('sets status with tag', async () => { // Arrange & Act const params = await helper.getParams({ items: [ { title: { text: 'Company information' }, status: { tag: { text: 'Completed' }, }, }, ], }) // Assert expect(params.items[0].status.tag).toBeDefined() expect(params.items[0].status.tag?.text).toBe('Completed') }) it('sets status tag with html content', async () => { // Arrange & Act const params = await helper.getParams({ items: [ { title: { text: 'Company information' }, status: { tag: { html: 'Completed' }, }, }, ], }) // Assert expect(params.items[0].status.tag?.html).toBe('Completed') expect(params.items[0].status.tag?.text).toBeUndefined() }) it('sets status tag with classes for blue color', async () => { // Arrange & Act const params = await helper.getParams({ items: [ { title: { text: 'Company information' }, status: { tag: { text: 'Completed', classes: 'govuk-tag--blue' }, }, }, ], }) // Assert expect(params.items[0].status.tag?.classes).toBe('govuk-tag--blue') }) it('sets status tag with classes for light blue color', async () => { // Arrange & Act const params = await helper.getParams({ items: [ { title: { text: 'Contact details' }, status: { tag: { text: 'In progress', classes: 'govuk-tag--blue' }, }, }, ], }) // Assert expect(params.items[0].status.tag?.classes).toBe('govuk-tag--blue') }) it('sets status tag with classes for grey color', async () => { // Arrange & Act const params = await helper.getParams({ items: [ { title: { text: 'Payment details' }, status: { tag: { text: 'Not started', classes: 'govuk-tag--grey' }, }, }, ], }) // Assert expect(params.items[0].status.tag?.classes).toBe('govuk-tag--grey') }) it('sets status tag with attributes', async () => { // Arrange & Act const params = await helper.getParams({ items: [ { title: { text: 'Company information' }, status: { tag: { text: 'Completed', attributes: { 'data-status': 'complete', }, }, }, }, ], }) // Assert expect(params.items[0].status.tag?.attributes).toEqual({ 'data-status': 'complete', }) }) it('sets status with text only', async () => { // Arrange & Act const params = await helper.getParams({ items: [ { title: { text: 'Submit application' }, status: { text: 'Cannot start yet', }, }, ], }) // Assert expect(params.items[0].status.text).toBe('Cannot start yet') expect(params.items[0].status.tag).toBeUndefined() expect(params.items[0].status.html).toBeUndefined() }) it('sets status with html only', async () => { // Arrange & Act const params = await helper.getParams({ items: [ { title: { text: 'Submit application' }, status: { html: 'Cannot start yet', }, }, ], }) // Assert expect(params.items[0].status.html).toBe('Cannot start yet') expect(params.items[0].status.tag).toBeUndefined() expect(params.items[0].status.text).toBeUndefined() }) it('sets status with classes', async () => { // Arrange & Act const params = await helper.getParams({ items: [ { title: { text: 'Submit application' }, status: { text: 'Cannot start yet', classes: 'app-task-list__status--custom', }, }, ], }) // Assert expect(params.items[0].status.classes).toBe('app-task-list__status--custom') }) }) describe('Optional attributes', () => { it('passes through idPrefix', async () => { // Arrange & Act const params = await helper.getParams({ idPrefix: 'registration', items: [ { title: { text: 'Company information' }, status: { tag: { text: 'Completed' } }, }, ], }) // Assert expect(params.idPrefix).toBe('registration') }) it('passes through classes', async () => { // Arrange & Act const params = await helper.getParams({ items: [ { title: { text: 'Company information' }, status: { tag: { text: 'Completed' } }, }, ], classes: 'app-task-list--custom', }) // Assert expect(params.classes).toBe('app-task-list--custom') }) it('passes through attributes', async () => { // Arrange & Act const params = await helper.getParams({ items: [ { title: { text: 'Company information' }, status: { tag: { text: 'Completed' } }, }, ], attributes: { 'data-module': 'task-list', 'data-track': 'tasks-shown', }, }) // Assert expect(params.attributes).toEqual({ 'data-module': 'task-list', 'data-track': 'tasks-shown', }) }) it('handles all options together', async () => { // Arrange & Act const params = await helper.getParams({ idPrefix: 'application', items: [ { title: { text: 'Company information', classes: 'title-class' }, hint: { text: 'Provide your company details' }, href: '/company-info', status: { tag: { text: 'Completed', classes: 'govuk-tag--blue', attributes: { 'data-status': 'complete' }, }, classes: 'status-class', }, classes: 'item-class', }, ], classes: 'list-class', attributes: { 'data-list': 'true', }, }) // Assert expect(params.idPrefix).toBe('application') expect(params.items[0].title.classes).toBe('title-class') expect(params.items[0].hint?.text).toBe('Provide your company details') expect(params.items[0].href).toBe('/company-info') expect(params.items[0].status.tag?.text).toBe('Completed') expect(params.items[0].status.tag?.classes).toBe('govuk-tag--blue') expect(params.items[0].status.tag?.attributes).toEqual({ 'data-status': 'complete' }) expect(params.items[0].status.classes).toBe('status-class') expect(params.items[0].classes).toBe('item-class') expect(params.classes).toBe('list-class') expect(params.attributes).toEqual({ 'data-list': 'true' }) }) }) describe('Template and context', () => { it('calls nunjucks with correct template path', async () => { // Arrange & Act const { template } = await helper.executeComponent({ items: [ { title: { text: 'Company information' }, status: { tag: { text: 'Completed' } }, }, ], }) // Assert expect(template).toBe('govuk/components/task-list/template.njk') }) it('wraps params in correct context structure', async () => { // Arrange & Act const { context } = (await helper.executeComponent({ items: [ { title: { text: 'Company information' }, href: '/company-info', status: { tag: { text: 'Completed', classes: 'govuk-tag--blue' }, }, }, ], classes: 'app-task-list--custom', })) as { context: { params: any } } // Assert expect(context).toHaveProperty('params') expect(context.params.items).toHaveLength(1) expect(context.params.items[0].title.text).toBe('Company information') expect(context.params.classes).toBe('app-task-list--custom') }) }) describe('DOM rendering smoke test', () => { it('renders task list with basic items', async () => { // Arrange & Act const html = await helper.renderWithNunjucks({ items: [ { title: { text: 'Company information' }, href: '/company-info', status: { tag: { text: 'Completed', classes: 'govuk-tag--blue' }, }, }, { title: { text: 'Contact details' }, href: '/contact-details', status: { tag: { text: 'In progress', classes: 'govuk-tag--blue' }, }, }, ], }) // Assert expect(html).toContain('govuk-task-list') expect(html).toContain('Company information') expect(html).toContain('/company-info') expect(html).toContain('Completed') expect(html).toContain('Contact details') expect(html).toContain('/contact-details') expect(html).toContain('In progress') }) it('renders task list with hints', async () => { // Arrange & Act const html = await helper.renderWithNunjucks({ items: [ { title: { text: 'Contact details' }, hint: { text: 'Include email and phone number' }, href: '/contact-details', status: { tag: { text: 'In progress' }, }, }, ], }) // Assert expect(html).toContain('govuk-task-list') expect(html).toContain('Contact details') expect(html).toContain('Include email and phone number') }) it('renders task list with text-only status', async () => { // Arrange & Act const html = await helper.renderWithNunjucks({ items: [ { title: { text: 'Submit application' }, status: { text: 'Cannot start yet', }, }, ], }) // Assert expect(html).toContain('govuk-task-list') expect(html).toContain('Submit application') expect(html).toContain('Cannot start yet') }) it('renders task list with item without href', async () => { // Arrange & Act const html = await helper.renderWithNunjucks({ items: [ { title: { text: 'Submit application' }, status: { text: 'Cannot start yet', }, }, ], }) // Assert expect(html).toContain('govuk-task-list') expect(html).toContain('Submit application') expect(html).not.toContain('href') }) it('renders task list with HTML content', async () => { // Arrange & Act const html = await helper.renderWithNunjucks({ items: [ { title: { html: 'Company information' }, hint: { html: 'Provide all details' }, href: '/company-info', status: { tag: { html: 'Completed' }, }, }, ], }) // Assert expect(html).toContain('govuk-task-list') expect(html).toContain('Company information') expect(html).toContain('all details') expect(html).toContain('Completed') }) it('renders task list with custom classes', async () => { // Arrange & Act const html = await helper.renderWithNunjucks({ items: [ { title: { text: 'Company information' }, status: { tag: { text: 'Completed' } }, }, ], classes: 'app-task-list--custom', }) // Assert expect(html).toContain('govuk-task-list') expect(html).toContain('app-task-list--custom') }) it('renders task list with custom idPrefix', async () => { // Arrange & Act const html = await helper.renderWithNunjucks({ idPrefix: 'registration', items: [ { title: { text: 'Personal details' }, status: { tag: { text: 'Completed' } }, }, ], }) // Assert expect(html).toContain('govuk-task-list') expect(html).toContain('registration') }) it('renders task list with colored tags', async () => { // Arrange & Act const html = await helper.renderWithNunjucks({ items: [ { title: { text: 'Task 1' }, status: { tag: { text: 'Completed', classes: 'govuk-tag--blue' }, }, }, { title: { text: 'Task 2' }, status: { tag: { text: 'In progress', classes: 'govuk-tag--blue' }, }, }, { title: { text: 'Task 3' }, status: { tag: { text: 'Not started', classes: 'govuk-tag--grey' }, }, }, ], }) // Assert expect(html).toContain('govuk-task-list') expect(html).toContain('govuk-tag--blue') expect(html).toContain('govuk-tag--blue') expect(html).toContain('govuk-tag--grey') }) }) describe('Conditional item visibility', () => { it('omits items where visibleWhen evaluates to false', async () => { // Arrange & Act const params = await helper.getParams({ items: [ { title: { text: 'Company information' }, status: { tag: { text: 'Completed' } }, }, { title: { text: 'Upload photo' }, status: { tag: { text: 'Not started' } }, visibleWhen: false, }, { title: { text: 'Submit' }, status: { tag: { text: 'Cannot start yet' } }, visibleWhen: true, }, ], }) // Assert expect(params.items).toHaveLength(2) expect(params.items[0].title.text).toBe('Company information') expect(params.items[1].title.text).toBe('Submit') }) it('keeps items where visibleWhen is undefined', async () => { // Arrange & Act const params = await helper.getParams({ items: [ { title: { text: 'Company information' }, status: { tag: { text: 'Completed' } }, }, ], }) // Assert expect(params.items).toHaveLength(1) }) }) })