Skip to main content
Glama
test-case-tools.test.tsโ€ข17.8 kB
import { describe, it } from 'node:test'; import { strict as assert } from 'node:assert'; /** * Unit tests for test case-related MCP tools * * Tests the following tools: * - get_test_case_by_key * - get_test_cases_advanced * - get_all_tcm_test_cases_by_project * - get_all_tcm_test_cases_with_root_suite_id * - get_test_cases_by_suite_id * - get_test_case_details_by_key * - generate_draft_test_by_key */ describe('Test Case Tools Unit Tests', () => { describe('get_test_case_by_key Tool', () => { it('should validate required parameters', () => { const validParams = { project_key: 'MCP', case_key: 'MCP-1', format: 'json' }; assert.ok(validParams.project_key, 'project_key should be required'); assert.ok(validParams.case_key, 'case_key should be required'); assert.ok(validParams.project_key.length > 0, 'project_key should not be empty'); assert.ok(validParams.case_key.length > 0, 'case_key should not be empty'); }); it('should validate case_key format', () => { const validCaseKey = 'MCP-1'; const invalidCaseKey = 'invalid-key'; assert.ok(validCaseKey.includes('-'), 'valid case key should contain hyphen'); assert.ok(validCaseKey.match(/^[A-Z]+-\d+$/), 'valid case key should match PROJECT-NUMBER pattern'); assert.ok(!invalidCaseKey.match(/^[A-Z]+-\d+$/), 'invalid case key should not match pattern'); }); it('should validate format parameter', () => { const validFormats = ['dto', 'json', 'string', 'markdown']; const invalidFormat = 'xml'; assert.ok(validFormats.includes('json'), 'json should be valid format'); assert.ok(validFormats.includes('markdown'), 'markdown should be valid format'); assert.ok(!validFormats.includes(invalidFormat), 'xml should not be valid format'); }); it('should handle include_steps parameter', () => { const params = { project_key: 'MCP', case_key: 'MCP-1', include_steps: true }; assert.equal(typeof params.include_steps, 'boolean', 'include_steps should be boolean'); }); }); describe('get_test_cases_advanced Tool', () => { it('should validate required parameters', () => { const validParams = { project_key: 'MCP', format: 'json' }; assert.ok(validParams.project_key, 'project_key should be required'); }); it('should validate pagination parameters', () => { const validPagination = { page: 0, size: 50, page_token: 'optional-token' }; assert.ok(validPagination.page >= 0, 'page should be non-negative'); assert.ok(validPagination.size > 0, 'size should be positive'); assert.ok(validPagination.size <= 1000, 'size should not exceed maximum'); }); it('should handle suite_id filter', () => { const params = { project_key: 'MCP', suite_id: 17470 }; assert.ok(params.suite_id > 0, 'suite_id should be positive when provided'); }); it('should handle automation_status filter', () => { const validStatuses = ['AUTOMATED', 'NOT_AUTOMATED', 'PARTIALLY_AUTOMATED']; const params = { project_key: 'MCP', automation_status: 'AUTOMATED' }; assert.ok(validStatuses.includes(params.automation_status), 'automation_status should be valid value'); }); it('should handle priority filter', () => { const validPriorities = ['CRITICAL', 'HIGH', 'MEDIUM', 'LOW']; const params = { project_key: 'MCP', priority: 'HIGH' }; assert.ok(validPriorities.includes(params.priority), 'priority should be valid value'); }); }); describe('get_all_tcm_test_cases_by_project Tool', () => { it('should validate required parameters', () => { const validParams = { project_key: 'MCP', max_page_size: 100, format: 'json' }; assert.ok(validParams.project_key, 'project_key should be required'); assert.ok(validParams.max_page_size > 0, 'max_page_size should be positive'); }); it('should handle page_token for pagination', () => { const params = { project_key: 'MCP', page_token: 'abc123token' }; assert.equal(typeof params.page_token, 'string', 'page_token should be string when provided'); }); it('should validate max_page_size limits', () => { const MAX_PAGE_SIZE = 100; const validSize = 50; const invalidSize = 150; assert.ok(validSize <= MAX_PAGE_SIZE, 'valid size should not exceed limit'); assert.ok(invalidSize > MAX_PAGE_SIZE, 'invalid size should exceed limit'); }); it('should handle include_steps parameter', () => { const params = { project_key: 'MCP', include_steps: false }; assert.equal(typeof params.include_steps, 'boolean', 'include_steps should be boolean'); }); }); describe('get_all_tcm_test_cases_with_root_suite_id Tool', () => { it('should validate required parameters', () => { const validParams = { project_key: 'MCP', max_page_size: 100, format: 'json' }; assert.ok(validParams.project_key, 'project_key should be required'); assert.ok(validParams.max_page_size > 0, 'max_page_size should be positive'); }); it('should handle root_suite_id filter', () => { const params = { project_key: 'MCP', root_suite_id: 18659 }; assert.ok(params.root_suite_id > 0, 'root_suite_id should be positive when provided'); }); it('should validate pagination with token', () => { const params = { project_key: 'MCP', page_token: 'next-page-token', max_page_size: 50 }; assert.equal(typeof params.page_token, 'string', 'page_token should be string'); assert.ok(params.max_page_size <= 100, 'max_page_size should not exceed limit'); }); }); describe('get_test_cases_by_suite_id Tool', () => { it('should validate required parameters', () => { const validParams = { project_key: 'MCP', suite_id: 17470, format: 'json' }; assert.ok(validParams.project_key, 'project_key should be required'); assert.ok(validParams.suite_id > 0, 'suite_id should be positive'); }); it('should validate pagination parameters', () => { const validPagination = { page: 0, size: 50 }; assert.ok(validPagination.page >= 0, 'page should be non-negative'); assert.ok(validPagination.size > 0, 'size should be positive'); assert.ok(validPagination.size <= 1000, 'size should not exceed maximum'); }); it('should handle include_steps parameter', () => { const params = { project_key: 'MCP', suite_id: 17470, include_steps: true }; assert.equal(typeof params.include_steps, 'boolean', 'include_steps should be boolean'); }); }); describe('get_test_case_details_by_key Tool', () => { it('should validate required parameters', () => { const validParams = { project_key: 'MCP', case_key: 'MCP-1', format: 'json' }; assert.ok(validParams.project_key, 'project_key should be required'); assert.ok(validParams.case_key, 'case_key should be required'); assert.ok(validParams.case_key.match(/^[A-Z]+-\d+$/), 'case_key should match pattern'); }); it('should handle include_hierarchy parameter', () => { const params = { project_key: 'MCP', case_key: 'MCP-1', include_hierarchy: true }; assert.equal(typeof params.include_hierarchy, 'boolean', 'include_hierarchy should be boolean'); }); it('should handle include_custom_fields parameter', () => { const params = { project_key: 'MCP', case_key: 'MCP-1', include_custom_fields: true }; assert.equal(typeof params.include_custom_fields, 'boolean', 'include_custom_fields should be boolean'); }); }); describe('generate_draft_test_by_key Tool', () => { it('should validate required parameters', () => { const validParams = { project_key: 'MCP', case_key: 'MCP-1', implementation_context: 'Test implementation context', target_framework: 'auto' }; assert.ok(validParams.project_key, 'project_key should be required'); assert.ok(validParams.case_key, 'case_key should be required'); assert.ok(validParams.implementation_context, 'implementation_context should be required'); }); it('should validate case_key format', () => { const validCaseKey = 'MCP-1'; const invalidCaseKey = 'invalid'; assert.ok(validCaseKey.match(/^[A-Z]+-\d+$/), 'valid case key should match pattern'); assert.ok(!invalidCaseKey.match(/^[A-Z]+-\d+$/), 'invalid case key should not match pattern'); }); it('should validate target_framework options', () => { const validFrameworks = ['auto', 'selenium', 'appium', 'playwright', 'cypress', 'testng', 'junit', 'pytest', 'mocha', 'jest']; const params = { target_framework: 'selenium' }; assert.ok(validFrameworks.includes(params.target_framework), 'target_framework should be valid option'); }); it('should handle optional parameters', () => { const params = { project_key: 'MCP', case_key: 'MCP-1', implementation_context: 'Context', target_framework: 'auto', include_page_objects: true, include_test_data: false, output_format: 'code_with_explanation' }; assert.equal(typeof params.include_page_objects, 'boolean', 'include_page_objects should be boolean'); assert.equal(typeof params.include_test_data, 'boolean', 'include_test_data should be boolean'); assert.ok(['code_only', 'code_with_explanation', 'detailed_analysis'].includes(params.output_format), 'output_format should be valid'); }); it('should validate implementation_context content', () => { const validContext = 'Test implementation found at: /path/to/test.java\n\nKey implementation details:\n1. Test creates account'; const emptyContext = ''; const shortContext = 'test'; assert.ok(validContext.length > 10, 'valid context should be meaningful'); assert.ok(emptyContext.length === 0, 'empty context should be detected'); assert.ok(shortContext.length < 10, 'short context should be detected'); }); }); describe('Test Case Response Validation', () => { it('should validate test case object structure', () => { const mockTestCase = { id: 123456, key: 'MCP-1', title: 'Test case title', description: 'Test case description', suiteId: 17470, automationState: { name: 'NOT_AUTOMATED' }, priority: { name: 'HIGH' }, draft: false, deprecated: false }; assert.ok(typeof mockTestCase.id === 'number', 'id should be number'); assert.ok(typeof mockTestCase.key === 'string', 'key should be string'); assert.ok(typeof mockTestCase.title === 'string', 'title should be string'); assert.ok(mockTestCase.automationState && mockTestCase.automationState.name, 'should have automation state'); assert.ok(mockTestCase.priority && mockTestCase.priority.name, 'should have priority'); }); it('should validate test case with steps', () => { const testCaseWithSteps = { id: 123456, key: 'MCP-1', title: 'Test case title', steps: [ { id: 1, description: 'Step 1', expectedResult: 'Expected 1' }, { id: 2, description: 'Step 2', expectedResult: 'Expected 2' } ] }; assert.ok(Array.isArray(testCaseWithSteps.steps), 'steps should be array'); assert.ok(testCaseWithSteps.steps.length > 0, 'should have steps'); assert.ok(testCaseWithSteps.steps[0].description, 'step should have description'); }); it('should validate test case with custom fields', () => { const testCaseWithCustomFields = { id: 123456, key: 'MCP-1', title: 'Test case title', customFields: [ { name: 'Manual Only', value: 'Yes' }, { name: 'Component', value: 'Login' } ] }; assert.ok(Array.isArray(testCaseWithCustomFields.customFields), 'customFields should be array'); assert.ok(testCaseWithCustomFields.customFields[0].name, 'custom field should have name'); assert.ok(testCaseWithCustomFields.customFields[0].value, 'custom field should have value'); }); it('should validate paged test case response', () => { const pagedResponse = { items: [ { id: 1, key: 'MCP-1', title: 'Test 1' }, { id: 2, key: 'MCP-2', title: 'Test 2' } ], _meta: { nextPageToken: 'token123', totalElements: 3, currentPage: 0, pageSize: 50 } }; assert.ok(Array.isArray(pagedResponse.items), 'items should be array'); assert.ok(pagedResponse._meta, 'response should have metadata'); assert.ok(typeof pagedResponse._meta.totalElements === 'number', 'totalElements should be number'); assert.equal(pagedResponse._meta.totalElements, 3, 'should match expected total for MCP'); }); }); describe('Error Handling', () => { it('should handle missing project_key', () => { const invalidParams = { case_key: 'MCP-1', format: 'json' }; assert.ok(!invalidParams.hasOwnProperty('project_key'), 'should detect missing project_key'); }); it('should handle missing case_key', () => { const invalidParams = { project_key: 'MCP', format: 'json' }; assert.ok(!invalidParams.hasOwnProperty('case_key'), 'should detect missing case_key'); }); it('should handle invalid case_key format', () => { const invalidCaseKeys = ['', 'invalid', '123', 'MCP', 'MCP-', '-4678']; invalidCaseKeys.forEach(key => { assert.ok(!key.match(/^[A-Z]+-\d+$/), `"${key}" should be invalid case key format`); }); }); it('should handle invalid suite_id', () => { const invalidSuiteIds = [0, -1, 'not-a-number', null]; invalidSuiteIds.forEach(id => { if (typeof id === 'number') { assert.ok(id <= 0, `${id} should be invalid suite_id`); } else { assert.ok(typeof id !== 'number', `${id} should not be a number`); } }); }); it('should provide helpful error messages for generate_draft_test_by_key', () => { const errorScenarios = [ { type: '500_error', message: 'Internal server error occurred', tips: 'Check Implementation Context: Ensure your implementation_context parameter contains meaningful information' }, { type: 'not_found', message: 'Test case not found', tips: 'Verify Test Case Key: Ensure MCP-1 exists in project MCP' }, { type: 'rules_engine', message: 'Rules engine configuration issue', tips: 'Set ENABLE_RULES_ENGINE=true in your .env file' } ]; errorScenarios.forEach(scenario => { assert.ok(scenario.message.length > 0, 'Error message should not be empty'); assert.ok(scenario.tips.length > 0, 'Troubleshooting tips should be provided'); }); }); it('should validate pagination error handling', () => { const MAX_PAGE_SIZE = 100; const requestedSize = 200; const shouldThrowError = requestedSize > MAX_PAGE_SIZE; assert.ok(shouldThrowError, 'Should detect page size exceeding limit'); const errorMessage = `Requested page size (${requestedSize}) exceeds configured maximum (${MAX_PAGE_SIZE})`; assert.ok(errorMessage.includes('exceeds configured maximum'), 'Error should explain the limit'); }); }); describe('Performance Considerations', () => { it('should validate large dataset handling', () => { const EXPECTED_MCP_TOTAL = 3; const MAX_PAGE_SIZE = 100; const expectedPages = Math.ceil(EXPECTED_MCP_TOTAL / MAX_PAGE_SIZE); assert.ok(expectedPages >= 1, 'Should require at least one page for all test cases'); assert.ok(expectedPages <= 50, 'Should not require excessive pagination'); }); it('should validate token-based pagination logic', () => { const paginationState = { pageToken: 'abc123', pageCount: 5, maxPages: 50 }; const shouldContinue = !!(paginationState.pageToken && paginationState.pageCount < paginationState.maxPages); assert.equal(typeof shouldContinue, 'boolean', 'shouldContinue should be boolean'); assert.ok(shouldContinue, 'Should continue when token exists and under max pages'); }); it('should validate memory-efficient processing', () => { const BATCH_SIZE = 100; const TOTAL_ITEMS = 3; const batches = Math.ceil(TOTAL_ITEMS / BATCH_SIZE); assert.ok(batches >= 1, 'Should process in at least one batch'); assert.ok(BATCH_SIZE <= 100, 'Batch size should be reasonable for memory usage'); }); }); });

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/maksimsarychau/mcp-zebrunner'

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