From 076a30d178bbfde3972f5adfc597adfbd26314f3 Mon Sep 17 00:00:00 2001 From: GloriousYellow Date: Wed, 20 Feb 2019 12:00:54 -0500 Subject: [PATCH] Measure upload speed (#28) Closes #27 --- api.js | 70 +++++++++++++++++++++++++++++++++------------------- cli.js | 38 ++++++++++++++++++++++------ package.json | 2 ++ readme.md | 1 + 4 files changed, 77 insertions(+), 34 deletions(-) diff --git a/api.js b/api.js index d3cb6f5..b39b7c5 100644 --- a/api.js +++ b/api.js @@ -2,37 +2,55 @@ /* eslint-env browser */ const puppeteer = require('puppeteer'); const Observable = require('zen-observable'); +const equals = require('deep-equal'); // TODO: Use `util.isDeepStrictEqual` when targeting Node.js 10 +const delay = require('delay'); -async function init(browser, page, observer, prevSpeed) { - const result = await page.evaluate(() => { - const $ = document.querySelector.bind(document); +async function init(browser, page, observer, opts) { + let prevResult; - return { - speed: Number($('#speed-value').textContent), - unit: $('#speed-units').textContent.trim(), - isDone: Boolean($('#speed-value.succeeded')) - }; - }); + /* eslint-disable no-constant-condition, no-await-in-loop */ - if (result.speed > 0 && result.speed !== prevSpeed) { - observer.next(result); - } + while (true) { + const result = await page.evaluate(() => { + const $ = document.querySelector.bind(document); + + return { + downloadSpeed: Number($('#speed-value').textContent), + uploadSpeed: Number($('#upload-value').textContent), + downloadUnit: $('#speed-units').textContent.trim(), + uploadUnit: $('#upload-units').textContent.trim(), + isDone: Boolean( + $('#speed-value.succeeded') && $('#upload-value.succeeded') + ) + }; + }); + + if (result.downloadSpeed > 0 && !equals(result, prevResult)) { + observer.next(result); + } - if (result.isDone) { - browser.close(); - observer.complete(); - } else { - setTimeout(init, 100, browser, page, observer, result.speed); + if (result.isDone || (opts && !opts.measureUpload && result.uploadSpeed)) { + browser.close(); + observer.complete(); + return; + } + + prevResult = result; + + await delay(100); } + + /* eslint-enable no-constant-condition, no-await-in-loop */ } -module.exports = () => new Observable(observer => { - // Wrapped in async IIFE as `new Observable` can't handle async function - (async () => { - const browser = await puppeteer.launch({args: ['--no-sandbox']}); - const page = await browser.newPage(); +module.exports = opts => + new Observable(observer => { + // Wrapped in async IIFE as `new Observable` can't handle async function + (async () => { + const browser = await puppeteer.launch({args: ['--no-sandbox']}); + const page = await browser.newPage(); - await page.goto('https://fast.com'); - await init(browser, page, observer); - })().catch(observer.error.bind(observer)); -}); + await page.goto('https://fast.com'); + await init(browser, page, observer, opts); + })().catch(observer.error.bind(observer)); + }); diff --git a/cli.js b/cli.js index 5784d09..cad7282 100755 --- a/cli.js +++ b/cli.js @@ -7,13 +7,14 @@ const logUpdate = require('log-update'); const ora = require('ora'); const api = require('./api'); -meow(` +const cli = meow(` Usage - $ fast - $ fast > file + $ fast + $ fast > file + $ fast --verbose `); -// Check connection +// Check connections dns.lookup('fast.com', err => { if (err && err.code === 'ENOTFOUND') { console.error(chalk.red('\n Please check your internet connection.\n')); @@ -24,13 +25,34 @@ dns.lookup('fast.com', err => { let data = {}; const spinner = ora(); -const speed = () => chalk[data.isDone ? 'green' : 'cyan'](data.speed + ' ' + chalk.dim(data.unit)) + '\n\n'; +const downloadSpeed = () => + `${data.downloadSpeed} ${chalk.dim(data.downloadUnit)} ↓`; + +const uploadSpeed = () => + data.uploadSpeed ? + `${data.uploadSpeed} ${chalk.dim(data.uploadUnit)} ↑` : + chalk.dim('- Mbps ↑'); + +const uColor = s => (data.isDone ? chalk.green(s) : chalk.cyan(s)); + +const dColor = s => ((data.isDone || data.uploadSpeed) ? chalk.green(s) : chalk.cyan(s)); + +const speedText = () => + cli.flags.verbose ? + `${dColor(downloadSpeed())} ${chalk.dim('/')} ${uColor(uploadSpeed())}` : + dColor(downloadSpeed()); + +const speed = () => speedText() + '\n\n'; function exit() { if (process.stdout.isTTY) { logUpdate(`\n\n ${speed()}`); + } else if (cli.flags.verbose) { + console.log( + `${data.downloadSpeed} ${data.downloadUnit} / ${data.uploadSpeed} ${data.uploadUnit}` + ); } else { - console.log(`${data.speed} ${data.unit}`); + console.log(`${data.downloadSpeed} ${data.downloadUnit}`); } process.exit(); @@ -40,7 +62,7 @@ if (process.stdout.isTTY) { setInterval(() => { const pre = '\n\n ' + chalk.gray.dim(spinner.frame()); - if (!data.speed) { + if (!data.downloadSpeed) { logUpdate(pre + '\n\n'); return; } @@ -51,7 +73,7 @@ if (process.stdout.isTTY) { (async () => { try { - await api().forEach(result => { + await api({measureUpload: cli.flags.verbose}).forEach(result => { data = result; }); diff --git a/package.json b/package.json index 727c445..69b36cd 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,8 @@ ], "dependencies": { "chalk": "^2.1.0", + "deep-equal": "^1.0.1", + "delay": "^4.1.0", "log-update": "^2.1.0", "meow": "^5.0.0", "ora": "^2.0.0", diff --git a/readme.md b/readme.md index b6202dd..ef2702a 100644 --- a/readme.md +++ b/readme.md @@ -22,6 +22,7 @@ $ fast --help Usage $ fast $ fast > file + $ fast --verbose ```