/** * Tests for: consistent-dark-mode * * Ensures consistent dark mode theming in Tailwind CSS classes. */ import { RuleTester } from "@typescript-eslint/rule-tester"; import { describe, it, afterAll } from "vitest"; import rule from "./consistent-dark-mode.js"; RuleTester.afterAll = afterAll; RuleTester.describe = describe; RuleTester.it = it; const ruleTester = new RuleTester({ languageOptions: { ecmaVersion: 2022, sourceType: "module", parserOptions: { ecmaFeatures: { jsx: true }, }, }, }); ruleTester.run("consistent-dark-mode", rule, { valid: [ // ============================================ // CONSISTENT DARK MODE (all colors themed) // ============================================ { name: "all background colors have dark variants", code: `
`, }, { name: "all text colors have dark variants", code: `
`, }, { name: "all border colors have dark variants", code: `
`, }, { name: "multiple color types all with dark variants", code: `
`, }, { name: "gradient colors all with dark variants", code: `
`, }, { name: "ring colors with dark variants", code: `
`, }, { name: "ring and ring-offset are independent - only ring themed is valid", code: `
`, }, { name: "ring and ring-offset are independent - only ring-offset themed is valid", code: `
`, }, // ============================================ // NO COLOR CLASSES (nothing to check) // ============================================ { name: "no color classes - layout only", code: `
`, }, { name: "no color classes - sizing only", code: `
`, }, { name: "no color classes - typography without color", code: `
`, }, { name: "empty className", code: `
`, }, { name: "whitespace only className", code: `
`, }, // ============================================ // EXEMPT VALUES (don't need dark variants) // ============================================ { name: "transparent background is exempt", code: `
`, }, { name: "inherit text color is exempt", code: `
`, }, { name: "current border color is exempt", code: `
`, }, { name: "multiple exempt values", code: `
`, }, { name: "exempt mixed with properly themed colors", code: `
`, }, { name: "shadow-none is exempt", code: `
`, }, // ============================================ // ONLY DARK VARIANTS (edge case - valid) // ============================================ { name: "only dark variant colors", code: `
`, }, // ============================================ // COMPLEX VARIANT CHAINS // ============================================ { name: "hover:dark: variant chain", code: `
`, }, { name: "responsive dark variants", code: `
`, }, { name: "focus and dark variants", code: `
`, }, { name: "complex variant chain with dark", code: `
`, }, // ============================================ // cn() / clsx() / classnames() CALLS - VALID // ============================================ { name: "cn() with consistent dark mode", code: `cn("bg-white dark:bg-slate-900 text-gray-900 dark:text-white")`, }, { name: "clsx() with consistent dark mode", code: `clsx("border-gray-200 dark:border-gray-700")`, }, { name: "classnames() with consistent dark mode", code: `classnames("bg-blue-500 dark:bg-blue-400")`, }, { name: "cva() with consistent dark mode", code: `cva("bg-white dark:bg-black text-gray-900 dark:text-gray-100")`, }, { name: "twMerge() with consistent dark mode", code: `twMerge("bg-red-500 dark:bg-red-400")`, }, { name: "cn() with no color classes", code: `cn("flex items-center gap-4")`, }, { name: "cn() with array of consistent classes", code: `cn(["bg-white dark:bg-black", "text-gray-900 dark:text-white"])`, }, // ============================================ // TEMPLATE LITERALS - VALID // ============================================ { name: "template literal with consistent dark mode", code: "
", }, { name: "cn() with template literal - consistent", code: "cn(`bg-blue-500 dark:bg-blue-400 text-white dark:text-gray-100`)", }, // ============================================ // JSX EXPRESSION CONTAINERS - VALID // ============================================ { name: "JSX expression with string literal - consistent", code: `
`, }, // ============================================ // DIFFERENT BORDER VARIANTS (grouped correctly) // ============================================ { name: "different border sides all themed", code: `
`, }, // ============================================ // MISC VALID CASES // ============================================ { name: "class attribute (not className)", code: `
`, }, { name: "placeholder color with dark variant", code: ``, }, { name: "divide color with dark variant", code: `
`, }, { name: "accent color with dark variant", code: ``, }, { name: "caret color with dark variant", code: ``, }, { name: "outline color with dark variant", code: `