3use Wikimedia\TestingAccessWrapper;
10 use MediaWikiCoversValidator;
13 return strtr( $text, [
20 'ResourceLoaderSources' => [],
21 'ResourceModuleSkinStyles' => [],
22 'ResourceModules' => [],
23 'EnableJavaScriptTest' =>
false,
24 'ResourceLoaderDebug' =>
false,
25 'LoadScript' =>
'/w/load.php',
33 'target' =>
'phpunit',
45 'test.private' => [
'group' =>
'private' ],
46 'test.shouldembed.empty' => [
'shouldEmbed' =>
true,
'isKnownEmpty' =>
true ],
47 'test.shouldembed' => [
'shouldEmbed' =>
true ],
50 'test.styles.mixed' => [],
51 'test.styles.noscript' => [
53 'group' =>
'noscript',
55 'test.styles.user' => [
59 'test.styles.user.empty' => [
62 'isKnownEmpty' =>
true,
64 'test.styles.private' => [
67 'styles' =>
'.private{}',
69 'test.styles.shouldembed' => [
71 'shouldEmbed' =>
true,
72 'styles' =>
'.shouldembed{}',
76 'test.scripts.user' => [
'group' =>
'user' ],
77 'test.scripts.user.empty' => [
'group' =>
'user',
'isKnownEmpty' =>
true ],
78 'test.scripts.raw' => [
'isRaw' =>
true ],
79 'test.scripts.shouldembed' => [
'shouldEmbed' =>
true ],
81 'test.ordering.a' => [
'shouldEmbed' =>
false ],
82 'test.ordering.b' => [
'shouldEmbed' =>
false ],
83 'test.ordering.c' => [
'shouldEmbed' =>
true,
'styles' =>
'.orderingC{}' ],
84 'test.ordering.d' => [
'shouldEmbed' =>
true,
'styles' =>
'.orderingD{}' ],
85 'test.ordering.e' => [
'shouldEmbed' =>
false ],
87 return array_map(
function (
$options ) {
97 $this->assertInternalType(
'array', $client->getDocumentAttributes() );
110 $context->getResourceLoader()->register( self::makeSampleModules() );
113 $client->setModules( [
116 'test.shouldembed.empty',
120 $client->setModuleStyles( [
122 'test.styles.user.empty',
123 'test.styles.private',
125 'test.styles.shouldembed',
126 'test.unregistered.styles',
128 $client->setModuleScripts( [
131 'test.scripts.user.empty',
132 'test.scripts.shouldembed',
133 'test.unregistered.scripts',
138 'test.private' =>
'loading',
139 'test.shouldembed.empty' =>
'ready',
140 'test.shouldembed' =>
'loading',
141 'test.styles.pure' =>
'ready',
142 'test.styles.user.empty' =>
'ready',
143 'test.styles.private' =>
'ready',
144 'test.styles.shouldembed' =>
'ready',
145 'test.scripts' =>
'loading',
146 'test.scripts.user' =>
'loading',
147 'test.scripts.user.empty' =>
'ready',
148 'test.scripts.shouldembed' =>
'loading',
159 'test.scripts.shouldembed',
162 'styles' => [
'test.styles.private',
'test.styles.shouldembed' ],
170 $access = TestingAccessWrapper::newFromObject( $client );
171 $this->assertEquals( $expected, $access->getData() );
183 $context->getResourceLoader()->register( self::makeSampleModules() );
186 $client->setConfig( [
'key' =>
'value' ] );
187 $client->setModules( [
191 $client->setModuleStyles( [
193 'test.styles.private',
195 $client->setModuleScripts( [
198 $client->setExemptStates( [
199 'test.exempt' =>
'ready',
203 $expected =
'<script>document.documentElement.className = document.documentElement.className.replace( /(^|\s)client-nojs(\s|$)/, "$1client-js$2" );</script>' .
"\n"
204 .
'<script>(window.RLQ=window.RLQ||[]).push(function(){'
205 .
'mw.config.set({"key":"value"});'
206 .
'mw.loader.state({"test.exempt":"ready","test.private":"loading","test.styles.pure":"ready","test.styles.private":"ready","test.scripts":"loading"});'
207 .
'mw.loader.implement("test.private@{blankVer}",function($,jQuery,require,module){},{"css":[]});'
208 .
'mw.loader.load(["test"]);'
209 .
'mw.loader.load("/w/load.php?debug=false\u0026lang=nl\u0026modules=test.scripts\u0026only=scripts\u0026skin=fallback");'
210 .
'});</script>' .
"\n"
211 .
'<link rel="stylesheet" href="/w/load.php?debug=false&lang=nl&modules=test.styles.pure&only=styles&skin=fallback"/>' .
"\n"
212 .
'<style>.private{}</style>' .
"\n"
213 .
'<script async="" src="/w/load.php?debug=false&lang=nl&modules=startup&only=scripts&skin=fallback"></script>';
217 $this->assertEquals( $expected, $client->getHeadHtml() );
228 [
'target' =>
'example' ]
232 $expected =
'<script>document.documentElement.className = document.documentElement.className.replace( /(^|\s)client-nojs(\s|$)/, "$1client-js$2" );</script>' .
"\n"
233 .
'<script async="" src="/w/load.php?debug=false&lang=nl&modules=startup&only=scripts&skin=fallback&target=example"></script>';
236 $this->assertEquals( $expected, $client->getHeadHtml() );
251 $expected =
'<script>document.documentElement.className = document.documentElement.className.replace( /(^|\s)client-nojs(\s|$)/, "$1client-js$2" );</script>' .
"\n"
252 .
'<script async="" src="/w/load.php?debug=false&lang=nl&modules=startup&only=scripts&skin=fallback"></script>';
255 $this->assertEquals( $expected, $client->getHeadHtml() );
264 $context->getResourceLoader()->register( self::makeSampleModules() );
267 $client->setConfig( [
'key' =>
'value' ] );
268 $client->setModules( [
270 'test.private.bottom',
272 $client->setModuleScripts( [
279 $this->assertEquals( $expected, $client->getBodyHtml() );
287 'modules' => [
'test.unknown' ],
293 'modules' => [
'test.styles.private' ],
295 'output' =>
'<style>.private{}</style>',
299 'modules' => [
'test.private' ],
301 'output' =>
'<script>(window.RLQ=window.RLQ||[]).push(function(){mw.loader.implement("test.private@{blankVer}",function($,jQuery,require,module){},{"css":[]});});</script>',
306 'modules' => [
'test.scripts.raw' ],
308 'output' =>
'<script async="" src="/w/load.php?debug=false&lang=nl&modules=test.scripts.raw&only=scripts&skin=fallback"></script>',
311 'context' => [
'sync' =>
true ],
312 'modules' => [
'test.scripts.raw' ],
314 'output' =>
'<script src="/w/load.php?debug=false&lang=nl&modules=test.scripts.raw&only=scripts&skin=fallback&sync=1"></script>',
318 'modules' => [
'test.scripts.user' ],
320 'output' =>
'<script>(window.RLQ=window.RLQ||[]).push(function(){mw.loader.load("/w/load.php?debug=false\u0026lang=nl\u0026modules=test.scripts.user\u0026only=scripts\u0026skin=fallback\u0026user=Example\u0026version=0a56zyi");});</script>',
323 'context' => [
'debug' =>
true ],
324 'modules' => [
'test.styles.pure',
'test.styles.mixed' ],
326 'output' =>
'<link rel="stylesheet" href="/w/load.php?debug=true&lang=nl&modules=test.styles.mixed&only=styles&skin=fallback"/>' .
"\n"
327 .
'<link rel="stylesheet" href="/w/load.php?debug=true&lang=nl&modules=test.styles.pure&only=styles&skin=fallback"/>',
330 'context' => [
'debug' =>
false ],
331 'modules' => [
'test.styles.pure',
'test.styles.mixed' ],
333 'output' =>
'<link rel="stylesheet" href="/w/load.php?debug=false&lang=nl&modules=test.styles.mixed%2Cpure&only=styles&skin=fallback"/>',
337 'modules' => [
'test.styles.noscript' ],
339 'output' =>
'<noscript><link rel="stylesheet" href="/w/load.php?debug=false&lang=nl&modules=test.styles.noscript&only=styles&skin=fallback"/></noscript>',
343 'modules' => [
'test.shouldembed' ],
345 'output' =>
'<script>(window.RLQ=window.RLQ||[]).push(function(){mw.loader.implement("test.shouldembed@09p30q0",function($,jQuery,require,module){},{"css":[]});});</script>',
349 'modules' => [
'test.styles.shouldembed' ],
351 'output' =>
'<style>.shouldembed{}</style>',
355 'modules' => [
'test.scripts.shouldembed' ],
357 'output' =>
'<script>(window.RLQ=window.RLQ||[]).push(function(){mw.loader.state({"test.scripts.shouldembed":"ready"});});</script>',
361 'modules' => [
'test',
'test.shouldembed' ],
363 'output' =>
'<script>(window.RLQ=window.RLQ||[]).push(function(){mw.loader.load("/w/load.php?debug=false\u0026lang=nl\u0026modules=test\u0026skin=fallback");mw.loader.implement("test.shouldembed@09p30q0",function($,jQuery,require,module){},{"css":[]});});</script>',
367 'modules' => [
'test.styles.pure',
'test.styles.shouldembed' ],
370 '<link rel="stylesheet" href="/w/load.php?debug=false&lang=nl&modules=test.styles.pure&only=styles&skin=fallback"/>' .
"\n"
371 .
'<style>.shouldembed{}</style>'
375 'modules' => [
'test.ordering.a',
'test.ordering.e',
'test.ordering.b',
'test.ordering.d',
'test.ordering.c' ],
378 '<link rel="stylesheet" href="/w/load.php?debug=false&lang=nl&modules=test.ordering.a%2Cb&only=styles&skin=fallback"/>' .
"\n"
379 .
'<style>.orderingC{}.orderingD{}</style>' .
"\n"
380 .
'<link rel="stylesheet" href="/w/load.php?debug=false&lang=nl&modules=test.ordering.e&only=styles&skin=fallback"/>'
400 $context->getResourceLoader()->register( self::makeSampleModules() );
403 $this->assertEquals( $expected, (
string)$actual );
WebRequest clone which takes values from a provided array.
A Config instance which stores all settings as a member variable.
static makeModule(array $options=[])
testGetData()
ResourceLoaderClientHtml::__construct ResourceLoaderClientHtml::setModules ResourceLoaderClientHtml::...
testGetHeadHtml()
ResourceLoaderClientHtml::setConfig ResourceLoaderClientHtml::setExemptStates ResourceLoaderClientHtm...
static makeSampleModules()
testGetHeadHtmlWithNullTarget()
Confirm that a null 'target' is the same as no target.
testGetDocumentAttributes()
ResourceLoaderClientHtml::getDocumentAttributes.
testGetBodyHtml()
ResourceLoaderClientHtml::getBodyHtml ResourceLoaderClientHtml::getLoad.
testGetHeadHtmlWithTarget()
Confirm that 'target' is passed down to the startup module's load url.
testMakeLoad(array $extraQuery, array $modules, $type, $expected)
provideMakeLoad ResourceLoaderClientHtml::makeLoad ResourceLoaderClientHtml::makeContext ResourceLoad...
static makeContext( $extraQuery=[])
static expandVariables( $text)
Bootstrap a ResourceLoader client on an HTML page.
static makeLoad(ResourceLoaderContext $mainContext, array $modules, $only, array $extraQuery=[])
Explicily load or embed modules on a page.
Object passed around to modules which contains information about the state of a specific loader reque...
Dynamic JavaScript and CSS resource loading system.
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped & $options
do that in ParserLimitReportFormat instead use this to modify the parameters of the image all existing parser cache entries will be invalid To avoid you ll need to handle that somehow(e.g. with the RejectParserCacheValue hook) because MediaWiki won 't do it for you. & $defaults also a ContextSource after deleting those rows but within the same transaction you ll probably need to make sure the header is varied on and they can depend only on the ResourceLoaderContext $context
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return true
processing should stop and the error should be shown to the user * false