|
1 | | -/* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports */ |
2 | | -import { colors as importableColors } from './colors'; |
3 | | - |
4 | | -const designTokens = require('../../../figma/tokens.json'); |
5 | | - |
6 | | -describe('Dark Theme Colors', () => { |
7 | | - it('js tokens for background.default matches figma tokens background.default', () => { |
8 | | - expect(importableColors.background.default).toStrictEqual( |
9 | | - designTokens.dark.colors.background.default.value, |
10 | | - ); |
11 | | - }); |
12 | | - |
13 | | - it('js tokens for background.defaultHover matches figma tokens background.defaultHover', () => { |
14 | | - expect(importableColors.background.defaultHover).toStrictEqual( |
15 | | - designTokens.dark.colors.background['default-hover'].value, |
16 | | - ); |
17 | | - }); |
18 | | - |
19 | | - it('js tokens for background.defaultPressed matches figma tokens background.defaultPressed', () => { |
20 | | - expect(importableColors.background.defaultPressed).toStrictEqual( |
21 | | - designTokens.dark.colors.background['default-pressed'].value, |
22 | | - ); |
23 | | - }); |
24 | | - |
25 | | - it('js tokens for background.alternative matches figma tokens background.alternative', () => { |
26 | | - expect(importableColors.background.alternative).toStrictEqual( |
27 | | - designTokens.dark.colors.background.alternative.value, |
28 | | - ); |
29 | | - }); |
30 | | - |
31 | | - it('js tokens for background.alternativeHover matches figma tokens background.alternativeHover', () => { |
32 | | - expect(importableColors.background.alternativeHover).toStrictEqual( |
33 | | - designTokens.dark.colors.background['alternative-hover'].value, |
34 | | - ); |
35 | | - }); |
36 | | - |
37 | | - it('js tokens for background.alternativePressed matches figma tokens background.alternativePressed', () => { |
38 | | - expect(importableColors.background.alternativePressed).toStrictEqual( |
39 | | - designTokens.dark.colors.background['alternative-pressed'].value, |
40 | | - ); |
41 | | - }); |
42 | | - |
43 | | - it('js tokens for background.hover matches figma tokens background.hover', () => { |
44 | | - expect(importableColors.background.hover).toStrictEqual( |
45 | | - designTokens.dark.colors.background.hover.value, |
46 | | - ); |
47 | | - }); |
48 | | - |
49 | | - it('js tokens for background.pressed matches figma tokens background.pressed', () => { |
50 | | - expect(importableColors.background.pressed).toStrictEqual( |
51 | | - designTokens.dark.colors.background.pressed.value, |
52 | | - ); |
53 | | - }); |
54 | | - |
55 | | - it('js tokens for text.default matches figma tokens text.default', () => { |
56 | | - expect(importableColors.text.default).toStrictEqual( |
57 | | - designTokens.dark.colors.text.default.value, |
58 | | - ); |
59 | | - }); |
60 | | - |
61 | | - it('js tokens for text.alternative matches figma tokens text.alternative', () => { |
62 | | - expect(importableColors.text.alternative).toStrictEqual( |
63 | | - designTokens.dark.colors.text.alternative.value, |
64 | | - ); |
65 | | - }); |
66 | | - |
67 | | - it('js tokens for text.muted matches figma tokens text.muted', () => { |
68 | | - expect(importableColors.text.muted).toStrictEqual( |
69 | | - designTokens.dark.colors.text.muted.value, |
70 | | - ); |
71 | | - }); |
72 | | - |
73 | | - it('js tokens for icon.default matches figma tokens icon.default', () => { |
74 | | - expect(importableColors.icon.default).toStrictEqual( |
75 | | - designTokens.dark.colors.icon.default.value, |
76 | | - ); |
77 | | - }); |
78 | | - |
79 | | - it('js tokens for icon.alternative matches figma tokens icon.alternative', () => { |
80 | | - expect(importableColors.icon.alternative).toStrictEqual( |
81 | | - designTokens.dark.colors.icon.alternative.value, |
82 | | - ); |
83 | | - }); |
84 | | - |
85 | | - it('js tokens for icon.muted matches figma tokens icon.muted', () => { |
86 | | - expect(importableColors.icon.muted).toStrictEqual( |
87 | | - designTokens.dark.colors.icon.muted.value, |
88 | | - ); |
89 | | - }); |
90 | | - |
91 | | - it('js tokens for border.default matches figma tokens border.default', () => { |
92 | | - expect(importableColors.border.default).toStrictEqual( |
93 | | - designTokens.dark.colors.border.default.value, |
94 | | - ); |
95 | | - }); |
96 | | - |
97 | | - it('js tokens for border.muted matches figma tokens border.muted', () => { |
98 | | - expect(importableColors.border.muted).toStrictEqual( |
99 | | - designTokens.dark.colors.border.muted.value, |
100 | | - ); |
101 | | - }); |
102 | | - |
103 | | - it('js tokens for overlay.default matches figma tokens overlay.default', () => { |
104 | | - expect(importableColors.overlay.default).toStrictEqual( |
105 | | - designTokens.dark.colors.overlay.default.value, |
106 | | - ); |
107 | | - }); |
108 | | - |
109 | | - it('js tokens for overlay.alternative matches figma tokens overlay.alternative', () => { |
110 | | - expect(importableColors.overlay.alternative).toStrictEqual( |
111 | | - designTokens.dark.colors.overlay.alternative.value, |
112 | | - ); |
113 | | - }); |
114 | | - |
115 | | - it('js tokens for primary.default matches figma tokens primary.default', () => { |
116 | | - expect(importableColors.primary.default).toStrictEqual( |
117 | | - designTokens.dark.colors.primary.default.value, |
118 | | - ); |
119 | | - }); |
120 | | - |
121 | | - it('js tokens for primary.default-hover matches figma tokens primary.default-hover in dark mode', () => { |
122 | | - expect(importableColors.primary.defaultHover).toStrictEqual( |
123 | | - designTokens.dark.colors.primary['default-hover'].value, |
124 | | - ); |
125 | | - }); |
126 | | - |
127 | | - it('js tokens for primary.default-pressed matches figma tokens primary.default-pressed in dark mode', () => { |
128 | | - expect(importableColors.primary.defaultPressed).toStrictEqual( |
129 | | - designTokens.dark.colors.primary['default-pressed'].value, |
130 | | - ); |
131 | | - }); |
132 | | - |
133 | | - it('js tokens for primary.alternative matches figma tokens primary.alternative', () => { |
134 | | - expect(importableColors.primary.alternative).toStrictEqual( |
135 | | - designTokens.dark.colors.primary.alternative.value, |
136 | | - ); |
137 | | - }); |
138 | | - |
139 | | - it('js tokens for primary.muted matches figma tokens primary.muted', () => { |
140 | | - expect(importableColors.primary.muted).toStrictEqual( |
141 | | - designTokens.dark.colors.primary.muted.value, |
142 | | - ); |
143 | | - }); |
144 | | - |
145 | | - it('js tokens for primary.inverse matches figma tokens primary.inverse', () => { |
146 | | - expect(importableColors.primary.inverse).toStrictEqual( |
147 | | - designTokens.dark.colors.primary.inverse.value, |
148 | | - ); |
149 | | - }); |
150 | | - |
151 | | - it('js tokens for error.default matches figma tokens error.default', () => { |
152 | | - expect(importableColors.error.default).toStrictEqual( |
153 | | - designTokens.dark.colors.error.default.value, |
154 | | - ); |
155 | | - }); |
156 | | - |
157 | | - it('js tokens for error.default-hover matches figma tokens error.default-hover in dark mode', () => { |
158 | | - expect(importableColors.error.defaultHover).toStrictEqual( |
159 | | - designTokens.dark.colors.error['default-hover'].value, |
160 | | - ); |
161 | | - }); |
162 | | - |
163 | | - it('js tokens for error.default-pressed matches figma tokens error.default-pressed in dark mode', () => { |
164 | | - expect(importableColors.error.defaultPressed).toStrictEqual( |
165 | | - designTokens.dark.colors.error['default-pressed'].value, |
166 | | - ); |
167 | | - }); |
168 | | - |
169 | | - it('js tokens for error.alternative matches figma tokens error.alternative', () => { |
170 | | - expect(importableColors.error.alternative).toStrictEqual( |
171 | | - designTokens.dark.colors.error.alternative.value, |
172 | | - ); |
173 | | - }); |
174 | | - |
175 | | - it('js tokens for error.muted matches figma tokens error.muted', () => { |
176 | | - expect(importableColors.error.muted).toStrictEqual( |
177 | | - designTokens.dark.colors.error.muted.value, |
178 | | - ); |
179 | | - }); |
180 | | - |
181 | | - it('js tokens for error.inverse matches figma tokens error.inverse', () => { |
182 | | - expect(importableColors.error.inverse).toStrictEqual( |
183 | | - designTokens.dark.colors.error.inverse.value, |
184 | | - ); |
185 | | - }); |
186 | | - |
187 | | - it('js tokens for warning.default matches figma tokens warning.default', () => { |
188 | | - expect(importableColors.warning.default).toStrictEqual( |
189 | | - designTokens.dark.colors.warning.default.value, |
190 | | - ); |
191 | | - }); |
192 | | - |
193 | | - it('js tokens for warning.default-hover matches figma tokens warning.default-hover in dark mode', () => { |
194 | | - expect(importableColors.warning.defaultHover).toStrictEqual( |
195 | | - designTokens.dark.colors.warning['default-hover'].value, |
196 | | - ); |
197 | | - }); |
198 | | - |
199 | | - it('js tokens for warning.default-pressed matches figma tokens warning.default-pressed in dark mode', () => { |
200 | | - expect(importableColors.warning.defaultPressed).toStrictEqual( |
201 | | - designTokens.dark.colors.warning['default-pressed'].value, |
202 | | - ); |
203 | | - }); |
204 | | - |
205 | | - it('js tokens for warning.muted matches figma tokens warning.muted', () => { |
206 | | - expect(importableColors.warning.muted).toStrictEqual( |
207 | | - designTokens.dark.colors.warning.muted.value, |
208 | | - ); |
209 | | - }); |
210 | | - |
211 | | - it('js tokens for warning.inverse matches figma tokens warning.inverse', () => { |
212 | | - expect(importableColors.warning.inverse).toStrictEqual( |
213 | | - designTokens.dark.colors.warning.inverse.value, |
214 | | - ); |
215 | | - }); |
216 | | - |
217 | | - it('js tokens for success.default matches figma tokens success.default', () => { |
218 | | - expect(importableColors.success.default).toStrictEqual( |
219 | | - designTokens.dark.colors.success.default.value, |
220 | | - ); |
221 | | - }); |
222 | | - |
223 | | - it('js tokens for success.default-hover matches figma tokens success.default-hover in dark mode', () => { |
224 | | - expect(importableColors.success.defaultHover).toStrictEqual( |
225 | | - designTokens.dark.colors.success['default-hover'].value, |
226 | | - ); |
227 | | - }); |
228 | | - |
229 | | - it('js tokens for success.default-pressed matches figma tokens success.default-pressed in dark mode', () => { |
230 | | - expect(importableColors.success.defaultPressed).toStrictEqual( |
231 | | - designTokens.dark.colors.success['default-pressed'].value, |
232 | | - ); |
233 | | - }); |
234 | | - |
235 | | - it('js tokens for success.muted matches figma tokens success.muted', () => { |
236 | | - expect(importableColors.success.muted).toStrictEqual( |
237 | | - designTokens.dark.colors.success.muted.value, |
238 | | - ); |
239 | | - }); |
240 | | - |
241 | | - it('js tokens for success.inverse matches figma tokens success.inverse', () => { |
242 | | - expect(importableColors.success.inverse).toStrictEqual( |
243 | | - designTokens.dark.colors.success.inverse.value, |
244 | | - ); |
245 | | - }); |
246 | | - |
247 | | - it('js tokens for info.default matches figma tokens info.default', () => { |
248 | | - expect(importableColors.info.default).toStrictEqual( |
249 | | - designTokens.dark.colors.info.default.value, |
250 | | - ); |
251 | | - }); |
252 | | - |
253 | | - it('js tokens for info.muted matches figma tokens info.muted', () => { |
254 | | - expect(importableColors.info.muted).toStrictEqual( |
255 | | - designTokens.dark.colors.info.muted.value, |
256 | | - ); |
257 | | - }); |
258 | | - |
259 | | - it('js tokens for info.inverse matches figma tokens info.inverse', () => { |
260 | | - expect(importableColors.info.inverse).toStrictEqual( |
261 | | - designTokens.dark.colors.info.inverse.value, |
262 | | - ); |
263 | | - }); |
264 | | - |
265 | | - it('js tokens for flask.default matches figma tokens flask.default', () => { |
266 | | - expect(importableColors.flask.default).toStrictEqual( |
267 | | - designTokens.dark.colors.flask.default.value, |
268 | | - ); |
269 | | - }); |
270 | | - |
271 | | - it('js tokens for flask.inverse matches figma tokens flask.inverse', () => { |
272 | | - expect(importableColors.flask.inverse).toStrictEqual( |
273 | | - designTokens.dark.colors.flask.inverse.value, |
274 | | - ); |
275 | | - }); |
276 | | - |
277 | | - it('js tokens for shadow.default matches figma tokens dark.shadows.xs.value.color', () => { |
278 | | - expect(importableColors.shadow.default).toStrictEqual( |
279 | | - designTokens.dark.shadows.xs.value.color, |
280 | | - ); |
281 | | - |
282 | | - expect(importableColors.shadow.default).toStrictEqual( |
283 | | - designTokens.dark.shadows.sm.value.color, |
284 | | - ); |
285 | | - |
286 | | - expect(importableColors.shadow.default).toStrictEqual( |
287 | | - designTokens.dark.shadows.md.value.color, |
288 | | - ); |
289 | | - |
290 | | - expect(importableColors.shadow.default).toStrictEqual( |
291 | | - designTokens.dark.shadows.lg.value.color, |
292 | | - ); |
293 | | - }); |
294 | | - |
295 | | - it('js tokens for shadow.primary matches figma tokens shadows.primary', () => { |
296 | | - expect(importableColors.shadow.primary).toStrictEqual( |
297 | | - designTokens.dark.shadows.primary.value.color, |
298 | | - ); |
299 | | - }); |
300 | | - |
301 | | - it('js tokens for shadow.error matches figma tokens shadows.error', () => { |
302 | | - expect(importableColors.shadow.error).toStrictEqual( |
303 | | - designTokens.dark.shadows.error.value.color, |
304 | | - ); |
| 1 | +import * as brandColors from '../../../figma/brandColors.json'; |
| 2 | +import * as darkTheme from '../../../figma/darkTheme.json'; |
| 3 | +import { colors as definedColors } from './colors'; |
| 4 | + |
| 5 | +type ColorDetails = { |
| 6 | + value: string; |
| 7 | + type: string; |
| 8 | + parent: string; |
| 9 | + description: string; |
| 10 | +}; |
| 11 | + |
| 12 | +/** |
| 13 | + * Recursively resolve color references in a theme object. |
| 14 | + * @param theme - Object containing theme definitions. |
| 15 | + * @param colors - Object containing color definitions. |
| 16 | + * @param rootTheme - Root theme object. |
| 17 | + */ |
| 18 | +function resolveColorReferences( |
| 19 | + theme: any, |
| 20 | + colors: any, |
| 21 | + rootTheme?: any, |
| 22 | +): void { |
| 23 | + Object.keys(theme).forEach((key) => { |
| 24 | + if (typeof theme[key] === 'object' && theme[key] !== null) { |
| 25 | + resolveColorReferences(theme[key], colors, rootTheme || theme); |
| 26 | + } else if (typeof theme[key] === 'string' && theme[key].startsWith('{')) { |
| 27 | + const match = theme[key].match(/\{(.+?)\}/u); |
| 28 | + if (match) { |
| 29 | + const [colorFamily, shade] = match[1].split('.'); |
| 30 | + if (colors[colorFamily]?.[shade]) { |
| 31 | + theme[key] = colors[colorFamily][shade].value; |
| 32 | + } else if (rootTheme?.[colorFamily]?.[shade]?.value) { |
| 33 | + theme[key] = rootTheme[colorFamily][shade].value; |
| 34 | + } |
| 35 | + } |
| 36 | + } |
| 37 | + }); |
| 38 | +} |
| 39 | + |
| 40 | +describe('Theme Color Resolution', () => { |
| 41 | + const clonedTheme = JSON.parse(JSON.stringify(darkTheme)) as { |
| 42 | + [key: string]: { [key: string]: ColorDetails }; |
| 43 | + }; |
| 44 | + resolveColorReferences(clonedTheme, brandColors, clonedTheme); |
| 45 | + |
| 46 | + Object.entries(clonedTheme).forEach(([category, details]) => { |
| 47 | + if (category !== 'default') { |
| 48 | + // Skip 'default' category if it's not part of definedColors |
| 49 | + Object.entries(details).forEach(([key, detail]) => { |
| 50 | + const cleanKey = key |
| 51 | + .replace(/\*/gu, '') |
| 52 | + .replace(/-([a-z])/gu, (_, p1) => p1.toUpperCase()) |
| 53 | + .replace(/\s*\(strong\)\s*/gu, ''); |
| 54 | + it(`ensures ${category}.${cleanKey} matches defined color`, () => { |
| 55 | + expect((definedColors as any)[category][cleanKey]).toStrictEqual( |
| 56 | + detail.value, |
| 57 | + ); |
| 58 | + }); |
| 59 | + }); |
| 60 | + } |
305 | 61 | }); |
306 | 62 | }); |
0 commit comments