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
2 changes: 2 additions & 0 deletions .Jules/vantage.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@
## 2026-05-15 - Standardizing Telemetry Resilience and Verifying Infrastructure Mocks | **Learning:** Telemetry must capture the full context of unknown errors via `String(e)` to avoid masking failure signals, and re-exporting mocks requires explicit execution to register in coverage reports. | **Action:** Updated `src/utils/github-releases.ts` to use `String(error)` in catch blocks and added an `exerciseMock` helper to `src/__tests__/mocks/astro-zod.ts` to achieve 100% coverage.

## 2026-05-20 - Hardening Telemetry Verification and Refining Stream Types | **Learning:** Index-based assertions in telemetry tests are brittle; using `.find()` ensures robust verification. Standardizing on `String(error)` across all API catch blocks prevents context loss during failure events. | **Action:** Refactored `chat-api.test.ts` and `github-releases.test.ts` to use search-based spy assertions, and added explicit return types to `chat-stream.ts` to resolve Astro compiler hints.

## 2026-05-24 - Comprehensive Unit Testing for Visitor Changelog Formatting | **Learning:** Single-pass Edge transformations require dedicated unit tests covering edge cases like empty inputs, internal agent filtering, and fallback formatting to prevent silent regressions in SSR release streams. | **Action:** Added `src/utils/visitor-changelog.test.ts` to test `toVisitorChangelogTitle`, `stripChangelogChrome`, `toVisitorReleaseBody`, and `toVisitorRelease`.
118 changes: 118 additions & 0 deletions src/utils/visitor-changelog.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { describe, expect, it } from 'vitest';

import {
stripChangelogChrome,
toVisitorChangelogTitle,
toVisitorRelease,
toVisitorReleaseBody,
} from './visitor-changelog';

describe('visitor-changelog utilities', () => {
describe('stripChangelogChrome', () => {
it('handles empty and whitespace-only strings', () => {
expect(stripChangelogChrome('')).toBe('');
expect(stripChangelogChrome(' ')).toBe('');
});

it('strips commit SHA, conventional commit prefix, and PR suffix', () => {
expect(stripChangelogChrome('a1b2c3d feat(ui): add new button (#123)')).toBe(
'add new button'
);
expect(stripChangelogChrome('fix: resolve alignment issue (#456)')).toBe(
'resolve alignment issue'
);
expect(stripChangelogChrome('chore(deps): update packages')).toBe('update packages');
});

it('collapses multiple whitespace characters', () => {
expect(stripChangelogChrome('feat: multiple spaces ')).toBe('multiple spaces');
});
});

describe('toVisitorChangelogTitle', () => {
it('returns empty string for empty input', () => {
expect(toVisitorChangelogTitle('')).toBe('');
expect(toVisitorChangelogTitle(' ')).toBe('');
});

it('looks up known PR numbers', () => {
expect(toVisitorChangelogTitle('feat: add a live RSS feed (#520)')).toBe(
'RSS feed of the work'
);
});

it('looks up known subjects when PR number is omitted', () => {
expect(toVisitorChangelogTitle('add a live RSS feed for the work')).toBe(
'RSS feed of the work'
);
});

it('formats unknown commits by stripping chrome and capitalizing the first letter', () => {
expect(
toVisitorChangelogTitle('f1a2b3c feat(nav): improve keyboard accessibility (#999)')
).toBe('Improve keyboard accessibility');
});

it('returns already clean visitor titles as-is', () => {
expect(toVisitorChangelogTitle('Clean visitor title without chrome')).toBe(
'Clean visitor title without chrome'
);
});

it('falls back gracefully when chrome stripping leaves an empty subject', () => {
expect(toVisitorChangelogTitle('a1b2c3d feat:')).toBe('Feat:');
});
});

describe('toVisitorReleaseBody', () => {
it('returns empty string for empty body', () => {
expect(toVisitorReleaseBody('')).toBe('');
expect(toVisitorReleaseBody(' ')).toBe('');
});

it('converts bullet point lines into visitor titles', () => {
const input =
'- 520 feat: add a live RSS feed for the work (#520)\n* 518 feat: add a working web app manifest (#518)';
const output = toVisitorReleaseBody(input);
expect(output).toBe('- RSS feed of the work\n- Web app manifest');
});

it('filters out internal agent or tool items from bullet lists', () => {
const input =
'- feat: add public feature\n- chore(jules): internal sync\n- refactor(engine): internal logic';
const output = toVisitorReleaseBody(input);
expect(output).toBe('- Add public feature');
});

it('falls back to toVisitorChangelogTitle if body contains no bullet items', () => {
const input = 'a1b2c3d feat: add a live RSS feed for the work (#520)';
expect(toVisitorReleaseBody(input)).toBe('RSS feed of the work');
});

it('falls back to toVisitorChangelogTitle if all bullet items are filtered as internal', () => {
const input = '- chore(jules): internal update\n- refactor(engine): backend tweak';
expect(toVisitorReleaseBody(input)).toBe(
'- chore(jules): internal update\n- refactor(engine): backend tweak'
);
});
});

describe('toVisitorRelease', () => {
it('transforms the release body while preserving other release properties', () => {
const release = {
version: 'v1.0.0',
publishedAt: '2026-05-01T12:00:00Z',
url: 'https://example.com/release/v1.0.0',
body: '- 520 feat: add a live RSS feed for the work (#520)',
};

const result = toVisitorRelease(release);
expect(result).toEqual({
version: 'v1.0.0',
publishedAt: '2026-05-01T12:00:00Z',
url: 'https://example.com/release/v1.0.0',
body: '- RSS feed of the work',
});
});
});
});
Loading