jest-expo 50.0.0-alpha.2 → 50.0.0-alpha.4
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 +5 -4
- package/src/preset/expoModules.js +9 -51
- package/src/preset/setup.js +54 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jest-expo",
|
|
3
|
-
"version": "50.0.0-alpha.
|
|
3
|
+
"version": "50.0.0-alpha.4",
|
|
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.
|
|
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": "
|
|
51
|
+
"gitHead": "3142a086578deffd8704a8f1b6f0f661527d836c"
|
|
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
|
],
|
|
@@ -296,6 +269,9 @@ module.exports = {
|
|
|
296
269
|
{ name: 'clearDiskCache', argumentsCount: 0, key: 'clearDiskCache' },
|
|
297
270
|
{ name: 'clearMemoryCache', argumentsCount: 0, key: 'clearMemoryCache' },
|
|
298
271
|
{ name: 'prefetch', argumentsCount: 1, key: 'prefetch' },
|
|
272
|
+
{ name: 'getCachePathAsync', argumentsCount: 1, key: 'getCachePathAsync' },
|
|
273
|
+
{ name: 'startAnimating', argumentsCount: 0, key: 'startAnimating' },
|
|
274
|
+
{ name: 'stopAnimating', argumentsCount: 0, key: 'stopAnimating' },
|
|
299
275
|
],
|
|
300
276
|
ExpoImageManipulator: [
|
|
301
277
|
{ name: 'manipulateAsync', argumentsCount: 3, key: 'manipulateAsync' },
|
|
@@ -397,7 +373,7 @@ module.exports = {
|
|
|
397
373
|
{ name: 'getCurrentInput', argumentsCount: 0, key: 21 },
|
|
398
374
|
{ name: 'startAudioRecording', argumentsCount: 0, key: 22 },
|
|
399
375
|
],
|
|
400
|
-
|
|
376
|
+
ExpoCamera: [
|
|
401
377
|
{ name: 'getAvailablePictureSizes', argumentsCount: 2, key: 'getAvailablePictureSizes' },
|
|
402
378
|
{
|
|
403
379
|
name: 'getAvailableVideoCodecsAsync',
|
|
@@ -441,7 +417,7 @@ module.exports = {
|
|
|
441
417
|
],
|
|
442
418
|
ExponentFileSystem: [
|
|
443
419
|
{ name: 'uploadAsync', argumentsCount: 3, key: 0 },
|
|
444
|
-
{ name: 'readDirectoryAsync', argumentsCount:
|
|
420
|
+
{ name: 'readDirectoryAsync', argumentsCount: 1, key: 1 },
|
|
445
421
|
{ name: 'getTotalDiskCapacityAsync', argumentsCount: 0, key: 2 },
|
|
446
422
|
{ name: 'getInfoAsync', argumentsCount: 2, key: 3 },
|
|
447
423
|
{ name: 'downloadAsync', argumentsCount: 3, key: 4 },
|
|
@@ -687,8 +663,6 @@ module.exports = {
|
|
|
687
663
|
mobileCountryCode: { type: 'object', mock: null },
|
|
688
664
|
mobileNetworkCode: { type: 'object', mock: null },
|
|
689
665
|
},
|
|
690
|
-
ExpoClipboard: {},
|
|
691
|
-
ExpoCrypto: {},
|
|
692
666
|
ExpoDevice: {
|
|
693
667
|
brand: { type: 'string' },
|
|
694
668
|
deviceName: { type: 'string' },
|
|
@@ -731,7 +705,7 @@ module.exports = {
|
|
|
731
705
|
SortBy: { type: 'object' },
|
|
732
706
|
},
|
|
733
707
|
ExponentAV: { Qualities: { type: 'object' } },
|
|
734
|
-
|
|
708
|
+
ExpoCamera: {
|
|
735
709
|
AutoFocus: { type: 'object' },
|
|
736
710
|
FlashMode: { type: 'object' },
|
|
737
711
|
Type: { type: 'object' },
|
|
@@ -742,9 +716,8 @@ module.exports = {
|
|
|
742
716
|
},
|
|
743
717
|
ExponentConstants: {
|
|
744
718
|
appOwnership: { type: 'string' },
|
|
745
|
-
debugMode: { type: 'boolean', mock:
|
|
719
|
+
debugMode: { type: 'boolean', mock: false },
|
|
746
720
|
deviceName: { type: 'string' },
|
|
747
|
-
deviceYearClass: { type: 'number', mock: 2023 },
|
|
748
721
|
executionEnvironment: { type: 'string' },
|
|
749
722
|
experienceUrl: { type: 'string' },
|
|
750
723
|
expoRuntimeVersion: { type: 'string' },
|
|
@@ -773,7 +746,7 @@ module.exports = {
|
|
|
773
746
|
ExponentGLView: {},
|
|
774
747
|
ExponentImagePicker: {},
|
|
775
748
|
ExpoNetwork: {},
|
|
776
|
-
ExpoPrint: {},
|
|
749
|
+
ExpoPrint: { Orientation: { type: 'object' } },
|
|
777
750
|
ExpoRandom: {},
|
|
778
751
|
ExpoScreenOrientation: {},
|
|
779
752
|
ExpoSecureStore: {
|
|
@@ -818,16 +791,6 @@ module.exports = {
|
|
|
818
791
|
ExpoAppleAuthentication: { propsNames: ['buttonStyle', 'buttonType', 'cornerRadius'] },
|
|
819
792
|
ExpoBarCodeScanner: { propsNames: ['barCodeTypes', 'type'] },
|
|
820
793
|
ExpoBlurView: { propsNames: ['intensity', 'tint'] },
|
|
821
|
-
ExpoClipboard: {
|
|
822
|
-
propsNames: [
|
|
823
|
-
'acceptedContentTypes',
|
|
824
|
-
'backgroundColor',
|
|
825
|
-
'cornerStyle',
|
|
826
|
-
'displayMode',
|
|
827
|
-
'foregroundColor',
|
|
828
|
-
'imageOptions',
|
|
829
|
-
],
|
|
830
|
-
},
|
|
831
794
|
ExpoImage: {
|
|
832
795
|
propsNames: [
|
|
833
796
|
'accessibilityLabel',
|
|
@@ -847,7 +810,7 @@ module.exports = {
|
|
|
847
810
|
],
|
|
848
811
|
},
|
|
849
812
|
ExpoLinearGradient: { propsNames: ['colors', 'endPoint', 'locations', 'startPoint'] },
|
|
850
|
-
|
|
813
|
+
ExpoCamera: {
|
|
851
814
|
propsNames: [
|
|
852
815
|
'autoFocus',
|
|
853
816
|
'barCodeScannerEnabled',
|
|
@@ -946,7 +909,6 @@ module.exports = {
|
|
|
946
909
|
getCurrentState: { type: 'function', functionType: 'promise' },
|
|
947
910
|
removeListeners: { type: 'function', functionType: 'async' },
|
|
948
911
|
},
|
|
949
|
-
RNCPickerManager: {},
|
|
950
912
|
RNCSafeAreaContext: {
|
|
951
913
|
getConstants: { type: 'function' },
|
|
952
914
|
initialWindowMetrics: { type: 'object' },
|
|
@@ -989,10 +951,6 @@ module.exports = {
|
|
|
989
951
|
updateGestureHandler: { type: 'function', functionType: 'async' },
|
|
990
952
|
},
|
|
991
953
|
RNSFullWindowOverlayManager: {},
|
|
992
|
-
RNSharedElementTransition: {
|
|
993
|
-
configure: { type: 'function', functionType: 'promise' },
|
|
994
|
-
getConstants: { type: 'function' },
|
|
995
|
-
},
|
|
996
954
|
RNSkia: {
|
|
997
955
|
getConstants: { type: 'function' },
|
|
998
956
|
install: { type: 'function', functionType: 'sync' },
|
package/src/preset/setup.js
CHANGED
|
@@ -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');
|
|
@@ -37,6 +40,10 @@ const expoModules = {
|
|
|
37
40
|
...internalExpoModules,
|
|
38
41
|
};
|
|
39
42
|
|
|
43
|
+
// Mock the experience URL in development mode for asset setup
|
|
44
|
+
expoModules.NativeUnimoduleProxy.modulesConstants.mockDefinition.ExponentConstants.experienceUrl.mock =
|
|
45
|
+
'exp://192.168.1.200:8081';
|
|
46
|
+
|
|
40
47
|
function mock(property, customMock) {
|
|
41
48
|
const propertyType = property.type;
|
|
42
49
|
let mockValue;
|
|
@@ -125,7 +132,7 @@ try {
|
|
|
125
132
|
}
|
|
126
133
|
}
|
|
127
134
|
|
|
128
|
-
jest.mock('react-native/
|
|
135
|
+
jest.mock('@react-native/assets-registry/registry', () => ({
|
|
129
136
|
registerAsset: jest.fn(() => 1),
|
|
130
137
|
getAssetByID: jest.fn(() => ({
|
|
131
138
|
fileSystemLocation: '/full/path/to/directory',
|
|
@@ -159,13 +166,35 @@ jest.doMock('react-native/Libraries/LogBox/LogBox', () => ({
|
|
|
159
166
|
},
|
|
160
167
|
}));
|
|
161
168
|
|
|
169
|
+
function attemptLookup(moduleName) {
|
|
170
|
+
// hack to get the package name from the module name
|
|
171
|
+
const filePath = stackTrace.getSync().find((line) => line.fileName.includes(moduleName));
|
|
172
|
+
if (!filePath) {
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
const modulePath = findUp.sync('package.json', { cwd: filePath.fileName });
|
|
176
|
+
const moduleMockPath = path.join(modulePath, '..', 'mocks', moduleName);
|
|
177
|
+
|
|
178
|
+
try {
|
|
179
|
+
const mockedPackageNativeModule = jest.requireActual(moduleMockPath);
|
|
180
|
+
return mockedPackageNativeModule;
|
|
181
|
+
} catch {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
162
186
|
try {
|
|
163
|
-
jest.
|
|
187
|
+
jest.doMock('expo-modules-core', () => {
|
|
164
188
|
const ExpoModulesCore = jest.requireActual('expo-modules-core');
|
|
165
189
|
const uuid = jest.requireActual('expo-modules-core/build/uuid/uuid.web');
|
|
166
190
|
|
|
191
|
+
// support old hard-coded mocks TODO: remove this
|
|
167
192
|
const { NativeModulesProxy } = ExpoModulesCore;
|
|
168
193
|
|
|
194
|
+
// Mock the `uuid` object with the implementation for web.
|
|
195
|
+
ExpoModulesCore.uuid.v4 = uuid.default.v4;
|
|
196
|
+
ExpoModulesCore.uuid.v5 = uuid.default.v5;
|
|
197
|
+
|
|
169
198
|
// After the NativeModules mock is set up, we can mock NativeModuleProxy's functions that call
|
|
170
199
|
// into the native proxy module. We're not really interested in checking whether the underlying
|
|
171
200
|
// method is called, just that the proxy method is called, since we have unit tests for the
|
|
@@ -174,10 +203,6 @@ try {
|
|
|
174
203
|
// NOTE: The adapter validates the number of arguments, which we don't do in the mocked functions.
|
|
175
204
|
// This means the mock functions will not throw validation errors the way they would in an app.
|
|
176
205
|
|
|
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
206
|
for (const moduleName of Object.keys(NativeModulesProxy)) {
|
|
182
207
|
const nativeModule = NativeModulesProxy[moduleName];
|
|
183
208
|
for (const propertyName of Object.keys(nativeModule)) {
|
|
@@ -186,8 +211,26 @@ try {
|
|
|
186
211
|
}
|
|
187
212
|
}
|
|
188
213
|
}
|
|
189
|
-
|
|
190
|
-
|
|
214
|
+
return {
|
|
215
|
+
...ExpoModulesCore,
|
|
216
|
+
requireNativeModule: (name) => {
|
|
217
|
+
// Support auto-mocking of expo-modules that:
|
|
218
|
+
// 1. have a mock in the `mocks` directory
|
|
219
|
+
// 2. the native module (e.g. ExpoCrypto) name matches the package name (expo-crypto)
|
|
220
|
+
const nativeModuleMock = attemptLookup(name);
|
|
221
|
+
if (!nativeModuleMock) {
|
|
222
|
+
return ExpoModulesCore.requireNativeModule(name);
|
|
223
|
+
}
|
|
224
|
+
return Object.fromEntries(
|
|
225
|
+
Object.entries(nativeModuleMock).map(([k, v]) => {
|
|
226
|
+
if (typeof v === 'function') {
|
|
227
|
+
return [k, jest.fn(v)];
|
|
228
|
+
}
|
|
229
|
+
return [k, v];
|
|
230
|
+
})
|
|
231
|
+
);
|
|
232
|
+
},
|
|
233
|
+
};
|
|
191
234
|
});
|
|
192
235
|
} catch (error) {
|
|
193
236
|
// Allow this module to be optional for bare-workflow
|
|
@@ -195,3 +238,6 @@ try {
|
|
|
195
238
|
throw error;
|
|
196
239
|
}
|
|
197
240
|
}
|
|
241
|
+
|
|
242
|
+
// Ensure the environment globals are installed before the first test runs.
|
|
243
|
+
require('expo/build/winter');
|