Rearrange codebase to prep for 2.0 development.
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
require_once '../Mustache.php';
|
||||
|
||||
class MustacheCallTest extends PHPUnit_Framework_TestCase {
|
||||
|
||||
public function testCallEatsContext() {
|
||||
$foo = new ClassWithCall();
|
||||
$foo->name = 'Bob';
|
||||
|
||||
$template = '{{# foo }}{{ label }}: {{ name }}{{/ foo }}';
|
||||
$data = array('label' => 'name', 'foo' => $foo);
|
||||
$m = new Mustache($template, $data);
|
||||
|
||||
$this->assertEquals('name: Bob', $m->render());
|
||||
}
|
||||
}
|
||||
|
||||
class ClassWithCall {
|
||||
public $name;
|
||||
public function __call($method, $args) {
|
||||
return 'unknown value';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
require_once '../Mustache.php';
|
||||
|
||||
class MustacheExceptionTest extends PHPUnit_Framework_TestCase {
|
||||
|
||||
const TEST_CLASS = 'Mustache';
|
||||
|
||||
protected $pickyMustache;
|
||||
protected $slackerMustache;
|
||||
|
||||
public function setUp() {
|
||||
$this->pickyMustache = new PickyMustache();
|
||||
$this->slackerMustache = new SlackerMustache();
|
||||
}
|
||||
|
||||
/**
|
||||
* @group interpolation
|
||||
* @expectedException MustacheException
|
||||
*/
|
||||
public function testThrowsUnknownVariableException() {
|
||||
$this->pickyMustache->render('{{not_a_variable}}');
|
||||
}
|
||||
|
||||
/**
|
||||
* @group sections
|
||||
* @expectedException MustacheException
|
||||
*/
|
||||
public function testThrowsUnclosedSectionException() {
|
||||
$this->pickyMustache->render('{{#unclosed}}');
|
||||
}
|
||||
|
||||
/**
|
||||
* @group sections
|
||||
* @expectedException MustacheException
|
||||
*/
|
||||
public function testThrowsUnclosedInvertedSectionException() {
|
||||
$this->pickyMustache->render('{{^unclosed}}');
|
||||
}
|
||||
|
||||
/**
|
||||
* @group sections
|
||||
* @expectedException MustacheException
|
||||
*/
|
||||
public function testThrowsUnexpectedCloseSectionException() {
|
||||
$this->pickyMustache->render('{{/unopened}}');
|
||||
}
|
||||
|
||||
/**
|
||||
* @group partials
|
||||
* @expectedException MustacheException
|
||||
*/
|
||||
public function testThrowsUnknownPartialException() {
|
||||
$this->pickyMustache->render('{{>impartial}}');
|
||||
}
|
||||
|
||||
/**
|
||||
* @group pragmas
|
||||
* @expectedException MustacheException
|
||||
*/
|
||||
public function testThrowsUnknownPragmaException() {
|
||||
$this->pickyMustache->render('{{%SWEET-MUSTACHE-BRO}}');
|
||||
}
|
||||
|
||||
/**
|
||||
* @group sections
|
||||
*/
|
||||
public function testDoesntThrowUnclosedSectionException() {
|
||||
$this->assertEquals('', $this->slackerMustache->render('{{#unclosed}}'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group sections
|
||||
*/
|
||||
public function testDoesntThrowUnexpectedCloseSectionException() {
|
||||
$this->assertEquals('', $this->slackerMustache->render('{{/unopened}}'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group partials
|
||||
*/
|
||||
public function testDoesntThrowUnknownPartialException() {
|
||||
$this->assertEquals('', $this->slackerMustache->render('{{>impartial}}'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group pragmas
|
||||
* @expectedException MustacheException
|
||||
*/
|
||||
public function testGetPragmaOptionsThrowsExceptionsIfItThinksYouHaveAPragmaButItTurnsOutYouDont() {
|
||||
$mustache = new TestableMustache();
|
||||
$mustache->testableGetPragmaOptions('PRAGMATIC');
|
||||
}
|
||||
|
||||
public function testOverrideThrownExceptionsViaConstructorOptions() {
|
||||
$exceptions = array(
|
||||
MustacheException::UNKNOWN_VARIABLE,
|
||||
MustacheException::UNCLOSED_SECTION,
|
||||
MustacheException::UNEXPECTED_CLOSE_SECTION,
|
||||
MustacheException::UNKNOWN_PARTIAL,
|
||||
MustacheException::UNKNOWN_PRAGMA,
|
||||
);
|
||||
|
||||
$one = new TestableMustache(null, null, null, array(
|
||||
'throws_exceptions' => array_fill_keys($exceptions, true)
|
||||
));
|
||||
|
||||
$thrownExceptions = $one->getThrownExceptions();
|
||||
foreach ($exceptions as $exception) {
|
||||
$this->assertTrue($thrownExceptions[$exception]);
|
||||
}
|
||||
|
||||
$two = new TestableMustache(null, null, null, array(
|
||||
'throws_exceptions' => array_fill_keys($exceptions, false)
|
||||
));
|
||||
|
||||
$thrownExceptions = $two->getThrownExceptions();
|
||||
foreach ($exceptions as $exception) {
|
||||
$this->assertFalse($thrownExceptions[$exception]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PickyMustache extends Mustache {
|
||||
protected $_throwsExceptions = array(
|
||||
MustacheException::UNKNOWN_VARIABLE => true,
|
||||
MustacheException::UNCLOSED_SECTION => true,
|
||||
MustacheException::UNEXPECTED_CLOSE_SECTION => true,
|
||||
MustacheException::UNKNOWN_PARTIAL => true,
|
||||
MustacheException::UNKNOWN_PRAGMA => true,
|
||||
);
|
||||
}
|
||||
|
||||
class SlackerMustache extends Mustache {
|
||||
protected $_throwsExceptions = array(
|
||||
MustacheException::UNKNOWN_VARIABLE => false,
|
||||
MustacheException::UNCLOSED_SECTION => false,
|
||||
MustacheException::UNEXPECTED_CLOSE_SECTION => false,
|
||||
MustacheException::UNKNOWN_PARTIAL => false,
|
||||
MustacheException::UNKNOWN_PRAGMA => false,
|
||||
);
|
||||
}
|
||||
|
||||
class TestableMustache extends Mustache {
|
||||
public function testableGetPragmaOptions($pragma_name) {
|
||||
return $this->_getPragmaOptions($pragma_name);
|
||||
}
|
||||
|
||||
public function getThrownExceptions() {
|
||||
return $this->_throwsExceptions;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
require_once '../Mustache.php';
|
||||
|
||||
class MustacheHigherOrderSectionsTest extends PHPUnit_Framework_TestCase {
|
||||
|
||||
public function setUp() {
|
||||
$this->foo = new Foo();
|
||||
}
|
||||
|
||||
public function testAnonymousFunctionSectionCallback() {
|
||||
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
|
||||
$this->markTestSkipped('Unable to test anonymous function section callbacks in PHP < 5.3');
|
||||
return;
|
||||
}
|
||||
|
||||
$this->foo->wrapper = function($text) {
|
||||
return sprintf('<div class="anonymous">%s</div>', $text);
|
||||
};
|
||||
|
||||
$this->assertEquals(
|
||||
sprintf('<div class="anonymous">%s</div>', $this->foo->name),
|
||||
$this->foo->render('{{#wrapper}}{{name}}{{/wrapper}}')
|
||||
);
|
||||
}
|
||||
|
||||
public function testSectionCallback() {
|
||||
$this->assertEquals(sprintf('%s', $this->foo->name), $this->foo->render('{{name}}'));
|
||||
$this->assertEquals(sprintf('<em>%s</em>', $this->foo->name), $this->foo->render('{{#wrap}}{{name}}{{/wrap}}'));
|
||||
}
|
||||
|
||||
public function testRuntimeSectionCallback() {
|
||||
$this->foo->double_wrap = array($this->foo, 'wrapWithBoth');
|
||||
$this->assertEquals(
|
||||
sprintf('<strong><em>%s</em></strong>', $this->foo->name),
|
||||
$this->foo->render('{{#double_wrap}}{{name}}{{/double_wrap}}')
|
||||
);
|
||||
}
|
||||
|
||||
public function testStaticSectionCallback() {
|
||||
$this->foo->trimmer = array(get_class($this->foo), 'staticTrim');
|
||||
$this->assertEquals($this->foo->name, $this->foo->render('{{#trimmer}} {{name}} {{/trimmer}}'));
|
||||
}
|
||||
|
||||
public function testViewArraySectionCallback() {
|
||||
$data = array(
|
||||
'name' => 'Bob',
|
||||
'trim' => array(get_class($this->foo), 'staticTrim'),
|
||||
);
|
||||
$this->assertEquals($data['name'], $this->foo->render('{{#trim}} {{name}} {{/trim}}', $data));
|
||||
}
|
||||
|
||||
public function testViewArrayAnonymousSectionCallback() {
|
||||
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
|
||||
$this->markTestSkipped('Unable to test anonymous function section callbacks in PHP < 5.3');
|
||||
return;
|
||||
}
|
||||
$data = array(
|
||||
'name' => 'Bob',
|
||||
'wrap' => function($text) {
|
||||
return sprintf('[[%s]]', $text);
|
||||
}
|
||||
);
|
||||
$this->assertEquals(
|
||||
sprintf('[[%s]]', $data['name']),
|
||||
$this->foo->render('{{#wrap}}{{name}}{{/wrap}}', $data)
|
||||
);
|
||||
}
|
||||
|
||||
public function testMonsters() {
|
||||
$frank = new Monster();
|
||||
$frank->title = 'Dr.';
|
||||
$frank->name = 'Frankenstein';
|
||||
$this->assertEquals('Dr. Frankenstein', $frank->render());
|
||||
|
||||
$dracula = new Monster();
|
||||
$dracula->title = 'Count';
|
||||
$dracula->name = 'Dracula';
|
||||
$this->assertEquals('Count Dracula', $dracula->render());
|
||||
}
|
||||
}
|
||||
|
||||
class Foo extends Mustache {
|
||||
public $name = 'Justin';
|
||||
public $lorem = 'Lorem ipsum dolor sit amet,';
|
||||
public $wrap;
|
||||
|
||||
public function __construct($template = null, $view = null, $partials = null) {
|
||||
$this->wrap = array($this, 'wrapWithEm');
|
||||
parent::__construct($template, $view, $partials);
|
||||
}
|
||||
|
||||
public function wrapWithEm($text) {
|
||||
return sprintf('<em>%s</em>', $text);
|
||||
}
|
||||
|
||||
public function wrapWithStrong($text) {
|
||||
return sprintf('<strong>%s</strong>', $text);
|
||||
}
|
||||
|
||||
public function wrapWithBoth($text) {
|
||||
return self::wrapWithStrong(self::wrapWithEm($text));
|
||||
}
|
||||
|
||||
public static function staticTrim($text) {
|
||||
return trim($text);
|
||||
}
|
||||
}
|
||||
|
||||
class Monster extends Mustache {
|
||||
public $_template = '{{#title}}{{title}} {{/title}}{{name}}';
|
||||
public $title;
|
||||
public $name;
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
require_once '../Mustache.php';
|
||||
|
||||
/**
|
||||
* @group mustache_injection
|
||||
*/
|
||||
class MustacheInjectionSectionTest extends PHPUnit_Framework_TestCase {
|
||||
|
||||
// interpolation
|
||||
|
||||
public function testInterpolationInjection() {
|
||||
$data = array(
|
||||
'a' => '{{ b }}',
|
||||
'b' => 'FAIL'
|
||||
);
|
||||
$template = '{{ a }}';
|
||||
$output = '{{ b }}';
|
||||
$m = new Mustache();
|
||||
$this->assertEquals($output, $m->render($template, $data));
|
||||
}
|
||||
|
||||
public function testUnescapedInterpolationInjection() {
|
||||
$data = array(
|
||||
'a' => '{{ b }}',
|
||||
'b' => 'FAIL'
|
||||
);
|
||||
$template = '{{{ a }}}';
|
||||
$output = '{{ b }}';
|
||||
$m = new Mustache();
|
||||
$this->assertEquals($output, $m->render($template, $data));
|
||||
}
|
||||
|
||||
|
||||
// sections
|
||||
|
||||
public function testSectionInjection() {
|
||||
$data = array(
|
||||
'a' => true,
|
||||
'b' => '{{ c }}',
|
||||
'c' => 'FAIL'
|
||||
);
|
||||
$template = '{{# a }}{{ b }}{{/ a }}';
|
||||
$output = '{{ c }}';
|
||||
$m = new Mustache();
|
||||
$this->assertEquals($output, $m->render($template, $data));
|
||||
}
|
||||
|
||||
public function testUnescapedSectionInjection() {
|
||||
$data = array(
|
||||
'a' => true,
|
||||
'b' => '{{ c }}',
|
||||
'c' => 'FAIL'
|
||||
);
|
||||
$template = '{{# a }}{{{ b }}}{{/ a }}';
|
||||
$output = '{{ c }}';
|
||||
$m = new Mustache();
|
||||
$this->assertEquals($output, $m->render($template, $data));
|
||||
}
|
||||
|
||||
|
||||
// partials
|
||||
|
||||
public function testPartialInjection() {
|
||||
$data = array(
|
||||
'a' => '{{ b }}',
|
||||
'b' => 'FAIL'
|
||||
);
|
||||
$template = '{{> partial }}';
|
||||
$partials = array(
|
||||
'partial' => '{{ a }}',
|
||||
);
|
||||
$output = '{{ b }}';
|
||||
$m = new Mustache();
|
||||
$this->assertEquals($output, $m->render($template, $data, $partials));
|
||||
}
|
||||
|
||||
public function testPartialUnescapedInjection() {
|
||||
$data = array(
|
||||
'a' => '{{ b }}',
|
||||
'b' => 'FAIL'
|
||||
);
|
||||
$template = '{{> partial }}';
|
||||
$partials = array(
|
||||
'partial' => '{{{ a }}}',
|
||||
);
|
||||
$output = '{{ b }}';
|
||||
$m = new Mustache();
|
||||
$this->assertEquals($output, $m->render($template, $data, $partials));
|
||||
}
|
||||
|
||||
|
||||
// lambdas
|
||||
|
||||
public function testLambdaInterpolationInjection() {
|
||||
$data = array(
|
||||
'a' => array($this, 'interpolationLambda'),
|
||||
'b' => '{{ c }}',
|
||||
'c' => 'FAIL'
|
||||
);
|
||||
$template = '{{ a }}';
|
||||
$output = '{{ c }}';
|
||||
$m = new Mustache();
|
||||
$this->assertEquals($output, $m->render($template, $data));
|
||||
}
|
||||
|
||||
public function interpolationLambda() {
|
||||
return '{{ b }}';
|
||||
}
|
||||
|
||||
public function testLambdaSectionInjection() {
|
||||
$data = array(
|
||||
'a' => array($this, 'sectionLambda'),
|
||||
'b' => '{{ c }}',
|
||||
'c' => 'FAIL'
|
||||
);
|
||||
$template = '{{# a }}b{{/ a }}';
|
||||
$output = '{{ c }}';
|
||||
$m = new Mustache();
|
||||
$this->assertEquals($output, $m->render($template, $data));
|
||||
}
|
||||
|
||||
public function sectionLambda($content) {
|
||||
return '{{ ' . $content . ' }}';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
require_once '../Mustache.php';
|
||||
require_once '../MustacheLoader.php';
|
||||
|
||||
/**
|
||||
* @group loader
|
||||
*/
|
||||
class MustacheLoaderTest extends PHPUnit_Framework_TestCase {
|
||||
|
||||
public function testTheActualFilesystemLoader() {
|
||||
$loader = new MustacheLoader(dirname(__FILE__).'/fixtures');
|
||||
$this->assertEquals(file_get_contents(dirname(__FILE__).'/fixtures/foo.mustache'), $loader['foo']);
|
||||
$this->assertEquals(file_get_contents(dirname(__FILE__).'/fixtures/bar.mustache'), $loader['bar']);
|
||||
}
|
||||
|
||||
public function testMustacheUsesFilesystemLoader() {
|
||||
$template = '{{> foo }} {{> bar }}';
|
||||
$data = array(
|
||||
'truthy' => true,
|
||||
'foo' => 'FOO',
|
||||
'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 }}';
|
||||
$data = array(
|
||||
'truthy' => true,
|
||||
'foo' => 'FOO',
|
||||
'bar' => 'BAR',
|
||||
);
|
||||
$output = 'FOO BAR';
|
||||
$m = new Mustache();
|
||||
$partials = new DifferentMustacheLoader();
|
||||
$this->assertEquals($output, $m->render($template, $data, $partials));
|
||||
}
|
||||
}
|
||||
|
||||
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,73 @@
|
||||
<?php
|
||||
|
||||
require_once '../Mustache.php';
|
||||
|
||||
/**
|
||||
* @group sections
|
||||
*/
|
||||
class MustacheObjectSectionTest extends PHPUnit_Framework_TestCase {
|
||||
public function testBasicObject() {
|
||||
$alpha = new Alpha();
|
||||
$this->assertEquals('Foo', $alpha->render('{{#foo}}{{name}}{{/foo}}'));
|
||||
}
|
||||
|
||||
public function testObjectWithGet() {
|
||||
$beta = new Beta();
|
||||
$this->assertEquals('Foo', $beta->render('{{#foo}}{{name}}{{/foo}}'));
|
||||
}
|
||||
|
||||
public function testSectionObjectWithGet() {
|
||||
$gamma = new Gamma();
|
||||
$this->assertEquals('Foo', $gamma->render('{{#bar}}{{#foo}}{{name}}{{/foo}}{{/bar}}'));
|
||||
}
|
||||
|
||||
public function testSectionObjectWithFunction() {
|
||||
$alpha = new Alpha();
|
||||
$alpha->foo = new Delta();
|
||||
$this->assertEquals('Foo', $alpha->render('{{#foo}}{{name}}{{/foo}}'));
|
||||
}
|
||||
}
|
||||
|
||||
class Alpha extends Mustache {
|
||||
public $foo;
|
||||
|
||||
public function __construct() {
|
||||
$this->foo = new StdClass();
|
||||
$this->foo->name = 'Foo';
|
||||
$this->foo->number = 1;
|
||||
}
|
||||
}
|
||||
|
||||
class Beta extends Mustache {
|
||||
protected $_data = array();
|
||||
|
||||
public function __construct() {
|
||||
$this->_data['foo'] = new StdClass();
|
||||
$this->_data['foo']->name = 'Foo';
|
||||
$this->_data['foo']->number = 1;
|
||||
}
|
||||
|
||||
public function __isset($name) {
|
||||
return array_key_exists($name, $this->_data);
|
||||
}
|
||||
|
||||
public function __get($name) {
|
||||
return $this->_data[$name];
|
||||
}
|
||||
}
|
||||
|
||||
class Gamma extends Mustache {
|
||||
public $bar;
|
||||
|
||||
public function __construct() {
|
||||
$this->bar = new Beta();
|
||||
}
|
||||
}
|
||||
|
||||
class Delta extends Mustache {
|
||||
protected $_name = 'Foo';
|
||||
|
||||
public function name() {
|
||||
return $this->_name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
require_once '../Mustache.php';
|
||||
|
||||
/**
|
||||
* @group pragmas
|
||||
*/
|
||||
class MustachePragmaTest extends PHPUnit_Framework_TestCase {
|
||||
|
||||
public function testUnknownPragmaException() {
|
||||
$m = new Mustache();
|
||||
|
||||
try {
|
||||
$m->render('{{%I-HAVE-THE-GREATEST-MUSTACHE}}');
|
||||
} catch (MustacheException $e) {
|
||||
$this->assertEquals(MustacheException::UNKNOWN_PRAGMA, $e->getCode(), 'Caught exception code was not MustacheException::UNKNOWN_PRAGMA');
|
||||
return;
|
||||
}
|
||||
|
||||
$this->fail('Mustache should have thrown an unknown pragma exception');
|
||||
}
|
||||
|
||||
public function testSuppressUnknownPragmaException() {
|
||||
$m = new LessWhinyMustache();
|
||||
|
||||
try {
|
||||
$this->assertEquals('', $m->render('{{%I-HAVE-THE-GREATEST-MUSTACHE}}'));
|
||||
} catch (MustacheException $e) {
|
||||
if ($e->getCode() == MustacheException::UNKNOWN_PRAGMA) {
|
||||
$this->fail('Mustache should have thrown an unknown pragma exception');
|
||||
} else {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function testPragmaReplace() {
|
||||
$m = new Mustache();
|
||||
$this->assertEquals('', $m->render('{{%UNESCAPED}}'), 'Pragma tag not removed');
|
||||
}
|
||||
|
||||
public function testPragmaReplaceMultiple() {
|
||||
$m = new Mustache();
|
||||
|
||||
$this->assertEquals('', $m->render('{{% UNESCAPED }}'), 'Pragmas should allow whitespace');
|
||||
$this->assertEquals('', $m->render('{{% UNESCAPED foo=bar }}'), 'Pragmas should allow whitespace');
|
||||
$this->assertEquals('', $m->render("{{%UNESCAPED}}\n{{%UNESCAPED}}"), 'Multiple pragma tags not removed');
|
||||
$this->assertEquals(' ', $m->render('{{%UNESCAPED}} {{%UNESCAPED}}'), 'Multiple pragma tags not removed');
|
||||
}
|
||||
|
||||
public function testPragmaReplaceNewline() {
|
||||
$m = new Mustache();
|
||||
$this->assertEquals('', $m->render("{{%UNESCAPED}}\n"), 'Trailing newline after pragma tag not removed');
|
||||
$this->assertEquals("\n", $m->render("\n{{%UNESCAPED}}\n"), 'Too many newlines removed with pragma tag');
|
||||
$this->assertEquals("1\n23", $m->render("1\n2{{%UNESCAPED}}\n3"), 'Wrong newline removed with pragma tag');
|
||||
}
|
||||
|
||||
public function testPragmaReset() {
|
||||
$m = new Mustache('', array('symbol' => '>>>'));
|
||||
$this->assertEquals('>>>', $m->render('{{{symbol}}}'));
|
||||
$this->assertEquals('>>>', $m->render('{{%UNESCAPED}}{{symbol}}'));
|
||||
$this->assertEquals('>>>', $m->render('{{{symbol}}}'));
|
||||
}
|
||||
}
|
||||
|
||||
class LessWhinyMustache extends Mustache {
|
||||
protected $_throwsExceptions = array(
|
||||
MustacheException::UNKNOWN_VARIABLE => false,
|
||||
MustacheException::UNCLOSED_SECTION => true,
|
||||
MustacheException::UNEXPECTED_CLOSE_SECTION => true,
|
||||
MustacheException::UNKNOWN_PARTIAL => false,
|
||||
MustacheException::UNKNOWN_PRAGMA => false,
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
require_once '../Mustache.php';
|
||||
|
||||
/**
|
||||
* @group pragmas
|
||||
*/
|
||||
class MustachePragmaUnescapedTest extends PHPUnit_Framework_TestCase {
|
||||
|
||||
public function testPragmaUnescaped() {
|
||||
$m = new Mustache(null, array('title' => 'Bear > Shark'));
|
||||
|
||||
$this->assertEquals('Bear > Shark', $m->render('{{%UNESCAPED}}{{title}}'));
|
||||
$this->assertEquals('Bear > Shark', $m->render('{{title}}'));
|
||||
$this->assertEquals('Bear > Shark', $m->render('{{%UNESCAPED}}{{{title}}}'));
|
||||
$this->assertEquals('Bear > Shark', $m->render('{{{title}}}'));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
require_once '../Mustache.php';
|
||||
require_once './lib/yaml/lib/sfYamlParser.php';
|
||||
|
||||
/**
|
||||
* A PHPUnit test case wrapping the Mustache Spec
|
||||
*
|
||||
* @group mustache-spec
|
||||
*/
|
||||
class MustacheSpecTest extends PHPUnit_Framework_TestCase {
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public function testSpecInitialized() {
|
||||
$spec_dir = dirname(__FILE__) . '/spec/specs/';
|
||||
if (!file_exists($spec_dir)) {
|
||||
$this->markTestSkipped('Mustache spec submodule not initialized: run "git submodule update --init"');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @group comments
|
||||
* @dataProvider loadCommentSpec
|
||||
*/
|
||||
public function testCommentSpec($desc, $template, $data, $partials, $expected) {
|
||||
$m = new Mustache($template, $data, $partials);
|
||||
$this->assertEquals($expected, $m->render(), $desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group delimiters
|
||||
* @dataProvider loadDelimitersSpec
|
||||
*/
|
||||
public function testDelimitersSpec($desc, $template, $data, $partials, $expected) {
|
||||
$m = new Mustache($template, $data, $partials);
|
||||
$this->assertEquals($expected, $m->render(), $desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group interpolation
|
||||
* @dataProvider loadInterpolationSpec
|
||||
*/
|
||||
public function testInterpolationSpec($desc, $template, $data, $partials, $expected) {
|
||||
$m = new Mustache($template, $data, $partials);
|
||||
$this->assertEquals($expected, $m->render(), $desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group inverted-sections
|
||||
* @dataProvider loadInvertedSpec
|
||||
*/
|
||||
public function testInvertedSpec($desc, $template, $data, $partials, $expected) {
|
||||
$m = new Mustache($template, $data, $partials);
|
||||
$this->assertEquals($expected, $m->render(), $desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group lambdas
|
||||
* @dataProvider loadLambdasSpec
|
||||
*/
|
||||
public function testLambdasSpec($desc, $template, $data, $partials, $expected) {
|
||||
if (!version_compare(PHP_VERSION, '5.3.0', '>=')) {
|
||||
$this->markTestSkipped('Unable to test Lambdas spec with PHP < 5.3.');
|
||||
}
|
||||
|
||||
$data = $this->prepareLambdasSpec($data);
|
||||
$m = new Mustache($template, $data, $partials);
|
||||
$this->assertEquals($expected, $m->render(), $desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract and lambdafy any 'lambda' values found in the $data array.
|
||||
*/
|
||||
protected function prepareLambdasSpec($data) {
|
||||
foreach ($data as $key => $val) {
|
||||
if ($key === 'lambda') {
|
||||
if (!isset($val['php'])) {
|
||||
$this->markTestSkipped(sprintf('PHP lambda test not implemented for this test.'));
|
||||
}
|
||||
|
||||
$func = $val['php'];
|
||||
$data[$key] = function($text = null) use ($func) { return eval($func); };
|
||||
} else if (is_array($val)) {
|
||||
$data[$key] = $this->prepareLambdasSpec($val);
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @group partials
|
||||
* @dataProvider loadPartialsSpec
|
||||
*/
|
||||
public function testPartialsSpec($desc, $template, $data, $partials, $expected) {
|
||||
$m = new Mustache($template, $data, $partials);
|
||||
$this->assertEquals($expected, $m->render(), $desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group sections
|
||||
* @dataProvider loadSectionsSpec
|
||||
*/
|
||||
public function testSectionsSpec($desc, $template, $data, $partials, $expected) {
|
||||
$m = new Mustache($template, $data, $partials);
|
||||
$this->assertEquals($expected, $m->render(), $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() {
|
||||
return $this->loadSpec('sections');
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for the mustache spec test.
|
||||
*
|
||||
* Loads YAML files from the spec and converts them to PHPisms.
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
protected function loadSpec($name) {
|
||||
$filename = dirname(__FILE__) . '/spec/specs/' . $name . '.yml';
|
||||
if (!file_exists($filename)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$data = array();
|
||||
$yaml = new sfYamlParser();
|
||||
$file = file_get_contents($filename);
|
||||
|
||||
// @hack: pre-process the 'lambdas' spec so the Symfony YAML parser doesn't complain.
|
||||
if ($name === '~lambdas') {
|
||||
$file = str_replace(" !code\n", "\n", $file);
|
||||
}
|
||||
|
||||
$spec = $yaml->parse($file);
|
||||
foreach ($spec['tests'] as $test) {
|
||||
$data[] = array(
|
||||
$test['name'] . ': ' . $test['desc'],
|
||||
$test['template'],
|
||||
$test['data'],
|
||||
isset($test['partials']) ? $test['partials'] : array(),
|
||||
$test['expected'],
|
||||
);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,464 @@
|
||||
<?php
|
||||
|
||||
require_once '../Mustache.php';
|
||||
|
||||
/**
|
||||
* A PHPUnit test case for Mustache.php.
|
||||
*
|
||||
* 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 {
|
||||
|
||||
const TEST_CLASS = 'Mustache';
|
||||
|
||||
protected $knownIssues = array(
|
||||
// Just the whitespace ones...
|
||||
);
|
||||
|
||||
/**
|
||||
* 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));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider constructorOptions
|
||||
*/
|
||||
public function testConstructorOptions($options, $charset, $delimiters, $pragmas) {
|
||||
$mustache = new MustacheExposedOptionsStub(null, null, null, $options);
|
||||
$this->assertEquals($charset, $mustache->getCharset());
|
||||
$this->assertEquals($delimiters, $mustache->getDelimiters());
|
||||
$this->assertEquals($pragmas, $mustache->getPragmas());
|
||||
}
|
||||
|
||||
public function constructorOptions() {
|
||||
return array(
|
||||
array(
|
||||
array(),
|
||||
'UTF-8',
|
||||
array('{{', '}}'),
|
||||
array(),
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'charset' => 'UTF-8',
|
||||
'delimiters' => '<< >>',
|
||||
'pragmas' => array(Mustache::PRAGMA_UNESCAPED => true)
|
||||
),
|
||||
'UTF-8',
|
||||
array('<<', '>>'),
|
||||
array(Mustache::PRAGMA_UNESCAPED => true),
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'charset' => 'cp866',
|
||||
'delimiters' => array('[[[[', ']]]]'),
|
||||
'pragmas' => array(Mustache::PRAGMA_UNESCAPED => true)
|
||||
),
|
||||
'cp866',
|
||||
array('[[[[', ']]]]'),
|
||||
array(Mustache::PRAGMA_UNESCAPED => true),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException MustacheException
|
||||
*/
|
||||
public function testConstructorInvalidPragmaOptionsThrowExceptions() {
|
||||
$mustache = new Mustache(null, null, null, array('pragmas' => array('banana phone' => true)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test __toString() function.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function test__toString() {
|
||||
$m = new Mustache('{{first_name}} {{last_name}}', array('first_name' => 'Karl', 'last_name' => 'Marx'));
|
||||
|
||||
$this->assertEquals('Karl Marx', $m->__toString());
|
||||
$this->assertEquals('Karl Marx', (string) $m);
|
||||
|
||||
$m2 = $this->getMock(self::TEST_CLASS, array('render'), array());
|
||||
$m2->expects($this->once())
|
||||
->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().
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function testRender() {
|
||||
$m = new Mustache();
|
||||
|
||||
$this->assertEquals('', $m->render(''));
|
||||
$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() {
|
||||
return $this->_pragmas;
|
||||
}
|
||||
public function getCharset() {
|
||||
return $this->_charset;
|
||||
}
|
||||
public function getDelimiters() {
|
||||
return array($this->_otag, $this->_ctag);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user