test : add comprehensive test suite for CSS ordering rules

Add tests for all three CSS property ordering rules:

    alphabetical-order,
    concentric-order,
    custom-order,

Tests cover all implemented vanilla-extract APIs, fontFace, globalFontFace, globalKeyframes, globalStyle, keyframes, style, and styleVariants.. Each test verifies both valid and invalid cases, along with proper auto-fixing functionality.
This commit is contained in:
Ante Budimir 2025-03-09 18:12:00 +02:00
parent 3e9bad1b02
commit 5f1e602dee
25 changed files with 3635 additions and 24 deletions

View file

@ -0,0 +1,151 @@
import tsParser from '@typescript-eslint/parser';
import { run } from 'eslint-vitest-rule-tester';
import customGroupOrderRule from '../rule-definition.js';
run({
name: 'vanilla-extract/custom-order/animation',
rule: customGroupOrderRule,
languageOptions: {
parser: tsParser,
parserOptions: {
ecmaVersion: 2022,
sourceType: 'module',
},
},
valid: [
// keyframes with custom group ordering (concentric for remaining)
{
code: `
import { keyframes } from '@vanilla-extract/css';
const fadeIn = keyframes({
'0%': {
position: 'relative',
transform: 'translateY(1rem)',
opacity: 0
},
'100%': {
position: 'relative',
transform: 'translateY(0)',
opacity: 1
}
});
`,
options: [
{
groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'],
sortRemainingProperties: 'concentric',
},
],
},
// keyframes with custom group ordering (alphabetical for remaining)
{
code: `
import { keyframes } from '@vanilla-extract/css';
const fadeIn = keyframes({
'0%': {
opacity: 0,
position: 'relative',
transform: 'translateY(1rem)'
},
'100%': {
opacity: 1,
position: 'relative',
transform: 'translateY(0)'
}
});
`,
options: [
{
groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'],
sortRemainingProperties: 'alphabetical',
},
],
},
],
invalid: [
// keyframes with incorrect ordering (concentric for remaining)
{
code: `
import { keyframes } from '@vanilla-extract/css';
const fadeIn = keyframes({
'0%': {
opacity: 0,
transform: 'translateY(1rem)',
position: 'relative'
},
'100%': {
opacity: 1,
transform: 'translateY(0)',
position: 'relative'
}
});
`,
options: [
{
groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'],
sortRemainingProperties: 'concentric',
},
],
errors: [{ messageId: 'incorrectOrder' }, { messageId: 'incorrectOrder' }],
output: `
import { keyframes } from '@vanilla-extract/css';
const fadeIn = keyframes({
'0%': {
position: 'relative',
transform: 'translateY(1rem)',
opacity: 0
},
'100%': {
position: 'relative',
transform: 'translateY(0)',
opacity: 1
}
});
`,
},
// keyframes with incorrect ordering (alphabetical for remaining)
{
code: `
import { keyframes } from '@vanilla-extract/css';
const fadeIn = keyframes({
'0%': {
transform: 'translateY(1rem)',
position: 'relative',
opacity: 0
},
'100%': {
transform: 'translateY(0)',
position: 'relative',
opacity: 1
}
});
`,
options: [
{
groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'],
sortRemainingProperties: 'alphabetical',
},
],
errors: [{ messageId: 'incorrectOrder' }, { messageId: 'incorrectOrder' }],
output: `
import { keyframes } from '@vanilla-extract/css';
const fadeIn = keyframes({
'0%': {
opacity: 0,
position: 'relative',
transform: 'translateY(1rem)'
},
'100%': {
opacity: 1,
position: 'relative',
transform: 'translateY(0)'
}
});
`,
},
],
});

View file

@ -0,0 +1,127 @@
import tsParser from '@typescript-eslint/parser';
import { run } from 'eslint-vitest-rule-tester';
import customGroupOrderRule from '../rule-definition.js';
run({
name: 'vanilla-extract/custom-order/font-face',
rule: customGroupOrderRule,
configs: {
languageOptions: {
parser: tsParser,
parserOptions: {
ecmaVersion: 2022,
sourceType: 'module',
},
},
},
valid: [
// fontFace
{
code: `
import { fontFace } from '@vanilla-extract/css';
const myFont = fontFace({
src: ['url("/fonts/MyFont.woff2") format("woff2")'],
ascentOverride: '90%',
descentOverride: '10%',
fontDisplay: 'swap',
fontFeatureSettings: '"liga" 1',
fontStretch: 'normal',
fontStyle: 'normal',
fontVariant: 'normal',
fontWeight: '400'
});
`,
options: [
{
groupOrder: ['dimensions', 'margin', 'font'],
sortRemainingProperties: 'concentric',
},
],
},
// globalFontFace
{
code: `
import { globalFontFace } from '@vanilla-extract/css';
globalFontFace('GlobalFont', {
src: ['url("/fonts/MyFont.woff2") format("woff2")'],
ascentOverride: '90%',
descentOverride: '10%',
fontDisplay: 'swap',
fontFeatureSettings: '"liga" 1',
fontStretch: 'normal',
fontStyle: 'normal',
fontVariant: 'normal',
fontWeight: '400'
});
`,
options: [
{
groupOrder: ['dimensions', 'margin', 'font'],
sortRemainingProperties: 'concentric',
},
],
},
],
invalid: [
// fontFace with src not first
{
code: `
import { fontFace } from '@vanilla-extract/css';
const myFont = fontFace({
fontWeight: '400',
src: ['url("/fonts/MyFont.woff2") format("woff2")'],
ascentOverride: '90%',
fontStyle: 'normal'
});
`,
options: [
{
groupOrder: ['dimensions', 'margin', 'font'],
sortRemainingProperties: 'concentric',
},
],
errors: [{ messageId: 'fontFaceOrder' }],
output: `
import { fontFace } from '@vanilla-extract/css';
const myFont = fontFace({
src: ['url("/fonts/MyFont.woff2") format("woff2")'],
ascentOverride: '90%',
fontStyle: 'normal',
fontWeight: '400'
});
`,
},
// globalFontFace with src not first
{
code: `
import { globalFontFace } from '@vanilla-extract/css';
globalFontFace('GlobalFont', {
fontWeight: '400',
fontStyle: 'normal',
src: ['url("/fonts/MyFont.woff2") format("woff2")'],
ascentOverride: '90%'
});
`,
options: [
{
groupOrder: ['dimensions', 'margin', 'font'],
sortRemainingProperties: 'concentric',
},
],
errors: [{ messageId: 'fontFaceOrder' }],
output: `
import { globalFontFace } from '@vanilla-extract/css';
globalFontFace('GlobalFont', {
src: ['url("/fonts/MyFont.woff2") format("woff2")'],
ascentOverride: '90%',
fontStyle: 'normal',
fontWeight: '400'
});
`,
},
],
});

View file

@ -0,0 +1,127 @@
import tsParser from '@typescript-eslint/parser';
import { run } from 'eslint-vitest-rule-tester';
import customGroupOrderRule from '../rule-definition.js';
run({
name: 'vanilla-extract/custom-order/global',
rule: customGroupOrderRule,
languageOptions: {
parser: tsParser,
parserOptions: {
ecmaVersion: 2022,
sourceType: 'module',
},
},
valid: [
// globalStyle with custom group ordering (concentric for remaining)
{
code: `
import { globalStyle } from '@vanilla-extract/css';
globalStyle('body', {
margin: 0,
position: 'relative',
display: 'block',
backgroundColor: 'white',
padding: 0,
color: 'black'
});
`,
options: [
{
groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'],
sortRemainingProperties: 'concentric',
},
],
},
// globalStyle with custom group ordering (alphabetical for remaining)
{
code: `
import { globalStyle } from '@vanilla-extract/css';
globalStyle('body', {
margin: 0,
backgroundColor: 'white',
color: 'black',
display: 'block',
padding: 0,
position: 'relative'
});
`,
options: [
{
groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'],
sortRemainingProperties: 'alphabetical',
},
],
},
],
invalid: [
// globalStyle with incorrect ordering (concentric for remaining)
{
code: `
import { globalStyle } from '@vanilla-extract/css';
globalStyle('body', {
color: 'black',
margin: 0,
backgroundColor: 'white',
padding: 0,
display: 'block',
position: 'relative'
});
`,
options: [
{
groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'],
sortRemainingProperties: 'concentric',
},
],
errors: [{ messageId: 'incorrectOrder' }],
output: `
import { globalStyle } from '@vanilla-extract/css';
globalStyle('body', {
margin: 0,
position: 'relative',
display: 'block',
backgroundColor: 'white',
padding: 0,
color: 'black'
});
`,
},
// globalStyle with incorrect ordering (alphabetical for remaining)
{
code: `
import { globalStyle } from '@vanilla-extract/css';
globalStyle('body', {
position: 'relative',
display: 'block',
margin: 0,
backgroundColor: 'white',
padding: 0,
color: 'black'
});
`,
options: [
{
groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'],
sortRemainingProperties: 'alphabetical',
},
],
errors: [{ messageId: 'incorrectOrder' }],
output: `
import { globalStyle } from '@vanilla-extract/css';
globalStyle('body', {
margin: 0,
backgroundColor: 'white',
color: 'black',
display: 'block',
padding: 0,
position: 'relative'
});
`,
},
],
});

View file

@ -0,0 +1,211 @@
import tsParser from '@typescript-eslint/parser';
import { run } from 'eslint-vitest-rule-tester';
import customGroupOrderRule from '../rule-definition.js';
run({
name: 'vanilla-extract/custom-order/recipe',
rule: customGroupOrderRule,
languageOptions: {
parser: tsParser,
parserOptions: {
ecmaVersion: 2022,
sourceType: 'module',
},
},
valid: [
// Recipe with custom group ordering (concentric for remaining)
{
code: `
import { recipe } from '@vanilla-extract/recipes';
const myRecipe = recipe({
base: {
width: '100%',
margin: 0,
position: 'relative',
display: 'flex',
alignItems: 'center',
backgroundColor: 'white'
},
variants: {
color: {
blue: {
position: 'relative',
backgroundColor: 'blue',
color: 'white'
},
red: {
position: 'relative',
backgroundColor: 'red',
color: 'black'
}
}
}
});
`,
options: [
{
groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'],
sortRemainingProperties: 'concentric',
},
],
},
// Recipe with custom group ordering (alphabetical for remaining)
{
code: `
import { recipe } from '@vanilla-extract/recipes';
const myRecipe = recipe({
base: {
width: '100%',
margin: 0,
alignItems: 'center',
backgroundColor: 'white',
display: 'flex',
position: 'relative'
},
variants: {
color: {
blue: {
backgroundColor: 'blue',
color: 'white',
position: 'relative'
},
red: {
backgroundColor: 'red',
color: 'black',
position: 'relative'
}
}
}
});
`,
options: [
{
groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'],
sortRemainingProperties: 'alphabetical',
},
],
},
],
invalid: [
// Recipe with incorrect ordering (concentric for remaining)
{
code: `
import { recipe } from '@vanilla-extract/recipes';
const myRecipe = recipe({
base: {
backgroundColor: 'white',
width: '100%',
display: 'flex',
alignItems: 'center',
margin: 0
},
variants: {
color: {
blue: {
color: 'white',
backgroundColor: 'blue',
position: 'relative'
},
red: {
color: 'black',
backgroundColor: 'red',
position: 'relative'
}
}
}
});
`,
options: [
{
groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'],
sortRemainingProperties: 'concentric',
},
],
errors: [{ messageId: 'incorrectOrder' }, { messageId: 'incorrectOrder' }, { messageId: 'incorrectOrder' }],
output: `
import { recipe } from '@vanilla-extract/recipes';
const myRecipe = recipe({
base: {
width: '100%',
margin: 0,
display: 'flex',
alignItems: 'center',
backgroundColor: 'white'
},
variants: {
color: {
blue: {
position: 'relative',
backgroundColor: 'blue',
color: 'white'
},
red: {
position: 'relative',
backgroundColor: 'red',
color: 'black'
}
}
}
});
`,
},
// Recipe with incorrect ordering (alphabetical for remaining)
{
code: `
import { recipe } from '@vanilla-extract/recipes';
const myRecipe = recipe({
base: {
position: 'relative',
display: 'flex',
alignItems: 'center',
backgroundColor: 'white',
width: '100%',
margin: 0
},
variants: {
color: {
blue: {
position: 'relative',
backgroundColor: 'blue',
color: 'white'
}
}
}
});
`,
options: [
{
groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'],
sortRemainingProperties: 'alphabetical',
},
],
errors: [{ messageId: 'incorrectOrder' }, { messageId: 'incorrectOrder' }],
output: `
import { recipe } from '@vanilla-extract/recipes';
const myRecipe = recipe({
base: {
width: '100%',
margin: 0,
alignItems: 'center',
backgroundColor: 'white',
display: 'flex',
position: 'relative'
},
variants: {
color: {
blue: {
backgroundColor: 'blue',
color: 'white',
position: 'relative'
}
}
}
});
`,
},
],
});

View file

@ -0,0 +1,252 @@
import tsParser from '@typescript-eslint/parser';
import { run } from 'eslint-vitest-rule-tester';
import customGroupOrderRule from '../rule-definition.js';
run({
name: 'vanilla-extract/custom-order/style',
rule: customGroupOrderRule,
languageOptions: {
parser: tsParser,
parserOptions: {
ecmaVersion: 2022,
sourceType: 'module',
},
},
valid: [
// Style with custom group ordering (dimensions, margin, font, border, boxShadow)
{
code: `
import { style } from '@vanilla-extract/css';
const myStyle = style({
// dimensions group first
width: '10rem',
minWidth: '5rem',
height: '10rem',
maxHeight: '20rem',
// margin group second
margin: '1rem',
marginTop: '0.5rem',
// font group third
fontFamily: 'sans-serif',
fontSize: '1rem',
fontWeight: 'bold',
// border group fourth
border: '1px solid black',
borderRadius: '4px',
// boxShadow group fifth
boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
// remaining properties in concentric order
position: 'relative',
display: 'flex',
backgroundColor: 'red',
padding: '2rem',
color: 'blue'
});
`,
options: [
{
groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'],
sortRemainingProperties: 'concentric',
},
],
},
// Style with nested selectors following custom group ordering
{
code: `
import { style } from '@vanilla-extract/css';
const myStyle = style({
width: '10rem',
margin: '1rem',
fontFamily: 'sans-serif',
border: '1px solid black',
boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
position: 'relative',
backgroundColor: 'red',
selectors: {
'&:hover': {
width: '12rem',
margin: '12px',
fontSize: '1rem',
borderColor: 'blue',
boxShadow: '0 4px 8px rgba(0,0,0,0.2)',
position: 'relative',
backgroundColor: 'blue',
color: 'white'
}
}
});
`,
options: [
{
groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'],
sortRemainingProperties: 'concentric',
},
],
},
{
code: `
import { style } from '@vanilla-extract/css';
const myStyle = style({
// dimensions group first
width: '10rem',
height: '10rem',
// margin group second
margin: '1rem',
// font group third
fontFamily: 'sans-serif',
// border group fourth
border: '1px solid black',
// boxShadow group fifth
boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
// remaining properties in alphabetical order
backgroundColor: 'red',
color: 'blue',
display: 'flex',
padding: '2rem',
position: 'relative'
});
`,
options: [
{
groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'],
sortRemainingProperties: 'alphabetical',
},
],
},
],
invalid: [
// Style with incorrect custom group ordering
{
code: `
import { style } from '@vanilla-extract/css';
const myStyle = style({
position: 'relative',
border: '1px solid black',
width: '10rem',
color: 'blue',
margin: '1rem',
fontFamily: 'sans-serif',
boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
backgroundColor: 'red'
});
`,
options: [
{
groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'],
sortRemainingProperties: 'concentric',
},
],
errors: [{ messageId: 'incorrectOrder' }],
output: `
import { style } from '@vanilla-extract/css';
const myStyle = style({
width: '10rem',
margin: '1rem',
fontFamily: 'sans-serif',
border: '1px solid black',
boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
position: 'relative',
backgroundColor: 'red',
color: 'blue'
});
`,
},
// Style with nested selectors having incorrect ordering
{
code: `
import { style } from '@vanilla-extract/css';
const myStyle = style({
border: '1px solid black',
width: '10rem',
position: 'relative',
margin: '1rem',
selectors: {
'&:hover': {
color: 'white',
width: '12rem',
border: '2px solid blue',
margin: '1.2rem',
backgroundColor: 'blue'
}
}
});
`,
options: [
{
groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'],
sortRemainingProperties: 'concentric',
},
],
errors: [{ messageId: 'incorrectOrder' }, { messageId: 'incorrectOrder' }],
output: `
import { style } from '@vanilla-extract/css';
const myStyle = style({
width: '10rem',
margin: '1rem',
border: '1px solid black',
position: 'relative',
selectors: {
'&:hover': {
width: '12rem',
margin: '1.2rem',
border: '2px solid blue',
backgroundColor: 'blue',
color: 'white'
}
}
});
`,
},
{
code: `
import { style } from '@vanilla-extract/css';
const myStyle = style({
position: 'relative',
border: '1px solid black',
width: '10rem',
padding: '2rem',
color: 'blue',
margin: '1rem',
display: 'flex',
fontFamily: 'sans-serif',
boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
backgroundColor: 'red'
});
`,
options: [
{
groupOrder: ['dimensions', 'margin', 'font', 'border', 'boxShadow'],
sortRemainingProperties: 'alphabetical',
},
],
errors: [{ messageId: 'incorrectOrder' }],
output: `
import { style } from '@vanilla-extract/css';
const myStyle = style({
width: '10rem',
margin: '1rem',
fontFamily: 'sans-serif',
border: '1px solid black',
boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
backgroundColor: 'red',
color: 'blue',
display: 'flex',
padding: '2rem',
position: 'relative'
});
`,
},
],
});

View file

@ -0,0 +1,187 @@
import tsParser from '@typescript-eslint/parser';
import { run } from 'eslint-vitest-rule-tester';
import customGroupOrderRule from '../rule-definition.js';
run({
name: 'vanilla-extract/custom-order/variants',
rule: customGroupOrderRule,
languageOptions: {
parser: tsParser,
parserOptions: {
ecmaVersion: 2022,
sourceType: 'module',
},
},
valid: [
// styleVariants with custom group ordering (concentric for remaining)
{
code: `
import { styleVariants } from '@vanilla-extract/css';
const variants = styleVariants({
primary: {
margin: '1rem',
padding: '0.5rem',
position: 'relative',
display: 'flex',
backgroundColor: 'blue',
color: 'white'
},
secondary: {
margin: '0.8rem',
padding: '0.4rem',
position: 'relative',
display: 'flex',
backgroundColor: 'gray',
color: 'black'
}
});
`,
options: [
{
groupOrder: ['margin', 'padding', 'dimensions', 'font', 'border', 'boxShadow'],
sortRemainingProperties: 'concentric',
},
],
},
// styleVariants with custom group ordering (alphabetical for remaining)
{
code: `
import { styleVariants } from '@vanilla-extract/css';
const variants = styleVariants({
primary: {
margin: '1rem',
padding: '0.5rem',
backgroundColor: 'blue',
color: 'white',
display: 'flex',
position: 'relative'
},
secondary: {
margin: '0.8rem',
padding: '0.4rem',
backgroundColor: 'gray',
color: 'black',
display: 'flex',
position: 'relative'
}
});
`,
options: [
{
groupOrder: ['margin', 'padding', 'dimensions', 'font', 'border', 'boxShadow'],
sortRemainingProperties: 'alphabetical',
},
],
},
],
invalid: [
// styleVariants with incorrect ordering (concentric for remaining)
{
code: `
import { styleVariants } from '@vanilla-extract/css';
const variants = styleVariants({
primary: {
color: 'white',
backgroundColor: 'blue',
padding: '0.5rem',
margin: '1rem',
display: 'flex',
position: 'relative'
},
secondary: {
color: 'black',
backgroundColor: 'gray',
padding: '0.4rem',
margin: '0.8rem',
display: 'flex',
position: 'relative'
}
});
`,
options: [
{
groupOrder: ['margin', 'padding', 'dimensions', 'font', 'border', 'boxShadow'],
sortRemainingProperties: 'concentric',
},
],
errors: [{ messageId: 'incorrectOrder' }, { messageId: 'incorrectOrder' }],
output: `
import { styleVariants } from '@vanilla-extract/css';
const variants = styleVariants({
primary: {
margin: '1rem',
padding: '0.5rem',
position: 'relative',
display: 'flex',
backgroundColor: 'blue',
color: 'white'
},
secondary: {
margin: '0.8rem',
padding: '0.4rem',
position: 'relative',
display: 'flex',
backgroundColor: 'gray',
color: 'black'
}
});
`,
},
// styleVariants with incorrect ordering (alphabetical for remaining)
{
code: `
import { styleVariants } from '@vanilla-extract/css';
const variants = styleVariants({
primary: {
position: 'relative',
display: 'flex',
margin: '1rem',
padding: '0.5rem',
backgroundColor: 'blue',
color: 'white'
},
secondary: {
color: 'black',
backgroundColor: 'gray',
padding: '0.4rem',
margin: '0.8rem',
display: 'flex',
position: 'relative'
}
});
`,
options: [
{
groupOrder: ['margin', 'padding', 'dimensions', 'font', 'border', 'boxShadow'],
sortRemainingProperties: 'alphabetical',
},
],
errors: [{ messageId: 'incorrectOrder' }, { messageId: 'incorrectOrder' }],
output: `
import { styleVariants } from '@vanilla-extract/css';
const variants = styleVariants({
primary: {
margin: '1rem',
padding: '0.5rem',
backgroundColor: 'blue',
color: 'white',
display: 'flex',
position: 'relative'
},
secondary: {
margin: '0.8rem',
padding: '0.4rem',
backgroundColor: 'gray',
color: 'black',
display: 'flex',
position: 'relative'
}
});
`,
},
],
});