Merge "Skin: Make skins aware of their registered skin name"
[lhc/web/wiklou.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 $this->setMwGlobals( 'wgUseRCPatrol', false );
297 $user = $this->getTestUser()->getUser();
298 $this->assertConditions(
299 [ # expected
300 ],
301 [
302 'hidepatrolled' => 1,
303 ],
304 "rc conditions: hidepatrolled=1 (user not allowed)",
305 $user
306 );
307 }
308
309 public function testRcHideunpatrolledDisabledFilter() {
310 $this->setMwGlobals( 'wgUseRCPatrol', false );
311 $user = $this->getTestUser()->getUser();
312 $this->assertConditions(
313 [ # expected
314 ],
315 [
316 'hideunpatrolled' => 1,
317 ],
318 "rc conditions: hideunpatrolled=1 (user not allowed)",
319 $user
320 );
321 }
322 public function testRcHidepatrolledFilter() {
323 $user = $this->getTestSysop()->getUser();
324 $this->assertConditions(
325 [ # expected
326 "rc_patrolled = 0",
327 ],
328 [
329 'hidepatrolled' => 1,
330 ],
331 "rc conditions: hidepatrolled=1",
332 $user
333 );
334 }
335
336 public function testRcHideunpatrolledFilter() {
337 $user = $this->getTestSysop()->getUser();
338 $this->assertConditions(
339 [ # expected
340 "rc_patrolled = 1",
341 ],
342 [
343 'hideunpatrolled' => 1,
344 ],
345 "rc conditions: hideunpatrolled=1",
346 $user
347 );
348 }
349
350 public function testRcHideminorFilter() {
351 $this->assertConditions(
352 [ # expected
353 "rc_minor = 0",
354 ],
355 [
356 'hideminor' => 1,
357 ],
358 "rc conditions: hideminor=1"
359 );
360 }
361
362 public function testRcHidemajorFilter() {
363 $this->assertConditions(
364 [ # expected
365 "rc_minor = 1",
366 ],
367 [
368 'hidemajor' => 1,
369 ],
370 "rc conditions: hidemajor=1"
371 );
372 }
373
374 public function testHideCategorization() {
375 $this->assertConditions(
376 [
377 # expected
378 "rc_type != '6'"
379 ],
380 [
381 'hidecategorization' => 1
382 ],
383 "rc conditions: hidecategorization=1"
384 );
385 }
386
387 public function testFilterUserExpLevelAll() {
388 $this->assertConditions(
389 [
390 # expected
391 ],
392 [
393 'userExpLevel' => 'registered;unregistered;newcomer;learner;experienced',
394 ],
395 "rc conditions: userExpLevel=registered;unregistered;newcomer;learner;experienced"
396 );
397 }
398
399 public function testFilterUserExpLevelRegisteredUnregistered() {
400 $this->assertConditions(
401 [
402 # expected
403 ],
404 [
405 'userExpLevel' => 'registered;unregistered',
406 ],
407 "rc conditions: userExpLevel=registered;unregistered"
408 );
409 }
410
411 public function testFilterUserExpLevelRegisteredUnregisteredLearner() {
412 $this->assertConditions(
413 [
414 # expected
415 ],
416 [
417 'userExpLevel' => 'registered;unregistered;learner',
418 ],
419 "rc conditions: userExpLevel=registered;unregistered;learner"
420 );
421 }
422
423 public function testFilterUserExpLevelAllExperienceLevels() {
424 $this->assertConditions(
425 [
426 # expected
427 'rc_user != 0',
428 ],
429 [
430 'userExpLevel' => 'newcomer;learner;experienced',
431 ],
432 "rc conditions: userExpLevel=newcomer;learner;experienced"
433 );
434 }
435
436 public function testFilterUserExpLevelRegistrered() {
437 $this->assertConditions(
438 [
439 # expected
440 'rc_user != 0',
441 ],
442 [
443 'userExpLevel' => 'registered',
444 ],
445 "rc conditions: userExpLevel=registered"
446 );
447 }
448
449 public function testFilterUserExpLevelUnregistrered() {
450 $this->assertConditions(
451 [
452 # expected
453 'rc_user' => 0,
454 ],
455 [
456 'userExpLevel' => 'unregistered',
457 ],
458 "rc conditions: userExpLevel=unregistered"
459 );
460 }
461
462 public function testFilterUserExpLevelRegistreredOrLearner() {
463 $this->assertConditions(
464 [
465 # expected
466 'rc_user != 0',
467 ],
468 [
469 'userExpLevel' => 'registered;learner',
470 ],
471 "rc conditions: userExpLevel=registered;learner"
472 );
473 }
474
475 public function testFilterUserExpLevelUnregistreredOrExperienced() {
476 $conds = $this->buildQuery( [ 'userExpLevel' => 'unregistered;experienced' ] );
477
478 $this->assertRegExp(
479 '/\(rc_user = 0\) OR \(\(user_editcount >= 500\) AND \(user_registration <= \'[^\']+\'\)\)/',
480 reset( $conds ),
481 "rc conditions: userExpLevel=unregistered;experienced"
482 );
483 }
484
485 public function testFilterUserExpLevel() {
486 $now = time();
487 $this->setMwGlobals( [
488 'wgLearnerEdits' => 10,
489 'wgLearnerMemberSince' => 4,
490 'wgExperiencedUserEdits' => 500,
491 'wgExperiencedUserMemberSince' => 30,
492 ] );
493
494 $this->createUsers( [
495 'Newcomer1' => [ 'edits' => 2, 'days' => 2 ],
496 'Newcomer2' => [ 'edits' => 12, 'days' => 3 ],
497 'Newcomer3' => [ 'edits' => 8, 'days' => 5 ],
498 'Learner1' => [ 'edits' => 15, 'days' => 10 ],
499 'Learner2' => [ 'edits' => 450, 'days' => 20 ],
500 'Learner3' => [ 'edits' => 460, 'days' => 33 ],
501 'Learner4' => [ 'edits' => 525, 'days' => 28 ],
502 'Experienced1' => [ 'edits' => 538, 'days' => 33 ],
503 ], $now );
504
505 // newcomers only
506 $this->assertArrayEquals(
507 [ 'Newcomer1', 'Newcomer2', 'Newcomer3' ],
508 $this->fetchUsers( [ 'newcomer' ], $now )
509 );
510
511 // newcomers and learner
512 $this->assertArrayEquals(
513 [
514 'Newcomer1', 'Newcomer2', 'Newcomer3',
515 'Learner1', 'Learner2', 'Learner3', 'Learner4',
516 ],
517 $this->fetchUsers( [ 'newcomer', 'learner' ], $now )
518 );
519
520 // newcomers and more learner
521 $this->assertArrayEquals(
522 [
523 'Newcomer1', 'Newcomer2', 'Newcomer3',
524 'Experienced1',
525 ],
526 $this->fetchUsers( [ 'newcomer', 'experienced' ], $now )
527 );
528
529 // learner only
530 $this->assertArrayEquals(
531 [ 'Learner1', 'Learner2', 'Learner3', 'Learner4' ],
532 $this->fetchUsers( [ 'learner' ], $now )
533 );
534
535 // more experienced only
536 $this->assertArrayEquals(
537 [ 'Experienced1' ],
538 $this->fetchUsers( [ 'experienced' ], $now )
539 );
540
541 // learner and more experienced
542 $this->assertArrayEquals(
543 [
544 'Learner1', 'Learner2', 'Learner3', 'Learner4',
545 'Experienced1',
546 ],
547 $this->fetchUsers( [ 'learner', 'experienced' ], $now ),
548 'Learner and more experienced'
549 );
550 }
551
552 private function createUsers( $specs, $now ) {
553 $dbw = wfGetDB( DB_MASTER );
554 foreach ( $specs as $name => $spec ) {
555 User::createNew(
556 $name,
557 [
558 'editcount' => $spec['edits'],
559 'registration' => $dbw->timestamp( $this->daysAgo( $spec['days'], $now ) ),
560 'email' => 'ut',
561 ]
562 );
563 }
564 }
565
566 private function fetchUsers( $filters, $now ) {
567 $tables = [];
568 $conds = [];
569 $fields = [];
570 $query_options = [];
571 $join_conds = [];
572
573 sort( $filters );
574
575 call_user_func_array(
576 [ $this->changesListSpecialPage, 'filterOnUserExperienceLevel' ],
577 [
578 get_class( $this->changesListSpecialPage ),
579 $this->changesListSpecialPage->getContext(),
580 $this->changesListSpecialPage->getDB(),
581 &$tables,
582 &$fields,
583 &$conds,
584 &$query_options,
585 &$join_conds,
586 $filters,
587 $now
588 ]
589 );
590
591 $result = wfGetDB( DB_MASTER )->select(
592 $tables,
593 'user_name',
594 array_filter( $conds ) + [ 'user_email' => 'ut' ]
595 );
596
597 $usernames = [];
598 foreach ( $result as $row ) {
599 $usernames[] = $row->user_name;
600 }
601
602 return $usernames;
603 }
604
605 private function daysAgo( $days, $now ) {
606 $secondsPerDay = 86400;
607 return $now - $days * $secondsPerDay;
608 }
609
610 public function testGetFilterGroupDefinitionFromLegacyCustomFilters() {
611 $customFilters = [
612 'hidefoo' => [
613 'msg' => 'showhidefoo',
614 'default' => true,
615 ],
616
617 'hidebar' => [
618 'msg' => 'showhidebar',
619 'default' => false,
620 ],
621 ];
622
623 $this->assertEquals(
624 [
625 'name' => 'unstructured',
626 'class' => ChangesListBooleanFilterGroup::class,
627 'priority' => -1,
628 'filters' => [
629 [
630 'name' => 'hidefoo',
631 'showHide' => 'showhidefoo',
632 'default' => true,
633 ],
634 [
635 'name' => 'hidebar',
636 'showHide' => 'showhidebar',
637 'default' => false,
638 ]
639 ],
640 ],
641 $this->changesListSpecialPage->getFilterGroupDefinitionFromLegacyCustomFilters(
642 $customFilters
643 )
644 );
645 }
646
647 public function testGetStructuredFilterJsData() {
648 $this->changesListSpecialPage->filterGroups = [];
649
650 $definition = [
651 [
652 'name' => 'gub-group',
653 'title' => 'gub-group-title',
654 'class' => ChangesListBooleanFilterGroup::class,
655 'filters' => [
656 [
657 'name' => 'hidefoo',
658 'label' => 'foo-label',
659 'description' => 'foo-description',
660 'default' => true,
661 'showHide' => 'showhidefoo',
662 'priority' => 2,
663 ],
664 [
665 'name' => 'hidebar',
666 'label' => 'bar-label',
667 'description' => 'bar-description',
668 'default' => false,
669 'priority' => 4,
670 ]
671 ],
672 ],
673
674 [
675 'name' => 'des-group',
676 'title' => 'des-group-title',
677 'class' => ChangesListStringOptionsFilterGroup::class,
678 'isFullCoverage' => true,
679 'filters' => [
680 [
681 'name' => 'grault',
682 'label' => 'grault-label',
683 'description' => 'grault-description',
684 ],
685 [
686 'name' => 'garply',
687 'label' => 'garply-label',
688 'description' => 'garply-description',
689 ],
690 ],
691 'queryCallable' => function () {
692 },
693 'default' => ChangesListStringOptionsFilterGroup::NONE,
694 ],
695
696 [
697 'name' => 'unstructured',
698 'class' => ChangesListBooleanFilterGroup::class,
699 'filters' => [
700 [
701 'name' => 'hidethud',
702 'showHide' => 'showhidethud',
703 'default' => true,
704 ],
705
706 [
707 'name' => 'hidemos',
708 'showHide' => 'showhidemos',
709 'default' => false,
710 ],
711 ],
712 ],
713
714 ];
715
716 $this->changesListSpecialPage->registerFiltersFromDefinitions( $definition );
717
718 $this->assertArrayEquals(
719 [
720 // Filters that only display in the unstructured UI are
721 // are not included, and neither are groups that would
722 // be empty due to the above.
723 'groups' => [
724 [
725 'name' => 'gub-group',
726 'title' => 'gub-group-title',
727 'type' => ChangesListBooleanFilterGroup::TYPE,
728 'priority' => -1,
729 'filters' => [
730 [
731 'name' => 'hidebar',
732 'label' => 'bar-label',
733 'description' => 'bar-description',
734 'default' => false,
735 'priority' => 4,
736 'cssClass' => null,
737 'conflicts' => [],
738 'subset' => [],
739 'defaultHighlightColor' => null
740 ],
741 [
742 'name' => 'hidefoo',
743 'label' => 'foo-label',
744 'description' => 'foo-description',
745 'default' => true,
746 'priority' => 2,
747 'cssClass' => null,
748 'conflicts' => [],
749 'subset' => [],
750 'defaultHighlightColor' => null
751 ],
752 ],
753 'fullCoverage' => true,
754 'conflicts' => [],
755 ],
756
757 [
758 'name' => 'des-group',
759 'title' => 'des-group-title',
760 'type' => ChangesListStringOptionsFilterGroup::TYPE,
761 'priority' => -2,
762 'fullCoverage' => true,
763 'filters' => [
764 [
765 'name' => 'grault',
766 'label' => 'grault-label',
767 'description' => 'grault-description',
768 'cssClass' => null,
769 'priority' => -2,
770 'conflicts' => [],
771 'subset' => [],
772 'defaultHighlightColor' => null
773 ],
774 [
775 'name' => 'garply',
776 'label' => 'garply-label',
777 'description' => 'garply-description',
778 'cssClass' => null,
779 'priority' => -3,
780 'conflicts' => [],
781 'subset' => [],
782 'defaultHighlightColor' => null
783 ],
784 ],
785 'conflicts' => [],
786 'separator' => ';',
787 'default' => ChangesListStringOptionsFilterGroup::NONE,
788 ],
789 ],
790 'messageKeys' => [
791 'gub-group-title',
792 'bar-label',
793 'bar-description',
794 'foo-label',
795 'foo-description',
796 'des-group-title',
797 'grault-label',
798 'grault-description',
799 'garply-label',
800 'garply-description',
801 ],
802 ],
803 $this->changesListSpecialPage->getStructuredFilterJsData(),
804 /** ordered= */ false,
805 /** named= */ true
806 );
807 }
808
809 public function provideParseParameters() {
810 return [
811 [ 'hidebots', [ 'hidebots' => true ] ],
812
813 [ 'bots', [ 'hidebots' => false ] ],
814
815 [ 'hideminor', [ 'hideminor' => true ] ],
816
817 [ 'minor', [ 'hideminor' => false ] ],
818
819 [ 'hidemajor', [ 'hidemajor' => true ] ],
820
821 [ 'hideliu', [ 'hideliu' => true ] ],
822
823 [ 'hidepatrolled', [ 'hidepatrolled' => true ] ],
824
825 [ 'hideunpatrolled', [ 'hideunpatrolled' => true ] ],
826
827 [ 'hideanons', [ 'hideanons' => true ] ],
828
829 [ 'hidemyself', [ 'hidemyself' => true ] ],
830
831 [ 'hidebyothers', [ 'hidebyothers' => true ] ],
832
833 [ 'hidehumans', [ 'hidehumans' => true ] ],
834
835 [ 'hidepageedits', [ 'hidepageedits' => true ] ],
836
837 [ 'pagedits', [ 'hidepageedits' => false ] ],
838
839 [ 'hidenewpages', [ 'hidenewpages' => true ] ],
840
841 [ 'hidecategorization', [ 'hidecategorization' => true ] ],
842
843 [ 'hidelog', [ 'hidelog' => true ] ],
844
845 [
846 'userExpLevel=learner;experienced',
847 [
848 'userExpLevel' => 'learner;experienced'
849 ],
850 ],
851
852 // A few random combos
853 [
854 'bots,hideliu,hidemyself',
855 [
856 'hidebots' => false,
857 'hideliu' => true,
858 'hidemyself' => true,
859 ],
860 ],
861
862 [
863 'minor,hideanons,categorization',
864 [
865 'hideminor' => false,
866 'hideanons' => true,
867 'hidecategorization' => false,
868 ]
869 ],
870
871 [
872 'hidehumans,bots,hidecategorization',
873 [
874 'hidehumans' => true,
875 'hidebots' => false,
876 'hidecategorization' => true,
877 ],
878 ],
879
880 [
881 'hidemyself,userExpLevel=newcomer;learner,hideminor',
882 [
883 'hidemyself' => true,
884 'hideminor' => true,
885 'userExpLevel' => 'newcomer;learner',
886 ],
887 ],
888 ];
889 }
890
891 public function provideGetFilterConflicts() {
892 return [
893 [
894 "parameters" => [],
895 "expectedConflicts" => false,
896 ],
897 [
898 "parameters" => [
899 "hideliu" => true,
900 "userExpLevel" => "newcomer",
901 ],
902 "expectedConflicts" => false,
903 ],
904 [
905 "parameters" => [
906 "hideanons" => true,
907 "userExpLevel" => "learner",
908 ],
909 "expectedConflicts" => false,
910 ],
911 [
912 "parameters" => [
913 "hidemajor" => true,
914 "hidenewpages" => true,
915 "hidepageedits" => true,
916 "hidecategorization" => false,
917 "hidelog" => true,
918 "hideWikidata" => true,
919 ],
920 "expectedConflicts" => true,
921 ],
922 [
923 "parameters" => [
924 "hidemajor" => true,
925 "hidenewpages" => false,
926 "hidepageedits" => true,
927 "hidecategorization" => false,
928 "hidelog" => false,
929 "hideWikidata" => true,
930 ],
931 "expectedConflicts" => true,
932 ],
933 [
934 "parameters" => [
935 "hidemajor" => true,
936 "hidenewpages" => false,
937 "hidepageedits" => false,
938 "hidecategorization" => true,
939 "hidelog" => true,
940 "hideWikidata" => true,
941 ],
942 "expectedConflicts" => false,
943 ],
944 [
945 "parameters" => [
946 "hideminor" => true,
947 "hidenewpages" => true,
948 "hidepageedits" => true,
949 "hidecategorization" => false,
950 "hidelog" => true,
951 "hideWikidata" => true,
952 ],
953 "expectedConflicts" => false,
954 ],
955 ];
956 }
957
958 /**
959 * @dataProvider provideGetFilterConflicts
960 */
961 public function testGetFilterConflicts( $parameters, $expectedConflicts ) {
962 $context = new RequestContext;
963 $context->setRequest( new FauxRequest( $parameters ) );
964 $this->changesListSpecialPage->setContext( $context );
965
966 $this->assertEquals(
967 $expectedConflicts,
968 $this->changesListSpecialPage->areFiltersInConflict()
969 );
970 }
971
972 public function validateOptionsProvider() {
973 return [
974 [
975 [ 'hideanons' => 1, 'hideliu' => 1, 'hidebots' => 1 ],
976 true,
977 [ 'hideliu' => 1, 'hidebots' => 1, ],
978 ],
979
980 [
981 [ 'hideanons' => 1, 'hideliu' => 1, 'hidebots' => 0 ],
982 true,
983 [ 'hidebots' => 0, 'hidehumans' => 1 ],
984 ],
985
986 [
987 [ 'hidemyself' => 1, 'hidebyothers' => 1 ],
988 true,
989 [],
990 ],
991 [
992 [ 'hidebots' => 1, 'hidehumans' => 1 ],
993 true,
994 [],
995 ],
996 [
997 [ 'hidepatrolled' => 1, 'hideunpatrolled' => 1 ],
998 true,
999 [],
1000 ],
1001 [
1002 [ 'hideminor' => 1, 'hidemajor' => 1 ],
1003 true,
1004 [],
1005 ],
1006 [
1007 // changeType
1008 [ 'hidepageedits' => 1, 'hidenewpages' => 1, 'hidecategorization' => 1, 'hidelog' => 1, ],
1009 true,
1010 [],
1011 ],
1012 ];
1013 }
1014 }