Skip to content

Commit ef3c888

Browse files
committed
test: handle shadows in separate test case
1 parent 6ba65ba commit ef3c888

File tree

6 files changed

+167
-100
lines changed

6 files changed

+167
-100
lines changed

.phpunit.result.cache

Lines changed: 0 additions & 1 deletion
This file was deleted.

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
}
5454
},
5555
"scripts": {
56-
"test": "vendor/bin/phpunit",
56+
"test": "vendor/bin/phpunit --testdox",
5757
"test:filter": "vendor/bin/phpunit --filter",
5858
"lint": "vendor/bin/mago lint",
5959
"fix": "vendor/bin/mago lint --format-after-fix --fix",

source/components/Tests/UnusedTokensTest.php

Lines changed: 66 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,66 +6,99 @@
66

77
class UnusedTokensTest extends TestCase
88
{
9+
private const SHADOW_TOKEN = 'shadow';
10+
private const SHADOW_REQUIRED_TOKENS = ['shadow-amount', 'shadow-color'];
11+
private const TOKEN_EXCEPTIONS = self::SHADOW_REQUIRED_TOKENS;
12+
private const COMPONENT_EXCEPTIONS = ['anchormenu', 'listing', 'slider-item', 'textarea', 'Tests'];
13+
914
/**
10-
* @testdox component utlilize all tokens declared in component.json
15+
* @testdox component utilizes all tokens declared in component.json
1116
* @dataProvider componentFilesProvider
1217
*/
1318
public function testComponentUtilizeAllTokens(string $component, string $tokenFile, string $styleFile): void
1419
{
15-
$tokens = static::extractTokensFromTokenFile($tokenFile);
16-
$styleFileContents = file_get_contents($styleFile);
17-
$missingTokens = [];
18-
$tokenExceptions = [
19-
'shadow-color',
20-
'shadow-amount',
21-
];
22-
23-
// Check if tokens are used in the component style file
24-
foreach ($tokens as $token) {
25-
if (in_array($token, $tokenExceptions)) {
26-
continue;
27-
}
20+
$tokens = self::extractTokensFromTokenFile($tokenFile);
21+
$styleFileContents = (string) file_get_contents($styleFile);
2822

29-
// Match tokens.use/get(<anything>, '<token>'[, <optional args>])
30-
$pattern = '/tokens\.(use|get)\s*\([^,]+,\s*[\'\"]' . preg_quote($token, '/') . '[\'\"](?:\s*,[^)]*)?\s*\)/m';
31-
preg_match_all($pattern, $styleFileContents, $matches);
32-
$used = !empty($matches[0]);
33-
34-
if (!$used) {
35-
$missingTokens[] = $token;
36-
}
37-
}
23+
self::assertShadowDependenciesAreDeclared($tokens, $styleFileContents, $component);
24+
$unusedTokens = self::findUnusedTokens($tokens, $styleFileContents, self::TOKEN_EXCEPTIONS);
3825

3926
$this->assertEmpty(
40-
$missingTokens,
27+
$unusedTokens,
4128
sprintf(
4229
"Component '%s' has declared but unused tokens in %s:%s- %s",
4330
$component,
4431
$styleFile,
4532
PHP_EOL,
46-
implode(PHP_EOL . '- ', $missingTokens),
33+
implode(PHP_EOL . '- ', $unusedTokens),
34+
),
35+
);
36+
}
37+
38+
private static function assertShadowDependenciesAreDeclared(
39+
array $tokens,
40+
string $styleFileContents,
41+
string $component
42+
): void {
43+
if (!self::styleFileUsesToken($styleFileContents, self::SHADOW_TOKEN)) {
44+
return;
45+
}
46+
47+
$missingTokens = array_values(array_diff(self::SHADOW_REQUIRED_TOKENS, $tokens));
48+
49+
self::assertEmpty(
50+
$missingTokens,
51+
sprintf(
52+
"Component '%s' is missing required shadow tokens: %s",
53+
$component,
54+
implode(', ', $missingTokens),
4755
),
4856
);
4957
}
5058

59+
private static function findUnusedTokens(array $tokens, string $styleFileContents, array $excludedTokens): array
60+
{
61+
$unusedTokens = [];
62+
63+
foreach ($tokens as $token) {
64+
if (in_array($token, $excludedTokens, true)) {
65+
continue;
66+
}
67+
68+
if (!self::styleFileUsesToken($styleFileContents, $token)) {
69+
$unusedTokens[] = $token;
70+
}
71+
}
72+
73+
return $unusedTokens;
74+
}
75+
76+
private static function styleFileUsesToken(string $styleFileContents, string $token): bool
77+
{
78+
// Match tokens.use/get(<anything>, '<token>'[, <optional args>])
79+
$pattern = '/tokens\.(use|get)\s*\([^,]+,\s*[\'\"]' . preg_quote($token, '/') . '[\'\"](?:\s*,[^)]*)?\s*\)/m';
80+
81+
return preg_match($pattern, $styleFileContents) === 1;
82+
}
83+
5184
private static function extractTokensFromTokenFile(string $tokenFile): array
5285
{
53-
$content = file_get_contents($tokenFile);
86+
$content = (string) file_get_contents($tokenFile);
5487
$data = json_decode($content, true);
5588

89+
if (!is_array($data)) {
90+
return [];
91+
}
92+
5693
return $data['tokens'] ?? [];
5794
}
5895

5996
public static function componentFilesProvider(): \Generator
6097
{
6198
$componentsDir = __DIR__ . '/../';
62-
$exceptions = [
63-
'anchormenu',
64-
'notice',
65-
'Tests',
66-
];
67-
$components = array_filter(scandir($componentsDir), function ($item) use ($componentsDir, $exceptions) {
68-
return is_dir($componentsDir . $item) && !in_array($item, ['.', '..', ...$exceptions]);
99+
$components = array_filter(scandir($componentsDir), function ($item) use ($componentsDir) {
100+
return is_dir($componentsDir . $item)
101+
&& !in_array($item, ['.', '..', ...self::COMPONENT_EXCEPTIONS], true);
69102
});
70103

71104
foreach ($components as $component) {

source/components/notice/style.scss

Lines changed: 99 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -81,48 +81,118 @@ $_: "c-notice";
8181
text-decoration: underline;
8282
}
8383

84-
@include tokens.color-variants($_, ("success", "danger", "info", "warning"));
85-
}
84+
&--success {
85+
background-color: tokens.get($_, "color--success");
86+
color: tokens.get($_, "color--success-contrast");
87+
border-color: tokens.get($_, "color--success-border");
88+
89+
a,
90+
a:hover,
91+
a:active,
92+
a:visited {
93+
color: tokens.get($_, "color--success-contrast");
94+
text-decoration: underline;
95+
}
8696

87-
.#{$_}.#{$_}--stretch {
88-
@include stretch.stretch();
89-
}
97+
.c-button {
98+
color: tokens.get($_, "color--success-contrast");
99+
}
100+
}
90101

91-
.#{$_}.#{$_}--action-below {
92-
grid-template-areas:
93-
"icon title"
94-
"icon message"
95-
". actions";
96-
grid-template-columns: min-content 1fr;
102+
&--danger {
103+
background-color: tokens.get($_, "color--danger");
104+
color: tokens.get($_, "color--danger-contrast");
105+
border-color: tokens.get($_, "color--danger-border");
106+
107+
a,
108+
a:hover,
109+
a:active,
110+
a:visited {
111+
color: tokens.get($_, "color--danger-contrast");
112+
text-decoration: underline;
113+
}
97114

98-
.#{$_}__actions {
99-
margin-top: tokens.use($_, "space");
100-
justify-content: flex-start;
115+
.c-button {
116+
color: tokens.get($_, "color--danger-contrast");
117+
}
101118
}
102119

103-
&:not(:has(.#{$_}__title)) {
104-
grid-template-areas:
105-
"icon message"
106-
". actions";
120+
&--info {
121+
background-color: tokens.get($_, "color--info");
122+
color: tokens.get($_, "color--info-contrast");
123+
border-color: tokens.get($_, "color--info-border");
124+
125+
a,
126+
a:hover,
127+
a:active,
128+
a:visited {
129+
color: tokens.get($_, "color--info-contrast");
130+
text-decoration: underline;
131+
}
132+
133+
.c-button {
134+
color: tokens.get($_, "color--info-contrast");
135+
}
107136
}
108137

109-
&:not(:has(.#{$_}__message)) {
138+
&--warning {
139+
background-color: tokens.get($_, "color--warning");
140+
color: tokens.get($_, "color--warning-contrast");
141+
border-color: tokens.get($_, "color--warning-border");
142+
143+
a,
144+
a:hover,
145+
a:active,
146+
a:visited {
147+
color: tokens.get($_, "color--warning-contrast");
148+
text-decoration: underline;
149+
}
150+
151+
.c-button {
152+
color: tokens.get($_, "color--warning-contrast");
153+
}
154+
}
155+
156+
.#{$_}.#{$_}--stretch {
157+
@include stretch.stretch();
158+
}
159+
160+
.#{$_}.#{$_}--action-below {
110161
grid-template-areas:
111162
"icon title"
163+
"icon message"
112164
". actions";
165+
grid-template-columns: min-content 1fr;
166+
167+
.#{$_}__actions {
168+
margin-top: tokens.use($_, "space");
169+
justify-content: flex-start;
170+
}
171+
172+
&:not(:has(.#{$_}__title)) {
173+
grid-template-areas:
174+
"icon message"
175+
". actions";
176+
}
177+
178+
&:not(:has(.#{$_}__message)) {
179+
grid-template-areas:
180+
"icon title"
181+
". actions";
182+
}
113183
}
114-
}
115184

116-
.#{$_}+.#{$_} {
117-
margin-top: tokens.use($_, "outer-space", 2);
118-
}
185+
.#{$_}+.#{$_} {
186+
margin-top: tokens.use($_, "outer-space", 2);
187+
}
119188

120-
@media print {
121-
.#{$_} {
122-
display: none;
189+
@media print {
190+
.#{$_} {
191+
display: none;
192+
}
123193
}
124-
}
125194

126-
.c-notice {
127-
animation: puff-in-center 0.2s cubic-bezier(0.470, 0.000, 0.745, 0.715) both;
195+
.c-notice {
196+
animation: puff-in-center 0.2s cubic-bezier(0.470, 0.000, 0.745, 0.715) both;
197+
}
128198
}

source/components/person/component.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"apiVersion": 1,
44
"name": "Person",
55
"slug": "person",
6-
"tokens": [],
6+
"tokens": ["shadow-amount", "shadow-color"],
77
"description": "The Person component provides a reusable pattern for displaying person information in the interface.",
88
"tags": [],
99
"similarComponents": ["signature"],

source/sass/mixin/_tokens.scss

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -105,39 +105,4 @@
105105
}
106106

107107
@return var(#{$p}--#{$token});
108-
}
109-
110-
/// Generates a color variant (background + contrast + border-color propagation).
111-
@mixin color-variant($prefix, $variant) {
112-
$p: _clean-prefix($prefix);
113-
114-
@if($p !="") {
115-
$p: "--#{$p}";
116-
}
117-
118-
background-color: var(#{$p}--color--#{$variant});
119-
color: var(#{$p}--color--#{$variant}-contrast);
120-
border-color: var(#{$p}--color--#{$variant}-border, var(--color--#{$variant}-border));
121-
122-
a,
123-
a:hover,
124-
a:active,
125-
a:visited {
126-
color: var(#{$p}--color--#{$variant}-contrast);
127-
text-decoration: underline;
128-
}
129-
130-
.c-button {
131-
color: var(#{$p}--color--#{$variant}-contrast);
132-
}
133-
}
134-
135-
/// Generates multiple color variant modifiers using BEM &--{variant} syntax.
136-
@mixin color-variants($prefix, $variants) {
137-
138-
@each $variant in $variants {
139-
&--#{$variant} {
140-
@include color-variant($prefix, $variant);
141-
}
142-
}
143108
}

0 commit comments

Comments
 (0)