-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Expand file tree
/
Copy pathOTAUpdatesModal.test.tsx
More file actions
181 lines (144 loc) · 5.08 KB
/
OTAUpdatesModal.test.tsx
File metadata and controls
181 lines (144 loc) · 5.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
import React from 'react';
import { fireEvent, waitFor } from '@testing-library/react-native';
import { Platform } from 'react-native';
import { reloadAsync } from 'expo-updates';
import Logger from '../../../util/Logger';
import { MetaMetricsEvents } from '../../../core/Analytics';
import renderWithProvider from '../../../util/test/renderWithProvider';
import { useAnalytics } from '../../hooks/useAnalytics/useAnalytics';
import { createMockUseAnalyticsHook } from '../../../util/test/analyticsMock';
import { AnalyticsEventBuilder } from '../../../util/analytics/AnalyticsEventBuilder';
// Mock theme utility
jest.mock('../../../util/theme', () => ({
useAssetFromTheme: jest.fn(() => ({ uri: 'mock-logo' })),
}));
// Create a mock tailwind function that can be called and has a style method
const mockTw = Object.assign(
jest.fn(() => ({})),
{
style: jest.fn(() => ({})),
},
);
// Mock tailwind
jest.mock('@metamask/design-system-twrnc-preset', () => ({
useTailwind: () => mockTw,
}));
// Mock for BottomSheet onCloseBottomSheet
const mockOnCloseBottomSheet = jest.fn((callback?: () => void) => {
if (callback) callback();
});
const getMockOnCloseBottomSheet = () => mockOnCloseBottomSheet;
jest.mock(
'../../../component-library/components/BottomSheets/BottomSheet',
() => {
const { View } = jest.requireActual('react-native');
const { forwardRef, useImperativeHandle } = jest.requireActual('react');
const MockBottomSheet = forwardRef(
(props: { children: React.ReactNode }, ref: React.Ref<unknown>) => {
useImperativeHandle(ref, () => ({
onOpenBottomSheet: jest.fn(),
onCloseBottomSheet: (callback?: () => void) => {
const mockFn = getMockOnCloseBottomSheet();
mockFn(callback);
},
}));
return (
<View testID="bottom-sheet" {...props}>
{props.children}
</View>
);
},
);
return {
__esModule: true,
default: MockBottomSheet,
};
},
);
jest.mock('expo-updates', () => ({
reloadAsync: jest.fn(),
}));
jest.mock('../../../util/metrics', () => ({
__esModule: true,
default: jest.fn().mockReturnValue({}),
}));
jest.mock('../../../util/Logger', () => ({
log: jest.fn(),
error: jest.fn(),
}));
const mockReloadAsync = reloadAsync as jest.MockedFunction<typeof reloadAsync>;
const mockLoggerError = Logger.error as jest.MockedFunction<
typeof Logger.error
>;
const mockTrackEvent = jest.fn();
jest.mock('../../hooks/useAnalytics/useAnalytics');
// Import component AFTER all mocks are defined
import OTAUpdatesModal from './OTAUpdatesModal';
describe('OTAUpdatesModal', () => {
beforeEach(() => {
jest.clearAllMocks();
jest.mocked(useAnalytics).mockReturnValue(
createMockUseAnalyticsHook({
trackEvent: mockTrackEvent,
createEventBuilder: AnalyticsEventBuilder.createEventBuilder,
}),
);
(Platform as unknown as { OS: string }).OS = 'ios';
mockOnCloseBottomSheet.mockImplementation((callback?: () => void) => {
if (callback) callback();
});
});
it('tracks view event on mount', () => {
renderWithProvider(<OTAUpdatesModal />);
expect(mockTrackEvent).toHaveBeenCalledWith(
expect.objectContaining({
name: MetaMetricsEvents.OTA_UPDATES_MODAL_VIEWED.category,
}),
);
});
it('tracks primary action when primary button is pressed', async () => {
const { getByText } = renderWithProvider(<OTAUpdatesModal />);
fireEvent.press(getByText('Reload'));
await waitFor(() => {
expect(mockTrackEvent).toHaveBeenCalledWith(
expect.objectContaining({
name: MetaMetricsEvents.OTA_UPDATES_MODAL_PRIMARY_ACTION_CLICKED
.category,
}),
);
});
});
it('reloads app when reload button is pressed on iOS', async () => {
const { getByText } = renderWithProvider(<OTAUpdatesModal />);
fireEvent.press(getByText('Reload'));
await waitFor(() => {
expect(mockReloadAsync).toHaveBeenCalledTimes(1);
});
});
it('does not reload app when reload button is pressed on Android', async () => {
(Platform as unknown as { OS: string }).OS = 'android';
const { getByText } = renderWithProvider(<OTAUpdatesModal />);
fireEvent.press(getByText('Got it'));
await waitFor(() => {
expect(mockReloadAsync).not.toHaveBeenCalled();
});
});
it('logs error when reloadAsync throws', async () => {
const reloadError = new Error('Reload failed');
mockReloadAsync.mockRejectedValueOnce(reloadError);
const { getByText } = renderWithProvider(<OTAUpdatesModal />);
fireEvent.press(getByText('Reload'));
await waitFor(() => {
expect(mockLoggerError).toHaveBeenCalledWith(
reloadError,
'OTA Updates: Error reloading app after modal reload pressed',
);
});
});
it('closes modal when close button is pressed', () => {
const { getByTestId } = renderWithProvider(<OTAUpdatesModal />);
const closeButton = getByTestId('close-button');
fireEvent.press(closeButton);
expect(mockOnCloseBottomSheet).toHaveBeenCalledTimes(1);
});
});