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.
93 lines
2.9 KiB
TypeScript
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');
|
|
});
|
|
});
|