import fse from 'fs-extra'; import os from 'node:os'; import path from 'node:path'; import { afterAll, beforeAll, describe, expect, it } from 'vitest'; import { convertSphinx } from '../src/sdk/converters/sphinx.js'; import type { SdkReference } from '../src/sdk/types.js'; const indexPage = { current_page_name: 'index', title: 'Example SDK documentation', body: '

Example SDK documentation

Welcome to the example SDK. It does things.

See the Widget docs and the docs site.

Warning

Handle with care.

', }; const widgetsPage = { current_page_name: 'widgets', title: 'widgets module', body: '

widgets module

class widgets.Widget(name)[source]

A widget.

spin(speed=1)

Spins the widget.

', }; const skippedPage = { current_page_name: 'genindex', title: 'Index', body: '

Index

' }; describe('convertSphinx', () => { let dir: string; let reference: SdkReference; beforeAll(async () => { dir = await fse.mkdtemp(path.join(os.tmpdir(), 'sphinx-test-')); await fse.writeJson(path.join(dir, 'index.fjson'), indexPage); await fse.writeJson(path.join(dir, 'widgets.fjson'), widgetsPage); await fse.writeJson(path.join(dir, 'genindex.fjson'), skippedPage); reference = await convertSphinx(dir); }); afterAll(async () => { await fse.remove(dir); }); it('emits one page per content file with slugs from current_page_name', () => { expect(reference.pages.map((page) => page.slug).sort()).toEqual(['index', 'widgets']); }); it('groups guide pages and autodoc module pages separately', () => { expect(reference.groups).toEqual([ { group: 'Getting Started', pages: ['index'] }, { group: 'API Reference', pages: ['widgets'] }, ]); }); it('tags autodoc pages as MODULE', () => { const widgets = reference.pages.find((page) => page.slug === 'widgets'); expect(widgets?.tag).toBe('MODULE'); expect(reference.pages.find((page) => page.slug === 'index')?.tag).toBeUndefined(); }); it('converts signatures to python code blocks with headings', () => { const content = reference.pages.find((page) => page.slug === 'widgets')?.content ?? ''; expect(content).toContain('### Widget'); expect(content).toContain('```python\nclass widgets.Widget(name)\n```'); expect(content).toContain('#### spin()'); expect(content).toContain('```python\nspin(speed=1)\n```'); }); it('strips headerlinks and viewcode links', () => { for (const page of reference.pages) { expect(page.content).not.toContain(''); expect(page.content).not.toContain('[source]'); expect(page.content).not.toContain('_modules'); } }); it('rewrites internal links and keeps external ones', () => { const index = reference.pages.find((page) => page.slug === 'index'); expect(index?.content).toContain('[Widget docs](/widgets)'); expect(index?.content).toContain('https://example.com/docs'); }); it('converts admonitions to callouts and extracts descriptions', () => { const index = reference.pages.find((page) => page.slug === 'index'); expect(index?.content).toContain(''); expect(index?.content).toContain('Handle with care.'); expect(index?.description).toBe('Welcome to the example SDK.'); }); });