WellNuo/__tests__/screens/subscription.test.tsx
Sergei 88fc9042a7 Add retry button to error states in equipment and subscription screens
- Added error state with retry functionality to equipment.tsx
  - Display error message when sensor loading fails
  - Provide "Try Again" button to retry loading
  - Clear error on successful retry

- Added error state with retry functionality to subscription.tsx
  - Display error message when beneficiary loading fails
  - Provide "Try Again" button with icon to retry loading
  - Show offline icon and proper error layout

- Added comprehensive tests for error handling
  - ErrorMessage component tests for inline errors
  - FullScreenError component tests
  - Equipment screen error state tests
  - Subscription screen error state tests

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-29 11:27:19 -08:00

104 lines
3.4 KiB
TypeScript

import React from 'react';
import { render, fireEvent, waitFor } from '@testing-library/react-native';
import { api } from '@/services/api';
// Mock dependencies
jest.mock('@/services/api');
jest.mock('expo-router', () => ({
useLocalSearchParams: () => ({ id: '1' }),
router: { back: jest.fn(), replace: jest.fn() },
}));
jest.mock('@/contexts/AuthContext', () => ({
useAuth: () => ({
user: { id: '1', email: 'test@example.com' },
}),
}));
jest.mock('@stripe/stripe-react-native', () => ({
usePaymentSheet: () => ({
initPaymentSheet: jest.fn(),
presentPaymentSheet: jest.fn(),
}),
}));
// Import the screen after mocks are set up
import SubscriptionScreen from '@/app/(tabs)/beneficiaries/[id]/subscription';
describe('SubscriptionScreen - Error Handling', () => {
beforeEach(() => {
jest.clearAllMocks();
});
it('displays error message when beneficiary loading fails', async () => {
const mockError = { ok: false, error: { message: 'Failed to load beneficiary data' } };
(api.getWellNuoBeneficiary as jest.Mock).mockResolvedValue(mockError);
(api.getTransactionHistory as jest.Mock).mockResolvedValue({ ok: true, data: { transactions: [] } });
const { findByText } = render(<SubscriptionScreen />);
await waitFor(() => {
expect(findByText('Failed to load beneficiary data')).toBeTruthy();
});
});
it('displays retry button when error occurs', async () => {
const mockError = { ok: false, error: { message: 'Network error' } };
(api.getWellNuoBeneficiary as jest.Mock).mockResolvedValue(mockError);
(api.getTransactionHistory as jest.Mock).mockResolvedValue({ ok: true, data: { transactions: [] } });
const { findByText } = render(<SubscriptionScreen />);
await waitFor(() => {
expect(findByText('Try Again')).toBeTruthy();
});
});
it('retries loading beneficiary when retry button is pressed', async () => {
const mockError = { ok: false, error: { message: 'Network error' } };
const mockSuccess = {
ok: true,
data: {
id: 1,
name: 'Test User',
subscription: { status: 'active' },
},
};
(api.getWellNuoBeneficiary as jest.Mock)
.mockResolvedValueOnce(mockError)
.mockResolvedValueOnce(mockSuccess);
(api.getTransactionHistory as jest.Mock).mockResolvedValue({ ok: true, data: { transactions: [] } });
const { findByText, queryByText } = render(<SubscriptionScreen />);
// Wait for error to appear
await waitFor(() => {
expect(findByText('Try Again')).toBeTruthy();
});
// Press retry button
const retryButton = await findByText('Try Again');
fireEvent.press(retryButton);
// Wait for error to disappear after successful retry
await waitFor(() => {
expect(queryByText('Network error')).toBeNull();
});
// Verify API was called twice (initial + retry)
expect(api.getWellNuoBeneficiary).toHaveBeenCalledTimes(2);
});
it('displays generic error message for exceptions', async () => {
(api.getWellNuoBeneficiary as jest.Mock).mockRejectedValue(
new Error('Connection timeout')
);
(api.getTransactionHistory as jest.Mock).mockResolvedValue({ ok: true, data: { transactions: [] } });
const { findByText } = render(<SubscriptionScreen />);
await waitFor(() => {
expect(findByText(/Connection timeout|Failed to load beneficiary data/)).toBeTruthy();
});
});
});