xref: /expo/apps/test-suite/TestModules.js (revision 5d138cd2)
1'use strict';
2
3import Constants from 'expo-constants';
4import { Platform } from 'expo-modules-core';
5
6import ExponentTest from './ExponentTest';
7import { isDeviceFarm } from './utils/Environment';
8
9function browserSupportsWebGL() {
10  try {
11    const canvas = document.createElement('canvas');
12    return (
13      !!window.WebGLRenderingContext &&
14      (canvas.getContext('webgl') || canvas.getContext('experimental-webgl'))
15    );
16  } catch (e) {
17    return false;
18  }
19}
20
21function optionalRequire(requirer) {
22  try {
23    return requirer();
24  } catch (e) {
25    // eslint-disable-next-line
26    return;
27  }
28}
29
30// Both Location and TaskManager test suites define tasks in TaskManager.
31// Since tasks can only be defined during initialization phase (not as a result
32// of calling some function when the application is running, but rather in global scope),
33// we need to trigger code execution of these modules here (not in `getTestModules`
34// which is called in one of the components).
35const LocationTestScreen = optionalRequire(() => require('./tests/Location'));
36const TaskManagerTestScreen = optionalRequire(() => require('./tests/TaskManager'));
37// I have a hunch that optionalRequire doesn't work when *not* in global scope
38// since I had to move Camera screen import here too to get rid of an error
39// caused by missing native module.
40const CameraTestScreen = optionalRequire(() => require('./tests/Camera'));
41
42// List of all modules for tests. Each file path must be statically present for
43// the packager to pick them all up.
44export function getTestModules() {
45  const modules = [
46    // Sanity
47    require('./tests/Basic'),
48  ];
49
50  // Expo core modules should run everywhere
51  modules.push(
52    require('./tests/Asset'),
53    require('./tests/Constants'),
54    require('./tests/FileSystem'),
55    require('./tests/Font'),
56    require('./tests/Permissions'),
57    require('./tests/ImagePicker'),
58    optionalRequire(() => require('./tests/Image'))
59  );
60
61  // Universally tested APIs
62  modules.push(
63    require('./tests/Random'),
64    require('./tests/Crypto'),
65    require('./tests/KeepAwake'),
66    require('./tests/Blur'),
67    require('./tests/LinearGradient'),
68    require('./tests/Facebook'),
69    require('./tests/HTML'),
70    require('./tests/FirebaseCore'),
71    require('./tests/FirebaseAnalytics'),
72    require('./tests/FirebaseRecaptcha'),
73    require('./tests/FirebaseJSSDKCompat'),
74    require('./tests/FirebaseJSSDK'),
75    require('./tests/ImageManipulator'),
76    optionalRequire(() => require('./tests/SQLite'))
77  );
78
79  if (Platform.OS === 'android') {
80    modules.push(require('./tests/JSC'));
81    modules.push(require('./tests/Hermes'));
82  }
83
84  /**
85   * TODO: provide support for other platforms too
86   */
87  if (Platform.OS === 'ios') {
88    modules.push(require('./tests/Clipboard'));
89  }
90
91  if (global.DETOX) {
92    modules.push(
93      require('./tests/Contacts'),
94      require('./tests/Haptics'),
95      require('./tests/Localization'),
96      require('./tests/SecureStore'),
97      require('./tests/SMS'),
98      require('./tests/StoreReview'),
99      require('./tests/Notifications')
100    );
101    return modules;
102  }
103
104  if (Platform.OS === 'web') {
105    modules.push(
106      require('./tests/Contacts'),
107      // require('./tests/SVG'),
108      require('./tests/Localization'),
109      require('./tests/Recording'),
110      optionalRequire(() => require('./tests/Notifications')),
111      LocationTestScreen
112    );
113
114    if (browserSupportsWebGL()) {
115      modules.push(optionalRequire(() => require('./tests/GLView')));
116    }
117
118    if (ExponentTest && !ExponentTest.isInCI) {
119      // modules.push(optionalRequire(() => require('./tests/Speech')));
120    }
121    return modules.filter(Boolean);
122  }
123
124  modules.push(
125    optionalRequire(() => require('./tests/Application')),
126    optionalRequire(() => require('./tests/AuthSession')),
127    optionalRequire(() => require('./tests/Device')),
128    optionalRequire(() => require('./tests/GLView')),
129    optionalRequire(() => require('./tests/Haptics')),
130    optionalRequire(() => require('./tests/Localization')),
131    optionalRequire(() => require('./tests/Network')),
132    optionalRequire(() => require('./tests/SecureStore')),
133    optionalRequire(() => require('./tests/Segment')),
134    optionalRequire(() => require('./tests/Speech')),
135    optionalRequire(() => require('./tests/Recording')),
136    optionalRequire(() => require('./tests/ScreenOrientation')),
137    optionalRequire(() => require('./tests/AdMobInterstitial')),
138    optionalRequire(() => require('./tests/AdMobRewarded')),
139    optionalRequire(() => require('./tests/FBBannerAd')),
140    optionalRequire(() => require('./tests/Notifications')),
141    optionalRequire(() => require('./tests/NavigationBar')),
142    optionalRequire(() => require('./tests/SystemUI'))
143  );
144
145  if (!isDeviceFarm()) {
146    // Times out sometimes
147    modules.push(
148      optionalRequire(() => require('./tests/AdMobPublisherBanner')),
149      optionalRequire(() => require('./tests/AdMobBanner'))
150    );
151    // Invalid placementId in CI (all tests fail)
152    modules.push(optionalRequire(() => require('./tests/FBNativeAd')));
153    // Requires interaction (sign in popup)
154    modules.push(optionalRequire(() => require('./tests/GoogleSignIn')));
155    // Popup to request device's location which uses Google's location service
156    modules.push(LocationTestScreen);
157    // Fails to redirect because of malformed URL in published version with release channel parameter
158    modules.push(optionalRequire(() => require('./tests/Linking')));
159    // Has uncontrolled view controllers
160    modules.push(require('./tests/SMS'));
161    // Requires permission
162    modules.push(optionalRequire(() => require('./tests/Contacts')));
163    modules.push(optionalRequire(() => require('./tests/Calendar')));
164    modules.push(optionalRequire(() => require('./tests/CalendarReminders')));
165    modules.push(optionalRequire(() => require('./tests/MediaLibrary')));
166
167    modules.push(optionalRequire(() => require('./tests/Battery')));
168    if (Constants.isDevice) {
169      modules.push(optionalRequire(() => require('./tests/Brightness')));
170    }
171    // Crashes app when mounting component
172    modules.push(optionalRequire(() => require('./tests/Video')));
173    // "sdkUnversionedTestSuite failed: java.lang.NullPointerException: Attempt to invoke interface method
174    // 'java.util.Map org.unimodules.interfaces.taskManager.TaskInterface.getOptions()' on a null object reference"
175    modules.push(TaskManagerTestScreen);
176    // Audio tests are flaky in CI due to asynchronous fetching of resources
177    modules.push(optionalRequire(() => require('./tests/Audio')));
178
179    // The Camera tests are flaky on iOS, i.e. they fail randomly
180    if (Constants.isDevice) {
181      modules.push(CameraTestScreen);
182    }
183  }
184  if (Constants.isDevice) {
185    modules.push(optionalRequire(() => require('./tests/Cellular')));
186    modules.push(optionalRequire(() => require('./tests/BarCodeScanner')));
187  }
188  return modules
189    .filter(Boolean)
190    .sort((a, b) => (a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1));
191}
192