jenkins-bot has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/322632 )

Change subject: Adding unit test base classes
......................................................................


Adding unit test base classes

... and first API unit tests as reference for further development

Change-Id: Ie2a7de98daac279a0450f6914ee2d2c82a81a351
---
M BlueSpice.hooks.php
M extension.json
M includes/CoreHooks.php
M includes/api/BSApiWikiPageTasks.php
A tests/BSApiExtJSStoreTestBase.php
A tests/BSApiTasksTestBase.php
A tests/BSPageFixturesProvider.php
A tests/api/BSApiTitleQueryStoreTest.php
A tests/api/BSApiWikiPageTasksTest.php
9 files changed, 410 insertions(+), 24 deletions(-)

Approvals:
  Mglaser: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/BlueSpice.hooks.php b/BlueSpice.hooks.php
index 12f9235..af7869a 100644
--- a/BlueSpice.hooks.php
+++ b/BlueSpice.hooks.php
@@ -1,6 +1,4 @@
 <?php
-#$wgHooks['UnitTestsList'][] = 'BsCoreHooks::onUnitTestsList';
-
 // START cache invalidation hooks
 $wgHooks['PageContentSaveComplete'][] = 
'BsCacheHelper::onPageContentSaveComplete';
 // END cache invalidation hooks
diff --git a/extension.json b/extension.json
index 4cfc8e0..e948cad 100644
--- a/extension.json
+++ b/extension.json
@@ -368,7 +368,8 @@
         "ParserFirstCallInit": "BsCoreHooks::onParserFirstCallInit",
         "UserAddGroup": "BsGroupHelper::addTemporaryGroupToUserHelper",
         "ExtensionTypes": "BsCoreHooks::onExtensionTypes",
-                               "PageContentSaveComplete": 
"BsCoreHooks::onPageContentSaveComplete"
+        "PageContentSaveComplete": "BsCoreHooks::onPageContentSaveComplete",
+        "UnitTestsList": "BsCoreHooks::onUnitTestsList"
     },
     "config": {
         "BlueSpiceExtInfo": {
@@ -529,7 +530,10 @@
         "BSEntityRegistry": "includes/EntityRegistry.php",
         "BSEntityConfig": "includes/entityconfigs/EntityConfig.php",
         "BSEntityContent": "includes/content/EntityContent.php",
-        "BSEntityContentHandler": "includes/content/EntityContentHandler.php"
+        "BSEntityContentHandler": "includes/content/EntityContentHandler.php",
+        "BSPageFixturesProvider": "tests/BSPageFixturesProvider.php",
+        "BSApiExtJSStoreTestBase": "tests/BSApiExtJSStoreTestBase.php",
+        "BSApiTasksTestBase": "tests/BSApiTasksTestBase.php"
     },
     "bsgConfigFiles": [],
     "load_composer_autoloader": true,
diff --git a/includes/CoreHooks.php b/includes/CoreHooks.php
index f082889..e867475 100755
--- a/includes/CoreHooks.php
+++ b/includes/CoreHooks.php
@@ -643,17 +643,7 @@
         * @return boolean Always true to keep hook running
         */
        public static function onUnitTestsList( &$files ) {
-               $oIterator = new RecursiveIteratorIterator(
-                       new RecursiveDirectoryIterator( dirname( __DIR__ ) . 
'/tests/' )
-               );
-               /**
-                * @var SplFileInfo $oFileInfo
-                */
-               foreach ( $oIterator as $oFileInfo ) {
-                       if ( substr( $oFileInfo->getFilename(), -8 ) === 
'Test.php' ) {
-                               $files[] = $oFileInfo->getPathname();
-                       }
-               }
+               $files[] = dirname( __DIR__ ) . '/tests/';
 
                return true;
        }
diff --git a/includes/api/BSApiWikiPageTasks.php 
b/includes/api/BSApiWikiPageTasks.php
index 6850e46..9aeb7fb 100644
--- a/includes/api/BSApiWikiPageTasks.php
+++ b/includes/api/BSApiWikiPageTasks.php
@@ -27,7 +27,7 @@
  */
 
 /**
- * Provides common tasks that can pe performed on a WikiPage
+ * Provides common tasks that can be performed on a WikiPage
  * @package BlueSpice_Foundation
  */
 class BSApiWikiPageTasks extends BSApiTasksBase {
@@ -170,20 +170,18 @@
                        return $oResponse;
                }
 
-               //Patern for Category tags
+               //Pattern for Category tags
                $sCanonicalNSName = MWNamespace::getCanonicalName( NS_CATEGORY 
);
                $sLocalNSName = BsNamespaceHelper::getNamespaceName( 
NS_CATEGORY );
                $sPattern = 
"#\[\[($sLocalNSName|$sCanonicalNSName):(.*?)\]\]#si";
                $matches = [];
-               $matchCount = 0;
                $matchCount = preg_match_all($sPattern, $sText, $matches, 
PREG_PATTERN_ORDER);
 
                $aCategories = [];
                //normalize
-               foreach ($matches[2] as $match){
-                       $sMatch = preg_replace('!_+!', ' ', $match);
-                       $sMatch = preg_replace('!\s+!', ' ', $sMatch);
-                       array_push($aCategories, $sMatch);
+               foreach ( $matches[2] as $match ){
+                       $oCategoryTitle = Title::newFromText( $match, 
NS_CATEGORY );
+                       array_push( $aCategories, $oCategoryTitle->getText() );
                }
 
                $oResponse->success = true;
@@ -276,6 +274,7 @@
                        DataUpdate::runUpdates( $oUpdates );
                        $oResponse->success = true;
                        $oResponse->message = wfMessage( 
'bs-wikipage-tasks-setcategories-success' )->plain();
+                       $oResponse->payload = $this->makeCategoryTaskPayload( 
$oTitle->getArticleID() );
                }
 
                return $oResponse;
@@ -398,7 +397,13 @@
                return $oTitle;
        }
 
-       public function needsToken() {
-               return parent::needsToken();
+       protected function makeCategoryTaskPayload( $pageId ) {
+               $oTitle = Title::newFromID( $pageId );
+               $result = $this->task_getExplicitCategories( (object)[ 
'page_id' => $pageId ], [] );
+               return array(
+                       'page_id' => $oTitle->getArticleID(),
+                       'page_prefixed_text' => $oTitle->getPrefixedText(),
+                       'categories' => $result->payload
+               );
        }
 }
diff --git a/tests/BSApiExtJSStoreTestBase.php 
b/tests/BSApiExtJSStoreTestBase.php
new file mode 100644
index 0000000..683e938
--- /dev/null
+++ b/tests/BSApiExtJSStoreTestBase.php
@@ -0,0 +1,169 @@
+<?php
+
+/**
+ *
+ * Class BSApiExtJSStoreTestBase
+ */
+abstract class BSApiExtJSStoreTestBase extends ApiTestCase {
+
+       protected $iFixtureTotal = 0;
+       abstract protected function getStoreSchema();
+       abstract protected function createStoreFixtureData();
+       abstract protected function getModuleName();
+
+       protected function setUp() {
+               parent::setUp();
+
+               $this->doLogin();
+       }
+
+       public function addDBDataOnce() {
+               $this->createStoreFixtureData();
+       }
+
+       public function testSchema() {
+               $results = $this->doApiRequest(
+                       $this->makeRequestParams()
+               );
+
+               $response = $results[0];
+               $firstRow = (object)$response['results'][0];
+               $schema = $this->getStoreSchema();
+               foreach( $schema as $schemaFieldName => $config ) {
+                       $this->assertObjectHasAttribute( $schemaFieldName, 
$firstRow, "Dataset misses field '$schemaFieldName'' from schema definition!" );
+                       $value = $firstRow->{$schemaFieldName};
+
+                       switch( $config['type'] ) {
+                               case 'string':
+                                       $this->assertEquals( true, is_string( 
$value ), "Value of field '$schemaFieldName' is not a string" );
+                                       break;
+                               case 'list':
+                                       $this->assertEquals( true, is_array( 
$value ), "Value of field '$schemaFieldName' is not a list" );
+                                       break;
+                               case 'numeric':
+                                       $this->assertEquals( true, is_numeric( 
$value ), "Value of field '$schemaFieldName' is not a number" );
+                                       break;
+                               case 'boolean':
+                                       $this->assertEquals( true, is_bool( 
$value ), "Value of field '$schemaFieldName' is not a boolean" );
+                                       break;
+                               case 'date':
+                                       $this->assertNotEquals( -1, 
strtotime(), "Value of field '$schemaFieldName' is not a valid date format" );
+                                       break;
+                               case 'title':
+                                       $this->assertNotNull( 
Title::newFromText( $value ), "Value of field '$schemaFieldName' is not a valid 
title" );
+                                       break;
+                               case 'templatetitle':
+                                       $this->assertNotNull( 
Title::newFromText( $value, NS_TEMPLATE ), "Value of field '$schemaFieldName' 
is not a valid template title" );
+                                       break;
+                       }
+               }
+       }
+
+       /**
+        * @param $limit
+        * @param $offset
+        *
+        * @dataProvider providePagingData
+        */
+       public function testPaging( $limit, $offset ) {
+               $results = $this->doApiRequest([
+                       'action' => $this->getModuleName(),
+                       'limit' => $limit,
+                       'offset' => $offset
+               ]);
+               $response = $results[0];
+
+               $this->assertAttributeEquals(
+                       $this->iFixtureTotal,
+                       'total',
+                       (object)$response,
+                       'Field "total" contains wrong value'
+               );
+
+               $this->assertLessThanOrEqual( $limit, 
count($response['results']), 'Number of results exceeds limit' );
+       }
+
+       public function providePagingData() {
+               return array(
+                       [ 2, 0 ],
+                       [ 2, 2 ],
+                       [ 2, 4 ],
+                       [ 4, 0 ],
+                       [ 4, 4 ],
+                       [ 4, 8 ]
+               );
+       }
+
+       /**
+        * [
+        * {
+        * "type":"string",
+        * "comparison":"ct",
+        * "value":"some text ...",
+        * "field":"someField"
+        * }
+        * ]
+        *
+        * @param $type
+        * @param $field
+        * @param $value
+        * @param $comparison
+        * @param $expectedTotal
+        *
+        * @dataProvider provideSingleFilterData
+        */
+       public function testSingleFilter( $type, $comparison, $field, $value, 
$expectedTotal ) {
+               $results = $this->doApiRequest([
+                       'action' => $this->getModuleName(),
+                       'filter' => FormatJson::encode([
+                               [
+                                       'type' => $type,
+                                       'comparison' => $comparison,
+                                       'field' => $field,
+                                       'value' => $value
+                               ]
+                       ])
+               ]);
+
+               $response = $results[0];
+
+               $this->assertAttributeEquals(
+                       $expectedTotal,
+                       'total',
+                       (object)$response,
+                       'Field "total" contains wrong value'
+               );
+       }
+
+       abstract public function provideSingleFilterData();
+
+       /**
+        * @param $filters
+        * @param $expectedTotal
+        *
+        * @dataProvider provideMultipleFilterData
+        */
+       public function testMultipleFilter( $filters, $expectedTotal ) {
+               $results = $this->doApiRequest([
+                       'action' => $this->getModuleName(),
+                       'filter' => FormatJson::encode( $filters )
+               ]);
+
+               $response = $results[0];
+
+               $this->assertAttributeEquals(
+                       $expectedTotal,
+                       'total',
+                       (object)$response,
+                       'Field "total" contains wrong value'
+               );
+       }
+
+       abstract public function provideMultipleFilterData();
+
+       protected function makeRequestParams() {
+               return [
+                       'action' => $this->getModuleName()
+               ];
+       }
+}
\ No newline at end of file
diff --git a/tests/BSApiTasksTestBase.php b/tests/BSApiTasksTestBase.php
new file mode 100644
index 0000000..63fdb60
--- /dev/null
+++ b/tests/BSApiTasksTestBase.php
@@ -0,0 +1,22 @@
+<?php
+
+abstract class BSApiTasksTestBase extends ApiTestCase {
+
+       abstract protected function getModuleName();
+
+       protected function setUp() {
+               parent::setUp();
+
+               $this->doLogin();
+       }
+
+       protected function executeTask( $taskName, $taskData ) {
+               $results = $this->doApiRequestWithToken([
+                       'action' => $this->getModuleName(),
+                       'task' => $taskName,
+                       'taskData' => FormatJson::encode( $taskData )
+               ]);
+
+               return (object)$results[0];
+       }
+}
\ No newline at end of file
diff --git a/tests/BSPageFixturesProvider.php b/tests/BSPageFixturesProvider.php
new file mode 100644
index 0000000..9779a75
--- /dev/null
+++ b/tests/BSPageFixturesProvider.php
@@ -0,0 +1,12 @@
+<?php
+
+class BSPageFixturesProvider {
+
+       /**
+        * @return array[]
+        */
+       public function getFixtureData() {
+               $oData = FormatJson::decode( file_get_contents( 
__DIR__."/data/pages.json" ) );
+               return $oData->pages;
+       }
+}
\ No newline at end of file
diff --git a/tests/api/BSApiTitleQueryStoreTest.php 
b/tests/api/BSApiTitleQueryStoreTest.php
new file mode 100644
index 0000000..b80840d
--- /dev/null
+++ b/tests/api/BSApiTitleQueryStoreTest.php
@@ -0,0 +1,70 @@
+<?php
+
+/**
+ * @group medium
+ *
+ * Class BSApiTitleQueryStoreTest
+ */
+class BSApiTitleQueryStoreTest extends BSApiExtJSStoreTestBase {
+       protected function getStoreSchema() {
+               return [
+                       'page_id' => [
+                               'type' => 'numeric'
+                       ],
+                       'page_namespace' => [
+                               'type' => 'numeric'
+                       ],
+                       'page_title' => [
+                               'type' => 'string'
+                       ],
+                       'prefixedText' => [
+                               'type' => 'string'
+                       ],
+                       'displayText' => [
+                               'type' => 'string'
+                       ],
+                       'type' => [
+                               'type' => 'string'
+                       ]
+               ];
+       }
+
+       protected function createStoreFixtureData() {
+               $oPageFixtures = new BSPageFixturesProvider();
+               $aFixtures = $oPageFixtures->getFixtureData();
+               foreach( $aFixtures as $aFixture ) {
+                       $this->insertPage( $aFixture[0], $aFixture[1] );
+               }
+       }
+
+       protected function getModuleName() {
+               return 'bs-titlequery-store';
+       }
+
+       protected function makeRequestParams() {
+               $aParams =  parent::makeRequestParams();
+               $aParams['options'] = FormatJson::encode([
+                       'namespaces' => [ NS_MAIN, NS_TEMPLATE ]
+               ]);
+
+               return $aParams;
+       }
+
+       public function provideSingleFilterData() {
+               return [
+                       'Filter by page_id' => [ 'numeric', 'eq', 'page_id', 
-1, 0 ]
+               ];
+       }
+
+       public function provideMultipleFilterData() {
+               return [
+                       'Filter by page_name and page_namespace' => [
+                               [
+
+                               ],
+                               0
+                       ]
+               ];
+       }
+
+}
\ No newline at end of file
diff --git a/tests/api/BSApiWikiPageTasksTest.php 
b/tests/api/BSApiWikiPageTasksTest.php
new file mode 100644
index 0000000..122da1c
--- /dev/null
+++ b/tests/api/BSApiWikiPageTasksTest.php
@@ -0,0 +1,116 @@
+<?php
+
+/**
+ * @group medium
+ *
+ * Class BSApiWikiPageTasksTest
+ */
+class BSApiWikiPageTasksTest extends BSApiTasksTestBase {
+       protected function getModuleName() {
+               return 'bs-wikipage-tasks';
+       }
+
+       public function setUp() {
+               parent::setUp();
+
+               $this->insertPage( 'Category Test', '[[Category:Mouse]] 
[[Category:Bird]] [[Category:Pink unicorn]]' );
+       }
+
+       public function testAddCategoriesSucceeds() {
+               $oTitle = Title::newFromText( 'Category Test' );
+               $aTestCategories = [
+                       'CatA' => Title::newFromText( 'CatA', NS_CATEGORY 
)->getText(),
+                       'cAT_B' => Title::newFromText( 'cAT_B', NS_CATEGORY 
)->getText(),
+                       'CAT C' => Title::newFromText( 'CAT C', NS_CATEGORY 
)->getText(),
+                       'cat____d'=> Title::newFromText( 'cat____d', 
NS_CATEGORY )->getText(),
+                       'CAT   f  g' => Title::newFromText( 'CAT   f  g', 
NS_CATEGORY )->getText()
+               ];
+
+               $response = $this->executeTask(
+                       'addCategories',
+                       [
+                               'page_id' => $oTitle->getArticleID(),
+                               'categories' => array_keys( $aTestCategories )
+                       ]
+               );
+
+               $this->assertEquals( true, $response->success, "Adding 
categories failed where it should have succeeded" );
+
+               $oWikiPage = WikiPage::factory( $oTitle );
+               $aCategoryTitles = $oWikiPage->getCategories();
+               $aActualCategories = [];
+               foreach( $aCategoryTitles as $oCategoryTitle ) {
+                       $aActualCategories[] = $oCategoryTitle->getText();
+               }
+
+               $aNormalizedTestCategories = array_values( $aTestCategories );
+               sort( $aNormalizedTestCategories );
+               $aIntersection = array_intersect( $aActualCategories, 
$aNormalizedTestCategories );
+               sort( $aIntersection );
+               $this->assertArrayEquals(
+                       $aIntersection,
+                       $aNormalizedTestCategories,
+                       'Not all categories were set'
+               );
+       }
+
+       public function testSetCategoriesSucceeds() {
+               $oTitle = Title::newFromText( 'Category Test' );
+               $aTestCategories = [
+                       'Cat' => Title::newFromText( 'Cat', NS_CATEGORY 
)->getText(),
+               ];
+
+               $response = $this->executeTask(
+                       'setCategories',
+                       [
+                               'page_id' => $oTitle->getArticleID(),
+                               'categories' => array_keys( $aTestCategories )
+                       ]
+               );
+
+               $this->assertEquals( true, $response->success, "Setting 
categories failed where it should have succeeded" );
+
+               $oWikiPage = WikiPage::factory( $oTitle );
+               $aCategoryTitles = $oWikiPage->getCategories();
+               $aActualCategories = [];
+               foreach( $aCategoryTitles as $oCategoryTitle ) {
+                       $aActualCategories[] = $oCategoryTitle->getText();
+               }
+
+               $aNormalizedTestCategories = array_values( $aTestCategories );
+
+               sort( $aNormalizedTestCategories );
+               sort( $aActualCategories );
+
+               $this->assertArrayEquals(
+                       $aActualCategories,
+                       $aNormalizedTestCategories,
+                       'Not all categories were set'
+               );
+       }
+
+       public function testRemoveCategoriesSucceeds() {
+               $oTitle = Title::newFromText( 'Category Test' );
+
+               $response = $this->executeTask(
+                       'removeCategories',
+                       [
+                               'page_id' => $oTitle->getArticleID(),
+                               'categories' => [ 'Mouse' ]
+                       ]
+               );
+
+               $this->assertEquals( true, $response->success, "Removing 
categories failed where it should have succeeded" );
+
+               $oWikiPage = WikiPage::factory( $oTitle );
+               $aCategoryTitles = $oWikiPage->getCategories();
+               $aActualCategories = [];
+               foreach( $aCategoryTitles as $oCategoryTitle ) {
+                       $aActualCategories[] = $oCategoryTitle->getText();
+               }
+
+               sort( $aActualCategories );
+
+               $this->assertFalse( in_array( 'Mouse', $aActualCategories ) );
+       }
+}
\ No newline at end of file

-- 
To view, visit https://gerrit.wikimedia.org/r/322632
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Ie2a7de98daac279a0450f6914ee2d2c82a81a351
Gerrit-PatchSet: 4
Gerrit-Project: mediawiki/extensions/BlueSpiceFoundation
Gerrit-Branch: master
Gerrit-Owner: Robert Vogel <vo...@hallowelt.biz>
Gerrit-Reviewer: Dvogel hallowelt <daniel.vo...@hallowelt.com>
Gerrit-Reviewer: Ljonka <l.verhovs...@gmail.com>
Gerrit-Reviewer: Mglaser <gla...@hallowelt.biz>
Gerrit-Reviewer: Pwirth <wi...@hallowelt.biz>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to