mirror of
https://github.com/antebudimir/eslint-plugin-vanilla-extract.git
synced 2025-12-31 17:03:32 +00:00
test ✅: add coverage for reference-based visitor creator
This commit is contained in:
parent
d4bac62046
commit
24681ebad9
1 changed files with 616 additions and 0 deletions
|
|
@ -0,0 +1,616 @@
|
|||
import type { Rule } from 'eslint';
|
||||
import tsParser from '@typescript-eslint/parser';
|
||||
import { run } from 'eslint-vitest-rule-tester';
|
||||
import alphabeticalOrderRule from '../../alphabetical-order/rule-definition.js';
|
||||
import concentricOrderRule from '../../concentric-order/rule-definition.js';
|
||||
import { createReferenceBasedNodeVisitors } from '../reference-based-visitor-creator.js';
|
||||
import type { OrderingStrategy } from '../../types.js';
|
||||
|
||||
// Test alphabetical order with reference-based visitor
|
||||
run({
|
||||
name: 'reference-based-visitor/alphabetical',
|
||||
rule: alphabeticalOrderRule,
|
||||
languageOptions: {
|
||||
parser: tsParser,
|
||||
parserOptions: {
|
||||
ecmaVersion: 2022,
|
||||
sourceType: 'module',
|
||||
},
|
||||
},
|
||||
valid: [
|
||||
// fontFace with src first (special fontFace ordering)
|
||||
`
|
||||
import { fontFace } from '@vanilla-extract/css';
|
||||
|
||||
const myFont = fontFace({
|
||||
src: 'url("/fonts/my-font.woff2")',
|
||||
fontFamily: 'MyFont',
|
||||
fontWeight: 'bold'
|
||||
});
|
||||
`,
|
||||
|
||||
// globalFontFace with src first (special fontFace ordering)
|
||||
`
|
||||
import { globalFontFace } from '@vanilla-extract/css';
|
||||
|
||||
globalFontFace('MyFont', {
|
||||
src: 'url("/fonts/my-font.woff2")',
|
||||
fontFamily: 'MyFont',
|
||||
fontWeight: 'bold'
|
||||
});
|
||||
`,
|
||||
|
||||
// style with alphabetical order
|
||||
`
|
||||
import { style } from '@vanilla-extract/css';
|
||||
|
||||
const myStyle = style({
|
||||
backgroundColor: 'blue',
|
||||
color: 'white',
|
||||
margin: '10px'
|
||||
});
|
||||
`,
|
||||
|
||||
// styleVariants with alphabetical order
|
||||
`
|
||||
import { styleVariants } from '@vanilla-extract/css';
|
||||
|
||||
const variants = styleVariants({
|
||||
primary: {
|
||||
backgroundColor: 'blue',
|
||||
color: 'white'
|
||||
},
|
||||
secondary: {
|
||||
backgroundColor: 'red',
|
||||
color: 'white'
|
||||
}
|
||||
});
|
||||
`,
|
||||
|
||||
// keyframes with alphabetical order
|
||||
`
|
||||
import { keyframes } from '@vanilla-extract/css';
|
||||
|
||||
const fadeIn = keyframes({
|
||||
'0%': {
|
||||
opacity: 0,
|
||||
transform: 'scale(0.9)'
|
||||
},
|
||||
'100%': {
|
||||
opacity: 1,
|
||||
transform: 'scale(1)'
|
||||
}
|
||||
});
|
||||
`,
|
||||
|
||||
// globalStyle with alphabetical order
|
||||
`
|
||||
import { globalStyle } from '@vanilla-extract/css';
|
||||
|
||||
globalStyle('.button', {
|
||||
backgroundColor: 'blue',
|
||||
color: 'white',
|
||||
padding: '10px'
|
||||
});
|
||||
`,
|
||||
|
||||
// globalKeyframes with alphabetical order
|
||||
`
|
||||
import { globalKeyframes } from '@vanilla-extract/css';
|
||||
|
||||
globalKeyframes('fadeIn', {
|
||||
'0%': {
|
||||
opacity: 0,
|
||||
transform: 'scale(0.9)'
|
||||
},
|
||||
'100%': {
|
||||
opacity: 1,
|
||||
transform: 'scale(1)'
|
||||
}
|
||||
});
|
||||
`,
|
||||
|
||||
// recipe with alphabetical order
|
||||
`
|
||||
import { recipe } from '@vanilla-extract/recipes';
|
||||
|
||||
const button = recipe({
|
||||
base: {
|
||||
backgroundColor: 'blue',
|
||||
color: 'white'
|
||||
},
|
||||
variants: {
|
||||
size: {
|
||||
small: {
|
||||
fontSize: '12px',
|
||||
padding: '4px'
|
||||
},
|
||||
large: {
|
||||
fontSize: '16px',
|
||||
padding: '8px'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
`,
|
||||
],
|
||||
invalid: [
|
||||
// style with wrong order
|
||||
{
|
||||
code: `
|
||||
import { style } from '@vanilla-extract/css';
|
||||
|
||||
const myStyle = style({
|
||||
margin: '10px',
|
||||
backgroundColor: 'blue'
|
||||
});
|
||||
`,
|
||||
errors: [{ messageId: 'alphabeticalOrder' }],
|
||||
},
|
||||
|
||||
// globalStyle with wrong order
|
||||
{
|
||||
code: `
|
||||
import { globalStyle } from '@vanilla-extract/css';
|
||||
|
||||
globalStyle('.button', {
|
||||
padding: '10px',
|
||||
backgroundColor: 'blue'
|
||||
});
|
||||
`,
|
||||
errors: [{ messageId: 'alphabeticalOrder' }],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
// Test concentric order with reference-based visitor
|
||||
run({
|
||||
name: 'reference-based-visitor/concentric',
|
||||
rule: concentricOrderRule,
|
||||
languageOptions: {
|
||||
parser: tsParser,
|
||||
parserOptions: {
|
||||
ecmaVersion: 2022,
|
||||
sourceType: 'module',
|
||||
},
|
||||
},
|
||||
valid: [
|
||||
// style with concentric order
|
||||
`
|
||||
import { style } from '@vanilla-extract/css';
|
||||
|
||||
const myStyle = style({
|
||||
display: 'flex',
|
||||
backgroundColor: 'blue'
|
||||
});
|
||||
`,
|
||||
],
|
||||
invalid: [
|
||||
// style with wrong concentric order
|
||||
{
|
||||
code: `
|
||||
import { style } from '@vanilla-extract/css';
|
||||
|
||||
const myStyle = style({
|
||||
backgroundColor: 'blue',
|
||||
display: 'flex'
|
||||
});
|
||||
`,
|
||||
errors: [{ messageId: 'incorrectOrder' }],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
// Test edge cases
|
||||
run({
|
||||
name: 'reference-based-visitor/edge-cases',
|
||||
rule: alphabeticalOrderRule,
|
||||
languageOptions: {
|
||||
parser: tsParser,
|
||||
parserOptions: {
|
||||
ecmaVersion: 2022,
|
||||
sourceType: 'module',
|
||||
},
|
||||
},
|
||||
valid: [
|
||||
// fontFace with no arguments
|
||||
`
|
||||
import { fontFace } from '@vanilla-extract/css';
|
||||
|
||||
const myFont = fontFace();
|
||||
`,
|
||||
|
||||
// globalFontFace with only one argument
|
||||
`
|
||||
import { globalFontFace } from '@vanilla-extract/css';
|
||||
|
||||
globalFontFace('MyFont');
|
||||
`,
|
||||
|
||||
// style with no arguments
|
||||
`
|
||||
import { style } from '@vanilla-extract/css';
|
||||
|
||||
const myStyle = style();
|
||||
`,
|
||||
|
||||
// globalStyle with only one argument
|
||||
`
|
||||
import { globalStyle } from '@vanilla-extract/css';
|
||||
|
||||
globalStyle('.button');
|
||||
`,
|
||||
|
||||
// Non-identifier callee (should be ignored)
|
||||
`
|
||||
import { style } from '@vanilla-extract/css';
|
||||
|
||||
const obj = {
|
||||
style: (props) => props
|
||||
};
|
||||
|
||||
obj.style({ margin: '10px', backgroundColor: 'blue' });
|
||||
`,
|
||||
|
||||
// Untracked function (should be ignored)
|
||||
`
|
||||
import { style } from '@vanilla-extract/css';
|
||||
|
||||
function customFunction(props) {
|
||||
return props;
|
||||
}
|
||||
|
||||
customFunction({ margin: '10px', backgroundColor: 'blue' });
|
||||
`,
|
||||
|
||||
// fontFace with correct alphabetical order after src
|
||||
`
|
||||
import { fontFace } from '@vanilla-extract/css';
|
||||
|
||||
const myFont = fontFace({
|
||||
src: 'url("/fonts/my-font.woff2")',
|
||||
fontFamily: 'MyFont',
|
||||
fontWeight: 'bold'
|
||||
});
|
||||
`,
|
||||
|
||||
// globalFontFace with correct alphabetical order after src
|
||||
`
|
||||
import { globalFontFace } from '@vanilla-extract/css';
|
||||
|
||||
globalFontFace('MyFont', {
|
||||
src: 'url("/fonts/my-font.woff2")',
|
||||
fontFamily: 'MyFont',
|
||||
fontWeight: 'bold'
|
||||
});
|
||||
`,
|
||||
],
|
||||
invalid: [
|
||||
// fontFace with wrong order (should report error)
|
||||
{
|
||||
code: `
|
||||
import { fontFace } from '@vanilla-extract/css';
|
||||
|
||||
const myFont = fontFace({
|
||||
fontWeight: 'bold',
|
||||
fontFamily: 'MyFont',
|
||||
src: 'url("/fonts/my-font.woff2")'
|
||||
});
|
||||
`,
|
||||
errors: [{ messageId: 'fontFaceOrder' }],
|
||||
},
|
||||
|
||||
// globalFontFace with wrong order (should report error)
|
||||
{
|
||||
code: `
|
||||
import { globalFontFace } from '@vanilla-extract/css';
|
||||
|
||||
globalFontFace('MyFont', {
|
||||
fontWeight: 'bold',
|
||||
src: 'url("/fonts/my-font.woff2")'
|
||||
});
|
||||
`,
|
||||
errors: [{ messageId: 'fontFaceOrder' }],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
// Test userDefinedGroupOrder strategy with reference-based visitor
|
||||
run({
|
||||
name: 'reference-based-visitor/user-defined-order',
|
||||
rule: {
|
||||
meta: {
|
||||
type: 'suggestion',
|
||||
docs: {
|
||||
description: 'Test user-defined group order',
|
||||
},
|
||||
messages: {
|
||||
incorrectOrder: 'Properties should be ordered according to user-defined groups.',
|
||||
},
|
||||
fixable: 'code',
|
||||
},
|
||||
create(context: Rule.RuleContext) {
|
||||
return createReferenceBasedNodeVisitors(
|
||||
context,
|
||||
'userDefinedGroupOrder',
|
||||
['display', 'position', 'color', 'backgroundColor'],
|
||||
'alphabetical'
|
||||
);
|
||||
},
|
||||
},
|
||||
languageOptions: {
|
||||
parser: tsParser,
|
||||
parserOptions: {
|
||||
ecmaVersion: 2022,
|
||||
sourceType: 'module',
|
||||
},
|
||||
},
|
||||
valid: [
|
||||
// style with correct user-defined order
|
||||
`
|
||||
import { style } from '@vanilla-extract/css';
|
||||
|
||||
const myStyle = style({
|
||||
display: 'flex',
|
||||
color: 'blue'
|
||||
});
|
||||
`,
|
||||
|
||||
// recipe with user-defined order
|
||||
`
|
||||
import { recipe } from '@vanilla-extract/recipes';
|
||||
|
||||
const button = recipe({
|
||||
base: {
|
||||
display: 'flex',
|
||||
color: 'blue'
|
||||
}
|
||||
});
|
||||
`,
|
||||
],
|
||||
invalid: [
|
||||
// style with wrong user-defined order
|
||||
{
|
||||
code: `
|
||||
import { style } from '@vanilla-extract/css';
|
||||
|
||||
const myStyle = style({
|
||||
color: 'blue',
|
||||
display: 'flex'
|
||||
});
|
||||
`,
|
||||
errors: [{ messageId: 'incorrectOrder' }],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
// Test userDefinedGroupOrder with empty array (should fallback to alphabetical)
|
||||
run({
|
||||
name: 'reference-based-visitor/user-defined-order-empty',
|
||||
rule: {
|
||||
meta: {
|
||||
type: 'suggestion',
|
||||
docs: {
|
||||
description: 'Test user-defined group order with empty array',
|
||||
},
|
||||
messages: {
|
||||
alphabeticalOrder: 'Properties should be in alphabetical order.',
|
||||
},
|
||||
fixable: 'code',
|
||||
},
|
||||
create(context: Rule.RuleContext) {
|
||||
return createReferenceBasedNodeVisitors(
|
||||
context,
|
||||
'userDefinedGroupOrder',
|
||||
[],
|
||||
'alphabetical'
|
||||
);
|
||||
},
|
||||
},
|
||||
languageOptions: {
|
||||
parser: tsParser,
|
||||
parserOptions: {
|
||||
ecmaVersion: 2022,
|
||||
sourceType: 'module',
|
||||
},
|
||||
},
|
||||
valid: [
|
||||
// style with alphabetical order (fallback)
|
||||
`
|
||||
import { style } from '@vanilla-extract/css';
|
||||
|
||||
const myStyle = style({
|
||||
backgroundColor: 'blue',
|
||||
color: 'white'
|
||||
});
|
||||
`,
|
||||
],
|
||||
invalid: [
|
||||
// style with wrong alphabetical order
|
||||
{
|
||||
code: `
|
||||
import { style } from '@vanilla-extract/css';
|
||||
|
||||
const myStyle = style({
|
||||
color: 'white',
|
||||
backgroundColor: 'blue'
|
||||
});
|
||||
`,
|
||||
errors: [{ messageId: 'alphabeticalOrder' }],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
// Test default case in ordering strategy
|
||||
run({
|
||||
name: 'reference-based-visitor/default-strategy',
|
||||
rule: {
|
||||
meta: {
|
||||
type: 'suggestion',
|
||||
docs: {
|
||||
description: 'Test default ordering strategy',
|
||||
},
|
||||
messages: {
|
||||
alphabeticalOrder: 'Properties should be in alphabetical order.',
|
||||
},
|
||||
fixable: 'code',
|
||||
},
|
||||
create(context: Rule.RuleContext) {
|
||||
return createReferenceBasedNodeVisitors(
|
||||
context,
|
||||
'unknown' as OrderingStrategy,
|
||||
undefined,
|
||||
undefined
|
||||
);
|
||||
},
|
||||
},
|
||||
languageOptions: {
|
||||
parser: tsParser,
|
||||
parserOptions: {
|
||||
ecmaVersion: 2022,
|
||||
sourceType: 'module',
|
||||
},
|
||||
},
|
||||
valid: [
|
||||
// Should fall back to alphabetical
|
||||
`
|
||||
import { style } from '@vanilla-extract/css';
|
||||
|
||||
const myStyle = style({
|
||||
backgroundColor: 'blue',
|
||||
color: 'white'
|
||||
});
|
||||
`,
|
||||
],
|
||||
invalid: [
|
||||
{
|
||||
code: `
|
||||
import { style } from '@vanilla-extract/css';
|
||||
|
||||
const myStyle = style({
|
||||
color: 'white',
|
||||
backgroundColor: 'blue'
|
||||
});
|
||||
`,
|
||||
errors: [{ messageId: 'alphabeticalOrder' }],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
// Test non-Identifier callee (should be ignored)
|
||||
run({
|
||||
name: 'reference-based-visitor/non-identifier-callee',
|
||||
rule: alphabeticalOrderRule,
|
||||
languageOptions: {
|
||||
parser: tsParser,
|
||||
parserOptions: {
|
||||
ecmaVersion: 2022,
|
||||
sourceType: 'module',
|
||||
},
|
||||
},
|
||||
valid: [
|
||||
// Member expression callee should be ignored
|
||||
`
|
||||
import { style } from '@vanilla-extract/css';
|
||||
|
||||
const obj = {
|
||||
style: (props) => props
|
||||
};
|
||||
|
||||
obj.style({ margin: '10px', backgroundColor: 'blue' });
|
||||
`,
|
||||
],
|
||||
invalid: [],
|
||||
});
|
||||
|
||||
// Test functions with no arguments
|
||||
run({
|
||||
name: 'reference-based-visitor/no-arguments',
|
||||
rule: alphabeticalOrderRule,
|
||||
languageOptions: {
|
||||
parser: tsParser,
|
||||
parserOptions: {
|
||||
ecmaVersion: 2022,
|
||||
sourceType: 'module',
|
||||
},
|
||||
},
|
||||
valid: [
|
||||
// fontFace with no arguments
|
||||
`
|
||||
import { fontFace } from '@vanilla-extract/css';
|
||||
|
||||
const myFont = fontFace();
|
||||
`,
|
||||
|
||||
// globalFontFace with only one argument
|
||||
`
|
||||
import { globalFontFace } from '@vanilla-extract/css';
|
||||
|
||||
globalFontFace('MyFont');
|
||||
`,
|
||||
|
||||
// style with no arguments
|
||||
`
|
||||
import { style } from '@vanilla-extract/css';
|
||||
|
||||
const myStyle = style();
|
||||
`,
|
||||
|
||||
// globalStyle with only one argument
|
||||
`
|
||||
import { globalStyle } from '@vanilla-extract/css';
|
||||
|
||||
globalStyle('.button');
|
||||
`,
|
||||
|
||||
// globalKeyframes with only one argument
|
||||
`
|
||||
import { globalKeyframes } from '@vanilla-extract/css';
|
||||
|
||||
globalKeyframes('fadeIn');
|
||||
`,
|
||||
],
|
||||
invalid: [],
|
||||
});
|
||||
|
||||
// Test concentric order with recipe
|
||||
run({
|
||||
name: 'reference-based-visitor/concentric-recipe',
|
||||
rule: concentricOrderRule,
|
||||
languageOptions: {
|
||||
parser: tsParser,
|
||||
parserOptions: {
|
||||
ecmaVersion: 2022,
|
||||
sourceType: 'module',
|
||||
},
|
||||
},
|
||||
valid: [
|
||||
// recipe with concentric order
|
||||
`
|
||||
import { recipe } from '@vanilla-extract/recipes';
|
||||
|
||||
const button = recipe({
|
||||
base: {
|
||||
display: 'flex',
|
||||
backgroundColor: 'blue'
|
||||
}
|
||||
});
|
||||
`,
|
||||
],
|
||||
invalid: [
|
||||
// recipe with wrong concentric order
|
||||
{
|
||||
code: `
|
||||
import { recipe } from '@vanilla-extract/recipes';
|
||||
|
||||
const button = recipe({
|
||||
base: {
|
||||
backgroundColor: 'blue',
|
||||
display: 'flex'
|
||||
}
|
||||
});
|
||||
`,
|
||||
errors: [{ messageId: 'incorrectOrder' }],
|
||||
},
|
||||
],
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue