Skip to content

Commit 2418a01

Browse files
committed
test: column control
1 parent 7f94df5 commit 2418a01

File tree

2 files changed

+369
-4
lines changed

2 files changed

+369
-4
lines changed

src/Html/Options/Plugins/ColumnControl.php

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,19 @@ protected function addColumnControl(int|string $target, array $content): static
3131
// get existing target and merge content if exists
3232
foreach ($this->attributes['columnControl'] as &$control) {
3333
if (isset($control['target']) && $control['target'] === $target) {
34-
$control['content'] = array_unique(
35-
array_merge($control['content'] ?? [], $content)
36-
);
34+
$existingContent = $control['content'] ?? [];
35+
$mergedContent = array_merge($existingContent, $content);
36+
37+
// Remove duplicates properly for mixed array types (strings and arrays)
38+
$uniqueContent = [];
39+
foreach ($mergedContent as $item) {
40+
$serialized = is_array($item) ? serialize($item) : $item;
41+
if (! in_array($serialized, array_map(fn ($i) => is_array($i) ? serialize($i) : $i, $uniqueContent))) {
42+
$uniqueContent[] = $item;
43+
}
44+
}
45+
46+
$control['content'] = $uniqueContent;
3747

3848
return $this;
3949
}
@@ -60,7 +70,7 @@ public function columnControlFooter(array $content, int $target = 0): static
6070

6171
public function columnControlFooterSearch(array $content = []): static
6272
{
63-
$this->addColumnControl('tfoot', [$content] ?? ['search']);
73+
$this->addColumnControl('tfoot', [empty($content) ? ['search'] : $content]);
6474

6575
return $this;
6676
}
Lines changed: 355 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,355 @@
1+
<?php
2+
3+
namespace Yajra\DataTables\Html\Tests\Html\Extensions;
4+
5+
use PHPUnit\Framework\Attributes\Test;
6+
use Yajra\DataTables\Html\Builder;
7+
use Yajra\DataTables\Html\Column;
8+
use Yajra\DataTables\Html\Tests\TestCase;
9+
10+
class ColumnControlTest extends TestCase
11+
{
12+
#[Test]
13+
public function it_can_set_column_control_options_on_builder()
14+
{
15+
$builder = $this->getHtmlBuilder();
16+
$options = [
17+
'target' => 0,
18+
'content' => ['search', 'order']
19+
];
20+
21+
$result = $builder->columnControl($options);
22+
23+
$this->assertInstanceOf(Builder::class, $result);
24+
$this->assertEquals($options, $builder->getAttributes()['columnControl']);
25+
}
26+
27+
#[Test]
28+
public function it_can_set_column_control_options_on_column()
29+
{
30+
$column = Column::make('name');
31+
$options = [
32+
'target' => 'thead:0',
33+
'content' => ['search']
34+
];
35+
36+
$result = $column->columnControl($options);
37+
38+
$this->assertInstanceOf(Column::class, $result);
39+
$this->assertEquals($options, $column->getAttributes()['columnControl']);
40+
}
41+
42+
#[Test]
43+
public function it_can_add_column_control_header()
44+
{
45+
$builder = $this->getHtmlBuilder();
46+
$content = ['search', 'order'];
47+
$target = 1;
48+
49+
$result = $builder->columnControlHeader($content, $target);
50+
51+
$this->assertInstanceOf(Builder::class, $result);
52+
$expected = [
53+
['target' => 'thead:1', 'content' => $content]
54+
];
55+
$this->assertEquals($expected, $builder->getAttributes()['columnControl']);
56+
}
57+
58+
#[Test]
59+
public function it_can_add_column_control_header_with_default_target()
60+
{
61+
$builder = $this->getHtmlBuilder();
62+
$content = ['search'];
63+
64+
$result = $builder->columnControlHeader($content);
65+
66+
$this->assertInstanceOf(Builder::class, $result);
67+
$expected = [
68+
['target' => 'thead:0', 'content' => $content]
69+
];
70+
$this->assertEquals($expected, $builder->getAttributes()['columnControl']);
71+
}
72+
73+
#[Test]
74+
public function it_can_add_column_control_footer()
75+
{
76+
$builder = $this->getHtmlBuilder();
77+
$content = ['search', 'order'];
78+
$target = 2;
79+
80+
$result = $builder->columnControlFooter($content, $target);
81+
82+
$this->assertInstanceOf(Builder::class, $result);
83+
$expected = [
84+
['target' => 'tfoot:2', 'content' => $content]
85+
];
86+
$this->assertEquals($expected, $builder->getAttributes()['columnControl']);
87+
}
88+
89+
#[Test]
90+
public function it_can_add_column_control_footer_with_default_target()
91+
{
92+
$builder = $this->getHtmlBuilder();
93+
$content = ['order'];
94+
95+
$result = $builder->columnControlFooter($content);
96+
97+
$this->assertInstanceOf(Builder::class, $result);
98+
$expected = [
99+
['target' => 'tfoot:0', 'content' => $content]
100+
];
101+
$this->assertEquals($expected, $builder->getAttributes()['columnControl']);
102+
}
103+
104+
#[Test]
105+
public function it_can_add_column_control_footer_search()
106+
{
107+
$builder = $this->getHtmlBuilder();
108+
109+
$result = $builder->columnControlFooterSearch();
110+
111+
$this->assertInstanceOf(Builder::class, $result);
112+
$expected = [
113+
['target' => 'tfoot', 'content' => [['search']]]
114+
];
115+
$this->assertEquals($expected, $builder->getAttributes()['columnControl']);
116+
}
117+
118+
#[Test]
119+
public function it_can_add_column_control_footer_search_with_custom_content()
120+
{
121+
$builder = $this->getHtmlBuilder();
122+
$content = ['customSearch'];
123+
124+
$result = $builder->columnControlFooterSearch($content);
125+
126+
$this->assertInstanceOf(Builder::class, $result);
127+
$expected = [
128+
['target' => 'tfoot', 'content' => [['customSearch']]]
129+
];
130+
$this->assertEquals($expected, $builder->getAttributes()['columnControl']);
131+
}
132+
133+
#[Test]
134+
public function it_can_add_column_control_search_dropdown()
135+
{
136+
$builder = $this->getHtmlBuilder();
137+
$target = 1;
138+
139+
$result = $builder->columnControlSearchDropdown($target);
140+
141+
$this->assertInstanceOf(Builder::class, $result);
142+
$expected = [
143+
['target' => 1, 'content' => ['order', 'searchDropdown']]
144+
];
145+
$this->assertEquals($expected, $builder->getAttributes()['columnControl']);
146+
147+
// Should also set ordering options
148+
$attributes = $builder->getAttributes();
149+
$this->assertEquals(['indicators' => false, 'handler' => false], $attributes['ordering']);
150+
}
151+
152+
#[Test]
153+
public function it_can_add_column_control_search_dropdown_with_default_target()
154+
{
155+
$builder = $this->getHtmlBuilder();
156+
157+
$result = $builder->columnControlSearchDropdown();
158+
159+
$this->assertInstanceOf(Builder::class, $result);
160+
$expected = [
161+
['target' => 0, 'content' => ['order', 'searchDropdown']]
162+
];
163+
$this->assertEquals($expected, $builder->getAttributes()['columnControl']);
164+
}
165+
166+
#[Test]
167+
public function it_can_add_column_control_search()
168+
{
169+
$builder = $this->getHtmlBuilder();
170+
$content = ['customSearch'];
171+
$target = 2;
172+
173+
$result = $builder->columnControlSearch($content, $target);
174+
175+
$this->assertInstanceOf(Builder::class, $result);
176+
$expected = [
177+
['target' => 2, 'content' => $content]
178+
];
179+
$this->assertEquals($expected, $builder->getAttributes()['columnControl']);
180+
}
181+
182+
#[Test]
183+
public function it_can_add_column_control_search_with_defaults()
184+
{
185+
$builder = $this->getHtmlBuilder();
186+
187+
$result = $builder->columnControlSearch();
188+
189+
$this->assertInstanceOf(Builder::class, $result);
190+
$expected = [
191+
['target' => 1, 'content' => ['search']]
192+
];
193+
$this->assertEquals($expected, $builder->getAttributes()['columnControl']);
194+
}
195+
196+
#[Test]
197+
public function it_can_add_column_control_spacer()
198+
{
199+
$builder = $this->getHtmlBuilder();
200+
$target = 3;
201+
202+
$result = $builder->columnControlSpacer($target);
203+
204+
$this->assertInstanceOf(Builder::class, $result);
205+
$expected = [
206+
['target' => 3, 'content' => [['extend' => 'spacer']]]
207+
];
208+
$this->assertEquals($expected, $builder->getAttributes()['columnControl']);
209+
}
210+
211+
#[Test]
212+
public function it_can_add_column_control_spacer_with_default_target()
213+
{
214+
$builder = $this->getHtmlBuilder();
215+
216+
$result = $builder->columnControlSpacer();
217+
218+
$this->assertInstanceOf(Builder::class, $result);
219+
$expected = [
220+
['target' => 1, 'content' => [['extend' => 'spacer']]]
221+
];
222+
$this->assertEquals($expected, $builder->getAttributes()['columnControl']);
223+
}
224+
225+
#[Test]
226+
public function it_can_add_column_control_title_with_string()
227+
{
228+
$builder = $this->getHtmlBuilder();
229+
$title = 'My Title';
230+
$target = 2;
231+
232+
$result = $builder->columnControlTitle($title, $target);
233+
234+
$this->assertInstanceOf(Builder::class, $result);
235+
$expected = [
236+
['target' => 2, 'content' => [['extend' => 'title', 'text' => 'My Title']]]
237+
];
238+
$this->assertEquals($expected, $builder->getAttributes()['columnControl']);
239+
}
240+
241+
#[Test]
242+
public function it_can_add_column_control_title_with_array()
243+
{
244+
$builder = $this->getHtmlBuilder();
245+
$title = ['text' => 'Custom Title', 'className' => 'custom-class'];
246+
$target = 3;
247+
248+
$result = $builder->columnControlTitle($title, $target);
249+
250+
$this->assertInstanceOf(Builder::class, $result);
251+
$expected = [
252+
['target' => 3, 'content' => [['extend' => 'title', 'text' => 'Custom Title', 'className' => 'custom-class']]]
253+
];
254+
$this->assertEquals($expected, $builder->getAttributes()['columnControl']);
255+
}
256+
257+
#[Test]
258+
public function it_can_add_column_control_title_with_defaults()
259+
{
260+
$builder = $this->getHtmlBuilder();
261+
262+
$result = $builder->columnControlTitle();
263+
264+
$this->assertInstanceOf(Builder::class, $result);
265+
$expected = [
266+
['target' => 1, 'content' => [['extend' => 'title', 'text' => null]]]
267+
];
268+
$this->assertEquals($expected, $builder->getAttributes()['columnControl']);
269+
}
270+
271+
#[Test]
272+
public function it_merges_content_for_same_target()
273+
{
274+
$builder = $this->getHtmlBuilder();
275+
276+
// Add first control for target 1
277+
$builder->columnControlSearch(['search'], 1);
278+
// Add second control for target 1
279+
$builder->columnControlSpacer(1);
280+
281+
$expected = [
282+
['target' => 1, 'content' => ['search', ['extend' => 'spacer']]]
283+
];
284+
$this->assertEquals($expected, $builder->getAttributes()['columnControl']);
285+
}
286+
287+
#[Test]
288+
public function it_removes_duplicate_content_when_merging()
289+
{
290+
$builder = $this->getHtmlBuilder();
291+
292+
// Add same content twice for the same target
293+
$builder->columnControlSearch(['search', 'order'], 1);
294+
295+
// Use reflection to access the protected method for testing
296+
$reflection = new \ReflectionClass($builder);
297+
$method = $reflection->getMethod('addColumnControl');
298+
$method->setAccessible(true);
299+
$method->invoke($builder, 1, ['search', 'filter']);
300+
301+
$attributes = $builder->getAttributes();
302+
$content = $attributes['columnControl'][0]['content'];
303+
304+
// Should have unique values only
305+
$this->assertCount(3, $content);
306+
$this->assertContains('search', $content);
307+
$this->assertContains('order', $content);
308+
$this->assertContains('filter', $content);
309+
}
310+
311+
#[Test]
312+
public function it_can_chain_multiple_column_control_methods()
313+
{
314+
$builder = $this->getHtmlBuilder();
315+
316+
$result = $builder
317+
->columnControlHeader(['search'])
318+
->columnControlFooter(['order'])
319+
->columnControlSpacer(2)
320+
->columnControlTitle('Test Title', 3);
321+
322+
$this->assertInstanceOf(Builder::class, $result);
323+
324+
$expected = [
325+
['target' => 'thead:0', 'content' => ['search']],
326+
['target' => 'tfoot:0', 'content' => ['order']],
327+
['target' => 2, 'content' => [['extend' => 'spacer']]],
328+
['target' => 3, 'content' => [['extend' => 'title', 'text' => 'Test Title']]]
329+
];
330+
$this->assertEquals($expected, $builder->getAttributes()['columnControl']);
331+
}
332+
333+
#[Test]
334+
public function it_works_with_column_instances()
335+
{
336+
$column = Column::make('name')
337+
->columnControlHeader(['search'])
338+
->columnControlSpacer()
339+
->columnControlTitle('Column Title');
340+
341+
$attributes = $column->getAttributes();
342+
343+
// We expect separate entries, not merged ones for different targets
344+
$this->assertCount(2, $attributes['columnControl']);
345+
346+
// Check first control (header)
347+
$this->assertEquals('thead:0', $attributes['columnControl'][0]['target']);
348+
$this->assertEquals(['search'], $attributes['columnControl'][0]['content']);
349+
350+
// Check second control (spacer + title merged for target 1)
351+
$this->assertEquals(1, $attributes['columnControl'][1]['target']);
352+
$this->assertContains(['extend' => 'spacer'], $attributes['columnControl'][1]['content']);
353+
$this->assertContains(['extend' => 'title', 'text' => 'Column Title'], $attributes['columnControl'][1]['content']);
354+
}
355+
}

0 commit comments

Comments
 (0)