448 lines
15 KiB
PHP
448 lines
15 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Class AutoloaderTest
|
|
*/
|
|
class HandlebarsTest extends \PHPUnit_Framework_TestCase
|
|
{
|
|
/**
|
|
* Test handlebars autoloader
|
|
*
|
|
* @return void
|
|
*/
|
|
public function testAutoLoad()
|
|
{
|
|
Handlebars\Autoloader::register(realpath(__DIR__ . '/../fixture/'));
|
|
|
|
$this->assertTrue(class_exists('Handlebars\\Test'));
|
|
$this->assertTrue(class_exists('Handlebars\\Example\\Test'));
|
|
}
|
|
|
|
/**
|
|
* Test basic tags
|
|
*
|
|
* @param string $src handlebars source
|
|
* @param array $data data
|
|
* @param string $result expected data
|
|
*
|
|
* @dataProvider simpleTagdataProvider
|
|
*
|
|
* @return void
|
|
*/
|
|
public function testBasicTags($src, $data, $result)
|
|
{
|
|
$loader = new \Handlebars\Loader\StringLoader();
|
|
$engine = new \Handlebars\Handlebars(array('loader' => $loader));
|
|
$this->assertEquals($result, $engine->render($src, $data));
|
|
}
|
|
|
|
/**
|
|
* Simple tag provider
|
|
*
|
|
* @return array
|
|
*/
|
|
public function simpleTagdataProvider()
|
|
{
|
|
return array(
|
|
array(
|
|
'{{! This is comment}}',
|
|
array(),
|
|
''
|
|
),
|
|
array(
|
|
'{{data}}',
|
|
array('data' => 'result'),
|
|
'result'
|
|
),
|
|
array(
|
|
'{{data.key}}',
|
|
array('data' => array('key' => 'result')),
|
|
'result'
|
|
),
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
* Test helpers (internal helpers)
|
|
*
|
|
* @param string $src handlebars source
|
|
* @param array $data data
|
|
* @param string $result expected data
|
|
*
|
|
* @dataProvider internalHelpersdataProvider
|
|
*
|
|
* @return void
|
|
*/
|
|
public function testSimpleHelpers($src, $data, $result)
|
|
{
|
|
$loader = new \Handlebars\Loader\StringLoader();
|
|
$helpers = new \Handlebars\Helpers();
|
|
$engine = new \Handlebars\Handlebars(array('loader' => $loader, 'helpers' => $helpers));
|
|
|
|
$this->assertEquals($result, $engine->render($src, $data));
|
|
}
|
|
|
|
/**
|
|
* Simple helpers provider
|
|
*
|
|
* @return array
|
|
*/
|
|
public function internalHelpersdataProvider()
|
|
{
|
|
return [
|
|
[
|
|
'{{#if data}}Yes{{/if}}',
|
|
['data' => true],
|
|
'Yes'
|
|
],
|
|
[
|
|
'{{#if data}}Yes{{/if}}',
|
|
['data' => false],
|
|
''
|
|
],
|
|
[
|
|
'{{#unless data}}OK{{/unless}}',
|
|
['data' => false],
|
|
'OK'
|
|
],
|
|
[
|
|
'{{#unless data}}OK {{else}}I believe{{/unless}}',
|
|
['data' => true],
|
|
'I believe'
|
|
],
|
|
[
|
|
'{{#with data}}{{key}}{{/with}}',
|
|
['data' => ['key' => 'result']],
|
|
'result'
|
|
],
|
|
[
|
|
'{{#each data}}{{this}}{{/each}}',
|
|
['data' => [1, 2, 3, 4]],
|
|
'1234'
|
|
],
|
|
[
|
|
'{{#each data[0:2]}}{{this}}{{/each}}',
|
|
['data' => [1, 2, 3, 4]],
|
|
'12'
|
|
],
|
|
[
|
|
'{{#each data[1:2]}}{{this}}{{/each}}',
|
|
['data' => [1, 2, 3, 4]],
|
|
'23'
|
|
],
|
|
[
|
|
'{{#upper data}}',
|
|
['data' => "hello"],
|
|
'HELLO'
|
|
],
|
|
[
|
|
'{{#lower data}}',
|
|
['data' => "HELlO"],
|
|
'hello'
|
|
],
|
|
[
|
|
'{{#capitalize data}}',
|
|
['data' => "hello"],
|
|
'Hello'
|
|
],
|
|
[
|
|
'{{#capitalize_words data}}',
|
|
['data' => "hello world"],
|
|
'Hello World'
|
|
],
|
|
[
|
|
'{{#reverse data}}',
|
|
['data' => "hello"],
|
|
'olleh'
|
|
],
|
|
[
|
|
"{{#inflect count 'album' 'albums' }}",
|
|
["count" => 1],
|
|
'album'
|
|
],
|
|
[
|
|
"{{#inflect count 'album' 'albums' }}",
|
|
["count" => 10],
|
|
'albums'
|
|
],
|
|
[
|
|
"{{#inflect count '%d album' '%d albums' }}",
|
|
["count" => 1],
|
|
'1 album'
|
|
],
|
|
[
|
|
"{{#inflect count '%d album' '%d albums' }}",
|
|
["count" => 10],
|
|
'10 albums'
|
|
],
|
|
[
|
|
"{{#default data 'OK' }}",
|
|
["data" => "hello"],
|
|
'hello'
|
|
],
|
|
[
|
|
"{{#default data 'OK' }}",
|
|
[],
|
|
'OK'
|
|
],
|
|
[
|
|
"{{#truncate data 8 '...'}}",
|
|
["data" => "Hello World! How are you?"],
|
|
'Hello Wo...'
|
|
],
|
|
[
|
|
"{{#raw}}I'm raw {{data}}{{/raw}}",
|
|
["data" => "raw to be included, but won't :)"],
|
|
"I'm raw {{data}}"
|
|
],
|
|
[
|
|
"{{#repeat 3}}Yes {{/repeat}}",
|
|
[],
|
|
"Yes Yes Yes "
|
|
],
|
|
[
|
|
"{{#repeat 4}}Nice {{data}} {{/repeat}}",
|
|
["data" => "Daddy!"],
|
|
"Nice Daddy! Nice Daddy! Nice Daddy! Nice Daddy! "
|
|
],
|
|
[
|
|
"{{#define test}}I'm Defined and Invoked{{/define}}{{#invoke test}}",
|
|
[],
|
|
"I'm Defined and Invoked"
|
|
],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @param string $src
|
|
* @param array $data
|
|
* @param string $result
|
|
* @param bool $enableDataVariables
|
|
* @dataProvider internalDataVariablesDataProvider
|
|
*/
|
|
public function testDataVariables($src, $data, $result, $enableDataVariables)
|
|
{
|
|
$loader = new \Handlebars\Loader\StringLoader();
|
|
$helpers = new \Handlebars\Helpers();
|
|
$engine = new \Handlebars\Handlebars(array(
|
|
'loader' => $loader,
|
|
'helpers' => $helpers,
|
|
'enableDataVariables'=> $enableDataVariables,
|
|
));
|
|
|
|
$this->assertEquals($result, $engine->render($src, $data));
|
|
}
|
|
|
|
public function testDataVariables1()
|
|
{
|
|
$object = new stdClass;
|
|
$object->{'@first'} = 'apple';
|
|
$object->{'@last'} = 'banana';
|
|
$object->{'@index'} = 'carrot';
|
|
$object->{'@unknown'} = 'zucchini';
|
|
$data = ['data' => [$object]];
|
|
$engine = new \Handlebars\Handlebars(array(
|
|
'loader' => new \Handlebars\Loader\StringLoader(),
|
|
'helpers' => new \Handlebars\Helpers(),
|
|
'enableDataVariables'=> false,
|
|
));
|
|
$template = "{{#each data}}{{@first}}, {{@last}}, {{@index}}, {{@unknown}}{{/each}}";
|
|
|
|
$this->assertEquals("", $engine->render($template, $data));
|
|
}
|
|
|
|
/**
|
|
* Data provider for data variables
|
|
* @return array
|
|
*/
|
|
public function internalDataVariablesDataProvider()
|
|
{
|
|
// Build a standard set of objects to test against
|
|
$keyPropertyName = '@key';
|
|
$firstPropertyName = '@first';
|
|
$lastPropertyName = '@last';
|
|
$unknownPropertyName = '@unknown';
|
|
$objects = [];
|
|
foreach (['apple', 'banana', 'carrot', 'zucchini'] as $itemValue) {
|
|
$object = new stdClass();
|
|
$object->$keyPropertyName = $itemValue;
|
|
$object->$firstPropertyName = $itemValue;
|
|
$object->$lastPropertyName = $itemValue;
|
|
$object->$unknownPropertyName = $itemValue;
|
|
$objects[] = $object;
|
|
}
|
|
|
|
// Build a list of scenarios. These will be used later to build fanned out scenarios that will be used against
|
|
// the test. Each entry represents two different tests: (1) when enableDataVariables is enabled and (2) not enabled.
|
|
$scenarios = [
|
|
[
|
|
'src' => '{{#each data}}{{@index}}{{/each}}',
|
|
'data' => ['data' => ['apple', 'banana', 'carrot', 'zucchini']],
|
|
// @index should work the same regardless of the feature flag
|
|
'outputNotEnabled' => '0123',
|
|
'outputEnabled' => '0123',
|
|
],
|
|
[
|
|
'src' => '{{#each data}}{{@key}}{{/each}}',
|
|
'data' => ['data' => ['apple', 'banana', 'carrot', 'zucchini']],
|
|
'outputNotEnabled' => '',
|
|
'outputEnabled' => '0123'
|
|
],
|
|
[
|
|
'src' => '{{#each data}}{{#each this}}outer: {{@../key}},inner: {{@key}};{{/each}}{{/each}}',
|
|
'data' => ['data' => [['apple', 'banana'], ['carrot', 'zucchini']]],
|
|
'outputNotEnabled' => 'outer: ,inner: ;outer: ,inner: ;outer: ,inner: ;outer: ,inner: ;',
|
|
'outputEnabled' => 'outer: 0,inner: 0;outer: 0,inner: 1;outer: 1,inner: 0;outer: 1,inner: 1;',
|
|
],
|
|
[
|
|
'src' => '{{#each data}}{{#if @first}}true{{else}}false{{/if}}{{/each}}',
|
|
'data' => ['data' => ['apple', 'banana', 'carrot', 'zucchini']],
|
|
'outputNotEnabled' => 'falsefalsefalsefalse',
|
|
'outputEnabled' => 'truefalsefalsefalse',
|
|
],
|
|
[
|
|
'src' => '{{#each data}}{{@first}}{{/each}}',
|
|
'data' => ['data' => ['apple', 'banana', 'carrot', 'zucchini']],
|
|
'outputNotEnabled' => '',
|
|
'outputEnabled' => 'truefalsefalsefalse',
|
|
],
|
|
[
|
|
'src' => '{{#each data}}{{#each this}}outer: {{@../first}},inner: {{@first}};{{/each}}{{/each}}',
|
|
'data' => ['data' => [['apple', 'banana'], ['carrot', 'zucchini']]],
|
|
'outputNotEnabled' => 'outer: ,inner: ;outer: ,inner: ;outer: ,inner: ;outer: ,inner: ;',
|
|
'outputEnabled' => 'outer: true,inner: true;outer: true,inner: false;outer: false,inner: true;outer: false,inner: false;',
|
|
],
|
|
[
|
|
'src' => '{{#each data}}{{#if @last}}true{{else}}false{{/if}}{{/each}}',
|
|
'data' => ['data' => ['apple', 'banana', 'carrot', 'zucchini']],
|
|
'outputNotEnabled' => 'falsefalsefalsefalse',
|
|
'outputEnabled' => 'falsefalsefalsetrue'
|
|
],
|
|
[
|
|
'src' => '{{#each data}}{{@last}}{{/each}}',
|
|
'data' => ['data' => ['apple', 'banana', 'carrot', 'zucchini']],
|
|
'outputNotEnabled' => '',
|
|
'outputEnabled' => 'falsefalsefalsetrue'
|
|
],
|
|
[
|
|
'src' => '{{#each data}}{{#each this}}outer: {{@../last}},inner: {{@last}};{{/each}}{{/each}}',
|
|
'data' => ['data' => [['apple', 'banana'], ['carrot', 'zucchini']]],
|
|
'outputNotEnabled' => 'outer: ,inner: ;outer: ,inner: ;outer: ,inner: ;outer: ,inner: ;',
|
|
'outputEnabled' => 'outer: false,inner: false;outer: false,inner: true;outer: true,inner: false;outer: true,inner: true;'
|
|
],
|
|
[
|
|
// @index variables are ignored and the data variable is used
|
|
'src' => '{{#each data}}{{@index}}{{/each}}',
|
|
'data' => ['data' => [['@index' => 'apple'], ['@index' => 'banana'], ['@index' => 'carrot'], ['@index' => 'zucchini']]],
|
|
'outputNotEnabled' => '0123',
|
|
'outputEnabled' => '0123'
|
|
],
|
|
[
|
|
// @key variables are ignored and the data variable is used
|
|
'src' => '{{#each data}}{{@index}}{{/each}}',
|
|
'data' => ['data' => $objects],
|
|
'outputNotEnabled' => '0123',
|
|
'outputEnabled' => '0123'
|
|
],
|
|
[
|
|
// @first variables are used when data variables are not enabled.
|
|
'src' => '{{#each data}}{{@first}}{{/each}}',
|
|
'data' => ['data' => $objects],
|
|
'outputNotEnabled' => 'applebananacarrotzucchini',
|
|
'outputEnabled' => 'truefalsefalsefalse'
|
|
],
|
|
[
|
|
// @last variables are used when data variables are not enabled.
|
|
'src' => '{{#each data}}{{@last}}{{/each}}',
|
|
'data' => ['data' => $objects],
|
|
'outputNotEnabled' => 'applebananacarrotzucchini',
|
|
'outputEnabled' => 'falsefalsefalsetrue'
|
|
],
|
|
[
|
|
// @unknown variables are used when data variables are not enabled however since "unknown" is not a valid
|
|
// value it should ignored.
|
|
'src' => '{{#each data}}{{@unknown}}{{/each}}',
|
|
'data' => ['data' => $objects],
|
|
'outputNotEnabled' => 'applebananacarrotzucchini',
|
|
'outputEnabled' => ''
|
|
],
|
|
];
|
|
|
|
// Build out a test case for when the enableDataVariables feature is enabled and when it's not
|
|
$fannedOutScenarios = [];
|
|
foreach ($scenarios as $scenario) {
|
|
$fannedOutScenarios['not enabled: ' . $scenario['src']] = [
|
|
$scenario['src'],
|
|
$scenario['data'],
|
|
$scenario['outputNotEnabled'],
|
|
false,
|
|
];
|
|
$fannedOutScenarios['enabled: ' . $scenario['src']] = [
|
|
$scenario['src'],
|
|
$scenario['data'],
|
|
$scenario['outputEnabled'],
|
|
true,
|
|
];
|
|
}
|
|
return $fannedOutScenarios;
|
|
}
|
|
|
|
/**
|
|
* Management helpers
|
|
*/
|
|
public function testHelpersManagement()
|
|
{
|
|
$helpers = new \Handlebars\Helpers(array('test' => function () {
|
|
}), false);
|
|
$engine = new \Handlebars\Handlebars(array('helpers' => $helpers));
|
|
$this->assertTrue(is_callable($engine->getHelper('test')));
|
|
$this->assertTrue($engine->hasHelper('test'));
|
|
$engine->removeHelper('test');
|
|
$this->assertFalse($engine->hasHelper('test'));
|
|
}
|
|
|
|
/**
|
|
* Custom helper test
|
|
*/
|
|
public function testCustomHelper()
|
|
{
|
|
$loader = new \Handlebars\Loader\StringLoader();
|
|
$engine = new \Handlebars\Handlebars(array('loader' => $loader));
|
|
$engine->addHelper('test', function () {
|
|
return 'Test helper is called';
|
|
});
|
|
$this->assertEquals('Test helper is called', $engine->render('{{#test}}', []));
|
|
}
|
|
|
|
/**
|
|
* @param $dir
|
|
*
|
|
* @return bool
|
|
*/
|
|
private function delTree($dir)
|
|
{
|
|
$files = array_diff(scandir($dir), array('.', '..'));
|
|
foreach ($files as $file) {
|
|
(is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file");
|
|
}
|
|
|
|
return rmdir($dir);
|
|
}
|
|
|
|
/**
|
|
* Its not a good test :) but ok
|
|
*/
|
|
public function testCacheSystem()
|
|
{
|
|
$path = sys_get_temp_dir() . '/__cache__handlebars';
|
|
|
|
@$this->delTree($path);
|
|
|
|
$dummy = new \Handlebars\Cache\Disk($path);
|
|
$engine = new \Handlebars\Handlebars(array('cache' => $dummy));
|
|
$this->assertEquals(0, count(glob($path . '/*')));
|
|
$engine->render('test', array());
|
|
$this->assertEquals(1, count(glob($path . '/*')));
|
|
}
|
|
} |