Files
Psychotoxical-psysonic/src/utils/releaseNotes/releaseNotesResolve.test.ts
T
cucadmuh c7d71ea57c feat(whats-new): remote release notes with dev workspace mode (#1058)
* feat(whats-new): remote release notes with dev workspace mode

Add WHATS_NEW.md, CI whats-new.md asset upload, and client fetch/cache
with embedded fallbacks. Dev and -dev builds read the full file from the
repo for debugging; RC/stable download the release asset on first use.

* fix(whats-new): render ## headings and add changelog tab

Parse h2 sections in release-notes markdown; load changelog alongside
highlights and let users switch views on the What's New page.

* fix(whats-new): prefetch on startup and fix CI typecheck prebuild

Prefetch whats-new asset when the shell loads on RC/stable builds.
Run prebuild:release-notes before tsc and coverage jobs so the
gitignored generated bundle exists in CI.

* docs: CHANGELOG and credits for What's New remote notes (PR #1058)

* fix(whats-new): always slice embedded release notes to current line

Drop full CHANGELOG embed for -dev bundles; tauri:dev still reads live
markdown from the repo. Ignore all of src/generated/ in git.

* fix(whats-new): fetch release asset via Rust to bypass CORS

Route whats-new.md download through fetch_url_bytes; rename the
technical tab label; add fetch unit tests (PR #1058 review).
2026-06-10 23:35:23 +03:00

82 lines
2.7 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from 'vitest';
const fetchWhatsNewAsset = vi.fn();
const readReleaseNotesCache = vi.fn();
const writeReleaseNotesCache = vi.fn();
vi.mock('./releaseNotesChannel', () => ({
isDevChannelVersion: (version: string) => /-dev(?:\b|$)/i.test(version.trim()),
isWorkspaceReleaseNotesMode: (version: string) => /-dev(?:\b|$)/i.test(version.trim()),
}));
vi.mock('./releaseNotesFetch', () => ({
fetchWhatsNewAsset: (...args: unknown[]) => fetchWhatsNewAsset(...args),
}));
vi.mock('./releaseNotesCache', () => ({
readReleaseNotesCache: (...args: unknown[]) => readReleaseNotesCache(...args),
writeReleaseNotesCache: (...args: unknown[]) => writeReleaseNotesCache(...args),
}));
vi.mock('../../generated/releaseNotesBundle', () => ({
WHATS_NEW_RAW: `## [1.48.0] - 2026-06-10
## Highlights
- Embedded what's new`,
CHANGELOG_RAW: `## [1.48.0]
## Added
- Embedded changelog fallback`,
}));
const { resolveReleaseNotes } = await import('./releaseNotesResolve');
describe('resolveReleaseNotes (shipped channel)', () => {
beforeEach(() => {
fetchWhatsNewAsset.mockReset();
readReleaseNotesCache.mockReset();
writeReleaseNotesCache.mockReset();
readReleaseNotesCache.mockResolvedValue(null);
fetchWhatsNewAsset.mockResolvedValue(null);
});
it('uses cache before network', async () => {
readReleaseNotesCache.mockResolvedValue('Cached body line');
const r = await resolveReleaseNotes('1.48.0');
expect(r.source).toBe('cache');
expect(r.entry?.body).toContain('Cached body line');
expect(fetchWhatsNewAsset).not.toHaveBeenCalled();
});
it('fetches remote and writes cache when no cache hit', async () => {
fetchWhatsNewAsset.mockResolvedValue('Fresh remote body');
const r = await resolveReleaseNotes('1.48.0-rc.1');
expect(r.source).toBe('remote');
expect(r.entry?.body).toBe('Fresh remote body');
expect(writeReleaseNotesCache).toHaveBeenCalledWith('1.48.0-rc.1', 'Fresh remote body');
});
it('falls back to embedded whats-new when offline', async () => {
const r = await resolveReleaseNotes('1.48.0');
expect(r.source).toBe('embedded-whats-new');
expect(r.entry?.body).toContain("Embedded what's new");
expect(r.entry?.date).toBe('2026-06-10');
});
});
describe('resolveReleaseNotes (workspace)', () => {
beforeEach(() => {
fetchWhatsNewAsset.mockReset();
readReleaseNotesCache.mockReset();
});
it('skips fetch for -dev versions', async () => {
const r = await resolveReleaseNotes('1.48.0-dev');
expect(['workspace', 'workspace-changelog']).toContain(r.source);
expect(fetchWhatsNewAsset).not.toHaveBeenCalled();
expect(r.entry?.body.length).toBeGreaterThan(0);
});
});