. namespace hoplite\test; use hoplite\http as http; require_once HOPLITE_ROOT . '/http/action.php'; require_once HOPLITE_ROOT . '/http/front_controller.php'; require_once HOPLITE_ROOT . '/http/interceptor.php'; require_once HOPLITE_ROOT . '/http/output_filter.php'; require_once HOPLITE_ROOT . '/http/url_map.php'; class ActionReporter extends http\Action { public $did_invoke = FALSE; public function Invoke(http\Request $q, http\Response $s) { $this->did_invoke = TRUE; } } class ClosureInterceptor implements http\Interceptor { private $interceptor; public $did_intercept = FALSE; public function __construct($interceptor) { $this->interceptor = $interceptor; } public function DoIntercept(http\FrontController $controller, http\Action $action = NULL, http\Request $request, http\Response $response) { $this->did_intercept = TRUE; if ($this->interceptor) { $interceptor = $this->interceptor; $interceptor($controller, $action, $request, $response); } } } class FrontControllerTest extends \PHPUnit_Framework_TestCase { /*! Configures a mock FrontControler. @param array|NULL Array of methods to mock @param varargs Constructor parameters. @return Mock FrontControler */ public function ConfigureMock() { $args = func_get_args(); return $this->getMock('hoplite\http\FrontController', $args[0], array_slice($args, 1)); } public function testProcessRequest() { $globals = array('_SERVER' => array( 'REQUEST_METHOD' => 'GET', 'PATH_INFO' => '/some/action/42' )); $mock = $this->ConfigureMock(array('RouteRequest', 'SendResponse'), $globals); $mock->request()->url = 'some/action/42'; $mock->expects($this->once()) ->method('RouteRequest') ->with($this->equalTo($mock->request())); $mock->expects($this->once()) ->method('SendResponse'); $mock->ProcessRequest(); } public function testRouteRequest() { $globals = array(); $mock = $this->ConfigureMock(array('SendResponse', 'InvokeAction'), $globals); $mock->request()->url = 'some/action/42'; $map_value = 'ActionReporter'; $action = new ActionReporter($mock); $url_map = $this->getMock('hoplite\http\UrlMap', array(), array($mock)); $url_map->expects($this->once()) ->method('Evaluate') ->with($this->equalTo($mock->request())) ->will($this->returnValue($map_value)); $url_map->expects($this->once()) ->method('LookupAction') ->with($this->equalTo($map_value)) ->will($this->returnValue($action)); $mock->set_url_map($url_map); $mock->RouteRequest($mock->request()); $this->assertTrue($action->did_invoke); } public function testRouteRequestInvalid() { $globals = array(); $mock = $this->ConfigureMock(array('SendResponse'), $globals); $mock->request()->url = 'another/action'; $mock->expects($this->never()) ->method('SendResponse'); $url_map = $this->getMock('hoplite\http\UrlMap', array(), array($mock)); $url_map->expects($this->once()) ->method('Evaluate') ->with($this->equalTo($mock->request())); $mock->set_url_map($url_map); $mock->RouteRequest($mock->request()); // Nothing should happen for a non-routed request. } public function testSendResponse() { $globals = array(); $mock = $this->ConfigureMock(array('_Exit'), $globals); $mock->expects($this->once()) ->method('_Exit'); $output_filter = $this->getMock('hoplite\http\OutputFilter', array(), array($mock)); $output_filter->expects($this->once()) ->method('FilterOutput') ->with($this->isInstanceOf('hoplite\http\Request'), $this->isInstanceOf('hoplite\http\Response')); $mock->set_output_filter($output_filter); $mock->SendResponse(); } public function testStopWithRedirect() { $globals = array(); $mock = $this->ConfigureMock(array('_Exit'), $globals); $mock->expects($this->once()) ->method('_Exit'); $output_filter = $this->getMock('hoplite\http\OutputFilter', array(), array($mock)); $output_filter->expects($this->once()) ->method('FilterOutput') ->with($this->isInstanceOf('hoplite\http\Request'), $this->isInstanceOf('hoplite\http\Response')); $mock->set_output_filter($output_filter); $mock->SendResponseRedirect('/foo/bar'); $this->assertEquals('/foo/bar', $mock->response()->headers['Location']); $this->assertEquals(http\ResponseCode::FOUND, $mock->response()->response_code); } public function testAbsolutify() { $globals = array( '_SERVER' => array( 'HTTP_HOST' => 'www.bluestatic.org', 'REQUEST_URI' => '/hoplite/webapp/test/path', 'PATH_INFO' => '/test/path', 'SERVER_PORT' => 80, ), ); $mock = new \hoplite\http\FrontController($globals); $this->assertEquals($mock->MakeURL('/'), '/hoplite/webapp/'); $this->assertEquals($mock->MakeURL('/', TRUE), 'http://www.bluestatic.org/hoplite/webapp/'); $this->assertEquals($mock->MakeURL('/path/2'), '/hoplite/webapp/path/2'); $this->assertEquals($mock->MakeURL('/path/3', TRUE), 'http://www.bluestatic.org/hoplite/webapp/path/3'); $globals['_SERVER']['HTTPS'] = 'on'; $globals['_SERVER']['SERVER_PORT'] = 443; $mock = new \hoplite\http\FrontController($globals); $this->assertEquals($mock->MakeURL('/'), '/hoplite/webapp/'); $this->assertEquals($mock->MakeURL('/', TRUE), 'https://www.bluestatic.org/hoplite/webapp/'); $this->assertEquals($mock->MakeURL('/path/2'), '/hoplite/webapp/path/2'); $this->assertEquals($mock->MakeURL('/path/3', TRUE), 'https://www.bluestatic.org/hoplite/webapp/path/3'); $globals['_SERVER']['SERVER_PORT'] = 8080; $mock = new \hoplite\http\FrontController($globals); $this->assertEquals($mock->MakeURL('/path/2'), '/hoplite/webapp/path/2'); $this->assertEquals($mock->MakeURL('/', TRUE), 'https://www.bluestatic.org:8080/hoplite/webapp/'); $this->assertEquals($mock->MakeURL('/path/3', TRUE), 'https://www.bluestatic.org:8080/hoplite/webapp/path/3'); } public function testAbsolutifyFront() { $globals = array( '_SERVER' => array( 'HTTP_HOST' => 'www.bluestatic.org', 'REQUEST_URI' => '/hoplite/webapp/', 'PATH_INFO' => NULL, 'SERVER_PORT' => 80, ), ); $mock = new \hoplite\http\FrontController($globals); $this->assertEquals($mock->MakeURL('/'), '/hoplite/webapp/'); $this->assertEquals($mock->MakeURL('/', TRUE), 'http://www.bluestatic.org/hoplite/webapp/'); $globals['_SERVER']['HTTPS'] = 'on'; $globals['_SERVER']['SERVER_PORT'] = 443; $mock = new \hoplite\http\FrontController($globals); $this->assertEquals($mock->MakeURL('/'), '/hoplite/webapp/'); $this->assertEquals($mock->MakeURL('/', TRUE), 'https://www.bluestatic.org/hoplite/webapp/'); $this->assertEquals($mock->MakeURL('/path/2'), '/hoplite/webapp/path/2'); $this->assertEquals($mock->MakeURL('/path/3', TRUE), 'https://www.bluestatic.org/hoplite/webapp/path/3'); $globals['_SERVER']['SERVER_PORT'] = 8080; $mock = new \hoplite\http\FrontController($globals); $this->assertEquals($mock->MakeURL('/path/2'), '/hoplite/webapp/path/2'); $this->assertEquals($mock->MakeURL('/', TRUE), 'https://www.bluestatic.org:8080/hoplite/webapp/'); $this->assertEquals($mock->MakeURL('/path/3', TRUE), 'https://www.bluestatic.org:8080/hoplite/webapp/path/3'); } public function testThreeInterceptors() { $interceptors = [ new ClosureInterceptor(NULL), new ClosureInterceptor(NULL), new ClosureInterceptor(NULL), ]; $mock = new \hoplite\http\FrontController([]); $mock->set_url_map(new http\UrlMap($mock)); foreach ($interceptors as $interceptor) { $mock->AddInterceptor($interceptor); } $mock->RouteRequest($mock->request()); foreach ($interceptors as $interceptor) { $this->assertTrue($interceptor->did_intercept); } } public function testInterruptInterceptor() { $i1 = new ClosureInterceptor(NULL); $i2 = new ClosureInterceptor(function($controller, $action, $request, $response) { $controller->SendResponseCode(400); }); $test = $this; $i3 = new ClosureInterceptor(function($controller, $action, $request, $response) use ($test) { $test->assertEquals(400, $response->response_code); }); $mock = $this->ConfigureMock(['SendResponse'], []); $mock->set_url_map(new http\UrlMap($mock)); $mock->AddInterceptor($i1); $mock->AddInterceptor($i2); $mock->AddInterceptor($i3); $mock->expects($this->once()) ->method('SendResponse'); $mock->RouteRequest($mock->request()); $this->assertEquals(400, $mock->response()->response_code); $this->assertTrue($i1->did_intercept); $this->assertTrue($i2->did_intercept); // i3 would not normally run but because _Exit is mocked, the script does // not finish. } }