Skip to main content
Glama

mcp-youtube

by kirbah
getTranscriptsHandler.test.ts13.2 kB
import { getTranscriptsHandler } from "../getTranscripts"; import { TranscriptService } from "../../../services/transcript.service"; // Corrected import import { formatVideoMap } from "../../../utils/responseFormatter"; import type { CallToolResult } from "@modelcontextprotocol/sdk/types"; import { mocked } from "jest-mock"; // Import mocked jest.mock("../../../services/transcript.service"); // Mock TranscriptService describe("getTranscriptsHandler", () => { let mockTranscriptService: jest.Mocked<TranscriptService>; // Renamed mock variable beforeEach(() => { mockTranscriptService = mocked(new TranscriptService(null as any)); // Use mocked mockTranscriptService.getTranscriptSegments = jest.fn(); // Mock the correct method jest.spyOn(console, "error").mockImplementation(() => {}); }); afterEach(() => { if ((console.error as any).mockRestore) { (console.error as any).mockRestore(); } jest.clearAllMocks(); }); it("should successfully return transcript for a single video", async () => { const mockInput = { videoIds: ["testVideoId1"], lang: "en", format: "key_segments", }; const mockTranscript = [{ text: "Hello world", offset: 0, duration: 100 }]; mockTranscriptService.getTranscriptSegments.mockResolvedValue( mockTranscript ); const result = await getTranscriptsHandler( mockInput, mockTranscriptService ); const mapOutput = formatVideoMap(mockInput.videoIds, [mockTranscript]); const expectedResponse = { success: true, content: [{ type: "text", text: JSON.stringify(mapOutput, null, 2) }], }; expect(result).toEqual(expectedResponse); expect(mockTranscriptService.getTranscriptSegments).toHaveBeenCalledWith( "testVideoId1", "en", "key_segments" ); expect(console.error).not.toHaveBeenCalled(); }); it("should successfully return transcripts for multiple videos with the specified lang", async () => { const mockInput = { videoIds: ["testVideoId1", "testVideoId2"], lang: "fr", format: "key_segments", }; const mockTranscript1 = [{ text: "Bonjour", offset: 0, duration: 100 }]; const mockTranscript2 = [{ text: "Salut", offset: 0, duration: 120 }]; mockTranscriptService.getTranscriptSegments .mockResolvedValueOnce(mockTranscript1) .mockResolvedValueOnce(mockTranscript2); const result = await getTranscriptsHandler( mockInput, mockTranscriptService ); const mapOutput = formatVideoMap(mockInput.videoIds, [ mockTranscript1, mockTranscript2, ]); const expectedResponse = { success: true, content: [{ type: "text", text: JSON.stringify(mapOutput, null, 2) }], }; expect(result).toEqual(expectedResponse); expect(mockTranscriptService.getTranscriptSegments).toHaveBeenCalledWith( "testVideoId1", "fr", "key_segments" ); expect(mockTranscriptService.getTranscriptSegments).toHaveBeenCalledWith( "testVideoId2", "fr", "key_segments" ); expect(console.error).not.toHaveBeenCalled(); }); it("should return an error if getTranscriptSegments fails for any video", async () => { const mockInput = { videoIds: ["testVideoId1", "testVideoId2"], lang: "es", format: "key_segments", }; const mockTranscript1 = [{ text: "Hola", offset: 0, duration: 100 }]; const mockError = new Error("Failed to fetch transcript for testVideoId2"); mockTranscriptService.getTranscriptSegments .mockResolvedValueOnce(mockTranscript1) .mockRejectedValueOnce(mockError); const result = await getTranscriptsHandler( mockInput, mockTranscriptService ); expect(result.success).toBe(false); expect(result.error).toBeDefined(); if (result.error) { const errorResult = result.error as CallToolResult["error"]; expect(errorResult.error).toBe("ToolExecutionError"); expect(errorResult.message).toBe( "Failed to fetch transcript for testVideoId2" ); } expect(mockTranscriptService.getTranscriptSegments).toHaveBeenCalledWith( "testVideoId1", "es", "key_segments" ); expect(mockTranscriptService.getTranscriptSegments).toHaveBeenCalledWith( "testVideoId2", "es", "key_segments" ); }); it("should return an empty success response if videoIds array is empty", async () => { const mockInput = { videoIds: [], lang: "en", format: "key_segments", }; const result = await getTranscriptsHandler( mockInput, mockTranscriptService ); const mapOutput = formatVideoMap(mockInput.videoIds, []); const expectedResponse = { success: true, content: [{ type: "text", text: JSON.stringify(mapOutput) }], }; expect(result).toEqual(expectedResponse); expect(mockTranscriptService.getTranscriptSegments).not.toHaveBeenCalled(); expect(console.error).not.toHaveBeenCalled(); }); it('should use default language "en" if lang is not provided in params', async () => { const mockInput = { videoIds: ["testVideoIdNoLang"], format: "key_segments", }; const mockTranscript = [ { text: "Default lang transcript", offset: 0, duration: 150 }, ]; mockTranscriptService.getTranscriptSegments.mockResolvedValue( mockTranscript ); const result = await getTranscriptsHandler( mockInput, mockTranscriptService ); const mapOutput = formatVideoMap(mockInput.videoIds, [mockTranscript]); const expectedResponse = { success: true, content: [{ type: "text", text: JSON.stringify(mapOutput, null, 2) }], }; expect(result).toEqual(expectedResponse); expect(mockTranscriptService.getTranscriptSegments).toHaveBeenCalledWith( "testVideoIdNoLang", "en", "key_segments" ); expect(console.error).not.toHaveBeenCalled(); }); it("should return a Zod validation error if videoIds is not an array", async () => { const mockInput = { videoIds: "not-an-array", lang: "en" } as any; const result = await getTranscriptsHandler( mockInput, mockTranscriptService ); expect(result.success).toBe(false); expect(result.error).toBeDefined(); if (result.error) { const errorResult = result.error as CallToolResult["error"]; expect(errorResult.error).toBe("ToolExecutionError"); const parsedMessage = JSON.parse(errorResult.message); expect(parsedMessage[0].message).toBe("Expected array, received string"); } expect(mockTranscriptService.getTranscriptSegments).not.toHaveBeenCalled(); }); it("should return a Zod validation error if a videoId in videoIds array is not a string", async () => { const mockInput = { videoIds: ["validId", 123], lang: "en" } as any; const result = await getTranscriptsHandler( mockInput, mockTranscriptService ); expect(result.success).toBe(false); expect(result.error).toBeDefined(); if (result.error) { const errorResult = result.error as CallToolResult["error"]; expect(errorResult.error).toBe("ToolExecutionError"); const parsedMessage = JSON.parse(errorResult.message); expect(parsedMessage[0].message).toBe("Expected string, received number"); } expect(mockTranscriptService.getTranscriptSegments).not.toHaveBeenCalled(); }); it("should return a Zod validation error if videoIds array contains a single non-string element", async () => { const mockInput = { videoIds: [123], lang: "en" } as any; const result = await getTranscriptsHandler( mockInput, mockTranscriptService ); expect(result.success).toBe(false); expect(result.error).toBeDefined(); if (result.error) { const errorResult = result.error as CallToolResult["error"]; expect(errorResult.error).toBe("ToolExecutionError"); const parsedMessage = JSON.parse(errorResult.message); expect(parsedMessage[0].message).toBe("Expected string, received number"); } expect(mockTranscriptService.getTranscriptSegments).not.toHaveBeenCalled(); }); it("should return a Zod validation error if lang is not a string (and not undefined)", async () => { const mockInput = { videoIds: ["vid1"], lang: 123 } as any; const result = await getTranscriptsHandler( mockInput, mockTranscriptService ); expect(result.success).toBe(false); expect(result.error).toBeDefined(); if (result.error) { const errorResult = result.error as CallToolResult["error"]; expect(errorResult.error).toBe("ToolExecutionError"); const parsedMessage = JSON.parse(errorResult.message); expect(parsedMessage[0].message).toBe("Expected string, received number"); } expect(mockTranscriptService.getTranscriptSegments).not.toHaveBeenCalled(); }); it('should successfully process requests with longer language codes like "en-US"', async () => { const mockInput = { videoIds: ["testVideoId1"], lang: "en-US", format: "key_segments", }; const mockTranscript = [ { text: "Hello US English", offset: 0, duration: 100 }, ]; mockTranscriptService.getTranscriptSegments.mockResolvedValue( mockTranscript ); const result = await getTranscriptsHandler( mockInput, mockTranscriptService ); expect(result.success).toBe(true); const mapOutput = formatVideoMap(mockInput.videoIds, [mockTranscript]); const expectedResponse = { success: true, content: [{ type: "text", text: JSON.stringify(mapOutput, null, 2) }], }; expect(result).toEqual(expectedResponse); expect(mockTranscriptService.getTranscriptSegments).toHaveBeenCalledWith( mockInput.videoIds[0], "en-US", "key_segments" ); expect(console.error).not.toHaveBeenCalled(); }); it("should return a Zod validation error if videoId in array is an empty string", async () => { const mockInput = { videoIds: [""], lang: "en" } as any; const result = await getTranscriptsHandler( mockInput, mockTranscriptService ); expect(result.success).toBe(false); expect(result.error).toBeDefined(); if (result.error) { const errorResult = result.error as CallToolResult["error"]; if (errorResult.message) { expect(errorResult.error).toBe("ToolExecutionError"); const parsedMessage = JSON.parse(errorResult.message); expect(parsedMessage[0].message).toBe("Video ID cannot be empty"); } else { throw new Error( "Expected error message for empty videoId was not defined." ); } } expect(mockTranscriptService.getTranscriptSegments).not.toHaveBeenCalled(); }); it("should return a Zod validation error if videoId in array is an empty string", async () => { const mockInput = { videoIds: [""], lang: "en" } as any; const result = await getTranscriptsHandler( mockInput, mockTranscriptService ); expect(result.success).toBe(false); expect(result.error).toBeDefined(); if (result.error) { const errorResult = result.error as CallToolResult["error"]; expect(errorResult.error).toBe("ToolExecutionError"); const parsedMessage = JSON.parse(errorResult.message); expect(parsedMessage[0].message).toBe("Video ID cannot be empty"); } expect(mockTranscriptService.getTranscriptSegments).not.toHaveBeenCalled(); }); it("should return a Zod validation error if videoIds array is missing (if schema requires it, e.g. not optional)", async () => { const mockInput = { lang: "en" } as any; const result = await getTranscriptsHandler( mockInput, mockTranscriptService ); expect(result.success).toBe(false); expect(result.error).toBeDefined(); if (result.error) { const errorResult = result.error as CallToolResult["error"]; expect(errorResult.error).toBe("ToolExecutionError"); const parsedMessage = JSON.parse(errorResult.message); expect(parsedMessage[0].message).toBe("Required"); } expect(mockTranscriptService.getTranscriptSegments).not.toHaveBeenCalled(); }); it('should successfully process if lang is undefined (and defaults to "en" in schema)', async () => { const mockInput = { videoIds: ["testVideoIdDefaultLang"] }; const mockTranscript = [ { text: "Transcript with default lang", offset: 0, duration: 180 }, ]; mockTranscriptService.getTranscriptSegments.mockResolvedValue( mockTranscript ); const result = await getTranscriptsHandler( mockInput, mockTranscriptService ); const mapOutput = formatVideoMap(mockInput.videoIds, [mockTranscript]); const expectedResponse = { success: true, content: [{ type: "text", text: JSON.stringify(mapOutput, null, 2) }], }; expect(result).toEqual(expectedResponse); expect(mockTranscriptService.getTranscriptSegments).toHaveBeenCalledWith( "testVideoIdDefaultLang", "en", "key_segments" ); expect(console.error).not.toHaveBeenCalled(); }); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/kirbah/mcp-youtube'

If you have feedback or need assistance with the MCP directory API, please join our Discord server