Network Speed Test Tool

Network Speed Test Tool

Note: This tool simulates a speed test using browser requests to public APIs. It is an estimate and not a replacement for a dedicated speed test application.

Test History

Your test history will appear here.

Your test history will appear here.

'; return; } ui.logList.innerHTML = testLog.map(log => `
${log.timestamp}

Ping: ${log.ping} ms, Download: ${log.download} Mbps, Upload: ${log.upload} Mbps

`).join(''); } function logEntry(ping, download, upload) { const timestamp = new Date().toLocaleString('en-US'); const logItem = { timestamp, ping: ping.toFixed(2), download: download.toFixed(2), upload: upload.toFixed(2) }; testLog.unshift(logItem); if (testLog.length > 50) testLog.pop(); // Limit log size saveState(); renderLog(); } function logToScreen(message, type = '') { const line = document.createElement('p'); line.className = `nst-log-line ${type}`; line.textContent = `[${new Date().toLocaleTimeString()}] ${message}`; ui.liveLog.appendChild(line); ui.liveLog.scrollTop = ui.liveLog.scrollHeight; } function showMessage(message, isError = true) { ui.errorMsg.textContent = message; ui.errorMsg.style.display = 'block'; } // --- SPEED TEST LOGIC --- async function testPing() { logToScreen("Testing latency..."); const start = performance.now(); try { await fetch('https://www.google.com', { mode: 'no-cors', method: 'HEAD', cache: 'no-store' }); const end = performance.now(); const ping = end - start; logToScreen(`Ping test success: ${ping.toFixed(2)} ms`, 'success'); return ping; } catch (e) { logToScreen(`Ping test failed: ${e.message}`, 'error'); return -1; } } async function testDownload() { logToScreen("Testing download speed..."); const url = 'https://jsonplaceholder.typicode.com/photos'; // ~2.3MB JSON file, CORS enabled try { const start = performance.now(); const response = await fetch(url, { cache: 'no-store' }); const blob = await response.blob(); const end = performance.now(); const durationS = (end - start) / 1000; const sizeBits = blob.size * 8; const mbps = (sizeBits / durationS) / 1_000_000; logToScreen(`Download test success: ${mbps.toFixed(2)} Mbps`, 'success'); return mbps; } catch (e) { logToScreen(`Download test failed: ${e.message}`, 'error'); return -1; } } async function testUpload() { logToScreen("Testing upload speed..."); const url = 'https://jsonplaceholder.typicode.com/posts'; // Accepts POST, CORS enabled const sizeBytes = 5 * 1024 * 1024; // 5MB const data = new Blob([new Uint8Array(sizeBytes)], { type: 'application/octet-stream' }); try { const start = performance.now(); await fetch(url, { method: 'POST', body: data }); const end = performance.now(); const durationS = (end - start) / 1000; const sizeBits = sizeBytes * 8; const mbps = (sizeBits / durationS) / 1_000_000; logToScreen(`Upload test success: ${mbps.toFixed(2)} Mbps`, 'success'); return mbps; } catch (e) { logToScreen(`Upload test failed: ${e.message}`, 'error'); return -1; } } async function runTestSequence() { if (isTesting) return; isTesting = true; ui.startBtn.disabled = true; ui.startBtn.textContent = 'Testing...'; ui.loader.style.display = 'block'; ui.resultsContainer.style.display = 'block'; ui.errorMsg.style.display = 'none'; ui.liveLog.innerHTML = ''; // Reset results ui.summaryPing.textContent = '...'; ui.summaryDownload.textContent = '...'; ui.summaryUpload.textContent = '...'; const ping = await testPing(); ui.summaryPing.textContent = ping < 0 ? 'N/A' : ping.toFixed(0); const download = await testDownload(); ui.summaryDownload.textContent = download < 0 ? 'N/A' : download.toFixed(2); const upload = await testUpload(); ui.summaryUpload.textContent = upload < 0 ? 'N/A' : upload.toFixed(2); logToScreen("Test complete."); currentTest = { ping, download, upload }; logEntry(ping, download, upload); isTesting = false; ui.startBtn.disabled = false; ui.startBtn.textContent = 'Start Test'; ui.loader.style.display = 'none'; } // --- PDF LOGIC --- function downloadPDF(type) { const { jsPDF } = window.jspdf; if (!jsPDF || !window.jspdf.autoTable) { alert("PDF library not loaded!"); return; } const doc = new jsPDF(); if (type === 'current') { if (currentTest.ping === 0) { alert("Please run a test before downloading."); return; } doc.setFontSize(18); doc.text("Network Speed Test Report", 14, 22); doc.autoTable({ startY: 30, theme: 'grid', body: [ ['Ping (Latency)', `${currentTest.ping.toFixed(2)} ms`], ['Download Speed', `${currentTest.download.toFixed(2)} Mbps`], ['Upload Speed', `${currentTest.upload.toFixed(2)} Mbps`], ] }); doc.save("Speed_Test_Report.pdf"); } else if (type === 'log') { if (testLog.length === 0) { alert("Log is empty. Please run a test first."); return; } doc.setFontSize(18); doc.text("Network Speed Test Log", 14, 22); doc.autoTable({ startY: 30, head: [['Timestamp', 'Ping (ms)', 'Download (Mbps)', 'Upload (Mbps)']], body: testLog.map(log => [log.timestamp, log.ping, log.download, log.upload]), theme: 'striped', headStyles: { fillColor: [22, 163, 74] } // var(--primary-color) }); doc.save("Speed_Test_Log.pdf"); } } // --- EVENT LISTENERS --- ui.startBtn.addEventListener('click', runTestSequence); ui.downloadReportBtn.addEventListener('click', () => downloadPDF('current')); ui.downloadLogBtn.addEventListener('click', () => downloadPDF('log')); ui.clearLogBtn.addEventListener('click', () => { testLog = []; saveState(); renderLog(); }); // --- TABBING LOGIC --- function switchTab(targetTabId) { ui.tabContents.forEach(c => c.classList.remove('active')); ui.tabButtons.forEach(b => b.classList.remove('active')); document.getElementById(`nst-tab-${targetTabId}`).classList.add('active'); document.querySelector(`.nst-tab-button[data-tab="${targetTabId}"]`).classList.add('active'); } function navigateTabs(dir) { const tabs = Array.from(ui.tabButtons); const active = tabs.find(t => t.classList.contains('active')); let index = tabs.indexOf(active) + dir; if (index < 0) index = 0; if (index >= tabs.length) index = tabs.length - 1; switchTab(tabs[index].dataset.tab); } ui.tabButtons.forEach(button => button.addEventListener('click', () => switchTab(button.dataset.tab))); ui.nextTabBtn.addEventListener('click', () => navigateTabs(1)); ui.prevTabBtn.addEventListener('click', () => navigateTabs(-1)); // --- UTILITY --- function escapeHTML(str) { const p = document.createElement('p'); p.textContent = str; return p.innerHTML; } // --- INITIALIZATION --- loadState(); renderLog(); });
Scroll to Top