ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
DataRendererTest.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
21require_once("vendor/composer/vendor/autoload.php");
22require_once(__DIR__ . "/TableRendererTestBase.php");
23
26use ILIAS\Data;
28
32class DTRenderer extends I\Table\Renderer
33{
34 public function p_getMultiActionHandler(I\Signal $signal)
35 {
36 return $this->getMultiActionHandler($signal);
37 }
38
39 public function p_getActionRegistration(string $action_id, I\Table\Action\Action $action)
40 {
41 return $this->getActionRegistration($action_id, $action);
42 }
43
45 array $actions,
46 I\Signal $action_signal,
47 I\Signal $modal_signal
48 ) {
49 return $this->buildMultiActionsDropdown($actions, $action_signal, $modal_signal);
50 }
51
52 public function p_getSingleActionsForRow(string $row_id, array $actions)
53 {
54 return $this->getSingleActionsForRow($row_id, $actions);
55 }
56
57 public function p_renderTableHeader(
58 TestDefaultRenderer $default_renderer,
59 I\Table\Data $component,
60 $tpl,
61 ?I\Signal $sortation_signal
62 ) {
63 $this->renderTableHeader($default_renderer, $component, $tpl, $sortation_signal, 1);
64 }
65 public function p_renderActionsHeader(
66 TestDefaultRenderer $default_renderer,
67 I\Table\Data $component,
68 $tpl
69 ) {
70 $this->renderActionsHeader($default_renderer, $component, $tpl, 1);
71 }
72}
73
78{
79 private function getRenderer()
80 {
81 return new DTRenderer(
82 $this->getUIFactory(),
83 $this->getTemplateFactory(),
84 $this->getLanguage(),
85 $this->getJavaScriptBinding(),
87 new \ILIAS\Data\Factory(),
88 new \ILIAS\UI\Help\TextRetriever\Echoing(),
89 $this->getUploadLimitResolver()
90 );
91 }
92
94 {
95 $renderer = $this->getRenderer();
96 $signal = new I\Signal('signal_id');
97 $closure = $renderer->p_getMultiActionHandler($signal);
98 $actual = $this->brutallyTrimHTML($closure('component_id'));
99 $expected = $this->brutallyTrimHTML(
100 "$(document).on('signal_id', function(event, signal_data) {
101 il.UI.table.data.get('component_id').doMultiAction(signal_data);
102 return false;
103 });"
104 );
105 $this->assertEquals($expected, $actual);
106 }
107
109 {
110 $renderer = $this->getRenderer();
111 $f = $this->getActionFactory();
112 $url = $this->getDataFactory()->uri('http://wwww.ilias.de?ref_id=1');
113 $url_builder = new URLBuilder($url);
114 list($builder, $token) = $url_builder->acquireParameter(['namespace'], 'param');
115
116 $action = $f->standard('label', $builder, $token);
117 $closure = $renderer->p_getActionRegistration('action_id', $action);
118
119 $actual = $this->brutallyTrimHTML($closure('component_id'));
120 $url = $url->__toString();
121 $expected = $this->brutallyTrimHTML(
122 '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",'
123 );
124 $this->assertStringStartsWith($expected, $actual);
125 }
126
128 {
129 $renderer = $this->getRenderer();
130 $f = $this->getActionFactory();
131 $signal1 = new I\Signal('signal_id');
132 $signal2 = new I\Signal('signal_id2');
133 $url = $this->getDataFactory()->uri('http://wwww.ilias.de?ref_id=1');
134 $url_builder = new URLBuilder($url);
135 list($builder, $token) = $url_builder->acquireParameter(['namespace'], 'param');
136 $actions = [
137 $f->standard('label1', $builder, $token),
138 $f->standard('label2', $builder, $token)
139 ];
140 $this->assertNull(
141 $renderer->p_buildMultiActionsDropdown([], $signal1, $signal2)
142 );
143 $this->assertEquals(
144 4, //2 actions, 1 divider, one all-action
145 count($renderer->p_buildMultiActionsDropdown($actions, $signal1, $signal2)->getItems())
146 );
147 }
149 {
150 $renderer = $this->getRenderer();
151 $f = $this->getActionFactory();
152 $url = $this->getDataFactory()->uri('http://wwww.ilias.de?ref_id=1');
153 $url_builder = new URLBuilder($url);
154 list($builder, $token) = $url_builder->acquireParameter(['namespace'], 'param');
155 $actions = [
156 'a1' => $f->standard('label1', $builder, $token)->withAsync(),
157 'a2' => $f->standard('label2', $builder, $token)
158 ];
159 $this->assertEquals(
160 2,
161 count($renderer->p_getSingleActionsForRow('row_id-1', $actions)->getItems())
162 );
163 }
164
166 {
167 $renderer = $this->getRenderer();
168 $data_factory = new \ILIAS\Data\Factory();
169 $tpl = $this->getTemplateFactory()->getTemplate("components/ILIAS/UI/src/templates/default/Table/tpl.datatable.html", true, true);
170 $f = $this->getColumnFactory();
171 $data = new class () implements ILIAS\UI\Component\Table\DataRetrieval {
172 public function getRows(
173 Component\Table\DataRowBuilder $row_builder,
174 array $visible_column_ids,
176 Data\Order $order,
177 ?array $filter_data,
178 ?array $additional_parameters
179 ): \Generator {
180 yield $row_builder->buldDataRow('', []);
181 }
182 public function getTotalRowCount(
183 ?array $filter_data,
184 ?array $additional_parameters
185 ): ?int {
186 return null;
187 }
188 };
189 $columns = [
190 'f1' => $f->text("Field 1")->withIndex(1),
191 'f2' => $f->text("Field 2")->withIndex(2)->withIsSortable(false),
192 'f3' => $f->number("Field 3")->withIndex(3)
193 ];
194 $sortation_signal = new I\Signal('sort_header_signal_id');
195 $sortation_signal->addOption('value', 'f1:ASC');
196 $table = $this->getUIFactory()->table()->data($data, '', $columns)
197 ->withRequest($this->getDummyRequest());
198 $renderer->p_renderTableHeader($this->getDefaultRenderer(), $table, $tpl, $sortation_signal);
199
200 $actual = $this->brutallyTrimHTML($tpl->get());
201 $expected = <<<EOT
202<div class="c-table-data" id="{ID}">
203 <div class="viewcontrols">{VIEW_CONTROLS}</div>
204 <div class="c-table-data__table-wrapper">
205 <table class="c-table-data__table" aria-labelledby="{ID}_label" aria-colcount="{COL_COUNT}" role="grid">
206 <thead>
207 <tr class="c-table-data__header c-table-data__row">
208 <th class="c-table-data__header c-table-data__cell c-table-data__cell--text" tabindex="-1" aria-colindex="1" aria-sort="ascending">
209 <div class="c-table-data__header__resize-wrapper">
210 <a tabindex="0" class="glyph" href="#" aria-label="sort_ascending" id="id_2"><span class="glyphicon glyphicon-arrow-up" aria-hidden="true"></span></a>
211 <button class="btn btn-link" id="id_1">Field 1</button>
212 </div>
213 </th>
214 <th class="c-table-data__header c-table-data__cell c-table-data__cell--text" tabindex="-1" aria-colindex="2">
215 <div class="c-table-data__header__resize-wrapper">Field 2</div>
216 </th>
217 <th class="c-table-data__header c-table-data__cell c-table-data__cell--number" tabindex="-1" aria-colindex="3">
218 <div class="c-table-data__header__resize-wrapper">
219 <button class="btn btn-link" id="id_3">Field 3</button>
220 </div>
221 </th>
222 </tr>
223 </thead>
224 <tbody class="c-table-data__body"></tbody>
225 </table>
226 </div>
227 <div class="c-table-data__async_modal_container"></div>
228 <dialog class="c-table-data__async_message c-modal" id="{ID}_msgmodal">
229 <div class="modal-dialog" role="document">
230 <div class="modal-content">
231 <div class="modal-header">
232 <form>
233 <button formmethod="dialog" class="close" aria-label="close">
234 <span aria-hidden="true">&times;</span></button>
235 </form>
236 </div>
237 <div class="c-table-data__async_messageresponse modal-body"></div>
238 </div>
239 </div>
240 </dialog>
241</div>
242EOT;
243 $expected = $this->brutallyTrimHTML($expected);
244 $this->assertEquals($expected, $actual);
245 }
246
247
249 {
250 $renderer = $this->getRenderer();
251 $data_factory = new \ILIAS\Data\Factory();
252 $tpl = $this->getTemplateFactory()->getTemplate("components/ILIAS/UI/src/templates/default/Table/tpl.datatable.html", true, true);
253 $f = $this->getColumnFactory();
254 $data = new class () implements ILIAS\UI\Component\Table\DataRetrieval {
255 public function getRows(
256 Component\Table\DataRowBuilder $row_builder,
257 array $visible_column_ids,
259 Data\Order $order,
260 ?array $filter_data,
261 ?array $additional_parameters
262 ): \Generator {
263 yield $row_builder->buldDataRow('', []);
264 }
265 public function getTotalRowCount(
266 ?array $filter_data,
267 ?array $additional_parameters
268 ): ?int {
269 return null;
270 }
271 };
272 $columns = [
273 'f1' => $f->text("Field 1")->withIsSortable(false),
274 'f2' => $f->text("Field 2")->withIsSortable(false)
275 ];
276
277 $sortation_signal = null;
278
279 $table = $this->getUIFactory()->table()->data($data, '', $columns)
280 ->withRequest($this->getDummyRequest());
281 $renderer->p_renderTableHeader($this->getDefaultRenderer(), $table, $tpl, $sortation_signal);
282 $actual = $this->brutallyTrimHTML($tpl->get());
283 $expected = <<<EOT
284<div class="c-table-data" id="{ID}">
285 <div class="viewcontrols">{VIEW_CONTROLS}</div>
286 <div class="c-table-data__table-wrapper">
287 <table class="c-table-data__table" aria-labelledby="{ID}_label" aria-colcount="{COL_COUNT}" role="grid">
288 <thead>
289 <tr class="c-table-data__header c-table-data__row">
290 <th class="c-table-data__header c-table-data__cell c-table-data__cell--text" tabindex="-1" aria-colindex="1">
291 <div class="c-table-data__header__resize-wrapper">Field 1</div>
292 </th>
293 <th class="c-table-data__header c-table-data__cell c-table-data__cell--text" tabindex="-1" aria-colindex="2">
294 <div class="c-table-data__header__resize-wrapper">Field 2</div>
295 </th>
296 </tr>
297 </thead>
298 <tbody class="c-table-data__body"></tbody>
299 </table>
300 </div>
301 <div class="c-table-data__async_modal_container"></div>
302 <dialog class="c-table-data__async_message c-modal" id="{ID}_msgmodal">
303 <div class="modal-dialog" role="document">
304 <div class="modal-content">
305 <div class="modal-header">
306 <form>
307 <button formmethod="dialog" class="close" aria-label="close">
308 <span aria-hidden="true">&times;</span></button>
309 </form>
310 </div>
311 <div class="c-table-data__async_messageresponse modal-body"></div>
312 </div>
313 </div>
314 </dialog>
315</div>
316EOT;
317 $expected = $this->brutallyTrimHTML($expected);
318 $this->assertEquals($expected, $actual);
319 }
320
322 {
323 $renderer = $this->getRenderer();
324 $data_factory = new \ILIAS\Data\Factory();
325 $tpl = $this->getTemplateFactory()->getTemplate("components/ILIAS/UI/src/templates/default/Table/tpl.datatable.html", true, true);
326 $f = $this->getColumnFactory();
327
328 $url = $data_factory->uri('http://wwww.ilias.de?ref_id=1');
329 $url_builder = new URLBuilder($url);
330 list($builder, $token) = $url_builder->acquireParameter(['namespace'], 'param');
331 $actions = [
332 'a2' => $this->getActionFactory()->standard('some action', $builder, $token)
333 ];
334
335 $data = new class () implements ILIAS\UI\Component\Table\DataRetrieval {
336 public function getRows(
337 Component\Table\DataRowBuilder $row_builder,
338 array $visible_column_ids,
340 Data\Order $order,
341 ?array $filter_data,
342 ?array $additional_parameters
343 ): \Generator {
344 yield $row_builder->buldDataRow('', []);
345 }
346 public function getTotalRowCount(
347 ?array $filter_data,
348 ?array $additional_parameters
349 ): ?int {
350 return null;
351 }
352 };
353 $columns = [
354 'f1' => $f->text("Field 1")->withIsSortable(false),
355 ];
356
357 $sortation_signal = null;
358
359 $table = $this->getUIFactory()->table()->data($data, '', $columns)
360 ->withActions($actions)
361 ->withRequest($this->getDummyRequest());
362 $renderer->p_renderActionsHeader($this->getDefaultRenderer(), $table, $tpl);
363 $actual = $this->brutallyTrimHTML($tpl->get());
364
365 $expected = '<th class="c-table-data__header c-table-data__cell c-table-data__header__rowaction" aria-colindex="2">actions</th>';
366 $this->assertStringContainsString($expected, $actual);
367 }
368
369 public function testDataTableRowBuilder()
370 {
371 $f = $this->getColumnFactory();
372 $columns = [
373 'f1' => $f->text("Field 1")->withIndex(1),
374 'f2' => $f->text("Field 2")->withIndex(2),
375 'f3' => $f->number("Field 3")->withIndex(3)
376 ];
377 $f = $this->getActionFactory();
378 $url = $this->getDataFactory()->uri('http://wwww.ilias.de?ref_id=1');
379 $url_builder = new URLBuilder($url);
380 list($builder, $token) = $url_builder->acquireParameter(['namespace'], 'param');
381 $actions = [
382 'a1' => $f->standard('label1', $builder, $token)->withAsync(),
383 'a2' => $f->standard('label2', $builder, $token)
384 ];
385
386 $rb = (new I\Table\DataRowBuilder())
387 ->withMultiActionsPresent(true)
388 ->withSingleActions($actions)
389 ->withVisibleColumns($columns);
390
391 $row = $rb->buildDataRow('row_id-1', []);
392 $this->assertInstanceOf(Component\Table\DataRow::class, $row);
393
394 return [$rb, $columns, $actions];
395 }
396
397 #[\PHPUnit\Framework\Attributes\Depends('testDataTableRowBuilder')]
398 public function testDataTableDataRowFromBuilder(array $params): I\Table\DataRow
399 {
400 list($rb, $columns, $actions) = $params;
401 $record = [
402 'f1' => 'v1',
403 'f2' => 'v2',
404 'f3' => 3
405 ];
406 $row = $rb->buildDataRow('row_id-1', $record);
407
408 $this->assertEquals(
409 $columns,
410 $row->getColumns()
411 );
412 $this->assertEquals(
413 $actions,
414 $row->getActions()
415 );
416 $this->assertEquals(
417 $record['f2'],
418 $row->getCellContent('f2')
419 );
420
421 return $row;
422 }
423
424 #[\PHPUnit\Framework\Attributes\Depends('testDataTableDataRowFromBuilder')]
425 public function testDataTableRenderStandardRow(I\Table\DataRow $row)
426 {
427 $actual = $this->brutallyTrimHTML($this->getDefaultRenderer()->render($row));
428 $expected = <<<EOT
429<td class="c-table-data__cell c-table-data__rowselection" tabindex="-1">
430 <input type="checkbox" value="row_id-1" class="c-table-data__row-selector"></td>
431<td class="c-table-data__cell c-table-data__cell--text " tabindex="-1"><span class="c-table-data__cell__col-title">Field 1:</span>v1
432</td>
433<td class="c-table-data__cell c-table-data__cell--text " tabindex="-1"><span class="c-table-data__cell__col-title">Field 2:</span>v2
434</td>
435<td class="c-table-data__cell c-table-data__cell--number " tabindex="-1"><span class="c-table-data__cell__col-title">Field 3:</span>3
436</td>
437<td class="c-table-data__cell c-table-data__rowaction" tabindex="-1">
438 <div class="dropdown" id="id_3">
439 <button class="btn btn-default dropdown-toggle" type="button" aria-label="actions" aria-haspopup="true" aria-expanded="false" aria-controls="id_3_menu">
440 <span class="caret"></span></button>
441 <ul id="id_3_menu" class="dropdown-menu">
442 <li>
443 <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>
444 </li>
445 <li>
446 <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>
447 </li>
448 </ul>
449 </div>
450</td>
451
452EOT;
453 $expected = $this->brutallyTrimHTML($expected);
454 $this->assertEquals($expected, $actual);
455 }
456
457 public function testRenderEmptyDataCell(): void
458 {
459 $data = new class () implements Component\Table\DataRetrieval {
460 public function getRows(
461 Component\Table\DataRowBuilder $row_builder,
462 array $visible_column_ids,
464 Data\Order $order,
465 ?array $filter_data,
466 ?array $additional_parameters
467 ): Generator {
468 yield from [];
469 }
470
471 public function getTotalRowCount(?array $filter_data, ?array $additional_parameters): ?int
472 {
473 return 0;
474 }
475 };
476
477 $columns = [
478 'f1' => $this->getUIFactory()->table()->column()->text('f1'),
479 'f2' => $this->getUIFactory()->table()->column()->text('f2'),
480 'f3' => $this->getUIFactory()->table()->column()->text('f3'),
481 'f4' => $this->getUIFactory()->table()->column()->text('f4'),
482 'f5' => $this->getUIFactory()->table()->column()->text('f5'),
483 ];
484
485 $table = $this->getTableFactory()->data($data, '', $columns)
486 ->withRequest($this->getDummyRequest());
487
488 $html = $this->getDefaultRenderer()->render($table);
489
490 $translation = $this->getLanguage()->txt('ui_table_no_records');
491 $column_count = count($columns);
492
493 // check that the empty cell is stretched over all columns.
494 $this->assertTrue(str_contains($html, "colspan=\"$column_count\""));
495 // check that the cell contains the default message.
496 $this->assertTrue(str_contains($html, $translation));
497 }
498}
$renderer
wrapper around the renderer to expose protected functions
p_renderTableHeader(TestDefaultRenderer $default_renderer, I\Table\Data $component, $tpl, ?I\Signal $sortation_signal)
p_renderActionsHeader(TestDefaultRenderer $default_renderer, I\Table\Data $component, $tpl)
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)
testDataTableRenderStandardRow(I\Table\DataRow $row)
testDataTableRenderHeaderWithoutSortableColums()
Builds data types.
Definition: Factory.php:36
Both the subject and the direction need to be specified when expressing an order.
Definition: Order.php:29
A simple class to express a naive range of whole positive numbers.
Definition: Range.php:29
Definition: UI.php:24
Tests for the Renderer of DataTables.
if(! $DIC->user() ->getId()||!ilLTIConsumerAccess::hasCustomProviderCreationAccess()) $params
Definition: ltiregstart.php:31
form( $class_path, string $cmd, string $submit_caption="")
button(string $caption, string $cmd)
Interface Observer \BackgroundTasks Contains several chained tasks and infos about them.
$url
Definition: shib_logout.php:68
getLanguage()
$token
Definition: xapitoken.php:70