2 use MediaWiki\MediaWikiServices
;
8 class SearchEnginePrefixTest
extends MediaWikiLangTestCase
{
15 public function addDBDataOnce() {
16 if ( !$this->isWikitextNS( NS_MAIN
) ) {
17 // tests are skipped if NS_MAIN is not wikitext
21 $this->insertPage( 'Sandbox' );
22 $this->insertPage( 'Bar' );
23 $this->insertPage( 'Example' );
24 $this->insertPage( 'Example Bar' );
25 $this->insertPage( 'Example Foo' );
26 $this->insertPage( 'Example Foo/Bar' );
27 $this->insertPage( 'Example/Baz' );
28 $this->insertPage( 'Redirect test', '#REDIRECT [[Redirect Test]]' );
29 $this->insertPage( 'Redirect Test' );
30 $this->insertPage( 'Redirect Test Worse Result' );
31 $this->insertPage( 'Redirect test2', '#REDIRECT [[Redirect Test2]]' );
32 $this->insertPage( 'Redirect TEST2', '#REDIRECT [[Redirect Test2]]' );
33 $this->insertPage( 'Redirect Test2' );
34 $this->insertPage( 'Redirect Test2 Worse Result' );
36 $this->insertPage( 'Talk:Sandbox' );
37 $this->insertPage( 'Talk:Example' );
39 $this->insertPage( 'User:Example' );
42 protected function setUp() {
45 if ( !$this->isWikitextNS( NS_MAIN
) ) {
46 $this->markTestSkipped( 'Main namespace does not support wikitext.' );
49 // Avoid special pages from extensions interferring with the tests
50 $this->setMwGlobals( 'wgSpecialPages', [] );
51 $this->search
= MediaWikiServices
::getInstance()->newSearchEngine();
52 $this->search
->setNamespaces( [] );
55 protected function searchProvision( array $results = null ) {
56 if ( $results === null ) {
57 $this->setMwGlobals( 'wgHooks', [] );
59 $this->setMwGlobals( 'wgHooks', [
60 'PrefixSearchBackend' => [
61 function ( $namespaces, $search, $limit, &$srchres ) use ( $results ) {
70 public static function provideSearch() {
78 'Main namespace with title prefix',
85 // Third result when testing offset
91 'Talk namespace prefix',
99 'User namespace prefix',
106 'Special namespace prefix',
107 'query' => 'Special:',
109 'Special:ActiveUsers',
110 'Special:AllMessages',
111 'Special:AllMyFiles',
113 // Third result when testing offset
115 'Special:AllMyUploads',
119 'Special namespace with prefix',
120 'query' => 'Special:Un',
123 'Special:UncategorizedCategories',
124 'Special:UncategorizedFiles',
126 // Third result when testing offset
128 'Special:UncategorizedImages',
133 'query' => 'Special:EditWatchlist',
135 'Special:EditWatchlist',
139 'Special page subpages',
140 'query' => 'Special:EditWatchlist/',
142 'Special:EditWatchlist/clear',
143 'Special:EditWatchlist/raw',
147 'Special page subpages with prefix',
148 'query' => 'Special:EditWatchlist/cl',
150 'Special:EditWatchlist/clear',
157 * @dataProvider provideSearch
158 * @covers SearchEngine::defaultPrefixSearch
160 public function testSearch( array $case ) {
161 $this->search
->setLimitOffset( 3 );
162 $results = $this->search
->defaultPrefixSearch( $case['query'] );
163 $results = array_map( function( Title
$t ) {
164 return $t->getPrefixedText();
174 * @dataProvider provideSearch
175 * @covers SearchEngine::defaultPrefixSearch
177 public function testSearchWithOffset( array $case ) {
178 $this->search
->setLimitOffset( 3, 1 );
179 $results = $this->search
->defaultPrefixSearch( $case['query'] );
180 $results = array_map( function( Title
$t ) {
181 return $t->getPrefixedText();
184 // We don't expect the first result when offsetting
185 array_shift( $case['results'] );
186 // And sometimes we expect a different last result
187 $expected = isset( $case['offsetresult'] ) ?
188 array_merge( $case['results'], $case['offsetresult'] ) :
198 public static function provideSearchBackend() {
215 'Exact match not on top (bug 70958)',
229 'Exact match missing (bug 70958)',
243 'Exact match missing and not existing',
257 "Exact match shouldn't override already found match if " .
258 "exact is redirect and found isn't",
260 // Target of the exact match is low in the list
261 'Redirect Test Worse Result',
264 'query' => 'redirect test',
266 // Redirect target is pulled up and exact match isn't added
268 'Redirect Test Worse Result',
272 "Exact match shouldn't override already found match if " .
273 "both exact match and found match are redirect",
275 // Another redirect to the same target as the exact match
276 // is low in the list
277 'Redirect Test2 Worse Result',
280 'query' => 'redirect TEST2',
282 // Found redirect is pulled to the top and exact match isn't
285 'Redirect Test2 Worse Result',
289 "Exact match should override any already found matches that " .
290 "are redirects to it",
292 // Another redirect to the same target as the exact match
293 // is low in the list
294 'Redirect Test Worse Result',
297 'query' => 'Redirect Test',
299 // Found redirect is pulled to the top and exact match isn't
302 'Redirect Test Worse Result',
310 * @dataProvider provideSearchBackend
311 * @covers PrefixSearch::searchBackend
313 public function testSearchBackend( array $case ) {
314 $search = $stub = $this->getMockBuilder( 'SearchEngine' )
315 ->setMethods( [ 'completionSearchBackend' ] )->getMock();
317 $return = SearchSuggestionSet
::fromStrings( $case['provision'] );
319 $search->expects( $this->any() )
320 ->method( 'completionSearchBackend' )
321 ->will( $this->returnValue( $return ) );
323 $search->setLimitOffset( 3 );
324 $results = $search->completionSearch( $case['query'] );
326 $results = $results->map( function( SearchSuggestion
$s ) {
327 return $s->getText();