Skip to main content
Glama
test-execution.ts6.91 kB
import { ZephyrClient } from '../clients/zephyr-client.js'; import { executeTestSchema, getTestExecutionStatusSchema, linkTestsToIssuesSchema, generateTestReportSchema, ExecuteTestInput, GetTestExecutionStatusInput, LinkTestsToIssuesInput, GenerateTestReportInput, } from '../utils/validation.js'; let zephyrClient: ZephyrClient | null = null; const getZephyrClient = (): ZephyrClient => { if (!zephyrClient) { zephyrClient = new ZephyrClient(); } return zephyrClient; }; export const executeTest = async (input: ExecuteTestInput) => { const validatedInput = executeTestSchema.parse(input); try { const execution = await getZephyrClient().updateTestExecution({ executionId: validatedInput.executionId, status: validatedInput.status, comment: validatedInput.comment, defects: validatedInput.defects, }); return { success: true, data: { id: execution.id, key: execution.key, cycleId: execution.cycleId, testCaseId: execution.testCaseId, status: execution.status, comment: execution.comment, executedOn: execution.executedOn, executedBy: execution.executedBy?.displayName, defects: execution.defects.map(defect => ({ key: defect.key, summary: defect.summary, })), }, }; } catch (error: any) { return { success: false, error: error.response?.data?.message || error.message, }; } }; export const getTestExecutionStatus = async (input: GetTestExecutionStatusInput) => { const validatedInput = getTestExecutionStatusSchema.parse(input); try { const summary = await getZephyrClient().getTestExecutionSummary(validatedInput.cycleId); return { success: true, data: { cycleId: validatedInput.cycleId, summary: { total: summary.total, passed: summary.passed, failed: summary.failed, blocked: summary.blocked, inProgress: summary.inProgress, notExecuted: summary.notExecuted, passRate: Math.round(summary.passRate), }, progress: { completed: summary.passed + summary.failed + summary.blocked, remaining: summary.notExecuted + summary.inProgress, completionPercentage: summary.total > 0 ? Math.round(((summary.passed + summary.failed + summary.blocked) / summary.total) * 100) : 0, }, }, }; } catch (error: any) { return { success: false, error: error.response?.data?.message || error.message, }; } }; export const linkTestsToIssues = async (input: LinkTestsToIssuesInput) => { const validatedInput = linkTestsToIssuesSchema.parse(input); try { const results = []; for (const issueKey of validatedInput.issueKeys) { try { await getZephyrClient().linkTestCaseToIssue(validatedInput.testCaseId, issueKey); results.push({ issueKey, success: true, }); } catch (error: any) { results.push({ issueKey, success: false, error: error.response?.data?.message || error.message, }); } } return { success: true, data: { testCaseId: validatedInput.testCaseId, linkResults: results, successCount: results.filter(r => r.success).length, failureCount: results.filter(r => !r.success).length, }, }; } catch (error: any) { return { success: false, error: error.response?.data?.message || error.message, }; } }; export const generateTestReport = async (input: GenerateTestReportInput) => { const validatedInput = generateTestReportSchema.parse(input); try { const report = await getZephyrClient().generateTestReport(validatedInput.cycleId); if (validatedInput.format === 'HTML') { const htmlReport = generateHtmlReport(report); return { success: true, data: { format: 'HTML', content: htmlReport, generatedOn: report.generatedOn, }, }; } return { success: true, data: { format: 'JSON', content: report, generatedOn: report.generatedOn, }, }; } catch (error: any) { return { success: false, error: error.response?.data?.message || error.message, }; } }; const generateHtmlReport = (report: any) => { return ` <!DOCTYPE html> <html> <head> <title>Test Execution Report - ${report.cycleName}</title> <style> body { font-family: Arial, sans-serif; margin: 20px; } .header { background-color: #f5f5f5; padding: 20px; border-radius: 5px; } .summary { display: flex; gap: 20px; margin: 20px 0; } .metric { background-color: #e8f4f8; padding: 15px; border-radius: 5px; text-align: center; } .metric h3 { margin: 0 0 10px 0; } .metric .value { font-size: 24px; font-weight: bold; } .executions { margin-top: 30px; } .execution { padding: 10px; border-left: 4px solid #ddd; margin: 10px 0; } .execution.pass { border-left-color: #4caf50; } .execution.fail { border-left-color: #f44336; } .execution.blocked { border-left-color: #ff9800; } .execution.progress { border-left-color: #2196f3; } </style> </head> <body> <div class="header"> <h1>Test Execution Report</h1> <h2>${report.cycleName}</h2> <p>Project: ${report.projectKey}</p> <p>Generated: ${new Date(report.generatedOn).toLocaleString()}</p> </div> <div class="summary"> <div class="metric"> <h3>Total Tests</h3> <div class="value">${report.summary.total}</div> </div> <div class="metric"> <h3>Passed</h3> <div class="value">${report.summary.passed}</div> </div> <div class="metric"> <h3>Failed</h3> <div class="value">${report.summary.failed}</div> </div> <div class="metric"> <h3>Blocked</h3> <div class="value">${report.summary.blocked}</div> </div> <div class="metric"> <h3>Pass Rate</h3> <div class="value">${Math.round(report.summary.passRate)}%</div> </div> </div> <div class="executions"> <h3>Test Executions</h3> ${report.executions.map((exec: any) => ` <div class="execution ${exec.status.toLowerCase()}"> <strong>${exec.key}</strong> - ${exec.status} ${exec.comment ? `<p>${exec.comment}</p>` : ''} ${exec.defects.length > 0 ? `<p>Defects: ${exec.defects.map((d: any) => d.key).join(', ')}</p>` : ''} </div> `).join('')} </div> </body> </html> `; };

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

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