diff --git a/src/Inputs/RadioInput.php b/src/Inputs/RadioInput.php index 749549a..3873739 100644 --- a/src/Inputs/RadioInput.php +++ b/src/Inputs/RadioInput.php @@ -46,6 +46,9 @@ public function getControl(): Html $items = $this->getItems(); $container = $this->container; + // one attribute on the fieldset disables every radio inside it, the same + // way CheckboxListInput handles a wholly disabled control + $container->setAttribute('disabled', $this->isControlDisabled()); $c = 0; $htmlId = $this->getHtmlId(); diff --git a/tests/E2E/FormSubmissionTest.php b/tests/E2E/FormSubmissionTest.php index c25fc69..7e9317c 100644 --- a/tests/E2E/FormSubmissionTest.php +++ b/tests/E2E/FormSubmissionTest.php @@ -261,6 +261,25 @@ function (): BootstrapForm { $this->assertNull($form['country']->getValue()); } + public function testWhollyDisabledRadioListIsRenderedDisabledAndRejectsItsPost(): void + { + $form = $this->submit( + function (): BootstrapForm { + $form = new BootstrapForm(); + $form->setAction('/'); + $form->addRadioList('size', 'Size', ['s' => 'Small', 'l' => 'Large']) + ->setDisabled(true); + $form->addSubmit('send'); + + return $form; + }, + ['size' => 's'] + ); + + $this->assertNull($form['size']->getValue()); + $this->assertStringContainsString('
', (string) $form['size']->getControl()); + } + public function testCheckboxListCollectsEveryCheckedValue(): void { $form = $this->submit( diff --git a/tests/Inputs/RadioInputTest.php b/tests/Inputs/RadioInputTest.php index 96be1a6..2de5379 100644 --- a/tests/Inputs/RadioInputTest.php +++ b/tests/Inputs/RadioInputTest.php @@ -16,6 +16,22 @@ public function testRadioInput(): void $this->assertEquals('
', (string) $input->getControl()); } + public function testDisabledRadioInput(): void + { + $form = new BootstrapForm(); + $input = $form->addRadioList('txt', 'lbl', [1 => '1', 2 => '2']); + $input->setDisabled(true); + $this->assertEquals('
', (string) $input->getControl()); + } + + public function testRadioInputWithSingleDisabledItem(): void + { + $form = new BootstrapForm(); + $input = $form->addRadioList('txt', 'lbl', [1 => '1', 2 => '2']); + $input->setDisabled([1]); + $this->assertEquals('
', (string) $input->getControl()); + } + public function testRadioInputV5(): void { BootstrapForm::switchBootstrapVersion(BootstrapVersion::V5); diff --git a/tests/Traits/ChoiceInputTraitTest.php b/tests/Traits/ChoiceInputTraitTest.php index 3c3d7a4..d8905d7 100644 --- a/tests/Traits/ChoiceInputTraitTest.php +++ b/tests/Traits/ChoiceInputTraitTest.php @@ -13,22 +13,41 @@ class ChoiceInputTraitTest extends BaseTestCase { - /** - * Known gap: RadioInput::getControl() only ever asks isValueDisabled() per - * item and never calls isControlDisabled(), so a radio list disabled as a - * whole still renders as interactive. CheckboxListInput and SelectInput both - * put the attribute on their element. Pinned here so that fixing RadioInput - * shows up as a failure of this test rather than going unnoticed. - */ - public function testDisablingTheWholeRadioListIsNotReflectedInTheHtml(): void + public function testWholeRadioListIsDisabledThroughItsFieldset(): void { $form = new BootstrapForm(); $radio = $form->addRadioList('a', 'b', ['x' => 'X', 'y' => 'Y']); $radio->setDisabled(true); + $html = (string) $radio->getControl(); + + // one attribute on the fieldset disables every radio inside it + $this->assertStringStartsWith('
', $html); + $this->assertSame(1, substr_count($html, 'disabled')); + } + + public function testReEnablingTheWholeRadioListDropsTheAttributeAgain(): void + { + $form = new BootstrapForm(); + $radio = $form->addRadioList('a', 'b', ['x' => 'X', 'y' => 'Y']); + $radio->setDisabled(true); + $radio->setDisabled(false); + $this->assertStringNotContainsString('disabled', (string) $radio->getControl()); } + public function testDisabledRadioListKeepsItsFieldsetAttributeThroughValidationState(): void + { + $form = new BootstrapForm(); + $radio = $form->addRadioList('a', 'b', ['x' => 'X', 'y' => 'Y']); + $radio->setDisabled(true); + $radio->addError('nope'); + + $html = (string) $radio->showValidation($radio->getControl()); + + $this->assertStringStartsWith('
', $html); + } + public function testDisablingRadioListClearsWhateverWasSelected(): void { $form = new BootstrapForm();