ILIAS  trunk Revision v11.0_alpha-2638-g80c1d007f79
SwitchableGroupInputTest.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
21 require_once(__DIR__ . "/../../../../../../../vendor/composer/vendor/autoload.php");
22 require_once(__DIR__ . "/../../../Base.php");
23 require_once(__DIR__ . "/CommonFieldRendering.php");
24 
30 use ILIAS\Data;
35 
36 class Group1 extends Group
37 {
38 }
39 
40 class Group2 extends Group
41 {
42  public function isClientSideValueOk($value): bool
43  {
45  }
46 }
47 
49 {
51 
55  protected $child1;
56 
60  protected $child2;
61 
65  protected $nested_child;
66 
70  protected $lng;
71 
72  protected Data\Factory $data_factory;
73  protected Refinery $refinery;
76 
77  public function setUp(): void
78  {
79  $this->nested_child = $this->createMock(I\Input\Field\FormInputInternal::class);
80  $this->child1 = $this->createMock(Group1::class);
81  $this->child2 = $this->createMock(Group2::class);
82  $this->data_factory = new Data\Factory();
83  $this->refinery = new Refinery($this->data_factory, $this->createMock(ILIAS\Language\Language::class));
84  $this->lng = $this->createMock(ILIAS\Language\Language::class);
85 
86  $this->nested_child
87  ->method("withNameFrom")
88  ->willReturn($this->nested_child);
89 
90  $this->child1
91  ->method("withNameFrom")
92  ->willReturn($this->child1);
93  $this->child1
94  ->method("getInputs")
95  ->willReturn([$this->nested_child]);
96 
97  $this->child2
98  ->method("withNameFrom")
99  ->willReturn($this->child2);
100  $this->child2
101  ->method("getInputs")
102  ->willReturn([$this->nested_child]);
103 
104  $this->switchable_group = (new SwitchableGroup(
105  $this->data_factory,
106  $this->refinery,
107  $this->lng,
108  ["child1" => $this->child1, "child2" => $this->child2],
109  "LABEL",
110  "BYLINE"
111  ))->withNameFrom(new class () implements NameSource {
112  public function getNewName(): string
113  {
114  return "name0";
115  }
116  });
117  }
118 
119  protected function buildFactory(): I\Input\Field\Factory
120  {
121  return new I\Input\Field\Factory(
122  $this->createMock(\ILIAS\UI\Implementation\Component\Input\Field\Node\Factory::class),
123  $this->createMock(\ILIAS\UI\Implementation\Component\Input\UploadLimitResolver::class),
124  new SignalGenerator(),
125  $this->data_factory,
126  $this->refinery,
127  $this->lng
128  );
129  }
130 
131  public function testWithDisabledDisablesChildren(): void
132  {
133  $this->assertNotSame($this->child1, $this->child2);
134 
135  $this->child1
136  ->expects($this->once())
137  ->method("withDisabled")
138  ->with(true)
139  ->willReturn($this->child2);
140  $this->child2
141  ->expects($this->once())
142  ->method("withDisabled")
143  ->with(true)
144  ->willReturn($this->child1);
145 
146  $new_group = $this->switchable_group->withDisabled(true);
147 
148  $this->assertEquals(["child1" => $this->child2, "child2" => $this->child1], $new_group->getInputs());
149  $this->assertInstanceOf(SwitchableGroup::class, $new_group);
150  $this->assertNotSame($this->switchable_group, $new_group);
151  }
152 
153  public function testWithRequiredDoesNotRequire(): void
154  {
155  $this->assertNotSame($this->child1, $this->child2);
156 
157  $this->child1
158  ->expects($this->never())
159  ->method("withRequired");
160  $this->child2
161  ->expects($this->never())
162  ->method("withRequired");
163 
164  $new_group = $this->switchable_group->withRequired(true);
165 
166  $this->assertEquals(["child1" => $this->child1, "child2" => $this->child2], $new_group->getInputs());
167  $this->assertInstanceOf(SwitchableGroup::class, $new_group);
168  $this->assertNotSame($this->switchable_group, $new_group);
169  }
170 
172  {
173  $this->expectException(InvalidArgumentException::class);
174 
175  $this->group = new SwitchableGroup(
176  $this->data_factory,
177  $this->refinery,
178  $this->lng,
179  [$this->createMock(I\Input\Field\FormInput::class)],
180  "LABEL",
181  "BYLINE"
182  );
183  }
184 
186  {
187  $this->assertNotSame($this->child1, $this->child2);
188 
189  $this->child1
190  ->expects($this->never())
191  ->method("withValue");
192  $this->child2
193  ->method('isClientSideValueOk')
194  ->willReturn(true);
195  $this->child2
196  ->expects($this->once())
197  ->method("withValue")
198  ->with([2])
199  ->willReturn($this->child2);
200 
201  $new_group = $this->switchable_group->withValue(["child2", [2]]);
202 
203  $this->assertEquals(["child1" => $this->child1, "child2" => $this->child2], $new_group->getInputs());
204  $this->assertInstanceOf(SwitchableGroup::class, $new_group);
205  $this->assertNotSame($this->switchable_group, $new_group);
206  }
207 
209  {
210  $this->expectException(InvalidArgumentException::class);
211  $this->switchable_group->withValue(null);
212  }
213 
215  {
216  $this->expectException(InvalidArgumentException::class);
217  $this->switchable_group->withValue([1, 2, 3]);
218  }
219 
220  public function testGroupOnlyDoesAcceptKeyOnly(): void
221  {
222  $new_group = $this->switchable_group->withValue("child1");
223  $this->assertEquals(["child1" => $this->child1, "child2" => $this->child2], $new_group->getInputs());
224  $this->assertInstanceOf(SwitchableGroup::class, $new_group);
225  $this->assertNotSame($this->switchable_group, $new_group);
226  }
227 
228  public function testGroupOnlyDoesNotAcceptInvalidKey(): void
229  {
230  $this->expectException(InvalidArgumentException::class);
231  $this->switchable_group->withValue("child3");
232  }
233 
234  public function testGroupForwardsValuesOnGetValue(): void
235  {
236  $this->assertNotSame($this->child1, $this->child2);
237 
238  $this->child1
239  ->expects($this->once())
240  ->method("getValue")
241  ->with()
242  ->willReturn("one");
243  $this->child2
244  ->expects($this->never())
245  ->method("getValue");
246 
247  $vals = $this->switchable_group->withValue("child1")->getValue();
248 
249  $this->assertEquals(["child1", "one"], $vals);
250  }
251 
253  {
254  $this->assertNotSame($this->child1, $this->child2);
255 
256  $input_data = $this->createMock(InputData::class);
257 
258  $input_data
259  ->expects($this->once())
260  ->method("getOr")
261  ->with("name0")
262  ->willReturn("child1");
263 
264  $expected_result = $this->data_factory->ok("one");
265 
266  $this->child1
267  ->expects($this->once())
268  ->method("withInput")
269  ->with($input_data)
270  ->willReturn($this->child1);
271  $this->child1
272  ->expects($this->once())
273  ->method("getContent")
274  ->with()
275  ->willReturn($expected_result);
276  $this->nested_child
277  ->expects($this->once())
278  ->method("getContent")
279  ->with()
280  ->willReturn($expected_result);
281  $this->child2
282  ->expects($this->never())
283  ->method("withInput");
284  $this->child2
285  ->expects($this->never())
286  ->method("getContent");
287 
288  $called = false;
289  $new_group = $this->switchable_group
290  ->withAdditionalTransformation($this->refinery->custom()->transformation(function ($v) use (&$called): string {
291  $called = true;
292  $this->assertEquals(["child1", ["one"]], $v);
293  return "result";
294  }))
295  ->withInput($input_data);
296 
297  $this->assertTrue($called);
298  $this->assertEquals(["child1" => $this->child1, "child2" => $this->child2], $new_group->getInputs());
299  $this->assertInstanceOf(SwitchableGroup::class, $new_group);
300  $this->assertNotSame($this->switchable_group, $new_group);
301  $this->assertEquals($this->data_factory->ok("result"), $new_group->getContent());
302  }
303 
305  {
306  $this->assertNotSame($this->child1, $this->child2);
307 
308  $input_data = $this->createMock(InputData::class);
309 
310  $input_data
311  ->expects($this->once())
312  ->method("getOr")
313  ->with("name0")
314  ->willReturn("child2");
315 
316  $this->child1
317  ->expects($this->never())
318  ->method("withInput");
319  $this->child1
320  ->expects($this->never())
321  ->method("getContent");
322  $this->child2
323  ->expects($this->once())
324  ->method("withInput")
325  ->with($input_data)
326  ->willReturn($this->child2);
327  $this->child2
328  ->expects($this->once())
329  ->method("getContent")
330  ->willReturn($this->data_factory->error(""));
331 
332  $i18n = "THERE IS SOME ERROR IN THIS GROUP";
333  $this->lng
334  ->expects($this->once())
335  ->method("txt")
336  ->with("ui_error_in_group")
337  ->willReturn($i18n);
338 
339  $new_group = $this->switchable_group
340  ->withAdditionalTransformation($this->refinery->custom()->transformation(function (): void {
341  $this->fail("This should not happen.");
342  }))
343  ->withInput($input_data);
344 
345  $this->assertEquals(["child1" => $this->child1, "child2" => $this->child2], $new_group->getInputs());
346  $this->assertInstanceOf(SwitchableGroup::class, $new_group);
347  $this->assertNotSame($this->switchable_group, $new_group);
348  $this->assertTrue($new_group->getContent()->isError());
349  }
350 
351  public function testErrorIsI18NOnError(): void
352  {
353  $this->assertNotSame($this->child1, $this->child2);
354 
355  $input_data = $this->createMock(InputData::class);
356 
357  $input_data
358  ->expects($this->once())
359  ->method("getOr")
360  ->with("name0")
361  ->willReturn("child2");
362 
363  $this->child2
364  ->method("withInput")
365  ->willReturn($this->child2);
366  $this->child2
367  ->method("getContent")
368  ->willReturn($this->data_factory->error(""));
369 
370  $i18n = "THERE IS SOME ERROR IN THIS GROUP";
371  $this->lng
372  ->expects($this->once())
373  ->method("txt")
374  ->with("ui_error_in_group")
375  ->willReturn($i18n);
376 
377  $switchable_group = $this->switchable_group
378  ->withInput($input_data);
379 
380  $this->assertTrue($switchable_group->getContent()->isError());
381  $this->assertEquals($i18n, $switchable_group->getContent()->error());
382  }
383 
385  {
386  $this->expectException(InvalidArgumentException::class);
387 
388  $input_data = $this->createMock(InputData::class);
389 
390  $input_data
391  ->expects($this->once())
392  ->method("getOr")
393  ->with("name0")
394  ->willReturn(123);
395 
396  $this->child1
397  ->expects($this->never())
398  ->method("withInput");
399  $this->child1
400  ->expects($this->never())
401  ->method("getContent");
402  $this->child2
403  ->expects($this->never())
404  ->method("withInput");
405  $this->child2
406  ->expects($this->never())
407  ->method("getContent");
408 
409  $this->switchable_group
410  ->withAdditionalTransformation($this->refinery->custom()->transformation(function () use (&$called): void {
411  $this->fail("This should not happen.");
412  }))
413  ->withInput($input_data);
414  }
415 
416  public function testRender(): SG
417  {
418  $f = $this->buildFactory();
419  $label = "label";
420  $byline = "byline";
421 
422  $group1 = $f->group([
423  "field_1" => $f->text("f", "some field")
424  ]);
425  $group2 = $f->group([
426  "field_2" => $f->text("f2", "some other field")
427  ]);
428 
429  $sg = $f->switchableGroup(
430  [
431  "g1" => $group1,
432  "g2" => $group2
433  ],
434  $label,
435  $byline
436  );
437 
438  $expected = <<<EOT
439 <fieldset class="c-input" data-il-ui-component="switchable-group-field-input" data-il-ui-input-name="" tabindex="0">
440  <label>label</label>
441  <div class="c-input__field">
442  <fieldset class="c-input" data-il-ui-component="group-field-input" data-il-ui-input-name="">
443  <label for="id_1">
444  <input type="radio" id="id_1" value="g1" />
445  <span></span>
446  </label>
447  <div class="c-input__field">
448  <fieldset class="c-input" data-il-ui-component="text-field-input" data-il-ui-input-name=""><label
449  for="id_2">f</label>
450  <div class="c-input__field"><input id="id_2" type="text" class="c-field-text" /></div>
451  <div class="c-input__help-byline">some field</div>
452  </fieldset>
453  </div>
454  </fieldset>
455  <fieldset class="c-input" data-il-ui-component="group-field-input" data-il-ui-input-name="">
456  <label for="id_3">
457  <input type="radio" id="id_3" value="g2" />
458  <span></span>
459  </label>
460  <div class="c-input__field">
461  <fieldset class="c-input" data-il-ui-component="text-field-input" data-il-ui-input-name=""><label
462  for="id_4">f2</label>
463  <div class="c-input__field"><input id="id_4" type="text" class="c-field-text" /></div>
464  <div class="c-input__help-byline">some other field</div>
465  </fieldset>
466  </div>
467  </fieldset>
468  </div>
469  <div class="c-input__help-byline">byline</div>
470 </fieldset>
471 EOT;
472  $this->assertEquals(
473  $this->brutallyTrimHTML($expected),
474  $this->render($sg)
475  );
476  return $sg;
477  }
478 
479  #[\PHPUnit\Framework\Attributes\Depends('testRender')]
480  public function testRenderWithValue(SG $sg): void
481  {
482  $r = $this->getDefaultRenderer();
483  $html = $this->render($sg->withValue('g2'));
484  $expected = '<label for="id_3"><input type="radio" id="id_3" value="g2" checked="checked" />';
485  $this->assertStringContainsString($expected, $this->render($sg->withValue('g2')));
486  }
487 
488  public function testRenderWithValueByIndex(): void
489  {
490  $f = $this->buildFactory();
491  $label = "label";
492  $byline = "byline";
493 
494  $group1 = $f->group([
495  "field_1" => $f->text("f", "some field")
496  ]);
497  $group2 = $f->group([
498  "field_2" => $f->text("f2", "some other field")
499  ]);
500  $empty_group_title = 'empty group, the title';
501  $empty_group_byline = 'empty group, the byline';
502  $group3 = $f->group([], $empty_group_title, $empty_group_byline);
503 
504  $sg = $f->switchableGroup([$group1, $group2, $group3], $label, $byline);
505 
506  $expected = '<label for="id_3"><input type="radio" id="id_3" value="1" checked="checked" />';
507  $this->assertStringContainsString($expected, $this->render($sg->withValue('1')));
508  }
509 
510  public function testCommonRendering(): void
511  {
512  $f = $this->getFieldFactory();
513  $label = "label";
514 
515  $group1 = $f->group([
516  "field_1" => $f->text("f")
517  ]);
518  $group2 = $f->group([
519  "field_2" => $f->text("f2")
520  ]);
521 
522  $sg = $f->switchableGroup(
523  [
524  "g1" => $group1,
525  "g2" => $group2
526  ],
527  $label
528  )->withNameFrom((new DefNamesource()));
529 
530  $this->testWithError($sg);
531  $this->testWithNoByline($sg);
532  $this->testWithRequired($sg);
533  $this->testWithDisabled($sg);
534  $this->testWithAdditionalOnloadCodeRendersId($sg);
535  }
536 }
Interface Observer Contains several chained tasks and infos about them.
ILIAS UI Component Input Field Group $switchable_group
isClientSideValueOk($value)
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
withNameFrom(NameSource $source, ?string $parent_name=null)
Definition: Input.php:200
Builds data types.
Definition: Factory.php:35
Describes a source for input names.
Definition: NameSource.php:26
$r