Files
ToolsPCastApi-TS/test/unit/PCastApi.test.ts

234 lines
8.6 KiB
TypeScript

import {describe, expect, it, beforeAll, afterAll} from 'bun:test';
import {PCastApi} from '../../src/PCastApi';
import {Channels} from '../../src/apis/Channels';
import {Streams} from '../../src/apis/Stream';
import {Reporting} from '../../src/apis/Reporting/Reporting';
import type {ApplicationCredentials} from '../../src/apis/PCastRequests';
import {mockChannel} from '../mocks/Channel';
import {mockMember} from '../mocks/Member';
describe('PCastApi', () => {
let originalFetch: typeof globalThis.fetch;
const mockCredentials: ApplicationCredentials = {
id: 'test-app-id',
secret: 'test-app-secret'
};
// Set up mock fetch before all tests to handle Channels.initialize()
beforeAll(() => {
originalFetch = globalThis.fetch;
globalThis.fetch = () =>
Promise.resolve({
ok: true,
status: 200,
headers: new Headers({'content-type': 'application/json'}),
json: async () => ({status: 'ok', channels: [], members: []})
} as Response);
});
afterAll(() => {
globalThis.fetch = originalFetch;
});
describe('when creating an instance', () => {
it('should create a PCastApi with the factory method', () => {
const api = PCastApi.create('https://pcast.example.com', mockCredentials);
expect(api).toBeInstanceOf(PCastApi);
});
it('should automatically append /pcast to URI if not present', () => {
const api = PCastApi.create('https://pcast.example.com', mockCredentials);
expect(api).toBeInstanceOf(PCastApi);
});
it('should not duplicate /pcast suffix if already present', () => {
const api = PCastApi.create('https://pcast.example.com/pcast', mockCredentials);
expect(api).toBeInstanceOf(PCastApi);
});
it('should handle URI with trailing slash', () => {
const api = PCastApi.create('https://pcast.example.com/', mockCredentials);
expect(api).toBeInstanceOf(PCastApi);
});
});
describe('when accessing sub-APIs', () => {
it('should expose channels API', () => {
const api = PCastApi.create('https://pcast.example.com', mockCredentials);
expect(api.channels).toBeInstanceOf(Channels);
});
it('should expose streams API', () => {
const api = PCastApi.create('https://pcast.example.com', mockCredentials);
expect(api.streams).toBeInstanceOf(Streams);
});
it('should expose reporting API', () => {
const api = PCastApi.create('https://pcast.example.com', mockCredentials);
expect(api.reporting).toBeInstanceOf(Reporting);
});
it('should return the same channels instance on multiple accesses', () => {
const api = PCastApi.create('https://pcast.example.com', mockCredentials);
expect(api.channels).toBe(api.channels);
});
it('should return the same streams instance on multiple accesses', () => {
const api = PCastApi.create('https://pcast.example.com', mockCredentials);
expect(api.streams).toBe(api.streams);
});
it('should return the same reporting instance on multiple accesses', () => {
const api = PCastApi.create('https://pcast.example.com', mockCredentials);
expect(api.reporting).toBe(api.reporting);
});
});
describe('legacy API methods', () => {
describe('when calling createChannel', () => {
it('should delegate to channels.create', async () => {
globalThis.fetch = () =>
Promise.resolve({
ok: true,
headers: new Headers({'content-type': 'application/json'}),
json: async () => ({status: 'ok', channel: {...mockChannel, name: 'Test Channel'}})
} as Response);
const api = PCastApi.create('https://pcast.example.com', mockCredentials);
const result = await api.createChannel('Test Channel', 'Description', ['opt1']);
expect(result.name).toBe('Test Channel');
});
});
describe('when calling getChannelInfoByAlias', () => {
it('should delegate to channels.get with alias parameter', async () => {
globalThis.fetch = () =>
Promise.resolve({
ok: true,
headers: new Headers({'content-type': 'application/json'}),
json: async () => ({status: 'ok', channels: [{...mockChannel, alias: 'my-alias'}]})
} as Response);
const api = PCastApi.create('https://pcast.example.com', mockCredentials);
const result = await api.getChannelInfoByAlias('my-alias');
expect(result?.alias).toBe('my-alias');
});
});
describe('when calling getChannelInfoByChannelId', () => {
it('should delegate to channels.get with channelId parameter', async () => {
globalThis.fetch = () =>
Promise.resolve({
ok: true,
headers: new Headers({'content-type': 'application/json'}),
json: async () => ({status: 'ok', channels: [{...mockChannel, channelId: 'specific-id'}]})
} as Response);
const api = PCastApi.create('https://pcast.example.com', mockCredentials);
const result = await api.getChannelInfoByChannelId('specific-id');
expect(result?.channelId).toBe('specific-id');
});
});
describe('when calling getChannelPublisherCount', () => {
it('should delegate to channels.getPublisherCount', async () => {
globalThis.fetch = () =>
Promise.resolve({
ok: true,
headers: new Headers({'content-type': 'text/plain'}),
text: async () => '5'
} as Response);
const api = PCastApi.create('https://pcast.example.com', mockCredentials);
const result = await api.getChannelPublisherCount('channel-123');
expect(result).toBe(5);
});
});
describe('when calling getChannelMembers', () => {
it('should delegate to channels.getMembers', async () => {
globalThis.fetch = () =>
Promise.resolve({
ok: true,
headers: new Headers({'content-type': 'application/json'}),
json: async () => ({status: 'ok', members: [{...mockMember, sessionId: 'sess-123'}]})
} as Response);
const api = PCastApi.create('https://pcast.example.com', mockCredentials);
const result = await api.getChannelMembers('channel-123');
expect(result).toHaveLength(1);
expect(result[0].sessionId).toBe('sess-123');
});
});
describe('when calling deleteChannel', () => {
it('should delegate to channels.delete with channelId', async () => {
globalThis.fetch = () =>
Promise.resolve({
ok: true,
headers: new Headers({'content-type': 'application/json'}),
json: async () => ({status: 'ok'})
} as Response);
const api = PCastApi.create('https://pcast.example.com', mockCredentials);
const result = await api.deleteChannel('channel-to-delete');
expect(result.status).toBe('ok');
});
});
describe('when calling generateViewingReport', () => {
it('should delegate to reporting.generateReport with correct parameters', async () => {
globalThis.fetch = () =>
Promise.resolve({
ok: true,
headers: new Headers({'content-type': 'text/plain'}),
text: async () => 'report-id-abc'
} as Response);
const api = PCastApi.create('https://pcast.example.com', mockCredentials);
const startDate = new Date('2024-01-01T00:00:00Z');
const endDate = new Date('2024-01-02T00:00:00Z');
const result = await api.generateViewingReport('RealTime', startDate, endDate, {tags: ['tag1']});
expect(result).toBe('report-id-abc');
});
it('should handle HLS viewing report kind', async () => {
globalThis.fetch = () =>
Promise.resolve({
ok: true,
headers: new Headers({'content-type': 'text/plain'}),
text: async () => 'report-id'
} as Response);
const api = PCastApi.create('https://pcast.example.com', mockCredentials);
const result = await api.generateViewingReport('HLS', new Date('2024-01-01'), new Date('2024-01-02'));
expect(result).toBe('report-id');
});
it('should handle DASH viewing report kind', async () => {
globalThis.fetch = () =>
Promise.resolve({
ok: true,
headers: new Headers({'content-type': 'text/plain'}),
text: async () => 'report-id'
} as Response);
const api = PCastApi.create('https://pcast.example.com', mockCredentials);
const result = await api.generateViewingReport('DASH', new Date('2024-01-01'), new Date('2024-01-02'));
expect(result).toBe('report-id');
});
});
});
});