MediaWiki  REL1_20
CSSJanusTest.php
Go to the documentation of this file.
00001 <?php
00008 class CSSJanusTest extends MediaWikiTestCase {
00012         function testTransform( $cssA, $cssB = null ) {
00013 
00014                 if ( $cssB ) {
00015                         $transformedA = CSSJanus::transform( $cssA );
00016                         $this->assertEquals( $transformedA, $cssB, 'Test A-B transformation' );
00017 
00018                         $transformedB = CSSJanus::transform( $cssB );
00019                         $this->assertEquals( $transformedB, $cssA, 'Test B-A transformation' );
00020 
00021                 // If no B version is provided, it means
00022                 // the output should equal the input.
00023                 } else {
00024                         $transformedA = CSSJanus::transform( $cssA );
00025                         $this->assertEquals( $transformedA, $cssA, 'Nothing was flipped' );
00026                 }
00027         }
00028 
00032         function testTransformAdvanced( $code, $expectedOutput, $options = array() ) {
00033                 $swapLtrRtlInURL = isset( $options['swapLtrRtlInURL'] ) ? $options['swapLtrRtlInURL'] : false;
00034                 $swapLeftRightInURL = isset( $options['swapLeftRightInURL'] ) ? $options['swapLeftRightInURL'] : false;
00035 
00036                 $flipped = CSSJanus::transform( $code, $swapLtrRtlInURL, $swapLeftRightInURL );
00037 
00038                 $this->assertEquals( $expectedOutput, $flipped,
00039                         'Test flipping, options: url-ltr-rtl=' . ($swapLtrRtlInURL ? 'true' : 'false')
00040                                 . ' url-left-right=' . ($swapLeftRightInURL ? 'true' : 'false')
00041                 );
00042         }
00047         function testTransformBroken( $code, $expectedOutput ) {
00048                 $flipped = CSSJanus::transform( $code );
00049 
00050                 $this->assertEquals( $expectedOutput, $flipped, 'Test flipping' );
00051         }
00052 
00057         function provideTransformCases() {
00058                 return array(
00059                         // Property keys
00060                         array(
00061                                 '.foo { left: 0; }',
00062                                 '.foo { right: 0; }'
00063                         ),
00064                         // Guard against partial keys
00065                         // (CSS currently doesn't have flippable properties
00066                         // that contain the direction as part of the key without
00067                         // dash separation)
00068                         array(
00069                                 '.foo { alright: 0; }'
00070                         ),
00071                         array(
00072                                 '.foo { balleft: 0; }'
00073                         ),
00074 
00075                         // Dashed property keys
00076                         array(
00077                                 '.foo { padding-left: 0; }',
00078                                 '.foo { padding-right: 0; }'
00079                         ),
00080                         array(
00081                                 '.foo { margin-left: 0; }',
00082                                 '.foo { margin-right: 0; }'
00083                         ),
00084                         array(
00085                                 '.foo { border-left: 0; }',
00086                                 '.foo { border-right: 0; }'
00087                         ),
00088 
00089                         // Double-dashed property keys
00090                         array(
00091                                 '.foo { border-left-color: red; }',
00092                                 '.foo { border-right-color: red; }'
00093                         ),
00094                         array(
00095                                 // Includes unknown properties?
00096                                 '.foo { x-left-y: 0; }',
00097                                 '.foo { x-right-y: 0; }'
00098                         ),
00099 
00100                         // Multi-value properties
00101                         array(
00102                                 '.foo { padding: 0; }'
00103                         ),
00104                         array(
00105                                 '.foo { padding: 0 1px; }'
00106                         ),
00107                         array(
00108                                 '.foo { padding: 0 1px 2px; }'
00109                         ),
00110                         array(
00111                                 '.foo { padding: 0 1px 2px 3px; }',
00112                                 '.foo { padding: 0 3px 2px 1px; }'
00113                         ),
00114 
00115                         // Shorthand / Four notation
00116                         array(
00117                                 '.foo { padding: .25em 15px 0pt 0ex; }',
00118                                 '.foo { padding: .25em 0ex 0pt 15px; }'
00119                         ),
00120                         array(
00121                                 '.foo { margin: 1px -4px 3px 2px; }',
00122                                 '.foo { margin: 1px 2px 3px -4px; }'
00123                         ),
00124                         array(
00125                                 '.foo { padding: 0 15px .25em 0; }',
00126                                 '.foo { padding: 0 0 .25em 15px; }'
00127                         ),
00128                         array(
00129                                 '.foo { padding: 1px 4.1grad 3px 2%; }',
00130                                 '.foo { padding: 1px 2% 3px 4.1grad; }'
00131                         ),
00132                         array(
00133                                 '.foo { padding: 1px 2px 3px auto; }',
00134                                 '.foo { padding: 1px auto 3px 2px; }'
00135                         ),
00136                         array(
00137                                 '.foo { padding: 1px inherit 3px auto; }',
00138                                 '.foo { padding: 1px auto 3px inherit; }'
00139                         ),
00140                         array(
00141                                 '.foo { border-radius: .25em 15px 0pt 0ex; }',
00142                                 '.foo { border-radius: .25em 0ex 0pt 15px; }'
00143                         ),
00144                         array(
00145                                 '.foo { x-unknown: a b c d; }'
00146                         ),
00147                         array(
00148                                 '.foo barpx 0 2% { opacity: 0; }'
00149                         ),
00150                         array(
00151                                 '#settings td p strong'
00152                         ),
00153                         array(
00154                                 # Not sure how 4+ values should behave,
00155                                 # testing to make sure changes are detected
00156                                 '.foo { x-unknown: 1 2 3 4 5; }',
00157                                 '.foo { x-unknown: 1 4 3 2 5; }',
00158                         ),
00159                         array(
00160                                 '.foo { x-unknown: 1 2 3 4 5 6; }',
00161                                 '.foo { x-unknown: 1 4 3 2 5 6; }',
00162                         ),
00163 
00164                         // Shorthand / Three notation
00165                         array(
00166                                 '.foo { margin: 1em 0 .25em; }'
00167                         ),
00168                         array(
00169                                 '.foo { margin:-1.5em 0 -.75em; }'
00170                         ),
00171 
00172                         // Shorthand / Two notation
00173                         array(
00174                                 '.foo { padding: 1px 2px; }'
00175                         ),
00176 
00177                         // Shorthand / One notation
00178                         array(
00179                                 '.foo { padding: 1px; }'
00180                         ),
00181 
00182                         // Direction
00183                         // Note: This differs from the Python implementation,
00184                         // see also CSSJanus::fixDirection for more info.
00185                         array(
00186                                 '.foo { direction: ltr; }',
00187                                 '.foo { direction: rtl; }'
00188                         ),
00189                         array(
00190                                 '.foo { direction: rtl; }',
00191                                 '.foo { direction: ltr; }'
00192                         ),
00193                         array(
00194                                 'input { direction: ltr; }',
00195                                 'input { direction: rtl; }'
00196                         ),
00197                         array(
00198                                 'input { direction: rtl; }',
00199                                 'input { direction: ltr; }'
00200                         ),
00201                         array(
00202                                 'body { direction: ltr; }',
00203                                 'body { direction: rtl; }'
00204                         ),
00205                         array(
00206                                 '.foo, body, input { direction: ltr; }',
00207                                 '.foo, body, input { direction: rtl; }'
00208                         ),
00209                         array(
00210                                 'body { padding: 10px; direction: ltr; }',
00211                                 'body { padding: 10px; direction: rtl; }'
00212                         ),
00213                         array(
00214                                 'body { direction: ltr } .myClass { direction: ltr }',
00215                                 'body { direction: rtl } .myClass { direction: rtl }'
00216                         ),
00217 
00218                         // Left/right values
00219                         array(
00220                                 '.foo { float: left; }',
00221                                 '.foo { float: right; }'
00222                         ),
00223                         array(
00224                                 '.foo { text-align: left; }',
00225                                 '.foo { text-align: right; }'
00226                         ),
00227                         array(
00228                                 '.foo { -x-unknown: left; }',
00229                                 '.foo { -x-unknown: right; }'
00230                         ),
00231                         // Guard against selectors that look flippable
00232                         array(
00233                                 '.column-left { width: 0; }'
00234                         ),
00235                         array(
00236                                 'a.left { width: 0; }'
00237                         ),
00238                         array(
00239                                 'a.leftification { width: 0; }'
00240                         ),
00241                         array(
00242                                 'a.ltr { width: 0; }'
00243                         ),
00244                         array(
00245                                 # <div class="a-ltr png">
00246                                 '.a-ltr.png { width: 0; }'
00247                         ),
00248                         array(
00249                                 # <foo-ltr attr="x">
00250                                 'foo-ltr[attr="x"] { width: 0; }'
00251                         ),
00252                         array(
00253                                 'div.left > span.right+span.left { width: 0; }'
00254                         ),
00255                         array(
00256                                 '.thisclass .left .myclass { width: 0; }'
00257                         ),
00258                         array(
00259                                 '.thisclass .left .myclass #myid { width: 0; }'
00260                         ),
00261 
00262                         // Cursor values (east/west)
00263                         array(
00264                                 '.foo { cursor: e-resize; }',
00265                                 '.foo { cursor: w-resize; }'
00266                         ),
00267                         array(
00268                                 '.foo { cursor: se-resize; }',
00269                                 '.foo { cursor: sw-resize; }'
00270                         ),
00271                         array(
00272                                 '.foo { cursor: ne-resize; }',
00273                                 '.foo { cursor: nw-resize; }'
00274                         ),
00275 
00276                         // Background
00277                         array(
00278                                 '.foo { background-position: top left; }',
00279                                 '.foo { background-position: top right; }'
00280                         ),
00281                         array(
00282                                 '.foo { background: url(/foo/bar.png) top left; }',
00283                                 '.foo { background: url(/foo/bar.png) top right; }'
00284                         ),
00285                         array(
00286                                 '.foo { background: url(/foo/bar.png) top left no-repeat; }',
00287                                 '.foo { background: url(/foo/bar.png) top right no-repeat; }'
00288                         ),
00289                         array(
00290                                 '.foo { background: url(/foo/bar.png) no-repeat top left; }',
00291                                 '.foo { background: url(/foo/bar.png) no-repeat top right; }'
00292                         ),
00293                         array(
00294                                 '.foo { background: #fff url(/foo/bar.png) no-repeat top left; }',
00295                                 '.foo { background: #fff url(/foo/bar.png) no-repeat top right; }'
00296                         ),
00297                         array(
00298                                 '.foo { background-position: 100% 40%; }',
00299                                 '.foo { background-position: 0% 40%; }'
00300                         ),
00301                         array(
00302                                 '.foo { background-position: 23% 0; }',
00303                                 '.foo { background-position: 77% 0; }'
00304                         ),
00305                         array(
00306                                 '.foo { background-position: 23% auto; }',
00307                                 '.foo { background-position: 77% auto; }'
00308                         ),
00309                         array(
00310                                 '.foo { background-position-x: 23%; }',
00311                                 '.foo { background-position-x: 77%; }'
00312                         ),
00313                         array(
00314                                 '.foo { background-position-y: 23%; }',
00315                                 '.foo { background-position-y: 23%; }'
00316                         ),
00317                         array(
00318                                 '.foo { background:url(../foo.png) no-repeat 75% 50%; }',
00319                                 '.foo { background:url(../foo.png) no-repeat 25% 50%; }'
00320                         ),
00321                         array(
00322                                 '.foo { background: 10% 20% } .bar { background: 40% 30% }',
00323                                 '.foo { background: 90% 20% } .bar { background: 60% 30% }'
00324                         ),
00325 
00326                         // Multiple rules
00327                         array(
00328                                 'body { direction: rtl; float: right; } .foo { direction: ltr; float: right; }',
00329                                 'body { direction: ltr; float: left; } .foo { direction: rtl; float: left; }',
00330                         ),
00331 
00332                         // Duplicate properties
00333                         array(
00334                                 '.foo { float: left; float: right; float: left; }',
00335                                 '.foo { float: right; float: left; float: right; }',
00336                         ),
00337 
00338                         // Preserve comments
00339                         array(
00340                                 '/* left /* right */left: 10px',
00341                                 '/* left /* right */right: 10px'
00342                         ),
00343                         array(
00344                                 '/*left*//*left*/left: 10px',
00345                                 '/*left*//*left*/right: 10px'
00346                         ),
00347                         array(
00348                                 '/* Going right is cool */ .foo { width: 0 }',
00349                         ),
00350                         array(
00351                                 "/* padding-right 1 2 3 4 */\n#test { width: 0}\n/*right*/"
00352                         ),
00353                         array(
00354                                 "/** Two line comment\n * left\n \*/\n#test {width: 0}"
00355                         ),
00356 
00357                         // @noflip annotation
00358                         array(
00359                                 // before selector (single)
00360                                 '/* @noflip */ div { float: left; }'
00361                         ),
00362                         array(
00363                                 // before selector (multiple)
00364                                 '/* @noflip */ div, .notme { float: left; }'
00365                         ),
00366                         array(
00367                                 // inside selector
00368                                 'div, /* @noflip */ .foo { float: left; }'
00369                         ),
00370                         array(
00371                                 // after selector
00372                                 'div, .notme /* @noflip */ { float: left; }'
00373                         ),
00374                         array(
00375                                 // before multiple rules
00376                                 '/* @noflip */ div { float: left; } .foo { float: left; }',
00377                                 '/* @noflip */ div { float: left; } .foo { float: right; }'
00378                         ),
00379                         array(
00380                                 // after multiple rules
00381                                 '.foo { float: left; } /* @noflip */ div { float: left; }',
00382                                 '.foo { float: right; } /* @noflip */ div { float: left; }'
00383                         ),
00384                         array(
00385                                 // before multiple properties
00386                                 'div { /* @noflip */ float: left; text-align: left; }',
00387                                 'div { /* @noflip */ float: left; text-align: right; }'
00388                         ),
00389                         array(
00390                                 // after multiple properties
00391                                 'div { float: left; /* @noflip */ text-align: left; }',
00392                                 'div { float: right; /* @noflip */ text-align: left; }'
00393                         ),
00394 
00395                         // Guard against css3 stuff
00396                         array(
00397                                 'background-image: -moz-linear-gradient(#326cc1, #234e8c);'
00398                         ),
00399                         array(
00400                                 'background-image: -webkit-gradient(linear, 100% 0%, 0% 0%, from(#666666), to(#ffffff));'
00401                         ),
00402 
00403                         // CSS syntax / white-space variations
00404                         // spaces, no spaces, tabs, new lines, omitting semi-colons
00405                         array(
00406                                 ".foo { left: 0; }",
00407                                 ".foo { right: 0; }"
00408                         ),
00409                         array(
00410                                 ".foo{ left: 0; }",
00411                                 ".foo{ right: 0; }"
00412                         ),
00413                         array(
00414                                 ".foo{ left: 0 }",
00415                                 ".foo{ right: 0 }"
00416                         ),
00417                         array(
00418                                 ".foo{left:0 }",
00419                                 ".foo{right:0 }"
00420                         ),
00421                         array(
00422                                 ".foo{left:0}",
00423                                 ".foo{right:0}"
00424                         ),
00425                         array(
00426                                 ".foo  {  left : 0 ; }",
00427                                 ".foo  {  right : 0 ; }"
00428                         ),
00429                         array(
00430                                 ".foo\n  {  left : 0 ; }",
00431                                 ".foo\n  {  right : 0 ; }"
00432                         ),
00433                         array(
00434                                 ".foo\n  {  \nleft : 0 ; }",
00435                                 ".foo\n  {  \nright : 0 ; }"
00436                         ),
00437                         array(
00438                                 ".foo\n  { \n left : 0 ; }",
00439                                 ".foo\n  { \n right : 0 ; }"
00440                         ),
00441                         array(
00442                                 ".foo\n  { \n left\n  : 0; }",
00443                                 ".foo\n  { \n right\n  : 0; }"
00444                         ),
00445                         array(
00446                                 ".foo \n  { \n left\n  : 0; }",
00447                                 ".foo \n  { \n right\n  : 0; }"
00448                         ),
00449                         array(
00450                                 ".foo\n{\nleft\n:\n0;}",
00451                                 ".foo\n{\nright\n:\n0;}"
00452                         ),
00453                         array(
00454                                 ".foo\n.bar {\n\tleft: 0;\n}",
00455                                 ".foo\n.bar {\n\tright: 0;\n}"
00456                         ),
00457                         array(
00458                                 ".foo\t{\tleft\t:\t0;}",
00459                                 ".foo\t{\tright\t:\t0;}"
00460                         ),
00461                 );
00462         }
00463 
00469         function provideTransformAdvancedCases() {
00470                 $bgPairs = array(
00471                         # [ - _ . ] <-> [ left right ltr rtl ]
00472                         'foo.jpg' => 'foo.jpg',
00473                         'left.jpg' => 'right.jpg',
00474                         'ltr.jpg' => 'rtl.jpg',
00475 
00476                         'foo-left.png' => 'foo-right.png',
00477                         'foo_left.png' => 'foo_right.png',
00478                         'foo.left.png' => 'foo.right.png',
00479 
00480                         'foo-ltr.png' => 'foo-rtl.png',
00481                         'foo_ltr.png' => 'foo_rtl.png',
00482                         'foo.ltr.png' => 'foo.rtl.png',
00483 
00484                         'left-foo.png' => 'right-foo.png',
00485                         'left_foo.png' => 'right_foo.png',
00486                         'left.foo.png' => 'right.foo.png',
00487 
00488                         'ltr-foo.png' => 'rtl-foo.png',
00489                         'ltr_foo.png' => 'rtl_foo.png',
00490                         'ltr.foo.png' => 'rtl.foo.png',
00491 
00492                         'foo-ltr-left.gif' => 'foo-rtl-right.gif',
00493                         'foo_ltr_left.gif' => 'foo_rtl_right.gif',
00494                         'foo.ltr.left.gif' => 'foo.rtl.right.gif',
00495                         'foo-ltr_left.gif' => 'foo-rtl_right.gif',
00496                         'foo_ltr.left.gif' => 'foo_rtl.right.gif',
00497                 );
00498                 $provider = array();
00499                 foreach ( $bgPairs as $left => $right ) {
00500                         # By default '-rtl' and '-left' etc. are not touched,
00501                         # Only when the appropiate parameter is set.
00502                         $provider[] = array(
00503                                 ".foo { background: url(images/$left); }",
00504                                 ".foo { background: url(images/$left); }"
00505                         );
00506                         $provider[] = array(
00507                                 ".foo { background: url(images/$right); }",
00508                                 ".foo { background: url(images/$right); }"
00509                         );
00510                         $provider[] = array(
00511                                 ".foo { background: url(images/$left); }",
00512                                 ".foo { background: url(images/$right); }",
00513                                 array(
00514                                         'swapLtrRtlInURL' => true,
00515                                         'swapLeftRightInURL' => true,
00516                                 )
00517                         );
00518                         $provider[] = array(
00519                                 ".foo { background: url(images/$right); }",
00520                                 ".foo { background: url(images/$left); }",
00521                                 array(
00522                                         'swapLtrRtlInURL' => true,
00523                                         'swapLeftRightInURL' => true,
00524                                 )
00525                         );
00526                 }
00527 
00528                 return $provider;
00529         }
00530 
00535         function provideTransformBrokenCases() {
00536                 return array(
00537                         // Guard against partial keys
00538                         array(
00539                                 '.foo { leftxx: 0; }',
00540                                 '.foo { leftxx: 0; }'
00541                         ),
00542                         array(
00543                                 '.foo { rightxx: 0; }',
00544                                 '.foo { rightxx: 0; }'
00545                         ),
00546 
00547                         // Guard against selectors that look flippable
00548                         array(
00549                                 # <foo-left-x attr="x">
00550                                 'foo-left-x[attr="x"] { width: 0; }',
00551                                 'foo-left-x[attr="x"] { width: 0; }'
00552                         ),
00553                         array(
00554                                 # <div class="foo" data-left="x">
00555                                 '.foo[data-left="x"] { width: 0; }',
00556                                 '.foo[data-left="x"] { width: 0; }'
00557                         ),
00558                 );
00559         }
00560 }