From 422743062a1d1f44c26d4cf3ced507f505ecbde5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Sep 2025 00:50:17 +0000 Subject: [PATCH 1/2] Initial plan From 227a83d594e297f20ff2c11cac1097d33105b5e7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Sep 2025 01:01:01 +0000 Subject: [PATCH 2/2] Fix NaN seed results by adding null/undefined validation Co-authored-by: coder13 <881394+coder13@users.noreply.github.com> --- dev-dist/sw.js | 2 +- src/lib/results.test.ts | 33 ++++++++++ src/lib/results.ts | 5 ++ src/lib/seedResult.test.ts | 62 +++++++++++++++++++ .../Competition/Schedule/EventActivity.tsx | 19 +++++- 5 files changed, 117 insertions(+), 4 deletions(-) create mode 100644 src/lib/results.test.ts create mode 100644 src/lib/seedResult.test.ts diff --git a/dev-dist/sw.js b/dev-dist/sw.js index 7a0a0a8..a774d19 100644 --- a/dev-dist/sw.js +++ b/dev-dist/sw.js @@ -81,7 +81,7 @@ define(['./workbox-5357ef54'], function (workbox) { [ { url: 'index.html', - revision: '0.3rdphr8mv9', + revision: '0.0d4ja86min8', }, ], {}, diff --git a/src/lib/results.test.ts b/src/lib/results.test.ts new file mode 100644 index 0000000..6a76b2c --- /dev/null +++ b/src/lib/results.test.ts @@ -0,0 +1,33 @@ +import { renderResultByEventId } from './results'; + +describe('renderResultByEventId', () => { + it('should return empty string for null result', () => { + expect(renderResultByEventId('333', 'single', null as any)).toBe(''); + }); + + it('should return empty string for undefined result', () => { + expect(renderResultByEventId('333', 'single', undefined as any)).toBe(''); + }); + + it('should return empty string for NaN result', () => { + expect(renderResultByEventId('333', 'single', NaN)).toBe(''); + }); + + it('should handle valid results correctly', () => { + // Test with a valid centisecond time (10.50 seconds = 1050 centiseconds) + const result = renderResultByEventId('333', 'single', 1050); + expect(result).toBe('10.50'); + }); + + it('should handle 333fm average correctly', () => { + // Test with FMC average (30.00 moves = 3000) + const result = renderResultByEventId('333fm', 'average', 3000); + expect(result).toBe('30.00'); + }); + + it('should handle 333fm single correctly', () => { + // Test with FMC single (30 moves) + const result = renderResultByEventId('333fm', 'single', 30); + expect(result).toBe(30); + }); +}); diff --git a/src/lib/results.ts b/src/lib/results.ts index 27c00be..1eff585 100644 --- a/src/lib/results.ts +++ b/src/lib/results.ts @@ -13,6 +13,11 @@ export const renderResultByEventId = ( rankingType: RankingType, result: AttemptResult, ) => { + // Return empty string if result is null, undefined, or NaN + if (result == null || (typeof result === 'number' && isNaN(result))) { + return ''; + } + if (eventId === '333fm') { return rankingType === 'average' ? ((result as number) / 100).toFixed(2).toString() : result; } diff --git a/src/lib/seedResult.test.ts b/src/lib/seedResult.test.ts new file mode 100644 index 0000000..02ab8d7 --- /dev/null +++ b/src/lib/seedResult.test.ts @@ -0,0 +1,62 @@ +import { EventId } from '@wca/helpers'; +import { renderResultByEventId } from '@/lib/results'; + +// Mock the WCA helpers functions since we're testing null/undefined handling +jest.mock('@wca/helpers', () => ({ + formatCentiseconds: jest.fn((time) => { + if (typeof time !== 'number' || isNaN(time)) { + return 'NaN'; + } + return (time / 100).toFixed(2); + }), + formatMultiResult: jest.fn(() => 'MBLD Result'), + decodeMultiResult: jest.fn(() => ({ attempted: 1, solved: 1 })), +})); + +describe('seedResult edge cases', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('renderResultByEventId null/undefined handling', () => { + it('should return empty string when result is null', () => { + const result = renderResultByEventId('333' as EventId, 'single', null as any); + expect(result).toBe(''); + }); + + it('should return empty string when result is undefined', () => { + const result = renderResultByEventId('333' as EventId, 'single', undefined as any); + expect(result).toBe(''); + }); + + it('should return empty string when result is NaN', () => { + const result = renderResultByEventId('333' as EventId, 'single', NaN); + expect(result).toBe(''); + }); + + it('should handle valid results correctly for 333', () => { + const result = renderResultByEventId('333' as EventId, 'single', 1050); + expect(result).toBe('10.50'); + }); + + it('should handle 333fm average with null result', () => { + const result = renderResultByEventId('333fm' as EventId, 'average', null as any); + expect(result).toBe(''); + }); + + it('should handle 333fm single with undefined result', () => { + const result = renderResultByEventId('333fm' as EventId, 'single', undefined as any); + expect(result).toBe(''); + }); + + it('should handle 333fm average correctly with valid result', () => { + const result = renderResultByEventId('333fm' as EventId, 'average', 3000); + expect(result).toBe('30.00'); + }); + + it('should handle 333fm single correctly with valid result', () => { + const result = renderResultByEventId('333fm' as EventId, 'single', 30); + expect(result).toBe(30); + }); + }); +}); diff --git a/src/pages/Competition/Schedule/EventActivity.tsx b/src/pages/Competition/Schedule/EventActivity.tsx index a88095f..58d43e9 100644 --- a/src/pages/Competition/Schedule/EventActivity.tsx +++ b/src/pages/Competition/Schedule/EventActivity.tsx @@ -116,10 +116,18 @@ export function EventActivity({ competitionId, activity, persons }: EventGroupPr } if (['a', 'm'].includes(prevRound.format)) { - return renderResultByEventId(eventId, 'average', prevRoundResults.average); + const averageResult = prevRoundResults.average; + if (averageResult == null) { + return ''; + } + return renderResultByEventId(eventId, 'average', averageResult); } - return renderResultByEventId(eventId, 'single', prevRoundResults.best); + const bestResult = prevRoundResults.best; + if (bestResult == null) { + return ''; + } + return renderResultByEventId(eventId, 'single', bestResult); } const averagePr = person.prAverage?.best; @@ -129,10 +137,15 @@ export function EventActivity({ competitionId, activity, persons }: EventGroupPr return ''; } + const resultValue = shouldShowAveragePr ? averagePr : singlePr; + if (resultValue == null) { + return ''; + } + return renderResultByEventId( eventId, shouldShowAveragePr ? 'average' : 'single', - shouldShowAveragePr ? averagePr : singlePr, + resultValue, ); }, [eventId, prevRound],