mirror of
https://github.com/inaturalist/iNaturalistReactNative.git
synced 2026-01-02 19:08:52 -05:00
* Standard Camera adjust for width when screen orientation changes. Closes #350. * Remove SafeAreaView from StandardCamera * Reduced pressable area for camera button * Lock StandardCamera orientation to portrait mode on smaller devices, detect device rotation * PhotoCarousel responsive to device rotation, mocks added to StandardCamera tests * Image rotation when rotation to and from landscape mode
258 lines
7.7 KiB
JavaScript
258 lines
7.7 KiB
JavaScript
import "i18n";
|
|
import "react-native-gesture-handler/jestSetup";
|
|
|
|
import mockBottomSheet from "@gorhom/bottom-sheet/mock";
|
|
import mockRNCNetInfo from "@react-native-community/netinfo/jest/netinfo-mock";
|
|
import inatjs from "inaturalistjs";
|
|
import React from "react";
|
|
import mockRNDeviceInfo from "react-native-device-info/jest/react-native-device-info-mock";
|
|
import mockRNLocalize from "react-native-localize/mock";
|
|
import mockSafeAreaContext from "react-native-safe-area-context/jest/mock";
|
|
|
|
import { makeResponse } from "./factory";
|
|
import {
|
|
mockCamera,
|
|
mockSortDevices,
|
|
mockUseCameraDevices
|
|
} from "./vision-camera/vision-camera";
|
|
|
|
jest.mock( "@sayem314/react-native-keep-awake" );
|
|
jest.mock( "react-native/Libraries/EventEmitter/NativeEventEmitter" );
|
|
|
|
jest.mock(
|
|
"@react-native-async-storage/async-storage",
|
|
() => require( "@react-native-async-storage/async-storage/jest/async-storage-mock" )
|
|
);
|
|
|
|
require( "react-native-reanimated/lib/reanimated2/jestUtils" ).setUpTests();
|
|
|
|
jest.mock( "react-native-vision-camera", ( ) => ( {
|
|
Camera: mockCamera,
|
|
sortDevices: mockSortDevices,
|
|
useCameraDevices: mockUseCameraDevices
|
|
} ) );
|
|
|
|
jest.mock( "react-native-localize", () => mockRNLocalize );
|
|
jest.mock( "react-native-safe-area-context", () => mockSafeAreaContext );
|
|
|
|
// mock Portal with a Modal component inside of it (MediaViewer)
|
|
jest.mock( "react-native-paper", () => {
|
|
const RealModule = jest.requireActual( "react-native-paper" );
|
|
const MockedModule = {
|
|
...RealModule,
|
|
// eslint-disable-next-line react/jsx-no-useless-fragment
|
|
Portal: ( { children } ) => <>{children}</>
|
|
};
|
|
return MockedModule;
|
|
} );
|
|
|
|
jest.mock( "@react-navigation/native", ( ) => {
|
|
const actualNav = jest.requireActual( "@react-navigation/native" );
|
|
return {
|
|
...actualNav,
|
|
useRoute: jest.fn( ( ) => ( { } ) ),
|
|
useNavigation: ( ) => ( {
|
|
setOptions: jest.fn( )
|
|
} )
|
|
};
|
|
} );
|
|
|
|
// this resolves error with importing file after Jest environment is torn down
|
|
// https://github.com/react-navigation/react-navigation/issues/9568#issuecomment-881943770
|
|
jest.mock( "@react-navigation/native/lib/commonjs/useLinking.native", ( ) => ( {
|
|
default: ( ) => ( { getInitialState: { then: jest.fn() } } ),
|
|
__esModule: true
|
|
} ) );
|
|
|
|
// https://github.com/callstack/react-native-testing-library/issues/658#issuecomment-766886514
|
|
jest.mock( "react-native/Libraries/LogBox/LogBox" );
|
|
|
|
jest.mock( "react-native-config", () => ( {
|
|
OAUTH_CLIENT_ID: process.env.OAUTH_CLIENT_ID,
|
|
OAUTH_CLIENT_SECRET: process.env.OAUTH_CLIENT_SECRET,
|
|
JWT_ANONYMOUS_API_SECRET: process.env.JWT_ANONYMOUS_API_SECRET,
|
|
API_URL: process.env.API_URL
|
|
} ) );
|
|
|
|
jest.mock( "react-native-device-info", () => mockRNDeviceInfo );
|
|
|
|
jest.mock( "react-native-sensitive-info", () => {
|
|
class RNSInfo {
|
|
static stores = new Map()
|
|
|
|
static getServiceName( o = {} ) {
|
|
return o.sharedPreferencesName
|
|
|| o.keychainService
|
|
|| "default";
|
|
}
|
|
|
|
static validateString( s ) {
|
|
if ( typeof s !== "string" ) { throw new Error( "Invalid string:", s ); }
|
|
}
|
|
|
|
static getItem = jest.fn( async ( k, o ) => {
|
|
RNSInfo.validateString( k );
|
|
|
|
const serviceName = RNSInfo.getServiceName( o );
|
|
const service = RNSInfo.stores.get( serviceName );
|
|
|
|
if ( service ) { return service.get( k ) || null; }
|
|
return null;
|
|
} )
|
|
|
|
static getAllItems = jest.fn( async o => {
|
|
const serviceName = RNSInfo.getServiceName( o );
|
|
const service = RNSInfo.stores.get( serviceName );
|
|
let mappedValues = [];
|
|
|
|
if ( service?.size ) {
|
|
// for ( const [k, v] of service.entries() ) {
|
|
// mappedValues.push( { key: k, value: v, service: serviceName } );
|
|
// }
|
|
mappedValues = service.entries( ).map(
|
|
( key, value ) => ( { key, value, service: serviceName } )
|
|
);
|
|
}
|
|
|
|
return mappedValues;
|
|
} )
|
|
|
|
static setItem = jest.fn( async ( k, v, o ) => {
|
|
RNSInfo.validateString( k );
|
|
RNSInfo.validateString( v );
|
|
|
|
const serviceName = RNSInfo.getServiceName( o );
|
|
let service = RNSInfo.stores.get( serviceName );
|
|
|
|
if ( !service ) {
|
|
RNSInfo.stores.set( serviceName, new Map() );
|
|
service = RNSInfo.stores.get( serviceName );
|
|
}
|
|
|
|
service.set( k, v );
|
|
|
|
return null;
|
|
} )
|
|
|
|
static deleteItem = jest.fn( async ( k, o ) => {
|
|
RNSInfo.validateString( k );
|
|
|
|
const serviceName = RNSInfo.getServiceName( o );
|
|
const service = RNSInfo.stores.get( serviceName );
|
|
|
|
if ( service ) { service.delete( k ); }
|
|
|
|
return null;
|
|
} )
|
|
|
|
static hasEnrolledFingerprints = jest.fn( async () => true )
|
|
|
|
static setInvalidatedByBiometricEnrollment = jest.fn()
|
|
|
|
// "Touch ID" | "Face ID" | false
|
|
static isSensorAvailable = jest.fn( async () => "Face ID" )
|
|
}
|
|
|
|
return RNSInfo;
|
|
} );
|
|
|
|
// Some test environments may need a little more time
|
|
jest.setTimeout( 50000 );
|
|
|
|
// https://github.com/zoontek/react-native-permissions
|
|
// eslint-disable-next-line global-require
|
|
jest.mock( "react-native-permissions", () => require( "react-native-permissions/mock" ) );
|
|
|
|
// mocking globally since this currently affects a handful of unit and integration tests
|
|
jest.mock( "@react-native-community/geolocation", ( ) => ( {
|
|
getCurrentPosition: ( ) => jest.fn( )
|
|
} ) );
|
|
require( "react-native" ).NativeModules.RNCGeolocation = { };
|
|
|
|
jest.mock( "@react-native-community/netinfo", () => mockRNCNetInfo );
|
|
|
|
// Make apisauce work with nock
|
|
jest.mock( "apisauce", ( ) => ( {
|
|
create: config => {
|
|
const axiosInstance = jest.requireActual( "axios" ).create( config );
|
|
const apisauce = jest.requireActual( "apisauce" );
|
|
return apisauce.create( { ...config, axiosInstance } );
|
|
}
|
|
} ) );
|
|
|
|
// FormData isn't available in the testing environment
|
|
function FormDataMock() {
|
|
this.append = jest.fn();
|
|
}
|
|
global.FormData = FormDataMock;
|
|
|
|
jest.mock( "react-native-fs", ( ) => {
|
|
const RNFS = {
|
|
appendFile: jest.fn( ),
|
|
DocumentDirectoryPath: jest.fn( ),
|
|
exists: jest.fn( async ( ) => true ),
|
|
moveFile: async ( ) => "testdata",
|
|
stat: jest.fn( ( ) => ( {
|
|
mtime: 123
|
|
} ) )
|
|
};
|
|
|
|
return RNFS;
|
|
} );
|
|
|
|
require( "react-native" ).NativeModules.FileReaderModule = { };
|
|
|
|
// Mock native animation for all tests
|
|
jest.mock( "react-native/Libraries/Animated/NativeAnimatedHelper" );
|
|
|
|
jest.mock( "@gorhom/bottom-sheet", ( ) => ( {
|
|
...mockBottomSheet,
|
|
__esModule: true,
|
|
// eslint-disable-next-line react/jsx-no-useless-fragment
|
|
BottomSheetTextInput: ( ) => <></>
|
|
} ) );
|
|
|
|
jest.mock( "@react-native-camera-roll/camera-roll", ( ) => ( {
|
|
nativeInterface: jest.fn( ),
|
|
CameraRoll: {
|
|
getPhotos: jest.fn( ( ) => ( {
|
|
page_info: {
|
|
end_cursor: jest.fn( ),
|
|
has_next_page: false
|
|
},
|
|
edges: [
|
|
// This expexcts something like
|
|
// { node: photo }
|
|
]
|
|
} ) ),
|
|
getAlbums: jest.fn( ( ) => ( {
|
|
// Expecting album titles as keys and photo counts as values
|
|
// "My Amazing album": 12
|
|
} ) )
|
|
}
|
|
} ) );
|
|
|
|
jest.mock( "react-native-exif-reader", ( ) => ( {
|
|
readExif: jest.fn( )
|
|
} ) );
|
|
|
|
// https://github.com/APSL/react-native-keyboard-aware-scroll-view/issues/493#issuecomment-861711442
|
|
jest.mock( "react-native-keyboard-aware-scroll-view", ( ) => ( {
|
|
KeyboardAwareScrollView: jest
|
|
.fn( )
|
|
.mockImplementation( ( { children } ) => children )
|
|
} ) );
|
|
|
|
// Mock inaturalistjs so we can make some fake responses
|
|
jest.mock( "inaturalistjs" );
|
|
inatjs.observations.search.mockResolvedValue( makeResponse( ) );
|
|
inatjs.observations.updates.mockResolvedValue( makeResponse( ) );
|
|
|
|
jest.mock( "react-native-orientation-locker", () => ( {
|
|
addEventListener: jest.fn(),
|
|
addDeviceOrientationListener: jest.fn(),
|
|
removeEventListener: jest.fn(),
|
|
lockToPortrait: jest.fn(),
|
|
removeOrientationListener: jest.fn()
|
|
} ) );
|