Skip to content

Commit 01ac0a7

Browse files
committed
refactor(datatables): improve custom button and tooltip implementation
- Reorder parameters: icon before tooltip for better ergonomics - Add conditional tooltip rendering to avoid empty title attributes - Implement smart icon handling to prevent empty HTML generation - Fix PSR-12 spacing (single blank line) - Add comprehensive test suite with 8 tests covering all features
1 parent 840de1e commit 01ac0a7

File tree

2 files changed

+147
-13
lines changed

2 files changed

+147
-13
lines changed

src/Datatables/Button.php

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,24 @@ public static function add(string $label = ''): self
3636
/**
3737
* Returns a custom button.
3838
*
39-
* @param string $route
40-
* @param array|string $args
41-
* @param string $tooltip
42-
* @param string $color
43-
* @param string $icon
44-
* @param array $attributes
39+
* @param string $route
40+
* @param array|string $args
41+
* @param string $icon
42+
* @param string $tooltip
43+
* @param string $color
44+
* @param array $attributes
4545
* @return string
4646
*/
47-
public static function custom(string $route, array|string $args = [], string $tooltip = '', string $color = 'default', string $icon = '', array $attributes = []): string
47+
public static function custom(string $route, array|string $args = [], string $icon = '', string $tooltip = '', string $color = 'default', array $attributes = []): string
4848
{
49-
return self::add()->route($route, $args)->tooltip($tooltip)->color($color)->icon($icon)->attributes($attributes)->make();
50-
}
49+
$button = self::add()->route($route, $args)->tooltip($tooltip);
5150

51+
if (! empty($icon)) {
52+
$button->icon($icon);
53+
}
54+
55+
return $button->color($color)->attributes($attributes)->make();
56+
}
5257

5358
/**
5459
* Returns an edit button.
@@ -186,8 +191,6 @@ public function link(string $href): self
186191
*/
187192
public function make(): string
188193
{
189-
$str = '<a href="%s" title="%s" class="btn btn-sm btn-%s ml-1%s" %s>%s%s</a>';
190-
191194
if (! empty($this->label) && ! empty($this->icon)) {
192195
$this->label = $this->label.' ';
193196
}
@@ -200,13 +203,16 @@ public function make(): string
200203
return sprintf('%s="%s"', $k, $this->attributes[$k]);
201204
}, array_keys($this->attributes)));
202205

203-
return sprintf($str, $this->href, $this->tooltip, $this->color, $this->class, $attributes, $this->label, $this->icon);
206+
$tooltip = ! empty($this->tooltip) ? sprintf(' title="%s"', $this->tooltip) : '';
207+
$str = '<a href="%s"%s class="btn btn-sm btn-%s ml-1%s" %s>%s%s</a>';
208+
209+
return sprintf($str, $this->href, $tooltip, $this->color, $this->class, $attributes, $this->label, $this->icon);
204210
}
205211

206212
/**
207213
* Sets tooltip of button.
208214
*
209-
* @param string $tooltip
215+
* @param string $tooltip
210216
* @return $this
211217
*/
212218
public function tooltip(string $tooltip): self

tests/Datatables/ButtonTest.php

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
<?php
2+
3+
namespace Sebastienheyd\Boilerplate\Tests\Datatables;
4+
5+
use Sebastienheyd\Boilerplate\Datatables\Button;
6+
use Sebastienheyd\Boilerplate\Tests\TestCase;
7+
8+
class ButtonTest extends TestCase
9+
{
10+
public function testTooltipMethod()
11+
{
12+
$button = Button::add('Test Button')
13+
->link('/test')
14+
->tooltip('This is a tooltip')
15+
->make();
16+
17+
$this->assertStringContainsString('title="This is a tooltip"', $button);
18+
}
19+
20+
public function testTooltipNotAddedWhenEmpty()
21+
{
22+
$button = Button::add('Test Button')
23+
->link('/test')
24+
->make();
25+
26+
$this->assertStringNotContainsString('title=', $button);
27+
}
28+
29+
public function testTooltipMethodChaining()
30+
{
31+
$button = Button::add('Test')
32+
->link('/test')
33+
->tooltip('Tooltip text')
34+
->color('primary')
35+
->icon('star')
36+
->make();
37+
38+
$this->assertStringContainsString('title="Tooltip text"', $button);
39+
$this->assertStringContainsString('btn-primary', $button);
40+
$this->assertStringContainsString('fa-star', $button);
41+
}
42+
43+
public function testButtonHtmlStructure()
44+
{
45+
$button = Button::add('Click me')
46+
->link('/action')
47+
->tooltip('Button tooltip')
48+
->color('success')
49+
->make();
50+
51+
$this->assertMatchesRegularExpression('/<a href="\/action" title="Button tooltip" class="btn btn-sm btn-success/', $button);
52+
}
53+
54+
public function testCustomButtonWithRoute()
55+
{
56+
// Define a test route
57+
$this->app['router']->get('/test/{id}', function () {
58+
return 'test';
59+
})->name('test.route');
60+
61+
$button = Button::custom(
62+
'test.route',
63+
['id' => 1],
64+
'star',
65+
'Custom tooltip',
66+
'success'
67+
);
68+
69+
$this->assertStringContainsString('title="Custom tooltip"', $button);
70+
$this->assertStringContainsString('btn-success', $button);
71+
$this->assertStringContainsString('fa-star', $button);
72+
$this->assertStringContainsString('/test/1', $button);
73+
}
74+
75+
public function testCustomButtonWithAttributes()
76+
{
77+
$this->app['router']->get('/test', function () {
78+
return 'test';
79+
})->name('test.route2');
80+
81+
$button = Button::custom(
82+
'test.route2',
83+
[],
84+
'heart',
85+
'Custom tooltip',
86+
'primary',
87+
['data-action' => 'custom-action', 'data-id' => '123']
88+
);
89+
90+
$this->assertStringContainsString('data-action="custom-action"', $button);
91+
$this->assertStringContainsString('data-id="123"', $button);
92+
$this->assertStringContainsString('btn-primary', $button);
93+
$this->assertStringContainsString('fa-heart', $button);
94+
}
95+
96+
public function testCustomButtonWithDefaults()
97+
{
98+
$this->app['router']->get('/default', function () {
99+
return 'test';
100+
})->name('test.default');
101+
102+
$button = Button::custom('test.default');
103+
104+
$this->assertStringNotContainsString('title=', $button);
105+
$this->assertStringContainsString('btn-default', $button);
106+
$this->assertStringNotContainsString('fa-', $button); // No icon by default
107+
}
108+
109+
public function testCustomButtonArgumentOrder()
110+
{
111+
// Test that $icon comes before $tooltip in the method signature
112+
$this->app['router']->get('/order', function () {
113+
return 'test';
114+
})->name('test.order');
115+
116+
$button = Button::custom(
117+
'test.order',
118+
[],
119+
'cog', // $icon (3rd parameter)
120+
'Tooltip', // $tooltip (4th parameter)
121+
'warning' // $color (5th parameter)
122+
);
123+
124+
$this->assertStringContainsString('fa-cog', $button);
125+
$this->assertStringContainsString('title="Tooltip"', $button);
126+
$this->assertStringContainsString('btn-warning', $button);
127+
}
128+
}

0 commit comments

Comments
 (0)