Commit 1bf5a17b authored by Nikola Stojiljkovic's avatar Nikola Stojiljkovic Committed by Christian Kuhn
Browse files

[TASK] Tweak of the Formhandler acceptance tests

Includes:
* Added testing of persistence
* Added tests for datetime fields
* Prevent random timeouts from affecting the test results
* Added displaying of modal with error message instead of an alert
  on trying to save a form with validation errors

The tests are stable using Selenium with Firefox. Using phantomjs gives
erratic results due to "QIODevice::write (QTcpSocket): device not open"
bug which randomly pops up.

Resolves: #76122
Releases: master
Change-Id: Ia0c06fc4dbd83e2373d33bb07c48559894fc3ec5
Reviewed-on: https://review.typo3.org/48068


Reviewed-by: Anja Leichsenring's avatarAnja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring's avatarAnja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
parent 24b61262
......@@ -131,13 +131,15 @@ define(['jquery', 'TYPO3/CMS/Backend/FormEngine'], function ($, FormEngine) {
$humanReadableField.val(value);
}
}
$humanReadableField.data('main-field', fieldName);
$humanReadableField.data('config', config);
$humanReadableField.on('change', function() {
FormEngineValidation.updateInputField($(this).attr('data-formengine-input-name'));
});
$humanReadableField.on('keyup', FormEngineValidation.validate);
// add the attribute so that acceptance tests can know when the field initialization has completed
$humanReadableField.attr('data-formengine-input-initialized', 'true');
};
/**
......
......@@ -226,7 +226,24 @@ var TBE_EDITOR = {
if (OK || sendAlert==-1) {
return true;
} else {
if (sendAlert) alert(TBE_EDITOR.labels.fieldsMissing);
if (sendAlert) {
var t = (opener != null && typeof opener.top.TYPO3 !== 'undefined' ? opener.top : top);
t.TYPO3.Modal.confirm(
t.TYPO3.lang['alert'] || 'Alert',
TBE_EDITOR.labels.fieldsMissing,
t.TYPO3.Severity.error,
[
{
text: t.TYPO3.lang['button.ok'] || 'OK',
active: true,
btnClass: 'btn-default',
name: 'ok'
}
]
).on('button.clicked', function(e) {
t.TYPO3.Modal.dismiss();
});
}
return false;
}
},
......
......@@ -44,41 +44,73 @@ class ElementsBasicCest
*/
public function checkThatBrowserSideValidationsWorkAndSaveRecord(Admin $I, Formhandler $formhandler)
{
$I->click(self::$listViewRecordSelector . ' a[data-original-title="Edit record"]');
$editRecordLinkCssPath = self::$listViewRecordSelector . ' a[data-original-title="Edit record"]';
$I->waitForElement($editRecordLinkCssPath, 30);
$I->click($editRecordLinkCssPath);
$I->waitForText('Edit Form', 3, 'h1');
$fieldTests = [
'input_1' => [
'tests' => [
[
'This is a demo text with 2 numbers #!',
'This is a demo text with 2 numbers #!',
],
],
'cleared' => [
''
]
],
'input_2, size=10' => [
'tests' => [
[
'This is a demo text with 2 numbers #!',
'This is a demo text with 2 numbers #!',
],
],
'cleared' => [
''
]
],
'input_3 max=4' => [
'tests' => [
[
'Kasper',
'Kasp',
],
],
'cleared' => [
''
]
],
'input_4 eval=alpha' => [
'tests' => [
[
'Kasper = TYPO3',
'KasperTYPO',
],
[
'Non-latin characters: ŠĐŽĆČ',
'Nonlatincharacters',
],
],
'cleared' => [
''
]
],
'input_5 eval=alphanum' => [
'tests' => [
[
'Kasper = TYPO3',
'KasperTYPO3',
],
],
'cleared' => [
''
]
],
'input_6 eval=date' => [
'tests' => [
[
'29-01-2016',
'29-01-2016',
......@@ -89,59 +121,183 @@ class ElementsBasicCest
'13-01-2017',
'1484265600',
],
'check valid leap year input' => [
[
'29-02-2016',
'29-02-2016',
'1456704000',
false,
'Check valid leap year input'
],
'check invalid leap year transformation' => [
[
'29-02-2015',
'01-03-2015',
'1425168000',
false,
'Check invalid leap year transformation'
],
],
'cleared' => [
'0'
]
],
'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'
]
],
'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'
]
],
'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'
]
],
'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',
]
],
'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',
'0',
]
],
'input_10 eval=is_in, is_in=abc123' => [
'tests' => [
[
'abcd1234',
'abc123',
......@@ -151,32 +307,60 @@ class ElementsBasicCest
'a3',
],
],
'cleared' => [
'',
]
],
'input_11 eval=lower' => [
'tests' => [
[
'Kasper TYPO3!',
'kasper typo3!',
],
],
'cleared' => [
'',
]
],
'input_12 eval=md5' => [
'tests' => [
[
'Kasper TYPO3!',
'748469dd64911af8df8f9a3dcb2c9378',
'748469dd64911af8df8f9a3dcb2c9378',
],
'check that whitespace is not trimmed' => [
'Kasper TYPO3! ',
'265e09df9b9b08ab1f946510f510d3ef',
[
' 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
'792a085606250c47d6ebb8c98804d5b0',
'792a085606250c47d6ebb8c98804d5b0'
]
],
'input_13 eval=nospace' => [
'tests' => [
[
' Kasper TYPO3! ',
'KasperTYPO3!',
],
],
'cleared' => [
'',
]
],
// @todo define test
//'input_14 eval=null' => [
//],
'input_15 eval=num' => [
'tests' => [
[
'12.335',
'12335',
......@@ -194,14 +378,24 @@ class ElementsBasicCest
'3',
],
],
'cleared' => [
'',
]
],
'input_16 eval=password' => [
'tests' => [
[
'Kasper',
'********',
'Kasper',
],
],
'cleared' => [
'',
]
],
'input_17 eval=time' => [
'tests' => [
[
'13:30',
'13:30',
......@@ -228,7 +422,13 @@ class ElementsBasicCest
'43560',
]
],
'cleared' => [
'0',
'00:00',
]
],
'input_18 eval=timesec' => [
'tests' => [
[
'13:30:00',
'13:30:00',
......@@ -246,7 +446,13 @@ class ElementsBasicCest
'43744',
],
],
'cleared' => [
'0',
'00:00:00',
]
],
'input_19 eval=trim' => [
'tests' => [
[
' Kasper ',
'Kasper',
......@@ -256,6 +462,10 @@ class ElementsBasicCest
'Kasper TYPO3',
],
],
'cleared' => [
'',
]
],
// @todo Check why this test is currently broken
//'input_20 eval with user function' => [
// [
......@@ -264,54 +474,84 @@ class ElementsBasicCest
// ]
//],
'input_23 eval=upper' => [
'tests' => [
[
'Kasper TYPO3!',
'KASPER TYPO3!',
],
],
'cleared' => [
'',
]
],
'input_24 eval=year' => [
'tests' => [
[
'2016',
'2016',
'2016',
],
[
'12',
'2012',
'2012',
],
'Invalid character is converted to current year' => [
[
'Kasper',
date('Y'),
date('Y'),
false,
'Invalid character is converted to current year'
],
],
'cleared' => [
'0',
'0',
]
],
'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',
// @todo Check for validation error
'-3',
true,
'Expecting a modal with error on trying to save.'
],
[
'3',
'3',
// @todo Check for validation error
'-3',
'-3',
true,
'Expecting a modal with error on trying to save.'
],
],
'cleared' => [
'0',
'0'
]
],
];
foreach ($fieldTests as $fieldKey => $testData) {
$formhandler->fillSeeDeleteInputField(
$formhandler->getContextForFormhandlerField($fieldKey),
foreach ($fieldTests as $fieldLabel => $testData) {
$formhandler->fillSeeSaveAndClearInputField(
$fieldLabel,
$testData
);
}
......
......@@ -15,6 +15,7 @@ namespace TYPO3\CMS\Core\Tests\Acceptance\Support\Helper;
*/
use Facebook\WebDriver\Remote\RemoteWebElement;
use Facebook\WebDriver\WebDriverKeys;
/**
* Helper to interact with formhandler fields
......@@ -44,22 +45,21 @@ class Formhandler
* @param string $fieldName
* @return RemoteWebElement
*/
public function getContextForFormhandlerField(string $fieldName)
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) {
// TODO FIX THAT! MUST JUST BE ONE XPATH (and maybe it should work)
return $webdriver->findElement(\WebDriverBy::xpath('//label[contains(text(),"' . $fieldName . '")]'))->findElement(
\WebDriverBy::xpath('ancestor::fieldset[@class="form-section"][1]')
return $webdriver->findElement(
\WebDriverBy::xpath('(//label[contains(text(),"' . $fieldName . '")])[1]/ancestor::fieldset[@class="form-section"][1]')
);
});
}
/**
* @param RemoteWebElement $fieldContext
* @param array $testValues An array of arrays that contains the values to validate.
* @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
......@@ -67,33 +67,97 @@ class Formhandler
* Example for field with alpha validation: [['foo', 'foo'], ['bar1'], ['bar']]
* Example for field with date validation: [['29-01-2016', '29-01-2016', '1454025600']]
*/
public function fillSeeDeleteInputField(RemoteWebElement $fieldContext, array $testValues)
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.');
$inputField = $fieldContext->findElement(\WebDriverBy::xpath('.//*/input[@data-formengine-input-name]'));
$internalInputField = $fieldContext->findElement(\WebDriverBy::xpath('.//*/input[@name="' . $inputField->getAttribute('data-formengine-input-name') . '"]'));
$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') . '"]';
foreach ($testValues as $comment => $testValue) {
if (!empty($comment)) {
$I->comment($comment);
$I->waitForElement($internalInputFieldXpath, 30);
$I->waitForElement($clearButtonXpath, 30);
// 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));
foreach ($testData['tests'] as $testValue) {
if (isset($testValue[4])) {
$I->comment($testValue[4]);
}