3 use MediaWiki\Cache\LinkCache
;
4 use MediaWiki\Config\ServiceOptions
;
5 use MediaWiki\Linker\LinkRenderer
;
6 use MediaWiki\Linker\LinkRendererFactory
;
7 use MediaWiki\Linker\LinkTarget
;
8 use MediaWiki\MainConfigNames
;
9 use MediaWiki\Page\PageReference
;
10 use MediaWiki\Page\PageReferenceValue
;
11 use MediaWiki\Title\Title
;
12 use MediaWiki\Title\TitleValue
;
15 * @covers \MediaWiki\Linker\LinkRenderer
17 class LinkRendererTest
extends MediaWikiLangTestCase
{
18 use LinkCacheTestTrait
;
22 * @var LinkRendererFactory
26 protected function setUp(): void
{
28 $this->overrideConfigValues( [
29 MainConfigNames
::Server
=> '//example.org',
30 MainConfigNames
::CanonicalServer
=> 'http://example.org',
31 MainConfigNames
::ScriptPath
=> '/w',
32 MainConfigNames
::Script
=> '/w/index.php',
34 $this->factory
= $this->getServiceContainer()->getLinkRendererFactory();
37 public static function provideMergeAttribs() {
38 yield
[ new TitleValue( NS_SPECIAL
, 'BlankPage' ) ];
39 yield
[ new PageReferenceValue( NS_SPECIAL
, 'BlankPage', PageReference
::LOCAL
) ];
43 * @dataProvider provideMergeAttribs
44 * @covers \MediaWiki\Linker\LinkRenderer::makeBrokenLink
46 public function testMergeAttribs( $target ) {
47 $linkRenderer = $this->factory
->create();
48 $link = $linkRenderer->makeBrokenLink( $target, null, [
51 // Suppresses href attribute
57 '<a href="/wiki/Special:BlankPage" class="new foobar" '
58 . 'title="Special:BlankPage (page does not exist)" bar="baz">'
59 . 'Special:BlankPage</a>',
64 public static function provideMakeKnownLink() {
65 yield
[ new TitleValue( NS_MAIN
, 'Foobar' ) ];
66 yield
[ new PageReferenceValue( NS_MAIN
, 'Foobar', PageReference
::LOCAL
) ];
70 * @dataProvider provideMakeKnownLink
71 * @covers \MediaWiki\Linker\LinkRenderer::makeKnownLink
73 public function testMakeKnownLink( $target ) {
74 $linkCache = $this->createMock( LinkCache
::class );
75 $linkCache->method( 'addLinkObj' )->willReturn( 42 );
76 $this->setService( 'LinkCache', $linkCache );
77 $linkRenderer = $this->getServiceContainer()->getLinkRendererFactory()->create();
81 '<a href="/w/index.php?title=Foobar&foo=bar" title="Foobar">Foobar</a>',
82 $linkRenderer->makeKnownLink( $target, null, [], [ 'foo' => 'bar' ] )
85 $linkRenderer->setForceArticlePath( true );
87 '<a href="/wiki/Foobar?foo=bar" title="Foobar">Foobar</a>',
88 $linkRenderer->makeKnownLink( $target, null, [], [ 'foo' => 'bar' ] )
92 $linkRenderer->setForceArticlePath( false );
93 $linkRenderer->setExpandURLs( PROTO_HTTPS
);
95 '<a href="https://example.org/wiki/Foobar" title="Foobar">Foobar</a>',
96 $linkRenderer->makeKnownLink( $target )
100 public static function provideMakeBrokenLink() {
102 new TitleValue( NS_MAIN
, 'Foobar' ),
103 new TitleValue( NS_SPECIAL
, 'Foobar' )
106 new PageReferenceValue( NS_MAIN
, 'Foobar', PageReference
::LOCAL
),
107 new PageReferenceValue( NS_SPECIAL
, 'Foobar', PageReference
::LOCAL
)
112 * @dataProvider provideMakeBrokenLink
113 * @covers \MediaWiki\Linker\LinkRenderer::makeBrokenLink
115 public function testMakeBrokenLink( $target, $special ) {
116 $linkRenderer = $this->factory
->create();
118 // action=edit&redlink=1 added
120 '<a href="/w/index.php?title=Foobar&action=edit&redlink=1" '
121 . 'class="new" title="Foobar (page does not exist)">Foobar</a>',
122 $linkRenderer->makeBrokenLink( $target )
125 // action=edit&redlink=1 not added due to action query parameter
127 '<a href="/w/index.php?title=Foobar&action=foobar" class="new" '
128 . 'title="Foobar (page does not exist)">Foobar</a>',
129 $linkRenderer->makeBrokenLink( $target, null, [], [ 'action' => 'foobar' ] )
132 // action=edit&redlink=1 not added due to NS_SPECIAL
134 '<a href="/wiki/Special:Foobar" class="new" title="Special:Foobar '
135 . '(page does not exist)">Special:Foobar</a>',
136 $linkRenderer->makeBrokenLink( $special )
140 if ( $target instanceof LinkTarget
) {
142 '<a href="/w/index.php?title=Foobar&action=edit&redlink=1" class="new" '
143 . 'title="Foobar (page does not exist)">Foobar</a>',
144 $linkRenderer->makeBrokenLink( $target->createFragmentTarget( 'foobar' ) )
149 public static function provideMakeLink() {
151 new TitleValue( NS_SPECIAL
, 'Foobar' ),
152 new TitleValue( NS_SPECIAL
, 'BlankPage' )
155 new PageReferenceValue( NS_SPECIAL
, 'Foobar', PageReference
::LOCAL
),
156 new PageReferenceValue( NS_SPECIAL
, 'BlankPage', PageReference
::LOCAL
)
161 * @dataProvider provideMakeLink
162 * @covers \MediaWiki\Linker\LinkRenderer::makeLink
164 public function testMakeLink( $foobar, $blankpage ) {
165 $linkRenderer = $this->factory
->create();
167 '<a href="/wiki/Special:Foobar" class="new" title="Special:Foobar '
168 . '(page does not exist)">foo</a>',
169 $linkRenderer->makeLink( $foobar, 'foo' )
173 '<a href="/wiki/Special:BlankPage" title="Special:BlankPage">blank</a>',
174 $linkRenderer->makeLink( $blankpage, 'blank' )
178 '<a href="/wiki/Special:Foobar" class="new" title="Special:Foobar '
179 . '(page does not exist)"><script>evil()</script></a>',
180 $linkRenderer->makeLink( $foobar, '<script>evil()</script>' )
184 '<a href="/wiki/Special:Foobar" class="new" title="Special:Foobar '
185 . '(page does not exist)"><script>evil()</script></a>',
186 $linkRenderer->makeLink( $foobar, new HtmlArmor( '<script>evil()</script>' ) )
190 '<a href="#fragment">fragment</a>',
191 $linkRenderer->makeLink( Title
::newFromText( '#fragment' ) )
195 public static function provideMakeRedirectHeader() {
199 'title' => 'Main_Page',
201 '<div class="redirectMsg"><p>Redirect to:</p><ul class="redirectText"><li><a class="new" title="Main Page (page does not exist)">Main Page</a></li></ul></div>'
205 'title' => 'Redirect',
208 '<div class="redirectMsg"><p>Redirect to:</p><ul class="redirectText"><li><a class="new" title="Redirect (page does not exist)">Redirect</a></li></ul></div>'
210 // Test "forceKnown"; change namespace to NS_SPECIAL so we don't
211 // have to mock the LinkCache.
214 'title' => 'Main_Page',
215 'namespace' => NS_SPECIAL
,
216 'forceKnown' => true,
218 '<div class="redirectMsg"><p>Redirect to:</p><ul class="redirectText"><li><a title="Special:Main Page">Special:Main Page</a></li></ul></div>',
222 'title' => 'Redirect',
223 'namespace' => NS_SPECIAL
,
225 'forceKnown' => true,
227 '<div class="redirectMsg"><p>Redirect to:</p><ul class="redirectText"><li><a href="/w/index.php?title=Special:Redirect&redirect=no" title="Special:Redirect">Special:Redirect</a></li></ul></div>',
233 * @dataProvider provideMakeRedirectHeader
234 * @covers \MediaWiki\Linker\LinkRenderer::makeRedirectHeader
236 public function testMakeRedirectHeader( $test, $expected ) {
237 $lang = $this->getServiceContainer()->getContentLanguage();
238 $target = $this->makeMockTitle( $test['title'], $test );
239 $forceKnown = $test['forceKnown'] ??
false;
241 $linkRenderer = $this->factory
->create();
244 $linkRenderer->makeRedirectHeader( $lang, $target, $forceKnown )
248 public static function provideGetLinkClasses() {
250 new TitleValue( NS_MAIN
, 'FooBar' ),
251 new TitleValue( NS_MAIN
, 'Redirect' ),
252 new TitleValue( NS_USER
, 'Someuser' )
255 new PageReferenceValue( NS_MAIN
, 'FooBar', PageReference
::LOCAL
),
256 new PageReferenceValue( NS_MAIN
, 'Redirect', PageReference
::LOCAL
),
257 new PageReferenceValue( NS_USER
, 'Someuser', PageReference
::LOCAL
)
262 * @dataProvider provideGetLinkClasses
263 * @covers \MediaWiki\Linker\LinkRenderer::getLinkClasses
265 public function testGetLinkClasses( $foobarTitle, $redirectTitle, $userTitle ) {
266 $services = $this->getServiceContainer();
267 $titleFormatter = $services->getTitleFormatter();
268 $specialPageFactory = $services->getSpecialPageFactory();
269 $hookContainer = $services->getHookContainer();
270 $linkCache = $services->getLinkCache();
271 if ( $foobarTitle instanceof PageReference
) {
272 $cacheTitle = Title
::newFromPageReference( $foobarTitle );
274 $cacheTitle = $foobarTitle;
276 $this->addGoodLinkObject( 1, $cacheTitle, 10, 0 );
277 if ( $redirectTitle instanceof PageReference
) {
278 $cacheTitle = Title
::newFromPageReference( $redirectTitle );
280 $cacheTitle = $redirectTitle;
282 $this->addGoodLinkObject( 2, $cacheTitle, 10, 1 );
284 if ( $userTitle instanceof PageReference
) {
285 $cacheTitle = Title
::newFromPageReference( $userTitle );
287 $cacheTitle = $userTitle;
289 $this->addGoodLinkObject( 3, $cacheTitle, 10, 0 );
291 $linkRenderer = new LinkRenderer(
296 new ServiceOptions( LinkRenderer
::CONSTRUCTOR_OPTIONS
, [ 'renderForComment' => false ] )
300 $linkRenderer->getLinkClasses( $foobarTitle )
304 $linkRenderer->getLinkClasses( $redirectTitle )
308 protected function tearDown(): void
{
309 Title
::clearCaches();