From 939cbd8f438887ee309f9f132538d926fad57933 Mon Sep 17 00:00:00 2001 From: Airike Jaska <95303654+airikej@users.noreply.github.com> Date: Fri, 6 Feb 2026 07:30:58 +0200 Subject: [PATCH 1/3] fix(choice-group): prevent double change events and unify card click behavior #504 --- .../choice-group-item/choice-group-item.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/tedi/components/form/choice-group/components/choice-group-item/choice-group-item.tsx b/src/tedi/components/form/choice-group/components/choice-group-item/choice-group-item.tsx index 1beb291e..2d23bb54 100644 --- a/src/tedi/components/form/choice-group/components/choice-group-item/choice-group-item.tsx +++ b/src/tedi/components/form/choice-group/components/choice-group-item/choice-group-item.tsx @@ -83,16 +83,17 @@ export const ChoiceGroupItem = (props: ExtendedChoiceGroupItemProps): React.Reac const InputComponent = type === 'radio' ? Radio : Checkbox; - const handleClick = (e: React.MouseEvent) => { - if ((e.target as HTMLElement).tagName === 'LABEL') return; - if (!disabled && variant === 'card') { - onChangeHandler(value, !isChecked); - } - }; + const handleClick = (e: React.MouseEvent) => { + if (disabled || variant !== 'card') return; + + const target = e.target as HTMLElement; + if (target.closest('input, label')) return; + document.getElementById(id)?.click(); + }; return ( -
+
{variant === 'default' || showIndicator ? ( { - e.stopPropagation(); onChangeHandler(value, e.target.checked); }} className={styles['tedi-choice-group-item__input']} From c6c9f3a2e494931c6dcd622fce6ac484cb8ae373 Mon Sep 17 00:00:00 2001 From: Airike Jaska <95303654+airikej@users.noreply.github.com> Date: Fri, 6 Feb 2026 08:16:31 +0200 Subject: [PATCH 2/3] fix(choice-group): fix ChoiceGroupItem test #504 --- .../choice-group-item.spec.tsx | 53 ++++++++++--------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/src/tedi/components/form/choice-group/components/choice-group-item/choice-group-item.spec.tsx b/src/tedi/components/form/choice-group/components/choice-group-item/choice-group-item.spec.tsx index 22e97fab..27eb7b91 100644 --- a/src/tedi/components/form/choice-group/components/choice-group-item/choice-group-item.spec.tsx +++ b/src/tedi/components/form/choice-group/components/choice-group-item/choice-group-item.spec.tsx @@ -33,33 +33,27 @@ describe('ChoiceGroupItem', () => { it('renders the radio input correctly', () => { renderWithContext(); - const radioInput = screen.getByRole('radio', { name: 'Test Label' }); + const radioInput = screen.getByLabelText('Test Label'); expect(radioInput).toBeInTheDocument(); + expect(radioInput).toHaveAttribute('type', 'radio'); }); it('renders the checkbox input correctly when type is checkbox', () => { renderWithContext({ type: 'checkbox' }); - const checkboxInput = screen.getByRole('checkbox', { name: 'Test Label' }); + const checkboxInput = screen.getByLabelText('Test Label'); expect(checkboxInput).toBeInTheDocument(); + expect(checkboxInput).toHaveAttribute('type', 'checkbox'); }); it('renders the card variant correctly', () => { renderWithContext({ variant: 'card' }); - const cardInput = screen.getByRole('radio', { name: 'Test Label' }); - expect(cardInput).toBeInTheDocument(); - }); - - it('calls onChange handler when input is clicked', () => { - const onChange = jest.fn(); - renderWithContext({ onChange }, { currentValue: '', name: 'test-name', onChange, inputType: 'radio' }); - const radioInput = screen.getByRole('radio', { name: 'Test Label' }); - fireEvent.click(radioInput); - expect(onChange).toHaveBeenCalledWith('test-value', true); + const input = screen.getByLabelText('Test Label'); + expect(input).toBeInTheDocument(); }); it('renders with disabled state correctly', () => { renderWithContext({ disabled: true }); - const radioInput = screen.getByRole('radio', { name: 'Test Label' }); + const radioInput = screen.getByLabelText('Test Label'); expect(radioInput).toBeDisabled(); }); @@ -76,20 +70,9 @@ describe('ChoiceGroupItem', () => { expect(indicator).toBeInTheDocument(); }); - it('calls onChange handler when card input is clicked', () => { - const onChange = jest.fn(); - renderWithContext( - { variant: 'card', onChange }, - { currentValue: '', name: 'test-name', onChange, inputType: 'radio' } - ); - const cardInput = screen.getByRole('radio', { name: 'Test Label' }); - fireEvent.click(cardInput); - expect(onChange).toHaveBeenCalledWith('test-value', true); - }); - it('renders the card variant with disabled state correctly', () => { renderWithContext({ variant: 'card', disabled: true }); - const cardInput = screen.getByRole('radio', { name: 'Test Label' }); + const cardInput = screen.getByLabelText('Test Label'); expect(cardInput).toBeDisabled(); }); @@ -99,4 +82,24 @@ describe('ChoiceGroupItem', () => { const helperText = screen.getByText('Helper text'); expect(helperText).toBeInTheDocument(); }); + + it('calls onChange handler when label is clicked', () => { + const onChange = jest.fn(); + renderWithContext({ onChange }, { currentValue: '', name: 'test-name', onChange, inputType: 'radio' }); + const label = screen.getByText('Test Label'); + fireEvent.click(label); + expect(onChange).toHaveBeenCalled(); + }); + + it('calls onChange handler when card is clicked', () => { + const onChange = jest.fn(); + renderWithContext( + { variant: 'card', onChange }, + { currentValue: '', name: 'test-name', onChange, inputType: 'radio' } + ); + + const card = screen.getByText('Test Label'); + fireEvent.click(card); + expect(onChange).toHaveBeenCalled(); + }); }); From e5ecaf360227342cb5ad86df16e7cae9f15fe280 Mon Sep 17 00:00:00 2001 From: Airike Jaska <95303654+airikej@users.noreply.github.com> Date: Fri, 6 Feb 2026 08:25:10 +0200 Subject: [PATCH 3/3] fix(choice-group): add more test to cover the line coverage #504 --- .../choice-group-item.spec.tsx | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/tedi/components/form/choice-group/components/choice-group-item/choice-group-item.spec.tsx b/src/tedi/components/form/choice-group/components/choice-group-item/choice-group-item.spec.tsx index 27eb7b91..1e2d8c94 100644 --- a/src/tedi/components/form/choice-group/components/choice-group-item/choice-group-item.spec.tsx +++ b/src/tedi/components/form/choice-group/components/choice-group-item/choice-group-item.spec.tsx @@ -102,4 +102,27 @@ describe('ChoiceGroupItem', () => { fireEvent.click(card); expect(onChange).toHaveBeenCalled(); }); + + it('programmatically clicks the input when card background is clicked', () => { + renderWithContext({ variant: 'card' }); + + const input = screen.getByLabelText('Test Label') as HTMLInputElement; + const clickSpy = jest.spyOn(input, 'click'); + const card = input.closest('.tedi-choice-group-item') as HTMLElement; + fireEvent.click(card); + + expect(clickSpy).toHaveBeenCalledTimes(1); + clickSpy.mockRestore(); + }); + + it('does NOT programmatically click input when clicking the native input directly', () => { + const mockInputClick = jest.fn(); + const mockInput = { click: mockInputClick } as unknown as HTMLInputElement; + + jest.spyOn(document, 'getElementById').mockReturnValue(mockInput); + renderWithContext({ variant: 'card' }); + const input = screen.getByLabelText('Test Label'); + fireEvent.click(input); + expect(mockInputClick).not.toHaveBeenCalled(); + }); });