* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\Extension\Core\Type\ButtonType; use Symfony\Component\Form\Extension\Core\Type\CheckboxType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\DateType; use Symfony\Component\Form\Extension\Core\Type\FileType; use Symfony\Component\Form\Extension\Core\Type\MoneyType; use Symfony\Component\Form\Extension\Core\Type\PercentType; use Symfony\Component\Form\Extension\Core\Type\RadioType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormError; /** * Abstract class providing test cases for the Bootstrap 4 Twig form theme. * * @author Hidde Wieringa */ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest { public function testRow() { $form = $this->factory->createNamed('name', TextType::class); $form->addError(new FormError('[trans]Error![/trans]')); $view = $form->createView(); $html = $this->renderRow($view); $this->assertMatchesXpath($html, '/div [ ./label[@for="name"] [ ./span[@class="alert alert-danger d-block"] [./span[@class="mb-0 d-block"] [./span[.="[trans]Error[/trans]"]] [./span[.="[trans]Error![/trans]"]] ] [count(./span)=1] ] /following-sibling::input[@id="name"] ] ' ); } public function testLabelOnForm() { $form = $this->factory->createNamed('name', DateType::class); $view = $form->createView(); $this->renderWidget($view, array('label' => 'foo')); $html = $this->renderLabel($view); $this->assertMatchesXpath($html, '/legend [@class="col-form-label required"] [.="[trans]Name[/trans]"] ' ); } public function testLabelDoesNotRenderFieldAttributes() { $form = $this->factory->createNamed('name', TextType::class); $html = $this->renderLabel($form->createView(), null, array( 'attr' => array( 'class' => 'my&class', ), )); $this->assertMatchesXpath($html, '/label [@for="name"] [@class="form-control-label required"] ' ); } public function testLabelWithCustomAttributesPassedDirectly() { $form = $this->factory->createNamed('name', TextType::class); $html = $this->renderLabel($form->createView(), null, array( 'label_attr' => array( 'class' => 'my&class', ), )); $this->assertMatchesXpath($html, '/label [@for="name"] [@class="my&class form-control-label required"] ' ); } public function testLabelWithCustomTextAndCustomAttributesPassedDirectly() { $form = $this->factory->createNamed('name', TextType::class); $html = $this->renderLabel($form->createView(), 'Custom label', array( 'label_attr' => array( 'class' => 'my&class', ), )); $this->assertMatchesXpath($html, '/label [@for="name"] [@class="my&class form-control-label required"] [.="[trans]Custom label[/trans]"] ' ); } public function testLabelWithCustomTextAsOptionAndCustomAttributesPassedDirectly() { $form = $this->factory->createNamed('name', TextType::class, null, array( 'label' => 'Custom label', )); $html = $this->renderLabel($form->createView(), null, array( 'label_attr' => array( 'class' => 'my&class', ), )); $this->assertMatchesXpath($html, '/label [@for="name"] [@class="my&class form-control-label required"] [.="[trans]Custom label[/trans]"] ' ); } public function testLegendOnExpandedType() { $form = $this->factory->createNamed('name', ChoiceType::class, null, array( 'label' => 'Custom label', 'expanded' => true, 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'), )); $view = $form->createView(); $this->renderWidget($view); $html = $this->renderLabel($view); $this->assertMatchesXpath($html, '/legend [@class="col-form-label required"] [.="[trans]Custom label[/trans]"] ' ); } public function testErrors() { $form = $this->factory->createNamed('name', TextType::class); $form->addError(new FormError('[trans]Error 1[/trans]')); $form->addError(new FormError('[trans]Error 2[/trans]')); $view = $form->createView(); $html = $this->renderErrors($view); $this->assertMatchesXpath($html, '/span [@class="alert alert-danger d-block"] [ ./span[@class="mb-0 d-block"] [./span[.="[trans]Error[/trans]"]] [./span[.="[trans]Error 1[/trans]"]] /following-sibling::span[@class="mb-0 d-block"] [./span[.="[trans]Error[/trans]"]] [./span[.="[trans]Error 2[/trans]"]] ] [count(./span)=2] ' ); } public function testErrorWithNoLabel() { $form = $this->factory->createNamed('name', TextType::class, array('label' => false)); $form->addError(new FormError('[trans]Error 1[/trans]')); $view = $form->createView(); $html = $this->renderLabel($view); $this->assertMatchesXpath($html, '//span[.="[trans]Error[/trans]"]'); } public function testCheckedCheckbox() { $form = $this->factory->createNamed('name', CheckboxType::class, true); $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')), '/div [@class="form-check"] [ ./input[@type="checkbox"][@name="name"][@id="my&id"][@class="my&class form-check-input"][@checked="checked"][@value="1"] /following-sibling::label [.="[trans]Name[/trans]"] [@class="form-check-label required"] ] ' ); } public function testSingleChoiceAttributesWithMainAttributes() { $form = $this->factory->createNamed('name', ChoiceType::class, '&a', array( 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'), 'multiple' => false, 'expanded' => false, 'attr' => array('class' => 'bar&baz'), )); $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'bar&baz')), '/select [@name="name"] [@class="bar&baz form-control"] [not(@required)] [ ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] [count(./option)=2] ' ); } public function testSingleExpandedChoiceAttributesWithMainAttributes() { $form = $this->factory->createNamed('name', ChoiceType::class, '&a', array( 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'), 'multiple' => false, 'expanded' => true, 'attr' => array('class' => 'bar&baz'), )); $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'bar&baz')), '/div [@class="bar&baz"] [ ./div [@class="form-check"] [ ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] /following-sibling::label [.="[trans]Choice&A[/trans]"] ] /following-sibling::div [@class="form-check"] [ ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)] /following-sibling::label [.="[trans]Choice&B[/trans]"] ] /following-sibling::input[@type="hidden"][@id="name__token"] ] ' ); } public function testUncheckedCheckbox() { $form = $this->factory->createNamed('name', CheckboxType::class, false); $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')), '/div [@class="form-check"] [ ./input[@type="checkbox"][@name="name"][@id="my&id"][@class="my&class form-check-input"][not(@checked)] /following-sibling::label [.="[trans]Name[/trans]"] ] ' ); } public function testCheckboxWithValue() { $form = $this->factory->createNamed('name', CheckboxType::class, false, array( 'value' => 'foo&bar', )); $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')), '/div [@class="form-check"] [ ./input[@type="checkbox"][@name="name"][@id="my&id"][@class="my&class form-check-input"][@value="foo&bar"] /following-sibling::label [.="[trans]Name[/trans]"] ] ' ); } public function testSingleChoiceExpanded() { $form = $this->factory->createNamed('name', ChoiceType::class, '&a', array( 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'), 'multiple' => false, 'expanded' => true, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [@class="form-check"] [ ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] /following-sibling::label [.="[trans]Choice&A[/trans]"] ] /following-sibling::div [@class="form-check"] [ ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)] /following-sibling::label [.="[trans]Choice&B[/trans]"] ] /following-sibling::input[@type="hidden"][@id="name__token"] ] ' ); } public function testSingleChoiceExpandedWithLabelsAsFalse() { $form = $this->factory->createNamed('name', ChoiceType::class, '&a', array( 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'), 'choice_label' => false, 'multiple' => false, 'expanded' => true, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [@class="form-check"] [ ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] /following-sibling::label ] /following-sibling::div [@class="form-check"] [ ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)] /following-sibling::label ] /following-sibling::input[@type="hidden"][@id="name__token"] ] ' ); } public function testSingleChoiceExpandedWithLabelsSetByCallable() { $form = $this->factory->createNamed('name', ChoiceType::class, '&a', array( 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'), 'choice_label' => function ($choice, $label, $value) { if ('&b' === $choice) { return false; } return 'label.'.$value; }, 'multiple' => false, 'expanded' => true, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [@class="form-check"] [ ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] /following-sibling::label [.="[trans]label.&a[/trans]"] ] /following-sibling::div [@class="form-check"] [ ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)] /following-sibling::label ] /following-sibling::div [@class="form-check"] [ ./input[@type="radio"][@name="name"][@id="name_2"][@value="&c"][not(@checked)] /following-sibling::label [.="[trans]label.&c[/trans]"] ] /following-sibling::input[@type="hidden"][@id="name__token"] ] ' ); } public function testSingleChoiceExpandedWithLabelsSetFalseByCallable() { $form = $this->factory->createNamed('name', ChoiceType::class, '&a', array( 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'), 'choice_label' => function () { return false; }, 'multiple' => false, 'expanded' => true, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [@class="form-check"] [ ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] /following-sibling::label ] /following-sibling::div [@class="form-check"] [ ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)] /following-sibling::label ] /following-sibling::input[@type="hidden"][@id="name__token"] ] ' ); } public function testSingleChoiceExpandedWithoutTranslation() { $form = $this->factory->createNamed('name', ChoiceType::class, '&a', array( 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'), 'multiple' => false, 'expanded' => true, 'choice_translation_domain' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [@class="form-check"] [ ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] /following-sibling::label [.="Choice&A"] ] /following-sibling::div [@class="form-check"] [ ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)] /following-sibling::label [.="Choice&B"] ] /following-sibling::input[@type="hidden"][@id="name__token"] ] ' ); } public function testSingleChoiceExpandedAttributes() { $form = $this->factory->createNamed('name', ChoiceType::class, '&a', array( 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'), 'choice_attr' => array('Choice&B' => array('class' => 'foo&bar')), 'multiple' => false, 'expanded' => true, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [@class="form-check"] [ ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] /following-sibling::label [.="[trans]Choice&A[/trans]"] ] /following-sibling::div [@class="form-check"] [ ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)][@class="foo&bar form-check-input"] /following-sibling::label [.="[trans]Choice&B[/trans]"] ] /following-sibling::input[@type="hidden"][@id="name__token"] ] ' ); } public function testSingleChoiceExpandedWithPlaceholder() { $form = $this->factory->createNamed('name', ChoiceType::class, '&a', array( 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'), 'multiple' => false, 'expanded' => true, 'placeholder' => 'Test&Me', 'required' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [@class="form-check"] [ ./input[@type="radio"][@name="name"][@id="name_placeholder"][not(@checked)] /following-sibling::label [.="[trans]Test&Me[/trans]"] ] /following-sibling::div [@class="form-check"] [ ./input[@type="radio"][@name="name"][@id="name_0"][@checked] /following-sibling::label [.="[trans]Choice&A[/trans]"] ] /following-sibling::div [@class="form-check"] [ ./input[@type="radio"][@name="name"][@id="name_1"][not(@checked)] /following-sibling::label [.="[trans]Choice&B[/trans]"] ] /following-sibling::input[@type="hidden"][@id="name__token"] ] ' ); } public function testSingleChoiceExpandedWithPlaceholderWithoutTranslation() { $form = $this->factory->createNamed('name', ChoiceType::class, '&a', array( 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'), 'multiple' => false, 'expanded' => true, 'required' => false, 'choice_translation_domain' => false, 'placeholder' => 'Placeholder&Not&Translated', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [@class="form-check"] [ ./input[@type="radio"][@name="name"][@id="name_placeholder"][not(@checked)] /following-sibling::label [.="Placeholder&Not&Translated"] ] /following-sibling::div [@class="form-check"] [ ./input[@type="radio"][@name="name"][@id="name_0"][@checked] /following-sibling::label [.="Choice&A"] ] /following-sibling::div [@class="form-check"] [ ./input[@type="radio"][@name="name"][@id="name_1"][not(@checked)] /following-sibling::label [.="Choice&B"] ] /following-sibling::input[@type="hidden"][@id="name__token"] ] ' ); } public function testSingleChoiceExpandedWithBooleanValue() { $form = $this->factory->createNamed('name', ChoiceType::class, true, array( 'choices' => array('Choice&A' => '1', 'Choice&B' => '0'), 'multiple' => false, 'expanded' => true, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [@class="form-check"] [ ./input[@type="radio"][@name="name"][@id="name_0"][@checked] /following-sibling::label [.="[trans]Choice&A[/trans]"] ] /following-sibling::div [@class="form-check"] [ ./input[@type="radio"][@name="name"][@id="name_1"][not(@checked)] /following-sibling::label [.="[trans]Choice&B[/trans]"] ] /following-sibling::input[@type="hidden"][@id="name__token"] ] ' ); } public function testMultipleChoiceExpanded() { $form = $this->factory->createNamed('name', ChoiceType::class, array('&a', '&c'), array( 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'), 'multiple' => true, 'expanded' => true, 'required' => true, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [@class="form-check"] [ ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@checked][not(@required)] /following-sibling::label [.="[trans]Choice&A[/trans]"] ] /following-sibling::div [@class="form-check"] [ ./input[@type="checkbox"][@name="name[]"][@id="name_1"][not(@checked)][not(@required)] /following-sibling::label [.="[trans]Choice&B[/trans]"] ] /following-sibling::div [@class="form-check"] [ ./input[@type="checkbox"][@name="name[]"][@id="name_2"][@checked][not(@required)] /following-sibling::label [.="[trans]Choice&C[/trans]"] ] /following-sibling::input[@type="hidden"][@id="name__token"] ] ' ); } public function testMultipleChoiceExpandedWithLabelsAsFalse() { $form = $this->factory->createNamed('name', ChoiceType::class, array('&a'), array( 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'), 'choice_label' => false, 'multiple' => true, 'expanded' => true, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [@class="form-check"] [ ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@value="&a"][@checked] /following-sibling::label ] /following-sibling::div [@class="form-check"] [ ./input[@type="checkbox"][@name="name[]"][@id="name_1"][@value="&b"][not(@checked)] /following-sibling::label ] /following-sibling::input[@type="hidden"][@id="name__token"] ] ' ); } public function testMultipleChoiceExpandedWithLabelsSetByCallable() { $form = $this->factory->createNamed('name', ChoiceType::class, array('&a'), array( 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'), 'choice_label' => function ($choice, $label, $value) { if ('&b' === $choice) { return false; } return 'label.'.$value; }, 'multiple' => true, 'expanded' => true, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [@class="form-check"] [ ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@value="&a"][@checked] /following-sibling::label [.="[trans]label.&a[/trans]"] ] /following-sibling::div [@class="form-check"] [ ./input[@type="checkbox"][@name="name[]"][@id="name_1"][@value="&b"][not(@checked)] /following-sibling::label ] /following-sibling::div [@class="form-check"] [ ./input[@type="checkbox"][@name="name[]"][@id="name_2"][@value="&c"][not(@checked)] /following-sibling::label [.="[trans]label.&c[/trans]"] ] /following-sibling::input[@type="hidden"][@id="name__token"] ] ' ); } public function testMultipleChoiceExpandedWithLabelsSetFalseByCallable() { $form = $this->factory->createNamed('name', ChoiceType::class, array('&a'), array( 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'), 'choice_label' => function () { return false; }, 'multiple' => true, 'expanded' => true, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [@class="form-check"] [ ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@value="&a"][@checked] /following-sibling::label ] /following-sibling::div [@class="form-check"] [ ./input[@type="checkbox"][@name="name[]"][@id="name_1"][@value="&b"][not(@checked)] /following-sibling::label ] /following-sibling::input[@type="hidden"][@id="name__token"] ] ' ); } public function testMultipleChoiceExpandedWithoutTranslation() { $form = $this->factory->createNamed('name', ChoiceType::class, array('&a', '&c'), array( 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'), 'multiple' => true, 'expanded' => true, 'required' => true, 'choice_translation_domain' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [@class="form-check"] [ ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@checked][not(@required)] /following-sibling::label [.="Choice&A"] ] /following-sibling::div [@class="form-check"] [ ./input[@type="checkbox"][@name="name[]"][@id="name_1"][not(@checked)][not(@required)] /following-sibling::label [.="Choice&B"] ] /following-sibling::div [@class="form-check"] [ ./input[@type="checkbox"][@name="name[]"][@id="name_2"][@checked][not(@required)] /following-sibling::label [.="Choice&C"] ] /following-sibling::input[@type="hidden"][@id="name__token"] ] ' ); } public function testMultipleChoiceExpandedAttributes() { $form = $this->factory->createNamed('name', ChoiceType::class, array('&a', '&c'), array( 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'), 'choice_attr' => array('Choice&B' => array('class' => 'foo&bar')), 'multiple' => true, 'expanded' => true, 'required' => true, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [@class="form-check"] [ ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@checked][not(@required)] /following-sibling::label [.="[trans]Choice&A[/trans]"] ] /following-sibling::div [@class="form-check"] [ ./input[@type="checkbox"][@name="name[]"][@id="name_1"][not(@checked)][not(@required)][@class="foo&bar form-check-input"] /following-sibling::label [.="[trans]Choice&B[/trans]"] ] /following-sibling::div [@class="form-check"] [ ./input[@type="checkbox"][@name="name[]"][@id="name_2"][@checked][not(@required)] /following-sibling::label [.="[trans]Choice&C[/trans]"] ] /following-sibling::input[@type="hidden"][@id="name__token"] ] ' ); } public function testCheckedRadio() { $form = $this->factory->createNamed('name', RadioType::class, true); $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')), '/div [@class="form-check"] [ ./input [@id="my&id"] [@type="radio"] [@name="name"] [@class="my&class form-check-input"] [@checked="checked"] [@value="1"] /following-sibling::label [@class="form-check-label required"] ] ' ); } public function testUncheckedRadio() { $form = $this->factory->createNamed('name', RadioType::class, false); $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')), '/div [@class="form-check"] [ ./input [@id="my&id"] [@type="radio"] [@name="name"] [@class="my&class form-check-input"] [not(@checked)] /following-sibling::label [@class="form-check-label required"] ] ' ); } public function testRadioWithValue() { $form = $this->factory->createNamed('name', RadioType::class, false, array( 'value' => 'foo&bar', )); $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')), '/div [@class="form-check"] [ ./input [@id="my&id"] [@type="radio"] [@name="name"] [@class="my&class form-check-input"] [@value="foo&bar"] /following-sibling::label [@class="form-check-label required"] [@for="my&id"] ] ' ); } public function testButtonAttributeNameRepeatedIfTrue() { $form = $this->factory->createNamed('button', ButtonType::class, null, array( 'attr' => array('foo' => true), )); $html = $this->renderWidget($form->createView()); // foo="foo" $this->assertSame('', $html); } public function testFile() { $form = $this->factory->createNamed('name', FileType::class); $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class form-control-file')), '/input [@type="file"] ' ); } public function testMoney() { $form = $this->factory->createNamed('name', MoneyType::class, 1234.56, array( 'currency' => 'EUR', )); $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')), '/div [@class="input-group"] [ ./div [@class="input-group-prepend"] [ ./span [@class="input-group-text"] [contains(.., "€")] ] /following-sibling::input [@id="my&id"] [@type="text"] [@name="name"] [@class="my&class form-control"] [@value="1234.56"] ] ' ); } public function testPercent() { $form = $this->factory->createNamed('name', PercentType::class, 0.1); $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')), '/div [@class="input-group"] [ ./input [@id="my&id"] [@type="text"] [@name="name"] [@class="my&class form-control"] [@value="10"] /following-sibling::div [@class="input-group-append"] [ ./span [@class="input-group-text"] [contains(.., "%")] ] ] ' ); } } __halt_compiler();----SIGNATURE:----mDttnTATabl3OqTLeLj/AXi/7homkqZDtd/AOSmS25/r04cmgkxxWtL/LvHJU2fnJ9wksLazJCbCpO4k5SXRN+U5IrGO88EiJq6MtcHwUlTYD9xpdZ0rFzqM9Pbid2DDfGAuVlXRy1pHm0jIO6C0ymoX/uEO0HHZu40ElIDevzJG8T8TfUrJ+aHuhZWu1QhhtZi7qI8DAyf6kZ0sATgviqKS/i3AylDbxjaupL3FCOlh291OcxYBKYUwwcwABaGef9yLP8rU16RHSKpa4cq6aetCglT4wtzNtTHqKVyjqTmwzqKOoqAlLVKLQHwgL2WddDu77AryQs1h7nC1FfCLpaCQMtQ4BASf/bPp0fBIqKcG2jYg6GSKWDqmlR/pkSpyKvIz3gKEg4xuvdJyJdVvegdmzZx/J6Zzqz4tAfeN2GosLCVG40sL0THbUsTGrG/ekWd2mItoTtOTJYc+6pHuM9fVLxzj/1QhG5PCD6sJfq0UEB9CCp8+73hWjk4cEZuuCOlJlf6wFpYgog4V6JUwYSGHA3JVR6wu8GRlTatqtnK4TFXYJzrmdV2ATQjCZtsYPge+NHYPCWJEUO2SvmOKGtwX9uBR+TOqn6Vhlf769rXQm3+TOl7C+jk08zDhiv3Ue/CNX5AgMqXWW7DIF13gVuAyYXCw4+rjgLYIKfyCYis=----ATTACHMENT:----MTM5MzUyNzY4OTg3NTY3OSA1ODk3MjgwMDAwNjg3ODcyIDc5NjYxNzU3NzE4MzQ2Mg==