ILIAS  trunk Revision v11.0_alpha-2638-g80c1d007f79
DataRendererTest.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
21 require_once("vendor/composer/vendor/autoload.php");
22 require_once(__DIR__ . "/TableRendererTestBase.php");
23 
26 use ILIAS\Data;
28 
32 class 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 
44  public function p_buildMultiActionsDropdown(
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(),
86  new ilImagePathResolver(),
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,
175  Data\Range $range,
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>
242 EOT;
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,
258  Data\Range $range,
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>
316 EOT;
317  $expected = $this->brutallyTrimHTML($expected);
318  $this->assertEquals($expected, $actual);
319  }
320 
321  public function testDataTableRenderHeaderWithActions(): void
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,
339  Data\Range $range,
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 
452 EOT;
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,
463  Data\Range $range,
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 }
testDataTableDataRowFromBuilder(array $params)
p_buildMultiActionsDropdown(array $actions, I\Signal $action_signal, I\Signal $modal_signal)
button(string $caption, string $cmd)
$renderer
if(! $DIC->user() ->getId()||!ilLTIConsumerAccess::hasCustomProviderCreationAccess()) $params
Definition: ltiregstart.php:31
Interface Observer Contains several chained tasks and infos about them.
Tests for the Renderer of DataTables.
testDataTableRenderStandardRow(I\Table\DataRow $row)
p_getSingleActionsForRow(string $row_id, array $actions)
$url
Definition: shib_logout.php:68
p_renderTableHeader(TestDefaultRenderer $default_renderer, I\Table\Data $component, $tpl, ?I\Signal $sortation_signal)
sort()
description: > Example for rendering a Sort Glyph.
Definition: sort.php:41
Both the subject and the direction need to be specified when expressing an order. ...
Definition: Order.php:28
p_renderActionsHeader(TestDefaultRenderer $default_renderer, I\Table\Data $component, $tpl)
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
getLanguage()
$token
Definition: xapitoken.php:70
testDataTableRenderHeaderWithoutSortableColums()
Tests for the Renderer of DataTables.
wrapper around the renderer to expose protected functions
p_getActionRegistration(string $action_id, I\Table\Action\Action $action)
Builds data types.
Definition: Factory.php:35
form( $class_path, string $cmd, string $submit_caption="")
p_getMultiActionHandler(I\Signal $signal)
URLBuilder.
Definition: URLBuilder.php:40
A simple class to express a naive range of whole positive numbers.
Definition: Range.php:28