2020-12-14 12:26:02 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace MediaWiki\Tests\Rest\Handler;
|
|
|
|
|
|
|
|
|
|
use DeferredUpdates;
|
|
|
|
|
use Exception;
|
|
|
|
|
use ExtensionRegistry;
|
|
|
|
|
use HashBagOStuff;
|
|
|
|
|
use HashConfig;
|
|
|
|
|
use MediaWiki\Config\ServiceOptions;
|
|
|
|
|
use MediaWiki\Json\JsonCodec;
|
2022-06-13 15:48:44 +00:00
|
|
|
use MediaWiki\MainConfigNames;
|
|
|
|
|
use MediaWiki\MainConfigSchema;
|
2020-12-14 12:26:02 +00:00
|
|
|
use MediaWiki\Parser\ParserCacheFactory;
|
2022-06-17 14:00:27 +00:00
|
|
|
use MediaWiki\Parser\Parsoid\ParsoidOutputAccess;
|
2020-12-14 12:26:02 +00:00
|
|
|
use MediaWiki\Rest\Handler\RevisionHTMLHandler;
|
|
|
|
|
use MediaWiki\Rest\LocalizedHttpException;
|
|
|
|
|
use MediaWiki\Rest\RequestData;
|
|
|
|
|
use MediaWiki\Revision\RevisionRecord;
|
|
|
|
|
use MediaWikiIntegrationTestCase;
|
|
|
|
|
use MWTimestamp;
|
|
|
|
|
use NullStatsdDataFactory;
|
|
|
|
|
use PHPUnit\Framework\MockObject\MockObject;
|
|
|
|
|
use Psr\Log\NullLogger;
|
|
|
|
|
use WANObjectCache;
|
|
|
|
|
use Wikimedia\Message\MessageValue;
|
|
|
|
|
use Wikimedia\Parsoid\Core\ClientError;
|
|
|
|
|
use Wikimedia\Parsoid\Core\ResourceLimitExceededException;
|
|
|
|
|
use Wikimedia\Parsoid\Parsoid;
|
|
|
|
|
use Wikimedia\UUID\GlobalIdGenerator;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers \MediaWiki\Rest\Handler\RevisionHTMLHandler
|
|
|
|
|
* @group Database
|
|
|
|
|
*/
|
|
|
|
|
class RevisionHTMLHandlerTest extends MediaWikiIntegrationTestCase {
|
|
|
|
|
use HandlerTestTrait;
|
2022-05-16 16:56:20 +00:00
|
|
|
use HTMLHandlerTestTrait;
|
2020-12-14 12:26:02 +00:00
|
|
|
|
|
|
|
|
private const WIKITEXT = 'Hello \'\'\'World\'\'\'';
|
|
|
|
|
|
2022-05-16 16:56:20 +00:00
|
|
|
private const HTML = '>World<';
|
|
|
|
|
|
|
|
|
|
/** @var HashBagOStuff */
|
|
|
|
|
private $parserCacheBagOStuff;
|
2020-12-14 12:26:02 +00:00
|
|
|
|
2020-12-15 22:12:49 +00:00
|
|
|
/** @var int */
|
|
|
|
|
private static $uuidCounter = 0;
|
|
|
|
|
|
2020-12-14 12:26:02 +00:00
|
|
|
protected function setUp(): void {
|
|
|
|
|
parent::setUp();
|
|
|
|
|
|
|
|
|
|
// Clean up these tables after each test
|
|
|
|
|
$this->tablesUsed = [
|
|
|
|
|
'page',
|
|
|
|
|
'revision',
|
|
|
|
|
'comment',
|
|
|
|
|
'text',
|
|
|
|
|
'content'
|
|
|
|
|
];
|
2022-05-16 16:56:20 +00:00
|
|
|
|
|
|
|
|
$this->parserCacheBagOStuff = new HashBagOStuff();
|
2020-12-14 12:26:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Checks whether Parsoid extension is installed and skips the test if it's not.
|
|
|
|
|
*/
|
|
|
|
|
private function checkParsoidInstalled() {
|
|
|
|
|
if ( !ExtensionRegistry::getInstance()->isLoaded( 'Parsoid' ) ) {
|
|
|
|
|
$this->markTestSkipped( 'Skip test, since parsoid is not configured' );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2022-06-17 14:00:27 +00:00
|
|
|
* @param ?Parsoid $parsoid
|
2022-06-13 15:48:44 +00:00
|
|
|
*
|
2020-12-14 12:26:02 +00:00
|
|
|
* @return RevisionHTMLHandler
|
|
|
|
|
*/
|
2022-06-17 14:00:27 +00:00
|
|
|
private function newHandler( ?Parsoid $parsoid = null ): RevisionHTMLHandler {
|
|
|
|
|
/** @var GlobalIdGenerator|MockObject $idGenerator */
|
|
|
|
|
$idGenerator = $this->createNoOpMock( GlobalIdGenerator::class, [ 'newUUIDv1' ] );
|
|
|
|
|
$idGenerator->method( 'newUUIDv1' )->willReturnCallback(
|
|
|
|
|
static function () {
|
|
|
|
|
return 'uuid' . ++self::$uuidCounter;
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
2020-12-14 12:26:02 +00:00
|
|
|
$parserCacheFactoryOptions = new ServiceOptions( ParserCacheFactory::CONSTRUCTOR_OPTIONS, [
|
|
|
|
|
'CacheEpoch' => '20200202112233',
|
2020-12-15 22:12:49 +00:00
|
|
|
'OldRevisionParserCacheExpireTime' => 60 * 60,
|
2020-12-14 12:26:02 +00:00
|
|
|
] );
|
|
|
|
|
|
2022-06-17 14:00:27 +00:00
|
|
|
$services = $this->getServiceContainer();
|
2020-12-14 12:26:02 +00:00
|
|
|
$parserCacheFactory = new ParserCacheFactory(
|
2022-05-16 16:56:20 +00:00
|
|
|
$this->parserCacheBagOStuff,
|
|
|
|
|
new WANObjectCache( [ 'cache' => $this->parserCacheBagOStuff, ] ),
|
2020-12-14 12:26:02 +00:00
|
|
|
$this->createHookContainer(),
|
|
|
|
|
new JsonCodec(),
|
|
|
|
|
new NullStatsdDataFactory(),
|
|
|
|
|
new NullLogger(),
|
2021-03-24 14:05:44 +00:00
|
|
|
$parserCacheFactoryOptions,
|
2022-06-17 14:00:27 +00:00
|
|
|
$services->getTitleFactory(),
|
|
|
|
|
$services->getWikiPageFactory()
|
2020-12-14 12:26:02 +00:00
|
|
|
);
|
|
|
|
|
|
2022-06-13 15:48:44 +00:00
|
|
|
$config = [
|
|
|
|
|
'RightsUrl' => 'https://example.com/rights',
|
|
|
|
|
'RightsText' => 'some rights',
|
|
|
|
|
'ParsoidCacheConfig' =>
|
|
|
|
|
MainConfigSchema::getDefaultValue( MainConfigNames::ParsoidCacheConfig )
|
|
|
|
|
];
|
2022-06-17 14:00:27 +00:00
|
|
|
|
|
|
|
|
$parsoidOutputAccess = new ParsoidOutputAccess(
|
|
|
|
|
new ServiceOptions(
|
|
|
|
|
ParsoidOutputAccess::CONSTRUCTOR_OPTIONS,
|
|
|
|
|
$services->getMainConfig()
|
|
|
|
|
),
|
2020-12-14 12:26:02 +00:00
|
|
|
$parserCacheFactory,
|
2022-06-17 14:00:27 +00:00
|
|
|
$services->getRevisionLookup(),
|
2021-05-04 20:45:30 +00:00
|
|
|
$idGenerator,
|
2022-06-17 14:00:27 +00:00
|
|
|
$services->getStatsdDataFactory(),
|
|
|
|
|
$parsoid ?? new Parsoid(
|
|
|
|
|
$services->get( 'ParsoidSiteConfig' ),
|
|
|
|
|
$services->get( 'ParsoidDataAccess' )
|
|
|
|
|
),
|
2022-06-29 17:01:21 +00:00
|
|
|
$services->getParsoidSiteConfig(),
|
2022-06-17 14:00:27 +00:00
|
|
|
$services->getParsoidPageConfigFactory()
|
2020-12-14 12:26:02 +00:00
|
|
|
);
|
|
|
|
|
|
2022-06-17 14:00:27 +00:00
|
|
|
$handler = new RevisionHTMLHandler(
|
|
|
|
|
new HashConfig( $config ),
|
|
|
|
|
$services->getRevisionLookup(),
|
|
|
|
|
$services->getTitleFormatter(),
|
|
|
|
|
$services->getPageStore(),
|
|
|
|
|
$this->getParsoidOutputStash(),
|
|
|
|
|
$services->getStatsdDataFactory(),
|
|
|
|
|
$parsoidOutputAccess
|
|
|
|
|
);
|
2020-12-14 12:26:02 +00:00
|
|
|
|
|
|
|
|
return $handler;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function getExistingPageWithRevisions( $name ) {
|
|
|
|
|
$page = $this->getNonexistingTestPage( $name );
|
|
|
|
|
|
|
|
|
|
$this->editPage( $page, self::WIKITEXT );
|
|
|
|
|
$revisions['first'] = $page->getRevisionRecord();
|
|
|
|
|
|
|
|
|
|
$this->editPage( $page, 'DEAD BEEF' );
|
|
|
|
|
$revisions['latest'] = $page->getRevisionRecord();
|
|
|
|
|
|
|
|
|
|
return [ $page, $revisions ];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testExecuteWithHtml() {
|
|
|
|
|
$this->checkParsoidInstalled();
|
|
|
|
|
[ $page, $revisions ] = $this->getExistingPageWithRevisions( __METHOD__ );
|
|
|
|
|
$this->assertTrue(
|
|
|
|
|
$this->editPage( $page, self::WIKITEXT )->isGood(),
|
2021-11-21 16:23:11 +00:00
|
|
|
'Edited a page'
|
2020-12-14 12:26:02 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$request = new RequestData(
|
|
|
|
|
[ 'pathParams' => [ 'id' => $revisions['first']->getId() ] ]
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$handler = $this->newHandler();
|
|
|
|
|
$data = $this->executeHandlerAndGetBodyData( $handler, $request, [
|
|
|
|
|
'format' => 'with_html'
|
|
|
|
|
] );
|
|
|
|
|
|
|
|
|
|
$this->assertResponseData( $revisions['first'], $data );
|
|
|
|
|
$this->assertStringContainsString( '<!DOCTYPE html>', $data['html'] );
|
|
|
|
|
$this->assertStringContainsString( '<html', $data['html'] );
|
|
|
|
|
$this->assertStringContainsString( self::HTML, $data['html'] );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testExecuteHtmlOnly() {
|
|
|
|
|
$this->checkParsoidInstalled();
|
|
|
|
|
[ $page, $revisions ] = $this->getExistingPageWithRevisions( __METHOD__ );
|
|
|
|
|
$this->assertTrue(
|
|
|
|
|
$this->editPage( $page, self::WIKITEXT )->isGood(),
|
2021-11-21 16:23:11 +00:00
|
|
|
'Edited a page'
|
2020-12-14 12:26:02 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$request = new RequestData(
|
|
|
|
|
[ 'pathParams' => [ 'id' => $revisions['first']->getId() ] ]
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$handler = $this->newHandler();
|
|
|
|
|
$response = $this->executeHandler( $handler, $request, [
|
|
|
|
|
'format' => 'html'
|
|
|
|
|
] );
|
|
|
|
|
|
|
|
|
|
$htmlResponse = (string)$response->getBody();
|
|
|
|
|
$this->assertStringContainsString( '<!DOCTYPE html>', $htmlResponse );
|
|
|
|
|
$this->assertStringContainsString( '<html', $htmlResponse );
|
|
|
|
|
$this->assertStringContainsString( self::HTML, $htmlResponse );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testEtagLastModified() {
|
|
|
|
|
$this->checkParsoidInstalled();
|
|
|
|
|
|
|
|
|
|
$time = time();
|
|
|
|
|
MWTimestamp::setFakeTime( $time );
|
|
|
|
|
|
|
|
|
|
[ $page, $revisions ] = $this->getExistingPageWithRevisions( __METHOD__ );
|
|
|
|
|
$request = new RequestData(
|
|
|
|
|
[ 'pathParams' => [ 'id' => $revisions['first']->getId() ] ]
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// First, test it works if nothing was cached yet.
|
|
|
|
|
// Make some time pass since page was created:
|
|
|
|
|
MWTimestamp::setFakeTime( $time + 10 );
|
2022-05-16 16:56:20 +00:00
|
|
|
$handler = $this->newHandler();
|
2020-12-14 12:26:02 +00:00
|
|
|
$response = $this->executeHandler( $handler, $request, [
|
|
|
|
|
'format' => 'html'
|
|
|
|
|
] );
|
|
|
|
|
$this->assertArrayHasKey( 'ETag', $response->getHeaders() );
|
|
|
|
|
$this->assertArrayHasKey( 'Last-Modified', $response->getHeaders() );
|
2020-12-15 22:12:49 +00:00
|
|
|
$this->assertSame( MWTimestamp::convert( TS_RFC2822, $time + 10 ),
|
2020-12-14 12:26:02 +00:00
|
|
|
$response->getHeaderLine( 'Last-Modified' ) );
|
|
|
|
|
|
2020-12-15 22:12:49 +00:00
|
|
|
$etag = $response->getHeaderLine( 'ETag' );
|
|
|
|
|
|
|
|
|
|
// Now, test that headers work when getting from cache too.
|
|
|
|
|
MWTimestamp::setFakeTime( $time + 20 );
|
2022-05-16 16:56:20 +00:00
|
|
|
$handler = $this->newHandler();
|
2020-12-14 12:26:02 +00:00
|
|
|
$response = $this->executeHandler( $handler, $request, [
|
|
|
|
|
'format' => 'html'
|
|
|
|
|
] );
|
|
|
|
|
$this->assertArrayHasKey( 'ETag', $response->getHeaders() );
|
2020-12-15 22:12:49 +00:00
|
|
|
$this->assertSame( $etag, $response->getHeaderLine( 'ETag' ) );
|
2020-12-14 12:26:02 +00:00
|
|
|
$this->assertArrayHasKey( 'Last-Modified', $response->getHeaders() );
|
|
|
|
|
$this->assertSame( MWTimestamp::convert( TS_RFC2822, $time + 10 ),
|
|
|
|
|
$response->getHeaderLine( 'Last-Modified' ) );
|
|
|
|
|
|
2020-12-15 22:12:49 +00:00
|
|
|
// Now, expire the cache, and assert we are getting a new timestamp back
|
|
|
|
|
MWTimestamp::setFakeTime( $time + 10000 );
|
2020-12-14 12:26:02 +00:00
|
|
|
$this->assertTrue(
|
|
|
|
|
$page->getTitle()->invalidateCache( MWTimestamp::convert( TS_MW, $time ) ),
|
2021-11-21 16:23:11 +00:00
|
|
|
'Can invalidate cache'
|
2020-12-14 12:26:02 +00:00
|
|
|
);
|
|
|
|
|
DeferredUpdates::doUpdates();
|
|
|
|
|
|
2022-05-16 16:56:20 +00:00
|
|
|
$handler = $this->newHandler();
|
2020-12-14 12:26:02 +00:00
|
|
|
$response = $this->executeHandler( $handler, $request, [
|
|
|
|
|
'format' => 'html'
|
|
|
|
|
] );
|
|
|
|
|
$this->assertArrayHasKey( 'ETag', $response->getHeaders() );
|
|
|
|
|
$this->assertNotSame( $etag, $response->getHeaderLine( 'ETag' ) );
|
|
|
|
|
$this->assertArrayHasKey( 'Last-Modified', $response->getHeaders() );
|
2020-12-15 22:12:49 +00:00
|
|
|
$this->assertSame( MWTimestamp::convert( TS_RFC2822, $time + 10000 ),
|
2020-12-14 12:26:02 +00:00
|
|
|
$response->getHeaderLine( 'Last-Modified' ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function provideHandlesParsoidError() {
|
|
|
|
|
yield 'ClientError' => [
|
|
|
|
|
new ClientError( 'TEST_TEST' ),
|
|
|
|
|
new LocalizedHttpException(
|
|
|
|
|
new MessageValue( 'rest-html-backend-error' ),
|
|
|
|
|
400,
|
|
|
|
|
[
|
|
|
|
|
'reason' => 'TEST_TEST'
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
];
|
|
|
|
|
yield 'ResourceLimitExceededException' => [
|
|
|
|
|
new ResourceLimitExceededException( 'TEST_TEST' ),
|
|
|
|
|
new LocalizedHttpException(
|
|
|
|
|
new MessageValue( 'rest-resource-limit-exceeded' ),
|
|
|
|
|
413,
|
|
|
|
|
[
|
|
|
|
|
'reason' => 'TEST_TEST'
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideHandlesParsoidError
|
|
|
|
|
*/
|
|
|
|
|
public function testHandlesParsoidError(
|
|
|
|
|
Exception $parsoidException,
|
|
|
|
|
Exception $expectedException
|
|
|
|
|
) {
|
|
|
|
|
$this->checkParsoidInstalled();
|
|
|
|
|
|
|
|
|
|
[ $page, $revisions ] = $this->getExistingPageWithRevisions( __METHOD__ );
|
|
|
|
|
$request = new RequestData(
|
|
|
|
|
[ 'pathParams' => [ 'id' => $revisions['first']->getId() ] ]
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$parsoid = $this->createNoOpMock( Parsoid::class, [ 'wikitext2html' ] );
|
|
|
|
|
$parsoid->expects( $this->once() )
|
|
|
|
|
->method( 'wikitext2html' )
|
|
|
|
|
->willThrowException( $parsoidException );
|
|
|
|
|
|
2022-05-16 16:56:20 +00:00
|
|
|
$handler = $this->newHandler( $parsoid );
|
2020-12-14 12:26:02 +00:00
|
|
|
$this->expectExceptionObject( $expectedException );
|
|
|
|
|
$this->executeHandler( $handler, $request, [
|
|
|
|
|
'format' => 'html'
|
|
|
|
|
] );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testExecute_missingparam() {
|
|
|
|
|
$request = new RequestData();
|
|
|
|
|
|
|
|
|
|
$this->expectExceptionObject(
|
|
|
|
|
new LocalizedHttpException(
|
|
|
|
|
new MessageValue( "paramvalidator-missingparam", [ 'revision' ] ),
|
|
|
|
|
400
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$handler = $this->newHandler();
|
|
|
|
|
$this->executeHandler( $handler, $request );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testExecute_error() {
|
|
|
|
|
$request = new RequestData( [ 'pathParams' => [ 'id' => '2076419894' ] ] );
|
|
|
|
|
|
|
|
|
|
$this->expectExceptionObject(
|
|
|
|
|
new LocalizedHttpException(
|
|
|
|
|
new MessageValue( "rest-nonexistent-revision", [ 'testing' ] ),
|
|
|
|
|
404
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$handler = $this->newHandler();
|
|
|
|
|
$this->executeHandler( $handler, $request );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param RevisionRecord $rev
|
|
|
|
|
* @param array $data
|
|
|
|
|
*/
|
|
|
|
|
private function assertResponseData( RevisionRecord $rev, array $data ): void {
|
|
|
|
|
$title = $rev->getPageAsLinkTarget();
|
|
|
|
|
|
|
|
|
|
$this->assertSame( $rev->getId(), $data['id'] );
|
|
|
|
|
$this->assertSame( $rev->getSize(), $data['size'] );
|
|
|
|
|
$this->assertSame( $rev->isMinor(), $data['minor'] );
|
|
|
|
|
$this->assertSame(
|
|
|
|
|
wfTimestampOrNull( TS_ISO_8601, $rev->getTimestamp() ),
|
|
|
|
|
$data['timestamp']
|
|
|
|
|
);
|
|
|
|
|
$this->assertSame( $title->getArticleID(), $data['page']['id'] );
|
|
|
|
|
$this->assertSame( $title->getDBkey(), $data['page']['key'] ); // assume main namespace
|
|
|
|
|
$this->assertSame( $title->getText(), $data['page']['title'] ); // assume main namespace
|
|
|
|
|
$this->assertSame( CONTENT_MODEL_WIKITEXT, $data['content_model'] );
|
|
|
|
|
$this->assertSame( 'https://example.com/rights', $data['license']['url'] );
|
|
|
|
|
$this->assertSame( 'some rights', $data['license']['title'] );
|
|
|
|
|
$this->assertSame( $rev->getComment()->text, $data['comment'] );
|
|
|
|
|
$this->assertSame( $rev->getUser()->getId(), $data['user']['id'] );
|
|
|
|
|
$this->assertSame( $rev->getUser()->getName(), $data['user']['name'] );
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-16 16:56:20 +00:00
|
|
|
/**
|
|
|
|
|
* The below 2 request are described as follows;
|
|
|
|
|
*
|
|
|
|
|
* Request One:
|
|
|
|
|
* This request stashes data-parsoid to the parsoid output stash and caches the
|
|
|
|
|
* stash key in ::cachedStashedKey so that we can use to perform a stash lookup
|
|
|
|
|
* in the near future.
|
|
|
|
|
*
|
|
|
|
|
* Request Two:
|
|
|
|
|
* This request then uses the request header ETag which is the same as that in
|
|
|
|
|
* the cached stashed key container because during the second request, no stashing
|
|
|
|
|
* was done and the page revision is the same so what is the in output response headers
|
|
|
|
|
* in the user's browser will be exactly what's in the parsoid output stash.
|
|
|
|
|
*
|
|
|
|
|
* NOTE: if we make another request which actually stashes, that cached stash key will
|
|
|
|
|
* be updated, and we can use it to access the stash's latest entry.
|
|
|
|
|
*/
|
|
|
|
|
public function testExecuteStashParsoidOutput() {
|
|
|
|
|
[ /* page */, $revisions ] = $this->getExistingPageWithRevisions( __METHOD__ );
|
|
|
|
|
$outputStash = $this->getParsoidOutputStash();
|
|
|
|
|
|
|
|
|
|
[ /* $html1 */, $etag1, $stashKey1 ] = $this->executeRevisionHTMLRequest(
|
|
|
|
|
$revisions['first']->getId(),
|
|
|
|
|
[ 'stash' => true ]
|
|
|
|
|
);
|
|
|
|
|
$this->assertNotNull( $outputStash->get( $stashKey1 ) );
|
|
|
|
|
|
|
|
|
|
[ /* $html2 */, $etag2, $stashKey2 ] = $this->executeRevisionHTMLRequest(
|
|
|
|
|
$revisions['first']->getId(),
|
|
|
|
|
[ 'stash' => false ]
|
|
|
|
|
);
|
|
|
|
|
$this->assertNotNull( $outputStash->get( $stashKey1 ) );
|
|
|
|
|
$this->assertNotNull( $outputStash->get( $stashKey2 ) );
|
|
|
|
|
|
|
|
|
|
$this->assertNotSame( $etag1, $etag2 );
|
|
|
|
|
|
|
|
|
|
// Make sure the output for stashed and unstashed doesn't have the same tag,
|
|
|
|
|
// since it will actually be different!
|
|
|
|
|
// FIXME: implement flavors
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-24 21:13:42 +00:00
|
|
|
public function testETagVariesOnFormat() {
|
|
|
|
|
$page = $this->getExistingTestPage();
|
|
|
|
|
|
|
|
|
|
[ /* $html1 */, $etag1 ] =
|
|
|
|
|
$this->executeRevisionHTMLRequest( $page->getLatest(), [], [ 'format' => 'html' ] );
|
|
|
|
|
|
|
|
|
|
[ /* $html2 */, $etag2 ] =
|
|
|
|
|
$this->executeRevisionHTMLRequest( $page->getLatest(), [], [ 'format' => 'with_html' ] );
|
|
|
|
|
|
|
|
|
|
$this->assertNotSame( $etag1, $etag2 );
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-13 09:31:50 +00:00
|
|
|
public function testStashingWithRateLimitExceeded() {
|
|
|
|
|
// Set the rate limit to 1 request per minute
|
2022-06-21 12:56:19 +00:00
|
|
|
$this->overrideConfigValue(
|
|
|
|
|
'RateLimits',
|
2022-06-13 09:31:50 +00:00
|
|
|
[
|
|
|
|
|
'stashbasehtml' => [
|
|
|
|
|
'&can-bypass' => false,
|
|
|
|
|
'ip' => [ 1, 60 ],
|
|
|
|
|
'newbie' => [ 1, 60 ]
|
|
|
|
|
]
|
|
|
|
|
] );
|
2022-06-21 12:56:19 +00:00
|
|
|
$this->setMainCache( CACHE_HASH );
|
2022-06-13 09:31:50 +00:00
|
|
|
|
|
|
|
|
$page = $this->getExistingTestPage();
|
|
|
|
|
|
|
|
|
|
$this->executeRevisionHTMLRequest( $page->getLatest(), [ 'stash' => true ] );
|
|
|
|
|
// In this request, the rate limit has been exceeded, so it should throw.
|
|
|
|
|
$this->expectException( LocalizedHttpException::class );
|
|
|
|
|
$this->expectExceptionCode( 429 );
|
|
|
|
|
$this->executeRevisionHTMLRequest( $page->getLatest(), [ 'stash' => true ] );
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-14 12:26:02 +00:00
|
|
|
}
|