Files
wgenerator/src/app/modules/songs/services/song-download.service.spec.ts
T
2026-06-09 16:31:42 +02:00

77 lines
2.8 KiB
TypeScript

import {TestBed} from '@angular/core/testing';
import {of} from 'rxjs';
import {UserSessionService} from '../../../services/user/user-session.service';
import {User} from '../../../services/user/user';
import {SongDataService} from './song-data.service';
import {SongDownloadService} from './song-download.service';
describe('SongDownloadService', () => {
let service: SongDownloadService;
let songDataServiceSpy: {listLoaded$: ReturnType<typeof vi.fn>};
let sessionSpy: {update$: ReturnType<typeof vi.fn>; user$: unknown};
let createObjectUrlSpy: ReturnType<typeof vi.spyOn>;
let revokeObjectUrlSpy: ReturnType<typeof vi.spyOn>;
let clickSpy: ReturnType<typeof vi.spyOn>;
beforeEach(async () => {
songDataServiceSpy = {
listLoaded$: vi.fn(),
};
sessionSpy = {
update$: vi.fn(),
user$: of({id: 'admin-1', name: 'Admin', role: 'admin', chordMode: 'onlyFirst', songUsage: {}} as User),
};
songDataServiceSpy.listLoaded$.mockReturnValue(
of([
{id: 'song-2', number: 2, title: 'Zweiter Song'},
{id: 'song-1', number: 1, title: 'Erster Song'},
] as never)
);
createObjectUrlSpy = vi.spyOn(window.URL, 'createObjectURL').mockReturnValue('blob:songs');
revokeObjectUrlSpy = vi.spyOn(window.URL, 'revokeObjectURL').mockImplementation(() => undefined);
clickSpy = vi.spyOn(HTMLAnchorElement.prototype, 'click').mockImplementation(() => undefined);
await TestBed.configureTestingModule({
providers: [
{provide: SongDataService, useValue: songDataServiceSpy},
{provide: UserSessionService, useValue: sessionSpy},
],
});
service = TestBed.inject(SongDownloadService);
});
afterEach(() => {
vi.useRealTimers();
vi.restoreAllMocks();
});
it('should download all songs as sorted JSON', async () => {
vi.useFakeTimers();
const result = await service.downloadSongs();
const [blob, fileName] = createObjectUrlSpy.mock.calls.at(-1) as unknown as [Blob, string];
expect(blob.type).toBe('application/json');
expect(fileName).toBeUndefined();
expect(clickSpy).toHaveBeenCalled();
expect(result?.songsDownloaded).toBe(2);
expect(result?.fileName).toMatch(/^songs-\d{4}-\d{2}-\d{2}\.json$/);
const text = await blob.text();
expect(JSON.parse(text).map((song: {id: string}) => song.id)).toEqual(['song-1', 'song-2']);
await vi.advanceTimersByTimeAsync(1000);
expect(revokeObjectUrlSpy).toHaveBeenCalledWith('blob:songs');
});
it('should reject downloads for non-admin users', async () => {
Object.defineProperty(sessionSpy, 'user$', {
value: of({id: 'user-1', name: 'User', role: 'leader', chordMode: 'onlyFirst', songUsage: {}} as User),
});
await expect(service.downloadSongs()).rejects.toThrow('Admin role required to download songs.');
});
});