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.
|
||||
// Wait two frames then, if we were near the estimated bottom, scroll
|
||||
// to the real bottom after measurements settle.
|
||||
let frame2: number | null = null;
|
||||
const frame1 = requestAnimationFrame(() => {
|
||||
const frame2 = requestAnimationFrame(() => {
|
||||
frame2 = requestAnimationFrame(() => {
|
||||
if (!nearBottom) return
|
||||
const el = resolveScrollContainer()
|
||||
if (!el) return
|
||||
@@ -1368,8 +1369,11 @@ const MessageList = React.forwardRef<MessageListHandle, MessageListProps>(({
|
||||
})
|
||||
return () => {
|
||||
cancelAnimationFrame(frame1)
|
||||
if (frame2 !== null) {
|
||||
cancelAnimationFrame(frame2)
|
||||
}
|
||||
}
|
||||
}, [historyVirtualizer, shouldVirtualizeHistory]);
|
||||
}, [historyVirtualizer, resolveScrollContainer, shouldVirtualizeHistory]);
|
||||
|
||||
const scheduleVirtualMeasure = React.useCallback(() => {
|
||||
if (!shouldVirtualizeHistory) {
|
||||
|
||||
@@ -40,9 +40,10 @@ export const calculateResetAfterSeconds = (resetAt) => {
|
||||
export const toUsageWindow = ({ usedPercent, windowSeconds, resetAt, valueLabel }) => {
|
||||
const resetAfterSeconds = calculateResetAfterSeconds(resetAt);
|
||||
const resetFormatted = hasResetTimestamp(resetAt) ? formatResetTime(resetAt) : null;
|
||||
const hasFiniteUsedPercent = typeof usedPercent === 'number' && Number.isFinite(usedPercent);
|
||||
return {
|
||||
usedPercent,
|
||||
remainingPercent: usedPercent !== null ? Math.max(0, 100 - usedPercent) : null,
|
||||
remainingPercent: hasFiniteUsedPercent ? Math.max(0, 100 - usedPercent) : null,
|
||||
windowSeconds: windowSeconds ?? null,
|
||||
resetAfterSeconds,
|
||||
resetAt,
|
||||
|
||||
@@ -32,4 +32,23 @@ describe('toUsageWindow', () => {
|
||||
expect(usageWindow.resetAtFormatted).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