Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,17 @@ Thank you for helping improve the Hive Commons documentation site

## Before you open a PR

From a fresh checkout, install the exact dependency set and run the same local
validation commands used by CI:
From a fresh checkout, install the exact dependency set and run the local
validation commands that cover the PR gates:

```bash
npm ci
npm run lint
npm run build
npm run lint:md # markdownlint for docs content
npm run type-check # TypeScript without emitting files
npm test # Vitest unit tests
npm run check-links # internal docs links
npm run lint # ESLint for src/
npm run build # production build and doc-sync scripts
```

To preview the docs locally while editing, run:
Expand Down
16 changes: 16 additions & 0 deletions src/__tests__/proxy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,22 @@ describe('proxy', () => {
expect(proxy(request('/zh-TW/docs/readme')).headers.get('location')).toBe('https://docs.hivecommons.dev/docs/readme')
})


it('redirects region-qualified docs locales to canonical docs paths', () => {
const response = proxy(request('/pt-BR/docs/hive/setup'))

expect(response.status).toBe(307)
expect(response.headers.get('location')).toBe('https://docs.hivecommons.dev/docs/hive/setup')
})

it('does not treat three-letter prefixes as localized docs URLs', () => {
const response = proxy(request('/abc/docs/page'))

expect(response.status).toBe(200)
expect(response.headers.get('x-middleware-rewrite')).toBe('https://docs.hivecommons.dev/en/abc/docs/page')
expect(response.headers.get('location')).toBeNull()
})

it('keeps non-doc localized pages in the i18n middleware flow', () => {
const response = proxy(request('/es/community'))

Expand Down
69 changes: 68 additions & 1 deletion src/__tests__/sitemap.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { describe, expect, it } from 'vitest'
import { afterEach, describe, expect, it, vi } from 'vitest'
import fs from 'fs'
import path from 'path'
import sitemap from '../app/sitemap'

const SITE_URL = 'https://docs.hivecommons.dev'
Expand Down Expand Up @@ -39,3 +41,68 @@ describe('sitemap', () => {
expect(urls.some((url) => url.includes('/images/'))).toBe(false)
})
})


describe('sitemap generated from fixture content', () => {
const realCwd = process.cwd()
let fixtureRoot: string | undefined

function write(relPath: string, content = '# stub\n') {
if (!fixtureRoot) throw new Error('fixtureRoot not initialized')
const full = path.join(fixtureRoot, relPath)
fs.mkdirSync(path.dirname(full), { recursive: true })
fs.writeFileSync(full, content)
return full
}

afterEach(() => {
vi.restoreAllMocks()
if (fixtureRoot) {
fs.rmSync(fixtureRoot, { recursive: true, force: true })
fixtureRoot = undefined
}
})

it('maps markdown files to routes, priorities, frequencies, and mtimes', () => {
fixtureRoot = fs.mkdtempSync(path.join(realCwd, '.sitemap-fixture-'))
const setupPath = write('docs/content/hive/guides/setup.md')
write('docs/content/hive/guides/advanced/scaling.mdx')
write('docs/content/pluk/cli/index.md')
vi.spyOn(process, 'cwd').mockReturnValue(fixtureRoot)

const entries = sitemap()
const byUrl = new Map(entries.map((entry) => [entry.url, entry]))

expect(byUrl.get(SITE_URL)?.priority).toBe(1.0)
expect(byUrl.get(`${SITE_URL}/en`)?.changeFrequency).toBe('monthly')
expect(byUrl.get(`${SITE_URL}/docs`)?.priority).toBe(0.9)
expect(byUrl.get(`${SITE_URL}/docs/hive`)?.priority).toBe(0.9)
expect(byUrl.get(`${SITE_URL}/docs/hive/guides/setup`)?.priority).toBe(0.7)
expect(byUrl.get(`${SITE_URL}/docs/hive/guides/setup`)?.changeFrequency).toBe('weekly')
expect(byUrl.get(`${SITE_URL}/docs/hive/guides/setup`)?.lastModified).toEqual(fs.statSync(setupPath).mtime)
expect(byUrl.has(`${SITE_URL}/docs/hive/guides/advanced/scaling`)).toBe(true)
expect(byUrl.has(`${SITE_URL}/docs/pluk/cli`)).toBe(true)
expect(byUrl.has(`${SITE_URL}/docs/pluk/cli/index`)).toBe(false)
})

it('omits generated routes for missing content while retaining project roots', () => {
fixtureRoot = fs.mkdtempSync(path.join(realCwd, '.sitemap-empty-'))
vi.spyOn(process, 'cwd').mockReturnValue(fixtureRoot)

const entries = sitemap()

expect(entries).toHaveLength(10)
expect(entries.map((entry) => entry.url)).toEqual(expect.arrayContaining([
SITE_URL,
`${SITE_URL}/en`,
`${SITE_URL}/docs`,
`${SITE_URL}/docs/hive`,
`${SITE_URL}/docs/hotshot`,
`${SITE_URL}/docs/pluk`,
`${SITE_URL}/docs/rationguard`,
`${SITE_URL}/docs/promptargs`,
`${SITE_URL}/docs/dibs`,
`${SITE_URL}/docs/spektacular`,
]))
})
})
Loading