tmp-ai / index.html
anonymousatom's picture
Add 3 files
aed95dc verified
raw
history blame
78 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI TestGenX - Advanced Test Automation</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.sidebar {
transition: all 0.3s ease;
}
.chart-container {
height: 300px;
}
.animate-pulse {
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
@keyframes pulse {
0%, 100% {
opacity: 1;
}
50% {
opacity: 0.5;
}
}
.test-card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
.file-upload {
border: 2px dashed #e5e7eb;
}
.file-upload:hover {
border-color: #9ca3af;
}
</style>
</head>
<body class="bg-white">
<div id="root"></div>
<script type="text/babel">
const { useState, useEffect } = React;
function App() {
const [sidebarOpen, setSidebarOpen] = useState(true);
const [activeTab, setActiveTab] = useState('dashboard');
const [testCases, setTestCases] = useState([]);
const [isGenerating, setIsGenerating] = useState(false);
const [executionStatus, setExecutionStatus] = useState('idle');
const [testResults, setTestResults] = useState([]);
const [projectName, setProjectName] = useState('My Project');
const [aiPrompt, setAiPrompt] = useState('');
const [websiteUrl, setWebsiteUrl] = useState('');
const [uploadedFile, setUploadedFile] = useState(null);
const [isAnalyzing, setIsAnalyzing] = useState(false);
const [analysisProgress, setAnalysisProgress] = useState(0);
const [failedTestsOnly, setFailedTestsOnly] = useState(false);
const [isDebugging, setIsDebugging] = useState(false);
const [debugSuggestions, setDebugSuggestions] = useState([]);
// Mock data initialization
useEffect(() => {
const mockTestCases = [
{ id: 1, name: 'Login functionality', status: 'passed', generatedBy: 'AI', lastRun: '2 mins ago', type: 'UI' },
{ id: 2, name: 'Checkout process', status: 'failed', generatedBy: 'AI', lastRun: '5 mins ago', type: 'API', error: 'Timeout waiting for payment button' },
{ id: 3, name: 'Search feature', status: 'pending', generatedBy: 'Manual', lastRun: 'Never', type: 'UI' },
{ id: 4, name: 'User profile update', status: 'passed', generatedBy: 'AI', lastRun: '10 mins ago', type: 'UI' },
{ id: 5, name: 'Payment gateway integration', status: 'failed', generatedBy: 'AI', lastRun: 'Now', type: 'API', error: 'Invalid response from payment provider' },
];
setTestCases(mockTestCases);
const mockResults = [
{ day: 'Mon', passed: 45, failed: 5 },
{ day: 'Tue', passed: 52, failed: 3 },
{ day: 'Wed', passed: 48, failed: 7 },
{ day: 'Thu', passed: 56, failed: 2 },
{ day: 'Fri', passed: 50, failed: 4 },
{ day: 'Sat', passed: 40, failed: 1 },
{ day: 'Sun', passed: 38, failed: 2 },
];
setTestResults(mockResults);
}, []);
const generateTests = () => {
setIsGenerating(true);
// Simulate AI generation
setTimeout(() => {
const newTest = {
id: testCases.length + 1,
name: `Test case for: ${aiPrompt || 'new feature'}`,
status: 'pending',
generatedBy: 'AI',
lastRun: 'Never',
type: aiPrompt.includes('API') ? 'API' : 'UI'
};
setTestCases([...testCases, newTest]);
setIsGenerating(false);
setAiPrompt('');
}, 2000);
};
const generateFromUrl = () => {
if (!websiteUrl) return;
setIsGenerating(true);
// Simulate URL analysis and test generation
const interval = setInterval(() => {
setAnalysisProgress(prev => {
if (prev >= 100) {
clearInterval(interval);
return 100;
}
return prev + 10;
});
}, 300);
setTimeout(() => {
const newTests = [
{
id: testCases.length + 1,
name: `Homepage load test for ${websiteUrl}`,
status: 'pending',
generatedBy: 'AI',
lastRun: 'Never',
type: 'UI'
},
{
id: testCases.length + 2,
name: `Navigation menu functionality for ${websiteUrl}`,
status: 'pending',
generatedBy: 'AI',
lastRun: 'Never',
type: 'UI'
},
{
id: testCases.length + 3,
name: `Form validation for ${websiteUrl}`,
status: 'pending',
generatedBy: 'AI',
lastRun: 'Never',
type: 'UI'
}
];
setTestCases([...testCases, ...newTests]);
setIsGenerating(false);
setAnalysisProgress(0);
setWebsiteUrl('');
}, 3000);
};
const analyzeDocument = () => {
if (!uploadedFile) return;
setIsAnalyzing(true);
// Simulate document analysis
const interval = setInterval(() => {
setAnalysisProgress(prev => {
if (prev >= 100) {
clearInterval(interval);
return 100;
}
return prev + 10;
});
}, 400);
setTimeout(() => {
const newTests = [
{
id: testCases.length + 1,
name: `Test for requirement: User authentication`,
status: 'pending',
generatedBy: 'AI',
lastRun: 'Never',
type: 'UI'
},
{
id: testCases.length + 2,
name: `Test for requirement: Data validation`,
status: 'pending',
generatedBy: 'AI',
lastRun: 'Never',
type: 'API'
},
{
id: testCases.length + 3,
name: `Test for requirement: Performance thresholds`,
status: 'pending',
generatedBy: 'AI',
lastRun: 'Never',
type: 'Performance'
}
];
setTestCases([...testCases, ...newTests]);
setIsAnalyzing(false);
setAnalysisProgress(0);
setUploadedFile(null);
}, 4000);
};
const executeTests = (onlyFailed = false) => {
setExecutionStatus('running');
setFailedTestsOnly(onlyFailed);
// Simulate test execution
setTimeout(() => {
const updatedTests = testCases.map(test => {
if (onlyFailed && test.status !== 'failed') return test;
return {
...test,
status: Math.random() > 0.2 ? 'passed' : 'failed',
lastRun: 'Just now',
...(Math.random() > 0.7 ? { error: `Error code: ${Math.floor(Math.random() * 1000)}` } : {})
};
});
setTestCases(updatedTests);
setExecutionStatus('completed');
}, 3000);
};
const debugFailedTests = () => {
setIsDebugging(true);
// Simulate AI debugging
setTimeout(() => {
const suggestions = [
{
testId: 2,
suggestion: "Increase wait time for payment button from 5s to 10s",
confidence: "85%"
},
{
testId: 5,
suggestion: "Add retry logic for payment API calls (3 attempts)",
confidence: "78%"
},
{
testId: 5,
suggestion: "Verify API response schema matches documentation",
confidence: "92%"
}
];
setDebugSuggestions(suggestions);
setIsDebugging(false);
}, 2500);
};
const applyDebugSuggestion = (suggestion) => {
// Simulate applying the suggestion
const updatedTests = testCases.map(test => {
if (test.id === suggestion.testId) {
return {
...test,
status: 'pending',
lastRun: 'Never',
debugApplied: suggestion.suggestion
};
}
return test;
});
setTestCases(updatedTests);
setDebugSuggestions(debugSuggestions.filter(s => s !== suggestion));
};
const getStatusColor = (status) => {
switch (status) {
case 'passed': return 'bg-gray-100 text-gray-800 border border-green-500';
case 'failed': return 'bg-gray-100 text-gray-800 border border-red-500';
case 'running': return 'bg-gray-100 text-gray-800 border border-blue-500';
case 'pending': return 'bg-gray-100 text-gray-800 border border-yellow-500';
default: return 'bg-gray-100 text-gray-800';
}
};
const getTypeColor = (type) => {
return type === 'UI' ? 'bg-gray-100 text-gray-800 border border-gray-300' :
type === 'API' ? 'bg-gray-100 text-gray-800 border border-gray-400' :
'bg-gray-100 text-gray-800 border border-gray-500';
};
const TestChart = () => {
const maxValue = Math.max(...testResults.map(r => r.passed + r.failed));
return (
<div className="chart-container bg-white p-4 border border-gray-200 rounded">
<h3 className="text-lg font-medium mb-4 text-gray-800">Test Execution Trends</h3>
<div className="flex items-end h-48 space-x-2">
{testResults.map((result, index) => {
const total = result.passed + result.failed;
const passedHeight = (result.passed / maxValue) * 100;
const failedHeight = (result.failed / maxValue) * 100;
return (
<div key={index} className="flex flex-col items-center flex-1">
<div className="flex flex-col-reverse w-full h-40">
<div
className="bg-gray-800 rounded-t"
style={{ height: `${failedHeight}%` }}
></div>
<div
className="bg-gray-300 rounded-t"
style={{ height: `${passedHeight}%` }}
></div>
</div>
<span className="text-xs mt-2 text-gray-600">{result.day}</span>
</div>
);
})}
</div>
<div className="flex justify-center mt-4 space-x-4">
<div className="flex items-center">
<div className="w-3 h-3 bg-gray-300 rounded-full mr-1"></div>
<span className="text-xs text-gray-600">Passed</span>
</div>
<div className="flex items-center">
<div className="w-3 h-3 bg-gray-800 rounded-full mr-1"></div>
<span className="text-xs text-gray-600">Failed</span>
</div>
</div>
</div>
);
};
return (
<div className="flex h-screen overflow-hidden bg-white">
{/* Sidebar */}
<div className={`sidebar ${sidebarOpen ? 'w-64' : 'w-20'} bg-black text-white transition-all duration-300 flex flex-col`}>
<div className="p-4 flex items-center justify-between border-b border-gray-800">
{sidebarOpen ? (
<h1 className="text-xl font-bold text-white">AI TestGenX</h1>
) : (
<div className="w-8 h-8 bg-white rounded-full flex items-center justify-center">
<i className="fas fa-robot text-black"></i>
</div>
)}
<button
onClick={() => setSidebarOpen(!sidebarOpen)}
className="text-gray-400 hover:text-white"
>
<i className={`fas ${sidebarOpen ? 'fa-times' : 'fa-bars'}`}></i>
</button>
</div>
<nav className="flex-1 p-4 space-y-2">
<button
onClick={() => setActiveTab('dashboard')}
className={`w-full flex items-center p-3 rounded ${activeTab === 'dashboard' ? 'bg-gray-800 text-white' : 'hover:bg-gray-800 text-gray-300'}`}
>
<i className="fas fa-tachometer-alt mr-3"></i>
{sidebarOpen && <span>Dashboard</span>}
</button>
<button
onClick={() => setActiveTab('tests')}
className={`w-full flex items-center p-3 rounded ${activeTab === 'tests' ? 'bg-gray-800 text-white' : 'hover:bg-gray-800 text-gray-300'}`}
>
<i className="fas fa-vial mr-3"></i>
{sidebarOpen && <span>Test Cases</span>}
</button>
<button
onClick={() => setActiveTab('generator')}
className={`w-full flex items-center p-3 rounded ${activeTab === 'generator' ? 'bg-gray-800 text-white' : 'hover:bg-gray-800 text-gray-300'}`}
>
<i className="fas fa-magic mr-3"></i>
{sidebarOpen && <span>AI Generator</span>}
</button>
<button
onClick={() => setActiveTab('execution')}
className={`w-full flex items-center p-3 rounded ${activeTab === 'execution' ? 'bg-gray-800 text-white' : 'hover:bg-gray-800 text-gray-300'}`}
>
<i className="fas fa-play-circle mr-3"></i>
{sidebarOpen && <span>Execution</span>}
</button>
<button
onClick={() => setActiveTab('reports')}
className={`w-full flex items-center p-3 rounded ${activeTab === 'reports' ? 'bg-gray-800 text-white' : 'hover:bg-gray-800 text-gray-300'}`}
>
<i className="fas fa-chart-bar mr-3"></i>
{sidebarOpen && <span>Reports</span>}
</button>
</nav>
<div className="p-4 border-t border-gray-800">
<div className="flex items-center">
<div className="w-10 h-10 rounded-full bg-gray-700 flex items-center justify-center">
<i className="fas fa-user text-gray-300"></i>
</div>
{sidebarOpen && (
<div className="ml-3">
<p className="text-sm font-medium text-white">John Doe</p>
<p className="text-xs text-gray-400">Admin</p>
</div>
)}
</div>
</div>
</div>
{/* Main Content */}
<div className="flex-1 overflow-auto">
{/* Header */}
<header className="bg-white border-b border-gray-200">
<div className="px-6 py-4 flex justify-between items-center">
<h2 className="text-xl font-medium text-gray-900">
{activeTab === 'dashboard' && 'Dashboard'}
{activeTab === 'tests' && 'Test Cases'}
{activeTab === 'generator' && 'AI Test Generator'}
{activeTab === 'execution' && 'Test Execution'}
{activeTab === 'reports' && 'Test Reports'}
</h2>
<div className="flex items-center space-x-4">
<div className="relative">
<input
type="text"
placeholder="Search..."
className="pl-10 pr-4 py-2 border border-gray-300 rounded focus:outline-none focus:ring-1 focus:ring-gray-400 focus:border-gray-400 bg-white"
/>
<i className="fas fa-search absolute left-3 top-3 text-gray-400"></i>
</div>
<button className="p-2 text-gray-600 hover:text-gray-900">
<i className="fas fa-bell"></i>
</button>
</div>
</div>
</header>
{/* Content Area */}
<main className="p-6 bg-gray-50">
{activeTab === 'dashboard' && (
<div className="space-y-6">
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<div className="bg-white p-6 border border-gray-200 rounded">
<div className="flex justify-between items-start">
<div>
<p className="text-sm text-gray-600">Total Test Cases</p>
<h3 className="text-2xl font-semibold mt-2 text-gray-800">{testCases.length}</h3>
</div>
<div className="bg-gray-100 p-3 rounded-full">
<i className="fas fa-vial text-gray-600"></i>
</div>
</div>
</div>
<div className="bg-white p-6 border border-gray-200 rounded">
<div className="flex justify-between items-start">
<div>
<p className="text-sm text-gray-600">Passed Tests</p>
<h3 className="text-2xl font-semibold mt-2 text-gray-800">
{testCases.filter(t => t.status === 'passed').length}
</h3>
</div>
<div className="bg-gray-100 p-3 rounded-full text-green-500">
<i className="fas fa-check-circle"></i>
</div>
</div>
</div>
<div className="bg-white p-6 border border-gray-200 rounded">
<div className="flex justify-between items-start">
<div>
<p className="text-sm text-gray-600">Failed Tests</p>
<h3 className="text-2xl font-semibold mt-2 text-gray-800">
{testCases.filter(t => t.status === 'failed').length}
</h3>
</div>
<div className="bg-gray-100 p-3 rounded-full text-red-500">
<i className="fas fa-times-circle"></i>
</div>
</div>
</div>
</div>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
<TestChart />
<div className="bg-white p-6 border border-gray-200 rounded">
<h3 className="text-lg font-medium mb-4 text-gray-800">Recent Activities</h3>
<div className="space-y-4">
{testCases.slice(0, 5).map(test => (
<div key={test.id} className="flex items-start">
<div className={`p-2 rounded-full mr-3 ${getStatusColor(test.status)}`}>
{test.status === 'passed' && <i className="fas fa-check text-green-500"></i>}
{test.status === 'failed' && <i className="fas fa-times text-red-500"></i>}
{test.status === 'running' && <i className="fas fa-sync-alt fa-spin text-blue-500"></i>}
{test.status === 'pending' && <i className="fas fa-clock text-yellow-500"></i>}
</div>
<div className="flex-1">
<p className="font-medium text-gray-800">{test.name}</p>
<p className="text-sm text-gray-500">
{test.generatedBy === 'AI' ? 'AI Generated' : 'Manual'} • {test.lastRun}
</p>
</div>
<span className={`text-xs px-2 py-1 rounded ${getTypeColor(test.type)}`}>
{test.type}
</span>
</div>
))}
</div>
</div>
</div>
</div>
)}
{activeTab === 'tests' && (
<div className="bg-white border border-gray-200 rounded overflow-hidden">
<div className="p-4 border-b border-gray-200 flex justify-between items-center">
<h3 className="text-lg font-medium text-gray-800">All Test Cases</h3>
<div className="flex space-x-3">
<button
onClick={() => setActiveTab('generator')}
className="flex items-center px-4 py-2 bg-black text-white rounded hover:bg-gray-800"
>
<i className="fas fa-plus mr-2"></i>
<span>Generate with AI</span>
</button>
<button className="flex items-center px-4 py-2 border border-gray-300 rounded hover:bg-gray-50">
<i className="fas fa-filter mr-2"></i>
<span>Filter</span>
</button>
</div>
</div>
<div className="overflow-x-auto">
<table className="min-w-full divide-y divide-gray-200">
<thead className="bg-gray-50">
<tr>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Name</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Type</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Generated By</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Last Run</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Actions</th>
</tr>
</thead>
<tbody className="bg-white divide-y divide-gray-200">
{testCases.map(test => (
<tr key={test.id} className="hover:bg-gray-50">
<td className="px-6 py-4 whitespace-nowrap">
<div className="flex items-center">
<div className="flex-shrink-0 h-10 w-10 bg-gray-100 rounded-full flex items-center justify-center">
<i className="fas fa-vial text-gray-600"></i>
</div>
<div className="ml-4">
<div className="text-sm font-medium text-gray-900">{test.name}</div>
{test.debugApplied && (
<div className="text-xs text-gray-500 mt-1">
<i className="fas fa-lightbulb text-yellow-500 mr-1"></i>
{test.debugApplied}
</div>
)}
</div>
</div>
</td>
<td className="px-6 py-4 whitespace-nowrap">
<span className={`px-2 inline-flex text-xs leading-5 font-semibold rounded ${getTypeColor(test.type)}`}>
{test.type}
</span>
</td>
<td className="px-6 py-4 whitespace-nowrap">
<span className={`px-2 inline-flex text-xs leading-5 font-semibold rounded ${getStatusColor(test.status)}`}>
{test.status}
</span>
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{test.generatedBy === 'AI' ? (
<span className="flex items-center">
<i className="fas fa-robot text-gray-600 mr-1"></i>
AI
</span>
) : 'Manual'}
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{test.lastRun}</td>
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium">
<button className="text-gray-600 hover:text-gray-900 mr-3">
<i className="fas fa-play"></i>
</button>
<button className="text-gray-600 hover:text-gray-900 mr-3">
<i className="fas fa-edit"></i>
</button>
<button className="text-gray-600 hover:text-gray-900">
<i className="fas fa-trash"></i>
</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
)}
{activeTab === 'generator' && (
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
<div className="lg:col-span-2 space-y-6">
<div className="bg-white p-6 border border-gray-200 rounded">
<h3 className="text-xl font-medium mb-4 text-gray-800">AI Test Generator</h3>
<div className="mb-6">
<label className="block text-sm font-medium text-gray-700 mb-2">Project Name</label>
<input
type="text"
value={projectName}
onChange={(e) => setProjectName(e.target.value)}
className="w-full px-4 py-2 border border-gray-300 rounded focus:ring-1 focus:ring-gray-400 focus:border-gray-400"
/>
</div>
<div className="mb-6">
<label className="block text-sm font-medium text-gray-700 mb-2">
Describe what you want to test
</label>
<textarea
value={aiPrompt}
onChange={(e) => setAiPrompt(e.target.value)}
rows="5"
placeholder="Example: 'Generate UI tests for login page with email and password fields, including validation for incorrect credentials'"
className="w-full px-4 py-2 border border-gray-300 rounded focus:ring-1 focus:ring-gray-400 focus:border-gray-400"
></textarea>
</div>
<div className="flex justify-end">
<button
onClick={generateTests}
disabled={isGenerating}
className="px-6 py-3 bg-black text-white rounded hover:bg-gray-800 disabled:opacity-50 flex items-center"
>
{isGenerating ? (
<>
<i className="fas fa-spinner fa-spin mr-2"></i>
Generating...
</>
) : (
<>
<i className="fas fa-magic mr-2"></i>
Generate Test Cases
</>
)}
</button>
</div>
</div>
<div className="bg-white p-6 border border-gray-200 rounded">
<h3 className="text-xl font-medium mb-4 text-gray-800">Generate from Website URL</h3>
<div className="mb-6">
<label className="block text-sm font-medium text-gray-700 mb-2">Website URL</label>
<input
type="url"
value={websiteUrl}
onChange={(e) => setWebsiteUrl(e.target.value)}
placeholder="https://example.com"
className="w-full px-4 py-2 border border-gray-300 rounded focus:ring-1 focus:ring-gray-400 focus:border-gray-400"
/>
</div>
{isGenerating && (
<div className="mb-4">
<div className="flex justify-between mb-1">
<span className="text-sm font-medium text-gray-700">Analyzing website...</span>
<span className="text-sm font-medium text-gray-700">{analysisProgress}%</span>
</div>
<div className="w-full bg-gray-200 rounded-full h-2.5">
<div
className="bg-gray-800 h-2.5 rounded-full"
style={{ width: `${analysisProgress}%` }}
></div>
</div>
</div>
)}
<div className="flex justify-end">
<button
onClick={generateFromUrl}
disabled={isGenerating || !websiteUrl}
className="px-6 py-3 bg-black text-white rounded hover:bg-gray-800 disabled:opacity-50 flex items-center"
>
{isGenerating ? (
<>
<i className="fas fa-spinner fa-spin mr-2"></i>
Analyzing...
</>
) : (
<>
<i className="fas fa-globe mr-2"></i>
Generate from URL
</>
)}
</button>
</div>
</div>
<div className="bg-white p-6 border border-gray-200 rounded">
<h3 className="text-xl font-medium mb-4 text-gray-800">Generate from Business Requirements</h3>
<div className="mb-6">
<label className="block text-sm font-medium text-gray-700 mb-2">Upload Document</label>
<div className="file-upload rounded-lg p-8 text-center cursor-pointer hover:bg-gray-50 transition-colors">
{uploadedFile ? (
<div className="flex items-center justify-center">
<i className="fas fa-file-alt text-gray-500 mr-2"></i>
<span className="text-gray-700">{uploadedFile.name}</span>
<button
onClick={(e) => {
e.stopPropagation();
setUploadedFile(null);
}}
className="ml-2 text-gray-500 hover:text-gray-700"
>
<i className="fas fa-times"></i>
</button>
</div>
) : (
<div>
<i className="fas fa-cloud-upload-alt text-gray-400 text-4xl mb-2"></i>
<p className="text-sm text-gray-500 mb-1">Drag & drop your document here</p>
<p className="text-xs text-gray-400">or click to browse (PDF, DOCX, TXT)</p>
<input
type="file"
className="hidden"
id="file-upload"
onChange={(e) => setUploadedFile(e.target.files[0])}
/>
<label
htmlFor="file-upload"
className="inline-block mt-3 px-4 py-2 bg-gray-100 text-gray-700 rounded hover:bg-gray-200 cursor-pointer"
>
Select File
</label>
</div>
)}
</div>
</div>
{isAnalyzing && (
<div className="mb-4">
<div className="flex justify-between mb-1">
<span className="text-sm font-medium text-gray-700">Analyzing document...</span>
<span className="text-sm font-medium text-gray-700">{analysisProgress}%</span>
</div>
<div className="w-full bg-gray-200 rounded-full h-2.5">
<div
className="bg-gray-800 h-2.5 rounded-full"
style={{ width: `${analysisProgress}%` }}
></div>
</div>
</div>
)}
<div className="flex justify-end">
<button
onClick={analyzeDocument}
disabled={isAnalyzing || !uploadedFile}
className="px-6 py-3 bg-black text-white rounded hover:bg-gray-800 disabled:opacity-50 flex items-center"
>
{isAnalyzing ? (
<>
<i className="fas fa-spinner fa-spin mr-2"></i>
Processing...
</>
) : (
<>
<i className="fas fa-file-import mr-2"></i>
Generate from Document
</>
)}
</button>
</div>
</div>
</div>
<div className="bg-white p-6 border border-gray-200 rounded">
<h3 className="text-xl font-medium mb-4 text-gray-800">AI Suggestions</h3>
<div className="space-y-4">
<div
className="p-4 border border-gray-200 rounded cursor-pointer hover:bg-gray-50 transition-colors"
onClick={() => setAiPrompt("Generate UI tests for login page with email and password fields, including validation for incorrect credentials")}
>
<h4 className="font-medium text-gray-800">Login Page Tests</h4>
<p className="text-sm text-gray-600 mt-1">Comprehensive UI tests for login functionality</p>
</div>
<div
className="p-4 border border-gray-200 rounded cursor-pointer hover:bg-gray-50 transition-colors"
onClick={() => setAiPrompt("Create API tests for user registration endpoint with validation for required fields")}
>
<h4 className="font-medium text-gray-800">Registration API Tests</h4>
<p className="text-sm text-gray-600 mt-1">Endpoint validation and error handling</p>
</div>
<div
className="p-4 border border-gray-200 rounded cursor-pointer hover:bg-gray-50 transition-colors"
onClick={() => setAiPrompt("Generate performance tests for product search functionality with 100 concurrent users")}
>
<h4 className="font-medium text-gray-800">Performance Tests</h4>
<p className="text-sm text-gray-600 mt-1">Load testing for critical features</p>
</div>
<div
className="p-4 border border-gray-200 rounded cursor-pointer hover:bg-gray-50 transition-colors"
onClick={() => setAiPrompt("Create accessibility tests for homepage to check WCAG 2.1 AA compliance")}
>
<h4 className="font-medium text-gray-800">Accessibility Tests</h4>
<p className="text-sm text-gray-600 mt-1">WCAG compliance validation</p>
</div>
</div>
</div>
</div>
)}
{activeTab === 'execution' && (
<div className="space-y-6">
<div className="bg-white p-6 border border-gray-200 rounded">
<div className="flex justify-between items-center mb-6">
<h3 className="text-xl font-medium text-gray-800">Test Execution</h3>
<div className="flex space-x-3">
<button
onClick={() => executeTests(false)}
disabled={executionStatus === 'running' || testCases.length === 0}
className={`px-4 py-2 rounded flex items-center ${executionStatus === 'running' && !failedTestsOnly ? 'bg-gray-800 text-white' : 'bg-black text-white hover:bg-gray-800'} disabled:opacity-50`}
>
{executionStatus === 'running' && !failedTestsOnly ? (
<>
<i className="fas fa-sync-alt fa-spin mr-2"></i>
Running Tests...
</>
) : (
<>
<i className="fas fa-play mr-2"></i>
Run All Tests
</>
)}
</button>
<button
onClick={() => executeTests(true)}
disabled={executionStatus === 'running' || testCases.filter(t => t.status === 'failed').length === 0}
className={`px-4 py-2 rounded flex items-center ${executionStatus === 'running' && failedTestsOnly ? 'bg-gray-800 text-white' : 'bg-gray-700 text-white hover:bg-gray-600'} disabled:opacity-50`}
>
{executionStatus === 'running' && failedTestsOnly ? (
<>
<i className="fas fa-sync-alt fa-spin mr-2"></i>
Debugging...
</>
) : (
<>
<i className="fas fa-bug mr-2"></i>
Debug Failed Only
</>
)}
</button>
<button
onClick={debugFailedTests}
disabled={isDebugging || testCases.filter(t => t.status === 'failed').length === 0}
className="px-4 py-2 border border-gray-300 rounded hover:bg-gray-50 flex items-center disabled:opacity-50"
>
{isDebugging ? (
<>
<i className="fas fa-spinner fa-spin mr-2"></i>
Analyzing...
</>
) : (
<>
<i className="fas fa-lightbulb mr-2"></i>
AI Debug Suggestions
</>
)}
</button>
</div>
</div>
{debugSuggestions.length > 0 && (
<div className="mb-6 bg-gray-50 p-4 rounded border border-gray-200">
<h4 className="font-medium text-gray-800 mb-3 flex items-center">
<i className="fas fa-robot text-gray-600 mr-2"></i>
AI Debugging Suggestions
</h4>
<div className="space-y-3">
{debugSuggestions.map((suggestion, index) => (
<div key={index} className="flex justify-between items-center p-3 bg-white border border-gray-200 rounded">
<div>
<p className="font-medium text-gray-800">
Test #{suggestion.testId}: {suggestion.suggestion}
</p>
<p className="text-xs text-gray-500 mt-1">
Confidence: {suggestion.confidence}
</p>
</div>
<button
onClick={() => applyDebugSuggestion(suggestion)}
className="px-3 py-1 bg-black text-white text-sm rounded hover:bg-gray-800"
>
Apply
</button>
</div>
))}
</div>
</div>
)}
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
<div className="border border-gray-200 rounded p-4">
<div className="flex justify-between items-center">
<div>
<p className="text-sm text-gray-600">Total to Run</p>
<p className="text-xl font-semibold text-gray-800">
{failedTestsOnly ?
testCases.filter(t => t.status === 'failed').length :
testCases.length}
</p>
</div>
<div className="bg-gray-100 p-3 rounded-full">
<i className="fas fa-list text-gray-600"></i>
</div>
</div>
</div>
<div className="border border-gray-200 rounded p-4">
<div className="flex justify-between items-center">
<div>
<p className="text-sm text-gray-600">Currently Running</p>
<p className="text-xl font-semibold text-blue-500">
{executionStatus === 'running' ? testCases.filter(t => t.status === 'running').length : 0}
</p>
</div>
<div className="bg-gray-100 p-3 rounded-full text-blue-500">
<i className="fas fa-sync-alt"></i>
</div>
</div>
</div>
<div className="border border-gray-200 rounded p-4">
<div className="flex justify-between items-center">
<div>
<p className="text-sm text-gray-600">Estimated Time</p>
<p className="text-xl font-semibold text-gray-800">
~{failedTestsOnly ?
testCases.filter(t => t.status === 'failed').length * 2 :
testCases.length * 2}s
</p>
</div>
<div className="bg-gray-100 p-3 rounded-full text-gray-600">
<i className="fas fa-clock"></i>
</div>
</div>
</div>
</div>
<div className="overflow-x-auto">
<table className="min-w-full divide-y divide-gray-200">
<thead className="bg-gray-50">
<tr>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Test Case</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Progress</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Duration</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Details</th>
</tr>
</thead>
<tbody className="bg-white divide-y divide-gray-200">
{testCases
.filter(test => !failedTestsOnly || test.status === 'failed')
.map(test => (
<tr key={test.id}>
<td className="px-6 py-4 whitespace-nowrap">
<div className="text-sm font-medium text-gray-900">{test.name}</div>
<div className="text-sm text-gray-500">{test.type}</div>
{test.error && (
<div className="text-xs text-red-500 mt-1">
<i className="fas fa-exclamation-circle mr-1"></i>
{test.error}
</div>
)}
</td>
<td className="px-6 py-4 whitespace-nowrap">
<span className={`px-2 inline-flex text-xs leading-5 font-semibold rounded ${getStatusColor(test.status)}`}>
{test.status}
</span>
</td>
<td className="px-6 py-4 whitespace-nowrap">
{test.status === 'running' ? (
<div className="w-full bg-gray-200 rounded-full h-2">
<div
className="bg-blue-500 h-2 rounded-full animate-pulse"
style={{ width: '45%' }}
></div>
</div>
) : test.status === 'pending' ? (
<div className="w-full bg-gray-200 rounded-full h-2"></div>
) : (
<div className="w-full bg-gray-200 rounded-full h-2">
<div
className={`h-2 rounded-full ${test.status === 'passed' ? 'bg-green-500' : 'bg-red-500'}`}
style={{ width: '100%' }}
></div>
</div>
)}
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{test.status === 'running' ? 'In progress' :
test.status === 'pending' ? '--' : '2.4s'}
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium">
<button className="text-gray-600 hover:text-gray-900">
View Logs
</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
)}
{activeTab === 'reports' && (
<div className="space-y-6">
<div className="bg-white p-6 border border-gray-200 rounded">
<h3 className="text-xl font-medium mb-6 text-gray-800">Test Reports</h3>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
<div className="border border-gray-200 rounded p-4">
<div className="flex justify-between">
<div>
<p className="text-sm text-gray-600">Total Executions</p>
<p className="text-xl font-semibold text-gray-800">127</p>
</div>
<div className="text-green-500">
<i className="fas fa-arrow-up"></i> 12%
</div>
</div>
<div className="mt-3 h-1 bg-gray-200 rounded-full">
<div className="h-1 bg-gray-800 rounded-full" style={{ width: '70%' }}></div>
</div>
</div>
<div className="border border-gray-200 rounded p-4">
<div className="flex justify-between">
<div>
<p className="text-sm text-gray-600">Pass Rate</p>
<p className="text-xl font-semibold text-gray-800">92%</p>
</div>
<div className="text-green-500">
<i className="fas fa-arrow-up"></i> 5%
</div>
</div>
<div className="mt-3 h-1 bg-gray-200 rounded-full">
<div className="h-1 bg-gray-300 rounded-full" style={{ width: '92%' }}></div>
</div>
</div>
<div className="border border-gray-200 rounded p-4">
<div className="flex justify-between">
<div>
<p className="text-sm text-gray-600">Flaky Tests</p>
<p className="text-xl font-semibold text-gray-800">4</p>
</div>
<div className="text-red-500">
<i className="fas fa-arrow-down"></i> 2
</div>
</div>
<div className="mt-3 h-1 bg-gray-200 rounded-full">
<div className="h-1 bg-yellow-500 rounded-full" style={{ width: '15%' }}></div>
</div>
</div>
<div className="border border-gray-200 rounded p-4">
<div className="flex justify-between">
<div>
<p className="text-sm text-gray-600">Avg. Duration</p>
<p className="text-xl font-semibold text-gray-800">3.2s</p>
</div>
<div className="text-green-500">
<i className="fas fa-arrow-down"></i> 0.8s
</div>
</div>
<div className="mt-3 h-1 bg-gray-200 rounded-full">
<div className="h-1 bg-blue-500 rounded-full" style={{ width: '40%' }}></div>
</div>
</div>
</div>
<TestChart />
<div className="mt-8">
<h4 className="text-lg font-medium mb-4 text-gray-800">Failed Tests Analysis</h4>
<div className="bg-gray-50 border border-gray-200 rounded p-4">
<div className="flex items-start">
<div className="bg-gray-100 p-3 rounded-full mr-4">
<i className="fas fa-exclamation-triangle text-gray-600"></i>
</div>
<div>
<h5 className="font-medium text-gray-800">Most Common Failure Patterns</h5>
<ul className="mt-2 space-y-2">
<li className="flex items-center">
<span className="w-2 h-2 bg-gray-800 rounded-full mr-2"></span>
<span>Timeout waiting for elements (42%)</span>
</li>
<li className="flex items-center">
<span className="w-2 h-2 bg-gray-800 rounded-full mr-2"></span>
<span>API response validation (33%)</span>
</li>
<li className="flex items-center">
<span className="w-2 h-2 bg-gray-800 rounded-full mr-2"></span>
<span>State management issues (25%)</span>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
)}
</main>
</div>
</div>
);
}
ReactDOM.render(<App />, document.getElementById('root'));
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=anonymousatom/tmp-ai" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>