ILIAS  trunk Revision v11.0_alpha-2638-g80c1d007f79
TreeMultiSelectTest.php
Go to the documentation of this file.
1 <?php
2 
18 declare(strict_types=1);
19 
25 
26 require_once(__DIR__ . "/../../../../../../../vendor/composer/vendor/autoload.php");
27 require_once(__DIR__ . "/../../../Base.php");
28 require_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;
39  protected Component\Menu\Drilldown & MockObject $drilldown_stub;
40  protected string $drilldown_html;
41  protected Component\Breadcrumbs\Breadcrumbs & MockObject $breadcrumbs_stub;
42  protected string $breadcrumbs_html;
43 
44  protected Component\SignalGeneratorInterface $signal_generator;
45  protected Component\Menu\Factory $menu_factory;
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,
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()->treeMultiSelect($node_retrieval, '');
146  $this->expectException(InvalidArgumentException::class);
147  $component = $component->withValue($value);
148  }
149 
151  public function testWithValueForValidArguments(array $value): void
152  {
153  $node_retrieval = $this->getNodeRetrieval();
154  $component = $this->getFieldFactory()->treeMultiSelect($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()->treeMultiSelect($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>
181 HTML;
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()->treeMultiSelect($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>
204 HTML;
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()->treeMultiSelect($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>
227 HTML;
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()->treeMultiSelect($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-multi-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>
306 HTML;
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'],
322  [1.000],
323  [1],
324  ];
325  }
326 
327  public static function getValidArgumentsForWithValue(): array
328  {
329  return [
330  [[1, 2, 3]],
331  [[-1]],
332  [['1', '2', '3']],
333  [['1']],
334  [['']],
335  [[' ']],
336  [[]]
337  ];
338  }
339 
340  protected function getMenuFactory(): Component\Menu\Factory
341  {
342  return new Component\Menu\Factory($this->signal_generator);
343  }
344 
345  protected function getFieldFactory(?Field\Node\Factory $node_factory = null): Field\Factory
346  {
347  return new Field\Factory(
348  ($node_factory) ?: $this->createMock(Field\Node\Factory::class),
349  $this->createMock(Component\Input\UploadLimitResolver::class),
350  $this->signal_generator,
351  $this->getDataFactory(),
352  $this->getRefinery(),
353  $this->getLanguage(),
354  );
355  }
356 
361  protected function getNodeRetrieval(array $node_stubs = [], array $leaf_stubs = []): NodeRetrieval & MockObject
362  {
363  $node_retrieval = $this->createMock(NodeRetrieval::class);
364  $node_retrieval->method('getNodes')->willReturnCallback(static fn() => yield from $node_stubs);
365  $node_retrieval->method('getNodesAsLeaf')->willReturnCallback(static fn() => yield from $leaf_stubs);
366  return $node_retrieval;
367  }
368 
370  protected function getLeafStub(string|int $id = '', string $name = ''): array
371  {
372  $stub = $this->createMock(Field\Node\Leaf::class);
373  $html = sha1(Field\Node\Leaf::class);
374  $stub->method('getCanonicalName')->willReturn($html);
375  $stub->method('getId')->willReturn($id);
376  $stub->method('getName')->willReturn($name);
377  return [$stub, $html];
378  }
379 
381  protected function getBreadcrumbsStub(): array
382  {
383  return $this->createSimpleRenderingStub(Component\Breadcrumbs\Breadcrumbs::class);
384  }
385 
387  protected function getDrilldownStub(): array
388  {
389  return $this->createSimpleRenderingStub(Component\Menu\Drilldown::class);
390  }
391 
393  protected function getLinkStub(): array
394  {
395  return $this->createSimpleRenderingStub(Component\Link\Standard::class);
396  }
397 
399  protected function getBulkyStub(): array
400  {
401  return $this->createSimpleRenderingStub(Component\Button\Bulky::class);
402  }
403 
405  protected function createSimpleRenderingStub(string $class_name): array
406  {
407  $stub = $this->createMock($class_name);
408  $html = sha1($class_name);
409  $stub->method('getCanonicalName')->willReturn($html);
410  $stub->method($this->anything())->willReturnSelf();
411  return [$stub, $html];
412  }
413 }
This implements commonalities between inputs.
Definition: Input.php:42
button(string $caption, string $cmd)
testWithValueForValidArguments(array $value)
getValidArgumentsForWithValue
$renderer
getLeafStub(string|int $id='', string $name='')
static getInvalidArgumentsForWithValue()
Factory for Date Formats.
Definition: Factory.php:26
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Definition: Checkbox.php:21
getLanguage()
Provides common functionality for UI tests.
Definition: Base.php:333
Component Breadcrumbs Breadcrumbs &MockObject $breadcrumbs_stub
Component Menu Drilldown &MockObject $drilldown_stub
close()
description: > Example for rendring a close glyph.
Definition: close.php:41
Provides methods to interface with javascript.
Component SignalGeneratorInterface $signal_generator
Component Link Standard &MockObject $link_stub
getNodeRetrieval(array $node_stubs=[], array $leaf_stubs=[])
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
__construct(Container $dic, ilPlugin $plugin)
link(string $caption, string $href, bool $new_viewport=false)
getFieldFactory(?Field\Node\Factory $node_factory=null)
breadcrumbs()
description: > Example showing how to construct Breadcrumbs with an array of Links and extending the...
Definition: breadcrumbs.php:33
disabled()
description: > Example showing how to plug a disabled checkbox into a form
Definition: disabled.php:32
testWithValueForInvalidArguments(mixed $value)
getInvalidArgumentsForWithValue
Component Menu Factory $menu_factory
header()
expected output: > ILIAS shows the rendered Component.
Definition: header.php:29
getDefaultRenderer(?JavaScriptBinding $js_binding=null, array $with_stub_renderings=[], array $with_additional_contexts=[],)
createSimpleRenderingStub(string $class_name)
Component Button Bulky &MockObject $bulky_stub