@@ -286,4 +286,376 @@ describe('postcss-unit-processor', () => {
286286 { processor }
287287 ) ;
288288 } ) ;
289+
290+ // Test quoted string values that should not be processed
291+ it ( 'should not process values in quoted strings' , async ( ) => {
292+ const processor = ( value , unit ) => {
293+ if ( unit === 'px' ) {
294+ return { value : value * 2 , unit : 'px' } ;
295+ }
296+ return { value, unit } ;
297+ } ;
298+ await testProcess (
299+ 'div { content: "100px"; background: url(100px); width: 100px; }' ,
300+ 'div { content: "100px"; background: url(100px); width: 200px; }' ,
301+ { processor }
302+ ) ;
303+ } ) ;
304+
305+ // Test blacklistedSelector with non-string selector
306+ it ( 'should handle non-string selector in blacklist check' , async ( ) => {
307+ const processor = ( value , unit ) => {
308+ if ( unit === 'px' ) {
309+ return { value : value * 2 , unit : 'px' } ;
310+ }
311+ return { value, unit } ;
312+ } ;
313+
314+ // Create CSS with a rule that has no selector
315+ const input = 'div { width: 100px; }' ;
316+ const result = await postcss ( [ unitProcessor ( { processor, selectorBlackList : [ 'test' ] } ) ] )
317+ . process ( input , { from : undefined } ) ;
318+ expect ( result . css ) . toEqual ( 'div { width: 200px; }' ) ;
319+ } ) ;
320+
321+ // Test property list with notContain pattern
322+ it ( 'should not process properties containing blacklisted string' , async ( ) => {
323+ const processor = ( value , unit ) => {
324+ if ( unit === 'px' ) {
325+ return { value : value * 2 , unit : 'px' } ;
326+ }
327+ return { value, unit } ;
328+ } ;
329+ await testProcess (
330+ 'div { max-width: 100px; min-test-width: 50px; width: 75px; height: 25px; }' ,
331+ 'div { max-width: 200px; min-test-width: 50px; width: 150px; height: 50px; }' ,
332+ { processor, propList : [ '*' , '!*test*' ] }
333+ ) ;
334+ } ) ;
335+
336+ // Test property list with notStartWith pattern
337+ it ( 'should not process properties starting with blacklisted string' , async ( ) => {
338+ const processor = ( value , unit ) => {
339+ if ( unit === 'px' ) {
340+ return { value : value * 2 , unit : 'px' } ;
341+ }
342+ return { value, unit } ;
343+ } ;
344+ await testProcess (
345+ 'div { max-width: 100px; test-width: 50px; width: 75px; height: 25px; }' ,
346+ 'div { max-width: 200px; test-width: 50px; width: 150px; height: 50px; }' ,
347+ { processor, propList : [ '*' , '!test*' ] }
348+ ) ;
349+ } ) ;
350+
351+ // Test property list with notEndWith pattern
352+ it ( 'should not process properties ending with blacklisted string' , async ( ) => {
353+ const processor = ( value , unit ) => {
354+ if ( unit === 'px' ) {
355+ return { value : value * 2 , unit : 'px' } ;
356+ }
357+ return { value, unit } ;
358+ } ;
359+ await testProcess (
360+ 'div { max-width: 100px; width-test: 50px; width: 75px; height: 25px; }' ,
361+ 'div { max-width: 200px; width-test: 50px; width: 150px; height: 50px; }' ,
362+ { processor, propList : [ '*' , '!*test' ] }
363+ ) ;
364+ } ) ;
365+
366+ // Test exclude option with function that returns true
367+ it ( 'should exclude files when exclude function returns true' , async ( ) => {
368+ const processor = ( value , unit ) => {
369+ if ( unit === 'px' ) {
370+ return { value : value * 2 , unit : 'px' } ;
371+ }
372+ return { value, unit } ;
373+ } ;
374+ const input = 'div { width: 100px; }' ;
375+ const result = await postcss ( [ unitProcessor ( { processor, exclude : ( ) => true } ) ] )
376+ . process ( input , { from : 'test.css' } ) ;
377+ expect ( result . css ) . toEqual ( 'div { width: 100px; }' ) ;
378+ } ) ;
379+
380+ // Test exclude option with string that matches file path
381+ it ( 'should exclude files when file path contains exclude string' , async ( ) => {
382+ const processor = ( value , unit ) => {
383+ if ( unit === 'px' ) {
384+ return { value : value * 2 , unit : 'px' } ;
385+ }
386+ return { value, unit } ;
387+ } ;
388+ const input = 'div { width: 100px; }' ;
389+ const result = await postcss ( [ unitProcessor ( { processor, exclude : 'test' } ) ] )
390+ . process ( input , { from : 'test.css' } ) ;
391+ expect ( result . css ) . toEqual ( 'div { width: 100px; }' ) ;
392+ } ) ;
393+
394+ // Test exclude option with regex that matches file path
395+ it ( 'should exclude files when file path matches exclude regex' , async ( ) => {
396+ const processor = ( value , unit ) => {
397+ if ( unit === 'px' ) {
398+ return { value : value * 2 , unit : 'px' } ;
399+ }
400+ return { value, unit } ;
401+ } ;
402+ const input = 'div { width: 100px; }' ;
403+ const result = await postcss ( [ unitProcessor ( { processor, exclude : / t e s t / } ) ] )
404+ . process ( input , { from : 'test.css' } ) ;
405+ expect ( result . css ) . toEqual ( 'div { width: 100px; }' ) ;
406+ } ) ;
407+
408+ // Test media query processing when excluded
409+ it ( 'should not process media queries when file is excluded' , async ( ) => {
410+ const processor = ( value , unit ) => {
411+ if ( unit === 'px' ) {
412+ return { value : value * 2 , unit : 'px' } ;
413+ }
414+ return { value, unit } ;
415+ } ;
416+ const input = '@media (max-width: 600px) { div { width: 100px; } }' ;
417+ const result = await postcss ( [ unitProcessor ( { processor, mediaQuery : true , exclude : / t e s t / } ) ] )
418+ . process ( input , { from : 'test.css' } ) ;
419+ expect ( result . css ) . toEqual ( '@media (max-width: 600px) { div { width: 100px; } }' ) ;
420+ } ) ;
421+
422+ // Test blacklistedSelector function directly by manipulating parent selector
423+ it ( 'should handle declaration with non-string parent selector' , async ( ) => {
424+ const processor = ( value , unit ) => {
425+ if ( unit === 'px' ) {
426+ return { value : value * 2 , unit : 'px' } ;
427+ }
428+ return { value, unit } ;
429+ } ;
430+
431+ const testPlugin = ( ) => {
432+ return {
433+ postcssPlugin : 'test-manipulation' ,
434+ Once ( root ) {
435+ // Apply unitProcessor first
436+ const unitProc = unitProcessor ( { processor, selectorBlackList : [ 'test' ] } ) ;
437+ if ( unitProc . Once ) unitProc . Once ( root ) ;
438+
439+ root . walkDecls ( decl => {
440+ if ( decl . prop === 'width' ) {
441+ // Temporarily set selector to non-string to trigger the blacklist check
442+ const originalSelector = decl . parent . selector ;
443+ decl . parent . selector = undefined ;
444+
445+ // Manually call the blacklist check portion
446+ if ( unitProc . Declaration ) {
447+ try {
448+ unitProc . Declaration ( decl ) ;
449+ } catch ( e ) {
450+ // Expected to fail due to unitReplace not being properly initialized in this context
451+ }
452+ }
453+
454+ // Restore selector
455+ decl . parent . selector = originalSelector ;
456+ }
457+ } ) ;
458+ }
459+ } ;
460+ } ;
461+ testPlugin . postcss = true ;
462+
463+ const input = 'div { width: 100px; }' ;
464+ await postcss ( [ testPlugin ( ) ] )
465+ . process ( input , { from : undefined } ) ;
466+ } ) ;
467+
468+ // Test customUnitList with non-array value
469+ it ( 'should handle non-array customUnitList' , async ( ) => {
470+ const processor = ( value , unit ) => {
471+ if ( unit === 'px' ) {
472+ return { value : value * 2 , unit : 'px' } ;
473+ }
474+ return { value, unit } ;
475+ } ;
476+ await testProcess (
477+ 'div { width: 100px; }' ,
478+ 'div { width: 200px; }' ,
479+ { processor, customUnitList : 'not-an-array' }
480+ ) ;
481+ } ) ;
482+
483+ // Test customUnitList with invalid units
484+ it ( 'should filter out invalid custom units' , async ( ) => {
485+ const processor = ( value , unit ) => {
486+ if ( unit === 'valid' ) {
487+ return { value : value * 2 , unit : 'valid' } ;
488+ }
489+ return { value, unit } ;
490+ } ;
491+ await testProcess (
492+ 'div { width: 100valid; margin: 50invalid123; padding: 25; }' ,
493+ 'div { width: 200valid; margin: 50invalid123; padding: 25; }' ,
494+ {
495+ processor,
496+ customUnitList : [
497+ 'valid' , // valid
498+ 'invalid123' , // invalid - contains numbers
499+ 123 , // invalid - not a string
500+ '' , // invalid - empty string
501+ ' ' , // invalid - only whitespace
502+ null , // invalid - null
503+ 'spec@al' // invalid - contains special chars
504+ ]
505+ }
506+ ) ;
507+ } ) ;
508+
509+ // Test processor returning object with null value
510+ it ( 'should handle processor returning object with null value' , async ( ) => {
511+ const processor = ( value , unit ) => {
512+ if ( unit === 'px' ) {
513+ return { value : null , unit : 'px' } ;
514+ }
515+ return { value, unit } ;
516+ } ;
517+ await testProcess (
518+ 'div { width: 100px; }' ,
519+ 'div { width: 0; }' ,
520+ { processor }
521+ ) ;
522+ } ) ;
523+
524+ // Test processor returning object with undefined value
525+ it ( 'should handle processor returning object with undefined value' , async ( ) => {
526+ const processor = ( value , unit ) => {
527+ if ( unit === 'px' ) {
528+ return { value : undefined , unit : 'px' } ;
529+ }
530+ return { value, unit } ;
531+ } ;
532+ await testProcess (
533+ 'div { width: 100px; }' ,
534+ 'div { width: 0; }' ,
535+ { processor }
536+ ) ;
537+ } ) ;
538+
539+ // Test processor returning object with falsy unit
540+ it ( 'should handle processor returning object with falsy unit' , async ( ) => {
541+ const processor = ( value , unit ) => {
542+ if ( unit === 'px' ) {
543+ return { value : 50 , unit : '' } ;
544+ }
545+ return { value, unit } ;
546+ } ;
547+ await testProcess (
548+ 'div { width: 100px; }' ,
549+ 'div { width: 50px; }' ,
550+ { processor }
551+ ) ;
552+ } ) ;
553+
554+ // Test processor returning object with null unit
555+ it ( 'should handle processor returning object with null unit' , async ( ) => {
556+ const processor = ( value , unit ) => {
557+ if ( unit === 'px' ) {
558+ return { value : 50 , unit : null } ;
559+ }
560+ return { value, unit } ;
561+ } ;
562+ await testProcess (
563+ 'div { width: 100px; }' ,
564+ 'div { width: 50px; }' ,
565+ { processor }
566+ ) ;
567+ } ) ;
568+
569+ // Test processor returning string number
570+ it ( 'should handle processor returning string number' , async ( ) => {
571+ const processor = ( value , unit ) => {
572+ if ( unit === 'px' ) {
573+ return '75.5' ;
574+ }
575+ return value ;
576+ } ;
577+ await testProcess (
578+ 'div { width: 100px; }' ,
579+ 'div { width: 75.5px; }' ,
580+ { processor }
581+ ) ;
582+ } ) ;
583+
584+ // Test processor returning NaN string
585+ it ( 'should handle processor returning non-numeric string' , async ( ) => {
586+ const processor = ( value , unit ) => {
587+ if ( unit === 'px' ) {
588+ return 'not-a-number' ;
589+ }
590+ return value ;
591+ } ;
592+ await testProcess (
593+ 'div { width: 100px; }' ,
594+ 'div { width: 0; }' ,
595+ { processor }
596+ ) ;
597+ } ) ;
598+
599+ // Test processor returning 0 value
600+ it ( 'should handle processor returning 0 value' , async ( ) => {
601+ const processor = ( value , unit ) => {
602+ if ( unit === 'px' ) {
603+ return 0 ;
604+ }
605+ return value ;
606+ } ;
607+ await testProcess (
608+ 'div { width: 100px; }' ,
609+ 'div { width: 0; }' ,
610+ { processor }
611+ ) ;
612+ } ) ;
613+
614+ // Test processor returning object with 0 value
615+ it ( 'should handle processor returning object with 0 value' , async ( ) => {
616+ const processor = ( value , unit ) => {
617+ if ( unit === 'px' ) {
618+ return { value : 0 , unit : 'px' } ;
619+ }
620+ return { value, unit } ;
621+ } ;
622+ await testProcess (
623+ 'div { width: 100px; }' ,
624+ 'div { width: 0; }' ,
625+ { processor }
626+ ) ;
627+ } ) ;
628+
629+ // Test processor returning exact number type
630+ it ( 'should handle processor returning exact number type' , async ( ) => {
631+ const processor = ( value , unit ) => {
632+ if ( unit === 'px' ) {
633+ return 42.75 ;
634+ }
635+ return value ;
636+ } ;
637+ await testProcess (
638+ 'div { width: 100px; }' ,
639+ 'div { width: 42.75px; }' ,
640+ { processor }
641+ ) ;
642+ } ) ;
643+
644+ // Test unitProcessor with no options (default parameter)
645+ it ( 'should handle unitProcessor called without options' , async ( ) => {
646+ const input = 'div { width: 100px; }' ;
647+ const result = await postcss ( [ unitProcessor ( ) ] )
648+ . process ( input , { from : undefined } ) ;
649+ expect ( result . css ) . toEqual ( 'div { width: 100px; }' ) ;
650+ expect ( result . warnings ( ) ) . toHaveLength ( 0 ) ;
651+ } ) ;
652+
653+ // Test unitProcessor with undefined options (default parameter)
654+ it ( 'should handle unitProcessor called with undefined options' , async ( ) => {
655+ const input = 'div { width: 100px; }' ;
656+ const result = await postcss ( [ unitProcessor ( undefined ) ] )
657+ . process ( input , { from : undefined } ) ;
658+ expect ( result . css ) . toEqual ( 'div { width: 100px; }' ) ;
659+ expect ( result . warnings ( ) ) . toHaveLength ( 0 ) ;
660+ } ) ;
289661} ) ;
0 commit comments