ReviewOS

also looking at this

stacks/drone

fix: keep documentation search results under docs

#106
Merged chris wants to merge codex/docs-search-base-path into main
5 files +107 -1
tests/unit/docs-search.test.tsadded+39-0
Changes to tests/unit/docs-search.test.ts
@@ -0,0 +1,39 @@
1import { afterAll, beforeAll, describe, expect, it } from 'bun:test'
2import { mkdtemp, mkdir, rm, writeFile } from 'node:fs/promises'
3import { tmpdir } from 'node:os'
4import { join } from 'node:path'
5import { buildSearchIndex } from '@stacksjs/bunpress'
6import type { BunPressConfig } from '@stacksjs/bunpress'
7
8let root: string
9beforeAll(async () => {
10 root = await mkdtemp(join(tmpdir(), 'bunpress-search-base-'))
11 await mkdir(join(root, 'docs'))
12 await writeFile(join(root, 'index.md'), '# Home\n\nStart here.\n')
13 await writeFile(join(root, 'guide.md'), '# Guide\n\nLead.\n\n## Details\n\nDetails.\n')
14 await writeFile(join(root, 'docs/repeat.md'), '# Repeat\n\nA real nested docs directory.\n')
15})
16afterAll(async () => { if (root) await rm(root, { recursive: true, force: true }) })
17
18describe('search result deployment paths', () => {
19 const urls = async (config: Partial<BunPressConfig>) => (await buildSearchIndex(root, { verbose: false, ...config } as BunPressConfig)).map(record => record.url)
20 it('keeps page, home and anchored results under an explicit base path', async () => {
21 expect(await urls({ basePath: '/docs' })).toEqual(['/docs/docs/repeat', '/docs/guide', '/docs/guide#details', '/docs/'])
22 })
23 it('normalizes a nested deployment path using the renderer contract', async () => {
24 expect(await urls({ basePath: ' manual/reference/// ' })).toEqual(['/manual/reference/docs/repeat', '/manual/reference/guide', '/manual/reference/guide#details', '/manual/reference/'])
25 })
26 it('uses the configured site URL path when no explicit base path exists', async () => {
27 expect(await urls({ sitemap: { baseUrl: 'https://example.test/help/docs/' } })).toEqual(['/help/docs/docs/repeat', '/help/docs/guide', '/help/docs/guide#details', '/help/docs/'])
28 })
29 it('prefixes locale fallback only after translation selection', async () => {
30 const index = await buildSearchIndex(root, { verbose: false, basePath: '/docs', i18n: { locales: ['en', 'es'], defaultLocale: 'en' } } as BunPressConfig)
31 expect(index.filter(record => record.locale === 'en').map(record => record.url)).toEqual(['/docs/docs/repeat', '/docs/guide', '/docs/guide#details', '/docs/'])
32 expect(index.filter(record => record.locale === 'es').map(record => record.url)).toEqual(['/docs/es/docs/repeat', '/docs/es/guide', '/docs/es/guide#details', '/docs/es'])
33 })
34 it('preserves root deployments and an explicit root override', async () => {
35 const expected = ['/docs/repeat', '/guide', '/guide#details', '/']
36 expect(await urls({})).toEqual(expected)
37 expect(await urls({ basePath: '/', sitemap: { baseUrl: 'https://example.test/help' } })).toEqual(expected)
38 })
39})