import React from 'react' import { render, fireEvent, waitFor } from '@testing-library/react-native' import { View } from 'react-native' import MembershipScreen from './membership' import { useMembership } from '@/hooks/use-membership' jest.mock('expo-router', () => ({ useRouter: jest.fn(() => ({ back: jest.fn(), push: jest.fn(), })), })) jest.mock('react-i18next', () => ({ useTranslation: jest.fn(() => ({ t: (key: string) => key, })), })) jest.mock('expo-status-bar', () => ({ StatusBar: 'StatusBar', })) jest.mock('react-native-safe-area-context', () => ({ SafeAreaView: ({ children }: { children: React.ReactNode }) => {children}, useSafeAreaInsets: () => ({ top: 0, bottom: 0, left: 0, right: 0 }), })) jest.mock('expo-linear-gradient', () => ({ LinearGradient: 'LinearGradient', })) jest.mock('expo-image', () => ({ Image: 'Image', })) jest.mock('react-native-reanimated-carousel', () => 'Carousel') jest.mock('react-native-svg', () => ({ __esModule: true, default: 'Svg', Svg: 'Svg', Path: 'Path', Defs: 'Defs', LinearGradient: 'LinearGradient', Stop: 'Stop', })) jest.mock('@/components/icon', () => ({ LeftArrowIcon: 'LeftArrowIcon', OmitIcon: 'OmitIcon', CheckIcon: 'CheckIcon', UncheckedIcon: 'UncheckedIcon', TermsIcon: 'TermsIcon', PrivacyIcon: 'PrivacyIcon', })) jest.mock('@/components/icon/checkMark', () => ({ CheckMarkIcon: 'CheckMarkIcon', })) jest.mock('@/components/drawer/PointsDrawer', () => 'PointsDrawer') jest.mock('@/components/ui/dropdown', () => 'Dropdown') jest.mock('@/components/GradientText', () => 'GradientText') jest.mock('@/hooks/use-membership') describe('MembershipScreen - 订阅按钮Loading状态', () => { const mockUseMembership = useMembership as jest.MockedFunction beforeEach(() => { jest.clearAllMocks() mockUseMembership.mockReturnValue({ creditPlans: [ { amountInCents: 1000, credits: 750, popular: false }, { amountInCents: 2000, credits: 1500, popular: true }, ], creditBalance: 100, selectedPlanIndex: 0, setSelectedPlanIndex: jest.fn(), isLoadingSubscriptions: false, isStripePricingLoading: false, createSubscription: jest.fn(), upgradeSubscription: jest.fn(), restoreSubscription: jest.fn(), rechargeToken: jest.fn(), activeAuthSubscription: null, hasActiveSubscription: false, stripePricingData: { pricing_table_items: [ { price_id: 'price-1', product_id: 'prod-1' }, { price_id: 'price-2', product_id: 'prod-2' }, ], }, } as any) }) it('应该在点击订阅按钮后显示loading状态', async () => { const createSubscription = jest.fn().mockImplementation(() => new Promise(resolve => setTimeout(resolve, 100))) mockUseMembership.mockReturnValue({ ...mockUseMembership(), createSubscription, } as any) const { getByText, getByTestId } = render() const checkbox = getByText('membership.agreementText').parent?.parent if (checkbox) fireEvent.press(checkbox) const subscribeButton = getByText('membership.subscribeNow') fireEvent.press(subscribeButton) await waitFor(() => { expect(createSubscription).toHaveBeenCalled() }) }) it('应该在订阅过程中禁用按钮', async () => { mockUseMembership.mockReturnValue({ ...mockUseMembership(), isLoadingSubscriptions: true, } as any) const { getByText } = render() const subscribeButton = getByText('membership.subscribeNow').parent expect(subscribeButton?.props.accessibilityState?.disabled).toBe(true) }) it('应该在未同意协议时禁用按钮', () => { const { getByText } = render() const subscribeButton = getByText('membership.subscribeNow').parent expect(subscribeButton?.props.accessibilityState?.disabled).toBe(true) }) })