‪TYPO3CMS  ‪main
SelectItemProcessorTest.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use PHPUnit\Framework\Attributes\DataProvider;
21 use PHPUnit\Framework\Attributes\Test;
26 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
27 
28 final class ‪SelectItemProcessorTest extends UnitTestCase
29 {
30  public static function ‪dividersAddedForEachGroupAndSortedDataProvider(): iterable
31  {
32  yield 'All empty' => [
33  'items' => [],
34  'groups' => [],
35  'sortOrders' => [],
36  'expected' => [],
37  ];
38 
39  yield 'no groups' => [
40  'items' => [
41  [
42  'label' => 'foo',
43  'value' => 'three',
44  ],
45  [
46  'label' => 'foo',
47  'value' => 'one',
48  ],
49  [
50  'label' => 'foo',
51  'value' => 'four',
52  ],
53  [
54  'label' => 'foo',
55  'value' => 'two',
56  ],
57  ],
58  'groups' => [],
59  'sortOrders' => [],
60  'expected' => [
61  [
62  'label' => 'foo',
63  'value' => 'three',
64  'icon' => null,
65  'group' => null,
66  'description' => null,
67  ],
68  [
69  'label' => 'foo',
70  'value' => 'one',
71  'icon' => null,
72  'group' => null,
73  'description' => null,
74  ],
75  [
76  'label' => 'foo',
77  'value' => 'four',
78  'icon' => null,
79  'group' => null,
80  'description' => null,
81  ],
82  [
83  'label' => 'foo',
84  'value' => 'two',
85  'icon' => null,
86  'group' => null,
87  'description' => null,
88  ],
89  ],
90  ];
91 
92  yield 'some with group, some without' => [
93  'items' => [
94  [
95  'label' => 'foo',
96  'value' => 'three',
97  'group' => 'group1',
98  ],
99  [
100  'label' => 'foo',
101  'value' => 'one',
102  'group' => 'group1',
103  ],
104  [
105  'label' => 'foo',
106  'value' => 'four',
107  ],
108  [
109  'label' => 'foo',
110  'value' => 'two',
111  ],
112  ],
113  'groups' => [
114  'group1' => 'Group 1',
115  ],
116  'sortOrders' => [],
117  'expected' => [
118  [
119  'label' => 'foo',
120  'value' => 'four',
121  'icon' => null,
122  'group' => 'none',
123  'description' => null,
124  ],
125  [
126  'label' => 'foo',
127  'value' => 'two',
128  'icon' => null,
129  'group' => 'none',
130  'description' => null,
131  ],
132  [
133  'label' => 'Group 1',
134  'value' => '--div--',
135  'group' => 'group1',
136  ],
137  [
138  'label' => 'foo',
139  'value' => 'three',
140  'icon' => null,
141  'group' => 'group1',
142  'description' => null,
143  ],
144  [
145  'label' => 'foo',
146  'value' => 'one',
147  'icon' => null,
148  'group' => 'group1',
149  'description' => null,
150  ],
151  ],
152  ];
153 
154  yield 'groups assigned, but not defined' => [
155  'items' => [
156  [
157  'label' => 'foo',
158  'value' => 'three',
159  'group' => 'group2',
160  ],
161  [
162  'label' => 'foo',
163  'value' => 'one',
164  'group' => 'group1',
165  ],
166  [
167  'label' => 'foo',
168  'value' => 'four',
169  'group' => 'group2',
170  ],
171  [
172  'label' => 'foo',
173  'value' => 'two',
174  'group' => 'group1',
175  ],
176  ],
177  'groups' => [],
178  'sortOrders' => [],
179  'expected' => [
180  [
181  'label' => 'group2',
182  'value' => '--div--',
183  'group' => 'group2',
184  ],
185  [
186  'label' => 'foo',
187  'value' => 'three',
188  'icon' => null,
189  'group' => 'group2',
190  'description' => null,
191  ],
192  [
193  'label' => 'foo',
194  'value' => 'four',
195  'icon' => null,
196  'group' => 'group2',
197  'description' => null,
198  ],
199  [
200  'label' => 'group1',
201  'value' => '--div--',
202  'group' => 'group1',
203  ],
204  [
205  'label' => 'foo',
206  'value' => 'one',
207  'icon' => null,
208  'group' => 'group1',
209  'description' => null,
210  ],
211  [
212  'label' => 'foo',
213  'value' => 'two',
214  'icon' => null,
215  'group' => 'group1',
216  'description' => null,
217  ],
218  ],
219  ];
220 
221  yield 'mixed order, default sorting' => [
222  'items' => [
223  [
224  'label' => 'foo',
225  'value' => 'three',
226  'group' => 'group2',
227  ],
228  [
229  'label' => 'foo',
230  'value' => 'one',
231  'group' => 'group1',
232  ],
233  [
234  'label' => 'foo',
235  'value' => 'four',
236  'group' => 'group2',
237  ],
238  [
239  'label' => 'foo',
240  'value' => 'two',
241  'group' => 'group1',
242  ],
243  ],
244  'groups' => [
245  'group1' => 'Group 1',
246  'group2' => 'Group 2',
247  ],
248  'sortOrders' => [],
249  'expected' => [
250  [
251  'label' => 'Group 1',
252  'value' => '--div--',
253  'group' => 'group1',
254  ],
255  [
256  'label' => 'foo',
257  'value' => 'one',
258  'icon' => null,
259  'group' => 'group1',
260  'description' => null,
261  ],
262  [
263  'label' => 'foo',
264  'value' => 'two',
265  'icon' => null,
266  'group' => 'group1',
267  'description' => null,
268  ],
269  [
270  'label' => 'Group 2',
271  'value' => '--div--',
272  'group' => 'group2',
273  ],
274  [
275  'label' => 'foo',
276  'value' => 'three',
277  'icon' => null,
278  'group' => 'group2',
279  'description' => null,
280  ],
281  [
282  'label' => 'foo',
283  'value' => 'four',
284  'icon' => null,
285  'group' => 'group2',
286  'description' => null,
287  ],
288  ],
289  ];
290 
291  yield 'legacy dividers defined in items together with groups are ignored' => [
292  'items' => [
293  [
294  'label' => 'manual group 1',
295  'value' => '--div--',
296  ],
297  [
298  'label' => 'foo',
299  'value' => 'three',
300  'group' => 'group2',
301  ],
302  [
303  'label' => 'foo',
304  'value' => 'one',
305  'group' => 'group1',
306  ],
307  [
308  'label' => 'manual group 2',
309  'value' => '--div--',
310  ],
311  [
312  'label' => 'foo',
313  'value' => 'four',
314  'group' => 'group2',
315  ],
316  [
317  'label' => 'foo',
318  'value' => 'two',
319  'group' => 'group1',
320  ],
321  ],
322  'groups' => [
323  'group1' => 'Group 1',
324  'group2' => 'Group 2',
325  ],
326  'sortOrders' => [],
327  'expected' => [
328  [
329  'label' => 'Group 1',
330  'value' => '--div--',
331  'group' => 'group1',
332  ],
333  [
334  'label' => 'foo',
335  'value' => 'one',
336  'icon' => null,
337  'group' => 'group1',
338  'description' => null,
339  ],
340  [
341  'label' => 'foo',
342  'value' => 'two',
343  'icon' => null,
344  'group' => 'group1',
345  'description' => null,
346  ],
347  [
348  'label' => 'Group 2',
349  'value' => '--div--',
350  'group' => 'group2',
351  ],
352  [
353  'label' => 'foo',
354  'value' => 'three',
355  'icon' => null,
356  'group' => 'group2',
357  'description' => null,
358  ],
359  [
360  'label' => 'foo',
361  'value' => 'four',
362  'icon' => null,
363  'group' => 'group2',
364  'description' => null,
365  ],
366  ],
367  ];
368 
369  yield 'legacy dividers with group defined in items together with groups override label' => [
370  'items' => [
371  [
372  'label' => 'manual group 1',
373  'value' => '--div--',
374  'group' => 'group1',
375  ],
376  [
377  'label' => 'foo',
378  'value' => 'three',
379  'group' => 'group2',
380  ],
381  [
382  'label' => 'foo',
383  'value' => 'one',
384  'group' => 'group1',
385  ],
386  [
387  'label' => 'manual group 2',
388  'value' => '--div--',
389  'group' => 'group2',
390  ],
391  [
392  'label' => 'foo',
393  'value' => 'four',
394  'group' => 'group2',
395  ],
396  [
397  'label' => 'foo',
398  'value' => 'two',
399  'group' => 'group1',
400  ],
401  ],
402  'groups' => [
403  'group1' => 'Group 1',
404  'group2' => 'Group 2',
405  ],
406  'sortOrders' => [],
407  'expected' => [
408  [
409  'label' => 'manual group 1',
410  'value' => '--div--',
411  'group' => 'group1',
412  ],
413  [
414  'label' => 'foo',
415  'value' => 'one',
416  'icon' => null,
417  'group' => 'group1',
418  'description' => null,
419  ],
420  [
421  'label' => 'foo',
422  'value' => 'two',
423  'icon' => null,
424  'group' => 'group1',
425  'description' => null,
426  ],
427  [
428  'label' => 'manual group 2',
429  'value' => '--div--',
430  'group' => 'group2',
431  ],
432  [
433  'label' => 'foo',
434  'value' => 'three',
435  'icon' => null,
436  'group' => 'group2',
437  'description' => null,
438  ],
439  [
440  'label' => 'foo',
441  'value' => 'four',
442  'icon' => null,
443  'group' => 'group2',
444  'description' => null,
445  ],
446  ],
447  ];
448 
449  yield 'mixed order, sort by value asc' => [
450  'items' => [
451  [
452  'label' => 'foo',
453  'value' => 'three',
454  'group' => 'group2',
455  ],
456  [
457  'label' => 'foo',
458  'value' => 'one',
459  'group' => 'group1',
460  ],
461  [
462  'label' => 'foo',
463  'value' => 'four',
464  'group' => 'group2',
465  ],
466  [
467  'label' => 'foo',
468  'value' => 'two',
469  'group' => 'group1',
470  ],
471  ],
472  'groups' => [
473  'group1' => 'Group 1',
474  'group2' => 'Group 2',
475  ],
476  'sortOrders' => [
477  'value' => 'asc',
478  ],
479  'expected' => [
480  [
481  'label' => 'Group 1',
482  'value' => '--div--',
483  'group' => 'group1',
484  ],
485  [
486  'label' => 'foo',
487  'value' => 'one',
488  'icon' => null,
489  'group' => 'group1',
490  'description' => null,
491  ],
492  [
493  'label' => 'foo',
494  'value' => 'two',
495  'icon' => null,
496  'group' => 'group1',
497  'description' => null,
498  ],
499  [
500  'label' => 'Group 2',
501  'value' => '--div--',
502  'group' => 'group2',
503  ],
504  [
505  'label' => 'foo',
506  'value' => 'four',
507  'icon' => null,
508  'group' => 'group2',
509  'description' => null,
510  ],
511  [
512  'label' => 'foo',
513  'value' => 'three',
514  'icon' => null,
515  'group' => 'group2',
516  'description' => null,
517  ],
518  ],
519  ];
520 
521  yield 'mixed order, sort by value desc' => [
522  'items' => [
523  [
524  'label' => 'foo',
525  'value' => 'three',
526  'group' => 'group2',
527  ],
528  [
529  'label' => 'foo',
530  'value' => 'one',
531  'group' => 'group1',
532  ],
533  [
534  'label' => 'foo',
535  'value' => 'four',
536  'group' => 'group2',
537  ],
538  [
539  'label' => 'foo',
540  'value' => 'two',
541  'group' => 'group1',
542  ],
543  ],
544  'groups' => [
545  'group1' => 'Group 1',
546  'group2' => 'Group 2',
547  ],
548  'sortOrders' => [
549  'value' => 'desc',
550  ],
551  'expected' => [
552  [
553  'label' => 'Group 1',
554  'value' => '--div--',
555  'group' => 'group1',
556  ],
557  [
558  'label' => 'foo',
559  'value' => 'two',
560  'icon' => null,
561  'group' => 'group1',
562  'description' => null,
563  ],
564  [
565  'label' => 'foo',
566  'value' => 'one',
567  'icon' => null,
568  'group' => 'group1',
569  'description' => null,
570  ],
571  [
572  'label' => 'Group 2',
573  'value' => '--div--',
574  'group' => 'group2',
575  ],
576  [
577  'label' => 'foo',
578  'value' => 'three',
579  'icon' => null,
580  'group' => 'group2',
581  'description' => null,
582  ],
583  [
584  'label' => 'foo',
585  'value' => 'four',
586  'icon' => null,
587  'group' => 'group2',
588  'description' => null,
589  ],
590  ],
591  ];
592 
593  yield 'mixed order, sort by label asc' => [
594  'items' => [
595  [
596  'label' => 'Three',
597  'value' => 'three',
598  'group' => 'group2',
599  ],
600  [
601  'label' => 'One',
602  'value' => 'one',
603  'group' => 'group1',
604  ],
605  [
606  'label' => 'Four',
607  'value' => 'four',
608  'group' => 'group2',
609  ],
610  [
611  'label' => 'Two',
612  'value' => 'two',
613  'group' => 'group1',
614  ],
615  ],
616  'groups' => [
617  'group1' => 'Group 1',
618  'group2' => 'Group 2',
619  ],
620  'sortOrders' => [
621  'label' => 'asc',
622  ],
623  'expected' => [
624  [
625  'label' => 'Group 1',
626  'value' => '--div--',
627  'group' => 'group1',
628  ],
629  [
630  'label' => 'One',
631  'value' => 'one',
632  'icon' => null,
633  'group' => 'group1',
634  'description' => null,
635  ],
636  [
637  'label' => 'Two',
638  'value' => 'two',
639  'icon' => null,
640  'group' => 'group1',
641  'description' => null,
642  ],
643  [
644  'label' => 'Group 2',
645  'value' => '--div--',
646  'group' => 'group2',
647  ],
648  [
649  'label' => 'Four',
650  'value' => 'four',
651  'icon' => null,
652  'group' => 'group2',
653  'description' => null,
654  ],
655  [
656  'label' => 'Three',
657  'value' => 'three',
658  'icon' => null,
659  'group' => 'group2',
660  'description' => null,
661  ],
662  ],
663  ];
664 
665  yield 'mixed order, sort by label desc' => [
666  'items' => [
667  [
668  'label' => 'Three',
669  'value' => 'three',
670  'group' => 'group2',
671  ],
672  [
673  'label' => 'One',
674  'value' => 'one',
675  'group' => 'group1',
676  ],
677  [
678  'label' => 'Four',
679  'value' => 'four',
680  'group' => 'group2',
681  ],
682  [
683  'label' => 'Two',
684  'value' => 'two',
685  'group' => 'group1',
686  ],
687  ],
688  'groups' => [
689  'group1' => 'Group 1',
690  'group2' => 'Group 2',
691  ],
692  'sortOrders' => [
693  'label' => 'desc',
694  ],
695  'expected' => [
696  [
697  'label' => 'Group 1',
698  'value' => '--div--',
699  'group' => 'group1',
700  ],
701  [
702  'label' => 'Two',
703  'value' => 'two',
704  'icon' => null,
705  'group' => 'group1',
706  'description' => null,
707  ],
708  [
709  'label' => 'One',
710  'value' => 'one',
711  'icon' => null,
712  'group' => 'group1',
713  'description' => null,
714  ],
715  [
716  'label' => 'Group 2',
717  'value' => '--div--',
718  'group' => 'group2',
719  ],
720  [
721  'label' => 'Three',
722  'value' => 'three',
723  'icon' => null,
724  'group' => 'group2',
725  'description' => null,
726  ],
727  [
728  'label' => 'Four',
729  'value' => 'four',
730  'icon' => null,
731  'group' => 'group2',
732  'description' => null,
733  ],
734  ],
735  ];
736 
737  yield 'mixed order, sort by label asc value asc' => [
738  'items' => [
739  [
740  'label' => 'Foo',
741  'value' => 'three',
742  'group' => 'group2',
743  ],
744  [
745  'label' => 'Foo',
746  'value' => 'one',
747  'group' => 'group1',
748  ],
749  [
750  'label' => 'Foo',
751  'value' => 'four',
752  'group' => 'group2',
753  ],
754  [
755  'label' => 'Foo',
756  'value' => 'two',
757  'group' => 'group1',
758  ],
759  ],
760  'groups' => [
761  'group1' => 'Group 1',
762  'group2' => 'Group 2',
763  ],
764  'sortOrders' => [
765  'label' => 'asc',
766  'value' => 'asc',
767  ],
768  'expected' => [
769  [
770  'label' => 'Group 1',
771  'value' => '--div--',
772  'group' => 'group1',
773  ],
774  [
775  'label' => 'Foo',
776  'value' => 'one',
777  'icon' => null,
778  'group' => 'group1',
779  'description' => null,
780  ],
781  [
782  'label' => 'Foo',
783  'value' => 'two',
784  'icon' => null,
785  'group' => 'group1',
786  'description' => null,
787  ],
788  [
789  'label' => 'Group 2',
790  'value' => '--div--',
791  'group' => 'group2',
792  ],
793  [
794  'label' => 'Foo',
795  'value' => 'four',
796  'icon' => null,
797  'group' => 'group2',
798  'description' => null,
799  ],
800  [
801  'label' => 'Foo',
802  'value' => 'three',
803  'icon' => null,
804  'group' => 'group2',
805  'description' => null,
806  ],
807  ],
808  ];
809  }
810 
811  #[DataProvider('dividersAddedForEachGroupAndSortedDataProvider')]
812  #[Test]
813  public function ‪dividersAreAddedForEachGroupWithLanguageServiceFactoryFallback(array $items, array $groups, array $sortOrders, array $expected): void
814  {
815  ‪$GLOBALS['BE_USER'] = $this->getMockBuilder(BackendUserAuthentication::class)->getMock();
816  $languageServiceMock = $this->createMock(LanguageService::class);
817  $languageServiceMock->method('sL')->willReturnArgument(0);
818  $languageServiceFactoryMock = $this->createMock(LanguageServiceFactory::class);
819  $languageServiceFactoryMock->method('createFromUserPreferences')->with(self::anything())->willReturn($languageServiceMock);
820  $selectItemProcessor = new ‪SelectItemProcessor($languageServiceFactoryMock);
821  $result = $selectItemProcessor->groupAndSortItems($items, $groups, $sortOrders);
822 
823  self::assertSame($expected, $result);
824  }
825 
826  #[DataProvider('dividersAddedForEachGroupAndSortedDataProvider')]
827  #[Test]
828  public function ‪dividersAreAddedForEachGroupWithGlobalLang(array $items, array $groups, array $sortOrders, array $expected): void
829  {
830  ‪$GLOBALS['BE_USER'] = $this->getMockBuilder(BackendUserAuthentication::class)->getMock();
831  $languageServiceMock = $this->createMock(LanguageService::class);
832  $languageServiceMock->method('sL')->willReturnArgument(0);
833  ‪$GLOBALS['LANG'] = $languageServiceMock;
834  $languageServiceFactoryMock = $this->createMock(LanguageServiceFactory::class);
835  $languageServiceFactoryMock->method('createFromUserPreferences')->with(self::anything())->willReturnCallback(static function () {
836  throw new \RuntimeException(
837  'LanguageServiceFactory->createFromUserPreferences() should not be called in ' . __METHOD__,
838  1689946260
839  );
840  });
841  $selectItemProcessor = new ‪SelectItemProcessor($languageServiceFactoryMock);
842  $result = $selectItemProcessor->groupAndSortItems($items, $groups, $sortOrders);
843 
844  self::assertSame($expected, $result);
845  }
846 }
‪TYPO3\CMS\Core\Localization\LanguageServiceFactory
Definition: LanguageServiceFactory.php:25
‪TYPO3\CMS\Backend\Tests\Unit\Form\Processor\SelectItemProcessorTest\dividersAddedForEachGroupAndSortedDataProvider
‪static dividersAddedForEachGroupAndSortedDataProvider()
Definition: SelectItemProcessorTest.php:30
‪TYPO3\CMS\Backend\Tests\Unit\Form\Processor\SelectItemProcessorTest
Definition: SelectItemProcessorTest.php:29
‪TYPO3\CMS\Backend\Tests\Unit\Form\Processor
Definition: SelectItemProcessorTest.php:18
‪TYPO3\CMS\Backend\Tests\Unit\Form\Processor\SelectItemProcessorTest\dividersAreAddedForEachGroupWithLanguageServiceFactoryFallback
‪dividersAreAddedForEachGroupWithLanguageServiceFactoryFallback(array $items, array $groups, array $sortOrders, array $expected)
Definition: SelectItemProcessorTest.php:813
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:62
‪TYPO3\CMS\Backend\Form\Processor\SelectItemProcessor
Definition: SelectItemProcessor.php:33
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Backend\Tests\Unit\Form\Processor\SelectItemProcessorTest\dividersAreAddedForEachGroupWithGlobalLang
‪dividersAreAddedForEachGroupWithGlobalLang(array $items, array $groups, array $sortOrders, array $expected)
Definition: SelectItemProcessorTest.php:828
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:46