]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blobdiff - tests/phpunit/includes/search/SearchEnginePrefixTest.php
MediaWiki 1.30.2
[autoinstallsdev/mediawiki.git] / tests / phpunit / includes / search / SearchEnginePrefixTest.php
diff --git a/tests/phpunit/includes/search/SearchEnginePrefixTest.php b/tests/phpunit/includes/search/SearchEnginePrefixTest.php
new file mode 100644 (file)
index 0000000..4c5bab3
--- /dev/null
@@ -0,0 +1,362 @@
+<?php
+
+use MediaWiki\MediaWikiServices;
+use Wikimedia\TestingAccessWrapper;
+
+/**
+ * @group Search
+ * @group Database
+ */
+class SearchEnginePrefixTest extends MediaWikiLangTestCase {
+       private $originalHandlers;
+
+       /**
+        * @var SearchEngine
+        */
+       private $search;
+
+       public function addDBDataOnce() {
+               if ( !$this->isWikitextNS( NS_MAIN ) ) {
+                       // tests are skipped if NS_MAIN is not wikitext
+                       return;
+               }
+
+               $this->insertPage( 'Sandbox' );
+               $this->insertPage( 'Bar' );
+               $this->insertPage( 'Example' );
+               $this->insertPage( 'Example Bar' );
+               $this->insertPage( 'Example Foo' );
+               $this->insertPage( 'Example Foo/Bar' );
+               $this->insertPage( 'Example/Baz' );
+               $this->insertPage( 'Sample' );
+               $this->insertPage( 'Sample Ban' );
+               $this->insertPage( 'Sample Eat' );
+               $this->insertPage( 'Sample Who' );
+               $this->insertPage( 'Sample Zoo' );
+               $this->insertPage( 'Redirect test', '#REDIRECT [[Redirect Test]]' );
+               $this->insertPage( 'Redirect Test' );
+               $this->insertPage( 'Redirect Test Worse Result' );
+               $this->insertPage( 'Redirect test2', '#REDIRECT [[Redirect Test2]]' );
+               $this->insertPage( 'Redirect TEST2', '#REDIRECT [[Redirect Test2]]' );
+               $this->insertPage( 'Redirect Test2' );
+               $this->insertPage( 'Redirect Test2 Worse Result' );
+
+               $this->insertPage( 'Talk:Sandbox' );
+               $this->insertPage( 'Talk:Example' );
+
+               $this->insertPage( 'User:Example' );
+       }
+
+       protected function setUp() {
+               parent::setUp();
+
+               if ( !$this->isWikitextNS( NS_MAIN ) ) {
+                       $this->markTestSkipped( 'Main namespace does not support wikitext.' );
+               }
+
+               // Avoid special pages from extensions interferring with the tests
+               $this->setMwGlobals( [
+                       'wgSpecialPages' => [],
+                       'wgHooks' => [],
+               ] );
+
+               $this->search = MediaWikiServices::getInstance()->newSearchEngine();
+               $this->search->setNamespaces( [] );
+
+               $this->originalHandlers = TestingAccessWrapper::newFromClass( 'Hooks' )->handlers;
+               TestingAccessWrapper::newFromClass( 'Hooks' )->handlers = [];
+
+               SpecialPageFactory::resetList();
+       }
+
+       public function tearDown() {
+               parent::tearDown();
+
+               TestingAccessWrapper::newFromClass( 'Hooks' )->handlers = $this->originalHandlers;
+
+               SpecialPageFactory::resetList();
+       }
+
+       protected function searchProvision( array $results = null ) {
+               if ( $results === null ) {
+                       $this->setMwGlobals( 'wgHooks', [] );
+               } else {
+                       $this->setMwGlobals( 'wgHooks', [
+                               'PrefixSearchBackend' => [
+                                       function ( $namespaces, $search, $limit, &$srchres ) use ( $results ) {
+                                               $srchres = $results;
+                                               return false;
+                                       }
+                               ],
+                       ] );
+               }
+       }
+
+       public static function provideSearch() {
+               return [
+                       [ [
+                               'Empty string',
+                               'query' => '',
+                               'results' => [],
+                       ] ],
+                       [ [
+                               'Main namespace with title prefix',
+                               'query' => 'Sa',
+                               'results' => [
+                                       'Sample',
+                                       'Sample Ban',
+                                       'Sample Eat',
+                               ],
+                               // Third result when testing offset
+                               'offsetresult' => [
+                                       'Sample Who',
+                               ],
+                       ] ],
+                       [ [
+                               'Talk namespace prefix',
+                               'query' => 'Talk:',
+                               'results' => [
+                                       'Talk:Example',
+                                       'Talk:Sandbox',
+                               ],
+                       ] ],
+                       [ [
+                               'User namespace prefix',
+                               'query' => 'User:',
+                               'results' => [
+                                       'User:Example',
+                               ],
+                       ] ],
+                       [ [
+                               'Special namespace prefix',
+                               'query' => 'Special:',
+                               'results' => [
+                                       'Special:ActiveUsers',
+                                       'Special:AllMessages',
+                                       'Special:AllMyUploads',
+                               ],
+                               // Third result when testing offset
+                               'offsetresult' => [
+                                       'Special:AllPages',
+                               ],
+                       ] ],
+                       [ [
+                               'Special namespace with prefix',
+                               'query' => 'Special:Un',
+                               'results' => [
+                                       'Special:Unblock',
+                                       'Special:UncategorizedCategories',
+                                       'Special:UncategorizedFiles',
+                               ],
+                               // Third result when testing offset
+                               'offsetresult' => [
+                                       'Special:UncategorizedPages',
+                               ],
+                       ] ],
+                       [ [
+                               'Special page name',
+                               'query' => 'Special:EditWatchlist',
+                               'results' => [
+                                       'Special:EditWatchlist',
+                               ],
+                       ] ],
+                       [ [
+                               'Special page subpages',
+                               'query' => 'Special:EditWatchlist/',
+                               'results' => [
+                                       'Special:EditWatchlist/clear',
+                                       'Special:EditWatchlist/raw',
+                               ],
+                       ] ],
+                       [ [
+                               'Special page subpages with prefix',
+                               'query' => 'Special:EditWatchlist/cl',
+                               'results' => [
+                                       'Special:EditWatchlist/clear',
+                               ],
+                       ] ],
+               ];
+       }
+
+       /**
+        * @dataProvider provideSearch
+        * @covers SearchEngine::defaultPrefixSearch
+        */
+       public function testSearch( array $case ) {
+               $this->search->setLimitOffset( 3 );
+               $results = $this->search->defaultPrefixSearch( $case['query'] );
+               $results = array_map( function ( Title $t ) {
+                       return $t->getPrefixedText();
+               }, $results );
+
+               $this->assertEquals(
+                       $case['results'],
+                       $results,
+                       $case[0]
+               );
+       }
+
+       /**
+        * @dataProvider provideSearch
+        * @covers SearchEngine::defaultPrefixSearch
+        */
+       public function testSearchWithOffset( array $case ) {
+               $this->search->setLimitOffset( 3, 1 );
+               $results = $this->search->defaultPrefixSearch( $case['query'] );
+               $results = array_map( function ( Title $t ) {
+                       return $t->getPrefixedText();
+               }, $results );
+
+               // We don't expect the first result when offsetting
+               array_shift( $case['results'] );
+               // And sometimes we expect a different last result
+               $expected = isset( $case['offsetresult'] ) ?
+                       array_merge( $case['results'], $case['offsetresult'] ) :
+                       $case['results'];
+
+               $this->assertEquals(
+                       $expected,
+                       $results,
+                       $case[0]
+               );
+       }
+
+       public static function provideSearchBackend() {
+               return [
+                       [ [
+                               'Simple case',
+                               'provision' => [
+                                       'Bar',
+                                       'Barcelona',
+                                       'Barbara',
+                               ],
+                               'query' => 'Bar',
+                               'results' => [
+                                       'Bar',
+                                       'Barcelona',
+                                       'Barbara',
+                               ],
+                       ] ],
+                       [ [
+                               'Exact match not on top (T72958)',
+                               'provision' => [
+                                       'Barcelona',
+                                       'Bar',
+                                       'Barbara',
+                               ],
+                               'query' => 'Bar',
+                               'results' => [
+                                       'Bar',
+                                       'Barcelona',
+                                       'Barbara',
+                               ],
+                       ] ],
+                       [ [
+                               'Exact match missing (T72958)',
+                               'provision' => [
+                                       'Barcelona',
+                                       'Barbara',
+                                       'Bart',
+                               ],
+                               'query' => 'Bar',
+                               'results' => [
+                                       'Bar',
+                                       'Barcelona',
+                                       'Barbara',
+                               ],
+                       ] ],
+                       [ [
+                               'Exact match missing and not existing',
+                               'provision' => [
+                                       'Exile',
+                                       'Exist',
+                                       'External',
+                               ],
+                               'query' => 'Ex',
+                               'results' => [
+                                       'Exile',
+                                       'Exist',
+                                       'External',
+                               ],
+                       ] ],
+                       [ [
+                               "Exact match shouldn't override already found match if " .
+                                       "exact is redirect and found isn't",
+                               'provision' => [
+                                       // Target of the exact match is low in the list
+                                       'Redirect Test Worse Result',
+                                       'Redirect Test',
+                               ],
+                               'query' => 'redirect test',
+                               'results' => [
+                                       // Redirect target is pulled up and exact match isn't added
+                                       'Redirect Test',
+                                       'Redirect Test Worse Result',
+                               ],
+                       ] ],
+                       [ [
+                               "Exact match shouldn't override already found match if " .
+                                       "both exact match and found match are redirect",
+                               'provision' => [
+                                       // Another redirect to the same target as the exact match
+                                       // is low in the list
+                                       'Redirect Test2 Worse Result',
+                                       'Redirect test2',
+                               ],
+                               'query' => 'redirect TEST2',
+                               'results' => [
+                                       // Found redirect is pulled to the top and exact match isn't
+                                       // added
+                                       'Redirect test2',
+                                       'Redirect Test2 Worse Result',
+                               ],
+                       ] ],
+                       [ [
+                               "Exact match should override any already found matches that " .
+                                       "are redirects to it",
+                               'provision' => [
+                                       // Another redirect to the same target as the exact match
+                                       // is low in the list
+                                       'Redirect Test Worse Result',
+                                       'Redirect test',
+                               ],
+                               'query' => 'Redirect Test',
+                               'results' => [
+                                       // Found redirect is pulled to the top and exact match isn't
+                                       // added
+                                       'Redirect Test',
+                                       'Redirect Test Worse Result',
+                                       'Redirect test',
+                               ],
+                       ] ],
+               ];
+       }
+
+       /**
+        * @dataProvider provideSearchBackend
+        * @covers PrefixSearch::searchBackend
+        */
+       public function testSearchBackend( array $case ) {
+               $search = $stub = $this->getMockBuilder( 'SearchEngine' )
+                       ->setMethods( [ 'completionSearchBackend' ] )->getMock();
+
+               $return = SearchSuggestionSet::fromStrings( $case['provision'] );
+
+               $search->expects( $this->any() )
+                       ->method( 'completionSearchBackend' )
+                       ->will( $this->returnValue( $return ) );
+
+               $search->setLimitOffset( 3 );
+               $results = $search->completionSearch( $case['query'] );
+
+               $results = $results->map( function ( SearchSuggestion $s ) {
+                       return $s->getText();
+               } );
+
+               $this->assertEquals(
+                       $case['results'],
+                       $results,
+                       $case[0]
+               );
+       }
+}