Skip to main content
Glama

docs-mcp-server

CancelJobTool.test.ts5.68 kB
import { beforeEach, describe, expect, it, type Mock, vi } from "vitest"; import type { PipelineManager } from "../pipeline/PipelineManager"; import { type PipelineJob, PipelineJobStatus } from "../pipeline/types"; import { CancelJobTool } from "./CancelJobTool"; import { ToolError } from "./errors"; // Mock dependencies vi.mock("../pipeline/PipelineManager"); vi.mock("../utils/logger"); describe("CancelJobTool", () => { let mockManagerInstance: Partial<PipelineManager>; let cancelJobTool: CancelJobTool; const MOCK_JOB_ID_QUEUED = "job-queued-1"; const MOCK_JOB_ID_RUNNING = "job-running-2"; const MOCK_JOB_ID_COMPLETED = "job-completed-3"; const MOCK_JOB_ID_FAILED = "job-failed-4"; const MOCK_JOB_ID_CANCELLED = "job-cancelled-5"; const MOCK_JOB_ID_NOT_FOUND = "job-not-found-6"; const createMockJob = (id: string, status: PipelineJobStatus): PipelineJob => ({ id, library: "lib-a", version: "1.0.0", status, createdAt: new Date("2023-01-01T10:00:00Z"), progress: null, error: status === PipelineJobStatus.FAILED ? new Error("Job failed") : null, startedAt: status !== PipelineJobStatus.QUEUED ? new Date("2023-01-01T10:05:00Z") : null, finishedAt: status === PipelineJobStatus.COMPLETED || status === PipelineJobStatus.FAILED || status === PipelineJobStatus.CANCELLED ? new Date("2023-01-01T10:15:00Z") : null, sourceUrl: "url1", scraperOptions: null, }); const mockJobsMap = new Map<string, PipelineJob>([ [MOCK_JOB_ID_QUEUED, createMockJob(MOCK_JOB_ID_QUEUED, PipelineJobStatus.QUEUED)], [MOCK_JOB_ID_RUNNING, createMockJob(MOCK_JOB_ID_RUNNING, PipelineJobStatus.RUNNING)], [ MOCK_JOB_ID_COMPLETED, createMockJob(MOCK_JOB_ID_COMPLETED, PipelineJobStatus.COMPLETED), ], [MOCK_JOB_ID_FAILED, createMockJob(MOCK_JOB_ID_FAILED, PipelineJobStatus.FAILED)], [ MOCK_JOB_ID_CANCELLED, createMockJob(MOCK_JOB_ID_CANCELLED, PipelineJobStatus.CANCELLED), ], ]); beforeEach(() => { vi.resetAllMocks(); // Define the mock implementation for the manager instance mockManagerInstance = { getJob: vi.fn().mockImplementation(async (jobId: string) => mockJobsMap.get(jobId)), cancelJob: vi.fn().mockResolvedValue(undefined), // Default success for cancelJob }; // Instantiate the tool with the correctly typed mock instance cancelJobTool = new CancelJobTool(mockManagerInstance as PipelineManager); }); it("should call manager.getJob with the provided jobId", async () => { await cancelJobTool.execute({ jobId: MOCK_JOB_ID_QUEUED }); expect(mockManagerInstance.getJob).toHaveBeenCalledWith(MOCK_JOB_ID_QUEUED); }); it("should throw ToolError if job is not found", async () => { await expect(cancelJobTool.execute({ jobId: MOCK_JOB_ID_NOT_FOUND })).rejects.toThrow( ToolError, ); await expect(cancelJobTool.execute({ jobId: MOCK_JOB_ID_NOT_FOUND })).rejects.toThrow( "not found", ); expect(mockManagerInstance.getJob).toHaveBeenCalledWith(MOCK_JOB_ID_NOT_FOUND); expect(mockManagerInstance.cancelJob).not.toHaveBeenCalled(); }); it.each([ { id: MOCK_JOB_ID_COMPLETED, status: PipelineJobStatus.COMPLETED }, { id: MOCK_JOB_ID_FAILED, status: PipelineJobStatus.FAILED }, { id: MOCK_JOB_ID_CANCELLED, status: PipelineJobStatus.CANCELLED }, ])( "should return success data and not call cancelJob if job is already $status", async ({ id, status }) => { const result = await cancelJobTool.execute({ jobId: id }); expect(mockManagerInstance.getJob).toHaveBeenCalledWith(id); expect(mockManagerInstance.cancelJob).not.toHaveBeenCalled(); expect(result.message).toContain(`already ${status}`); expect(result.finalStatus).toBe(status); }, ); it.each([ { id: MOCK_JOB_ID_QUEUED, status: PipelineJobStatus.QUEUED }, { id: MOCK_JOB_ID_RUNNING, status: PipelineJobStatus.RUNNING }, ])( "should call cancelJob and return success data if job is $status", async ({ id }) => { // Mock getJob to return the job again after cancellation attempt for status check (mockManagerInstance.getJob as Mock) .mockResolvedValueOnce(mockJobsMap.get(id)) // First call finds the job .mockResolvedValueOnce({ ...mockJobsMap.get(id), status: PipelineJobStatus.CANCELLING, }); // Second call shows cancelling status const result = await cancelJobTool.execute({ jobId: id }); expect(mockManagerInstance.getJob).toHaveBeenCalledWith(id); expect(mockManagerInstance.cancelJob).toHaveBeenCalledWith(id); expect(result.message).toContain("Cancellation requested"); expect(result.message).toContain(PipelineJobStatus.CANCELLING); // Check updated status in message expect(result.finalStatus).toBe(PipelineJobStatus.CANCELLING); }, ); it("should throw ToolError if cancelJob throws an error", async () => { const cancelError = new Error("Cancellation failed"); (mockManagerInstance.cancelJob as Mock).mockRejectedValue(cancelError); await expect(cancelJobTool.execute({ jobId: MOCK_JOB_ID_RUNNING })).rejects.toThrow( ToolError, ); await expect(cancelJobTool.execute({ jobId: MOCK_JOB_ID_RUNNING })).rejects.toThrow( "Failed to cancel job", ); await expect(cancelJobTool.execute({ jobId: MOCK_JOB_ID_RUNNING })).rejects.toThrow( cancelError.message, ); expect(mockManagerInstance.getJob).toHaveBeenCalledWith(MOCK_JOB_ID_RUNNING); expect(mockManagerInstance.cancelJob).toHaveBeenCalledWith(MOCK_JOB_ID_RUNNING); }); });

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/arabold/docs-mcp-server'

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