Add test coverage for Mustache.php 2.0
Update legacy tests for new codebase.
This commit is contained in:
@@ -0,0 +1,90 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Mustache\Test;
|
||||||
|
|
||||||
|
use Mustache\Mustache;
|
||||||
|
use Mustache\Buffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group unit
|
||||||
|
*/
|
||||||
|
class BufferTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider getConstructorArgs
|
||||||
|
*/
|
||||||
|
public function testConstructor($indent, $charset) {
|
||||||
|
$buffer = new Buffer($indent, $charset);
|
||||||
|
$this->assertEquals($indent, $buffer->getIndent());
|
||||||
|
$this->assertEquals($charset, $buffer->getCharset());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getConstructorArgs() {
|
||||||
|
return array(
|
||||||
|
array('', 'UTF-8'),
|
||||||
|
array(' ', 'ISO-8859-1'),
|
||||||
|
array("\t\t\t", 'Shift_JIS'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testWrite() {
|
||||||
|
$buffer = new Buffer;
|
||||||
|
$this->assertEquals('', $buffer->flush());
|
||||||
|
|
||||||
|
$buffer->writeLine();
|
||||||
|
$buffer->writeLine();
|
||||||
|
$buffer->writeLine();
|
||||||
|
$this->assertEquals("\n\n\n", $buffer->flush());
|
||||||
|
$this->assertEquals('', $buffer->flush());
|
||||||
|
|
||||||
|
$buffer->write('foo');
|
||||||
|
$buffer->write('bar');
|
||||||
|
$buffer->writeLine();
|
||||||
|
$buffer->write('baz');
|
||||||
|
$this->assertEquals("foobar\nbaz", $buffer->flush());
|
||||||
|
$this->assertEquals('', $buffer->flush());
|
||||||
|
|
||||||
|
$indent = "\t\t";
|
||||||
|
$buffer->setIndent($indent);
|
||||||
|
$buffer->writeText('foo');
|
||||||
|
$buffer->writeLine();
|
||||||
|
$buffer->writeText('bar');
|
||||||
|
$this->assertEquals("\t\tfoo\n\t\tbar", $buffer->flush());
|
||||||
|
$this->assertEquals('', $buffer->flush());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider getEscapeAndIndent
|
||||||
|
*/
|
||||||
|
public function testEscapingAndIndenting($text, $escape, $indent, $whitespace, $expected) {
|
||||||
|
$buffer = new Buffer;
|
||||||
|
$buffer->setIndent($whitespace);
|
||||||
|
|
||||||
|
$buffer->write($text, $indent, $escape);
|
||||||
|
$this->assertEquals($expected, $buffer->flush());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEscapeAndIndent() {
|
||||||
|
return array(
|
||||||
|
array('> "fun & games" <', false, false, "\t", '> "fun & games" <'),
|
||||||
|
array('> "fun & games" <', true, false, "\t", '> "fun & games" <'),
|
||||||
|
array('> "fun & games" <', true, true, "\t", "\t> "fun & games" <"),
|
||||||
|
array('> "fun & games" <', false, true, "\t", "\t> \"fun & games\" <"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testChangeIndent() {
|
||||||
|
$indent = "\t\t";
|
||||||
|
$buffer = new Buffer($indent);
|
||||||
|
$this->assertEquals($indent, $buffer->getIndent());
|
||||||
|
|
||||||
|
$indent = "";
|
||||||
|
$buffer->setIndent($indent);
|
||||||
|
$this->assertEquals($indent, $buffer->getIndent());
|
||||||
|
|
||||||
|
$indent = " ";
|
||||||
|
$buffer->setIndent($indent);
|
||||||
|
$this->assertEquals($indent, $buffer->getIndent());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Mustache\Test;
|
||||||
|
|
||||||
|
use Mustache\Compiler;
|
||||||
|
use Mustache\Tokenizer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group unit
|
||||||
|
*/
|
||||||
|
class CompilerTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider getCompileValues
|
||||||
|
*/
|
||||||
|
public function testCompile($source, array $tree, $name, $expected) {
|
||||||
|
$compiler = new Compiler;
|
||||||
|
|
||||||
|
$compiled = $compiler->compile($source, $tree, $name);
|
||||||
|
foreach ($expected as $contains) {
|
||||||
|
$this->assertContains($contains, $compiled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCompileValues() {
|
||||||
|
return array(
|
||||||
|
array('', array(), 'Banana', array(
|
||||||
|
"\nclass Banana extends \Mustache\Template",
|
||||||
|
'$buffer->flush();',
|
||||||
|
)),
|
||||||
|
|
||||||
|
array('', array('TEXT'), 'Monkey', array(
|
||||||
|
"\nclass Monkey extends \Mustache\Template",
|
||||||
|
'$buffer->writeText(\'TEXT\');',
|
||||||
|
'$buffer->flush();',
|
||||||
|
)),
|
||||||
|
|
||||||
|
array(
|
||||||
|
'',
|
||||||
|
array(
|
||||||
|
'foo',
|
||||||
|
"\n",
|
||||||
|
array(
|
||||||
|
Tokenizer::TAG => '_v',
|
||||||
|
Tokenizer::NAME => 'name',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
Tokenizer::TAG => '_v',
|
||||||
|
Tokenizer::NAME => '.',
|
||||||
|
),
|
||||||
|
"'bar'",
|
||||||
|
),
|
||||||
|
'Monkey',
|
||||||
|
array(
|
||||||
|
"\nclass Monkey extends \Mustache\Template",
|
||||||
|
'$buffer->writeText(\'foo\');',
|
||||||
|
'$buffer->writeLine();',
|
||||||
|
'$value = $context->find(\'name\');',
|
||||||
|
'$buffer->writeText($value, true);',
|
||||||
|
'$value = $context->last();',
|
||||||
|
'$buffer->writeText(\'\\\'bar\\\'\');',
|
||||||
|
'$buffer->flush();',
|
||||||
|
)
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function testCompilerThrowsUnknownNodeTypeException() {
|
||||||
|
$compiler = new Compiler;
|
||||||
|
$compiler->compile('', array(array(Tokenizer::TAG => 'invalid')), 'SomeClass');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,150 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Mustache\Test;
|
||||||
|
|
||||||
|
use Mustache\Context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group unit
|
||||||
|
*/
|
||||||
|
class ContextTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
public function testConstructor() {
|
||||||
|
$one = new Context;
|
||||||
|
$this->assertSame('', $one->find('foo'));
|
||||||
|
$this->assertSame('', $one->find('bar'));
|
||||||
|
|
||||||
|
$two = new Context(array(
|
||||||
|
'foo' => 'FOO',
|
||||||
|
'bar' => '<BAR>'
|
||||||
|
));
|
||||||
|
$this->assertEquals('FOO', $two->find('foo'));
|
||||||
|
$this->assertEquals('<BAR>', $two->find('bar'));
|
||||||
|
|
||||||
|
$obj = new \StdClass;
|
||||||
|
$obj->name = 'NAME';
|
||||||
|
$three = new Context($obj);
|
||||||
|
$this->assertSame($obj, $three->last());
|
||||||
|
$this->assertEquals('NAME', $three->find('name'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsTruthy() {
|
||||||
|
$context = new Context;
|
||||||
|
|
||||||
|
$this->assertTrue($context->isTruthy('string'));
|
||||||
|
$this->assertTrue($context->isTruthy(new \StdClass));
|
||||||
|
$this->assertTrue($context->isTruthy(1));
|
||||||
|
$this->assertTrue($context->isTruthy(array('a', 'b')));
|
||||||
|
|
||||||
|
$this->assertFalse($context->isTruthy(null));
|
||||||
|
$this->assertFalse($context->isTruthy(''));
|
||||||
|
$this->assertFalse($context->isTruthy(0));
|
||||||
|
$this->assertFalse($context->isTruthy(array()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsCallable() {
|
||||||
|
$dummy = new TestDummy;
|
||||||
|
$context = new Context;
|
||||||
|
|
||||||
|
$this->assertTrue($context->isCallable(function() { return null; }));
|
||||||
|
$this->assertTrue($context->isCallable(array('\Mustache\Test\TestDummy', 'foo')));
|
||||||
|
$this->assertTrue($context->isCallable(array($dummy, 'bar')));
|
||||||
|
$this->assertTrue($context->isCallable($dummy));
|
||||||
|
|
||||||
|
$this->assertFalse($context->isCallable('count'));
|
||||||
|
$this->assertFalse($context->isCallable('TestDummy::foo'));
|
||||||
|
$this->assertFalse($context->isCallable(array('\Mustache\Test\TestDummy', 'name')));
|
||||||
|
$this->assertFalse($context->isCallable(array('NotReallyAClass', 'foo')));
|
||||||
|
$this->assertFalse($context->isCallable(array($dummy, 'name')));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider getIterables
|
||||||
|
*/
|
||||||
|
public function testIsIterable($value, $iterable) {
|
||||||
|
$context = new Context;
|
||||||
|
$this->assertEquals($iterable, $context->isIterable($value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIterables() {
|
||||||
|
return array(
|
||||||
|
array(array(0 => 'a', 1 => 'b'), true),
|
||||||
|
array(array(0 => 'a', 2 => 'b'), false),
|
||||||
|
array(array(1 => 'a', 2 => 'b'), false),
|
||||||
|
array(array('a' => 0, 'b' => 1), false),
|
||||||
|
array('some string', false),
|
||||||
|
array(new \ArrayIterator, true),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testPushPopAndLast() {
|
||||||
|
$context = new Context;
|
||||||
|
$this->assertFalse($context->last());
|
||||||
|
|
||||||
|
$dummy = new TestDummy;
|
||||||
|
$context->push($dummy);
|
||||||
|
$this->assertSame($dummy, $context->last());
|
||||||
|
$this->assertSame($dummy, $context->pop());
|
||||||
|
$this->assertFalse($context->last());
|
||||||
|
|
||||||
|
$obj = new \StdClass;
|
||||||
|
$context->push($dummy);
|
||||||
|
$this->assertSame($dummy, $context->last());
|
||||||
|
$context->push($obj);
|
||||||
|
$this->assertSame($obj, $context->last());
|
||||||
|
$this->assertSame($obj, $context->pop());
|
||||||
|
$this->assertSame($dummy, $context->pop());
|
||||||
|
$this->assertFalse($context->last());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFind() {
|
||||||
|
$context = new Context;
|
||||||
|
|
||||||
|
$dummy = new TestDummy;
|
||||||
|
|
||||||
|
$obj = new \StdClass;
|
||||||
|
$obj->name = 'obj';
|
||||||
|
|
||||||
|
$arr = array(
|
||||||
|
'a' => array('b' => array('c' => 'see')),
|
||||||
|
'b' => 'bee',
|
||||||
|
);
|
||||||
|
|
||||||
|
$string = 'some arbitrary string';
|
||||||
|
|
||||||
|
$context->push($dummy);
|
||||||
|
$this->assertEquals('dummy', $context->find('name'));
|
||||||
|
|
||||||
|
$context->push($obj);
|
||||||
|
$this->assertEquals('obj', $context->find('name'));
|
||||||
|
|
||||||
|
$context->pop();
|
||||||
|
$this->assertEquals('dummy', $context->find('name'));
|
||||||
|
|
||||||
|
$dummy->name = 'dummyer';
|
||||||
|
$this->assertEquals('dummyer', $context->find('name'));
|
||||||
|
|
||||||
|
$context->push($arr);
|
||||||
|
$this->assertEquals('bee', $context->find('b'));
|
||||||
|
$this->assertEquals('see', $context->findDot('a.b.c'));
|
||||||
|
|
||||||
|
$dummy->name = 'dummy';
|
||||||
|
|
||||||
|
$context->push($string);
|
||||||
|
$this->assertSame($string, $context->last());
|
||||||
|
$this->assertEquals('dummy', $context->find('name'));
|
||||||
|
$this->assertEquals('see', $context->findDot('a.b.c'));
|
||||||
|
$this->assertEquals('<foo>', $context->find('foo'));
|
||||||
|
$this->assertEquals('<bar>', $context->findDot('bar'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestDummy {
|
||||||
|
public $name = 'dummy';
|
||||||
|
public function __invoke() {}
|
||||||
|
public static function foo() {
|
||||||
|
return '<foo>';
|
||||||
|
}
|
||||||
|
public function bar() {
|
||||||
|
return '<bar>';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,18 +1,25 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
require_once '../Mustache.php';
|
namespace Mustache\Test\Functional;
|
||||||
|
|
||||||
class MustacheCallTest extends PHPUnit_Framework_TestCase {
|
use Mustache\Mustache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group magic_methods
|
||||||
|
* @group functional
|
||||||
|
*/
|
||||||
|
class CallTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
|
||||||
public function testCallEatsContext() {
|
public function testCallEatsContext() {
|
||||||
|
$m = new Mustache;
|
||||||
|
$tpl = $m->loadTemplate('{{# foo }}{{ label }}: {{ name }}{{/ foo }}');
|
||||||
|
|
||||||
$foo = new ClassWithCall();
|
$foo = new ClassWithCall();
|
||||||
$foo->name = 'Bob';
|
$foo->name = 'Bob';
|
||||||
|
|
||||||
$template = '{{# foo }}{{ label }}: {{ name }}{{/ foo }}';
|
|
||||||
$data = array('label' => 'name', 'foo' => $foo);
|
$data = array('label' => 'name', 'foo' => $foo);
|
||||||
$m = new Mustache($template, $data);
|
|
||||||
|
|
||||||
$this->assertEquals('name: Bob', $m->render());
|
$this->assertEquals('name: Bob', $tpl->render($data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,12 +4,15 @@ namespace Mustache\Test\Functional;
|
|||||||
|
|
||||||
use Mustache\Mustache;
|
use Mustache\Mustache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group examples
|
||||||
|
* @group functional
|
||||||
|
*/
|
||||||
class ExamplesTest extends \PHPUnit_Framework_TestCase {
|
class ExamplesTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test everything in the `examples` directory.
|
* Test everything in the `examples` directory.
|
||||||
*
|
*
|
||||||
* @group examples
|
|
||||||
* @dataProvider getExamples
|
* @dataProvider getExamples
|
||||||
*
|
*
|
||||||
* @param string $context
|
* @param string $context
|
||||||
|
|||||||
@@ -1,93 +1,115 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
require_once '../Mustache.php';
|
namespace Mustache\Test\Functional;
|
||||||
|
|
||||||
class MustacheHigherOrderSectionsTest extends PHPUnit_Framework_TestCase {
|
use Mustache\Mustache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group lambdas
|
||||||
|
* @group functional
|
||||||
|
*/
|
||||||
|
class HigherOrderSectionsTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
|
||||||
|
private $mustache;
|
||||||
|
|
||||||
public function setUp() {
|
public function setUp() {
|
||||||
$this->foo = new Foo();
|
$this->mustache = new Mustache;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAnonymousFunctionSectionCallback() {
|
public function testAnonymousFunctionSectionCallback() {
|
||||||
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
|
$tpl = $this->mustache->loadTemplate('{{#wrapper}}{{name}}{{/wrapper}}');
|
||||||
$this->markTestSkipped('Unable to test anonymous function section callbacks in PHP < 5.3');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->foo->wrapper = function($text) {
|
$foo = new Foo;
|
||||||
|
$foo->name = 'Mario';
|
||||||
|
$foo->wrapper = function($text) {
|
||||||
return sprintf('<div class="anonymous">%s</div>', $text);
|
return sprintf('<div class="anonymous">%s</div>', $text);
|
||||||
};
|
};
|
||||||
|
|
||||||
$this->assertEquals(
|
$this->assertEquals(sprintf('<div class="anonymous">%s</div>', $foo->name), $tpl->render($foo));
|
||||||
sprintf('<div class="anonymous">%s</div>', $this->foo->name),
|
|
||||||
$this->foo->render('{{#wrapper}}{{name}}{{/wrapper}}')
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSectionCallback() {
|
public function testSectionCallback() {
|
||||||
$this->assertEquals(sprintf('%s', $this->foo->name), $this->foo->render('{{name}}'));
|
$one = $this->mustache->loadTemplate('{{name}}');
|
||||||
$this->assertEquals(sprintf('<em>%s</em>', $this->foo->name), $this->foo->render('{{#wrap}}{{name}}{{/wrap}}'));
|
$two = $this->mustache->loadTemplate('{{#wrap}}{{name}}{{/wrap}}');
|
||||||
|
|
||||||
|
$foo = new Foo;
|
||||||
|
$foo->name = 'Luigi';
|
||||||
|
|
||||||
|
$this->assertEquals($foo->name, $one->render($foo));
|
||||||
|
$this->assertEquals(sprintf('<em>%s</em>', $foo->name), $two->render($foo));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRuntimeSectionCallback() {
|
public function testRuntimeSectionCallback() {
|
||||||
$this->foo->double_wrap = array($this->foo, 'wrapWithBoth');
|
$tpl = $this->mustache->loadTemplate('{{#double_wrap}}{{name}}{{/double_wrap}}');
|
||||||
$this->assertEquals(
|
|
||||||
sprintf('<strong><em>%s</em></strong>', $this->foo->name),
|
$foo = new Foo;
|
||||||
$this->foo->render('{{#double_wrap}}{{name}}{{/double_wrap}}')
|
$foo->double_wrap = array($foo, 'wrapWithBoth');
|
||||||
);
|
|
||||||
|
$this->assertEquals(sprintf('<strong><em>%s</em></strong>', $foo->name), $tpl->render($foo));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testStaticSectionCallback() {
|
public function testStaticSectionCallback() {
|
||||||
$this->foo->trimmer = array(get_class($this->foo), 'staticTrim');
|
$tpl = $this->mustache->loadTemplate('{{#trimmer}} {{name}} {{/trimmer}}');
|
||||||
$this->assertEquals($this->foo->name, $this->foo->render('{{#trimmer}} {{name}} {{/trimmer}}'));
|
|
||||||
|
$foo = new Foo;
|
||||||
|
$foo->trimmer = array(get_class($foo), 'staticTrim');
|
||||||
|
|
||||||
|
$this->assertEquals($foo->name, $tpl->render($foo));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testViewArraySectionCallback() {
|
public function testViewArraySectionCallback() {
|
||||||
|
$tpl = $this->mustache->loadTemplate('{{#trim}} {{name}} {{/trim}}');
|
||||||
|
|
||||||
|
$foo = new Foo;
|
||||||
|
|
||||||
$data = array(
|
$data = array(
|
||||||
'name' => 'Bob',
|
'name' => 'Bob',
|
||||||
'trim' => array(get_class($this->foo), 'staticTrim'),
|
'trim' => array(get_class($foo), 'staticTrim'),
|
||||||
);
|
);
|
||||||
$this->assertEquals($data['name'], $this->foo->render('{{#trim}} {{name}} {{/trim}}', $data));
|
|
||||||
|
$this->assertEquals($data['name'], $tpl->render($data));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testViewArrayAnonymousSectionCallback() {
|
public function testViewArrayAnonymousSectionCallback() {
|
||||||
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
|
$tpl = $this->mustache->loadTemplate('{{#wrap}}{{name}}{{/wrap}}');
|
||||||
$this->markTestSkipped('Unable to test anonymous function section callbacks in PHP < 5.3');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$data = array(
|
$data = array(
|
||||||
'name' => 'Bob',
|
'name' => 'Bob',
|
||||||
'wrap' => function($text) {
|
'wrap' => function($text) {
|
||||||
return sprintf('[[%s]]', $text);
|
return sprintf('[[%s]]', $text);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
sprintf('[[%s]]', $data['name']),
|
sprintf('[[%s]]', $data['name']),
|
||||||
$this->foo->render('{{#wrap}}{{name}}{{/wrap}}', $data)
|
$tpl->render($data)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMonsters() {
|
public function testMonsters() {
|
||||||
|
$tpl = $this->mustache->loadTemplate('{{#title}}{{title}} {{/title}}{{name}}');
|
||||||
|
|
||||||
$frank = new Monster();
|
$frank = new Monster();
|
||||||
$frank->title = 'Dr.';
|
$frank->title = 'Dr.';
|
||||||
$frank->name = 'Frankenstein';
|
$frank->name = 'Frankenstein';
|
||||||
$this->assertEquals('Dr. Frankenstein', $frank->render());
|
$this->assertEquals('Dr. Frankenstein', $tpl->render($frank));
|
||||||
|
|
||||||
$dracula = new Monster();
|
$dracula = new Monster();
|
||||||
$dracula->title = 'Count';
|
$dracula->title = 'Count';
|
||||||
$dracula->name = 'Dracula';
|
$dracula->name = 'Dracula';
|
||||||
$this->assertEquals('Count Dracula', $dracula->render());
|
$this->assertEquals('Count Dracula', $tpl->render($dracula));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Foo extends Mustache {
|
class Foo {
|
||||||
public $name = 'Justin';
|
public $name = 'Justin';
|
||||||
public $lorem = 'Lorem ipsum dolor sit amet,';
|
public $lorem = 'Lorem ipsum dolor sit amet,';
|
||||||
public $wrap;
|
public $wrap;
|
||||||
|
|
||||||
public function __construct($template = null, $view = null, $partials = null) {
|
public function __construct() {
|
||||||
$this->wrap = array($this, 'wrapWithEm');
|
$this->wrap = function($text) {
|
||||||
parent::__construct($template, $view, $partials);
|
return sprintf('<em>%s</em>', $text);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public function wrapWithEm($text) {
|
public function wrapWithEm($text) {
|
||||||
@@ -107,8 +129,7 @@ class Foo extends Mustache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Monster extends Mustache {
|
class Monster {
|
||||||
public $_template = '{{#title}}{{title}} {{/title}}{{name}}';
|
|
||||||
public $title;
|
public $title;
|
||||||
public $name;
|
public $name;
|
||||||
}
|
}
|
||||||
@@ -1,127 +1,127 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
require_once '../Mustache.php';
|
namespace Mustache\Test\Functional;
|
||||||
|
|
||||||
|
use Mustache\Mustache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @group mustache_injection
|
* @group mustache_injection
|
||||||
|
* @group functional
|
||||||
*/
|
*/
|
||||||
class MustacheInjectionSectionTest extends PHPUnit_Framework_TestCase {
|
class MustacheInjectionTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
|
||||||
|
private $mustache;
|
||||||
|
|
||||||
|
public function setUp() {
|
||||||
|
$this->mustache = new Mustache;
|
||||||
|
}
|
||||||
|
|
||||||
// interpolation
|
// interpolation
|
||||||
|
|
||||||
public function testInterpolationInjection() {
|
public function testInterpolationInjection() {
|
||||||
|
$tpl = $this->mustache->loadTemplate('{{ a }}');
|
||||||
|
|
||||||
$data = array(
|
$data = array(
|
||||||
'a' => '{{ b }}',
|
'a' => '{{ b }}',
|
||||||
'b' => 'FAIL'
|
'b' => 'FAIL'
|
||||||
);
|
);
|
||||||
$template = '{{ a }}';
|
|
||||||
$output = '{{ b }}';
|
$this->assertEquals('{{ b }}', $tpl->render($data));
|
||||||
$m = new Mustache();
|
|
||||||
$this->assertEquals($output, $m->render($template, $data));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUnescapedInterpolationInjection() {
|
public function testUnescapedInterpolationInjection() {
|
||||||
|
$tpl = $this->mustache->loadTemplate('{{{ a }}}');
|
||||||
|
|
||||||
$data = array(
|
$data = array(
|
||||||
'a' => '{{ b }}',
|
'a' => '{{ b }}',
|
||||||
'b' => 'FAIL'
|
'b' => 'FAIL'
|
||||||
);
|
);
|
||||||
$template = '{{{ a }}}';
|
|
||||||
$output = '{{ b }}';
|
$this->assertEquals('{{ b }}', $tpl->render($data));
|
||||||
$m = new Mustache();
|
|
||||||
$this->assertEquals($output, $m->render($template, $data));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// sections
|
// sections
|
||||||
|
|
||||||
public function testSectionInjection() {
|
public function testSectionInjection() {
|
||||||
|
$tpl = $this->mustache->loadTemplate('{{# a }}{{ b }}{{/ a }}');
|
||||||
|
|
||||||
$data = array(
|
$data = array(
|
||||||
'a' => true,
|
'a' => true,
|
||||||
'b' => '{{ c }}',
|
'b' => '{{ c }}',
|
||||||
'c' => 'FAIL'
|
'c' => 'FAIL'
|
||||||
);
|
);
|
||||||
$template = '{{# a }}{{ b }}{{/ a }}';
|
|
||||||
$output = '{{ c }}';
|
$this->assertEquals('{{ c }}', $tpl->render($data));
|
||||||
$m = new Mustache();
|
|
||||||
$this->assertEquals($output, $m->render($template, $data));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUnescapedSectionInjection() {
|
public function testUnescapedSectionInjection() {
|
||||||
|
$tpl = $this->mustache->loadTemplate('{{# a }}{{{ b }}}{{/ a }}');
|
||||||
|
|
||||||
$data = array(
|
$data = array(
|
||||||
'a' => true,
|
'a' => true,
|
||||||
'b' => '{{ c }}',
|
'b' => '{{ c }}',
|
||||||
'c' => 'FAIL'
|
'c' => 'FAIL'
|
||||||
);
|
);
|
||||||
$template = '{{# a }}{{{ b }}}{{/ a }}';
|
|
||||||
$output = '{{ c }}';
|
$this->assertEquals('{{ c }}', $tpl->render($data));
|
||||||
$m = new Mustache();
|
|
||||||
$this->assertEquals($output, $m->render($template, $data));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// partials
|
// partials
|
||||||
|
|
||||||
public function testPartialInjection() {
|
public function testPartialInjection() {
|
||||||
|
$tpl = $this->mustache->loadTemplate('{{> partial }}');
|
||||||
|
$this->mustache->setPartials(array(
|
||||||
|
'partial' => '{{ a }}',
|
||||||
|
));
|
||||||
|
|
||||||
$data = array(
|
$data = array(
|
||||||
'a' => '{{ b }}',
|
'a' => '{{ b }}',
|
||||||
'b' => 'FAIL'
|
'b' => 'FAIL'
|
||||||
);
|
);
|
||||||
$template = '{{> partial }}';
|
|
||||||
$partials = array(
|
$this->assertEquals('{{ b }}', $tpl->render($data));
|
||||||
'partial' => '{{ a }}',
|
|
||||||
);
|
|
||||||
$output = '{{ b }}';
|
|
||||||
$m = new Mustache();
|
|
||||||
$this->assertEquals($output, $m->render($template, $data, $partials));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUnescapedInjection() {
|
public function testPartialUnescapedInjection() {
|
||||||
|
$tpl = $this->mustache->loadTemplate('{{> partial }}');
|
||||||
|
$this->mustache->setPartials(array(
|
||||||
|
'partial' => '{{{ a }}}',
|
||||||
|
));
|
||||||
|
|
||||||
$data = array(
|
$data = array(
|
||||||
'a' => '{{ b }}',
|
'a' => '{{ b }}',
|
||||||
'b' => 'FAIL'
|
'b' => 'FAIL'
|
||||||
);
|
);
|
||||||
$template = '{{> partial }}';
|
|
||||||
$partials = array(
|
$this->assertEquals('{{ b }}', $tpl->render($data));
|
||||||
'partial' => '{{{ a }}}',
|
|
||||||
);
|
|
||||||
$output = '{{ b }}';
|
|
||||||
$m = new Mustache();
|
|
||||||
$this->assertEquals($output, $m->render($template, $data, $partials));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// lambdas
|
// lambdas
|
||||||
|
|
||||||
public function testLambdaInterpolationInjection() {
|
public function testLambdaInterpolationInjection() {
|
||||||
|
$tpl = $this->mustache->loadTemplate('{{ a }}');
|
||||||
|
|
||||||
$data = array(
|
$data = array(
|
||||||
'a' => array($this, 'interpolationLambda'),
|
'a' => function() { return '{{ b }}'; },
|
||||||
'b' => '{{ c }}',
|
'b' => '{{ c }}',
|
||||||
'c' => 'FAIL'
|
'c' => 'FAIL'
|
||||||
);
|
);
|
||||||
$template = '{{ a }}';
|
|
||||||
$output = '{{ c }}';
|
|
||||||
$m = new Mustache();
|
|
||||||
$this->assertEquals($output, $m->render($template, $data));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function interpolationLambda() {
|
$this->assertEquals('{{ c }}', $tpl->render($data));
|
||||||
return '{{ b }}';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testLambdaSectionInjection() {
|
public function testLambdaSectionInjection() {
|
||||||
|
$tpl = $this->mustache->loadTemplate('{{# a }}b{{/ a }}');
|
||||||
|
|
||||||
$data = array(
|
$data = array(
|
||||||
'a' => array($this, 'sectionLambda'),
|
'a' => function ($text) { return '{{ ' . $text . ' }}'; },
|
||||||
'b' => '{{ c }}',
|
'b' => '{{ c }}',
|
||||||
'c' => 'FAIL'
|
'c' => 'FAIL'
|
||||||
);
|
);
|
||||||
$template = '{{# a }}b{{/ a }}';
|
|
||||||
$output = '{{ c }}';
|
|
||||||
$m = new Mustache();
|
|
||||||
$this->assertEquals($output, $m->render($template, $data));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function sectionLambda($content) {
|
$this->assertEquals('{{ c }}', $tpl->render($data));
|
||||||
return '{{ ' . $content . ' }}';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,22 +1,30 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
require_once '../Mustache.php';
|
namespace Mustache\Test\Functional;
|
||||||
require_once './lib/yaml/lib/sfYamlParser.php';
|
|
||||||
|
use Mustache\Mustache;
|
||||||
|
use Mustache\Loader\StringLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A PHPUnit test case wrapping the Mustache Spec
|
* A PHPUnit test case wrapping the Mustache Spec
|
||||||
*
|
*
|
||||||
* @group mustache-spec
|
* @group mustache-spec
|
||||||
|
* @group functional
|
||||||
*/
|
*/
|
||||||
class MustacheSpecTest extends PHPUnit_Framework_TestCase {
|
class MustacheSpecTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
|
||||||
|
private static $mustache;
|
||||||
|
|
||||||
|
public static function setUpBeforeClass() {
|
||||||
|
self::$mustache = new Mustache;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For some reason data providers can't mark tests skipped, so this test exists
|
* For some reason data providers can't mark tests skipped, so this test exists
|
||||||
* simply to provide a 'skipped' test if the `spec` submodule isn't initialized.
|
* simply to provide a 'skipped' test if the `spec` submodule isn't initialized.
|
||||||
*/
|
*/
|
||||||
public function testSpecInitialized() {
|
public function testSpecInitialized() {
|
||||||
$spec_dir = dirname(__FILE__) . '/spec/specs/';
|
if (!file_exists(__DIR__.'/../../../spec/specs/')) {
|
||||||
if (!file_exists($spec_dir)) {
|
|
||||||
$this->markTestSkipped('Mustache spec submodule not initialized: run "git submodule update --init"');
|
$this->markTestSkipped('Mustache spec submodule not initialized: run "git submodule update --init"');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -25,56 +33,72 @@ class MustacheSpecTest extends PHPUnit_Framework_TestCase {
|
|||||||
* @group comments
|
* @group comments
|
||||||
* @dataProvider loadCommentSpec
|
* @dataProvider loadCommentSpec
|
||||||
*/
|
*/
|
||||||
public function testCommentSpec($desc, $template, $data, $partials, $expected) {
|
public function testCommentSpec($desc, $source, $partials, $data, $expected) {
|
||||||
$m = new Mustache($template, $data, $partials);
|
$template = self::loadTemplate($source, $partials);
|
||||||
$this->assertEquals($expected, $m->render(), $desc);
|
$this->assertEquals($expected, $template($data), $desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadCommentSpec() {
|
||||||
|
return $this->loadSpec('comments');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @group delimiters
|
* @group delimiters
|
||||||
* @dataProvider loadDelimitersSpec
|
* @dataProvider loadDelimitersSpec
|
||||||
*/
|
*/
|
||||||
public function testDelimitersSpec($desc, $template, $data, $partials, $expected) {
|
public function testDelimitersSpec($desc, $source, $partials, $data, $expected) {
|
||||||
$m = new Mustache($template, $data, $partials);
|
$template = self::loadTemplate($source, $partials);
|
||||||
$this->assertEquals($expected, $m->render(), $desc);
|
$this->assertEquals($expected, $template($data), $desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadDelimitersSpec() {
|
||||||
|
return $this->loadSpec('delimiters');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @group interpolation
|
* @group interpolation
|
||||||
* @dataProvider loadInterpolationSpec
|
* @dataProvider loadInterpolationSpec
|
||||||
*/
|
*/
|
||||||
public function testInterpolationSpec($desc, $template, $data, $partials, $expected) {
|
public function testInterpolationSpec($desc, $source, $partials, $data, $expected) {
|
||||||
$m = new Mustache($template, $data, $partials);
|
$template = self::loadTemplate($source, $partials);
|
||||||
$this->assertEquals($expected, $m->render(), $desc);
|
$this->assertEquals($expected, $template($data), $desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadInterpolationSpec() {
|
||||||
|
return $this->loadSpec('interpolation');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @group inverted
|
||||||
* @group inverted-sections
|
* @group inverted-sections
|
||||||
* @dataProvider loadInvertedSpec
|
* @dataProvider loadInvertedSpec
|
||||||
*/
|
*/
|
||||||
public function testInvertedSpec($desc, $template, $data, $partials, $expected) {
|
public function testInvertedSpec($desc, $source, $partials, $data, $expected) {
|
||||||
$m = new Mustache($template, $data, $partials);
|
$template = self::loadTemplate($source, $partials);
|
||||||
$this->assertEquals($expected, $m->render(), $desc);
|
$this->assertEquals($expected, $template($data), $desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadInvertedSpec() {
|
||||||
|
return $this->loadSpec('inverted');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @group lambdas
|
* @group lambdas
|
||||||
* @dataProvider loadLambdasSpec
|
* @dataProvider loadLambdasSpec
|
||||||
*/
|
*/
|
||||||
public function testLambdasSpec($desc, $template, $data, $partials, $expected) {
|
public function testLambdasSpec($desc, $source, $partials, $data, $expected) {
|
||||||
if (!version_compare(PHP_VERSION, '5.3.0', '>=')) {
|
$template = self::loadTemplate($source, $partials);
|
||||||
$this->markTestSkipped('Unable to test Lambdas spec with PHP < 5.3.');
|
$this->assertEquals($expected, $template($this->prepareLambdasSpec($data)), $desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = $this->prepareLambdasSpec($data);
|
public function loadLambdasSpec() {
|
||||||
$m = new Mustache($template, $data, $partials);
|
return $this->loadSpec('~lambdas');
|
||||||
$this->assertEquals($expected, $m->render(), $desc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract and lambdafy any 'lambda' values found in the $data array.
|
* Extract and lambdafy any 'lambda' values found in the $data array.
|
||||||
*/
|
*/
|
||||||
protected function prepareLambdasSpec($data) {
|
private function prepareLambdasSpec($data) {
|
||||||
foreach ($data as $key => $val) {
|
foreach ($data as $key => $val) {
|
||||||
if ($key === 'lambda') {
|
if ($key === 'lambda') {
|
||||||
if (!isset($val['php'])) {
|
if (!isset($val['php'])) {
|
||||||
@@ -94,42 +118,22 @@ class MustacheSpecTest extends PHPUnit_Framework_TestCase {
|
|||||||
* @group partials
|
* @group partials
|
||||||
* @dataProvider loadPartialsSpec
|
* @dataProvider loadPartialsSpec
|
||||||
*/
|
*/
|
||||||
public function testPartialsSpec($desc, $template, $data, $partials, $expected) {
|
public function testPartialsSpec($desc, $source, $partials, $data, $expected) {
|
||||||
$m = new Mustache($template, $data, $partials);
|
$template = self::loadTemplate($source, $partials);
|
||||||
$this->assertEquals($expected, $m->render(), $desc);
|
$this->assertEquals($expected, $template($data), $desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadPartialsSpec() {
|
||||||
|
return $this->loadSpec('partials');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @group sections
|
* @group sections
|
||||||
* @dataProvider loadSectionsSpec
|
* @dataProvider loadSectionsSpec
|
||||||
*/
|
*/
|
||||||
public function testSectionsSpec($desc, $template, $data, $partials, $expected) {
|
public function testSectionsSpec($desc, $source, $partials, $data, $expected) {
|
||||||
$m = new Mustache($template, $data, $partials);
|
$template = self::loadTemplate($source, $partials);
|
||||||
$this->assertEquals($expected, $m->render(), $desc);
|
$this->assertEquals($expected, $template($data), $desc);
|
||||||
}
|
|
||||||
|
|
||||||
public function loadCommentSpec() {
|
|
||||||
return $this->loadSpec('comments');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function loadDelimitersSpec() {
|
|
||||||
return $this->loadSpec('delimiters');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function loadInterpolationSpec() {
|
|
||||||
return $this->loadSpec('interpolation');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function loadInvertedSpec() {
|
|
||||||
return $this->loadSpec('inverted');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function loadLambdasSpec() {
|
|
||||||
return $this->loadSpec('~lambdas');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function loadPartialsSpec() {
|
|
||||||
return $this->loadSpec('partials');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function loadSectionsSpec() {
|
public function loadSectionsSpec() {
|
||||||
@@ -144,14 +148,14 @@ class MustacheSpecTest extends PHPUnit_Framework_TestCase {
|
|||||||
* @access public
|
* @access public
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected function loadSpec($name) {
|
private function loadSpec($name) {
|
||||||
$filename = dirname(__FILE__) . '/spec/specs/' . $name . '.yml';
|
$filename = __DIR__ . '/../../../spec/specs/' . $name . '.yml';
|
||||||
if (!file_exists($filename)) {
|
if (!file_exists($filename)) {
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = array();
|
$data = array();
|
||||||
$yaml = new sfYamlParser();
|
$yaml = new \sfYamlParser;
|
||||||
$file = file_get_contents($filename);
|
$file = file_get_contents($filename);
|
||||||
|
|
||||||
// @hack: pre-process the 'lambdas' spec so the Symfony YAML parser doesn't complain.
|
// @hack: pre-process the 'lambdas' spec so the Symfony YAML parser doesn't complain.
|
||||||
@@ -160,15 +164,23 @@ class MustacheSpecTest extends PHPUnit_Framework_TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$spec = $yaml->parse($file);
|
$spec = $yaml->parse($file);
|
||||||
|
|
||||||
foreach ($spec['tests'] as $test) {
|
foreach ($spec['tests'] as $test) {
|
||||||
$data[] = array(
|
$data[] = array(
|
||||||
$test['name'] . ': ' . $test['desc'],
|
$test['name'] . ': ' . $test['desc'],
|
||||||
$test['template'],
|
$test['template'],
|
||||||
$test['data'],
|
|
||||||
isset($test['partials']) ? $test['partials'] : array(),
|
isset($test['partials']) ? $test['partials'] : array(),
|
||||||
|
$test['data'],
|
||||||
$test['expected'],
|
$test['expected'],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function loadTemplate($source, $partials) {
|
||||||
|
self::$mustache->setPartials($partials);
|
||||||
|
|
||||||
|
return self::$mustache->loadTemplate($source);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,48 +1,64 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
require_once '../Mustache.php';
|
namespace Mustache\Test\Functional;
|
||||||
|
|
||||||
|
use Mustache\Mustache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @group sections
|
* @group sections
|
||||||
|
* @group functional
|
||||||
*/
|
*/
|
||||||
class MustacheObjectSectionTest extends PHPUnit_Framework_TestCase {
|
class ObjectSectionTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
private $mustache;
|
||||||
|
|
||||||
|
public function setUp() {
|
||||||
|
$this->mustache = new Mustache;
|
||||||
|
}
|
||||||
|
|
||||||
public function testBasicObject() {
|
public function testBasicObject() {
|
||||||
$alpha = new Alpha();
|
$tpl = $this->mustache->loadTemplate('{{#foo}}{{name}}{{/foo}}');
|
||||||
$this->assertEquals('Foo', $alpha->render('{{#foo}}{{name}}{{/foo}}'));
|
$this->assertEquals('Foo', $tpl->render(new Alpha));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group magic_methods
|
||||||
|
*/
|
||||||
public function testObjectWithGet() {
|
public function testObjectWithGet() {
|
||||||
$beta = new Beta();
|
$tpl = $this->mustache->loadTemplate('{{#foo}}{{name}}{{/foo}}');
|
||||||
$this->assertEquals('Foo', $beta->render('{{#foo}}{{name}}{{/foo}}'));
|
$this->assertEquals('Foo', $tpl->render(new Beta));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group magic_methods
|
||||||
|
*/
|
||||||
public function testSectionObjectWithGet() {
|
public function testSectionObjectWithGet() {
|
||||||
$gamma = new Gamma();
|
$tpl = $this->mustache->loadTemplate('{{#bar}}{{#foo}}{{name}}{{/foo}}{{/bar}}');
|
||||||
$this->assertEquals('Foo', $gamma->render('{{#bar}}{{#foo}}{{name}}{{/foo}}{{/bar}}'));
|
$this->assertEquals('Foo', $tpl->render(new Gamma));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSectionObjectWithFunction() {
|
public function testSectionObjectWithFunction() {
|
||||||
$alpha = new Alpha();
|
$tpl = $this->mustache->loadTemplate('{{#foo}}{{name}}{{/foo}}');
|
||||||
$alpha->foo = new Delta();
|
$alpha = new Alpha;
|
||||||
$this->assertEquals('Foo', $alpha->render('{{#foo}}{{name}}{{/foo}}'));
|
$alpha->foo = new Delta;
|
||||||
|
$this->assertEquals('Foo', $tpl->render($alpha));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Alpha extends Mustache {
|
class Alpha {
|
||||||
public $foo;
|
public $foo;
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$this->foo = new StdClass();
|
$this->foo = new \StdClass();
|
||||||
$this->foo->name = 'Foo';
|
$this->foo->name = 'Foo';
|
||||||
$this->foo->number = 1;
|
$this->foo->number = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Beta extends Mustache {
|
class Beta {
|
||||||
protected $_data = array();
|
protected $_data = array();
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$this->_data['foo'] = new StdClass();
|
$this->_data['foo'] = new \StdClass();
|
||||||
$this->_data['foo']->name = 'Foo';
|
$this->_data['foo']->name = 'Foo';
|
||||||
$this->_data['foo']->number = 1;
|
$this->_data['foo']->number = 1;
|
||||||
}
|
}
|
||||||
@@ -56,7 +72,7 @@ class Beta extends Mustache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Gamma extends Mustache {
|
class Gamma {
|
||||||
public $bar;
|
public $bar;
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
@@ -64,7 +80,7 @@ class Gamma extends Mustache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Delta extends Mustache {
|
class Delta {
|
||||||
protected $_name = 'Foo';
|
protected $_name = 'Foo';
|
||||||
|
|
||||||
public function name() {
|
public function name() {
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Mustache\Test\Loader;
|
||||||
|
|
||||||
|
use Mustache\Loader\ArrayLoader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group unit
|
||||||
|
*/
|
||||||
|
class ArrayLoaderTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
public function testConstructor() {
|
||||||
|
$loader = new ArrayLoader(array(
|
||||||
|
'foo' => 'bar'
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->assertEquals('bar', $loader->load('foo'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSetAndLoadTemplates() {
|
||||||
|
$loader = new ArrayLoader(array(
|
||||||
|
'foo' => 'bar'
|
||||||
|
));
|
||||||
|
$this->assertEquals('bar', $loader->load('foo'));
|
||||||
|
|
||||||
|
$loader->setTemplate('baz', 'qux');
|
||||||
|
$this->assertEquals('qux', $loader->load('baz'));
|
||||||
|
|
||||||
|
$loader->setTemplates(array(
|
||||||
|
'foo' => 'FOO',
|
||||||
|
'baz' => 'BAZ',
|
||||||
|
));
|
||||||
|
$this->assertEquals('FOO', $loader->load('foo'));
|
||||||
|
$this->assertEquals('BAZ', $loader->load('baz'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function testMissingTemplatesThrowExceptions() {
|
||||||
|
$loader = new ArrayLoader;
|
||||||
|
$loader->load('not_a_real_template');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,60 +1,41 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
require_once '../Mustache.php';
|
namespace Mustache\Test\Loader;
|
||||||
require_once '../MustacheLoader.php';
|
|
||||||
|
use Mustache\Loader\FilesystemLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @group loader
|
* @group unit
|
||||||
*/
|
*/
|
||||||
class MustacheLoaderTest extends PHPUnit_Framework_TestCase {
|
class FilesystemLoaderTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
public function testConstructor() {
|
||||||
public function testTheActualFilesystemLoader() {
|
$baseDir = realpath(__DIR__.'/../../../fixtures/templates');
|
||||||
$loader = new MustacheLoader(dirname(__FILE__).'/fixtures');
|
$loader = new FilesystemLoader($baseDir, array('extension' => '.ms'));
|
||||||
$this->assertEquals(file_get_contents(dirname(__FILE__).'/fixtures/foo.mustache'), $loader['foo']);
|
$this->assertEquals('alpha contents', $loader->load('alpha'));
|
||||||
$this->assertEquals(file_get_contents(dirname(__FILE__).'/fixtures/bar.mustache'), $loader['bar']);
|
$this->assertEquals('beta contents', $loader->load('beta.ms'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMustacheUsesFilesystemLoader() {
|
public function testLoadTemplates() {
|
||||||
$template = '{{> foo }} {{> bar }}';
|
$baseDir = realpath(__DIR__.'/../../../fixtures/templates');
|
||||||
$data = array(
|
$loader = new FilesystemLoader($baseDir);
|
||||||
'truthy' => true,
|
$this->assertEquals('one contents', $loader->load('one'));
|
||||||
'foo' => 'FOO',
|
$this->assertEquals('two contents', $loader->load('two.mustache'));
|
||||||
'bar' => 'BAR',
|
|
||||||
);
|
|
||||||
$output = 'FOO BAR';
|
|
||||||
$m = new Mustache();
|
|
||||||
$partials = new MustacheLoader(dirname(__FILE__).'/fixtures');
|
|
||||||
$this->assertEquals($output, $m->render($template, $data, $partials));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMustacheUsesDifferentLoadersToo() {
|
/**
|
||||||
$template = '{{> foo }} {{> bar }}';
|
* @expectedException \RuntimeException
|
||||||
$data = array(
|
*/
|
||||||
'truthy' => true,
|
public function testMissingBaseDirThrowsException() {
|
||||||
'foo' => 'FOO',
|
$loader = new FilesystemLoader(__DIR__.'/not_a_directory');
|
||||||
'bar' => 'BAR',
|
}
|
||||||
);
|
|
||||||
$output = 'FOO BAR';
|
/**
|
||||||
$m = new Mustache();
|
* @expectedException \InvalidArgumentException
|
||||||
$partials = new DifferentMustacheLoader();
|
*/
|
||||||
$this->assertEquals($output, $m->render($template, $data, $partials));
|
public function testMissingTemplateThrowsException() {
|
||||||
|
$baseDir = realpath(__DIR__.'/../../../fixtures/templates');
|
||||||
|
$loader = new FilesystemLoader($baseDir);
|
||||||
|
|
||||||
|
$loader->load('fake');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DifferentMustacheLoader implements ArrayAccess {
|
|
||||||
protected $partials = array(
|
|
||||||
'foo' => '{{ foo }}',
|
|
||||||
'bar' => '{{# truthy }}{{ bar }}{{/ truthy }}',
|
|
||||||
);
|
|
||||||
|
|
||||||
public function offsetExists($offset) {
|
|
||||||
return isset($this->partials[$offset]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function offsetGet($offset) {
|
|
||||||
return $this->partials[$offset];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function offsetSet($offset, $value) {}
|
|
||||||
public function offsetUnset($offset) {}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Mustache\Test\Loader;
|
||||||
|
|
||||||
|
use Mustache\Loader\StringLoader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group unit
|
||||||
|
*/
|
||||||
|
class StringLoaderTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
public function testLoadTemplates() {
|
||||||
|
$loader = new StringLoader;
|
||||||
|
|
||||||
|
$this->assertEquals('foo', $loader->load('foo'));
|
||||||
|
$this->assertEquals('{{ bar }}', $loader->load('{{ bar }}'));
|
||||||
|
$this->assertEquals("\n{{! comment }}\n", $loader->load("\n{{! comment }}\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
+116
-433
@@ -1,464 +1,147 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
require_once '../Mustache.php';
|
namespace Mustache\Test;
|
||||||
|
|
||||||
|
use Mustache\Compiler;
|
||||||
|
use Mustache\Mustache;
|
||||||
|
use Mustache\Loader\StringLoader;
|
||||||
|
use Mustache\Loader\ArrayLoader;
|
||||||
|
use Mustache\Parser;
|
||||||
|
use Mustache\Tokenizer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A PHPUnit test case for Mustache.php.
|
* @group unit
|
||||||
*
|
|
||||||
* This is a very basic, very rudimentary unit test case. It's probably more important to have tests
|
|
||||||
* than to have elegant tests, so let's bear with it for a bit.
|
|
||||||
*
|
|
||||||
* This class assumes an example directory exists at `../examples` with the following structure:
|
|
||||||
*
|
|
||||||
* @code
|
|
||||||
* examples
|
|
||||||
* foo
|
|
||||||
* Foo.php
|
|
||||||
* foo.mustache
|
|
||||||
* foo.txt
|
|
||||||
* bar
|
|
||||||
* Bar.php
|
|
||||||
* bar.mustache
|
|
||||||
* bar.txt
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* To use this test:
|
|
||||||
*
|
|
||||||
* 1. {@link http://www.phpunit.de/manual/current/en/installation.html Install PHPUnit}
|
|
||||||
* 2. run phpunit from the `test` directory:
|
|
||||||
* `phpunit MustacheTest`
|
|
||||||
* 3. Fix bugs. Lather, rinse, repeat.
|
|
||||||
*
|
|
||||||
* @extends PHPUnit_Framework_TestCase
|
|
||||||
*/
|
*/
|
||||||
class MustacheTest extends PHPUnit_Framework_TestCase {
|
class MustacheTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
|
||||||
const TEST_CLASS = 'Mustache';
|
private static $tempDir;
|
||||||
|
|
||||||
protected $knownIssues = array(
|
public static function setUpBeforeClass() {
|
||||||
// Just the whitespace ones...
|
self::$tempDir = sys_get_temp_dir() . '/mustache_test';
|
||||||
);
|
if (file_exists(self::$tempDir)) {
|
||||||
|
self::rmdir(self::$tempDir);
|
||||||
/**
|
}
|
||||||
* Test Mustache constructor.
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function test__construct() {
|
|
||||||
$template = '{{#mustaches}}{{#last}}and {{/last}}{{type}}{{^last}}, {{/last}}{{/mustaches}}';
|
|
||||||
$data = array(
|
|
||||||
'mustaches' => array(
|
|
||||||
array('type' => 'Natural'),
|
|
||||||
array('type' => 'Hungarian'),
|
|
||||||
array('type' => 'Dali'),
|
|
||||||
array('type' => 'English'),
|
|
||||||
array('type' => 'Imperial'),
|
|
||||||
array('type' => 'Freestyle', 'last' => 'true'),
|
|
||||||
)
|
|
||||||
);
|
|
||||||
$output = 'Natural, Hungarian, Dali, English, Imperial, and Freestyle';
|
|
||||||
|
|
||||||
$m1 = new Mustache();
|
|
||||||
$this->assertEquals($output, $m1->render($template, $data));
|
|
||||||
|
|
||||||
$m2 = new Mustache($template);
|
|
||||||
$this->assertEquals($output, $m2->render(null, $data));
|
|
||||||
|
|
||||||
$m3 = new Mustache($template, $data);
|
|
||||||
$this->assertEquals($output, $m3->render());
|
|
||||||
|
|
||||||
$m4 = new Mustache(null, $data);
|
|
||||||
$this->assertEquals($output, $m4->render($template));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private static function rmdir($path) {
|
||||||
* @dataProvider constructorOptions
|
$path = rtrim($path, '/').'/';
|
||||||
*/
|
$handle = opendir($path);
|
||||||
public function testConstructorOptions($options, $charset, $delimiters, $pragmas) {
|
while (($file = readdir($handle)) !== false) {
|
||||||
$mustache = new MustacheExposedOptionsStub(null, null, null, $options);
|
if ($file == '.' || $file == '..') {
|
||||||
$this->assertEquals($charset, $mustache->getCharset());
|
continue;
|
||||||
$this->assertEquals($delimiters, $mustache->getDelimiters());
|
|
||||||
$this->assertEquals($pragmas, $mustache->getPragmas());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function constructorOptions() {
|
$fullpath = $path.$file;
|
||||||
return array(
|
if (is_dir($fullpath)) {
|
||||||
array(
|
self::rmdir($fullpath);
|
||||||
array(),
|
} else {
|
||||||
'UTF-8',
|
unlink($fullpath);
|
||||||
array('{{', '}}'),
|
}
|
||||||
array(),
|
}
|
||||||
|
|
||||||
|
closedir($handle);
|
||||||
|
rmdir($path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testConstructor() {
|
||||||
|
$loader = new StringLoader;
|
||||||
|
$partialsLoader = new ArrayLoader;
|
||||||
|
$mustache = new Mustache(array(
|
||||||
|
'template_class_prefix' => '__whot__',
|
||||||
|
'cache' => self::$tempDir,
|
||||||
|
'loader' => $loader,
|
||||||
|
'partials_loader' => $partialsLoader,
|
||||||
|
'partials' => array(
|
||||||
|
'foo' => '{{ foo }}',
|
||||||
),
|
),
|
||||||
array(
|
'charset' => 'ISO-8859-1',
|
||||||
array(
|
));
|
||||||
'charset' => 'UTF-8',
|
|
||||||
'delimiters' => '<< >>',
|
$this->assertSame($loader, $mustache->getLoader());
|
||||||
'pragmas' => array(Mustache::PRAGMA_UNESCAPED => true)
|
$this->assertSame($partialsLoader, $mustache->getPartialsLoader());
|
||||||
),
|
$this->assertEquals('{{ foo }}', $partialsLoader->load('foo'));
|
||||||
'UTF-8',
|
$this->assertContains('__whot__', $mustache->getTemplateClassName('{{ foo }}'));
|
||||||
array('<<', '>>'),
|
$this->assertEquals('ISO-8859-1', $mustache->getCharset());
|
||||||
array(Mustache::PRAGMA_UNESCAPED => true),
|
}
|
||||||
),
|
|
||||||
array(
|
public function testSettingServices() {
|
||||||
array(
|
$loader = new StringLoader;
|
||||||
'charset' => 'cp866',
|
$tokenizer = new Tokenizer;
|
||||||
'delimiters' => array('[[[[', ']]]]'),
|
$parser = new Parser;
|
||||||
'pragmas' => array(Mustache::PRAGMA_UNESCAPED => true)
|
$compiler = new Compiler;
|
||||||
),
|
$mustache = new Mustache;
|
||||||
'cp866',
|
|
||||||
array('[[[[', ']]]]'),
|
$this->assertNotSame($loader, $mustache->getLoader());
|
||||||
array(Mustache::PRAGMA_UNESCAPED => true),
|
$mustache->setLoader($loader);
|
||||||
),
|
$this->assertSame($loader, $mustache->getLoader());
|
||||||
);
|
|
||||||
|
$this->assertNotSame($loader, $mustache->getPartialsLoader());
|
||||||
|
$mustache->setPartialsLoader($loader);
|
||||||
|
$this->assertSame($loader, $mustache->getPartialsLoader());
|
||||||
|
|
||||||
|
$this->assertNotSame($tokenizer, $mustache->getTokenizer());
|
||||||
|
$mustache->setTokenizer($tokenizer);
|
||||||
|
$this->assertSame($tokenizer, $mustache->getTokenizer());
|
||||||
|
|
||||||
|
$this->assertNotSame($parser, $mustache->getParser());
|
||||||
|
$mustache->setParser($parser);
|
||||||
|
$this->assertSame($parser, $mustache->getParser());
|
||||||
|
|
||||||
|
$this->assertNotSame($compiler, $mustache->getCompiler());
|
||||||
|
$mustache->setCompiler($compiler);
|
||||||
|
$this->assertSame($compiler, $mustache->getCompiler());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @expectedException MustacheException
|
* @group functional
|
||||||
*/
|
*/
|
||||||
public function testConstructorInvalidPragmaOptionsThrowExceptions() {
|
public function testCache() {
|
||||||
$mustache = new Mustache(null, null, null, array('pragmas' => array('banana phone' => true)));
|
$mustache = new Mustache(array(
|
||||||
|
'template_class_prefix' => '__whot__',
|
||||||
|
'cache' => self::$tempDir,
|
||||||
|
));
|
||||||
|
|
||||||
|
$source = '{{ foo }}';
|
||||||
|
$template = $mustache->loadTemplate($source);
|
||||||
|
$className = $mustache->getTemplateClassName($source);
|
||||||
|
$fileName = self::$tempDir . '/' . $className . '.php';
|
||||||
|
$this->assertInstanceOf($className, $template);
|
||||||
|
$this->assertFileExists($fileName);
|
||||||
|
$this->assertContains("\nclass $className extends \Mustache\Template", file_get_contents($fileName));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test __toString() function.
|
* @group functional
|
||||||
*
|
* @expectedException \RuntimeException
|
||||||
* @access public
|
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
public function test__toString() {
|
public function testCacheFailsThrowException() {
|
||||||
$m = new Mustache('{{first_name}} {{last_name}}', array('first_name' => 'Karl', 'last_name' => 'Marx'));
|
global $mustacheFilesystemRenameHax;
|
||||||
|
|
||||||
$this->assertEquals('Karl Marx', $m->__toString());
|
$mustacheFilesystemRenameHax = true;
|
||||||
$this->assertEquals('Karl Marx', (string) $m);
|
|
||||||
|
|
||||||
$m2 = $this->getMock(self::TEST_CLASS, array('render'), array());
|
$mustache = new Mustache(array('cache' => self::$tempDir));
|
||||||
$m2->expects($this->once())
|
$mustache->loadTemplate('{{ foo }}');
|
||||||
->method('render')
|
|
||||||
->will($this->returnValue('foo'));
|
|
||||||
|
|
||||||
$this->assertEquals('foo', $m2->render());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test__toStringException() {
|
|
||||||
$m = $this->getMock(self::TEST_CLASS, array('render'), array());
|
|
||||||
$m->expects($this->once())
|
|
||||||
->method('render')
|
|
||||||
->will($this->throwException(new Exception));
|
|
||||||
|
|
||||||
try {
|
|
||||||
$out = (string) $m;
|
|
||||||
} catch (Exception $e) {
|
|
||||||
$this->fail('__toString should catch all exceptions');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test render().
|
* @expectedException \RuntimeException
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
public function testRender() {
|
public function testImmutablePartialsLoadersThrowException() {
|
||||||
$m = new Mustache();
|
$mustache = new Mustache(array(
|
||||||
|
'partials_loader' => new StringLoader,
|
||||||
|
));
|
||||||
|
|
||||||
$this->assertEquals('', $m->render(''));
|
$mustache->setPartials(array('foo' => '{{ foo }}'));
|
||||||
$this->assertEquals('foo', $m->render('foo'));
|
|
||||||
$this->assertEquals('', $m->render(null));
|
|
||||||
|
|
||||||
$m2 = new Mustache('foo');
|
|
||||||
$this->assertEquals('foo', $m2->render());
|
|
||||||
|
|
||||||
$m3 = new Mustache('');
|
|
||||||
$this->assertEquals('', $m3->render());
|
|
||||||
|
|
||||||
$m3 = new Mustache();
|
|
||||||
$this->assertEquals('', $m3->render(null));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test render() with data.
|
|
||||||
*
|
|
||||||
* @group interpolation
|
|
||||||
*/
|
|
||||||
public function testRenderWithData() {
|
|
||||||
$m = new Mustache('{{first_name}} {{last_name}}');
|
|
||||||
$this->assertEquals('Charlie Chaplin', $m->render(null, array('first_name' => 'Charlie', 'last_name' => 'Chaplin')));
|
|
||||||
$this->assertEquals('Zappa, Frank', $m->render('{{last_name}}, {{first_name}}', array('first_name' => 'Frank', 'last_name' => 'Zappa')));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @group partials
|
|
||||||
*/
|
|
||||||
public function testRenderWithPartials() {
|
|
||||||
$m = new Mustache('{{>stache}}', null, array('stache' => '{{first_name}} {{last_name}}'));
|
|
||||||
$this->assertEquals('Charlie Chaplin', $m->render(null, array('first_name' => 'Charlie', 'last_name' => 'Chaplin')));
|
|
||||||
$this->assertEquals('Zappa, Frank', $m->render('{{last_name}}, {{first_name}}', array('first_name' => 'Frank', 'last_name' => 'Zappa')));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @group interpolation
|
|
||||||
* @dataProvider interpolationData
|
|
||||||
*/
|
|
||||||
public function testDoubleRenderMustacheTags($template, $context, $expected) {
|
|
||||||
$m = new Mustache($template, $context);
|
|
||||||
$this->assertEquals($expected, $m->render());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function interpolationData() {
|
|
||||||
return array(
|
|
||||||
array(
|
|
||||||
'{{#a}}{{=<% %>=}}{{b}} c<%={{ }}=%>{{/a}}',
|
|
||||||
array('a' => array(array('b' => 'Do Not Render'))),
|
|
||||||
'{{b}} c'
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
'{{#a}}{{b}}{{/a}}',
|
|
||||||
array('a' => array('b' => '{{c}}'), 'c' => 'FAIL'),
|
|
||||||
'{{c}}'
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mustache should allow newlines (and other whitespace) in comments and all other tags.
|
|
||||||
*
|
|
||||||
* @group comments
|
|
||||||
*/
|
|
||||||
public function testNewlinesInComments() {
|
|
||||||
$m = new Mustache("{{! comment \n \t still a comment... }}");
|
|
||||||
$this->assertEquals('', $m->render());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mustache should return the same thing when invoked multiple times.
|
|
||||||
*/
|
|
||||||
public function testMultipleInvocations() {
|
|
||||||
$m = new Mustache('x');
|
|
||||||
$first = $m->render();
|
|
||||||
$second = $m->render();
|
|
||||||
|
|
||||||
$this->assertEquals('x', $first);
|
|
||||||
$this->assertEquals($first, $second);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mustache should return the same thing when invoked multiple times.
|
|
||||||
*
|
|
||||||
* @group interpolation
|
|
||||||
*/
|
|
||||||
public function testMultipleInvocationsWithTags() {
|
|
||||||
$m = new Mustache('{{one}} {{two}}', array('one' => 'foo', 'two' => 'bar'));
|
|
||||||
$first = $m->render();
|
|
||||||
$second = $m->render();
|
|
||||||
|
|
||||||
$this->assertEquals('foo bar', $first);
|
|
||||||
$this->assertEquals($first, $second);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mustache should not use templates passed to the render() method for subsequent invocations.
|
|
||||||
*/
|
|
||||||
public function testResetTemplateForMultipleInvocations() {
|
|
||||||
$m = new Mustache('Sirve.');
|
|
||||||
$this->assertEquals('No sirve.', $m->render('No sirve.'));
|
|
||||||
$this->assertEquals('Sirve.', $m->render());
|
|
||||||
|
|
||||||
$m2 = new Mustache();
|
|
||||||
$this->assertEquals('No sirve.', $m2->render('No sirve.'));
|
|
||||||
$this->assertEquals('', $m2->render());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test the __clone() magic function.
|
|
||||||
*
|
|
||||||
* @group examples
|
|
||||||
* @dataProvider getExamples
|
|
||||||
*
|
|
||||||
* @param string $class
|
|
||||||
* @param string $template
|
|
||||||
* @param string $output
|
|
||||||
*/
|
|
||||||
public function test__clone($class, $template, $output) {
|
|
||||||
if (isset($this->knownIssues[$class])) {
|
|
||||||
return $this->markTestSkipped($this->knownIssues[$class]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$m = new $class;
|
|
||||||
$n = clone $m;
|
|
||||||
|
|
||||||
$n_output = $n->render($template);
|
|
||||||
|
|
||||||
$o = clone $n;
|
|
||||||
|
|
||||||
$this->assertEquals($m->render($template), $n_output);
|
|
||||||
$this->assertEquals($n_output, $o->render($template));
|
|
||||||
|
|
||||||
$this->assertNotSame($m, $n);
|
|
||||||
$this->assertNotSame($n, $o);
|
|
||||||
$this->assertNotSame($m, $o);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test everything in the `examples` directory.
|
|
||||||
*
|
|
||||||
* @group examples
|
|
||||||
* @dataProvider getExamples
|
|
||||||
*
|
|
||||||
* @param string $class
|
|
||||||
* @param string $template
|
|
||||||
* @param string $output
|
|
||||||
*/
|
|
||||||
public function testExamples($class, $template, $output) {
|
|
||||||
if (isset($this->knownIssues[$class])) {
|
|
||||||
return $this->markTestSkipped($this->knownIssues[$class]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$m = new $class;
|
|
||||||
$this->assertEquals($output, $m->render($template));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Data provider for testExamples method.
|
|
||||||
*
|
|
||||||
* Assumes that an `examples` directory exists inside parent directory.
|
|
||||||
* This examples directory should contain any number of subdirectories, each of which contains
|
|
||||||
* three files: one Mustache class (.php), one Mustache template (.mustache), and one output file
|
|
||||||
* (.txt).
|
|
||||||
*
|
|
||||||
* This whole mess will be refined later to be more intuitive and less prescriptive, but it'll
|
|
||||||
* do for now. Especially since it means we can have unit tests :)
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function getExamples() {
|
|
||||||
$basedir = dirname(__FILE__) . '/../examples/';
|
|
||||||
|
|
||||||
$ret = array();
|
|
||||||
|
|
||||||
$files = new RecursiveDirectoryIterator($basedir);
|
|
||||||
while ($files->valid()) {
|
|
||||||
|
|
||||||
if ($files->hasChildren() && $children = $files->getChildren()) {
|
|
||||||
$example = $files->getSubPathname();
|
|
||||||
$class = null;
|
|
||||||
$template = null;
|
|
||||||
$output = null;
|
|
||||||
|
|
||||||
foreach ($children as $file) {
|
|
||||||
if (!$file->isFile()) continue;
|
|
||||||
|
|
||||||
$filename = $file->getPathname();
|
|
||||||
$info = pathinfo($filename);
|
|
||||||
|
|
||||||
if (isset($info['extension'])) {
|
|
||||||
switch($info['extension']) {
|
|
||||||
case 'php':
|
|
||||||
$class = $info['filename'];
|
|
||||||
include_once($filename);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'mustache':
|
|
||||||
$template = file_get_contents($filename);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'txt':
|
|
||||||
$output = file_get_contents($filename);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($class)) {
|
|
||||||
$ret[$example] = array($class, $template, $output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$files->next();
|
|
||||||
}
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @group delimiters
|
|
||||||
*/
|
|
||||||
public function testCrazyDelimiters() {
|
|
||||||
$m = new Mustache(null, array('result' => 'success'));
|
|
||||||
$this->assertEquals('success', $m->render('{{=[[ ]]=}}[[ result ]]'));
|
|
||||||
$this->assertEquals('success', $m->render('{{=(( ))=}}(( result ))'));
|
|
||||||
$this->assertEquals('success', $m->render('{{={$ $}=}}{$ result $}'));
|
|
||||||
$this->assertEquals('success', $m->render('{{=<.. ..>=}}<.. result ..>'));
|
|
||||||
$this->assertEquals('success', $m->render('{{=^^ ^^}}^^ result ^^'));
|
|
||||||
$this->assertEquals('success', $m->render('{{=// \\\\}}// result \\\\'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @group delimiters
|
|
||||||
*/
|
|
||||||
public function testResetDelimiters() {
|
|
||||||
$m = new Mustache(null, array('result' => 'success'));
|
|
||||||
$this->assertEquals('success', $m->render('{{=[[ ]]=}}[[ result ]]'));
|
|
||||||
$this->assertEquals('success', $m->render('{{=<< >>=}}<< result >>'));
|
|
||||||
$this->assertEquals('success', $m->render('{{=<% %>=}}<% result %>'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @group delimiters
|
|
||||||
*/
|
|
||||||
public function testStickyDelimiters() {
|
|
||||||
$m = new Mustache(null, array('result' => 'FAIL'));
|
|
||||||
$this->assertEquals('{{ result }}', $m->render('{{=[[ ]]=}}{{ result }}[[={{ }}=]]'));
|
|
||||||
$this->assertEquals('{{#result}}{{/result}}', $m->render('{{=[[ ]]=}}{{#result}}{{/result}}[[={{ }}=]]'));
|
|
||||||
$this->assertEquals('{{ result }}', $m->render('{{=[[ ]]=}}[[#result]]{{ result }}[[/result]][[={{ }}=]]'));
|
|
||||||
$this->assertEquals('{{ result }}', $m->render('{{#result}}{{=[[ ]]=}}{{ result }}[[/result]][[^result]][[={{ }}=]][[ result ]]{{/result}}'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @group sections
|
|
||||||
* @dataProvider poorlyNestedSections
|
|
||||||
* @expectedException MustacheException
|
|
||||||
*/
|
|
||||||
public function testPoorlyNestedSections($template) {
|
|
||||||
$m = new Mustache($template);
|
|
||||||
$m->render();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function poorlyNestedSections() {
|
|
||||||
return array(
|
|
||||||
array('{{#foo}}'),
|
|
||||||
array('{{#foo}}{{/bar}}'),
|
|
||||||
array('{{#foo}}{{#bar}}{{/foo}}'),
|
|
||||||
array('{{#foo}}{{#bar}}{{/foo}}{{/bar}}'),
|
|
||||||
array('{{#foo}}{{/bar}}{{/foo}}'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensure that Mustache doesn't double-render sections (allowing mustache injection).
|
|
||||||
*
|
|
||||||
* @group sections
|
|
||||||
*/
|
|
||||||
public function testMustacheInjection() {
|
|
||||||
$template = '{{#foo}}{{bar}}{{/foo}}';
|
|
||||||
$view = array(
|
|
||||||
'foo' => true,
|
|
||||||
'bar' => '{{win}}',
|
|
||||||
'win' => 'FAIL',
|
|
||||||
);
|
|
||||||
|
|
||||||
$m = new Mustache($template, $view);
|
|
||||||
$this->assertEquals('{{win}}', $m->render());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MustacheExposedOptionsStub extends Mustache {
|
|
||||||
public function getPragmas() {
|
// It's prob'ly best if you ignore this bit.
|
||||||
return $this->_pragmas;
|
|
||||||
}
|
namespace Mustache;
|
||||||
public function getCharset() {
|
|
||||||
return $this->_charset;
|
function rename($a, $b) {
|
||||||
}
|
global $mustacheFilesystemRenameHax;
|
||||||
public function getDelimiters() {
|
|
||||||
return array($this->_otag, $this->_ctag);
|
return ($mustacheFilesystemRenameHax) ? false : \rename($a, $b);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,157 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Mustache\Test;
|
||||||
|
|
||||||
|
use Mustache\Parser;
|
||||||
|
use Mustache\Tokenizer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group unit
|
||||||
|
*/
|
||||||
|
class ParserTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider getTokenSets
|
||||||
|
*/
|
||||||
|
public function testParse($tokens, $expected)
|
||||||
|
{
|
||||||
|
$parser = new Parser;
|
||||||
|
$this->assertEquals($expected, $parser->parse($tokens));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTokenSets()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array(
|
||||||
|
array(),
|
||||||
|
array()
|
||||||
|
),
|
||||||
|
|
||||||
|
array(
|
||||||
|
array('text'),
|
||||||
|
array('text')
|
||||||
|
),
|
||||||
|
|
||||||
|
array(
|
||||||
|
array(array(
|
||||||
|
Tokenizer::TAG => '_v',
|
||||||
|
Tokenizer::NAME => 'name'
|
||||||
|
)),
|
||||||
|
array(array(
|
||||||
|
Tokenizer::TAG => '_v',
|
||||||
|
Tokenizer::NAME => 'name'
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
|
||||||
|
array(
|
||||||
|
array(
|
||||||
|
'foo',
|
||||||
|
array(
|
||||||
|
Tokenizer::TAG => '^',
|
||||||
|
Tokenizer::INDEX => 123,
|
||||||
|
Tokenizer::NAME => 'parent'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
Tokenizer::TAG => '_v',
|
||||||
|
Tokenizer::NAME => 'name'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
Tokenizer::TAG => '/',
|
||||||
|
Tokenizer::INDEX => 456,
|
||||||
|
Tokenizer::NAME => 'parent'
|
||||||
|
),
|
||||||
|
'bar',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'foo',
|
||||||
|
array(
|
||||||
|
Tokenizer::TAG => '^',
|
||||||
|
Tokenizer::NAME => 'parent',
|
||||||
|
Tokenizer::INDEX => 123,
|
||||||
|
Tokenizer::END => 456,
|
||||||
|
Tokenizer::NODES => array(
|
||||||
|
array(
|
||||||
|
Tokenizer::TAG => '_v',
|
||||||
|
Tokenizer::NAME => 'name'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'bar',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider getBadParseTrees
|
||||||
|
* @expectedException \LogicException
|
||||||
|
*/
|
||||||
|
public function testParserThrowsExceptions($tokens) {
|
||||||
|
$parser = new Parser;
|
||||||
|
$parser->parse($tokens);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBadParseTrees() {
|
||||||
|
return array(
|
||||||
|
// no close
|
||||||
|
array(
|
||||||
|
array(
|
||||||
|
array(
|
||||||
|
Tokenizer::TAG => '#',
|
||||||
|
Tokenizer::INDEX => 123,
|
||||||
|
Tokenizer::NAME => 'parent'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// no close inverted
|
||||||
|
array(
|
||||||
|
array(
|
||||||
|
array(
|
||||||
|
Tokenizer::TAG => '^',
|
||||||
|
Tokenizer::INDEX => 123,
|
||||||
|
Tokenizer::NAME => 'parent'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// no opening inverted
|
||||||
|
array(
|
||||||
|
array(
|
||||||
|
array(
|
||||||
|
Tokenizer::TAG => '/',
|
||||||
|
Tokenizer::INDEX => 123,
|
||||||
|
Tokenizer::NAME => 'parent'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// weird nesting
|
||||||
|
array(
|
||||||
|
array(
|
||||||
|
array(
|
||||||
|
Tokenizer::TAG => '#',
|
||||||
|
Tokenizer::INDEX => 123,
|
||||||
|
Tokenizer::NAME => 'parent'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
Tokenizer::TAG => '#',
|
||||||
|
Tokenizer::INDEX => 123,
|
||||||
|
Tokenizer::NAME => 'child'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
Tokenizer::TAG => '/',
|
||||||
|
Tokenizer::INDEX => 123,
|
||||||
|
Tokenizer::NAME => 'parent'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
Tokenizer::TAG => '/',
|
||||||
|
Tokenizer::INDEX => 123,
|
||||||
|
Tokenizer::NAME => 'child'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Mustache\Test;
|
||||||
|
|
||||||
|
use Mustache\Context;
|
||||||
|
use Mustache\Mustache;
|
||||||
|
use Mustache\Template;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group unit
|
||||||
|
*/
|
||||||
|
class TemplateTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
public function testConstructor() {
|
||||||
|
$mustache = new Mustache;
|
||||||
|
$template = new TemplateStub($mustache);
|
||||||
|
$this->assertSame($mustache, $template->getMustache());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRendering() {
|
||||||
|
$rendered = '<< wheee >>';
|
||||||
|
$mustache = new Mustache;
|
||||||
|
$template = new TemplateStub($mustache);
|
||||||
|
$template->rendered = $rendered;
|
||||||
|
$context = new Context;
|
||||||
|
|
||||||
|
$this->assertEquals($rendered, $template());
|
||||||
|
$this->assertEquals($rendered, $template->render());
|
||||||
|
$this->assertEquals($rendered, $template->renderInternal($context));
|
||||||
|
$this->assertEquals($rendered, $template->render(array('foo' => 'bar')));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TemplateStub extends Template {
|
||||||
|
public $rendered;
|
||||||
|
|
||||||
|
public function getMustache() {
|
||||||
|
return $this->mustache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function renderInternal(Context $context) {
|
||||||
|
return $this->rendered;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Mustache\Test;
|
||||||
|
|
||||||
|
use Mustache\Tokenizer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group unit
|
||||||
|
*/
|
||||||
|
class TokenizerTest extends \PHPUnit_Framework_TestCase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider getTokens
|
||||||
|
*/
|
||||||
|
public function testScan($text, $delimiters, $expected) {
|
||||||
|
$tokenizer = new Tokenizer;
|
||||||
|
$this->assertSame($expected, $tokenizer->scan($text, $delimiters));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTokens() {
|
||||||
|
return array(
|
||||||
|
array(
|
||||||
|
'text',
|
||||||
|
null,
|
||||||
|
array('text'),
|
||||||
|
),
|
||||||
|
|
||||||
|
array(
|
||||||
|
'text',
|
||||||
|
'<<< >>>',
|
||||||
|
array('text'),
|
||||||
|
),
|
||||||
|
|
||||||
|
array(
|
||||||
|
'{{ name }}',
|
||||||
|
null,
|
||||||
|
array(
|
||||||
|
array(
|
||||||
|
Tokenizer::TAG => '_v',
|
||||||
|
Tokenizer::NAME => 'name',
|
||||||
|
Tokenizer::OTAG => '{{',
|
||||||
|
Tokenizer::CTAG => '}}',
|
||||||
|
Tokenizer::INDEX => 10,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
|
||||||
|
array(
|
||||||
|
'{{ name }}',
|
||||||
|
'<<< >>>',
|
||||||
|
array('{{ name }}'),
|
||||||
|
),
|
||||||
|
|
||||||
|
array(
|
||||||
|
'<<< name >>>',
|
||||||
|
'<<< >>>',
|
||||||
|
array(
|
||||||
|
array(
|
||||||
|
Tokenizer::TAG => '_v',
|
||||||
|
Tokenizer::NAME => 'name',
|
||||||
|
Tokenizer::OTAG => '<<<',
|
||||||
|
Tokenizer::CTAG => '>>>',
|
||||||
|
Tokenizer::INDEX => 12,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
|
||||||
|
array(
|
||||||
|
"{{{ a }}}\n{{# b }} \n{{= | | =}}| c ||/ b |\n|{ d }|",
|
||||||
|
null,
|
||||||
|
array(
|
||||||
|
array(
|
||||||
|
Tokenizer::TAG => '{',
|
||||||
|
Tokenizer::NAME => 'a',
|
||||||
|
Tokenizer::OTAG => '{{',
|
||||||
|
Tokenizer::CTAG => '}}',
|
||||||
|
Tokenizer::INDEX => 8,
|
||||||
|
),
|
||||||
|
"\n",
|
||||||
|
array(
|
||||||
|
Tokenizer::TAG => '#',
|
||||||
|
Tokenizer::NAME => 'b',
|
||||||
|
Tokenizer::OTAG => '{{',
|
||||||
|
Tokenizer::CTAG => '}}',
|
||||||
|
Tokenizer::INDEX => 18,
|
||||||
|
),
|
||||||
|
null,
|
||||||
|
array(
|
||||||
|
Tokenizer::TAG => '_v',
|
||||||
|
Tokenizer::NAME => 'c',
|
||||||
|
Tokenizer::OTAG => '|',
|
||||||
|
Tokenizer::CTAG => '|',
|
||||||
|
Tokenizer::INDEX => 37,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
Tokenizer::TAG => '/',
|
||||||
|
Tokenizer::NAME => 'b',
|
||||||
|
Tokenizer::OTAG => '|',
|
||||||
|
Tokenizer::CTAG => '|',
|
||||||
|
Tokenizer::INDEX => 37,
|
||||||
|
),
|
||||||
|
"\n",
|
||||||
|
array(
|
||||||
|
Tokenizer::TAG => '{',
|
||||||
|
Tokenizer::NAME => 'd',
|
||||||
|
Tokenizer::OTAG => '|',
|
||||||
|
Tokenizer::CTAG => '|',
|
||||||
|
Tokenizer::INDEX => 51,
|
||||||
|
),
|
||||||
|
|
||||||
|
)
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user