import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { afterEach, describe, expect, it } from 'vitest'
import {
extractComponent,
extractDeprecation,
parseComponentExports,
} from '../../../scripts/extract-docs-components'
const tempDirs: string[] = []
function createTempDir(): string {
const dir = mkdtempSync(join(tmpdir(), 'mint-docs-components-'))
tempDirs.push(dir)
return dir
}
afterEach(() => {
for (const dir of tempDirs.splice(0)) {
rmSync(dir, { recursive: true, force: true })
}
})
describe('extract docs component helpers', () => {
it('parses grouped Vue component exports with JSDoc metadata', () => {
const dir = createTempDir()
const indexPath = join(dir, 'index.ts')
writeFileSync(indexPath, `
// Base Components
/** Primary action. */
export { default as MintButton } from './Button.vue'
// Scheduling / Booking Components
/**
* @deprecated Prefer ScheduleCalendar.
*/
export { default as OldCalendar } from './OldCalendar.vue'
// Custom Group
export { default as SpecialThing } from './SpecialThing.vue'
`)
expect(parseComponentExports(indexPath)).toEqual([
{
name: 'MintButton',
fileBase: 'Button',
group: 'base',
description: 'Primary action.',
},
{
name: 'OldCalendar',
fileBase: 'OldCalendar',
group: 'scheduling',
description: '@deprecated Prefer ScheduleCalendar.',
deprecated: true,
replacement: 'ScheduleCalendar',
},
{
name: 'SpecialThing',
fileBase: 'SpecialThing',
group: 'custom-group',
},
])
})
it('extracts deprecation replacements from use/prefer prose', () => {
expect(extractDeprecation('@deprecated Use `NewThing()` instead.')).toEqual({
deprecated: true,
replacement: 'NewThing',
})
expect(extractDeprecation('Stable component.')).toEqual({})
})
it('extracts SFC props, emits, and slots from public components', () => {
const dir = createTempDir()
const componentPath = join(dir, 'src', 'components', 'FancyButton.vue')
mkdirSync(join(dir, 'src', 'components'), { recursive: true })
writeFileSync(componentPath, `
`)
expect(extractComponent(componentPath, 'FancyButton', 'base', dir)).toMatchObject({
name: 'FancyButton',
kind: 'component',
group: 'base',
source: 'packages/sdk-frontend/src/components/FancyButton.vue',
description: 'Fancy button docs.',
examples: [
{
title: 'Recommended',
language: 'vue',
code: '',
},
],
props: [
{
name: 'label',
type: 'string',
required: true,
description: 'Visible label.',
},
{
name: 'variant',
type: "'primary' | 'secondary'",
required: false,
default: "'primary'",
description: '',
},
],
emits: [
{ name: 'update:modelValue', type: '(value: string) => void' },
{ name: 'click', type: '() => void' },
],
slots: [
{ name: 'default', description: '' },
{ name: 'suffix', description: '' },
],
})
})
})