Merge "refreshLinks.php: allow refreshing by categories, tracking or not"
[lhc/web/wiklou.git] / tests / qunit / suites / resources / mediawiki.rcfilters / dm.FiltersViewModel.test.js
1 ( function ( mw, $ ) {
2 QUnit.module( 'mediawiki.rcfilters - FiltersViewModel' );
3
4 QUnit.test( 'Setting up filters', function ( assert ) {
5 var definition = {
6 group1: {
7 title: 'Group 1',
8 type: 'send_unselected_if_any',
9 filters: [
10 {
11 name: 'group1filter1',
12 label: 'Group 1: Filter 1',
13 description: 'Description of Filter 1 in Group 1'
14 },
15 {
16 name: 'group1filter2',
17 label: 'Group 1: Filter 2',
18 description: 'Description of Filter 2 in Group 1'
19 }
20 ]
21 },
22 group2: {
23 title: 'Group 2',
24 type: 'send_unselected_if_any',
25 filters: [
26 {
27 name: 'group2filter1',
28 label: 'Group 2: Filter 1',
29 description: 'Description of Filter 1 in Group 2'
30 },
31 {
32 name: 'group2filter2',
33 label: 'Group 2: Filter 2',
34 description: 'Description of Filter 2 in Group 2'
35 }
36 ]
37 },
38 group3: {
39 title: 'Group 3',
40 type: 'string_options',
41 filters: [
42 {
43 name: 'group3filter1',
44 label: 'Group 3: Filter 1',
45 description: 'Description of Filter 1 in Group 3'
46 },
47 {
48 name: 'group3filter2',
49 label: 'Group 3: Filter 2',
50 description: 'Description of Filter 2 in Group 3'
51 }
52 ]
53 }
54 },
55 model = new mw.rcfilters.dm.FiltersViewModel();
56
57 model.initializeFilters( definition );
58
59 assert.ok(
60 model.getItemByName( 'group1filter1' ) instanceof mw.rcfilters.dm.FilterItem &&
61 model.getItemByName( 'group1filter2' ) instanceof mw.rcfilters.dm.FilterItem &&
62 model.getItemByName( 'group2filter1' ) instanceof mw.rcfilters.dm.FilterItem &&
63 model.getItemByName( 'group2filter2' ) instanceof mw.rcfilters.dm.FilterItem &&
64 model.getItemByName( 'group3filter1' ) instanceof mw.rcfilters.dm.FilterItem &&
65 model.getItemByName( 'group3filter2' ) instanceof mw.rcfilters.dm.FilterItem,
66 'Filters instantiated and stored correctly'
67 );
68
69 assert.deepEqual(
70 model.getSelectedState(),
71 {
72 group1filter1: false,
73 group1filter2: false,
74 group2filter1: false,
75 group2filter2: false,
76 group3filter1: false,
77 group3filter2: false
78 },
79 'Initial state of filters'
80 );
81
82 model.updateFilters( {
83 group1filter1: true,
84 group2filter2: true,
85 group3filter1: true
86 } );
87 assert.deepEqual(
88 model.getSelectedState(),
89 {
90 group1filter1: true,
91 group1filter2: false,
92 group2filter1: false,
93 group2filter2: true,
94 group3filter1: true,
95 group3filter2: false
96 },
97 'Updating filter states correctly'
98 );
99 } );
100
101 QUnit.test( 'Finding matching filters', function ( assert ) {
102 var matches,
103 definition = {
104 group1: {
105 title: 'Group 1',
106 type: 'send_unselected_if_any',
107 filters: [
108 {
109 name: 'group1filter1',
110 label: 'Group 1: Filter 1',
111 description: 'Description of Filter 1 in Group 1'
112 },
113 {
114 name: 'group1filter2',
115 label: 'Group 1: Filter 2',
116 description: 'Description of Filter 2 in Group 1'
117 }
118 ]
119 },
120 group2: {
121 title: 'Group 2',
122 type: 'send_unselected_if_any',
123 filters: [
124 {
125 name: 'group2filter1',
126 label: 'Group 2: Filter 1',
127 description: 'Description of Filter 1 in Group 2'
128 },
129 {
130 name: 'group2filter2',
131 label: 'Group 2: Filter 2',
132 description: 'Description of Filter 2 in Group 2'
133 }
134 ]
135 }
136 },
137 model = new mw.rcfilters.dm.FiltersViewModel();
138
139 model.initializeFilters( definition );
140
141 matches = model.findMatches( 'group 1' );
142 assert.equal(
143 matches.group1.length,
144 2,
145 'findMatches finds correct group with correct number of results'
146 );
147
148 assert.deepEqual(
149 matches.group1.map( function ( item ) { return item.getName(); } ),
150 [ 'group1filter1', 'group1filter2' ],
151 'findMatches finds the correct items within a single group'
152 );
153
154 matches = model.findMatches( 'filter 1' );
155 assert.ok(
156 matches.group1.length === 1 && matches.group2.length === 1,
157 'findMatches finds correct number of results in multiple groups'
158 );
159
160 assert.deepEqual(
161 [
162 matches.group1.map( function ( item ) { return item.getName(); } ),
163 matches.group2.map( function ( item ) { return item.getName(); } )
164 ],
165 [
166 [ 'group1filter1' ],
167 [ 'group2filter1' ]
168 ],
169 'findMatches finds the correct items within multiple groups'
170 );
171
172 matches = model.findMatches( 'foo' );
173 assert.ok(
174 $.isEmptyObject( matches ),
175 'findMatches returns an empty object when no results found'
176 );
177 } );
178
179 QUnit.test( 'getParametersFromFilters', function ( assert ) {
180 var definition = {
181 group1: {
182 title: 'Group 1',
183 type: 'send_unselected_if_any',
184 filters: [
185 {
186 name: 'hidefilter1',
187 label: 'Group 1: Filter 1',
188 description: 'Description of Filter 1 in Group 1'
189 },
190 {
191 name: 'hidefilter2',
192 label: 'Group 1: Filter 2',
193 description: 'Description of Filter 2 in Group 1'
194 },
195 {
196 name: 'hidefilter3',
197 label: 'Group 1: Filter 3',
198 description: 'Description of Filter 3 in Group 1'
199 }
200 ]
201 },
202 group2: {
203 title: 'Group 2',
204 type: 'send_unselected_if_any',
205 filters: [
206 {
207 name: 'hidefilter4',
208 label: 'Group 2: Filter 1',
209 description: 'Description of Filter 1 in Group 2'
210 },
211 {
212 name: 'hidefilter5',
213 label: 'Group 2: Filter 2',
214 description: 'Description of Filter 2 in Group 2'
215 },
216 {
217 name: 'hidefilter6',
218 label: 'Group 2: Filter 3',
219 description: 'Description of Filter 3 in Group 2'
220 }
221 ]
222 },
223 group3: {
224 title: 'Group 3',
225 type: 'string_options',
226 separator: ',',
227 filters: [
228 {
229 name: 'filter7',
230 label: 'Group 3: Filter 1',
231 description: 'Description of Filter 1 in Group 3'
232 },
233 {
234 name: 'filter8',
235 label: 'Group 3: Filter 2',
236 description: 'Description of Filter 2 in Group 3'
237 },
238 {
239 name: 'filter9',
240 label: 'Group 3: Filter 3',
241 description: 'Description of Filter 3 in Group 3'
242 }
243 ]
244 }
245 },
246 model = new mw.rcfilters.dm.FiltersViewModel();
247
248 model.initializeFilters( definition );
249
250 // Starting with all filters unselected
251 assert.deepEqual(
252 model.getParametersFromFilters(),
253 {
254 hidefilter1: 0,
255 hidefilter2: 0,
256 hidefilter3: 0,
257 hidefilter4: 0,
258 hidefilter5: 0,
259 hidefilter6: 0,
260 group3: 'all',
261 },
262 'Unselected filters return all parameters falsey or \'all\'.'
263 );
264
265 // Select 1 filter
266 model.updateFilters( {
267 hidefilter1: true,
268 hidefilter2: false,
269 hidefilter3: false,
270 hidefilter4: false,
271 hidefilter5: false,
272 hidefilter6: false
273 } );
274 // Only one filter in one group
275 assert.deepEqual(
276 model.getParametersFromFilters(),
277 {
278 // Group 1 (one selected, the others are true)
279 hidefilter1: 0,
280 hidefilter2: 1,
281 hidefilter3: 1,
282 // Group 2 (nothing is selected, all false)
283 hidefilter4: 0,
284 hidefilter5: 0,
285 hidefilter6: 0,
286 group3: 'all'
287 },
288 'One filters in one "send_unselected_if_any" group returns the other parameters truthy.'
289 );
290
291 // Select 2 filters
292 model.updateFilters( {
293 hidefilter1: true,
294 hidefilter2: true,
295 hidefilter3: false,
296 hidefilter4: false,
297 hidefilter5: false,
298 hidefilter6: false
299 } );
300 // Two selected filters in one group
301 assert.deepEqual(
302 model.getParametersFromFilters(),
303 {
304 // Group 1 (two selected, the others are true)
305 hidefilter1: 0,
306 hidefilter2: 0,
307 hidefilter3: 1,
308 // Group 2 (nothing is selected, all false)
309 hidefilter4: 0,
310 hidefilter5: 0,
311 hidefilter6: 0,
312 group3: 'all'
313 },
314 'One filters in one "send_unselected_if_any" group returns the other parameters truthy.'
315 );
316
317 // Select 3 filters
318 model.updateFilters( {
319 hidefilter1: true,
320 hidefilter2: true,
321 hidefilter3: true,
322 hidefilter4: false,
323 hidefilter5: false,
324 hidefilter6: false
325 } );
326 // All filters of the group are selected == this is the same as not selecting any
327 assert.deepEqual(
328 model.getParametersFromFilters(),
329 {
330 // Group 1 (all selected, all false)
331 hidefilter1: 0,
332 hidefilter2: 0,
333 hidefilter3: 0,
334 // Group 2 (nothing is selected, all false)
335 hidefilter4: 0,
336 hidefilter5: 0,
337 hidefilter6: 0,
338 group3: 'all'
339 },
340 'All filters selected in one "send_unselected_if_any" group returns all parameters falsy.'
341 );
342
343 // Select 1 filter from string_options
344 model.updateFilters( {
345 filter7: true,
346 filter8: false,
347 filter9: false
348 } );
349 // All filters of the group are selected == this is the same as not selecting any
350 assert.deepEqual(
351 model.getParametersFromFilters(),
352 {
353 // Group 1 (all selected, all)
354 hidefilter1: 0,
355 hidefilter2: 0,
356 hidefilter3: 0,
357 // Group 2 (nothing is selected, all false)
358 hidefilter4: 0,
359 hidefilter5: 0,
360 hidefilter6: 0,
361 group3: 'filter7'
362 },
363 'One filter selected in "string_option" group returns that filter in the value.'
364 );
365
366 // Select 2 filters from string_options
367 model.updateFilters( {
368 filter7: true,
369 filter8: true,
370 filter9: false
371 } );
372 // All filters of the group are selected == this is the same as not selecting any
373 assert.deepEqual(
374 model.getParametersFromFilters(),
375 {
376 // Group 1 (all selected, all)
377 hidefilter1: 0,
378 hidefilter2: 0,
379 hidefilter3: 0,
380 // Group 2 (nothing is selected, all false)
381 hidefilter4: 0,
382 hidefilter5: 0,
383 hidefilter6: 0,
384 group3: 'filter7,filter8'
385 },
386 'Two filters selected in "string_option" group returns those filters in the value.'
387 );
388
389 // Select 3 filters from string_options
390 model.updateFilters( {
391 filter7: true,
392 filter8: true,
393 filter9: true
394 } );
395 // All filters of the group are selected == this is the same as not selecting any
396 assert.deepEqual(
397 model.getParametersFromFilters(),
398 {
399 // Group 1 (all selected, all)
400 hidefilter1: 0,
401 hidefilter2: 0,
402 hidefilter3: 0,
403 // Group 2 (nothing is selected, all false)
404 hidefilter4: 0,
405 hidefilter5: 0,
406 hidefilter6: 0,
407 group3: 'all'
408 },
409 'All filters selected in "string_option" group returns \'all\'.'
410 );
411
412 } );
413
414 QUnit.test( 'getFiltersFromParameters', function ( assert ) {
415 var definition = {
416 group1: {
417 title: 'Group 1',
418 type: 'send_unselected_if_any',
419 filters: [
420 {
421 name: 'hidefilter1',
422 label: 'Show filter 1',
423 description: 'Description of Filter 1 in Group 1',
424 default: true
425 },
426 {
427 name: 'hidefilter2',
428 label: 'Show filter 2',
429 description: 'Description of Filter 2 in Group 1'
430 },
431 {
432 name: 'hidefilter3',
433 label: 'Show filter 3',
434 description: 'Description of Filter 3 in Group 1',
435 default: true
436 }
437 ]
438 },
439 group2: {
440 title: 'Group 2',
441 type: 'send_unselected_if_any',
442 filters: [
443 {
444 name: 'hidefilter4',
445 label: 'Show filter 4',
446 description: 'Description of Filter 1 in Group 2'
447 },
448 {
449 name: 'hidefilter5',
450 label: 'Show filter 5',
451 description: 'Description of Filter 2 in Group 2',
452 default: true
453 },
454 {
455 name: 'hidefilter6',
456 label: 'Show filter 6',
457 description: 'Description of Filter 3 in Group 2'
458 }
459 ]
460 },
461 group3: {
462 title: 'Group 3',
463 type: 'string_options',
464 separator: ',',
465 filters: [
466 {
467 name: 'filter7',
468 label: 'Group 3: Filter 1',
469 description: 'Description of Filter 1 in Group 3'
470 },
471 {
472 name: 'filter8',
473 label: 'Group 3: Filter 2',
474 description: 'Description of Filter 2 in Group 3',
475 default: true
476 },
477 {
478 name: 'filter9',
479 label: 'Group 3: Filter 3',
480 description: 'Description of Filter 3 in Group 3'
481 }
482 ]
483 }
484 },
485 defaultFilterRepresentation = {
486 // Group 1 and 2, "send_unselected_if_any", the values of the filters are "flipped" from the values of the parameters
487 hidefilter1: false,
488 hidefilter2: true,
489 hidefilter3: false,
490 hidefilter4: true,
491 hidefilter5: false,
492 hidefilter6: true,
493 // Group 3, "string_options", default values correspond to parameters and filters
494 filter7: false,
495 filter8: true,
496 filter9: false
497 },
498 model = new mw.rcfilters.dm.FiltersViewModel();
499
500 model.initializeFilters( definition );
501
502 // Empty query = only default values
503 assert.deepEqual(
504 model.getFiltersFromParameters( {} ),
505 defaultFilterRepresentation,
506 'Empty parameter query results in filters in initial default state'
507 );
508
509 assert.deepEqual(
510 model.getFiltersFromParameters( {
511 hidefilter2: '1'
512 } ),
513 $.extend( {}, defaultFilterRepresentation, {
514 hidefilter1: false, // The text is "show filter 1"
515 hidefilter2: false, // The text is "show filter 2"
516 hidefilter3: false // The text is "show filter 3"
517 } ),
518 'One truthy parameter in a group whose other parameters are true by default makes the rest of the filters in the group false (unchecked)'
519 );
520
521 assert.deepEqual(
522 model.getFiltersFromParameters( {
523 hidefilter1: '1',
524 hidefilter2: '1',
525 hidefilter3: '1'
526 } ),
527 $.extend( {}, defaultFilterRepresentation, {
528 hidefilter1: false, // The text is "show filter 1"
529 hidefilter2: false, // The text is "show filter 2"
530 hidefilter3: false // The text is "show filter 3"
531 } ),
532 'All paremeters in the same \'send_unselected_if_any\' group false is equivalent to none are truthy (checked) in the interface'
533 );
534
535 // The ones above don't update the model, so we have a clean state.
536 // getFiltersFromParameters is stateless; any change is unaffected by the current state
537 // This test is demonstrating wrong usage of the method;
538 // We should be aware that getFiltersFromParameters is stateless,
539 // so each call gives us a filter state that only reflects the query given.
540 // This means that the two calls to updateFilters() below collide.
541 // The result of the first is overridden by the result of the second,
542 // since both get a full state object from getFiltersFromParameters that **only** relates
543 // to the input it receives.
544 model.updateFilters(
545 model.getFiltersFromParameters( {
546 hidefilter1: '1'
547 } )
548 );
549
550 model.updateFilters(
551 model.getFiltersFromParameters( {
552 hidefilter6: '1'
553 } )
554 );
555
556 // The result here is ignoring the first updateFilters call
557 // We should receive default values + hidefilter6 as false
558 assert.deepEqual(
559 model.getSelectedState(),
560 $.extend( {}, defaultFilterRepresentation, {
561 hidefilter5: false,
562 hidefilter6: false
563 } ),
564 'getFiltersFromParameters does not care about previous or existing state.'
565 );
566
567 // Reset
568 model = new mw.rcfilters.dm.FiltersViewModel();
569 model.initializeFilters( definition );
570
571 model.updateFilters(
572 model.getFiltersFromParameters( {
573 hidefilter1: '0'
574 } )
575 );
576 model.updateFilters(
577 model.getFiltersFromParameters( {
578 hidefilter1: '1'
579 } )
580 );
581
582 // Simulates minor edits being hidden in preferences, then unhidden via URL
583 // override.
584 assert.deepEqual(
585 model.getSelectedState(),
586 defaultFilterRepresentation,
587 'After checking and then unchecking a \'send_unselected_if_any\' filter (without touching other filters in that group), results are default'
588 );
589
590 model.updateFilters(
591 model.getFiltersFromParameters( {
592 group3: 'filter7'
593 } )
594 );
595 assert.deepEqual(
596 model.getSelectedState(),
597 $.extend( {}, defaultFilterRepresentation, {
598 filter7: true,
599 filter8: false,
600 filter9: false
601 } ),
602 'A \'string_options\' parameter containing 1 value, results in the corresponding filter as checked'
603 );
604
605 model.updateFilters(
606 model.getFiltersFromParameters( {
607 group3: 'filter7,filter8'
608 } )
609 );
610 assert.deepEqual(
611 model.getSelectedState(),
612 $.extend( {}, defaultFilterRepresentation, {
613 filter7: true,
614 filter8: true,
615 filter9: false
616 } ),
617 'A \'string_options\' parameter containing 2 values, results in both corresponding filters as checked'
618 );
619
620 model.updateFilters(
621 model.getFiltersFromParameters( {
622 group3: 'filter7,filter8,filter9'
623 } )
624 );
625 assert.deepEqual(
626 model.getSelectedState(),
627 $.extend( {}, defaultFilterRepresentation, {
628 filter7: false,
629 filter8: false,
630 filter9: false
631 } ),
632 'A \'string_options\' parameter containing all values, results in all filters of the group as unchecked.'
633 );
634
635 model.updateFilters(
636 model.getFiltersFromParameters( {
637 group3: 'filter7,all,filter9'
638 } )
639 );
640 assert.deepEqual(
641 model.getSelectedState(),
642 $.extend( {}, defaultFilterRepresentation, {
643 filter7: false,
644 filter8: false,
645 filter9: false
646 } ),
647 'A \'string_options\' parameter containing the value \'all\', results in all filters of the group as unchecked.'
648 );
649
650 model.updateFilters(
651 model.getFiltersFromParameters( {
652 group3: 'filter7,foo,filter9'
653 } )
654 );
655 assert.deepEqual(
656 model.getSelectedState(),
657 $.extend( {}, defaultFilterRepresentation, {
658 filter7: true,
659 filter8: false,
660 filter9: true
661 } ),
662 'A \'string_options\' parameter containing an invalid value, results in the invalid value ignored and the valid corresponding filters checked.'
663 );
664 } );
665
666 QUnit.test( 'sanitizeStringOptionGroup', function ( assert ) {
667 var definition = {
668 group1: {
669 title: 'Group 1',
670 type: 'string_options',
671 filters: [
672 {
673 name: 'filter1',
674 label: 'Show filter 1',
675 description: 'Description of Filter 1 in Group 1'
676 },
677 {
678 name: 'filter2',
679 label: 'Show filter 2',
680 description: 'Description of Filter 2 in Group 1'
681 },
682 {
683 name: 'filter3',
684 label: 'Show filter 3',
685 description: 'Description of Filter 3 in Group 1'
686 }
687 ]
688 }
689 },
690 model = new mw.rcfilters.dm.FiltersViewModel();
691
692 model.initializeFilters( definition );
693
694 assert.deepEqual(
695 model.sanitizeStringOptionGroup( 'group1', [ 'filter1', 'filter1', 'filter2' ] ),
696 [ 'filter1', 'filter2' ],
697 'Remove duplicate values'
698 );
699
700 assert.deepEqual(
701 model.sanitizeStringOptionGroup( 'group1', [ 'filter1', 'foo', 'filter2' ] ),
702 [ 'filter1', 'filter2' ],
703 'Remove invalid values'
704 );
705
706 assert.deepEqual(
707 model.sanitizeStringOptionGroup( 'group1', [ 'filter1', 'all', 'filter2' ] ),
708 [ 'all' ],
709 'If any value is "all", the only value is "all".'
710 );
711 } );
712
713 QUnit.test( 'setFiltersToDefaults', function ( assert ) {
714 var definition = {
715 group1: {
716 title: 'Group 1',
717 type: 'send_unselected_if_any',
718 exclusionType: 'default',
719 filters: [
720 {
721 name: 'hidefilter1',
722 label: 'Show filter 1',
723 description: 'Description of Filter 1 in Group 1',
724 default: true
725 },
726 {
727 name: 'hidefilter2',
728 label: 'Show filter 2',
729 description: 'Description of Filter 2 in Group 1'
730 },
731 {
732 name: 'hidefilter3',
733 label: 'Show filter 3',
734 description: 'Description of Filter 3 in Group 1',
735 default: true
736 }
737 ]
738 },
739 group2: {
740 title: 'Group 2',
741 type: 'send_unselected_if_any',
742 filters: [
743 {
744 name: 'hidefilter4',
745 label: 'Show filter 4',
746 description: 'Description of Filter 1 in Group 2'
747 },
748 {
749 name: 'hidefilter5',
750 label: 'Show filter 5',
751 description: 'Description of Filter 2 in Group 2',
752 default: true
753 },
754 {
755 name: 'hidefilter6',
756 label: 'Show filter 6',
757 description: 'Description of Filter 3 in Group 2'
758 }
759 ]
760 }
761 },
762 model = new mw.rcfilters.dm.FiltersViewModel();
763
764 model.initializeFilters( definition );
765
766 assert.deepEqual(
767 model.getFullState(),
768 {
769 // Group 1
770 hidefilter1: { selected: true, active: true },
771 hidefilter2: { selected: false, active: true },
772 hidefilter3: { selected: true, active: true },
773 // Group 2
774 hidefilter4: { selected: false, active: true },
775 hidefilter5: { selected: true, active: true },
776 hidefilter6: { selected: false, active: true },
777 },
778 'Initial state: all filters are active, and select states are default.'
779 );
780
781 // Default behavior for 'exclusion' type with only 1 item selected, means that:
782 // - The items in the same group that are *not* selected are *not* active
783 // - Items in other groups are unaffected (all active)
784 model.updateFilters( {
785 hidefilter1: false,
786 hidefilter2: false,
787 hidefilter3: false,
788 hidefilter4: false,
789 hidefilter5: false,
790 hidefilter6: true
791 } );
792 assert.deepEqual(
793 model.getFullState(),
794 {
795 // Group 1: not affected
796 hidefilter1: { selected: false, active: true },
797 hidefilter2: { selected: false, active: true },
798 hidefilter3: { selected: false, active: true },
799 // Group 2: affected
800 hidefilter4: { selected: false, active: false },
801 hidefilter5: { selected: false, active: false },
802 hidefilter6: { selected: true, active: true },
803 },
804 'Default exclusion behavior with 1 item selected in the group.'
805 );
806
807 // Default behavior for 'exclusion' type with multiple items selected, but not all, means that:
808 // - The items in the same group that are *not* selected are *not* active
809 // - Items in other groups are unaffected (all active)
810 model.updateFilters( {
811 // Literally updating filters to create a clean state
812 hidefilter1: false,
813 hidefilter2: false,
814 hidefilter3: false,
815 hidefilter4: false,
816 hidefilter5: true,
817 hidefilter6: true
818 } );
819 assert.deepEqual(
820 model.getFullState(),
821 {
822 // Group 1: not affected
823 hidefilter1: { selected: false, active: true },
824 hidefilter2: { selected: false, active: true },
825 hidefilter3: { selected: false, active: true },
826 // Group 2: affected
827 hidefilter4: { selected: false, active: false },
828 hidefilter5: { selected: true, active: true },
829 hidefilter6: { selected: true, active: true },
830 },
831 'Default exclusion behavior with multiple items (but not all) selected in the group.'
832 );
833
834 // Default behavior for 'exclusion' type with all items in the group selected, means that:
835 // - All items in the group are NOT active
836 // - Items in other groups are unaffected (all active)
837 model.updateFilters( {
838 // Literally updating filters to create a clean state
839 hidefilter1: false,
840 hidefilter2: false,
841 hidefilter3: false,
842 hidefilter4: true,
843 hidefilter5: true,
844 hidefilter6: true
845 } );
846 assert.deepEqual(
847 model.getFullState(),
848 {
849 // Group 1: not affected
850 hidefilter1: { selected: false, active: true },
851 hidefilter2: { selected: false, active: true },
852 hidefilter3: { selected: false, active: true },
853 // Group 2: affected
854 hidefilter4: { selected: true, active: false },
855 hidefilter5: { selected: true, active: false },
856 hidefilter6: { selected: true, active: false },
857 },
858 'Default exclusion behavior with all items in the group.'
859 );
860 } );
861
862 QUnit.test( 'reapplyActiveFilters - "explicit" exclusion rules', function ( assert ) {
863 var definition = {
864 group1: {
865 title: 'Group 1',
866 type: 'send_unselected_if_any',
867 exclusionType: 'explicit',
868 filters: [
869 {
870 name: 'filter1',
871 excludes: [ 'filter2', 'filter3' ],
872 label: 'Show filter 1',
873 description: 'Description of Filter 1 in Group 1'
874 },
875 {
876 name: 'filter2',
877 excludes: [ 'filter3' ],
878 label: 'Show filter 2',
879 description: 'Description of Filter 2 in Group 1'
880 },
881 {
882 name: 'filter3',
883 label: 'Show filter 3',
884 excludes: [ 'filter1' ],
885 description: 'Description of Filter 3 in Group 1'
886 },
887 {
888 name: 'filter4',
889 label: 'Show filter 4',
890 description: 'Description of Filter 4 in Group 1'
891 }
892 ]
893 }
894 },
895 defaultFilterRepresentation = {
896 // Group 1 and 2, "send_unselected_if_any", the values of the filters are "flipped" from the values of the parameters
897 hidefilter1: false,
898 hidefilter2: true,
899 hidefilter3: false,
900 hidefilter4: true,
901 hidefilter5: false,
902 hidefilter6: true,
903 // Group 3, "string_options", default values correspond to parameters and filters
904 filter7: false,
905 filter8: true,
906 filter9: false
907 },
908 model = new mw.rcfilters.dm.FiltersViewModel();
909
910 model.initializeFilters( definition );
911
912 assert.deepEqual(
913 model.getFullState(),
914 {
915 filter1: { selected: false, active: true },
916 filter2: { selected: false, active: true },
917 filter3: { selected: false, active: true },
918 filter4: { selected: false, active: true }
919 },
920 'Initial state: all filters are active.'
921 );
922
923 // "Explicit" behavior for 'exclusion' with one item checked:
924 // - Items in the 'excluded' list of the selected filter are inactive
925 model.updateFilters( {
926 // Literally updating filters to create a clean state
927 filter1: true, // Excludes 'hidefilter2', 'hidefilter3'
928 filter2: false, // Excludes 'hidefilter3'
929 filter3: false, // Excludes 'hidefilter1'
930 filter4: false // No exclusion list
931 } );
932 assert.deepEqual(
933 model.getFullState(),
934 {
935 filter1: { selected: true, active: true },
936 filter2: { selected: false, active: false },
937 filter3: { selected: false, active: false },
938 filter4: { selected: false, active: true }
939 },
940 '"Explicit" exclusion behavior with one item selected that has an exclusion list.'
941 );
942
943 // "Explicit" behavior for 'exclusion' with two item checked:
944 // - Items in the 'excluded' list of each of the selected filter are inactive
945 model.updateFilters( {
946 // Literally updating filters to create a clean state
947 filter1: true, // Excludes 'hidefilter2', 'hidefilter3'
948 filter2: false, // Excludes 'hidefilter3'
949 filter3: true, // Excludes 'hidefilter1'
950 filter4: false // No exclusion list
951 } );
952 assert.deepEqual(
953 model.getFullState(),
954 {
955 filter1: { selected: true, active: false },
956 filter2: { selected: false, active: false },
957 filter3: { selected: true, active: false },
958 filter4: { selected: false, active: true }
959 },
960 '"Explicit" exclusion behavior with two selected items that both have an exclusion list.'
961 );
962
963 // "Explicit behavior" with two filters that exclude the same item
964
965 // Two filters selected, both exclude 'hidefilter3'
966 model.updateFilters( {
967 // Literally updating filters to create a clean state
968 filter1: true, // Excludes 'hidefilter2', 'hidefilter3'
969 filter2: true, // Excludes 'hidefilter3'
970 filter3: false, // Excludes 'hidefilter1'
971 filter4: false // No exclusion list
972 } );
973 assert.deepEqual(
974 model.getFullState(),
975 {
976 filter1: { selected: true, active: true },
977 filter2: { selected: true, active: false }, // Excluded by filter1
978 filter3: { selected: false, active: false }, // Excluded by both filter1 and filter2
979 filter4: { selected: false, active: true }
980 },
981 '"Explicit" exclusion behavior with two selected items that both exclude another item.'
982 );
983
984 // Unselect filter2: filter3 should still be excluded, because filter1 excludes it and is selected
985 model.updateFilters( {
986 filter2: false, // Excludes 'hidefilter3'
987 } );
988 assert.deepEqual(
989 model.getFullState(),
990 {
991 filter1: { selected: true, active: true },
992 filter2: { selected: false, active: false }, // Excluded by filter1
993 filter3: { selected: false, active: false }, // Still excluded by filter1
994 filter4: { selected: false, active: true }
995 },
996 '"Explicit" exclusion behavior unselecting one item that excludes another item, that is being excluded by a third active item.'
997 );
998
999 // Unselect filter1: filter3 should now be active, since both filters that exclude it are unselected
1000 model.updateFilters( {
1001 filter1: false, // Excludes 'hidefilter3' and 'hidefilter2'
1002 } );
1003 assert.deepEqual(
1004 model.getFullState(),
1005 {
1006 filter1: { selected: false, active: true },
1007 filter2: { selected: false, active: true }, // No longer excluded by filter1
1008 filter3: { selected: false, active: true }, // No longer excluded by either filter1 nor filter2
1009 filter4: { selected: false, active: true }
1010 },
1011 '"Explicit" exclusion behavior unselecting both items that excluded the same third item.'
1012 );
1013
1014 } );
1015 }( mediaWiki, jQuery ) );