[TASK] Add functional test for exbase validation caching 07/49307/15
authorAlexander Stehlik <alexander.stehlik@gmail.com>
Sat, 9 Jun 2018 16:50:11 +0000 (18:50 +0200)
committerAnja Leichsenring <aleichsenring@ab-softlab.de>
Sat, 9 Jun 2018 19:41:37 +0000 (21:41 +0200)
The tests demonstrate the issue described in the ticket
is not present anymore.

Resolves: #77338
Releases: master
Change-Id: I7002b9754f556f23850fda5026861c742f70bcdc
Reviewed-on: https://review.typo3.org/49307
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Classes/Controller/BlogController.php
typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Classes/Domain/Validator/PostValidator.php [new file with mode: 0644]
typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/ext_localconf.php
typo3/sysext/extbase/Tests/Functional/Mvc/Validation/ActionControllerValidationTest.php [new file with mode: 0644]

index a67538b..8c2b3d3 100644 (file)
@@ -16,6 +16,7 @@ namespace ExtbaseTeam\BlogExample\Controller;
  */
 
 use TYPO3\CMS\Extbase\Annotation as Extbase;
+use TYPO3\CMS\Extbase\Annotation\IgnoreValidation;
 
 /**
  * BlogController
@@ -51,6 +52,43 @@ class BlogController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController
     }
 
     /**
+     * @return string
+     */
+    public function testFormAction()
+    {
+        return 'testFormAction';
+    }
+
+    /**
+     * @param \ExtbaseTeam\BlogExample\Domain\Model\Post $blogPost
+     * // needs to be imported entirely, else the annotationChecker script of bamboo will complain
+     * @IgnoreValidation("blogPost")
+     */
+    public function testForwardAction($blogPost)
+    {
+        $this->forward('testForwardTarget', null, null, ['blogPost' => $blogPost]);
+    }
+
+    /**
+     * @param \ExtbaseTeam\BlogExample\Domain\Model\Post $blogPost
+     * @return string
+     */
+    public function testForwardTargetAction($blogPost)
+    {
+        return 'testForwardTargetAction';
+    }
+
+    /**
+     * @param \ExtbaseTeam\BlogExample\Domain\Model\Blog $blog
+     * @param \ExtbaseTeam\BlogExample\Domain\Model\Post $blogPost
+     * @return string
+     */
+    public function testRelatedObjectAction($blog, $blogPost = null)
+    {
+        return 'testRelatedObject';
+    }
+
+    /**
      * @param \TYPO3\CMS\Extbase\Mvc\RequestInterface $request
      * @param \TYPO3\CMS\Extbase\Mvc\ResponseInterface $response
      * @throws \RuntimeException
@@ -68,6 +106,17 @@ class BlogController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController
     }
 
     /**
+     * Disable the default error flash message, otherwise we get an error because the flash message
+     * session handling is not available during functional tests.
+     *
+     * @return bool
+     */
+    protected function getErrorFlashMessage()
+    {
+        return false;
+    }
+
+    /**
      * @param \Iterator|\TYPO3\CMS\Extbase\DomainObject\AbstractEntity[] $iterator
      * @return array
      */
diff --git a/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Classes/Domain/Validator/PostValidator.php b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Classes/Domain/Validator/PostValidator.php
new file mode 100644 (file)
index 0000000..16781ae
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+namespace ExtbaseTeam\BlogExample\Domain\Validator;
+
+/*
+ * 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!
+ */
+
+use ExtbaseTeam\BlogExample\Domain\Model\Post;
+use TYPO3\CMS\Extbase\Validation\Error;
+use TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator;
+
+/**
+ * A custom validator for blog posts.
+ */
+class PostValidator extends AbstractValidator
+{
+
+    /**
+     * Check if $value is valid. If it is not valid, needs to add an error
+     * to result.
+     *
+     * @param Post $value
+     */
+    protected function isValid($value)
+    {
+        if ($value->getTitle() === '77') {
+            $error = new Error('Title custom validation failed', 1480872650);
+            $this->result->forProperty('title')->addError($error);
+        }
+    }
+}
index 6d5907c..0ec79aa 100644 (file)
@@ -5,7 +5,7 @@ defined('TYPO3_MODE') or die();
     'ExtbaseTeam.BlogExample',
     'Blogs',
     [
-        'Blog' => 'list',
+        'Blog' => 'list,testForm,testForward,testForwardTarget,testRelatedObject',
     ],
     []
 );
diff --git a/typo3/sysext/extbase/Tests/Functional/Mvc/Validation/ActionControllerValidationTest.php b/typo3/sysext/extbase/Tests/Functional/Mvc/Validation/ActionControllerValidationTest.php
new file mode 100644 (file)
index 0000000..424a453
--- /dev/null
@@ -0,0 +1,196 @@
+<?php
+namespace TYPO3\CMS\Extbase\Tests\Functional\Mvc\Validation;
+
+/*
+ * 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!
+ */
+
+use ExtbaseTeam\BlogExample\Controller\BlogController;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Extbase\Error\Error;
+use TYPO3\CMS\Extbase\Mvc\Controller\MvcPropertyMappingConfigurationService;
+use TYPO3\CMS\Extbase\Object\ObjectManager;
+use TYPO3\CMS\Extbase\Security\Cryptography\HashService;
+use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
+
+/**
+ * Tests for the validation logic of the Extbase ActionController.
+ */
+class ActionControllerValidationTest extends FunctionalTestCase
+{
+    /**
+     * @var array
+     */
+    protected $testExtensionsToLoad = [
+        'typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example'
+    ];
+
+    /**
+     * @return array
+     */
+    public function forwardedActionValidatesPreviouslyIgnoredArgumentDataProvider()
+    {
+        return [
+            'new blog post' => [
+                ['title' => '12'],
+                ['blogPost[title]'],
+                [1428504122]
+            ],
+            'existing blog post' => [
+                ['__identity' => 1, 'title' => '12'],
+                ['blogPost[__identity]', 'blogPost[title]'],
+                [1428504122]
+            ],
+            'existing blog post custom validator' => [
+                ['__identity' => 1, 'title' => '77'],
+                ['blogPost[__identity]', 'blogPost[title]'],
+                [1428504122, 1480872650]
+            ],
+        ];
+    }
+
+    /**
+     * @test
+     * @dataProvider forwardedActionValidatesPreviouslyIgnoredArgumentDataProvider
+     * @param array $blogPostArgument
+     * @param array $trustedProperties
+     * @param array $expectedErrorCodes
+     */
+    public function forwardedActionValidatesPreviouslyIgnoredArgument(array $blogPostArgument, array $trustedProperties, array $expectedErrorCodes)
+    {
+        $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] = 'testkey';
+
+        $this->importDataSet('PACKAGE:typo3/testing-framework/Resources/Core/Functional/Fixtures/pages.xml');
+        $this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/blogs.xml');
+        $this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/posts.xml');
+
+        $objectManager = $this->getObjectManager();
+        $response = $objectManager->get(\TYPO3\CMS\Extbase\Mvc\Web\Response::class);
+        $request = $objectManager->get(\TYPO3\CMS\Extbase\Mvc\Web\Request::class);
+
+        $request->setControllerActionName('testForward');
+        $request->setArgument('blogPost', $blogPostArgument);
+        $request->setArgument('__trustedProperties', $this->generateTrustedPropertiesToken($trustedProperties));
+
+        $referrerRequest['@action'] = 'testForm';
+        $request->setArgument(
+            '__referrer',
+            ['@request' => $this->getHashService()->appendHmac(serialize($referrerRequest))]
+        );
+
+        while (!$request->isDispatched()) {
+            try {
+                $blogController = $objectManager->get(BlogController::class);
+                $blogController->processRequest($request, $response);
+            } catch (\TYPO3\CMS\Extbase\Mvc\Exception\StopActionException $e) {
+            }
+        }
+
+        /* @var \TYPO3\CMS\Extbase\Error\Error $titleLengthError */
+        $titleMappingResults = $request->getOriginalRequestMappingResults()->forProperty('blogPost.title');
+        $titleErrors = $titleMappingResults->getFlattenedErrors();
+        $this->assertCount(count($expectedErrorCodes), $titleErrors['']);
+
+        $titleErrors = $titleErrors[''];
+        /** @var Error $titleError */
+        foreach ($titleErrors as $titleError) {
+            $this->assertContains($titleError->getCode(), $expectedErrorCodes);
+        }
+        $this->assertEquals('testFormAction', $response->getContent());
+    }
+
+    /**
+     * @test
+     */
+    public function validationResultsAreProvidedForTheSameObjectInDifferentArguments()
+    {
+        $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] = 'testkey';
+
+        $this->importDataSet('PACKAGE:typo3/testing-framework/Resources/Core/Functional/Fixtures/pages.xml');
+        $this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/blogs.xml');
+        $this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/posts.xml');
+
+        $objectManager = $this->getObjectManager();
+        $response = $objectManager->get(\TYPO3\CMS\Extbase\Mvc\Web\Response::class);
+        $request = $objectManager->get(\TYPO3\CMS\Extbase\Mvc\Web\Request::class);
+
+        $request->setControllerActionName('testRelatedObject');
+        $request->setArgument('blog', ['__identity' => 1, 'description' => str_repeat('test', 40)]);
+        $request->setArgument(
+            'blogPost',
+            ['__identity' => 1, 'title' => '77', 'blog' => ['__identity' => 1, 'title' => str_repeat('test', 21)]]
+        );
+        $request->setArgument(
+            '__trustedProperties',
+            $this->generateTrustedPropertiesToken(
+                [
+                    'blog[__identity]',
+                    'blog[description]',
+                    'blogPost[__identity]',
+                    'blogPost[title]',
+                    'blogPost[blog][__identity]',
+                    'blogPost[blog][title]'
+                ]
+            )
+        );
+
+        $referrerRequest['@action'] = 'testForm';
+        $request->setArgument(
+            '__referrer',
+            ['@request' => $this->getHashService()->appendHmac(serialize($referrerRequest))]
+        );
+
+        while (!$request->isDispatched()) {
+            try {
+                $blogController = $objectManager->get(BlogController::class);
+                $blogController->processRequest($request, $response);
+            } catch (\TYPO3\CMS\Extbase\Mvc\Exception\StopActionException $e) {
+            }
+        }
+
+        /* @var \TYPO3\CMS\Extbase\Error\Error $titleLengthError */
+        $errors = $request->getOriginalRequestMappingResults()->getFlattenedErrors();
+        $this->assertCount(1, $errors['blog.title']);
+        $this->assertCount(1, $errors['blog.description']);
+        $this->assertCount(2, $errors['blogPost.title']);
+
+        $this->assertEquals('testFormAction', $response->getContent());
+    }
+
+    /**
+     * @param array $formFieldNames
+     * @return string
+     */
+    protected function generateTrustedPropertiesToken(array $formFieldNames)
+    {
+        $mvcPropertyMappingConfigurationService = $this->getObjectManager()->get(
+            MvcPropertyMappingConfigurationService::class
+        );
+        return $mvcPropertyMappingConfigurationService->generateTrustedPropertiesToken($formFieldNames, '');
+    }
+
+    /**
+     * @return HashService
+     */
+    protected function getHashService()
+    {
+        return $this->getObjectManager()->get(HashService::class);
+    }
+
+    /**
+     * @return \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
+     */
+    protected function getObjectManager()
+    {
+        return GeneralUtility::makeInstance(ObjectManager::class);
+    }
+}