aboutsummaryrefslogtreecommitdiffstats
path: root/tests/template
diff options
context:
space:
mode:
Diffstat (limited to 'tests/template')
-rw-r--r--tests/template/datasets/event_inheritance/ext/kappa/styles/all/template/test.html1
-rw-r--r--tests/template/datasets/event_inheritance/ext/kappa/styles/silver/template/test.html1
-rw-r--r--tests/template/datasets/event_inheritance/ext/kappa/styles/silver_inherit/template/test.html1
-rw-r--r--tests/template/datasets/event_inheritance/ext/omega/styles/all/template/test.html1
-rw-r--r--tests/template/datasets/event_inheritance/ext/omega/styles/silver/template/test.html1
-rw-r--r--tests/template/datasets/event_inheritance/ext/omega/styles/silver/template/two.html1
-rw-r--r--tests/template/datasets/event_inheritance/ext/zeta/styles/all/template/test.html1
-rw-r--r--tests/template/datasets/event_inheritance/styles/silver/template/event_test.html1
-rw-r--r--tests/template/datasets/event_inheritance/styles/silver/template/event_two.html1
-rw-r--r--tests/template/datasets/event_inheritance/styles/silver_inherit/template/event_test.html1
-rw-r--r--tests/template/datasets/ext_trivial/ext/trivial/styles/all/template/event_variable_spacing.html6
-rw-r--r--tests/template/datasets/ext_trivial/ext/trivial/styles/all/template/universal.html1
-rw-r--r--tests/template/datasets/ext_trivial/ext/trivial/styles/silver/template/simple.html1
-rw-r--r--tests/template/datasets/ext_trivial/styles/silver/template/event_simple.html1
-rw-r--r--tests/template/datasets/ext_trivial/styles/silver/template/event_universal.html1
-rw-r--r--tests/template/datasets/ext_trivial/styles/silver/template/variable_spacing.html1
-rw-r--r--tests/template/includephp_test.php56
-rw-r--r--tests/template/parent_templates/parent_and_child.html1
-rw-r--r--tests/template/parent_templates/parent_and_child.js1
-rw-r--r--tests/template/parent_templates/parent_only.css0
-rw-r--r--tests/template/parent_templates/parent_only.html1
-rw-r--r--tests/template/parent_templates/parent_only.js1
-rw-r--r--tests/template/subdir/includephp_from_subdir_test.php27
-rw-r--r--tests/template/template_events_test.php115
-rw-r--r--tests/template/template_includecss_test.php28
-rw-r--r--tests/template/template_includejs_test.php103
-rw-r--r--tests/template/template_inheritance_test.php55
-rw-r--r--tests/template/template_parser_test.php29
-rw-r--r--tests/template/template_test.php419
-rw-r--r--tests/template/template_test_case.php124
-rw-r--r--tests/template/template_test_case_with_tree.php29
-rw-r--r--tests/template/templates/basic.html3
-rw-r--r--tests/template/templates/child_only.css0
-rw-r--r--tests/template/templates/child_only.html1
-rw-r--r--tests/template/templates/child_only.js1
-rw-r--r--tests/template/templates/define.html12
-rw-r--r--tests/template/templates/define_advanced.html12
-rw-r--r--tests/template/templates/define_include.html3
-rw-r--r--tests/template/templates/define_include2.html11
-rw-r--r--tests/template/templates/events.html4
-rw-r--r--tests/template/templates/expressions.html29
-rw-r--r--tests/template/templates/if.html14
-rw-r--r--tests/template/templates/include_loop.html4
-rw-r--r--tests/template/templates/include_loop1.html1
-rw-r--r--tests/template/templates/include_loop2.html1
-rw-r--r--tests/template/templates/include_loop3.html1
-rw-r--r--tests/template/templates/include_variable.html1
-rw-r--r--tests/template/templates/include_variables.html1
-rw-r--r--tests/template/templates/includecss.html3
-rw-r--r--tests/template/templates/includejs.html36
-rw-r--r--tests/template/templates/includephp_relative.html (renamed from tests/template/templates/includephp.html)1
-rw-r--r--tests/template/templates/includephp_variables.html2
-rw-r--r--tests/template/templates/invalid/endif_without_if.html1
-rw-r--r--tests/template/templates/invalid/output/endif_without_if.html1
-rw-r--r--tests/template/templates/invalid/output/include_nonexistent_file.html1
-rw-r--r--tests/template/templates/invalid/output/unknown_tag.html1
-rw-r--r--tests/template/templates/lang.html2
-rw-r--r--tests/template/templates/loop_expressions.html11
-rw-r--r--tests/template/templates/loop_nested.html10
-rw-r--r--tests/template/templates/loop_nested2.html6
-rw-r--r--tests/template/templates/loop_nested_deep_multilevel_ref.html13
-rw-r--r--tests/template/templates/loop_nested_multilevel_ref.html10
-rw-r--r--tests/template/templates/loop_reuse.html6
-rw-r--r--tests/template/templates/loop_size.html39
-rw-r--r--tests/template/templates/loop_underscore.html21
-rw-r--r--tests/template/templates/loop_vars.html14
-rw-r--r--tests/template/templates/parent_and_child.html1
-rw-r--r--tests/template/templates/parent_and_child.js1
-rw-r--r--tests/template/templates/subdir/parent_only.js0
-rw-r--r--tests/template/templates/subdir/subsubdir/parent_only.js0
-rw-r--r--tests/template/templates/subdir/variable.html1
-rw-r--r--tests/template/templates/trivial.html1
-rw-r--r--tests/template/templates/twig.html6
-rw-r--r--tests/template/templates/twig_parent.html7
-rw-r--r--tests/template/templates/variable_spacing.html6
75 files changed, 1046 insertions, 264 deletions
diff --git a/tests/template/datasets/event_inheritance/ext/kappa/styles/all/template/test.html b/tests/template/datasets/event_inheritance/ext/kappa/styles/all/template/test.html
new file mode 100644
index 0000000000..3eb906a09e
--- /dev/null
+++ b/tests/template/datasets/event_inheritance/ext/kappa/styles/all/template/test.html
@@ -0,0 +1 @@
+Kappa test event in all
diff --git a/tests/template/datasets/event_inheritance/ext/kappa/styles/silver/template/test.html b/tests/template/datasets/event_inheritance/ext/kappa/styles/silver/template/test.html
new file mode 100644
index 0000000000..3b65d80a6d
--- /dev/null
+++ b/tests/template/datasets/event_inheritance/ext/kappa/styles/silver/template/test.html
@@ -0,0 +1 @@
+Kappa test event in silver
diff --git a/tests/template/datasets/event_inheritance/ext/kappa/styles/silver_inherit/template/test.html b/tests/template/datasets/event_inheritance/ext/kappa/styles/silver_inherit/template/test.html
new file mode 100644
index 0000000000..26826d59e3
--- /dev/null
+++ b/tests/template/datasets/event_inheritance/ext/kappa/styles/silver_inherit/template/test.html
@@ -0,0 +1 @@
+Kappa test event in silver_inherit
diff --git a/tests/template/datasets/event_inheritance/ext/omega/styles/all/template/test.html b/tests/template/datasets/event_inheritance/ext/omega/styles/all/template/test.html
new file mode 100644
index 0000000000..003d193dc3
--- /dev/null
+++ b/tests/template/datasets/event_inheritance/ext/omega/styles/all/template/test.html
@@ -0,0 +1 @@
+Omega test event in all
diff --git a/tests/template/datasets/event_inheritance/ext/omega/styles/silver/template/test.html b/tests/template/datasets/event_inheritance/ext/omega/styles/silver/template/test.html
new file mode 100644
index 0000000000..6bf06f5457
--- /dev/null
+++ b/tests/template/datasets/event_inheritance/ext/omega/styles/silver/template/test.html
@@ -0,0 +1 @@
+Omega test event in silver
diff --git a/tests/template/datasets/event_inheritance/ext/omega/styles/silver/template/two.html b/tests/template/datasets/event_inheritance/ext/omega/styles/silver/template/two.html
new file mode 100644
index 0000000000..7f8058f4e4
--- /dev/null
+++ b/tests/template/datasets/event_inheritance/ext/omega/styles/silver/template/two.html
@@ -0,0 +1 @@
+two in silver in omega
diff --git a/tests/template/datasets/event_inheritance/ext/zeta/styles/all/template/test.html b/tests/template/datasets/event_inheritance/ext/zeta/styles/all/template/test.html
new file mode 100644
index 0000000000..5fc7e5ac12
--- /dev/null
+++ b/tests/template/datasets/event_inheritance/ext/zeta/styles/all/template/test.html
@@ -0,0 +1 @@
+Zeta test event in all
diff --git a/tests/template/datasets/event_inheritance/styles/silver/template/event_test.html b/tests/template/datasets/event_inheritance/styles/silver/template/event_test.html
new file mode 100644
index 0000000000..4d78dddb12
--- /dev/null
+++ b/tests/template/datasets/event_inheritance/styles/silver/template/event_test.html
@@ -0,0 +1 @@
+<!-- EVENT test -->
diff --git a/tests/template/datasets/event_inheritance/styles/silver/template/event_two.html b/tests/template/datasets/event_inheritance/styles/silver/template/event_two.html
new file mode 100644
index 0000000000..fe46be3782
--- /dev/null
+++ b/tests/template/datasets/event_inheritance/styles/silver/template/event_two.html
@@ -0,0 +1 @@
+<!-- EVENT two -->
diff --git a/tests/template/datasets/event_inheritance/styles/silver_inherit/template/event_test.html b/tests/template/datasets/event_inheritance/styles/silver_inherit/template/event_test.html
new file mode 100644
index 0000000000..4d78dddb12
--- /dev/null
+++ b/tests/template/datasets/event_inheritance/styles/silver_inherit/template/event_test.html
@@ -0,0 +1 @@
+<!-- EVENT test -->
diff --git a/tests/template/datasets/ext_trivial/ext/trivial/styles/all/template/event_variable_spacing.html b/tests/template/datasets/ext_trivial/ext/trivial/styles/all/template/event_variable_spacing.html
new file mode 100644
index 0000000000..028f8aa0d1
--- /dev/null
+++ b/tests/template/datasets/ext_trivial/ext/trivial/styles/all/template/event_variable_spacing.html
@@ -0,0 +1,6 @@
+|{VARIABLE}|
+{VARIABLE}|{VARIABLE}|
+
+|{VARIABLE}
+
+<div class="{VARIABLE}">test</div>
diff --git a/tests/template/datasets/ext_trivial/ext/trivial/styles/all/template/universal.html b/tests/template/datasets/ext_trivial/ext/trivial/styles/all/template/universal.html
new file mode 100644
index 0000000000..f2c5762ade
--- /dev/null
+++ b/tests/template/datasets/ext_trivial/ext/trivial/styles/all/template/universal.html
@@ -0,0 +1 @@
+Universal in trivial extension.
diff --git a/tests/template/datasets/ext_trivial/ext/trivial/styles/silver/template/simple.html b/tests/template/datasets/ext_trivial/ext/trivial/styles/silver/template/simple.html
new file mode 100644
index 0000000000..fe32a1ed3f
--- /dev/null
+++ b/tests/template/datasets/ext_trivial/ext/trivial/styles/silver/template/simple.html
@@ -0,0 +1 @@
+Simple in trivial extension.
diff --git a/tests/template/datasets/ext_trivial/styles/silver/template/event_simple.html b/tests/template/datasets/ext_trivial/styles/silver/template/event_simple.html
new file mode 100644
index 0000000000..604c1acdce
--- /dev/null
+++ b/tests/template/datasets/ext_trivial/styles/silver/template/event_simple.html
@@ -0,0 +1 @@
+<!-- EVENT simple -->
diff --git a/tests/template/datasets/ext_trivial/styles/silver/template/event_universal.html b/tests/template/datasets/ext_trivial/styles/silver/template/event_universal.html
new file mode 100644
index 0000000000..15425cacc3
--- /dev/null
+++ b/tests/template/datasets/ext_trivial/styles/silver/template/event_universal.html
@@ -0,0 +1 @@
+<!-- EVENT universal -->
diff --git a/tests/template/datasets/ext_trivial/styles/silver/template/variable_spacing.html b/tests/template/datasets/ext_trivial/styles/silver/template/variable_spacing.html
new file mode 100644
index 0000000000..49d8a6b873
--- /dev/null
+++ b/tests/template/datasets/ext_trivial/styles/silver/template/variable_spacing.html
@@ -0,0 +1 @@
+<!-- EVENT event_variable_spacing -->
diff --git a/tests/template/includephp_test.php b/tests/template/includephp_test.php
new file mode 100644
index 0000000000..ff7b890d11
--- /dev/null
+++ b/tests/template/includephp_test.php
@@ -0,0 +1,56 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2011 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+require_once dirname(__FILE__) . '/template_test_case.php';
+
+class phpbb_template_includephp_test extends phpbb_template_template_test_case
+{
+ public function test_includephp_relative()
+ {
+ $this->setup_engine(array('tpl_allow_php' => true));
+
+ $this->run_template('includephp_relative.html', array(), array(), array(), "Path is relative to board root.\ntesting included php");
+
+ $this->template->set_filenames(array('test' => 'includephp_relative.html'));
+ $this->assertEquals("Path is relative to board root.\ntesting included php", $this->display('test'), "Testing INCLUDEPHP");
+ }
+
+ public function test_includephp_variables()
+ {
+ $this->setup_engine(array('tpl_allow_php' => true));
+
+ $this->run_template('includephp_variables.html', array('TEMPLATES' => 'templates'), array(), array(), "Path includes variables.\ntesting included php");
+
+ $this->template->set_filenames(array('test' => 'includephp_variables.html'));
+ $this->assertEquals("Path includes variables.\ntesting included php", $this->display('test'), "Testing INCLUDEPHP");
+ }
+
+ public function test_includephp_absolute()
+ {
+ global $phpbb_root_path;
+
+ $path_to_php = str_replace('\\', '/', dirname(__FILE__)) . '/templates/_dummy_include.php.inc';
+ $this->assertTrue(phpbb_is_absolute($path_to_php));
+ $template_text = "Path is absolute.\n<!-- INCLUDEPHP $path_to_php -->";
+
+ $cache_dir = $phpbb_root_path . 'cache/';
+ $fp = fopen($cache_dir . 'includephp_absolute.html', 'w');
+ fputs($fp, $template_text);
+ fclose($fp);
+
+ $this->setup_engine(array('tpl_allow_php' => true));
+
+ $this->style->set_custom_style('tests', $cache_dir, array(), '');
+
+ $this->run_template('includephp_absolute.html', array(), array(), array(), "Path is absolute.\ntesting included php");
+
+ $this->template->set_filenames(array('test' => 'includephp_absolute.html'));
+ $this->assertEquals("Path is absolute.\ntesting included php", $this->display('test'), "Testing INCLUDEPHP");
+ }
+}
diff --git a/tests/template/parent_templates/parent_and_child.html b/tests/template/parent_templates/parent_and_child.html
new file mode 100644
index 0000000000..71984b48ad
--- /dev/null
+++ b/tests/template/parent_templates/parent_and_child.html
@@ -0,0 +1 @@
+Parent template.
diff --git a/tests/template/parent_templates/parent_and_child.js b/tests/template/parent_templates/parent_and_child.js
new file mode 100644
index 0000000000..6d9bb163bf
--- /dev/null
+++ b/tests/template/parent_templates/parent_and_child.js
@@ -0,0 +1 @@
+// JavaScript file in a parent style.
diff --git a/tests/template/parent_templates/parent_only.css b/tests/template/parent_templates/parent_only.css
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/template/parent_templates/parent_only.css
diff --git a/tests/template/parent_templates/parent_only.html b/tests/template/parent_templates/parent_only.html
new file mode 100644
index 0000000000..8cfb90eca2
--- /dev/null
+++ b/tests/template/parent_templates/parent_only.html
@@ -0,0 +1 @@
+Only in parent.
diff --git a/tests/template/parent_templates/parent_only.js b/tests/template/parent_templates/parent_only.js
new file mode 100644
index 0000000000..9c3007d83f
--- /dev/null
+++ b/tests/template/parent_templates/parent_only.js
@@ -0,0 +1 @@
+// JavaScript file only in parent style.
diff --git a/tests/template/subdir/includephp_from_subdir_test.php b/tests/template/subdir/includephp_from_subdir_test.php
new file mode 100644
index 0000000000..6f9bc1efa6
--- /dev/null
+++ b/tests/template/subdir/includephp_from_subdir_test.php
@@ -0,0 +1,27 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2011 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+require_once dirname(__FILE__) . '/../template_test_case.php';
+
+class phpbb_template_subdir_includephp_from_subdir_test extends phpbb_template_template_test_case
+{
+ // Exact copy of test_includephp_relatve from ../includephp_test.php.
+ // Verifies that relative php inclusion works when including script
+ // (and thus current working directory) is in a subdirectory of
+ // board root.
+ public function test_includephp_relative()
+ {
+ $this->setup_engine(array('tpl_allow_php' => true));
+
+ $this->run_template('includephp_relative.html', array(), array(), array(), "Path is relative to board root.\ntesting included php");
+
+ $this->template->set_filenames(array('test' => 'includephp_relative.html'));
+ $this->assertEquals("Path is relative to board root.\ntesting included php", $this->display('test'), "Testing INCLUDEPHP");
+ }
+}
diff --git a/tests/template/template_events_test.php b/tests/template/template_events_test.php
new file mode 100644
index 0000000000..f7bcd2dcc6
--- /dev/null
+++ b/tests/template/template_events_test.php
@@ -0,0 +1,115 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2011 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+require_once dirname(__FILE__) . '/template_test_case.php';
+
+class phpbb_template_template_events_test extends phpbb_template_template_test_case
+{
+ public function template_data()
+ {
+ return array(
+ /*
+ array(
+ '', // Description
+ '', // dataset
+ array(), // style names
+ '', // file
+ array(), // vars
+ array(), // block vars
+ array(), // destroy
+ '', // expected result
+ ),
+ */
+ array(
+ 'Simple template event',
+ 'ext_trivial',
+ array(),
+ 'event_simple.html',
+ array(),
+ array(),
+ array(),
+ "Simple in trivial extension.",
+ ),
+ array(
+ 'Universal template event ("all" style)',
+ 'ext_trivial',
+ array(),
+ 'event_universal.html',
+ array(),
+ array(),
+ array(),
+ "Universal in trivial extension.",
+ ),
+ array(
+ 'Template event with inheritance - parent',
+ 'event_inheritance',
+ array('silver'),
+ 'event_test.html',
+ array(),
+ array(),
+ array(),
+'Kappa test event in silver
+Omega test event in silver
+Zeta test event in all',
+ ),
+ array(
+ 'Template event with inheritance - child',
+ 'event_inheritance',
+ array('silver_inherit', 'silver'),
+ 'event_test.html',
+ array(),
+ array(),
+ array(),
+'Kappa test event in silver_inherit
+Omega test event in silver
+Zeta test event in all',
+ ),
+ array(
+ 'Definition in parent style',
+ 'event_inheritance',
+ array('silver_inherit', 'silver'),
+ 'event_two.html',
+ array(),
+ array(),
+ array(),
+'two in silver in omega',
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider template_data
+ */
+ public function test_event($desc, $dataset, $style_names, $file, array $vars, array $block_vars, array $destroy, $expected)
+ {
+ // Reset the engine state
+ $this->setup_engine_for_events($dataset, $style_names);
+
+ // Run test
+ $this->run_template($file, $vars, $block_vars, $destroy, $expected);
+ }
+
+ protected function setup_engine_for_events($dataset, $style_names, array $new_config = array())
+ {
+ global $phpbb_root_path, $phpEx, $user;
+
+ $defaults = $this->config_defaults();
+ $config = new phpbb_config(array_merge($defaults, $new_config));
+
+ $this->template_path = dirname(__FILE__) . "/datasets/$dataset/styles/silver/template";
+ $this->style_resource_locator = new phpbb_style_resource_locator();
+ $this->extension_manager = new phpbb_mock_filesystem_extension_manager(
+ dirname(__FILE__) . "/datasets/$dataset/"
+ );
+ $this->template = new phpbb_template_twig($phpbb_root_path, $phpEx, $config, $user, new phpbb_template_context, $this->extension_manager);
+ $this->style_provider = new phpbb_style_path_provider();
+ $this->style = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $this->style_resource_locator, $this->style_provider, $this->template);
+ $this->style->set_custom_style('silver', array($this->template_path), $style_names, '');
+ }
+}
diff --git a/tests/template/template_includecss_test.php b/tests/template/template_includecss_test.php
new file mode 100644
index 0000000000..f8999ad1a9
--- /dev/null
+++ b/tests/template/template_includecss_test.php
@@ -0,0 +1,28 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+require_once dirname(__FILE__) . '/template_test_case_with_tree.php';
+
+class phpbb_template_template_includecss_test extends phpbb_template_template_test_case_with_tree
+{
+ public function test_includecss_compilation()
+ {
+ // Reset the engine state
+ $this->setup_engine(array('assets_version' => 1));
+
+ // Prepare correct result
+ $scripts = array(
+ '<link href="' . $this->test_path . '/templates/child_only.css?assets_version=1" rel="stylesheet" type="text/css" media="screen, projection" />',
+ '<link href="' . $this->test_path . '/parent_templates/parent_only.css?assets_version=1" rel="stylesheet" type="text/css" media="screen, projection" />',
+ );
+
+ // Run test
+ $this->run_template('includecss.html', array(), array(), array(), implode('', $scripts));
+ }
+}
diff --git a/tests/template/template_includejs_test.php b/tests/template/template_includejs_test.php
new file mode 100644
index 0000000000..b67fa123a1
--- /dev/null
+++ b/tests/template/template_includejs_test.php
@@ -0,0 +1,103 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2011 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+require_once dirname(__FILE__) . '/template_test_case_with_tree.php';
+
+class phpbb_template_template_includejs_test extends phpbb_template_template_test_case_with_tree
+{
+ public function template_data()
+ {
+ return array(
+ /*
+ array(
+ // vars
+ // expected
+ ),
+ */
+ array(
+ array('TEST' => 1),
+ '<script type="text/javascript" src="' . $this->test_path . '/templates/parent_and_child.js?assets_version=1"></script>',
+ ),
+ array(
+ array('TEST' => 2),
+ '<script type="text/javascript" src="' . $this->test_path . '/templates/parent_and_child.js?assets_version=0"></script>',
+ ),
+ array(
+ array('TEST' => 3),
+ '<script type="text/javascript" src="' . $this->test_path . '/templates/parent_and_child.js?test=1&assets_version=0"></script>',
+ ),
+ array(
+ array('TEST' => 4),
+ '<script type="text/javascript" src="' . $this->test_path . '/templates/parent_and_child.js?test=1&amp;assets_version=0"></script>',
+ ),
+ array(
+ array('TEST' => 6),
+ '<script type="text/javascript" src="' . $this->test_path . '/parent_templates/parent_only.js?assets_version=1"></script>',
+ ),
+ array(
+ array('TEST' => 7),
+ '<script type="text/javascript" src="' . $this->test_path . '/templates/child_only.js?assets_version=1"></script>',
+ ),
+ array(
+ array('TEST' => 8),
+ '<script type="text/javascript" src="' . $this->test_path . '/templates/subdir/parent_only.js?assets_version=1"></script>',
+ ),
+ array(
+ array('TEST' => 9),
+ '<script type="text/javascript" src="' . $this->test_path . '/templates/subdir/subsubdir/parent_only.js?assets_version=1"></script>',
+ ),
+ array(
+ array('TEST' => 10),
+ '<script type="text/javascript" src="' . $this->test_path . '/templates/subdir/parent_only.js?assets_version=1"></script>',
+ ),
+ array(
+ array('TEST' => 11),
+ '<script type="text/javascript" src="' . $this->test_path . '/templates/child_only.js?test1=1&amp;test2=2&amp;assets_version=1#test3"></script>',
+ ),
+ array(
+ array('TEST' => 12),
+ '<script type="text/javascript" src="' . $this->test_path . '/parent_templates/parent_only.js?test1=1&amp;test2=2&amp;assets_version=1#test3"></script>',
+ ),
+ array(
+ array('TEST' => 14),
+ '<script type="text/javascript" src="' . $this->test_path . '/parent_templates/parent_only.js?test1=&quot;&amp;assets_version=1#test3"></script>',
+ ),
+ array(
+ array('TEST' => 15),
+ '<script type="text/javascript" src="http://phpbb.com/b.js?c=d#f"></script>',
+ ),
+ array(
+ array('TEST' => 16),
+ '<script type="text/javascript" src="http://phpbb.com/b.js?c=d&assets_version=2#f"></script>',
+ ),
+ array(
+ array('TEST' => 17),
+ '<script type="text/javascript" src="//phpbb.com/b.js"></script>',
+ ),
+ array(
+ array('TEST' => 18),
+ '<script type="text/javascript" src="' . $this->test_path . '/templates/parent_and_child.js?test=1&test2=0&amp;assets_version=1"></script>',
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider template_data
+ */
+ public function test_includejs_compilation($vars, $expected)
+ {
+ // Reset the engine state
+ $this->setup_engine(array('assets_version' => 1));
+
+ $this->template->assign_vars($vars);
+
+ // Run test
+ $this->run_template('includejs.html', array_merge(array('PARENT' => 'parent_only.js', 'SUBDIR' => 'subdir', 'EXT' => 'js'), $vars), array(), array(), $expected);
+ }
+}
diff --git a/tests/template/template_inheritance_test.php b/tests/template/template_inheritance_test.php
new file mode 100644
index 0000000000..cc71ff99e0
--- /dev/null
+++ b/tests/template/template_inheritance_test.php
@@ -0,0 +1,55 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2011 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+require_once dirname(__FILE__) . '/template_test_case_with_tree.php';
+
+class phpbb_template_template_inheritance_test extends phpbb_template_template_test_case_with_tree
+{
+ /**
+ * @todo put test data into templates/xyz.test
+ */
+ public function template_data()
+ {
+ return array(
+ // First element of the array is test name - keep them distinct
+ array(
+ 'simple inheritance - only parent template exists',
+ 'parent_only.html',
+ array(),
+ array(),
+ array(),
+ "Only in parent.",
+ ),
+ array(
+ 'simple inheritance - only child template exists',
+ 'child_only.html',
+ array(),
+ array(),
+ array(),
+ "Only in child.",
+ ),
+ array(
+ 'simple inheritance - both parent and child templates exist',
+ 'parent_and_child.html',
+ array(),
+ array(),
+ array(),
+ "Child template.",
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider template_data
+ */
+ public function test_template($name, $file, array $vars, array $block_vars, array $destroy, $expected)
+ {
+ $this->run_template($file, $vars, $block_vars, $destroy, $expected);
+ }
+}
diff --git a/tests/template/template_parser_test.php b/tests/template/template_parser_test.php
new file mode 100644
index 0000000000..c200770adf
--- /dev/null
+++ b/tests/template/template_parser_test.php
@@ -0,0 +1,29 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
+require_once dirname(__FILE__) . '/template_test_case.php';
+
+class phpbb_template_template_parser_test extends phpbb_template_template_test_case
+{
+ public function test_set_filenames()
+ {
+ $this->template->set_filenames(array(
+ 'basic' => 'basic.html',
+ ));
+
+ $this->assertEquals("passpasspass<!-- DUMMY var -->", str_replace(array("\n", "\r", "\t"), '', $this->template->assign_display('basic')));
+
+ $this->template->set_filenames(array(
+ 'basic' => 'if.html',
+ ));
+
+ $this->assertEquals("03!false", str_replace(array("\n", "\r", "\t"), '', $this->template->assign_display('basic')));
+ }
+}
diff --git a/tests/template/template_test.php b/tests/template/template_test.php
index 94ec2ab8a7..dd9ba21c26 100644
--- a/tests/template/template_test.php
+++ b/tests/template/template_test.php
@@ -8,104 +8,14 @@
*/
require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
-require_once dirname(__FILE__) . '/../../phpBB/includes/template.php';
+require_once dirname(__FILE__) . '/template_test_case.php';
-class phpbb_template_template_test extends phpbb_test_case
+class phpbb_template_template_test extends phpbb_template_template_test_case
{
- private $template;
- private $template_path;
-
- // Keep the contents of the cache for debugging?
- const PRESERVE_CACHE = true;
-
- private function display($handle)
- {
- // allow the templates to throw notices
- $error_level = error_reporting();
- error_reporting($error_level & ~E_NOTICE);
-
- ob_start();
-
- try
- {
- $this->assertTrue($this->template->display($handle, false));
- }
- catch (Exception $exception)
- {
- // reset the error level even when an error occurred
- // PHPUnit turns trigger_error into exceptions as well
- error_reporting($error_level);
- ob_end_clean();
- throw $exception;
- }
-
- $result = self::trim_template_result(ob_get_clean());
-
- // reset error level
- error_reporting($error_level);
- return $result;
- }
-
- private static function trim_template_result($result)
- {
- return str_replace("\n\n", "\n", implode("\n", array_map('trim', explode("\n", trim($result)))));
- }
-
- private function setup_engine()
- {
- $this->template_path = dirname(__FILE__) . '/templates';
- $this->template = new template();
- $this->template->set_custom_template($this->template_path, 'tests');
- }
-
- protected function setUp()
- {
- // Test the engine can be used
- $this->setup_engine();
-
- $template_cache_dir = dirname($this->template->cachepath);
- if (!is_writable($template_cache_dir))
- {
- $this->markTestSkipped("Template cache directory ({$template_cache_dir}) is not writable.");
- }
-
- $file_array = scandir($template_cache_dir);
- $file_prefix = basename($this->template->cachepath);
- foreach ($file_array as $file)
- {
- if (strpos($file, $file_prefix) === 0)
- {
- unlink($template_cache_dir . '/' . $file);
- }
- }
-
- $GLOBALS['config'] = array(
- 'load_tplcompile' => true,
- 'tpl_allow_php' => false,
- );
- }
-
- protected function tearDown()
- {
- if (is_object($this->template))
- {
- $template_cache_dir = dirname($this->template->cachepath);
- $file_array = scandir($template_cache_dir);
- $file_prefix = basename($this->template->cachepath);
- foreach ($file_array as $file)
- {
- if (strpos($file, $file_prefix) === 0)
- {
- unlink($template_cache_dir . '/' . $file);
- }
- }
- }
- }
-
/**
* @todo put test data into templates/xyz.test
*/
- static public function template_data()
+ public function template_data()
{
return array(
/*
@@ -122,7 +32,7 @@ class phpbb_template_template_test extends phpbb_test_case
array(),
array(),
array(),
- "pass\npass\n<!-- DUMMY var -->",
+ "pass\npass\npass\n<!-- DUMMY var -->",
),
array(
'variable.html',
@@ -136,28 +46,42 @@ class phpbb_template_template_test extends phpbb_test_case
array(),
array(),
array(),
- '0',
+ '03!false',
),
array(
'if.html',
array('S_VALUE' => true),
array(),
array(),
- "1\n0",
+ '1!false',
),
array(
'if.html',
array('S_VALUE' => true, 'S_OTHER_VALUE' => true),
array(),
array(),
- '1',
+ '1!false',
),
array(
'if.html',
array('S_VALUE' => false, 'S_OTHER_VALUE' => true),
array(),
array(),
- '2',
+ '2!false',
+ ),
+ array(
+ 'if.html',
+ array('S_TEST' => false),
+ array(),
+ array(),
+ '03false',
+ ),
+ array(
+ 'if.html',
+ array('S_TEST' => 0),
+ array(),
+ array(),
+ '03!false',
),
array(
'loop.html',
@@ -192,22 +116,22 @@ class phpbb_template_template_test extends phpbb_test_case
array(),
array('loop' => array(array('VARIABLE' => 'x'))),
array(),
- "first\n0\nx\nset\nlast",
- ),/* no nested top level loops
+ "first\n0 - a\nx - b\nset\nlast",
+ ),
array(
'loop_vars.html',
array(),
array('loop' => array(array('VARIABLE' => 'x'), array('VARIABLE' => 'y'))),
array(),
- "first\n0\n0\n2\nx\nset\n1\n1\n2\ny\nset\nlast",
+ "first\n0 - a\nx - b\nset\n1 - a\ny - b\nset\nlast",
),
array(
'loop_vars.html',
array(),
array('loop' => array(array('VARIABLE' => 'x'), array('VARIABLE' => 'y')), 'loop.inner' => array(array(), array())),
array(),
- "first\n0\n0\n2\nx\nset\n1\n1\n2\ny\nset\nlast\n0\n\n1\nlast inner\ninner loop",
- ),*/
+ "first\n0 - a\nx - b\nset\n1 - a\ny - b\nset\nlast\n0 - c\n1 - c\nlast inner",
+ ),
array(
'loop_advanced.html',
array(),
@@ -216,18 +140,41 @@ class phpbb_template_template_test extends phpbb_test_case
"101234561\nx\n101234561\nx\n101234561\nx\n1234561\nx\n1\nx\n101\nx\n234\nx\n10\nx\n561\nx\n561",
),
array(
+ 'loop_nested2.html',
+ array(),
+ array('outer' => array(array(), array()), 'outer.middle' => array(array(), array())),
+ array(),
+ "o0o1m01m11",
+ ),
+ array(
'define.html',
array(),
array('loop' => array(array(), array(), array(), array(), array(), array(), array()), 'test' => array(array()), 'test.deep' => array(array()), 'test.deep.defines' => array(array())),
array(),
- "xyz\nabc",
+ "xyz\nabc\n\$VALUE == 'abc'abc\nbar\nbar\nabc\ntest!@#$%^&*()_-=+{}[]:;\",<.>/?",
+ ),
+ array(
+ 'define_advanced.html',
+ array(),
+ array('loop' => array(array(), array(), array(), array(), array(), array(), array()), 'test' => array(array()), 'test.deep' => array(array()), 'test.deep.defines' => array(array())),
+ array(),
+ "abc\nzxc\ncde\nbcd",
),
array(
'expressions.html',
array(),
array(),
array(),
- trim(str_repeat("pass", 39)),
+ trim(str_repeat("pass\n", 10) . "\n"
+ . str_repeat("pass\n", 4) . "\n"
+ . str_repeat("pass\n", 2) . "\n"
+ . str_repeat("pass\n", 6) . "\n"
+ . str_repeat("pass\n", 2) . "\n"
+ . str_repeat("pass\n", 6) . "\n"
+ . str_repeat("pass\n", 2) . "\n"
+ . str_repeat("pass\n", 2) . "\n"
+ . str_repeat("pass\n", 3) . "\n"
+ . str_repeat("pass\n", 2) . "\n"),
),
array(
'php.html',
@@ -251,6 +198,27 @@ class phpbb_template_template_test extends phpbb_test_case
'value',
),
array(
+ 'include_loop.html',
+ array(),
+ array('loop' => array(array('NESTED_FILE' => 'include_loop1.html')), 'loop.inner' => array(array('NESTED_FILE' => 'include_loop1.html'), array('NESTED_FILE' => 'include_loop2.html'), array('NESTED_FILE' => 'include_loop3.html'))),
+ array(),
+ "1\n_1\n_02\n_3",
+ ),
+ array(
+ 'include_variable.html',
+ array('FILE' => 'variable.html', 'VARIABLE' => 'value'),
+ array(),
+ array(),
+ 'value',
+ ),
+ array(
+ 'include_variables.html',
+ array('SUBDIR' => 'subdir', 'VARIABLE' => 'value'),
+ array(),
+ array(),
+ 'value',
+ ),
+ array(
'loop_vars.html',
array(),
array('loop' => array(array('VARIABLE' => 'x'), array('VARIABLE' => 'y')), 'loop.inner' => array(array(), array())),
@@ -280,25 +248,73 @@ class phpbb_template_template_test extends phpbb_test_case
"first\n0\n0\n2\nx\nset\n1\n1\n2\ny\nset\nlast",
),*/
array(
- 'lang.html',
+ // Just like a regular loop but the name begins
+ // with an underscore
+ 'loop_underscore.html',
array(),
array(),
array(),
- "{ VARIABLE }\n{ VARIABLE }",
+ "noloop\nnoloop",
),
array(
'lang.html',
- array('L_VARIABLE' => "Value'"),
array(),
array(),
- "Value'\nValue\'",
+ array(),
+ "VARIABLE\n1_VARIABLE\nVARIABLE\n1_VARIABLE",
),
array(
'lang.html',
- array('LA_VARIABLE' => "Value'"),
array(),
array(),
- "{ VARIABLE }\nValue'",
+ array(),
+ "Value'\n1 O'Clock\nValue\'\n1 O\'Clock",
+ array('VARIABLE' => "Value'", '1_VARIABLE' => "1 O'Clock"),
+ ),
+ array(
+ 'loop_nested_multilevel_ref.html',
+ array(),
+ array(),
+ array(),
+ "top-level content",
+ ),
+ array(
+ 'loop_nested_multilevel_ref.html',
+ array(),
+ array('outer' => array(array('VARIABLE' => 'x'), array('VARIABLE' => 'y')), 'outer.inner' => array(array('VARIABLE' => 'z'), array('VARIABLE' => 'zz'))),
+ array(),
+ "top-level content\nouter x\nouter y\ninner z\nfirst row\n\ninner zz",
+ ),
+ array(
+ 'loop_nested_deep_multilevel_ref.html',
+ array(),
+ array('outer' => array(array()), 'outer.middle' => array(array()), 'outer.middle.inner' => array(array('VARIABLE' => 'z'), array('VARIABLE' => 'zz'))),
+ array(),
+ "top-level content\nouter\nmiddle\ninner z\nfirst row of 2 in inner\n\ninner zz",
+ ),
+ array(
+ 'loop_size.html',
+ array(),
+ array('loop' => array(array()), 'empty_loop' => array()),
+ array(),
+ "nonexistent = 0\n! nonexistent\n\nempty = 0\n! empty\nloop\n\nin loop",
+ ),
+ /* Does not pass with the current implementation.
+ array(
+ 'loop_reuse.html',
+ array(),
+ array('one' => array(array('VAR' => 'a'), array('VAR' => 'b')), 'one.one' => array(array('VAR' => 'c'), array('VAR' => 'd'))),
+ array(),
+ // Not entirely sure what should be outputted but the current output of "a" is most certainly wrong
+ "a\nb\nc\nd",
+ ),
+ */
+ array(
+ 'twig.html',
+ array('VARIABLE' => 'FOObar',),
+ array(),
+ array(),
+ "13FOOBAR|foobar",
),
);
}
@@ -310,149 +326,96 @@ class phpbb_template_template_test extends phpbb_test_case
$this->template->set_filenames(array('test' => $filename));
$this->assertFileNotExists($this->template_path . '/' . $filename, 'Testing missing file, file cannot exist');
- $expecting = sprintf('template->_tpl_load_file(): File %s does not exist or is empty', realpath($this->template_path . '/../') . '/templates/' . $filename);
- $this->setExpectedTriggerError(E_USER_ERROR, $expecting);
+ $this->setExpectedException('Twig_Error_Loader');
$this->display('test');
}
- public function test_empty_file()
- {
- $expecting = 'template->set_filenames: Empty filename specified for test';
-
- $this->setExpectedTriggerError(E_USER_ERROR, $expecting);
- $this->template->set_filenames(array('test' => ''));
- }
public function test_invalid_handle()
{
- $expecting = 'template->_tpl_load(): No file specified for handle test';
- $this->setExpectedTriggerError(E_USER_ERROR, $expecting);
+ $this->setExpectedException('Twig_Error_Loader');
$this->display('test');
}
- private function run_template($file, array $vars, array $block_vars, array $destroy, $expected, $cache_file)
- {
- $this->template->set_filenames(array('test' => $file));
- $this->template->assign_vars($vars);
-
- foreach ($block_vars as $block => $loops)
- {
- foreach ($loops as $_vars)
- {
- $this->template->assign_block_vars($block, $_vars);
- }
- }
-
- foreach ($destroy as $block)
- {
- $this->template->destroy_block_vars($block);
- }
-
- try
- {
- $this->assertEquals($expected, $this->display('test'), "Testing $file");
- $this->assertFileExists($cache_file);
- }
- catch (ErrorException $e)
- {
- if (file_exists($cache_file))
- {
- copy($cache_file, str_replace('ctpl_', 'tests_ctpl_', $cache_file));
- }
-
- throw $e;
- }
-
- // For debugging
- if (self::PRESERVE_CACHE)
- {
- copy($cache_file, str_replace('ctpl_', 'tests_ctpl_', $cache_file));
- }
- }
-
/**
* @dataProvider template_data
*/
- public function test_template($file, array $vars, array $block_vars, array $destroy, $expected)
+ public function test_template($file, array $vars, array $block_vars, array $destroy, $expected, $lang_vars = array())
{
- $cache_file = $this->template->cachepath . str_replace('/', '.', $file) . '.php';
+ $this->run_template($file, $vars, $block_vars, $destroy, $expected, $lang_vars);
+ }
- $this->assertFileNotExists($cache_file);
+ public function test_assign_display()
+ {
+ $this->run_template('basic.html', array(), array(), array(), "pass\npass\npass\n<!-- DUMMY var -->");
- $this->run_template($file, $vars, $block_vars, $destroy, $expected, $cache_file);
+ $this->template->set_filenames(array(
+ 'test' => 'basic.html',
+ 'container' => 'variable.html',
+ ));
- // Reset the engine state
- $this->setup_engine();
+ $this->template->assign_display('test', 'VARIABLE', false);
- $this->run_template($file, $vars, $block_vars, $destroy, $expected, $cache_file);
+ $this->assertEquals("pass\npass\npass\n<!-- DUMMY var -->", $this->display('container'), "Testing assign_display($file)");
}
- /**
- * @dataProvider template_data
- */
- public function test_assign_display($file, array $vars, array $block_vars, array $destroy, $expected)
+ public function test_append_var_without_assign_var()
{
$this->template->set_filenames(array(
- 'test' => $file,
- 'container' => 'variable.html',
+ 'append_var' => 'variable.html'
));
- $this->template->assign_vars($vars);
- foreach ($block_vars as $block => $loops)
- {
- foreach ($loops as $_vars)
- {
- $this->template->assign_block_vars($block, $_vars);
- }
- }
+ $items = array('This ', 'is ', 'a ', 'test');
+ $expecting = implode('', $items);
- foreach ($destroy as $block)
+ foreach ($items as $word)
{
- $this->template->destroy_block_vars($block);
+ $this->template->append_var('VARIABLE', $word);
}
- $error_level = error_reporting();
- error_reporting($error_level & ~E_NOTICE);
-
- $this->assertEquals($expected, self::trim_template_result($this->template->assign_display('test')), "Testing assign_display($file)");
-
- $this->template->assign_display('test', 'VARIABLE', false);
-
- error_reporting($error_level);
-
- $this->assertEquals($expected, $this->display('container'), "Testing assign_display($file)");
+ $this->assertEquals($expecting, $this->display('append_var'));
}
- public function test_php()
+ public function test_append_var_with_assign_var()
{
- $GLOBALS['config']['tpl_allow_php'] = true;
-
- $cache_file = $this->template->cachepath . 'php.html.php';
+ $this->template->set_filenames(array(
+ 'append_var' => 'variable.html'
+ ));
- $this->assertFileNotExists($cache_file);
+ $start = 'This ';
+ $items = array('is ', 'a ', 'test');
+ $expecting = $start . implode('', $items);
- $this->run_template('php.html', array(), array(), array(), 'test', $cache_file);
+ $this->template->assign_var('VARIABLE', $start);
+ foreach ($items as $word)
+ {
+ $this->template->append_var('VARIABLE', $word);
+ }
- $GLOBALS['config']['tpl_allow_php'] = false;
+ $this->assertEquals($expecting, $this->display('append_var'));
}
- public function test_includephp()
+ public function test_php()
{
- $GLOBALS['config']['tpl_allow_php'] = true;
+ global $phpbb_root_path;
- $cache_file = $this->template->cachepath . 'includephp.html.php';
+ $template_text = '<!-- PHP -->echo "test";<!-- ENDPHP -->';
- $this->run_template('includephp.html', array(), array(), array(), 'testing included php', $cache_file);
+ $cache_dir = $phpbb_root_path . 'cache/';
+ $fp = fopen($cache_dir . 'php.html', 'w');
+ fputs($fp, $template_text);
+ fclose($fp);
- $this->template->set_filenames(array('test' => 'includephp.html'));
- $this->assertEquals('testing included php', $this->display('test'), "Testing INCLUDEPHP");
+ $this->setup_engine(array('tpl_allow_php' => true));
- $GLOBALS['config']['tpl_allow_php'] = false;
+ $this->style->set_custom_style('tests', $cache_dir, array(), '');
+
+ $this->run_template('php.html', array(), array(), array(), 'test');
}
- static public function alter_block_array_data()
+ public function alter_block_array_data()
{
return array(
array(
@@ -555,10 +518,40 @@ EOT
$this->template->assign_block_vars('outer.middle', array());
$this->template->assign_block_vars('outer.middle', array());
- $this->assertEquals("outer - 0\nmiddle - 0\nmiddle - 1\nouter - 1\nmiddle - 0\nmiddle - 1\nouter - 2\nmiddle - 0\nmiddle - 1", $this->display('test'), 'Ensuring template is built correctly before modification');
+ $this->assertEquals("outer - 0middle - 0middle - 1outer - 1middle - 0middle - 1outer - 2middle - 0middle - 1", $this->display('test'), 'Ensuring template is built correctly before modification');
$this->template->alter_block_array($alter_block, $vararray, $key, $mode);
- $this->assertEquals($expect, $this->display('test'), $description);
+ $this->assertEquals(str_replace(array("\n", "\r", "\t"), '', $expect), str_replace(array("\n", "\r", "\t"), '', $this->display('test')), $description);
}
-}
+ public function test_more_alter_block_array()
+ {
+ $this->template->set_filenames(array('test' => 'loop_nested.html'));
+
+ $this->template->assign_var('TEST_MORE', true);
+
+ // @todo Change this
+ $this->template->assign_block_vars('outer', array());
+ $this->template->assign_block_vars('outer.middle', array());
+ $this->template->assign_block_vars('outer', array());
+ $this->template->assign_block_vars('outer.middle', array());
+ $this->template->assign_block_vars('outer.middle', array());
+ $this->template->assign_block_vars('outer', array());
+ $this->template->assign_block_vars('outer.middle', array());
+ $this->template->assign_block_vars('outer.middle', array());
+ $this->template->assign_block_vars('outer.middle', array());
+
+ $expect = 'outer - 0[outer|3]middle - 0[middle|1]outer - 1[outer|3]middle - 0[middle|2]middle - 1[middle|2]outer - 2[outer|3]middle - 0[middle|3]middle - 1[middle|3]middle - 2[middle|3]';
+ $this->assertEquals($expect, str_replace(array("\n", "\r", "\t"), '', $this->display('test')), 'Ensuring template is built correctly before modification');
+
+ $this->template->alter_block_array('outer', array());
+
+ $expect = 'outer - 0[outer|4]outer - 1[outer|4]middle - 0[middle|1]outer - 2[outer|4]middle - 0[middle|2]middle - 1[middle|2]outer - 3[outer|4]middle - 0[middle|3]middle - 1[middle|3]middle - 2[middle|3]';
+ $this->assertEquals($expect, str_replace(array("\n", "\r", "\t"), '', $this->display('test')), 'Ensuring S_NUM_ROWS is correct after insertion');
+
+ $this->template->alter_block_array('outer', array('VARIABLE' => 'test'), 2, 'change');
+
+ $expect = 'outer - 0[outer|4]outer - 1[outer|4]middle - 0[middle|1]outer - 2 - test[outer|4]middle - 0[middle|2]middle - 1[middle|2]outer - 3[outer|4]middle - 0[middle|3]middle - 1[middle|3]middle - 2[middle|3]';
+ $this->assertEquals($expect, str_replace(array("\n", "\r", "\t"), '', $this->display('test')), 'Ensuring S_NUM_ROWS is correct after modification');
+ }
+}
diff --git a/tests/template/template_test_case.php b/tests/template/template_test_case.php
new file mode 100644
index 0000000000..6d87e5ebc0
--- /dev/null
+++ b/tests/template/template_test_case.php
@@ -0,0 +1,124 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2011 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
+
+class phpbb_template_template_test_case extends phpbb_test_case
+{
+ protected $style;
+ protected $template;
+ protected $template_path;
+ protected $style_resource_locator;
+ protected $style_provider;
+ protected $user;
+
+ protected $test_path = 'tests/template';
+
+ // Keep the contents of the cache for debugging?
+ const PRESERVE_CACHE = true;
+
+ protected function display($handle)
+ {
+ ob_start();
+
+ try
+ {
+ $this->template->display($handle, false);
+ }
+ catch (Exception $exception)
+ {
+ // reset output buffering even when an error occurred
+ // PHPUnit turns trigger_error into exceptions as well
+ ob_end_clean();
+ throw $exception;
+ }
+
+ $result = self::trim_template_result(ob_get_clean());
+
+ return $result;
+ }
+
+ protected static function trim_template_result($result)
+ {
+ return str_replace("\n\n", "\n", implode("\n", array_map('trim', explode("\n", trim($result)))));
+ }
+
+ protected function config_defaults()
+ {
+ $defaults = array(
+ 'load_tplcompile' => true,
+ 'tpl_allow_php' => false,
+ );
+ return $defaults;
+ }
+
+ protected function setup_engine(array $new_config = array())
+ {
+ global $phpbb_root_path, $phpEx;
+
+ $defaults = $this->config_defaults();
+ $config = new phpbb_config(array_merge($defaults, $new_config));
+ $this->user = new phpbb_user;
+
+ $this->template_path = $this->test_path . '/templates';
+ $this->style_resource_locator = new phpbb_style_resource_locator();
+ $this->style_provider = new phpbb_style_path_provider();
+ $this->template = new phpbb_template_twig($phpbb_root_path, $phpEx, $config, $this->user, new phpbb_template_context());
+ $this->style = new phpbb_style($phpbb_root_path, $phpEx, $config, $this->user, $this->style_resource_locator, $this->style_provider, $this->template);
+ $this->style->set_custom_style('tests', $this->template_path, array(), '');
+ }
+
+ protected function setUp()
+ {
+ // Test the engine can be used
+ $this->setup_engine();
+
+ $this->template->clear_cache();
+ }
+
+ protected function tearDown()
+ {
+ if ($this->template)
+ {
+ $this->template->clear_cache();
+ }
+ }
+
+ protected function run_template($file, array $vars, array $block_vars, array $destroy, $expected, $lang_vars = array())
+ {
+ $this->template->set_filenames(array('test' => $file));
+ $this->template->assign_vars($vars);
+
+ foreach ($block_vars as $block => $loops)
+ {
+ foreach ($loops as $_vars)
+ {
+ $this->template->assign_block_vars($block, $_vars);
+ }
+ }
+
+ foreach ($destroy as $block)
+ {
+ $this->template->destroy_block_vars($block);
+ }
+
+ // Previous functionality was $cachefile (string), which was removed, check to prevent errors
+ if (is_array($lang_vars))
+ {
+ foreach ($lang_vars as $name => $value)
+ {
+ $this->user->lang[$name] = $value;
+ }
+ }
+
+ $expected = str_replace(array("\n", "\r", "\t"), '', $expected);
+ $output = str_replace(array("\n", "\r", "\t"), '', $this->display('test'));
+ $this->assertEquals($expected, $output, "Testing $file");
+ }
+}
diff --git a/tests/template/template_test_case_with_tree.php b/tests/template/template_test_case_with_tree.php
new file mode 100644
index 0000000000..4b8cbada45
--- /dev/null
+++ b/tests/template/template_test_case_with_tree.php
@@ -0,0 +1,29 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2011 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+require_once dirname(__FILE__) . '/template_test_case.php';
+
+class phpbb_template_template_test_case_with_tree extends phpbb_template_template_test_case
+{
+ protected function setup_engine(array $new_config = array())
+ {
+ global $phpbb_root_path, $phpEx, $user;
+
+ $defaults = $this->config_defaults();
+ $config = new phpbb_config(array_merge($defaults, $new_config));
+
+ $this->template_path = $this->test_path . '/templates';
+ $this->parent_template_path = $this->test_path . '/parent_templates';
+ $this->style_resource_locator = new phpbb_style_resource_locator();
+ $this->style_provider = new phpbb_style_path_provider();
+ $this->template = new phpbb_template_twig($phpbb_root_path, $phpEx, $config, $user, new phpbb_template_context());
+ $this->style = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $this->style_resource_locator, $this->style_provider, $this->template);
+ $this->style->set_custom_style('tests', array($this->template_path, $this->parent_template_path), array(), '');
+ }
+}
diff --git a/tests/template/templates/basic.html b/tests/template/templates/basic.html
index c1dd690260..e5c6f280fb 100644
--- a/tests/template/templates/basic.html
+++ b/tests/template/templates/basic.html
@@ -16,5 +16,8 @@ fail
<!-- BEGINELSE -->
pass
<!-- END empty -->
+<!-- IF not S_EMPTY -->
+pass
+<!-- ENDIF -->
<!-- DUMMY var -->
diff --git a/tests/template/templates/child_only.css b/tests/template/templates/child_only.css
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/template/templates/child_only.css
diff --git a/tests/template/templates/child_only.html b/tests/template/templates/child_only.html
new file mode 100644
index 0000000000..6121fef5c5
--- /dev/null
+++ b/tests/template/templates/child_only.html
@@ -0,0 +1 @@
+Only in child.
diff --git a/tests/template/templates/child_only.js b/tests/template/templates/child_only.js
new file mode 100644
index 0000000000..542b26526c
--- /dev/null
+++ b/tests/template/templates/child_only.js
@@ -0,0 +1 @@
+// JavaScript file only in a child style.
diff --git a/tests/template/templates/define.html b/tests/template/templates/define.html
index 82237d21a3..66e874ca63 100644
--- a/tests/template/templates/define.html
+++ b/tests/template/templates/define.html
@@ -2,7 +2,15 @@
{$VALUE}
<!-- DEFINE $VALUE = 'abc' -->
{$VALUE}
+<!-- IF $VALUE != 'abc' -->
+$VALUE != 'abc'
+<!-- ELSEIF $VALUE == 'abc' -->
+$VALUE == 'abc'
+<!-- ENDIF -->
+<!-- INCLUDE define_include.html -->
+{$INCLUDED_VALUE}
+{$VALUE}
<!-- UNDEFINE $VALUE -->
{$VALUE}
-<!-- DEFINE $VALUE -->
-
+<!-- DEFINE $VALUE = 'test!@#$%^&*()_-=+{}[]:;",<.>/?' -->
+{$VALUE}
diff --git a/tests/template/templates/define_advanced.html b/tests/template/templates/define_advanced.html
new file mode 100644
index 0000000000..83467a5b4b
--- /dev/null
+++ b/tests/template/templates/define_advanced.html
@@ -0,0 +1,12 @@
+<!-- DEFINE $VALUE -->
+abc
+<!-- ENDDEFINE -->
+{$VALUE}
+<!-- DEFINE $VALUE1 -->
+bcd
+<!-- ENDDEFINE -->
+<!-- DEFINE $VALUE2 -->
+cde
+<!-- ENDDEFINE -->
+<!-- INCLUDE define_include2.html -->
+{$INCLUDED_VALUE3}
diff --git a/tests/template/templates/define_include.html b/tests/template/templates/define_include.html
new file mode 100644
index 0000000000..9c470c296a
--- /dev/null
+++ b/tests/template/templates/define_include.html
@@ -0,0 +1,3 @@
+{$VALUE}
+<!-- DEFINE $INCLUDED_VALUE = 'bar' -->
+{$INCLUDED_VALUE}
diff --git a/tests/template/templates/define_include2.html b/tests/template/templates/define_include2.html
new file mode 100644
index 0000000000..874f3e1852
--- /dev/null
+++ b/tests/template/templates/define_include2.html
@@ -0,0 +1,11 @@
+<!-- DEFINE $INCLUDED_VALUE1 -->
+zxc
+<!-- ENDDEFINE -->
+<!-- DEFINE $INCLUDED_VALUE2 -->
+qwe
+<!-- ENDDEFINE -->
+{$INCLUDED_VALUE1}
+<!-- DEFINE $INCLUDED_VALUE3 -->
+{$VALUE2}
+{$VALUE1}
+<!-- ENDDEFINE -->
diff --git a/tests/template/templates/events.html b/tests/template/templates/events.html
new file mode 100644
index 0000000000..c44a7469e7
--- /dev/null
+++ b/tests/template/templates/events.html
@@ -0,0 +1,4 @@
+<!-- EVENT child_only -->
+<!-- EVENT parent_only -->
+<!-- EVENT parent_and_child -->
+<!-- EVENT random_event -->
diff --git a/tests/template/templates/expressions.html b/tests/template/templates/expressions.html
index c40d967dab..e1283f165f 100644
--- a/tests/template/templates/expressions.html
+++ b/tests/template/templates/expressions.html
@@ -1,86 +1,57 @@
<!-- IF 10 is even -->pass<!-- ELSE -->fail<!-- ENDIF -->
-
<!-- IF 9 is even -->fail<!-- ELSE -->pass<!-- ENDIF -->
-
<!-- IF not 390 is even -->fail<!-- ELSE -->pass<!-- ENDIF -->
-
<!-- IF 9 is odd -->pass<!-- ELSE -->fail<!-- ENDIF -->
-
<!-- IF 32 is odd -->fail<!-- ELSE -->pass<!-- ENDIF -->
-
<!-- IF 32 is div by 16 -->pass<!-- ELSE -->fail<!-- ENDIF -->
-
<!-- IF 10 is not even -->fail<!-- ELSE -->pass<!-- ENDIF -->
-
<!-- IF 24 == 24 -->pass<!-- ELSE -->fail<!-- ENDIF -->
-
<!-- IF 24 eq 24 -->pass<!-- ELSE -->fail<!-- ENDIF -->
-
<!-- IF ((((((24 == 24)))))) -->pass<!-- ELSE -->fail<!-- ENDIF -->
<!-- IF 24 != 20 -->pass<!-- ELSE -->fail<!-- ENDIF -->
-
<!-- IF 24 <> 20 -->pass<!-- ELSE -->fail<!-- ENDIF -->
-
<!-- IF 24 ne 20 -->pass<!-- ELSE -->fail<!-- ENDIF -->
-
<!-- IF 24 neq 20 -->pass<!-- ELSE -->fail<!-- ENDIF -->
<!-- IF 10 lt 20 -->pass<!-- ELSE -->fail<!-- ENDIF -->
-
<!-- IF 10 < 20 -->pass<!-- ELSE -->fail<!-- ENDIF -->
<!-- IF 10 le 20 -->pass<!-- ELSE -->fail<!-- ENDIF -->
-
<!-- IF 10 lte 20 -->pass<!-- ELSE -->fail<!-- ENDIF -->
-
<!-- IF 10 <= 20 -->pass<!-- ELSE -->fail<!-- ENDIF -->
-
<!-- IF 20 le 20 -->pass<!-- ELSE -->fail<!-- ENDIF -->
-
<!-- IF 20 lte 20 -->pass<!-- ELSE -->fail<!-- ENDIF -->
-
<!-- IF 20 <= 20 -->pass<!-- ELSE -->fail<!-- ENDIF -->
<!-- IF 9 gt 1 -->pass<!-- ELSE -->fail<!-- ENDIF -->
-
<!-- IF 9 > 1 -->pass<!-- ELSE -->fail<!-- ENDIF -->
<!-- IF 9 >= 1 -->pass<!-- ELSE -->fail<!-- ENDIF -->
-
<!-- IF 9 gte 1 -->pass<!-- ELSE -->fail<!-- ENDIF -->
-
<!-- IF 9 ge 1 -->pass<!-- ELSE -->fail<!-- ENDIF -->
-
<!-- IF 9 >= 9 -->pass<!-- ELSE -->fail<!-- ENDIF -->
-
<!-- IF 9 gte 9 -->pass<!-- ELSE -->fail<!-- ENDIF -->
-
<!-- IF 9 ge 9 -->pass<!-- ELSE -->fail<!-- ENDIF -->
<!-- IF true && (10 > 4) -->pass<!-- ELSE -->fail<!-- ENDIF -->
-
<!-- IF true and (10 > 4) -->pass<!-- ELSE -->fail<!-- ENDIF -->
<!-- IF false || true -->pass<!-- ELSE -->fail<!-- ENDIF -->
-
<!-- IF false or true -->pass<!-- ELSE -->fail<!-- ENDIF -->
<!-- IF !false -->pass<!-- ELSE -->fail<!-- ENDIF -->
-
<!-- IF not false -->pass<!-- ELSE -->fail<!-- ENDIF -->
-
<!-- IF not not not false -->pass<!-- ELSE -->fail<!-- ENDIF -->
<!-- IF 6 % 4 == 2 -->pass<!-- ELSE -->fail<!-- ENDIF -->
-
<!-- IF 24 mod 12 == 0 -->pass<!-- ELSE -->fail<!-- ENDIF -->
diff --git a/tests/template/templates/if.html b/tests/template/templates/if.html
index c502e52f51..c010aff7fa 100644
--- a/tests/template/templates/if.html
+++ b/tests/template/templates/if.html
@@ -3,9 +3,17 @@
<!-- ELSEIF S_OTHER_VALUE -->
2
<!-- ELSE -->
-0
+03
<!-- ENDIF -->
-<!-- IF (S_VALUE > S_OTHER_VALUE) -->
-0
+<!-- IF S_VALUE and S_OTHER_VALUE and (S_VALUE > S_OTHER_VALUE) -->
+04
+<!-- ENDIF -->
+
+<!-- IF S_TEST === false -->
+false
+<!-- ENDIF -->
+
+<!-- IF S_TEST !== false -->
+!false
<!-- ENDIF -->
diff --git a/tests/template/templates/include_loop.html b/tests/template/templates/include_loop.html
new file mode 100644
index 0000000000..d5c3d9bc82
--- /dev/null
+++ b/tests/template/templates/include_loop.html
@@ -0,0 +1,4 @@
+<!-- BEGIN loop -->
+<!-- INCLUDE {loop.NESTED_FILE} -->
+<!-- BEGIN inner -->_<!-- INCLUDE {inner.NESTED_FILE} --><!-- END inner -->
+<!-- END loop -->
diff --git a/tests/template/templates/include_loop1.html b/tests/template/templates/include_loop1.html
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/tests/template/templates/include_loop1.html
@@ -0,0 +1 @@
+1
diff --git a/tests/template/templates/include_loop2.html b/tests/template/templates/include_loop2.html
new file mode 100644
index 0000000000..9e22bcb8e3
--- /dev/null
+++ b/tests/template/templates/include_loop2.html
@@ -0,0 +1 @@
+02
diff --git a/tests/template/templates/include_loop3.html b/tests/template/templates/include_loop3.html
new file mode 100644
index 0000000000..00750edc07
--- /dev/null
+++ b/tests/template/templates/include_loop3.html
@@ -0,0 +1 @@
+3
diff --git a/tests/template/templates/include_variable.html b/tests/template/templates/include_variable.html
new file mode 100644
index 0000000000..b907e0b44f
--- /dev/null
+++ b/tests/template/templates/include_variable.html
@@ -0,0 +1 @@
+<!-- INCLUDE {FILE} -->
diff --git a/tests/template/templates/include_variables.html b/tests/template/templates/include_variables.html
new file mode 100644
index 0000000000..8371a061b5
--- /dev/null
+++ b/tests/template/templates/include_variables.html
@@ -0,0 +1 @@
+<!-- INCLUDE {SUBDIR}/variable.html -->
diff --git a/tests/template/templates/includecss.html b/tests/template/templates/includecss.html
new file mode 100644
index 0000000000..a09e44f240
--- /dev/null
+++ b/tests/template/templates/includecss.html
@@ -0,0 +1,3 @@
+<!-- INCLUDECSS child_only.css -->
+<!-- INCLUDECSS parent_only.css -->
+{$STYLESHEETS}
diff --git a/tests/template/templates/includejs.html b/tests/template/templates/includejs.html
new file mode 100644
index 0000000000..0bcdf1a815
--- /dev/null
+++ b/tests/template/templates/includejs.html
@@ -0,0 +1,36 @@
+<!-- IF TEST === 1 -->
+ <!-- INCLUDEJS parent_and_child.js -->
+<!-- ELSEIF TEST === 2 -->
+ <!-- INCLUDEJS parent_and_child.js?assets_version=0 -->
+<!-- ELSEIF TEST === 3 -->
+ <!-- INCLUDEJS parent_and_child.js?test=1&assets_version=0 -->
+<!-- ELSEIF TEST === 4 -->
+ <!-- INCLUDEJS parent_and_child.js?test=1&amp;assets_version=0 -->
+<!-- ELSEIF TEST === 6 -->
+ <!-- INCLUDEJS {PARENT} -->
+<!-- ELSEIF TEST === 7 -->
+ <!-- DEFINE $TEST = 'child_only.js' -->
+ <!-- INCLUDEJS {$TEST} -->
+<!-- ELSEIF TEST === 8 -->
+ <!-- INCLUDEJS subdir/{PARENT} -->
+<!-- ELSEIF TEST === 9 -->
+ <!-- INCLUDEJS {SUBDIR}/subsubdir/{PARENT} -->
+<!-- ELSEIF TEST === 10 -->
+ <!-- INCLUDEJS {SUBDIR}/parent_only.{EXT} -->
+<!-- ELSEIF TEST === 11 -->
+ <!-- DEFINE $TEST = 'child_only.js?test1=1&amp;test2=2#test3' -->
+ <!-- INCLUDEJS {$TEST} -->
+<!-- ELSEIF TEST === 12 -->
+ <!-- INCLUDEJS parent_only.js?test1=1&amp;test2=2#test3 -->
+<!-- ELSEIF TEST === 14 -->
+ <!-- INCLUDEJS parent_only.js?test1=&quot;#test3 -->
+<!-- ELSEIF TEST === 15 -->
+ <!-- INCLUDEJS http://phpbb.com/b.js?c=d#f -->
+<!-- ELSEIF TEST === 16 -->
+ <!-- INCLUDEJS http://phpbb.com/b.js?c=d&assets_version=2#f -->
+<!-- ELSEIF TEST === 17 -->
+ <!-- INCLUDEJS //phpbb.com/b.js -->
+<!-- ELSEIF TEST === 18 -->
+ <!-- INCLUDEJS parent_and_child.js?test=1&test2=0 -->
+<!-- ENDIF -->
+{$SCRIPTS}
diff --git a/tests/template/templates/includephp.html b/tests/template/templates/includephp_relative.html
index 70ebdac0d0..297c9efcb0 100644
--- a/tests/template/templates/includephp.html
+++ b/tests/template/templates/includephp_relative.html
@@ -1 +1,2 @@
+Path is relative to board root.
<!-- INCLUDEPHP ../tests/template/templates/_dummy_include.php.inc -->
diff --git a/tests/template/templates/includephp_variables.html b/tests/template/templates/includephp_variables.html
new file mode 100644
index 0000000000..6106efc86a
--- /dev/null
+++ b/tests/template/templates/includephp_variables.html
@@ -0,0 +1,2 @@
+Path includes variables.
+<!-- INCLUDEPHP ../tests/template/{TEMPLATES}/_dummy_include.php.inc -->
diff --git a/tests/template/templates/invalid/endif_without_if.html b/tests/template/templates/invalid/endif_without_if.html
new file mode 100644
index 0000000000..e371ffd150
--- /dev/null
+++ b/tests/template/templates/invalid/endif_without_if.html
@@ -0,0 +1 @@
+<!-- ENDIF -->
diff --git a/tests/template/templates/invalid/output/endif_without_if.html b/tests/template/templates/invalid/output/endif_without_if.html
new file mode 100644
index 0000000000..5f2239c964
--- /dev/null
+++ b/tests/template/templates/invalid/output/endif_without_if.html
@@ -0,0 +1 @@
+Parse error (fatal, destroys php runtime).
diff --git a/tests/template/templates/invalid/output/include_nonexistent_file.html b/tests/template/templates/invalid/output/include_nonexistent_file.html
new file mode 100644
index 0000000000..8a118d2713
--- /dev/null
+++ b/tests/template/templates/invalid/output/include_nonexistent_file.html
@@ -0,0 +1 @@
+style resource locator: File for handle nonexistent.html does not exist. Could not find:
diff --git a/tests/template/templates/invalid/output/unknown_tag.html b/tests/template/templates/invalid/output/unknown_tag.html
new file mode 100644
index 0000000000..1489e5e31a
--- /dev/null
+++ b/tests/template/templates/invalid/output/unknown_tag.html
@@ -0,0 +1 @@
+<!-- UNKNOWNTAG variable.html -->
diff --git a/tests/template/templates/lang.html b/tests/template/templates/lang.html
index 2b5ea1cafe..3eecc298cb 100644
--- a/tests/template/templates/lang.html
+++ b/tests/template/templates/lang.html
@@ -1,3 +1,5 @@
{L_VARIABLE}
+{L_1_VARIABLE}
{LA_VARIABLE}
+{LA_1_VARIABLE}
diff --git a/tests/template/templates/loop_expressions.html b/tests/template/templates/loop_expressions.html
new file mode 100644
index 0000000000..6bff53f388
--- /dev/null
+++ b/tests/template/templates/loop_expressions.html
@@ -0,0 +1,11 @@
+<!-- BEGIN loop -->
+
+<!-- IF loop.S_ROW_NUM is even by 4 -->on<!-- ELSE -->off<!-- ENDIF -->
+
+<!-- END loop -->
+
+<!-- BEGIN loop -->
+
+<!-- IF loop.S_ROW_NUM is odd by 3 -->on<!-- ELSE -->off<!-- ENDIF -->
+
+<!-- END loop -->
diff --git a/tests/template/templates/loop_nested.html b/tests/template/templates/loop_nested.html
index 9b251cd453..cf099ecc15 100644
--- a/tests/template/templates/loop_nested.html
+++ b/tests/template/templates/loop_nested.html
@@ -1,8 +1,6 @@
<!-- BEGIN outer -->
- outer - {outer.S_ROW_COUNT}<!-- IF outer.VARIABLE --> - {outer.VARIABLE}<!-- ENDIF -->
-
- <!-- BEGIN middle -->
- middle - {middle.S_ROW_COUNT}<!-- IF middle.VARIABLE --> - {middle.VARIABLE}<!-- ENDIF -->
-
- <!-- END middle -->
+outer - {outer.S_ROW_COUNT}<!-- IF outer.VARIABLE --> - {outer.VARIABLE}<!-- ENDIF --><!-- IF TEST_MORE -->[{outer.S_BLOCK_NAME}|{outer.S_NUM_ROWS}]<!-- ENDIF -->
+<!-- BEGIN middle -->
+middle - {outer.middle.S_ROW_COUNT}<!-- IF outer.middle.VARIABLE --> - {outer.middle.VARIABLE}<!-- ENDIF --><!-- IF TEST_MORE -->[{outer.middle.S_BLOCK_NAME}|{outer.middle.S_NUM_ROWS}]<!-- ENDIF -->
+<!-- END middle -->
<!-- END outer -->
diff --git a/tests/template/templates/loop_nested2.html b/tests/template/templates/loop_nested2.html
new file mode 100644
index 0000000000..3eeeb5e36a
--- /dev/null
+++ b/tests/template/templates/loop_nested2.html
@@ -0,0 +1,6 @@
+<!-- BEGIN outer -->
+o{outer.S_ROW_COUNT}
+<!-- BEGIN middle -->
+m{outer.middle.S_ROW_COUNT}{outer.S_ROW_COUNT}
+<!-- END middle -->
+<!-- END outer -->
diff --git a/tests/template/templates/loop_nested_deep_multilevel_ref.html b/tests/template/templates/loop_nested_deep_multilevel_ref.html
new file mode 100644
index 0000000000..bcc2a7c07b
--- /dev/null
+++ b/tests/template/templates/loop_nested_deep_multilevel_ref.html
@@ -0,0 +1,13 @@
+top-level content
+<!-- BEGIN outer -->
+ outer
+ <!-- BEGIN middle -->
+ {outer.middle.S_BLOCK_NAME}
+ <!-- BEGIN inner -->
+ inner {inner.VARIABLE}
+ <!-- IF outer.middle.inner.S_FIRST_ROW -->
+ first row of {outer.middle.inner.S_NUM_ROWS} in {middle.inner.S_BLOCK_NAME}
+ <!-- ENDIF -->
+ <!-- END inner -->
+ <!-- END middle -->
+<!-- END outer -->
diff --git a/tests/template/templates/loop_nested_multilevel_ref.html b/tests/template/templates/loop_nested_multilevel_ref.html
new file mode 100644
index 0000000000..f2f1c746ed
--- /dev/null
+++ b/tests/template/templates/loop_nested_multilevel_ref.html
@@ -0,0 +1,10 @@
+top-level content
+<!-- BEGIN outer -->
+ outer {outer.VARIABLE}
+ <!-- BEGIN inner -->
+ inner {inner.VARIABLE}
+ <!-- IF outer.inner.S_FIRST_ROW -->
+ first row
+ <!-- ENDIF -->
+ <!-- END inner -->
+<!-- END outer -->
diff --git a/tests/template/templates/loop_reuse.html b/tests/template/templates/loop_reuse.html
new file mode 100644
index 0000000000..bd0354ae6f
--- /dev/null
+++ b/tests/template/templates/loop_reuse.html
@@ -0,0 +1,6 @@
+<!-- BEGIN one -->
+ {one.VAR}
+ <!-- BEGIN one -->
+ {one.one.VAR}
+ <!-- END one -->
+<!-- END one -->
diff --git a/tests/template/templates/loop_size.html b/tests/template/templates/loop_size.html
new file mode 100644
index 0000000000..8f581cef10
--- /dev/null
+++ b/tests/template/templates/loop_size.html
@@ -0,0 +1,39 @@
+<!-- IF .nonexistent_loop -->
+ nonexistent
+<!-- ENDIF -->
+
+<!-- IF .nonexistent_loop == 0 -->
+ nonexistent = 0
+<!-- ENDIF -->
+
+<!-- IF ! .nonexistent_loop -->
+ ! nonexistent
+<!-- ENDIF -->
+
+<!-- IF .empty_loop -->
+ empty
+<!-- ENDIF -->
+
+<!-- IF .empty_loop == 0 -->
+ empty = 0
+<!-- ENDIF -->
+
+<!-- IF ! .empty_loop -->
+ ! empty
+<!-- ENDIF -->
+
+<!-- IF .loop -->
+ loop
+<!-- ENDIF -->
+
+<!-- IF .loop == 0 -->
+ loop = 0
+<!-- ENDIF -->
+
+<!-- IF ! .loop -->
+ ! loop
+<!-- ENDIF -->
+
+<!-- BEGIN loop -->
+ in loop
+<!-- END loop -->
diff --git a/tests/template/templates/loop_underscore.html b/tests/template/templates/loop_underscore.html
new file mode 100644
index 0000000000..4001007868
--- /dev/null
+++ b/tests/template/templates/loop_underscore.html
@@ -0,0 +1,21 @@
+<!-- BEGIN _underscore_loop -->
+loop
+<!-- BEGINELSE -->
+noloop
+<!-- END _underscore_loop -->
+
+<!-- IF ._underscore_loop -->
+loop
+<!-- ELSE -->
+noloop
+<!-- ENDIF -->
+
+<!-- IF ._underscore_loop == 2 -->
+loop
+<!-- ENDIF -->
+
+<!-- BEGIN _underscore_loop -->
+<!-- BEGIN !block -->
+loop#{loop.S_ROW_COUNT}-block#{block.S_ROW_COUNT}
+<!-- END !block -->
+<!-- END _underscore_loop -->
diff --git a/tests/template/templates/loop_vars.html b/tests/template/templates/loop_vars.html
index 4f02fd2e6c..7d86d4b7b6 100644
--- a/tests/template/templates/loop_vars.html
+++ b/tests/template/templates/loop_vars.html
@@ -1,21 +1,13 @@
<!-- BEGIN loop -->
<!-- IF loop.S_FIRST_ROW -->first<!-- ENDIF -->
-
-{loop.S_ROW_COUNT}
-
-{loop.VARIABLE}
-
+{loop.S_ROW_NUM} - a
+{loop.VARIABLE} - b
<!-- IF loop.VARIABLE -->set<!-- ENDIF -->
-
<!-- IF loop.S_LAST_ROW -->
last
<!-- ENDIF -->
<!-- BEGIN inner -->
-
-{inner.S_ROW_COUNT}
-
+{inner.S_ROW_NUM} - c
<!-- IF inner.S_LAST_ROW and inner.S_ROW_COUNT and inner.S_NUM_ROWS -->last inner<!-- ENDIF -->
-
<!-- END inner -->
<!-- END loop -->
-<!-- IF .loop.inner -->inner loop<!-- ENDIF -->
diff --git a/tests/template/templates/parent_and_child.html b/tests/template/templates/parent_and_child.html
new file mode 100644
index 0000000000..16223d91e7
--- /dev/null
+++ b/tests/template/templates/parent_and_child.html
@@ -0,0 +1 @@
+Child template.
diff --git a/tests/template/templates/parent_and_child.js b/tests/template/templates/parent_and_child.js
new file mode 100644
index 0000000000..d544d94d83
--- /dev/null
+++ b/tests/template/templates/parent_and_child.js
@@ -0,0 +1 @@
+// JavaScript file in a child style.
diff --git a/tests/template/templates/subdir/parent_only.js b/tests/template/templates/subdir/parent_only.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/template/templates/subdir/parent_only.js
diff --git a/tests/template/templates/subdir/subsubdir/parent_only.js b/tests/template/templates/subdir/subsubdir/parent_only.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/template/templates/subdir/subsubdir/parent_only.js
diff --git a/tests/template/templates/subdir/variable.html b/tests/template/templates/subdir/variable.html
new file mode 100644
index 0000000000..f68f91597c
--- /dev/null
+++ b/tests/template/templates/subdir/variable.html
@@ -0,0 +1 @@
+{VARIABLE}
diff --git a/tests/template/templates/trivial.html b/tests/template/templates/trivial.html
new file mode 100644
index 0000000000..3a1c1c5324
--- /dev/null
+++ b/tests/template/templates/trivial.html
@@ -0,0 +1 @@
+This is a trivial template.
diff --git a/tests/template/templates/twig.html b/tests/template/templates/twig.html
new file mode 100644
index 0000000000..17b94ad8d4
--- /dev/null
+++ b/tests/template/templates/twig.html
@@ -0,0 +1,6 @@
+<!-- EXTENDS "twig_parent.html" -->
+
+<!-- BLOCK overwritten -->
+3{VARIABLE|upper}|{VARIABLE|lower}
+<!-- ENDBLOCK -->
+
diff --git a/tests/template/templates/twig_parent.html b/tests/template/templates/twig_parent.html
new file mode 100644
index 0000000000..e9863221e1
--- /dev/null
+++ b/tests/template/templates/twig_parent.html
@@ -0,0 +1,7 @@
+<!-- BLOCK notoverwritten -->
+1
+<!-- ENDBLOCK -->
+
+<!-- BLOCK overwritten -->
+2
+<!-- ENDBLOCK -->
diff --git a/tests/template/templates/variable_spacing.html b/tests/template/templates/variable_spacing.html
new file mode 100644
index 0000000000..028f8aa0d1
--- /dev/null
+++ b/tests/template/templates/variable_spacing.html
@@ -0,0 +1,6 @@
+|{VARIABLE}|
+{VARIABLE}|{VARIABLE}|
+
+|{VARIABLE}
+
+<div class="{VARIABLE}">test</div>