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)
})
})