@@ -806,4 +806,87 @@ describe("Test the real swipe behavior of Carousel to ensure it's working as exp
806806 TICK ( ) ;
807807 pushExpect ( 1 ) ;
808808 } ) ;
809+
810+ it ( "should keep correct page after left overscroll at first page when calling next() or scrollTo()" , async ( ) => {
811+ const handlerOffset = { current : 0 } ;
812+ let nextSlide : ( ( opts ?: { animated ?: boolean } ) => void ) | undefined ;
813+ let scrollToIndex : ( ( opts ?: { index : number ; animated ?: boolean } ) => void ) | undefined ;
814+
815+ const Wrapper : FC < Partial < TCarouselProps < string > > > = React . forwardRef ( ( customProps , ref ) => {
816+ const progressAnimVal = useSharedValue ( 0 ) ;
817+ const mockHandlerOffset = useSharedValue ( handlerOffset . current ) ;
818+ const defaultRenderItem = ( {
819+ item,
820+ index,
821+ } : {
822+ item : string ;
823+ index : number ;
824+ } ) => (
825+ < Animated . View
826+ testID = { `carousel-item-${ index } ` }
827+ style = { { width : slideWidth , height : slideHeight } }
828+ >
829+ { item }
830+ </ Animated . View >
831+ ) ;
832+ const { renderItem = defaultRenderItem , ...defaultProps } = createDefaultProps (
833+ progressAnimVal ,
834+ customProps
835+ ) ;
836+
837+ useDerivedValue ( ( ) => {
838+ handlerOffset . current = mockHandlerOffset . value ;
839+ } , [ mockHandlerOffset ] ) ;
840+
841+ return (
842+ < Carousel
843+ { ...defaultProps }
844+ defaultScrollOffsetValue = { mockHandlerOffset }
845+ renderItem = { renderItem }
846+ ref = { ref }
847+ />
848+ ) ;
849+ } ) ;
850+
851+ const { getByTestId } = render (
852+ < Wrapper
853+ ref = { ( ref ) => {
854+ if ( ref ) {
855+ nextSlide = ref . next ;
856+ scrollToIndex = ref . scrollTo ;
857+ }
858+ } }
859+ loop = { false }
860+ overscrollEnabled
861+ style = { { width : slideWidth , height : slideHeight } }
862+ />
863+ ) ;
864+ await verifyInitialRender ( getByTestId ) ;
865+
866+ // Simulate left overscroll at first page
867+ fireGestureHandler < PanGesture > ( getByGestureTestId ( gestureTestId ) , [
868+ { state : State . BEGAN , translationX : 0 , velocityX : 0 } ,
869+ { state : State . ACTIVE , translationX : slideWidth / 4 , velocityX : slideWidth } ,
870+ { state : State . ACTIVE , translationX : 0.00003996 , velocityX : slideWidth } ,
871+ { state : State . END , translationX : 0.00003996 , velocityX : slideWidth } ,
872+ ] ) ;
873+
874+ nextSlide ?.( { animated : false } ) ;
875+ await waitFor ( ( ) => {
876+ expect ( handlerOffset . current ) . toBe ( - slideWidth ) ;
877+ } ) ;
878+
879+ // Overscroll again, then call scrollTo()
880+ fireGestureHandler < PanGesture > ( getByGestureTestId ( gestureTestId ) , [
881+ { state : State . BEGAN , translationX : 0 , velocityX : - slideWidth } ,
882+ { state : State . ACTIVE , translationX : slideWidth , velocityX : slideWidth } ,
883+ { state : State . ACTIVE , translationX : slideWidth + 0.00003996 , velocityX : slideWidth } ,
884+ { state : State . END , translationX : slideWidth + 0.00003996 , velocityX : slideWidth } ,
885+ ] ) ;
886+
887+ scrollToIndex ?.( { index : 1 , animated : false } ) ;
888+ await waitFor ( ( ) => {
889+ expect ( handlerOffset . current ) . toBe ( - slideWidth ) ;
890+ } ) ;
891+ } ) ;
809892} ) ;
0 commit comments