Skip to main content
Glama
getIssue.test.ts7.9 kB
import { Success, Failure } from '../../../utils/try' import { callJiraApi, RestMethod } from '../callJiraApi' import { getIssueByKey } from '../getIssue' import getAllChangeLogsForIssue from '../issueChangeLogs/getAllChangeLogsForIssue' import type { JiraIssue, IssueChangeLogEntry } from '../../types/issue.types' import type { JiraApiConfig } from '../apiTypes' // Mock dependencies jest.mock('../callJiraApi') jest.mock('../issueChangeLogs/getAllChangeLogsForIssue') const mockedCallJiraApi = callJiraApi as jest.MockedFunction<typeof callJiraApi> const mockedGetAllChangeLogsForIssue = getAllChangeLogsForIssue as jest.MockedFunction<typeof getAllChangeLogsForIssue> describe('getIssue', () => { const mockConfig: JiraApiConfig = { baseUrl: 'https://jira.example.com', username: 'testuser', apiToken: 'test-token', } const issueKey = 'TEST-123' // Create a partial mock that satisfies the requirements for testing const mockIssue = { expand: 'expand-string', id: '12345', self: 'https://jira.example.com/rest/api/3/issue/TEST-123', key: issueKey, changelog: { startAt: 0, maxResults: 10, total: 10, histories: [], }, fields: { summary: 'Test Issue', status: { self: 'status-self', description: 'status-description', iconUrl: 'status-icon-url', name: 'Open', id: 'status-id', statusCategory: { self: 'status-category-self', id: 123, key: 'status-category-key', colorName: 'status-category-color', name: 'status-category-name', }, }, priority: { self: 'priority-self', iconUrl: 'priority-icon-url', name: 'Medium', id: 'priority-id', }, issuetype: { self: 'issuetype-self', id: 'issuetype-id', description: 'issuetype-description', iconUrl: 'issuetype-icon-url', name: 'Story', subtask: false, avatarId: 10000, hierarchyLevel: 0, }, project: { self: 'project-self', id: 'project-id', key: 'TEST', name: 'Test Project', projectTypeKey: 'project-type-key', simplified: true, avatarUrls: {}, projectCategory: { self: 'category-self', id: 'category-id', description: 'category-description', name: 'category-name', }, }, created: '2023-01-01T12:00:00.000Z', updated: '2023-01-02T12:00:00.000Z', description: { version: 1, type: 'doc', content: [], }, watches: { self: 'watches-self', watchCount: 1, isWatching: false, }, assignee: { self: 'assignee-self', accountId: 'user-123', emailAddress: 'user@example.com', avatarUrls: { '48x48': 'avatar-url', '24x24': 'avatar-url', '16x16': 'avatar-url', '32x32': 'avatar-url', }, displayName: 'Test User', active: true, timeZone: 'UTC', accountType: 'atlassian', }, statuscategorychangedate: '2023-01-01T12:00:00.000Z', progress: { progress: 0, total: 0, }, votes: { self: 'votes-self', votes: 0, hasVoted: false, }, // Add required fields with null values customfield_13100: null, customfield_12801: null, customfield_14788: null, labels: [], } as unknown as JiraIssue['fields'], } as unknown as JiraIssue const mockChangeLogs: IssueChangeLogEntry[] = [ { id: 'changelog-1', author: { self: 'author-self', accountId: 'user-123', emailAddress: 'user@example.com', avatarUrls: { '48x48': 'avatar-url', '24x24': 'avatar-url', '16x16': 'avatar-url', '32x32': 'avatar-url', }, displayName: 'Test User', active: true, timeZone: 'UTC', accountType: 'atlassian', }, created: '2023-01-01T12:00:00.000Z', items: [], }, ] beforeEach(() => { jest.clearAllMocks() }) describe('getIssueByKey', () => { test('should return failure when API call fails', async () => { // Setup const mockError = new Error('API Error') mockedCallJiraApi.mockResolvedValue(Failure(mockError)) // Execute const result = await getIssueByKey(issueKey, mockConfig) // Verify expect(mockedCallJiraApi).toHaveBeenCalledWith({ config: mockConfig, endpoint: `/rest/api/3/issue/${issueKey}?expand=changelog`, method: RestMethod.GET, }) expect(result.success).toBe(false) expect(result.error).toEqual(mockError) expect(mockedGetAllChangeLogsForIssue).not.toHaveBeenCalled() }) test('should return issue when changelog is complete', async () => { // Setup mockedCallJiraApi.mockResolvedValue(Success(mockIssue)) // Execute const result = await getIssueByKey(issueKey, mockConfig) // Verify expect(mockedCallJiraApi).toHaveBeenCalledWith({ config: mockConfig, endpoint: `/rest/api/3/issue/${issueKey}?expand=changelog`, method: RestMethod.GET, }) expect(result.success).toBe(true) expect(result.value).toEqual(mockIssue) expect(mockedGetAllChangeLogsForIssue).not.toHaveBeenCalled() }) test('should fetch all changelogs when initial changelog is incomplete', async () => { // Setup const incompleteIssue = { ...mockIssue, changelog: { startAt: 0, maxResults: 5, total: 10, histories: [], }, } mockedCallJiraApi.mockResolvedValue(Success(incompleteIssue)) mockedGetAllChangeLogsForIssue.mockResolvedValue(Success(mockChangeLogs)) // Execute const result = await getIssueByKey(issueKey, mockConfig) // Verify expect(mockedCallJiraApi).toHaveBeenCalledWith({ config: mockConfig, endpoint: `/rest/api/3/issue/${issueKey}?expand=changelog`, method: RestMethod.GET, }) expect(mockedGetAllChangeLogsForIssue).toHaveBeenCalledWith(issueKey, mockConfig) expect(result.success).toBe(true) expect(result.value).toEqual({ ...incompleteIssue, changelog: { startAt: 0, maxResults: mockChangeLogs.length, total: mockChangeLogs.length, histories: mockChangeLogs, }, }) }) test('should return failure when getAllChangeLogsForIssue fails', async () => { // Setup const incompleteIssue = { ...mockIssue, changelog: { startAt: 0, maxResults: 5, total: 10, histories: [], }, } const changeLogError = new Error('Failed to fetch changelogs') mockedCallJiraApi.mockResolvedValue(Success(incompleteIssue)) mockedGetAllChangeLogsForIssue.mockResolvedValue(Failure(changeLogError)) // Execute const result = await getIssueByKey(issueKey, mockConfig) // Verify expect(mockedCallJiraApi).toHaveBeenCalledWith({ config: mockConfig, endpoint: `/rest/api/3/issue/${issueKey}?expand=changelog`, method: RestMethod.GET, }) expect(mockedGetAllChangeLogsForIssue).toHaveBeenCalledWith(issueKey, mockConfig) expect(result.success).toBe(false) expect(result.error).toEqual(changeLogError) }) }) describe('hasCompleteChangeLog', () => { test('should not fetch all changelogs when total equals maxResults', async () => { // Setup const completeChangelogIssue = { ...mockIssue, changelog: { startAt: 0, maxResults: 10, total: 10, histories: [], }, } // Execute mockedCallJiraApi.mockResolvedValue(Success(completeChangelogIssue)) await getIssueByKey(issueKey, mockConfig) // Verify expect(mockedGetAllChangeLogsForIssue).not.toHaveBeenCalled() }) test('should fetch all changelogs when total is greater than maxResults', async () => { // Setup const incompleteChangelogIssue = { ...mockIssue, changelog: { startAt: 0, maxResults: 5, total: 10, histories: [], }, } // Execute mockedCallJiraApi.mockResolvedValue(Success(incompleteChangelogIssue)) mockedGetAllChangeLogsForIssue.mockResolvedValue(Success([])) await getIssueByKey(issueKey, mockConfig) // Verify expect(mockedGetAllChangeLogsForIssue).toHaveBeenCalled() }) }) })

Latest Blog Posts

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

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