test_results_viewer.html•9.99 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test Results</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
background-color: #f4f7f9;
color: #333;
margin: 0;
padding: 20px;
}
h1, h2, h3 {
color: #2c3e50;
}
h1 {
text-align: center;
margin-bottom: 30px;
}
#summary {
background-color: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
margin-bottom: 30px;
}
#results-container {
display: flex;
flex-direction: column;
gap: 20px;
}
.test-group {
background-color: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.module-group {
background-color: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
margin-bottom: 20px;
}
.module-group > h2 {
color: #1976d2;
border-bottom: 2px solid #e3f2fd;
padding-bottom: 10px;
margin-bottom: 20px;
}
.test-group {
background-color: #f8f9fa;
padding: 15px;
border-radius: 6px;
margin-bottom: 15px;
border-left: 4px solid #2196f3;
}
.test-group > h3 {
color: #2c3e50;
margin-top: 0;
margin-bottom: 15px;
}
.model-group {
margin-top: 15px;
padding-left: 20px;
border-left: 3px solid #e0e0e0;
}
.model-group > h4 {
color: #555;
margin-bottom: 10px;
}
.run-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 15px;
margin-top: 10px;
}
.test-run {
padding: 15px;
border-radius: 6px;
border: 1px solid;
}
.test-run.success {
background-color: #e8f5e9;
border-color: #4caf50;
}
.test-run.failure {
background-color: #ffebee;
border-color: #f44336;
}
.test-run h4 {
margin-top: 0;
}
.test-run h5 {
margin-top: 0;
margin-bottom: 10px;
color: #333;
font-size: 14px;
}
.failure-reason {
color: #c62828;
font-family: monospace;
white-space: pre-wrap;
background: #fff0f0;
padding: 5px;
border-radius: 4px;
}
details {
margin-top: 10px;
}
summary {
cursor: pointer;
font-weight: bold;
}
.tools-content, .agent-result {
margin-top: 10px;
background: #fdfdfd;
padding: 10px;
border-radius: 4px;
border: 1px solid #eee;
}
pre {
white-space: pre-wrap;
word-wrap: break-word;
font-size: 13px;
}
code {
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
}
</style>
</head>
<body>
<h1>MCP E2E Test Results</h1>
<div id="summary">
<h2>Summary</h2>
<p>Total Tests Run: <span id="total-tests"></span></p>
<p>Success Rate: <span id="success-rate"></span>%</p>
</div>
<div id="results-container"></div>
<script>
document.addEventListener('DOMContentLoaded', () => {
fetch('test_results.json')
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
renderResults(data);
})
.catch(error => {
console.error('Error fetching or parsing test_results.json:', error);
document.getElementById('results-container').innerHTML = '<p style="color: red;">Could not load test results. Please ensure test_results.json is in the same directory and is valid JSON.</p>';
});
});
function renderResults(data) {
const container = document.getElementById('results-container');
if (!data || data.length === 0) {
container.innerHTML = '<p>No test results found.</p>';
return;
}
// Calculate summary
const totalRuns = data.length;
const successfulRuns = data.filter(run => run.status === 'success').length;
const successRate = totalRuns > 0 ? (successfulRuns / totalRuns * 100).toFixed(2) : 0;
document.getElementById('total-tests').textContent = totalRuns;
document.getElementById('success-rate').textContent = successRate;
// Group first by module, then by test name
const groupedByModule = data.reduce((acc, run) => {
const moduleName = run.module_name || 'Unknown Module';
const testName = run.test_name;
if (!acc[moduleName]) {
acc[moduleName] = {};
}
if (!acc[moduleName][testName]) {
acc[moduleName][testName] = [];
}
acc[moduleName][testName].push(run);
return acc;
}, {});
// Render modules
for (const moduleName in groupedByModule) {
const moduleGroupEl = document.createElement('div');
moduleGroupEl.className = 'module-group';
moduleGroupEl.innerHTML = `<h2>${moduleName}</h2>`;
const tests = groupedByModule[moduleName];
for (const testName in tests) {
const testGroupEl = document.createElement('div');
testGroupEl.className = 'test-group';
testGroupEl.innerHTML = `<h3>${testName}</h3>`;
const groupedByModel = tests[testName].reduce((acc, run) => {
const modelName = run.model_name;
if (!acc[modelName]) {
acc[modelName] = [];
}
acc[modelName].push(run);
return acc;
}, {});
for (const modelName in groupedByModel) {
const modelGroupEl = document.createElement('div');
modelGroupEl.className = 'model-group';
modelGroupEl.innerHTML = `<h4>${modelName}</h4>`;
const runGridEl = document.createElement('div');
runGridEl.className = 'run-grid';
groupedByModel[modelName].forEach(run => {
const runEl = document.createElement('div');
runEl.className = `test-run ${run.status}`;
let runContent = `<h5>Run ${run.run_number} - ${run.status.toUpperCase()}</h5>`;
if (run.status === 'failure' && run.failure_reason) {
runContent += `<p><strong>Failure Reason:</strong></p><pre class="failure-reason"><code>${escapeHtml(run.failure_reason)}</code></pre>`;
}
runContent += `
<details>
<summary>Agent Result</summary>
<div class="agent-result"><pre><code>${escapeHtml(run.agent_result || 'No result')}</code></pre></div>
</details>
`;
if (run.tools_used && run.tools_used.length > 0) {
runContent += `
<details>
<summary>Tools Used (${run.tools_used.length})</summary>
<div class="tools-content">
<pre><code>${escapeHtml(JSON.stringify(run.tools_used, null, 2))}</code></pre>
</div>
</details>
`;
} else {
runContent += `<p>No tools were used.</p>`;
}
runEl.innerHTML = runContent;
runGridEl.appendChild(runEl);
});
modelGroupEl.appendChild(runGridEl);
testGroupEl.appendChild(modelGroupEl);
}
moduleGroupEl.appendChild(testGroupEl);
}
container.appendChild(moduleGroupEl);
}
}
function escapeHtml(unsafe) {
if (unsafe === null || typeof unsafe === 'undefined') {
return '';
}
return unsafe
.toString()
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
</script>
</body>
</html>