Skip to content

Commit 163dd1d

Browse files
committed
perf: update tests for readme routes
1 parent 1ef80c0 commit 163dd1d

File tree

2 files changed

+122
-12
lines changed

2 files changed

+122
-12
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import { describe, expect, it, vi } from 'vitest'
2+
3+
// Mock Nitro globals before importing the module
4+
vi.stubGlobal('defineCachedFunction', (fn: Function) => fn)
5+
const $fetchMock = vi.fn()
6+
vi.stubGlobal('$fetch', $fetchMock)
7+
8+
const { fetchReadmeFromJsdelivr, isStandardReadme } =
9+
await import('../../../../server/utils/readme-loaders')
10+
11+
describe('isStandardReadme', () => {
12+
it('returns true for standard README filenames', () => {
13+
expect(isStandardReadme('README.md')).toBe(true)
14+
expect(isStandardReadme('readme.md')).toBe(true)
15+
expect(isStandardReadme('Readme.md')).toBe(true)
16+
expect(isStandardReadme('README')).toBe(true)
17+
expect(isStandardReadme('readme')).toBe(true)
18+
expect(isStandardReadme('README.markdown')).toBe(true)
19+
expect(isStandardReadme('readme.markdown')).toBe(true)
20+
})
21+
22+
it('returns false for non-standard filenames', () => {
23+
expect(isStandardReadme('CONTRIBUTING.md')).toBe(false)
24+
expect(isStandardReadme('README.txt')).toBe(false)
25+
expect(isStandardReadme('readme.rst')).toBe(false)
26+
expect(isStandardReadme(undefined)).toBe(false)
27+
expect(isStandardReadme('')).toBe(false)
28+
})
29+
})
30+
31+
describe('fetchReadmeFromJsdelivr', () => {
32+
it('returns content when first filename succeeds', async () => {
33+
const content = '# Package'
34+
const fetchMock = vi.fn().mockResolvedValue({
35+
ok: true,
36+
text: async () => content,
37+
})
38+
vi.stubGlobal('fetch', fetchMock)
39+
40+
const result = await fetchReadmeFromJsdelivr('some-pkg', ['README.md'])
41+
42+
expect(result).toBe(content)
43+
expect(fetchMock).toHaveBeenCalledWith('https://cdn.jsdelivr.net/npm/some-pkg/README.md')
44+
})
45+
46+
it('tries next filename when response is not ok', async () => {
47+
const content = '# Fallback'
48+
const fetchMock = vi
49+
.fn()
50+
.mockResolvedValueOnce({ ok: false })
51+
.mockResolvedValueOnce({ ok: true, text: async () => content })
52+
vi.stubGlobal('fetch', fetchMock)
53+
54+
const result = await fetchReadmeFromJsdelivr('pkg', ['README.md', 'readme.md'])
55+
56+
expect(result).toBe(content)
57+
expect(fetchMock).toHaveBeenCalledTimes(2)
58+
})
59+
60+
it('includes version in URL when version is passed', async () => {
61+
const fetchMock = vi.fn().mockResolvedValue({
62+
ok: true,
63+
text: async () => '',
64+
})
65+
vi.stubGlobal('fetch', fetchMock)
66+
67+
await fetchReadmeFromJsdelivr('pkg', ['README.md'], '1.2.3')
68+
69+
expect(fetchMock).toHaveBeenCalledWith('https://cdn.jsdelivr.net/npm/pkg@1.2.3/README.md')
70+
})
71+
72+
it('returns null when all fetches fail', async () => {
73+
const fetchMock = vi.fn().mockResolvedValue({ ok: false })
74+
vi.stubGlobal('fetch', fetchMock)
75+
76+
const result = await fetchReadmeFromJsdelivr('pkg', ['README.md', 'readme.md'])
77+
78+
expect(result).toBeNull()
79+
expect(fetchMock).toHaveBeenCalledTimes(2)
80+
})
81+
})

test/unit/server/utils/readme.spec.ts

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -331,23 +331,52 @@ describe('Markdown File URL Resolution', () => {
331331
})
332332
})
333333

334-
describe('Markdown Content Extraction', () => {
335-
describe('Markdown', () => {
336-
it('returns original markdown content unchanged', async () => {
337-
const markdown = `# Title\n\nSome **bold** text and a [link](https://example.com).`
338-
const result = await renderReadmeHtml(markdown, 'test-pkg')
334+
describe('ReadmeResponse shape (HTML route contract)', () => {
335+
it('returns ReadmeResponse with html, mdExists, playgroundLinks, toc', async () => {
336+
const markdown = `# Title\n\nSome **bold** text.`
337+
const result = await renderReadmeHtml(markdown, 'test-pkg')
338+
339+
expect(result).toMatchObject({
340+
html: expect.any(String),
341+
mdExists: true,
342+
playgroundLinks: [],
343+
toc: expect.any(Array),
344+
})
345+
expect(result.html).toContain('Title')
346+
expect(result.html).toContain('bold')
347+
})
348+
349+
it('returns empty-state shape when content is empty', async () => {
350+
const result = await renderReadmeHtml('', 'test-pkg')
339351

340-
expect(result.md).toBe(markdown)
352+
expect(result).toMatchObject({
353+
html: '',
354+
playgroundLinks: [],
355+
toc: [],
341356
})
357+
expect(result.playgroundLinks).toHaveLength(0)
358+
expect(result.toc).toHaveLength(0)
342359
})
343-
describe('HTML', () => {
344-
it('returns sanitized html', async () => {
345-
const markdown = `# Title\n\nSome **bold** text and a [link](https://example.com).`
346-
const result = await renderReadmeHtml(markdown, 'test-pkg')
347360

348-
expect(result.html).toBe(`<h3 id="user-content-title" data-level="1">Title</h3>
361+
it('extracts toc from headings', async () => {
362+
const markdown = `# Install\n\n## CLI\n\n## API`
363+
const result = await renderReadmeHtml(markdown, 'test-pkg')
364+
365+
expect(result.toc).toHaveLength(3)
366+
expect(result.toc[0]).toMatchObject({ text: 'Install', depth: 1 })
367+
expect(result.toc[1]).toMatchObject({ text: 'CLI', depth: 2 })
368+
expect(result.toc[2]).toMatchObject({ text: 'API', depth: 2 })
369+
expect(result.toc.every(t => t.id.startsWith('user-content-'))).toBe(true)
370+
})
371+
})
372+
373+
describe('HTML output', () => {
374+
it('returns sanitized html', async () => {
375+
const markdown = `# Title\n\nSome **bold** text and a [link](https://example.com).`
376+
const result = await renderReadmeHtml(markdown, 'test-pkg')
377+
378+
expect(result.html).toBe(`<h3 id="user-content-title" data-level="1">Title</h3>
349379
<p>Some <strong>bold</strong> text and a <a href="https://example.com" rel="nofollow noreferrer noopener" target="_blank">link</a>.</p>
350380
`)
351-
})
352381
})
353382
})

0 commit comments

Comments
 (0)