MDL-28666 Files API and db changes
[moodle.git] / lib / tests / cssslib_test.php
blob2faf911590c13166c605682732d36dbabc973d03
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17 /**
18 * This file contains the unittests for the css optimiser in csslib.php
20 * @package core_css
21 * @category phpunit
22 * @copyright 2012 Sam Hemelryk
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 defined('MOODLE_INTERNAL') || die();
28 global $CFG;
29 require_once($CFG->libdir . '/csslib.php');
32 /**
33 * CSS optimiser test class
35 * @package core_css
36 * @category css
37 * @copyright 2012 Sam Hemelryk
38 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
40 class css_optimiser_testcase extends advanced_testcase {
42 /**
43 * Sets up the test class
45 protected function setUp() {
46 global $CFG;
47 parent::setUp();
48 // We need to disable these if they are enabled to that we can predict
49 // the output.
50 $CFG->cssoptimiserstats = false;
51 $CFG->cssoptimiserpretty = false;
53 $this->resetAfterTest(true);
56 /**
57 * Test the process method
59 public function test_process() {
60 $optimiser = new css_optimiser;
62 $this->check_background($optimiser);
63 $this->check_borders($optimiser);
64 $this->check_colors($optimiser);
65 $this->check_margins($optimiser);
66 $this->check_padding($optimiser);
67 $this->check_widths($optimiser);
69 $this->try_broken_css_found_in_moodle($optimiser);
70 $this->try_invalid_css_handling($optimiser);
71 $this->try_bulk_processing($optimiser);
72 $this->try_break_things($optimiser);
75 /**
76 * Background colour tests
77 * @param css_optimiser $optimiser
79 protected function check_background(css_optimiser $optimiser) {
81 $cssin = '.test {background-color: #123456;}';
82 $cssout = '.test{background:#123456;}';
83 $this->assertEquals($cssout, $optimiser->process($cssin));
85 $cssin = '.test {background-image: url(\'test.png\');}';
86 $cssout = '.test{background-image:url(\'test.png\');}';
87 $this->assertEquals($cssout, $optimiser->process($cssin));
89 $cssin = '.test {background: #123456 url(\'test.png\') no-repeat top left;}';
90 $cssout = '.test{background:#123456 url(\'test.png\') no-repeat top left;}';
91 $this->assertEquals($cssout, $optimiser->process($cssin));
93 $cssin = '.test {background: url(\'test.png\') no-repeat top left;}.test{background-position: bottom right}.test {background-color:#123456;}';
94 $cssout = '.test{background:#123456 url(\'test.png\') no-repeat bottom right;}';
95 $this->assertEquals($cssout, $optimiser->process($cssin));
97 $cssin = '.test {background: url( \'test.png\' )}.test{background: bottom right}.test {background:#123456;}';
98 $cssout = '.test{background-image:url(\'test.png\');background-position:bottom right;background-color:#123456;}';
99 $this->assertEquals($cssout, $optimiser->process($cssin));
101 $cssin = '.test {background-color: #123456;background-repeat: repeat-x; background-position: 100% 0%;}';
102 $cssout = '.test{background-color:#123456;background-repeat:repeat-x;background-position:100% 0%;}';
103 $this->assertEquals($cssout, $optimiser->process($cssin));
105 $cssin = '.tree_item.branch {background-image: url([[pix:t/expanded]]);background-position: 0 10%;background-repeat: no-repeat;}
106 .tree_item.branch.navigation_node {background-image:none;padding-left:0;}';
107 $cssout = '.tree_item.branch{background:url([[pix:t/expanded]]) no-repeat 0 10%;} .tree_item.branch.navigation_node{background-image:none;padding-left:0;}';
108 $this->assertEquals($cssout, $optimiser->process($cssin));
110 $cssin = '.block_tree .tree_item.emptybranch {background-image: url([[pix:t/collapsed_empty]]);background-position: 0% 5%;background-repeat: no-repeat;}
111 .block_tree .collapsed .tree_item.branch {background-image: url([[pix:t/collapsed]]);}';
112 $cssout = '.block_tree .tree_item.emptybranch{background:url([[pix:t/collapsed_empty]]) no-repeat 0% 5%;} .block_tree .collapsed .tree_item.branch{background-image:url([[pix:t/collapsed]]);}';
113 $this->assertEquals($cssout, $optimiser->process($cssin));
116 $cssin = '#nextLink{background:url(data:image/gif;base64,AAAA);}';
117 $cssout = '#nextLink{background-image:url(data:image/gif;base64,AAAA);}';
118 $this->assertEquals($cssout, $optimiser->process($cssin));
120 $cssin = '#nextLink{background-image:url(data:image/gif;base64,AAAA);}';
121 $cssout = '#nextLink{background-image:url(data:image/gif;base64,AAAA);}';
122 $this->assertEquals($cssout, $optimiser->process($cssin));
124 $cssin = '.test {background: #123456 url(data:image/gif;base64,AAAA) no-repeat top left;}';
125 $cssout = '.test{background:#123456 url(data:image/gif;base64,AAAA) no-repeat top left;}';
126 $this->assertEquals($cssout, $optimiser->process($cssin));
130 * Border tests
131 * @param css_optimiser $optimiser
133 protected function check_borders(css_optimiser $optimiser) {
134 $cssin = '.test {border: 1px solid #654321} .test {border-bottom-color: #123456}';
135 $cssout = '.test{border:1px solid;border-color:#654321 #654321 #123456;}';
136 $this->assertEquals($cssout, $optimiser->process($cssin));
138 $cssin = '.one {border:1px solid red;}';
139 $cssout = '.one{border:1px solid #FF0000;}';
140 $this->assertEquals($cssout, $optimiser->process($cssin));
142 $cssin = '.one {border:1px solid;} .one {border:2px dotted #DDD;}';
143 $cssout = '.one{border:2px dotted #DDDDDD;}';
144 $this->assertEquals($cssout, $optimiser->process($cssin));
146 $cssin = '.one {border:2px dotted #DDD;}.one {border:1px solid;} ';
147 $cssout = '.one{border:1px solid #DDDDDD;}';
148 $this->assertEquals($cssout, $optimiser->process($cssin));
150 $cssin = '.one, .two {border:1px solid red;}';
151 $cssout = ".one, .two{border:1px solid #FF0000;}";
152 $this->assertEquals($cssout, $optimiser->process($cssin));
154 $cssin = '.one, .two {border:0px;}';
155 $cssout = ".one, .two{border-width:0;}";
156 $this->assertEquals($cssout, $optimiser->process($cssin));
158 $cssin = '.one, .two {border-top: 5px solid white;}';
159 $cssout = ".one, .two{border-top:5px solid #FFFFFF;}";
160 $this->assertEquals($cssout, $optimiser->process($cssin));
162 $cssin = '.one {border:1px solid red;} .two {border:1px solid red;}';
163 $cssout = ".one, .two{border:1px solid #FF0000;}";
164 $this->assertEquals($cssout, $optimiser->process($cssin));
166 $cssin = '.one {border:1px solid red;width:20px;} .two {border:1px solid red;height:20px;}';
167 $cssout = ".one{width:20px;border:1px solid #FF0000;} .two{height:20px;border:1px solid #FF0000;}";
168 $this->assertEquals($cssout, $optimiser->process($cssin));
170 $cssin = '.test {border: 1px solid #123456;} .test {border-color: #654321}';
171 $cssout = '.test{border:1px solid #654321;}';
172 $this->assertEquals($cssout, $optimiser->process($cssin));
174 $cssin = '.test {border-width: 1px; border-style: solid; border-color: #123456;}';
175 $cssout = '.test{border:1px solid #123456;}';
176 $this->assertEquals($cssout, $optimiser->process($cssin));
178 $cssin = '.test {border:1px solid #123456;border-top:2px dotted #654321;}';
179 $cssout = '.test{border:1px solid #123456;border-top:2px dotted #654321;}';
180 $this->assertEquals($cssout, $optimiser->process($cssin));
182 $cssin = '.test {border:1px solid #123456;border-left:2px dotted #654321;}';
183 $cssout = '.test{border:1px solid #123456;border-left:2px dotted #654321;}';
184 $this->assertEquals($cssout, $optimiser->process($cssin));
186 $cssin = '.test {border-left:2px dotted #654321;border:1px solid #123456;}';
187 $cssout = '.test{border:1px solid #123456;}';
188 $this->assertEquals($cssout, $optimiser->process($cssin));
190 $cssin = '.test {border:1px solid;border-top-color:#123456;}';
191 $cssout = '.test{border:1px solid;border-top-color:#123456;}';
192 $this->assertEquals($cssout, $optimiser->process($cssin));
194 $cssin = '.test {border:1px solid;border-top-color:#111; border-bottom-color: #222;border-left-color: #333;}';
195 $cssout = '.test{border:1px solid;border-top-color:#111;border-bottom-color:#222;border-left-color:#333;}';
196 $this->assertEquals($cssout, $optimiser->process($cssin));
198 $cssin = '.test {border:1px solid;border-top-color:#111; border-bottom-color: #222;border-left-color: #333;border-right-color:#444;}';
199 $cssout = '.test{border:1px solid;border-color:#111 #444 #222 #333;}';
200 $this->assertEquals($cssout, $optimiser->process($cssin));
202 $cssin = '.generaltable .cell {border-color:#EEEEEE;} .generaltable .cell {border-width: 1px;border-style: solid;}';
203 $cssout = '.generaltable .cell{border:1px solid #EEEEEE;}';
204 $this->assertEquals($cssout, $optimiser->process($cssin));
206 $cssin = '#page-admin-roles-override .rolecap {border:none;border-bottom:1px solid #CECECE;}';
207 $cssout = '#page-admin-roles-override .rolecap{border-top:0;border-right:0;border-bottom:1px solid #CECECE;border-left:0;}';
208 $this->assertEquals($cssout, $optimiser->process($cssin));
212 * Test colour styles
213 * @param css_optimiser $optimiser
215 protected function check_colors(css_optimiser $optimiser) {
216 $css = '.css{}';
217 $this->assertEquals($css, $optimiser->process($css));
219 $css = '.css{color:#123456;}';
220 $this->assertEquals($css, $optimiser->process($css));
222 $css = '#some{color:#123456;}';
223 $this->assertEquals($css, $optimiser->process($css));
225 $css = 'div{color:#123456;}';
226 $this->assertEquals($css, $optimiser->process($css));
228 $css = 'div.css{color:#123456;}';
229 $this->assertEquals($css, $optimiser->process($css));
231 $css = 'div#some{color:#123456;}';
232 $this->assertEquals($css, $optimiser->process($css));
234 $css = 'div[type=blah]{color:#123456;}';
235 $this->assertEquals($css, $optimiser->process($css));
237 $css = 'div.css[type=blah]{color:#123456;}';
238 $this->assertEquals($css, $optimiser->process($css));
240 $css = 'div#some[type=blah]{color:#123456;}';
241 $this->assertEquals($css, $optimiser->process($css));
243 $css = '#some.css[type=blah]{color:#123456;}';
244 $this->assertEquals($css, $optimiser->process($css));
246 $css = '#some .css[type=blah]{color:#123456;}';
247 $this->assertEquals($css, $optimiser->process($css));
249 $cssin = '.one {color:red;} .two {color:#F00;}';
250 $cssout = ".one, .two{color:#F00;}";
251 $this->assertEquals($cssout, $optimiser->process($cssin));
253 $cssin = '.one {color:#123;color:#321;}';
254 $cssout = '.one{color:#321;}';
255 $this->assertEquals($cssout, $optimiser->process($cssin));
257 $cssin = '.one {color:#123; color : #321 ;}';
258 $cssout = '.one{color:#321;}';
259 $this->assertEquals($cssout, $optimiser->process($cssin));
261 $cssin = '.one {color:#123;} .one {color:#321;}';
262 $cssout = '.one{color:#321;}';
263 $this->assertEquals($cssout, $optimiser->process($cssin));
265 $cssin = '.one {color:#123 !important;color:#321;}';
266 $cssout = '.one{color:#123 !important;}';
267 $this->assertEquals($cssout, $optimiser->process($cssin));
269 $cssin = '.one {color:#123 !important;} .one {color:#321;}';
270 $cssout = '.one{color:#123 !important;}';
271 $this->assertEquals($cssout, $optimiser->process($cssin));
273 $cssin = '.one {color:rgb(255, 128, 1)}';
274 $cssout = '.one{color:rgb(255, 128, 1);}';
275 $this->assertEquals($cssout, $optimiser->process($cssin));
277 $cssin = '.one {color:rgba(255, 128, 1, 0.5)}';
278 $cssout = '.one{color:rgba(255, 128, 1, 0.5);}';
279 $this->assertEquals($cssout, $optimiser->process($cssin));
281 $cssin = '.one {color:hsl(120, 65%, 75%)}';
282 $cssout = '.one{color:hsl(120, 65%, 75%);}';
283 $this->assertEquals($cssout, $optimiser->process($cssin));
285 $cssin = '.one {color:hsla(120,65%,75%,0.5)}';
286 $cssout = '.one{color:hsla(120,65%,75%,0.5);}';
287 $this->assertEquals($cssout, $optimiser->process($cssin));
289 // Try some invalid colours to make sure we don't mangle them.
290 $css = 'div#some{color:#1;}';
291 $this->assertEquals($css, $optimiser->process($css));
293 $css = 'div#some{color:#12;}';
294 $this->assertEquals($css, $optimiser->process($css));
296 $css = 'div#some{color:#1234;}';
297 $this->assertEquals($css, $optimiser->process($css));
299 $css = 'div#some{color:#12345;}';
300 $this->assertEquals($css, $optimiser->process($css));
303 protected function check_widths(css_optimiser $optimiser) {
304 $cssin = '.css {width:0}';
305 $cssout = '.css{width:0;}';
306 $this->assertEquals($cssout, $optimiser->process($cssin));
308 $cssin = '.css {width:0px}';
309 $cssout = '.css{width:0;}';
310 $this->assertEquals($cssout, $optimiser->process($cssin));
312 $cssin = '.css {width:0em}';
313 $cssout = '.css{width:0;}';
314 $this->assertEquals($cssout, $optimiser->process($cssin));
316 $cssin = '.css {width:0pt}';
317 $cssout = '.css{width:0;}';
318 $this->assertEquals($cssout, $optimiser->process($cssin));
320 $cssin = '.css {width:0mm}';
321 $cssout = '.css{width:0;}';
322 $this->assertEquals($cssout, $optimiser->process($cssin));
324 $cssin = '.css {width:100px}';
325 $cssout = '.css{width:100px;}';
326 $this->assertEquals($cssout, $optimiser->process($cssin));
330 * Test margin styles
331 * @param css_optimiser $optimiser
333 protected function check_margins(css_optimiser $optimiser) {
334 $cssin = '.one {margin: 1px 2px 3px 4px}';
335 $cssout = '.one{margin:1px 2px 3px 4px;}';
336 $this->assertEquals($cssout, $optimiser->process($cssin));
338 $cssin = '.one {margin-top:1px; margin-left:4px; margin-right:2px; margin-bottom: 3px;}';
339 $cssout = '.one{margin:1px 2px 3px 4px;}';
340 $this->assertEquals($cssout, $optimiser->process($cssin));
342 $cssin = '.one {margin-top:1px; margin-left:4px;}';
343 $cssout = '.one{margin-top:1px;margin-left:4px;}';
344 $this->assertEquals($cssout, $optimiser->process($cssin));
346 $cssin = '.one {margin:1px; margin-left:4px;}';
347 $cssout = '.one{margin:1px 1px 1px 4px;}';
348 $this->assertEquals($cssout, $optimiser->process($cssin));
350 $cssin = '.one {margin:1px; margin-bottom:4px;}';
351 $cssout = '.one{margin:1px 1px 4px;}';
352 $this->assertEquals($cssout, $optimiser->process($cssin));
354 $cssin = '.one, .two, .one.two, .one .two {margin:0;} .one.two {margin:0 7px;}';
355 $cssout = '.one, .two, .one .two{margin:0;} .one.two{margin:0 7px;}';
356 $this->assertEquals($cssout, $optimiser->process($cssin));
360 * Test padding styles
362 * @param css_optimiser $optimiser
364 protected function check_padding(css_optimiser $optimiser) {
365 $cssin = '.one {margin: 1px 2px 3px 4px}';
366 $cssout = '.one{margin:1px 2px 3px 4px;}';
367 $this->assertEquals($cssout, $optimiser->process($cssin));
369 $cssin = '.one {margin-top:1px; margin-left:4px; margin-right:2px; margin-bottom: 3px;}';
370 $cssout = '.one{margin:1px 2px 3px 4px;}';
371 $this->assertEquals($cssout, $optimiser->process($cssin));
373 $cssin = '.one {margin-top:1px; margin-left:4px;}';
374 $cssout = '.one{margin-top:1px;margin-left:4px;}';
375 $this->assertEquals($cssout, $optimiser->process($cssin));
377 $cssin = '.one {margin:1px; margin-left:4px;}';
378 $cssout = '.one{margin:1px 1px 1px 4px;}';
379 $this->assertEquals($cssout, $optimiser->process($cssin));
381 $cssin = '.one {margin:1px; margin-bottom:4px;}';
382 $cssout = '.one{margin:1px 1px 4px;}';
383 $this->assertEquals($cssout, $optimiser->process($cssin));
385 $cssin = '.one {margin:0 !important;}';
386 $cssout = '.one{margin:0 !important;}';
387 $this->assertEquals($cssout, $optimiser->process($cssin));
389 $cssin = '.one {padding:0 !important;}';
390 $cssout = '.one{padding:0 !important;}';
391 $this->assertEquals($cssout, $optimiser->process($cssin));
393 $cssin = '.one, .two, .one.two, .one .two {margin:0;} .one.two {margin:0 7px;}';
394 $cssout = '.one, .two, .one .two{margin:0;} .one.two{margin:0 7px;}';
395 $this->assertEquals($cssout, $optimiser->process($cssin));
399 * Test some totally invalid CSS optimisation
401 * @param css_optimiser $optimiser
403 protected function try_invalid_css_handling(css_optimiser $optimiser) {
405 $cssin = array(
406 '.one{}',
407 '.one {:}',
408 '.one {;}',
409 '.one {;;;;;}',
410 '.one {:;}',
411 '.one {:;:;:;:::;;;}',
412 '.one {!important}',
413 '.one {:!important}',
414 '.one {:!important;}',
415 '.one {;!important}'
417 $cssout = '.one{}';
418 foreach ($cssin as $css) {
419 $this->assertEquals($cssout, $optimiser->process($css));
422 $cssin = array(
423 '.one{background-color:red;}',
424 '.one {background-color:red;} .one {background-color:}',
425 '.one {background-color:red;} .one {background-color;}',
426 '.one {background-color:red;} .one {background-color}',
427 '.one {background-color:red;} .one {background-color:;}',
428 '.one {background-color:red;} .one {:blue;}',
429 '.one {background-color:red;} .one {:#00F}',
431 $cssout = '.one{background:#F00;}';
432 foreach ($cssin as $css) {
433 $this->assertEquals($cssout, $optimiser->process($css));
436 $cssin = '..one {background-color:color:red}';
437 $cssout = '..one{background-color:color:red;}';
438 $this->assertEquals($cssout, $optimiser->process($cssin));
440 $cssin = '#.one {background-color:color:red}';
441 $cssout = '#.one{background-color:color:red;}';
442 $this->assertEquals($cssout, $optimiser->process($cssin));
444 $cssin = '##one {background-color:color:red}';
445 $cssout = '##one{background-color:color:red;}';
446 $this->assertEquals($cssout, $optimiser->process($cssin));
448 $cssin = '.one {background-color:color:red}';
449 $cssout = '.one{background-color:color:red;}';
450 $this->assertEquals($cssout, $optimiser->process($cssin));
452 $cssin = '.one {background-color:red;color;border-color:blue}';
453 $cssout = '.one{background:#F00;border-color:#00F;}';
454 $this->assertEquals($cssout, $optimiser->process($cssin));
456 $cssin = '{background-color:#123456;color:red;}{color:green;}';
457 $cssout = "{color:#008000;background:#123456;}";
458 $this->assertEquals($cssout, $optimiser->process($cssin));
460 $cssin = '.one {color:red;} {color:green;} .one {background-color:blue;}';
461 $cssout = ".one{color:#F00;background:#00F;} {color:#008000;}";
462 $this->assertEquals($cssout, $optimiser->process($cssin));
466 * Try to break some things
467 * @param css_optimiser $optimiser
469 protected function try_break_things(css_optimiser $optimiser) {
470 // Wildcard test
471 $cssin = '* {color: black;}';
472 $cssout = '*{color:#000;}';
473 $this->assertEquals($cssout, $optimiser->process($cssin));
475 // Wildcard test
476 $cssin = '.one * {color: black;}';
477 $cssout = '.one *{color:#000;}';
478 $this->assertEquals($cssout, $optimiser->process($cssin));
480 // Wildcard test
481 $cssin = '* .one * {color: black;}';
482 $cssout = '* .one *{color:#000;}';
483 $this->assertEquals($cssout, $optimiser->process($cssin));
485 // Wildcard test
486 $cssin = '*,* {color: black;}';
487 $cssout = '*{color:#000;}';
488 $this->assertEquals($cssout, $optimiser->process($cssin));
490 // Wildcard test
491 $cssin = '*, * .one {color: black;}';
492 $cssout = "*,\n* .one{color:#000;}";
493 $this->assertEquals($cssout, $optimiser->process($cssin));
495 // Wildcard test
496 $cssin = '*, *.one {color: black;}';
497 $cssout = "*,\n*.one{color:#000;}";
498 $this->assertEquals($cssout, $optimiser->process($cssin));
500 // Psedo test
501 $cssin = '.one:before {color: black;}';
502 $cssout = '.one:before{color:#000;}';
503 $this->assertEquals($cssout, $optimiser->process($cssin));
505 // Psedo test
506 $cssin = '.one:after {color: black;}';
507 $cssout = '.one:after{color:#000;}';
508 $this->assertEquals($cssout, $optimiser->process($cssin));
510 // Psedo test
511 $cssin = '.one:onclick {color: black;}';
512 $cssout = '.one:onclick{color:#000;}';
513 $this->assertEquals($cssout, $optimiser->process($cssin));
515 // Test complex CSS rules that don't really exist but mimic other CSS rules
516 $cssin = '.one {master-of-destruction: explode(\' \', "What madness");}';
517 $cssout = '.one{master-of-destruction:explode(\' \', "What madness");}';
518 $this->assertEquals($cssout, $optimiser->process($cssin));
520 // Test some complex IE css... I couldn't even think of a more complext solution
521 // than the CSS they came up with.
522 $cssin = 'a { opacity: 0.5; -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; filter: alpha(opacity=50); }';
523 $cssout = 'a{opacity:0.5;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";filter:alpha(opacity=50);}';
524 $this->assertEquals($cssout, $optimiser->process($cssin));
528 * A bulk processing test
529 * @param css_optimiser $optimiser
531 protected function try_bulk_processing(css_optimiser $optimiser) {
532 global $CFG;
533 $cssin = <<<CSS
534 .test .one {
535 margin:5px;
536 border:0;
538 .test .one {
539 margin: 10px;
540 color: red;
543 .test.one {
544 margin: 15px;
547 #test .one {margin: 20px;}
548 #test #one {margin: 25px;}.test #one {margin: 30px;}
549 .test .one { background-color: #123; }
550 .test.one{border:1px solid blue}.test.one{border-color:green;}
552 @media print {
553 #test .one {margin: 35px;}
556 @media print {
557 #test .one {margin: 40px;color: #123456;}
558 #test #one {margin: 45px;}
561 @media print,screen {
562 #test .one {color: #654321;}
565 #test .one,
566 #new.style {color:#000;}
567 CSS;
569 $cssout = <<<CSS
570 .test .one{color:#F00;margin:10px;border-width:0;background:#123;}
571 .test.one{margin:15px;border:1px solid #008000;}
572 #test .one{color:#000;margin:20px;}
573 #test #one{margin:25px;}
574 .test #one{margin:30px;}
575 #new.style{color:#000;}
578 @media print {
579 #test .one{color:#123456;margin:40px;}
580 #test #one{margin:45px;}
583 @media print,screen {
584 #test .one{color:#654321;}
586 CSS;
587 $CFG->cssoptimiserpretty = 1;
588 $this->assertEquals($optimiser->process($cssin), $cssout);
592 * Test CSS colour matching
594 public function test_css_is_colour() {
595 // First lets test hex colours
596 $this->assertTrue(css_is_colour('#123456'));
597 $this->assertTrue(css_is_colour('#123'));
598 $this->assertTrue(css_is_colour('#ABCDEF'));
599 $this->assertTrue(css_is_colour('#ABC'));
600 $this->assertTrue(css_is_colour('#abcdef'));
601 $this->assertTrue(css_is_colour('#abc'));
602 $this->assertTrue(css_is_colour('#aBcDeF'));
603 $this->assertTrue(css_is_colour('#aBc'));
604 $this->assertTrue(css_is_colour('#1a2Bc3'));
605 $this->assertTrue(css_is_colour('#1Ac'));
607 // Note the following two colour's arn't really colours but browsers process
608 // them still.
609 $this->assertTrue(css_is_colour('#A'));
610 $this->assertTrue(css_is_colour('#12'));
611 // Having four or five characters however are not valid colours and
612 // browsers don't parse them. They need to fail so that broken CSS
613 // stays broken after optimisation.
614 $this->assertFalse(css_is_colour('#1234'));
615 $this->assertFalse(css_is_colour('#12345'));
617 $this->assertFalse(css_is_colour('#BCDEFG'));
618 $this->assertFalse(css_is_colour('#'));
619 $this->assertFalse(css_is_colour('#0000000'));
620 $this->assertFalse(css_is_colour('#132-245'));
621 $this->assertFalse(css_is_colour('#13 23 43'));
622 $this->assertFalse(css_is_colour('123456'));
624 // Next lets test real browser mapped colours
625 $this->assertTrue(css_is_colour('black'));
626 $this->assertTrue(css_is_colour('blue'));
627 $this->assertTrue(css_is_colour('BLACK'));
628 $this->assertTrue(css_is_colour('Black'));
629 $this->assertTrue(css_is_colour('bLACK'));
630 $this->assertTrue(css_is_colour('mediumaquamarine'));
631 $this->assertTrue(css_is_colour('mediumAquamarine'));
632 $this->assertFalse(css_is_colour('monkey'));
633 $this->assertFalse(css_is_colour(''));
634 $this->assertFalse(css_is_colour('not a colour'));
636 // Next lets test rgb(a) colours
637 $this->assertTrue(css_is_colour('rgb(255,255,255)'));
638 $this->assertTrue(css_is_colour('rgb(0, 0, 0)'));
639 $this->assertTrue(css_is_colour('RGB (255, 255 , 255)'));
640 $this->assertTrue(css_is_colour('rgba(0,0,0,0)'));
641 $this->assertTrue(css_is_colour('RGBA(255,255,255,1)'));
642 $this->assertTrue(css_is_colour('rgbA(255,255,255,0.5)'));
643 $this->assertFalse(css_is_colour('rgb(-255,-255,-255)'));
644 $this->assertFalse(css_is_colour('rgb(256,-256,256)'));
646 // Now lets test HSL colours
647 $this->assertTrue(css_is_colour('hsl(0,0%,100%)'));
648 $this->assertTrue(css_is_colour('hsl(180, 0%, 10%)'));
649 $this->assertTrue(css_is_colour('hsl (360, 100% , 95%)'));
651 // Finally test the special values
652 $this->assertTrue(css_is_colour('inherit'));
656 * Test the css_is_width function
658 public function test_css_is_width() {
660 $this->assertTrue(css_is_width('0'));
661 $this->assertTrue(css_is_width('0px'));
662 $this->assertTrue(css_is_width('0em'));
663 $this->assertTrue(css_is_width('199px'));
664 $this->assertTrue(css_is_width('199em'));
665 $this->assertTrue(css_is_width('199%'));
666 $this->assertTrue(css_is_width('-1'));
667 $this->assertTrue(css_is_width('-1px'));
668 $this->assertTrue(css_is_width('auto'));
669 $this->assertTrue(css_is_width('inherit'));
671 $this->assertFalse(css_is_width('-'));
672 $this->assertFalse(css_is_width('bananas'));
673 $this->assertFalse(css_is_width(''));
674 $this->assertFalse(css_is_width('top'));
678 * This function tests some of the broken crazy CSS we have in Moodle.
679 * For each of these things the value needs to be corrected if we can be 100%
680 * certain what is going wrong, Or it needs to be left as is.
682 * @param css_optimiser $optimiser
684 public function try_broken_css_found_in_moodle(css_optimiser $optimiser) {
685 // Notice how things are out of order here but that they get corrected
686 $cssin = '.test {background:url([[pix:theme|pageheaderbgred]]) top center no-repeat}';
687 $cssout = '.test{background:url([[pix:theme|pageheaderbgred]]) no-repeat top center;}';
688 $this->assertEquals($cssout, $optimiser->process($cssin));
690 // Cursor hand isn't valid
691 $cssin = '.test {cursor: hand;}';
692 $cssout = '.test{cursor:hand;}';
693 $this->assertEquals($cssout, $optimiser->process($cssin));
695 // Zoom property isn't valid
696 $cssin = '.test {zoom: 1;}';
697 $cssout = '.test{zoom:1;}';
698 $this->assertEquals($cssout, $optimiser->process($cssin));
700 // Left isn't a valid position property
701 $cssin = '.test {position: left;}';
702 $cssout = '.test{position:left;}';
703 $this->assertEquals($cssout, $optimiser->process($cssin));
705 // The dark red color isn't a valid HTML color but has a standardised
706 // translation of #8B0000
707 $cssin = '.test {color: darkred;}';
708 $cssout = '.test{color:#8B0000;}';
709 $this->assertEquals($cssout, $optimiser->process($cssin));
711 // You can't use argb colours as border colors
712 $cssin = '.test {border-bottom: 1px solid rgba(0,0,0,0.25);}';
713 $cssout = '.test{border-bottom:1px solid rgba(0,0,0,0.25);}';
714 $this->assertEquals($cssout, $optimiser->process($cssin));
716 // Opacity with annoying IE equivilants....
717 $cssin = '.test {opacity: 0.5; -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; filter: alpha(opacity=50);}';
718 $cssout = '.test{opacity:0.5;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";filter:alpha(opacity=50);}';
719 $this->assertEquals($cssout, $optimiser->process($cssin));