ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
TreeSelectTest.php
Go to the documentation of this file.
1<?php
2
18declare(strict_types=1);
19
24use PHPUnit\Framework\MockObject\MockObject;
25
26require_once(__DIR__ . "/../../../../../../../vendor/composer/vendor/autoload.php");
27require_once(__DIR__ . "/../../../Base.php");
28require_once(__DIR__ . "/InputTest.php");
29
34{
35 protected Component\Button\Bulky & MockObject $bulky_stub;
36 protected string $bulky_html;
37 protected Component\Link\Standard & MockObject $link_stub;
38 protected string $link_html;
40 protected string $drilldown_html;
42 protected string $breadcrumbs_html;
43
44 protected Component\SignalGeneratorInterface $signal_generator;
46
47 protected function setUp(): void
48 {
53
54 $this->signal_generator = new IncrementalSignalGenerator();
55
56 $this->menu_factory = $this->createMock(Component\Menu\Factory::class);
57 $this->menu_factory->method('drilldown')->willReturn($this->drilldown_stub);
58
59 parent::setUp();
60 }
61
62 public function getDefaultRenderer(
63 ?JavaScriptBinding $js_binding = null,
64 array $with_stub_renderings = [],
65 array $with_additional_contexts = [],
67 $with_stub_renderings = array_merge($with_stub_renderings, [
68 $this->bulky_stub,
69 $this->drilldown_stub,
70 $this->breadcrumbs_stub,
71 ]);
72
73 return parent::getDefaultRenderer($js_binding, $with_stub_renderings, $with_additional_contexts);
74 }
75
76 public function getUIFactory(): \NoUIFactory
77 {
78 $icon_factory = $this->createMock(Component\Symbol\Icon\Factory::class);
79 $glyph_factory = $this->createMock(Component\Symbol\Glyph\Factory::class);
80 $glyph_mock = $this->createMock(Component\Symbol\Glyph\Glyph::class);
81 $glyph_factory->method($this->anything())->willReturn($glyph_mock);
82 $symbol_factory = $this->createMock(Component\Symbol\Factory::class);
83 $symbol_factory->method('icon')->willReturn($icon_factory);
84
85 $button_factory = $this->createMock(Component\Button\Factory::class);
86 $button_factory->method('bulky')->willReturn($this->bulky_stub);
87
88 $link_factory = $this->createMock(Component\Link\Factory::class);
89 $link_factory->method('standard')->willReturn($this->link_stub);
90
91 $node_factory = $this->createMock(Field\Node\Factory::class);
92 $field_factory = $this->createMock(Field\Factory::class);
93 $field_factory->method('node')->willReturn($node_factory);
94 $input_factory = $this->createMock(Component\Input\Factory::class);
95 $input_factory->method('field')->willReturn($field_factory);
96
97 return new class (
98 $button_factory,
99 $symbol_factory,
100 $link_factory,
101 $input_factory,
102 $this->menu_factory,
103 $this->breadcrumbs_stub,
104 ) extends \NoUIFactory {
105 public function __construct(
106 protected Component\Button\Factory $button_factory,
107 protected Component\Symbol\Factory $symbol_factory,
108 protected Component\Link\Factory $link_factory,
109 protected Component\Input\Factory $input_factory,
110 protected Component\Menu\Factory $menu_factory,
111 protected Component\Breadcrumbs\Breadcrumbs $breadcrumbs,
112 ) {
113 }
114 public function button(): Component\Button\Factory
115 {
116 return $this->button_factory;
117 }
118 public function breadcrumbs(array $crumbs): Component\Breadcrumbs\Breadcrumbs
119 {
120 return $this->breadcrumbs;
121 }
122 public function symbol(): Component\Symbol\Factory
123 {
124 return $this->symbol_factory;
125 }
126 public function link(): Component\Link\Factory
127 {
128 return $this->link_factory;
129 }
130 public function input(): Component\Input\Factory
131 {
132 return $this->input_factory;
133 }
134 public function menu(): Component\Menu\Factory
135 {
136 return $this->menu_factory;
137 }
138 };
139 }
140
142 public function testWithValueForInvalidArguments(mixed $value): void
143 {
144 $node_retrieval = $this->getNodeRetrieval();
145 $component = $this->getFieldFactory()->treeSelect($node_retrieval, '');
146 $this->expectException(InvalidArgumentException::class);
147 $component = $component->withValue($value);
148 }
149
151 public function testWithValueForValidArguments(string|int|null $value): void
152 {
153 $node_retrieval = $this->getNodeRetrieval();
154 $component = $this->getFieldFactory()->treeSelect($node_retrieval, '');
155 $component = $component->withValue($value);
156 $this->assertEquals([$value], $component->getValue());
157 }
158
159 public function testRenderWithValue(): void
160 {
161 $node_id = 'some-existing-node-id';
162 $node_name = 'some existing node';
163
164 [$leaf_stub,] = $this->getLeafStub($node_id, $node_name);
165
166 $node_retrieval = $this->getNodeRetrieval([], [$leaf_stub]);
167
168 $component = $this->getFieldFactory()->treeSelect($node_retrieval, '');
169 $component = $component->withValue($node_id);
170
171 $renderer = $this->getDefaultRenderer(null, [$leaf_stub]);
172
173 $expected_html = <<<HTML
174<li data-node-id="$node_id">
175 <span data-node-name>$node_name</span>
176 <button data-action="remove" type="button" class="close" aria-label="unselect_node">
177 <span aria-hidden="true">&times;</span>
178 </button>
179 <input id="id_2" type="hidden" value="$node_id" />
180</li>
181HTML;
182
183 $actual_html = $renderer->render($component);
184
185 $this->assertTrue(
186 str_contains(
187 $this->brutallyTrimHTML($actual_html),
188 $this->brutallyTrimHTML($expected_html),
189 )
190 );
191 }
192
193 public function testRenderWithDisabled(): void
194 {
195 $node_retrieval = $this->getNodeRetrieval();
196
197 $component = $this->getFieldFactory()->treeSelect($node_retrieval, '');
198 $component = $component->withDisabled(true);
199
200 $renderer = $this->getDefaultRenderer();
201
202 $expected_html = <<<HTML
203<input id="id_2" type="button" aria-label="select" value="select" disabled>
204HTML;
205
206 $actual_html = $renderer->render($component);
207
208 $this->assertTrue(
209 str_contains(
210 $this->brutallyTrimHTML($actual_html),
211 $this->brutallyTrimHTML($expected_html),
212 )
213 );
214 }
215
216 public function testRenderWithRequired(): void
217 {
218 $node_retrieval = $this->getNodeRetrieval();
219
220 $component = $this->getFieldFactory()->treeSelect($node_retrieval, '');
221 $component = $component->withRequired(true);
222
223 $renderer = $this->getDefaultRenderer();
224
225 $expected_html = <<<HTML
226<label for="id_2"><span class="asterisk" aria-label="required_field">*</span></label>
227HTML;
228
229 $actual_html = $renderer->render($component);
230
231 $this->assertTrue(
232 str_contains(
233 $this->brutallyTrimHTML($actual_html),
234 $this->brutallyTrimHTML($expected_html),
235 )
236 );
237 }
238
239 public function testRenderDrilldownMenu(): void
240 {
241 $this->menu_factory = $this->getMenuFactory();
242
243 [$leaf_stub, $leaf_html] = $this->getLeafStub();
244
245 $tree_select_label = 'some tree select label';
246
247 $node_retrieval = $this->getNodeRetrieval([$leaf_stub]);
248
249 $component = $this->getFieldFactory()->treeSelect($node_retrieval, $tree_select_label);
250 $component = $component->withNameFrom(new DefNamesource());
251
252 $renderer = $this->getDefaultRenderer(null, [$leaf_stub]);
253
254 $expected_html = <<<HTML
255<fieldset class="c-input" data-il-ui-component="tree-select-field-input" data-il-ui-input-name="name_0">
256 <label for="id_3">some tree select label</label>
257 <div class="c-input__field">
258 <div class="c-input-tree_select">
259 <dialog class="c-modal">
260 <div class="modal-dialog" role="document">
261 <div class="modal-content">
262 <div class="modal-header">
263 <button data-action="close" type="button" class="close" aria-label="close">
264 <span aria-hidden="true">&times;</span>
265 </button>
266 <h1 class="modal-title">$tree_select_label</h1>
267 </div>
268 <div class="modal-body">
269 <template>$this->breadcrumbs_html</template>
270 $this->breadcrumbs_html
271 <section class="c-drilldown" id="id_2">
272 <header class="c-drilldown__header--showbacknav">
273 <div></div>
274 <div></div>
275 <div class="c-drilldown__backnav"> $this->bulky_html</div>
276 </header>
277 <div class="c-drilldown__menu">
278 <ul aria-live="polite" aria-label="$tree_select_label">
279 $leaf_html
280 <li class="c-drilldown__menu--no-items"> drilldown_no_items</li>
281 </ul>
282 </div>
283 </section>
284 </div>
285 <div class="modal-footer">
286 <button data-action="close" type="button" class="btn btn-default" aria-label="close">close</button>
287 <button data-action="close" type="button" class="btn btn-primary" aria-label="select">select</button>
288 </div>
289 </div>
290 </div>
291 </dialog>
292 <ul class="c-input-tree_select__selection">
293 <template>
294 <li data-node-id="">
295 <span data-node-name></span>
296 <button data-action="remove" type="button" class="close" aria-label="">
297 <span aria-hidden="true">&times;</span>
298 </button>
299 <input id="id_1" type="hidden" name="name_0[input_0][]" value="" /></li>
300 </template>
301 </ul>
302 <input id="id_3" type="button" aria-label="select" value="select">
303 </div>
304 </div>
305</fieldset>
306HTML;
307
308 $actual_html = $renderer->render($component);
309
310 $this->assertEquals(
311 $this->brutallyTrimHTML($expected_html),
312 $this->brutallyTrimHTML($actual_html),
313 );
314 }
315
316 public static function getInvalidArgumentsForWithValue(): array
317 {
318 return [
319 [true],
320 [new stdClass()],
321 [1.000],
322 [[1, 2, 3]],
323 [[]],
324 ];
325 }
326
327 public static function getValidArgumentsForWithValue(): array
328 {
329 return [
330 [1],
331 [-1],
332 ['1'],
333 [''],
334 [' '],
335 [null],
336 ];
337 }
338
339 protected function getMenuFactory(): Component\Menu\Factory
340 {
341 return new Component\Menu\Factory($this->signal_generator);
342 }
343
344 protected function getFieldFactory(?Field\Node\Factory $node_factory = null): Field\Factory
345 {
346 return new Field\Factory(
347 ($node_factory) ?: $this->createMock(Field\Node\Factory::class),
348 $this->createMock(Component\Input\UploadLimitResolver::class),
349 $this->signal_generator,
350 $this->getDataFactory(),
351 $this->getRefinery(),
352 $this->getLanguage(),
353 );
354 }
355
360 protected function getNodeRetrieval(array $node_stubs = [], array $leaf_stubs = []): NodeRetrieval & MockObject
361 {
362 $node_retrieval = $this->createMock(NodeRetrieval::class);
363 $node_retrieval->method('getNodes')->willReturnCallback(static fn() => yield from $node_stubs);
364 $node_retrieval->method('getNodesAsLeaf')->willReturnCallback(static fn() => yield from $leaf_stubs);
365 return $node_retrieval;
366 }
367
369 protected function getLeafStub(string|int $id = '', string $name = ''): array
370 {
371 $stub = $this->createMock(Field\Node\Leaf::class);
372 $html = sha1(Field\Node\Leaf::class);
373 $stub->method('getCanonicalName')->willReturn($html);
374 $stub->method('getId')->willReturn($id);
375 $stub->method('getName')->willReturn($name);
376 return [$stub, $html];
377 }
378
380 protected function getBreadcrumbsStub(): array
381 {
382 return $this->createSimpleRenderingStub(Component\Breadcrumbs\Breadcrumbs::class);
383 }
384
386 protected function getDrilldownStub(): array
387 {
388 return $this->createSimpleRenderingStub(Component\Menu\Drilldown::class);
389 }
390
392 protected function getLinkStub(): array
393 {
394 return $this->createSimpleRenderingStub(Component\Link\Standard::class);
395 }
396
398 protected function getBulkyStub(): array
399 {
400 return $this->createSimpleRenderingStub(Component\Button\Bulky::class);
401 }
402
404 protected function createSimpleRenderingStub(string $class_name): array
405 {
406 $stub = $this->createMock($class_name);
407 $html = sha1($class_name);
408 $stub->method('getCanonicalName')->willReturn($html);
409 $stub->method($this->anything())->willReturnSelf();
410 return [$stub, $html];
411 }
412}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
$renderer
Builds a Color from either hex- or rgb values.
Definition: Factory.php:31
Factory for Date Formats.
Definition: Factory.php:27
Builds data types.
Definition: Factory.php:36
This implements commonalities between inputs.
Definition: Input.php:43
Provides common functionality for UI tests.
Definition: Base.php:337
createSimpleRenderingStub(string $class_name)
getNodeRetrieval(array $node_stubs=[], array $leaf_stubs=[])
Component Link Standard &MockObject $link_stub
Component Menu Factory $menu_factory
static getValidArgumentsForWithValue()
testWithValueForValidArguments(string|int|null $value)
@dataProvider getValidArgumentsForWithValue
getFieldFactory(?Field\Node\Factory $node_factory=null)
getDefaultRenderer(?JavaScriptBinding $js_binding=null, array $with_stub_renderings=[], array $with_additional_contexts=[],)
string $breadcrumbs_html
getLeafStub(string|int $id='', string $name='')
testWithValueForInvalidArguments(mixed $value)
@dataProvider getInvalidArgumentsForWithValue
Component Breadcrumbs Breadcrumbs &MockObject $breadcrumbs_stub
Component Menu Drilldown &MockObject $drilldown_stub
string $drilldown_html
Component Button Bulky &MockObject $bulky_stub
static getInvalidArgumentsForWithValue()
Component SignalGeneratorInterface $signal_generator
This is what a factory for input fields looks like.
Definition: Factory.php:31
This describes a symbol.
Definition: Symbol.php:30
Provides methods to interface with javascript.
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
button(string $caption, string $cmd)
link(string $caption, string $href, bool $new_viewport=false)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Definition: Bulky.php:21
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Definition: Checkbox.php:21
getLanguage()