import { RuleTester } from 'eslint' import { parser } from 'typescript-eslint' import { describe, it } from 'vitest' import { noHandmadeHeader } from './no-handmade-header' RuleTester.describe = describe RuleTester.it = it RuleTester.itOnly = it.only const tester = new RuleTester({ languageOptions: { parser, parserOptions: { ecmaFeatures: { jsx: true } } }, linterOptions: { reportUnusedDisableDirectives: 'off' }, }) const component = (body: string) => `export function Probe({ title, open }: { title: string; open: boolean }) {\n return (\n${body}\n )\n}\n` const handmade = [{ messageId: 'handmade' }] tester.run('no-handmade-header', noHandmadeHeader, { valid: [ // 26 September: the package's own parts import the header from their sibling file. { name: 'the header inside the package, from its own file', code: `import { ContainerHeader } from './ContainerHeader'\n${component('')}` }, { name: 'Panel in an app', code: `import { Panel } from '@estiva-app/ui'\n${component('x')}` }, { name: 'the bare header in an app, escaped with its reason', code: `import { ContainerHeader } from '@estiva-app/ui'\n${component('// @estiva-escape(no-handmade-header): a header over a loading skeleton that cannot scroll\n')}` }, { name: 'the part itself', code: component('
\n\n
\n
') }, { name: "a group heading inside a list: SectionHeader's row, not a column's bar (Ship's issue groups)", code: component('
\n

{3}

\n
\n
'), }, { name: "a label strip on a card (Peek's huddle card)", code: component('\n
Huddle
\n
\n'), }, { name: 'a row a person presses is a row, not a header', code: component('
\n
{}}>{title}
\n
\n
') }, { name: 'a row with no title: a toolbar, a field', code: component('
\n
\n
\n
') }, { name: 'a row with nothing after it heads nothing', code: component('
\n
{title}
\n
') }, { name: 'a row with no side padding of its own', code: component('
\n
{title}
\n
\n
') }, { name: 'a column of rows', code: component('
\n
{title}
\n
\n
') }, { name: 'an escape with its reason', code: component('
\n{/* @estiva-escape(no-handmade-header): a print header that must not follow the theme */}\n
{title}
\n
\n
'), }, ], invalid: [ { name: "the package's header on its own in an app: a panel made by hand, naming Panel (26 September)", code: `import { ContainerHeader as Header } from '@estiva-app/ui'\n${component('
\n
\n
{title}
\n
')}`, errors: [{ messageId: 'bare' }], }, { // The Folders page's right pane, at the commit before 3dc663b. name: 'a pane that heads itself around an editable name', code: component('
\n{/* ContainerHeader draws a static title, so this pane heads itself. */}\n
\n
\n} label="Close" />\n
\n
\n
'), errors: handmade, }, { // The Folders page's thread pane, at the commit before 3dc663b. name: 'a pane that heads itself with a title and a caption', code: component('
\n
\n
\n

{title ?? "Conversation"}

\n{open &&

In Ship

}\n
\n
\n
\n
'), errors: handmade, }, { name: "ContainerHeader's exact class list, typed by hand (Peek's FilesPanel and ThreadPanel)", code: component('
\n
\nFiles\n
\n
\n
'), errors: handmade, }, { name: 'the shape, not the class names: other padding, other gap, a heading, a column that grows', code: component(''), errors: handmade, }, { name: "a header bar's height and hairline, whatever the column is", code: component('
\n
{title}
\n
\n
'), errors: handmade, }, { name: 'a bar shown only while something is open', code: component('
\n{open && (\n
{title}
\n)}\n
\n
'), errors: handmade, }, { name: 'classes put together with cn() and a variant', code: component('
\n
{title}
\n
\n
'), errors: handmade, }, { // DialogShell's bar, before it drew ContainerHeader: a part's title, named as one. name: "a bar whose title is a part's Title", code: component('
\n
\n{open ?? }>{title}}\n
\n
\n
'), errors: handmade, }, { name: 'an escape with no reason escapes nothing', code: component('
\n{/* @estiva-escape(no-handmade-header): */}\n
{title}
\n
\n
'), errors: [{ messageId: 'escapeWithoutReason' }, { messageId: 'handmade' }], }, ], })