diff --git a/components/measurement/MeasurementContainer.js b/components/measurement/MeasurementContainer.js index 16049582c..6121f181c 100644 --- a/components/measurement/MeasurementContainer.js +++ b/components/measurement/MeasurementContainer.js @@ -39,7 +39,12 @@ const MeasurementContainer = ({ measurement, ...props }) => { } const TestDetails = mapTestDetails[measurement.test_name] || DefaultTestDetails - return + + return ( + + + + ) } export default MeasurementContainer diff --git a/components/measurement/PerformanceDetails.js b/components/measurement/PerformanceDetails.js index 88bbcaebb..dd23bf182 100644 --- a/components/measurement/PerformanceDetails.js +++ b/components/measurement/PerformanceDetails.js @@ -13,40 +13,37 @@ const PerformanceDetails = ({ timeouts }) => { const intl = useIntl() - let items = [ - { - label: intl.formatMessage({ id: 'Measurement.Details.Performance.Label.AvgPing' }), - value: averagePing.toString() + ' ms' - }, - { - label: intl.formatMessage({ id: 'Measurement.Details.Performance.Label.MaxPing' }), - value: `${isNdt7 ? '~' : ''}${maxPing.toString()} ms` - }, - { - label: intl.formatMessage({ id: 'Measurement.Details.Performance.Label.MSS' }), - value: mss.toString() - }, - { - label: isNdt7 ? intl.formatMessage({ - id: 'Measurement.Details.Performance.Label.RetransmitRate', - defaultMessage: 'Retransmit Rate' - }): intl.formatMessage({ id: 'Measurement.Details.Performance.Label.PktLoss' }), - value: packetLoss.toString() + '%' - }, - ] + let items = [] + averagePing && items.push({ + label: intl.formatMessage({ id: 'Measurement.Details.Performance.Label.AvgPing' }), + value: `${averagePing} ms` + }) + maxPing && items.push({ + label: intl.formatMessage({ id: 'Measurement.Details.Performance.Label.MaxPing' }), + value: `${isNdt7 ? '~' : ''}${maxPing} ms` + }) + mss && items.push({ + label: intl.formatMessage({ id: 'Measurement.Details.Performance.Label.MSS' }), + value: `${mss}` + }) + + packetLoss != undefined && items.push({ + label: isNdt7 ? intl.formatMessage({ + id: 'Measurement.Details.Performance.Label.RetransmitRate' + }): intl.formatMessage({ id: 'Measurement.Details.Performance.Label.PktLoss' }), + value: `${packetLoss}%` + }) //Only add outOfOrder and timeouts if NDT4/5 measurement - if(!isNdt7){ - items = items.concat([ - { - label: intl.formatMessage({ id: 'Measurement.Details.Performance.Label.OutOfOrder' }), - value: outOfOrder.toString() + '%' - }, - { - label: intl.formatMessage({ id: 'Measurement.Details.Performance.Label.Timeouts' }), - value: timeouts.toString() - } - ]) + if(!isNdt7) { + outOfOrder != undefined && items.push({ + label: intl.formatMessage({ id: 'Measurement.Details.Performance.Label.OutOfOrder' }), + value: outOfOrder.toString() + '%' + }) + timeouts != undefined && items.push({ + label: intl.formatMessage({ id: 'Measurement.Details.Performance.Label.Timeouts' }), + value: timeouts.toString() + }) } return ( diff --git a/components/measurement/nettests/Dash.js b/components/measurement/nettests/Dash.js index bc05bf199..406b1d363 100644 --- a/components/measurement/nettests/Dash.js +++ b/components/measurement/nettests/Dash.js @@ -1,24 +1,8 @@ - import React from 'react' import PropTypes from 'prop-types' -import { - Heading, - Flex, - Box, - theme -} from 'ooni-components' - +import { Flex, Box } from 'ooni-components' import { Text } from 'rebass' import { useIntl } from 'react-intl' - -import { - VictoryChart, - VictoryLine, - VictoryTooltip, - VictoryVoronoiContainer, - VictoryAxis -} from 'victory' - import MdFlashOn from 'react-icons/lib/md/flash-on' const InfoBoxItem = ({ @@ -92,10 +76,9 @@ const getOptimalQualityForBitrate = (testKeys) => { const DashDetails = ({ measurement, render }) => { const intl = useIntl() const testKeys = measurement.test_keys - // const isFailed = testKeys.failure !== null - // const failure = testKeys.failure + const failure = testKeys.failure - if (typeof testKeys.simple === 'undefined' || typeof testKeys.receiver_data === 'undefined') { + if (failure === true || typeof testKeys.simple === 'undefined' || typeof testKeys.receiver_data === 'undefined') { return render({ status: 'error' }) @@ -105,13 +88,6 @@ const DashDetails = ({ measurement, render }) => { const medianBitrate = (testKeys.simple.median_bitrate / 1000).toFixed(2) const playoutDelay = (testKeys.simple.min_playout_delay).toFixed(2) - // construct data for graph - const clientData = testKeys.receiver_data - const data = clientData.map(iteration => ({ - x: iteration.iteration, - y: iteration.rate / 1000, - })) - return ( render({ statusIcon: , @@ -134,55 +110,7 @@ const DashDetails = ({ measurement, render }) => { ), - details: ( - - {/* - Video Quality by time - - `${d.y} Mb/s`} - labelComponent={} - /> - } - > - i.x + 's'))} - style={{ - tickLabels: { fontSize: 10, padding: 5} - }} - /> - - - - - */} - - ) + details: null }) ) } diff --git a/components/measurement/nettests/HTTPHeaderFieldManipulation.js b/components/measurement/nettests/HTTPHeaderFieldManipulation.js index 8eb1b44af..2f03aa2b0 100644 --- a/components/measurement/nettests/HTTPHeaderFieldManipulation.js +++ b/components/measurement/nettests/HTTPHeaderFieldManipulation.js @@ -9,7 +9,7 @@ export const HttpHeaderFieldManipulationDetails = ({ measurement, render }) => { const testKeys = measurement.test_keys let isAnomaly = false let isFailed = true - const tampering = testKeys.tampering + const tampering = testKeys?.tampering || {} Object.keys(tampering).forEach((key) => { if (tampering[key] === true) { isAnomaly = true @@ -18,7 +18,6 @@ export const HttpHeaderFieldManipulationDetails = ({ measurement, render }) => { isFailed = false } }) - const headerDiff = testKeys.tampering.header_name_diff return ( render({ @@ -29,13 +28,6 @@ export const HttpHeaderFieldManipulationDetails = ({ measurement, render }) => { summaryText: isAnomaly ? 'Measurement.HTTPHeaderManipulation.MiddleBoxesDetected.SummaryText' : 'Measurement.HTTPHeaderManipulation.NoMiddleBoxes.SummaryText', - details: ( -
- {/*isAnomaly: {isAnomaly.toString()} - isFailed: {isFailed.toString()} - headerDiff: {headerDiff.toString()}*/} -
- ) }) ) } diff --git a/components/measurement/nettests/Ndt.js b/components/measurement/nettests/Ndt.js index 24c3b3a2f..f5b6d8c2b 100644 --- a/components/measurement/nettests/Ndt.js +++ b/components/measurement/nettests/Ndt.js @@ -26,7 +26,7 @@ const InfoBoxItem = ({ ) -const ServerLocation = ({ serverAddress, isNdt7 }) => { +const ServerLocation = ({ serverAddress = '', isNdt7 }) => { const server = mlabServerDetails(serverAddress, isNdt7) return ( @@ -41,6 +41,7 @@ const ServerLocation = ({ serverAddress, isNdt7 }) => { const NdtDetails = ({ measurement, render }) => { const intl = useIntl() const testKeys = measurement.test_keys + const isFailed = testKeys.failure !== null const failure = testKeys.failure const isNdt7 = testKeys.protocol === 7 @@ -55,27 +56,44 @@ const NdtDetails = ({ measurement, render }) => { const uploadMbit = simple.upload && (simple.upload / 1000).toFixed(2) const ping = simple.ping && (simple.ping).toFixed(1) - if (isNdt7) { - const summary = testKeys.summary || {} - - // Summary - packetLoss = summary.retransmit_rate && (summary.retransmit_rate * 100).toFixed(3) - minRTT = summary.min_rtt && (summary.min_rtt).toFixed(0) - maxRTT = summary.max_rtt && (summary.max_rtt).toFixed(0) - mss = summary.mss - outOfOrder = null - timeouts = null - } - else { - const advanced = testKeys.advanced || {} - - // Advanced - packetLoss = advanced.packet_loss && (advanced.packet_loss * 100).toFixed(3) - outOfOrder = advanced.out_of_order && (advanced.out_of_order * 100).toFixed(1) - minRTT = advanced.min_rtt && (advanced.min_rtt).toFixed(0) - maxRTT = advanced.max_rtt && (advanced.max_rtt).toFixed(0) - mss = advanced.mss - timeouts = advanced.timeouts + let performanceDetails = null + try { + if (isNdt7) { + const summary = testKeys.summary || {} + // Summary + packetLoss = summary.retransmit_rate && (summary.retransmit_rate * 100).toFixed(3) + minRTT = summary.min_rtt && (summary.min_rtt).toFixed(0) + maxRTT = summary.max_rtt && (summary.max_rtt).toFixed(0) + mss = summary.mss + outOfOrder = null + timeouts = null + } + else { + const advanced = testKeys.advanced || null + // Advanced + delete advanced['out_of_order'] + packetLoss = advanced.packet_loss && (advanced.packet_loss * 100).toFixed(3) + outOfOrder = advanced.out_of_order && (advanced.out_of_order * 100).toFixed(1) + minRTT = advanced.min_rtt && (advanced.min_rtt).toFixed(0) + maxRTT = advanced.max_rtt && (advanced.max_rtt).toFixed(0) + mss = advanced?.mss + timeouts = advanced?.timeouts + } + performanceDetails = ( + + ) + } catch (e) { + console.error(`Error in parsing test_keys for ${measurement.test_name}`) + console.error(e) + // Leaves performanceDetails `null` and thus isn't rendered } // FIXME we need to style the failed test case properly @@ -85,38 +103,30 @@ const NdtDetails = ({ measurement, render }) => { statusLabel: intl.formatMessage({id: 'Measurement.Hero.Status.NDT.Title'}), statusInfo: ( - {isFailed ? + {isFailed ? (

Failed Test

- : + ) : ( } + content={ + + } /> - } + )}
), details: ( -
{!isFailed && - } -
+
{!isFailed && performanceDetails}
) }) ) diff --git a/components/measurement/nettests/WebConnectivity.js b/components/measurement/nettests/WebConnectivity.js index 210ad2448..b4120f81f 100644 --- a/components/measurement/nettests/WebConnectivity.js +++ b/components/measurement/nettests/WebConnectivity.js @@ -150,6 +150,9 @@ const RequestResponseContainer = ({request}) => { } const FailureString = ({failure}) => { + if (typeof failure === 'undefined') { + return () + } if (!failure) { return (
diff --git a/components/measurement/useTestKeyController.js b/components/measurement/useTestKeyController.js new file mode 100644 index 000000000..16959facd --- /dev/null +++ b/components/measurement/useTestKeyController.js @@ -0,0 +1,72 @@ +// This file contains a custom hook to render a toolbar +// that can be used to enable/disable parts of `testKeys` +// To use it, add the below code in components/measurement/MeasurementContainer.js +/* +import { useTestKeyController } from './useTestKeyController' +... +... +const { testKeys, TestKeyController } = useTestKeyController(measurement.test_keys) +const measurementMod = Object.assign({}, measurement, { test_keys: testKeys }) + +return ( + + + + +) +*/ + +import React, { useState, useCallback } from 'react' +import { Flex } from 'ooni-components' + + +const setValues = (input, value = true) => { + // Maps each key in `test_keys` to a boolean value, by default true + return Object.keys(input).reduce((o, k) => { + o[k] = value + return o + }, {all: value}) +} + +export const useTestKeyController = (testKeysInitial) => { + const [testKeys, setTestKeys] = useState(testKeysInitial) + const [keysMap, setKeysMap] = useState(setValues(testKeysInitial)) + + const TestKeyController = () => { + const onChange = useCallback((event) => { + const {name, checked} = event.target + + if (name === 'all') { + setTestKeys(checked ? testKeysInitial : {}) + setKeysMap(setValues(testKeysInitial, checked)) + } else { + const newTestKeys = {...testKeys} + // add or delete the original entry from `test_keys` + if (checked) { + newTestKeys[name] = testKeysInitial[name] + } else { + delete newTestKeys[name] + } + setTestKeys(newTestKeys) + setKeysMap(keysMap => { + const newKeysMap = {...keysMap} + newKeysMap[name] = checked + return newKeysMap + }) + } + }, [keysMap, testKeys, setKeysMap, setTestKeys]) + + return ( + + {Object.keys(keysMap).map((k, i) => + + + + + )} + + ) + } + + return { testKeys, TestKeyController } +}