diff --git a/web/scripts/__tests__/static-pages.test.ts b/web/scripts/__tests__/static-pages.test.ts
index e4de2640..c8f0bdd1 100644
--- a/web/scripts/__tests__/static-pages.test.ts
+++ b/web/scripts/__tests__/static-pages.test.ts
@@ -7,7 +7,7 @@ import {
rmSync,
} from 'node:fs';
import { join, resolve } from 'node:path';
-import { generateStaticPages } from '../static-pages';
+import { generateStaticPages, generateAtomFeed } from '../static-pages';
import type { ActivityData } from '../../shared/types';
const TEST_OUT = resolve(__dirname, '__test-output-static-pages__');
@@ -1375,3 +1375,159 @@ describe('generateStaticPages', () => {
}
});
});
+
+describe('generateAtomFeed', () => {
+ it('generates a valid Atom 1.0 envelope', () => {
+ const feed = generateAtomFeed([], '2026-03-04T00:00:00Z');
+ expect(feed).toContain('');
+ expect(feed).toContain('');
+ expect(feed).toContain('Colony Governance Feed');
+ expect(feed).toContain('2026-03-04T00:00:00Z');
+ expect(feed).toContain('');
+ });
+
+ it('includes an entry for each proposal with required Atom fields', () => {
+ const proposals = [
+ {
+ number: 42,
+ title: 'Add dark mode',
+ phase: 'implemented' as const,
+ author: 'hivemoot-builder',
+ createdAt: '2026-02-01T12:00:00Z',
+ commentCount: 3,
+ body: 'Dark mode improves readability.',
+ },
+ ];
+ const feed = generateAtomFeed(proposals, '2026-03-04T00:00:00Z');
+ expect(feed).toContain('');
+ expect(feed).toContain('Add dark mode');
+ expect(feed).toContain('/proposal/42/');
+ expect(feed).toContain('2026-02-01T12:00:00Z');
+ expect(feed).toContain('hivemoot-builder');
+ expect(feed).toContain('');
+ expect(feed).toContain('Dark mode improves readability');
+ });
+
+ it('orders entries newest first', () => {
+ const proposals = [
+ {
+ number: 1,
+ title: 'Old',
+ phase: 'implemented' as const,
+ author: 'a',
+ createdAt: '2026-01-01T00:00:00Z',
+ commentCount: 0,
+ },
+ {
+ number: 2,
+ title: 'New',
+ phase: 'discussion' as const,
+ author: 'b',
+ createdAt: '2026-03-01T00:00:00Z',
+ commentCount: 0,
+ },
+ ];
+ const feed = generateAtomFeed(proposals, '2026-03-04T00:00:00Z');
+ const pos1 = feed.indexOf('/proposal/1/');
+ const pos2 = feed.indexOf('/proposal/2/');
+ // Newer proposal (#2) appears before older (#1)
+ expect(pos2).toBeLessThan(pos1);
+ });
+
+ it('XML-escapes < > & in proposal titles and authors', () => {
+ const proposals = [
+ {
+ number: 7,
+ title: 'Fix