There is a common and reasonable need for longer lines in tests. The nudge for shorter lines doesn't seem valuable here. The natural breaks will likely still fall in 80-100 given the enforced practice for non-test code, e.g. whether through habit, or 80-100 column markers in text editors, or the finite width of diff and code review interfaces. Change-Id: I879479e13551789a67624ce66f0946d2f185e6ee
453 lines
14 KiB
PHP
453 lines
14 KiB
PHP
<?php
|
||
|
||
namespace MediaWiki\Tests\Integration\CommentFormatter;
|
||
|
||
use LinkCacheTestTrait;
|
||
use MediaWiki\Cache\LinkBatchFactory;
|
||
use MediaWiki\CommentFormatter\CommentParser;
|
||
use MediaWiki\Logger\LoggerFactory;
|
||
use MediaWiki\Tests\Unit\DummyServicesTrait;
|
||
use SiteConfiguration;
|
||
use Title;
|
||
|
||
/**
|
||
* @covers \MediaWiki\CommentFormatter\CommentParser
|
||
*/
|
||
class CommentParserTest extends \MediaWikiIntegrationTestCase {
|
||
use DummyServicesTrait;
|
||
use LinkCacheTestTrait;
|
||
|
||
private function getParser() {
|
||
$services = $this->getServiceContainer();
|
||
return new CommentParser(
|
||
$services->getLinkRenderer(),
|
||
$services->getLinkBatchFactory(),
|
||
$services->getLinkCache(),
|
||
$services->getRepoGroup(),
|
||
$services->getContentLanguage(),
|
||
$services->getContentLanguage(),
|
||
$services->getTitleParser(),
|
||
$services->getNamespaceInfo(),
|
||
$services->getHookContainer()
|
||
);
|
||
}
|
||
|
||
private function setupInterwiki() {
|
||
$this->overrideMwServices( null, [
|
||
'InterwikiLookup' => function () {
|
||
return $this->getDummyInterwikiLookup( [
|
||
'interwiki' => [
|
||
'iw_prefix' => 'interwiki',
|
||
'iw_url' => 'https://interwiki/$1',
|
||
]
|
||
] );
|
||
}
|
||
] );
|
||
}
|
||
|
||
private function setupConf() {
|
||
$conf = new SiteConfiguration();
|
||
$conf->settings = [
|
||
'wgServer' => [
|
||
'enwiki' => '//en.example.org'
|
||
],
|
||
'wgArticlePath' => [
|
||
'enwiki' => '/w/$1',
|
||
],
|
||
];
|
||
$conf->suffixes = [ 'wiki' ];
|
||
$this->setMwGlobals( [
|
||
'wgScript' => '/wiki/index.php',
|
||
'wgArticlePath' => '/wiki/$1',
|
||
'wgCapitalLinks' => true,
|
||
'wgConf' => $conf,
|
||
] );
|
||
}
|
||
|
||
/**
|
||
* Copied from LinkerTest so that LinkerTest can be deleted once deprecation
|
||
* and removal of Linker::formatComment() is complete.
|
||
*
|
||
* @return array[]
|
||
*/
|
||
public function provideFormatComment() {
|
||
$wikiId = 'enwiki'; // $wgConf has a fake entry for this
|
||
return [
|
||
// Linker::formatComment
|
||
[
|
||
'a<script>b',
|
||
'a<script>b',
|
||
],
|
||
[
|
||
'a—b',
|
||
'a—b',
|
||
],
|
||
[
|
||
"'''not bolded'''",
|
||
"'''not bolded'''",
|
||
],
|
||
[
|
||
"try <script>evil</scipt> things",
|
||
"try <script>evil</scipt> things",
|
||
],
|
||
// Linker::formatAutocomments
|
||
[
|
||
'<span dir="auto"><span class="autocomment"><a href="/wiki/Special:BlankPage#autocomment" title="Special:BlankPage">→autocomment</a></span></span>',
|
||
"/* autocomment */",
|
||
],
|
||
[
|
||
'<span dir="auto"><span class="autocomment"><a href="/wiki/Special:BlankPage#linkie.3F" title="Special:BlankPage">→[[linkie?]]</a></span></span>',
|
||
"/* [[linkie?]] */",
|
||
],
|
||
[
|
||
'<span dir="auto"><span class="autocomment">: </span> // Edit via via</span>',
|
||
// Regression test for T222857
|
||
"/* */ // Edit via via",
|
||
],
|
||
[
|
||
'<span dir="auto"><span class="autocomment">: </span> foobar</span>',
|
||
// Regression test for T222857
|
||
"/**/ foobar",
|
||
],
|
||
[
|
||
'<span dir="auto"><span class="autocomment"><a href="/wiki/Special:BlankPage#autocomment" title="Special:BlankPage">→autocomment</a>: </span> post</span>',
|
||
"/* autocomment */ post",
|
||
],
|
||
[
|
||
'pre <span dir="auto"><span class="autocomment"><a href="/wiki/Special:BlankPage#autocomment" title="Special:BlankPage">→autocomment</a></span></span>',
|
||
"pre /* autocomment */",
|
||
],
|
||
[
|
||
'pre <span dir="auto"><span class="autocomment"><a href="/wiki/Special:BlankPage#autocomment" title="Special:BlankPage">→autocomment</a>: </span> post</span>',
|
||
"pre /* autocomment */ post",
|
||
],
|
||
[
|
||
'<span dir="auto"><span class="autocomment"><a href="/wiki/Special:BlankPage#autocomment" title="Special:BlankPage">→autocomment</a>: </span> multiple? <span dir="auto"><span class="autocomment"><a href="/wiki/Special:BlankPage#autocomment2" title="Special:BlankPage">→autocomment2</a></span></span></span>',
|
||
"/* autocomment */ multiple? /* autocomment2 */",
|
||
],
|
||
[
|
||
'<span dir="auto"><span class="autocomment"><a href="/wiki/Special:BlankPage#autocomment_containing_.2F.2A" title="Special:BlankPage">→autocomment containing /*</a>: </span> T70361</span>',
|
||
"/* autocomment containing /* */ T70361"
|
||
],
|
||
[
|
||
'<span dir="auto"><span class="autocomment"><a href="/wiki/Special:BlankPage#autocomment_containing_.22quotes.22" title="Special:BlankPage">→autocomment containing "quotes"</a></span></span>',
|
||
"/* autocomment containing \"quotes\" */"
|
||
],
|
||
[
|
||
'<span dir="auto"><span class="autocomment"><a href="/wiki/Special:BlankPage#autocomment_containing_.3Cscript.3Etags.3C.2Fscript.3E" title="Special:BlankPage">→autocomment containing <script>tags</script></a></span></span>',
|
||
"/* autocomment containing <script>tags</script> */"
|
||
],
|
||
[
|
||
'<span dir="auto"><span class="autocomment"><a href="#autocomment">→autocomment</a></span></span>',
|
||
"/* autocomment */",
|
||
false, true
|
||
],
|
||
[
|
||
'<span dir="auto"><span class="autocomment">autocomment</span></span>',
|
||
"/* autocomment */",
|
||
null
|
||
],
|
||
[
|
||
'',
|
||
"/* */",
|
||
false, true
|
||
],
|
||
[
|
||
'',
|
||
"/* */",
|
||
null
|
||
],
|
||
[
|
||
'<span dir="auto"><span class="autocomment">[[</span></span>',
|
||
"/* [[ */",
|
||
false, true
|
||
],
|
||
[
|
||
'<span dir="auto"><span class="autocomment">[[</span></span>',
|
||
"/* [[ */",
|
||
null
|
||
],
|
||
[
|
||
"foo <span dir=\"auto\"><span class=\"autocomment\"><a href=\"#.23\">→[[#_\t_]]</a></span></span>",
|
||
"foo /* [[#_\t_]] */",
|
||
false, true
|
||
],
|
||
[
|
||
"foo <span dir=\"auto\"><span class=\"autocomment\"><a href=\"#_.09\">#_\t_</a></span></span>",
|
||
"foo /* [[#_\t_]] */",
|
||
null
|
||
],
|
||
[
|
||
'<span dir="auto"><span class="autocomment"><a href="/wiki/Special:BlankPage#autocomment" title="Special:BlankPage">→autocomment</a></span></span>',
|
||
"/* autocomment */",
|
||
false, false
|
||
],
|
||
[
|
||
'<span dir="auto"><span class="autocomment"><a class="external" rel="nofollow" href="//en.example.org/w/Special:BlankPage#autocomment">→autocomment</a></span></span>',
|
||
"/* autocomment */",
|
||
false, false, $wikiId
|
||
],
|
||
// Linker::formatLinksInComment
|
||
[
|
||
'abc <a href="/wiki/index.php?title=Link&action=edit&redlink=1" class="new" title="Link (page does not exist)">link</a> def',
|
||
"abc [[link]] def",
|
||
],
|
||
[
|
||
'abc <a href="/wiki/index.php?title=Link&action=edit&redlink=1" class="new" title="Link (page does not exist)">text</a> def',
|
||
"abc [[link|text]] def",
|
||
],
|
||
[
|
||
'abc <a href="/wiki/Special:BlankPage" title="Special:BlankPage">Special:BlankPage</a> def',
|
||
"abc [[Special:BlankPage|]] def",
|
||
],
|
||
[
|
||
'abc <a href="/wiki/index.php?title=%C4%84%C5%9B%C5%BC&action=edit&redlink=1" class="new" title="Ąśż (page does not exist)">ąśż</a> def',
|
||
"abc [[%C4%85%C5%9B%C5%BC]] def",
|
||
],
|
||
[
|
||
'abc <a href="/wiki/Special:BlankPage#section" title="Special:BlankPage">#section</a> def',
|
||
"abc [[#section]] def",
|
||
],
|
||
[
|
||
'abc <a href="/wiki/index.php?title=/subpage&action=edit&redlink=1" class="new" title="/subpage (page does not exist)">/subpage</a> def',
|
||
"abc [[/subpage]] def",
|
||
],
|
||
[
|
||
'abc <a href="/wiki/index.php?title=%22evil!%22&action=edit&redlink=1" class="new" title=""evil!" (page does not exist)">"evil!"</a> def',
|
||
"abc [[\"evil!\"]] def",
|
||
],
|
||
[
|
||
'abc [[<script>very evil</script>]] def',
|
||
"abc [[<script>very evil</script>]] def",
|
||
],
|
||
[
|
||
'abc [[|]] def',
|
||
"abc [[|]] def",
|
||
],
|
||
[
|
||
'abc <a href="/wiki/index.php?title=Link&action=edit&redlink=1" class="new" title="Link (page does not exist)">link</a> def',
|
||
"abc [[link]] def",
|
||
false, false
|
||
],
|
||
[
|
||
'abc <a class="external" rel="nofollow" href="//en.example.org/w/Link">link</a> def',
|
||
"abc [[link]] def",
|
||
false, false, $wikiId
|
||
],
|
||
[
|
||
'<a href="/wiki/index.php?title=Special:Upload&wpDestFile=LinkerTest.jpg" class="new" title="LinkerTest.jpg">Media:LinkerTest.jpg</a>',
|
||
'[[Media:LinkerTest.jpg]]'
|
||
],
|
||
[
|
||
'<a href="/wiki/Special:BlankPage" title="Special:BlankPage">Special:BlankPage</a>',
|
||
'[[:Special:BlankPage]]'
|
||
],
|
||
[
|
||
'<a href="/wiki/index.php?title=Link&action=edit&redlink=1" class="new" title="Link (page does not exist)">linktrail</a>...',
|
||
'[[link]]trail...'
|
||
],
|
||
[
|
||
'<a href="/wiki/Present" title="Present">Present</a>',
|
||
'[[Present]]',
|
||
],
|
||
[
|
||
'<a href="https://interwiki/Some_page" class="extiw" title="interwiki:Some page">interwiki:Some page</a>',
|
||
'[[interwiki:Some page]]',
|
||
],
|
||
[
|
||
'<a href="https://interwiki/Present" class="extiw" title="interwiki:Present">interwiki:Present</a> <a href="/wiki/Present" title="Present">Present</a>',
|
||
'[[interwiki:Present]] [[Present]]'
|
||
]
|
||
];
|
||
// phpcs:enable
|
||
}
|
||
|
||
/**
|
||
* Adapted from LinkerTest
|
||
*
|
||
* @dataProvider provideFormatComment
|
||
*/
|
||
public function testFormatComment(
|
||
$expected, $comment, $title = false, $local = false, $wikiId = null
|
||
) {
|
||
$conf = new SiteConfiguration();
|
||
$conf->settings = [
|
||
'wgServer' => [
|
||
'enwiki' => '//en.example.org',
|
||
'dewiki' => '//de.example.org',
|
||
],
|
||
'wgArticlePath' => [
|
||
'enwiki' => '/w/$1',
|
||
'dewiki' => '/w/$1',
|
||
],
|
||
];
|
||
$conf->suffixes = [ 'wiki' ];
|
||
|
||
$this->setMwGlobals( [
|
||
'wgScript' => '/wiki/index.php',
|
||
'wgArticlePath' => '/wiki/$1',
|
||
'wgCapitalLinks' => true,
|
||
'wgConf' => $conf,
|
||
// TODO: update tests when the default changes
|
||
'wgFragmentMode' => [ 'legacy' ],
|
||
] );
|
||
|
||
$this->setupInterwiki();
|
||
$this->addGoodLinkObject( 1, Title::newFromText( 'Present' ) );
|
||
|
||
if ( $title === false ) {
|
||
// We need a page title that exists
|
||
$title = Title::newFromText( 'Special:BlankPage' );
|
||
}
|
||
|
||
$parser = $this->getParser();
|
||
$result = $parser->finalize(
|
||
$parser->preprocess(
|
||
$comment,
|
||
$title,
|
||
$local,
|
||
$wikiId
|
||
)
|
||
);
|
||
|
||
$this->assertEquals( $expected, $result );
|
||
}
|
||
|
||
/**
|
||
* Adapted from LinkerTest
|
||
*/
|
||
public static function provideFormatLinksInComment() {
|
||
return [
|
||
[
|
||
'foo bar <a href="/wiki/Special:BlankPage" title="Special:BlankPage">Special:BlankPage</a>',
|
||
'foo bar [[Special:BlankPage]]',
|
||
null,
|
||
],
|
||
[
|
||
'<a href="/wiki/Special:BlankPage" title="Special:BlankPage">Special:BlankPage</a>',
|
||
'[[ :Special:BlankPage]]',
|
||
null,
|
||
],
|
||
[
|
||
'[[Foo<a href="/wiki/Special:BlankPage" title="Special:BlankPage">Special:BlankPage</a>',
|
||
'[[Foo[[Special:BlankPage]]',
|
||
null,
|
||
],
|
||
[
|
||
'<a class="external" rel="nofollow" href="//en.example.org/w/Foo%27bar">Foo'bar</a>',
|
||
"[[Foo'bar]]",
|
||
'enwiki',
|
||
],
|
||
[
|
||
'foo bar <a class="external" rel="nofollow" href="//en.example.org/w/Special:BlankPage">Special:BlankPage</a>',
|
||
'foo bar [[Special:BlankPage]]',
|
||
'enwiki',
|
||
],
|
||
[
|
||
'foo bar <a class="external" rel="nofollow" href="//en.example.org/w/File:Example">Image:Example</a>',
|
||
'foo bar [[Image:Example]]',
|
||
'enwiki',
|
||
],
|
||
];
|
||
// phpcs:enable
|
||
}
|
||
|
||
/**
|
||
* Adapted from LinkerTest. Note that we test the new HTML escaping variant.
|
||
*
|
||
* @dataProvider provideFormatLinksInComment
|
||
*/
|
||
public function testFormatLinksInComment( $expected, $input, $wiki ) {
|
||
$this->setupConf();
|
||
$parser = $this->getParser();
|
||
$title = Title::newFromText( 'Special:BlankPage' );
|
||
$result = $parser->finalize(
|
||
$parser->preprocess(
|
||
$input, $title, false, $wiki, false
|
||
)
|
||
);
|
||
|
||
$this->assertEquals( $expected, $result );
|
||
}
|
||
|
||
public function testLinkCacheInteraction() {
|
||
$this->tablesUsed[] = 'page';
|
||
$services = $this->getServiceContainer();
|
||
$present = Title::newFromText( 'Present' );
|
||
$absent = Title::newFromText( 'Absent' );
|
||
$this->editPage(
|
||
$present,
|
||
'content'
|
||
);
|
||
$parser = $this->getParser();
|
||
$linkCache = $services->getLinkCache();
|
||
$result = $parser->finalize( [
|
||
$parser->preprocess( "[[$present]]" ),
|
||
$parser->preprocess( "[[$absent]]" )
|
||
] );
|
||
$expected = [
|
||
'<a href="/index.php/Present" title="Present">Present</a>',
|
||
'<a href="/index.php?title=Absent&action=edit&redlink=1" class="new" title="Absent (page does not exist)">Absent</a>'
|
||
];
|
||
$this->assertSame( $expected, $result );
|
||
$this->assertGreaterThan( 0, $linkCache->getGoodLinkID( $present ) );
|
||
$this->assertTrue( $linkCache->isBadLink( $absent ) );
|
||
|
||
// Run the comment batch again and confirm that LinkBatch does not need
|
||
// to execute a query. This is a CommentParser responsibility since
|
||
// LinkBatch does not provide a transparent read-through cache.
|
||
// TODO: Generic $this->assertQueryCount() would do the job.
|
||
$lbf = $services->getDBLoadBalancerFactory();
|
||
$fakeLB = $lbf->newMainLB();
|
||
$fakeLB->disable( __METHOD__ );
|
||
$linkBatchFactory = new LinkBatchFactory(
|
||
$services->getLinkCache(),
|
||
$services->getTitleFormatter(),
|
||
$services->getContentLanguage(),
|
||
$services->getGenderCache(),
|
||
$fakeLB,
|
||
LoggerFactory::getInstance( 'LinkBatch' )
|
||
);
|
||
$parser = new CommentParser(
|
||
$services->getLinkRenderer(),
|
||
$linkBatchFactory,
|
||
$linkCache,
|
||
$services->getRepoGroup(),
|
||
$services->getContentLanguage(),
|
||
$services->getContentLanguage(),
|
||
$services->getTitleParser(),
|
||
$services->getNamespaceInfo(),
|
||
$services->getHookContainer()
|
||
);
|
||
$result = $parser->finalize( [
|
||
$parser->preprocess( "[[$present]]" ),
|
||
$parser->preprocess( "[[$absent]]" )
|
||
] );
|
||
$this->assertSame( $expected, $result );
|
||
}
|
||
|
||
/**
|
||
* Regression test for T300311
|
||
*/
|
||
public function testInterwikiLinkCachePollution() {
|
||
$this->tablesUsed[] = 'page';
|
||
$this->setupConf();
|
||
$this->setupInterwiki();
|
||
$present = Title::newFromText( 'Template:Present' );
|
||
$this->editPage(
|
||
$present,
|
||
'content'
|
||
);
|
||
$this->getServiceContainer()->getLinkCache()->clear();
|
||
$parser = $this->getParser();
|
||
$result = $parser->finalize(
|
||
$parser->preprocess( "[[interwiki:$present]] [[$present]]" )
|
||
);
|
||
$this->assertSame(
|
||
// phpcs:ignore Generic.Files.LineLength
|
||
"<a href=\"https://interwiki/$present\" class=\"extiw\" title=\"interwiki:$present\">interwiki:$present</a> <a href=\"/wiki/$present\" title=\"$present\">$present</a>",
|
||
$result
|
||
);
|
||
}
|
||
|
||
}
|