Skip to content

Commit 9722108

Browse files
committed
Add tests for key merging
1 parent aef2551 commit 9722108

File tree

2 files changed

+178
-15
lines changed

2 files changed

+178
-15
lines changed

extra/html-extra/HtmlExtension.php

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
use Twig\Environment;
1616
use Twig\Error\RuntimeError;
1717
use Twig\Extension\AbstractExtension;
18-
use Twig\Extension\CoreExtension;
19-
use Twig\Extension\EscaperExtension;
2018
use Twig\Runtime\EscaperRuntime;
2119
use Twig\TwigFilter;
2220
use Twig\TwigFunction;
@@ -144,21 +142,32 @@ public static function htmlAttrMerge(...$arrays): array
144142
throw new RuntimeError(sprintf('The "attr_merge" filter only works with arrays or "Traversable", got "%s" for argument %d.', \gettype($array), $argNumber + 1));
145143
}
146144

147-
$array = CoreExtension::toArray($array);
145+
$array = (array) ($array);
148146

149-
foreach (['class', 'style', 'data', 'aria'] as $deepMergeKey) {
150-
if (isset($array[$deepMergeKey])) {
151-
$value = $array[$deepMergeKey];
152-
unset($array[$deepMergeKey]);
147+
foreach (['data', 'aria'] as $flatOutKey) {
148+
if (!isset($array[$flatOutKey])) {
149+
continue;
150+
}
151+
$values = (array) $array[$flatOutKey];
152+
foreach ($values as $key => $value) {
153+
$result[$flatOutKey.'-'.$key] = $value;
154+
}
155+
unset($array[$flatOutKey]);
156+
}
153157

154-
if (!is_iterable($value)) {
155-
$value = (array) $value;
156-
}
158+
foreach (['class', 'style'] as $deepMergeKey) {
159+
if (!isset($array[$deepMergeKey])) {
160+
continue;
161+
}
157162

158-
$value = CoreExtension::toArray($value);
163+
$value = $array[$deepMergeKey];
164+
unset($array[$deepMergeKey]);
159165

160-
$result[$deepMergeKey] = array_merge($result[$deepMergeKey] ?? [], $value);
166+
if (!is_iterable($value)) {
167+
$value = (array) $value;
161168
}
169+
170+
$result[$deepMergeKey] = array_merge($result[$deepMergeKey] ?? [], $value);
162171
}
163172

164173
$result = array_merge($result, $array);

extra/html-extra/Tests/HtmlAttrMergeTest.php

Lines changed: 157 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,165 @@ public function testMerge(array $expected, array $inputs): void
1919

2020
public function htmlAttrProvider(): \Generator
2121
{
22-
yield 'simple test' => [
23-
['id' => 'some-id', 'class' => ['some-class']],
22+
yield 'merging different attributes from two arrays' => [
23+
['id' => 'some-id', 'label' => 'some-label'],
2424
[
2525
['id' => 'some-id'],
26-
['class' => 'some-class'],
26+
['label' => 'some-label'],
27+
]
28+
];
29+
30+
yield 'merging different attributes from three arrays' => [
31+
['id' => 'some-id', 'label' => 'some-label', 'role' => 'main'],
32+
[
33+
['id' => 'some-id'],
34+
['label' => 'some-label'],
35+
['role' => 'main'],
36+
]
37+
];
38+
39+
yield 'merging different attributes from Traversables' => [
40+
['id' => 'some-id', 'label' => 'some-label', 'role' => 'main'],
41+
[
42+
new \ArrayIterator(['id' => 'some-id']),
43+
new \ArrayIterator(['label' => 'some-label']),
44+
new \ArrayIterator(['role' => 'main']),
45+
]
46+
];
47+
48+
yield 'later keys override previous ones' => [
49+
['id' => 'other'],
50+
[
51+
['id' => 'this'],
52+
['id' => 'that'],
53+
['id' => 'other'],
54+
]
55+
];
56+
57+
yield 'ignore empty strings or arrays passed as arguments' => [
58+
['some' => 'attribute'],
59+
[
60+
['some' => 'attribute'],
61+
[], // empty array
62+
'', // empty string
63+
]
64+
];
65+
66+
yield 'keep "true" and "false" boolean values' => [
67+
['disabled' => true, 'enabled' => false],
68+
[
69+
['disabled' => true],
70+
['enabled' => false],
71+
]
72+
];
73+
74+
yield 'consolidate values for the "class" key' => [
75+
['class' => ['foo', 'bar', 'baz']],
76+
[
77+
['class' => ['foo']],
78+
['class' => 'bar'], // string, not array
79+
['class' => ['baz']],
80+
]
81+
];
82+
83+
yield 'class values can be overridden when they use names (array keys)' => [
84+
['class' => ['foo', 'bar', 'importance' => 'high']],
85+
[
86+
['class' => 'foo'],
87+
['class' => ['bar', 'importance' => 'low']],
88+
['class' => ['importance' => 'high']],
89+
]
90+
];
91+
92+
yield 'inline style values with numerical keys are merely collected' => [
93+
['style' => ['font-weight: light', 'color: green', 'font-weight: bold']],
94+
[
95+
['style' => ['font-weight: light']],
96+
['style' => ['color: green', 'font-weight: bold']],
97+
]
98+
];
99+
100+
yield 'inline style values can be overridden when they use names (array keys)' => [
101+
['style' => ['font-weight' => 'bold', 'color' => 'red']],
102+
[
103+
['style' => ['font-weight' => 'light']],
104+
['style' => ['color' => 'green', 'font-weight' => 'bold']],
105+
['style' => ['color' => 'red']],
106+
]
107+
];
108+
109+
yield 'no merging happens when mixing numerically indexed inline styles with named ones' => [
110+
['style' => ['color: green', 'color' => 'red']],
111+
[
112+
['style' => ['color: green']],
113+
['style' => ['color' => 'red']],
114+
]
115+
];
116+
117+
yield 'turning aria attributes from array to flat keys' => [
118+
['aria-role' => 'banner'],
119+
[
120+
['aria' => ['role' => 'main']],
121+
['aria' => ['role' => 'banner']],
122+
]
123+
];
124+
125+
yield 'using aria attributes from a sub-array' => [
126+
['aria-role' => 'main', 'aria-label' => 'none'],
127+
[
128+
['aria' => ['role' => 'main', 'label' => 'none']],
129+
]
130+
];
131+
132+
yield 'merging aria attributes, where the array values overrides the flat one' => [
133+
['aria-role' => 'navigation'],
134+
[
135+
['aria-role' => 'main'],
136+
['aria' => ['role' => 'banner']],
137+
['aria' => ['role' => 'navigation']],
138+
]
139+
];
140+
141+
yield 'merging aria attributes, where the flat ones overrides the array' => [
142+
['aria-role' => 'navigation'],
143+
[
144+
['aria' => ['role' => 'main']],
145+
['aria-role' => 'banner'],
146+
['aria-role' => 'navigation'],
147+
]
148+
];
149+
150+
yield 'using data attributes in a sub-array' => [
151+
['data-foo' => 'this', 'data-bar' => 'that'],
152+
[
153+
['data' => ['foo' => 'this']],
154+
['data' => ['bar' => 'that']],
155+
]
156+
];
157+
158+
yield 'turning data attributes from array to flat keys' => [
159+
['data-test' => 'bar'],
160+
[
161+
['data' => ['test' => 'foo']],
162+
['data' => ['test' => 'bar']],
163+
]
164+
];
165+
166+
yield 'merging data attributes, where the array values overrides the flat one' => [
167+
['data-test' => 'baz'],
168+
[
169+
['data-test' => 'foo'],
170+
['data' => ['test' => 'bar']],
171+
['data' => ['test' => 'baz']],
172+
]
173+
];
174+
175+
yield 'merging data attributes, where the flat ones overrides the array' => [
176+
['data-test' => 'baz'],
177+
[
178+
['data' => ['test' => 'foo']],
179+
['data-test' => 'bar'],
180+
['data-test' => 'baz'],
27181
]
28182
];
29183
}

0 commit comments

Comments
 (0)