ILIAS  release_8 Revision v8.24
DataRendererTest.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
21require_once("libs/composer/vendor/autoload.php");
22require_once(__DIR__ . "/TableTestBase.php");
23
26use ILIAS\Data;
28use Psr\Http\Message\ServerRequestInterface;
30
34class DTRenderer extends I\Table\Renderer
35{
36 public function p_getMultiActionHandler(I\Signal $signal)
37 {
38 return $this->getMultiActionHandler($signal);
39 }
40
41 public function p_getActionRegistration(string $action_id, I\Table\Action\Action $action)
42 {
43 return $this->getActionRegistration($action_id, $action);
44 }
45
47 array $actions,
48 I\Signal $action_signal,
49 I\Signal $modal_signal
50 ) {
51 return $this->buildMultiActionsDropdown($actions, $action_signal, $modal_signal);
52 }
53
54 public function p_getSingleActionsForRow(string $row_id, array $actions)
55 {
56 return $this->getSingleActionsForRow($row_id, $actions);
57 }
58
59 public function p_renderTableHeader(
60 TestDefaultRenderer $default_renderer,
61 I\Table\Data $component,
62 $tpl,
63 ?I\Signal $sortation_signal
64 ) {
65 return $this->renderTableHeader($default_renderer, $component, $tpl, $sortation_signal);
66 }
67}
68
69
74{
75 private function getRenderer()
76 {
77 return new DTRenderer(
78 $this->getUIFactory(),
79 $this->getTemplateFactory(),
80 $this->getLanguage(),
81 $this->getJavaScriptBinding(),
82 $this->getRefinery(),
84 new \ILIAS\Data\Factory()
85 );
86 }
87
88 private function getActionFactory()
89 {
90 return new I\Table\Action\Factory();
91 }
92
93 private function getColumnFactory()
94 {
95 return new I\Table\Column\Factory(
96 $this->getLanguage()
97 );
98 }
99
100 private function getDummyRequest()
101 {
102 $request = $this->createMock(ServerRequestInterface::class);
103 $request
104 ->method("getUri")
105 ->willReturn(new class () {
106 public function __toString()
107 {
108 return 'http://localhost:80';
109 }
110 });
111
112 $request
113 ->method("getQueryParams")
114 ->willReturn([]);
115 return $request;
116 }
117
118 public function getDataFactory(): Data\Factory
119 {
120 return new Data\Factory();
121 }
122
123 public function getUIFactory(): NoUIFactory
124 {
125 $factory = new class ($this->getTableFactory()) extends NoUIFactory {
126 protected Component\Table\Factory $table_factory;
127 public function __construct(
128 Component\Table\Factory $table_factory
129 ) {
130 $this->table_factory = $table_factory;
131 }
132 public function button(): Component\Button\Factory
133 {
134 return new I\Button\Factory();
135 }
136 public function dropdown(): Component\Dropdown\Factory
137 {
138 return new I\Dropdown\Factory();
139 }
140 public function symbol(): Component\Symbol\Factory
141 {
142 return new I\Symbol\Factory(
143 new I\Symbol\Icon\Factory(),
144 new I\Symbol\Glyph\Factory(),
145 new I\Symbol\Avatar\Factory()
146 );
147 }
148 public function table(): Component\Table\Factory
149 {
150 return $this->table_factory;
151 }
152 public function divider(): Component\Divider\Factory
153 {
154 return new I\Divider\Factory();
155 }
156 };
157 return $factory;
158 }
159
161 {
162 $renderer = $this->getRenderer();
163 $signal = new I\Signal('signal_id');
164 $closure = $renderer->p_getMultiActionHandler($signal);
165 $actual = $this->brutallyTrimHTML($closure('component_id'));
166 $expected = $this->brutallyTrimHTML(
167 "$(document).on('signal_id', function(event, signal_data) {
168 il.UI.table.data.get('component_id').doMultiAction(signal_data);
169 return false;
170 });"
171 );
172 $this->assertEquals($expected, $actual);
173 }
174
176 {
177 $renderer = $this->getRenderer();
178 $f = $this->getActionFactory();
179 $url = $this->getDataFactory()->uri('http://wwww.ilias.de?ref_id=1');
180 $url_builder = new URLBuilder($url);
181 list($builder, $token) = $url_builder->acquireParameter(['namespace'], 'param');
182
183 $action = $f->standard('label', $builder, $token);
184 $closure = $renderer->p_getActionRegistration('action_id', $action);
185
186 $actual = $this->brutallyTrimHTML($closure('component_id'));
187 $url = $url->__toString();
188 $expected = $this->brutallyTrimHTML(
189 'il.UI.table.data.get(\'component_id\').registerAction(\'action_id\', false, new il.UI.core.URLBuilder(new URL("http://wwww.ilias.de?ref_id=1&namespace_param="), new Map([["namespace_param",new il.UI.core.URLBuilderToken(["namespace"], "param",'
190 );
191 $this->assertStringStartsWith($expected, $actual);
192 }
193
195 {
196 $renderer = $this->getRenderer();
197 $f = $this->getActionFactory();
198 $signal1 = new I\Signal('signal_id');
199 $signal2 = new I\Signal('signal_id2');
200 $url = $this->getDataFactory()->uri('http://wwww.ilias.de?ref_id=1');
201 $url_builder = new URLBuilder($url);
202 list($builder, $token) = $url_builder->acquireParameter(['namespace'], 'param');
203 $actions = [
204 $f->standard('label1', $builder, $token),
205 $f->standard('label2', $builder, $token)
206 ];
207 $this->assertNull(
208 $renderer->p_buildMultiActionsDropdown([], $signal1, $signal2)
209 );
210 $this->assertEquals(
211 4, //2 actions, 1 divider, one all-action
212 count($renderer->p_buildMultiActionsDropdown($actions, $signal1, $signal2)->getItems())
213 );
214 }
216 {
217 $renderer = $this->getRenderer();
218 $f = $this->getActionFactory();
219 $url = $this->getDataFactory()->uri('http://wwww.ilias.de?ref_id=1');
220 $url_builder = new URLBuilder($url);
221 list($builder, $token) = $url_builder->acquireParameter(['namespace'], 'param');
222 $actions = [
223 'a1' => $f->standard('label1', $builder, $token)->withAsync(),
224 'a2' => $f->standard('label2', $builder, $token)
225 ];
226 $this->assertEquals(
227 2,
228 count($renderer->p_getSingleActionsForRow('row_id-1', $actions)->getItems())
229 );
230 }
231
233 {
234 $renderer = $this->getRenderer();
235 $data_factory = new \ILIAS\Data\Factory();
236 $tpl = $this->getTemplateFactory()->getTemplate("src/UI/templates/default/Table/tpl.datatable.html", true, true);
237 $f = $this->getColumnFactory();
238 $data = new class () implements ILIAS\UI\Component\Table\DataRetrieval {
239 public function getRows(
240 Component\Table\DataRowBuilder $row_builder,
241 array $visible_column_ids,
242 Data\Range $range,
243 Data\Order $order,
244 ?array $filter_data,
245 ?array $additional_parameters
246 ): \Generator {
247 yield $row_builder->buldDataRow('', []);
248 }
249 public function getTotalRowCount(
250 ?array $filter_data,
251 ?array $additional_parameters
252 ): ?int {
253 return null;
254 }
255 };
256 $columns = [
257 'f1' => $f->text("Field 1")->withIndex(1),
258 'f2' => $f->text("Field 2")->withIndex(2)->withIsSortable(false),
259 'f3' => $f->number("Field 3")->withIndex(3)
260 ];
261 $sortation_signal = new I\Signal('sort_header_signal_id');
262 $sortation_signal->addOption('value', 'f1:ASC');
263 $table = $this->getUIFactory()->table()->data('', $columns, $data)
264 ->withRequest($this->getDummyRequest());
265 $renderer->p_renderTableHeader($this->getDefaultRenderer(), $table, $tpl, $sortation_signal);
266
267 $actual = $this->brutallyTrimHTML($tpl->get());
268 $expected = <<<EOT
269<div class="c-table-data" id="{ID}">
270 <div class="viewcontrols">{VIEW_CONTROLS}</div>
271 <div class="c-table-data__table-wrapper">
272 <table class="c-table-data__table" role="grid" aria-labelledby="{ID}_label" aria-colcount="{COL_COUNT}">
273 <thead>
274 <tr class="c-table-data__header c-table-data__row" role="rowgroup">
275 <th class="c-table-data__header c-table-data__cell c-table-data__cell--text" role="columnheader" tabindex="-1" aria-colindex="0" aria-sort="order_option_generic_ascending">
276 <div class="c-table-data__header__resize-wrapper">
277 <a tabindex="0" class="glyph" href="#" aria-label="sort_ascending" id="id_2"><span class="glyphicon glyphicon-arrow-up" aria-hidden="true"></span></a>
278 <button class="btn btn-link" id="id_1">Field 1</button>
279 </div>
280 </th>
281 <th class="c-table-data__header c-table-data__cell c-table-data__cell--text" role="columnheader" tabindex="-1" aria-colindex="1">
282 <div class="c-table-data__header__resize-wrapper">Field 2</div>
283 </th>
284 <th class="c-table-data__header c-table-data__cell c-table-data__cell--number" role="columnheader" tabindex="-1" aria-colindex="2">
285 <div class="c-table-data__header__resize-wrapper">
286 <button class="btn btn-link" id="id_3">Field 3</button>
287 </div>
288 </th>
289 </tr>
290 </thead>
291 <tbody class="c-table-data__body" role="rowgroup"></tbody>
292 </table>
293 </div>
294 <div class="c-table-data__async_modal_container"></div>
295
296 <div class="c-table-data__async_message modal" role="dialog" id="{ID}_msgmodal">
297 <div class="modal-dialog" role="document">
298 <div class="modal-content">
299 <div class="modal-header">
300 <button type="button" class="close" data-dismiss="modal" aria-label="close"><span aria-hidden="true">&times;</span></button>
301 </div>
302 <div class="c-table-data__async_messageresponse modal-body"></div>
303 </div>
304 </div>
305 </div>
306
307</div>
308EOT;
309 $expected = $this->brutallyTrimHTML($expected);
310 $this->assertEquals($expected, $actual);
311 }
312
313
315 {
316 $renderer = $this->getRenderer();
317 $data_factory = new \ILIAS\Data\Factory();
318 $tpl = $this->getTemplateFactory()->getTemplate("src/UI/templates/default/Table/tpl.datatable.html", true, true);
319 $f = $this->getColumnFactory();
320 $data = new class () implements ILIAS\UI\Component\Table\DataRetrieval {
321 public function getRows(
322 Component\Table\DataRowBuilder $row_builder,
323 array $visible_column_ids,
324 Data\Range $range,
325 Data\Order $order,
326 ?array $filter_data,
327 ?array $additional_parameters
328 ): \Generator {
329 yield $row_builder->buldDataRow('', []);
330 }
331 public function getTotalRowCount(
332 ?array $filter_data,
333 ?array $additional_parameters
334 ): ?int {
335 return null;
336 }
337 };
338 $columns = [
339 'f1' => $f->text("Field 1")->withIsSortable(false),
340 'f2' => $f->text("Field 2")->withIsSortable(false)
341 ];
342
343 $sortation_signal = null;
344
345 $table = $this->getUIFactory()->table()->data('', $columns, $data)
346 ->withRequest($this->getDummyRequest());
347 $renderer->p_renderTableHeader($this->getDefaultRenderer(), $table, $tpl, $sortation_signal);
348 $actual = $this->brutallyTrimHTML($tpl->get());
349 $expected = <<<EOT
350<div class="c-table-data" id="{ID}">
351 <div class="viewcontrols">{VIEW_CONTROLS}</div>
352 <div class="c-table-data__table-wrapper">
353 <table class="c-table-data__table" role="grid" aria-labelledby="{ID}_label" aria-colcount="{COL_COUNT}">
354 <thead>
355 <tr class="c-table-data__header c-table-data__row" role="rowgroup">
356 <th class="c-table-data__header c-table-data__cell c-table-data__cell--text" role="columnheader" tabindex="-1" aria-colindex="0">
357 <div class="c-table-data__header__resize-wrapper">Field 1</div>
358 </th>
359 <th class="c-table-data__header c-table-data__cell c-table-data__cell--text" role="columnheader" tabindex="-1" aria-colindex="1">
360 <div class="c-table-data__header__resize-wrapper">Field 2</div>
361 </th>
362 </tr>
363 </thead>
364 <tbody class="c-table-data__body" role="rowgroup"></tbody>
365 </table>
366 </div>
367
368 <div class="c-table-data__async_modal_container"></div>
369
370 <div class="c-table-data__async_message modal" role="dialog" id="{ID}_msgmodal">
371 <div class="modal-dialog" role="document">
372 <div class="modal-content">
373 <div class="modal-header">
374 <button type="button" class="close" data-dismiss="modal" aria-label="close"><span aria-hidden="true">&times;</span></button>
375 </div>
376 <div class="c-table-data__async_messageresponse modal-body"></div>
377 </div>
378 </div>
379 </div>
380
381</div>
382EOT;
383 $expected = $this->brutallyTrimHTML($expected);
384 $this->assertEquals($expected, $actual);
385 }
386
388 {
389 $renderer = $this->getRenderer();
390 $data_factory = new \ILIAS\Data\Factory();
391 $tpl = $this->getTemplateFactory()->getTemplate("src/UI/templates/default/Table/tpl.datatable.html", true, true);
392 $f = $this->getColumnFactory();
393
394 $url = $data_factory->uri('http://wwww.ilias.de?ref_id=1');
395 $url_builder = new URLBuilder($url);
396 list($builder, $token) = $url_builder->acquireParameter(['namespace'], 'param');
397 $actions = [
398 'a2' => $this->getActionFactory()->standard('some action', $builder, $token)
399 ];
400
401 $data = new class () implements ILIAS\UI\Component\Table\DataRetrieval {
402 public function getRows(
403 Component\Table\DataRowBuilder $row_builder,
404 array $visible_column_ids,
405 Data\Range $range,
406 Data\Order $order,
407 ?array $filter_data,
408 ?array $additional_parameters
409 ): \Generator {
410 yield $row_builder->buldDataRow('', []);
411 }
412 public function getTotalRowCount(
413 ?array $filter_data,
414 ?array $additional_parameters
415 ): ?int {
416 return null;
417 }
418 };
419 $columns = [
420 'f1' => $f->text("Field 1")->withIsSortable(false),
421 ];
422
423 $sortation_signal = null;
424
425 $table = $this->getUIFactory()->table()->data('', $columns, $data)
426 ->withActions($actions)
427 ->withRequest($this->getDummyRequest());
428 $renderer->p_renderTableHeader($this->getDefaultRenderer(), $table, $tpl, $sortation_signal);
429 $actual = $this->brutallyTrimHTML($tpl->get());
430
431 $expected = '<th class="c-table-data__header c-table-data__cell c-table-data__header__rowaction" role="columnheader" aria-colindex="1">actions</th>';
432 $this->assertStringContainsString($expected, $actual);
433 }
434
435 public function testDataTableRowBuilder()
436 {
437 $f = $this->getColumnFactory();
438 $columns = [
439 'f1' => $f->text("Field 1")->withIndex(1),
440 'f2' => $f->text("Field 2")->withIndex(2),
441 'f3' => $f->number("Field 3")->withIndex(3)
442 ];
443 $f = $this->getActionFactory();
444 $url = $this->getDataFactory()->uri('http://wwww.ilias.de?ref_id=1');
445 $url_builder = new URLBuilder($url);
446 list($builder, $token) = $url_builder->acquireParameter(['namespace'], 'param');
447 $actions = [
448 'a1' => $f->standard('label1', $builder, $token)->withAsync(),
449 'a2' => $f->standard('label2', $builder, $token)
450 ];
451
452 $rb = (new I\Table\DataRowBuilder())
453 ->withMultiActionsPresent(true)
454 ->withSingleActions($actions)
455 ->withVisibleColumns($columns);
456
457 $row = $rb->buildDataRow('row_id-1', []);
458 $this->assertInstanceOf(Component\Table\DataRow::class, $row);
459
460 return [$rb, $columns, $actions];
461 }
462
466 public function testDataTableDataRowFromBuilder(array $params): I\Table\DataRow
467 {
468 list($rb, $columns, $actions) = $params;
469 $record = [
470 'f1' => 'v1',
471 'f2' => 'v2',
472 'f3' => 3
473 ];
474 $row = $rb->buildDataRow('row_id-1', $record);
475
476 $this->assertEquals(
477 $columns,
478 $row->getColumns()
479 );
480 $this->assertEquals(
481 $actions,
482 $row->getActions()
483 );
484 $this->assertEquals(
485 $record['f2'],
486 $row->getCellContent('f2')
487 );
488
489 return $row;
490 }
491
495 public function testDataTableRenderStandardRow(I\Table\DataRow $row)
496 {
497 $actual = $this->brutallyTrimHTML($this->getDefaultRenderer()->render($row));
498 $expected = <<<EOT
499<td class="c-table-data__cell c-table-data__rowselection" role="gridcell" tabindex="-1">
500 <input type="checkbox" value="row_id-1" class="c-table-data__row-selector">
501</td>
502<td class="c-table-data__cell c-table-data__cell--text " role="gridcell" aria-colindex="1" tabindex="-1">
503 <span class="c-table-data__cell__col-title">Field 1:</span>v1
504</td>
505<td class="c-table-data__cell c-table-data__cell--text " role="gridcell" aria-colindex="2" tabindex="-1">
506 <span class="c-table-data__cell__col-title">Field 2:</span>v2
507</td>
508<td class="c-table-data__cell c-table-data__cell--number " role="gridcell" aria-colindex="3" tabindex="-1">
509 <span class="c-table-data__cell__col-title">Field 3:</span>3
510</td>
511<td class="c-table-data__cell c-table-data__rowaction" role="gridcell" tabindex="-1">
512 <div class="dropdown">
513 <button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown" id="id_3" aria-label="actions" aria-haspopup="true" aria-expanded="false" aria-controls="id_3_menu"><span class="caret"></span></button>
514 <ul id="id_3_menu" class="dropdown-menu">
515 <li><button class="btn btn-link" data-action="http://wwww.ilias.de?ref_id=1&namespace_param%5B%5D=row_id-1" id="id_1">label1</button></li>
516 <li><button class="btn btn-link" data-action="http://wwww.ilias.de?ref_id=1&namespace_param%5B%5D=row_id-1" id="id_2">label2</button></li>
517 </ul>
518 </div>
519</td>
520EOT;
521 $expected = $this->brutallyTrimHTML($expected);
522 $this->assertEquals($expected, $actual);
523 }
524
525 public function testRenderEmptyDataCell(): void
526 {
527 $data = new class () implements Component\Table\DataRetrieval {
528 public function getRows(
529 Component\Table\DataRowBuilder $row_builder,
530 array $visible_column_ids,
531 Data\Range $range,
532 Data\Order $order,
533 ?array $filter_data,
534 ?array $additional_parameters
535 ): Generator {
536 yield from [];
537 }
538
539 public function getTotalRowCount(?array $filter_data, ?array $additional_parameters): ?int
540 {
541 return 0;
542 }
543 };
544
545 $columns = [
546 'f1' => $this->getUIFactory()->table()->column()->text('f1'),
547 'f2' => $this->getUIFactory()->table()->column()->text('f2'),
548 'f3' => $this->getUIFactory()->table()->column()->text('f3'),
549 'f4' => $this->getUIFactory()->table()->column()->text('f4'),
550 'f5' => $this->getUIFactory()->table()->column()->text('f5'),
551 ];
552
553 $table = $this->getTableFactory()->data('', $columns, $data)
554 ->withRequest($this->getDummyRequest());
555
556 $html = $this->getDefaultRenderer()->render($table);
557
558 $translation = $this->getLanguage()->txt('ui_table_no_records');
559 $column_count = count($columns);
560
561 // check that the empty cell is stretched over all columns.
562 $this->assertTrue(str_contains($html, "colspan=\"$column_count\""));
563 // check that the cell contains the default message.
564 $this->assertTrue(str_contains($html, $translation));
565 }
566}
wrapper around the renderer to expose protected functions
p_renderTableHeader(TestDefaultRenderer $default_renderer, I\Table\Data $component, $tpl, ?I\Signal $sortation_signal)
p_getMultiActionHandler(I\Signal $signal)
p_getSingleActionsForRow(string $row_id, array $actions)
p_getActionRegistration(string $action_id, I\Table\Action\Action $action)
p_buildMultiActionsDropdown(array $actions, I\Signal $action_signal, I\Signal $modal_signal)
Tests for the Renderer of DataTables.
testDataTableDataRowFromBuilder(array $params)
@depends testDataTableRowBuilder
testDataTableRenderStandardRow(I\Table\DataRow $row)
@depends testDataTableDataRowFromBuilder
testDataTableRenderHeaderWithoutSortableColums()
Builds a Color from either hex- or rgb values.
Definition: Factory.php:17
Builds data types.
Definition: Factory.php:21
Both the subject and the direction need to be specified when expressing an order.
Definition: Order.php:13
A simple class to express a range of whole positive numbers.
Definition: Range.php:31
getJavaScriptBinding()
Definition: Base.php:330
getTemplateFactory()
Definition: Base.php:315
brutallyTrimHTML(string $html)
A more radical version of normalizeHTML.
Definition: Base.php:444
getDefaultRenderer(JavaScriptBinding $js_binding=null, array $with_stub_renderings=[])
Definition: Base.php:355
Basic Tests for all Tables.
if($DIC->http() ->request() ->getMethod()=="GET" &&isset($DIC->http() ->request() ->getQueryParams()['tex'])) $tpl
Definition: latex.php:41
if(! $DIC->user() ->getId()||!ilLTIConsumerAccess::hasCustomProviderCreationAccess()) $params
Definition: ltiregstart.php:33
$factory
Definition: metadata.php:75
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Class ChatMainBarProvider \MainMenu\Provider.
Class Factory.
$url
$token
Definition: xapitoken.php:70