From 797e49035654c9cb3bcbaef89057136c26286daf Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Wed, 4 Sep 2024 15:20:36 +0200 Subject: [PATCH] Improve exception expectations reliability --- tests/Cache/FilesystemTest.php | 18 ++++---- tests/CustomExtensionTest.php | 5 ++- tests/EnvironmentTest.php | 11 ++--- tests/ExpressionParserTest.php | 66 ++++++++++++++-------------- tests/Extension/SandboxTest.php | 13 +++--- tests/LexerTest.php | 19 ++++---- tests/Loader/ArrayTest.php | 9 ++-- tests/Loader/ChainTest.php | 6 +-- tests/Node/Expression/CallTest.php | 28 ++++++++---- tests/Node/Expression/FilterTest.php | 14 +++--- tests/ParserTest.php | 17 +++---- tests/TemplateTest.php | 19 ++++---- tests/TokenStreamTest.php | 14 +++--- 13 files changed, 128 insertions(+), 111 deletions(-) diff --git a/tests/Cache/FilesystemTest.php b/tests/Cache/FilesystemTest.php index dbb085b3fb3..e880562fff9 100644 --- a/tests/Cache/FilesystemTest.php +++ b/tests/Cache/FilesystemTest.php @@ -81,9 +81,6 @@ public function testWrite() public function testWriteFailMkdir() { - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('Unable to create the cache directory'); - if (\defined('PHP_WINDOWS_VERSION_BUILD')) { $this->markTestSkipped('Read-only directories not possible on Windows.'); } @@ -97,14 +94,14 @@ public function testWriteFailMkdir() @mkdir($this->directory, 0555, true); $this->assertDirectoryExists($this->directory); + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Unable to create the cache directory'); + $this->cache->write($key, $content); } public function testWriteFailDirWritable() { - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('Unable to write in the cache directory'); - if (\defined('PHP_WINDOWS_VERSION_BUILD')) { $this->markTestSkipped('Read-only directories not possible on Windows.'); } @@ -120,14 +117,14 @@ public function testWriteFailDirWritable() @mkdir($this->directory.'/cache', 0555); $this->assertDirectoryExists($this->directory.'/cache'); + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Unable to write in the cache directory'); + $this->cache->write($key, $content); } public function testWriteFailWriteFile() { - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('Failed to write cache file'); - $key = $this->directory.'/cache/cachefile.php'; $content = $this->generateSource(); @@ -137,6 +134,9 @@ public function testWriteFailWriteFile() @mkdir($key, 0777, true); $this->assertDirectoryExists($key); + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Failed to write cache file'); + $this->cache->write($key, $content); } diff --git a/tests/CustomExtensionTest.php b/tests/CustomExtensionTest.php index fab7813b11c..40be3b38293 100644 --- a/tests/CustomExtensionTest.php +++ b/tests/CustomExtensionTest.php @@ -23,11 +23,12 @@ class CustomExtensionTest extends TestCase */ public function testGetInvalidOperators(ExtensionInterface $extension, $expectedExceptionMessage) { + $env = new Environment(new ArrayLoader()); + $env->addExtension($extension); + $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage($expectedExceptionMessage); - $env = new Environment(new ArrayLoader()); - $env->addExtension($extension); $env->getUnaryOperators(); } diff --git a/tests/EnvironmentTest.php b/tests/EnvironmentTest.php index a5f082ecb99..ff8dc741bc1 100644 --- a/tests/EnvironmentTest.php +++ b/tests/EnvironmentTest.php @@ -333,12 +333,12 @@ public function testAddMockExtension() public function testOverrideExtension() { + $twig = new Environment(new ArrayLoader()); + $twig->addExtension(new EnvironmentTest_Extension()); + $this->expectException(\LogicException::class); $this->expectExceptionMessage('Unable to register extension "Twig\Tests\EnvironmentTest_Extension" as it is already registered.'); - $twig = new Environment(new ArrayLoader()); - - $twig->addExtension(new EnvironmentTest_Extension()); $twig->addExtension(new EnvironmentTest_Extension()); } @@ -370,11 +370,12 @@ public function testAddRuntimeLoader() public function testFailLoadTemplate() { + $template = 'testFailLoadTemplate.twig'; + $twig = new Environment(new ArrayLoader([$template => false])); + $this->expectException(RuntimeError::class); $this->expectExceptionMessage('Failed to load Twig template "testFailLoadTemplate.twig", index "112233": cache might be corrupted in "testFailLoadTemplate.twig".'); - $template = 'testFailLoadTemplate.twig'; - $twig = new Environment(new ArrayLoader([$template => false])); $twig->loadTemplate($twig->getTemplateClass($template), $template, 112233); } diff --git a/tests/ExpressionParserTest.php b/tests/ExpressionParserTest.php index 94d67033e98..82ff47d44de 100644 --- a/tests/ExpressionParserTest.php +++ b/tests/ExpressionParserTest.php @@ -41,10 +41,10 @@ class ExpressionParserTest extends TestCase */ public function testCanOnlyAssignToNames($template) { - $this->expectException(SyntaxError::class); - $env = new Environment(new ArrayLoader(), ['cache' => false, 'autoescape' => false]); $parser = new Parser($env); + + $this->expectException(SyntaxError::class); $parser->parse($env->tokenize(new Source($template, 'index'))); } @@ -84,10 +84,10 @@ public function testSequenceExpression($template, $expected) */ public function testSequenceSyntaxError($template) { - $this->expectException(SyntaxError::class); - $env = new Environment(new ArrayLoader(), ['cache' => false, 'autoescape' => false]); $parser = new Parser($env); + + $this->expectException(SyntaxError::class); $parser->parse($env->tokenize(new Source($template, 'index'))); } @@ -210,12 +210,11 @@ public static function getTestsForSequence() public function testStringExpressionDoesNotConcatenateTwoConsecutiveStrings() { - $this->expectException(SyntaxError::class); - $env = new Environment(new ArrayLoader(), ['cache' => false, 'autoescape' => false, 'optimizations' => 0]); $stream = $env->tokenize(new Source('{{ "a" "b" }}', 'index')); $parser = new Parser($env); + $this->expectException(SyntaxError::class); $parser->parse($stream); } @@ -278,32 +277,30 @@ public static function getTestsForString() public function testAttributeCallDoesNotSupportNamedArguments() { - $this->expectException(SyntaxError::class); - $env = new Environment(new ArrayLoader(), ['cache' => false, 'autoescape' => false]); $parser = new Parser($env); + $this->expectException(SyntaxError::class); $parser->parse($env->tokenize(new Source('{{ foo.bar(name="Foo") }}', 'index'))); } public function testMacroCallDoesNotSupportNamedArguments() { - $this->expectException(SyntaxError::class); - $env = new Environment(new ArrayLoader(), ['cache' => false, 'autoescape' => false]); $parser = new Parser($env); + $this->expectException(SyntaxError::class); $parser->parse($env->tokenize(new Source('{% from _self import foo %}{% macro foo() %}{% endmacro %}{{ foo(name="Foo") }}', 'index'))); } public function testMacroDefinitionDoesNotSupportNonNameVariableName() { - $this->expectException(SyntaxError::class); - $this->expectExceptionMessage('An argument must be a name. Unexpected token "string" of value "a" ("name" expected) in "index" at line 1.'); - $env = new Environment(new ArrayLoader(), ['cache' => false, 'autoescape' => false]); $parser = new Parser($env); + $this->expectException(SyntaxError::class); + $this->expectExceptionMessage('An argument must be a name. Unexpected token "string" of value "a" ("name" expected) in "index" at line 1.'); + $parser->parse($env->tokenize(new Source('{% macro foo("a") %}{% endmacro %}', 'index'))); } @@ -312,12 +309,12 @@ public function testMacroDefinitionDoesNotSupportNonNameVariableName() */ public function testMacroDefinitionDoesNotSupportNonConstantDefaultValues($template) { - $this->expectException(SyntaxError::class); - $this->expectExceptionMessage('A default value for an argument must be a constant (a boolean, a string, a number, a sequence, or a mapping) in "index" at line 1'); - $env = new Environment(new ArrayLoader(), ['cache' => false, 'autoescape' => false]); $parser = new Parser($env); + $this->expectException(SyntaxError::class); + $this->expectExceptionMessage('A default value for an argument must be a constant (a boolean, a string, a number, a sequence, or a mapping) in "index" at line 1'); + $parser->parse($env->tokenize(new Source($template, 'index'))); } @@ -359,67 +356,68 @@ public static function getMacroDefinitionSupportsConstantDefaultValues() public function testUnknownFunction() { - $this->expectException(SyntaxError::class); - $this->expectExceptionMessage('Unknown "cycl" function. Did you mean "cycle" in "index" at line 1?'); - $env = new Environment(new ArrayLoader(), ['cache' => false, 'autoescape' => false]); $parser = new Parser($env); + $this->expectException(SyntaxError::class); + $this->expectExceptionMessage('Unknown "cycl" function. Did you mean "cycle" in "index" at line 1?'); + $parser->parse($env->tokenize(new Source('{{ cycl() }}', 'index'))); } public function testUnknownFunctionWithoutSuggestions() { - $this->expectException(SyntaxError::class); - $this->expectExceptionMessage('Unknown "foobar" function in "index" at line 1.'); - $env = new Environment(new ArrayLoader(), ['cache' => false, 'autoescape' => false]); $parser = new Parser($env); + $this->expectException(SyntaxError::class); + $this->expectExceptionMessage('Unknown "foobar" function in "index" at line 1.'); + $parser->parse($env->tokenize(new Source('{{ foobar() }}', 'index'))); } public function testUnknownFilter() { - $this->expectException(SyntaxError::class); - $this->expectExceptionMessage('Unknown "lowe" filter. Did you mean "lower" in "index" at line 1?'); - $env = new Environment(new ArrayLoader(), ['cache' => false, 'autoescape' => false]); $parser = new Parser($env); + $this->expectException(SyntaxError::class); + $this->expectExceptionMessage('Unknown "lowe" filter. Did you mean "lower" in "index" at line 1?'); + $parser->parse($env->tokenize(new Source('{{ 1|lowe }}', 'index'))); } public function testUnknownFilterWithoutSuggestions() { - $this->expectException(SyntaxError::class); - $this->expectExceptionMessage('Unknown "foobar" filter in "index" at line 1.'); - $env = new Environment(new ArrayLoader(), ['cache' => false, 'autoescape' => false]); $parser = new Parser($env); + $this->expectException(SyntaxError::class); + $this->expectExceptionMessage('Unknown "foobar" filter in "index" at line 1.'); + $parser->parse($env->tokenize(new Source('{{ 1|foobar }}', 'index'))); } public function testUnknownTest() { - $this->expectException(SyntaxError::class); - $this->expectExceptionMessage('Unknown "nul" test. Did you mean "null" in "index" at line 1'); - $env = new Environment(new ArrayLoader(), ['cache' => false, 'autoescape' => false]); $parser = new Parser($env); $stream = $env->tokenize(new Source('{{ 1 is nul }}', 'index')); + + $this->expectException(SyntaxError::class); + $this->expectExceptionMessage('Unknown "nul" test. Did you mean "null" in "index" at line 1'); + $parser->parse($stream); } public function testUnknownTestWithoutSuggestions() { - $this->expectException(SyntaxError::class); - $this->expectExceptionMessage('Unknown "foobar" test in "index" at line 1.'); - $env = new Environment(new ArrayLoader(), ['cache' => false, 'autoescape' => false]); $parser = new Parser($env); + $this->expectException(SyntaxError::class); + $this->expectExceptionMessage('Unknown "foobar" test in "index" at line 1.'); + $parser->parse($env->tokenize(new Source('{{ 1 is foobar }}', 'index'))); } diff --git a/tests/Extension/SandboxTest.php b/tests/Extension/SandboxTest.php index 810bbf74e58..70052b859c8 100644 --- a/tests/Extension/SandboxTest.php +++ b/tests/Extension/SandboxTest.php @@ -14,6 +14,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Twig\Environment; +use Twig\Error\RuntimeError; use Twig\Error\SyntaxError; use Twig\Extension\SandboxExtension; use Twig\Extension\StringLoaderExtension; @@ -72,10 +73,11 @@ protected function setUp(): void */ public function testSandboxForCoreTags(string $tag, string $template) { + $twig = $this->getEnvironment(true, [], self::$templates, []); + $this->expectException(SecurityError::class); $this->expectExceptionMessageMatches(sprintf('/Tag "%s" is not allowed in "index \(string template .+?\)" at line 1/', $tag)); - $twig = $this->getEnvironment(true, [], self::$templates, []); $twig->createTemplate($template, 'index')->render([]); } @@ -124,10 +126,11 @@ public static function getSandboxedForExtendsAndUseTagsTests() public function testSandboxWithInheritance() { + $twig = $this->getEnvironment(true, [], self::$templates, ['extends', 'block']); + $this->expectException(SecurityError::class); $this->expectExceptionMessage('Filter "json_encode" is not allowed in "1_child" at line 3.'); - $twig = $this->getEnvironment(true, [], self::$templates, ['extends', 'block']); $twig->load('1_child')->render([]); } @@ -441,14 +444,14 @@ public function testSandboxDisabledAfterIncludeFunctionError() public function testSandboxWithNoClosureFilter() { - $this->expectException('\Twig\Error\RuntimeError'); - $this->expectExceptionMessage('The callable passed to the "filter" filter must be a Closure in sandbox mode in "index" at line 1.'); - $twig = $this->getEnvironment(true, ['autoescape' => 'html'], ['index' => <<expectException(RuntimeError::class); + $this->expectExceptionMessage('The callable passed to the "filter" filter must be a Closure in sandbox mode in "index" at line 1.'); + $twig->load('index')->render([]); } diff --git a/tests/LexerTest.php b/tests/LexerTest.php index 4763731300c..d8da5545821 100644 --- a/tests/LexerTest.php +++ b/tests/LexerTest.php @@ -319,12 +319,12 @@ public function testStringWithHash() public function testStringWithUnterminatedInterpolation() { + $template = '{{ "bar #{x" }}'; + $lexer = new Lexer(new Environment(new ArrayLoader())); + $this->expectException(SyntaxError::class); $this->expectExceptionMessage('Unclosed """'); - $template = '{{ "bar #{x" }}'; - - $lexer = new Lexer(new Environment(new ArrayLoader())); $lexer->tokenize(new Source($template, 'index')); } @@ -388,9 +388,6 @@ public function testOperatorEndingWithALetterAtTheEndOfALine() public function testUnterminatedVariable() { - $this->expectException(SyntaxError::class); - $this->expectExceptionMessage('Unclosed "variable" in "index" at line 3'); - $template = ' {{ @@ -401,14 +398,14 @@ public function testUnterminatedVariable() '; $lexer = new Lexer(new Environment(new ArrayLoader())); + + $this->expectException(SyntaxError::class); + $this->expectExceptionMessage('Unclosed "variable" in "index" at line 3'); $lexer->tokenize(new Source($template, 'index')); } public function testUnterminatedBlock() { - $this->expectException(SyntaxError::class); - $this->expectExceptionMessage('Unclosed "block" in "index" at line 3'); - $template = ' {% @@ -419,6 +416,10 @@ public function testUnterminatedBlock() '; $lexer = new Lexer(new Environment(new ArrayLoader())); + + $this->expectException(SyntaxError::class); + $this->expectExceptionMessage('Unclosed "block" in "index" at line 3'); + $lexer->tokenize(new Source($template, 'index')); } diff --git a/tests/Loader/ArrayTest.php b/tests/Loader/ArrayTest.php index 543fe9ff6a9..478adf9317c 100644 --- a/tests/Loader/ArrayTest.php +++ b/tests/Loader/ArrayTest.php @@ -19,10 +19,9 @@ class ArrayTest extends TestCase { public function testGetSourceContextWhenTemplateDoesNotExist() { - $this->expectException(LoaderError::class); - $loader = new ArrayLoader(); + $this->expectException(LoaderError::class); $loader->getSourceContext('foo'); } @@ -57,10 +56,9 @@ public function testGetCacheKeyIsProtectedFromEdgeCollisions() public function testGetCacheKeyWhenTemplateDoesNotExist() { - $this->expectException(LoaderError::class); - $loader = new ArrayLoader(); + $this->expectException(LoaderError::class); $loader->getCacheKey('foo'); } @@ -80,10 +78,9 @@ public function testIsFresh() public function testIsFreshWhenTemplateDoesNotExist() { - $this->expectException(LoaderError::class); - $loader = new ArrayLoader(); + $this->expectException(LoaderError::class); $loader->isFresh('foo', time()); } } diff --git a/tests/Loader/ChainTest.php b/tests/Loader/ChainTest.php index 52d6d4c7202..16ccb9473c2 100644 --- a/tests/Loader/ChainTest.php +++ b/tests/Loader/ChainTest.php @@ -43,10 +43,9 @@ public function testGetSourceContext() public function testGetSourceContextWhenTemplateDoesNotExist() { - $this->expectException(LoaderError::class); - $loader = new ChainLoader([]); + $this->expectException(LoaderError::class); $loader->getSourceContext('foo'); } @@ -63,10 +62,9 @@ public function testGetCacheKey() public function testGetCacheKeyWhenTemplateDoesNotExist() { - $this->expectException(LoaderError::class); - $loader = new ChainLoader([]); + $this->expectException(LoaderError::class); $loader->getCacheKey('foo'); } diff --git a/tests/Node/Expression/CallTest.php b/tests/Node/Expression/CallTest.php index a1ea76fd445..75cac054734 100644 --- a/tests/Node/Expression/CallTest.php +++ b/tests/Node/Expression/CallTest.php @@ -30,37 +30,41 @@ public function testGetArguments() public function testGetArgumentsWhenPositionalArgumentsAfterNamedArguments() { + $node = $this->createFunctionExpression('date', 'date'); + $this->expectException(SyntaxError::class); $this->expectExceptionMessage('Positional arguments cannot be used after named arguments for function "date".'); - $node = $this->createFunctionExpression('date', 'date'); $this->getArguments($node, ['date', ['timestamp' => 123456, 'Y-m-d']]); } public function testGetArgumentsWhenArgumentIsDefinedTwice() { + $node = $this->createFunctionExpression('date', 'date'); + $this->expectException(SyntaxError::class); $this->expectExceptionMessage('Argument "format" is defined twice for function "date".'); - $node = $this->createFunctionExpression('date', 'date'); $this->getArguments($node, ['date', ['Y-m-d', 'format' => 'U']]); } public function testGetArgumentsWithWrongNamedArgumentName() { + $node = $this->createFunctionExpression('date', 'date'); + $this->expectException(SyntaxError::class); $this->expectExceptionMessage('Unknown argument "unknown" for function "date(format, timestamp)".'); - $node = $this->createFunctionExpression('date', 'date'); $this->getArguments($node, ['date', ['Y-m-d', 'timestamp' => null, 'unknown' => '']]); } public function testGetArgumentsWithWrongNamedArgumentNames() { + $node = $this->createFunctionExpression('date', 'date'); + $this->expectException(SyntaxError::class); $this->expectExceptionMessage('Unknown arguments "unknown1", "unknown2" for function "date(format, timestamp)".'); - $node = $this->createFunctionExpression('date', 'date'); $this->getArguments($node, ['date', ['Y-m-d', 'timestamp' => null, 'unknown1' => '', 'unknown2' => '']]); } @@ -70,10 +74,11 @@ public function testResolveArgumentsWithMissingValueForOptionalArgument() $this->markTestSkipped('substr_compare() has a default value in 8.0, so the test does not work anymore, one should find another PHP built-in function for this test to work in PHP 8.'); } + $node = $this->createFunctionExpression('substr_compare', 'substr_compare'); + $this->expectException(SyntaxError::class); $this->expectExceptionMessage('Argument "case_sensitivity" could not be assigned for function "substr_compare(main_str, str, offset, length, case_sensitivity)" because it is mapped to an internal PHP function which cannot determine default value for optional argument "length".'); - $node = $this->createFunctionExpression('substr_compare', 'substr_compare'); $this->getArguments($node, ['substr_compare', ['abcd', 'bc', 'offset' => 1, 'case_sensitivity' => true]]); } @@ -91,36 +96,41 @@ public function testGetArgumentsForStaticMethod() public function testResolveArgumentsWithMissingParameterForArbitraryArguments() { + $node = $this->createFunctionExpression('foo', [$this, 'customFunctionWithArbitraryArguments'], true); + $this->expectException(\LogicException::class); $this->expectExceptionMessage('The last parameter of "Twig\\Tests\\Node\\Expression\\CallTest::customFunctionWithArbitraryArguments" for function "foo" must be an array with default value, eg. "array $arg = []".'); - $node = $this->createFunctionExpression('foo', [$this, 'customFunctionWithArbitraryArguments'], true); $this->getArguments($node, [[$this, 'customFunctionWithArbitraryArguments'], []]); } public function testGetArgumentsWithInvalidCallable() { + $node = $this->createFunctionExpression('foo', '', true); + $this->expectException(\LogicException::class); $this->expectExceptionMessage('Callback for function "foo" is not callable in the current scope.'); - $node = $this->createFunctionExpression('foo', '', true); + $this->getArguments($node, ['', []]); } public function testResolveArgumentsWithMissingParameterForArbitraryArgumentsOnFunction() { + $node = $this->createFunctionExpression('foo', 'Twig\Tests\Node\Expression\custom_call_test_function', true); + $this->expectException(\LogicException::class); $this->expectExceptionMessageMatches('#^The last parameter of "Twig\\\\Tests\\\\Node\\\\Expression\\\\custom_call_test_function" for function "foo" must be an array with default value, eg\\. "array \\$arg \\= \\[\\]"\\.$#'); - $node = $this->createFunctionExpression('foo', 'Twig\Tests\Node\Expression\custom_call_test_function', true); $this->getArguments($node, ['Twig\Tests\Node\Expression\custom_call_test_function', []]); } public function testResolveArgumentsWithMissingParameterForArbitraryArgumentsOnObject() { + $node = $this->createFunctionExpression('foo', new CallableTestClass(), true); + $this->expectException(\LogicException::class); $this->expectExceptionMessageMatches('#^The last parameter of "Twig\\\\Tests\\\\Node\\\\Expression\\\\CallableTestClass\\:\\:__invoke" for function "foo" must be an array with default value, eg\\. "array \\$arg \\= \\[\\]"\\.$#'); - $node = $this->createFunctionExpression('foo', new CallableTestClass(), true); $this->getArguments($node, [new CallableTestClass(), []]); } diff --git a/tests/Node/Expression/FilterTest.php b/tests/Node/Expression/FilterTest.php index ca792bc4d86..1339b07dd46 100644 --- a/tests/Node/Expression/FilterTest.php +++ b/tests/Node/Expression/FilterTest.php @@ -128,29 +128,31 @@ public static function provideTests(): iterable public function testCompileWithWrongNamedArgumentName() { - $this->expectException(SyntaxError::class); - $this->expectExceptionMessage('Unknown argument "foobar" for filter "date(format, timezone)" at line 1.'); - $date = new ConstantExpression(0, 1); $node = $this->createFilter($this->getEnvironment(), $date, 'date', [ 'foobar' => new ConstantExpression('America/Chicago', 1), ]); $compiler = $this->getCompiler(); + + $this->expectException(SyntaxError::class); + $this->expectExceptionMessage('Unknown argument "foobar" for filter "date(format, timezone)" at line 1.'); + $compiler->compile($node); } public function testCompileWithMissingNamedArgument() { - $this->expectException(SyntaxError::class); - $this->expectExceptionMessage('Value for argument "from" is required for filter "replace" at line 1.'); - $value = new ConstantExpression(0, 1); $node = $this->createFilter($this->getEnvironment(), $value, 'replace', [ 'to' => new ConstantExpression('foo', 1), ]); $compiler = $this->getCompiler(); + + $this->expectException(SyntaxError::class); + $this->expectExceptionMessage('Value for argument "from" is required for filter "replace" at line 1.'); + $compiler->compile($node); } diff --git a/tests/ParserTest.php b/tests/ParserTest.php index 72709283704..4d61c2341d0 100644 --- a/tests/ParserTest.php +++ b/tests/ParserTest.php @@ -29,9 +29,6 @@ class ParserTest extends TestCase { public function testUnknownTag() { - $this->expectException(SyntaxError::class); - $this->expectExceptionMessage('Unknown "foo" tag. Did you mean "for" at line 1?'); - $stream = new TokenStream([ new Token(Token::BLOCK_START_TYPE, '', 1), new Token(Token::NAME_TYPE, 'foo', 1), @@ -39,14 +36,15 @@ public function testUnknownTag() new Token(Token::EOF_TYPE, '', 1), ]); $parser = new Parser(new Environment(new ArrayLoader())); + + $this->expectException(SyntaxError::class); + $this->expectExceptionMessage('Unknown "foo" tag. Did you mean "for" at line 1?'); + $parser->parse($stream); } public function testUnknownTagWithoutSuggestions() { - $this->expectException(SyntaxError::class); - $this->expectExceptionMessage('Unknown "foobar" tag at line 1.'); - $stream = new TokenStream([ new Token(Token::BLOCK_START_TYPE, '', 1), new Token(Token::NAME_TYPE, 'foobar', 1), @@ -54,6 +52,10 @@ public function testUnknownTagWithoutSuggestions() new Token(Token::EOF_TYPE, '', 1), ]); $parser = new Parser(new Environment(new ArrayLoader())); + + $this->expectException(SyntaxError::class); + $this->expectExceptionMessage('Unknown "foobar" tag at line 1.'); + $parser->parse($stream); } @@ -92,13 +94,12 @@ public static function getFilterBodyNodesData() */ public function testFilterBodyNodesThrowsException($input) { - $this->expectException(SyntaxError::class); - $parser = $this->getParser(); $m = new \ReflectionMethod($parser, 'filterBodyNodes'); $m->setAccessible(true); + $this->expectException(SyntaxError::class); $m->invoke($parser, $input); } diff --git a/tests/TemplateTest.php b/tests/TemplateTest.php index 1f2a8d28165..801701af2cc 100644 --- a/tests/TemplateTest.php +++ b/tests/TemplateTest.php @@ -27,10 +27,10 @@ class TemplateTest extends TestCase { public function testDisplayBlocksAcceptTemplateOnlyAsBlocks() { - $this->expectException(\LogicException::class); - $twig = new Environment(new ArrayLoader()); $template = new TemplateForTest($twig); + + $this->expectException(\LogicException::class); $template->displayBlock('foo', [], ['foo' => [new \stdClass(), 'foo']]); } @@ -143,31 +143,34 @@ public static function getRenderTemplateWithoutOutputData() public function testRenderBlockWithUndefinedBlock() { + $twig = new Environment(new ArrayLoader()); + $template = new TemplateForTest($twig, 'index.twig'); + $this->expectException(RuntimeError::class); $this->expectExceptionMessage('Block "unknown" on template "index.twig" does not exist in "index.twig".'); - $twig = new Environment(new ArrayLoader()); - $template = new TemplateForTest($twig, 'index.twig'); $template->renderBlock('unknown', []); } public function testDisplayBlockWithUndefinedBlock() { + $twig = new Environment(new ArrayLoader()); + $template = new TemplateForTest($twig, 'index.twig'); + $this->expectException(RuntimeError::class); $this->expectExceptionMessage('Block "unknown" on template "index.twig" does not exist in "index.twig".'); - $twig = new Environment(new ArrayLoader()); - $template = new TemplateForTest($twig, 'index.twig'); $template->displayBlock('unknown', []); } public function testDisplayBlockWithUndefinedParentBlock() { + $twig = new Environment(new ArrayLoader()); + $template = new TemplateForTest($twig, 'parent.twig'); + $this->expectException(RuntimeError::class); $this->expectExceptionMessage('Block "foo" should not call parent() in "index.twig" as the block does not exist in the parent template "parent.twig"'); - $twig = new Environment(new ArrayLoader()); - $template = new TemplateForTest($twig, 'parent.twig'); $template->displayBlock('foo', [], ['foo' => [new TemplateForTest($twig, 'index.twig'), 'block_foo']], false); } diff --git a/tests/TokenStreamTest.php b/tests/TokenStreamTest.php index e8cb474b38f..8f86ac87a7b 100644 --- a/tests/TokenStreamTest.php +++ b/tests/TokenStreamTest.php @@ -48,12 +48,13 @@ public function testNext() public function testEndOfTemplateNext() { - $this->expectException(SyntaxError::class); - $this->expectExceptionMessage('Unexpected end of template'); - $stream = new TokenStream([ new Token(Token::BLOCK_START_TYPE, 1, 1), ]); + + $this->expectException(SyntaxError::class); + $this->expectExceptionMessage('Unexpected end of template'); + while (!$stream->isEOF()) { $stream->next(); } @@ -61,12 +62,13 @@ public function testEndOfTemplateNext() public function testEndOfTemplateLook() { - $this->expectException(SyntaxError::class); - $this->expectExceptionMessage('Unexpected end of template'); - $stream = new TokenStream([ new Token(Token::BLOCK_START_TYPE, 1, 1), ]); + + $this->expectException(SyntaxError::class); + $this->expectExceptionMessage('Unexpected end of template'); + while (!$stream->isEOF()) { $stream->look(); $stream->next();