Skip to content

Commit 272d17e

Browse files
committed
minor #1606 [Icons] Test IconRenderer (smnandre)
This PR was squashed before being merged into the 2.x branch. Discussion ---------- [Icons] Test IconRenderer Create tests for the IconRenderer Add internal docblock to clarify the attributes precedence (+ one CS fix passing by) -- + moved the InMemoryRegistrey in the `tests` directory As `@kbond` says, it won't be used by final users so it's better there Commits ------- e33253c [Icons] Test IconRenderer
2 parents 29be872 + e33253c commit 272d17e

File tree

5 files changed

+189
-5
lines changed

5 files changed

+189
-5
lines changed

src/Icons/src/IconRenderer.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,20 @@
1919
final class IconRenderer
2020
{
2121
public function __construct(
22-
private IconRegistryInterface $registry,
23-
private array $defaultIconAttributes = [],
22+
private readonly IconRegistryInterface $registry,
23+
private readonly array $defaultIconAttributes = [],
2424
) {
2525
}
2626

2727
/**
28+
* Renders an icon.
29+
*
30+
* Provided attributes are merged with the default attributes.
31+
* Existing icon attributes are then merged with those new attributes.
32+
*
33+
* Precedence order:
34+
* Icon file < Renderer configuration < Renderer invocation
35+
*
2836
* @param array<string,string|bool> $attributes
2937
*/
3038
public function renderIcon(string $name, array $attributes = []): string

src/Icons/tests/Integration/RenderIconsInTwigTest.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ public function testRenderIcons(): void
2323
{
2424
$output = self::getContainer()->get(Environment::class)->render('template1.html.twig');
2525

26-
$this->assertSame(<<<HTML
26+
$this->assertSame(
27+
<<<HTML
2728
<ul class="svg">
2829
<li id="first"><svg viewBox="0 0 24 24" fill="currentColor" class="h-8 w-8"><path fill-rule="evenodd" d="M7.5 6a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0ZM3.751 20.105a8.25 8.25 0 0 1 16.498 0 .75.75 0 0 1-.437.695A18.683 18.683 0 0 1 12 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 0 1-.437-.695Z" clip-rule="evenodd"></path></svg></li>
2930
<li id="second"><svg viewBox="0 0 24 24" fill="currentColor" class="w-6 h-6"><path fill-rule="evenodd" d="M7.5 6a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0ZM3.751 20.105a8.25 8.25 0 0 1 16.498 0 .75.75 0 0 1-.437.695A18.683 18.683 0 0 1 12 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 0 1-.437-.695Z" clip-rule="evenodd"></path></svg></li>
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\UX\Icons\Tests\Unit;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\UX\Icons\Exception\IconNotFoundException;
16+
use Symfony\UX\Icons\IconRegistryInterface;
17+
use Symfony\UX\Icons\IconRenderer;
18+
use Symfony\UX\Icons\Svg\Icon;
19+
use Symfony\UX\Icons\Tests\Util\InMemoryIconRegistry;
20+
21+
/**
22+
* @author Simon André <[email protected]>
23+
*/
24+
class IconRendererTest extends TestCase
25+
{
26+
public function testRenderIcon(): void
27+
{
28+
$registry = $this->createRegistry([
29+
'user' => '<circle ',
30+
]);
31+
$iconRenderer = new IconRenderer($registry);
32+
33+
$icon = $iconRenderer->renderIcon('user');
34+
35+
$this->assertStringContainsString('<svg', $icon);
36+
$this->assertStringContainsString('<circle', $icon);
37+
}
38+
39+
public function testRenderIconThrowsExceptionWhenIconNotFound(): void
40+
{
41+
$registry = $this->createRegistry([]);
42+
$iconRenderer = new IconRenderer($registry);
43+
44+
$this->expectException(IconNotFoundException::class);
45+
46+
$iconRenderer->renderIcon('foo');
47+
}
48+
49+
public function testRenderIconThrowsExceptionWhenAttributesAreInvalid(): void
50+
{
51+
$registry = $this->createRegistry(['foo' => '<path d="M0 0L12 12"/>']);
52+
$iconRenderer = new IconRenderer($registry);
53+
54+
$this->expectException(\InvalidArgumentException::class);
55+
56+
$iconRenderer->renderIcon('foo', [1, 2, null]);
57+
}
58+
59+
public function testRenderIconWithAttributes(): void
60+
{
61+
$registry = $this->createRegistry([
62+
'foo' => '<path d="M0 0L12 12"/>',
63+
]);
64+
$iconRenderer = new IconRenderer($registry);
65+
$attributes = ['viewBox' => '0 0 24 24', 'class' => 'icon', 'id' => 'FooBar'];
66+
67+
$svg = $iconRenderer->renderIcon('foo', $attributes);
68+
69+
$this->assertSame('<svg viewBox="0 0 24 24" class="icon" id="FooBar"><path d="M0 0L12 12"/></svg>', $svg);
70+
}
71+
72+
public function testRenderIconWithDefaultAttributes(): void
73+
{
74+
$registry = $this->createRegistry([
75+
'foo' => '<path d="M0 0L12 12"/>',
76+
]);
77+
$iconRenderer = new IconRenderer($registry, ['viewBox' => '0 0 24 24', 'class' => 'icon']);
78+
79+
$svg = $iconRenderer->renderIcon('foo');
80+
81+
$this->assertSame('<svg viewBox="0 0 24 24" class="icon"><path d="M0 0L12 12"/></svg>', $svg);
82+
}
83+
84+
/**
85+
* @dataProvider provideAttributesWithDefaultAttributesCases
86+
*/
87+
public function testRenderIconWithAttributesAndDefaultAttributes($iconAttrs, $defaultAttrs, $renderAttr, $expectedTag): void
88+
{
89+
$registry = $this->createRegistry([
90+
'foo' => ['', $iconAttrs],
91+
]);
92+
$iconRenderer = new IconRenderer($registry, $defaultAttrs);
93+
94+
$svg = $iconRenderer->renderIcon('foo', $renderAttr);
95+
$this->assertStringStartsWith($expectedTag, $svg);
96+
}
97+
98+
public static function provideAttributesWithDefaultAttributesCases()
99+
{
100+
yield 'no_attributes' => [
101+
[],
102+
[],
103+
[],
104+
'<svg>',
105+
];
106+
yield 'icon_attributes_are_used' => [
107+
['id' => 'icon'],
108+
[],
109+
[],
110+
'<svg id="icon">',
111+
];
112+
yield 'default_attributes_are_used' => [
113+
[],
114+
['id' => 'default'],
115+
[],
116+
'<svg id="default">',
117+
];
118+
yield 'render_attributes_are_used' => [
119+
[],
120+
[],
121+
['id' => 'render'],
122+
'<svg id="render">',
123+
];
124+
yield 'default_attributes_take_precedence_on_icon' => [
125+
['id' => 'icon'],
126+
['id' => 'default'],
127+
[],
128+
'<svg id="default">',
129+
];
130+
yield 'default_attributes_are_merged_with_icon_attributes' => [
131+
['id' => 'icon', 'foo' => 'bar'],
132+
['id' => 'default', 'baz' => 'qux'],
133+
[],
134+
'<svg id="default" foo="bar" baz="qux">',
135+
];
136+
yield 'render_attributes_take_precedence_on_default' => [
137+
[],
138+
['id' => 'default'],
139+
['id' => 'render'],
140+
'<svg id="render">',
141+
];
142+
yield 'render_attributes_are_merged_with_default_attributes' => [
143+
[],
144+
['id' => 'default', 'foo' => 'bar'],
145+
['id' => 'render', 'baz' => 'qux'],
146+
'<svg id="render" foo="bar" baz="qux">',
147+
];
148+
yield 'render_attributes_take_precedence_on_icon' => [
149+
['id' => 'icon'],
150+
[],
151+
['id' => 'render'],
152+
'<svg id="render">',
153+
];
154+
yield 'render_attributes_are_merged_with_icon_attributes' => [
155+
['id' => 'icon', 'foo' => 'bar'],
156+
[],
157+
['id' => 'render', 'baz' => 'qux'],
158+
'<svg id="render" foo="bar" baz="qux">',
159+
];
160+
}
161+
162+
private function createRegistry(array $icons): IconRegistryInterface
163+
{
164+
$registryIcons = [];
165+
foreach ($icons as $name => $data) {
166+
$data = (array) $data;
167+
if (array_is_list($data)) {
168+
$data = ['innerSvg' => $data[0], 'attributes' => $data[1] ?? []];
169+
}
170+
$registryIcons[$name] = new Icon(...$data);
171+
}
172+
173+
return new InMemoryIconRegistry($registryIcons);
174+
}
175+
}

src/Icons/tests/Unit/Registry/InMemoryIconRegistryTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313

1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\UX\Icons\Exception\IconNotFoundException;
16-
use Symfony\UX\Icons\Registry\InMemoryIconRegistry;
1716
use Symfony\UX\Icons\Svg\Icon;
17+
use Symfony\UX\Icons\Tests\Util\InMemoryIconRegistry;
1818

1919
/**
2020
* @author Simon André <[email protected]>

src/Icons/src/Registry/InMemoryIconRegistry.php renamed to src/Icons/tests/Util/InMemoryIconRegistry.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* file that was distributed with this source code.
1010
*/
1111

12-
namespace Symfony\UX\Icons\Registry;
12+
namespace Symfony\UX\Icons\Tests\Util;
1313

1414
use Symfony\UX\Icons\Exception\IconNotFoundException;
1515
use Symfony\UX\Icons\IconRegistryInterface;

0 commit comments

Comments
 (0)