@@ -369,4 +369,192 @@ describe(enforceMotionSafeVariant.name, () => {
369369 } ) ;
370370 } ) ;
371371
372+ it ( "should still report when motion-reduce exists but allowMotionReduce is disabled" , ( ) => {
373+ lint ( enforceMotionSafeVariant , {
374+ invalid : [
375+ {
376+ angular : `<img class="motion-reduce:transition-none transition-all" />` ,
377+ html : `<img class="motion-reduce:transition-none transition-all" />` ,
378+ jsx : `() => <img class="motion-reduce:transition-none transition-all" />` ,
379+ svelte : `<img class="motion-reduce:transition-none transition-all" />` ,
380+ vue : `<template><img class="motion-reduce:transition-none transition-all" /></template>` ,
381+
382+ errors : 1 ,
383+
384+ options : [ { allowMotionReduce : false } ]
385+ }
386+ ]
387+ } ) ;
388+ } ) ;
389+
390+ it ( "should never report classes that already use the motion-reduce variant" , ( ) => {
391+ lint ( enforceMotionSafeVariant , {
392+ valid : [
393+ {
394+ angular : `<img class="motion-reduce:transition-none" />` ,
395+ html : `<img class="motion-reduce:transition-none" />` ,
396+ jsx : `() => <img class="motion-reduce:transition-none" />` ,
397+ svelte : `<img class="motion-reduce:transition-none" />` ,
398+ vue : `<template><img class="motion-reduce:transition-none" /></template>`
399+ } ,
400+ {
401+ angular : `<img class="motion-reduce:animate-none" />` ,
402+ html : `<img class="motion-reduce:animate-none" />` ,
403+ jsx : `() => <img class="motion-reduce:animate-none" />` ,
404+ svelte : `<img class="motion-reduce:animate-none" />` ,
405+ vue : `<template><img class="motion-reduce:animate-none" /></template>`
406+ }
407+ ]
408+ } ) ;
409+ } ) ;
410+
411+ it ( "should suppress regardless of class order when allowMotionReduce is enabled" , ( ) => {
412+ lint ( enforceMotionSafeVariant , {
413+ valid : [
414+ {
415+ angular : `<img class="transition-all motion-reduce:transition-none" />` ,
416+ html : `<img class="transition-all motion-reduce:transition-none" />` ,
417+ jsx : `() => <img class="transition-all motion-reduce:transition-none" />` ,
418+ svelte : `<img class="transition-all motion-reduce:transition-none" />` ,
419+ vue : `<template><img class="transition-all motion-reduce:transition-none" /></template>` ,
420+
421+ options : [ { allowMotionReduce : true } ]
422+ }
423+ ]
424+ } ) ;
425+ } ) ;
426+
427+ it ( "should report motion classes from priorLiterals when allowMotionReduce is disabled" , ( ) => {
428+ const expression = "${true ? 'foo' : 'bar'}" ;
429+
430+ lint ( enforceMotionSafeVariant , {
431+ invalid : [
432+ {
433+ jsx : `() => <img class={\`motion-reduce:transition-none ${ expression } transition-all\`} />` ,
434+ svelte : `<img class={\`motion-reduce:transition-none ${ expression } transition-all\`} />` ,
435+
436+ errors : 1 ,
437+
438+ options : [ { allowMotionReduce : false } ]
439+ }
440+ ]
441+ } ) ;
442+ } ) ;
443+
444+ it ( "should report arbitrary value transition and animate classes without motion-safe" , ( ) => {
445+ lint ( enforceMotionSafeVariant , {
446+ invalid : [
447+ {
448+ angular : `<img class="transition-[opacity]" />` ,
449+ html : `<img class="transition-[opacity]" />` ,
450+ jsx : `() => <img class="transition-[opacity]" />` ,
451+ svelte : `<img class="transition-[opacity]" />` ,
452+ vue : `<template><img class="transition-[opacity]" /></template>` ,
453+
454+ errors : 1
455+ } ,
456+ {
457+ angular : `<img class="animate-[spin_1s_linear_infinite]" />` ,
458+ html : `<img class="animate-[spin_1s_linear_infinite]" />` ,
459+ jsx : `() => <img class="animate-[spin_1s_linear_infinite]" />` ,
460+ svelte : `<img class="animate-[spin_1s_linear_infinite]" />` ,
461+ vue : `<template><img class="animate-[spin_1s_linear_infinite]" /></template>` ,
462+
463+ errors : 1
464+ }
465+ ] ,
466+ valid : [
467+ {
468+ angular : `<img class="motion-safe:transition-[opacity]" />` ,
469+ html : `<img class="motion-safe:transition-[opacity]" />` ,
470+ jsx : `() => <img class="motion-safe:transition-[opacity]" />` ,
471+ svelte : `<img class="motion-safe:transition-[opacity]" />` ,
472+ vue : `<template><img class="motion-safe:transition-[opacity]" /></template>`
473+ } ,
474+ {
475+ angular : `<img class="motion-safe:animate-[spin_1s_linear_infinite]" />` ,
476+ html : `<img class="motion-safe:animate-[spin_1s_linear_infinite]" />` ,
477+ jsx : `() => <img class="motion-safe:animate-[spin_1s_linear_infinite]" />` ,
478+ svelte : `<img class="motion-safe:animate-[spin_1s_linear_infinite]" />` ,
479+ vue : `<template><img class="motion-safe:animate-[spin_1s_linear_infinite]" /></template>`
480+ }
481+ ]
482+ } ) ;
483+ } ) ;
484+
485+ it ( "should report important motion classes without motion-safe" , ( ) => {
486+ lint ( enforceMotionSafeVariant , {
487+ invalid : [
488+ {
489+ angular : `<img class="!transition-all" />` ,
490+ html : `<img class="!transition-all" />` ,
491+ jsx : `() => <img class="!transition-all" />` ,
492+ svelte : `<img class="!transition-all" />` ,
493+ vue : `<template><img class="!transition-all" /></template>` ,
494+
495+ errors : 1
496+ } ,
497+ {
498+ angular : `<img class="transition-all!" />` ,
499+ html : `<img class="transition-all!" />` ,
500+ jsx : `() => <img class="transition-all!" />` ,
501+ svelte : `<img class="transition-all!" />` ,
502+ vue : `<template><img class="transition-all!" /></template>` ,
503+
504+ errors : 1
505+ } ,
506+ {
507+ angular : `<img class="!animate-spin" />` ,
508+ html : `<img class="!animate-spin" />` ,
509+ jsx : `() => <img class="!animate-spin" />` ,
510+ svelte : `<img class="!animate-spin" />` ,
511+ vue : `<template><img class="!animate-spin" /></template>` ,
512+
513+ errors : 1
514+ } ,
515+ {
516+ angular : `<img class="animate-spin!" />` ,
517+ html : `<img class="animate-spin!" />` ,
518+ jsx : `() => <img class="animate-spin!" />` ,
519+ svelte : `<img class="animate-spin!" />` ,
520+ vue : `<template><img class="animate-spin!" /></template>` ,
521+
522+ errors : 1
523+ }
524+ ] ,
525+ valid : [
526+ {
527+ angular : `<img class="motion-safe:!transition-all" />` ,
528+ html : `<img class="motion-safe:!transition-all" />` ,
529+ jsx : `() => <img class="motion-safe:!transition-all" />` ,
530+ svelte : `<img class="motion-safe:!transition-all" />` ,
531+ vue : `<template><img class="motion-safe:!transition-all" /></template>`
532+ } ,
533+ {
534+ angular : `<img class="motion-safe:transition-all!" />` ,
535+ html : `<img class="motion-safe:transition-all!" />` ,
536+ jsx : `() => <img class="motion-safe:transition-all!" />` ,
537+ svelte : `<img class="motion-safe:transition-all!" />` ,
538+ vue : `<template><img class="motion-safe:transition-all!" /></template>`
539+ }
540+ ]
541+ } ) ;
542+ } ) ;
543+
544+ it ( "should report duplicate offending classes deterministically" , ( ) => {
545+ lint ( enforceMotionSafeVariant , {
546+ invalid : [
547+ {
548+ angular : `<img class="transition-all transition-all" />` ,
549+ html : `<img class="transition-all transition-all" />` ,
550+ jsx : `() => <img class="transition-all transition-all" />` ,
551+ svelte : `<img class="transition-all transition-all" />` ,
552+ vue : `<template><img class="transition-all transition-all" /></template>` ,
553+
554+ errors : 2
555+ }
556+ ]
557+ } ) ;
558+ } ) ;
559+
372560} ) ;
0 commit comments