summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnold Daniels <arnold@jasny.net>2016-11-21 09:24:55 +0100
committerArnold Daniels <arnold@jasny.net>2016-11-21 09:24:55 +0100
commitf5c6c856ba7e2a96ffefef278ebc8eb54b167bb9 (patch)
treec38e4a6ffcd5609d6a82b8080f2630ad9f196e51
parent0574cb923457b4ad4dddc451a3d244814ddc1858 (diff)
downloadcontroller-1.0.0.zip
controller-1.0.0.tar.gz
controller-1.0.0.tar.bz2
Tests and minor fixes for Twig viewv1.0.0origin/refactor
-rw-r--r--src/Controller/View/Twig.php61
-rw-r--r--tests/Controller/View/TwigTest.php439
-rw-r--r--tests/support/TestHelper.php2
3 files changed, 252 insertions, 250 deletions
diff --git a/src/Controller/View/Twig.php b/src/Controller/View/Twig.php
index 3645ec5..38e97d0 100644
--- a/src/Controller/View/Twig.php
+++ b/src/Controller/View/Twig.php
@@ -2,7 +2,6 @@
namespace Jasny\Controller\View;
-use Jasny\Controller\Session\Flash;
use Psr\Http\Message\ServerRequestInterface;
/**
@@ -16,7 +15,7 @@ trait Twig
*/
protected $twig;
-
+
/**
* Get server request
* @return ServerRequestInterface
@@ -31,36 +30,54 @@ trait Twig
*/
abstract public function output($data, $format = null);
-
+
/**
* Get path of the view files
- *
+ *
* @return string
*/
protected function getViewPath()
{
return getcwd();
}
+
+ /**
+ * Assert valid variable, function and filter name
+ *
+ * @param string $name
+ * @throws \InvalidArgumentException
+ */
+ protected function assertViewVariableName($name)
+ {
+ if (!is_string($name)) {
+ $type = (is_object($name) ? get_class($name) . ' ' : '') . gettype($name);
+ throw new \InvalidArgumentException("Expected name to be a string, not a $type");
+ }
+
+ if (!preg_match('/^[a-z]\w*$/i', $name)) {
+ throw new \InvalidArgumentException("Invalid name '$name'");
+ }
+ }
/**
* Add a global variable to the view.
- *
+ *
* @param string $name Variable name
* @param mixed $value
* @return $this
*/
public function setViewVariable($name, $value)
{
- if (!$name) throw new \InvalidArgumentException("Name should not be empty");
+ $this->assertViewVariableName($name);
$this->getTwig()->addGlobal($name, $value);
return $this;
}
-
+
/**
* Expose a function to the view.
- *
+ *
* @param string $name Function name
* @param string|null $function
* @param string $as 'function' or 'filter'
@@ -68,16 +85,19 @@ trait Twig
*/
public function setViewFunction($name, $function = null, $as = 'function')
{
+ $this->assertViewVariableName($name);
+
if ($as === 'function') {
$function = new \Twig_SimpleFunction($name, $function ?: $name);
$this->getTwig()->addFunction($function);
} elseif ($as === 'filter') {
- $filter = \Twig_SimpleFilter($name, $function ?: $name);
+ $filter = new \Twig_SimpleFilter($name, $function ?: $name);
$this->getTwig()->addFilter($filter);
} else {
- throw new \InvalidArgumentException("You should create either function or filter, not '$as'");
+ $not = is_string($as) ? "'$as'" : 'a ' . gettype($as);
+ throw new \InvalidArgumentException("You should create either a 'function' or 'filter', not $not");
}
-
+
return $this;
}
@@ -86,11 +106,11 @@ trait Twig
*
* @return \Twig_Environment
*/
- protected function createTwigEnvironment()
+ public function createTwigEnvironment()
{
$path = $this->getViewPath();
$loader = new \Twig_Loader_Filesystem($path);
-
+
return new \Twig_Environment($loader);
}
@@ -104,16 +124,17 @@ trait Twig
$extensions = ['DateExtension', 'PcreExtension', 'TextExtension', 'ArrayExtension'];
foreach ($extensions as $name) {
$class = "Jasny\Twig\\$name";
-
+
if (class_exists($class)) {
$this->twig->addExtension(new $class());
}
}
+
+ $this->twig->addGlobal('current_url', $this->getRequest()->getUri());
- $uri = $this->getRequest()->getUri();
-
- $this->setViewVariable('current_url', $uri);
- $this->setViewVariable('flash', new Flash());
+ if (method_exists($this, 'flash')) {
+ $this->twig->addGlobal('flash', $this->flash());
+ }
}
/**
@@ -126,10 +147,10 @@ trait Twig
if (!isset($this->twig)) {
$this->initTwig();
}
-
+
return $this->twig;
}
-
+
/**
* View rendered template
diff --git a/tests/Controller/View/TwigTest.php b/tests/Controller/View/TwigTest.php
index bf4adb8..e46757e 100644
--- a/tests/Controller/View/TwigTest.php
+++ b/tests/Controller/View/TwigTest.php
@@ -2,326 +2,307 @@
namespace Jasny\Controller\View;
-use Jasny\Controller\View\Twig;
+use Jasny\Controller\View;
use Jasny\Controller\Session\Flash;
use Psr\Http\Message\ServerRequestInterface;
-use Psr\Http\Message\ResponseInterface;
-use Psr\Http\Message\StreamInterface;
use Psr\Http\Message\UriInterface;
+use Jasny\Controller\TestHelper;
/**
* @covers Jasny\Controller\View\Twig
*/
class TwigTest extends \PHPUnit_Framework_TestCase
{
- public function setUp()
+ use TestHelper;
+
+ protected function getControllerClass()
{
- $this->markTestIncomplete();
+ return View\Twig::class;
}
/**
* Test creating twig environment
*/
- public function testGetTwig()
+ public function testCreateTwigEnvironment()
{
- $view = $this->getView(['getTwigLoader', 'getTwigEnvironment', 'createTwigFunction', 'createTwigFilter', 'setViewExtension', 'setViewVariable']);
- list($request, $response) = $this->getRequests();
- list($loader, $env) = $this->getTwigObjects();
-
- $view->expects($this->once())->method('getTwigLoader')->will($this->returnValue($loader));
- $view->expects($this->once())->method('getTwigEnvironment')->with($this->equalTo($loader))->will($this->returnValue($env));
- $view->expects($this->exactly(4))->method('setViewExtension')->with($this->callback(function($ext) {
- return in_array(get_class($ext), ['Jasny\Twig\DateExtension', 'Jasny\Twig\PcreExtension', 'Jasny\Twig\TextExtension', 'Jasny\Twig\ArrayExtension'], true);
- }))->will($this->returnSelf());
-
- $path = '/test/request/path';
- $uri = $this->createMock(UriInterface::class);
-
- $view->expects($this->once())->method('getRequest')->will($this->returnValue($request));
- $request->expects($this->once())->method('getUri')->will($this->returnValue($uri));
- $uri->expects($this->once())->method('getPath')->will($this->returnValue($path));
- $view->expects($this->exactly(2))->method('setViewVariable')->withConsecutive(
- [$this->equalTo('current_url'), $this->equalTo($path)],
- [$this->equalTo('flash'), $this->callback(function($flash) {
- return $flash instanceof Flash && empty($flash->get());
- })]
- );
-
- $result = $view->getTwig();
- $resultSaved = $view->getTwig();
-
- $this->assertEquals($env, $result, "Twig environment should be returned");
- $this->assertEquals($env, $resultSaved, "Saved twig environment should be returned");
- }
-
- /**
- * Test getting twig loader and environment
- */
- public function testGetTwigEnvironment()
- {
- $view = $this->getView();
- $loader = $view->getTwigLoader();
- $env = $view->getTwigEnvironment($loader);
-
- $this->assertInstanceOf(Twig_Environment::class, $env);
- $this->assertInstanceOf(Twig_Loader_Filesystem::class, $loader);
- $this->assertEquals([getcwd()], $loader->getPaths(), "Twig loader should be configured for current dir");
+ $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 'view' function
- *
- * @dataProvider viewProvider
- * @param string $tmplName Name of template to render
- * @param string $tmplNameFull Name of template with extension
- * @param array $context Variables to render
- * @param string $charset Twig sharset
- * @param string $html Rendered template
+ * Test intializing twig environment
*/
- public function testView($tmplName, $tmplNameFull, $context, $charset, $html)
+ public function testInitTwig()
{
- $view = $this->getView(['getTwig']);
- list($request, $response) = $this->getRequests();
- list($loader, $env, $tmpl) = $this->getTwigObjects();
-
- $stream = $this->createMock(StreamInterface::class);
-
- $view->expects($this->once())->method('getTwig')->will($this->returnValue($env));
- $view->expects($this->once())->method('getResponse')->will($this->returnValue($response));
- $env->expects($this->once())->method('loadTemplate')->with($this->equalTo($tmplNameFull))->will($this->returnValue($tmpl));
- $env->expects($this->once())->method('getCharset')->will($this->returnValue($charset));
- $response->expects($this->once())->method('withHeader')->with($this->equalTo('Content-Type'), $this->equalTo('text/html; charset=' . $charset ))->will($this->returnSelf());
- $response->expects($this->once())->method('getBody')->will($this->returnValue($stream));
- $tmpl->expects($this->once())->method('render')->with($this->equalTo($context))->will($this->returnValue($html));
- $stream->expects($this->once())->method('write')->with($this->equalTo($html));
-
- $result = $view->view($tmplName, $context);
-
- $this->assertEquals($response, $result, "Response should be returned");
+ $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();
}
/**
- * Provide data for testing view method
- *
- * @return array
+ * Test Jasny Twig extensions when intializing twig environment
*/
- public function viewProvider()
+ public function testInitTwigWithJasnyExtensions()
{
- return [
- ['test-template', 'test-template.html.twig', ['test' => 'value'], 'test-charset', 'rendered template'],
- ['test-template.html.twig', 'test-template.html.twig', ['test' => 'value'], 'test-charset', 'rendered template'],
- ];
+ $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();
}
/**
- * Test creating twig function
- *
- * @dataProvider createTwigFunctionFilterProvider
- * @param string $class Twig function or filter class
- * @param string $createMethod
- * @param string $name Created function or filter name
- * @param callable $function
+ * Test session flash when intializing twig environment
*/
- public function testCreateTwigFunctionFilter($class, $createMethod, $name, $function)
+ public function testInitTwigWithSessionFlash()
{
- if (!$name) $this->expectException(InvalidArgumentException::class);
-
- $view = $this->getView();
- $result = $view->createTwigFunction($name, $function);
- $callback = $result->getCallable();
-
- $this->assertInstanceOf(Twig_SimpleFunction::class, $result, "Result must be an instance of 'Twig_SimpleFunction'");
- $this->assertEquals($name, $result->getName(), "Function name is not set correctly");
-
- if (!$function) {
- $this->assertEquals($name, $callback);
- } else {
- $this->assertEquals(call_user_func($function), call_user_func($callback), "Function body was not set correctly");
- }
+ $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 creating functions and filter for twig
+ * Provide data for testing 'setViewVariable' method
*
* @return array
*/
- public function createTwigFunctionFilterProvider()
+ public function setViewVariableProvider()
{
return [
- [Twig_SimpleFunction::class, 'createTwigFunction', 'test_name', function() {return 'success_call';}],
- [Twig_SimpleFunction::class, 'createTwigFunction', 'test_name', null],
- [Twig_SimpleFilter::class, 'createTwigFilter', 'test_name', function() {return 'success_call';}],
- [Twig_SimpleFilter::class, 'createTwigFilter', 'test_name', null],
- [Twig_SimpleFunction::class, 'createTwigFunction', '', function() {return 'success_call';}],
- [Twig_SimpleFilter::class, 'createTwigFilter', '', function() {return 'success_call';}],
- ];
+ ['foo', null],
+ ['foo', 'bar'],
+ ['foo', ['bar', 'zoo']],
+ ['foo', (object)['a' => 'bar', 'b' => 'zoo']],
+ ];
}
-
+
/**
- * Test 'setViewFunction' method
+ * Test 'setViewVariable' method
*
- * @dataProvider setViewFunctionFunctionProvider
- * @param string $name
- * @param callable $callable
- * @param string $type
- * @param boolean $positive
+ * @dataProvider setViewVariableProvider
*/
- public function testSetViewFunctionFunction($name, $callable, $type, $positive)
+ public function testSetViewVariable($name, $value)
{
- $view = $this->getView(['getTwig', 'createTwigFunction', 'createTwigFilter']);
- $twig = $this->createMock(Twig_Environment::class);
- $function = $this->createMock(Twig_SimpleFunction::class);
-
- if ($positive) {
- $view->expects($this->once())->method('getTwig')->will($this->returnValue($twig));
- $view->expects($this->once())->method('createTwigFunction')->with($this->equalTo($name), $this->equalTo($callable))->will($this->returnValue($function));
- $view->expects($this->never())->method('createTwigFilter');
- $twig->expects($this->once())->method('addFunction')->with($this->equalTo($function));
- } else {
- $this->expectException(InvalidArgumentException::class);
- }
+ $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 = $view->setViewFunction($name, $callable, $type);
+ $result = $controller->setViewVariable($name, $value);
- $this->assertEquals($view, $result, "Method should return \$this");
+ $this->assertSame($controller, $result);
}
+
/**
* Provide data for testing 'setViewFunction' method when creating functions
*
* @return array
*/
- public function setViewFunctionFunctionProvider()
+ public function setViewFunctionProvider()
{
return [
- ['test_name', function() {}, 'function', true],
- ['test_name', function() {}, 'not_function_or_filter', false]
+ ['test_name', function() {}],
+ ['str_rot13'],
+ ['obfuscate', 'str_rot13']
];
}
/**
- * Test 'setViewFunction' method
- *
- * @dataProvider setViewFunctionFilterProvider
+ * Test 'setViewFunction' method for adding functions
+ * @dataProvider setViewFunctionProvider
+ *
* @param string $name
* @param callable $callable
*/
- public function testSetViewFunctionFilter($name, $callable)
+ public function testSetViewFunctionFunction($name, $callable = null)
{
- $view = $this->getView(['getTwig', 'createTwigFunction', 'createTwigFilter']);
- $twig = $this->createMock(Twig_Environment::class);
- $function = $this->createMock(Twig_SimpleFilter::class);
-
- $view->expects($this->once())->method('getTwig')->will($this->returnValue($twig));
- $view->expects($this->once())->method('createTwigFilter')->with($this->equalTo($name), $this->equalTo($callable))->will($this->returnValue($function));
- $view->expects($this->never())->method('createTwigFunction');
- $twig->expects($this->once())->method('addFilter')->with($this->equalTo($function));
-
- $result = $view->setViewFunction($name, $callable, 'filter');
-
- $this->assertEquals($view, $result, "Method should return \$this");
+ $twig = $this->createMock(\Twig_Environment::class);
+
+ $controller = $this->getController(['getTwig']);
+ $controller->method('getTwig')->willReturn($twig);
+
+ $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');
}
/**
- * Provide data for testing 'setViewFunction' method when creating filter
- *
- * @return array
+ * Test 'setViewFunction' method for adding filters
+ * @dataProvider setViewFunctionProvider
+ *
+ * @param string $name
+ * @param callable $callable
*/
- public function setViewFunctionFilterProvider()
+ 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()
{
return [
- ['test_name', function() {}]
+ ['foo', "'foo'"],
+ [10, 'a integer'],
+ [['filter'], 'a array']
];
}
-
+
/**
- * Test 'setViewVariable' method
- *
- * @dataProvider setViewVariableProvider
+ * @dataProvider invalidAsProvider
+ *
+ * @param mixed $as
+ * @param string $not
*/
- public function testSetViewVariable($name, $value)
+ public function testSetViewFunctionInvalid($as, $not)
{
- $view = $this->getView(['getTwig']);
- $twig = $this->createMock(Twig_Environment::class);
-
- if (!$name) {
- $this->expectException(InvalidArgumentException::class);
- } else {
- $view->expects($this->once())->method('getTwig')->will($this->returnValue($twig));
- $twig->expects($this->once())->method('addGlobal')->with($this->equalTo($name), $this->equalTo($value));
- }
-
- $result = $view->setViewVariable($name, $value);
-
- $this->assertEquals($view, $result, "Method should return \$this");
+ $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);
}
-
- /**
- * Provide data for testing 'setViewVariable' method
- *
- * @return array
- */
- public function setViewVariableProvider()
+
+
+ public function assertViewVariableNameProvider()
{
return [
- ['test_name', 'test_value'],
- ['test_name', ''],
- ['', 'test_value'],
- ];
+ ['setViewVariable'],
+ ['setViewFunction', 'function'],
+ ['setViewFunction', 'filter']
+ ];
}
-
+
/**
- * Test edding extension to twig
+ * @dataProvider assertViewVariableNameProvider
+ *
+ * @expectedException InvalidArgumentException
+ * @expectedExceptionMessage Expected name to be a string, not a stdClass object
*/
- public function testSetViewExtension()
+ public function testAssertViewVariableNameNonString($fn, $as = null)
{
- $view = $this->getView(['getTwig']);
- $twig = $this->createMock(Twig_Environment::class);
- $ext = $this->createMock(Twig_ExtensionInterface::class);
-
- $view->expects($this->once())->method('getTwig')->will($this->returnValue($twig));
- $twig->expects($this->once())->method('addExtension')->with($this->equalTo($ext));
-
- $result = $view->setViewExtension($ext);
-
- $this->assertEquals($view, $result, "Method should return \$this");
+ $twig = $this->createMock(\Twig_Environment::class);
+
+ $controller = $this->getController(['getTwig']);
+ $controller->method('getTwig')->willReturn($twig);
+
+ $controller->$fn(new \stdClass(), null, $as);
}
-
+
/**
- * Get mock for testing trait
- *
- * @param array $methods Methods to mock
- * @return Twig
+ * @dataProvider assertViewVariableNameProvider
+ *
+ * @expectedException InvalidArgumentException
+ * @expectedExceptionMessage Invalid name 'hello world'
*/
- public function getView($methods = [])
+ public function testAssertViewVariableNameInvalid($fn, $as = null)
{
- return $this->getMockForTrait(Twig::class, [], '', true, true, true, $methods);
+ $twig = $this->createMock(\Twig_Environment::class);
+
+ $controller = $this->getController(['getTwig']);
+ $controller->method('getTwig')->willReturn($twig);
+
+ $controller->$fn('hello world', null, $as);
}
-
- /**
- * Get mocks representing twig objects
- *
- * @return array
- */
- public function getTwigObjects()
+
+
+ public function viewProvider()
{
return [
- $this->createMock(Twig_Loader_Filesystem::class),
- $this->createMock(Twig_Environment::class),
- $this->createMock(Twig_Template::class)
+ ['foo', 'foo.html.twig'],
+ ['foo.html.twig', 'foo.html.twig'],
+ ['foo.html', 'foo.html']
];
}
-
+
/**
- * Get request and response instances
- *
- * @return array
+ * @dataProvider viewProvider
+ *
+ * @param string $name
+ * @param string $filename
*/
- public function getRequests()
+ public function testView($name, $filename)
{
- return [
- $this->createMock(ServerRequestInterface::class),
- $this->createMock(ResponseInterface::class)
- ];
+ $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');
+
+ $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(['getTwig', 'output']);
+ $controller->expects($this->atLeastOnce())->method('getTwig')->willReturn($twig);
+ $controller->expects($this->once())->method('output')->with('hello world', 'text/html; charset=test-charset');
+
+ $controller->view($name, $context);
}
}
diff --git a/tests/support/TestHelper.php b/tests/support/TestHelper.php
index 3a87863..a046e4e 100644
--- a/tests/support/TestHelper.php
+++ b/tests/support/TestHelper.php
@@ -32,7 +32,7 @@ trait TestHelper
* Get mock for controller
*
* @param array $methods Methods to mock
- * @return Controller|\PHPUnit_Framework_MockObject_MockObject
+ * @return Controller|Controller\Session|Controller\View\Twig|\PHPUnit_Framework_MockObject_MockObject
*/
public function getController($methods = [], $mockClassName = null)
{