1import * as React from 'react';
2
3import { DevLauncher } from '../../native-modules/DevLauncher';
4import {
5  AppInfo,
6  toggleDebugRemoteJSAsync,
7  toggleElementInspectorAsync,
8  toggleFastRefreshAsync,
9  togglePerformanceMonitorAsync,
10  copyToClipboardAsync,
11  reloadAsync,
12} from '../../native-modules/DevMenu';
13import { render, waitFor, fireEvent, act } from '../../test-utils';
14import { Main } from '../Main';
15
16const { navigateToLauncherAsync } = DevLauncher;
17
18const mockToggleDebugRemoteJSAsync = toggleDebugRemoteJSAsync as jest.Mock;
19const mockToggleElementInspectorAsync = toggleElementInspectorAsync as jest.Mock;
20const mockToggleFastRefreshAsync = toggleFastRefreshAsync as jest.Mock;
21const mockTogglePerformanceMonitorAsync = togglePerformanceMonitorAsync as jest.Mock;
22const mockCopyToClipboardAsync = copyToClipboardAsync as jest.Mock;
23const mockNavigateToLauncherAsync = navigateToLauncherAsync as jest.Mock;
24const mockReloadAsync = reloadAsync as jest.Mock;
25
26const mockFns: jest.Mock[] = [
27  mockToggleDebugRemoteJSAsync,
28  mockToggleElementInspectorAsync,
29  mockToggleFastRefreshAsync,
30  mockTogglePerformanceMonitorAsync,
31  mockCopyToClipboardAsync,
32  mockNavigateToLauncherAsync,
33  mockReloadAsync,
34];
35
36describe('<Main />', () => {
37  afterEach(() => {
38    mockFns.forEach((fn) => fn.mockClear());
39  });
40
41  test('renders', async () => {
42    const { getByText } = render(<Main />, { initialAppProviderProps: {} });
43    await waitFor(() => getByText(/go home/i));
44  });
45
46  test('renders build info from dev menu', async () => {
47    const fakeAppInfo: AppInfo = {
48      appName: 'testing',
49      appVersion: '123',
50      appIcon: 'hello',
51      hostUrl: '321',
52      sdkVersion: '500.0.0',
53      runtimeVersion: '10',
54    };
55
56    const { getByText, queryByText } = render(<Main />, {
57      initialAppProviderProps: { appInfo: fakeAppInfo },
58    });
59
60    await waitFor(() => getByText(/go home/i));
61
62    expect(queryByText(fakeAppInfo.appName)).not.toBe(null);
63    expect(queryByText(fakeAppInfo.appVersion)).not.toBe(null);
64    expect(queryByText(fakeAppInfo.hostUrl)).not.toBe(null);
65    expect(queryByText(fakeAppInfo.runtimeVersion)).not.toBe(null);
66  });
67
68  test('hooked up to devsettings fns', async () => {
69    const { getByText, getByTestId } = render(<Main />);
70    await waitFor(() => getByText(/go home/i));
71
72    expect(togglePerformanceMonitorAsync).toHaveBeenCalledTimes(0);
73    await act(async () => fireEvent.press(getByText(/toggle performance monitor/i)));
74    expect(togglePerformanceMonitorAsync).toHaveBeenCalledTimes(1);
75
76    expect(toggleElementInspectorAsync).toHaveBeenCalledTimes(0);
77    await act(async () => fireEvent.press(getByText(/toggle element inspector/i)));
78    expect(toggleElementInspectorAsync).toHaveBeenCalledTimes(1);
79
80    expect(toggleFastRefreshAsync).toHaveBeenCalledTimes(0);
81    await act(async () => fireEvent.press(getByTestId('fast-refresh')));
82    expect(toggleFastRefreshAsync).toHaveBeenCalledTimes(1);
83  });
84
85  describe('Remote JS Debugger', () => {
86    it('should be available for SDK < 49', async () => {
87      const { getByText, getByTestId } = render(<Main />, {
88        initialAppProviderProps: {
89          appInfo: {
90            sdkVersion: '48.0.0',
91          },
92        },
93      });
94      await waitFor(() => getByText(/go home/i));
95
96      expect(toggleDebugRemoteJSAsync).toHaveBeenCalledTimes(0);
97      await act(async () => fireEvent.press(getByTestId('remote-js-debugger')));
98      expect(toggleDebugRemoteJSAsync).toHaveBeenCalledTimes(1);
99    });
100
101    it('should be disabled for SDK 49+', async () => {
102      const { getByText, getByTestId } = render(<Main />);
103      await waitFor(() => getByText(/go home/i));
104
105      expect(getByTestId('remote-js-debugger')).toBeDisabled();
106    });
107  });
108
109  test('copy text functions', async () => {
110    const fakeAppInfo: AppInfo = {
111      appName: 'testing',
112      appVersion: '123',
113      appIcon: 'hello',
114      hostUrl: '321',
115      sdkVersion: '500.0.0',
116      runtimeVersion: '10',
117    };
118
119    const { getByText, getByTestId } = render(<Main />, {
120      initialAppProviderProps: { appInfo: fakeAppInfo },
121    });
122    await waitFor(() => getByText(/go home/i));
123
124    expect(copyToClipboardAsync).toHaveBeenCalledTimes(0);
125    await act(async () => fireEvent.press(getByText(/copy all/i)));
126    expect(copyToClipboardAsync).toHaveBeenCalledTimes(1);
127
128    expect(copyToClipboardAsync).toHaveBeenLastCalledWith(expect.stringContaining('sdkVersion'));
129    expect(copyToClipboardAsync).toHaveBeenLastCalledWith(expect.stringContaining('appVersion'));
130    expect(copyToClipboardAsync).toHaveBeenLastCalledWith(expect.stringContaining('appName'));
131    expect(copyToClipboardAsync).toHaveBeenLastCalledWith(
132      expect.stringContaining('runtimeVersion')
133    );
134
135    mockCopyToClipboardAsync.mockClear();
136
137    expect(copyToClipboardAsync).toHaveBeenCalledTimes(0);
138    await act(async () => fireEvent.press(getByTestId(/main.copyUrlButton/i)));
139    expect(copyToClipboardAsync).toHaveBeenCalledTimes(1);
140
141    expect(copyToClipboardAsync).toHaveBeenLastCalledWith(fakeAppInfo.hostUrl);
142  });
143
144  test('return to dev launcher and reload', async () => {
145    const { getByText } = render(<Main />);
146    await waitFor(() => getByText(/go home/i));
147
148    expect(navigateToLauncherAsync).toHaveBeenCalledTimes(0);
149    await act(async () => fireEvent.press(getByText(/go home/i)));
150    expect(navigateToLauncherAsync).toHaveBeenCalledTimes(1);
151
152    expect(reloadAsync).toHaveBeenCalledTimes(0);
153    await act(async () => fireEvent.press(getByText(/reload/i)));
154    expect(reloadAsync).toHaveBeenCalledTimes(1);
155  });
156});
157