import { mkdirSync, mkdtempSync, writeFileSync } from 'node:fs' import { tmpdir } from 'node:os' import { dirname, join } from 'node:path' import { ESLint, RuleTester } from 'eslint' import { parser } from 'typescript-eslint' import { describe, expect, it } from 'vitest' import { copies, looksOf, parseForLooks } from './looks-of' import { noCopiedLook } from './no-copied-look' import estiva from './index' RuleTester.describe = describe RuleTester.it = it RuleTester.itOnly = it.only const tester = new RuleTester({ languageOptions: { parser, parserOptions: { ecmaFeatures: { jsx: true } } }, linterOptions: { reportUnusedDisableDirectives: 'off' }, }) /** * Two small repos on disk: an app, with the package's catalogue installed beside * it (`node_modules/@estiva-app/ui/registry.json`, its `looks`), and a copy of * the package's own layout. The looks are the ones the parts have today. */ const root = mkdtempSync(join(tmpdir(), 'no-copied-look-')) const write = (path: string, text: string) => { mkdirSync(dirname(join(root, path)), { recursive: true }) writeFileSync(join(root, path), text) } const SECTION_LABEL = 'text-h5 leading-3 leaf:font-mono leaf:text-small leaf:uppercase leaf:tracking-widest text-text-secondary' const registry = (entries: { name: string; sourceFile: string; looks: string[] }[]) => JSON.stringify({ schemaVersion: 2, entries }) write('app/package.json', '{ "name": "app" }') write( 'app/node_modules/@estiva-app/ui/registry.json', registry([ { name: 'SectionLabel', sourceFile: 'src/SectionLabel.tsx', looks: [SECTION_LABEL] }, { name: 'Card', sourceFile: 'src/Card.tsx', looks: ['rounded-lg border bg-bg-surface border-border-default'] }, { name: 'Avatar', sourceFile: 'src/Avatar.tsx', looks: ['rounded-full bg-bg-inset text-text-secondary font-medium'] }, ]), ) // The app's own reusable part, and its wrapper of the package's Avatar. write('app/src/components/ui/MetaText.tsx', "export function MetaText({ children }: { children: string }) {\n return {children}\n}\n") write('app/src/components/ui/Avatar.tsx', "import { Avatar as UiAvatar } from '@estiva-app/ui'\nexport function Avatar(props: { name: string }) {\n return \n}\n") write('pkg/package.json', '{ "name": "@estiva-app/ui" }') write('pkg/src/TextInput.tsx', "export function TextInput() {\n return \n}\n") write('app/src/components/ui/looks.ts', "export const WRITING_BOX_CLASSES = 'relative bg-bg-inset border border-border-default rounded-lg p-3 signal:focus-within:border-border-focus signal:focus-within:shadow-focus-ring'\n") write('pkg/src/looks.ts', "export const FIELD_BOX_CLASSES = 'bg-bg-inset border border-border-default hover:border-border-strong focus:border-border-focus rounded-lg'\n") const app = join(root, 'app/src/components/Probe.tsx') const appWrapper = join(root, 'app/src/components/ui/Avatar.tsx') const pkg = join(root, 'pkg/src/Textarea.tsx') const probe = (jsx: string) => `export function Probe() {\n return (\n ${jsx}\n )\n}\n` tester.run('no-copied-look', noCopiedLook, { valid: [ { name: 'placement only: where it sits is everyone’s', filename: app, code: probe('
') }, { name: 'three look words: a text style, not a part', filename: app, code: probe('x') }, { name: 'the part used, not copied', filename: app, code: `import { SectionLabel } from '@estiva-app/ui'\n${probe('Files')}` }, { name: 'a wrapper of the package’s part, named like it (Peek’s Avatar): its own look is the part’s, never a copy', filename: appWrapper, code: "import { Avatar as UiAvatar } from '@estiva-app/ui'\nexport function Avatar() {\n return \n}\n", }, { name: 'a look written once in the package and imported is not a copy', filename: pkg, code: `import { FIELD_BOX_CLASSES } from './looks'\n${probe('