Skip to main content
Glama

JIRA MCP Server

worklog-api.integration.test.ts9.22 kB
/** * Worklog API Integration Tests * * Tests complete worklog workflows from handlers through use cases to repositories */ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { AddWorklogHandler } from "@features/jira/issues/handlers/add-worklog.handler"; import { DeleteWorklogHandler } from "@features/jira/issues/handlers/delete-worklog.handler"; import { GetWorklogsHandler } from "@features/jira/issues/handlers/get-worklogs.handler"; import { UpdateWorklogHandler } from "@features/jira/issues/handlers/update-worklog.handler"; import { AddWorklogUseCaseImpl, DeleteWorklogUseCaseImpl, GetWorklogsUseCaseImpl, UpdateWorklogUseCaseImpl, } from "@features/jira/issues/use-cases/worklog.use-cases"; import { WorklogValidatorImpl } from "@features/jira/issues/validators/worklog.validator"; import { mockWorklogEntry, worklogMockFactory, } from "@test/mocks/worklog/worklog-entry.mock"; import { jiraApiMocks } from "@test/utils/mock-helpers"; describe("Worklog API Integration", () => { let addHandler: AddWorklogHandler; let getHandler: GetWorklogsHandler; let updateHandler: UpdateWorklogHandler; let deleteHandler: DeleteWorklogHandler; let validator: WorklogValidatorImpl; beforeEach(() => { // Create mock repository const mockRepository = { addWorklog: async () => mockWorklogEntry, getWorklogs: async () => [mockWorklogEntry], updateWorklog: async () => mockWorklogEntry, deleteWorklog: async () => undefined, }; // Create use cases with mock repository const addUseCase = new AddWorklogUseCaseImpl(mockRepository); const getUseCase = new GetWorklogsUseCaseImpl(mockRepository); const updateUseCase = new UpdateWorklogUseCaseImpl(mockRepository); const deleteUseCase = new DeleteWorklogUseCaseImpl(mockRepository); // Create validator validator = new WorklogValidatorImpl(); // Create handlers addHandler = new AddWorklogHandler(addUseCase, validator); getHandler = new GetWorklogsHandler(getUseCase, validator); updateHandler = new UpdateWorklogHandler(updateUseCase, validator); deleteHandler = new DeleteWorklogHandler(deleteUseCase, validator); }); afterEach(() => { jiraApiMocks.clearMocks(); }); describe("Complete CRUD Workflow", () => { test("should complete full worklog lifecycle", async () => { const issueKey = "TEST-123"; // 1. Add worklog const addParams = { issueKey, timeSpent: "2h", comment: "Initial work on feature", }; const addResult = await addHandler.handle(addParams); expect(addResult.success).toBe(true); expect(addResult.data).toBeDefined(); // 2. Get worklogs const getParams = { issueKey }; const getResult = await getHandler.handle(getParams); expect(getResult.success).toBe(true); expect(getResult.data).toBeDefined(); // 3. Update worklog const updateParams = { issueKey, worklogId: "10001", timeSpent: "3h", comment: "Updated work description", }; const updateResult = await updateHandler.handle(updateParams); expect(updateResult.success).toBe(true); expect(updateResult.data).toBeDefined(); // 4. Delete worklog const deleteParams = { issueKey, worklogId: "10001", }; const deleteResult = await deleteHandler.handle(deleteParams); expect(deleteResult.success).toBe(true); expect(deleteResult.data).toBeDefined(); }); }); describe("Cross-Handler Data Consistency", () => { test("should maintain data consistency across operations", async () => { const issueKey = "TEST-456"; const worklogData = worklogMockFactory.createWorklogEntry({ issueId: "10456", timeSpent: "4h", timeSpentSeconds: 14400, }); // Mock repository to return consistent data const mockRepository = { addWorklog: async () => worklogData, getWorklogs: async () => [worklogData], updateWorklog: async () => ({ ...worklogData, timeSpent: "5h", timeSpentSeconds: 18000, }), deleteWorklog: async () => undefined, }; const addUseCase = new AddWorklogUseCaseImpl(mockRepository); const getUseCase = new GetWorklogsUseCaseImpl(mockRepository); const updateUseCase = new UpdateWorklogUseCaseImpl(mockRepository); const addHandler = new AddWorklogHandler(addUseCase, validator); const getHandler = new GetWorklogsHandler(getUseCase, validator); const updateHandler = new UpdateWorklogHandler(updateUseCase, validator); // Add worklog const addResult = await addHandler.handle({ issueKey, timeSpent: "4h", comment: "Consistent data test", }); expect(addResult.success).toBe(true); // Get worklogs should return the same data const getResult = await getHandler.handle({ issueKey }); expect(getResult.success).toBe(true); // Update should maintain consistency const updateResult = await updateHandler.handle({ issueKey, worklogId: worklogData.id, timeSpent: "5h", }); expect(updateResult.success).toBe(true); }); }); describe("Error Propagation", () => { test("should properly propagate repository errors through layers", async () => { const errorRepository = { addWorklog: async () => { throw new Error("Database connection failed"); }, getWorklogs: async () => { throw new Error("Database connection failed"); }, updateWorklog: async () => { throw new Error("Database connection failed"); }, deleteWorklog: async () => { throw new Error("Database connection failed"); }, }; const addUseCase = new AddWorklogUseCaseImpl(errorRepository); const getUseCase = new GetWorklogsUseCaseImpl(errorRepository); const updateUseCase = new UpdateWorklogUseCaseImpl(errorRepository); const deleteUseCase = new DeleteWorklogUseCaseImpl(errorRepository); const addHandler = new AddWorklogHandler(addUseCase, validator); const getHandler = new GetWorklogsHandler(getUseCase, validator); const updateHandler = new UpdateWorklogHandler(updateUseCase, validator); const deleteHandler = new DeleteWorklogHandler(deleteUseCase, validator); // Test error propagation for each operation const addResult = await addHandler.handle({ issueKey: "TEST-123", timeSpent: "2h", }); expect(addResult.success).toBe(false); expect(addResult.error).toContain("Database connection failed"); const getResult = await getHandler.handle({ issueKey: "TEST-123", }); expect(getResult.success).toBe(false); expect(getResult.error).toContain("Database connection failed"); const updateResult = await updateHandler.handle({ issueKey: "TEST-123", worklogId: "10001", timeSpent: "3h", }); expect(updateResult.success).toBe(false); expect(updateResult.error).toContain("Database connection failed"); const deleteResult = await deleteHandler.handle({ issueKey: "TEST-123", worklogId: "10001", }); expect(deleteResult.success).toBe(false); expect(deleteResult.error).toContain("Database connection failed"); }); }); describe("Validation Integration", () => { test("should validate parameters at handler level", async () => { // Test invalid time format const invalidTimeResult = await addHandler.handle({ issueKey: "TEST-123", timeSpent: "invalid-time", }); expect(invalidTimeResult.success).toBe(false); // Test invalid issue key const invalidIssueResult = await getHandler.handle({ issueKey: "", }); expect(invalidIssueResult.success).toBe(false); // Test missing required fields const missingFieldsResult = await updateHandler.handle({ issueKey: "TEST-123", // Missing worklogId }); expect(missingFieldsResult.success).toBe(false); }); }); describe("Performance Integration", () => { test("should handle large worklog operations efficiently", async () => { const largeWorklogList = worklogMockFactory.createWorklogList(100); const mockRepository = { addWorklog: async () => mockWorklogEntry, getWorklogs: async () => largeWorklogList, updateWorklog: async () => mockWorklogEntry, deleteWorklog: async () => undefined, }; const getUseCase = new GetWorklogsUseCaseImpl(mockRepository); const getHandler = new GetWorklogsHandler(getUseCase, validator); const startTime = Date.now(); const result = await getHandler.handle({ issueKey: "TEST-123", maxResults: 1000, }); const endTime = Date.now(); const executionTime = endTime - startTime; expect(result.success).toBe(true); expect(executionTime).toBeLessThan(1000); // Should complete within 1 second }); }); });

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/Dsazz/mcp-jira'

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