diff options
11 files changed, 108 insertions, 34 deletions
diff --git a/tests/phpunit/includes/Storage/DerivedPageDataUpdaterTest.php b/tests/phpunit/includes/Storage/DerivedPageDataUpdaterTest.php index 6eb49eeeb117..91614f56649d 100644 --- a/tests/phpunit/includes/Storage/DerivedPageDataUpdaterTest.php +++ b/tests/phpunit/includes/Storage/DerivedPageDataUpdaterTest.php @@ -1129,16 +1129,11 @@ class DerivedPageDataUpdaterTest extends MediaWikiIntegrationTestCase { * @covers \MediaWiki\Storage\DerivedPageDataUpdater::doUpdates() * @covers \MediaWiki\Storage\DerivedPageDataUpdater::doSecondaryDataUpdates() * @covers \MediaWiki\Storage\DerivedPageDataUpdater::doParserCacheUpdate() - * @covers \MediaWiki\RecentChanges\ChangeTrackingEventIngress::handlePageRevisionUpdatedEvent() - * @covers \MediaWiki\RecentChanges\ChangeTrackingEventIngress::anyChangedSlotSupportsCategories() */ public function testDoUpdates( bool $simulateNullEdit, - bool $simulatePageCreation, - bool $rcWatchCategoryMembership + bool $simulatePageCreation ) { - $this->overrideConfigValue( MainConfigNames::RCWatchCategoryMembership, $rcWatchCategoryMembership ); - $page = $this->getPage( __METHOD__ ); $content = [ SlotRecord::MAIN => new WikitextContent( 'current [[main]]' ) ]; @@ -1257,15 +1252,6 @@ class DerivedPageDataUpdaterTest extends MediaWikiIntegrationTestCase { $this->runDeferredUpdates(); $this->assertSame( 1, $listenerCalled, 'PageRevisionUpdatedEvent listener' ); - $this->assertSame( - $rcWatchCategoryMembership && !$simulateNullEdit ? 1 : 0, - $this->getServiceContainer() - ->getJobQueueGroup() - ->get( 'categoryMembershipChange' ) - ->getSize(), - 'CategoryMembershipChangeJob should only be enqueued for non-null edits (T390636)' - ); - // TODO: MCR: test data updates for additional slots! // TODO: test update for edit without page creation // TODO: test message cache purge @@ -1281,13 +1267,11 @@ class DerivedPageDataUpdaterTest extends MediaWikiIntegrationTestCase { // null or non-null edit [ true, false ], // page creation - [ true, false ], - // category membership notifications enabled or disabled [ true, false ] ); foreach ( $testCases as $params ) { - [ $simulateNullEdit, $simulatePageCreation, $rcWatchCategoryMembership ] = $params; + [ $simulateNullEdit, $simulatePageCreation ] = $params; if ( $simulateNullEdit && $simulatePageCreation ) { // Page creations cannot be null edits, so don't simulate an impossible scenario @@ -1295,10 +1279,9 @@ class DerivedPageDataUpdaterTest extends MediaWikiIntegrationTestCase { } $description = sprintf( - '%s edit, %s category membership notifications %s', + '%s edit%s', $simulateNullEdit ? 'null' : 'non-null', - $simulatePageCreation ? 'page creation, ' : '', - $rcWatchCategoryMembership ? 'enabled' : 'disabled' + $simulatePageCreation ? ', page creation, ' : '' ); yield $description => $params; diff --git a/tests/phpunit/includes/Storage/PageUpdaterTest.php b/tests/phpunit/includes/Storage/PageUpdaterTest.php index d0af2f7d9d83..904ac1069139 100644 --- a/tests/phpunit/includes/Storage/PageUpdaterTest.php +++ b/tests/phpunit/includes/Storage/PageUpdaterTest.php @@ -10,6 +10,7 @@ use MediaWiki\Content\TextContent; use MediaWiki\Content\WikitextContent; use MediaWiki\Deferred\DeferredUpdates; use MediaWiki\Json\FormatJson; +use MediaWiki\MainConfigNames; use MediaWiki\Message\Message; use MediaWiki\Page\Event\PageRevisionUpdatedEvent; use MediaWiki\Page\PageIdentity; @@ -49,6 +50,10 @@ class PageUpdaterTest extends MediaWikiIntegrationTestCase { protected function setUp(): void { parent::setUp(); + // Force enable RC entry creation for category changes + // so that tests can verify whether CategoryMembershipChangeJobs get enqueued. + $this->overrideConfigValue( MainConfigNames::RCWatchCategoryMembership, true ); + $slotRoleRegistry = $this->getServiceContainer()->getSlotRoleRegistry(); if ( !$slotRoleRegistry->isDefinedRole( 'aux' ) ) { @@ -69,6 +74,13 @@ class PageUpdaterTest extends MediaWikiIntegrationTestCase { // protect against service container resets $this->setService( 'SlotRoleRegistry', $slotRoleRegistry ); + + // Clear some extension hook handlers that may interfere with mock object expectations. + $this->clearHooks( [ + 'RevisionRecordInserted', + 'PageSaveComplete', + 'LinksUpdateComplete', + ] ); } private function getDummyTitle( $method ) { @@ -707,7 +719,8 @@ class PageUpdaterTest extends MediaWikiIntegrationTestCase { $this->expectChangeTrackingUpdates( 1, 0, 1, - $page->getNamespace() === NS_USER_TALK ? 1 : 0 + $page->getNamespace() === NS_USER_TALK ? 1 : 0, + 1 ); $this->expectSearchUpdates( 1 ); @@ -751,7 +764,7 @@ class PageUpdaterTest extends MediaWikiIntegrationTestCase { // Null edits should not go into recentchanges, should not // increment counters, and should not trigger talk page notifications. - $this->expectChangeTrackingUpdates( 0, 0, 0, 0 ); + $this->expectChangeTrackingUpdates( 0, 0, 0, 0, 0 ); // Update derived data on null edits $this->expectSearchUpdates( 1 ); @@ -796,7 +809,7 @@ class PageUpdaterTest extends MediaWikiIntegrationTestCase { // Silent dummy revisions should not go into recentchanges, // should not increment counters, and should not trigger talk page // notifications. - $this->expectChangeTrackingUpdates( 0, 0, 0, 0 ); + $this->expectChangeTrackingUpdates( 0, 0, 0, 0, 0 ); // Do not update derived data on dummy revisions! $this->expectSearchUpdates( 0 ); @@ -1262,7 +1275,7 @@ class PageUpdaterTest extends MediaWikiIntegrationTestCase { // Clear pending jobs so the spies don't get confused $this->runJobs(); - $this->expectChangeTrackingUpdates( 0, 0, 0, 0 ); + $this->expectChangeTrackingUpdates( 0, 0, 0, 0, 0 ); $this->expectSearchUpdates( 0 ); $updater = $page->newPageUpdater( $user ); diff --git a/tests/phpunit/includes/api/ApiImportTest.php b/tests/phpunit/includes/api/ApiImportTest.php index a3a3203f26d6..4c6c26e26a1a 100644 --- a/tests/phpunit/includes/api/ApiImportTest.php +++ b/tests/phpunit/includes/api/ApiImportTest.php @@ -30,6 +30,13 @@ class ApiImportTest extends ApiUploadTestCase { } public function testImport() { + // Clear some extension hook handlers that may interfere with mock object expectations. + $this->clearHooks( [ + 'RevisionRecordInserted', + 'PageSaveComplete', + 'LinksUpdateComplete', + ] ); + $title = $this->getNonexistingTestPage()->getTitle(); // We expect two PageRevisionUpdated events, one triggered by @@ -89,7 +96,7 @@ class ApiImportTest extends ApiUploadTestCase { // Expect only non-edit recent changes entry, but no edit count // or user talk. - $this->expectChangeTrackingUpdates( 0, 1, 0, 0 ); + $this->expectChangeTrackingUpdates( 0, 1, 0, 0, 1 ); // Expect search updates to be triggered $this->expectSearchUpdates( 1 ); diff --git a/tests/phpunit/includes/filerepo/file/LocalFileTest.php b/tests/phpunit/includes/filerepo/file/LocalFileTest.php index 5a9b0a9ae327..8bba9ec1dfd2 100644 --- a/tests/phpunit/includes/filerepo/file/LocalFileTest.php +++ b/tests/phpunit/includes/filerepo/file/LocalFileTest.php @@ -896,8 +896,14 @@ class LocalFileTest extends MediaWikiIntegrationTestCase { * @covers \LocalFile */ public function testUpload_updatePropagation() { + // Clear some extension hook handlers that may interfere with mock object expectations. + $this->clearHooks( [ + 'PageSaveComplete', + 'RevisionRecordInserted', + ] ); + // Expect two non-edit recent changes entries but only one edit count. - $this->expectChangeTrackingUpdates( 0, 2, 1, 0 ); + $this->expectChangeTrackingUpdates( 0, 2, 1, 0, 1 ); // Expect only one search update, the re-upload doesn't change the page. $this->expectSearchUpdates( 1 ); diff --git a/tests/phpunit/includes/import/ImportableOldRevisionImporterTest.php b/tests/phpunit/includes/import/ImportableOldRevisionImporterTest.php index f974eec26f7e..ed064e19ed99 100644 --- a/tests/phpunit/includes/import/ImportableOldRevisionImporterTest.php +++ b/tests/phpunit/includes/import/ImportableOldRevisionImporterTest.php @@ -190,7 +190,7 @@ class ImportableOldRevisionImporterTest extends MediaWikiIntegrationTestCase { public function testUpdatePropagation( PageIdentity $title ) { $revision = $this->getWikiRevision( Title::castFromPageIdentity( $title ) ); - $this->expectChangeTrackingUpdates( 0, 0, 0, 0 ); + $this->expectChangeTrackingUpdates( 0, 0, 0, 0, 1 ); $this->expectSearchUpdates( 1 ); $this->expectLocalizationUpdate( $title->getNamespace() === NS_MEDIAWIKI ? 1 : 0 ); diff --git a/tests/phpunit/includes/page/MovePageTest.php b/tests/phpunit/includes/page/MovePageTest.php index be3043578b90..07aaf63a09f9 100644 --- a/tests/phpunit/includes/page/MovePageTest.php +++ b/tests/phpunit/includes/page/MovePageTest.php @@ -741,6 +741,14 @@ class MovePageTest extends MediaWikiIntegrationTestCase { * @dataProvider provideUpdatePropagation */ public function testUpdatePropagation( $old, $new, ?Content $content = null ) { + // Clear some extension hook handlers that may interfere with mock object expectations. + $this->clearHooks( [ + 'RevisionRecordInserted', + 'PageSaveComplete', + 'PageMoveComplete', + 'LinksUpdateComplete', + ] ); + $old = Title::newFromText( $old ); $new = Title::newFromText( $new ); @@ -754,7 +762,7 @@ class MovePageTest extends MediaWikiIntegrationTestCase { // Should be counted as user contributions (T163966) // Should generate an RC entry for the move log, but not for // the dummy revision or redirect page. - $this->expectChangeTrackingUpdates( 0, 1, 1, 0 ); + $this->expectChangeTrackingUpdates( 0, 1, 1, 0, 1 ); // The moved page and the redirect should both get re-indexed. $this->expectSearchUpdates( 2 ); diff --git a/tests/phpunit/includes/page/UndeletePageTest.php b/tests/phpunit/includes/page/UndeletePageTest.php index a33201382924..7a471a748db5 100644 --- a/tests/phpunit/includes/page/UndeletePageTest.php +++ b/tests/phpunit/includes/page/UndeletePageTest.php @@ -76,6 +76,9 @@ class UndeletePageTest extends MediaWikiIntegrationTestCase { $this->fail( $updater->getStatus()->getWikiText() ); } + // Run jobs that were enqueued by page creation now, since they might expect the page to exist. + $this->runJobs( [ 'minJobs' => 0 ] ); + $this->pages[] = [ 'page' => $page, 'revId' => $revisionRecord->getId() ]; $this->deletePage( $page, '', $performer ); } @@ -223,6 +226,12 @@ class UndeletePageTest extends MediaWikiIntegrationTestCase { * @covers \MediaWiki\Page\UndeletePage::undeleteUnsafe */ public function testUpdatePropagation( ProperPageIdentity $page, ?Content $content = null ) { + // Clear some extension hook handlers that may interfere with mock object expectations. + $this->clearHooks( [ + 'LinksUpdateComplete', + 'PageUndeleteComplete', + ] ); + $content ??= new WikitextContent( 'hi' ); $this->setupPage( $page->getDBkey(), $page->getNamespace(), $content ); $this->runJobs(); @@ -231,7 +240,7 @@ class UndeletePageTest extends MediaWikiIntegrationTestCase { // Should generate an RC entry for undeletion, // but not a regular page edit. - $this->expectChangeTrackingUpdates( 0, 1, 0, 0 ); + $this->expectChangeTrackingUpdates( 0, 1, 0, 0, 0 ); $this->expectSearchUpdates( 1 ); $this->expectLocalizationUpdate( $page->getNamespace() === NS_MEDIAWIKI ? 1 : 0 ); diff --git a/tests/phpunit/includes/page/WikiPageDbTest.php b/tests/phpunit/includes/page/WikiPageDbTest.php index 3efff6e309d0..d4e30e48fac2 100644 --- a/tests/phpunit/includes/page/WikiPageDbTest.php +++ b/tests/phpunit/includes/page/WikiPageDbTest.php @@ -1777,6 +1777,13 @@ more stuff PageIdentity $title, ?Content $content = null ) { + // Clear some extension hook handlers that may interfere with mock object expectations. + $this->clearHooks( [ + 'PageSaveComplete', + 'RevisionRecordInserted', + 'ArticleProtectComplete', + ] ); + $content ??= new TextContent( 'Lorem Ipsum' ); $page = $this->createPage( $title, $content ); @@ -1784,7 +1791,7 @@ more stuff $this->runJobs(); // Expect only non-edit recent changes entry - $this->expectChangeTrackingUpdates( 0, 1, 0, 0 ); + $this->expectChangeTrackingUpdates( 0, 1, 0, 0, 0 ); // Expect no resource module purges on protection $this->expectResourceLoaderUpdates( 0 ); diff --git a/tests/phpunit/includes/recentchanges/ChangeTrackingUpdateSpyTrait.php b/tests/phpunit/includes/recentchanges/ChangeTrackingUpdateSpyTrait.php index d7df06882f7a..dd31a56f75d5 100644 --- a/tests/phpunit/includes/recentchanges/ChangeTrackingUpdateSpyTrait.php +++ b/tests/phpunit/includes/recentchanges/ChangeTrackingUpdateSpyTrait.php @@ -2,6 +2,8 @@ namespace MediaWiki\Tests\recentchanges; +use MediaWiki\JobQueue\JobQueueGroup; +use MediaWiki\MainConfigNames; use MediaWiki\RecentChanges\RecentChange; use MediaWiki\User\TalkPageNotificationManager; use MediaWiki\User\UserEditTracker; @@ -25,8 +27,13 @@ trait ChangeTrackingUpdateSpyTrait { int $rcEdit, int $rcOther, int $userEditCount, - int $talkPageNotifications + int $talkPageNotifications, + int $categoryMembershipChangeJobs ) { + // Force enable RC entry creation for category changes + // to verify CategoryMembershipChangeJobs get enqueued irrespective of local configuration. + $this->overrideConfigValue( MainConfigNames::RCWatchCategoryMembership, true ); + // Hack for spying on RC insertions $rcEditStatus = $this->createMock( StatusValue::class ); $rcEditStatus->expects( $this->exactly( $rcEdit ) ) @@ -75,6 +82,25 @@ trait ChangeTrackingUpdateSpyTrait { ->method( 'removeUserHasNewMessages' ); $this->setService( 'TalkPageNotificationManager', $talkPageNotificationManager ); + + $categoryMembershipChangeJobStatus = $this->createMock( StatusValue::class ); + $categoryMembershipChangeJobStatus->expects( $this->exactly( $categoryMembershipChangeJobs ) ) + ->method( 'setOK' ); + + $jobQueueGroup = $this->createMock( JobQueueGroup::class ); + $jobQueueGroup->method( $this->logicalOr( 'push', 'lazyPush' ) ) + ->willReturnCallback( + static function ( $specs ) use ( $categoryMembershipChangeJobStatus ): void { + $specs = is_array( $specs ) ? $specs : [ $specs ]; + foreach ( $specs as $spec ) { + if ( $spec->getType() === 'categoryMembershipChange' ) { + $categoryMembershipChangeJobStatus->setOK( true ); + } + } + } + ); + + $this->setService( 'JobQueueGroup', $jobQueueGroup ); } } diff --git a/tests/phpunit/integration/includes/page/DeletePageTest.php b/tests/phpunit/integration/includes/page/DeletePageTest.php index 78e35dcaead9..c6f7f46ec397 100644 --- a/tests/phpunit/integration/includes/page/DeletePageTest.php +++ b/tests/phpunit/integration/includes/page/DeletePageTest.php @@ -478,6 +478,11 @@ class DeletePageTest extends MediaWikiIntegrationTestCase { * @covers \MediaWiki\Page\UndeletePage::undeleteUnsafe */ public function testUpdatePropagation( $name, ?Content $content = null ) { + // Clear some extension hook handlers that may interfere with mock object expectations. + $this->clearHooks( [ + 'PageDeleteComplete', + ] ); + $content ??= new WikitextContent( self::PAGE_TEXT ); $deleterUser = static::getTestSysop()->getUser(); $deleter = new UltimateAuthority( $deleterUser ); @@ -489,7 +494,8 @@ class DeletePageTest extends MediaWikiIntegrationTestCase { // but not a regular page edit. $this->expectChangeTrackingUpdates( 0, 1, 0, - $page->getNamespace() === NS_USER_TALK ? -1 : 0 + $page->getNamespace() === NS_USER_TALK ? -1 : 0, + 0 ); // TODO: Assert that the search index is updated after deletion. diff --git a/tests/phpunit/integration/includes/page/RollbackPageTest.php b/tests/phpunit/integration/includes/page/RollbackPageTest.php index 7ef37b73a795..973febea3eb3 100644 --- a/tests/phpunit/integration/includes/page/RollbackPageTest.php +++ b/tests/phpunit/integration/includes/page/RollbackPageTest.php @@ -588,6 +588,12 @@ class RollbackPageTest extends MediaWikiIntegrationTestCase { ?Content $content1 = null, ?Content $content2 = null ) { + // Clear some extension hook handlers that may interfere with mock object expectations. + $this->clearHooks( [ + 'PageSaveComplete', + 'RevisionRecordInserted', + ] ); + $page = $this->getServiceContainer()->getWikiPageFactory() ->newFromTitle( Title::newFromText( __METHOD__ ) ); @@ -602,7 +608,8 @@ class RollbackPageTest extends MediaWikiIntegrationTestCase { // Should generate an RC entry for rollback $this->expectChangeTrackingUpdates( 1, 0, 1, - $page->getNamespace() === NS_USER_TALK ? 1 : 0 + $page->getNamespace() === NS_USER_TALK ? 1 : 0, + 1 ); $this->expectSearchUpdates( 1 ); @@ -617,5 +624,7 @@ class RollbackPageTest extends MediaWikiIntegrationTestCase { ->newRollbackPage( $page, $admin, $user1 ) ->rollbackIfAllowed(); $this->assertStatusGood( $rollbackResult ); + + $this->runDeferredUpdates(); } } |