- Add new menu components: Menu, Link, ListItem, Footer - Add footer component which leverages menu components for generating template data. - Add footer to the component registry to be used in Skin class. - Update Skin methods to leverage new Menu and related components. - Move footer data generation methods from Skin and SkinTemplate into SkinComponentFooter class methods. - Remove Skin::getFooterLinks, Skin::getSiteFooterLinks - Deprecate Skin::footerLink. - Update RELEASE-NOTES with breaking changes, deprecations. - No visual regressions for the footer or menus. - SkinComponentRegistryContext::getLanguage now returns language object (interface is marked as @unstable so changes here acceptable) Bug: T302116 Depends-On: I97512d06df6f86236379a16fb0fbd6aa3f61deb5 Change-Id: I06054c2dead4773789b8c3d88a6b1ed8f78cd614
131 lines
3.8 KiB
PHP
131 lines
3.8 KiB
PHP
<?php
|
|
|
|
use MediaWiki\MainConfigNames;
|
|
use PHPUnit\Framework\MockObject\MockObject;
|
|
|
|
/**
|
|
* @covers SkinMustache
|
|
*
|
|
* @group Output
|
|
*/
|
|
class SkinMustacheTest extends MediaWikiIntegrationTestCase {
|
|
|
|
/**
|
|
* @param string $html
|
|
* @param Title $title
|
|
* @return MockObject|OutputPage
|
|
*/
|
|
private function getMockOutputPage( $html, $title ) {
|
|
$mockContentSecurityPolicy = $this->createMock( ContentSecurityPolicy::class );
|
|
|
|
$mockContentSecurityPolicy->method( 'getNonce' )
|
|
->willReturn( 'secret' );
|
|
|
|
$mock = $this->createMock( OutputPage::class );
|
|
$mock->method( 'getHTML' )
|
|
->willReturn( $html );
|
|
$mock->method( 'getCategoryLinks' )
|
|
->willReturn( [] );
|
|
$mock->method( 'getIndicators' )
|
|
->willReturn( [
|
|
'id' => '<a>indicator</a>'
|
|
] );
|
|
$mock->method( 'getTitle' )
|
|
->willReturn( $title );
|
|
$mock->method( 'getIndicators' )
|
|
->willReturn( '' );
|
|
$mock->method( 'getLanguageLinks' )
|
|
->willReturn( [] );
|
|
$mock->method( 'getCSP' )
|
|
->willReturn( $mockContentSecurityPolicy );
|
|
$mock->method( 'isTOCEnabled' )
|
|
->willReturn( true );
|
|
$mock->method( 'getSections' )
|
|
->willReturn( [] );
|
|
return $mock;
|
|
}
|
|
|
|
private function validateTemplateData( $data, $key ) {
|
|
$value = $data[$key];
|
|
if ( $value === null ) {
|
|
// Cannot validate a null value
|
|
return;
|
|
} elseif ( is_array( $value ) ) {
|
|
$this->assertTrue(
|
|
strpos( $key, 'data-' ) === 0 || strpos( $key, 'array-' ) === 0,
|
|
"Template data that is an object should be associated with a key" .
|
|
" prefixed with `data-` or `array-` ($key)"
|
|
);
|
|
|
|
// Validate the children
|
|
foreach ( $value as $childKey => $childValue ) {
|
|
if ( is_string( $childKey ) ) {
|
|
$this->validateTemplateData( $value, $childKey );
|
|
} else {
|
|
$this->assertStringStartsWith(
|
|
'array-',
|
|
$key,
|
|
"Template data that is a flat array should be associated with a key prefixed `array-` ($key)"
|
|
);
|
|
}
|
|
}
|
|
} elseif ( is_string( $value ) ) {
|
|
if ( strpos( $value, '<' ) !== false ) {
|
|
$this->assertTrue(
|
|
strpos( $key, 'html-' ) === 0 || $key === 'html',
|
|
"Template data containing HTML must be prefixed with `html-` ($key)"
|
|
);
|
|
}
|
|
} elseif ( is_bool( $value ) ) {
|
|
$this->assertTrue(
|
|
strpos( $key, 'is-' ) === 0 || strpos( $key, 'has-' ) === 0,
|
|
"Template data containing booleans must be prefixed with `is-` or `has-` ($key)"
|
|
);
|
|
} elseif ( is_numeric( $value ) ) {
|
|
$this->assertTrue(
|
|
strpos( $key, 'number-' ) === 0,
|
|
"Template data containing numbers must be prefixed with `number-` ($key)"
|
|
);
|
|
} else {
|
|
$this->fail(
|
|
"Keys must be primitives e.g. arrays OR strings OR bools OR null ($key)."
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @covers Skin::getTemplateData
|
|
* @covers MediaWiki\Skin\SkinComponentLogo::getTemplateData
|
|
* @covers MediaWiki\Skin\SkinComponentSearch::getTemplateData
|
|
* @covers MediaWiki\Skin\SkinComponentTableOfContents::getTemplateData
|
|
* @covers MediaWiki\Skin\SkinComponentFooter::getTemplateData
|
|
*/
|
|
public function testGetTemplateData() {
|
|
$config = $this->getServiceContainer()->getMainConfig();
|
|
$bodytext = '<p>hello</p>';
|
|
$context = new RequestContext();
|
|
$title = Title::makeTitle( NS_MAIN, 'Mustache skin' );
|
|
$context->setTitle( $title );
|
|
$out = $this->getMockOutputPage( $bodytext, $title );
|
|
$context->setOutput( $out );
|
|
$this->overrideConfigValue( MainConfigNames::Logos, [] );
|
|
$skin = new SkinMustache( [
|
|
'name' => 'test',
|
|
'templateDirectory' => __DIR__,
|
|
] );
|
|
$context->setConfig( $config );
|
|
$skin->setContext( $context );
|
|
$data = $skin->getTemplateData();
|
|
|
|
// Validate the default template data respects the naming rules
|
|
foreach ( array_keys( $data ) as $key ) {
|
|
$this->validateTemplateData( $data, $key );
|
|
}
|
|
|
|
// Validate search data
|
|
$searchData = $data['data-search-box'];
|
|
foreach ( array_keys( $searchData ) as $key ) {
|
|
$this->validateTemplateData( $searchData, $key );
|
|
}
|
|
}
|
|
}
|