Skip to content

Commit

Permalink
feat: correctly implement speed test run
Browse files Browse the repository at this point in the history
  • Loading branch information
emekaorji committed Dec 1, 2023
1 parent 19a55cb commit 462e05f
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 32 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@
"contributes": {
"commands": [
{
"command": "speed-test.testSpeed",
"title": "Speed Test"
"command": "SpeedTest.testSpeed",
"title": "Run Internet Speed Test"
}
]
},
Expand Down
136 changes: 115 additions & 21 deletions src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,121 @@
// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
import * as vscode from 'vscode';

// This method is called when your extension is activated
// Your extension is activated the very first time the command is executed
import type { Result } from './getSpeed';
import { getSpeed } from './getSpeed';

type Progress = vscode.Progress<{
message?: string | undefined;
increment?: number | undefined;
}>;

export function activate(context: vscode.ExtensionContext) {
// Use the console to output diagnostic information (console.log) and errors (console.error)
// This line of code will only be executed once when your extension is activated
console.log(
'Congratulations, your extension "awesome-vscode-extension-boilerplate" is now active!',
);

// The command has been defined in the package.json file
// Now provide the implementation of the command with registerCommand
// The commandId parameter must match the command field in package.json
const disposable = vscode.commands.registerCommand('speed-test.testSpeed', () => {
// The code you place here will be executed every time your command is executed
// Display a message box to the user
vscode.window.showInformationMessage('Speed Test is running');
});

context.subscriptions.push(disposable);
const myStatusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 1);
myStatusBarItem.command = 'SpeedTest.testSpeed';
myStatusBarItem.name = 'Speed Test';
myStatusBarItem.text = `$(loading~spin)$(arrow-small-down)0$(arrow-small-up)0`;
myStatusBarItem.tooltip = new vscode.MarkdownString(
'$(ports-open-browser-icon) Speed Test Running',
true,
);
context.subscriptions.push(myStatusBarItem);
myStatusBarItem.show();

let isRunning = false;
let progress: Progress | undefined;
let abortController = new AbortController();

async function runSpeedTest() {
if (isRunning) return;

let result: Result | undefined;
const lastCheckedDate = new Date().toUTCString();

try {
isRunning = true;
myStatusBarItem.text = `$(loading~spin)$(arrow-small-down)0$(arrow-small-up)0`;
await getSpeed().forEach((result_) => {
result = result_;
myStatusBarItem.text = `$(loading~spin)$(arrow-small-down)${result.downloadSpeed}${result.downloadUnit}$(arrow-small-up)${result.uploadSpeed}${result.uploadUnit}`;
if (progress) {
progress.report({
message: `Download: ${result.downloadSpeed}${result.downloadUnit} | Upload: ${result.uploadSpeed}${result.uploadUnit}`,
});
}
if (abortController.signal.aborted) {
abortController = new AbortController();
// eslint-disable-next-line no-throw-literal
throw { name: 'Aborted' };
}
});
isRunning = false;
if (!result) throw new Error('Could not detect network speed');
myStatusBarItem.text = `$(ports-open-browser-icon)$(arrow-small-down)${result.downloadSpeed}${result.downloadUnit}$(arrow-small-up)${result.uploadSpeed}${result.uploadUnit}`;
myStatusBarItem.tooltip = new vscode.MarkdownString(
`### $(ports-open-browser-icon) Speed Test Status\n\nDownload Speed - ${result.downloadSpeed}${result.downloadUnit}\n\nUpload Speed - ${result.uploadSpeed}${result.uploadUnit}\n\n__Last checked at ${lastCheckedDate}__`,
true,
);
const selection = await vscode.window.showInformationMessage(
`Speed test completed successfully. Download - ${result.downloadSpeed}${result.downloadUnit} | Upload - ${result.uploadSpeed}${result.uploadUnit}`,
'Run again',
);
if (selection === 'Run again') runSpeedTestWithReport();
} catch (error: any) {
isRunning = false;
if (error.name === 'Aborted' && result) {
myStatusBarItem.text = `$(ports-open-browser-icon)$(arrow-small-down)${result.downloadSpeed}${result.downloadUnit}$(arrow-small-up)${result.uploadSpeed}${result.uploadUnit}`;
myStatusBarItem.tooltip = new vscode.MarkdownString(
`### $(ports-open-browser-icon) Speed Test Status\n\nDownload Speed - ${result.downloadSpeed}${result.downloadUnit}\n\nUpload Speed - ${result.uploadSpeed}${result.uploadUnit}\n\n__Last checked at ${lastCheckedDate}__`,
true,
);
const selection = await vscode.window.showWarningMessage(
`Speed Test Aborted. Download - ${result.downloadSpeed}${result.downloadUnit} | Upload - ${result.uploadSpeed}${result.uploadUnit}`,
'Run again',
);
if (selection === 'Run again') runSpeedTestWithReport();
} else {
console.log(error.code, error.name, error.message);
myStatusBarItem.text = `$(error) Speed Test Error`;
const selection = await vscode.window.showErrorMessage(error, 'Retry');
if (selection === 'Retry') runSpeedTestWithReport();
}
}
}

function showProgressReport() {
if (progress) return;
vscode.window.withProgress(
{ location: vscode.ProgressLocation.Notification, title: 'Speed Test', cancellable: true },
async (progress_, token) => {
progress = progress_;
token.onCancellationRequested(() => {
abortController.abort();
});

return new Promise((resolve) => {
const intervalId = setInterval(() => {
if (!isRunning) {
progress = undefined;
resolve('');
clearInterval(intervalId);
}
}, 100);
});
},
);
}

function runSpeedTestWithReport() {
runSpeedTest();
showProgressReport();
}

const disposable = vscode.commands.registerCommand('SpeedTest.testSpeed', () =>
runSpeedTestWithReport(),
);

context.subscriptions.push(disposable);

runSpeedTest();
}

// This method is called when your extension is deactivated
export function deactivate() {}
12 changes: 3 additions & 9 deletions src/getSpeed.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
'use strict';
import { isDeepStrictEqual } from 'node:util';
// import { isDeepStrictEqual } from 'node:util';

import delay from 'delay';
import type { Browser, Page } from 'puppeteer';
import puppeteer from 'puppeteer';
import Observable from 'zen-observable';

interface Result {
export interface Result {
downloadSpeed: number;
uploadSpeed: number;
downloadUnit: string | undefined;
Expand All @@ -25,8 +25,6 @@ async function init(
page: Page,
observer: ZenObservable.SubscriptionObserver<Result>,
) {
let previousResult;

while (true) {
// eslint-disable-next-line no-await-in-loop
const result: Result = await page.evaluate(() => {
Expand All @@ -47,18 +45,14 @@ async function init(
};
});

if (result.downloadSpeed > 0 && !isDeepStrictEqual(result, previousResult)) {
observer.next(result);
}
observer.next(result);

if (result.isDone || result.uploadSpeed) {
browser.close();
observer.complete();
return;
}

previousResult = result;

// eslint-disable-next-line no-await-in-loop
await delay(100);
}
Expand Down

0 comments on commit 462e05f

Please sign in to comment.