Skip to content

Commit 78323d2

Browse files
retlehsclaude
andauthored
✅ Expand build integration test coverage (#35)
- Dedupe precedence: base values win for fonts, font sizes, and radius (not just colors) - Disable flags preserve all base values including colliding slugs - Label customization: shadeLabels, fontLabels, fontSizeLabels, borderRadiusLabels Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent b2f448f commit 78323d2

2 files changed

Lines changed: 334 additions & 9 deletions

File tree

tests/build.test.ts

Lines changed: 268 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ import path from 'path';
99
const fixtureDir = path.resolve(__dirname, 'fixture');
1010
const outDir = path.join(fixtureDir, 'dist');
1111

12-
async function runBuild(pluginOptions = {}) {
12+
async function runBuild(pluginOptions = {}, baseThemeJson = 'theme.json') {
1313
await build({
1414
plugins: [
1515
tailwindcss(),
1616
wordpressThemeJson({
17-
baseThemeJsonPath: path.join(fixtureDir, 'theme.json'),
17+
baseThemeJsonPath: path.join(fixtureDir, baseThemeJson),
1818
outputPath: 'theme.json',
1919
...pluginOptions,
2020
}),
@@ -39,14 +39,15 @@ describe('vite build integration', () => {
3939
});
4040

4141
describe('colors', () => {
42-
it('should extract all 11 shades for each color', async () => {
42+
it('should extract all 11 shades for each color family', async () => {
4343
const themeJson = await runBuild();
4444
const palette = themeJson.settings.color.palette;
4545

46+
const expectedShades = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
47+
4648
const redColors = palette.filter((c: any) => c.slug.startsWith('red-'));
4749
expect(redColors).toHaveLength(11);
4850

49-
const expectedShades = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
5051
for (const shade of expectedShades) {
5152
expect(palette).toContainEqual(
5253
expect.objectContaining({
@@ -74,47 +75,305 @@ describe('vite build integration', () => {
7475
}
7576
});
7677

78+
it('should use oklch color format', async () => {
79+
const themeJson = await runBuild();
80+
const palette = themeJson.settings.color.palette;
81+
const colorsWithShades = palette.filter((c: any) => c.slug.includes('-'));
82+
83+
for (const color of colorsWithShades) {
84+
expect(color.color).toMatch(/^oklch\(/);
85+
}
86+
});
87+
7788
it('should not include colors when disabled', async () => {
7889
const themeJson = await runBuild({ disableTailwindColors: true });
7990
expect(themeJson.settings.color.palette).toBeUndefined();
8091
});
8192
});
8293

8394
describe('fonts', () => {
84-
it('should extract font families', async () => {
95+
it('should extract all default font families', async () => {
8596
const themeJson = await runBuild();
8697
const fonts = themeJson.settings.typography.fontFamilies;
8798

99+
expect(fonts).toHaveLength(3);
88100
expect(fonts).toContainEqual(
89101
expect.objectContaining({ slug: 'sans' })
90102
);
103+
expect(fonts).toContainEqual(
104+
expect.objectContaining({ slug: 'serif' })
105+
);
91106
expect(fonts).toContainEqual(
92107
expect.objectContaining({ slug: 'mono' })
93108
);
94109
});
110+
111+
it('should include full fontFamily values', async () => {
112+
const themeJson = await runBuild();
113+
const fonts = themeJson.settings.typography.fontFamilies;
114+
const sans = fonts.find((f: any) => f.slug === 'sans');
115+
116+
expect(sans.fontFamily).toContain('sans-serif');
117+
});
118+
119+
it('should not include fonts when disabled', async () => {
120+
const themeJson = await runBuild({ disableTailwindFonts: true });
121+
expect(themeJson.settings.typography.fontFamilies).toBeUndefined();
122+
});
95123
});
96124

97125
describe('font sizes', () => {
98-
it('should extract all font sizes', async () => {
126+
it('should extract all 13 font sizes', async () => {
99127
const themeJson = await runBuild();
100128
const sizes = themeJson.settings.typography.fontSizes;
101129

130+
expect(sizes).toHaveLength(13);
131+
102132
const expectedSizes = ['xs', 'sm', 'base', 'lg', 'xl', '2xl', '3xl', '4xl', '5xl', '6xl', '7xl', '8xl', '9xl'];
103133
for (const size of expectedSizes) {
104134
expect(sizes).toContainEqual(
105135
expect.objectContaining({ slug: size })
106136
);
107137
}
108138
});
139+
140+
it('should sort font sizes from smallest to largest', async () => {
141+
const themeJson = await runBuild();
142+
const sizes = themeJson.settings.typography.fontSizes;
143+
const remValues = sizes.map((s: any) => parseFloat(s.size));
144+
145+
for (let i = 1; i < remValues.length; i++) {
146+
expect(remValues[i]).toBeGreaterThanOrEqual(remValues[i - 1]);
147+
}
148+
});
149+
150+
it('should not include font sizes when disabled', async () => {
151+
const themeJson = await runBuild({ disableTailwindFontSizes: true });
152+
expect(themeJson.settings.typography.fontSizes).toBeUndefined();
153+
});
109154
});
110155

111156
describe('border radius', () => {
112-
it('should extract border radius sizes', async () => {
157+
it('should extract all 8 border radius sizes', async () => {
113158
const themeJson = await runBuild({ disableTailwindBorderRadius: false });
114159
const radiusSizes = themeJson.settings.border?.radiusSizes;
115160

116-
expect(radiusSizes).toBeDefined();
117-
expect(radiusSizes!.length).toBeGreaterThan(0);
161+
expect(radiusSizes).toHaveLength(8);
162+
163+
const expectedSlugs = ['xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl', '4xl'];
164+
for (const slug of expectedSlugs) {
165+
expect(radiusSizes).toContainEqual(
166+
expect.objectContaining({ slug })
167+
);
168+
}
169+
});
170+
171+
it('should sort border radius sizes from smallest to largest', async () => {
172+
const themeJson = await runBuild({ disableTailwindBorderRadius: false });
173+
const radiusSizes = themeJson.settings.border?.radiusSizes;
174+
const remValues = radiusSizes!.map((s: any) => parseFloat(s.size));
175+
176+
for (let i = 1; i < remValues.length; i++) {
177+
expect(remValues[i]).toBeGreaterThanOrEqual(remValues[i - 1]);
178+
}
179+
});
180+
181+
it('should not include border radius when disabled', async () => {
182+
const themeJson = await runBuild({ disableTailwindBorderRadius: true });
183+
expect(themeJson.settings.border?.radiusSizes).toBeUndefined();
184+
});
185+
});
186+
187+
describe('base theme.json', () => {
188+
it('should preserve settings from base theme.json', async () => {
189+
const themeJson = await runBuild();
190+
191+
expect(themeJson.settings.color.custom).toBe(false);
192+
expect(themeJson.settings.color.defaultPalette).toBe(false);
193+
expect(themeJson.settings.typography.defaultFontSizes).toBe(false);
194+
expect(themeJson.settings.typography.customFontSize).toBe(false);
195+
});
196+
197+
it('should include the __processed__ marker', async () => {
198+
const themeJson = await runBuild();
199+
expect(themeJson.__processed__).toBe('This file was generated using Vite');
200+
});
201+
202+
it('should remove __preprocessed__ marker from base', async () => {
203+
const themeJson = await runBuild({}, 'theme-with-base.json');
204+
expect(themeJson.__preprocessed__).toBeUndefined();
205+
expect(themeJson.__processed__).toBe('This file was generated using Vite');
206+
});
207+
});
208+
209+
describe('base theme.json with existing values', () => {
210+
it('should preserve base palette when colors are disabled', async () => {
211+
const themeJson = await runBuild(
212+
{ disableTailwindColors: true },
213+
'theme-with-base.json'
214+
);
215+
const palette = themeJson.settings.color.palette;
216+
217+
expect(palette).toHaveLength(2);
218+
expect(palette).toContainEqual(
219+
expect.objectContaining({ slug: 'brand', color: '#ff6600' })
220+
);
221+
});
222+
223+
it('should preserve base fontFamilies when fonts are disabled', async () => {
224+
const themeJson = await runBuild(
225+
{ disableTailwindFonts: true },
226+
'theme-with-base.json'
227+
);
228+
const fonts = themeJson.settings.typography.fontFamilies;
229+
230+
expect(fonts).toHaveLength(2);
231+
expect(fonts).toContainEqual(
232+
expect.objectContaining({ slug: 'brand' })
233+
);
234+
expect(fonts).toContainEqual(
235+
expect.objectContaining({ slug: 'sans', fontFamily: 'CustomSans, sans-serif' })
236+
);
237+
});
238+
239+
it('should preserve base fontSizes when font sizes are disabled', async () => {
240+
const themeJson = await runBuild(
241+
{ disableTailwindFontSizes: true },
242+
'theme-with-base.json'
243+
);
244+
const sizes = themeJson.settings.typography.fontSizes;
245+
246+
expect(sizes).toHaveLength(2);
247+
expect(sizes).toContainEqual(
248+
expect.objectContaining({ slug: 'tiny', size: '.5rem' })
249+
);
250+
expect(sizes).toContainEqual(
251+
expect.objectContaining({ slug: 'xl', size: '99rem' })
252+
);
253+
});
254+
255+
it('should preserve base radiusSizes when border radius is disabled', async () => {
256+
const themeJson = await runBuild(
257+
{ disableTailwindBorderRadius: true },
258+
'theme-with-base.json'
259+
);
260+
const radiusSizes = themeJson.settings.border?.radiusSizes;
261+
262+
expect(radiusSizes).toHaveLength(2);
263+
expect(radiusSizes).toContainEqual(
264+
expect.objectContaining({ slug: 'pill', size: '9999px' })
265+
);
266+
expect(radiusSizes).toContainEqual(
267+
expect.objectContaining({ slug: 'xl', size: '99rem' })
268+
);
269+
});
270+
271+
it('should include base custom colors alongside generated ones', async () => {
272+
const themeJson = await runBuild({}, 'theme-with-base.json');
273+
const palette = themeJson.settings.color.palette;
274+
275+
expect(palette).toContainEqual(
276+
expect.objectContaining({ slug: 'brand', color: '#ff6600' })
277+
);
278+
expect(palette.some((c: any) => c.slug.startsWith('blue-'))).toBe(true);
279+
});
280+
281+
it('should dedupe colors by slug with base values winning', async () => {
282+
const themeJson = await runBuild({}, 'theme-with-base.json');
283+
const palette = themeJson.settings.color.palette;
284+
285+
const red500 = palette.filter((c: any) => c.slug === 'red-500');
286+
expect(red500).toHaveLength(1);
287+
expect(red500[0].color).toBe('#custom-red');
288+
});
289+
290+
it('should dedupe fontFamilies by slug with base values winning', async () => {
291+
const themeJson = await runBuild({}, 'theme-with-base.json');
292+
const fonts = themeJson.settings.typography.fontFamilies;
293+
294+
const sans = fonts.filter((f: any) => f.slug === 'sans');
295+
expect(sans).toHaveLength(1);
296+
expect(sans[0].fontFamily).toBe('CustomSans, sans-serif');
297+
});
298+
299+
it('should dedupe fontSizes by slug with base values winning', async () => {
300+
const themeJson = await runBuild({}, 'theme-with-base.json');
301+
const sizes = themeJson.settings.typography.fontSizes;
302+
303+
const xl = sizes.filter((s: any) => s.slug === 'xl');
304+
expect(xl).toHaveLength(1);
305+
expect(xl[0].size).toBe('99rem');
306+
});
307+
308+
it('should dedupe radiusSizes by slug with base values winning', async () => {
309+
const themeJson = await runBuild(
310+
{ disableTailwindBorderRadius: false },
311+
'theme-with-base.json'
312+
);
313+
const radiusSizes = themeJson.settings.border?.radiusSizes;
314+
315+
const xl = radiusSizes!.filter((r: any) => r.slug === 'xl');
316+
expect(xl).toHaveLength(1);
317+
expect(xl[0].size).toBe('99rem');
318+
});
319+
});
320+
321+
describe('label customization', () => {
322+
it('should apply shadeLabels to color names', async () => {
323+
const themeJson = await runBuild({
324+
shadeLabels: { '500': 'Default' },
325+
});
326+
const palette = themeJson.settings.color.palette;
327+
328+
expect(palette).toContainEqual(
329+
expect.objectContaining({
330+
slug: 'red-500',
331+
name: 'Default Red',
332+
})
333+
);
334+
});
335+
336+
it('should apply fontLabels to font family names', async () => {
337+
const themeJson = await runBuild({
338+
fontLabels: { sans: 'System Sans' },
339+
});
340+
const fonts = themeJson.settings.typography.fontFamilies;
341+
342+
expect(fonts).toContainEqual(
343+
expect.objectContaining({
344+
slug: 'sans',
345+
name: 'System Sans',
346+
})
347+
);
348+
});
349+
350+
it('should apply fontSizeLabels to font size names', async () => {
351+
const themeJson = await runBuild({
352+
fontSizeLabels: { xl: 'Extra Large' },
353+
});
354+
const sizes = themeJson.settings.typography.fontSizes;
355+
356+
expect(sizes).toContainEqual(
357+
expect.objectContaining({
358+
slug: 'xl',
359+
name: 'Extra Large',
360+
})
361+
);
362+
});
363+
364+
it('should apply borderRadiusLabels to radius names', async () => {
365+
const themeJson = await runBuild({
366+
disableTailwindBorderRadius: false,
367+
borderRadiusLabels: { xl: 'Extra Large' },
368+
});
369+
const radiusSizes = themeJson.settings.border?.radiusSizes;
370+
371+
expect(radiusSizes).toContainEqual(
372+
expect.objectContaining({
373+
slug: 'xl',
374+
name: 'Extra Large',
375+
})
376+
);
118377
});
119378
});
120379
});

0 commit comments

Comments
 (0)