diff --git a/typo3/sysext/core/Classes/DataHandling/DataHandler.php b/typo3/sysext/core/Classes/DataHandling/DataHandler.php index 24629cf2e0fa98e86c779a595471feac2bbb0dad..5ce12baa46a6ef0d11564eb8422a6a82ab2cb0c1 100644 --- a/typo3/sysext/core/Classes/DataHandling/DataHandler.php +++ b/typo3/sysext/core/Classes/DataHandling/DataHandler.php @@ -2699,14 +2699,14 @@ class DataHandler switch ($func) { case 'int': case 'year': - case 'time': - case 'timesec': $value = (int)$value; break; + case 'time': + case 'timesec': case 'date': case 'datetime': // a hyphen as first character indicates a negative timestamp - if (strpos($value, '-') === false || strpos($value, '-') === 0) { + if ((strpos($value, '-') === false && strpos($value, ':') === false) || strpos($value, '-') === 0) { $value = (int)$value; } else { // ISO 8601 dates diff --git a/typo3/sysext/core/Tests/Acceptance/Backend/Formhandler/ElementsBasicCest.php b/typo3/sysext/core/Tests/Acceptance/Backend/Formhandler/ElementsBasicCest.php index fb7a900e8346c3d2bb26170928f56bc2df19de19..f3f329c7bacdcef22bf34dfa3dce9c6043869267 100644 --- a/typo3/sysext/core/Tests/Acceptance/Backend/Formhandler/ElementsBasicCest.php +++ b/typo3/sysext/core/Tests/Acceptance/Backend/Formhandler/ElementsBasicCest.php @@ -16,6 +16,7 @@ namespace TYPO3\CMS\Core\Tests\Acceptance\Backend\Formhandler; use TYPO3\CMS\Core\Tests\Acceptance\Step\Backend\Admin; use TYPO3\CMS\Core\Tests\Acceptance\Support\Helper\Formhandler; +use TYPO3\CMS\Core\Tests\Acceptance\Support\Helper\FormHandlerElementTestDataObject; use TYPO3\CMS\Core\Tests\Acceptance\Support\Page\PageTree; /** @@ -25,6 +26,7 @@ class ElementsBasicCest { /** * Selector of the record container in the listview + * * @var string */ protected static $listViewRecordSelector = '#recordlist-tx_styleguide_elements_basic'; @@ -48,301 +50,205 @@ class ElementsBasicCest */ public function checkThatBrowserSideValidationsWorkAndSaveRecord(Admin $I, Formhandler $formhandler) { - $editRecordLinkCssPath = self::$listViewRecordSelector . ' a[data-original-title="Edit record"]'; - $I->waitForElement($editRecordLinkCssPath, 30); - $I->click($editRecordLinkCssPath); - $I->waitForText('Edit Form', 3, 'h1'); + $this->waitForFormReady($I); $fieldTests = [ 'input_1' => [ - 'tests' => [ - [ - 'This is a demo text with 2 numbers #!', - 'This is a demo text with 2 numbers #!', - ], - ], - 'cleared' => [ - '' - ] + new FormHandlerElementTestDataObject( + 'This is a demo text with 2 numbers #!', + 'This is a demo text with 2 numbers #!' + ) ], 'input_2, size=10' => [ - 'tests' => [ - [ - 'This is a demo text with 2 numbers #!', - 'This is a demo text with 2 numbers #!', - ], - ], - 'cleared' => [ - '' - ] + new FormHandlerElementTestDataObject( + 'This is a demo text with 2 numbers #!', + 'This is a demo text with 2 numbers #!' + ) ], 'input_3 max=4' => [ - 'tests' => [ - [ - 'Kasper', - 'Kasp', - ], - ], - 'cleared' => [ - '' - ] + new FormHandlerElementTestDataObject( + 'Kasper', + 'Kasp' + ) ], 'input_4 eval=alpha' => [ - 'tests' => [ - [ - 'Kasper = TYPO3', - 'KasperTYPO', - ], - [ - 'Non-latin characters: Å ÄŽĆČ', - 'Nonlatincharacters', - ], - ], - 'cleared' => [ - '' - ] + new FormHandlerElementTestDataObject( + 'Kasper = TYPO3', + 'KasperTYPO' + ), + new FormHandlerElementTestDataObject( + 'Non-latin characters: Å ÄŽĆČ', + 'Nonlatincharacters' + ), ], 'input_5 eval=alphanum' => [ - 'tests' => [ - [ - 'Kasper = TYPO3', - 'KasperTYPO3', - ], - ], - 'cleared' => [ - '' - ] + new FormHandlerElementTestDataObject( + 'Kasper = TYPO3', + 'KasperTYPO3' + ), + ], 'input_8 eval=double2' => [ - 'tests' => [ - [ - '12.335', - '12.34', - '12.34', - ], - [ - '12,335', - '12.34', - '12.34', - ], - [ - '1.1', - '1.10', - '1.10', - ], - [ - 'TYPO3', - '3.00', - '3.00', - ], - [ - '3TYPO', - '3.00', - '3.00', - ], - ], - // @todo: add support for null values to the core - 'cleared' => [ - '0.00', - '0.00', - ] + new FormHandlerElementTestDataObject( + '12.335', + '12.34', + '12.34' + ), + new FormHandlerElementTestDataObject( + '12,335', + '12.34', + '12.34' + ), + new FormHandlerElementTestDataObject( + '1.1', + '1.10', + '1.10' + ), + new FormHandlerElementTestDataObject( + 'TYPO3', + '3.00', + '3.00' + ), + new FormHandlerElementTestDataObject( + '3TYPO', + '3.00', + '3.00' + ) ], 'input_9 eval=int' => [ - 'tests' => [ - [ - '12.335', - '12', - '12', - ], - [ - '12,9', - '12', - '12', - ], - [ - 'TYPO3', - '0', - '0', - ], - [ - '3TYPO', - '3', - '3', - ], - ], - // @todo: add support for null values to the core - 'cleared' => [ - '0', + new FormHandlerElementTestDataObject( + '12.335', + '12', + '12' + + ), + new FormHandlerElementTestDataObject( + '12,9', + '12', + '12' + ), + new FormHandlerElementTestDataObject( + 'TYPO3', '0', - ] + '0' + ), + new FormHandlerElementTestDataObject( + '3TYPO', + '3', + '3' + ) ], 'input_10 eval=is_in, is_in=abc123' => [ - 'tests' => [ - [ - 'abcd1234', - 'abc123', - ], - [ - 'Kasper TYPO3', - 'a3', - ], - ], - 'cleared' => [ - '', - ] + new FormHandlerElementTestDataObject( + 'abcd1234', + 'abc123' + ), + new FormHandlerElementTestDataObject( + 'Kasper TYPO3', + 'a3' + ) ], 'input_11 eval=lower' => [ - 'tests' => [ - [ - 'Kasper TYPO3!', - 'kasper typo3!', - ], - ], - 'cleared' => [ - '', - ] + new FormHandlerElementTestDataObject( + 'Kasper TYPO3!', + 'kasper typo3!' + ) ], 'input_12 eval=md5' => [ - 'tests' => [ - [ - 'Kasper TYPO3!', - '748469dd64911af8df8f9a3dcb2c9378', - '748469dd64911af8df8f9a3dcb2c9378', - ], - [ - ' Kasper TYPO3! ', - '792a085606250c47d6ebb8c98804d5b0', - '792a085606250c47d6ebb8c98804d5b0', - false, - 'Check that whitespaces are not trimmed.' - ], - ], - 'cleared' => [ - // @todo: add support for null values to the core - // cleared value currently keeps the previous value on save + new FormHandlerElementTestDataObject( + 'Kasper TYPO3!', + '748469dd64911af8df8f9a3dcb2c9378', + '748469dd64911af8df8f9a3dcb2c9378' + ), + new FormHandlerElementTestDataObject( + ' Kasper TYPO3! ', '792a085606250c47d6ebb8c98804d5b0', - '792a085606250c47d6ebb8c98804d5b0' - ] - + '792a085606250c47d6ebb8c98804d5b0', + '792a085606250c47d6ebb8c98804d5b0', + false, + 'Check that whitespaces are not trimmed.' + ) ], 'input_13 eval=nospace' => [ - 'tests' => [ - [ - ' Kasper TYPO3! ', - 'KasperTYPO3!', - ], - ], - 'cleared' => [ - '', - ] + new FormHandlerElementTestDataObject( + ' Kasper TYPO3! ', + 'KasperTYPO3!' + ) ], - // @todo define test - //'input_14 eval=null' => [ - //], 'input_15 eval=num' => [ - 'tests' => [ - [ - '12.335', - '12335', - ], - [ - '12,9', - '129', - ], - [ - 'TYPO3', - '3', - ], - [ - '3TYPO', - '3', - ], - ], - 'cleared' => [ - '', - ] + new FormHandlerElementTestDataObject( + '12.335', + '12335' + ), + new FormHandlerElementTestDataObject( + '12,9', + '129' + ), + new FormHandlerElementTestDataObject( + 'TYPO3', + '3' + ), + new FormHandlerElementTestDataObject( + '3TYPO', + '3' + ), ], 'input_16 eval=password' => [ - 'tests' => [ - [ - 'Kasper', - '********', - 'Kasper', - ], - ], - 'cleared' => [ - '', - ] + new FormHandlerElementTestDataObject( + 'Kasper', + '********', + 'Kasper' + ), ], - 'input_19 eval=trim' => [ - 'tests' => [ - [ - ' Kasper ', - 'Kasper', - ], - [ - ' Kasper TYPO3 ', - 'Kasper TYPO3', - ], - ], - 'cleared' => [ - '', - ] + 'input_19 eval=trim' => [ + new FormHandlerElementTestDataObject( + ' Kasper ', + 'Kasper' + ), + new FormHandlerElementTestDataObject( + ' Kasper TYPO3 ', + 'Kasper TYPO3' + ), ], - // @todo Check why this test is currently broken - //'input_20 eval with user function' => [ - // [ - // 'Kasper', - // 'KasperJSfoo', - // ] - //], 'input_23 eval=upper' => [ - 'tests' => [ - [ - 'Kasper TYPO3!', - 'KASPER TYPO3!', - ], - ], - 'cleared' => [ - '', - ] + new FormHandlerElementTestDataObject( + 'Kasper TYPO3!', + 'KASPER TYPO3!' + ) ], 'input_25 eval=int, default=0, range lower=-2, range upper=2' => [ - 'tests' => [ - [ - 'Kasper TYPO3', - '0', - '0', - ], - [ - '2', - '2', - '2' - ], - [ - '-1', - '-1', - '-1', - ], - [ - '-3', - '-3', - '-3', - true, - 'Expecting a modal with error on trying to save.' - ], - [ - '3', - '-3', - '-3', - true, - 'Expecting a modal with error on trying to save.' - ], - ], - 'cleared' => [ + new FormHandlerElementTestDataObject( + 'Kasper TYPO3', '0', '0' - ] + ), + new FormHandlerElementTestDataObject( + '2', + '2', + '2' + ), + new FormHandlerElementTestDataObject( + '-1', + '-1', + '-1' + ), + new FormHandlerElementTestDataObject( + '-3', + '-3', + '-3', + '-3', + true, + 'Expecting a modal with error on trying to save.' + + ), + new FormHandlerElementTestDataObject( + '3', + '-3', + '-3', + '-3', + true, + 'Expecting a modal with error on trying to save.' + ) ], ]; @@ -358,228 +264,282 @@ class ElementsBasicCest * @param Admin $I * @param Formhandler $formhandler */ - public function checkThatBrowserSideValidationsWorkAndSaveRecordForDateFields(Admin $I, Formhandler $formhandler) + public function checkThatValidationWorks_evalYear(Admin $I, Formhandler $formhandler) { - $editRecordLinkCssPath = self::$listViewRecordSelector . ' a[data-original-title="Edit record"]'; - $I->waitForElement($editRecordLinkCssPath, 30); - $I->click($editRecordLinkCssPath); - $I->waitForText('Edit Form', 3, 'h1'); + $this->waitForFormReady($I); - $fieldTests = [ + $testData = [ + 'input_24 eval=year' => [ + new FormHandlerElementTestDataObject( + '2016', + '2016', + '2016' + ), + new FormHandlerElementTestDataObject( + '12', + '2012', + '2012' + ), + new FormHandlerElementTestDataObject( + 'Kasper', + date('Y'), + date('Y'), + date('Y'), + false, + 'Invalid character is converted to current year' + ) + ] + ]; + + $this->runTests($formhandler, $testData); + } + + /** + * @param \TYPO3\CMS\Core\Tests\Acceptance\Step\Backend\Admin $I + * @param \TYPO3\CMS\Core\Tests\Acceptance\Support\Helper\Formhandler $formhandler + */ + public function checkThatBrowserSideValidationWorks_EvalDate(Admin $I, Formhandler $formhandler) + { + $this->waitForFormReady($I); + $fieldData = [ 'input_6 eval=date' => [ - 'tests' => [ - [ - '29-01-2016', - '29-01-2016', - '1454025600', - ], - [ - '13-13-2016', - '13-01-2017', - '1484265600', - ], - [ - '29-02-2016', - '29-02-2016', - '1456704000', - false, - 'Check valid leap year input' - ], - [ - '29-02-2015', - '01-03-2015', - '1425168000', - false, - 'Check invalid leap year transformation' - ], - ], - 'cleared' => [ - '0' - ] - ], + new FormHandlerElementTestDataObject( + '29-01-2016', + '29-01-2016', + '2016-01-29T00:00:00Z', + '2016-01-29T00:00:00+00:00' + ), + new FormHandlerElementTestDataObject( + '13-13-2016', + '13-01-2017', + '2017-01-13T00:00:00Z', + '2017-01-13T00:00:00+00:00' + ), + new FormHandlerElementTestDataObject( + '29-02-2016', + '29-02-2016', + '2016-02-29T00:00:00Z', + '2016-02-29T00:00:00+00:00', + false, + 'Check valid leap year input' + ), + new FormHandlerElementTestDataObject( + '29-02-2015', + '01-03-2015', + '2015-03-01T00:00:00Z', + '2015-03-01T00:00:00+00:00', + false, + 'Check invalid leap year transformation' + ) + ] + ]; + $this->runTests($formhandler, $fieldData); + } + + public function checkThatValidationWorks_EvalDate_TypeDate(Admin $I, Formhandler $formhandler) + { + $this->waitForFormReady($I); + $testData = [ 'input_36 dbType=date eval=date' => [ - 'tests' => [ - [ - '29-01-2016', - '29-01-2016', - '1454025600', - ], - [ - '13-13-2016', - '13-01-2017', - '1484265600', - ], - [ - '29-02-2016', - '29-02-2016', - '1456704000', - false, - 'Check valid leap year input' - ], - [ - '29-02-2015', - '01-03-2015', - '1425168000', - false, - 'Check invalid leap year transformation' - ], - ], - 'cleared' => [ - '0' - ] - ], + new FormHandlerElementTestDataObject( + '29-01-2016', + '29-01-2016', + '2016-01-29T00:00:00Z', + '2016-01-29T00:00:00+00:00' + ), + new FormHandlerElementTestDataObject( + '13-13-2016', + '13-01-2017', + '2017-01-13T00:00:00Z', + '2017-01-13T00:00:00+00:00' + ), + new FormHandlerElementTestDataObject( + '29-02-2016', + '29-02-2016', + '2016-02-29T00:00:00Z', + '2016-02-29T00:00:00+00:00', + false, + 'Check valid leap year input' + ), + new FormHandlerElementTestDataObject( + '29-02-2015', + '01-03-2015', + '2015-03-01T00:00:00Z', + '2015-03-01T00:00:00+00:00', + false, + 'Check invalid leap year transformation' + ), + ] + ]; + $this->runTests($formhandler, $testData); + } + + public function checkThatValidationWorks_EvalDateTime(Admin $I, Formhandler $formhandler) + { + $this->waitForFormReady($I); + $testData = [ 'input_7 eval=datetime' => [ - 'tests' => [ - [ - '05:23 29-01-2016', - '05:23 29-01-2016', - '1454044980', - ], - [ - '05:23 13-13-2016', - '05:23 13-01-2017', - '1484284980', - ], - [ - '05:23 29-02-2016', - '05:23 29-02-2016', - '1456723380', - false, - 'Check valid leap year input' - ], - [ - '05:23 29-02-2015', - '05:23 01-03-2015', - '1425187380', - false, - 'Check invalid leap year transformation' - ], - ], - 'cleared' => [ - '0' - ] - ], + new FormHandlerElementTestDataObject( + '05:23 29-01-2016', + '05:23 29-01-2016', + '2016-01-29T05:23:00Z', + '2016-01-29T05:23:00+00:00' + ), + new FormHandlerElementTestDataObject( + '05:23 13-13-2016', + '05:23 13-01-2017', + '2017-01-13T05:23:00Z', + '2017-01-13T05:23:00+00:00' + ), + new FormHandlerElementTestDataObject( + '05:23 29-02-2016', + '05:23 29-02-2016', + '2016-02-29T05:23:00Z', + '2016-02-29T05:23:00+00:00', + false, + 'Check valid leap year input' + ), + new FormHandlerElementTestDataObject( + '05:23 29-02-2015', + '05:23 01-03-2015', + '2015-03-01T05:23:00Z', + '2015-03-01T05:23:00+00:00', + false, + 'Check invalid leap year transformation' + ) + ] + ]; + $this->runTests($formhandler, $testData); + } + + public function checkThatValidationWorks_EvalDateTime_DbTypeDateTime(Admin $I, Formhandler $formhandler) + { + $this->waitForFormReady($I); + $testData = [ 'input_37 dbType=datetime eval=datetime' => [ - 'tests' => [ - [ - '05:23 29-01-2016', - '05:23 29-01-2016', - '1454044980', - ], - [ - '05:23 13-13-2016', - '05:23 13-01-2017', - '1484284980', - ], - [ - '05:23 29-02-2016', - '05:23 29-02-2016', - '1456723380', - false, - 'Check valid leap year input' - ], - [ - '05:23 29-02-2015', - '05:23 01-03-2015', - '1425187380', - false, - 'Check invalid leap year transformation' - ], - ], - 'cleared' => [ - '0' - ] + new FormHandlerElementTestDataObject( + '05:23 29-01-2016', + '05:23 29-01-2016', + '2016-01-29T05:23:00Z', + '2016-01-29T05:23:00+00:00' + ), + new FormHandlerElementTestDataObject( + '05:23 13-13-2016', + '05:23 13-01-2017', + '2017-01-13T05:23:00Z', + '2017-01-13T05:23:00+00:00' + ), + new FormHandlerElementTestDataObject( + '05:23 29-02-2016', + '05:23 29-02-2016', + '2016-02-29T05:23:00Z', + '2016-02-29T05:23:00+00:00', + false, + 'Check valid leap year input' + ), + new FormHandlerElementTestDataObject( + '05:23 29-02-2015', + '05:23 01-03-2015', + '2015-03-01T05:23:00Z', + '2015-03-01T05:23:00+00:00', + false, + 'Check invalid leap year transformation' + ), ], + ]; + $this->runTests($formhandler, $testData); + } + + public function checkThatValidationWorks_evalTime(Admin $I, Formhandler $formhandler) + { + $this->waitForFormReady($I); + $testData = [ 'input_17 eval=time' => [ - 'tests' => [ - [ - '13:30', - '13:30', - '48600', - ], - [ - '123', - '12:03', - '43380', - ], - [ - '12345', - '12:34', - '45240', - ], - [ - '12:04+5', - '12:09', - '43740', - ], - [ - '12:09-3', - '12:06', - '43560', - ] - ], - 'cleared' => [ - '0', - '00:00', - ] + new FormHandlerElementTestDataObject( + '13:30', + '13:30', + '13:30', + (new \DateTime('13:30'))->getTimestamp() + ), + new FormHandlerElementTestDataObject( + '123', + '12:03', + '12:03', + (new \DateTime('12:03'))->getTimestamp() + ), + new FormHandlerElementTestDataObject( + '12345', + '12:34', + '12:34', + (new \DateTime('12:34'))->getTimestamp() + ), + new FormHandlerElementTestDataObject( + '12:04+5', + '12:09', + '12:09', + (new \DateTime('12:09'))->getTimestamp() + ), + new FormHandlerElementTestDataObject( + '12:09-3', + '12:06', + '12:06', + (new \DateTime('12:06'))->getTimestamp() + ) ], - 'input_18 eval=timesec' => [ - 'tests' => [ - [ - '13:30:00', - '13:30:00', - '48600', - ], - [ - '12345', - '12:34:05', - '45245', - ], - [ - // @todo is that the expected behavior? - '12:04:04+5', - '12:09:04', - '43744', - ], - ], - 'cleared' => [ - '0', - '00:00:00', - ] - ], - 'input_24 eval=year' => [ - 'tests' => [ + ]; + $this->runTests($formhandler, $testData); + } - [ - '2016', - '2016', - '2016', - ], - [ - '12', - '2012', - '2012', - ], - [ - 'Kasper', - date('Y'), - date('Y'), - false, - 'Invalid character is converted to current year' - ], - ], - 'cleared' => [ - '0', - '0', - ] + public function checkThatValidationWorks_evalTimesec(Admin $I, Formhandler $formhandler) + { + $this->waitForFormReady($I); + $testData = [ + 'input_18 eval=timesec' => [ + new FormHandlerElementTestDataObject( + '13:30:00', + '13:30:00', + '13:30:00', + (new \DateTime('13:30:00'))->getTimestamp() + ), + new FormHandlerElementTestDataObject( + '12345', + '12:34:05', + '12:34:05', + (new \DateTime('12:34:05'))->getTimestamp() + ), + new FormHandlerElementTestDataObject( + '12:04:04+5', + '12:09:04', + '12:09:04', + (new \DateTime('12:09:04'))->getTimestamp() + ) ], ]; + $this->runTests($formhandler, $testData); + } - foreach ($fieldTests as $fieldLabel => $testData) { + /** + * @param \TYPO3\CMS\Core\Tests\Acceptance\Support\Helper\Formhandler $formhandler + * @param $fieldData + */ + protected function runTests(Formhandler $formhandler, $fieldData) + { + foreach ($fieldData as $fieldLabel => $testData) { $formhandler->fillSeeSaveAndClearInputField( $fieldLabel, $testData ); } } + + /** + * @param \TYPO3\CMS\Core\Tests\Acceptance\Step\Backend\Admin $I + */ + protected function waitForFormReady(Admin $I) + { + $editRecordLinkCssPath = self::$listViewRecordSelector . ' a[data-original-title="Edit record"]'; + $I->waitForElement($editRecordLinkCssPath, 30); + $I->click($editRecordLinkCssPath); + $I->waitForText('Edit Form', 3, 'h1'); + } } diff --git a/typo3/sysext/core/Tests/Acceptance/Support/Helper/FormHandlerElementTestDataObject.php b/typo3/sysext/core/Tests/Acceptance/Support/Helper/FormHandlerElementTestDataObject.php new file mode 100644 index 0000000000000000000000000000000000000000..ca37a365c87c607ae4434b00f01783ebf3fe529b --- /dev/null +++ b/typo3/sysext/core/Tests/Acceptance/Support/Helper/FormHandlerElementTestDataObject.php @@ -0,0 +1,92 @@ +<?php +declare(strict_types=1); + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +namespace TYPO3\CMS\Core\Tests\Acceptance\Support\Helper; + +/** + * Class FormHandlerElementTestDataObject. + */ +class FormHandlerElementTestDataObject +{ + /** + * The test value. + * + * @var string + */ + public $inputValue; + + /** + * The expected value as seen by the user. + * + * @var string + */ + public $expectedValue; + + /** + * The expected value in the value attribute of the hidden field + * (full ISO date for example). + * + * @var string + */ + public $expectedInternalValue; + + /** + * Expected value in hidden field after saving the data. + * + * @var string + */ + public $expectedValueAfterSave; + + /** + * Does this test data set result in a modal window (e.g. for errors)? + * + * @var bool + */ + public $notificationExpected; + + /** + * Comment echoed in test log. + * + * @var string + */ + public $comment; + + /** + * FormHandlerElementTestDataObject constructor. + * + * @param string $inputValue + * @param string $expectedValue + * @param string $expectedInternalValue + * @param string $expectedValueAfterSave + * @param bool $notificationExpected + * @param string $comment + */ + public function __construct( + string $inputValue, + string $expectedValue, + string $expectedInternalValue = '', + string $expectedValueAfterSave = '', + bool $notificationExpected = false, + string $comment = '' + ) { + $this->inputValue = $inputValue; + $this->expectedValue = $expectedValue; + $this->expectedInternalValue = $expectedInternalValue; + $this->expectedValueAfterSave = $expectedValueAfterSave; + $this->notificationExpected = $notificationExpected; + $this->comment = $comment; + } +} diff --git a/typo3/sysext/core/Tests/Acceptance/Support/Helper/Formhandler.php b/typo3/sysext/core/Tests/Acceptance/Support/Helper/Formhandler.php index 60488b46116250e5febf6b8d0dea948adb972b6a..d0cec70245bbfd605c7af27c4c0b852e1e633b90 100644 --- a/typo3/sysext/core/Tests/Acceptance/Support/Helper/Formhandler.php +++ b/typo3/sysext/core/Tests/Acceptance/Support/Helper/Formhandler.php @@ -24,10 +24,15 @@ class Formhandler { /** * Selector to select one formengine section + * * @var string */ public static $selectorFormSection = '.form-section'; - + protected $visibleFieldPath = './/*/input[@data-formengine-input-name]'; + protected $initializedInputFieldXpath; + protected $internalInputFieldXpath; + protected $internalInputFieldXpath1; + protected $internalFieldXpath; /** * @var \AcceptanceTester */ @@ -41,123 +46,187 @@ class Formhandler $this->tester = $I; } - /** - * @param string $fieldName - * @return RemoteWebElement - */ - protected function getContextForFormhandlerField(string $fieldName) - { - $I = $this->tester; - $I->comment('Get context for field "' . $fieldName . '"'); - - return $I->executeInSelenium(function (\Facebook\WebDriver\Remote\RemoteWebDriver $webdriver) use ($fieldName) { - return $webdriver->findElement( - \WebDriverBy::xpath('(//label[contains(text(),"' . $fieldName . '")])[1]/ancestor::fieldset[@class="form-section"][1]') - ); - }); - } - /** * @param string $fieldLabel - * @param array $testData An array of arrays that contains the data to validate. - * * First value is the input value - * * second value is the value that is expected after the validation - * * optional third value is the "internal" value like required for date fields (value is internally - * represented by a timestamp). If this value is not defined the second value will be used. - * Example for field with alpha validation: [['foo', 'foo'], ['bar1'], ['bar']] - * Example for field with date validation: [['29-01-2016', '29-01-2016', '1454025600']] + * @param FormHandlerElementTestDataObject[] $testData An array of Objects that contains the data to validate. */ public function fillSeeSaveAndClearInputField($fieldLabel, array $testData) { - $fieldContext = $this->getContextForFormhandlerField($fieldLabel); $I = $this->tester; $I->wantTo('Fill field, check the fieldvalue after evaluation and delete the value.'); - $visibleFieldXpath = './/*/input[@data-formengine-input-name]'; - $clearButtonXpath = '(//label[contains(text(),"' . $fieldLabel . '")])[1]/parent::*//*/button[@class="close"]'; - $initializedInputFieldXpath = '(//label[contains(text(),"' . $fieldLabel . '")])[1]/parent::*//*/input[@data-formengine-input-name][@data-formengine-input-initialized]'; - $I->waitForElement($initializedInputFieldXpath, 30); - $inputField = $fieldContext->findElement(\WebDriverBy::xpath($visibleFieldXpath)); - $internalInputFieldXpath = '(//label[contains(text(),"' . $fieldLabel . '")])[1]/parent::*//*/input[@name="' . $inputField->getAttribute('data-formengine-input-name') . '"]'; + $this->initializeFieldSelectors($fieldLabel); - $I->waitForElement($internalInputFieldXpath, 30); - $I->waitForElement($clearButtonXpath, 30); + foreach ($testData as $data) { + list($inputField, $internalInputField) = $this->getInputFields($fieldLabel); + $fieldContext = $this->getContextForFormhandlerField($fieldLabel); - // the internal field name will not change during this function execution - $internalFieldXpath = './/*/input[@name="' . $inputField->getAttribute('data-formengine-input-name') . '"]'; - $internalInputField = $fieldContext->findElement(\WebDriverBy::xpath($internalFieldXpath)); + $expectedInternal = $data->expectedInternalValue !== '' ? $data->expectedInternalValue : $data->expectedValue; + $expectedInternalAfterSave = $data->expectedValueAfterSave !== '' ? $data->expectedValueAfterSave : $expectedInternal; + $this->addComment($data->comment); - foreach ($testData['tests'] as $testValue) { - if (isset($testValue[4])) { - $I->comment($testValue[4]); - } $I->comment('Fill the field and switch focus to trigger validation.'); - $I->fillField($inputField, $testValue[0]); + $I->fillField($inputField, $data->inputValue); // change the focus to trigger validation $inputField->sendKeys(WebDriverKeys::TAB); // click on the div so that any opened popup (potentially from the field below) is closed $fieldContext->click(); - $I->comment('Test value of "visible" field'); - $I->canSeeInField($inputField, $testValue[1]); - $I->comment('Test value of the internal field'); - $I->canSeeInField($internalInputField, (isset($testValue[2]) ? $testValue[2] : $testValue[1])); - - // save the change - $saveButtonLink = '//*/button[@name="_savedok"][1]'; - $I->waitForElement($saveButtonLink, 30); - if (isset($testValue[3]) && $testValue[3]) { - $I->click($saveButtonLink); - $I->switchToWindow(); - $notificationCloseXpath = '//*[@class="modal-title"][contains(text(),"Alert")]/parent::*/button[@class="close"]'; - $I->waitForElement($notificationCloseXpath, 30); - $I->click($notificationCloseXpath); + $this->testFieldValues($inputField, $data->expectedValue, $internalInputField, $expectedInternal); + + if ($data->notificationExpected) { + $this->save(); + $this->closeNotification(); return; } else { - $I->click($saveButtonLink); + $this->save(); } // wait for the save to be completed - $I->waitForElement('//*/button[@name="_savedok"][not(@disabled)][1]', 30); - $I->waitForElement($initializedInputFieldXpath, 30); - $I->waitForElement($internalInputFieldXpath, 30); - $I->waitForElement($clearButtonXpath, 30); + $this->waitForSaveToBeCompleted(); - // find the input fields again - $fieldContext = $this->getContextForFormhandlerField($fieldLabel); - $inputField = $fieldContext->findElement(\WebDriverBy::xpath($visibleFieldXpath)); - $internalInputField = $fieldContext->findElement(\WebDriverBy::xpath($internalFieldXpath)); + // find the fields again (after reload of iframe) + list($inputField, $internalInputField) = $this->getInputFields($fieldLabel); // validate that the save was successful - $I->comment('Test value of "visible" field after the save'); - $I->canSeeInField($inputField, $testValue[1]); - $I->comment('Test value of the internal field after the save'); - $I->canSeeInField($internalInputField, isset($testValue[2]) ? $testValue[2] : $testValue[1]); + $this->testFieldValues($inputField, $data->expectedValue, $internalInputField, $expectedInternalAfterSave); } + list($inputField) = $this->getInputFields($fieldLabel); + // clear the field - $I->waitForElement($clearButtonXpath, 30); - $I->click($clearButtonXpath); - $I->canSeeInField($inputField, ''); + $this->clearField($inputField); + $this->save(); + $this->waitForSaveToBeCompleted(); + } + + /** + * @param $comment + */ + protected function addComment($comment) + { + if ($comment !== null) { + $this->tester->comment($comment); + } + } + + protected function clearField($inputField) + { + $I = $this->tester; + $I->comment('Clear the field'); + $I->waitForElementVisible($this->initializedInputFieldXpath); + $I->fillField($inputField, ''); + } + + protected function closeNotification() + { + $I = $this->tester; + $I->switchToWindow(); + $notificationCloseXpath = '//*[@class="modal-title"][contains(text(),"Alert")]/parent::*/button[@class="close"]'; + $I->waitForElement($notificationCloseXpath, 30); + $I->click($notificationCloseXpath); + } + + /** + * @param string $fieldName + * @return RemoteWebElement + */ + protected function getContextForFormhandlerField(string $fieldName) + { + $I = $this->tester; + $I->comment('Get context for field "' . $fieldName . '"'); + + return $I->executeInSelenium( + function (\Facebook\WebDriver\Remote\RemoteWebDriver $webdriver) use ($fieldName) { + return $webdriver->findElement( + \WebDriverBy::xpath( + '(//label[contains(text(),"' . + $fieldName . + '")])[1]/ancestor::fieldset[@class="form-section"][1]' + ) + ); + } + ); + } + + /** + * @param $fieldLabel + * @return array + */ + protected function getInputFields($fieldLabel) + { + $I = $this->tester; + $I->comment('get input fields'); + $I->waitForElement($this->initializedInputFieldXpath, 30); + $fieldContext = $this->getContextForFormhandlerField($fieldLabel); + $inputField = $fieldContext->findElement(\WebDriverBy::xpath($this->visibleFieldPath)); + $internalInputFieldXpath = '(//label[contains(text(),"' . + $fieldLabel . + '")])[1]/parent::*//*/input[@name="' . + $inputField->getAttribute('data-formengine-input-name') . + '"]'; + + $I->waitForElement($internalInputFieldXpath, 30); + + $this->internalFieldXpath = './/*/input[@name="' . + $inputField->getAttribute('data-formengine-input-name') . + '"]'; + $internalInputField = $fieldContext->findElement(\WebDriverBy::xpath($this->internalFieldXpath)); + + $this->internalInputFieldXpath = $internalInputFieldXpath; + return [$inputField, $internalInputField]; + } + + /** + * @param $fieldLabel + * @return array + */ + protected function initializeFieldSelectors($fieldLabel) + { + $this->initializedInputFieldXpath = '(//label[contains(text(),"' . + $fieldLabel . + '")])[1]/parent::*//*/input[@data-formengine-input-name]' . + '[@data-formengine-input-initialized]'; + } - // save the change again + /** + */ + protected function save() + { + $I = $this->tester; + $I->comment('Save the form'); $saveButtonLink = '//*/button[@name="_savedok"][1]'; $I->waitForElement($saveButtonLink, 30); $I->click($saveButtonLink); + } - // wait for the save to be completed - $I->waitForElement('//*/button[@name="_savedok"][not(@disabled)][1]', 30); - $I->waitForElement($initializedInputFieldXpath, 30); - $I->waitForElement($internalInputFieldXpath, 30); - $I->waitForElement($clearButtonXpath, 30); - - // find the input fields again - $fieldContext = $this->getContextForFormhandlerField($fieldLabel); - $inputField = $fieldContext->findElement(\WebDriverBy::xpath($visibleFieldXpath)); - $internalInputField = $fieldContext->findElement(\WebDriverBy::xpath($internalFieldXpath)); + /** + * @param $inputField + * @param $expectedAfterValidation + * @param $internalInputField + * @param $expectedInternal + */ + protected function testFieldValues( + $inputField, + $expectedAfterValidation, + $internalInputField, + $expectedInternal + ) { + $I = $this->tester; + $I->comment('Test value of "visible" field'); + $I->canSeeInField($inputField, $expectedAfterValidation); + $I->comment('Test value of the internal field'); + $I->canSeeInField($internalInputField, $expectedInternal); + } - // validate that the save was successful - $I->canSeeInField($inputField, isset($testData['cleared'][1]) ? $testData['cleared'][1] : ''); - $I->canSeeInField($internalInputField, isset($testData['cleared'][0]) ? $testData['cleared'][0] : ''); + /** + */ + protected function waitForSaveToBeCompleted() + { + $I = $this->tester; + $I->comment('wait for save to be completed'); + $I->waitForElement('//*/button[@name="_savedok"][not(@disabled)][1]', 30); + $I->waitForElement($this->initializedInputFieldXpath, 30); + $I->waitForElement($this->internalInputFieldXpath, 30); } }