mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
TraceView: Remove unused trace selectors (#70527)
Remove unused selectors
This commit is contained in:
parent
da54fe8ae8
commit
5b13b71ed0
@ -17,35 +17,14 @@ import { values as _values } from 'lodash';
|
||||
import TreeNode from 'app/features/explore/TraceView/components/utils/TreeNode';
|
||||
|
||||
import traceGenerator from '../demo/trace-generators';
|
||||
import { TraceResponse, TraceSpan, TraceSpanData } from '../types/trace';
|
||||
import { numberSortComparator } from '../utils/sort';
|
||||
import { TraceResponse } from '../types/trace';
|
||||
|
||||
import {
|
||||
getSpanId,
|
||||
getSpanName,
|
||||
getSpanParentId,
|
||||
getSpanProcess,
|
||||
getSpanProcessId,
|
||||
getSpanServiceName,
|
||||
getSpanTimestamp,
|
||||
} from './span';
|
||||
import { getSpanId, getSpanParentId } from './span';
|
||||
import * as traceSelectors from './trace';
|
||||
import { followsFromRef } from './trace.fixture';
|
||||
|
||||
const generatedTrace: TraceResponse = traceGenerator.trace({ numberOfSpans: 45 });
|
||||
|
||||
it('getTraceId() should return the traceID', () => {
|
||||
expect(traceSelectors.getTraceId(generatedTrace)).toBe(generatedTrace.traceID);
|
||||
});
|
||||
|
||||
it('hydrateSpansWithProcesses() should return the trace with processes on each span', () => {
|
||||
const hydratedTrace = traceSelectors.hydrateSpansWithProcesses(generatedTrace);
|
||||
|
||||
hydratedTrace.spans.forEach((span) =>
|
||||
expect(getSpanProcess(span as TraceSpan)).toBe(generatedTrace.processes[getSpanProcessId(span)])
|
||||
);
|
||||
});
|
||||
|
||||
it('getTraceSpansAsMap() should return a map of all of the spans', () => {
|
||||
const spanMap = traceSelectors.getTraceSpansAsMap(generatedTrace);
|
||||
[...spanMap.entries()].forEach((pair) => {
|
||||
@ -70,300 +49,3 @@ describe('getTraceSpanIdsAsTree()', () => {
|
||||
expect(() => traceSelectors.getTraceSpanIdsAsTree(followsFromRef)).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
it('getParentSpan() should return the parent span of the tree', () => {
|
||||
expect(traceSelectors.getParentSpan(generatedTrace)).toBe(
|
||||
traceSelectors
|
||||
.getTraceSpansAsMap(generatedTrace)
|
||||
.get(traceSelectors.getTraceSpanIdsAsTree(generatedTrace).children[0].value)
|
||||
);
|
||||
});
|
||||
|
||||
it('getParentSpan() should return the first span if there are multiple parents', () => {
|
||||
const initialTimestamp = new Date().getTime() * 1000;
|
||||
const firstSpan = {
|
||||
startTime: initialTimestamp,
|
||||
spanID: 'my-span-1',
|
||||
references: [],
|
||||
};
|
||||
|
||||
const trace = {
|
||||
spans: [
|
||||
{
|
||||
startTime: initialTimestamp + 2000,
|
||||
spanID: 'my-span-3',
|
||||
references: [],
|
||||
},
|
||||
firstSpan,
|
||||
{
|
||||
startTime: initialTimestamp + 1000,
|
||||
spanID: 'my-span-2',
|
||||
references: [],
|
||||
},
|
||||
],
|
||||
} as unknown as TraceResponse;
|
||||
|
||||
expect(traceSelectors.getParentSpan(trace)).toBe(firstSpan);
|
||||
});
|
||||
|
||||
it('getTraceName() should return a formatted name for the first span', () => {
|
||||
const hydratedTrace = traceSelectors.hydrateSpansWithProcesses(generatedTrace);
|
||||
const parentSpan = traceSelectors.getParentSpan(hydratedTrace);
|
||||
|
||||
expect(traceSelectors.getTraceName(hydratedTrace)).toBe(
|
||||
`${getSpanServiceName(parentSpan)}: ${getSpanName(parentSpan)}`
|
||||
);
|
||||
});
|
||||
|
||||
it('getTraceSpanCount() should return the length of the spans array', () => {
|
||||
expect(traceSelectors.getTraceSpanCount(generatedTrace)).toBe(generatedTrace.spans.length);
|
||||
});
|
||||
|
||||
it('getTraceDuration() should return the duration for the span', () => {
|
||||
expect(traceSelectors.getTraceDuration(generatedTrace)).toBe(generatedTrace.spans[0].duration);
|
||||
});
|
||||
|
||||
it('getTraceTimestamp() should return the first timestamp for the conventional trace', () => {
|
||||
expect(traceSelectors.getTraceTimestamp(generatedTrace)).toBe(generatedTrace.spans[0].startTime);
|
||||
});
|
||||
|
||||
it('getTraceDepth() should determine the total depth of the trace tree', () => {
|
||||
expect(traceSelectors.getTraceDepth(generatedTrace)).toBe(
|
||||
traceSelectors.getTraceSpanIdsAsTree(generatedTrace).depth - 1
|
||||
);
|
||||
});
|
||||
|
||||
it('getSpanDepthForTrace() should determine the depth of a given span in the parent', () => {
|
||||
function testDepthCalc(span: TraceSpanData) {
|
||||
let depth = 2;
|
||||
let currentId = getSpanParentId(span);
|
||||
|
||||
const findCurrentSpanById = (item: TraceSpanData) => getSpanId(item) === currentId;
|
||||
while (currentId !== getSpanId(generatedTrace.spans[0])) {
|
||||
depth++;
|
||||
currentId = getSpanParentId(generatedTrace.spans.find(findCurrentSpanById)!);
|
||||
}
|
||||
|
||||
// console.log('hypothetical depth', depth);
|
||||
|
||||
expect(
|
||||
traceSelectors.getSpanDepthForTrace({
|
||||
trace: generatedTrace,
|
||||
span,
|
||||
})
|
||||
).toBe(depth);
|
||||
}
|
||||
|
||||
// test depth calculations for a few random spans
|
||||
testDepthCalc(generatedTrace.spans[1]);
|
||||
testDepthCalc(generatedTrace.spans[Math.floor(generatedTrace.spans.length / 2)]);
|
||||
testDepthCalc(generatedTrace.spans[Math.floor(generatedTrace.spans.length / 4)]);
|
||||
testDepthCalc(generatedTrace.spans[Math.floor(generatedTrace.spans.length * 0.75)]);
|
||||
});
|
||||
|
||||
it('getTraceServices() should return an unique array of all services in the trace', () => {
|
||||
const svcs = [...traceSelectors.getTraceServices(generatedTrace)].sort();
|
||||
const set = new Set(_values(generatedTrace.processes).map((v) => v.serviceName));
|
||||
const setSvcs = [...set.values()].sort();
|
||||
expect(svcs).toEqual(setSvcs);
|
||||
});
|
||||
|
||||
it('getTraceServiceCount() should return the length of the service list', () => {
|
||||
expect(traceSelectors.getTraceServiceCount(generatedTrace)).toBe(
|
||||
Object.values(generatedTrace.processes).reduce((results, process) => results.add(process.serviceName), new Set())
|
||||
.size
|
||||
);
|
||||
});
|
||||
|
||||
it('formatDurationForUnit() should use the formatters to return the proper value', () => {
|
||||
expect(traceSelectors.formatDurationForUnit({ duration: 302000, unit: 'ms' })).toBe('302ms');
|
||||
|
||||
expect(traceSelectors.formatDurationForUnit({ duration: 1302000, unit: 'ms' })).toBe('1302ms');
|
||||
|
||||
expect(traceSelectors.formatDurationForUnit({ duration: 1302000, unit: 's' })).toBe('1.302s');
|
||||
|
||||
expect(traceSelectors.formatDurationForUnit({ duration: 90000, unit: 's' })).toBe('0.09s');
|
||||
});
|
||||
|
||||
it('formatDurationForTrace() should return a ms value for traces shorter than a second', () => {
|
||||
const firstSpan = generatedTrace.spans[0];
|
||||
firstSpan.duration = 600000;
|
||||
expect(
|
||||
traceSelectors.formatDurationForTrace({
|
||||
trace: {
|
||||
...generatedTrace,
|
||||
spans: [firstSpan],
|
||||
},
|
||||
duration: 302000,
|
||||
})
|
||||
).toBe('302ms');
|
||||
});
|
||||
|
||||
it('formatDurationForTrace() should return a s value for traces longer than a second', () => {
|
||||
expect(
|
||||
traceSelectors.formatDurationForTrace({
|
||||
trace: {
|
||||
...generatedTrace,
|
||||
spans: generatedTrace.spans.concat([
|
||||
{
|
||||
...generatedTrace.spans[0],
|
||||
duration: 1000000,
|
||||
},
|
||||
]),
|
||||
},
|
||||
duration: 302000,
|
||||
})
|
||||
).toBe('0.302s');
|
||||
|
||||
expect(
|
||||
traceSelectors.formatDurationForTrace({
|
||||
trace: {
|
||||
...generatedTrace,
|
||||
spans: generatedTrace.spans.concat([
|
||||
{
|
||||
...generatedTrace.spans[0],
|
||||
duration: 1200000,
|
||||
},
|
||||
]),
|
||||
},
|
||||
duration: 302000,
|
||||
})
|
||||
).toBe('0.302s');
|
||||
});
|
||||
|
||||
it('getSortedSpans() should sort spans given a sort object', () => {
|
||||
expect(
|
||||
traceSelectors.getSortedSpans({
|
||||
trace: generatedTrace,
|
||||
spans: generatedTrace.spans,
|
||||
sort: {
|
||||
dir: 1,
|
||||
comparator: numberSortComparator,
|
||||
selector: getSpanTimestamp,
|
||||
},
|
||||
})
|
||||
).toEqual([...generatedTrace.spans].sort((spanA, spanB) => spanA.startTime - spanB.startTime));
|
||||
|
||||
expect(
|
||||
traceSelectors.getSortedSpans({
|
||||
trace: generatedTrace,
|
||||
spans: generatedTrace.spans,
|
||||
sort: {
|
||||
dir: -1,
|
||||
comparator: numberSortComparator,
|
||||
selector: getSpanTimestamp,
|
||||
},
|
||||
})
|
||||
).toEqual([...generatedTrace.spans].sort((spanA, spanB) => spanB.startTime - spanA.startTime));
|
||||
});
|
||||
|
||||
it('getTreeSizeForTraceSpan() should return the size for the parent span', () => {
|
||||
expect(
|
||||
traceSelectors.getTreeSizeForTraceSpan({
|
||||
trace: generatedTrace,
|
||||
span: generatedTrace.spans[0],
|
||||
})
|
||||
).toBe(generatedTrace.spans.length - 1);
|
||||
});
|
||||
|
||||
it('getTreeSizeForTraceSpan() should return the size for a child span', () => {
|
||||
expect(
|
||||
traceSelectors.getTreeSizeForTraceSpan({
|
||||
trace: generatedTrace,
|
||||
span: generatedTrace.spans[1],
|
||||
})
|
||||
).toBe(traceSelectors.getTraceSpanIdsAsTree(generatedTrace).find(generatedTrace.spans[1].spanID)!.size - 1);
|
||||
});
|
||||
|
||||
it('getTreeSizeForTraceSpan() should return -1 for an absent span', () => {
|
||||
const absentSpan = generatedTrace.spans[0];
|
||||
absentSpan.spanID = 'whatever';
|
||||
|
||||
expect(
|
||||
traceSelectors.getTreeSizeForTraceSpan({
|
||||
trace: generatedTrace,
|
||||
span: absentSpan,
|
||||
})
|
||||
).toBe(-1);
|
||||
});
|
||||
|
||||
it('getTraceName() should return the trace name based on the parentSpan', () => {
|
||||
const serviceName = generatedTrace.processes[generatedTrace.spans[0].processID].serviceName;
|
||||
const operationName = generatedTrace.spans[0].operationName;
|
||||
|
||||
expect(traceSelectors.getTraceName(generatedTrace)).toBe(`${serviceName}: ${operationName}`);
|
||||
});
|
||||
|
||||
it('omitCollapsedSpans() should filter out collapsed spans', () => {
|
||||
const span = generatedTrace.spans[1];
|
||||
const size = traceSelectors.getTraceSpanIdsAsTree(generatedTrace).find(span.spanID)!.size - 1;
|
||||
|
||||
expect(
|
||||
traceSelectors.omitCollapsedSpans({
|
||||
trace: generatedTrace,
|
||||
spans: generatedTrace.spans,
|
||||
collapsed: [span.spanID],
|
||||
}).length
|
||||
).toBe(generatedTrace.spans.length - size);
|
||||
});
|
||||
|
||||
it('getTicksForTrace() should return a list of ticks given interval parameters', () => {
|
||||
const trace = generatedTrace;
|
||||
const timestamp = new Date().getTime() * 1000;
|
||||
|
||||
trace.spans.forEach((span) => {
|
||||
span.duration = 3000000;
|
||||
span.startTime = timestamp;
|
||||
});
|
||||
|
||||
expect(
|
||||
traceSelectors.getTicksForTrace({
|
||||
trace,
|
||||
interval: 3,
|
||||
width: 10,
|
||||
})
|
||||
).toEqual([
|
||||
{ timestamp, width: 10 },
|
||||
{ timestamp: timestamp + 1000000, width: 10 },
|
||||
{ timestamp: timestamp + 2000000, width: 10 },
|
||||
{ timestamp: timestamp + 3000000, width: 10 },
|
||||
]);
|
||||
});
|
||||
|
||||
it('getTicksForTrace() should use defaults', () => {
|
||||
const timestamp = new Date().getTime() * 1000;
|
||||
const trace = traceGenerator.trace({ numberOfSpans: 1 });
|
||||
|
||||
trace.spans = [
|
||||
{
|
||||
traceID: '5031233a-d0b5-5d41-9b4b-4c072bcf5020',
|
||||
processID: 'b5f4e0ff-7318-5017-a3f3-9c7b423a82aa',
|
||||
spanID: 'e871771f-f1b4-54af-9e9d-826259c2915e',
|
||||
flags: 0,
|
||||
logs: [],
|
||||
operationName: 'POST',
|
||||
startTime: timestamp,
|
||||
duration: 4000000,
|
||||
},
|
||||
];
|
||||
|
||||
expect(traceSelectors.getTicksForTrace({ trace })).toEqual([
|
||||
{ timestamp, width: traceSelectors.DEFAULT_TICK_WIDTH },
|
||||
{
|
||||
timestamp: timestamp + 1000000,
|
||||
width: traceSelectors.DEFAULT_TICK_WIDTH,
|
||||
},
|
||||
{
|
||||
timestamp: timestamp + 2000000,
|
||||
width: traceSelectors.DEFAULT_TICK_WIDTH,
|
||||
},
|
||||
{
|
||||
timestamp: timestamp + 3000000,
|
||||
width: traceSelectors.DEFAULT_TICK_WIDTH,
|
||||
},
|
||||
{
|
||||
timestamp: timestamp + 4000000,
|
||||
width: traceSelectors.DEFAULT_TICK_WIDTH,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
@ -12,35 +12,14 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { createSelector, createStructuredSelector } from 'reselect';
|
||||
import { createSelector } from 'reselect';
|
||||
|
||||
import { Trace, TraceData, TraceProcess, TraceResponse, TraceSpanData } from '../types/trace';
|
||||
import { TraceResponse, TraceSpanData } from '../types/trace';
|
||||
import TreeNode from '../utils/TreeNode';
|
||||
import { formatMillisecondTime, formatSecondTime, ONE_SECOND } from '../utils/date';
|
||||
import { numberSortComparator } from '../utils/sort';
|
||||
|
||||
import { getProcessServiceName } from './process';
|
||||
import {
|
||||
getSpanId,
|
||||
getSpanName,
|
||||
getSpanServiceName,
|
||||
getSpanTimestamp,
|
||||
getSpanDuration,
|
||||
getSpanProcessId,
|
||||
} from './span';
|
||||
import { getSpanId } from './span';
|
||||
|
||||
export const getTraceId = (trace: TraceData) => trace.traceID;
|
||||
export const getTraceSpans = (trace: TraceResponse) => trace.spans;
|
||||
const getTraceProcesses = (trace: TraceData | Trace) => trace.processes;
|
||||
|
||||
const getSpanWithProcess = createSelector(
|
||||
(state: { span: TraceSpanData; processes: Record<string, TraceProcess> }) => state.span,
|
||||
(state: { span: TraceSpanData; processes: Record<string, TraceProcess> }) => state.processes,
|
||||
(span, processes) => ({
|
||||
...span,
|
||||
process: processes[getSpanProcessId(span)],
|
||||
})
|
||||
);
|
||||
|
||||
export const getTraceSpansAsMap = createSelector(getTraceSpans, (spans) =>
|
||||
spans.reduce((map, span: TraceSpanData) => map.set(getSpanId(span), span), new Map())
|
||||
@ -95,127 +74,6 @@ export function getTraceSpanIdsAsTree(trace: TraceResponse) {
|
||||
return root;
|
||||
}
|
||||
|
||||
// attach "process" as an object to each span.
|
||||
export const hydrateSpansWithProcesses = (trace: TraceResponse) => {
|
||||
const spans = getTraceSpans(trace);
|
||||
const processes = getTraceProcesses(trace);
|
||||
|
||||
return {
|
||||
...trace,
|
||||
spans: spans.map((span: TraceSpanData) => getSpanWithProcess({ span, processes })),
|
||||
};
|
||||
};
|
||||
|
||||
export const getTraceSpanCount = createSelector(getTraceSpans, (spans) => spans.length);
|
||||
|
||||
export const getTraceTimestamp = createSelector(getTraceSpans, (spans) =>
|
||||
spans.reduce(
|
||||
(prevTimestamp: number, span: TraceSpanData) =>
|
||||
prevTimestamp ? Math.min(prevTimestamp, getSpanTimestamp(span)) : getSpanTimestamp(span),
|
||||
0
|
||||
)
|
||||
);
|
||||
|
||||
export const getTraceDuration = createSelector(getTraceSpans, getTraceTimestamp, (spans, timestamp) =>
|
||||
spans.reduce(
|
||||
(prevDuration: number, span: TraceSpanData) =>
|
||||
prevDuration
|
||||
? Math.max(getSpanTimestamp(span) - timestamp! + getSpanDuration(span), prevDuration)
|
||||
: getSpanDuration(span),
|
||||
0
|
||||
)
|
||||
);
|
||||
|
||||
export const getParentSpan = createSelector(
|
||||
getTraceSpanIdsAsTree,
|
||||
getTraceSpansAsMap,
|
||||
(tree, spanMap) =>
|
||||
tree.children
|
||||
.map((node: TreeNode) => spanMap.get(node.value))
|
||||
.sort((spanA: TraceSpanData, spanB: TraceSpanData) =>
|
||||
numberSortComparator(getSpanTimestamp(spanA), getSpanTimestamp(spanB))
|
||||
)[0]
|
||||
);
|
||||
|
||||
export const getTraceDepth = createSelector(getTraceSpanIdsAsTree, (spanTree) => spanTree.depth - 1);
|
||||
|
||||
export const getSpanDepthForTrace = createSelector(
|
||||
createSelector((state: { trace: TraceResponse }) => state.trace, getTraceSpanIdsAsTree),
|
||||
createSelector((state: { span: TraceSpanData }) => state.span, getSpanId),
|
||||
(node, spanID) => node.getPath(spanID)!.length - 1
|
||||
);
|
||||
|
||||
export const getTraceServices = createSelector(getTraceProcesses, (processes) =>
|
||||
Object.keys(processes).reduce(
|
||||
(services, processID) => services.add(getProcessServiceName(processes[processID])),
|
||||
new Set()
|
||||
)
|
||||
);
|
||||
|
||||
export const getTraceServiceCount = createSelector(getTraceServices, (services) => services.size);
|
||||
|
||||
// establish constants to determine how math should be handled
|
||||
// for nanosecond-to-millisecond conversions.
|
||||
export const DURATION_FORMATTERS = {
|
||||
ms: formatMillisecondTime,
|
||||
s: formatSecondTime,
|
||||
};
|
||||
|
||||
const getDurationFormatterForTrace = createSelector(getTraceDuration, (totalDuration: number) =>
|
||||
totalDuration >= ONE_SECOND ? DURATION_FORMATTERS.s : DURATION_FORMATTERS.ms
|
||||
);
|
||||
|
||||
export const formatDurationForUnit = createSelector(
|
||||
({ duration }: { duration: number }) => duration,
|
||||
({ unit }: { unit: 'ms' | 's' }) => DURATION_FORMATTERS[unit],
|
||||
(duration, formatter) => formatter(duration)
|
||||
);
|
||||
|
||||
export const formatDurationForTrace = createSelector(
|
||||
({ duration }: { duration: number }) => duration,
|
||||
createSelector(({ trace }: { trace: TraceResponse }) => trace, getDurationFormatterForTrace),
|
||||
(duration, formatter) => formatter(duration)
|
||||
);
|
||||
|
||||
export const getSortedSpans = createSelector(
|
||||
({ trace }: { trace: TraceResponse }) => trace,
|
||||
({ spans }: { spans: TraceSpanData[] }) => spans,
|
||||
({
|
||||
sort,
|
||||
}: {
|
||||
sort: {
|
||||
dir: number;
|
||||
comparator: (itemA: number, itemB: number) => number;
|
||||
selector: (itemA: TraceSpanData, itemB: TraceResponse) => number;
|
||||
};
|
||||
}) => sort,
|
||||
(trace, spans, { dir, comparator, selector }) =>
|
||||
[...spans].sort((spanA, spanB) => dir * comparator(selector(spanA, trace), selector(spanB, trace)))
|
||||
);
|
||||
|
||||
export const getTreeSizeForTraceSpan = createSelector(
|
||||
createSelector((state: { trace: TraceResponse }) => state.trace, getTraceSpanIdsAsTree),
|
||||
createSelector((state: { span: TraceSpanData }) => state.span, getSpanId),
|
||||
(tree, spanID) => {
|
||||
const node = tree.find(spanID);
|
||||
if (!node) {
|
||||
return -1;
|
||||
}
|
||||
return node.size - 1;
|
||||
}
|
||||
);
|
||||
|
||||
export const getTraceName = createSelector(
|
||||
createSelector(
|
||||
createSelector(hydrateSpansWithProcesses, getParentSpan),
|
||||
createStructuredSelector({
|
||||
name: getSpanName,
|
||||
serviceName: getSpanServiceName,
|
||||
})
|
||||
),
|
||||
({ name, serviceName }: { name: string; serviceName: string }) => `${serviceName}: ${name}`
|
||||
);
|
||||
|
||||
export const omitCollapsedSpans = createSelector(
|
||||
({ spans }: { spans: TraceSpanData[] }) => spans,
|
||||
createSelector(({ trace }: { trace: TraceResponse }) => trace, getTraceSpanIdsAsTree),
|
||||
@ -229,21 +87,3 @@ export const omitCollapsedSpans = createSelector(
|
||||
return hiddenSpanIds.size > 0 ? spans.filter((span) => !hiddenSpanIds.has(getSpanId(span))) : spans;
|
||||
}
|
||||
);
|
||||
|
||||
export const DEFAULT_TICK_INTERVAL = 4;
|
||||
export const DEFAULT_TICK_WIDTH = 3;
|
||||
export const getTicksForTrace = createSelector(
|
||||
({ trace }: { trace: TraceResponse }) => trace,
|
||||
({ interval = DEFAULT_TICK_INTERVAL }: { interval?: number }) => interval,
|
||||
({ width = DEFAULT_TICK_WIDTH }: { width?: number }) => width,
|
||||
(
|
||||
trace,
|
||||
interval: number,
|
||||
width: number
|
||||
// timestamps will be spaced over the interval, starting from the initial timestamp
|
||||
) =>
|
||||
[...Array(interval + 1).keys()].map((num) => ({
|
||||
timestamp: getTraceTimestamp(trace) + getTraceDuration(trace) * (num / interval),
|
||||
width,
|
||||
}))
|
||||
);
|
||||
|
@ -36,12 +36,6 @@ it('localeStringComparator() should properly sort a list of strings', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('numberSortComparator() should properly sort a list of numbers', () => {
|
||||
const arr = [3, -1.1, 4, -1, 9, 4, 2, Infinity, 0, 0];
|
||||
|
||||
expect(arr.sort(sortUtils.numberSortComparator)).toEqual([-1.1, -1, 0, 0, 2, 3, 4, 4, 9, Infinity]);
|
||||
});
|
||||
|
||||
it('classNameForSortDir() should return the proper asc classes', () => {
|
||||
expect(sortUtils.classNameForSortDir(1)).toBe('sorted ascending');
|
||||
});
|
||||
|
@ -16,10 +16,6 @@ export function localeStringComparator(itemA: string, itemB: string) {
|
||||
return itemA.localeCompare(itemB);
|
||||
}
|
||||
|
||||
export function numberSortComparator(itemA: number, itemB: number) {
|
||||
return itemA - itemB;
|
||||
}
|
||||
|
||||
export function classNameForSortDir(dir: number) {
|
||||
return `sorted ${dir === 1 ? 'ascending' : 'descending'}`;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user