diff --git a/src/ui/components/Carousel/Carousel.native.test.tsx b/src/ui/components/Carousel/Carousel.native.test.tsx new file mode 100644 index 00000000000..0820467d859 --- /dev/null +++ b/src/ui/components/Carousel/Carousel.native.test.tsx @@ -0,0 +1,82 @@ +import React from 'react' +import { SharedValue } from 'react-native-reanimated' + +import { act, fireEvent, render, screen } from 'tests/utils' + +import { Carousel, calculateProgress } from './Carousel' + +const PROGRESS_VALUE = { value: 0 } as SharedValue +const MOCKED_CAROUSEL_WIDTH = 300 +const MOCKED_CAROUSEL_HEIGHT = 200 + +const mockSetIndex = jest.fn() +const mockRenderItem = jest.fn() + +jest.mock('react-native-reanimated', () => { + const Reanimated = jest.requireActual('react-native-reanimated/mock') + + return { + ...Reanimated, + useAnimatedScrollHandler: jest.fn(), + useSharedValue: jest.fn(() => PROGRESS_VALUE), + useAnimatedRef: jest.fn(() => ({ + current: { scrollToIndex: jest.fn() }, + })), + } +}) + +describe('Carousel', () => { + const mockData = [ + { id: '1', text: 'Item 1' }, + { id: '2', text: 'Item 2' }, + { id: '3', text: 'Item 3' }, + ] + + it('should renders correctly', () => { + render( + + ) + + expect(screen.getByTestId('carousel')).toBeOnTheScreen() + }) + + it('updates progressValue on scroll', async () => { + render( + + ) + + const carousel = await screen.findByTestId('carousel') + + await act(async () => { + fireEvent.scroll(carousel, { + nativeEvent: { + contentOffset: { x: MOCKED_CAROUSEL_WIDTH, y: 0 }, + layoutMeasurement: { width: MOCKED_CAROUSEL_WIDTH, height: MOCKED_CAROUSEL_HEIGHT }, + contentSize: { width: MOCKED_CAROUSEL_WIDTH * 3, height: MOCKED_CAROUSEL_HEIGHT }, + }, + }) + }) + + expect(mockSetIndex).toHaveBeenCalledTimes(1) + }) +}) + +describe('calculateProgress', () => { + it('should calculate correctly progress value', () => { + expect(calculateProgress(MOCKED_CAROUSEL_WIDTH / 2, MOCKED_CAROUSEL_WIDTH)).toBe(0.5) + }) +}) diff --git a/src/ui/components/Carousel/Carousel.tsx b/src/ui/components/Carousel/Carousel.tsx index b425d3216de..ef8f92795d8 100644 --- a/src/ui/components/Carousel/Carousel.tsx +++ b/src/ui/components/Carousel/Carousel.tsx @@ -1,4 +1,3 @@ -import { ViewToken } from '@shopify/flash-list' import React, { useEffect, useRef } from 'react' import { ViewabilityConfigCallbackPairs, @@ -7,6 +6,7 @@ import { Platform, StyleProp, ViewStyle, + ViewToken, } from 'react-native' import Animated, { SharedValue, @@ -32,6 +32,10 @@ type CarouselProps = { const isWeb = Platform.OS === 'web' +export const calculateProgress = (contentOffsetX: number, width: number) => { + return Math.abs(contentOffsetX / width) +} + export const Carousel = (props: CarouselProps) => { const carouselRef = useAnimatedRef>() @@ -57,8 +61,7 @@ export const Carousel = (props: CarouselProps) => { const onScroll = useAnimatedScrollHandler({ onScroll: (e) => { - const absoluteProgress = Math.abs(e.contentOffset.x / width) - progressValue.value = absoluteProgress + progressValue.value = calculateProgress(e.contentOffset.x, width) }, })