Files
supabase/apps/docs/internals/internal-links.test.ts
2026-06-22 12:11:55 +02:00

142 lines
4.3 KiB
TypeScript

import { fromMarkdown } from 'mdast-util-from-markdown'
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
import { addBaseUrlPrefix, getInternalLinkBaseUrl, withDocsBasePath } from './internal-links'
describe('withDocsBasePath', () => {
it('prepends /docs to a root-relative href', () => {
expect(withDocsBasePath('/guides/self-hosting/docker')).toBe('/docs/guides/self-hosting/docker')
})
it('prepends /docs to a single-segment href', () => {
expect(withDocsBasePath('/contribute')).toBe('/docs/contribute')
})
it('leaves hrefs that already start with /docs/ alone', () => {
expect(withDocsBasePath('/docs/guides/foo')).toBe('/docs/guides/foo')
})
it('leaves the exact /docs href alone', () => {
expect(withDocsBasePath('/docs')).toBe('/docs')
})
it('does not match prefixes like /docsx that only share leading chars', () => {
expect(withDocsBasePath('/docsx/foo')).toBe('/docs/docsx/foo')
})
it('leaves absolute http(s) URLs alone', () => {
expect(withDocsBasePath('https://example.com/foo')).toBe('https://example.com/foo')
})
it('leaves protocol-relative URLs alone', () => {
expect(withDocsBasePath('//cdn.example.com/foo')).toBe('//cdn.example.com/foo')
})
it('leaves anchor-only hrefs alone', () => {
expect(withDocsBasePath('#section')).toBe('#section')
})
it('leaves mailto: hrefs alone', () => {
expect(withDocsBasePath('mailto:team@example.com')).toBe('mailto:team@example.com')
})
it('leaves relative ./ and ../ hrefs alone', () => {
expect(withDocsBasePath('./sibling')).toBe('./sibling')
expect(withDocsBasePath('../parent')).toBe('../parent')
})
it('preserves query strings and fragments', () => {
expect(withDocsBasePath('/guides/foo?x=1#bar')).toBe('/docs/guides/foo?x=1#bar')
})
})
describe('getInternalLinkBaseUrl', () => {
const ORIGINAL_ENV = process.env
beforeEach(() => {
process.env = { ...ORIGINAL_ENV }
delete process.env.VERCEL_ENV
delete process.env.VERCEL_URL
})
afterEach(() => {
process.env = ORIGINAL_ENV
})
it('returns the production host when VERCEL_ENV=production', () => {
process.env.VERCEL_ENV = 'production'
expect(getInternalLinkBaseUrl()).toBe('https://supabase.com')
})
it('production wins even if VERCEL_URL is also set', () => {
process.env.VERCEL_ENV = 'production'
process.env.VERCEL_URL = 'should-be-ignored.vercel.app'
expect(getInternalLinkBaseUrl()).toBe('https://supabase.com')
})
it('returns the deployment URL when VERCEL_ENV=preview', () => {
process.env.VERCEL_ENV = 'preview'
process.env.VERCEL_URL = 'supabase-com-abc123.vercel.app'
expect(getInternalLinkBaseUrl()).toBe('https://supabase-com-abc123.vercel.app')
})
it('returns empty when preview is set but VERCEL_URL is missing', () => {
process.env.VERCEL_ENV = 'preview'
expect(getInternalLinkBaseUrl()).toBe('')
})
it('returns empty when VERCEL_ENV=development', () => {
process.env.VERCEL_ENV = 'development'
process.env.VERCEL_URL = 'localhost-tunnel.vercel.app'
expect(getInternalLinkBaseUrl()).toBe('')
})
it('returns empty when VERCEL_ENV is not set (local)', () => {
expect(getInternalLinkBaseUrl()).toBe('')
})
})
describe('addBaseUrlPrefix', () => {
const ORIGINAL_ENV = process.env
beforeEach(() => {
process.env = { ...ORIGINAL_ENV, VERCEL_ENV: 'production' }
})
afterEach(() => {
process.env = ORIGINAL_ENV
})
const linkUrls = (markdown: string): string[] => {
const tree = fromMarkdown(markdown)
addBaseUrlPrefix(tree)
const urls: string[] = []
const visit = (n: any) => {
if (n.type === 'link') urls.push(n.url)
if (Array.isArray(n.children)) n.children.forEach(visit)
}
visit(tree)
return urls
}
it('prepends baseUrl to root-relative link URLs', () => {
expect(linkUrls('[home](/foo)')).toEqual(['https://supabase.com/foo'])
})
it('leaves absolute, anchor, and protocol-relative URLs alone', () => {
expect(linkUrls('[a](https://x.com) [b](#h) [c](//cdn/x)')).toEqual([
'https://x.com',
'#h',
'//cdn/x',
])
})
it('does not rewrite image URLs', () => {
expect(linkUrls('![alt](/img.png)')).toEqual([])
})
it('skips links inside fenced code blocks', () => {
expect(linkUrls('```\n[x](/x)\n```\n\n[y](/y)')).toEqual(['https://supabase.com/y'])
})
})