ソースを参照

Rough out Middleware Dispatcher

This is a very very rough prototype of how PSR7 request dispatching could be
integrated into into the TestSuite. There is still a lot TODO, but
a very basic GET request is somewhat functional right now.
Mark Story 9 年 前
コミット
0ef9d475a1

+ 5 - 4
src/TestSuite/IntegrationTestCase.php

@@ -386,9 +386,7 @@ abstract class IntegrationTestCase extends TestCase
     protected function _sendRequest($url, $method, $data = [])
     {
         if ($this->_useHttpServer) {
-            // The PSR7 mode will need to convert back into a cake request.
-            // and figure out how to handle the session data.
-            throw new \LogicException('Not implemented yet.');
+            $dispatcher = new MiddlewareDispatcher($this);
         } else {
             $dispatcher = new RequestDispatcher($this);
         }
@@ -414,8 +412,11 @@ abstract class IntegrationTestCase extends TestCase
      * @param \Cake\Controller\Controller $controller Controller instance.
      * @return void
      */
-    public function controllerSpy($event, $controller)
+    public function controllerSpy($event, $controller = null)
     {
+        if (!$controller) {
+            $controller = $event->subject();
+        }
         $this->_controller = $controller;
         $events = $controller->eventManager();
         $events->on('View.beforeRender', function ($event, $viewFile) {

+ 88 - 0
src/TestSuite/MiddlewareDispatcher.php

@@ -0,0 +1,88 @@
+<?php
+/**
+ * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
+ * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the LICENSE.txt
+ * Redistributions of files must retain the above copyright notice
+ *
+ * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ * @since         3.3.0
+ * @license       http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+namespace Cake\TestSuite;
+
+use Cake\Core\Configure;
+use Cake\Event\EventManager;
+use Cake\Http\ResponseTransformer;
+use Cake\Http\Server;
+use Cake\Http\ServerRequestFactory;
+use LogicException;
+use ReflectionClass;
+use ReflectionException;
+
+/**
+ * Dispatches a request capturing the response for integration
+ * testing purposes into the Cake\Http stack.
+ *
+ * @internal
+ */
+class MiddlewareDispatcher
+{
+    /**
+     * Constructor
+     *
+     * @param \Cake\TestSuite\IntegrationTestCase $test The test case to run.
+     */
+    public function __construct($test)
+    {
+        $this->_test = $test;
+    }
+
+    /**
+     * Run a request and get the response.
+     *
+     * @param \Cake\Network\Request $request The request to execute.
+     * @return \Cake\Network\Response The generated response.
+     */
+    public function execute($request)
+    {
+        try {
+            $namespace = Configure::read('App.namespace');
+            $reflect = new ReflectionClass($namespace . '\Application');
+            $app = $reflect->newInstance('./config');
+        } catch (ReflectionException $e) {
+            throw new LogicException(sprintf(
+                'Cannot load "%s" for use in integration testing.',
+                $class
+            ));
+        }
+
+        // Spy on the controller using the initialize hook instead
+        // of the dispatcher hooks as those will be going away one day.
+        EventManager::instance()->on(
+            'Controller.initialize',
+            [$this->_test, 'controllerSpy']
+        );
+
+        $server = new Server($app);
+
+        // TODO How to handle passing all headers.
+        // The Request doesn't expose a way to read all headers values.
+        // TODO How to pass session data? PSR7 requests don't handle sessions..
+        // TODO pass php://input stream, base, webroot
+        $serverData = [
+            'REQUEST_URI' => $request->here,
+            'REQUEST_METHOD' => $request->method(),
+        ];
+        $psrRequest = ServerRequestFactory::fromGlobals(
+            array_merge($_SERVER, $serverData),
+            $request->query,
+            $request->data(),
+            $request->cookies
+        );
+        $response = $server->run($psrRequest);
+        return ResponseTransformer::toCake($response);
+    }
+}

+ 51 - 1
tests/TestCase/TestSuite/IntegrationTestCaseTest.php

@@ -43,6 +43,7 @@ class IntegrationTestCaseTest extends IntegrationTestCase
         DispatcherFactory::clear();
         DispatcherFactory::add('Routing');
         DispatcherFactory::add('ControllerFactory');
+        $this->useHttpServer(false);
     }
 
     /**
@@ -173,6 +174,23 @@ class IntegrationTestCaseTest extends IntegrationTestCase
     }
 
     /**
+     * Test sending get requests with Http\Server
+     *
+     * @return void
+     */
+    public function testGetHttpServer()
+    {
+        DispatcherFactory::clear();
+        $this->useHttpServer(true);
+        $this->assertNull($this->_response);
+
+        $this->get('/request_action/test_request_action');
+        $this->assertNotEmpty($this->_response);
+        $this->assertInstanceOf('Cake\Network\Response', $this->_response);
+        $this->assertEquals('This is a test', $this->_response->body());
+    }
+
+    /**
      * Test sending requests stores references to controller/view/layout.
      *
      * @return void
@@ -192,6 +210,39 @@ class IntegrationTestCaseTest extends IntegrationTestCase
     }
 
     /**
+     * Test PSR7 requests store references to controller/view/layout
+     *
+     * @return void
+     */
+    public function testRequestSetsPropertiesHttpServer()
+    {
+        $this->markTestIncomplete('not done');
+        DispatcherFactory::clear();
+        $this->useHttpServer(true);
+
+        $this->post('/posts/index');
+        $this->assertInstanceOf('Cake\Controller\Controller', $this->_controller);
+        $this->assertNotEmpty($this->_viewName, 'View name not set');
+        $this->assertContains('Template' . DS . 'Posts' . DS . 'index.ctp', $this->_viewName);
+        $this->assertNotEmpty($this->_layoutName, 'Layout name not set');
+        $this->assertContains('Template' . DS . 'Layout' . DS . 'default.ctp', $this->_layoutName);
+
+        $this->assertTemplate('index');
+        $this->assertLayout('default');
+        $this->assertEquals('value', $this->viewVariable('test'));
+    }
+
+    /**
+     * Test that the PSR7 requests get post, cookies, and other request data passed along.
+     *
+     * @return void
+     */
+    public function testPsrRequestData()
+    {
+        $this->markTestIncomplete('not done');
+    }
+
+    /**
      * Assert that the stored template doesn't change when cells are rendered.
      *
      * @return void
@@ -242,7 +293,6 @@ class IntegrationTestCaseTest extends IntegrationTestCase
         $this->assertCookieNotSet('remember_me');
     }
 
-
     /**
      * Tests the failure message for assertCookieNotSet when no
      * response whas generated

+ 39 - 0
tests/test_app/TestApp/Application.php

@@ -0,0 +1,39 @@
+<?php
+/**
+ * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
+ * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the LICENSE.txt
+ * Redistributions of files must retain the above copyright notice
+ *
+ * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ * @link          http://cakephp.org CakePHP(tm) Project
+ * @since         3.3.0
+ * @license       http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+namespace TestApp;
+
+use Cake\Http\BaseApplication;
+use Cake\Routing\Middleware\RoutingMiddleware;
+
+class Application extends BaseApplication
+{
+    /**
+     * Bootstrap hook.
+     *
+     * Nerfed as this is for IntegrationTestCase testing.
+     *
+     * @return void
+     */
+    public function bootstrap()
+    {
+        // Do nothing.
+    }
+
+    public function middleware($middleware)
+    {
+        $middleware->push(new RoutingMiddleware());
+        return $middleware;
+    }
+}