Skip to main content
Glama
atlassian.pages.controller.test.ts14.2 kB
import atlassianPagesController from './atlassian.pages.controller.js'; import { getAtlassianCredentials } from '../utils/transport.util.js'; import { config } from '../utils/config.util.js'; import { McpError } from '../utils/error.util.js'; describe('Atlassian Pages Controller', () => { // Load configuration before all tests beforeAll(() => { // Load configuration from all sources config.load(); const credentials = getAtlassianCredentials(); if (!credentials) { console.warn( 'Skipping Atlassian Pages Controller tests: No credentials available', ); } }); // Helper function to skip tests when credentials are missing const skipIfNoCredentials = () => !getAtlassianCredentials(); describe('list', () => { it('should return a formatted list of pages', async () => { if (skipIfNoCredentials()) return; // Call the function const result = await atlassianPagesController.list(); // Verify the response structure expect(result).toHaveProperty('content'); expect(typeof result.content).toBe('string'); // Verify the content format if ( !result.content.includes( 'No Confluence pages found matching your criteria.', ) ) { expect(result.content).toContain('# Confluence Pages'); expect(result.content).toContain('**ID**'); expect(result.content).toContain('**Title**'); expect(result.content).toContain('**Space ID**'); expect(result.content).toContain('**Status**'); // Check for pagination information in the content if it exists expect(result.content).toContain('Information retrieved at:'); if (result.content.includes('More results are available')) { expect(result.content).toMatch( /\*Use --cursor "([^"]+)" to view more\.\*/, ); } } }, 15000); it('should handle filtering by space ID', async () => { if (skipIfNoCredentials()) return; // First, get a list of pages to find a valid space ID const initialResult = await atlassianPagesController.list(); // Skip if no pages are available if ( initialResult.content.includes( 'No Confluence pages found matching your criteria.', ) ) { console.warn('Skipping test: No pages available'); return; } // Extract a space ID from the list result const match = initialResult.content.match( /\*\*Space ID\*\*: ([0-9]+)/, ); if (!match || !match[1]) { console.warn( 'Skipping test: Could not extract space ID from list result', ); return; } const spaceId = match[1]; // Call the function with the space ID filter using spaceIds const result = await atlassianPagesController.list({ spaceIds: [spaceId], }); // Verify the response expect(result).toHaveProperty('content'); expect(typeof result.content).toBe('string'); // If results were found, verify they contain the space ID if ( !result.content.includes( 'No Confluence pages found matching your criteria.', ) ) { expect(result.content).toContain(`**Space ID**: ${spaceId}`); } }, 15000); it('should handle filtering by status', async () => { if (skipIfNoCredentials()) return; // Test filtering by 'current' status const result = await atlassianPagesController.list({ status: ['current'], limit: 5, }); // Verify the response expect(result).toHaveProperty('content'); expect(typeof result.content).toBe('string'); // If results were found, verify they contain current status if ( !result.content.includes( 'No Confluence pages found matching your criteria.', ) ) { expect(result.content).toContain('**Status**: current'); // No archived status should be present expect(result.content).not.toContain('**Status**: archived'); } }, 15000); it('should handle filtering by query (title search)', async () => { if (skipIfNoCredentials()) return; // First, get a list of pages to find a common term to search for const initialResult = await atlassianPagesController.list({ limit: 5, }); // Skip if no pages are available if ( initialResult.content.includes( 'No Confluence pages found matching your criteria.', ) ) { console.warn('Skipping test: No pages available'); return; } // Extract a title to search for a fragment of it const titleMatch = initialResult.content.match( /\*\*Title\*\*: ([^\n]+)/, ); // If we can't find a title, use a generic search term let searchTerm = 'a'; if (titleMatch && titleMatch[1]) { const words = titleMatch[1].split(' '); if (words.length > 0 && words[0].length > 3) { searchTerm = words[0]; } } // Call the function with the query filter const result = await atlassianPagesController.list({ title: searchTerm, limit: 5, }); // Verify the response expect(result).toHaveProperty('content'); expect(typeof result.content).toBe('string'); // Note: We can't guarantee the search will find results, so // we only verify the call completes successfully }, 15000); it('should handle sorting with different parameters', async () => { if (skipIfNoCredentials()) return; // Test sorting by created date ascending const ascResult = await atlassianPagesController.list({ sort: 'created-date', limit: 5, }); // Test sorting by created date descending const descResult = await atlassianPagesController.list({ sort: '-created-date', limit: 5, }); // Verify the responses expect(ascResult).toHaveProperty('content'); expect(descResult).toHaveProperty('content'); // Note: It's difficult to verify sorting in Markdown output, // so we just verify the calls complete successfully }, 15000); // Updated test for pagination it('should handle pagination with limit and cursor', async () => { if (skipIfNoCredentials()) return; // Get the first page with a small limit const firstPageResult = await atlassianPagesController.list({ limit: 2, }); // Verify the first page response expect(firstPageResult).toHaveProperty('content'); expect(typeof firstPageResult.content).toBe('string'); // If there are more pages indicated in the content, test cursor-based pagination // Extract cursor from content const cursorMatch = firstPageResult.content.match( /\*Use --cursor "([^"]+)" to view more\.\*/, ); const nextCursor = cursorMatch ? cursorMatch[1] : null; if ( nextCursor && firstPageResult.content.includes('More results are available') ) { // Get the second page using the cursor from first page const secondPageResult = await atlassianPagesController.list({ limit: 2, cursor: nextCursor, }); // Verify the second page response expect(secondPageResult).toHaveProperty('content'); expect(typeof secondPageResult.content).toBe('string'); } else { console.info('Skipping cursor test: No more pages available'); } }, 15000); it('should handle empty results gracefully', async () => { if (skipIfNoCredentials()) return; // Instead of mocking, use a unique search term guaranteed to return no results const uniqueSearchTerm = `NonExistentPage${Date.now()}${Math.random().toString(36).substring(2, 8)}`; // Call with a search term that won't match any pages const result = await atlassianPagesController.list({ title: uniqueSearchTerm, }); // Verify the empty result message expect(result.content).toContain( 'No Confluence pages found matching your criteria.', ); expect(result.content).toContain('Information retrieved at:'); }, 15000); it('should handle combinations of filters', async () => { if (skipIfNoCredentials()) return; // First, get a list of pages to find a valid space ID const initialResult = await atlassianPagesController.list(); // Skip if no pages are available if ( initialResult.content.includes( 'No Confluence pages found matching your criteria.', ) ) { console.warn('Skipping test: No pages available'); return; } // Extract a space ID from the list result const spaceMatch = initialResult.content.match( /\*\*Space ID\*\*: ([0-9]+)/, ); if (!spaceMatch || !spaceMatch[1]) { console.warn('Skipping test: Could not extract space ID'); return; } const spaceId = spaceMatch[1]; // Combine filters: space ID + status + limit using spaceIds const result = await atlassianPagesController.list({ spaceIds: [spaceId], status: ['current'], limit: 3, }); // Verify the response expect(result).toHaveProperty('content'); // If results were found, verify they contain both filters if ( !result.content.includes( 'No Confluence pages found matching your criteria.', ) ) { expect(result.content).toContain(`**Space ID**: ${spaceId}`); expect(result.content).toContain('**Status**: current'); // Check that the limit was respected const entriesCount = ( result.content.match(/\*\*ID\*\*:/g) || [] ).length; expect(entriesCount).toBeLessThanOrEqual(3); } }, 15000); it('should handle invalid space ID by throwing an error', async () => { if (skipIfNoCredentials()) return; // Call with an invalid space ID format using spaceIds await expect( atlassianPagesController.list({ spaceIds: ['invalid-space-id'], }), ).rejects.toThrow(McpError); // Try to catch the error to verify its properties using spaceIds try { await atlassianPagesController.list({ spaceIds: ['invalid-space-id'], }); } catch (error) { expect(error).toBeInstanceOf(McpError); if (error instanceof McpError) { // Don't check for specific message content since it comes from the API expect(error.type).toBe('API_ERROR'); } } }, 15000); it('should handle invalid sort parameter by throwing an error', async () => { if (skipIfNoCredentials()) return; // Call with an invalid sort parameter await expect( atlassianPagesController.list({ sort: 'invalid' as any, }), ).rejects.toThrow(McpError); }, 15000); }); describe('get', () => { // Helper function to get a valid page ID for testing async function getFirstPageId(): Promise<string | null> { if (skipIfNoCredentials()) return null; try { const listResult = await atlassianPagesController.list({ limit: 1, }); // Skip if no pages are available if ( listResult.content.includes( 'No Confluence pages found matching your criteria.', ) ) { return null; } // Extract a page ID from the list result const match = listResult.content.match(/\*\*ID\*\*: ([0-9]+)/); return match && match[1] ? match[1] : null; } catch (error) { console.warn('Could not extract page ID for tests:', error); return null; } } it('should return formatted details for a valid page ID', async () => { if (skipIfNoCredentials()) return; // Get a valid page ID for testing const pageId = await getFirstPageId(); // Skip if no page ID was found if (!pageId) { console.warn('Skipping test: No valid page ID found'); return; } // Call the function with the extracted ID const result = await atlassianPagesController.get({ pageId: pageId, }); // Verify the response structure expect(result).toHaveProperty('content'); expect(typeof result.content).toBe('string'); // Verify the content format expect(result.content).toContain('# Confluence Page:'); expect(result.content).toContain(`**ID**: ${pageId}`); expect(result.content).toContain('**Title**:'); expect(result.content).toContain('**Space ID**:'); expect(result.content).toContain('**Status**:'); expect(result.content).toContain('**Created At**:'); expect(result.content).toContain('**Author ID**:'); expect(result.content).toContain('## Basic Information'); expect(result.content).toContain('## Content'); expect(result.content).toContain('## Labels'); expect(result.content).toContain('## Links'); expect(result.content).toContain('**Web UI**:'); expect(result.content).toContain('*Information retrieved at:'); expect(result.content).toContain('*View this page in Confluence: '); }, 15000); it('should include content body in the page details', async () => { if (skipIfNoCredentials()) return; // Get a valid page ID for testing const pageId = await getFirstPageId(); // Skip if no page ID was found if (!pageId) { console.warn('Skipping test: No valid page ID found'); return; } // Call the function with the extracted ID const result = await atlassianPagesController.get({ pageId: pageId, }); // Verify content section is included expect(result.content).toContain('## Content'); // Content might be empty, but the section header should exist }, 15000); it('should throw an error for invalid page ID format', async () => { if (skipIfNoCredentials()) return; // Use an invalid ID (non-numeric) const invalidId = 'invalid-page-id'; // Try to catch the error to verify its properties await expect( atlassianPagesController.get({ pageId: invalidId }), ).rejects.toThrow(McpError); try { await atlassianPagesController.get({ pageId: invalidId }); fail('Expected an error to be thrown'); } catch (error) { expect(error).toBeInstanceOf(McpError); if (error instanceof McpError) { // Error type could be API_ERROR or INVALID_INPUT expect(['API_ERROR', 'INVALID_INPUT']).toContain( error.type, ); } } }, 15000); it('should throw an error for non-existent page ID', async () => { if (skipIfNoCredentials()) return; // Test with non-existent page ID try { await atlassianPagesController.get({ pageId: '999999999' }); fail('Expected an error to be thrown'); } catch (error) { if (error instanceof McpError) { expect(error.statusCode).toBe(404); expect(error.type).toBe('NOT_FOUND'); // NOT_FOUND for resource not found (updated to match error handler behavior) } } }, 15000); }); });

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/aashari/mcp-server-atlassian-confluence'

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