Introduce PHPUnit tests in Vector
To make it happen, we also need to provide a way to inject different TemplateParser. Change-Id: I14d8474a2b52f040b688245cbd5bd6f12dddf846
This commit is contained in:
parent
2adc7af88c
commit
09671d768f
|
@ -71,6 +71,18 @@ class SkinVector extends SkinTemplate {
|
|||
return $modules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the VectorTemplate
|
||||
*
|
||||
* @param string $classname
|
||||
* @return VectorTemplate
|
||||
*/
|
||||
public function setupTemplate( $classname ) {
|
||||
$template = new VectorTemplate( $this->getConfig() );
|
||||
$template->setTemplateParser( new TemplateParser( __DIR__ . '/templates' ) );
|
||||
return $template;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the logo should be preloaded with an HTTP link header or not
|
||||
* @since 1.29
|
||||
|
|
|
@ -34,11 +34,24 @@ class VectorTemplate extends BaseTemplate {
|
|||
private $templateParser;
|
||||
|
||||
/**
|
||||
* @param Config|null $config
|
||||
* @param TemplateParser $parser
|
||||
*/
|
||||
public function __construct( Config $config = null ) {
|
||||
parent::__construct( $config );
|
||||
$this->templateParser = new TemplateParser( __DIR__ . '/templates' );
|
||||
public function setTemplateParser( TemplateParser $parser ) {
|
||||
$this->templateParser = $parser;
|
||||
}
|
||||
|
||||
/**
|
||||
* The template parser might be undefined. This function will check if it set first
|
||||
*
|
||||
* @return TemplateParser
|
||||
*/
|
||||
protected function getTemplateParser() {
|
||||
if ( $this->templateParser === null ) {
|
||||
throw new \LogicException(
|
||||
'TemplateParser has to be set first via setTemplateParser method'
|
||||
);
|
||||
}
|
||||
return $this->templateParser;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -121,12 +134,12 @@ class VectorTemplate extends BaseTemplate {
|
|||
'html-debuglog' => $this->get( 'debughtml', '' ),
|
||||
// From BaseTemplate::getTrail (handles bottom JavaScript)
|
||||
'html-printtail' => $this->getTrail() . '</body></html>',
|
||||
'html-footer' => $this->templateParser->processTemplate( 'Footer', [
|
||||
'html-footer' => $this->getTemplateParser()->processTemplate( 'Footer', [
|
||||
'html-userlangattributes' => $this->get( 'userlangattributes', '' ),
|
||||
'html-hook-vector-before-footer' => $htmlHookVectorBeforeFooter,
|
||||
'array-footer-rows' => $this->getTemplateFooterRows(),
|
||||
] ),
|
||||
'html-navigation' => $this->templateParser->processTemplate( 'Navigation', [
|
||||
'html-navigation' => $this->getTemplateParser()->processTemplate( 'Navigation', [
|
||||
'html-navigation-heading' => $this->getMsg( 'navigation-heading' ),
|
||||
'html-personal-menu' => $this->renderNavigation( [ 'PERSONAL' ] ),
|
||||
'html-navigation-left-tabs' => $this->renderNavigation( [ 'NAMESPACES', 'VARIANTS' ] ),
|
||||
|
@ -142,7 +155,7 @@ class VectorTemplate extends BaseTemplate {
|
|||
];
|
||||
|
||||
// Prepare and output the HTML response
|
||||
echo $this->templateParser->processTemplate( 'index', $params );
|
||||
echo $this->getTemplateParser()->processTemplate( 'index', $params );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -285,7 +298,7 @@ class VectorTemplate extends BaseTemplate {
|
|||
$props['html-portal-content'] = $content;
|
||||
}
|
||||
|
||||
return $this->templateParser->processTemplate( 'Portal', $props );
|
||||
return $this->getTemplateParser()->processTemplate( 'Portal', $props );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -368,7 +381,7 @@ class VectorTemplate extends BaseTemplate {
|
|||
$props[ 'html-items' ] .= $this->makeListItem( $key, $item );
|
||||
}
|
||||
|
||||
return $this->templateParser->processTemplate( 'VectorTabs', $props );
|
||||
return $this->getTemplateParser()->processTemplate( 'VectorTabs', $props );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -395,7 +408,7 @@ class VectorTemplate extends BaseTemplate {
|
|||
$props['html-items'] .= $this->makeListItem( $key, $item );
|
||||
}
|
||||
|
||||
return $this->templateParser->processTemplate( 'VectorMenu', $props );
|
||||
return $this->getTemplateParser()->processTemplate( 'VectorMenu', $props );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -417,7 +430,7 @@ class VectorTemplate extends BaseTemplate {
|
|||
] );
|
||||
}
|
||||
|
||||
return $this->templateParser->processTemplate( 'VectorTabs', $props );
|
||||
return $this->getTemplateParser()->processTemplate( 'VectorTabs', $props );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -437,7 +450,7 @@ class VectorTemplate extends BaseTemplate {
|
|||
$props['html-items'] .= $this->makeListItem( $key, $item );
|
||||
}
|
||||
|
||||
return $this->templateParser->processTemplate( 'VectorMenu', $props );
|
||||
return $this->getTemplateParser()->processTemplate( 'VectorMenu', $props );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -472,7 +485,7 @@ class VectorTemplate extends BaseTemplate {
|
|||
$props['html-personal-tools'] .= $this->makeListItem( $key, $item );
|
||||
}
|
||||
|
||||
return $this->templateParser->processTemplate( 'PersonalMenu', $props );
|
||||
return $this->getTemplateParser()->processTemplate( 'PersonalMenu', $props );
|
||||
}
|
||||
|
||||
private function renderSearchComponent() {
|
||||
|
@ -492,6 +505,6 @@ class VectorTemplate extends BaseTemplate {
|
|||
),
|
||||
'searchInputLabel' => $this->getMsg( 'search' )
|
||||
];
|
||||
return $this->templateParser->processTemplate( 'SearchBox', $props );
|
||||
return $this->getTemplateParser()->processTemplate( 'SearchBox', $props );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
<?php
|
||||
namespace MediaWiki\Skins\Vector\Tests\Integration;
|
||||
|
||||
use Wikimedia\TestingAccessWrapper;
|
||||
|
||||
/**
|
||||
* Class VectorTemplateTest
|
||||
* @package MediaWiki\Skins\Vector\Tests\Unit
|
||||
* @group Vector
|
||||
* @group Skins
|
||||
*
|
||||
* @coversDefaultClass \VectorTemplate
|
||||
*/
|
||||
class VectorTemplateTest extends \MediaWikiTestCase {
|
||||
|
||||
/**
|
||||
* @return \VectorTemplate
|
||||
*/
|
||||
private function provideVectorTemplateObject() {
|
||||
$template = new \VectorTemplate( \GlobalVarConfig::newInstance() );
|
||||
$template->setTemplateParser( new \TemplateParser() );
|
||||
return $template;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $nodeString an HTML of the node we want to verify
|
||||
* @param string $tag Tag of the element we want to check
|
||||
* @param string $attribute Attribute of the element we want to check
|
||||
* @param string $search Value of the attribute we want to verify
|
||||
* @return bool
|
||||
*/
|
||||
private function expectNodeAttribute( $nodeString, $tag, $attribute, $search ) {
|
||||
$node = new \DOMDocument();
|
||||
$node->loadHTML( $nodeString );
|
||||
$element = $node->getElementsByTagName( $tag )->item( 0 );
|
||||
if ( !$element ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$values = explode( ' ', $element->getAttribute( $attribute ) );
|
||||
return in_array( $search, $values );
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::makeListItem
|
||||
*/
|
||||
public function testMakeListItemRespectsCollapsibleOption() {
|
||||
$template = $this->provideVectorTemplateObject();
|
||||
$listItemClass = 'my_test_class';
|
||||
$options = [ 'vector-collapsible' => true ];
|
||||
$item = [ 'class' => $listItemClass ];
|
||||
$nonCollapsible = $template->makeListItem( 'key', $item, [] );
|
||||
$collapsible = $template->makeListItem( 'key', [], $options );
|
||||
|
||||
$this->assertTrue(
|
||||
$this->expectNodeAttribute( $collapsible, 'li', 'class', 'collapsible' ),
|
||||
'The collapsible element has to have `collapsible` class'
|
||||
);
|
||||
$this->assertFalse(
|
||||
$this->expectNodeAttribute( $nonCollapsible, 'li', 'class', 'collapsible' ),
|
||||
'The non-collapsible element should not have `collapsible` class'
|
||||
);
|
||||
$this->assertTrue(
|
||||
$this->expectNodeAttribute( $nonCollapsible, 'li', 'class', $listItemClass ),
|
||||
'The non-collapsible element should preserve item class'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::makeListItem
|
||||
*/
|
||||
public function testWatcAndUnwatchHasIconClass() {
|
||||
$template = $this->provideVectorTemplateObject();
|
||||
$this->setMwGlobals( [
|
||||
'wgVectorUseIconWatch' => true
|
||||
] );
|
||||
$listItemClass = 'my_test_class';
|
||||
$options = [];
|
||||
$item = [ 'class' => $listItemClass ];
|
||||
|
||||
$watchListItem = $template->makeListItem( 'watch', $item, [] );
|
||||
$unwatchListItem = $template->makeListItem( 'unwatch', [], $options );
|
||||
$regularListItem = $template->makeListItem( 'whatever', $item, $options );
|
||||
|
||||
$this->assertTrue(
|
||||
$this->expectNodeAttribute( $watchListItem, 'li', 'class', 'icon' ),
|
||||
'Watch list items require an "icon" class'
|
||||
);
|
||||
$this->assertTrue(
|
||||
$this->expectNodeAttribute( $unwatchListItem, 'li', 'class', 'icon' ),
|
||||
'Unwatch list items require an "icon" class'
|
||||
);
|
||||
$this->assertFalse(
|
||||
$this->expectNodeAttribute( $regularListItem, 'li', 'class', 'icon' ),
|
||||
'List item other than watch or unwatch should not have an "icon" class'
|
||||
);
|
||||
$this->assertTrue(
|
||||
$this->expectNodeAttribute( $watchListItem, 'li', 'class', $listItemClass ),
|
||||
'Watch list items require an item class'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::makeListItem
|
||||
*/
|
||||
public function testWatchAndUnwatchHasIconClassOnlyIfVectorUseIconWatchIsSet() {
|
||||
$template = $this->provideVectorTemplateObject();
|
||||
$this->setMwGlobals( [
|
||||
'wgVectorUseIconWatch' => false
|
||||
] );
|
||||
$listItemClass = 'my_test_class';
|
||||
$item = [ 'class' => $listItemClass ];
|
||||
|
||||
$watchListItem = $template->makeListItem( 'watch', $item, [] );
|
||||
|
||||
$this->assertFalse(
|
||||
$this->expectNodeAttribute( $watchListItem, 'li', 'class', 'icon' ),
|
||||
'Watch list should not have an "icon" class when VectorUserIconWatch is disabled'
|
||||
);
|
||||
$this->assertTrue(
|
||||
$this->expectNodeAttribute( $watchListItem, 'li', 'class', $listItemClass ),
|
||||
'Watch list items require an item class'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::renderViewsComponent
|
||||
*/
|
||||
public function testRenderViewsComponent() {
|
||||
$langAttrs = 'LANG_ATTRIBUTES';
|
||||
$templateParserMock = $this->createMock( \TemplateParser::class );
|
||||
$templateParserMock->expects( $this->once() )
|
||||
->method( 'processTemplate' )
|
||||
->with( 'VectorTabs', $this->callback( function ( $data ) use ( $langAttrs ){
|
||||
if ( !array_key_exists( 'empty-portlet', $data ) ) {
|
||||
return false;
|
||||
}
|
||||
return $data['empty-portlet'] == 'emptyPortlet' &&
|
||||
$data['html-userlangattributes'] == $langAttrs;
|
||||
} ) );
|
||||
|
||||
$vectorTemplate = new \VectorTemplate( \GlobalVarConfig::newInstance() );
|
||||
$vectorTemplate->setTemplateParser( $templateParserMock );
|
||||
$vectorTemplate->set( 'view_urls', [] );
|
||||
$vectorTemplate->set( 'skin', new \SkinVector() );
|
||||
$vectorTemplate->set( 'userlangattributes', $langAttrs );
|
||||
$openVectorTemplate = TestingAccessWrapper::newFromObject( $vectorTemplate );
|
||||
|
||||
$openVectorTemplate->renderViewsComponent();
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue