openreader/tests/unit/changelog.spec.ts
Richard R 9e09f80067 feat(changelog): add changelog feed support and settings integration
Introduce changelog feed manifest support, including client and shared
utilities for fetching and parsing changelog data. Add a new
Settings modal panel for viewing changelog entries, with version
detection based on the current app version. Expose a configurable
changelog feed URL in both environment variables and admin panel
runtime settings. Update documentation and deployment workflow to
support changelog feed generation and consumption. Include unit tests
for changelog utilities.
2026-05-14 09:45:04 -06:00

93 lines
2.9 KiB
TypeScript

import { expect, test } from '@playwright/test';
import {
findCurrentVersionIndex,
isMutableIndex,
normalizeVersion,
sortManifestEntries,
tagsMatchVersion,
toSafeTagSlug,
type ChangelogManifestEntry,
} from '../../src/lib/shared/changelog';
test.describe('changelog utilities', () => {
test('normalizes version strings with and without v prefix', () => {
expect(normalizeVersion('v2.2.0')).toBe('2.2.0');
expect(normalizeVersion('2.2.0')).toBe('2.2.0');
expect(normalizeVersion(' V2.2.0 ')).toBe('2.2.0');
});
test('matches tag and version reliably', () => {
expect(tagsMatchVersion('v2.2.0', '2.2.0')).toBe(true);
expect(tagsMatchVersion('2.2.0', 'v2.2.0')).toBe(true);
expect(tagsMatchVersion('v2.2.1', '2.2.0')).toBe(false);
});
test('finds the running version index in manifest entries', () => {
const entries: ChangelogManifestEntry[] = [
{
tag_name: 'v2.3.0',
name: 'v2.3.0',
published_at: '2026-05-01T00:00:00.000Z',
html_url: 'https://example.com/1',
prerelease: false,
body_path: 'changelog/releases/v2-3-0.json',
},
{
tag_name: 'v2.2.0',
name: 'v2.2.0',
published_at: '2026-04-01T00:00:00.000Z',
html_url: 'https://example.com/2',
prerelease: false,
body_path: 'changelog/releases/v2-2-0.json',
},
];
expect(findCurrentVersionIndex(entries, '2.2.0')).toBe(1);
expect(findCurrentVersionIndex(entries, 'v2.3.0')).toBe(0);
expect(findCurrentVersionIndex(entries, '1.0.0')).toBe(-1);
});
test('sorts manifest newest first by published_at', () => {
const entries: ChangelogManifestEntry[] = [
{
tag_name: 'v2.1.0',
name: 'v2.1.0',
published_at: '2026-03-01T00:00:00.000Z',
html_url: 'https://example.com/1',
prerelease: false,
body_path: 'changelog/releases/v2-1-0.json',
},
{
tag_name: 'v2.3.0',
name: 'v2.3.0',
published_at: '2026-05-01T00:00:00.000Z',
html_url: 'https://example.com/3',
prerelease: false,
body_path: 'changelog/releases/v2-3-0.json',
},
{
tag_name: 'v2.2.0',
name: 'v2.2.0',
published_at: '2026-04-01T00:00:00.000Z',
html_url: 'https://example.com/2',
prerelease: false,
body_path: 'changelog/releases/v2-2-0.json',
},
];
expect(sortManifestEntries(entries).map((entry) => entry.tag_name)).toEqual(['v2.3.0', 'v2.2.0', 'v2.1.0']);
});
test('treats only newest three entries as mutable by default', () => {
expect(isMutableIndex(0)).toBe(true);
expect(isMutableIndex(1)).toBe(true);
expect(isMutableIndex(2)).toBe(true);
expect(isMutableIndex(3)).toBe(false);
});
test('builds filesystem-safe slugs for release tags', () => {
expect(toSafeTagSlug('v2.2.0')).toBe('v2.2.0');
expect(toSafeTagSlug('v2.2.0+build/meta')).toBe('v2.2.0-build-meta');
});
});