Files
jose/test/unit/declaration_comments.test.ts
2026-07-30 00:37:15 +02:00

147 lines
4.0 KiB
TypeScript

import test from 'ava'
import { execFileSync } from 'node:child_process'
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { fileURLToPath } from 'node:url'
const processor = fileURLToPath(new URL('../../tools/declaration-comments.js', import.meta.url))
test('tools/declaration-comments.js', (t) => {
const cwd = mkdtempSync(join(tmpdir(), 'jose-declaration-comments-'))
const types = join(cwd, 'dist', 'types')
const declaration = join(types, 'example.d.ts')
t.teardown(() => rmSync(cwd, { recursive: true }))
const input = `/**
* Module documentation.
*
* @module
*/
import type { KeyLike } from './types.d.ts'
/**
* First summary.
*
* Extended documentation only needed on the generated documentation page.
*
* > [!WARNING]\\
* > Do not ignore this.
*
* This function is exported from the main module entry point as well as from its subpath export.
*
* @example
*
* \`\`\`ts
* @deprecated This is example code, not a tag.
* \`\`\`
*
* @typeParam T Type parameter documentation.
* @see https://example.com
* @deprecated Use next instead.
* @param value Input value.
* @returns The result.
* @throws When the input is invalid.
*/
export declare function example<T>(value: T): KeyLike
/**
* > [!NOTE]
* > Alerts can precede a summary.
*
* Summary after the alert.
*/
export interface AlertFirst {}
export interface Options {
/**
* Member summary with contractual behavior.
*
* Extended generated documentation.
*
* @see https://example.com/options
*/
option?: boolean
}
/**
* Internal helper summary.
*
* Additional internal documentation.
*
* @internal
*/
export interface InternalHelper {}
`
mkdirSync(types, { recursive: true })
writeFileSync(declaration, input)
const env = { ...process.env }
delete env.NODE_OPTIONS
const output = execFileSync(process.execPath, [processor], { cwd, env, encoding: 'utf8' })
t.is(output, 'rewrote 5 declaration comment(s) for editor hovers\n')
const expected = `import type { KeyLike } from './types.d.ts'
/**
* First summary.
*
* > Warning: Do not ignore this.
*
* @deprecated Use next instead.
* @param value Input value.
* @returns The result.
* @throws When the input is invalid.
*/
export declare function example<T>(value: T): KeyLike
/**
* > Note: Alerts can precede a summary.
*
* Summary after the alert.
*/
export interface AlertFirst {}
export interface Options {
/** Member summary with contractual behavior. */
option?: boolean
}
/** Internal helper summary. */
export interface InternalHelper {}
`
t.is(readFileSync(declaration, 'utf8'), expected)
t.is(
execFileSync(process.execPath, [processor], { cwd, env, encoding: 'utf8' }),
'rewrote 0 declaration comment(s) for editor hovers\n',
)
t.is(readFileSync(declaration, 'utf8'), expected)
writeFileSync(declaration, input)
const privateTypes = join(types, 'lib')
mkdirSync(privateTypes)
writeFileSync(
join(privateTypes, 'private.d.ts'),
`/**
* Private declaration documentation.
*
* @module
*/
export interface PrivateDeclaration {}
`,
)
const report = execFileSync(process.execPath, [processor], {
cwd,
env: { ...env, JOSE_DEBUG_TYPES: '1' },
encoding: 'utf8',
})
t.true(report.startsWith('stripped published declaration documentation\n\n'))
t.true(report.includes('dist/types/example.d.ts:1\n- Module documentation.'))
t.true(
report.includes('- Extended documentation only needed on the generated documentation page.'),
)
t.true(report.includes('- @example'))
t.true(report.includes('- @typeParam T Type parameter documentation.'))
t.true(report.includes('- @see https://example.com'))
t.true(report.includes('- @internal'))
t.false(report.includes('- @deprecated Use next instead.'))
t.false(report.includes('private.d.ts'))
t.true(report.endsWith('rewrote 6 declaration comment(s) for editor hovers\n'))
t.is(readFileSync(declaration, 'utf8'), expected)
})