veza/apps/web/src/features/streaming/services/hlsService.test.ts
2025-12-12 21:34:34 -05:00

214 lines
6.3 KiB
TypeScript

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { apiClient } from '@/services/api/client';
import {
getHLSMasterPlaylistURL,
getHLSQualityPlaylistURL,
getHLSSegmentURL,
getHLSStreamInfo,
type HLSStreamInfo,
} from './hlsService';
// Mock apiClient
vi.mock('@/services/api/client', () => ({
apiClient: {
defaults: {
baseURL: 'http://localhost:8080/api/v1',
},
get: vi.fn(),
},
}));
describe('hlsService', () => {
beforeEach(() => {
vi.clearAllMocks();
});
describe('getHLSMasterPlaylistURL', () => {
it('should generate correct master playlist URL', () => {
const trackId = 123;
const url = getHLSMasterPlaylistURL(trackId);
expect(url).toBe(
'http://localhost:8080/api/v1/tracks/123/hls/master.m3u8',
);
});
it('should handle different base URLs', () => {
(apiClient.defaults as any).baseURL = 'https://api.example.com/api/v1';
const url = getHLSMasterPlaylistURL(456);
expect(url).toBe(
'https://api.example.com/api/v1/tracks/456/hls/master.m3u8',
);
});
it('should handle base URL without trailing slash', () => {
(apiClient.defaults as any).baseURL = 'http://localhost:8080/api/v1';
const url = getHLSMasterPlaylistURL(789);
expect(url).toBe(
'http://localhost:8080/api/v1/tracks/789/hls/master.m3u8',
);
});
});
describe('getHLSQualityPlaylistURL', () => {
beforeEach(() => {
(apiClient.defaults as any).baseURL = 'http://localhost:8080/api/v1';
});
it('should generate correct quality playlist URL', () => {
const trackId = 123;
const bitrate = '128k';
const url = getHLSQualityPlaylistURL(trackId, bitrate);
expect(url).toBe(
'http://localhost:8080/api/v1/tracks/123/hls/128k/playlist.m3u8',
);
});
it('should handle different bitrates', () => {
const trackId = 123;
const bitrates = ['128k', '192k', '320k'];
bitrates.forEach((bitrate) => {
const url = getHLSQualityPlaylistURL(trackId, bitrate);
expect(url).toBe(
`http://localhost:8080/api/v1/tracks/123/hls/${bitrate}/playlist.m3u8`,
);
});
});
it('should handle different track IDs', () => {
const bitrate = '192k';
const trackIds = [1, 100, 999];
trackIds.forEach((trackId) => {
const url = getHLSQualityPlaylistURL(trackId, bitrate);
expect(url).toBe(
`http://localhost:8080/api/v1/tracks/${trackId}/hls/${bitrate}/playlist.m3u8`,
);
});
});
});
describe('getHLSSegmentURL', () => {
beforeEach(() => {
(apiClient.defaults as any).baseURL = 'http://localhost:8080/api/v1';
});
it('should generate correct segment URL', () => {
const trackId = 123;
const bitrate = '128k';
const segment = 'segment_000.ts';
const url = getHLSSegmentURL(trackId, bitrate, segment);
expect(url).toBe(
'http://localhost:8080/api/v1/tracks/123/hls/128k/segment_000.ts',
);
});
it('should handle different segment names', () => {
const trackId = 123;
const bitrate = '192k';
const segments = ['segment_000.ts', 'segment_001.ts', 'segment_002.ts'];
segments.forEach((segment) => {
const url = getHLSSegmentURL(trackId, bitrate, segment);
expect(url).toBe(
`http://localhost:8080/api/v1/tracks/123/hls/${bitrate}/${segment}`,
);
});
});
it('should handle different bitrates and segments', () => {
const trackId = 456;
const combinations = [
{ bitrate: '128k', segment: 'segment_000.ts' },
{ bitrate: '192k', segment: 'segment_001.ts' },
{ bitrate: '320k', segment: 'segment_002.ts' },
];
combinations.forEach(({ bitrate, segment }) => {
const url = getHLSSegmentURL(trackId, bitrate, segment);
expect(url).toBe(
`http://localhost:8080/api/v1/tracks/456/hls/${bitrate}/${segment}`,
);
});
});
});
describe('getHLSStreamInfo', () => {
beforeEach(() => {
(apiClient.defaults as any).baseURL = 'http://localhost:8080/api/v1';
});
it('should fetch HLS stream info successfully', async () => {
const trackId = 123;
const mockResponse: HLSStreamInfo = {
trackId: 123,
bitrates: [128, 192, 320],
playlistUrl: 'http://localhost:8080/api/v1/tracks/123/hls/master.m3u8',
};
vi.mocked(apiClient.get).mockResolvedValue({
data: mockResponse,
} as any);
const result = await getHLSStreamInfo(trackId);
expect(apiClient.get).toHaveBeenCalledWith('/tracks/123/hls/info');
expect(result).toEqual(mockResponse);
expect(result.trackId).toBe(123);
expect(result.bitrates).toEqual([128, 192, 320]);
expect(result.playlistUrl).toBe(
'http://localhost:8080/api/v1/tracks/123/hls/master.m3u8',
);
});
it('should handle API errors', async () => {
const trackId = 999;
const error = new Error('Track not found');
vi.mocked(apiClient.get).mockRejectedValue(error);
await expect(getHLSStreamInfo(trackId)).rejects.toThrow(
'Track not found',
);
expect(apiClient.get).toHaveBeenCalledWith('/tracks/999/hls/info');
});
it('should handle different track IDs', async () => {
const trackIds = [1, 100, 999];
for (const trackId of trackIds) {
const mockResponse: HLSStreamInfo = {
trackId,
bitrates: [128, 192],
playlistUrl: `http://localhost:8080/api/v1/tracks/${trackId}/hls/master.m3u8`,
};
vi.mocked(apiClient.get).mockResolvedValueOnce({
data: mockResponse,
} as any);
const result = await getHLSStreamInfo(trackId);
expect(result.trackId).toBe(trackId);
expect(apiClient.get).toHaveBeenCalledWith(
`/tracks/${trackId}/hls/info`,
);
}
});
it('should handle empty bitrates array', async () => {
const trackId = 123;
const mockResponse: HLSStreamInfo = {
trackId: 123,
bitrates: [],
playlistUrl: 'http://localhost:8080/api/v1/tracks/123/hls/master.m3u8',
};
vi.mocked(apiClient.get).mockResolvedValue({
data: mockResponse,
} as any);
const result = await getHLSStreamInfo(trackId);
expect(result.bitrates).toEqual([]);
});
});
});