4 * Class CRM_Core_RegionTest
7 class CRM_Core_RegionTest
extends CiviUnitTestCase
{
9 public function setUp() {
11 require_once 'CRM/Core/Smarty.php';
12 require_once 'CRM/Core/Region.php';
14 // Templates injected into regions should normally be file names, but for unit-testing it's handy to use "string:" notation
15 require_once 'CRM/Core/Smarty/resources/String.php';
16 civicrm_smarty_register_string_resource();
20 * When a {crmRegion} is blank and when there are no extra snippets, the
23 public function testBlank() {
24 $smarty = CRM_Core_Smarty
::singleton();
25 $actual = $smarty->fetch('string:{crmRegion name=testBlank}{/crmRegion}');
27 $this->assertEquals($expected, $actual);
31 * When a {crmRegion} is not blank and when there are no extra snippets,
32 * the output is only determined by the {crmRegion} block.
34 public function testDefault() {
35 $smarty = CRM_Core_Smarty
::singleton();
36 $actual = $smarty->fetch('string:{crmRegion name=testDefault}default<br/>{/crmRegion}');
37 $expected = 'default<br/>';
38 $this->assertEquals($expected, $actual);
42 * Disable the normal content of a {crmRegion} and apply different content from a snippet
44 public function testOverride() {
45 CRM_Core_Region
::instance('testOverride')->update('default', [
48 CRM_Core_Region
::instance('testOverride')->add([
49 'markup' => 'override<br/>',
52 $smarty = CRM_Core_Smarty
::singleton();
53 $actual = $smarty->fetch('string:{crmRegion name=testOverride}default<br/>{/crmRegion}');
54 $expected = 'override<br/>';
55 $this->assertEquals($expected, $actual);
59 * Test that each of the major content formats are correctly evaluated.
61 public function testAllTypes() {
62 CRM_Core_Region
::instance('testAllTypes')->add([
63 'markup' => 'some-markup<br/>',
65 CRM_Core_Region
::instance('testAllTypes')->add([
66 // note: 'template' would normally be a file name
67 'template' => 'string:smarty-is-{$snippet.extrainfo}<br/>',
68 'extrainfo' => 'dynamic',
70 CRM_Core_Region
::instance('testAllTypes')->add([
71 // note: returns a value which gets appended to the region
72 'callback' => 'implode',
73 'arguments' => ['-', ['callback', 'with', 'specific', 'args<br/>']],
75 CRM_Core_Region
::instance('testAllTypes')->add([
76 // note: returns a value which gets appended to the region
77 'callback' => function(&$spec, &$html) {
78 return "callback-return<br/>";
81 CRM_Core_Region
::instance('testAllTypes')->add([
82 // note: returns void; directly modifies region's $html
83 'callback' => function(&$spec, &$html) {
84 $html = "callback-ref<br/>" . $html;
87 CRM_Core_Region
::instance('testAllTypes')->add([
88 'scriptUrl' => '/foo%20bar.js',
90 CRM_Core_Region
::instance('testAllTypes')->add([
91 'script' => 'alert("hi");',
93 CRM_Core_Region
::instance('testAllTypes')->add([
94 'jquery' => '$("div");',
96 CRM_Core_Region
::instance('testAllTypes')->add([
97 'styleUrl' => '/foo%20bar.css',
99 CRM_Core_Region
::instance('testAllTypes')->add([
100 'style' => 'body { background: black; }',
103 $smarty = CRM_Core_Smarty
::singleton();
104 $actual = $smarty->fetch('string:{crmRegion name=testAllTypes}default<br/>{/crmRegion}');
105 $expected = "callback-ref<br/>"
108 . "smarty-is-dynamic<br/>"
109 . "callback-with-specific-args<br/>"
110 . "callback-return<br/>"
111 . "<script type=\"text/javascript\" src=\"/foo%20bar.js\">\n</script>\n"
112 . "<script type=\"text/javascript\">\nalert(\"hi\");\n</script>\n"
113 . "<script type=\"text/javascript\">\nCRM.\$(function(\$) {\n\$(\"div\");\n});\n</script>\n"
114 . "<link href=\"/foo%20bar.css\" rel=\"stylesheet\" type=\"text/css\"/>\n"
115 . "<style type=\"text/css\">\nbody { background: black; }\n</style>\n";
116 $this->assertEquals($expected, $actual);
120 * Test of nested arrangement in which one {crmRegion} directly includes another {crmRegion}
122 public function testDirectNest() {
123 CRM_Core_Region
::instance('testDirectNestOuter')->add([
124 'template' => 'string:O={$snippet.weight} ',
127 CRM_Core_Region
::instance('testDirectNestOuter')->add([
128 'template' => 'string:O={$snippet.weight} ',
132 CRM_Core_Region
::instance('testDirectNestInner')->add([
133 'template' => 'string:I={$snippet.weight} ',
136 CRM_Core_Region
::instance('testDirectNestInner')->add([
137 'template' => 'string:I={$snippet.weight} ',
141 $smarty = CRM_Core_Smarty
::singleton();
142 $actual = $smarty->fetch('string:{crmRegion name=testDirectNestOuter}left {crmRegion name=testDirectNestInner}middle {/crmRegion}right {/crmRegion}');
143 $expected = 'O=-5 left I=-5 middle I=5 right O=5 ';
144 $this->assertEquals($expected, $actual);
148 * Test of nested arrangement in which one {crmRegion} is enhanced with a snippet which, in turn, includes another {crmRegion}
150 public function testIndirectNest() {
151 CRM_Core_Region
::instance('testIndirectNestOuter')->add([
152 // Note: all three $snippet references are bound to the $snippet which caused this template to be included,
153 // regardless of any nested {crmRegion}s
154 'template' => 'string: O={$snippet.region}{crmRegion name=testIndirectNestInner} O={$snippet.region}{/crmRegion} O={$snippet.region}',
157 CRM_Core_Region
::instance('testIndirectNestInner')->add([
158 'template' => 'string: I={$snippet.region}',
161 $smarty = CRM_Core_Smarty
::singleton();
162 $actual = $smarty->fetch('string:{crmRegion name=testIndirectNestOuter}default{/crmRegion}');
163 $expected = 'default O=testIndirectNestOuter O=testIndirectNestOuter I=testIndirectNestInner O=testIndirectNestOuter';
164 $this->assertEquals($expected, $actual);
168 * Output from an inner-region should not be executed verbatim; this is obvious but good to verify
170 public function testNoInjection() {
171 CRM_Core_Region
::instance('testNoInjectionOuter')->add([
172 'template' => 'string:{$snippet.scarystuff} ',
173 'scarystuff' => '{$is_outer_scary}',
175 CRM_Core_Region
::instance('testNoInjectionInner')->add([
176 'template' => 'string:{$snippet.scarystuff} ',
177 'scarystuff' => '{$is_inner_scary}',
180 $smarty = CRM_Core_Smarty
::singleton();
181 $smarty->assign('is_outer_scary', 'egad');
182 $smarty->assign('is_inner_scary', 'egad');
183 $smarty->assign('also_scary', 'egad');
184 $actual = $smarty->fetch('string:{crmRegion name=testNoInjectionOuter}left {crmRegion name=testNoInjectionInner}middle {literal}{$also_scary}{/literal} {/crmRegion}right {/crmRegion}');
185 $expected = 'left middle {$also_scary} {$is_inner_scary} right {$is_outer_scary} ';
186 $this->assertEquals($expected, $actual);
190 * Make sure that standard Smarty variables ($smarty->assign(...)) as well
191 * as the magical $snippet variable both evaluate correctly.
193 public function testSmartyVars() {
194 $smarty = CRM_Core_Smarty
::singleton();
195 $smarty->assign('extrainfo', 'one');
196 CRM_Core_Region
::instance('testSmartyVars')->add([
197 'template' => 'string:var-style-{$extrainfo}<br/>',
200 CRM_Core_Region
::instance('testSmartyVars')->add([
201 'template' => 'string:var-style-{$snippet.extrainfo}<br/>',
202 'extrainfo' => 'two',
205 $actual = $smarty->fetch('string:{crmRegion name=testSmartyVars}default<br/>{/crmRegion}');
206 $expected = 'default<br/>var-style-one<br/>var-style-two<br/>';
207 $this->assertEquals($expected, $actual);
210 public function testWeight() {
211 CRM_Core_Region
::instance('testWeight')->add([
212 'markup' => 'prepend-5<br/>',
215 CRM_Core_Region
::instance('testWeight')->add([
216 'markup' => 'append+3<br/>',
219 CRM_Core_Region
::instance('testWeight')->add([
220 'markup' => 'prepend-3<br/>',
223 CRM_Core_Region
::instance('testWeight')->add([
224 'markup' => 'append+5<br/>',
228 $smarty = CRM_Core_Smarty
::singleton();
229 $actual = $smarty->fetch('string:{crmRegion name=testWeight}default<br/>{/crmRegion}');
230 $expected = 'prepend-5<br/>prepend-3<br/>default<br/>append+3<br/>append+5<br/>';
231 $this->assertEquals($expected, $actual);