Scape/tests/ParserTest.php

187 lines
6.3 KiB
PHP
Raw Permalink Normal View History

<?php
declare(strict_types=1);
namespace Scape\Tests;
use PHPUnit\Framework\TestCase;
use Scape\Parser\Lexer;
use Scape\Parser\Parser;
use Scape\Parser\Node\TextNode;
use Scape\Parser\Node\VariableNode;
use Scape\Parser\Node\ForeachNode;
use Scape\Parser\Node\BlockNode;
use Scape\Parser\Node\ExtendsNode;
use Scape\Parser\Node\IncludeNode;
use Scape\Parser\Node\FilterLoadNode;
use Scape\Parser\Node\ParentNode;
class ParserTest extends TestCase
{
public function testParsesSimpleText(): void
{
$lexer = new Lexer("Hello World");
$parser = new Parser($lexer->tokenize());
$nodes = $parser->parse();
$this->assertCount(1, $nodes);
$this->assertInstanceOf(TextNode::class, $nodes[0]);
$this->assertEquals("Hello World", $nodes[0]->content);
}
public function testParsesInterpolation(): void
{
$lexer = new Lexer("{{ var }}");
$parser = new Parser($lexer->tokenize());
$nodes = $parser->parse();
$this->assertCount(1, $nodes);
$this->assertInstanceOf(VariableNode::class, $nodes[0]);
$this->assertEquals("var", $nodes[0]->path);
$this->assertFalse($nodes[0]->isRaw);
}
public function testParsesInterpolationWithFilters(): void
{
$template = "{{ price | currency('USD') | lower }}";
$lexer = new Lexer($template);
$parser = new Parser($lexer->tokenize());
$nodes = $parser->parse();
$this->assertInstanceOf(VariableNode::class, $nodes[0]);
$this->assertEquals("price", $nodes[0]->path);
$this->assertCount(2, $nodes[0]->filters);
$this->assertEquals("currency", $nodes[0]->filters[0]['name']);
$this->assertEquals(["'USD'"], $nodes[0]->filters[0]['args']);
$this->assertEquals("lower", $nodes[0]->filters[1]['name']);
}
public function testParsesForeach(): void
{
$template = "{( foreach item in items )} {{ item }} {( endforeach )}";
$lexer = new Lexer($template);
$parser = new Parser($lexer->tokenize());
$nodes = $parser->parse();
$this->assertCount(1, $nodes);
$this->assertInstanceOf(ForeachNode::class, $nodes[0]);
$this->assertEquals("items", $nodes[0]->collection);
$this->assertEquals("item", $nodes[0]->valueVar);
$this->assertNull($nodes[0]->keyVar);
$this->assertCount(3, $nodes[0]->body); // Space, Variable, Space
}
public function testParsesForeachWithKey(): void
{
$template = "{( foreach k, v in items )}{( endforeach )}";
$lexer = new Lexer($template);
$parser = new Parser($lexer->tokenize());
$nodes = $parser->parse();
$this->assertInstanceOf(ForeachNode::class, $nodes[0]);
$this->assertEquals("k", $nodes[0]->keyVar);
$this->assertEquals("v", $nodes[0]->valueVar);
}
public function testParsesForeachWithPositionalTags(): void
{
$template = "{( foreach item in items )}{( first )}FIRST{( endfirst )}{( inner )}INNER{( endinner )}{( last )}LAST{( endlast )}{( endforeach )}";
$lexer = new Lexer($template);
$parser = new Parser($lexer->tokenize());
$nodes = $parser->parse();
$node = $nodes[0];
$this->assertInstanceOf(ForeachNode::class, $node);
$this->assertCount(1, $node->first);
$this->assertInstanceOf(TextNode::class, $node->first[0]);
$this->assertEquals("FIRST", $node->first[0]->content);
$this->assertCount(1, $node->inner);
$this->assertEquals("INNER", $node->inner[0]->content);
$this->assertCount(1, $node->last);
$this->assertEquals("LAST", $node->last[0]->content);
}
public function testParsesExtends(): void
{
$template = "{[ extends 'layout.main' ]}";
$lexer = new Lexer($template);
$parser = new Parser($lexer->tokenize());
$nodes = $parser->parse();
$this->assertInstanceOf(ExtendsNode::class, $nodes[0]);
$this->assertEquals("layout.main", $nodes[0]->path);
}
public function testParsesBlock(): void
{
$template = "{[ block 'content' ]}Block Content{[ endblock ]}";
$lexer = new Lexer($template);
$parser = new Parser($lexer->tokenize());
$nodes = $parser->parse();
$this->assertInstanceOf(BlockNode::class, $nodes[0]);
$this->assertEquals("content", $nodes[0]->name);
$this->assertCount(1, $nodes[0]->body);
$this->assertEquals("Block Content", $nodes[0]->body[0]->content);
}
public function testParsesInclude(): void
{
$template = "{[ include 'partials.nav' ]}";
$lexer = new Lexer($template);
$parser = new Parser($lexer->tokenize());
$nodes = $parser->parse();
$this->assertInstanceOf(IncludeNode::class, $nodes[0]);
$this->assertEquals("partials.nav", $nodes[0]->path);
$this->assertNull($nodes[0]->context);
}
public function testParsesIncludeWithContext(): void
{
$template = "{[ include 'partials.user' with user_data ]}";
$lexer = new Lexer($template);
$parser = new Parser($lexer->tokenize());
$nodes = $parser->parse();
$this->assertInstanceOf(IncludeNode::class, $nodes[0]);
$this->assertEquals("user_data", $nodes[0]->context);
}
public function testParsesParent(): void
{
$template = "{[ parent ]}";
$lexer = new Lexer($template);
$parser = new Parser($lexer->tokenize());
$nodes = $parser->parse();
$this->assertInstanceOf(ParentNode::class, $nodes[0]);
}
public function testParsesUses(): void
{
$template = "{( uses filters:string )}";
$lexer = new Lexer($template);
$parser = new Parser($lexer->tokenize());
$nodes = $parser->parse();
$this->assertInstanceOf(FilterLoadNode::class, $nodes[0]);
$this->assertTrue($nodes[0]->isInternal);
$this->assertEquals("filters:string", $nodes[0]->path);
}
public function testParsesLoadFilter(): void
{
$template = "{( load_filter('custom.my_filter') )}";
$lexer = new Lexer($template);
$parser = new Parser($lexer->tokenize());
$nodes = $parser->parse();
$this->assertInstanceOf(FilterLoadNode::class, $nodes[0]);
$this->assertFalse($nodes[0]->isInternal);
$this->assertEquals("custom.my_filter", $nodes[0]->path);
}
}