187 lines
6.3 KiB
PHP
187 lines
6.3 KiB
PHP
<?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);
|
|
}
|
|
}
|