ci / module boundaries / boundaries (push) Successful in 7s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m2s
ci / ts / ts (packages + web) (push) Successful in 3m8s
ci / desktop / rust (desktop proxy) (push) Successful in 4m21s
release / release (версия и заметки) (push) Successful in 6s
release / android (APK в релиз) (push) Successful in 4m0s
release / desktop (Linux и Windows в релиз) (push) Successful in 11m49s
release / prune (старые файлы и прогоны) (push) Successful in 5s
Clean release notes in Android and desktop update dialogs. Persist downloaded audio and offline playback events per server and user; add desktop update checks, checksum verification and installer launch.
31 lines
1.8 KiB
TypeScript
31 lines
1.8 KiB
TypeScript
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
import type { AuthSession, PlayEvent } from '@pipu/core';
|
|
import { desktopEventSink, evictRecent, offlineOwner } from './offline';
|
|
import { createDesktop } from '../../desktop';
|
|
import { albumTracks } from '../../test/fakeApi';
|
|
|
|
afterEach(() => {
|
|
localStorage.clear();
|
|
delete (window as Window & { __TAURI__?: unknown }).__TAURI__;
|
|
});
|
|
|
|
describe('desktop cache policy', () => {
|
|
it('evicts oldest recent files while keeping manual downloads outside the limit', () => {
|
|
const entry = (id: string, used: number, pinned = false) => ({ id, used, pinned, track: albumTracks[0]!, audio: { size: 60 } as Blob });
|
|
expect(evictRecent([entry('new', 3), entry('manual', 0, true), entry('old', 1), entry('middle', 2)], 100)).toEqual(['old', 'middle']);
|
|
});
|
|
});
|
|
|
|
it('persists offline events across sink restarts and deduplicates retries', async () => {
|
|
(window as Window & { __TAURI__?: unknown }).__TAURI__ = { core: { invoke: async () => ({ proxyBase: 'http://local', server: 'https://music.example' }) } };
|
|
await createDesktop();
|
|
const post = vi.fn().mockRejectedValueOnce(new TypeError('offline')).mockResolvedValue({ data: {}, response: new Response('{}') });
|
|
const session = { state: { status: 'signed_in', user: { id: 'alice' } }, client: { POST: post } } as unknown as AuthSession;
|
|
const owner = offlineOwner(session)!;
|
|
const event: PlayEvent = { id: 'one', type: 'play_start', occurred_at: new Date().toISOString(), track_id: 'track' };
|
|
await expect(desktopEventSink(session, owner)([event])).rejects.toThrow('offline');
|
|
await desktopEventSink(session, owner)([event]);
|
|
expect(post.mock.calls[1]?.[1].body.events).toEqual([event]);
|
|
expect(JSON.parse(localStorage.getItem(`pipu.events.${owner}`)!)).toEqual([]);
|
|
});
|