Merge branch 'master' into master-civimail-abtest
[civicrm-core.git] / tests / phpunit / CRM / Core / ResourcesTest.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2014 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28 require_once 'CiviTest/CiviUnitTestCase.php';
29
30 /**
31 * Tests for linking to resource files
32 */
33 class CRM_Core_ResourcesTest extends CiviUnitTestCase {
34 /**
35 * @return array
36 */
37 function get_info() {
38 return array(
39 'name' => 'Resources',
40 'description' => 'Tests for linking to resource files',
41 'group' => 'Core',
42 );
43 }
44
45 /**
46 * @var CRM_Core_Resources
47 */
48 protected $res;
49
50 /**
51 * @var CRM_Extension_Mapper
52 */
53 protected $mapper;
54
55 function setUp() {
56 parent::setUp();
57
58 list ($this->basedir, $this->container, $this->mapper) = $this->_createMapper();
59 $cache = new CRM_Utils_Cache_Arraycache(array());
60 $this->res = new CRM_Core_Resources($this->mapper, $cache, NULL);
61 $this->res->setCacheCode('resTest');
62 CRM_Core_Resources::singleton($this->res);
63
64 // Templates injected into regions should normally be file names, but for unit-testing it's handy to use "string:" notation
65 require_once 'CRM/Core/Smarty/resources/String.php';
66 civicrm_smarty_register_string_resource( );
67 }
68
69 function testAddScriptFile() {
70 $this->res
71 ->addScriptFile('com.example.ext', 'foo%20bar.js', 0, 'testAddScriptFile')
72 ->addScriptFile('com.example.ext', 'foo%20bar.js', 0, 'testAddScriptFile') // extra
73 ->addScriptFile('civicrm', 'foo%20bar.js', 0, 'testAddScriptFile')
74 ;
75
76 $smarty = CRM_Core_Smarty::singleton();
77 $actual = $smarty->fetch('string:{crmRegion name=testAddScriptFile}{/crmRegion}');
78 $expected = "" // stable ordering: alphabetical by (snippet.weight,snippet.name)
79 . "<script type=\"text/javascript\" src=\"http://core-app/foo%20bar.js?r=resTest\">\n</script>\n"
80 . "<script type=\"text/javascript\" src=\"http://ext-dir/com.example.ext/foo%20bar.js?r=resTest\">\n</script>\n"
81 ;
82 $this->assertEquals($expected, $actual);
83 }
84
85 /**
86 * When adding a script file, any ts() expressions should be translated and added to the 'strings'
87 *
88 * FIXME: This can't work because the tests run in English and CRM_Core_Resources optimizes
89 * away the English data from $settings['strings']
90 function testAddScriptFile_strings() {
91 file_put_contents($this->mapper->keyToBasePath('com.example.ext') . '/hello.js', 'alert(ts("Hello world"));');
92 $this->res->addScriptFile('com.example.ext', 'hello.js', 0, 'testAddScriptFile_strings');
93 $settings = $this->res->getSettings();
94 $expected = array('Hello world');
95 $this->assertEquals($expected, $settings['strings']);
96 }
97 */
98
99 function testAddScriptURL() {
100 $this->res
101 ->addScriptUrl('/whiz/foo%20bar.js', 0, 'testAddScriptURL')
102 ->addScriptUrl('/whiz/foo%20bar.js', 0, 'testAddScriptURL') // extra
103 ->addScriptUrl('/whizbang/foo%20bar.js', 0, 'testAddScriptURL')
104 ;
105
106 $smarty = CRM_Core_Smarty::singleton();
107 $actual = $smarty->fetch('string:{crmRegion name=testAddScriptURL}{/crmRegion}');
108 $expected = "" // stable ordering: alphabetical by (snippet.weight,snippet.name)
109 . "<script type=\"text/javascript\" src=\"/whiz/foo%20bar.js\">\n</script>\n"
110 . "<script type=\"text/javascript\" src=\"/whizbang/foo%20bar.js\">\n</script>\n"
111 ;
112 $this->assertEquals($expected, $actual);
113 }
114
115 function testAddScript() {
116 $this->res
117 ->addScript('alert("hi");', 0, 'testAddScript')
118 ->addScript('alert("there");', 0, 'testAddScript')
119 ;
120
121 $smarty = CRM_Core_Smarty::singleton();
122 $actual = $smarty->fetch('string:{crmRegion name=testAddScript}{/crmRegion}');
123 $expected = ""
124 . "<script type=\"text/javascript\">\nalert(\"hi\");\n</script>\n"
125 . "<script type=\"text/javascript\">\nalert(\"there\");\n</script>\n"
126 ;
127 $this->assertEquals($expected, $actual);
128 }
129
130 function testAddVars() {
131 $this->res
132 ->addVars('food', array('fruit' => array('mine' => 'apple', 'ours' => 'banana')))
133 ->addVars('food', array('fruit' => array('mine' => 'new apple', 'yours' => 'orange')))
134 ;
135 $this->assertTreeEquals(
136 array('vars' => array('food' => array('fruit' => array('yours' => 'orange', 'mine' => 'new apple', 'ours' => 'banana')))),
137 $this->res->getSettings()
138 );
139 }
140
141 function testAddSetting() {
142 $this->res
143 ->addSetting(array('fruit' => array('mine' => 'apple')))
144 ->addSetting(array('fruit' => array('yours' => 'orange')))
145 ;
146 $this->assertTreeEquals(
147 array('fruit' => array('yours' => 'orange', 'mine' => 'apple')),
148 $this->res->getSettings()
149 );
150 $actual = $this->res->renderSetting();
151 $expected = json_encode(array('fruit' => array('yours' => 'orange', 'mine' => 'apple')));
152 $this->assertTrue(strpos($actual, $expected) !== FALSE);
153 }
154
155 function testAddSettingFactory() {
156 $this->res->addSettingsFactory(function() {
157 return array('fruit' => array('yours' => 'orange'));
158 });
159 $this->res->addSettingsFactory(function() {
160 return array('fruit' => array('mine' => 'apple'));
161 });
162
163 $actual = $this->res->getSettings();
164 $expected = array('fruit' => array('yours' => 'orange', 'mine' => 'apple'));
165 $this->assertTreeEquals($expected, $actual);
166 }
167
168 function testAddSettingAndSettingFactory() {
169 $this->res->addSetting(array('fruit' => array('mine' => 'apple')));
170
171 $muckableValue = array('fruit' => array('yours' => 'orange', 'theirs' => 'apricot'));
172 $this->res->addSettingsFactory(function() use (&$muckableValue) {
173 return $muckableValue;
174 });
175 $actual = $this->res->getSettings();
176 $expected = array('fruit' => array('mine' => 'apple', 'yours' => 'orange', 'theirs' => 'apricot'));
177 $this->assertTreeEquals($expected, $actual);
178
179 // note: the setting is not fixed based on what the factory returns when registered; it's based
180 // on what the factory returns when getSettings is called
181 $muckableValue = array('fruit' => array('yours' => 'banana'));
182 $actual = $this->res->getSettings();
183 $expected = array('fruit' => array('mine' => 'apple', 'yours' => 'banana'));
184 $this->assertTreeEquals($expected, $actual);
185 }
186
187 function testCrmJS() {
188 $smarty = CRM_Core_Smarty::singleton();
189
190 $actual = $smarty->fetch('string:{crmScript ext=com.example.ext file=foo%20bar.js region=testCrmJS}');
191 $this->assertEquals('', $actual);
192
193 $actual = $smarty->fetch('string:{crmScript url=/whiz/foo%20bar.js region=testCrmJS weight=1}');
194 $this->assertEquals('', $actual);
195
196 $actual = $smarty->fetch('string:{crmRegion name=testCrmJS}{/crmRegion}');
197 $expected = "" // stable ordering: alphabetical by (snippet.weight,snippet.name)
198 . "<script type=\"text/javascript\" src=\"http://ext-dir/com.example.ext/foo%20bar.js?r=resTest\">\n</script>\n"
199 . "<script type=\"text/javascript\" src=\"/whiz/foo%20bar.js\">\n</script>\n"
200 ;
201 $this->assertEquals($expected, $actual);
202 }
203
204 function testAddStyleFile() {
205 $this->res
206 ->addStyleFile('com.example.ext', 'foo%20bar.css', 0, 'testAddStyleFile')
207 ->addStyleFile('com.example.ext', 'foo%20bar.css', 0, 'testAddStyleFile') // extra
208 ->addStyleFile('civicrm', 'foo%20bar.css', 0, 'testAddStyleFile')
209 ;
210
211 $smarty = CRM_Core_Smarty::singleton();
212 $actual = $smarty->fetch('string:{crmRegion name=testAddStyleFile}{/crmRegion}');
213 $expected = "" // stable ordering: alphabetical by (snippet.weight,snippet.name)
214 . "<link href=\"http://core-app/foo%20bar.css?r=resTest\" rel=\"stylesheet\" type=\"text/css\"/>\n"
215 . "<link href=\"http://ext-dir/com.example.ext/foo%20bar.css?r=resTest\" rel=\"stylesheet\" type=\"text/css\"/>\n"
216 ;
217 $this->assertEquals($expected, $actual);
218 }
219
220 function testAddStyleURL() {
221 $this->res
222 ->addStyleUrl('/whiz/foo%20bar.css', 0, 'testAddStyleURL')
223 ->addStyleUrl('/whiz/foo%20bar.css', 0, 'testAddStyleURL') // extra
224 ->addStyleUrl('/whizbang/foo%20bar.css', 0, 'testAddStyleURL')
225 ;
226
227 $smarty = CRM_Core_Smarty::singleton();
228 $actual = $smarty->fetch('string:{crmRegion name=testAddStyleURL}{/crmRegion}');
229 $expected = "" // stable ordering: alphabetical by (snippet.weight,snippet.name)
230 . "<link href=\"/whiz/foo%20bar.css\" rel=\"stylesheet\" type=\"text/css\"/>\n"
231 . "<link href=\"/whizbang/foo%20bar.css\" rel=\"stylesheet\" type=\"text/css\"/>\n"
232 ;
233 $this->assertEquals($expected, $actual);
234 }
235
236 function testAddStyle() {
237 $this->res
238 ->addStyle('body { background: black; }', 0, 'testAddStyle')
239 ->addStyle('body { text-color: black; }', 0, 'testAddStyle')
240 ;
241
242 $smarty = CRM_Core_Smarty::singleton();
243 $actual = $smarty->fetch('string:{crmRegion name=testAddStyle}{/crmRegion}');
244 $expected = ""
245 . "<style type=\"text/css\">\nbody { background: black; }\n</style>\n"
246 . "<style type=\"text/css\">\nbody { text-color: black; }\n</style>\n"
247 ;
248 $this->assertEquals($expected, $actual);
249 }
250
251 function testCrmCSS() {
252 $smarty = CRM_Core_Smarty::singleton();
253
254 $actual = $smarty->fetch('string:{crmStyle ext=com.example.ext file=foo%20bar.css region=testCrmCSS}');
255 $this->assertEquals('', $actual);
256
257 $actual = $smarty->fetch('string:{crmStyle url=/whiz/foo%20bar.css region=testCrmCSS weight=1}');
258 $this->assertEquals('', $actual);
259
260 $actual = $smarty->fetch('string:{crmRegion name=testCrmCSS}{/crmRegion}');
261 $expected = "" // stable ordering: alphabetical by (snippet.weight,snippet.name)
262 . "<link href=\"http://ext-dir/com.example.ext/foo%20bar.css?r=resTest\" rel=\"stylesheet\" type=\"text/css\"/>\n"
263 . "<link href=\"/whiz/foo%20bar.css\" rel=\"stylesheet\" type=\"text/css\"/>\n"
264 ;
265 $this->assertEquals($expected, $actual);
266 }
267
268 function testGetURL() {
269 $this->assertEquals(
270 'http://core-app/dir/file%20name.txt',
271 $this->res->getURL('civicrm', 'dir/file%20name.txt')
272 );
273 $this->assertEquals(
274 'http://ext-dir/com.example.ext/dir/file%20name.txt',
275 $this->res->getURL('com.example.ext', 'dir/file%20name.txt')
276 );
277 $this->assertEquals(
278 'http://core-app/',
279 $this->res->getURL('civicrm')
280 );
281 $this->assertEquals(
282 'http://ext-dir/com.example.ext/',
283 $this->res->getURL('com.example.ext')
284 );
285 }
286
287 function testCrmResURL() {
288 $smarty = CRM_Core_Smarty::singleton();
289
290 $actual = $smarty->fetch('string:{crmResURL ext=com.example.ext file=foo%20bar.png}');
291 $this->assertEquals('http://ext-dir/com.example.ext/foo%20bar.png', $actual);
292
293 $actual = $smarty->fetch('string:{crmResURL ext=com.example.ext file=foo%20bar.png addCacheCode=1}');
294 $this->assertEquals('http://ext-dir/com.example.ext/foo%20bar.png?r=resTest', $actual);
295
296 $actual = $smarty->fetch('string:{crmResURL ext=com.example.ext}');
297 $this->assertEquals('http://ext-dir/com.example.ext/', $actual);
298 }
299
300 /**
301 * @param CRM_Utils_Cache_Interface $cache
302 * @param null $cacheKey
303 *
304 * @internal param string $appendPathGarbage
305 * @return array(string $basedir, CRM_Extension_Container_Interface, CRM_Extension_Mapper)
306 */
307 function _createMapper(CRM_Utils_Cache_Interface $cache = NULL, $cacheKey = NULL) {
308 $basedir = rtrim($this->createTempDir('ext-'), '/');
309 mkdir("$basedir/com.example.ext");
310 file_put_contents("$basedir/com.example.ext/info.xml", "<extension key='com.example.ext' type='report'><file>oddball</file></extension>");
311 // not needed for now // file_put_contents("$basedir/weird/bar/oddball.php", "<?php\n");
312 $c = new CRM_Extension_Container_Basic($basedir, 'http://ext-dir', $cache, $cacheKey);
313 $mapper = new CRM_Extension_Mapper($c, NULL, NULL, '/pathto/civicrm', 'http://core-app');
314 return array($basedir, $c, $mapper);
315 }
316
317 }