1 | <?php |
||||
2 | |||||
3 | declare(strict_types=1); |
||||
4 | |||||
5 | namespace Yiisoft\Yii\Widgets\Tests\Dropdown; |
||||
6 | |||||
7 | use PHPUnit\Framework\TestCase; |
||||
8 | use Yiisoft\Definitions\Exception\CircularReferenceException; |
||||
9 | use Yiisoft\Definitions\Exception\InvalidConfigException; |
||||
10 | use Yiisoft\Definitions\Exception\NotInstantiableException; |
||||
11 | use Yiisoft\Factory\NotFoundException; |
||||
12 | use Yiisoft\Yii\Widgets\Dropdown; |
||||
13 | use Yiisoft\Yii\Widgets\Tests\Support\Assert; |
||||
14 | use Yiisoft\Yii\Widgets\Tests\Support\TestTrait; |
||||
15 | |||||
16 | /** |
||||
17 | * @psalm-suppress PropertyNotSetInConstructor |
||||
18 | */ |
||||
19 | final class Bootstrap5Test extends TestCase |
||||
20 | { |
||||
21 | use TestTrait; |
||||
22 | |||||
23 | /** |
||||
24 | * Add a header to label sections of actions in any dropdown menu. |
||||
25 | * |
||||
26 | * @link https://getbootstrap.com/docs/5.2/components/dropdowns/#headers |
||||
27 | * |
||||
28 | * @throws CircularReferenceException |
||||
29 | * @throws InvalidConfigException |
||||
30 | * @throws NotFoundException |
||||
31 | * @throws NotInstantiableException |
||||
32 | */ |
||||
33 | public function testHeaders(): void |
||||
34 | { |
||||
35 | $definitions = [ |
||||
36 | 'containerClass()' => ['btn-group'], |
||||
37 | 'headerClass()' => ['dropdown-header'], |
||||
38 | 'headerTag()' => ['h6'], |
||||
39 | 'itemClass()' => ['dropdown-item'], |
||||
40 | 'itemsContainerClass()' => ['dropdown-menu'], |
||||
41 | 'toggleAttributes()' => [['aria-expanded' => 'false', 'data-bs-toggle' => 'dropdown']], |
||||
42 | 'toggleClass()' => ['btn btn-secondary dropdown-toggle'], |
||||
43 | ]; |
||||
44 | |||||
45 | Assert::equalsWithoutLE( |
||||
46 | <<<HTML |
||||
47 | <div class="btn-group"> |
||||
48 | <button type="button" class="btn btn-secondary dropdown-toggle" aria-expanded="false" data-bs-toggle="dropdown">Dropdown</button> |
||||
49 | <ul class="dropdown-menu"> |
||||
50 | <li><h6 class="dropdown-header">Dropdown header</h6></li> |
||||
51 | <li><a class="dropdown-item" href="#">Action</a></li> |
||||
52 | <li><a class="dropdown-item" href="#">Another action</a></li> |
||||
53 | </ul> |
||||
54 | </div> |
||||
55 | HTML, |
||||
56 | Dropdown::widget([], $definitions) |
||||
57 | ->items( |
||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
58 | [ |
||||
59 | [ |
||||
60 | 'label' => 'Dropdown', |
||||
61 | 'link' => '#', |
||||
62 | 'items' => [ |
||||
63 | ['label' => 'Dropdown header', 'link' => ''], |
||||
64 | ['label' => 'Action', 'link' => '#'], |
||||
65 | ['label' => 'Another action', 'link' => '#'], |
||||
66 | ], |
||||
67 | ], |
||||
68 | ] |
||||
69 | ) |
||||
70 | ->render() |
||||
71 | ); |
||||
72 | } |
||||
73 | |||||
74 | /** |
||||
75 | * Similarly, create split button dropdowns with virtually the same markup as single button dropdowns, but with the |
||||
76 | * addition of `.dropdown-toggle-split` for proper spacing around the dropdown caret. |
||||
77 | * |
||||
78 | * We use this extra class to reduce the horizontal padding on either side of the caret by 25% and remove the |
||||
79 | * margin-left that’s added for regular button dropdowns. Those extra changes keep the caret centered in the split |
||||
80 | * button and provide a more appropriately sized hit area next to the main button. |
||||
81 | * |
||||
82 | * @link https://getbootstrap.com/docs/5.2/components/dropdowns/#split-button |
||||
83 | * |
||||
84 | * @throws CircularReferenceException |
||||
85 | * @throws InvalidConfigException |
||||
86 | * @throws NotFoundException |
||||
87 | * @throws NotInstantiableException |
||||
88 | */ |
||||
89 | public function testSplit(): void |
||||
90 | { |
||||
91 | $definitions = [ |
||||
92 | 'containerClass()' => ['btn-group'], |
||||
93 | 'dividerClass()' => ['dropdown-divider'], |
||||
94 | 'itemClass()' => ['dropdown-item'], |
||||
95 | 'itemsContainerClass()' => ['dropdown-menu'], |
||||
96 | 'toggleAttributes()' => [['aria-expanded' => 'false', 'data-bs-toggle' => 'dropdown']], |
||||
97 | 'toggleClass()' => ['btn btn-danger dropdown-toggle dropdown-toggle-split'], |
||||
98 | 'splitButtonClass()' => ['btn btn-danger'], |
||||
99 | 'splitButtonSpanClass()' => ['visually-hidden'], |
||||
100 | ]; |
||||
101 | |||||
102 | Assert::equalsWithoutLE( |
||||
103 | <<<HTML |
||||
104 | <div class="btn-group"> |
||||
105 | <button type="button" class="btn btn-danger">Action</button> |
||||
106 | <button type="button" id="dropdown-example" class="btn btn-danger dropdown-toggle dropdown-toggle-split" aria-expanded="false" data-bs-toggle="dropdown"><span class="visually-hidden">Action</span></button> |
||||
107 | <ul class="dropdown-menu" aria-labelledby="dropdown-example"> |
||||
108 | <li><a class="dropdown-item" href="#">Action</a></li> |
||||
109 | <li><a class="dropdown-item" href="#">Another action</a></li> |
||||
110 | <li><a class="dropdown-item" href="#">Something else here</a></li> |
||||
111 | <li><hr class="dropdown-divider"></li> |
||||
112 | <li><a class="dropdown-item" href="#">Separated link</a></li> |
||||
113 | </ul> |
||||
114 | </div> |
||||
115 | HTML, |
||||
116 | Dropdown::widget([], $definitions) |
||||
117 | ->id('dropdown-example') |
||||
0 ignored issues
–
show
The method
id() does not exist on Yiisoft\Widget\Widget . It seems like you code against a sub-type of said class. However, the method does not exist in Yiisoft\Yii\Widgets\Menu or Yiisoft\Yii\Widgets\ContentDecorator or Yiisoft\Yii\Widgets\Breadcrumbs . Are you sure you never get one of those?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
118 | ->items( |
||||
119 | [ |
||||
120 | [ |
||||
121 | 'label' => 'Action', |
||||
122 | 'link' => '#', |
||||
123 | 'items' => [ |
||||
124 | ['label' => 'Action', 'link' => '#'], |
||||
125 | ['label' => 'Another action', 'link' => '#'], |
||||
126 | ['label' => 'Something else here', 'link' => '#'], |
||||
127 | '-', |
||||
128 | ['label' => 'Separated link', 'link' => '#'], |
||||
129 | ], |
||||
130 | ], |
||||
131 | ] |
||||
132 | ) |
||||
133 | ->toggleType('link') |
||||
134 | ->toggleType('split') |
||||
135 | ->render() |
||||
136 | ); |
||||
137 | } |
||||
138 | |||||
139 | /** |
||||
140 | * @link https://getbootstrap.com/docs/5.2/components/dropdowns/#dropend |
||||
141 | * |
||||
142 | * @throws CircularReferenceException |
||||
143 | * @throws InvalidConfigException |
||||
144 | * @throws NotFoundException |
||||
145 | * @throws NotInstantiableException |
||||
146 | */ |
||||
147 | public function testSplitDropend(): void |
||||
148 | { |
||||
149 | $definitions = [ |
||||
150 | 'containerClass()' => ['btn-group dropend'], |
||||
151 | 'dividerClass()' => ['dropdown-divider'], |
||||
152 | 'itemClass()' => ['dropdown-item'], |
||||
153 | 'itemsContainerClass()' => ['dropdown-menu'], |
||||
154 | 'toggleAttributes()' => [['aria-expanded' => 'false', 'data-bs-toggle' => 'dropdown']], |
||||
155 | 'toggleClass()' => ['btn btn-secondary dropdown-toggle dropdown-toggle-split'], |
||||
156 | 'splitButtonClass()' => ['btn btn-secondary'], |
||||
157 | 'splitButtonSpanClass()' => ['visually-hidden'], |
||||
158 | ]; |
||||
159 | |||||
160 | Assert::equalsWithoutLE( |
||||
161 | <<<HTML |
||||
162 | <div class="btn-group dropend"> |
||||
163 | <button type="button" class="btn btn-secondary">Split dropend</button> |
||||
164 | <button type="button" id="dropdown-example" class="btn btn-secondary dropdown-toggle dropdown-toggle-split" aria-expanded="false" data-bs-toggle="dropdown"><span class="visually-hidden">Split dropend</span></button> |
||||
165 | <ul class="dropdown-menu" aria-labelledby="dropdown-example"> |
||||
166 | <li><a class="dropdown-item" href="#">Action</a></li> |
||||
167 | <li><a class="dropdown-item" href="#">Another action</a></li> |
||||
168 | <li><a class="dropdown-item" href="#">Something else here</a></li> |
||||
169 | <li><hr class="dropdown-divider"></li> |
||||
170 | <li><a class="dropdown-item" href="#">Separated link</a></li> |
||||
171 | </ul> |
||||
172 | </div> |
||||
173 | HTML, |
||||
174 | Dropdown::widget([], $definitions) |
||||
175 | ->id('dropdown-example') |
||||
176 | ->items( |
||||
177 | [ |
||||
178 | [ |
||||
179 | 'label' => 'Split dropend', |
||||
180 | 'link' => '#', |
||||
181 | 'items' => [ |
||||
182 | ['label' => 'Action', 'link' => '#'], |
||||
183 | ['label' => 'Another action', 'link' => '#'], |
||||
184 | ['label' => 'Something else here', 'link' => '#'], |
||||
185 | '-', |
||||
186 | ['label' => 'Separated link', 'link' => '#'], |
||||
187 | ], |
||||
188 | ], |
||||
189 | ] |
||||
190 | ) |
||||
191 | ->toggleType('link') |
||||
192 | ->toggleType('split') |
||||
193 | ->render() |
||||
194 | ); |
||||
195 | } |
||||
196 | |||||
197 | /** |
||||
198 | * @link https://getbootstrap.com/docs/5.2/components/dropdowns/#dropstart |
||||
199 | * |
||||
200 | * @throws CircularReferenceException |
||||
201 | * @throws InvalidConfigException |
||||
202 | * @throws NotFoundException |
||||
203 | * @throws NotInstantiableException |
||||
204 | */ |
||||
205 | public function testSplitDropStart(): void |
||||
206 | { |
||||
207 | $definitions = [ |
||||
208 | 'containerClass()' => ['btn-group dropstart'], |
||||
209 | 'dividerClass()' => ['dropdown-divider'], |
||||
210 | 'itemClass()' => ['dropdown-item'], |
||||
211 | 'itemsContainerClass()' => ['dropdown-menu'], |
||||
212 | 'toggleAttributes()' => [['aria-expanded' => 'false', 'data-bs-toggle' => 'dropdown']], |
||||
213 | 'toggleClass()' => ['btn btn-secondary dropdown-toggle dropdown-toggle-split'], |
||||
214 | 'splitButtonClass()' => ['btn btn-secondary'], |
||||
215 | 'splitButtonSpanClass()' => ['visually-hidden'], |
||||
216 | ]; |
||||
217 | |||||
218 | Assert::equalsWithoutLE( |
||||
219 | <<<HTML |
||||
220 | <div class="btn-group dropstart"> |
||||
221 | <button type="button" id="dropdown-example" class="btn btn-secondary dropdown-toggle dropdown-toggle-split" aria-expanded="false" data-bs-toggle="dropdown"><span class="visually-hidden">Split dropstart</span></button> |
||||
222 | <ul class="dropdown-menu" aria-labelledby="dropdown-example"> |
||||
223 | <li><a class="dropdown-item" href="#">Action</a></li> |
||||
224 | <li><a class="dropdown-item" href="#">Another action</a></li> |
||||
225 | <li><a class="dropdown-item" href="#">Something else here</a></li> |
||||
226 | <li><hr class="dropdown-divider"></li> |
||||
227 | <li><a class="dropdown-item" href="#">Separated link</a></li> |
||||
228 | </ul> |
||||
229 | <button type="button" class="btn btn-secondary">Split dropstart</button> |
||||
230 | </div> |
||||
231 | HTML, |
||||
232 | Dropdown::widget([], $definitions) |
||||
233 | ->id('dropdown-example') |
||||
234 | ->items( |
||||
235 | [ |
||||
236 | [ |
||||
237 | 'label' => 'Split dropstart', |
||||
238 | 'link' => '#', |
||||
239 | 'items' => [ |
||||
240 | ['label' => 'Action', 'link' => '#'], |
||||
241 | ['label' => 'Another action', 'link' => '#'], |
||||
242 | ['label' => 'Something else here', 'link' => '#'], |
||||
243 | '-', |
||||
244 | ['label' => 'Separated link', 'link' => '#'], |
||||
245 | ], |
||||
246 | ], |
||||
247 | ] |
||||
248 | ) |
||||
249 | ->toggleType('link') |
||||
250 | ->toggleType('split') |
||||
251 | ->render() |
||||
252 | ); |
||||
253 | } |
||||
254 | |||||
255 | /** |
||||
256 | * @link https://getbootstrap.com/docs/5.2/components/dropdowns/#dropup |
||||
257 | * |
||||
258 | * @throws CircularReferenceException |
||||
259 | * @throws InvalidConfigException |
||||
260 | * @throws NotFoundException |
||||
261 | * @throws NotInstantiableException |
||||
262 | */ |
||||
263 | public function testSplitDropup(): void |
||||
264 | { |
||||
265 | $definitions = [ |
||||
266 | 'containerClass()' => ['btn-group dropup'], |
||||
267 | 'dividerClass()' => ['dropdown-divider'], |
||||
268 | 'itemClass()' => ['dropdown-item'], |
||||
269 | 'itemsContainerClass()' => ['dropdown-menu'], |
||||
270 | 'toggleAttributes()' => [['aria-expanded' => 'false', 'data-bs-toggle' => 'dropdown']], |
||||
271 | 'toggleClass()' => ['btn btn-secondary dropdown-toggle dropdown-toggle-split'], |
||||
272 | 'splitButtonClass()' => ['btn btn-secondary'], |
||||
273 | 'splitButtonSpanClass()' => ['visually-hidden'], |
||||
274 | ]; |
||||
275 | |||||
276 | Assert::equalsWithoutLE( |
||||
277 | <<<HTML |
||||
278 | <div class="btn-group dropup"> |
||||
279 | <button type="button" class="btn btn-secondary">Split dropup</button> |
||||
280 | <button type="button" id="dropdown-example" class="btn btn-secondary dropdown-toggle dropdown-toggle-split" aria-expanded="false" data-bs-toggle="dropdown"><span class="visually-hidden">Split dropup</span></button> |
||||
281 | <ul class="dropdown-menu" aria-labelledby="dropdown-example"> |
||||
282 | <li><a class="dropdown-item" href="#">Action</a></li> |
||||
283 | <li><a class="dropdown-item" href="#">Another action</a></li> |
||||
284 | <li><a class="dropdown-item" href="#">Something else here</a></li> |
||||
285 | <li><hr class="dropdown-divider"></li> |
||||
286 | <li><a class="dropdown-item" href="#">Separated link</a></li> |
||||
287 | </ul> |
||||
288 | </div> |
||||
289 | HTML, |
||||
290 | Dropdown::widget([], $definitions) |
||||
291 | ->id('dropdown-example') |
||||
292 | ->items( |
||||
293 | [ |
||||
294 | [ |
||||
295 | 'label' => 'Split dropup', |
||||
296 | 'link' => '#', |
||||
297 | 'items' => [ |
||||
298 | ['label' => 'Action', 'link' => '#'], |
||||
299 | ['label' => 'Another action', 'link' => '#'], |
||||
300 | ['label' => 'Something else here', 'link' => '#'], |
||||
301 | '-', |
||||
302 | ['label' => 'Separated link', 'link' => '#'], |
||||
303 | ], |
||||
304 | ], |
||||
305 | ] |
||||
306 | ) |
||||
307 | ->toggleType('link') |
||||
308 | ->toggleType('split') |
||||
309 | ->render() |
||||
310 | ); |
||||
311 | } |
||||
312 | |||||
313 | /** |
||||
314 | * @link https://getbootstrap.com/docs/5.2/components/dropdowns/#sizing |
||||
315 | * |
||||
316 | * @throws CircularReferenceException |
||||
317 | * @throws InvalidConfigException |
||||
318 | * @throws NotFoundException |
||||
319 | * @throws NotInstantiableException |
||||
320 | */ |
||||
321 | public function testSplitSizingWithLargeButton(): void |
||||
322 | { |
||||
323 | $definitions = [ |
||||
324 | 'containerClass()' => ['btn-group'], |
||||
325 | 'dividerClass()' => ['dropdown-divider'], |
||||
326 | 'itemClass()' => ['dropdown-item'], |
||||
327 | 'itemsContainerClass()' => ['dropdown-menu'], |
||||
328 | 'toggleAttributes()' => [['aria-expanded' => 'false', 'data-bs-toggle' => 'dropdown']], |
||||
329 | 'toggleClass()' => ['btn btn-lg btn-secondary dropdown-toggle dropdown-toggle-split'], |
||||
330 | 'splitButtonClass()' => ['btn btn-secondary btn-lg'], |
||||
331 | 'splitButtonSpanClass()' => ['visually-hidden'], |
||||
332 | ]; |
||||
333 | |||||
334 | Assert::equalsWithoutLE( |
||||
335 | <<<HTML |
||||
336 | <div class="btn-group"> |
||||
337 | <button type="button" class="btn btn-secondary btn-lg">Large split button</button> |
||||
338 | <button type="button" id="dropdown-example" class="btn btn-lg btn-secondary dropdown-toggle dropdown-toggle-split" aria-expanded="false" data-bs-toggle="dropdown"><span class="visually-hidden">Large split button</span></button> |
||||
339 | <ul class="dropdown-menu" aria-labelledby="dropdown-example"> |
||||
340 | <li><a class="dropdown-item" href="#">Action</a></li> |
||||
341 | <li><a class="dropdown-item" href="#">Another action</a></li> |
||||
342 | <li><a class="dropdown-item" href="#">Something else here</a></li> |
||||
343 | <li><hr class="dropdown-divider"></li> |
||||
344 | <li><a class="dropdown-item" href="#">Separated link</a></li> |
||||
345 | </ul> |
||||
346 | </div> |
||||
347 | HTML, |
||||
348 | Dropdown::widget([], $definitions) |
||||
349 | ->id('dropdown-example') |
||||
350 | ->items( |
||||
351 | [ |
||||
352 | [ |
||||
353 | 'label' => 'Large split button', |
||||
354 | 'link' => '#', |
||||
355 | 'items' => [ |
||||
356 | ['label' => 'Action', 'link' => '#'], |
||||
357 | ['label' => 'Another action', 'link' => '#'], |
||||
358 | ['label' => 'Something else here', 'link' => '#'], |
||||
359 | '-', |
||||
360 | ['label' => 'Separated link', 'link' => '#'], |
||||
361 | ], |
||||
362 | ], |
||||
363 | ] |
||||
364 | ) |
||||
365 | ->toggleType('split') |
||||
366 | ->render() |
||||
367 | ); |
||||
368 | } |
||||
369 | |||||
370 | /** |
||||
371 | * @link https://getbootstrap.com/docs/5.2/components/dropdowns/#sizing |
||||
372 | * |
||||
373 | * @throws CircularReferenceException |
||||
374 | * @throws InvalidConfigException |
||||
375 | * @throws NotFoundException |
||||
376 | * @throws NotInstantiableException |
||||
377 | */ |
||||
378 | public function testSplitSizingWithSmallButton(): void |
||||
379 | { |
||||
380 | $definitions = [ |
||||
381 | 'containerClass()' => ['btn-group'], |
||||
382 | 'dividerClass()' => ['dropdown-divider'], |
||||
383 | 'itemClass()' => ['dropdown-item'], |
||||
384 | 'itemsContainerClass()' => ['dropdown-menu'], |
||||
385 | 'toggleAttributes()' => [['aria-expanded' => 'false', 'data-bs-toggle' => 'dropdown']], |
||||
386 | 'toggleClass()' => ['btn btn-sm btn-secondary dropdown-toggle dropdown-toggle-split'], |
||||
387 | 'splitButtonClass()' => ['btn btn-secondary btn-sm'], |
||||
388 | 'splitButtonSpanClass()' => ['visually-hidden'], |
||||
389 | ]; |
||||
390 | |||||
391 | Assert::equalsWithoutLE( |
||||
392 | <<<HTML |
||||
393 | <div class="btn-group"> |
||||
394 | <button type="button" class="btn btn-secondary btn-sm">Large split button</button> |
||||
395 | <button type="button" id="dropdown-example" class="btn btn-sm btn-secondary dropdown-toggle dropdown-toggle-split" aria-expanded="false" data-bs-toggle="dropdown"><span class="visually-hidden">Large split button</span></button> |
||||
396 | <ul class="dropdown-menu" aria-labelledby="dropdown-example"> |
||||
397 | <li><a class="dropdown-item" href="#">Action</a></li> |
||||
398 | <li><a class="dropdown-item" href="#">Another action</a></li> |
||||
399 | <li><a class="dropdown-item" href="#">Something else here</a></li> |
||||
400 | <li><hr class="dropdown-divider"></li> |
||||
401 | <li><a class="dropdown-item" href="#">Separated link</a></li> |
||||
402 | </ul> |
||||
403 | </div> |
||||
404 | HTML, |
||||
405 | Dropdown::widget([], $definitions) |
||||
406 | ->id('dropdown-example') |
||||
407 | ->items( |
||||
408 | [ |
||||
409 | [ |
||||
410 | 'label' => 'Large split button', |
||||
411 | 'link' => '#', |
||||
412 | 'items' => [ |
||||
413 | ['label' => 'Action', 'link' => '#'], |
||||
414 | ['label' => 'Another action', 'link' => '#'], |
||||
415 | ['label' => 'Something else here', 'link' => '#'], |
||||
416 | '-', |
||||
417 | ['label' => 'Separated link', 'link' => '#'], |
||||
418 | ], |
||||
419 | ], |
||||
420 | ] |
||||
421 | ) |
||||
422 | ->toggleType('split') |
||||
423 | ->render() |
||||
424 | ); |
||||
425 | } |
||||
426 | } |
||||
427 |