hypertwist/website/scripts/render-public-search-assets-lib.test.mjs
2026-06-30 05:27:38 +00:00

104 lines
3.4 KiB
JavaScript

import fs from 'node:fs'
import os from 'node:os'
import path from 'node:path'
import { describe, expect, it } from 'vitest'
import {
buildPublicRobotsTxt,
buildPublicSearchAssetPlan,
buildPublicSitemapXml,
renderPublicSearchAssets,
} from './render-public-search-assets-lib.mjs'
function createRouteRegistry() {
return [
{ path: '/', crawlable: true },
{ path: '/features', crawlable: true },
{ path: '/login', crawlable: false },
{ path: '/register', crawlable: false },
]
}
function createPolicy() {
return {
baseUrl: 'https://hypertwist.app/',
explicitDisallowPaths: ['/app', '/api/', '/auth', '/health', '/app'],
}
}
describe('buildPublicSearchAssetPlan', () => {
it('derives crawlable routes and crawler disallow rules from shared inputs', () => {
const plan = buildPublicSearchAssetPlan(createRouteRegistry(), createPolicy())
expect(plan.baseUrl).toBe('https://hypertwist.app')
expect(plan.crawlableRoutes.map((route) => route.path)).toEqual(['/', '/features'])
expect(plan.crawlerDisallowPaths).toEqual([
'/app',
'/api/',
'/auth',
'/health',
'/login',
'/register',
])
})
})
describe('buildPublicSitemapXml', () => {
it('renders crawlable routes into sitemap XML', () => {
const xml = buildPublicSitemapXml(createRouteRegistry(), createPolicy())
expect(xml).toContain('<loc>https://hypertwist.app/</loc>')
expect(xml).toContain('<loc>https://hypertwist.app/features</loc>')
expect(xml).not.toContain('/login')
expect(xml).not.toContain('/register')
})
})
describe('buildPublicRobotsTxt', () => {
it('renders the shared protected-route boundary into robots posture', () => {
const robots = buildPublicRobotsTxt(createRouteRegistry(), createPolicy())
expect(robots).toContain('User-agent: *')
expect(robots).toContain('Allow: /')
expect(robots).toContain('Disallow: /app')
expect(robots).toContain('Disallow: /api/')
expect(robots).toContain('Disallow: /auth')
expect(robots).toContain('Disallow: /health')
expect(robots).toContain('Disallow: /login')
expect(robots).toContain('Disallow: /register')
expect(robots).toContain('Sitemap: https://hypertwist.app/sitemap.xml')
})
})
describe('renderPublicSearchAssets', () => {
it('writes both sitemap and robots assets from the same authority inputs', async () => {
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'hypertwist-public-search-assets-'))
const registryPath = path.join(tempRoot, 'public-route-registry.json')
const policyPath = path.join(tempRoot, 'public-search-policy.json')
const sitemapPath = path.join(tempRoot, 'sitemap.xml')
const robotsPath = path.join(tempRoot, 'robots.txt')
fs.writeFileSync(registryPath, JSON.stringify(createRouteRegistry(), null, 2))
fs.writeFileSync(policyPath, JSON.stringify(createPolicy(), null, 2))
const rendered = await renderPublicSearchAssets({
registryPath,
policyPath,
sitemapPath,
robotsPath,
})
expect(rendered.crawlableRoutes).toHaveLength(2)
expect(rendered.crawlerDisallowPaths).toEqual([
'/app',
'/api/',
'/auth',
'/health',
'/login',
'/register',
])
expect(fs.readFileSync(sitemapPath, 'utf8')).toContain('<loc>https://hypertwist.app/features</loc>')
expect(fs.readFileSync(robotsPath, 'utf8')).toContain('Disallow: /health')
})
})