+
+ {{{html-title-heading}}}
+ {{>Indicators}}
+
+
{{{html-tagline}}}
+
+
\ No newline at end of file
diff --git a/templates/PageSidebar.mustache b/templates/PageSidebar.mustache
new file mode 100644
index 000000000..974c5c77a
--- /dev/null
+++ b/templates/PageSidebar.mustache
@@ -0,0 +1,9 @@
+{{!
+
+}}
+
\ No newline at end of file
diff --git a/templates/Drawer__siteStats.mustache b/templates/SiteStats.mustache
similarity index 78%
rename from templates/Drawer__siteStats.mustache
rename to templates/SiteStats.mustache
index 4886161da..a5dc268a1 100644
--- a/templates/Drawer__siteStats.mustache
+++ b/templates/SiteStats.mustache
@@ -1,8 +1,8 @@
-
{{{html-site-notice}}}
+
+
{{{html-site-notice}}}
+
- {{>ContentHeader}}
+ {{>PageHeader}}
{{{html-subtitle}}}
{{#html-undelete-link}}
{{{.}}}
{{/html-undelete-link}}
{{{html-user-message}}}
{{{html-body-content--formatted}}}
- {{#toc-enabled}}{{>ContentSidebar}}{{/toc-enabled}}
- {{>ContentFooter}}
+ {{#toc-enabled}}{{>PageSidebar}}{{/toc-enabled}}
+ {{>PageFooter}}
{{{html-after-content}}}
diff --git a/tests/phpunit/Partials/DrawerTest.php b/tests/phpunit/Partials/DrawerTest.php
deleted file mode 100644
index 1d637aeee..000000000
--- a/tests/phpunit/Partials/DrawerTest.php
+++ /dev/null
@@ -1,85 +0,0 @@
-assertEmpty( $partial->decorateMainMenuData( [
- 'array-portlets-rest' => [],
- ] )['array-portlets-rest'] );
- }
-
- /**
- * @covers \MediaWiki\Skins\Citizen\Partials\Drawer::decorateMainMenuData
- * @return void
- */
- public function testDecorateMainMenuRemovePageTools() {
- $partial = new Drawer( new SkinCitizen() );
-
- $mainMenuData = [
- 'array-portlets-rest' => [
- [ 'id' => 'foo' ],
- [ 'id' => 'p-tb' ],
- ],
- ];
-
- $this->assertNotEmpty( $partial->decorateMainMenuData( $mainMenuData ) );
- $this->assertArrayHasKey( 'array-portlets-rest', $partial->decorateMainMenuData( $mainMenuData ) );
- $this->assertNotContains( [ 'id' => 'pt-tb' ], $partial->decorateMainMenuData( $mainMenuData )['array-portlets-rest'] );
- }
-
- /**
- * @covers \MediaWiki\Skins\Citizen\Partials\Drawer::getSiteStatsData
- * @return void
- */
- public function testGetSiteStatsDataDisabled() {
- $this->overrideConfigValues( [
- 'CitizenEnableDrawerSiteStats' => false,
- ] );
-
- $partial = new Drawer( new SkinCitizen() );
- $this->assertEmpty( $partial->getSiteStatsData() );
- }
-
- /**
- * @covers \MediaWiki\Skins\Citizen\Partials\Drawer::getSiteStatsData
- * @covers \MediaWiki\Skins\Citizen\Partials\Drawer::getSiteStatValue
- * @return void
- */
- public function testGetSiteStatsDataNoFormat() {
- $this->overrideConfigValues( [
- 'CitizenEnableDrawerSiteStats' => true,
- 'CitizenUseNumberFormatter' => false,
- ] );
-
- $partial = new Drawer( new SkinCitizen() );
- $data = $partial->getSiteStatsData();
-
- $this->assertArrayHasKey( 'array-drawer-sitestats-item', $data );
- $this->assertCount( 4, $data['array-drawer-sitestats-item'] );
-
- foreach ( $data['array-drawer-sitestats-item'] as $stat ) {
- $this->assertArrayHasKey( 'id', $stat );
- $this->assertArrayHasKey( 'icon', $stat );
- $this->assertArrayHasKey( 'value', $stat );
- $this->assertArrayHasKey( 'label', $stat );
-
- $this->assertContains( $stat['id'], [ 'articles', 'images', 'users', 'edits' ] );
- }
- }
-}
diff --git a/tests/phpunit/Partials/FooterTest.php b/tests/phpunit/Partials/FooterTest.php
deleted file mode 100644
index 055a13188..000000000
--- a/tests/phpunit/Partials/FooterTest.php
+++ /dev/null
@@ -1,43 +0,0 @@
- [
- 'array-items' => [
- [ 'name' => 'copyright' ]
- ]
- ]
- ];
-
- $out = $partial->decorateFooterData( $data );
-
- $this->assertArraySubmapSame( [
- 'data-info' => [
- 'array-items' => [
- [
- 'name' => 'copyright',
- 'label' => wfMessage( 'citizen-page-info-copyright' )->text()
- ]
- ],
- ]
- ], $out );
- }
-}
diff --git a/tests/phpunit/Partials/HeaderTest.php b/tests/phpunit/Partials/HeaderTest.php
deleted file mode 100644
index 913bd6873..000000000
--- a/tests/phpunit/Partials/HeaderTest.php
+++ /dev/null
@@ -1,39 +0,0 @@
-decorateSearchBoxData( [] );
-
- $this->assertArrayHasKey( 'msg-citizen-search-toggle-shortcut', $out );
- $this->assertEquals( '[/]', $out['msg-citizen-search-toggle-shortcut'] );
- }
-
- /**
- * @covers \MediaWiki\Skins\Citizen\Partials\Header::getUserInfoData
- * @covers \MediaWiki\Skins\Citizen\Partials\Header::getUserPageHTML
- * @covers \MediaWiki\Skins\Citizen\Partials\Header::getUserGroupsHTML
- * @covers \MediaWiki\Skins\Citizen\Partials\Header::getUserContributionsHTML
- * @return void
- */
- public function testGetUserInfoData() {
- $partial = new Header( new SkinCitizen() );
- $out = $partial->getUserInfoData( [] );
-
- $this->assertArrayHasKey( 'id', $out );
- }
-}
diff --git a/tests/phpunit/Partials/PageTitleTest.php b/tests/phpunit/Partials/PageTitleTest.php
deleted file mode 100644
index e4d24a2b5..000000000
--- a/tests/phpunit/Partials/PageTitleTest.php
+++ /dev/null
@@ -1,57 +0,0 @@
-setTitle( $title );
- $partial = new PageTitle( new SkinCitizen() );
-
- $data = sprintf(
- '
%s
',
- 'Foo Title (paren)'
- );
- $text = $partial->decorateTitle( $data );
-
- $this->assertStringNotContainsString( 'mw-page-title-parenthesis', $text );
- }
-
- /**
- * @covers \MediaWiki\Skins\Citizen\Partials\PageTitle
- * @return void
- * @throws MWException
- */
- public function testDecorateTitle() {
- $title = Title::makeTitle( NS_MAIN, 'Foo' );
- RequestContext::resetMain();
- RequestContext::getMain()->setTitle( $title );
- $partial = new PageTitle( new SkinCitizen() );
-
- $data = sprintf(
- '
%s
',
- 'Foo Title (paren)'
- );
- $text = $partial->decorateTitle( $data );
-
- $this->assertStringContainsString( 'mw-page-title-parenthesis', $text );
- }
-}
diff --git a/tests/phpunit/Partials/TaglineTest.php b/tests/phpunit/Partials/TaglineTest.php
deleted file mode 100644
index f135ebb23..000000000
--- a/tests/phpunit/Partials/TaglineTest.php
+++ /dev/null
@@ -1,70 +0,0 @@
-assertEmpty( $partial->getTagline() );
- }
-
- /**
- * @covers \MediaWiki\Skins\Citizen\Partials\Tagline
- * @return void
- */
- public function testGetTagLineShortDesc() {
- $title = Title::makeTitle( NS_MAIN, 'Foo' );
-
- RequestContext::resetMain();
-
- $out = new OutputPage( RequestContext::getMain() );
- $out->setProperty( 'shortdesc', '
' );
-
- RequestContext::getMain()->setOutput( $out );
- RequestContext::getMain()->setTitle( $title );
-
- $partial = new Tagline( new SkinCitizen() );
-
- $this->assertEquals( '', $partial->getTagline() );
- }
-
- /**
- * @covers \MediaWiki\Skins\Citizen\Partials\Tagline
- * @return void
- */
- public function testGetTagLineNoNSText() {
- $title = $this->getMockBuilder( Title::class )->disableOriginalConstructor()->getMock();
- $title->expects( $this->once() )->method( 'getNsText' )->willReturn( false );
-
- RequestContext::resetMain();
-
- $out = new OutputPage( RequestContext::getMain() );
- $out->setProperty( 'shortdesc', null );
-
- RequestContext::getMain()->setOutput( $out );
- RequestContext::getMain()->setTitle( $title );
-
- $partial = new Tagline( new SkinCitizen() );
-
- $this->assertEquals(
- wfMessage( 'tagline' )->text(),
- $partial->getTagline()
- );
- }
-}
diff --git a/tests/phpunit/Unit/Components/CitizenComponentLinkTest.php b/tests/phpunit/Unit/Components/CitizenComponentLinkTest.php
new file mode 100644
index 000000000..8f10c7126
--- /dev/null
+++ b/tests/phpunit/Unit/Components/CitizenComponentLinkTest.php
@@ -0,0 +1,59 @@
+createMock( MessageLocalizer::class );
+ // Adjusting mock to prevent calling the service container.
+ $localizer->method( 'msg' )
+ ->willReturnCallback( function ( $key ) use ( $accessKeyHint ) {
+ // Directly create Message object without accessing real message texts
+ // to avoid 'Premature access to service container' error.
+ return $this->createConfiguredMock( Message::class, [
+ 'exists' => true,
+ 'text' => $key === $accessKeyHint . '-label' ? 'Mock aria label' : $key,
+ '__toString' => 'Mock aria label',
+ ] );
+ } );
+
+ // Create the component
+ $linkComponent = new CitizenComponentLink( $href, $text, $icon, $localizer, $accessKeyHint );
+ $actual = $linkComponent->getTemplateData();
+
+ // Assert the expected values
+ $this->assertEquals( $icon, $actual['icon'] );
+ $this->assertEquals( $text, $actual['text'] );
+ $this->assertEquals( $href, $actual['href'] );
+
+ // New assertions for HTML attributes
+ $expectedTitle = "tooltip-sample-accesskeyword-separatorbrackets";
+ $expectedAriaLabel = "Mock aria label";
+ $attributesString = $actual['html-attributes'];
+
+ // Assert that the expected attributes are present in the string
+ $this->assertStringContainsString( 'title="' . $expectedTitle . '"', $attributesString );
+ $this->assertStringContainsString( 'aria-label="' . $expectedAriaLabel . '"', $attributesString );
+ }
+}
diff --git a/tests/phpunit/Unit/Components/CitizenComponentMainMenuTest.php b/tests/phpunit/Unit/Components/CitizenComponentMainMenuTest.php
new file mode 100644
index 000000000..3bc56cbec
--- /dev/null
+++ b/tests/phpunit/Unit/Components/CitizenComponentMainMenuTest.php
@@ -0,0 +1,66 @@
+assertInstanceOf( CitizenComponent::class, $mainMenu );
+ }
+
+ /**
+ * @return array[]
+ */
+ public function provideMainMenuData(): array {
+ return [
+ [
+ 'sidebarData' => [
+ 'data-portlets-first' => [],
+ 'array-portlets-rest' => [],
+ ]
+ ]
+ ];
+ }
+
+ /**
+ * @covers ::getTemplateData
+ * @dataProvider provideMainMenuData
+ */
+ public function testGetTemplateData( array $sidebarData ) {
+ // Create a new CitizenComponentMainMenu object
+ $mainMenu = new CitizenComponentMainMenu( $sidebarData );
+
+ // Call the getTemplateData method
+ $templateData = $mainMenu->getTemplateData();
+
+ // Assert the structure and types of expected keys
+ $this->assertIsArray( $templateData['data-portlets-first'] );
+ $this->assertIsArray( $templateData['array-portlets-rest'] );
+
+ // Assert the structure and types of expected keys
+ $this->assertArrayHasKey( 'data-portlets-first', $templateData );
+ $this->assertArrayHasKey( 'array-portlets-rest', $templateData );
+ }
+}
diff --git a/tests/phpunit/Unit/Components/CitizenComponentMenuListItemTest.php b/tests/phpunit/Unit/Components/CitizenComponentMenuListItemTest.php
new file mode 100644
index 000000000..b69cdb641
--- /dev/null
+++ b/tests/phpunit/Unit/Components/CitizenComponentMenuListItemTest.php
@@ -0,0 +1,38 @@
+link = $link;
+ $this->class = $class;
+ $this->id = $id;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getTemplateData(): array {
+ return $this->link->getTemplateData() + [
+ 'item-class' => $this->class,
+ 'item-id' => $this->id,
+ ];
+ }
+}
diff --git a/tests/phpunit/Unit/Components/CitizenComponentMenuTest.php b/tests/phpunit/Unit/Components/CitizenComponentMenuTest.php
new file mode 100644
index 000000000..29c075150
--- /dev/null
+++ b/tests/phpunit/Unit/Components/CitizenComponentMenuTest.php
@@ -0,0 +1,98 @@
+ 'some-class',
+ 'label' => 'Some label',
+ 'html-tooltip' => 'Some tooltip',
+ 'label-class' => 'some-label-class',
+ 'html-before-portal' => 'Some before portal',
+ 'html-items' => 'Some items',
+ 'html-after-portal' => 'Some after portal',
+ 'array-list-items' => [ 'some-item-one', 'some-item-2', 'some-item-3' ]
+ ]
+ ]
+ ];
+ }
+
+ /**
+ * @return array[]
+ */
+ public function provideCountData(): array {
+ return [
+ [
+ [
+ 'array-list-items' => [ 'some-item-one', 'some-item-2', 'some-item-3' ]
+ ],
+ 3
+ ],
+ [
+ [
+ 'html-items' => 'Some itemSome itemSome item'
+ ],
+ 3
+ ]
+ ];
+ }
+
+ /**
+ * This test checks if the CitizenComponentMenu class can be instantiated
+ * @covers ::__construct
+ */
+ public function testConstruct() {
+ // Create a new CitizenComponentMenu object
+ $menu = new CitizenComponentMenu( [] );
+
+ // Check if the object is an instance of CitizenComponent
+ $this->assertInstanceOf( CitizenComponent::class, $menu );
+ }
+
+ /**
+ * This test checks if the count method returns the correct number of items
+ * @covers ::count
+ * @dataProvider provideCountData
+ */
+ public function testCount( array $data, int $expected ) {
+ // Create a new CitizenComponentMenu object
+ $menu = new CitizenComponentMenu( $data );
+
+ // Check if the count method returns the correct number of items
+ $this->assertSame( $expected, $menu->count() );
+ }
+
+ /**
+ * This test checks if the getTemplateData method returns the correct data
+ * @covers ::getTemplateData
+ * @dataProvider provideMenuData
+ */
+ public function testGetTemplateData( array $data ) {
+ // Create a new CitizenComponentMenu object
+ $menu = new CitizenComponentMenu( $data );
+
+ // Call the getTemplateData method
+ $actualData = $menu->getTemplateData();
+
+ // Check if the getTemplateData method returns the correct data
+ $this->assertSame( $data, $actualData );
+ }
+}
diff --git a/tests/phpunit/Hooks/ResourceLoaderHooksTest.php b/tests/phpunit/integration/Hooks/ResourceLoaderHooksTest.php
similarity index 95%
rename from tests/phpunit/Hooks/ResourceLoaderHooksTest.php
rename to tests/phpunit/integration/Hooks/ResourceLoaderHooksTest.php
index c281fd41f..f0e10dbfc 100644
--- a/tests/phpunit/Hooks/ResourceLoaderHooksTest.php
+++ b/tests/phpunit/integration/Hooks/ResourceLoaderHooksTest.php
@@ -2,15 +2,16 @@
declare( strict_types=1 );
-namespace MediaWiki\Skins\Citizen\Tests\Hooks;
+namespace MediaWiki\Skins\Citizen\Tests\Integration\Hooks;
use MediaWiki\ResourceLoader\Context;
use MediaWiki\Skins\Citizen\Hooks\ResourceLoaderHooks;
+use MediaWikiIntegrationTestCase;
/**
* @group Citizen
*/
-class ResourceLoaderHooksTest extends \MediaWikiIntegrationTestCase {
+class ResourceLoaderHooksTest extends MediaWikiIntegrationTestCase {
/**
* @covers \MediaWiki\Skins\Citizen\Hooks\ResourceLoaderHooks
* @return void
diff --git a/tests/phpunit/Hooks/SkinHooksTest.php b/tests/phpunit/integration/Hooks/SkinHooksTest.php
similarity index 98%
rename from tests/phpunit/Hooks/SkinHooksTest.php
rename to tests/phpunit/integration/Hooks/SkinHooksTest.php
index 58169f26c..740255c29 100644
--- a/tests/phpunit/Hooks/SkinHooksTest.php
+++ b/tests/phpunit/integration/Hooks/SkinHooksTest.php
@@ -2,12 +2,13 @@
declare( strict_types=1 );
-namespace MediaWiki\Skins\Citizen\Tests\Hooks;
+namespace MediaWiki\Skins\Citizen\Tests\Integration\Hooks;
use MediaWiki\Request\ContentSecurityPolicy;
use MediaWiki\Skins\Citizen\Hooks\SkinHooks;
use MediaWiki\Skins\Citizen\SkinCitizen;
use MediaWiki\Title\Title;
+use MediaWikiIntegrationTestCase;
use OutputPage;
use RequestContext;
use ResourceLoaderContext;
@@ -16,7 +17,7 @@
/**
* @group Citizen
*/
-class SkinHooksTest extends \MediaWikiIntegrationTestCase {
+class SkinHooksTest extends MediaWikiIntegrationTestCase {
/**
* @covers \MediaWiki\Skins\Citizen\Hooks\SkinHooks
* @return void
diff --git a/tests/phpunit/Partials/BodyContentTest.php b/tests/phpunit/integration/Partials/BodyContentTest.php
similarity index 97%
rename from tests/phpunit/Partials/BodyContentTest.php
rename to tests/phpunit/integration/Partials/BodyContentTest.php
index aa0aafaa5..35d8b9d12 100644
--- a/tests/phpunit/Partials/BodyContentTest.php
+++ b/tests/phpunit/integration/Partials/BodyContentTest.php
@@ -2,7 +2,7 @@
declare( strict_types=1 );
-namespace MediaWiki\Skins\Citizen\Tests\Partials;
+namespace MediaWiki\Skins\Citizen\Tests\Integration\Partials;
use MediaWiki\Skins\Citizen\Partials\BodyContent;
use MediaWiki\Skins\Citizen\SkinCitizen;
diff --git a/tests/phpunit/Partials/PageToolsTest.php b/tests/phpunit/integration/Partials/PageToolsTest.php
similarity index 98%
rename from tests/phpunit/Partials/PageToolsTest.php
rename to tests/phpunit/integration/Partials/PageToolsTest.php
index e31b124cf..4300285fe 100644
--- a/tests/phpunit/Partials/PageToolsTest.php
+++ b/tests/phpunit/integration/Partials/PageToolsTest.php
@@ -2,7 +2,7 @@
declare( strict_types=1 );
-namespace MediaWiki\Skins\Citizen\Tests\Partials;
+namespace MediaWiki\Skins\Citizen\Tests\Integration\Partials;
use MediaWiki\Skins\Citizen\Partials\PageTools;
use MediaWiki\Skins\Citizen\SkinCitizen;
diff --git a/tests/phpunit/SkinCitizenTest.php b/tests/phpunit/integration/SkinCitizenTest.php
similarity index 98%
rename from tests/phpunit/SkinCitizenTest.php
rename to tests/phpunit/integration/SkinCitizenTest.php
index ce22e8ab0..2442c17f9 100644
--- a/tests/phpunit/SkinCitizenTest.php
+++ b/tests/phpunit/integration/SkinCitizenTest.php
@@ -2,7 +2,7 @@
declare( strict_types=1 );
-namespace MediaWiki\Skins\Citizen\Tests;
+namespace MediaWiki\Skins\Citizen\Integration\Tests;
use Exception;
use MediaWiki\Skins\Citizen\SkinCitizen;