Skip to main content
Glama

Atlassian Bitbucket MCP Server

by aashari
atlassian.repositories.cli.test.ts13.3 kB
import { CliTestUtil } from '../utils/cli.test.util.js'; import { getAtlassianCredentials } from '../utils/transport.util.js'; import { config } from '../utils/config.util.js'; describe('Atlassian Repositories CLI Commands', () => { // Load configuration and check for credentials before all tests beforeAll(() => { // Load configuration from all sources config.load(); // Log warning if credentials aren't available const credentials = getAtlassianCredentials(); if (!credentials) { console.warn( 'Skipping Atlassian Repositories CLI tests: No credentials available', ); } }); // Helper function to skip tests when credentials are missing const skipIfNoCredentials = () => { const credentials = getAtlassianCredentials(); if (!credentials) { return true; } return false; }; // Helper to get a valid workspace slug for testing async function getWorkspaceSlug(): Promise<string | null> { // First, get a list of workspaces const workspacesResult = await CliTestUtil.runCommand([ 'ls-workspaces', ]); // Skip if no workspaces are available if ( workspacesResult.stdout.includes('No Bitbucket workspaces found.') ) { return null; // Skip silently for this helper function } // Extract a workspace slug from the output const slugMatch = workspacesResult.stdout.match( /\*\*Slug\*\*:\s+([^\n]+)/, ); if (!slugMatch || !slugMatch[1]) { return null; // Skip silently for this helper function } return slugMatch[1].trim(); } describe('ls-repos command', () => { // Test listing repositories for a workspace it('should list repositories in a workspace', async () => { if (skipIfNoCredentials()) { return; } // Get a valid workspace const workspaceSlug = await getWorkspaceSlug(); if (!workspaceSlug) { return; // Skip if no valid workspace found } // Run the CLI command const result = await CliTestUtil.runCommand([ 'ls-repos', '--workspace-slug', workspaceSlug, ]); // Check command exit code expect(result.exitCode).toBe(0); // Verify the output format if there are repositories if (!result.stdout.includes('No repositories found')) { // Validate expected Markdown structure CliTestUtil.validateOutputContains(result.stdout, [ '# Bitbucket Repositories', '**Name**', '**Full Name**', '**Owner**', ]); // Validate Markdown formatting CliTestUtil.validateMarkdownOutput(result.stdout); } }, 30000); // Increased timeout for API call // Test with pagination it('should support pagination with --limit flag', async () => { if (skipIfNoCredentials()) { return; } // Get a valid workspace const workspaceSlug = await getWorkspaceSlug(); if (!workspaceSlug) { return; // Skip if no valid workspace found } // Run the CLI command with limit const result = await CliTestUtil.runCommand([ 'ls-repos', '--workspace-slug', workspaceSlug, '--limit', '1', ]); // Check command exit code expect(result.exitCode).toBe(0); // If there are multiple repositories, pagination section should be present if ( !result.stdout.includes('No repositories found') && result.stdout.includes('items remaining') ) { CliTestUtil.validateOutputContains(result.stdout, [ 'Pagination', 'Next cursor:', ]); } }, 30000); // Increased timeout for API call // Test with query filtering it('should support filtering with --query parameter', async () => { if (skipIfNoCredentials()) { return; } // Get a valid workspace const workspaceSlug = await getWorkspaceSlug(); if (!workspaceSlug) { return; // Skip if no valid workspace found } // Use a common term that might be in repository names const query = 'api'; // Run the CLI command with query const result = await CliTestUtil.runCommand([ 'ls-repos', '--workspace-slug', workspaceSlug, '--query', query, ]); // Check command exit code expect(result.exitCode).toBe(0); // Output might contain filtered results or no matches, both are valid if (result.stdout.includes('No repositories found')) { // Valid case - no repositories match the query CliTestUtil.validateOutputContains(result.stdout, [ 'No repositories found', ]); } else { // Valid case - some repositories match, check formatting CliTestUtil.validateMarkdownOutput(result.stdout); } }, 30000); // Increased timeout for API call // Test with role filtering (if supported by the API) it('should support filtering by --role', async () => { if (skipIfNoCredentials()) { return; } // Get a valid workspace const workspaceSlug = await getWorkspaceSlug(); if (!workspaceSlug) { return; // Skip if no valid workspace found } // Test one role - we pick 'contributor' as it's most likely to have results const result = await CliTestUtil.runCommand([ 'ls-repos', '--workspace-slug', workspaceSlug, '--role', 'contributor', ]); // Check command exit code expect(result.exitCode).toBe(0); // Output might contain filtered results or no matches, both are valid if (result.stdout.includes('No repositories found')) { // Valid case - no repositories match the role filter CliTestUtil.validateOutputContains(result.stdout, [ 'No repositories found', ]); } else { // Valid case - some repositories match the role, check formatting CliTestUtil.validateMarkdownOutput(result.stdout); } }, 30000); // Increased timeout for API call // Test with sort parameter it('should support sorting with --sort parameter', async () => { if (skipIfNoCredentials()) { return; } // Get a valid workspace const workspaceSlug = await getWorkspaceSlug(); if (!workspaceSlug) { return; // Skip if no valid workspace found } // Test sorting by name (alphabetical) const result = await CliTestUtil.runCommand([ 'ls-repos', '--workspace-slug', workspaceSlug, '--sort', 'name', ]); // Check command exit code expect(result.exitCode).toBe(0); // Sorting doesn't affect whether items are returned if (!result.stdout.includes('No repositories found')) { // Validate Markdown formatting CliTestUtil.validateMarkdownOutput(result.stdout); } }, 30000); // Increased timeout for API call // Test without workspace parameter (now optional) it('should use default workspace when workspace is not provided', async () => { if (skipIfNoCredentials()) { return; } // Run command without workspace parameter const result = await CliTestUtil.runCommand(['ls-repos']); // Should succeed with exit code 0 (using default workspace) expect(result.exitCode).toBe(0); // Output should contain either repositories or "No repositories found" const hasRepos = !result.stdout.includes('No repositories found'); if (hasRepos) { // Validate expected Markdown structure if repos are found CliTestUtil.validateOutputContains(result.stdout, [ '# Bitbucket Repositories', ]); } else { // No repositories were found but command should still succeed CliTestUtil.validateOutputContains(result.stdout, [ 'No repositories found', ]); } }, 15000); // Test with invalid parameter value it('should handle invalid limit values properly', async () => { if (skipIfNoCredentials()) { return; } // Get a valid workspace const workspaceSlug = await getWorkspaceSlug(); if (!workspaceSlug) { return; // Skip if no valid workspace found } // Run with non-numeric limit const result = await CliTestUtil.runCommand([ 'ls-repos', '--workspace-slug', workspaceSlug, '--limit', 'invalid', ]); // This might either return an error (non-zero exit code) or handle it gracefully (zero exit code) // Both behaviors are acceptable, we just need to check that the command completes if (result.exitCode !== 0) { expect(result.stderr).toContain('error'); } else { // Command completed without error, the implementation should handle it gracefully expect(result.exitCode).toBe(0); } }, 30000); }); describe('get-repo command', () => { // Helper to get a valid repository for testing async function getRepositorySlug( workspaceSlug: string, ): Promise<string | null> { // Get repositories for this workspace const reposResult = await CliTestUtil.runCommand([ 'ls-repos', '--workspace-slug', workspaceSlug, ]); // Skip if no repositories are available if (reposResult.stdout.includes('No repositories found')) { return null; // Skip silently for this helper function } // Extract a repository slug from the output const repoMatch = reposResult.stdout.match( /\*\*Name\*\*:\s+([^\n]+)/, ); if (!repoMatch || !repoMatch[1]) { console.warn( 'Skipping test: Could not extract repository slug', ); return null; } return repoMatch[1].trim(); } // Test to fetch a specific repository it('should retrieve repository details', async () => { if (skipIfNoCredentials()) { return; } // Get valid workspace and repository slugs const workspaceSlug = await getWorkspaceSlug(); if (!workspaceSlug) { return; // Skip if no valid workspace found } const repoSlug = await getRepositorySlug(workspaceSlug); if (!repoSlug) { return; // Skip if no valid repository found } // Run the get-repo command const result = await CliTestUtil.runCommand([ 'get-repo', '--workspace-slug', workspaceSlug, '--repo-slug', repoSlug, ]); // Instead of expecting a success, check if the command ran // If access is unavailable, just note it and skip the test validation if (result.exitCode !== 0) { console.warn( 'Skipping test validation: Could not retrieve repository details', ); return; } // Verify the output structure and content CliTestUtil.validateOutputContains(result.stdout, [ `# Repository: ${repoSlug}`, '## Basic Information', '**Name**', '**Full Name**', '**UUID**', '## Owner', '## Links', ]); // Validate Markdown formatting CliTestUtil.validateMarkdownOutput(result.stdout); }, 30000); // Increased timeout for API calls // Test with missing workspace parameter it('should use default workspace when workspace is not provided', async () => { if (skipIfNoCredentials()) { return; } // Run command without the workspace parameter const result = await CliTestUtil.runCommand([ 'get-repo', '--repo-slug', 'some-repo', ]); // Now that workspace is optional, we should get a different error // (repository not found), but not a missing parameter error expect(result.exitCode).not.toBe(0); // Should NOT indicate missing required option for workspace expect(result.stderr).not.toContain('workspace-slug'); }, 15000); // Test with missing repository parameter it('should fail when repository is not provided', async () => { if (skipIfNoCredentials()) { return; } // Get a valid workspace const workspaceSlug = await getWorkspaceSlug(); if (!workspaceSlug) { return; // Skip if no valid workspace found } // Run command without the repository parameter const result = await CliTestUtil.runCommand([ 'get-repo', '--workspace-slug', workspaceSlug, ]); // Should fail with non-zero exit code expect(result.exitCode).not.toBe(0); // Should indicate missing required option expect(result.stderr).toContain('required option'); }, 15000); // Test with invalid repository slug it('should handle invalid repository slugs gracefully', async () => { if (skipIfNoCredentials()) { return; } // Get a valid workspace const workspaceSlug = await getWorkspaceSlug(); if (!workspaceSlug) { return; // Skip if no valid workspace found } // Use a deliberately invalid repository slug const invalidSlug = 'invalid-repository-slug-that-does-not-exist'; // Run command with invalid repository slug const result = await CliTestUtil.runCommand([ 'get-repo', '--workspace-slug', workspaceSlug, '--repo-slug', invalidSlug, ]); // Should fail with non-zero exit code expect(result.exitCode).not.toBe(0); // Should contain error information expect(result.stderr).toContain('error'); }, 30000); // Test with invalid workspace slug but valid repository format it('should handle invalid workspace slugs gracefully', async () => { if (skipIfNoCredentials()) { return; } // Use deliberately invalid workspace and repository slugs const invalidWorkspace = 'invalid-workspace-that-does-not-exist'; const someRepo = 'some-repo'; // Run command with invalid workspace slug const result = await CliTestUtil.runCommand([ 'get-repo', '--workspace-slug', invalidWorkspace, '--repo-slug', someRepo, ]); // Should fail with non-zero exit code expect(result.exitCode).not.toBe(0); // Should contain error information expect(result.stderr).toContain('error'); }, 30000); }); });

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-bitbucket'

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