1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
<?php
namespace MediaWiki\Tests\Api\Query;
use ISearchResultSet;
use MediaWiki\MainConfigNames;
use MediaWiki\Revision\RevisionLookup;
use MediaWiki\Tests\Api\ApiTestCase;
use MediaWiki\Title\Title;
use MockSearchEngine;
use MockSearchResult;
use MockSearchResultSet;
/**
* @group medium
* @covers MediaWiki\Api\ApiQuerySearch
*/
class ApiQuerySearchTest extends ApiTestCase {
protected function setUp(): void {
parent::setUp();
MockSearchEngine::clearMockResults();
$this->registerMockSearchEngine();
$this->setService( 'RevisionLookup', $this->createMock( RevisionLookup::class ) );
}
private function registerMockSearchEngine() {
$this->overrideConfigValue( MainConfigNames::SearchType, MockSearchEngine::class );
}
public function provideSearchResults() {
return [
'empty search result' => [ [], [] ],
'has search results' => [
[ 'Zomg' ],
[ $this->mockResultClosure( 'Zomg' ) ],
],
'filters broken search results' => [
[ 'A', 'B' ],
[
$this->mockResultClosure( 'a' ),
$this->mockResultClosure( 'Zomg', [ 'setBrokenTitle' => true ] ),
$this->mockResultClosure( 'b' ),
],
],
'filters results with missing revision' => [
[ 'B', 'A' ],
[
$this->mockResultClosure( 'Zomg', [ 'setMissingRevision' => true ] ),
$this->mockResultClosure( 'b' ),
$this->mockResultClosure( 'a' ),
],
],
];
}
/**
* @dataProvider provideSearchResults
*/
public function testSearchResults( $expect, $hits, array $params = [] ) {
MockSearchEngine::addMockResults( 'my query', $hits );
[ $response, $request ] = $this->doApiRequest( $params + [
'action' => 'query',
'list' => 'search',
'srsearch' => 'my query',
] );
$titles = array_column( $response['query']['search'], 'title' );
$this->assertEquals( $expect, $titles );
}
public function provideInterwikiResults() {
return [
'empty' => [ [], [] ],
'one wiki response' => [
[ 'utwiki' => [ 'Qwerty' ] ],
[
ISearchResultSet::SECONDARY_RESULTS => [
'utwiki' => new MockSearchResultSet( [
$this->mockResultClosure(
'Qwerty',
[ 'setInterwikiPrefix' => 'utwiki' ]
),
] ),
],
]
],
];
}
/**
* @dataProvider provideInterwikiResults
*/
public function testInterwikiResults( $expect, $hits, array $params = [] ) {
MockSearchEngine::setMockInterwikiResults( $hits );
[ $response, $request ] = $this->doApiRequest( $params + [
'action' => 'query',
'list' => 'search',
'srsearch' => 'my query',
'srinterwiki' => true,
] );
if ( !$expect ) {
$this->assertArrayNotHasKey( 'interwikisearch', $response['query'] );
return;
}
$results = [];
$this->assertArrayHasKey( 'interwikisearchinfo', $response['query'] );
foreach ( $response['query']['interwikisearch'] as $wiki => $wikiResults ) {
$results[$wiki] = [];
foreach ( $wikiResults as $wikiResult ) {
$results[$wiki][] = $wikiResult['title'];
}
}
$this->assertEquals( $expect, $results );
}
/**
* Returns a closure that evaluates to a MockSearchResult, to be resolved by
* MockSearchEngine::addMockResults() or MockresultSet::extractResults().
*
* This is needed because MockSearchResults cannot be instantiated in a data provider,
* since they load revisions. This would hit the "real" database instead of the mock
* database, which in turn may cause cache pollution and other inconsistencies, see T202641.
*
* @param string $titleText
* @param array $setters
* @return callable function(): MockSearchResult
*/
private function mockResultClosure( $titleText, $setters = [] ) {
return static function () use ( $titleText, $setters ) {
$title = Title::newFromText( $titleText );
$title->resetArticleID( 0 );
$result = new MockSearchResult( $title );
foreach ( $setters as $method => $param ) {
$result->$method( $param );
}
return $result;
};
}
}
|