] );
}
+ /**
+ * @dataProvider mimeTypeProvider
+ */
+ public function testGetMimeType( $fileContents, $fileExtension, $expected ) {
+ $fileName = wfTempDir() . DIRECTORY_SEPARATOR . uniqid( 'MW_PHPUnit_CSSMinTest_' ) . '.'
+ . $fileExtension;
+ $this->addTmpFiles( $fileName );
+ file_put_contents( $fileName, $fileContents );
+ $this->assertSame( $expected, CSSMin::getMimeType( $fileName ) );
+ }
+
+ public function mimeTypeProvider() {
+ return [
+ 'JPEG with short extension' => [
+ "\xFF\xD8\xFF",
+ 'jpg',
+ 'image/jpeg'
+ ],
+ 'JPEG with long extension' => [
+ "\xFF\xD8\xFF",
+ 'jpeg',
+ 'image/jpeg'
+ ],
+ 'PNG' => [
+ "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A",
+ 'png',
+ 'image/png'
+ ],
+
+ 'PNG extension but JPEG content' => [
+ "\xFF\xD8\xFF",
+ 'png',
+ 'image/png'
+ ],
+ 'JPEG extension but PNG content' => [
+ "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A",
+ 'jpg',
+ 'image/jpeg'
+ ],
+ 'PNG extension but SVG content' => [
+ '<?xml version="1.0"?><svg></svg>',
+ 'png',
+ 'image/png'
+ ],
+ 'SVG extension but PNG content' => [
+ "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A",
+ 'svg',
+ 'image/svg+xml'
+ ],
+
+ 'SVG with all headers' => [
+ '<?xml version="1.0"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" '
+ . '"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg></svg>',
+ 'svg',
+ 'image/svg+xml'
+ ],
+ 'SVG with XML header only' => [
+ '<?xml version="1.0"?><svg></svg>',
+ 'svg',
+ 'image/svg+xml'
+ ],
+ 'SVG with DOCTYPE only' => [
+ '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" '
+ . '"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg></svg>',
+ 'svg',
+ 'image/svg+xml'
+ ],
+ 'SVG without any header' => [
+ '<svg></svg>',
+ 'svg',
+ 'image/svg+xml'
+ ],
+ ];
+ }
+
/**
* @dataProvider provideMinifyCases
* @covers CSSMin::minify
[ "foo, bar {\n\tprop: value; /* comment */\n}", "foo,bar{prop:value; }" ],
// Keep track of things that aren't as minified as much as they
- // could be (bug 35493)
+ // could be (T37493)
[ 'foo { prop: value ;}', 'foo{prop:value }' ],
[ 'foo { prop : value; }', 'foo{prop :value}' ],
[ 'foo { prop: value ; }', 'foo{prop:value }' ],
];
}
+ public static function provideIsRemoteUrl() {
+ return [
+ [ true, 'http://localhost/w/red.gif?123' ],
+ [ true, 'https://example.org/x.png' ],
+ [ true, '//example.org/x.y.z/image.png' ],
+ [ true, '//localhost/styles.css?query=yes' ],
+ [ true, 'data:image/gif;base64,R0lGODlhAQABAIAAAP8AADAAACwAAAAAAQABAAACAkQBADs=' ],
+ [ false, 'x.gif' ],
+ [ false, '/x.gif' ],
+ [ false, './x.gif' ],
+ [ false, '../x.gif' ],
+ ];
+ }
+
+ /**
+ * @dataProvider provideIsRemoteUrl
+ * @cover CSSMin::isRemoteUrl
+ */
+ public function testIsRemoteUrl( $expect, $url ) {
+ $this->assertEquals( CSSMinTestable::isRemoteUrl( $url ), $expect );
+ }
+
+ public static function provideIsLocalUrls() {
+ return [
+ [ false, 'x.gif' ],
+ [ true, '/x.gif' ],
+ [ false, './x.gif' ],
+ [ false, '../x.gif' ],
+ ];
+ }
+
+ /**
+ * @dataProvider provideIsLocalUrls
+ * @cover CSSMin::isLocalUrl
+ */
+ public function testIsLocalUrl( $expect, $url ) {
+ $this->assertEquals( CSSMinTestable::isLocalUrl( $url ), $expect );
+ }
+
/**
* This tests funky parameters to CSSMin::remap. testRemapRemapping tests
* the basic functionality.
'foo { prop: url(http://example.org/bar.png); }',
],
[
- 'With trailing slash on remote (bug 27052)',
+ 'With trailing slash on remote (T29052)',
[ 'foo { prop: url(../bar.png); }', false, 'http://example.org/quux/', false ],
'foo { prop: url(http://example.org/bar.png); }',
],
$this->assertEquals( $expectedOutput, $realOutput, "CSSMin::remap: $message" );
}
- public static function provideIsRemoteUrl() {
- return [
- [ true, 'http://localhost/w/red.gif?123' ],
- [ true, 'https://example.org/x.png' ],
- [ true, '//example.org/x.y.z/image.png' ],
- [ true, '//localhost/styles.css?query=yes' ],
- [ true, 'data:image/gif;base64,R0lGODlhAQABAIAAAP8AADAAACwAAAAAAQABAAACAkQBADs=' ],
- [ false, 'x.gif' ],
- [ false, '/x.gif' ],
- [ false, './x.gif' ],
- [ false, '../x.gif' ],
- ];
- }
-
- /**
- * @dataProvider provideIsRemoteUrl
- * @cover CSSMin::isRemoteUrl
- */
- public function testIsRemoteUrl( $expect, $url ) {
- $this->assertEquals( CSSMinTestable::isRemoteUrl( $url ), $expect );
- }
-
- public static function provideIsLocalUrls() {
- return [
- [ false, 'x.gif' ],
- [ true, '/x.gif' ],
- [ false, './x.gif' ],
- [ false, '../x.gif' ],
- ];
- }
-
- /**
- * @dataProvider provideIsLocalUrls
- * @cover CSSMin::isLocalUrl
- */
- public function testIsLocalUrl( $expect, $url ) {
- $this->assertEquals( CSSMinTestable::isLocalUrl( $url ), $expect );
- }
-
public static function provideRemapRemappingCases() {
// red.gif and green.gif are one-pixel 35-byte GIFs.
// large.png is a 35K PNG that should be non-embeddable.
],
[
'Remote URL (unnecessary quotes not preserved)',
- 'foo { background: url("http://example.org/w/foo.png"); }',
- 'foo { background: url(http://example.org/w/foo.png); }',
+ 'foo { background: url("http://example.org/w/unnecessary-quotes.png"); }',
+ 'foo { background: url(http://example.org/w/unnecessary-quotes.png); }',
],
[
'Embedded file',
'@import url(http://doc.example.org/styles.css)',
],
[
- '@import rule to URL (should we remap this?)',
- '@import url(//localhost/styles.css?query=yes)',
- '@import url(//localhost/styles.css?query=yes)',
+ '@import rule to local file (should we remap this?)',
+ '@import url(/styles.css)',
+ '@import url(http://doc.example.org/styles.css)',
+ ],
+ [
+ '@import rule to URL',
+ '@import url(//localhost/styles.css?query=val)',
+ '@import url(//localhost/styles.css?query=val)',
+ ],
+ [
+ 'Background URL (double quotes)',
+ 'foo { background: url("//localhost/styles.css?quoted=double") }',
+ 'foo { background: url(//localhost/styles.css?quoted=double) }',
+ ],
+ [
+ 'Background URL (single quotes)',
+ 'foo { background: url(\'//localhost/styles.css?quoted=single\') }',
+ 'foo { background: url(//localhost/styles.css?quoted=single) }',
+ ],
+ [
+ 'Background URL (containing parentheses; T60473)',
+ 'foo { background: url("//localhost/styles.css?query=(parens)") }',
+ 'foo { background: url("//localhost/styles.css?query=(parens)") }',
+ ],
+ [
+ 'Background URL (double quoted, containing single quotes; T60473)',
+ 'foo { background: url("//localhost/styles.css?quote=\'") }',
+ 'foo { background: url("//localhost/styles.css?quote=\'") }',
+ ],
+ [
+ 'Background URL (single quoted, containing double quotes; T60473)',
+ 'foo { background: url(\'//localhost/styles.css?quote="\') }',
+ 'foo { background: url("//localhost/styles.css?quote=\"") }',
],
[
'Simple case with comments before url',
'{ background: /*asd*/ url(http://localhost/w/something.png); background: /*jkl*/ url(http://localhost/w/something.png); }',
],
[
- 'Sanity check for offending line from jquery.ui.theme.css (bug 60077)',
+ 'Sanity check for offending line from jquery.ui.theme.css (T62077)',
'.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3/*{borderColorDefault}*/; background: #e6e6e6/*{bgColorDefault}*/ url(images/ui-bg_glass_75_e6e6e6_1x400.png)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #555555/*{fcDefault}*/; }',
'.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3/*{borderColorDefault}*/; background: #e6e6e6/*{bgColorDefault}*/ url(http://localhost/w/images/ui-bg_glass_75_e6e6e6_1x400.png)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #555555/*{fcDefault}*/; }',
],
}
/**
- * Seperated because they are currently broken (bug 35492)
+ * Seperated because they are currently broken (T37492)
*
* @group Broken
* @dataProvider provideStringCases