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('
') },
{
name: "a group heading inside a list: SectionHeader's row, not a column's bar (Ship's issue groups)",
code: component(''),
},
{
name: "a label strip on a card (Peek's huddle card)",
code: component('\nHuddle
\n\n'),
},
{ name: 'a row a person presses is a row, not a header', code: component('') },
{ name: 'a row with no title: a toolbar, a field', code: component('') },
{ name: 'a row with nothing after it heads nothing', code: component('') },
{ name: 'a row with no side padding of its own', code: component('') },
{ name: 'a column of rows', code: component('') },
{
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('')}`,
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
'),
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(''),
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(''),
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(''),
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(''),
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' }],
},
],
})