Files
Twig/tests/Extension/AttributeExtensionTest.php

183 lines
8.2 KiB
PHP

<?php
/*
* This file is part of Twig.
*
* (c) Fabien Potencier
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Twig\Tests\Extension;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Twig\DeprecatedCallableInfo;
use Twig\Error\RuntimeError;
use Twig\Extension\AttributeExtension;
use Twig\ExtensionSet;
use Twig\Tests\Extension\Fixtures\ExtensionWithAttributes;
use Twig\Tests\Extension\Fixtures\FilterWithoutValue;
use Twig\Tests\Extension\Fixtures\TestWithoutValue;
use Twig\TwigFilter;
use Twig\TwigFunction;
use Twig\TwigTest;
class AttributeExtensionTest extends TestCase
{
/**
* @dataProvider provideFilters
*/
#[DataProvider('provideFilters')]
public function testFilter(string $name, string $method, array $options)
{
$extension = new AttributeExtension(ExtensionWithAttributes::class);
foreach ($extension->getFilters() as $filter) {
if ($filter->getName() === $name) {
$this->assertEquals(new TwigFilter($name, [ExtensionWithAttributes::class, $method], $options), $filter);
return;
}
}
$this->fail(\sprintf('Filter "%s" is not registered.', $name));
}
public static function provideFilters()
{
yield 'with name' => ['foo', 'fooFilter', ['is_safe' => ['html']]];
yield 'with env' => ['with_env_filter', 'withEnvFilter', ['needs_environment' => true]];
yield 'with context' => ['with_context_filter', 'withContextFilter', ['needs_context' => true]];
yield 'with env and context' => ['with_env_and_context_filter', 'withEnvAndContextFilter', ['needs_environment' => true, 'needs_context' => true]];
yield 'with sandbox' => ['with_sandbox_filter', 'withSandboxFilter', ['needs_is_sandboxed' => true]];
yield 'always allowed' => ['always_allowed_filter', 'alwaysAllowedFilter', ['always_allowed_in_sandbox' => true]];
yield 'variadic' => ['variadic_filter', 'variadicFilter', ['is_variadic' => true]];
yield 'deprecated' => ['deprecated_filter', 'deprecatedFilter', ['deprecation_info' => new DeprecatedCallableInfo('foo/bar', '1.2')]];
yield 'deprecated positional' => ['deprecated_positional_filter', 'deprecatedPositionalFilter', ['deprecation_info' => new DeprecatedCallableInfo('foo/bar', '1.2')]];
yield 'pattern' => ['pattern_*_filter', 'patternFilter', []];
}
/**
* @dataProvider provideFunctions
*/
#[DataProvider('provideFunctions')]
public function testFunction(string $name, string $method, array $options)
{
$extension = new AttributeExtension(ExtensionWithAttributes::class);
foreach ($extension->getFunctions() as $function) {
if ($function->getName() === $name) {
$this->assertEquals(new TwigFunction($name, [ExtensionWithAttributes::class, $method], $options), $function);
return;
}
}
$this->fail(\sprintf('Function "%s" is not registered.', $name));
}
public static function provideFunctions()
{
yield 'with name' => ['foo', 'fooFunction', ['is_safe' => ['html']]];
yield 'with env' => ['with_env_function', 'withEnvFunction', ['needs_environment' => true]];
yield 'with context' => ['with_context_function', 'withContextFunction', ['needs_context' => true]];
yield 'with env and context' => ['with_env_and_context_function', 'withEnvAndContextFunction', ['needs_environment' => true, 'needs_context' => true]];
yield 'with sandbox' => ['with_sandbox_function', 'withSandboxFunction', ['needs_is_sandboxed' => true]];
yield 'always allowed' => ['always_allowed_function', 'alwaysAllowedFunction', ['always_allowed_in_sandbox' => true]];
yield 'no argument' => ['no_arg_function', 'noArgFunction', []];
yield 'variadic' => ['variadic_function', 'variadicFunction', ['is_variadic' => true]];
yield 'deprecated' => ['deprecated_function', 'deprecatedFunction', ['deprecation_info' => new DeprecatedCallableInfo('foo/bar', '1.2')]];
yield 'deprecated positional' => ['deprecated_positional_function', 'deprecatedPositionalFunction', ['deprecation_info' => new DeprecatedCallableInfo('foo/bar', '1.2')]];
}
/**
* @dataProvider provideTests
*/
#[DataProvider('provideTests')]
public function testTest(string $name, string $method, array $options)
{
$extension = new AttributeExtension(ExtensionWithAttributes::class);
foreach ($extension->getTests() as $test) {
if ($test->getName() === $name) {
$this->assertEquals(new TwigTest($name, [ExtensionWithAttributes::class, $method], $options), $test);
return;
}
}
$this->fail(\sprintf('Test "%s" is not registered.', $name));
}
public static function provideTests()
{
yield 'with name' => ['foo', 'fooTest', []];
yield 'with env' => ['with_env_test', 'withEnvTest', ['needs_environment' => true]];
yield 'with context' => ['with_context_test', 'withContextTest', ['needs_context' => true]];
yield 'with env and context' => ['with_env_and_context_test', 'withEnvAndContextTest', ['needs_environment' => true, 'needs_context' => true]];
yield 'with sandbox' => ['with_sandbox_test', 'withSandboxTest', ['needs_is_sandboxed' => true]];
yield 'always allowed' => ['always_allowed_test', 'alwaysAllowedTest', ['always_allowed_in_sandbox' => true]];
yield 'variadic' => ['variadic_test', 'variadicTest', ['is_variadic' => true]];
yield 'deprecated' => ['deprecated_test', 'deprecatedTest', ['deprecation_info' => new DeprecatedCallableInfo('foo/bar', '1.2')]];
yield 'deprecated positional' => ['deprecated_positional_test', 'deprecatedPositionalTest', ['deprecation_info' => new DeprecatedCallableInfo('foo/bar', '1.2')]];
}
public function testFilterRequireOneArgument()
{
$extension = new AttributeExtension(FilterWithoutValue::class);
$this->expectException(\LogicException::class);
$this->expectExceptionMessage('"'.FilterWithoutValue::class.'::myFilter()" needs at least 1 arguments to be used AsTwigFilter, but only 0 defined.');
$extension->getTests();
}
public function testTestRequireOneArgument()
{
$extension = new AttributeExtension(TestWithoutValue::class);
$this->expectException(\LogicException::class);
$this->expectExceptionMessage('"'.TestWithoutValue::class.'::myTest()" needs at least 1 arguments to be used AsTwigTest, but only 0 defined.');
$extension->getTests();
}
public function testLastModifiedWithObject()
{
$extension = new AttributeExtension(\stdClass::class);
$this->assertSame(filemtime((new \ReflectionClass(AttributeExtension::class))->getFileName()), $extension->getLastModified());
}
public function testLastModifiedWithClass()
{
$extension = new AttributeExtension('__CLASS_FOR_TEST_LAST_MODIFIED__');
$filename = tempnam(sys_get_temp_dir(), 'twig');
try {
file_put_contents($filename, '<?php class __CLASS_FOR_TEST_LAST_MODIFIED__ {}');
require $filename;
$this->assertSame(filemtime($filename), $extension->getLastModified());
} finally {
unlink($filename);
}
}
public function testMultipleRegistrations()
{
$extensionSet = new ExtensionSet();
$extensionSet->addExtension($extension1 = new AttributeExtension(ExtensionWithAttributes::class));
$extensionSet->addExtension($extension2 = new AttributeExtension(\stdClass::class));
$this->assertCount(2, $extensionSet->getExtensions());
$this->assertNotNull($extensionSet->getFilter('foo'));
$this->assertSame($extension1, $extensionSet->getExtension(ExtensionWithAttributes::class));
$this->assertSame($extension2, $extensionSet->getExtension(\stdClass::class));
$this->expectException(RuntimeError::class);
$this->expectExceptionMessage('The "Twig\Extension\AttributeExtension" extension is not enabled.');
$extensionSet->getExtension(AttributeExtension::class);
}
}