import { describe, it, expect } from 'vitest' import { parseChangelog, isVersionNewer } from './useChangelog' describe('parseChangelog', () => { it('parses single version с features section', () => { const raw = `# Release Notes ## [2.14.0](https://example.com/compare/v2.13.0...v2.14.0) (2026-05-12) ### ✨ Features * **webhook:** time-series histogram stats endpoint ([5479142](https://example.com/commit/5479142)) ` const entries = parseChangelog(raw) expect(entries).toHaveLength(1) expect(entries[0].version).toBe('2.14.0') expect(entries[0].date).toBe('2026-05-12') expect(entries[0].compareUrl).toContain('compare/v2.13.0...v2.14.0') expect(entries[0].sections).toHaveLength(1) expect(entries[0].sections[0].emoji).toBe('✨') expect(entries[0].sections[0].title).toBe('Features') expect(entries[0].sections[0].items).toHaveLength(1) expect(entries[0].sections[0].items[0].scope).toBe('webhook') expect(entries[0].sections[0].items[0].description).toBe('time-series histogram stats endpoint') expect(entries[0].sections[0].items[0].commit).toBe('5479142') expect(entries[0].sections[0].items[0].commitUrl).toContain('/commit/5479142') }) it('parses multiple versions newest-first', () => { const raw = `## [2.14.0](url1) (2026-05-12) ### ✨ Features * **a:** first ([abc1234](url2)) ## [2.13.0](url3) (2026-05-11) ### 🐛 Fixes * **b:** second ([def5678](url4)) ` const entries = parseChangelog(raw) expect(entries.map((e) => e.version)).toEqual(['2.14.0', '2.13.0']) }) it('handles section без emoji', () => { const raw = `## [1.0.0](url) (2026-01-01) ### Features * first feature ` const entries = parseChangelog(raw) expect(entries[0].sections[0].emoji).toBeUndefined() expect(entries[0].sections[0].title).toBe('Features') }) it('handles item без scope', () => { const raw = `## [1.0.0](url) (2026-01-01) ### Features * description without scope * another one ([abc1234](url2)) ` const entries = parseChangelog(raw) const items = entries[0].sections[0].items expect(items[0].scope).toBeUndefined() expect(items[0].description).toBe('description without scope') expect(items[1].scope).toBeUndefined() expect(items[1].description).toBe('another one') expect(items[1].commit).toBe('abc1234') }) it('handles empty changelog', () => { expect(parseChangelog('')).toEqual([]) expect(parseChangelog('# Just a title\n\nNo versions yet.')).toEqual([]) }) it('handles version без date', () => { const raw = `## [1.0.0](url) ### Features * foo ` const entries = parseChangelog(raw) expect(entries[0].version).toBe('1.0.0') expect(entries[0].date).toBeUndefined() }) it('handles version с multiple sections', () => { const raw = `## [2.10.0](url) (2026-05-12) ### ✨ Features * **timetravel:** new tab ### 🐛 Fixes * **ux:** friendly errors ` const entries = parseChangelog(raw) expect(entries[0].sections).toHaveLength(2) expect(entries[0].sections[0].title).toBe('Features') expect(entries[0].sections[1].title).toBe('Fixes') }) }) describe('isVersionNewer', () => { it('returns true когда seen is null', () => { expect(isVersionNewer('2.14.0', null)).toBe(true) }) it('compares major.minor.patch correctly', () => { expect(isVersionNewer('2.14.0', '2.13.0')).toBe(true) expect(isVersionNewer('2.14.1', '2.14.0')).toBe(true) expect(isVersionNewer('3.0.0', '2.99.99')).toBe(true) expect(isVersionNewer('2.13.0', '2.14.0')).toBe(false) expect(isVersionNewer('2.14.0', '2.14.0')).toBe(false) }) it('strips v prefix', () => { expect(isVersionNewer('v2.14.0', '2.13.0')).toBe(true) expect(isVersionNewer('2.14.0', 'v2.13.0')).toBe(true) }) it('returns false для unparseable formats (treat as not newer)', () => { expect(isVersionNewer('dev', '2.14.0')).toBe(false) expect(isVersionNewer('2.14.0', 'dev')).toBe(false) expect(isVersionNewer('local', 'unknown')).toBe(false) }) })