From b505708dddf4d0a10de72c3cd7a28b09ef01431f Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Sat, 17 May 2014 12:38:54 +0200 Subject: [PATCH] Fixed the handling of boolean attributes in ChoiceFormField An option is marked as selected by the presence of the selected attribute, not by the presence of a non-empty selected attribute. The same is true for checked radio buttons or checkboxes. --- .../DomCrawler/Field/ChoiceFormField.php | 8 ++-- .../Tests/Field/ChoiceFormFieldTest.php | 43 ++++++++++++++++++- 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php b/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php index efdcf5b922..3d582ff013 100644 --- a/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php +++ b/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php @@ -170,7 +170,7 @@ class ChoiceFormField extends FormField $option = $this->buildOptionValue($node); $this->options[] = $option; - if ($node->getAttribute('checked')) { + if ($node->hasAttribute('checked')) { $this->value = $option['value']; } } @@ -219,7 +219,7 @@ class ChoiceFormField extends FormField $optionValue = $this->buildOptionValue($this->node); $this->options[] = $optionValue; - if ($this->node->getAttribute('checked')) { + if ($this->node->hasAttribute('checked')) { $this->value = $optionValue['value']; } } else { @@ -234,7 +234,7 @@ class ChoiceFormField extends FormField foreach ($this->xpath->query('descendant::option', $this->node) as $option) { $this->options[] = $this->buildOptionValue($option); - if ($option->getAttribute('selected')) { + if ($option->hasAttribute('selected')) { $found = true; if ($this->multiple) { $this->value[] = $option->getAttribute('value'); @@ -265,7 +265,7 @@ class ChoiceFormField extends FormField $defaultValue = (isset($node->nodeValue) && !empty($node->nodeValue)) ? $node->nodeValue : '1'; $option['value'] = $node->hasAttribute('value') ? $node->getAttribute('value') : $defaultValue; - $option['disabled'] = ($node->hasAttribute('disabled') && $node->getAttribute('disabled') == 'disabled'); + $option['disabled'] = $node->hasAttribute('disabled'); return $option; } diff --git a/src/Symfony/Component/DomCrawler/Tests/Field/ChoiceFormFieldTest.php b/src/Symfony/Component/DomCrawler/Tests/Field/ChoiceFormFieldTest.php index cf7cd5a2f2..c3709abd2e 100644 --- a/src/Symfony/Component/DomCrawler/Tests/Field/ChoiceFormFieldTest.php +++ b/src/Symfony/Component/DomCrawler/Tests/Field/ChoiceFormFieldTest.php @@ -73,6 +73,11 @@ class ChoiceFormFieldTest extends FormFieldTestCase $field = new ChoiceFormField($node); $this->assertTrue($field->isMultiple(), '->isMultiple() returns true for selects with the multiple attribute'); + + $node = $this->createNode('select', '', array('multiple' => '')); + $field = new ChoiceFormField($node); + + $this->assertTrue($field->isMultiple(), '->isMultiple() returns true for selects with an empty multiple attribute'); } public function testSelects() @@ -107,6 +112,14 @@ class ChoiceFormFieldTest extends FormFieldTestCase } } + public function testSelectWithEmptyBooleanAttribute() + { + $node = $this->createSelectNode(array('foo' => false, 'bar' => true), array(), ''); + $field = new ChoiceFormField($node); + + $this->assertEquals('bar', $field->getValue()); + } + public function testMultipleSelects() { $node = $this->createSelectNode(array('foo' => false, 'bar' => false), array('multiple' => 'multiple')); @@ -166,12 +179,25 @@ class ChoiceFormFieldTest extends FormFieldTestCase } } + public function testRadioButtonsWithEmptyBooleanAttribute() + { + $node = $this->createNode('input', '', array('type' => 'radio', 'name' => 'name', 'value' => 'foo')); + $field = new ChoiceFormField($node); + $node = $this->createNode('input', '', array('type' => 'radio', 'name' => 'name', 'value' => 'bar', 'checked' => '')); + $field->addChoice($node); + + $this->assertTrue($field->hasValue(), '->hasValue() returns true when a radio button is selected'); + $this->assertEquals('bar', $field->getValue(), '->getValue() returns the value attribute of the selected radio button'); + } + public function testRadioButtonIsDisabled() { $node = $this->createNode('input', '', array('type' => 'radio', 'name' => 'name', 'value' => 'foo', 'disabled' => 'disabled')); $field = new ChoiceFormField($node); $node = $this->createNode('input', '', array('type' => 'radio', 'name' => 'name', 'value' => 'bar')); $field->addChoice($node); + $node = $this->createNode('input', '', array('type' => 'radio', 'name' => 'name', 'value' => 'baz', 'disabled' => '')); + $field->addChoice($node); $field->select('foo'); $this->assertEquals('foo', $field->getValue(), '->getValue() returns the value attribute of the selected radio button'); @@ -180,6 +206,10 @@ class ChoiceFormFieldTest extends FormFieldTestCase $field->select('bar'); $this->assertEquals('bar', $field->getValue(), '->getValue() returns the value attribute of the selected radio button'); $this->assertFalse($field->isDisabled()); + + $field->select('baz'); + $this->assertEquals('baz', $field->getValue(), '->getValue() returns the value attribute of the selected radio button'); + $this->assertTrue($field->isDisabled()); } public function testCheckboxes() @@ -225,6 +255,15 @@ class ChoiceFormFieldTest extends FormFieldTestCase } } + public function testCheckboxWithEmptyBooleanAttribute() + { + $node = $this->createNode('input', '', array('type' => 'checkbox', 'name' => 'name', 'value' => 'foo', 'checked' => '')); + $field = new ChoiceFormField($node); + + $this->assertTrue($field->hasValue(), '->hasValue() returns true when the checkbox is checked'); + $this->assertEquals('foo', $field->getValue()); + } + public function testTick() { $node = $this->createSelectNode(array('foo' => false, 'bar' => false)); @@ -284,7 +323,7 @@ class ChoiceFormFieldTest extends FormFieldTestCase $this->assertEquals('foo', $field->getValue(), '->select() changes the selected option'); } - protected function createSelectNode($options, $attributes = array()) + protected function createSelectNode($options, $attributes = array(), $selectedAttrText = 'selected') { $document = new \DOMDocument(); $node = $document->createElement('select'); @@ -298,7 +337,7 @@ class ChoiceFormFieldTest extends FormFieldTestCase $option = $document->createElement('option', $value); $option->setAttribute('value', $value); if ($selected) { - $option->setAttribute('selected', 'selected'); + $option->setAttribute('selected', $selectedAttrText); } $node->appendChild($option); }