// Real Internet Speed Test Implementation const { useState, useEffect, useRef } = React; const InternetSpeedTest = () => { const [testState, setTestState] = useState('idle'); const [downloadSpeed, setDownloadSpeed] = useState(0); const [uploadSpeed, setUploadSpeed] = useState(0); const [ping, setPing] = useState(0); const [isp, setIsp] = useState(''); const [location, setLocation] = useState(''); const [showDetails, setShowDetails] = useState(false); const [downloadProgress, setDownloadProgress] = useState([]); const needleRef = useRef(null); const canvasRef = useRef(null); // Constants for test const TEST_SERVER = 'https://www.beanormal.com/speed-test'; const PING_TEST_COUNT = 5; const DOWNLOAD_SIZE = 96746791; // Gerçek dosya boyutu (96.7 MB) const UPLOAD_SIZE = 5 * 1024 * 1024; // 5 MB test upload // Fetch IP information on load useEffect(() => { const getNetworkInfo = async () => { try { const response = await fetch('https://ipapi.co/json/'); const data = await response.json(); setIsp(data.org?.split(' ')[0] || ''); setLocation(`${data.city || ''}, ${data.region_code || ''}`); } catch (err) { console.error("Failed to get network info", err); } }; getNetworkInfo(); initCanvas(); }, []); // Update needle position when download speed changes useEffect(() => { animateNeedle(downloadSpeed); }, [downloadSpeed]); // Draw the speed graph when download progress updates useEffect(() => { if (downloadProgress.length > 0) { drawSpeedGraph(); } }, [downloadProgress]); // Initialize canvas const initCanvas = () => { if (!canvasRef.current) return; const canvas = canvasRef.current; const ctx = canvas.getContext('2d'); canvas.width = canvas.offsetWidth * window.devicePixelRatio; canvas.height = canvas.offsetHeight * window.devicePixelRatio; ctx.scale(window.devicePixelRatio, window.devicePixelRatio); ctx.clearRect(0, 0, canvas.width, canvas.height); }; // Draw speed graph with real data const drawSpeedGraph = () => { if (!canvasRef.current || !downloadProgress.length) return; const canvas = canvasRef.current; const ctx = canvas.getContext('2d'); ctx.clearRect(0, 0, canvas.width, canvas.height); const width = canvas.offsetWidth; const height = canvas.offsetHeight; const maxSpeed = Math.max(...downloadProgress.map(p => p.speed)) * 1.2; // Draw the graph path ctx.beginPath(); ctx.moveTo(0, height); downloadProgress.forEach((point, index) => { const x = (index / (downloadProgress.length - 1)) * width; const y = height - (point.speed / maxSpeed) * height; ctx.lineTo(x, y); }); // Complete the path ctx.lineTo(width, height); ctx.lineTo(0, height); // Fill with gradient const gradient = ctx.createLinearGradient(0, 0, 0, height); gradient.addColorStop(0, 'rgba(138, 143, 255, 0.7)'); gradient.addColorStop(1, 'rgba(138, 143, 255, 0)'); ctx.fillStyle = gradient; ctx.fill(); // Draw the line ctx.beginPath(); ctx.moveTo(0, height); downloadProgress.forEach((point, index) => { const x = (index / (downloadProgress.length - 1)) * width; const y = height - (point.speed / maxSpeed) * height; ctx.lineTo(x, y); }); ctx.strokeStyle = '#22d3ee'; ctx.lineWidth = 2; ctx.stroke(); }; // Animate needle movement const animateNeedle = (speed) => { if (!needleRef.current) return; // Calculate angle based on speed tiers let degrees; if (speed <= 50) { // 0-50 Mbps -> 0-90 degrees degrees = (speed / 50) * 90; } else if (speed <= 150) { // 50-150 Mbps -> 90-135 degrees degrees = 90 + ((speed - 50) / 100) * 45; } else { // 150-250+ Mbps -> 135-180 degrees (capped at 180) degrees = 135 + Math.min(((speed - 150) / 100) * 45, 45); } // Apply smooth animation const currentRotation = needleRef.current.style.transform ? parseFloat(needleRef.current.style.transform.replace('rotate(', '').replace('deg)', '')) || 0 : 0; const duration = 300; const startTime = performance.now(); const animate = (time) => { const elapsed = time - startTime; const progress = Math.min(elapsed / duration, 1); // Ease out cubic for natural movement const easing = 1 - Math.pow(1 - progress, 3); const currentDegrees = currentRotation + (degrees - currentRotation) * easing; needleRef.current.style.transform = `rotate(${currentDegrees}deg)`; if (progress < 1) { requestAnimationFrame(animate); } }; requestAnimationFrame(animate); }; // Test ping by sending multiple small requests const testPing = async () => { const pingUrl = `${TEST_SERVER}/ping-test.php`; const pings = []; for (let i = 0; i < PING_TEST_COUNT; i++) { const start = performance.now(); try { await fetch(pingUrl, { method: 'GET', cache: 'no-store', headers: { 'Cache-Control': 'no-cache' } }); const end = performance.now(); pings.push(end - start); } catch (err) { console.error("Ping test failed", err); } } // Calculate average ping const avgPing = pings.length ? Math.round(pings.reduce((a, b) => a + b, 0) / pings.length) : 0; setPing(avgPing); return avgPing; }; // Test download speed const testDownload = async () => { const downloadUrl = `${TEST_SERVER}/download-test.php?size=${DOWNLOAD_SIZE}&cacheBust=${Date.now()}`; return new Promise((resolve) => { const xhr = new XMLHttpRequest(); let startTime; let prevLoaded = 0; let prevTime = 0; const progressUpdates = []; xhr.open('GET', downloadUrl, true); xhr.responseType = 'arraybuffer'; xhr.onloadstart = () => { startTime = performance.now(); prevTime = startTime; }; xhr.onprogress = (event) => { if (event.lengthComputable) { const currentTime = performance.now(); const loadDiff = event.loaded - prevLoaded; const timeDiff = currentTime - prevTime; if (timeDiff > 0 && loadDiff > 0) { // Calculate current speed in Mbps const currentSpeed = (loadDiff * 8) / (timeDiff / 1000) / 1000000; progressUpdates.push({ time: currentTime - startTime, loaded: event.loaded, total: event.total, speed: currentSpeed }); // Son 5 değerin ortalamasını almak için (yumuşak artış) const last5 = progressUpdates.slice(-5); const avgSpeed = last5.reduce((sum, item) => sum + item.speed, 0) / last5.length; setDownloadProgress([...progressUpdates]); setDownloadSpeed(avgSpeed); // Ortalama hızı göster (daha yumuşak artış) prevLoaded = event.loaded; prevTime = currentTime; } } }; xhr.onload = () => { if (xhr.status === 200) { const endTime = performance.now(); const duration = (endTime - startTime) / 1000; // seconds const size = xhr.response.byteLength * 8; // bits // Calculate final speed in Mbps const finalSpeed = size / duration / 1000000; resolve(finalSpeed); } else { console.error("Download test failed with status", xhr.status); resolve(0); } }; xhr.onerror = () => { console.error("XHR download error"); resolve(0); }; xhr.send(); }); }; // Test upload speed const testUpload = async () => { const uploadUrl = `${TEST_SERVER}/upload-test.php?cacheBust=${Date.now()}`; // Create data to upload (random binary data) const data = new ArrayBuffer(UPLOAD_SIZE); const view = new Uint8Array(data); for (let i = 0; i < UPLOAD_SIZE; i++) { view[i] = Math.floor(Math.random() * 256); } return new Promise((resolve) => { const xhr = new XMLHttpRequest(); const startTime = performance.now(); xhr.open('POST', uploadUrl, true); xhr.setRequestHeader('Content-Type', 'application/octet-stream'); xhr.onload = () => { if (xhr.status === 200) { const endTime = performance.now(); const duration = (endTime - startTime) / 1000; // seconds const size = UPLOAD_SIZE * 8; // bits // Calculate upload speed in Mbps const speed = size / duration / 1000000; resolve(speed); } else { console.error("Upload test failed with status", xhr.status); resolve(0); } }; xhr.onerror = () => { console.error("XHR upload error"); resolve(0); }; xhr.send(data); }); }; // Start the complete speed test const startTest = async () => { if (testState === 'running') return; setTestState('running'); setDownloadSpeed(0); setUploadSpeed(0); setPing(0); setDownloadProgress([]); try { // 1. Test ping await testPing(); // 2. Test download speed const dlSpeed = await testDownload(); setDownloadSpeed(dlSpeed); // 3. Test upload speed const ulSpeed = await testUpload(); setUploadSpeed(ulSpeed); setTestState('completed'); } catch (err) { console.error("Speed test failed", err); setTestState('error'); } }; return (
Test your connection speed to optimize your online experience
{/* Needle - positioned absolute and rotated around center bottom point */}
Test Method: XMLHttpRequest with real file transfer
Test Server: {TEST_SERVER.replace(/^https?:\/\//, '')}
Download Test Size: {DOWNLOAD_SIZE / (1024 * 1024)} MB
Upload Test Size: {UPLOAD_SIZE / (1024 * 1024)} MB