Files
Sankofa/portal/src/app/developer/webhooks/test/page.tsx
defiQUG 9daf1fd378 Apply Composer changes: comprehensive API updates, migrations, middleware, and infrastructure improvements
- Add comprehensive database migrations (001-024) for schema evolution
- Enhance API schema with expanded type definitions and resolvers
- Add new middleware: audit logging, rate limiting, MFA enforcement, security, tenant auth
- Implement new services: AI optimization, billing, blockchain, compliance, marketplace
- Add adapter layer for cloud integrations (Cloudflare, Kubernetes, Proxmox, storage)
- Update Crossplane provider with enhanced VM management capabilities
- Add comprehensive test suite for API endpoints and services
- Update frontend components with improved GraphQL subscriptions and real-time updates
- Enhance security configurations and headers (CSP, CORS, etc.)
- Update documentation and configuration files
- Add new CI/CD workflows and validation scripts
- Implement design system improvements and UI enhancements
2025-12-12 18:01:35 -08:00

192 lines
7.0 KiB
TypeScript

'use client';
import { useState } from 'react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/Card';
import { Send, CheckCircle, XCircle, Clock } from 'lucide-react';
export default function WebhookTestingPage() {
const [url, setUrl] = useState('');
const [method, setMethod] = useState('POST');
const [headers, setHeaders] = useState('{"Content-Type": "application/json"}');
const [payload, setPayload] = useState('{"event": "test", "data": {}}');
const [testResult, setTestResult] = useState<any>(null);
const [isTesting, setIsTesting] = useState(false);
const testWebhook = async () => {
setIsTesting(true);
setTestResult(null);
try {
const startTime = Date.now();
const response = await fetch('/api/webhooks/test', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
url,
method,
headers: JSON.parse(headers),
payload: JSON.parse(payload),
}),
});
const endTime = Date.now();
const data = await response.json();
setTestResult({
success: response.ok,
status: response.status,
statusText: response.statusText,
responseTime: endTime - startTime,
response: data,
timestamp: new Date().toISOString(),
});
} catch (error: any) {
setTestResult({
success: false,
error: error.message,
timestamp: new Date().toISOString(),
});
} finally {
setIsTesting(false);
}
};
return (
<div className="container mx-auto px-4 py-8">
<div className="mb-8">
<h1 className="text-3xl font-bold text-white mb-2">Webhook Testing Tool</h1>
<p className="text-gray-400">Test your webhook endpoints before configuring them</p>
</div>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
<Card className="bg-gray-800 border-gray-700">
<CardHeader>
<CardTitle className="text-white">Webhook Configuration</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div>
<label className="block text-sm text-gray-300 mb-2">Webhook URL</label>
<input
type="url"
value={url}
onChange={(e) => setUrl(e.target.value)}
placeholder="https://example.com/webhook"
className="w-full px-4 py-2 bg-gray-900 border border-gray-700 rounded text-white"
/>
</div>
<div>
<label className="block text-sm text-gray-300 mb-2">HTTP Method</label>
<select
value={method}
onChange={(e) => setMethod(e.target.value)}
className="w-full px-4 py-2 bg-gray-900 border border-gray-700 rounded text-white"
>
<option value="POST">POST</option>
<option value="GET">GET</option>
<option value="PUT">PUT</option>
<option value="PATCH">PATCH</option>
<option value="DELETE">DELETE</option>
</select>
</div>
<div>
<label className="block text-sm text-gray-300 mb-2">Headers (JSON)</label>
<textarea
value={headers}
onChange={(e) => setHeaders(e.target.value)}
className="w-full h-24 px-4 py-2 bg-gray-900 border border-gray-700 rounded text-white font-mono text-sm"
placeholder='{"Content-Type": "application/json"}'
/>
</div>
<div>
<label className="block text-sm text-gray-300 mb-2">Payload (JSON)</label>
<textarea
value={payload}
onChange={(e) => setPayload(e.target.value)}
className="w-full h-32 px-4 py-2 bg-gray-900 border border-gray-700 rounded text-white font-mono text-sm"
placeholder='{"event": "test", "data": {}}'
/>
</div>
<button
onClick={testWebhook}
disabled={!url || isTesting}
className="w-full px-6 py-3 bg-orange-500 text-white rounded-lg hover:bg-orange-600 transition-colors disabled:opacity-50 flex items-center justify-center gap-2"
>
<Send className="h-4 w-4" />
{isTesting ? 'Testing...' : 'Test Webhook'}
</button>
</CardContent>
</Card>
<Card className="bg-gray-800 border-gray-700">
<CardHeader>
<CardTitle className="text-white">Test Results</CardTitle>
</CardHeader>
<CardContent>
{!testResult ? (
<div className="text-center py-12 text-gray-400">
<p>Test results will appear here</p>
</div>
) : (
<div className="space-y-4">
<div className="flex items-center gap-2">
{testResult.success ? (
<CheckCircle className="h-5 w-5 text-green-400" />
) : (
<XCircle className="h-5 w-5 text-red-400" />
)}
<span className={`font-semibold ${testResult.success ? 'text-green-400' : 'text-red-400'}`}>
{testResult.success ? 'Success' : 'Failed'}
</span>
</div>
{testResult.status && (
<div>
<p className="text-sm text-gray-400 mb-1">Status</p>
<p className="text-white font-mono">
{testResult.status} {testResult.statusText}
</p>
</div>
)}
{testResult.responseTime && (
<div>
<p className="text-sm text-gray-400 mb-1">Response Time</p>
<p className="text-white font-mono">{testResult.responseTime}ms</p>
</div>
)}
{testResult.timestamp && (
<div>
<p className="text-sm text-gray-400 mb-1">Timestamp</p>
<p className="text-white text-sm">{new Date(testResult.timestamp).toLocaleString()}</p>
</div>
)}
{testResult.response && (
<div>
<p className="text-sm text-gray-400 mb-1">Response</p>
<pre className="p-3 bg-gray-900 rounded text-white font-mono text-xs overflow-auto max-h-64">
{JSON.stringify(testResult.response, null, 2)}
</pre>
</div>
)}
{testResult.error && (
<div>
<p className="text-sm text-gray-400 mb-1">Error</p>
<p className="text-red-400 font-mono text-sm">{testResult.error}</p>
</div>
)}
</div>
)}
</CardContent>
</Card>
</div>
</div>
);
}