diff --git a/apps/www/generate-sitemap.test.ts b/apps/www/generate-sitemap.test.ts index 52d39ab6186..7778886cf17 100644 --- a/apps/www/generate-sitemap.test.ts +++ b/apps/www/generate-sitemap.test.ts @@ -10,6 +10,7 @@ import { blogPostingSchema, serializeJsonLd } from './lib/json-ld' const GENERATOR = path.join(process.cwd(), 'internals', 'generate-sitemap.mjs') const LEGACY_LINK = 'https://supabase.com/changelog/12345-legacy-entry' const TIMED_LINK = 'https://supabase.com/changelog/23456-timed-entry' +const TEXT_SLUG_LINK = 'https://supabase.com/changelog/text-slug-entry' const SPAWN_TIMEOUT_MS = 30_000 const createdDirs: string[] = [] @@ -57,7 +58,15 @@ function rssItem(link: string, pubDate: string): string { } function rss(items: string[]): string { - return `\n\n${items.join('\n')}\n\n` + return [ + '', + '', + 'https://supabase.com/changelog', + '', + ...items, + '', + '', + ].join('\n') } function urlEntries(xml: string): UrlEntry[] { @@ -91,8 +100,9 @@ describe('generate-sitemap lastmod', () => { '_events/2026-02-01-webinar.mdx': mdx("date: '2026-02-01T19:00:00.000-07:00'"), 'pages/company.tsx': '', 'public/changelog-rss.xml': rss([ - rssItem(LEGACY_LINK, 'Tue, 03 Feb 2026 00:00:00 +0000'), rssItem(TIMED_LINK, 'Wed, 04 Feb 2026 20:15:00 -0700'), + rssItem(TEXT_SLUG_LINK, 'Thu, 05 Feb 2026 00:00:00 +0000'), + rssItem(LEGACY_LINK, 'Tue, 03 Feb 2026 00:00:00 +0000'), ]), }) result = runGenerator(fixtureDir) @@ -155,9 +165,20 @@ describe('generate-sitemap lastmod', () => { expect(entryFor(TIMED_LINK)?.lastmod).toBe('2026-02-05') }) + it('includes changelog entries whose slug has no numeric prefix', () => { + expect(entryFor(TEXT_SLUG_LINK)?.lastmod).toBe('2026-02-05') + }) + + it('emits exactly the RSS item links as changelog URLs', () => { + const changelogLocs = entries + .filter((entry) => entry.loc.startsWith('https://supabase.com/changelog')) + .map((entry) => entry.loc) + expect(changelogLocs).toEqual([TIMED_LINK, TEXT_SLUG_LINK, LEGACY_LINK]) + }) + it('emits only day-precision lastmod values, one per dated source', () => { const lastmods = entries.map((entry) => entry.lastmod).filter(Boolean) - expect(lastmods).toHaveLength(9) + expect(lastmods).toHaveLength(10) for (const lastmod of lastmods) expect(lastmod).toMatch(/^\d{4}-\d{2}-\d{2}$/) }) @@ -267,6 +288,11 @@ describe('generate-sitemap rejects dates it cannot trust', () => { files: { 'public/changelog-rss.xml': rss([rssItem(LEGACY_LINK, 'Invalid Date +0000')]) }, stderrIncludes: [`changelog-rss ${LEGACY_LINK}`, '"Invalid Date +0000"'], }, + { + name: 'an unparseable changelog pubDate on a text-slug entry', + files: { 'public/changelog-rss.xml': rss([rssItem(TEXT_SLUG_LINK, 'Invalid Date +0000')]) }, + stderrIncludes: [`changelog-rss ${TEXT_SLUG_LINK}`, '"Invalid Date +0000"'], + }, ] for (const testCase of cases) { diff --git a/apps/www/internals/generate-sitemap.mjs b/apps/www/internals/generate-sitemap.mjs index 60f7ecba619..2a879479f1c 100644 --- a/apps/www/internals/generate-sitemap.mjs +++ b/apps/www/internals/generate-sitemap.mjs @@ -180,7 +180,7 @@ async function generate() { const lastmodByUrl = new Map() for (const [, item] of rss.matchAll(/([\s\S]*?)<\/item>/g)) { - const link = item.match(/(https:\/\/supabase\.com\/changelog\/\d+[^<]*)<\/link>/)?.[1] + const link = item.match(/(https:\/\/supabase\.com\/changelog\/[^<]+)<\/link>/)?.[1] if (!link || lastmodByUrl.has(link)) continue const pubDate = item.match(/([^<]*)<\/pubDate>/)?.[1] lastmodByUrl.set(link, pubDate ? changelogLastmod(pubDate, link) : undefined)