jest-expo 50.0.0-alpha.2 → 50.0.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jest-expo",
3
- "version": "50.0.0-alpha.2",
3
+ "version": "50.0.0-alpha.3",
4
4
  "description": "A Jest preset to painlessly test your Expo / React Native apps.",
5
5
  "license": "MIT",
6
6
  "main": "src",
@@ -31,7 +31,7 @@
31
31
  "preset": "jest-expo/universal"
32
32
  },
33
33
  "dependencies": {
34
- "@expo/config": "~8.3.0",
34
+ "@expo/config": "~8.4.0",
35
35
  "@expo/json-file": "^8.2.37",
36
36
  "@jest/create-cache-key-function": "^29.2.1",
37
37
  "babel-jest": "^29.2.1",
@@ -41,11 +41,12 @@
41
41
  "jest-watch-typeahead": "2.2.1",
42
42
  "json5": "^2.2.3",
43
43
  "lodash": "^4.17.19",
44
- "react-test-renderer": "18.2.0"
44
+ "react-test-renderer": "18.2.0",
45
+ "stacktrace-js": "^2.0.2"
45
46
  },
46
47
  "bugs": {
47
48
  "url": "https://github.com/expo/expo/issues"
48
49
  },
49
50
  "homepage": "https://github.com/expo/expo/tree/main/packages/jest-expo",
50
- "gitHead": "ee2c866ba3c7fbc35ff2a3e896041cf15d3bd7c5"
51
+ "gitHead": "da25937e2a99661cbe5eb60ca1d8d6245fc96a50"
51
52
  }
@@ -227,19 +227,6 @@ module.exports = {
227
227
  key: 'getMobileNetworkCodeAsync',
228
228
  },
229
229
  ],
230
- ExpoClipboard: [
231
- { name: 'getImageAsync', argumentsCount: 1, key: 'getImageAsync' },
232
- { name: 'getStringAsync', argumentsCount: 1, key: 'getStringAsync' },
233
- { name: 'getUrlAsync', argumentsCount: 0, key: 'getUrlAsync' },
234
- { name: 'hasImageAsync', argumentsCount: 0, key: 'hasImageAsync' },
235
- { name: 'hasStringAsync', argumentsCount: 0, key: 'hasStringAsync' },
236
- { name: 'hasUrlAsync', argumentsCount: 0, key: 'hasUrlAsync' },
237
- { name: 'setImageAsync', argumentsCount: 1, key: 'setImageAsync' },
238
- { name: 'setStringAsync', argumentsCount: 2, key: 'setStringAsync' },
239
- { name: 'setUrlAsync', argumentsCount: 1, key: 'setUrlAsync' },
240
- { name: 'startObserving', argumentsCount: 0, key: 'startObserving' },
241
- { name: 'stopObserving', argumentsCount: 0, key: 'stopObserving' },
242
- ],
243
230
  ExpoContacts: [
244
231
  { name: 'getDefaultContainerIdentifierAsync', argumentsCount: 0, key: 0 },
245
232
  { name: 'addExistingGroupToContainerAsync', argumentsCount: 2, key: 1 },
@@ -260,19 +247,6 @@ module.exports = {
260
247
  { name: 'writeContactToFileAsync', argumentsCount: 1, key: 16 },
261
248
  { name: 'dismissFormAsync', argumentsCount: 0, key: 17 },
262
249
  ],
263
- ExpoCrypto: [
264
- { name: 'digest', argumentsCount: 3, key: 'digest' },
265
- { name: 'digestString', argumentsCount: 3, key: 'digestString' },
266
- { name: 'digestStringAsync', argumentsCount: 3, key: 'digestStringAsync' },
267
- { name: 'getRandomBase64String', argumentsCount: 1, key: 'getRandomBase64String' },
268
- {
269
- name: 'getRandomBase64StringAsync',
270
- argumentsCount: 1,
271
- key: 'getRandomBase64StringAsync',
272
- },
273
- { name: 'getRandomValues', argumentsCount: 1, key: 'getRandomValues' },
274
- { name: 'randomUUID', argumentsCount: 0, key: 'randomUUID' },
275
- ],
276
250
  ExpoDevice: [
277
251
  { name: 'getDeviceTypeAsync', argumentsCount: 0, key: 'getDeviceTypeAsync' },
278
252
  { name: 'getUptimeAsync', argumentsCount: 0, key: 'getUptimeAsync' },
@@ -282,7 +256,6 @@ module.exports = {
282
256
  key: 'isRootedExperimentalAsync',
283
257
  },
284
258
  ],
285
- ExpoDevMenu: [],
286
259
  ExpoDocumentPicker: [
287
260
  { name: 'getDocumentAsync', argumentsCount: 1, key: 'getDocumentAsync' },
288
261
  ],
@@ -441,7 +414,7 @@ module.exports = {
441
414
  ],
442
415
  ExponentFileSystem: [
443
416
  { name: 'uploadAsync', argumentsCount: 3, key: 0 },
444
- { name: 'readDirectoryAsync', argumentsCount: 2, key: 1 },
417
+ { name: 'readDirectoryAsync', argumentsCount: 1, key: 1 },
445
418
  { name: 'getTotalDiskCapacityAsync', argumentsCount: 0, key: 2 },
446
419
  { name: 'getInfoAsync', argumentsCount: 2, key: 3 },
447
420
  { name: 'downloadAsync', argumentsCount: 3, key: 4 },
@@ -687,8 +660,6 @@ module.exports = {
687
660
  mobileCountryCode: { type: 'object', mock: null },
688
661
  mobileNetworkCode: { type: 'object', mock: null },
689
662
  },
690
- ExpoClipboard: {},
691
- ExpoCrypto: {},
692
663
  ExpoDevice: {
693
664
  brand: { type: 'string' },
694
665
  deviceName: { type: 'string' },
@@ -742,9 +713,8 @@ module.exports = {
742
713
  },
743
714
  ExponentConstants: {
744
715
  appOwnership: { type: 'string' },
745
- debugMode: { type: 'boolean', mock: true },
716
+ debugMode: { type: 'boolean', mock: false },
746
717
  deviceName: { type: 'string' },
747
- deviceYearClass: { type: 'number', mock: 2023 },
748
718
  executionEnvironment: { type: 'string' },
749
719
  experienceUrl: { type: 'string' },
750
720
  expoRuntimeVersion: { type: 'string' },
@@ -773,7 +743,7 @@ module.exports = {
773
743
  ExponentGLView: {},
774
744
  ExponentImagePicker: {},
775
745
  ExpoNetwork: {},
776
- ExpoPrint: {},
746
+ ExpoPrint: { Orientation: { type: 'object' } },
777
747
  ExpoRandom: {},
778
748
  ExpoScreenOrientation: {},
779
749
  ExpoSecureStore: {
@@ -818,16 +788,6 @@ module.exports = {
818
788
  ExpoAppleAuthentication: { propsNames: ['buttonStyle', 'buttonType', 'cornerRadius'] },
819
789
  ExpoBarCodeScanner: { propsNames: ['barCodeTypes', 'type'] },
820
790
  ExpoBlurView: { propsNames: ['intensity', 'tint'] },
821
- ExpoClipboard: {
822
- propsNames: [
823
- 'acceptedContentTypes',
824
- 'backgroundColor',
825
- 'cornerStyle',
826
- 'displayMode',
827
- 'foregroundColor',
828
- 'imageOptions',
829
- ],
830
- },
831
791
  ExpoImage: {
832
792
  propsNames: [
833
793
  'accessibilityLabel',
@@ -946,7 +906,6 @@ module.exports = {
946
906
  getCurrentState: { type: 'function', functionType: 'promise' },
947
907
  removeListeners: { type: 'function', functionType: 'async' },
948
908
  },
949
- RNCPickerManager: {},
950
909
  RNCSafeAreaContext: {
951
910
  getConstants: { type: 'function' },
952
911
  initialWindowMetrics: { type: 'object' },
@@ -989,10 +948,6 @@ module.exports = {
989
948
  updateGestureHandler: { type: 'function', functionType: 'async' },
990
949
  },
991
950
  RNSFullWindowOverlayManager: {},
992
- RNSharedElementTransition: {
993
- configure: { type: 'function', functionType: 'promise' },
994
- getConstants: { type: 'function' },
995
- },
996
951
  RNSkia: {
997
952
  getConstants: { type: 'function' },
998
953
  install: { type: 'function', functionType: 'sync' },
@@ -4,7 +4,10 @@
4
4
  */
5
5
  'use strict';
6
6
 
7
+ const findUp = require('find-up');
8
+ const path = require('path');
7
9
  const mockNativeModules = require('react-native/Libraries/BatchedBridge/NativeModules');
10
+ const stackTrace = require('stacktrace-js');
8
11
 
9
12
  const publicExpoModules = require('./expoModules');
10
13
  const internalExpoModules = require('./internalExpoModules');
@@ -159,13 +162,35 @@ jest.doMock('react-native/Libraries/LogBox/LogBox', () => ({
159
162
  },
160
163
  }));
161
164
 
165
+ function attemptLookup(moduleName) {
166
+ // hack to get the package name from the module name
167
+ const filePath = stackTrace.getSync().find((line) => line.fileName.includes(moduleName));
168
+ if (!filePath) {
169
+ return null;
170
+ }
171
+ const modulePath = findUp.sync('package.json', { cwd: filePath.fileName });
172
+ const moduleMockPath = path.join(modulePath, '..', 'mocks', moduleName);
173
+
174
+ try {
175
+ const mockedPackageNativeModule = jest.requireActual(moduleMockPath);
176
+ return mockedPackageNativeModule;
177
+ } catch {
178
+ return null;
179
+ }
180
+ }
181
+
162
182
  try {
163
- jest.mock('expo-modules-core', () => {
183
+ jest.doMock('expo-modules-core', () => {
164
184
  const ExpoModulesCore = jest.requireActual('expo-modules-core');
165
185
  const uuid = jest.requireActual('expo-modules-core/build/uuid/uuid.web');
166
186
 
187
+ // support old hard-coded mocks TODO: remove this
167
188
  const { NativeModulesProxy } = ExpoModulesCore;
168
189
 
190
+ // Mock the `uuid` object with the implementation for web.
191
+ ExpoModulesCore.uuid.v4 = uuid.default.v4;
192
+ ExpoModulesCore.uuid.v5 = uuid.default.v5;
193
+
169
194
  // After the NativeModules mock is set up, we can mock NativeModuleProxy's functions that call
170
195
  // into the native proxy module. We're not really interested in checking whether the underlying
171
196
  // method is called, just that the proxy method is called, since we have unit tests for the
@@ -174,10 +199,6 @@ try {
174
199
  // NOTE: The adapter validates the number of arguments, which we don't do in the mocked functions.
175
200
  // This means the mock functions will not throw validation errors the way they would in an app.
176
201
 
177
- // Mock the `uuid` object with the implementation for web.
178
- ExpoModulesCore.uuid.v4 = uuid.default.v4;
179
- ExpoModulesCore.uuid.v5 = uuid.default.v5;
180
-
181
202
  for (const moduleName of Object.keys(NativeModulesProxy)) {
182
203
  const nativeModule = NativeModulesProxy[moduleName];
183
204
  for (const propertyName of Object.keys(nativeModule)) {
@@ -186,8 +207,26 @@ try {
186
207
  }
187
208
  }
188
209
  }
189
-
190
- return ExpoModulesCore;
210
+ return {
211
+ ...ExpoModulesCore,
212
+ requireNativeModule: (name) => {
213
+ // Support auto-mocking of expo-modules that:
214
+ // 1. have a mock in the `mocks` directory
215
+ // 2. the native module (e.g. ExpoCrypto) name matches the package name (expo-crypto)
216
+ const nativeModuleMock = attemptLookup(name);
217
+ if (!nativeModuleMock) {
218
+ return ExpoModulesCore.requireNativeModule(name);
219
+ }
220
+ return Object.fromEntries(
221
+ Object.entries(nativeModuleMock).map(([k, v]) => {
222
+ if (typeof v === 'function') {
223
+ return [k, jest.fn(v)];
224
+ }
225
+ return [k, v];
226
+ })
227
+ );
228
+ },
229
+ };
191
230
  });
192
231
  } catch (error) {
193
232
  // Allow this module to be optional for bare-workflow