fix(quota): guard remaining usage percent (#1242)
* fix(quota): guard remaining usage percent * test(quota): cover non-finite usage percents * fix(ui): clean up virtual scroll frame --------- Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com> Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
This commit is contained in:
committed by
GitHub
co-authored by
Isaac Sanchez
Bohdan Triapitsyn
parent
eb8b9ed715
commit
11e5ab93a9
@@ -1355,8 +1355,9 @@ const MessageList = React.forwardRef<MessageListHandle, MessageListProps>(({
|
|||||||
// measure() defers via useAnimationFrameWithResizeObserver.
|
// measure() defers via useAnimationFrameWithResizeObserver.
|
||||||
// Wait two frames then, if we were near the estimated bottom, scroll
|
// Wait two frames then, if we were near the estimated bottom, scroll
|
||||||
// to the real bottom after measurements settle.
|
// to the real bottom after measurements settle.
|
||||||
|
let frame2: number | null = null;
|
||||||
const frame1 = requestAnimationFrame(() => {
|
const frame1 = requestAnimationFrame(() => {
|
||||||
const frame2 = requestAnimationFrame(() => {
|
frame2 = requestAnimationFrame(() => {
|
||||||
if (!nearBottom) return
|
if (!nearBottom) return
|
||||||
const el = resolveScrollContainer()
|
const el = resolveScrollContainer()
|
||||||
if (!el) return
|
if (!el) return
|
||||||
@@ -1368,8 +1369,11 @@ const MessageList = React.forwardRef<MessageListHandle, MessageListProps>(({
|
|||||||
})
|
})
|
||||||
return () => {
|
return () => {
|
||||||
cancelAnimationFrame(frame1)
|
cancelAnimationFrame(frame1)
|
||||||
|
if (frame2 !== null) {
|
||||||
|
cancelAnimationFrame(frame2)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, [historyVirtualizer, shouldVirtualizeHistory]);
|
}, [historyVirtualizer, resolveScrollContainer, shouldVirtualizeHistory]);
|
||||||
|
|
||||||
const scheduleVirtualMeasure = React.useCallback(() => {
|
const scheduleVirtualMeasure = React.useCallback(() => {
|
||||||
if (!shouldVirtualizeHistory) {
|
if (!shouldVirtualizeHistory) {
|
||||||
|
|||||||
@@ -40,9 +40,10 @@ export const calculateResetAfterSeconds = (resetAt) => {
|
|||||||
export const toUsageWindow = ({ usedPercent, windowSeconds, resetAt, valueLabel }) => {
|
export const toUsageWindow = ({ usedPercent, windowSeconds, resetAt, valueLabel }) => {
|
||||||
const resetAfterSeconds = calculateResetAfterSeconds(resetAt);
|
const resetAfterSeconds = calculateResetAfterSeconds(resetAt);
|
||||||
const resetFormatted = hasResetTimestamp(resetAt) ? formatResetTime(resetAt) : null;
|
const resetFormatted = hasResetTimestamp(resetAt) ? formatResetTime(resetAt) : null;
|
||||||
|
const hasFiniteUsedPercent = typeof usedPercent === 'number' && Number.isFinite(usedPercent);
|
||||||
return {
|
return {
|
||||||
usedPercent,
|
usedPercent,
|
||||||
remainingPercent: usedPercent !== null ? Math.max(0, 100 - usedPercent) : null,
|
remainingPercent: hasFiniteUsedPercent ? Math.max(0, 100 - usedPercent) : null,
|
||||||
windowSeconds: windowSeconds ?? null,
|
windowSeconds: windowSeconds ?? null,
|
||||||
resetAfterSeconds,
|
resetAfterSeconds,
|
||||||
resetAt,
|
resetAt,
|
||||||
|
|||||||
@@ -32,4 +32,23 @@ describe('toUsageWindow', () => {
|
|||||||
expect(usageWindow.resetAtFormatted).toBe(formatResetTime(0));
|
expect(usageWindow.resetAtFormatted).toBe(formatResetTime(0));
|
||||||
expect(usageWindow.resetAfterFormatted).toBe(formatResetTime(0));
|
expect(usageWindow.resetAfterFormatted).toBe(formatResetTime(0));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('does not derive remaining percent from missing usage', () => {
|
||||||
|
expect(toUsageWindow({ usedPercent: undefined }).remainingPercent).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not derive remaining percent from non-finite usage', () => {
|
||||||
|
expect(toUsageWindow({ usedPercent: NaN }).remainingPercent).toBeNull();
|
||||||
|
expect(toUsageWindow({ usedPercent: Infinity }).remainingPercent).toBeNull();
|
||||||
|
expect(toUsageWindow({ usedPercent: -Infinity }).remainingPercent).toBeNull();
|
||||||
|
expect(toUsageWindow({ usedPercent: null }).remainingPercent).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('derives remaining percent from a valid usage value', () => {
|
||||||
|
expect(toUsageWindow({ usedPercent: 60 }).remainingPercent).toBe(40);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('clamps remaining percent to zero when usage exceeds 100', () => {
|
||||||
|
expect(toUsageWindow({ usedPercent: 110 }).remainingPercent).toBe(0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user