mirror of
https://github.com/selfxyz/self.git
synced 2026-01-14 00:58:07 -05:00
* feat: add mock document generator demo * feat: add mock document generator * fixes * chore: refresh workflow cache * update lock * build * updates * more fixes * code rabbit feedback * compiles * save wip * updates * merge with dev and fixes * fix: align hoisting and demo Jest resolver (#1003) * chore(app): map common src paths and declare svg flag module * ci fix * update lock * save wip * chore: address yarn lock issues (#1004) * address yarn lock issues * fix postinstall * fix ci * use metro js proxy * android build working for /app * save wip * fix merge * pipeline fixes * format * fix pipelines * bump limit and split * fix pipeline issues * chore: decouple demo app build (#1013) * chore: decouple demo app build * chore: move demo app to workspace * chore: unpublish demo workspace * fix mobile sdk tests * updates * remove polyfills * update merge * update resolutions * update resolutions * fix merge * fix paths * save wip * save wip fixes rd2 * working android * update lock * save wip ios building * fix merge * readd public key * fixes * ci fixes * fixes * fix web building * fix ci * fix tests * update lock * fix ci rd2 * formatting and fix ci * fix * finalize ci fixes * fix tests and metro config paths for building * save wip * install missing package for pipeline * fix wip app building * wip react config * save working emulator compile * first round of pr fixes and feedback * clean up demo app artifacts from sdk * Add Gradle wrapper files for mobile-sdk-demo Android build - Added gradlew, gradlew.bat, and gradle/wrapper/ directory - Updated .gitignore to allow committing Gradle wrapper files - Fixes Android build error: spawn ./gradlew ENOENT * codex feedback and fixes * fix tests * file renames * revert back to dev * add types * coderabbit fixes * fix tests * fix tests * fix test * fixes * fix wip coderabbit issues * coderabbit suggestions rd 2 * fix ci pipelines and addresss warnings * cr fixes * convert kebab to camelCase * save wip fixes * update reinstall and lock files * fixes * remove file * fix lint * fix polyfill fallback issues * ensure that mock document is not on ofac list * prettier
710 lines
20 KiB
JavaScript
710 lines
20 KiB
JavaScript
// SPDX-FileCopyrightText: 2025 Social Connect Labs, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
|
|
|
/* global jest */
|
|
/** @jest-environment jsdom */
|
|
require('react-native-gesture-handler/jestSetup');
|
|
|
|
// Mock NativeAnimatedHelper - using virtual mock during RN 0.76.9 prep phase
|
|
jest.mock(
|
|
'react-native/src/private/animated/NativeAnimatedHelper',
|
|
() => ({}),
|
|
{ virtual: true },
|
|
);
|
|
|
|
// Mock React Native bridge config for mobile-sdk-alpha components
|
|
global.__fbBatchedBridgeConfig = {
|
|
messageQueue: {
|
|
SPY_MODE: false,
|
|
},
|
|
remoteModuleConfig: [],
|
|
};
|
|
|
|
// Set up global React Native test environment
|
|
global.__DEV__ = true;
|
|
|
|
// Mock TurboModuleRegistry to provide required native modules for BOTH main app and mobile-sdk-alpha
|
|
jest.mock('react-native/Libraries/TurboModule/TurboModuleRegistry', () => ({
|
|
getEnforcing: jest.fn(name => {
|
|
if (name === 'PlatformConstants') {
|
|
return {
|
|
getConstants: () => ({
|
|
reactNativeVersion: { major: 0, minor: 76, patch: 9 },
|
|
forceTouchAvailable: false,
|
|
osVersion: '14.0',
|
|
systemName: 'iOS',
|
|
interfaceIdiom: 'phone',
|
|
Dimensions: {
|
|
window: { width: 375, height: 667, scale: 2 },
|
|
screen: { width: 375, height: 667, scale: 2 },
|
|
},
|
|
}),
|
|
};
|
|
}
|
|
if (name === 'SettingsManager') {
|
|
return {
|
|
getConstants: () => ({}),
|
|
};
|
|
}
|
|
if (name === 'DeviceInfo') {
|
|
return {
|
|
getConstants: () => ({
|
|
Dimensions: {
|
|
window: { width: 375, height: 667, scale: 2 },
|
|
screen: { width: 375, height: 667, scale: 2 },
|
|
},
|
|
}),
|
|
};
|
|
}
|
|
return {
|
|
getConstants: () => ({}),
|
|
};
|
|
}),
|
|
get: jest.fn(() => null),
|
|
}));
|
|
|
|
// Mock the mobile-sdk-alpha's React Native instance separately
|
|
jest.mock(
|
|
'../packages/mobile-sdk-alpha/node_modules/react-native/Libraries/TurboModule/TurboModuleRegistry',
|
|
() => ({
|
|
getEnforcing: jest.fn(name => {
|
|
if (name === 'PlatformConstants') {
|
|
return {
|
|
getConstants: () => ({
|
|
reactNativeVersion: { major: 0, minor: 76, patch: 9 },
|
|
forceTouchAvailable: false,
|
|
osVersion: '14.0',
|
|
systemName: 'iOS',
|
|
interfaceIdiom: 'phone',
|
|
Dimensions: {
|
|
window: { width: 375, height: 667, scale: 2 },
|
|
screen: { width: 375, height: 667, scale: 2 },
|
|
},
|
|
}),
|
|
};
|
|
}
|
|
return {
|
|
getConstants: () => ({}),
|
|
};
|
|
}),
|
|
get: jest.fn(() => null),
|
|
}),
|
|
{ virtual: true },
|
|
);
|
|
|
|
// Mock mobile-sdk-alpha's Dimensions module
|
|
jest.mock(
|
|
'../packages/mobile-sdk-alpha/node_modules/react-native/Libraries/Utilities/Dimensions',
|
|
() => ({
|
|
getConstants: jest.fn(() => ({
|
|
window: { width: 375, height: 667, scale: 2 },
|
|
screen: { width: 375, height: 667, scale: 2 },
|
|
})),
|
|
set: jest.fn(),
|
|
get: jest.fn(() => ({
|
|
window: { width: 375, height: 667, scale: 2 },
|
|
screen: { width: 375, height: 667, scale: 2 },
|
|
})),
|
|
addEventListener: jest.fn(),
|
|
removeEventListener: jest.fn(),
|
|
}),
|
|
{ virtual: true },
|
|
);
|
|
|
|
// Mock mobile-sdk-alpha's PixelRatio module
|
|
jest.mock(
|
|
'../packages/mobile-sdk-alpha/node_modules/react-native/Libraries/Utilities/PixelRatio',
|
|
() => ({
|
|
get: jest.fn(() => 2),
|
|
getFontScale: jest.fn(() => 1),
|
|
getPixelSizeForLayoutSize: jest.fn(layoutSize => layoutSize * 2),
|
|
roundToNearestPixel: jest.fn(layoutSize => Math.round(layoutSize * 2) / 2),
|
|
startDetecting: jest.fn(),
|
|
}),
|
|
{ virtual: true },
|
|
);
|
|
|
|
// Mock mobile-sdk-alpha's StyleSheet module directly
|
|
jest.mock(
|
|
'../packages/mobile-sdk-alpha/node_modules/react-native/Libraries/StyleSheet/StyleSheet',
|
|
() => ({
|
|
create: jest.fn(styles => styles),
|
|
flatten: jest.fn(style => style),
|
|
hairlineWidth: 1,
|
|
absoluteFillObject: {
|
|
position: 'absolute',
|
|
left: 0,
|
|
right: 0,
|
|
top: 0,
|
|
bottom: 0,
|
|
},
|
|
roundToNearestPixel: jest.fn(layoutSize => Math.round(layoutSize * 2) / 2),
|
|
}),
|
|
{ virtual: true },
|
|
);
|
|
|
|
// Mock NativeDeviceInfo specs for both main app and mobile-sdk-alpha
|
|
jest.mock('react-native/src/private/specs/modules/NativeDeviceInfo', () => ({
|
|
getConstants: jest.fn(() => ({
|
|
Dimensions: {
|
|
window: { width: 375, height: 667, scale: 2 },
|
|
screen: { width: 375, height: 667, scale: 2 },
|
|
},
|
|
})),
|
|
}));
|
|
|
|
// Mock react-native-gesture-handler to prevent getConstants errors
|
|
jest.mock('react-native-gesture-handler', () => {
|
|
const RN = jest.requireActual('react-native');
|
|
return {
|
|
...jest.requireActual('react-native-gesture-handler/jestSetup'),
|
|
GestureHandlerRootView: ({ children }) => children,
|
|
ScrollView: RN.ScrollView,
|
|
TouchableOpacity: RN.TouchableOpacity,
|
|
TouchableHighlight: RN.TouchableHighlight,
|
|
FlatList: RN.FlatList,
|
|
};
|
|
});
|
|
|
|
// Mock NativeEventEmitter to prevent null argument errors
|
|
jest.mock('react-native/Libraries/EventEmitter/NativeEventEmitter', () => {
|
|
return class MockNativeEventEmitter {
|
|
constructor(nativeModule) {
|
|
// Accept any nativeModule argument (including null/undefined)
|
|
this.nativeModule = nativeModule;
|
|
}
|
|
|
|
addListener = jest.fn();
|
|
removeListener = jest.fn();
|
|
removeAllListeners = jest.fn();
|
|
emit = jest.fn();
|
|
};
|
|
});
|
|
|
|
// Mock problematic mobile-sdk-alpha components that use React Native StyleSheet
|
|
jest.mock('@selfxyz/mobile-sdk-alpha', () => ({
|
|
NFCScannerScreen: jest.fn(() => null),
|
|
SelfClientProvider: jest.fn(({ children }) => children),
|
|
useSelfClient: jest.fn(() => {
|
|
// Create a consistent mock instance for memoization testing
|
|
if (!global.mockSelfClientInstance) {
|
|
global.mockSelfClientInstance = {
|
|
// Mock selfClient object with common methods
|
|
connect: jest.fn(),
|
|
disconnect: jest.fn(),
|
|
isConnected: false,
|
|
extractMRZInfo: jest.fn(mrzString => {
|
|
// Mock extractMRZInfo with realistic behavior
|
|
if (!mrzString || typeof mrzString !== 'string') {
|
|
throw new Error('Invalid MRZ string provided');
|
|
}
|
|
|
|
// Valid MRZ example from the test
|
|
if (mrzString.includes('L898902C3')) {
|
|
return {
|
|
documentNumber: 'L898902C3',
|
|
validation: {
|
|
overall: true,
|
|
},
|
|
// Add other expected MRZ fields
|
|
firstName: 'ANNA',
|
|
lastName: 'ERIKSSON',
|
|
nationality: 'UTO',
|
|
dateOfBirth: '740812',
|
|
sex: 'F',
|
|
expirationDate: '120415',
|
|
};
|
|
}
|
|
|
|
// For malformed/invalid MRZ strings, throw an error
|
|
throw new Error('Invalid MRZ format');
|
|
}),
|
|
trackEvent: jest.fn(),
|
|
};
|
|
}
|
|
return global.mockSelfClientInstance;
|
|
}),
|
|
createSelfClient: jest.fn(() => ({
|
|
// Mock createSelfClient return value
|
|
connect: jest.fn(),
|
|
disconnect: jest.fn(),
|
|
isConnected: false,
|
|
extractMRZInfo: jest.fn(mrzString => {
|
|
// Mock extractMRZInfo with realistic behavior
|
|
if (!mrzString || typeof mrzString !== 'string') {
|
|
throw new Error('Invalid MRZ string provided');
|
|
}
|
|
|
|
// Valid MRZ example from the test
|
|
if (mrzString.includes('L898902C3')) {
|
|
return {
|
|
documentNumber: 'L898902C3',
|
|
validation: {
|
|
overall: true,
|
|
},
|
|
// Add other expected MRZ fields
|
|
firstName: 'ANNA',
|
|
lastName: 'ERIKSSON',
|
|
nationality: 'UTO',
|
|
dateOfBirth: '740812',
|
|
sex: 'F',
|
|
expirationDate: '120415',
|
|
};
|
|
}
|
|
|
|
// For malformed/invalid MRZ strings, throw an error
|
|
throw new Error('Invalid MRZ format');
|
|
}),
|
|
trackEvent: jest.fn(),
|
|
})),
|
|
createListenersMap: jest.fn(() => ({
|
|
// Mock createListenersMap return value
|
|
map: new Map(),
|
|
addListener: jest.fn(),
|
|
removeListener: jest.fn(),
|
|
})),
|
|
isPassportDataValid: jest.fn((data, callbacks) => {
|
|
// Mock validation function with realistic behavior
|
|
if (!data || !data.passportMetadata) {
|
|
// Call appropriate callbacks for missing data
|
|
if (callbacks?.onPassportMetadataNull) {
|
|
callbacks.onPassportMetadataNull();
|
|
}
|
|
return false;
|
|
}
|
|
// Return true for valid data, false for invalid
|
|
return data.valid !== false;
|
|
}),
|
|
SdkEvents: {
|
|
// Mock SDK events object
|
|
PROVING_PASSPORT_DATA_NOT_FOUND: 'PROVING_PASSPORT_DATA_NOT_FOUND',
|
|
PROVING_STARTED: 'PROVING_STARTED',
|
|
PROVING_COMPLETED: 'PROVING_COMPLETED',
|
|
PROVING_FAILED: 'PROVING_FAILED',
|
|
// Add other events as needed
|
|
},
|
|
// Add other components and hooks as needed
|
|
}));
|
|
|
|
// Mock Sentry to prevent NativeModule.getConstants errors
|
|
jest.mock('@sentry/react-native', () => ({
|
|
addBreadcrumb: jest.fn(),
|
|
captureException: jest.fn(),
|
|
captureFeedback: jest.fn(),
|
|
captureMessage: jest.fn(),
|
|
setContext: jest.fn(),
|
|
setExtra: jest.fn(),
|
|
setTag: jest.fn(),
|
|
setUser: jest.fn(),
|
|
init: jest.fn(),
|
|
wrap: jest.fn(component => component),
|
|
withScope: jest.fn(callback => {
|
|
// Mock scope object
|
|
const scope = {
|
|
setLevel: jest.fn(),
|
|
setTag: jest.fn(),
|
|
setExtra: jest.fn(),
|
|
setContext: jest.fn(),
|
|
setUser: jest.fn(),
|
|
};
|
|
callback(scope);
|
|
}),
|
|
}));
|
|
|
|
jest.mock('@env', () => ({
|
|
ENABLE_DEBUG_LOGS: 'false',
|
|
MIXPANEL_NFC_PROJECT_TOKEN: 'test-token',
|
|
}));
|
|
|
|
global.FileReader = class {
|
|
constructor() {
|
|
this.onload = null;
|
|
}
|
|
readAsArrayBuffer() {
|
|
if (this.onload) {
|
|
this.onload({ target: { result: new ArrayBuffer(0) } });
|
|
}
|
|
}
|
|
};
|
|
|
|
jest.mock('@react-native-firebase/messaging', () => {
|
|
return () => ({
|
|
hasPermission: jest.fn(() => Promise.resolve(true)),
|
|
requestPermission: jest.fn(() => Promise.resolve(true)),
|
|
getToken: jest.fn(() => Promise.resolve('mock-token')),
|
|
onMessage: jest.fn(() => jest.fn()),
|
|
onNotificationOpenedApp: jest.fn(() => jest.fn()),
|
|
getInitialNotification: jest.fn(() => Promise.resolve(null)),
|
|
setBackgroundMessageHandler: jest.fn(),
|
|
registerDeviceForRemoteMessages: jest.fn(() => Promise.resolve()),
|
|
subscribeToTopic: jest.fn(),
|
|
unsubscribeFromTopic: jest.fn(),
|
|
});
|
|
});
|
|
|
|
jest.mock('@react-native-firebase/remote-config', () => {
|
|
const mockValue = { asBoolean: jest.fn(() => false) };
|
|
const mockConfig = {
|
|
setDefaults: jest.fn(),
|
|
setConfigSettings: jest.fn(),
|
|
fetchAndActivate: jest.fn(() => Promise.resolve(true)),
|
|
getValue: jest.fn(() => mockValue),
|
|
};
|
|
return () => mockConfig;
|
|
});
|
|
|
|
// Mock react-native-haptic-feedback
|
|
jest.mock('react-native-haptic-feedback', () => ({
|
|
trigger: jest.fn(),
|
|
}));
|
|
|
|
// Mock Segment Analytics
|
|
jest.mock('@segment/analytics-react-native', () => {
|
|
const mockClient = {
|
|
add: jest.fn(),
|
|
track: jest.fn(),
|
|
identify: jest.fn(),
|
|
screen: jest.fn(),
|
|
group: jest.fn(),
|
|
alias: jest.fn(),
|
|
reset: jest.fn(),
|
|
};
|
|
|
|
// Mock flush policy classes
|
|
const MockFlushPolicy = class {
|
|
constructor() {}
|
|
};
|
|
|
|
return {
|
|
createClient: jest.fn(() => mockClient),
|
|
EventPlugin: jest.fn(),
|
|
PluginType: {
|
|
ENRICHMENT: 'enrichment',
|
|
DESTINATION: 'destination',
|
|
BEFORE: 'before',
|
|
before: 'before',
|
|
},
|
|
StartupFlushPolicy: MockFlushPolicy,
|
|
BackgroundFlushPolicy: MockFlushPolicy,
|
|
};
|
|
});
|
|
|
|
// Note: @selfxyz/mobile-sdk-alpha is NOT mocked to allow testing real package methods
|
|
// This is intentional for the mobile-sdk-alpha migration testing
|
|
|
|
// Mock react-native-keychain
|
|
jest.mock('react-native-keychain', () => ({
|
|
SECURITY_LEVEL_ANY: 'MOCK_SECURITY_LEVEL_ANY',
|
|
SECURITY_LEVEL_SECURE_SOFTWARE: 'MOCK_SECURITY_LEVEL_SECURE_SOFTWARE',
|
|
SECURITY_LEVEL_SECURE_HARDWARE: 'MOCK_SECURITY_LEVEL_SECURE_HARDWARE',
|
|
setGenericPassword: jest.fn(),
|
|
getGenericPassword: jest.fn(),
|
|
resetGenericPassword: jest.fn(),
|
|
ACCESSIBLE: {
|
|
WHEN_UNLOCKED: 'AccessibleWhenUnlocked',
|
|
AFTER_FIRST_UNLOCK: 'AccessibleAfterFirstUnlock',
|
|
ALWAYS: 'AccessibleAlways',
|
|
WHEN_PASSCODE_SET_THIS_DEVICE_ONLY:
|
|
'AccessibleWhenPasscodeSetThisDeviceOnly',
|
|
WHEN_UNLOCKED_THIS_DEVICE_ONLY: 'AccessibleWhenUnlockedThisDeviceOnly',
|
|
AFTER_FIRST_UNLOCK_THIS_DEVICE_ONLY:
|
|
'AccessibleAfterFirstUnlockThisDeviceOnly',
|
|
ALWAYS_THIS_DEVICE_ONLY: 'AccessibleAlwaysThisDeviceOnly',
|
|
},
|
|
ACCESS_CONTROL: {
|
|
USER_PRESENCE: 'UserPresence',
|
|
BIOMETRY_ANY: 'BiometryAny',
|
|
BIOMETRY_CURRENT_SET: 'BiometryCurrentSet',
|
|
DEVICE_PASSCODE: 'DevicePasscode',
|
|
APPLICATION_PASSWORD: 'ApplicationPassword',
|
|
BIOMETRY_ANY_OR_DEVICE_PASSCODE: 'BiometryAnyOrDevicePasscode',
|
|
BIOMETRY_CURRENT_SET_OR_DEVICE_PASSCODE:
|
|
'BiometryCurrentSetOrDevicePasscode',
|
|
},
|
|
}));
|
|
|
|
// Mock AsyncStorage
|
|
jest.mock('@react-native-async-storage/async-storage', () => ({
|
|
setItem: jest.fn(),
|
|
getItem: jest.fn(),
|
|
removeItem: jest.fn(),
|
|
mergeItem: jest.fn(),
|
|
clear: jest.fn(),
|
|
getAllKeys: jest.fn(),
|
|
flushGetRequests: jest.fn(),
|
|
multiGet: jest.fn(),
|
|
multiSet: jest.fn(),
|
|
multiRemove: jest.fn(),
|
|
multiMerge: jest.fn(),
|
|
}));
|
|
|
|
// Mock react-native-check-version
|
|
jest.mock('react-native-check-version', () => ({
|
|
checkVersion: jest.fn().mockResolvedValue({
|
|
needsUpdate: false,
|
|
currentVersion: '1.0.0',
|
|
latestVersion: '1.0.0',
|
|
}),
|
|
}));
|
|
|
|
// Mock @react-native-community/netinfo
|
|
jest.mock('@react-native-community/netinfo', () => ({
|
|
addEventListener: jest.fn(() => jest.fn()),
|
|
useNetInfo: jest.fn().mockReturnValue({
|
|
type: 'wifi',
|
|
isConnected: true,
|
|
isInternetReachable: true,
|
|
details: {
|
|
isConnectionExpensive: false,
|
|
cellularGeneration: '4g',
|
|
},
|
|
}),
|
|
fetch: jest
|
|
.fn()
|
|
.mockResolvedValue({ isConnected: true, isInternetReachable: true }),
|
|
}));
|
|
|
|
// Mock react-native-nfc-manager
|
|
jest.mock('react-native-nfc-manager', () => ({
|
|
start: jest.fn(),
|
|
isSupported: jest.fn().mockResolvedValue(true),
|
|
isEnabled: jest.fn().mockResolvedValue(true),
|
|
registerTagEvent: jest.fn(),
|
|
unregisterTagEvent: jest.fn(),
|
|
requestTechnology: jest.fn(),
|
|
cancelTechnologyRequest: jest.fn(),
|
|
getTag: jest.fn(),
|
|
setAlertMessage: jest.fn(),
|
|
sendMifareCommand: jest.fn(),
|
|
sendCommandAPDU: jest.fn(),
|
|
transceive: jest.fn(),
|
|
getMaxTransceiveLength: jest.fn(),
|
|
setTimeout: jest.fn(),
|
|
connect: jest.fn(),
|
|
close: jest.fn(),
|
|
cleanUpTag: jest.fn(),
|
|
default: {
|
|
start: jest.fn(),
|
|
isSupported: jest.fn().mockResolvedValue(true),
|
|
isEnabled: jest.fn().mockResolvedValue(true),
|
|
registerTagEvent: jest.fn(),
|
|
unregisterTagEvent: jest.fn(),
|
|
requestTechnology: jest.fn(),
|
|
cancelTechnologyRequest: jest.fn(),
|
|
getTag: jest.fn(),
|
|
setAlertMessage: jest.fn(),
|
|
sendMifareCommand: jest.fn(),
|
|
sendCommandAPDU: jest.fn(),
|
|
transceive: jest.fn(),
|
|
getMaxTransceiveLength: jest.fn(),
|
|
setTimeout: jest.fn(),
|
|
connect: jest.fn(),
|
|
close: jest.fn(),
|
|
cleanUpTag: jest.fn(),
|
|
},
|
|
}));
|
|
|
|
// Mock react-native-passport-reader
|
|
jest.mock('react-native-passport-reader', () => {
|
|
const mockScanPassport = jest.fn();
|
|
// Mock the parameter count for scanPassport (iOS native method takes 9 parameters)
|
|
Object.defineProperty(mockScanPassport, 'length', { value: 9 });
|
|
|
|
const mockPassportReader = {
|
|
configure: jest.fn(),
|
|
scanPassport: mockScanPassport,
|
|
readPassport: jest.fn(),
|
|
cancelPassportRead: jest.fn(),
|
|
trackEvent: jest.fn(),
|
|
flush: jest.fn(),
|
|
reset: jest.fn(),
|
|
};
|
|
|
|
return {
|
|
PassportReader: mockPassportReader,
|
|
default: mockPassportReader,
|
|
reset: jest.fn(),
|
|
scan: jest.fn(),
|
|
};
|
|
});
|
|
|
|
const { NativeModules } = require('react-native');
|
|
|
|
NativeModules.PassportReader = {
|
|
configure: jest.fn(),
|
|
scanPassport: jest.fn(),
|
|
trackEvent: jest.fn(),
|
|
flush: jest.fn(),
|
|
reset: jest.fn(),
|
|
};
|
|
|
|
// Mock @/utils/passportReader to properly expose the interface expected by tests
|
|
jest.mock('./src/utils/passportReader', () => {
|
|
const mockScanPassport = jest.fn();
|
|
// Mock the parameter count for scanPassport (iOS native method takes 9 parameters)
|
|
Object.defineProperty(mockScanPassport, 'length', { value: 9 });
|
|
|
|
const mockPassportReader = {
|
|
configure: jest.fn(),
|
|
scanPassport: mockScanPassport,
|
|
trackEvent: jest.fn(),
|
|
flush: jest.fn(),
|
|
reset: jest.fn(),
|
|
};
|
|
|
|
return {
|
|
PassportReader: mockPassportReader,
|
|
reset: jest.fn(),
|
|
scan: jest.fn(),
|
|
default: mockPassportReader,
|
|
};
|
|
});
|
|
|
|
// Mock @stablelib packages
|
|
jest.mock('@stablelib/cbor', () => ({
|
|
encode: jest.fn(),
|
|
decode: jest.fn(),
|
|
}));
|
|
|
|
jest.mock('@stablelib/utf8', () => ({
|
|
encode: jest.fn(),
|
|
decode: jest.fn(),
|
|
}));
|
|
|
|
// Mock react-native-app-auth
|
|
jest.mock('react-native-app-auth', () => ({
|
|
authorize: jest.fn().mockResolvedValue({ accessToken: 'mock-access-token' }),
|
|
}));
|
|
|
|
// Mock @robinbobin/react-native-google-drive-api-wrapper
|
|
jest.mock('@robinbobin/react-native-google-drive-api-wrapper', () => {
|
|
class MockUploader {
|
|
setData() {
|
|
return this;
|
|
}
|
|
setDataMimeType() {
|
|
return this;
|
|
}
|
|
setRequestBody() {
|
|
return this;
|
|
}
|
|
execute = jest.fn();
|
|
}
|
|
|
|
class MockFiles {
|
|
newMultipartUploader() {
|
|
return new MockUploader();
|
|
}
|
|
list = jest.fn().mockResolvedValue({ files: [] });
|
|
delete = jest.fn();
|
|
getText = jest.fn().mockResolvedValue('');
|
|
}
|
|
|
|
class GDrive {
|
|
accessToken = '';
|
|
files = new MockFiles();
|
|
}
|
|
|
|
return {
|
|
__esModule: true,
|
|
GDrive,
|
|
MIME_TYPES: { application: { json: 'application/json' } },
|
|
APP_DATA_FOLDER_ID: 'appDataFolder',
|
|
};
|
|
});
|
|
|
|
// Mock react-native-cloud-storage
|
|
jest.mock('react-native-cloud-storage', () => {
|
|
const mockCloudStorage = {
|
|
setProviderOptions: jest.fn(),
|
|
isCloudAvailable: jest.fn().mockResolvedValue(true),
|
|
createFolder: jest.fn(),
|
|
deleteFolder: jest.fn(),
|
|
listFiles: jest.fn(),
|
|
readFile: jest.fn(),
|
|
writeFile: jest.fn(),
|
|
deleteFile: jest.fn(),
|
|
getFileInfo: jest.fn(),
|
|
getStorageInfo: jest.fn(),
|
|
getProvider: jest.fn(),
|
|
mkdir: jest.fn(),
|
|
exists: jest.fn(),
|
|
rmdir: jest.fn(),
|
|
};
|
|
|
|
return {
|
|
__esModule: true,
|
|
CloudStorage: mockCloudStorage,
|
|
CloudStorageScope: {
|
|
AppData: 'AppData',
|
|
Documents: 'Documents',
|
|
Full: 'Full',
|
|
},
|
|
CloudStorageProvider: {
|
|
GoogleDrive: 'GoogleDrive',
|
|
ICloud: 'ICloud',
|
|
},
|
|
};
|
|
});
|
|
|
|
// Mock @react-native-clipboard/clipboard
|
|
jest.mock('@react-native-clipboard/clipboard', () => ({
|
|
getString: jest.fn().mockResolvedValue(''),
|
|
setString: jest.fn(),
|
|
hasString: jest.fn().mockResolvedValue(false),
|
|
}));
|
|
|
|
// Mock react-native-localize
|
|
jest.mock('react-native-localize', () => ({
|
|
getLocales: jest.fn().mockReturnValue([
|
|
{
|
|
countryCode: 'US',
|
|
languageTag: 'en-US',
|
|
languageCode: 'en',
|
|
isRTL: false,
|
|
},
|
|
]),
|
|
getCountry: jest.fn().mockReturnValue('US'),
|
|
getTimeZone: jest.fn().mockReturnValue('America/New_York'),
|
|
getCurrencies: jest.fn().mockReturnValue(['USD']),
|
|
getTemperatureUnit: jest.fn().mockReturnValue('celsius'),
|
|
getFirstWeekDay: jest.fn().mockReturnValue(0),
|
|
uses24HourClock: jest.fn().mockReturnValue(false),
|
|
usesMetricSystem: jest.fn().mockReturnValue(false),
|
|
findBestAvailableLanguage: jest.fn().mockReturnValue({
|
|
languageTag: 'en-US',
|
|
isRTL: false,
|
|
}),
|
|
}));
|
|
|
|
jest.mock('./src/utils/notifications/notificationService', () =>
|
|
require('./tests/__setup__/notificationServiceMock.js'),
|
|
);
|
|
|
|
// Mock React Navigation
|
|
jest.mock('@react-navigation/native', () => {
|
|
const actualNav = jest.requireActual('@react-navigation/native');
|
|
return {
|
|
...actualNav,
|
|
useNavigation: jest.fn(() => ({
|
|
navigate: jest.fn(),
|
|
goBack: jest.fn(),
|
|
canGoBack: jest.fn(() => true),
|
|
dispatch: jest.fn(),
|
|
})),
|
|
createNavigationContainerRef: jest.fn(() => ({
|
|
current: null,
|
|
getCurrentRoute: jest.fn(),
|
|
})),
|
|
createStaticNavigation: jest.fn(() => ({ displayName: 'MockNavigation' })),
|
|
};
|
|
});
|
|
|
|
jest.mock('@react-navigation/native-stack', () => ({
|
|
createNativeStackNavigator: jest.fn(() => ({
|
|
displayName: 'MockStackNavigator',
|
|
})),
|
|
createNavigatorFactory: jest.fn(),
|
|
}));
|