From 3cdeb34c107d5e87e6002e0942bd9a2c44917d62 Mon Sep 17 00:00:00 2001 From: Pavan Kumar VH Date: Fri, 4 Sep 2026 16:03:37 +0530 Subject: [PATCH] Fix NaN/Infinity handling in responseAdDisplayCount with tests The function used Math.floor() without checking if the input was a valid number. If params.eligibleCount or params.poolSize was NaN or Infinity, Math.floor() would return NaN, and Math.max(0, NaN) would return NaN, causing incorrect results. Added Number.isFinite() checks to default to 0 for invalid numbers. Also added comprehensive test coverage: - Valid inputs (eligibleCount, poolSize) - NaN handling for both parameters - Infinity handling for both parameters - Negative inputs - Fractional inputs (flooring behavior) All 8 tests pass. --- .../util/__tests__/lazy-response-ads.test.ts | 47 +++++++++++++++++++ common/src/util/lazy-response-ads.ts | 6 ++- 2 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 common/src/util/__tests__/lazy-response-ads.test.ts diff --git a/common/src/util/__tests__/lazy-response-ads.test.ts b/common/src/util/__tests__/lazy-response-ads.test.ts new file mode 100644 index 0000000000..1b8e499f90 --- /dev/null +++ b/common/src/util/__tests__/lazy-response-ads.test.ts @@ -0,0 +1,47 @@ +import { describe, expect, it } from 'bun:test' + +import { responseAdDisplayCount } from '../lazy-response-ads' + +describe('responseAdDisplayCount', () => { + it('returns eligibleCount when poolSize is at or above the max', () => { + expect( + responseAdDisplayCount({ eligibleCount: 5, poolSize: 100 }), + ).toBe(5) + }) + + it('clamps to poolSize when poolSize is below the max', () => { + expect(responseAdDisplayCount({ eligibleCount: 10, poolSize: 3 })).toBe(3) + }) + + it('returns 0 when eligibleCount is NaN', () => { + expect(responseAdDisplayCount({ eligibleCount: NaN, poolSize: 10 })).toBe(0) + }) + + it('returns 0 when poolSize is NaN', () => { + expect(responseAdDisplayCount({ eligibleCount: 5, poolSize: NaN })).toBe(0) + }) + + it('returns 0 when eligibleCount is Infinity', () => { + expect( + responseAdDisplayCount({ eligibleCount: Infinity, poolSize: 10 }), + ).toBe(0) + }) + + it('returns 0 when poolSize is Infinity', () => { + expect( + responseAdDisplayCount({ eligibleCount: 5, poolSize: Infinity }), + ).toBe(0) + }) + + it('returns 0 when both inputs are negative', () => { + expect( + responseAdDisplayCount({ eligibleCount: -5, poolSize: -10 }), + ).toBe(0) + }) + + it('floors fractional inputs', () => { + expect( + responseAdDisplayCount({ eligibleCount: 5.7, poolSize: 3.2 }), + ).toBe(3) + }) +}) diff --git a/common/src/util/lazy-response-ads.ts b/common/src/util/lazy-response-ads.ts index 1b491a44d8..2214f85dea 100644 --- a/common/src/util/lazy-response-ads.ts +++ b/common/src/util/lazy-response-ads.ts @@ -16,8 +16,10 @@ export function responseAdDisplayCount(params: { eligibleCount: number poolSize: number }): number { - const eligibleCount = Math.max(0, Math.floor(params.eligibleCount)) - const poolSize = Math.max(0, Math.floor(params.poolSize)) + const safeEligibleCount = Number.isFinite(params.eligibleCount) ? params.eligibleCount : 0 + const safePoolSize = Number.isFinite(params.poolSize) ? params.poolSize : 0 + const eligibleCount = Math.max(0, Math.floor(safeEligibleCount)) + const poolSize = Math.max(0, Math.floor(safePoolSize)) return poolSize >= MAX_RESPONSE_AD_POOL_SIZE ? eligibleCount : Math.min(eligibleCount, poolSize)