tao-test/app/taoClientDiagnostic/views/js/tools/upload/tester.js

240 lines
7.1 KiB
JavaScript

/**
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; under version 2
* of the License (non-upgradable).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright (c) 2016-2021 (original work) Open Assessment Technologies SA ;
*/
define([
'jquery',
'lodash',
'i18n',
'async',
'util/url',
'taoClientDiagnostic/tools/getConfig',
'taoClientDiagnostic/tools/getLabels',
'taoClientDiagnostic/tools/getStatus'
], function($, _, __, async, urlHelper, getConfig, getLabels, getStatus) {
'use strict';
/**
* A binary kilo bytes (KiB)
* @type {number}
* @private
*/
const _kilo = 1024;
/**
* A binary mega bytes (MiB)
* @type {number}
* @private
*/
const _mega = _kilo * _kilo;
/**
* Result of diagnostic
* @type {Array}
* @private
*/
let data = [];
/**
* Default values for the upload speed tester
* @type {object}
* @private
*/
const _defaults = {
id: 'upload',
// Size of data to sent to server during speed test in bytes
size: _mega,
// Optimal speed in bytes per second
optimal: _mega
};
/**
* A list of thresholds for bandwidth check
* @type {Array}
* @private
*/
const _thresholds = [
{
threshold: 0,
message: __('Low upload speed'),
type: 'error'
},
{
threshold: 33,
message: __('Average upload speed'),
type: 'warning'
},
{
threshold: 66,
message: __('Good upload speed'),
type: 'success'
}
];
/**
* List of translated texts per level.
* The level is provided through the config as a numeric value, starting from 1.
* @type {object}
* @private
*/
const _messages = [
// level 1
{
title: __('Upload speed'),
status: __('Checking upload speed...'),
uploadAvg: __('Average upload speed'),
uploadMax: __('Max upload speed')
}
];
/**
* Generate random string of given length
* @param {number} length
*/
function generateStr(length) {
let text = '';
const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (let i = 0; i < length; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
}
/**
* Upload generated string to check upload speed.
* @param {number} size of string to upload in bytes
* @return {object} jqXHR
*/
function upload(size) {
const url = urlHelper.route('upload', 'CompatibilityChecker', 'taoClientDiagnostic', { cache: Date.now() });
const str = generateStr(size);
data = [];
return $.ajax({
url: url,
type: 'POST',
data: {
upload: str
},
xhr: () => {
const xhr = new window.XMLHttpRequest();
const startTime = Date.now();
// Upload progress
xhr.upload.addEventListener(
'progress',
evt => {
if (evt.lengthComputable) {
const passedTime = Date.now() - startTime;
data.push({
time: passedTime,
loaded: evt.loaded,
speed: (evt.loaded * 8) / _mega / (passedTime / 1000)
});
}
},
false
);
return xhr;
}
});
}
/**
* Performs a upload speed test
* @param {object} config - Some optional configs
* @param {string} [config.id] - The identifier of the test
* @param {number} [config.size] - Size of data to sent to server during speed test in bytes
* @param {number} [config.optimal] - Optimal speed in bytes per second
* @param {string} [config.level] - The intensity level of the test. It will aim which messages list to use.
* @returns {object}
*/
return function uploadTester(config) {
const initConfig = getConfig(config, _defaults);
const labels = getLabels(_messages, initConfig.level);
return {
/**
* Performs upload speed test, then call a function to provide the result
* @param {Function} done
*/
start(done) {
upload(parseInt(initConfig.size, 10)).then(() => {
let totalSpeed = 0;
let maxSpeed = 0;
_.forEach(data, val => {
totalSpeed += val.speed;
if (maxSpeed < val.speed) {
maxSpeed = Math.round(val.speed * 100) / 100;
}
});
const avgSpeed = Math.round((totalSpeed / data.length) * 100) / 100;
const results = {
max: maxSpeed,
avg: avgSpeed,
type: 'upload'
};
const status = this.getFeedback(avgSpeed);
const summary = this.getSummary(results);
done(status, summary, results);
});
},
/**
* Gets the labels loaded for the tester
* @returns {object}
*/
get labels() {
return labels;
},
/**
* Builds the results summary
* @param {object} results
* @returns {object}
*/
getSummary(results) {
return {
uploadAvg: { message: labels.uploadAvg, value: `${results.avg} Mbps` },
uploadMax: { message: labels.uploadMax, value: `${results.max} Mbps` }
};
},
/**
* Gets the feedback status for the provided result value
* @param {number} result
* @returns {object}
*/
getFeedback(result) {
const optimal = initConfig.optimal / _mega;
const status = getStatus((100 / optimal) * result, _thresholds);
status.id = initConfig.id;
status.title = labels.title;
return status;
}
};
};
});