@@ -36,13 +36,63 @@ describe('variants runtime', () => {
3636 expect ( button ( { tone : 'accent' } ) ) . toBe ( 'text-_b_hececec_B' )
3737 } )
3838
39+ it ( 'escapes rpx units and color literals inside tv output' , ( ) => {
40+ const stack = tv ( {
41+ base : 'text-[24rpx] bg-[#0f0]' ,
42+ variants : {
43+ tone : {
44+ danger : 'text-[#FF0000] text-[32rpx]' ,
45+ } ,
46+ } ,
47+ } )
48+
49+ const baseOutput = stack ( ) ?. split ( ' ' )
50+ expect ( new Set ( baseOutput ) ) . toEqual ( new Set ( [ 'text-_b24rpx_B' , 'bg-_b_h0f0_B' ] ) )
51+
52+ const variantOutput = stack ( { tone : 'danger' } ) ?. split ( ' ' )
53+ expect ( new Set ( variantOutput ) ) . toEqual ( new Set ( [
54+ 'text-_b32rpx_B' ,
55+ 'bg-_b_h0f0_B' ,
56+ 'text-_b_hFF0000_B' ,
57+ ] ) )
58+ } )
59+
3960 it ( 'supports custom transformers through create' , ( ) => {
4061 const { tv : rawTv } = createVariants ( { escape : false } )
4162 const badge = rawTv ( { base : 'text-[#ececec]' } )
4263
4364 expect ( badge ( ) ) . toBe ( 'text-[#ececec]' )
4465 } )
4566
67+ it ( 'respects disabled escape/unescape options in runtime factory' , ( ) => {
68+ const runtime = createVariants ( { escape : false , unescape : false } )
69+ const badge = runtime . tv ( {
70+ base : 'text-[#ECECEC]' ,
71+ variants : {
72+ tone : {
73+ accent : 'text-[#101010]' ,
74+ } ,
75+ } ,
76+ } )
77+
78+ // Should bypass escape/unescape while still merging conflicting classes.
79+ expect ( badge ( { tone : 'accent' } ) ) . toBe ( 'text-[#101010]' )
80+
81+ const aggregate = runtime . cn ( 'text-[#ECECEC]' , 'text-[#101010]' )
82+ expect ( aggregate ( ) ) . toBe ( 'text-[#101010]' )
83+ expect ( aggregate ( { twMerge : false } ) ) . toBe ( 'text-[#ECECEC] text-[#101010]' )
84+
85+ const mergedTv = runtime . tv ( {
86+ base : 'text-[#101010]' ,
87+ variants : {
88+ tone : {
89+ accent : 'text-[#ECECEC]' ,
90+ } ,
91+ } ,
92+ } )
93+ expect ( mergedTv ( { tone : 'accent' } ) ) . toBe ( 'text-[#ECECEC]' )
94+ } )
95+
4696 it ( 'wraps cn aggregation with merge + escaping' , ( ) => {
4797 const aggregate = cn ( 'text-[#ececec]' , 'text-[#ECECEC]' )
4898
@@ -74,4 +124,78 @@ describe('variants runtime', () => {
74124 expect ( aggregate ( ) ) . toBeUndefined ( )
75125 expect ( cnBase ( ) ) . toBeUndefined ( )
76126 } )
127+
128+ it ( 'aggregates rpx units and hex colors via cn helpers' , ( ) => {
129+ const aggregate = cn ( 'text-[16rpx]' , 'bg-[#ff0000]' , 'text-[#00FF00]' )
130+
131+ expect ( aggregate ( ) ) . toBe ( 'text-_b16rpx_B bg-_b_hff0000_B text-_b_h00FF00_B' )
132+ expect ( cnBase ( 'border-[2rpx]' , 'text-[#123456]' ) ) . toBe ( 'border-_b2rpx_B text-_b_h123456_B' )
133+ } )
134+
135+ it ( 'preserves tailwind-variants metadata when wrapping components' , ( ) => {
136+ const badge = tv ( {
137+ base : 'text-[#ececec]' ,
138+ variants : {
139+ size : {
140+ sm : 'text-sm' ,
141+ } ,
142+ } ,
143+ defaultVariants : {
144+ size : 'sm' ,
145+ } ,
146+ } )
147+
148+ expect ( badge . variantKeys ) . toEqual ( [ 'size' ] )
149+ expect ( badge . defaultVariants ) . toEqual ( { size : 'sm' } )
150+ } )
151+
152+ it ( 'wraps slot functions so per-slot output is escaped and merged' , ( ) => {
153+ const alert = tv ( {
154+ slots : {
155+ base : 'text-[#101010]' ,
156+ icon : 'text-[#202020]' ,
157+ } ,
158+ variants : {
159+ tone : {
160+ accent : {
161+ base : 'text-[#ECECEC]' ,
162+ icon : 'text-[#ECECEC]' ,
163+ } ,
164+ } ,
165+ } ,
166+ } )
167+
168+ const slots = alert ( { tone : 'accent' } )
169+ expect ( typeof slots . base ) . toBe ( 'function' )
170+ expect ( slots . base ( ) ) . toBe ( 'text-_b_hECECEC_B' )
171+ expect ( slots . icon ( ) ) . toBe ( 'text-_b_hECECEC_B' )
172+ expect ( slots . icon ( { class : 'text-[#303030]' } ) ) . toBe ( 'text-_b_h303030_B' )
173+ } )
174+
175+ it ( 'merges config overrides from createTV invocations' , ( ) => {
176+ const makeTv = createTV ( { twMerge : false } )
177+ const badge = makeTv ( {
178+ base : 'text-[#101010]' ,
179+ variants : {
180+ tone : {
181+ accent : 'text-[#ECECEC]' ,
182+ } ,
183+ } ,
184+ } )
185+
186+ expect ( badge ( { tone : 'accent' } ) ) . toBe ( 'text-_b_h101010_B text-_b_hECECEC_B' )
187+
188+ const mergedBadge = makeTv (
189+ {
190+ base : 'text-[#101010]' ,
191+ variants : {
192+ tone : {
193+ accent : 'text-[#ECECEC]' ,
194+ } ,
195+ } ,
196+ } ,
197+ { twMerge : true } ,
198+ )
199+ expect ( mergedBadge ( { tone : 'accent' } ) ) . toBe ( 'text-_b_hECECEC_B' )
200+ } )
77201} )
0 commit comments