Merge pull request #4871 from eileenmcnaughton/CRM-15795
[civicrm-core.git] / tests / phpunit / CRM / Core / ResourcesTest.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.6 |
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 /**
36 * @var CRM_Core_Resources
37 */
38 protected $res;
39
40 /**
41 * @var CRM_Extension_Mapper
42 */
43 protected $mapper;
44
45 public function setUp() {
46 parent::setUp();
47
48 list ($this->basedir, $this->container, $this->mapper) = $this->_createMapper();
49 $cache = new CRM_Utils_Cache_Arraycache(array());
50 $this->res = new CRM_Core_Resources($this->mapper, $cache, NULL);
51 $this->res->setCacheCode('resTest');
52 CRM_Core_Resources::singleton($this->res);
53
54 // Templates injected into regions should normally be file names, but for unit-testing it's handy to use "string:" notation
55 require_once 'CRM/Core/Smarty/resources/String.php';
56 civicrm_smarty_register_string_resource();
57 }
58
59 public function testAddScriptFile() {
60 $this->res
61 ->addScriptFile('com.example.ext', 'foo%20bar.js', 0, 'testAddScriptFile')
62 ->addScriptFile('com.example.ext', 'foo%20bar.js', 0, 'testAddScriptFile') // extra
63 ->addScriptFile('civicrm', 'foo%20bar.js', 0, 'testAddScriptFile');
64
65 $smarty = CRM_Core_Smarty::singleton();
66 $actual = $smarty->fetch('string:{crmRegion name=testAddScriptFile}{/crmRegion}');
67 $expected = "" // stable ordering: alphabetical by (snippet.weight,snippet.name)
68 . "<script type=\"text/javascript\" src=\"http://core-app/foo%20bar.js?r=resTest\">\n</script>\n"
69 . "<script type=\"text/javascript\" src=\"http://ext-dir/com.example.ext/foo%20bar.js?r=resTest\">\n</script>\n";
70 $this->assertEquals($expected, $actual);
71 }
72
73 /**
74 * When adding a script file, any ts() expressions should be translated and added to the 'strings'
75 *
76 * FIXME: This can't work because the tests run in English and CRM_Core_Resources optimizes
77 * away the English data from $settings['strings']
78 public function testAddScriptFile_strings() {
79 file_put_contents($this->mapper->keyToBasePath('com.example.ext') . '/hello.js', 'alert(ts("Hello world"));');
80 $this->res->addScriptFile('com.example.ext', 'hello.js', 0, 'testAddScriptFile_strings');
81 $settings = $this->res->getSettings();
82 $expected = array('Hello world');
83 $this->assertEquals($expected, $settings['strings']);
84 }
85 */
86
87 public function testAddScriptURL() {
88 $this->res
89 ->addScriptUrl('/whiz/foo%20bar.js', 0, 'testAddScriptURL')
90 ->addScriptUrl('/whiz/foo%20bar.js', 0, 'testAddScriptURL') // extra
91 ->addScriptUrl('/whizbang/foo%20bar.js', 0, 'testAddScriptURL');
92
93 $smarty = CRM_Core_Smarty::singleton();
94 $actual = $smarty->fetch('string:{crmRegion name=testAddScriptURL}{/crmRegion}');
95 $expected = "" // stable ordering: alphabetical by (snippet.weight,snippet.name)
96 . "<script type=\"text/javascript\" src=\"/whiz/foo%20bar.js\">\n</script>\n"
97 . "<script type=\"text/javascript\" src=\"/whizbang/foo%20bar.js\">\n</script>\n";
98 $this->assertEquals($expected, $actual);
99 }
100
101 public function testAddScript() {
102 $this->res
103 ->addScript('alert("hi");', 0, 'testAddScript')
104 ->addScript('alert("there");', 0, 'testAddScript');
105
106 $smarty = CRM_Core_Smarty::singleton();
107 $actual = $smarty->fetch('string:{crmRegion name=testAddScript}{/crmRegion}');
108 $expected = ""
109 . "<script type=\"text/javascript\">\nalert(\"hi\");\n</script>\n"
110 . "<script type=\"text/javascript\">\nalert(\"there\");\n</script>\n";
111 $this->assertEquals($expected, $actual);
112 }
113
114 public function testAddVars() {
115 $this->res
116 ->addVars('food', array('fruit' => array('mine' => 'apple', 'ours' => 'banana')))
117 ->addVars('food', array('fruit' => array('mine' => 'new apple', 'yours' => 'orange')));
118 $this->assertTreeEquals(
119 array('vars' => array('food' => array('fruit' => array('yours' => 'orange', 'mine' => 'new apple', 'ours' => 'banana')))),
120 $this->res->getSettings()
121 );
122 }
123
124 public function testAddSetting() {
125 $this->res
126 ->addSetting(array('fruit' => array('mine' => 'apple')))
127 ->addSetting(array('fruit' => array('yours' => 'orange')));
128 $this->assertTreeEquals(
129 array('fruit' => array('yours' => 'orange', 'mine' => 'apple')),
130 $this->res->getSettings()
131 );
132 $actual = $this->res->renderSetting();
133 $expected = json_encode(array('fruit' => array('yours' => 'orange', 'mine' => 'apple')));
134 $this->assertTrue(strpos($actual, $expected) !== FALSE);
135 }
136
137 public function testAddSettingFactory() {
138 $this->res->addSettingsFactory(function() {
139 return array('fruit' => array('yours' => 'orange'));
140 });
141 $this->res->addSettingsFactory(function() {
142 return array('fruit' => array('mine' => 'apple'));
143 });
144
145 $actual = $this->res->getSettings();
146 $expected = array('fruit' => array('yours' => 'orange', 'mine' => 'apple'));
147 $this->assertTreeEquals($expected, $actual);
148 }
149
150 public function testAddSettingAndSettingFactory() {
151 $this->res->addSetting(array('fruit' => array('mine' => 'apple')));
152
153 $muckableValue = array('fruit' => array('yours' => 'orange', 'theirs' => 'apricot'));
154 $this->res->addSettingsFactory(function() use (&$muckableValue) {
155 return $muckableValue;
156 });
157 $actual = $this->res->getSettings();
158 $expected = array('fruit' => array('mine' => 'apple', 'yours' => 'orange', 'theirs' => 'apricot'));
159 $this->assertTreeEquals($expected, $actual);
160
161 // note: the setting is not fixed based on what the factory returns when registered; it's based
162 // on what the factory returns when getSettings is called
163 $muckableValue = array('fruit' => array('yours' => 'banana'));
164 $actual = $this->res->getSettings();
165 $expected = array('fruit' => array('mine' => 'apple', 'yours' => 'banana'));
166 $this->assertTreeEquals($expected, $actual);
167 }
168
169 public function testCrmJS() {
170 $smarty = CRM_Core_Smarty::singleton();
171
172 $actual = $smarty->fetch('string:{crmScript ext=com.example.ext file=foo%20bar.js region=testCrmJS}');
173 $this->assertEquals('', $actual);
174
175 $actual = $smarty->fetch('string:{crmScript url=/whiz/foo%20bar.js region=testCrmJS weight=1}');
176 $this->assertEquals('', $actual);
177
178 $actual = $smarty->fetch('string:{crmRegion name=testCrmJS}{/crmRegion}');
179 $expected = "" // stable ordering: alphabetical by (snippet.weight,snippet.name)
180 . "<script type=\"text/javascript\" src=\"http://ext-dir/com.example.ext/foo%20bar.js?r=resTest\">\n</script>\n"
181 . "<script type=\"text/javascript\" src=\"/whiz/foo%20bar.js\">\n</script>\n";
182 $this->assertEquals($expected, $actual);
183 }
184
185 public function testAddStyleFile() {
186 $this->res
187 ->addStyleFile('com.example.ext', 'foo%20bar.css', 0, 'testAddStyleFile')
188 ->addStyleFile('com.example.ext', 'foo%20bar.css', 0, 'testAddStyleFile') // extra
189 ->addStyleFile('civicrm', 'foo%20bar.css', 0, 'testAddStyleFile');
190
191 $smarty = CRM_Core_Smarty::singleton();
192 $actual = $smarty->fetch('string:{crmRegion name=testAddStyleFile}{/crmRegion}');
193 $expected = "" // stable ordering: alphabetical by (snippet.weight,snippet.name)
194 . "<link href=\"http://core-app/foo%20bar.css?r=resTest\" rel=\"stylesheet\" type=\"text/css\"/>\n"
195 . "<link href=\"http://ext-dir/com.example.ext/foo%20bar.css?r=resTest\" rel=\"stylesheet\" type=\"text/css\"/>\n";
196 $this->assertEquals($expected, $actual);
197 }
198
199 public function testAddStyleURL() {
200 $this->res
201 ->addStyleUrl('/whiz/foo%20bar.css', 0, 'testAddStyleURL')
202 ->addStyleUrl('/whiz/foo%20bar.css', 0, 'testAddStyleURL') // extra
203 ->addStyleUrl('/whizbang/foo%20bar.css', 0, 'testAddStyleURL');
204
205 $smarty = CRM_Core_Smarty::singleton();
206 $actual = $smarty->fetch('string:{crmRegion name=testAddStyleURL}{/crmRegion}');
207 $expected = "" // stable ordering: alphabetical by (snippet.weight,snippet.name)
208 . "<link href=\"/whiz/foo%20bar.css\" rel=\"stylesheet\" type=\"text/css\"/>\n"
209 . "<link href=\"/whizbang/foo%20bar.css\" rel=\"stylesheet\" type=\"text/css\"/>\n";
210 $this->assertEquals($expected, $actual);
211 }
212
213 public function testAddStyle() {
214 $this->res
215 ->addStyle('body { background: black; }', 0, 'testAddStyle')
216 ->addStyle('body { text-color: black; }', 0, 'testAddStyle');
217
218 $smarty = CRM_Core_Smarty::singleton();
219 $actual = $smarty->fetch('string:{crmRegion name=testAddStyle}{/crmRegion}');
220 $expected = ""
221 . "<style type=\"text/css\">\nbody { background: black; }\n</style>\n"
222 . "<style type=\"text/css\">\nbody { text-color: black; }\n</style>\n";
223 $this->assertEquals($expected, $actual);
224 }
225
226 public function testCrmCSS() {
227 $smarty = CRM_Core_Smarty::singleton();
228
229 $actual = $smarty->fetch('string:{crmStyle ext=com.example.ext file=foo%20bar.css region=testCrmCSS}');
230 $this->assertEquals('', $actual);
231
232 $actual = $smarty->fetch('string:{crmStyle url=/whiz/foo%20bar.css region=testCrmCSS weight=1}');
233 $this->assertEquals('', $actual);
234
235 $actual = $smarty->fetch('string:{crmRegion name=testCrmCSS}{/crmRegion}');
236 $expected = "" // stable ordering: alphabetical by (snippet.weight,snippet.name)
237 . "<link href=\"http://ext-dir/com.example.ext/foo%20bar.css?r=resTest\" rel=\"stylesheet\" type=\"text/css\"/>\n"
238 . "<link href=\"/whiz/foo%20bar.css\" rel=\"stylesheet\" type=\"text/css\"/>\n";
239 $this->assertEquals($expected, $actual);
240 }
241
242 public function testGetURL() {
243 $this->assertEquals(
244 'http://core-app/dir/file%20name.txt',
245 $this->res->getURL('civicrm', 'dir/file%20name.txt')
246 );
247 $this->assertEquals(
248 'http://ext-dir/com.example.ext/dir/file%20name.txt',
249 $this->res->getURL('com.example.ext', 'dir/file%20name.txt')
250 );
251 $this->assertEquals(
252 'http://core-app/',
253 $this->res->getURL('civicrm')
254 );
255 $this->assertEquals(
256 'http://ext-dir/com.example.ext/',
257 $this->res->getURL('com.example.ext')
258 );
259 }
260
261 public function testCrmResURL() {
262 $smarty = CRM_Core_Smarty::singleton();
263
264 $actual = $smarty->fetch('string:{crmResURL ext=com.example.ext file=foo%20bar.png}');
265 $this->assertEquals('http://ext-dir/com.example.ext/foo%20bar.png', $actual);
266
267 $actual = $smarty->fetch('string:{crmResURL ext=com.example.ext file=foo%20bar.png addCacheCode=1}');
268 $this->assertEquals('http://ext-dir/com.example.ext/foo%20bar.png?r=resTest', $actual);
269
270 $actual = $smarty->fetch('string:{crmResURL ext=com.example.ext}');
271 $this->assertEquals('http://ext-dir/com.example.ext/', $actual);
272 }
273
274 /**
275 * @param CRM_Utils_Cache_Interface $cache
276 * @param null $cacheKey
277 *
278 * @internal param string $appendPathGarbage
279 * @return array(string $basedir, CRM_Extension_Container_Interface, CRM_Extension_Mapper)
280 */
281 public function _createMapper(CRM_Utils_Cache_Interface $cache = NULL, $cacheKey = NULL) {
282 $basedir = rtrim($this->createTempDir('ext-'), '/');
283 mkdir("$basedir/com.example.ext");
284 file_put_contents("$basedir/com.example.ext/info.xml", "<extension key='com.example.ext' type='report'><file>oddball</file></extension>");
285 // not needed for now // file_put_contents("$basedir/weird/bar/oddball.php", "<?php\n");
286 $c = new CRM_Extension_Container_Basic($basedir, 'http://ext-dir', $cache, $cacheKey);
287 $mapper = new CRM_Extension_Mapper($c, NULL, NULL, '/pathto/civicrm', 'http://core-app');
288 return array($basedir, $c, $mapper);
289 }
290
291 }