Skip to content

Commit

Permalink
Rough out Middleware Dispatcher
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
markstory committed Jun 14, 2016
1 parent 9f0820d commit 0ef9d47
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 5 deletions.
9 changes: 5 additions & 4 deletions src/TestSuite/IntegrationTestCase.php
Expand Up @@ -386,9 +386,7 @@ public function delete($url)
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);
}
Expand All @@ -414,8 +412,11 @@ protected function _sendRequest($url, $method, $data = [])
* @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) {
Expand Down
88 changes: 88 additions & 0 deletions 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);
}
}
52 changes: 51 additions & 1 deletion tests/TestCase/TestSuite/IntegrationTestCaseTest.php
Expand Up @@ -43,6 +43,7 @@ public function setUp()
DispatcherFactory::clear();
DispatcherFactory::add('Routing');
DispatcherFactory::add('ControllerFactory');
$this->useHttpServer(false);
}

/**
Expand Down Expand Up @@ -172,6 +173,23 @@ public function testGet()
$this->assertEquals('This is a test', $this->_response->body());
}

/**
* 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.
*
Expand All @@ -191,6 +209,39 @@ public function testRequestSetsProperties()
$this->assertEquals('value', $this->viewVariable('test'));
}

/**
* 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.
*
Expand Down Expand Up @@ -242,7 +293,6 @@ public function testCookieNotSetFailure()
$this->assertCookieNotSet('remember_me');
}


/**
* Tests the failure message for assertCookieNotSet when no
* response whas generated
Expand Down
39 changes: 39 additions & 0 deletions 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;
}
}

0 comments on commit 0ef9d47

Please sign in to comment.