- 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>
104 lines
3.4 KiB
TypeScript
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();
|
|
});
|
|
});
|
|
});
|