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