Fix: reparse close tag, custom provider, simplify compile method, add providers and tests

This commit is contained in:
bzick
2013-05-30 19:00:00 +04:00
parent 707a13cd08
commit 32ccaa91f0
13 changed files with 482 additions and 347 deletions

View File

@@ -24,6 +24,11 @@ class TestCase extends \PHPUnit_Framework_TestCase {
FS::clean(CYTRO_RESOURCES.'/compile/');
}
$this->cytro = Cytro::factory(CYTRO_RESOURCES.'/template', CYTRO_RESOURCES.'/compile');
$this->cytro->addModifier('dots', __CLASS__.'::dots');
}
public static function dots($value) {
return $value."...";
}
public static function setUpBeforeClass() {
@@ -85,10 +90,105 @@ class TestCase extends \PHPUnit_Framework_TestCase {
$this->fail("Code $code must be invalid");
}
public function assertRender($tpl, $result) {
public function assertRender($tpl, $result, $debug = false) {
$template = $this->cytro->compileCode($tpl);
if($debug) {
print_r("$tpl:\n".$template->getBody());
}
$this->assertSame($result, $template->fetch($this->values));
}
public static function providerNumbers() {
return array(
array('77', 77),
array('-33', -33),
array('0.2', 0.2),
array('-0.3', -0.3),
array('1e6', 1e6),
array('-2e6', -2e6),
);
}
public static function providerStrings() {
return array(
array('"str"', 'str'),
array('"str\nand\nmany\nlines"', "str\nand\nmany\nlines"),
array('"str and \'substr\'"', "str and 'substr'"),
array('"str and \"substr\""', 'str and "substr"'),
array("'str'", 'str'),
array("'str\\nin\\none\\nline'", 'str\nin\none\nline'),
array("'str and \"substr\"'", 'str and "substr"'),
array("'str and \'substr\''", "str and 'substr'"),
array('"$one"', '1'),
array('"$one $two"', '1 2'),
array('"$one and $two"', '1 and 2'),
array('"a $one and $two b"', 'a 1 and 2 b'),
array('"{$one}"', '1'),
array('"a {$one} b"', 'a 1 b'),
array('"{$one + 2}"', '3'),
array('"{$one * $two + 1}"', '3'),
array('"{$one} and {$two}"', '1 and 2'),
array('"$one and {$two}"', '1 and 2'),
array('"{$one} and $two"', '1 and 2'),
array('"a {$one} and {$two} b"', 'a 1 and 2 b'),
array('"{$one+1} and {$two-1}"', '2 and 1'),
array('"a {$one+1} and {$two-1} b"', 'a 2 and 1 b'),
array('"a {$one|dots} and {$two|dots} b"', 'a 1... and 2... b'),
array('"a {$one|dots} and $two b"', 'a 1... and 2 b'),
array('"a $one and {$two|dots} b"', 'a 1 and 2... b'),
);
}
public function providerVariables() {
return array();
}
public static function providerObjects() {
return array();
}
public static function providerArrays() {
$scalars = array();
$data = array(
array('[]', array()),
array('[[],[]]', array(array(), array())),
);
foreach(self::providerScalars() as $scalar) {
$scalars[0][] = $scalar[0];
$scalars[1][] = $scalar[1];
$data[] = array(
"[".$scalar[0]."]",
array($scalar[1])
);
$data[] = array(
"['some_key' =>".$scalar[0]."]",
array('some_key' => $scalar[1])
);
}
$data[] = array(
"[".implode(", ", $scalars[0])."]",
$scalars[1]
);
return $data;
}
public static function providerScalars() {
return array_merge(
self::providerNumbers(),
self::providerStrings()
);
}
public static function providerValues() {
return array_merge(
self::providerScalars(),
self::providerArrays(),
self::providerVariables(),
self::providerObjects()
);
}
}
class Fake implements \ArrayAccess {
@@ -113,4 +213,8 @@ class Fake implements \ArrayAccess {
public function offsetUnset($offset) {
unset($this->vars[$offset]);
}
public function proxy() {
return implode(", ", func_get_args());
}
}

View File

@@ -1,17 +0,0 @@
<?php
namespace Cytro;
class CustomProvider extends TestCase {
public function setUp() {
$this->setUp();
$this->cytro->addProvider("my", new FSProvider(CYTRO_RESOURCES.'/provider'));
}
public function testCustom() {
$this->render("start: {include 'my:include.tpl'}", 'start: include template');
$this->render("start: {import 'my:macros.tpl' as ops} {ops.add a=3 b=6}");
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace Cytro;
class CustomProviderTest extends TestCase {
public function setUp() {
parent::setUp();
$this->cytro->addProvider("my", new FSProvider(CYTRO_RESOURCES.'/provider'));
}
public function testCustom() {
$this->assertRender("start: {include 'my:include.tpl'}", 'start: include template');
//$this->assertRender("start: {import 'my:macros.tpl' as ops} {ops.add a=3 b=6}");
}
}

View File

@@ -5,8 +5,8 @@ namespace Cytro;
class ModifiersTest extends TestCase {
public static function providerTruncate() {
$lorem = 'Lorem ipsum dolor sit amet';
$uni = 'Лорем ипсум долор сит амет';
$lorem = 'Lorem ipsum dolor sit amet'; // en
$uni = 'Лорем ипсум долор сит амет'; // ru
return array(
// ascii chars
array($lorem, 'Lorem ip...', 8),
@@ -23,13 +23,15 @@ class ModifiersTest extends TestCase {
);
}
/**
* @dataProvider providerTruncate
* @param $in
* @param $out
* @param $count
* @param string $delim
* @param bool $by_word
* @param bool $by_words
* @param bool $middle
*/
public function testTruncate($in, $out, $count, $delim = '...', $by_words = false, $middle = false) {
$tpl = $this->cytro->compileCode('{$text|truncate:$count:$delim:$by_words:$middle}');
@@ -41,4 +43,58 @@ class ModifiersTest extends TestCase {
"middle" => $middle
)));
}
public static function providerUpLow() {
return array(
array("up", "lorem", "LOREM"),
array("up", "Lorem", "LOREM"),
array("up", "loREM", "LOREM"),
array("up", "223a", "223A"),
array("low", "lorem", "lorem"),
array("low", "Lorem", "lorem"),
array("low", "loREM", "lorem"),
array("low", "223A", "223a"),
);
}
/**
* @dataProvider providerUpLow
* @param $modifier
* @param $in
* @param $out
*/
public function testUpLow($modifier, $in, $out) {
$tpl = $this->cytro->compileCode('{$text|'.$modifier.'}');
$this->assertEquals($out, $tpl->fetch(array(
"text" => $in,
)));
}
public static function providerLength() {
return array(
array("length", 6),
array("длина", 5),
array("length - длина", 14),
array(array(1, 33, "c" => 4), 3),
array(new \ArrayIterator(array(1, "c" => 4)), 2),
array(true, 0),
array(new \stdClass(), 0),
array(5, 0)
);
}
/**
* @dataProvider providerLength
* @param $in
* @param $in
* @param $out
*/
public function testLength($in, $out) {
$tpl = $this->cytro->compileCode('{$data|length}');
$this->assertEquals($out, $tpl->fetch(array(
"data" => $in,
)));
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace Cytro;
class TagsTest extends TestCase {
// public function _testSandbox() {
// try {
// var_dump($this->cytro->compileCode(" literal: { \$a} end")->getBody());
// } catch(\Exception $e) {
// echo "$e";
// }
// exit;
// }
/**
* @dataProvider providerScalars
*/
public function testVar($tpl_val, $val) {
$this->assertRender("{var \$a=$tpl_val}\nVar: {\$a}", "\nVar: ".$val);
}
/**
* @dataProvider providerScalars
*/
public function testVarBlock($tpl_val, $val) {
$this->assertRender("{var \$a}before {{$tpl_val}} after{/var}\nVar: {\$a}", "\nVar: before ".$val." after");
}
/**
* @dataProvider providerScalars
*/
public function testVarBlockModified($tpl_val, $val) {
$this->assertRender("{var \$a|low|dots}before {{$tpl_val}} after{/var}\nVar: {\$a}", "\nVar: ".strtolower("before ".$val." after")."...");
}
public function testCycle() {
}
public function testFilter() {
}
}

View File

@@ -4,6 +4,11 @@ use Cytro\Template,
Cytro,
Cytro\Render;
/**
* Test template parsing
*
* @package Cytro
*/
class TemplateTest extends TestCase {
public function setUp() {
@@ -15,11 +20,6 @@ class TemplateTest extends TestCase {
)));
}
/*public function testSandbox() {
var_dump($this->cytro->compileCode('{"$s:{$b+1}f d {$d}"}')->_body);
exit;
}*/
public static function providerVars() {
$a = array("a" => "World");
$obj = new \stdClass;
@@ -73,41 +73,6 @@ class TemplateTest extends TestCase {
);
}
public static function providerScalars() {
return array(
array('77', 77),
array('-33', -33),
array('0.2', 0.2),
array('-0.3', -0.3),
array('1e6', 1e6),
array('-2e6', -2e6),
array('"str"', 'str'),
array('"str\nand\nmany\nlines"', "str\nand\nmany\nlines"),
array('"str and \'substr\'"', "str and 'substr'"),
array('"str and \"substr\""', 'str and "substr"'),
array("'str'", 'str'),
array("'str\\nin\\none\\nline'", 'str\nin\none\nline'),
array("'str and \"substr\"'", 'str and "substr"'),
array("'str and \'substr\''", "str and 'substr'"),
array('"$one"', '1'),
array('"$one $two"', '1 2'),
array('"$one and $two"', '1 and 2'),
array('"a $one and $two b"', 'a 1 and 2 b'),
array('"{$one}"', '1'),
array('"a {$one} b"', 'a 1 b'),
array('"{$one + 2}"', '3'),
array('"{$one * $two + 1}"', '3'),
array('"{$one} and {$two}"', '1 and 2'),
array('"$one and {$two}"', '1 and 2'),
array('"{$one} and $two"', '1 and 2'),
array('"a {$one} and {$two} b"', 'a 1 and 2 b'),
array('"{$one+1} and {$two-1}"', '2 and 1'),
array('"a {$one+1} and {$two-1} b"', 'a 2 and 1 b'),
array('"a {$one|dots} and {$two|dots} b"', 'a 1... and 2... b'),
array('"a {$one|dots} and $two b"', 'a 1... and 2 b'),
array('"a $one and {$two|dots} b"', 'a 1 and 2... b'),
);
}
public static function providerVarsInvalid() {
return array(
@@ -347,7 +312,7 @@ class TemplateTest extends TestCase {
public static function providerCreateVarInvalid() {
return array(
array('Create: {var $v} Result: {$v} end', 'Cytro\CompileException', "Unexpected end of expression"),
array('Create: {var $v} Result: {$v} end', 'Cytro\CompileException', "Unclosed tag: {var} opened"),
array('Create: {var $v = } Result: {$v} end', 'Cytro\CompileException', "Unexpected end of expression"),
array('Create: {var $v = 1++} Result: {$v} end', 'Cytro\CompileException', "Unexpected token '++'"),
array('Create: {var $v = c} Result: {$v} end', 'Cytro\CompileException', "Unexpected token 'c'"),
@@ -586,7 +551,7 @@ class TemplateTest extends TestCase {
array('Layers: {for $a=4 to=6} block1 {if 1} {/for} {/if} end', 'Cytro\CompileException', "Unexpected closing of the tag 'for'"),
array('Layers: {switch 1} {if 1} {case 1} {/if} {/switch} end', 'Cytro\CompileException', "Unexpected tag 'case' (this tag can be used with 'switch')"),
array('Layers: {/switch} end', 'Cytro\CompileException', "Unexpected closing of the tag 'switch'"),
array('Layers: {if 1} end', 'Cytro\CompileException', "Unclosed tag(s): {if}"),
array('Layers: {if 1} end', 'Cytro\CompileException', "Unclosed tag: {if}"),
);
}