Commit a189ffe5 authored by Zack Cuddy's avatar Zack Cuddy Committed by Nicolò Maria Mezzopera

Geo - Fix incorrect percentages

There was a rounding bug
on the node status bar
page.

We rounded decimals to the
.10 place which wasn't
accurate enough.

This instead rounds
down to the .10 space.

This ensures we never run
into a false 100%.
parent 509feeef
...@@ -740,6 +740,24 @@ export const roundOffFloat = (number, precision = 0) => { ...@@ -740,6 +740,24 @@ export const roundOffFloat = (number, precision = 0) => {
return Math.round(number * multiplier) / multiplier; return Math.round(number * multiplier) / multiplier;
}; };
/**
* Method to round down values with decimal places
* with provided precision.
*
* Eg; roundDownFloat(3.141592, 3) = 3.141
*
* Refer to spec/javascripts/lib/utils/common_utils_spec.js for
* more supported examples.
*
* @param {Float} number
* @param {Number} precision
*/
export const roundDownFloat = (number, precision = 0) => {
// eslint-disable-next-line no-restricted-properties
const multiplier = Math.pow(10, precision);
return Math.floor(number * multiplier) / multiplier;
};
/** /**
* Represents navigation type constants of the Performance Navigation API. * Represents navigation type constants of the Performance Navigation API.
* Detailed explanation see https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigation. * Detailed explanation see https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigation.
......
<script> <script>
import { GlTooltipDirective } from '@gitlab/ui'; import { GlTooltipDirective } from '@gitlab/ui';
import { __ } from '~/locale'; import { __ } from '~/locale';
import { roundOffFloat } from '~/lib/utils/common_utils'; import { roundDownFloat } from '~/lib/utils/common_utils';
export default { export default {
directives: { directives: {
...@@ -89,7 +89,7 @@ export default { ...@@ -89,7 +89,7 @@ export default {
return 0; return 0;
} }
const percent = roundOffFloat((count / this.totalCount) * 100, 1); const percent = roundDownFloat((count / this.totalCount) * 100, 1);
if (percent > 0 && percent < 1) { if (percent > 0 && percent < 1) {
return '< 1'; return '< 1';
} }
......
---
title: Geo Nodes Status - Fix incorrect percentages
merge_request: 47013
author:
type: fixed
...@@ -959,6 +959,25 @@ describe('common_utils', () => { ...@@ -959,6 +959,25 @@ describe('common_utils', () => {
}); });
}); });
describe('roundDownFloat', () => {
it('Rounds down decimal places of a float number with provided precision', () => {
expect(commonUtils.roundDownFloat(3.141592, 3)).toBe(3.141);
});
it('Rounds down a float number to a whole number when provided precision is zero', () => {
expect(commonUtils.roundDownFloat(3.141592, 0)).toBe(3);
expect(commonUtils.roundDownFloat(3.9, 0)).toBe(3);
});
it('Rounds down float number to nearest 0, 10, 100, 1000 and so on when provided precision is below 0', () => {
expect(commonUtils.roundDownFloat(34567.14159, -1)).toBeCloseTo(34560);
expect(commonUtils.roundDownFloat(34567.14159, -2)).toBeCloseTo(34500);
expect(commonUtils.roundDownFloat(34567.14159, -3)).toBeCloseTo(34000);
expect(commonUtils.roundDownFloat(34567.14159, -4)).toBeCloseTo(30000);
expect(commonUtils.roundDownFloat(34567.14159, -5)).toBeCloseTo(0);
});
});
describe('searchBy', () => { describe('searchBy', () => {
const searchSpace = { const searchSpace = {
iid: 1, iid: 1,
......
...@@ -29,6 +29,13 @@ describe('StackedProgressBarComponent', () => { ...@@ -29,6 +29,13 @@ describe('StackedProgressBarComponent', () => {
vm.$destroy(); vm.$destroy();
}); });
const findSuccessBarText = wrapper => wrapper.$el.querySelector('.status-green').innerText.trim();
const findNeutralBarText = wrapper =>
wrapper.$el.querySelector('.status-neutral').innerText.trim();
const findFailureBarText = wrapper => wrapper.$el.querySelector('.status-red').innerText.trim();
const findUnavailableBarText = wrapper =>
wrapper.$el.querySelector('.status-unavailable').innerText.trim();
describe('computed', () => { describe('computed', () => {
describe('neutralCount', () => { describe('neutralCount', () => {
it('returns neutralCount based on totalCount, successCount and failureCount', () => { it('returns neutralCount based on totalCount, successCount and failureCount', () => {
...@@ -37,24 +44,54 @@ describe('StackedProgressBarComponent', () => { ...@@ -37,24 +44,54 @@ describe('StackedProgressBarComponent', () => {
}); });
}); });
describe('methods', () => { describe('template', () => {
it('renders container element', () => {
expect(vm.$el.classList.contains('stacked-progress-bar')).toBeTruthy();
});
it('renders empty state when count is unavailable', () => {
const vmX = createComponent({ totalCount: 0, successCount: 0, failureCount: 0 });
expect(findUnavailableBarText(vmX)).not.toBeUndefined();
});
it('renders bar elements when count is available', () => {
expect(findSuccessBarText(vm)).not.toBeUndefined();
expect(findNeutralBarText(vm)).not.toBeUndefined();
expect(findFailureBarText(vm)).not.toBeUndefined();
});
describe('getPercent', () => { describe('getPercent', () => {
it('returns percentage from provided count based on `totalCount`', () => { it('returns correct percentages from provided count based on `totalCount`', () => {
expect(vm.getPercent(500)).toBe(10); vm = createComponent({ totalCount: 100, successCount: 25, failureCount: 10 });
expect(findSuccessBarText(vm)).toBe('25%');
expect(findNeutralBarText(vm)).toBe('65%');
expect(findFailureBarText(vm)).toBe('10%');
}); });
it('returns percentage with decimal place from provided count based on `totalCount`', () => { it('returns percentage with decimal place when decimal is greater than 1', () => {
expect(vm.getPercent(67)).toBe(1.3); vm = createComponent({ successCount: 67 });
expect(findSuccessBarText(vm)).toBe('1.3%');
}); });
it('returns percentage as `< 1` from provided count based on `totalCount` when evaluated value is less than 1', () => { it('returns percentage as `< 1%` from provided count based on `totalCount` when evaluated value is less than 1', () => {
expect(vm.getPercent(10)).toBe('< 1'); vm = createComponent({ successCount: 10 });
expect(findSuccessBarText(vm)).toBe('< 1%');
}); });
it('returns 0 if totalCount is falsy', () => { it('returns not available if totalCount is falsy', () => {
vm = createComponent({ totalCount: 0 }); vm = createComponent({ totalCount: 0 });
expect(vm.getPercent(100)).toBe(0); expect(findUnavailableBarText(vm)).toBe('Not available');
});
it('returns 99.9% when numbers are extreme decimals', () => {
vm = createComponent({ totalCount: 1000000 });
expect(findNeutralBarText(vm)).toBe('99.9%');
}); });
}); });
...@@ -82,23 +119,4 @@ describe('StackedProgressBarComponent', () => { ...@@ -82,23 +119,4 @@ describe('StackedProgressBarComponent', () => {
}); });
}); });
}); });
describe('template', () => {
it('renders container element', () => {
expect(vm.$el.classList.contains('stacked-progress-bar')).toBeTruthy();
});
it('renders empty state when count is unavailable', () => {
const vmX = createComponent({ totalCount: 0, successCount: 0, failureCount: 0 });
expect(vmX.$el.querySelectorAll('.status-unavailable').length).not.toBe(0);
vmX.$destroy();
});
it('renders bar elements when count is available', () => {
expect(vm.$el.querySelectorAll('.status-green').length).not.toBe(0);
expect(vm.$el.querySelectorAll('.status-neutral').length).not.toBe(0);
expect(vm.$el.querySelectorAll('.status-red').length).not.toBe(0);
});
});
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment