Localisation updates from https://translatewiki.net.
[mediawiki.git] / tests / phpunit / structure / PerformanceBudgetTest.php
blobdfd49eb363f700324a955da7fff35974895ba58a
1 <?php
3 use MediaWiki\Context\DerivativeContext;
4 use MediaWiki\Context\RequestContext;
5 use MediaWiki\Output\OutputPage;
6 use MediaWiki\Request\FauxRequest;
7 use MediaWiki\ResourceLoader\Context;
8 use MediaWiki\ResourceLoader\Module;
9 use MediaWiki\User\User;
11 /**
12 * @group Database
13 * @coversNothing
15 class PerformanceBudgetTest extends MediaWikiIntegrationTestCase {
16 /**
17 * Calculates the size of a module
19 * @param array $moduleNames
20 * @param string $skinName
21 * @param bool $isScripts
23 * @return float|int
24 * @throws \Wikimedia\RequestTimeout\TimeoutException
25 * @throws MediaWiki\Config\ConfigException
27 protected function getContentTransferSize( $moduleNames, $skinName, $isScripts = false ) {
28 // Calculate Size
29 $resourceLoader = $this->getServiceContainer()->getResourceLoader();
30 $request = new FauxRequest(
32 'lang' => 'en',
33 'modules' => implode( '|', $moduleNames ),
34 'skin' => $skinName,
37 $modules = [];
38 foreach ( $moduleNames as $moduleName ) {
39 $modules[ $moduleName ] = $resourceLoader->getModule( $moduleName );
42 $context = new Context( $resourceLoader, $request );
43 $contentContext = new \MediaWiki\ResourceLoader\DerivativeContext( $context );
44 $contentContext->setOnly(
45 $isScripts
46 ? Module::TYPE_COMBINED
47 : Module::TYPE_STYLES
49 // Create a module response for the given module and calculate the size
50 $content = $resourceLoader->makeModuleResponse( $contentContext, $modules );
51 $contentTransferSize = strlen( gzencode( $content, 9 ) );
52 return $contentTransferSize;
55 /**
56 * Prepares a skin for testing, assigning context and output page
58 * @param string $skinName
60 * @return \Skin
61 * @throws \SkinException
63 protected function prepareSkin( string $skinName ): \Skin {
64 $skinFactory = $this->getServiceContainer()->getSkinFactory();
65 $skin = $skinFactory->makeSkin( $skinName );
66 $title = $this->getExistingTestPage()->getTitle();
67 $context = new DerivativeContext( RequestContext::getMain() );
68 $anon = new User();
69 $context->setUser( $anon );
70 $context->setTitle( $title );
71 $context->setSkin( $skin );
72 $outputPage = new OutputPage( $context );
73 $context->setOutput( $outputPage );
74 $skin->setContext( $context );
75 $outputPage->setTitle( $title );
76 $outputPage->output( true );
77 return $skin;
80 /**
81 * Converts a string to bytes
83 * @param string|int|float $size
85 * @return float|int
87 private function getSizeInBytes( $size ) {
88 if ( is_string( $size ) ) {
89 if ( strpos( $size, 'KB' ) !== false || strpos( $size, 'kB' ) !== false ) {
90 $size = (float)str_replace( [ 'KB', 'kB', ' KB', ' kB' ], '', $size );
91 $size = $size * 1024;
92 } elseif ( strpos( $size, 'B' ) !== false ) {
93 $size = (float)str_replace( [ ' B', 'B' ], '', $size );
96 return $size;
99 /**
100 * @param string $skinName
101 * @param array $moduleNames
102 * @param bool $isScripts
104 private function testModuleSizes( $skinName, $moduleNames, $isScripts = false ) {
105 $size = $this->getContentTransferSize( $moduleNames, $skinName, $isScripts );
107 $moduleType = $isScripts ? 'scripts' : 'styles';
108 $sizeKb = ceil( ( $size * 10 ) / 1024 ) / 10;
109 $warning = "Total size of $moduleType modules is " . $sizeKb . "kB.\n" .
110 "If you are adding code on page load, please reduce $moduleType that you are loading on page load.\n" .
111 "Read https://www.mediawiki.org/wiki/Performance_budgeting for more context on this number.\n\n";
112 print( $warning );
113 $this->markTestSkipped( 'Tests are non-blocking for now.' );
117 * Tests the size of modules in allowed skins
119 * @coversNothing
121 * @return void
122 * @throws \Wikimedia\RequestTimeout\TimeoutException
123 * @throws MediaWiki\Config\ConfigException
125 public function testTotalModulesSize() {
126 $skinName = 'vector-2022';
127 $skin = $this->prepareSkin( $skinName );
128 $moduleStyles = $skin->getOutput()->getModuleStyles();
129 $moduleScripts = $skin->getOutput()->getModules();
130 $this->testModuleSizes( $skinName, $moduleStyles );
131 $this->testModuleSizes( $skinName, $moduleScripts, true );