import {describe, expect, it, beforeEach, mock} from 'bun:test'; import {Reporting, type PublishingReportOptions, type ViewingReportOptions, type IngestBufferUnderrunOptions} from '../../../../src/apis/Reporting/Reporting'; import {ReportKind} from '../../../../src/apis/Reporting/ReportKind'; import {ViewingReportKind} from '../../../../src/apis/Reporting/ViewingReportKind'; import type {PCastHttpRequests} from '../../../../src/apis/PCastRequests'; import {HttpMethod} from '../../../../src/net/http/HttpMethod'; describe('Reporting', () => { let mockHttpRequests: PCastHttpRequests; let reporting: Reporting; beforeEach(() => { mockHttpRequests = { request: mock(() => Promise.resolve('report-id-123')) } as unknown as PCastHttpRequests; reporting = new Reporting(mockHttpRequests); }); describe('when generating a publishing report', () => { const publishingOptions: PublishingReportOptions = { start: '2024-01-01T00:00:00Z', end: '2024-01-02T00:00:00Z', applicationIds: ['app-123'], channelIds: ['channel-456'] }; it('should send PUT request to publishing endpoint', async () => { await reporting.generateReport(ReportKind.Publishing, publishingOptions); expect(mockHttpRequests.request).toHaveBeenCalledWith( HttpMethod.PUT, '/reporting/publishing', expect.objectContaining({ body: expect.any(String) }) ); }); it('should include all options in the request body', async () => { await reporting.generateReport(ReportKind.Publishing, publishingOptions); const [, , options] = (mockHttpRequests.request as any).mock.calls[0]; const body = JSON.parse(options.body); expect(body.publishingReport.start).toBe('2024-01-01T00:00:00Z'); expect(body.publishingReport.end).toBe('2024-01-02T00:00:00Z'); expect(body.publishingReport.applicationIds).toEqual(['app-123']); expect(body.publishingReport.channelIds).toEqual(['channel-456']); }); it('should return the report ID', async () => { const result = await reporting.generateReport(ReportKind.Publishing, publishingOptions); expect(result).toBe('report-id-123'); }); }); describe('when generating a viewing report', () => { const viewingOptions: ViewingReportOptions = { kind: ViewingReportKind.RealTime, start: '2024-01-01T00:00:00Z', end: '2024-01-02T00:00:00Z', sessionIds: ['session-123'] }; it('should send PUT request to viewing endpoint', async () => { await reporting.generateReport(ReportKind.Viewing, viewingOptions); expect(mockHttpRequests.request).toHaveBeenCalledWith(HttpMethod.PUT, '/reporting/viewing', expect.any(Object)); }); it('should convert ViewingReportKind enum to type string', async () => { await reporting.generateReport(ReportKind.Viewing, viewingOptions); const [, , options] = (mockHttpRequests.request as any).mock.calls[0]; const body = JSON.parse(options.body); expect(body.viewingReport.kind).toBe('RealTime'); }); it('should handle HLS viewing report kind', async () => { const hlsOptions: ViewingReportOptions = { ...viewingOptions, kind: ViewingReportKind.HLS }; await reporting.generateReport(ReportKind.Viewing, hlsOptions); const [, , options] = (mockHttpRequests.request as any).mock.calls[0]; const body = JSON.parse(options.body); expect(body.viewingReport.kind).toBe('HLS'); }); it('should handle DASH viewing report kind', async () => { const dashOptions: ViewingReportOptions = { ...viewingOptions, kind: ViewingReportKind.DASH }; await reporting.generateReport(ReportKind.Viewing, dashOptions); const [, , options] = (mockHttpRequests.request as any).mock.calls[0]; const body = JSON.parse(options.body); expect(body.viewingReport.kind).toBe('DASH'); }); it('should default tags and originTags to empty arrays when not provided', async () => { await reporting.generateReport(ReportKind.Viewing, viewingOptions); const [, , options] = (mockHttpRequests.request as any).mock.calls[0]; const body = JSON.parse(options.body); expect(body.viewingReport.tags).toEqual([]); expect(body.viewingReport.originTags).toEqual([]); }); it('should preserve provided tags and originTags', async () => { const optionsWithTags: ViewingReportOptions = { ...viewingOptions, tags: ['tag1', 'tag2'], originTags: ['origin1'] }; await reporting.generateReport(ReportKind.Viewing, optionsWithTags); const [, , options] = (mockHttpRequests.request as any).mock.calls[0]; const body = JSON.parse(options.body); expect(body.viewingReport.tags).toEqual(['tag1', 'tag2']); expect(body.viewingReport.originTags).toEqual(['origin1']); }); }); describe('when generating an ingest buffer underrun report', () => { const ingestOptions: IngestBufferUnderrunOptions = { kind: 'BufferUnderrun', start: '2024-01-01T00:00:00Z', end: '2024-01-02T00:00:00Z', ingestIds: ['ingest-123'] }; it('should send PUT request to ingest endpoint', async () => { await reporting.generateReport(ReportKind.Ingest, ingestOptions); expect(mockHttpRequests.request).toHaveBeenCalledWith(HttpMethod.PUT, '/reporting/ingest', expect.any(Object)); }); it('should include BufferUnderrun kind in request body', async () => { await reporting.generateReport(ReportKind.Ingest, ingestOptions); const [, , options] = (mockHttpRequests.request as any).mock.calls[0]; const body = JSON.parse(options.body); expect(body.ingestReport.kind).toBe('BufferUnderrun'); }); it('should include ingestIds in request body', async () => { await reporting.generateReport(ReportKind.Ingest, ingestOptions); const [, , options] = (mockHttpRequests.request as any).mock.calls[0]; const body = JSON.parse(options.body); expect(body.ingestReport.ingestIds).toEqual(['ingest-123']); }); }); describe('when calling requestPublishingReport directly', () => { it('should throw error when start date is missing', async () => { const invalidOptions = {end: '2024-01-02T00:00:00Z'} as PublishingReportOptions; await expect(reporting.requestPublishingReport(invalidOptions)).rejects.toThrow('requires a start and end Date'); }); it('should throw error when end date is missing', async () => { const invalidOptions = {start: '2024-01-01T00:00:00Z'} as PublishingReportOptions; await expect(reporting.requestPublishingReport(invalidOptions)).rejects.toThrow('requires a start and end Date'); }); it('should succeed with valid start and end dates', async () => { const validOptions: PublishingReportOptions = { start: '2024-01-01T00:00:00Z', end: '2024-01-02T00:00:00Z' }; const result = await reporting.requestPublishingReport(validOptions); expect(result).toBe('report-id-123'); }); }); });