wiki.techinc.nl/tests/phpunit/unit/includes/resourceloader/ResourceLoaderImageTest.php

135 lines
4.2 KiB
PHP
Raw Normal View History

<?php
/**
* @group ResourceLoader
resourceloader: Add version to ResourceLoaderImage urls for long-cache The code previously here did not work well as it merely forwarded the hash from the current web request. This had numerous issues: 1. It was often null because requests for stylesheets do not cary a version hash. 2. When requested by JavaScript, the version hash would be a combination-hash of many unrelated modules, thus when requested as part of different batches, it would produce different urls which is not ideal. The impact of this is minimal currently because we basically never use these urls, as SVGs are almost always embedded instead of ref'ed by url. PNG urls are only generated for non-JS modules and then only used in older browsers not supporting SVG. And, even after all that, for the edge case of an SVG being ref'ed by url, they would be stored in LocalStorage by mw.loader with the name+version of the module the image belonged to, not the version hash of the batch request it came with. Which means that, yes, localstorage key for "somemodule+someversion" would have different values for different users, based on which batch the value came with, because the image urls were using the version hash of the batch request from ResourceLoaderContext. This is weird, but didn't cause bugs or inefficiencies because the user would never be exposed to the other possible urls for that image because we always check LocalStorage first. It did cause fragmentation server-side in Varnish, though. This is all fixed now by always including a version, and setting it to the version of the module. This means there is no more Varnish fragmentation for these. And it means that browsers are now allowed to cache the images served from these urls for 30+ days (immutable) instead of only 5min, which is what happened when they didn't have a version parameter (or set to null). Bug: T233343 Change-Id: I4af7fda03698ed4c288d154e7787fb2f3cbbe6c5
2019-09-26 16:26:52 +00:00
* @covers ResourceLoaderImage
*/
class ResourceLoaderImageTest extends MediaWikiUnitTestCase {
private $imagesPath;
protected function setUp() : void {
parent::setUp();
$this->imagesPath = __DIR__ . '/../../../data/resourceloader';
}
protected function getTestImage( $name ) {
$options = ResourceLoaderImageModuleTest::$commonImageData[$name];
$fileDescriptor = is_string( $options ) ? $options : $options['file'];
$allowedVariants = ( is_array( $options ) && isset( $options['variants'] ) ) ?
$options['variants'] : [];
$variants = array_fill_keys( $allowedVariants, [ 'color' => 'red' ] );
return new ResourceLoaderImageTestable(
$name,
'test',
$fileDescriptor,
$this->imagesPath,
$variants
);
}
public static function provideGetPath() {
return [
[ 'abc', 'en', 'abc.gif' ],
[ 'abc', 'he', 'abc.gif' ],
[ 'def', 'en', 'def.svg' ],
[ 'def', 'he', 'def.svg' ],
[ 'ghi', 'en', 'ghi.svg' ],
[ 'ghi', 'he', 'jkl.svg' ],
[ 'mno', 'en', 'mno-ltr.svg' ],
[ 'mno', 'ar', 'mno-rtl.svg' ],
[ 'mno', 'he', 'mno-ltr.svg' ],
[ 'pqr', 'en', 'pqr-b.svg' ],
[ 'pqr', 'en-gb', 'pqr-b.svg' ],
[ 'pqr', 'de', 'pqr-f.svg' ],
[ 'pqr', 'de-formal', 'pqr-f.svg' ],
[ 'pqr', 'ar', 'pqr-f.svg' ],
[ 'pqr', 'fr', 'pqr-a.svg' ],
[ 'pqr', 'he', 'pqr-a.svg' ],
];
}
/**
* @dataProvider provideGetPath
*/
public function testGetPath( $imageName, $languageCode, $path ) {
static $dirMap = [
'en' => 'ltr',
'en-gb' => 'ltr',
'de' => 'ltr',
'de-formal' => 'ltr',
'fr' => 'ltr',
'he' => 'rtl',
'ar' => 'rtl',
];
$image = $this->getTestImage( $imageName );
$context = new DerivativeResourceLoaderContext(
$this->createMock( ResourceLoaderContext::class )
);
$context->setLanguage( $languageCode );
$context->setDirection( $dirMap[$languageCode] );
$this->assertEquals( $image->getPath( $context ), $this->imagesPath . '/' . $path );
}
public function testGetExtension() {
$image = $this->getTestImage( 'def' );
$this->assertEquals( $image->getExtension(), 'svg' );
$this->assertEquals( $image->getExtension( 'original' ), 'svg' );
$this->assertEquals( $image->getExtension( 'rasterized' ), 'png' );
$image = $this->getTestImage( 'abc' );
$this->assertEquals( $image->getExtension(), 'gif' );
$this->assertEquals( $image->getExtension( 'original' ), 'gif' );
$this->assertEquals( $image->getExtension( 'rasterized' ), 'gif' );
}
public function testGetImageData() {
$context = $this->createMock( ResourceLoaderContext::class );
$image = $this->getTestImage( 'def' );
$data = file_get_contents( $this->imagesPath . '/def.svg' );
$dataConstructive = file_get_contents( $this->imagesPath . '/def_variantize.svg' );
$this->assertEquals( $image->getImageData( $context, null, 'original' ), $data );
$this->assertEquals(
$image->getImageData( $context, 'destructive', 'original' ),
$dataConstructive
);
// Stub, since we don't know if we even have a SVG handler, much less what exactly it'll output
$this->assertEquals( $image->getImageData( $context, null, 'rasterized' ), 'RASTERIZESTUB' );
$image = $this->getTestImage( 'abc' );
$data = file_get_contents( $this->imagesPath . '/abc.gif' );
$this->assertEquals( $image->getImageData( $context, null, 'original' ), $data );
$this->assertEquals( $image->getImageData( $context, null, 'rasterized' ), $data );
}
public function testMassageSvgPathdata() {
$image = $this->getTestImage( 'ghi' );
$data = file_get_contents( $this->imagesPath . '/ghi.svg' );
$dataMassaged = file_get_contents( $this->imagesPath . '/ghi_massage.svg' );
$this->assertEquals( $image->massageSvgPathdata( $data ), $dataMassaged );
}
}
class ResourceLoaderImageTestable extends ResourceLoaderImage {
private $mockFallbacks = [
'en-gb' => [ 'en' ],
'de-formal' => [ 'de' ],
];
// Make some protected methods public
public function massageSvgPathdata( $svg ) {
return parent::massageSvgPathdata( $svg );
}
// Stub, since we don't know if we even have a SVG handler, much less what exactly it'll output
public function rasterize( $svg ) {
return 'RASTERIZESTUB';
}
protected function getLangFallbacks( string $code ) : array {
return $this->mockFallbacks[$code] ?? [];
}
}