gplx/mediawiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/LinksUpdateSQLStoreDBIntegr...

253 lines
7.7 KiB
PHP

<?php
namespace SMW\Tests\Integration\MediaWiki;
use MediaWiki\Deferred\LinksUpdate\LinksUpdate;
use MediaWiki\MediaWikiServices;
use MediaWiki\Parser\ParserOutput;
use MediaWiki\Title\Title;
use SMW\DIWikiPage;
use SMW\ParserData;
use SMW\Services\ServicesFactory;
use SMW\Tests\SMWIntegrationTestCase;
use SMW\Tests\Utils\PageCreator;
use UnexpectedValueException;
/**
* @group semantic-mediawiki
* @group Database
* @group medium
*
* @license GPL-2.0-or-later
* @since 1.9.1
*
* @author mwjames
*/
class LinksUpdateSQLStoreDBIntegrationTest extends SMWIntegrationTestCase {
private $title = null;
private $mwHooksHandler;
private $semanticDataValidator;
private $pageDeleter;
private $revisionGuard;
private $pageCreator;
protected function setUp(): void {
parent::setUp();
$serviceFactory = ServicesFactory::getInstance();
$this->revisionGuard = $serviceFactory->singleton( 'RevisionGuard' );
$this->testEnvironment->addConfiguration(
'smwgPageSpecialProperties',
[ '_MDAT' ]
);
$this->mwHooksHandler = $this->testEnvironment->getUtilityFactory()->newMwHooksHandler();
$this->mwHooksHandler->deregisterListedHooks();
$this->mwHooksHandler->invokeHooksFromRegistry();
$this->semanticDataValidator = $this->testEnvironment->getUtilityFactory()->newValidatorFactory()->newSemanticDataValidator();
$this->pageDeleter = $this->testEnvironment->getUtilityFactory()->newPageDeleter();
$this->pageCreator = $serviceFactory->newPageCreator();
}
public function tearDown(): void {
$this->mwHooksHandler->restoreListedHooks();
if ( $this->title !== null ) {
$this->pageDeleter->deletePage( $this->title );
}
parent::tearDown();
}
public function testPageCreationAndRevisionHandlingBeforeLinksUpdate() {
$this->title = MediaWikiServices::getInstance()->getTitleFactory()->newFromText( __METHOD__ );
$beforeAlterationRevId = $this->createSinglePageWithAnnotations();
$this->assertSemanticDataBeforeContentAlteration();
$afterAlterationRevId = $this->alterPageContentToCreateNewRevisionWithoutAnnotations();
$this->assertSemanticDataAfterContentAlteration();
$this->assertNotSame(
$beforeAlterationRevId,
$afterAlterationRevId
);
}
/**
* @depends testPageCreationAndRevisionHandlingBeforeLinksUpdate
* @dataProvider propertyCountProvider
*/
public function testLinksUpdateAndVerifyStoreUpdate( $expected ) {
$this->title = MediaWikiServices::getInstance()->getTitleFactory()->newFromText( __METHOD__ );
$beforeAlterationRevId = $this->createSinglePageWithAnnotations();
$afterAlterationRevId = $this->alterPageContentToCreateNewRevisionWithoutAnnotations();
$this->testEnvironment->executePendingDeferredUpdates();
$this->fetchRevisionAndRunLinksUpdater(
$expected['beforeAlterationRevId'],
$beforeAlterationRevId
);
$this->fetchRevisionAndRunLinksUpdater(
$expected['afterAlterationRevId'],
$afterAlterationRevId
);
}
protected function createSinglePageWithAnnotations() {
$pageCreator = new PageCreator();
$pageCreator->createPage( $this->title )->doEdit( 'Add user property Aa and Fuyu {{#set:|Aa=Bb|Fuyu=Natsu}}' );
$this->testEnvironment->executePendingDeferredUpdates();
return $this->revisionGuard->newRevisionFromPage( $pageCreator->getPage() )->getId();
}
protected function alterPageContentToCreateNewRevisionWithoutAnnotations() {
$pageCreator = new PageCreator();
$pageCreator->createPage( $this->title )->doEdit( 'No annotations' );
$this->testEnvironment->executePendingDeferredUpdates();
return $this->revisionGuard->newRevisionFromPage( $pageCreator->getPage() )->getId();
}
protected function assertSemanticDataBeforeContentAlteration() {
$wikiPage = $this->pageCreator->createPage( $this->title );
$revision = $this->revisionGuard->newRevisionFromPage( $wikiPage );
$parserData = $this->retrieveAndLoadData();
$this->assertCount( 3, $parserData->getSemanticData()->getProperties() );
$this->assertEquals(
$parserData->getSemanticData()->getHash(),
$this->retrieveAndLoadData( $revision->getId() )->getSemanticData()->getHash(),
'Asserts that data are equals with or without a revision'
);
$this->semanticDataValidator->assertThatSemanticDataHasPropertyCountOf(
4,
$this->getStore()->getSemanticData( DIWikiPage::newFromTitle( $this->title ) ),
'Asserts property Aa, Fuyu, _SKEY, and _MDAT exists'
);
}
protected function assertSemanticDataAfterContentAlteration() {
$this->semanticDataValidator->assertThatSemanticDataHasPropertyCountOf(
2,
$this->getStore()->getSemanticData( DIWikiPage::newFromTitle( $this->title ) ),
'Asserts property _SKEY and _MDAT exists'
);
}
protected function fetchRevisionAndRunLinksUpdater( array $expected, $revId ) {
$parserData = $this->retrieveAndLoadData( $revId );
// Status before the update
$this->assertPropertyCount( $expected['poBefore'], $expected['storeBefore'], $parserData );
$this->runLinksUpdater( $this->title, $parserData->getOutput() );
// Status after the update
$this->assertPropertyCount( $expected['poAfter'], $expected['storeAfter'], $parserData );
}
protected function assertPropertyCount( $poExpected, $storeExpected, $parserData ) {
$this->semanticDataValidator->assertThatSemanticDataHasPropertyCountOf(
$poExpected['count'],
$parserData->getSemanticData(),
$poExpected['msg']
);
$this->semanticDataValidator->assertThatSemanticDataHasPropertyCountOf(
$storeExpected['count'],
$this->getStore()->getSemanticData( DIWikiPage::newFromTitle( $this->title ) ),
$storeExpected['msg']
);
}
protected function runLinksUpdater( Title $title, $parserOutput ) {
$linksUpdate = new LinksUpdate( $title, $parserOutput );
$linksUpdate->doUpdate();
$this->testEnvironment->executePendingDeferredUpdates();
}
protected function retrieveAndLoadData( $revId = null ) {
$revision = $revId !== null
? MediaWikiServices::getInstance()->getRevisionLookup()->getRevisionById( $revId )
: null;
$contentParser = ServicesFactory::getInstance()->newContentParser(
$this->title
);
$contentParser->setRevision( $revision );
$parserOutput = $contentParser->parse()->getOutput();
$parserOutput->setExtensionData( ParserData::OPT_FORCED_UPDATE, true );
if ( $parserOutput instanceof ParserOutput ) {
return new ParserData( $this->title, $parserOutput );
}
throw new UnexpectedValueException( 'ParserOutput is missing' );
}
public function propertyCountProvider() {
// Property _SKEY is always present even within an empty container
// po = ParserOutput, before means prior LinksUpdate
$provider = [];
$provider[] = [ [
'beforeAlterationRevId' => [
'poBefore' => [
'count' => 3,
'msg' => 'Asserts property Aa, Fuyu, and _SKEY exists before the update'
],
'storeBefore' => [
'count' => 2,
'msg' => 'Asserts property _SKEY and _MDAT exists in Store before the update'
],
'poAfter' => [
'count' => 4,
'msg' => 'Asserts property Aa, Fuyu, _SKEY, and _MDAT exists after the update'
],
'storeAfter' => [
'count' => 4,
'msg' => 'Asserts property Aa, Fuyu, _SKEY, and _MDAT exists after the update'
]
],
'afterAlterationRevId' => [
'poBefore' => [
'count' => 0,
'msg' => 'Asserts no property exists before the update'
],
'storeBefore' => [
'count' => 4,
'msg' => 'Asserts property Aa, Fuyu, _SKEY, and _MDAT from the previous state as no update has been made yet'
],
'poAfter' => [
'count' => 0,
'msg' => 'Asserts property _MDAT exists after the update'
],
'storeAfter' => [
'count' => 2,
'msg' => 'Asserts property _SKEY, _MDAT exists after the update'
]
]
] ];
return $provider;
}
}