diff options
-rw-r--r-- | src/Controller/View.php | 38 | ||||
-rw-r--r-- | src/Controller/View/PHP.php | 40 | ||||
-rw-r--r-- | src/Controller/View/Twig.php | 22 | ||||
-rw-r--r-- | tests/Controller/View/PHPTest.php | 54 | ||||
-rw-r--r-- | tests/Controller/View/TwigTest.php | 298 | ||||
-rw-r--r-- | tests/Controller/ViewTest.php | 83 |
6 files changed, 246 insertions, 289 deletions
diff --git a/src/Controller/View.php b/src/Controller/View.php index f3e39de..b32c285 100644 --- a/src/Controller/View.php +++ b/src/Controller/View.php @@ -12,11 +12,23 @@ use Psr\Http\Message\ResponseInterface; trait View { /** + * @var ViewInterface + */ + protected $viewer; + + /** * Get server request * * @return ServerRequestInterface */ abstract public function getRequest(); + + /** + * Get server request + * + * @return ResponseInterface + */ + abstract public function getResponse(); /** * Get response. set for controller @@ -25,12 +37,30 @@ trait View */ abstract public function setResponse(ResponseInterface $response); + /** * Get the template engine abstraction * * @return ViewInterface */ - abstract public function getViewer(); + public function getViewer() + { + if (!isset($this->viewer)) { + throw new \LogicException("Viewer has not been set"); + } + + return $this->viewer; + } + + /** + * Get the template engine abstraction + * + * @param ViewInterface $viewer + */ + public function setViewer(ViewInterface $viewer) + { + $this->viewer = $viewer; + } /** @@ -38,7 +68,7 @@ trait View * * @return string */ - protected function getViewPath() + public function getViewPath() { return getcwd(); } @@ -51,13 +81,13 @@ trait View */ public function view($name, array $context = []) { - $context += ['current_url', $this->getRequest()->getUri()]; + $context += ['current_url' => $this->getRequest()->getUri()]; if (method_exists($this, 'flash')) { $context += ['flash' => $this->flash()]; } - $response = $this->getViewer()->view($this->getResponse(), $name, $context); + $response = $this->getViewer()->render($this->getResponse(), $name, $context); $this->setResponse($response); } diff --git a/src/Controller/View/PHP.php b/src/Controller/View/PHP.php new file mode 100644 index 0000000..0f7a5b7 --- /dev/null +++ b/src/Controller/View/PHP.php @@ -0,0 +1,40 @@ +<?php + +namespace Jasny\Controller\View; + +use Jasny\Controller\View; +use Jasny\View\PHP as PHPView; + +/** + * View using PHP + */ +trait PHP +{ + use View; + + /** + * Get the template engine abstraction + * + * @return PHPView + */ + public function getViewer() + { + if (!isset($this->viewer)) { + $this->viewer = $this->createPHPView(['path' => $this->getViewPath()]); + } + + return $this->viewer; + } + + /** + * Create a twig view object. + * @ignore + * @codeCoverageIgnore + * + * @return PHPView; + */ + protected function createPHPView($options) + { + return new PHPView($options); + } +} diff --git a/src/Controller/View/Twig.php b/src/Controller/View/Twig.php index c6c69af..78df6b0 100644 --- a/src/Controller/View/Twig.php +++ b/src/Controller/View/Twig.php @@ -3,10 +3,8 @@ namespace Jasny\Controller\View; use Jasny\Controller\View; -use Jasny\ViewInterface; use Jasny\View\Twig as TwigView; - /** * View using Twig */ @@ -15,12 +13,6 @@ trait Twig use View; /** - * @var ViewInterface - */ - protected $viewer; - - - /** * Get the template engine abstraction * * @return TwigView @@ -28,10 +20,22 @@ trait Twig public function getViewer() { if (!isset($this->viewer)) { - $this->viewer = new TwigView(['path' => $this->getViewPath()]); + $this->viewer = $this->createTwigView(['path' => $this->getViewPath()]); $this->viewer->addDefaultExtensions(); } return $this->viewer; } + + /** + * Create a twig view object. + * @ignore + * @codeCoverageIgnore + * + * @return TwigView; + */ + protected function createTwigView($options) + { + return new TwigView($options); + } } diff --git a/tests/Controller/View/PHPTest.php b/tests/Controller/View/PHPTest.php new file mode 100644 index 0000000..c9b8c3f --- /dev/null +++ b/tests/Controller/View/PHPTest.php @@ -0,0 +1,54 @@ +<?php + +namespace Jasny\Controller\View; + +use Jasny\Controller\View; +use Jasny\View\PHP as PHPView; +use Jasny\Controller\TestHelper; + +/** + * @covers Jasny\Controller\View\PHP + */ +class PHPTest extends \PHPUnit_Framework_TestCase +{ + use TestHelper { + getController as private _getController; + } + + /** + * @return string + */ + protected function getControllerClass() + { + return View\PHP::class; + } + + /** + * Get mock controller + * + * @param array $methods + * @param string $className + * @return RouteActionController|\PHPUnit_Framework_MockObject_MockObject + */ + protected function getController($methods = [], $className = null) + { + $controller = $this->_getController(array_merge($methods, ['createPHPView', 'getViewPath']), $className); + $controller->method('getViewPath')->willReturn('/tmp'); + + return $controller; + } + + + public function testGetViewer() + { + $viewer = $this->createMock(PHPView::class); + + $controller = $this->getController(); + $controller->method('createPHPView')->willReturn($viewer); + + $this->assertSame($viewer, $controller->getViewer()); + + // Idempotent + $this->assertSame($viewer, $controller->getViewer()); + } +} diff --git a/tests/Controller/View/TwigTest.php b/tests/Controller/View/TwigTest.php index 8fe27c7..566787f 100644 --- a/tests/Controller/View/TwigTest.php +++ b/tests/Controller/View/TwigTest.php @@ -3,307 +3,53 @@ namespace Jasny\Controller\View; use Jasny\Controller\View; -use Jasny\Controller\Session\Flash; -use Psr\Http\Message\ServerRequestInterface; -use Psr\Http\Message\UriInterface; +use Jasny\View\Twig as TwigView; use Jasny\Controller\TestHelper; /** - * @covers Jasny\Controller\View * @covers Jasny\Controller\View\Twig */ class TwigTest extends \PHPUnit_Framework_TestCase { - use TestHelper; - - protected function getControllerClass() - { - return View\Twig::class; - } - - /** - * Test creating twig environment - */ - public function testCreateTwigEnvironment() - { - $controller = $this->getController([]); - $twig = $controller->createTwigEnvironment(); - - $this->assertInstanceOf(\Twig_Environment::class, $twig); - $this->assertInstanceOf(\Twig_Loader_Filesystem::class, $twig->getLoader()); - $this->assertEquals([getcwd()], $twig->getLoader()->getPaths()); - } - - /** - * Test intializing twig environment - */ - public function testInitTwig() - { - $uri = $this->createMock(UriInterface::class); - - $request = $this->createMock(ServerRequestInterface::class); - $request->expects($this->once())->method('getUri')->willReturn($uri); - - $twig = $this->createMock(\Twig_Environment::class); - $twig->expects($this->once())->method('addGlobal')->with('current_url', $this->identicalTo($uri)); - - $controller = $this->getController(['createTwigEnvironment']); - $controller->expects($this->any())->method('getRequest')->willReturn($request); - $controller->expects($this->once())->method('createTwigEnvironment')->willReturn($twig); - - $controller->getTwig(); - } - - /** - * Test Jasny Twig extensions when intializing twig environment - */ - public function testInitTwigWithJasnyExtensions() - { - $request = $this->createMock(ServerRequestInterface::class); - - $twig = $this->createMock(\Twig_Environment::class); - $twig->expects($this->exactly(4))->method('addExtension')->withConsecutive( - [$this->isInstanceOf('Jasny\Twig\DateExtension')], - [$this->isInstanceOf('Jasny\Twig\PcreExtension')], - [$this->isInstanceOf('Jasny\Twig\TextExtension')], - [$this->isInstanceOf('Jasny\Twig\ArrayExtension')] - ); - - $controller = $this->getController(['createTwigEnvironment']); - $controller->expects($this->any())->method('getRequest')->willReturn($request); - $controller->expects($this->once())->method('createTwigEnvironment')->willReturn($twig); - - $controller->getTwig(); + use TestHelper { + getController as private _getController; } /** - * Test session flash when intializing twig environment + * @return string */ - public function testInitTwigWithSessionFlash() - { - $request = $this->createMock(ServerRequestInterface::class); - $flash = $this->createMock(Flash::class); - - $twig = $this->createMock(\Twig_Environment::class); - $twig->expects($this->any())->method('addGlobal')->withConsecutive([], ['flash', $flash]); - - $controller = $this->getController(['createTwigEnvironment', 'flash']); - $controller->expects($this->any())->method('getRequest')->willReturn($request); - $controller->expects($this->once())->method('flash')->willReturn($flash); - $controller->expects($this->once())->method('createTwigEnvironment')->willReturn($twig); - - $controller->getTwig(); - } - - /** - * Provide data for testing 'setViewVariable' method - * - * @return array - */ - public function setViewVariableProvider() - { - return [ - ['foo', null], - ['foo', 'bar'], - ['foo', ['bar', 'zoo']], - ['foo', (object)['a' => 'bar', 'b' => 'zoo']], - ]; - } - - /** - * Test 'setViewVariable' method - * - * @dataProvider setViewVariableProvider - */ - public function testSetViewVariable($name, $value) + protected function getControllerClass() { - $twig = $this->createMock(\Twig_Environment::class); - - $controller = $this->getController(['getTwig']); - $controller->method('getTwig')->willReturn($twig); - - $twig->expects($this->once())->method('addGlobal')->with($name, $value); - - $result = $controller->setViewVariable($name, $value); - - $this->assertSame($controller, $result); + return View\Twig::class; } - /** - * Provide data for testing 'setViewFunction' method when creating functions - * - * @return array - */ - public function setViewFunctionProvider() - { - return [ - ['test_name', function() {}], - ['str_rot13'], - ['obfuscate', 'str_rot13'] - ]; - } - - /** - * Test 'setViewFunction' method for adding functions - * @dataProvider setViewFunctionProvider + * Get mock controller * - * @param string $name - * @param callable $callable + * @param array $methods + * @param string $className + * @return RouteActionController|\PHPUnit_Framework_MockObject_MockObject */ - public function testSetViewFunctionFunction($name, $callable = null) + protected function getController($methods = [], $className = null) { - $twig = $this->createMock(\Twig_Environment::class); - - $controller = $this->getController(['getTwig']); - $controller->method('getTwig')->willReturn($twig); + $controller = $this->_getController(array_merge($methods, ['createTwigView', 'getViewPath']), $className); + $controller->method('getViewPath')->willReturn('/tmp'); - $fn = $callable ?: $name; - - $twig->expects($this->once())->method('addFunction') - ->with($this->callback(function($function) use ($name, $fn) { - $this->assertInstanceOf(\Twig_SimpleFunction::class, $function); - $this->assertEquals($name, $function->getName()); - $this->assertSame($fn, $function->getCallable()); - return true; - })); - - $twig->expects($this->never())->method('addFilter'); - - $controller->setViewFunction($name, $callable, 'function'); + return $controller; } - /** - * Test 'setViewFunction' method for adding filters - * @dataProvider setViewFunctionProvider - * - * @param string $name - * @param callable $callable - */ - public function testSetViewFunctionFilter($name, $callable = null) - { - $twig = $this->createMock(\Twig_Environment::class); - - $controller = $this->getController(['getTwig']); - $controller->method('getTwig')->willReturn($twig); - - $fn = $callable ?: $name; - - $twig->expects($this->once())->method('addFilter') - ->with($this->callback(function($function) use ($name, $fn) { - $this->assertInstanceOf(\Twig_SimpleFilter::class, $function); - $this->assertEquals($name, $function->getName()); - $this->assertSame($fn, $function->getCallable()); - return true; - })); - - $twig->expects($this->never())->method('addFunction'); - - $controller->setViewFunction($name, $callable, 'filter'); - } - - public function invalidAsProvider() + public function testGetViewer() { - return [ - ['foo', "'foo'"], - [10, 'a integer'], - [['filter'], 'a array'] - ]; - } - - /** - * @dataProvider invalidAsProvider - * - * @param mixed $as - * @param string $not - */ - public function testSetViewFunctionInvalid($as, $not) - { - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage("You should create either a 'function' or 'filter', not $not"); - - $twig = $this->createMock(\Twig_Environment::class); - - $controller = $this->getController(['getTwig']); - $controller->method('getTwig')->willReturn($twig); - - $controller->setViewFunction('abc', null, $as); - } - - - public function assertViewVariableNameProvider() - { - return [ - ['setViewVariable'], - ['setViewFunction', 'function'], - ['setViewFunction', 'filter'] - ]; - } - - /** - * @dataProvider assertViewVariableNameProvider - * - * @expectedException InvalidArgumentException - * @expectedExceptionMessage Expected name to be a string, not a stdClass object - */ - public function testAssertViewVariableNameNonString($fn, $as = null) - { - $twig = $this->createMock(\Twig_Environment::class); - - $controller = $this->getController(['getTwig']); - $controller->method('getTwig')->willReturn($twig); - - $controller->$fn(new \stdClass(), null, $as); - } - - /** - * @dataProvider assertViewVariableNameProvider - * - * @expectedException InvalidArgumentException - * @expectedExceptionMessage Invalid name 'hello world' - */ - public function testAssertViewVariableNameInvalid($fn, $as = null) - { - $twig = $this->createMock(\Twig_Environment::class); - - $controller = $this->getController(['getTwig']); - $controller->method('getTwig')->willReturn($twig); - - $controller->$fn('hello world', null, $as); - } - - - public function viewProvider() - { - return [ - ['foo', 'foo.html.twig'], - ['foo.html.twig', 'foo.html.twig'], - ['foo.html', 'foo.html'] - ]; - } - - /** - * @dataProvider viewProvider - * - * @param string $name - * @param string $filename - */ - public function testView($name, $filename) - { - $context = ['foo' => 1, 'bar' => 2, 'zoo' => ['monkey', 'lion']]; - - $template = $this->createMock(\Twig_TemplateInterface::class); - $template->expects($this->once())->method('render')->with($context)->willReturn('hello world'); + $viewer = $this->createMock(TwigView::class); + $viewer->expects($this->once())->method('addDefaultExtensions'); - $twig = $this->createMock(\Twig_Environment::class); - $twig->expects($this->once())->method('loadTemplate')->with($filename)->willReturn($template); - $twig->expects($this->once())->method('getCharset')->willReturn('test-charset'); + $controller = $this->getController(); + $controller->method('createTwigView')->willReturn($viewer); - $controller = $this->getController(['getTwig', 'output']); - $controller->expects($this->atLeastOnce())->method('getTwig')->willReturn($twig); - $controller->expects($this->once())->method('output')->with('hello world', 'text/html; charset=test-charset'); + $this->assertSame($viewer, $controller->getViewer()); - $controller->view($name, $context); + // Idempotent + $this->assertSame($viewer, $controller->getViewer()); } } diff --git a/tests/Controller/ViewTest.php b/tests/Controller/ViewTest.php new file mode 100644 index 0000000..0473a3f --- /dev/null +++ b/tests/Controller/ViewTest.php @@ -0,0 +1,83 @@ +<?php + +namespace Jasny\Controller\View; + +use Jasny\Controller\View; +use Jasny\ViewInterface; +use Jasny\Controller\TestHelper; +use Jasny\Controller\Session\Flash; +use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\UriInterface; + +/** + * @covers Jasny\Controller\View + */ +class ViewTest extends \PHPUnit_Framework_TestCase +{ + use TestHelper; + + /** + * @return string + */ + protected function getControllerClass() + { + return View::class; + } + + public function testGetViewer() + { + $viewer = $this->createMock(ViewInterface::class); + + $controller = $this->getController(); + $controller->setViewer($viewer); + + $this->assertSame($viewer, $controller->getViewer()); + } + + /** + * @expectedException LogicException + * @expectedExceptionMessage Viewer has not been set + */ + public function testGetViewerNotSet() + { + $this->getController()->getViewer(); + } + + + public function testGetViewPath() + { + $this->assertSame(getcwd(), $this->getController()->getViewPath()); + } + + + public function testView() + { + $uri = $this->createMock(UriInterface::class); + + $request = $this->createMock(ServerRequestInterface::class); + $request->expects($this->once())->method('getUri')->willReturn($uri); + + $response = $this->createMock(ResponseInterface::class); + $finalResponse = $this->createMock(ResponseInterface::class); + + $flash = $this->createMock(Flash::class); + + $name = 'foo'; + $context = ['color' => 'blue', 'animal' => 'monkey']; + + $viewer = $this->createMock(ViewInterface::class); + $viewer->expects($this->once())->method('render') + ->with($response, $name, $this->identicalTo($context + ['current_url' => $uri, 'flash' => $flash])) + ->willReturn($finalResponse); + + $controller = $this->getController(['flash']); + $controller->method('getRequest')->willReturn($request); + $controller->method('getResponse')->willReturn($response); + $controller->method('flash')->willReturn($flash); + $controller->expects($this->once())->method('setResponse')->with($finalResponse); + $controller->setViewer($viewer); + + $controller->view($name, $context); + } +} |