ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
SwitchableGroupInputTest.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
21require_once(__DIR__ . "/../../../../../../../vendor/composer/vendor/autoload.php");
22require_once(__DIR__ . "/../../../Base.php");
23require_once(__DIR__ . "/CommonFieldRendering.php");
24
30use ILIAS\Data;
32use ILIAS\Refinery\Factory as Refinery;
33use PHPUnit\Framework\MockObject\MockObject;
35
36class Group1 extends Group
37{
38}
39
40class Group2 extends Group
41{
42 public function isClientSideValueOk($value): bool
43 {
44 return parent::isClientSideValueOk($value);
45 }
46}
47
49{
50 use CommonFieldRendering;
51
55 protected $child1;
56
60 protected $child2;
61
65 protected $nested_child;
66
70 protected $lng;
71
72 protected Data\Factory $data_factory;
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
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>
471EOT;
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}
isClientSideValueOk($value)
ATTENTION:
Builds data types.
Definition: Factory.php:36
This implements the group input.
Definition: Group.php:41
Definition: UI.php:24
Provides common functionality for UI tests.
Definition: Base.php:337
ILIAS UI Component Input Field Group $switchable_group
This describes switchable group inputs.
Describes how Input-Elements want to interact with posted data.
Definition: InputData.php:30
Describes a source for input names.
Definition: NameSource.php:27
withNameFrom(NameSource $source, ?string $parent_name=null)
@inheritDoc
Interface Observer \BackgroundTasks Contains several chained tasks and infos about them.