@@ -9,12 +9,12 @@ import path from 'path';
99const fixtureDir = path . resolve ( __dirname , 'fixture' ) ;
1010const 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 ( / ^ o k l c h \( / ) ;
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