mirror of
https://github.com/diocloid/LinkTitles.git
synced 2025-07-12 17:29:30 +02:00
353 lines
13 KiB
PHP
353 lines
13 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Unit tests for the Linker class, i.e. the core functionality
|
|
*
|
|
* Copyright 2012-2024 Daniel Kraus <bovender@bovender.de> ('bovender')
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
* MA 02110-1301, USA.
|
|
*
|
|
* @author Daniel Kraus <bovender@bovender.de>
|
|
*/
|
|
|
|
/**
|
|
* Unit tests for the LinkTitles\Linker class.
|
|
*
|
|
* The test class is prefixed with 'LinkTitles' to avoid a naming collision
|
|
* with a class that exists in the MediaWiki core.
|
|
*
|
|
* (Ideally the test classes should be namespaced, but when you do that, they
|
|
* will no longer be automatically discovered.)
|
|
*
|
|
* @group bovender
|
|
* @group Database
|
|
*/
|
|
|
|
use MediaWiki\MediaWikiServices;
|
|
|
|
class LinkTitlesLinkerTest extends LinkTitles\TestCase {
|
|
protected $title;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp(); // call last to have the Targets object invalidated after inserting the page
|
|
}
|
|
|
|
public function addDBData() {
|
|
$this->title = $this->insertPage( 'source page', 'This page is the test page' )['title'];
|
|
$this->insertPage( 'link target', 'This page serves as a link target' );
|
|
parent::addDBDataOnce(); // call parent after adding page to have targets invalidated
|
|
}
|
|
|
|
/**
|
|
* @dataProvider provideTestTitleWithNumberData
|
|
*/
|
|
public function testTitleWithNumber( $input, $expectedOutput ) {
|
|
$config = new LinkTitles\Config();
|
|
$config->wordStartOnly = true;
|
|
$config->wordEndOnly = true;
|
|
$this->insertPage( 'numbered-1', 'This page serves as a link target with a numbered title' );
|
|
$this->insertPage( 'numbered-101', 'This page serves as a link target with a numbered title' );
|
|
parent::addDBDataOnce(); // call parent after adding page to have targets invalidated
|
|
$source = LinkTitles\Source::createFromTitleAndText( $this->title, $input, $config );
|
|
$linker = new LinkTitles\Linker( $config );
|
|
$result = $linker->linkContent( $source );
|
|
if ( !$result ) { $result = $input; }
|
|
$this->assertSame( $expectedOutput, $result );
|
|
}
|
|
|
|
public function provideTestTitleWithNumberData() {
|
|
return [
|
|
[
|
|
"Page text with numbered-1 in it.",
|
|
"Page text with [[numbered-1]] in it.",
|
|
],
|
|
[
|
|
"Page text with numbered-101 in it.",
|
|
"Page text with [[numbered-101]] in it.",
|
|
],
|
|
[
|
|
"Page text with numbered-1010 in it.",
|
|
"Page text with numbered-1010 in it.",
|
|
],
|
|
[
|
|
"Page text with link target1 in it.",
|
|
"Page text with link target1 in it.",
|
|
],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Test issue #39, https://github.com/bovender/LinkTitles/issues/39
|
|
*/
|
|
public function testNoautolinks() {
|
|
$config = new LinkTitles\Config();
|
|
$config->firstOnly = false;
|
|
LinkTitles\Splitter::invalidate();
|
|
$input = 'This is a text with <noautolinks><nowiki>link target</nowiki></noautolinks>';
|
|
$source = LinkTitles\Source::createFromTitleAndText( $this->title, $input, $config );
|
|
$linker = new LinkTitles\Linker( $config );
|
|
$result = $linker->linkContent( $source );
|
|
if ( !$result ) { $result = $input; }
|
|
$this->assertSame( $input, $result );
|
|
}
|
|
|
|
/**
|
|
* @dataProvider provideLinkContentTemplatesData
|
|
*/
|
|
public function testLinkContentTemplates( $skipTemplates, $input, $expectedOutput ) {
|
|
$config = new LinkTitles\Config();
|
|
$config->firstOnly = false;
|
|
$config->skipTemplates = $skipTemplates;
|
|
LinkTitles\Splitter::invalidate();
|
|
$source = LinkTitles\Source::createFromTitleAndText( $this->title, $input, $config );
|
|
$linker = new LinkTitles\Linker( $config );
|
|
$result = $linker->linkContent( $source );
|
|
if ( !$result ) { $result = $input; }
|
|
$this->assertSame( $expectedOutput, $result );
|
|
}
|
|
|
|
public function provideLinkContentTemplatesData() {
|
|
return [
|
|
[
|
|
true, // skipTemplates
|
|
'With skipTemplates = true, a {{template|with=link target}} in it should not be linked',
|
|
'With skipTemplates = true, a {{template|with=link target}} in it should not be linked',
|
|
],
|
|
[
|
|
false, // skipTemplates
|
|
'With skipTemplates = false, a {{template|with=link target}} in it should be linked',
|
|
'With skipTemplates = false, a {{template|with=[[link target]]}} in it should be linked',
|
|
],
|
|
[
|
|
false, // skipTemplates
|
|
'With skipTemplates = false, a {{template|with=already linked [[link target]]}} in it should not be linked again',
|
|
'With skipTemplates = false, a {{template|with=already linked [[link target]]}} in it should not be linked again',
|
|
]
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @dataProvider provideLinkContentSmartModeData
|
|
*/
|
|
public function testLinkContentSmartMode( $capitalLinks, $smartMode, $input, $expectedOutput ) {
|
|
$this->setMwGlobals( 'wgCapitalLinks', $capitalLinks );
|
|
$config = new LinkTitles\Config();
|
|
$config->firstOnly = false;
|
|
$config->smartMode = $smartMode;
|
|
$linker = new LinkTitles\Linker( $config );
|
|
$source = LinkTitles\Source::createFromTitleAndText( $this->title, $input, $config );
|
|
$result = $linker->linkContent( $source );
|
|
if ( !$result ) { $result = $input; }
|
|
$this->assertSame( $expectedOutput, $result );
|
|
}
|
|
|
|
public function provideLinkContentSmartModeData() {
|
|
return [
|
|
[
|
|
true, // wgCapitalLinks
|
|
true, // smartMode
|
|
'With smart mode on and $wgCapitalLinks = true, this page should link to link target',
|
|
'With smart mode on and $wgCapitalLinks = true, this page should link to [[link target]]'
|
|
],
|
|
[
|
|
true, // wgCapitalLinks
|
|
false, // smartMode
|
|
'With smart mode off and $wgCapitalLinks = true, this page should link to link target',
|
|
'With smart mode off and $wgCapitalLinks = true, this page should link to [[link target]]'
|
|
],
|
|
[
|
|
true, // wgCapitalLinks
|
|
true, // smartMode
|
|
'With smart mode on and $wgCapitalLinks = true, this page should link to Link target',
|
|
'With smart mode on and $wgCapitalLinks = true, this page should link to [[Link target]]'
|
|
],
|
|
[
|
|
true, // wgCapitalLinks
|
|
false, // smartMode
|
|
'With smart mode off and $wgCapitalLinks = true, this page should not link to Link Target',
|
|
'With smart mode off and $wgCapitalLinks = true, this page should not link to Link Target'
|
|
],
|
|
[
|
|
false, // wgCapitalLinks
|
|
true, // smartMode
|
|
'With smart mode on and $wgCapitalLinks = false, this page should link to Link target',
|
|
'With smart mode on and $wgCapitalLinks = false, this page should link to [[Link target]]'
|
|
],
|
|
[
|
|
false, // wgCapitalLinks
|
|
true, // smartMode
|
|
'With smart mode on and $wgCapitalLinks = false, this page should link to link target',
|
|
'With smart mode on and $wgCapitalLinks = false, this page should link to [[Link target|link target]]'
|
|
],
|
|
[
|
|
false, // wgCapitalLinks
|
|
false, // smartMode
|
|
'With smart mode off and $wgCapitalLinks = false, this page should not link to link target',
|
|
'With smart mode off and $wgCapitalLinks = false, this page should not link to link target'
|
|
],
|
|
[
|
|
false, // wgCapitalLinks
|
|
false, // smartMode
|
|
'With smart mode off and $wgCapitalLinks = false, this page should not link to Link target',
|
|
'With smart mode off and $wgCapitalLinks = false, this page should not link to [[Link target]]'
|
|
],
|
|
[
|
|
false, // wgCapitalLinks
|
|
true, // smartMode
|
|
'With smart mode on and $wgCapitalLinks = false, this page should link to Link target',
|
|
'With smart mode on and $wgCapitalLinks = false, this page should link to [[Link target]]'
|
|
],
|
|
[
|
|
false, // wgCapitalLinks
|
|
false, // smartMode
|
|
'With smart mode off and $wgCapitalLinks = false, this page should not link to Link Target',
|
|
'With smart mode off and $wgCapitalLinks = false, this page should not link to Link Target'
|
|
],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @dataProvider provideLinkContentFirstOnlyData
|
|
*/
|
|
public function testLinkContentFirstOnly( $firstOnly, $input, $expectedOutput ) {
|
|
$config = new LinkTitles\Config();
|
|
$config->firstOnly = $firstOnly;
|
|
$linker = new LinkTitles\Linker( $config );
|
|
$source = LinkTitles\Source::createFromTitleAndText( $this->title, $input, $config );
|
|
$result = $linker->linkContent( $source );
|
|
if ( !$result ) { $result = $input; }
|
|
$this->assertSame( $expectedOutput, $result );
|
|
}
|
|
|
|
public function provideLinkContentFirstOnlyData() {
|
|
return [
|
|
[
|
|
false, // firstOnly
|
|
'With firstOnly = false, link target is a link target multiple times',
|
|
'With firstOnly = false, [[link target]] is a [[link target]] multiple times'
|
|
],
|
|
[
|
|
false, // firstOnly
|
|
'With firstOnly = false, [[link target]] is a link target multiple times',
|
|
'With firstOnly = false, [[link target]] is a [[link target]] multiple times'
|
|
],
|
|
[
|
|
true, // firstOnly
|
|
'With firstOnly = true, link target is a link target only once',
|
|
'With firstOnly = true, [[link target]] is a link target only once'
|
|
],
|
|
[
|
|
true, // firstOnly
|
|
'With firstOnly = true, [[link target]] is a link target only once',
|
|
'With firstOnly = true, [[link target]] is a link target only once'
|
|
],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @dataProvider provideLinkContentHeadingsData
|
|
*/
|
|
public function testLinkContentHeadings( $parseHeadings, $input, $expectedOutput ) {
|
|
$config = new LinkTitles\Config();
|
|
$config->parseHeadings = $parseHeadings;
|
|
LinkTitles\Splitter::invalidate();
|
|
$source = LinkTitles\Source::createFromTitleAndText( $this->title, $input, $config );
|
|
$linker = new LinkTitles\Linker( $config );
|
|
$result = $linker->linkContent( $source );
|
|
if ( !$result ) { $result = $input; }
|
|
$this->assertSame( $expectedOutput, $result );
|
|
}
|
|
|
|
public function provideLinkContentHeadingsData() {
|
|
return [
|
|
[
|
|
true, // parseHeadings
|
|
"With parseHeadings = true,\n== a heading with link target in it ==\n should be linked",
|
|
"With parseHeadings = true,\n== a heading with [[link target]] in it ==\n should be linked",
|
|
],
|
|
[
|
|
true, // parseHeadings
|
|
"With parseHeadings = true,\n== <span>a heading with link target in ity/span> ==\n should be linked",
|
|
"With parseHeadings = true,\n== <span>a heading with [[link target]] in ity/span> ==\n should be linked",
|
|
],
|
|
[
|
|
false, // parseHeadings
|
|
"With parseHeadings = false,\n== a heading with link target in it ==\n should not be linked",
|
|
"With parseHeadings = false,\n== a heading with link target in it ==\n should not be linked",
|
|
],
|
|
];
|
|
}
|
|
|
|
public function testLinkContentBlackList() {
|
|
$config = new LinkTitles\Config();
|
|
$config->blackList = [ 'Foo', 'Link target', 'Bar' ];
|
|
LinkTitles\Targets::invalidate();
|
|
$linker = new LinkTitles\Linker( $config );
|
|
$text = 'If the link target is blacklisted, it should not be linked';
|
|
$source = LinkTitles\Source::createFromTitleAndText( $this->title, $text, $config );
|
|
$result = $linker->linkContent( $source );
|
|
if ( !$result ) { $result = $text; }
|
|
$this->assertSame( $text, $result );
|
|
}
|
|
|
|
// Tests for namespace handling are commented out until I find a way to add
|
|
// a custom namespace during testing. (The assertTrue assertion below fails.)
|
|
|
|
/**
|
|
* @dataProvider provideLinkContentNamespacesData
|
|
*/
|
|
public function testLinkContentTargetNamespaces( $namespaces, $input, $expectedOutput ) {
|
|
$config = new LinkTitles\Config();
|
|
$config->targetNamespaces = $namespaces;
|
|
|
|
$ns = 4000;
|
|
$nsText = 'customnamespace';
|
|
$this->mergeMwGlobalArrayValue( 'wgExtraNamespaces', [ $ns => $nsText ] );
|
|
|
|
// Reset namespace caches.
|
|
// See https://stackoverflow.com/q/45974979/270712
|
|
$namespaceInfo = MediaWikiServices::getInstance()->getNamespaceInfo();
|
|
$namespaceInfo->getCanonicalNamespaces( true );
|
|
$wgContLang = \MediaWiki\MediaWikiServices::getInstance()->getContentLanguage();
|
|
$wgContLang->resetNamespaces();
|
|
$this->assertTrue( $namespaceInfo->exists( $ns ), "The namespace with id $ns should exist!" );
|
|
|
|
$this->insertPage( "in custom namespace", 'This is a page in a custom namespace', $ns );
|
|
LinkTitles\Targets::invalidate();
|
|
$linker = new LinkTitles\Linker( $config );
|
|
$source = LinkTitles\Source::createFromTitleAndText( $this->title, $input, $config );
|
|
$result = $linker->linkContent( $source );
|
|
if ( !$result ) { $result = $input; }
|
|
$this->assertSame( $expectedOutput, $result );
|
|
}
|
|
|
|
public function provideLinkContentNamespacesData() {
|
|
return [
|
|
[
|
|
[], // namespaces
|
|
'With targetNamespaces = [], page in custom namespace should not be linked',
|
|
'With targetNamespaces = [], page in custom namespace should not be linked'
|
|
],
|
|
[
|
|
[ 4000 ], // namespaces
|
|
'With targetNamespaces = [ 4000 ], page in custom namespace should be linked',
|
|
'With targetNamespaces = [ 4000 ], page [[customnamespace:In custom namespace|in custom namespace]] should be linked'
|
|
],
|
|
];
|
|
}
|
|
}
|