]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blob - tests/phpunit/includes/specialpage/ChangesListSpecialPageTest.php
MediaWiki 1.30.2
[autoinstallsdev/mediawiki.git] / tests / phpunit / includes / specialpage / ChangesListSpecialPageTest.php
1 <?php
2
3 use Wikimedia\TestingAccessWrapper;
4
5 /**
6  * Test class for ChangesListSpecialPage class
7  *
8  * Copyright © 2011-, Antoine Musso, Stephane Bisson, Matthew Flaschen
9  *
10  * @author Antoine Musso
11  * @author Stephane Bisson
12  * @author Matthew Flaschen
13  * @group Database
14  *
15  * @covers ChangesListSpecialPage
16  */
17 class ChangesListSpecialPageTest extends AbstractChangesListSpecialPageTestCase {
18         protected function getPage() {
19                 $mock = $this->getMockBuilder( ChangesListSpecialPage::class )
20                         ->setConstructorArgs(
21                                 [
22                                         'ChangesListSpecialPage',
23                                         ''
24                                 ]
25                         )
26                         ->setMethods( [ 'getPageTitle' ] )
27                         ->getMockForAbstractClass();
28
29                 $mock->method( 'getPageTitle' )->willReturn(
30                         Title::makeTitle( NS_SPECIAL, 'ChangesListSpecialPage' )
31                 );
32
33                 $mock = TestingAccessWrapper::newFromObject(
34                         $mock
35                 );
36
37                 return $mock;
38         }
39
40         private function buildQuery(
41                 $requestOptions = null,
42                 $user = null
43         ) {
44                 $context = new RequestContext;
45                 $context->setRequest( new FauxRequest( $requestOptions ) );
46                 if ( $user ) {
47                         $context->setUser( $user );
48                 }
49
50                 $this->changesListSpecialPage->setContext( $context );
51                 $this->changesListSpecialPage->filterGroups = [];
52                 $formOptions = $this->changesListSpecialPage->setup( null );
53
54                 #  Filter out rc_timestamp conditions which depends on the test runtime
55                 # This condition is not needed as of march 2, 2011 -- hashar
56                 # @todo FIXME: Find a way to generate the correct rc_timestamp
57
58                 $tables = [];
59                 $fields = [];
60                 $queryConditions = [];
61                 $query_options = [];
62                 $join_conds = [];
63
64                 call_user_func_array(
65                         [ $this->changesListSpecialPage, 'buildQuery' ],
66                         [
67                                 &$tables,
68                                 &$fields,
69                                 &$queryConditions,
70                                 &$query_options,
71                                 &$join_conds,
72                                 $formOptions
73                         ]
74                 );
75
76                 $queryConditions = array_filter(
77                         $queryConditions,
78                         'ChangesListSpecialPageTest::filterOutRcTimestampCondition'
79                 );
80
81                 return $queryConditions;
82         }
83
84         /** helper to test SpecialRecentchanges::buildQuery() */
85         private function assertConditions(
86                 $expected,
87                 $requestOptions = null,
88                 $message = '',
89                 $user = null
90         ) {
91                 $queryConditions = $this->buildQuery( $requestOptions, $user );
92
93                 $this->assertEquals(
94                         self::normalizeCondition( $expected ),
95                         self::normalizeCondition( $queryConditions ),
96                         $message
97                 );
98         }
99
100         private static function normalizeCondition( $conds ) {
101                 $normalized = array_map(
102                         function ( $k, $v ) {
103                                 return is_numeric( $k ) ? $v : "$k = $v";
104                         },
105                         array_keys( $conds ),
106                         $conds
107                 );
108                 sort( $normalized );
109                 return $normalized;
110         }
111
112         /** return false if condition begin with 'rc_timestamp ' */
113         private static function filterOutRcTimestampCondition( $var ) {
114                 return ( false === strpos( $var, 'rc_timestamp ' ) );
115         }
116
117         public function testRcNsFilter() {
118                 $this->assertConditions(
119                         [ # expected
120                                 "rc_namespace = '0'",
121                         ],
122                         [
123                                 'namespace' => NS_MAIN,
124                         ],
125                         "rc conditions with one namespace"
126                 );
127         }
128
129         public function testRcNsFilterInversion() {
130                 $this->assertConditions(
131                         [ # expected
132                                 "rc_namespace != '0'",
133                         ],
134                         [
135                                 'namespace' => NS_MAIN,
136                                 'invert' => 1,
137                         ],
138                         "rc conditions with namespace inverted"
139                 );
140         }
141
142         public function testRcNsFilterMultiple() {
143                 $this->assertConditions(
144                         [ # expected
145                                 "rc_namespace IN ('1','2','3')",
146                         ],
147                         [
148                                 'namespace' => '1;2;3',
149                         ],
150                         "rc conditions with multiple namespaces"
151                 );
152         }
153
154         public function testRcNsFilterMultipleAssociated() {
155                 $this->assertConditions(
156                         [ # expected
157                                 "rc_namespace IN ('0','1','4','5','6','7')",
158                         ],
159                         [
160                                 'namespace' => '1;4;7',
161                                 'associated' => 1,
162                         ],
163                         "rc conditions with multiple namespaces and associated"
164                 );
165         }
166
167         public function testRcNsFilterMultipleAssociatedInvert() {
168                 $this->assertConditions(
169                         [ # expected
170                                 "rc_namespace NOT IN ('2','3','8','9')",
171                         ],
172                         [
173                                 'namespace' => '2;3;9',
174                                 'associated' => 1,
175                                 'invert' => 1
176                         ],
177                         "rc conditions with multiple namespaces, associated and inverted"
178                 );
179         }
180
181         public function testRcNsFilterMultipleInvert() {
182                 $this->assertConditions(
183                         [ # expected
184                                 "rc_namespace NOT IN ('1','2','3')",
185                         ],
186                         [
187                                 'namespace' => '1;2;3',
188                                 'invert' => 1,
189                         ],
190                         "rc conditions with multiple namespaces inverted"
191                 );
192         }
193
194         public function testRcHidemyselfFilter() {
195                 $user = $this->getTestUser()->getUser();
196                 $this->assertConditions(
197                         [ # expected
198                                 "rc_user_text != '{$user->getName()}'",
199                         ],
200                         [
201                                 'hidemyself' => 1,
202                         ],
203                         "rc conditions: hidemyself=1 (logged in)",
204                         $user
205                 );
206
207                 $user = User::newFromName( '10.11.12.13', false );
208                 $this->assertConditions(
209                         [ # expected
210                                 "rc_user_text != '10.11.12.13'",
211                         ],
212                         [
213                                 'hidemyself' => 1,
214                         ],
215                         "rc conditions: hidemyself=1 (anon)",
216                         $user
217                 );
218         }
219
220         public function testRcHidebyothersFilter() {
221                 $user = $this->getTestUser()->getUser();
222                 $this->assertConditions(
223                         [ # expected
224                                 "rc_user_text = '{$user->getName()}'",
225                         ],
226                         [
227                                 'hidebyothers' => 1,
228                         ],
229                         "rc conditions: hidebyothers=1 (logged in)",
230                         $user
231                 );
232
233                 $user = User::newFromName( '10.11.12.13', false );
234                 $this->assertConditions(
235                         [ # expected
236                                 "rc_user_text = '10.11.12.13'",
237                         ],
238                         [
239                                 'hidebyothers' => 1,
240                         ],
241                         "rc conditions: hidebyothers=1 (anon)",
242                         $user
243                 );
244         }
245
246         public function testRcHidepageedits() {
247                 $this->assertConditions(
248                         [ # expected
249                                 "rc_type != '0'",
250                         ],
251                         [
252                                 'hidepageedits' => 1,
253                         ],
254                         "rc conditions: hidepageedits=1"
255                 );
256         }
257
258         public function testRcHidenewpages() {
259                 $this->assertConditions(
260                         [ # expected
261                                 "rc_type != '1'",
262                         ],
263                         [
264                                 'hidenewpages' => 1,
265                         ],
266                         "rc conditions: hidenewpages=1"
267                 );
268         }
269
270         public function testRcHidelog() {
271                 $this->assertConditions(
272                         [ # expected
273                                 "rc_type != '3'",
274                         ],
275                         [
276                                 'hidelog' => 1,
277                         ],
278                         "rc conditions: hidelog=1"
279                 );
280         }
281
282         public function testRcHidehumans() {
283                 $this->assertConditions(
284                         [ # expected
285                                 'rc_bot' => 1,
286                         ],
287                         [
288                                 'hidebots' => 0,
289                                 'hidehumans' => 1,
290                         ],
291                         "rc conditions: hidebots=0 hidehumans=1"
292                 );
293         }
294
295         public function testRcHidepatrolledDisabledFilter() {
296                 $user = $this->getTestUser()->getUser();
297                 $this->assertConditions(
298                         [ # expected
299                         ],
300                         [
301                                 'hidepatrolled' => 1,
302                         ],
303                         "rc conditions: hidepatrolled=1 (user not allowed)",
304                         $user
305                 );
306         }
307
308         public function testRcHideunpatrolledDisabledFilter() {
309                 $user = $this->getTestUser()->getUser();
310                 $this->assertConditions(
311                         [ # expected
312                         ],
313                         [
314                                 'hideunpatrolled' => 1,
315                         ],
316                         "rc conditions: hideunpatrolled=1 (user not allowed)",
317                         $user
318                 );
319         }
320         public function testRcHidepatrolledFilter() {
321                 $user = $this->getTestSysop()->getUser();
322                 $this->assertConditions(
323                         [ # expected
324                                 "rc_patrolled = 0",
325                         ],
326                         [
327                                 'hidepatrolled' => 1,
328                         ],
329                         "rc conditions: hidepatrolled=1",
330                         $user
331                 );
332         }
333
334         public function testRcHideunpatrolledFilter() {
335                 $user = $this->getTestSysop()->getUser();
336                 $this->assertConditions(
337                         [ # expected
338                                 "rc_patrolled = 1",
339                         ],
340                         [
341                                 'hideunpatrolled' => 1,
342                         ],
343                         "rc conditions: hideunpatrolled=1",
344                         $user
345                 );
346         }
347
348         public function testRcHideminorFilter() {
349                 $this->assertConditions(
350                         [ # expected
351                                 "rc_minor = 0",
352                         ],
353                         [
354                                 'hideminor' => 1,
355                         ],
356                         "rc conditions: hideminor=1"
357                 );
358         }
359
360         public function testRcHidemajorFilter() {
361                 $this->assertConditions(
362                         [ # expected
363                                 "rc_minor = 1",
364                         ],
365                         [
366                                 'hidemajor' => 1,
367                         ],
368                         "rc conditions: hidemajor=1"
369                 );
370         }
371
372         public function testHideCategorization() {
373                 $this->assertConditions(
374                         [
375                                 # expected
376                                 "rc_type != '6'"
377                         ],
378                         [
379                                 'hidecategorization' => 1
380                         ],
381                         "rc conditions: hidecategorization=1"
382                 );
383         }
384
385         public function testFilterUserExpLevelAll() {
386                 $this->assertConditions(
387                         [
388                                 # expected
389                         ],
390                         [
391                                 'userExpLevel' => 'registered;unregistered;newcomer;learner;experienced',
392                         ],
393                         "rc conditions: userExpLevel=registered;unregistered;newcomer;learner;experienced"
394                 );
395         }
396
397         public function testFilterUserExpLevelRegisteredUnregistered() {
398                 $this->assertConditions(
399                         [
400                                 # expected
401                         ],
402                         [
403                                 'userExpLevel' => 'registered;unregistered',
404                         ],
405                         "rc conditions: userExpLevel=registered;unregistered"
406                 );
407         }
408
409         public function testFilterUserExpLevelRegisteredUnregisteredLearner() {
410                 $this->assertConditions(
411                         [
412                                 # expected
413                         ],
414                         [
415                                 'userExpLevel' => 'registered;unregistered;learner',
416                         ],
417                         "rc conditions: userExpLevel=registered;unregistered;learner"
418                 );
419         }
420
421         public function testFilterUserExpLevelAllExperienceLevels() {
422                 $this->assertConditions(
423                         [
424                                 # expected
425                                 'rc_user != 0',
426                         ],
427                         [
428                                 'userExpLevel' => 'newcomer;learner;experienced',
429                         ],
430                         "rc conditions: userExpLevel=newcomer;learner;experienced"
431                 );
432         }
433
434         public function testFilterUserExpLevelRegistrered() {
435                 $this->assertConditions(
436                         [
437                                 # expected
438                                 'rc_user != 0',
439                         ],
440                         [
441                                 'userExpLevel' => 'registered',
442                         ],
443                         "rc conditions: userExpLevel=registered"
444                 );
445         }
446
447         public function testFilterUserExpLevelUnregistrered() {
448                 $this->assertConditions(
449                         [
450                                 # expected
451                                 'rc_user' => 0,
452                         ],
453                         [
454                                 'userExpLevel' => 'unregistered',
455                         ],
456                         "rc conditions: userExpLevel=unregistered"
457                 );
458         }
459
460         public function testFilterUserExpLevelRegistreredOrLearner() {
461                 $this->assertConditions(
462                         [
463                                 # expected
464                                 'rc_user != 0',
465                         ],
466                         [
467                                 'userExpLevel' => 'registered;learner',
468                         ],
469                         "rc conditions: userExpLevel=registered;learner"
470                 );
471         }
472
473         public function testFilterUserExpLevelUnregistreredOrExperienced() {
474                 $conds = $this->buildQuery( [ 'userExpLevel' => 'unregistered;experienced' ] );
475
476                 $this->assertRegExp(
477                         '/\(rc_user = 0\) OR \(\(user_editcount >= 500\) AND \(user_registration <= \'[^\']+\'\)\)/',
478                         reset( $conds ),
479                         "rc conditions: userExpLevel=unregistered;experienced"
480                 );
481         }
482
483         public function testFilterUserExpLevel() {
484                 $now = time();
485                 $this->setMwGlobals( [
486                         'wgLearnerEdits' => 10,
487                         'wgLearnerMemberSince' => 4,
488                         'wgExperiencedUserEdits' => 500,
489                         'wgExperiencedUserMemberSince' => 30,
490                 ] );
491
492                 $this->createUsers( [
493                         'Newcomer1' => [ 'edits' => 2, 'days' => 2 ],
494                         'Newcomer2' => [ 'edits' => 12, 'days' => 3 ],
495                         'Newcomer3' => [ 'edits' => 8, 'days' => 5 ],
496                         'Learner1' => [ 'edits' => 15, 'days' => 10 ],
497                         'Learner2' => [ 'edits' => 450, 'days' => 20 ],
498                         'Learner3' => [ 'edits' => 460, 'days' => 33 ],
499                         'Learner4' => [ 'edits' => 525, 'days' => 28 ],
500                         'Experienced1' => [ 'edits' => 538, 'days' => 33 ],
501                 ], $now );
502
503                 // newcomers only
504                 $this->assertArrayEquals(
505                         [ 'Newcomer1', 'Newcomer2', 'Newcomer3' ],
506                         $this->fetchUsers( [ 'newcomer' ], $now )
507                 );
508
509                 // newcomers and learner
510                 $this->assertArrayEquals(
511                         [
512                                 'Newcomer1', 'Newcomer2', 'Newcomer3',
513                                 'Learner1', 'Learner2', 'Learner3', 'Learner4',
514                         ],
515                         $this->fetchUsers( [ 'newcomer', 'learner' ], $now )
516                 );
517
518                 // newcomers and more learner
519                 $this->assertArrayEquals(
520                         [
521                                 'Newcomer1', 'Newcomer2', 'Newcomer3',
522                                 'Experienced1',
523                         ],
524                         $this->fetchUsers( [ 'newcomer', 'experienced' ], $now )
525                 );
526
527                 // learner only
528                 $this->assertArrayEquals(
529                         [ 'Learner1', 'Learner2', 'Learner3', 'Learner4' ],
530                         $this->fetchUsers( [ 'learner' ], $now )
531                 );
532
533                 // more experienced only
534                 $this->assertArrayEquals(
535                         [ 'Experienced1' ],
536                         $this->fetchUsers( [ 'experienced' ], $now )
537                 );
538
539                 // learner and more experienced
540                 $this->assertArrayEquals(
541                         [
542                                 'Learner1', 'Learner2', 'Learner3', 'Learner4',
543                                 'Experienced1',
544                         ],
545                         $this->fetchUsers( [ 'learner', 'experienced' ], $now ),
546                         'Learner and more experienced'
547                 );
548         }
549
550         private function createUsers( $specs, $now ) {
551                 $dbw = wfGetDB( DB_MASTER );
552                 foreach ( $specs as $name => $spec ) {
553                         User::createNew(
554                                 $name,
555                                 [
556                                         'editcount' => $spec['edits'],
557                                         'registration' => $dbw->timestamp( $this->daysAgo( $spec['days'], $now ) ),
558                                         'email' => 'ut',
559                                 ]
560                         );
561                 }
562         }
563
564         private function fetchUsers( $filters, $now ) {
565                 $tables = [];
566                 $conds = [];
567                 $fields = [];
568                 $query_options = [];
569                 $join_conds = [];
570
571                 sort( $filters );
572
573                 call_user_func_array(
574                         [ $this->changesListSpecialPage, 'filterOnUserExperienceLevel' ],
575                         [
576                                 get_class( $this->changesListSpecialPage ),
577                                 $this->changesListSpecialPage->getContext(),
578                                 $this->changesListSpecialPage->getDB(),
579                                 &$tables,
580                                 &$fields,
581                                 &$conds,
582                                 &$query_options,
583                                 &$join_conds,
584                                 $filters,
585                                 $now
586                         ]
587                 );
588
589                 $result = wfGetDB( DB_MASTER )->select(
590                         $tables,
591                         'user_name',
592                         array_filter( $conds ) + [ 'user_email' => 'ut' ]
593                 );
594
595                 $usernames = [];
596                 foreach ( $result as $row ) {
597                         $usernames[] = $row->user_name;
598                 }
599
600                 return $usernames;
601         }
602
603         private function daysAgo( $days, $now ) {
604                 $secondsPerDay = 86400;
605                 return $now - $days * $secondsPerDay;
606         }
607
608         public function testGetFilterGroupDefinitionFromLegacyCustomFilters() {
609                 $customFilters = [
610                         'hidefoo' => [
611                                 'msg' => 'showhidefoo',
612                                 'default' => true,
613                         ],
614
615                         'hidebar' => [
616                                 'msg' => 'showhidebar',
617                                 'default' => false,
618                         ],
619                 ];
620
621                 $this->assertEquals(
622                         [
623                                 'name' => 'unstructured',
624                                 'class' => ChangesListBooleanFilterGroup::class,
625                                 'priority' => -1,
626                                 'filters' => [
627                                         [
628                                                 'name' => 'hidefoo',
629                                                 'showHide' => 'showhidefoo',
630                                                 'default' => true,
631                                         ],
632                                         [
633                                                 'name' => 'hidebar',
634                                                 'showHide' => 'showhidebar',
635                                                 'default' => false,
636                                         ]
637                                 ],
638                         ],
639                         $this->changesListSpecialPage->getFilterGroupDefinitionFromLegacyCustomFilters(
640                                 $customFilters
641                         )
642                 );
643         }
644
645         public function testGetStructuredFilterJsData() {
646                 $this->changesListSpecialPage->filterGroups = [];
647
648                 $definition = [
649                         [
650                                 'name' => 'gub-group',
651                                 'title' => 'gub-group-title',
652                                 'class' => ChangesListBooleanFilterGroup::class,
653                                 'filters' => [
654                                         [
655                                                 'name' => 'hidefoo',
656                                                 'label' => 'foo-label',
657                                                 'description' => 'foo-description',
658                                                 'default' => true,
659                                                 'showHide' => 'showhidefoo',
660                                                 'priority' => 2,
661                                         ],
662                                         [
663                                                 'name' => 'hidebar',
664                                                 'label' => 'bar-label',
665                                                 'description' => 'bar-description',
666                                                 'default' => false,
667                                                 'priority' => 4,
668                                         ]
669                                 ],
670                         ],
671
672                         [
673                                 'name' => 'des-group',
674                                 'title' => 'des-group-title',
675                                 'class' => ChangesListStringOptionsFilterGroup::class,
676                                 'isFullCoverage' => true,
677                                 'filters' => [
678                                         [
679                                                 'name' => 'grault',
680                                                 'label' => 'grault-label',
681                                                 'description' => 'grault-description',
682                                         ],
683                                         [
684                                                 'name' => 'garply',
685                                                 'label' => 'garply-label',
686                                                 'description' => 'garply-description',
687                                         ],
688                                 ],
689                                 'queryCallable' => function () {
690                                 },
691                                 'default' => ChangesListStringOptionsFilterGroup::NONE,
692                         ],
693
694                         [
695                                 'name' => 'unstructured',
696                                 'class' => ChangesListBooleanFilterGroup::class,
697                                 'filters' => [
698                                         [
699                                                 'name' => 'hidethud',
700                                                 'showHide' => 'showhidethud',
701                                                 'default' => true,
702                                         ],
703
704                                         [
705                                                 'name' => 'hidemos',
706                                                 'showHide' => 'showhidemos',
707                                                 'default' => false,
708                                         ],
709                                 ],
710                         ],
711
712                 ];
713
714                 $this->changesListSpecialPage->registerFiltersFromDefinitions( $definition );
715
716                 $this->assertArrayEquals(
717                         [
718                                 // Filters that only display in the unstructured UI are
719                                 // are not included, and neither are groups that would
720                                 // be empty due to the above.
721                                 'groups' => [
722                                         [
723                                                 'name' => 'gub-group',
724                                                 'title' => 'gub-group-title',
725                                                 'type' => ChangesListBooleanFilterGroup::TYPE,
726                                                 'priority' => -1,
727                                                 'filters' => [
728                                                         [
729                                                                 'name' => 'hidebar',
730                                                                 'label' => 'bar-label',
731                                                                 'description' => 'bar-description',
732                                                                 'default' => false,
733                                                                 'priority' => 4,
734                                                                 'cssClass' => null,
735                                                                 'conflicts' => [],
736                                                                 'subset' => [],
737                                                         ],
738                                                         [
739                                                                 'name' => 'hidefoo',
740                                                                 'label' => 'foo-label',
741                                                                 'description' => 'foo-description',
742                                                                 'default' => true,
743                                                                 'priority' => 2,
744                                                                 'cssClass' => null,
745                                                                 'conflicts' => [],
746                                                                 'subset' => [],
747                                                         ],
748                                                 ],
749                                                 'fullCoverage' => true,
750                                                 'conflicts' => [],
751                                         ],
752
753                                         [
754                                                 'name' => 'des-group',
755                                                 'title' => 'des-group-title',
756                                                 'type' => ChangesListStringOptionsFilterGroup::TYPE,
757                                                 'priority' => -2,
758                                                 'fullCoverage' => true,
759                                                 'filters' => [
760                                                         [
761                                                                 'name' => 'grault',
762                                                                 'label' => 'grault-label',
763                                                                 'description' => 'grault-description',
764                                                                 'cssClass' => null,
765                                                                 'priority' => -2,
766                                                                 'conflicts' => [],
767                                                                 'subset' => [],
768                                                         ],
769                                                         [
770                                                                 'name' => 'garply',
771                                                                 'label' => 'garply-label',
772                                                                 'description' => 'garply-description',
773                                                                 'cssClass' => null,
774                                                                 'priority' => -3,
775                                                                 'conflicts' => [],
776                                                                 'subset' => [],
777                                                         ],
778                                                 ],
779                                                 'conflicts' => [],
780                                                 'separator' => ';',
781                                                 'default' => ChangesListStringOptionsFilterGroup::NONE,
782                                         ],
783                                 ],
784                                 'messageKeys' => [
785                                         'gub-group-title',
786                                         'bar-label',
787                                         'bar-description',
788                                         'foo-label',
789                                         'foo-description',
790                                         'des-group-title',
791                                         'grault-label',
792                                         'grault-description',
793                                         'garply-label',
794                                         'garply-description',
795                                 ],
796                         ],
797                         $this->changesListSpecialPage->getStructuredFilterJsData(),
798                         /** ordered= */ false,
799                         /** named= */ true
800                 );
801         }
802
803         public function provideParseParameters() {
804                 return [
805                         [ 'hidebots', [ 'hidebots' => true ] ],
806
807                         [ 'bots', [ 'hidebots' => false ] ],
808
809                         [ 'hideminor', [ 'hideminor' => true ] ],
810
811                         [ 'minor', [ 'hideminor' => false ] ],
812
813                         [ 'hidemajor', [ 'hidemajor' => true ] ],
814
815                         [ 'hideliu', [ 'hideliu' => true ] ],
816
817                         [ 'hidepatrolled', [ 'hidepatrolled' => true ] ],
818
819                         [ 'hideunpatrolled', [ 'hideunpatrolled' => true ] ],
820
821                         [ 'hideanons', [ 'hideanons' => true ] ],
822
823                         [ 'hidemyself', [ 'hidemyself' => true ] ],
824
825                         [ 'hidebyothers', [ 'hidebyothers' => true ] ],
826
827                         [ 'hidehumans', [ 'hidehumans' => true ] ],
828
829                         [ 'hidepageedits', [ 'hidepageedits' => true ] ],
830
831                         [ 'pagedits', [ 'hidepageedits' => false ] ],
832
833                         [ 'hidenewpages', [ 'hidenewpages' => true ] ],
834
835                         [ 'hidecategorization', [ 'hidecategorization' => true ] ],
836
837                         [ 'hidelog', [ 'hidelog' => true ] ],
838
839                         [
840                                 'userExpLevel=learner;experienced',
841                                 [
842                                         'userExpLevel' => 'learner;experienced'
843                                 ],
844                         ],
845
846                         // A few random combos
847                         [
848                                 'bots,hideliu,hidemyself',
849                                 [
850                                         'hidebots' => false,
851                                         'hideliu' => true,
852                                         'hidemyself' => true,
853                                 ],
854                         ],
855
856                         [
857                                 'minor,hideanons,categorization',
858                                 [
859                                         'hideminor' => false,
860                                         'hideanons' => true,
861                                         'hidecategorization' => false,
862                                 ]
863                         ],
864
865                         [
866                                 'hidehumans,bots,hidecategorization',
867                                 [
868                                         'hidehumans' => true,
869                                         'hidebots' => false,
870                                         'hidecategorization' => true,
871                                 ],
872                         ],
873
874                         [
875                                 'hidemyself,userExpLevel=newcomer;learner,hideminor',
876                                 [
877                                         'hidemyself' => true,
878                                         'hideminor' => true,
879                                         'userExpLevel' => 'newcomer;learner',
880                                 ],
881                         ],
882                 ];
883         }
884
885         public function provideGetFilterConflicts() {
886                 return [
887                         [
888                                 "parameters" => [],
889                                 "expectedConflicts" => false,
890                         ],
891                         [
892                                 "parameters" => [
893                                         "hideliu" => true,
894                                         "userExpLevel" => "newcomer",
895                                 ],
896                                 "expectedConflicts" => false,
897                         ],
898                         [
899                                 "parameters" => [
900                                         "hideanons" => true,
901                                         "userExpLevel" => "learner",
902                                 ],
903                                 "expectedConflicts" => false,
904                         ],
905                         [
906                                 "parameters" => [
907                                         "hidemajor" => true,
908                                         "hidenewpages" => true,
909                                         "hidepageedits" => true,
910                                         "hidecategorization" => false,
911                                         "hidelog" => true,
912                                         "hideWikidata" => true,
913                                 ],
914                                 "expectedConflicts" => true,
915                         ],
916                         [
917                                 "parameters" => [
918                                         "hidemajor" => true,
919                                         "hidenewpages" => false,
920                                         "hidepageedits" => true,
921                                         "hidecategorization" => false,
922                                         "hidelog" => false,
923                                         "hideWikidata" => true,
924                                 ],
925                                 "expectedConflicts" => true,
926                         ],
927                         [
928                                 "parameters" => [
929                                         "hidemajor" => true,
930                                         "hidenewpages" => false,
931                                         "hidepageedits" => false,
932                                         "hidecategorization" => true,
933                                         "hidelog" => true,
934                                         "hideWikidata" => true,
935                                 ],
936                                 "expectedConflicts" => false,
937                         ],
938                         [
939                                 "parameters" => [
940                                         "hideminor" => true,
941                                         "hidenewpages" => true,
942                                         "hidepageedits" => true,
943                                         "hidecategorization" => false,
944                                         "hidelog" => true,
945                                         "hideWikidata" => true,
946                                 ],
947                                 "expectedConflicts" => false,
948                         ],
949                 ];
950         }
951
952         /**
953          * @dataProvider provideGetFilterConflicts
954          */
955         public function testGetFilterConflicts( $parameters, $expectedConflicts ) {
956                 $context = new RequestContext;
957                 $context->setRequest( new FauxRequest( $parameters ) );
958                 $this->changesListSpecialPage->setContext( $context );
959
960                 $this->assertEquals(
961                         $expectedConflicts,
962                         $this->changesListSpecialPage->areFiltersInConflict()
963                 );
964         }
965
966         public function validateOptionsProvider() {
967                 return [
968                         [
969                                 [ 'hideanons' => 1, 'hideliu' => 1, 'hidebots' => 1 ],
970                                 true,
971                                 [ 'hideliu' => 1, 'hidebots' => 1, ],
972                         ],
973
974                         [
975                                 [ 'hideanons' => 1, 'hideliu' => 1, 'hidebots' => 0 ],
976                                 true,
977                                 [ 'hidebots' => 0, 'hidehumans' => 1 ],
978                         ],
979
980                         [
981                                 [ 'hidemyself' => 1, 'hidebyothers' => 1 ],
982                                 true,
983                                 [],
984                         ],
985                         [
986                                 [ 'hidebots' => 1, 'hidehumans' => 1 ],
987                                 true,
988                                 [],
989                         ],
990                         [
991                                 [ 'hidepatrolled' => 1, 'hideunpatrolled' => 1 ],
992                                 true,
993                                 [],
994                         ],
995                         [
996                                 [ 'hideminor' => 1, 'hidemajor' => 1 ],
997                                 true,
998                                 [],
999                         ],
1000                         [
1001                                 // changeType
1002                                 [ 'hidepageedits' => 1, 'hidenewpages' => 1, 'hidecategorization' => 1, 'hidelog' => 1, ],
1003                                 true,
1004                                 [],
1005                         ],
1006                 ];
1007         }
1008 }