litellm/ui/litellm-dashboard/tests/eslint-rules/no-complex-jsx-arrow.test.ts
ryan-crabbe-berri 67fce87b16
chore(ui): add filename, size, JSX-handler, prefer-const, and antd lint rules (#34341)
* chore(ui): add filename, size, JSX-handler, prefer-const, and antd lint rules

Wires up five error-level ESLint rules on the dashboard, grandfathering every
current offender into eslint-suppressions.json so the gate only bites new code
and ratchets down as files are fixed

- local/filename-pascal-case: new local rule requiring PascalCase .tsx names,
  exempting Next.js reserved files (page, layout, route, ...) and test/spec files
  (239 grandfathered)
- max-lines: 800 lines over src/**, excluding tests, src/data, and generated
  schema.d.ts (20 grandfathered)
- local/no-complex-jsx-arrow: new local rule flagging inline JSX arrow handlers
  with block bodies over two statements; each failure is a small extract-to-named
  -handler refactor (65 grandfathered)
- prefer-const: flipped from off to error (103 grandfathered)
- no-restricted-imports: added antd to the phase-out ban alongside tremor, and
  pointed both messages at shadcn/ui primitives (405 antd import sites grandfathered)

Both new local rules ship with RuleTester coverage

* fix(ui): preserve secondary extensions in filename-pascal-case suggestion

The suggestion text built the rename from only the head segment, so a
multi-dot file like my-component.utils.tsx was told to become
MyComponent.tsx instead of MyComponent.utils.tsx. Rebuild it from the
PascalCased head plus the untouched remaining segments, and add tests
covering multi-dot filenames and the hyphenated Next.js reserved names
(global-error, apple-icon, opengraph-image, twitter-image)
2026-07-22 19:34:35 -07:00

34 lines
1.3 KiB
TypeScript

import { RuleTester } from "eslint";
import rule from "../../scripts/eslint-rules/no-complex-jsx-arrow.mjs";
const ruleTester = new RuleTester({
languageOptions: { ecmaVersion: "latest", sourceType: "module", parserOptions: { ecmaFeatures: { jsx: true } } },
});
ruleTester.run("no-complex-jsx-arrow", rule as never, {
valid: [
"const x = <button onClick={() => doThing()} />;",
"const x = <button onClick={() => { a(); }} />;",
"const x = <button onClick={() => { a(); b(); }} />;",
"const handler = () => { a(); b(); c(); }; const x = <button onClick={handler} />;",
"const run = () => { a(); b(); c(); };",
"foo(() => { a(); b(); c(); });",
"const x = <List renderItem={(i) => i.name} />;",
{ code: "const x = <button onClick={() => { a(); b(); c(); }} />;", options: [{ maxStatements: 3 }] },
],
invalid: [
{
code: "const x = <button onClick={() => { a(); b(); c(); }} />;",
errors: [{ messageId: "tooComplex", data: { count: 3, max: 2 } }],
},
{
code: "const x = <form onSubmit={() => { a(); b(); c(); d(); }} />;",
errors: [{ messageId: "tooComplex", data: { count: 4, max: 2 } }],
},
{
code: "const x = <button onClick={() => { a(); b(); }} />;",
options: [{ maxStatements: 1 }],
errors: [{ messageId: "tooComplex", data: { count: 2, max: 1 } }],
},
],
});