Localisation updates from https://translatewiki.net.
[mediawiki.git] / tests / phpunit / includes / search / PrefixSearchTest.php
blob0673c26d61e4b4cec411a9d7b598dea4982bad8f
1 <?php
3 use MediaWiki\MainConfigNames;
4 use MediaWiki\Title\Title;
6 /**
7 * @group Search
8 * @group Database
9 * @covers \PrefixSearch
11 class PrefixSearchTest extends MediaWikiLangTestCase {
12 private const NS_NONCAP = 12346;
14 public function addDBDataOnce() {
15 if ( !$this->isWikitextNS( NS_MAIN ) ) {
16 // tests are skipped if NS_MAIN is not wikitext
17 return;
20 $this->insertPage( 'Sandbox' );
21 $this->insertPage( 'Bar' );
22 $this->insertPage( 'Example' );
23 $this->insertPage( 'Example Bar' );
24 $this->insertPage( 'Example Foo' );
25 $this->insertPage( 'Example Foo/Bar' );
26 $this->insertPage( 'Example/Baz' );
27 $this->insertPage( 'Redirect test', '#REDIRECT [[Redirect Test]]' );
28 $this->insertPage( 'Redirect Test' );
29 $this->insertPage( 'Redirect Test Worse Result' );
30 $this->insertPage( 'Redirect test2', '#REDIRECT [[Redirect Test2]]' );
31 $this->insertPage( 'Redirect TEST2', '#REDIRECT [[Redirect Test2]]' );
32 $this->insertPage( 'Redirect Test2' );
33 $this->insertPage( 'Redirect Test2 Worse Result' );
35 $this->insertPage( 'Talk:Sandbox' );
36 $this->insertPage( 'Talk:Example' );
38 $this->insertPage( 'User:Example' );
40 $this->overrideConfigValues( [
41 MainConfigNames::ExtraNamespaces => [ self::NS_NONCAP => 'NonCap' ],
42 MainConfigNames::CapitalLinkOverrides => [ self::NS_NONCAP => false ],
43 ] );
45 $this->insertPage( Title::makeTitle( self::NS_NONCAP, 'Bar' ) );
46 $this->insertPage( Title::makeTitle( self::NS_NONCAP, 'Upper' ) );
47 $this->insertPage( Title::makeTitle( self::NS_NONCAP, 'sandbox' ) );
50 protected function setUp(): void {
51 parent::setUp();
53 if ( !$this->isWikitextNS( NS_MAIN ) ) {
54 $this->markTestSkipped( 'Main namespace does not support wikitext.' );
57 // Avoid special pages from extensions interfering with the tests
58 $this->overrideConfigValues( [
59 MainConfigNames::SpecialPages => [],
60 MainConfigNames::Hooks => [],
61 MainConfigNames::ExtraNamespaces => [ self::NS_NONCAP => 'NonCap' ],
62 MainConfigNames::CapitalLinkOverrides => [ self::NS_NONCAP => false ],
63 ] );
66 protected function searchProvision( ?array $results = null ) {
67 if ( $results === null ) {
68 $this->overrideConfigValue( MainConfigNames::Hooks, [] );
69 } else {
70 $this->setTemporaryHook(
71 'PrefixSearchBackend',
72 static function ( $namespaces, $search, $limit, &$srchres ) use ( $results ) {
73 $srchres = $results;
74 return false;
80 public static function provideSearch() {
81 return [
82 [ [
83 'Empty string',
84 'query' => '',
85 'results' => [],
86 ] ],
87 [ [
88 'Main namespace with title prefix',
89 'query' => 'Ex',
90 'results' => [
91 'Example',
92 'Example/Baz',
93 'Example Bar',
95 // Third result when testing offset
96 'offsetresult' => [
97 'Example Foo',
99 ] ],
101 'Talk namespace prefix',
102 'query' => 'Talk:',
103 'results' => [
104 'Talk:Example',
105 'Talk:Sandbox',
107 ] ],
109 'User namespace prefix',
110 'query' => 'User:',
111 'results' => [
112 'User:Example',
114 ] ],
116 'Special namespace prefix',
117 'query' => 'Special:',
118 'results' => [
119 'Special:ActiveUsers',
120 'Special:AllMessages',
121 'Special:AllPages',
123 // Third result when testing offset
124 'offsetresult' => [
125 'Special:AncientPages',
127 ] ],
129 'Special namespace with prefix',
130 'query' => 'Special:Un',
131 'results' => [
132 'Special:Unblock',
133 'Special:UncategorizedCategories',
134 'Special:UncategorizedFiles',
136 // Third result when testing offset
137 'offsetresult' => [
138 'Special:UncategorizedPages',
140 ] ],
142 'Special page name',
143 'query' => 'Special:EditWatchlist',
144 'results' => [],
145 ] ],
147 'Special page subpages',
148 'query' => 'Special:EditWatchlist/',
149 'results' => [
150 'Special:EditWatchlist/clear',
151 'Special:EditWatchlist/raw',
153 ] ],
155 'Special page subpages with prefix',
156 'query' => 'Special:EditWatchlist/cl',
157 'results' => [
158 'Special:EditWatchlist/clear',
160 ] ],
162 'Namespace with case sensitive first letter',
163 'query' => 'NonCap:upper',
164 'results' => []
165 ] ],
167 'Multinamespace search',
168 'query' => 'B',
169 'results' => [
170 'Bar',
171 'NonCap:Bar',
173 'namespaces' => [ NS_MAIN, self::NS_NONCAP ],
174 ] ],
176 'Multinamespace search with lowercase first letter',
177 'query' => 'sand',
178 'results' => [
179 'Sandbox',
180 'NonCap:sandbox',
182 'namespaces' => [ NS_MAIN, self::NS_NONCAP ],
183 ] ],
188 * @dataProvider provideSearch
189 * @covers \PrefixSearch::search
190 * @covers \PrefixSearch::searchBackend
192 public function testSearch( array $case ) {
193 $this->searchProvision( null );
195 $namespaces = $case['namespaces'] ?? [];
197 $searcher = new StringPrefixSearch;
198 $results = $searcher->search( $case['query'], 3, $namespaces );
199 $this->assertEquals(
200 $case['results'],
201 $results,
202 $case[0]
207 * @dataProvider provideSearch
208 * @covers \PrefixSearch::search
209 * @covers \PrefixSearch::searchBackend
211 public function testSearchWithOffset( array $case ) {
212 $this->searchProvision( null );
214 $namespaces = $case['namespaces'] ?? [];
216 $searcher = new StringPrefixSearch;
217 $results = $searcher->search( $case['query'], 3, $namespaces, 1 );
219 // We don't expect the first result when offsetting
220 array_shift( $case['results'] );
221 // And sometimes we expect a different last result
222 $expected = isset( $case['offsetresult'] ) ?
223 array_merge( $case['results'], $case['offsetresult'] ) :
224 $case['results'];
226 $this->assertEquals(
227 $expected,
228 $results,
229 $case[0]
233 public static function provideSearchBackend() {
234 return [
236 'Simple case',
237 'provision' => [
238 'Bar',
239 'Barcelona',
240 'Barbara',
242 'query' => 'Bar',
243 'results' => [
244 'Bar',
245 'Barcelona',
246 'Barbara',
248 ] ],
250 'Exact match not on top (T72958)',
251 'provision' => [
252 'Barcelona',
253 'Bar',
254 'Barbara',
256 'query' => 'Bar',
257 'results' => [
258 'Bar',
259 'Barcelona',
260 'Barbara',
262 ] ],
264 'Exact match missing (T72958)',
265 'provision' => [
266 'Barcelona',
267 'Barbara',
268 'Bart',
270 'query' => 'Bar',
271 'results' => [
272 'Bar',
273 'Barcelona',
274 'Barbara',
276 ] ],
278 'Exact match missing and not existing',
279 'provision' => [
280 'Exile',
281 'Exist',
282 'External',
284 'query' => 'Ex',
285 'results' => [
286 'Exile',
287 'Exist',
288 'External',
290 ] ],
292 "Exact match shouldn't override already found match if " .
293 "exact is redirect and found isn't",
294 'provision' => [
295 // Target of the exact match is low in the list
296 'Redirect Test Worse Result',
297 'Redirect Test',
299 'query' => 'redirect test',
300 'results' => [
301 // Redirect target is pulled up and exact match isn't added
302 'Redirect Test',
303 'Redirect Test Worse Result',
305 ] ],
307 "Exact match should override already found match if " .
308 "both exact match and found match are redirect",
309 'provision' => [
310 // Another redirect to the same target as the exact match
311 // is low in the list
312 'Redirect Test2 Worse Result',
313 'Redirect test2',
315 'query' => 'redirect TEST2',
316 'results' => [
317 // Found redirect is pulled to the top and exact match isn't
318 // added
319 'Redirect TEST2',
320 'Redirect Test2 Worse Result',
322 ] ],
324 "Exact match should override any already found matches that " .
325 "are redirects to it",
326 'provision' => [
327 // Another redirect to the same target as the exact match
328 // is low in the list
329 'Redirect Test Worse Result',
330 'Redirect test',
332 'query' => 'Redirect Test',
333 'results' => [
334 // Found redirect is pulled to the top and exact match isn't
335 // added
336 'Redirect Test',
337 'Redirect Test Worse Result',
339 ] ],
344 * @dataProvider provideSearchBackend
345 * @covers \PrefixSearch::searchBackend
347 public function testSearchBackend( array $case ) {
348 $this->filterDeprecated( '/Use of PrefixSearchBackend hook/' );
349 $this->searchProvision( $case['provision'] );
350 $searcher = new StringPrefixSearch;
351 $results = $searcher->search( $case['query'], 3 );
352 $this->assertEquals(
353 $case['results'],
354 $results,
355 $case[0]