diff --git a/src/__tests__/wheel-web.00.test.tsx b/src/__tests__/wheel-web.00.test.tsx new file mode 100644 index 0000000..a0d1dd2 --- /dev/null +++ b/src/__tests__/wheel-web.00.test.tsx @@ -0,0 +1,82 @@ +/** + * - Render the *web* wheel component and simulate a drag that lands on "00". + * - Assert the component calls setValue(0) (a number). + */ + +import React from 'react'; +import { render } from '@testing-library/react-native'; +import { PanResponder } from 'react-native'; +import WheelWeb from '../components/time-picker/wheel-web'; +import type { PickerOption } from '../types'; + +// Helper to build options that reproduce a web bug where 00 wasn't selectable. +const makeItems = (n = 5): PickerOption[] => + Array.from({ length: n }, (_, i) => ({ + value: i === 0 ? '00' : i, // "00", 1, 2, 3, ... + text: String(i).padStart(2, '0'), // "00", "01", "02", ... + })); + +describe('WheelWeb — selecting 00', () => { + let panSpec: any | null = null; + + beforeEach(() => { + panSpec = null; + jest.spyOn(PanResponder, 'create').mockImplementation((spec: any) => { + panSpec = spec; + return { panHandlers: spec } as any; + }); + }); + + afterEach(() => { + jest.restoreAllMocks(); + }); + + test('emits numeric 0 when landing on "00"', () => { + // Build the wheel options the component will render (replicate bug condition): + const items = makeItems(5); // ["00", 1, 2, 3, 4] + const setValue = jest.fn(); + + render( + + ); + + expect(panSpec).toBeTruthy(); // Sanity: confirm we captured the gesture handlers + + const STEP = 28; + panSpec.onPanResponderGrant(); // Simulates “finger down” (gesture start). + panSpec.onPanResponderRelease({}, { dy: STEP }); // Simulates “finger up” after dragging by 1 row. + + expect(setValue).toHaveBeenCalledTimes(1); + expect(setValue).toHaveBeenCalledWith(0); + }); + + test('no change when releasing on the same value (including "00")', () => { + const items = makeItems(5); + const setValue = jest.fn(); + + // Start already on 0 (which will match "00" thanks to Number(...)) + render( + + ); + + expect(panSpec).toBeTruthy(); + + // Release without moving (dy = 0) → should not emit anything + panSpec.onPanResponderGrant(); + panSpec.onPanResponderRelease({}, { dy: 0 }); + + expect(setValue).not.toHaveBeenCalled(); + }); +}); diff --git a/src/components/time-picker/wheel-web.tsx b/src/components/time-picker/wheel-web.tsx index e74fd8b..968f60d 100644 --- a/src/components/time-picker/wheel-web.tsx +++ b/src/components/time-picker/wheel-web.tsx @@ -38,7 +38,10 @@ const WheelWeb = ({ const radius = height / 2; const valueIndex = useMemo(() => { - return items.findIndex((item) => item.value === value) || 0; + const idx = items.findIndex( + (item) => Number(item?.value) === Number(value) + ); + return idx >= 0 ? idx : 0; }, [items, value]); const panResponder = useMemo(() => { @@ -67,13 +70,13 @@ const WheelWeb = ({ } } const newValue = items[newValueIndex]; - if (newValue?.value === value) { + if (Number(newValue?.value) === Number(value)) { translateY.setOffset(0); translateY.setValue(0); - } else if (newValue?.value) { - setValue(newValue.value); - } else if (items[0]?.value) { - setValue(items[0].value); + } else if (newValue?.value != null) { + setValue(Number(newValue.value)); + } else if (items[0]?.value != null) { + setValue(Number(items[0].value)); } }, }); @@ -107,7 +110,7 @@ const WheelWeb = ({ //translateY.setValue(0); translateY.setOffset(0); const currentIndex = displayValues.findIndex( - (item) => item?.value === value + (item) => Number(item?.value) === Number(value) ); return displayValues && displayValues.length > 0 ? displayValues.map((_, index) => @@ -166,7 +169,7 @@ const WheelWeb = ({ }, ] : [], - opacity: displayValue?.value !== value ? 0.3 : 1, + opacity: Number(displayValue?.value) !== Number(value) ? 0.3 : 1, }} >