Skip to content

Commit

Permalink
CRDCDH-956 Sort charts by Node Total
Browse files Browse the repository at this point in the history
Also add missing test cases for stats
  • Loading branch information
amattu2 committed Mar 14, 2024
1 parent 92f81d3 commit a87db98
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 6 deletions.
94 changes: 94 additions & 0 deletions src/utils/statisticUtils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import * as utils from "./statisticUtils";

describe("compareNodeStats cases", () => {
const node1A = { total: 1, nodeName: "NodeA" } as SubmissionStatistic;
const node1B = { total: 1, nodeName: "NodeB" } as SubmissionStatistic;
const node3A = { total: 3, nodeName: "AAA Node" } as SubmissionStatistic;
const node3B = { total: 3, nodeName: "Node3" } as SubmissionStatistic;
const node5 = { total: 5, nodeName: "Node5" } as SubmissionStatistic;

it("should correctly sort in ascending order by node.total", () => {
const sortedStats = [node3B, node1A, node5].sort(utils.compareNodeStats);

expect(sortedStats).toEqual([node1A, node3B, node5]);
});

it("should correctly sort in ascending order by node.nodeName when node.total is equal", () => {
const sortedStats = [node3B, node1A, node3A, node1B].sort(utils.compareNodeStats);

expect(sortedStats).toEqual([node1A, node1B, node3A, node3B]);
});
it("should return 1 when a.total is greater than b.total", () => {
const a = { total: 2, nodeName: "Node 1" } as SubmissionStatistic;
const b = { total: 1, nodeName: "Node 2" } as SubmissionStatistic;

expect(utils.compareNodeStats(a, b)).toEqual(1);
});

it("should return 1 when a.nodeName comes after b.nodeName", () => {
const a = { total: 1, nodeName: "Node 2" } as SubmissionStatistic;
const b = { total: 1, nodeName: "Node 1" } as SubmissionStatistic;

expect(utils.compareNodeStats(a, b)).toEqual(1);
});

it("should return 0 when both nodes are equal 1/2", () => {
const a = { total: 1, nodeName: "Node 1" } as SubmissionStatistic;
const b = { total: 1, nodeName: "Node 1" } as SubmissionStatistic;

expect(utils.compareNodeStats(a, b)).toEqual(0);
});

it("should return 0 when both nodes are equal 2/2", () => {
const a = { total: 0, nodeName: "" } as SubmissionStatistic;
const b = { total: 0, nodeName: "" } as SubmissionStatistic;

expect(utils.compareNodeStats(a, b)).toEqual(0);
});

it("should return -1 when a.total is less than b.total", () => {
const a = { total: 1, nodeName: "Node 1" } as SubmissionStatistic;
const b = { total: 2, nodeName: "Node 2" } as SubmissionStatistic;

expect(utils.compareNodeStats(a, b)).toEqual(-1);
});

it("should return -1 when a.nodeName comes before b.nodeName", () => {
const a = { total: 1, nodeName: "Node 1" } as SubmissionStatistic;
const b = { total: 1, nodeName: "Node 2" } as SubmissionStatistic;

expect(utils.compareNodeStats(a, b)).toEqual(-1);
});
});

describe('calculateMaxDomain cases', () => {
it.each([-1, NaN, undefined, 0, Infinity, -Infinity])('should default to 1 when dataMax is invalid (%s)', (dataMax) => {
expect(utils.calculateMaxDomain(dataMax)).toBe(1);
});

it('should round up to the nearest 1,000 when dataMax above 1,000', () => {
expect(utils.calculateMaxDomain(1001)).toBe(2000);
expect(utils.calculateMaxDomain(2500)).toBe(3000);
expect(utils.calculateMaxDomain(10000)).toBe(10000);
expect(utils.calculateMaxDomain(23949)).toBe(24000);
});

it('should round up to the nearest 100 when dataMax is between 100 and 1,000', () => {
expect(utils.calculateMaxDomain(101)).toBe(200);
expect(utils.calculateMaxDomain(550)).toBe(600);
expect(utils.calculateMaxDomain(1000)).toBe(1000);
});

it('should round up to the nearest 10 when dataMax is between 10 and 100', () => {
expect(utils.calculateMaxDomain(11)).toBe(20);
expect(utils.calculateMaxDomain(55)).toBe(60);
expect(utils.calculateMaxDomain(99)).toBe(100);
expect(utils.calculateMaxDomain(100)).toBe(100);
});

it("should round up to the nearest 10 when dataMax is between 1 and 10", () => {
expect(utils.calculateMaxDomain(1)).toBe(10);
expect(utils.calculateMaxDomain(5)).toBe(10);
expect(utils.calculateMaxDomain(10)).toBe(10);
});
});
23 changes: 17 additions & 6 deletions src/utils/statisticUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,25 @@ export const buildPrimaryChartSeries = (stats: SubmissionStatistic[], omitSeries
}));

/**
* A utility function to sort the node statistics by the node name
* A utility function to sort the node statistics in ascending order by:
*
* - SubmissionStatistic.total (primary)
* - SubmissionStatistic.nodeName (secondary)
*
* This utility is required because the API does not guarantee the order of the nodes,
* and changing the order of the nodes causes re-animation of the charts.
*
* @param stats Data Submissions statistics
* @returns The sorted statistics
* @param a The first SubmissionStatistic
* @param b The second SubmissionStatistic
* @returns The comparison result
*/
export const compareNodeStats = (a: SubmissionStatistic, b: SubmissionStatistic) => a.nodeName.localeCompare(b.nodeName);
export const compareNodeStats = (a: SubmissionStatistic, b: SubmissionStatistic): number => {
if (a.total === b.total) {
return a.nodeName.localeCompare(b.nodeName);
}

return a.total - b.total;
};

/**
* Format a Y-Axis tick label
Expand All @@ -62,8 +73,8 @@ export const formatTick = (tick: number, normalized = false) => (normalized
* @param dataMax The maximum value in the dataset
* @returns The calculated maximum domain
*/
export const calculateMaxDomain = (dataMax: number) => {
if (dataMax <= 0 || Number.isNaN(dataMax)) {
export const calculateMaxDomain = (dataMax: number): number => {
if (dataMax <= 0 || Number.isNaN(dataMax) || !Number.isFinite(dataMax)) {
return 1;
}
if (dataMax > 1000) {
Expand Down

0 comments on commit a87db98

Please sign in to comment.