diff --git a/src/Inputs/DateInput.php b/src/Inputs/DateInput.php index e237308..d559bc3 100644 --- a/src/Inputs/DateInput.php +++ b/src/Inputs/DateInput.php @@ -55,11 +55,27 @@ public function __construct($label = null, ?int $maxLength = null) parent::__construct($label, null); - $this->addRule(fn (Control $input) => DateTimeFormat::validate($this->format, $input->getValue()), $this->invalidFormatMessage); + // must be a static callable, otherwise Nette::exportRules() stops at this rule + // and every rule/condition added later is missing in data-nette-rules + $this->addRule([self::class, 'validateFormat'], $this->invalidFormatMessage); $this->setFormat(static::$defaultFormat); } + /** + * Checks that the value matches the control's format. + * + * Kept as a public static method (instead of a closure) so that the rule is exportable + * and does not cut off the rules that follow it. The client side has no validator of + * this name and simply skips it. + */ + public static function validateFormat(Control $input): bool + { + assert($input instanceof self); + + return DateTimeFormat::validate($input->getFormat(), $input->getValue()); + } + /** * @inheritdoc */ diff --git a/tests/Inputs/DateInputTest.php b/tests/Inputs/DateInputTest.php index 04582dd..7123b0b 100644 --- a/tests/Inputs/DateInputTest.php +++ b/tests/Inputs/DateInputTest.php @@ -5,16 +5,20 @@ use Contributte\FormsBootstrap\BootstrapForm; use Contributte\FormsBootstrap\Enums\DateTimeFormat; use Contributte\FormsBootstrap\Inputs\DateInput; +use Nette\Forms\Form; use Tests\BaseTestCase; class DateInputTest extends BaseTestCase { + // rule that DateInput adds in its constructor + private const FORMAT_RULE = '[{"op":"Contributte\\\\FormsBootstrap\\\\Inputs\\\\DateInput::validateFormat","msg":"invalid/incorrect format"}]'; + public function testDefaultDate(): void { $form = new BootstrapForm(); $dt = $form->addBootstrapDate('date', 'Date'); - $this->assertEquals('', $dt->getControl()->render()); + $this->assertEquals('', $dt->getControl()->render()); } public function testWithCustomStaticFormat(): void @@ -22,7 +26,26 @@ public function testWithCustomStaticFormat(): void $form = new BootstrapForm(); DateInput::$defaultFormat = DateTimeFormat::D_YMD_DASHES; $dt = $form->addBootstrapDate('date', 'Date'); - $this->assertEquals('', $dt->getControl()->render()); + $this->assertEquals('', $dt->getControl()->render()); + } + + /** + * @see https://github.com/contributte/forms-bootstrap/issues/61 + */ + public function testConditionsAreExported(): void + { + $form = new BootstrapForm(); + $checkbox = $form->addCheckbox('agree', 'Agree'); + $date = $form->addBootstrapDate('date', 'Date'); + $date->addConditionOn($checkbox, Form::Equal, true) + ->setRequired('Date is required'); + $date->addCondition(Form::Filled) + ->addRule(Form::MinLength, 'Too short', 3); + + $rules = $date->getControl()->render(); + $this->assertStringContainsString(':equal', $rules); + $this->assertStringContainsString(':filled', $rules); + $this->assertStringContainsString(':minLength', $rules); } } diff --git a/tests/Inputs/DateTimeInputTest.php b/tests/Inputs/DateTimeInputTest.php index 9867dd2..0ec9b23 100644 --- a/tests/Inputs/DateTimeInputTest.php +++ b/tests/Inputs/DateTimeInputTest.php @@ -11,11 +11,14 @@ class DateTimeInputTest extends BaseTestCase { + // rule that DateInput adds in its constructor + private const FORMAT_RULE = '[{"op":"Contributte\\\\FormsBootstrap\\\\Inputs\\\\DateInput::validateFormat","msg":"invalid/incorrect format"}]'; + public function testDefaultDateTime(): void { $form = new BootstrapForm(); $dt = $form->addBootstrapDateTime('datetime', 'Date and time'); - $this->assertEquals('', $dt->getControl()->render()); + $this->assertEquals('', $dt->getControl()->render()); } public function testDefaultAdditionalClasses(): void @@ -24,7 +27,7 @@ public function testDefaultAdditionalClasses(): void DateTimeInput::$additionalHtmlClasses[] = 'datetimepicker'; DateTimeInput::$additionalHtmlClasses[] = 'cool'; $dt = $form->addBootstrapDateTime('datetime', 'Date and time'); - $this->assertEquals('', $dt->getControl()->render()); + $this->assertEquals('', $dt->getControl()->render()); } public function testNotMessingHtmlClassOfDateAndDateTime(): void @@ -62,4 +65,27 @@ public function testValidationWithCorrectFormat(): void $this->assertEquals(new DateTime('2020-05-01'), $dt->getValue()); } + public function testValidationWithIncorrectFormat(): void + { + $form = new BootstrapForm(); + $dt = $form->addBootstrapDateTime('datetime', 'Date and time'); + $dt->setValue('not a date at all'); + $submit = $form->addSubmit('send'); + $form->setSubmittedBy($submit); + $form->validate(); + $this->assertFalse($form->isValid()); + $this->assertSame([$dt->invalidFormatMessage], $dt->getErrors()); + } + + public function testEmptyOptionalValueDoesNotFailValidation(): void + { + $form = new BootstrapForm(); + $dt = $form->addBootstrapDateTime('datetime', 'Date and time'); + $submit = $form->addSubmit('send'); + $form->setSubmittedBy($submit); + $form->validate(); + $this->assertTrue($form->isValid()); + $this->assertSame([], $dt->getErrors()); + } + }