diff --git a/app/App.tsx b/app/App.tsx index b4220c7aa..12fe27516 100644 --- a/app/App.tsx +++ b/app/App.tsx @@ -4,7 +4,7 @@ import { Buffer } from 'buffer'; import React from 'react'; import { YStack } from 'tamagui'; -import AppNavigation from './src/Navigation'; +import AppNavigation from './src/navigation'; import { initSentry, wrapWithSentry } from './src/Sentry'; import { AuthProvider } from './src/stores/authProvider'; import { DatabaseProvider } from './src/stores/databaseProvider'; diff --git a/app/ios/Podfile.lock b/app/ios/Podfile.lock index fdefe4004..bd1c58ba8 100644 --- a/app/ios/Podfile.lock +++ b/app/ios/Podfile.lock @@ -1656,9 +1656,9 @@ PODS: - segment-analytics-react-native (2.20.3): - React-Core - sovran-react-native - - Sentry (8.48.0): - - Sentry/Core (= 8.48.0) - - Sentry/Core (8.48.0) + - Sentry (8.49.2): + - Sentry/Core (= 8.49.2) + - Sentry/Core (8.49.2) - Sentry/HybridSDK (8.48.0) - SentryPrivate (8.21.0) - SocketRocket (0.7.0) diff --git a/app/jest.config.js b/app/jest.config.js index 8eb675e9b..1ecef3169 100644 --- a/app/jest.config.js +++ b/app/jest.config.js @@ -1,3 +1,13 @@ module.exports = { preset: 'react-native', + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], + transformIgnorePatterns: [ + 'node_modules/(?!(react-native|@react-native|@react-navigation|@react-native-community|@segment/analytics-react-native|@openpassport|react-native-keychain|react-native-check-version|react-native-nfc-manager|react-native-passport-reader|uuid|@stablelib|@react-native-google-signin|react-native-cloud-storage|@react-native-clipboard)/)', + ], + setupFiles: ['/jest.setup.js'], + testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.[jt]sx?$', + moduleNameMapper: { + '^@env$': '/tests/__setup__/@env.js', + '^@openpassport/(.*)$': '/../common/node_modules/@openpassport/$1', + }, }; diff --git a/app/jest.setup.js b/app/jest.setup.js new file mode 100644 index 000000000..4add38b05 --- /dev/null +++ b/app/jest.setup.js @@ -0,0 +1,257 @@ +/* global jest */ +/** @jest-environment jsdom */ +require('react-native-gesture-handler/jestSetup'); + +jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper'); + +// 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(), + }; + + return { + createClient: jest.fn(() => mockClient), + EventPlugin: jest.fn(), + PluginType: { + ENRICHMENT: 'enrichment', + DESTINATION: 'destination', + BEFORE: 'before', + }, + }; +}); + +// 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(), + useNetInfo: jest.fn().mockReturnValue({ + type: 'wifi', + isConnected: true, + isInternetReachable: true, + details: { + isConnectionExpensive: false, + cellularGeneration: '4g', + }, + }), + fetch: jest.fn(), +})); + +// 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', () => ({ + default: { + initialize: jest.fn(), + scanPassport: jest.fn(), + readPassport: jest.fn(), + cancelPassportRead: jest.fn(), + }, +})); + +// 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-google-signin/google-signin +jest.mock('@react-native-google-signin/google-signin', () => ({ + GoogleSignin: { + configure: jest.fn(), + hasPlayServices: jest.fn().mockResolvedValue(true), + signIn: jest.fn().mockResolvedValue({ + user: { + id: 'mock-user-id', + email: 'mock@example.com', + name: 'Mock User', + photo: 'mock-photo-url', + }, + }), + signOut: jest.fn(), + revokeAccess: jest.fn(), + isSignedIn: jest.fn().mockResolvedValue(false), + getCurrentUser: jest.fn().mockResolvedValue(null), + getTokens: jest.fn().mockResolvedValue({ + accessToken: 'mock-access-token', + idToken: 'mock-id-token', + }), + }, + statusCodes: { + SIGN_IN_REQUIRED: 'SIGN_IN_REQUIRED', + IN_PROGRESS: 'IN_PROGRESS', + PLAY_SERVICES_NOT_AVAILABLE: 'PLAY_SERVICES_NOT_AVAILABLE', + }, +})); + +// 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, + }), +})); diff --git a/app/package.json b/app/package.json index 80ec80756..8dc805ab1 100644 --- a/app/package.json +++ b/app/package.json @@ -110,6 +110,8 @@ "@react-native/metro-config": "0.75.4", "@react-native/typescript-config": "0.75.4", "@tamagui/types": "1.110.0", + "@testing-library/react-hooks": "^8.0.1", + "@testing-library/react-native": "^13.2.0", "@tsconfig/react-native": "^3.0.0", "@types/add": "^2", "@types/elliptic": "^6", @@ -121,6 +123,7 @@ "@types/react-native": "^0.73.0", "@types/react-native-dotenv": "^0.2.0", "@types/react-native-sqlite-storage": "^6.0.5", + "@types/react-test-renderer": "^18", "eslint": "^8.19.0", "eslint-config-prettier": "^10.1.2", "eslint-plugin-prettier": "^5.2.6", @@ -129,6 +132,7 @@ "prettier": "^3.5.3", "react-native-bundle-visualizer": "^3.1.3", "react-native-svg-transformer": "^1.5.0", + "react-test-renderer": "^18.3.1", "stream-browserify": "^3.0.0", "typescript": "5.0.4" }, diff --git a/app/src/Navigation/account.ts b/app/src/Navigation/account.ts deleted file mode 100644 index 8b2b78fab..000000000 --- a/app/src/Navigation/account.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { NativeStackNavigationOptions } from '@react-navigation/native-stack'; - -import { HomeNavBar } from '../components/NavBar'; -import DisclaimerScreen from '../screens/DisclaimerScreen'; -import HomeScreen from '../screens/HomeScreen'; -import { black } from '../utils/colors'; - -const accountScreens = { - Home: { - screen: HomeScreen, - options: { - title: 'Self', - header: HomeNavBar, - navigationBarColor: black, - presentation: 'card', - } as NativeStackNavigationOptions, - }, - Disclaimer: { - screen: DisclaimerScreen, - options: { - title: 'Disclaimer', - headerShown: false, - } as NativeStackNavigationOptions, - }, -}; - -export default accountScreens; diff --git a/app/src/Navigation/aesop.ts b/app/src/Navigation/aesop.ts deleted file mode 100644 index 55a01050a..000000000 --- a/app/src/Navigation/aesop.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { NativeStackNavigationOptions } from '@react-navigation/native-stack'; - -import { ProgressNavBar } from '../components/NavBar'; -import { shouldShowAesopRedesign } from '../hooks/useAesopRedesign'; -import PassportOnboardingScreen from '../screens/_Aesop/PassportOnboardingScreen'; -import { white } from '../utils/colors'; - -const aesopScreens = { - PassportOnboarding: { - screen: PassportOnboardingScreen, - options: { - animation: 'slide_from_bottom', - header: ProgressNavBar, - title: 'Scan your passport', - headerStyle: { - backgroundColor: white, - }, - headerCurrentStep: 1, - headerTotalSteps: 4, - } as NativeStackNavigationOptions, - }, - - // stub the rest of the steps. will update in future pr - PassportCamera: { - screen: PassportOnboardingScreen, - options: { - animation: 'slide_from_bottom', - header: ProgressNavBar, - title: 'Take a photo', - headerStyle: { - backgroundColor: white, - }, - headerCurrentStep: 2, - headerTotalSteps: 4, - } as NativeStackNavigationOptions, - }, - - PassportNFC: { - screen: PassportOnboardingScreen, - options: { - animation: 'slide_from_bottom', - header: ProgressNavBar, - title: 'Scan NFC', - headerStyle: { - backgroundColor: white, - }, - headerCurrentStep: 3, - headerTotalSteps: 4, - } as NativeStackNavigationOptions, - }, - - PassportComplete: { - screen: PassportOnboardingScreen, - options: { - animation: 'slide_from_bottom', - header: ProgressNavBar, - title: 'Complete', - headerStyle: { - backgroundColor: white, - }, - headerCurrentStep: 4, - headerTotalSteps: 4, - } as NativeStackNavigationOptions, - }, -}; - -export default shouldShowAesopRedesign() ? aesopScreens : {}; diff --git a/app/src/hooks/useConnectionModal.ts b/app/src/hooks/useConnectionModal.ts index 471243346..23dc8c210 100644 --- a/app/src/hooks/useConnectionModal.ts +++ b/app/src/hooks/useConnectionModal.ts @@ -2,7 +2,7 @@ import { useNetInfo } from '@react-native-community/netinfo'; import { useEffect } from 'react'; import { Linking, Platform } from 'react-native'; -import { navigationRef } from '../Navigation'; +import { navigationRef } from '../navigation'; import { useModal } from './useModal'; const connectionModalParams = { diff --git a/app/src/hooks/useModal.ts b/app/src/hooks/useModal.ts index c75924b87..0cd97deb5 100644 --- a/app/src/hooks/useModal.ts +++ b/app/src/hooks/useModal.ts @@ -1,7 +1,7 @@ import { useNavigation } from '@react-navigation/native'; import { useCallback, useState } from 'react'; -import { ModalParams } from '../screens/Settings/ModalScreen'; +import { ModalParams } from '../screens/static/ModalScreen'; export const useModal = (params: ModalParams) => { const [visible, setVisible] = useState(false); diff --git a/app/src/navigation/aesop.ts b/app/src/navigation/aesop.ts new file mode 100644 index 000000000..d9d1cbebb --- /dev/null +++ b/app/src/navigation/aesop.ts @@ -0,0 +1,26 @@ +import { NativeStackNavigationOptions } from '@react-navigation/native-stack'; + +import { ProgressNavBar } from '../components/NavBar'; +import { shouldShowAesopRedesign } from '../hooks/useAesopRedesign'; +import PassportOnboardingScreen from '../screens/aesop/PassportOnboardingScreen'; +import { white } from '../utils/colors'; + +const aesopScreens = { + PassportOnboarding: { + screen: PassportOnboardingScreen, + options: { + animation: 'slide_from_bottom', + header: ProgressNavBar, + title: 'Scan your passport', + headerStyle: { + backgroundColor: white, + }, + headerCurrentStep: 1, + headerTotalSteps: 4, + } as NativeStackNavigationOptions, + }, +}; + +export const getAesopScreens = () => + shouldShowAesopRedesign() ? aesopScreens : {}; +export default getAesopScreens(); diff --git a/app/src/Navigation/dev.ts b/app/src/navigation/dev.ts similarity index 55% rename from app/src/Navigation/dev.ts rename to app/src/navigation/dev.ts index d2afce853..209bc2d9a 100644 --- a/app/src/Navigation/dev.ts +++ b/app/src/navigation/dev.ts @@ -1,17 +1,15 @@ import { NativeStackNavigationOptions } from '@react-navigation/native-stack'; -import DevHapticFeedbackScreen from '../screens/Settings/DevHapticFeedback'; -import DevSettingsScreen from '../screens/Settings/DevSettingsScreen'; +import DevHapticFeedbackScreen from '../screens/dev/DevHapticFeedback'; +import DevSettingsScreen from '../screens/dev/DevSettingsScreen'; +import MockDataScreen from '../screens/dev/MockDataScreen'; import { white } from '../utils/colors'; -const settingsScreens = { - DevSettings: { - screen: DevSettingsScreen, +const devScreens = { + CreateMock: { + screen: MockDataScreen, options: { - title: 'Developer Settings', - headerStyle: { - backgroundColor: white, - }, + title: 'Mock Passport', } as NativeStackNavigationOptions, }, DevHapticFeedback: { @@ -20,6 +18,15 @@ const settingsScreens = { title: 'Haptic Feedback', } as NativeStackNavigationOptions, }, + DevSettings: { + screen: DevSettingsScreen, + options: { + title: 'Developer Settings', + headerStyle: { + backgroundColor: white, + }, + } as NativeStackNavigationOptions, + }, }; -export default settingsScreens; +export default devScreens; diff --git a/app/src/Navigation/home.ts b/app/src/navigation/home.ts similarity index 75% rename from app/src/Navigation/home.ts rename to app/src/navigation/home.ts index 7795a0d88..97f3bdba9 100644 --- a/app/src/Navigation/home.ts +++ b/app/src/navigation/home.ts @@ -1,11 +1,18 @@ import { NativeStackNavigationOptions } from '@react-navigation/native-stack'; -import HomeNavBar from '../components/NavBar/HomeNavBar'; -import DisclaimerScreen from '../screens/DisclaimerScreen'; -import HomeScreen from '../screens/HomeScreen'; +import { HomeNavBar } from '../components/NavBar'; +import DisclaimerScreen from '../screens/home/DisclaimerScreen'; +import HomeScreen from '../screens/home/HomeScreen'; import { black } from '../utils/colors'; const homeScreens = { + Disclaimer: { + screen: DisclaimerScreen, + options: { + title: 'Disclaimer', + headerShown: false, + } as NativeStackNavigationOptions, + }, Home: { screen: HomeScreen, options: { @@ -15,13 +22,6 @@ const homeScreens = { presentation: 'card', } as NativeStackNavigationOptions, }, - Disclaimer: { - screen: DisclaimerScreen, - options: { - title: 'Disclaimer', - headerShown: false, - } as NativeStackNavigationOptions, - }, }; export default homeScreens; diff --git a/app/src/Navigation/index.tsx b/app/src/navigation/index.tsx similarity index 87% rename from app/src/Navigation/index.tsx rename to app/src/navigation/index.tsx index a02097bfa..a2f914ba5 100644 --- a/app/src/Navigation/index.tsx +++ b/app/src/navigation/index.tsx @@ -14,8 +14,7 @@ import AppLayout from '../layouts/AppLayout'; import analytics from '../utils/analytics'; import { white } from '../utils/colors'; import { setupUniversalLinkListenerInNavigation } from '../utils/deeplinks'; -import accountScreens from './account'; -import aesopScreens from './aesop'; +import { getAesopScreens } from './aesop'; import devScreens from './dev'; import homeScreens from './home'; import passportScreens from './passport'; @@ -24,25 +23,26 @@ import recoveryScreens from './recovery'; import settingsScreens from './settings'; import staticScreens from './static'; +export const navigationScreens = { + ...staticScreens, + ...passportScreens, + ...homeScreens, + ...proveScreens, + ...settingsScreens, + ...recoveryScreens, + ...devScreens, + // add last to override other screens + ...getAesopScreens(), +}; + const AppNavigation = createNativeStackNavigator({ initialRouteName: 'Splash', - orientation: 'portrait_up', screenOptions: { header: DefaultNavBar, navigationBarColor: white, }, layout: AppLayout, - screens: { - ...staticScreens, - ...passportScreens, - ...homeScreens, - ...proveScreens, - ...accountScreens, - ...settingsScreens, - ...recoveryScreens, - ...devScreens, - ...aesopScreens, - }, + screens: navigationScreens, }); export type RootStackParamList = StaticParamList; diff --git a/app/src/Navigation/passport.ts b/app/src/navigation/passport.ts similarity index 54% rename from app/src/Navigation/passport.ts rename to app/src/navigation/passport.ts index b3aa34d1e..609fdbef6 100644 --- a/app/src/Navigation/passport.ts +++ b/app/src/navigation/passport.ts @@ -1,23 +1,18 @@ import { NativeStackNavigationOptions } from '@react-navigation/native-stack'; -import MockDataScreen from '../screens/MockDataScreen'; -import ConfirmBelongingScreen from '../screens/Onboarding/ConfirmBelongingScreen'; -import LoadingScreen from '../screens/Onboarding/LoadingScreen'; -import PassportCameraScreen from '../screens/Onboarding/PassportCameraScreen'; -import PassportCameraTrouble from '../screens/Onboarding/PassportCameraTrouble'; -import PassportNFCScanScreen from '../screens/Onboarding/PassportNFCScanScreen'; -import PassportNFCTrouble from '../screens/Onboarding/PassportNFCTrouble'; -import PassportOnboardingScreen from '../screens/Onboarding/PassportOnboardingScreen'; -import UnsupportedPassportScreen from '../screens/Onboarding/UnsupportedPassport'; -import { black } from '../utils/colors'; +import PassportCameraScreen from '../screens/passport/PassportCameraScreen'; +import PassportCameraTrouble from '../screens/passport/PassportCameraTroubleScreen'; +import PassportNFCScanScreen from '../screens/passport/PassportNFCScanScreen'; +import PassportNFCTrouble from '../screens/passport/PassportNFCTroubleScreen'; +import PassportOnboardingScreen from '../screens/passport/PassportOnboardingScreen'; +import UnsupportedPassportScreen from '../screens/passport/UnsupportedPassportScreen'; const passportScreens = { - PassportOnboarding: { - screen: PassportOnboardingScreen, + PassportCamera: { + screen: PassportCameraScreen, options: { - animation: 'slide_from_bottom', - // presentation: 'modal' wanted to do this but seems to break stuff headerShown: false, + animation: 'slide_from_bottom', } as NativeStackNavigationOptions, }, PassportCameraTrouble: { @@ -28,21 +23,6 @@ const passportScreens = { presentation: 'modal', } as NativeStackNavigationOptions, }, - PassportNFCTrouble: { - screen: PassportNFCTrouble, - options: { - headerShown: false, - animation: 'slide_from_bottom', - presentation: 'modal', - } as NativeStackNavigationOptions, - }, - PassportCamera: { - screen: PassportCameraScreen, - options: { - headerShown: false, - animation: 'slide_from_bottom', - } as NativeStackNavigationOptions, - }, PassportNFCScan: { screen: PassportNFCScanScreen, options: { @@ -55,29 +35,26 @@ const passportScreens = { dateOfExpiry: '', }, }, - ConfirmBelongingScreen: { - screen: ConfirmBelongingScreen, + PassportNFCTrouble: { + screen: PassportNFCTrouble, options: { headerShown: false, + animation: 'slide_from_bottom', + presentation: 'modal', } as NativeStackNavigationOptions, }, - UnsupportedPassport: { - screen: UnsupportedPassportScreen, + PassportOnboarding: { + screen: PassportOnboardingScreen, options: { + animation: 'slide_from_bottom', + // presentation: 'modal' wanted to do this but seems to break stuff headerShown: false, } as NativeStackNavigationOptions, }, - LoadingScreen: { - screen: LoadingScreen, + UnsupportedPassport: { + screen: UnsupportedPassportScreen, options: { headerShown: false, - navigationBarColor: black, - } as NativeStackNavigationOptions, - }, - CreateMock: { - screen: MockDataScreen, - options: { - title: 'Mock Passport', } as NativeStackNavigationOptions, }, }; diff --git a/app/src/Navigation/prove.ts b/app/src/navigation/prove.ts similarity index 63% rename from app/src/Navigation/prove.ts rename to app/src/navigation/prove.ts index e577a0c90..5e2348885 100644 --- a/app/src/Navigation/prove.ts +++ b/app/src/navigation/prove.ts @@ -1,36 +1,32 @@ import { NativeStackNavigationOptions } from '@react-navigation/native-stack'; -import PassportDataNotFound from '../screens/Onboarding/PassportDataNotFound'; -import ProofRequestStatusScreen from '../screens/ProveFlow/ProofRequestStatusScreen'; -import ProveScreen from '../screens/ProveFlow/ProveScreen'; -import QRCodeTroubleScreen from '../screens/ProveFlow/QRCodeTrouble'; -import QRCodeViewFinderScreen from '../screens/ProveFlow/ViewFinder'; +import ConfirmBelongingScreen from '../screens/prove/ConfirmBelongingScreen'; +import ProofRequestStatusScreen from '../screens/prove/ProofRequestStatusScreen'; +import ProveScreen from '../screens/prove/ProveScreen'; +import QRCodeTroubleScreen from '../screens/prove/QRCodeTroubleScreen'; +import QRCodeViewFinderScreen from '../screens/prove/ViewFinderScreen'; +import LoadingScreen from '../screens/static/LoadingScreen'; import { black, white } from '../utils/colors'; const proveScreens = { - QRCodeViewFinder: { - screen: QRCodeViewFinderScreen, + ConfirmBelongingScreen: { + screen: ConfirmBelongingScreen, options: { headerShown: false, - animation: 'slide_from_bottom', - // presentation: 'modal', } as NativeStackNavigationOptions, }, - QRCodeTrouble: { - screen: QRCodeTroubleScreen, + LoadingScreen: { + screen: LoadingScreen, options: { headerShown: false, - animation: 'slide_from_bottom', - presentation: 'modal', + navigationBarColor: black, } as NativeStackNavigationOptions, }, - PassportDataNotFound: { - screen: PassportDataNotFound, + ProofRequestStatusScreen: { + screen: ProofRequestStatusScreen, options: { headerShown: false, - gestureEnabled: false, animation: 'slide_from_bottom', - // presentation: 'modal', } as NativeStackNavigationOptions, }, ProveScreen: { @@ -45,11 +41,20 @@ const proveScreens = { }, } as NativeStackNavigationOptions, }, - ProofRequestStatusScreen: { - screen: ProofRequestStatusScreen, + QRCodeTrouble: { + screen: QRCodeTroubleScreen, + options: { + headerShown: false, + animation: 'slide_from_bottom', + presentation: 'modal', + } as NativeStackNavigationOptions, + }, + QRCodeViewFinder: { + screen: QRCodeViewFinderScreen, options: { headerShown: false, animation: 'slide_from_bottom', + // presentation: 'modal', } as NativeStackNavigationOptions, }, }; diff --git a/app/src/Navigation/recovery.ts b/app/src/navigation/recovery.ts similarity index 61% rename from app/src/Navigation/recovery.ts rename to app/src/navigation/recovery.ts index d7caf1f82..e9ed0c19f 100644 --- a/app/src/Navigation/recovery.ts +++ b/app/src/navigation/recovery.ts @@ -1,10 +1,11 @@ import { NativeStackNavigationOptions } from '@react-navigation/native-stack'; -import AccountRecoveryChoiceScreen from '../screens/AccountFlow/AccountRecoveryChoiceScreen'; -import AccountRecoveryScreen from '../screens/AccountFlow/AccountRecoveryScreen'; -import AccountVerifiedSuccessScreen from '../screens/AccountFlow/AccountVerifiedSuccessScreen'; -import RecoverWithPhraseScreen from '../screens/AccountFlow/RecoverWithPhraseScreen'; -import SaveRecoveryPhraseScreen from '../screens/AccountFlow/SaveRecoveryPhraseScreen'; +import AccountRecoveryChoiceScreen from '../screens/recovery/AccountRecoveryChoiceScreen'; +import AccountRecoveryScreen from '../screens/recovery/AccountRecoveryScreen'; +import AccountVerifiedSuccessScreen from '../screens/recovery/AccountVerifiedSuccessScreen'; +import PassportDataNotFound from '../screens/recovery/PassportDataNotFoundScreen'; +import RecoverWithPhraseScreen from '../screens/recovery/RecoverWithPhraseScreen'; +import SaveRecoveryPhraseScreen from '../screens/recovery/SaveRecoveryPhraseScreen'; import { black, slate300 } from '../utils/colors'; const recoveryScreens = { @@ -20,13 +21,22 @@ const recoveryScreens = { headerShown: false, } as NativeStackNavigationOptions, }, - SaveRecoveryPhrase: { - screen: SaveRecoveryPhraseScreen, + AccountVerifiedSuccess: { + screen: AccountVerifiedSuccessScreen, options: { headerShown: false, animation: 'slide_from_bottom', } as NativeStackNavigationOptions, }, + PassportDataNotFound: { + screen: PassportDataNotFound, + options: { + headerShown: false, + gestureEnabled: false, + animation: 'slide_from_bottom', + // presentation: 'modal', + } as NativeStackNavigationOptions, + }, RecoverWithPhrase: { screen: RecoverWithPhraseScreen, options: { @@ -41,8 +51,8 @@ const recoveryScreens = { headerBackTitle: 'close', } as NativeStackNavigationOptions, }, - AccountVerifiedSuccess: { - screen: AccountVerifiedSuccessScreen, + SaveRecoveryPhrase: { + screen: SaveRecoveryPhraseScreen, options: { headerShown: false, animation: 'slide_from_bottom', diff --git a/app/src/Navigation/settings.ts b/app/src/navigation/settings.ts similarity index 78% rename from app/src/Navigation/settings.ts rename to app/src/navigation/settings.ts index 27a00bf2b..4885371df 100644 --- a/app/src/Navigation/settings.ts +++ b/app/src/navigation/settings.ts @@ -1,37 +1,23 @@ import { NativeStackNavigationOptions } from '@react-navigation/native-stack'; -import ProofHistoryDetailScreen from '../screens/ProofHistoryDetailScreen'; -import ProofHistoryScreen from '../screens/ProofHistoryScreen'; -import CloudBackupScreen from '../screens/Settings/CloudBackupScreen'; -import PassportDataInfoScreen from '../screens/Settings/PassportDataInfoScreen'; -import ShowRecoveryPhraseScreen from '../screens/Settings/ShowRecoveryPhraseScreen'; -import SettingsScreen from '../screens/SettingsScreen'; +import CloudBackupScreen from '../screens/settings/CloudBackupScreen'; +import PassportDataInfoScreen from '../screens/settings/PassportDataInfoScreen'; +import ProofHistoryDetailScreen from '../screens/settings/ProofHistoryDetailScreen'; +import ProofHistoryScreen from '../screens/settings/ProofHistoryScreen'; +import SettingsScreen from '../screens/settings/SettingsScreen'; +import ShowRecoveryPhraseScreen from '../screens/settings/ShowRecoveryPhraseScreen'; import { black, slate300, white } from '../utils/colors'; const settingsScreens = { - Settings: { - screen: SettingsScreen, + CloudBackupSettings: { + screen: CloudBackupScreen, options: { - animation: 'slide_from_bottom', - title: 'Settings', + title: 'Cloud backup', headerStyle: { - backgroundColor: white, + backgroundColor: black, }, headerTitleStyle: { - color: black, - }, - navigationBarColor: black, - } as NativeStackNavigationOptions, - config: { - screens: {}, - }, - }, - ShowRecoveryPhrase: { - screen: ShowRecoveryPhraseScreen, - options: { - title: 'Recovery Phrase', - headerStyle: { - backgroundColor: white, + color: slate300, }, } as NativeStackNavigationOptions, }, @@ -44,18 +30,6 @@ const settingsScreens = { }, } as NativeStackNavigationOptions, }, - CloudBackupSettings: { - screen: CloudBackupScreen, - options: { - title: 'Cloud backup', - headerStyle: { - backgroundColor: black, - }, - headerTitleStyle: { - color: slate300, - }, - } as NativeStackNavigationOptions, - }, ProofHistory: { screen: ProofHistoryScreen, options: { @@ -69,6 +43,32 @@ const settingsScreens = { title: 'Approval', }, }, + Settings: { + screen: SettingsScreen, + options: { + animation: 'slide_from_bottom', + title: 'Settings', + headerStyle: { + backgroundColor: white, + }, + headerTitleStyle: { + color: black, + }, + navigationBarColor: black, + } as NativeStackNavigationOptions, + config: { + screens: {}, + }, + }, + ShowRecoveryPhrase: { + screen: ShowRecoveryPhraseScreen, + options: { + title: 'Recovery Phrase', + headerStyle: { + backgroundColor: white, + }, + } as NativeStackNavigationOptions, + }, }; export default settingsScreens; diff --git a/app/src/Navigation/static.tsx b/app/src/navigation/static.tsx similarity index 81% rename from app/src/Navigation/static.tsx rename to app/src/navigation/static.tsx index b134597ca..6d1613eee 100644 --- a/app/src/Navigation/static.tsx +++ b/app/src/navigation/static.tsx @@ -2,21 +2,12 @@ import { NativeStackNavigationOptions } from '@react-navigation/native-stack'; import React from 'react'; import { StatusBar } from 'react-native'; -import LaunchScreen from '../screens/LaunchScreen'; -import ModalScreen from '../screens/Settings/ModalScreen'; -import SplashScreen from '../screens/SplashScreen'; +import LaunchScreen from '../screens/static/LaunchScreen'; +import ModalScreen from '../screens/static/ModalScreen'; +import SplashScreen from '../screens/static/SplashScreen'; import { black } from '../utils/colors'; const staticScreens = { - Splash: { - screen: SplashScreen, - options: { - header: () => ( - - ), - navigationBarColor: black, - }, - }, Launch: { screen: LaunchScreen, options: { @@ -32,6 +23,15 @@ const staticScreens = { animation: 'fade', } as NativeStackNavigationOptions, }, + Splash: { + screen: SplashScreen, + options: { + header: () => ( + + ), + navigationBarColor: black, + }, + }, }; export default staticScreens; diff --git a/app/src/screens/_Aesop/PassportOnboardingScreen.tsx b/app/src/screens/aesop/PassportOnboardingScreen.tsx similarity index 100% rename from app/src/screens/_Aesop/PassportOnboardingScreen.tsx rename to app/src/screens/aesop/PassportOnboardingScreen.tsx diff --git a/app/src/screens/Settings/DevHapticFeedback.tsx b/app/src/screens/dev/DevHapticFeedback.tsx similarity index 100% rename from app/src/screens/Settings/DevHapticFeedback.tsx rename to app/src/screens/dev/DevHapticFeedback.tsx diff --git a/app/src/screens/Settings/DevSettingsScreen.tsx b/app/src/screens/dev/DevSettingsScreen.tsx similarity index 100% rename from app/src/screens/Settings/DevSettingsScreen.tsx rename to app/src/screens/dev/DevSettingsScreen.tsx diff --git a/app/src/screens/MockDataScreen.tsx b/app/src/screens/dev/MockDataScreen.tsx similarity index 94% rename from app/src/screens/MockDataScreen.tsx rename to app/src/screens/dev/MockDataScreen.tsx index 522cdd08e..bf186e8bd 100644 --- a/app/src/screens/MockDataScreen.tsx +++ b/app/src/screens/dev/MockDataScreen.tsx @@ -18,18 +18,23 @@ import { YStack, } from 'tamagui'; -import { countryCodes } from '../../../common/src/constants/constants'; -import { getSKIPEM } from '../../../common/src/utils/csca'; -import { genAndInitMockPassportData } from '../../../common/src/utils/passports/genMockPassportData'; -import { initPassportDataParsing } from '../../../common/src/utils/passports/passport'; -import { PrimaryButton } from '../components/buttons/PrimaryButton'; -import { SecondaryButton } from '../components/buttons/SecondaryButton'; -import ButtonsContainer from '../components/ButtonsContainer'; -import { BodyText } from '../components/typography/BodyText'; -import { Title } from '../components/typography/Title'; -import { storePassportData } from '../stores/passportDataProvider'; -import { borderColor, separatorColor, textBlack, white } from '../utils/colors'; -import { buttonTap, selectionChange } from '../utils/haptic'; +import { getSKIPEM } from '../../../.././common/src/utils/csca'; +import { countryCodes } from '../../../../common/src/constants/constants'; +import { genAndInitMockPassportData } from '../../../../common/src/utils/passports/genMockPassportData'; +import { initPassportDataParsing } from '../../../../common/src/utils/passports/passport'; +import { PrimaryButton } from '../../components/buttons/PrimaryButton'; +import { SecondaryButton } from '../../components/buttons/SecondaryButton'; +import ButtonsContainer from '../../components/ButtonsContainer'; +import { BodyText } from '../../components/typography/BodyText'; +import { Title } from '../../components/typography/Title'; +import { storePassportData } from '../../stores/passportDataProvider'; +import { + borderColor, + separatorColor, + textBlack, + white, +} from '../../utils/colors'; +import { buttonTap, selectionChange } from '../../utils/haptic'; interface MockDataScreenProps {} diff --git a/app/src/screens/DisclaimerScreen.tsx b/app/src/screens/home/DisclaimerScreen.tsx similarity index 79% rename from app/src/screens/DisclaimerScreen.tsx rename to app/src/screens/home/DisclaimerScreen.tsx index d3ec4ea4d..8e8e17849 100644 --- a/app/src/screens/DisclaimerScreen.tsx +++ b/app/src/screens/home/DisclaimerScreen.tsx @@ -4,14 +4,14 @@ import React, { useEffect } from 'react'; import { StyleSheet } from 'react-native'; import { YStack } from 'tamagui'; -import warningAnimation from '../assets/animations/warning.json'; -import { PrimaryButton } from '../components/buttons/PrimaryButton'; -import Caution from '../components/typography/Caution'; -import { SubHeader } from '../components/typography/SubHeader'; -import { ExpandableBottomLayout } from '../layouts/ExpandableBottomLayout'; -import { useSettingStore } from '../stores/settingStore'; -import { black, white } from '../utils/colors'; -import { confirmTap, notificationWarning } from '../utils/haptic'; +import warningAnimation from '../../assets/animations/warning.json'; +import { PrimaryButton } from '../../components/buttons/PrimaryButton'; +import Caution from '../../components/typography/Caution'; +import { SubHeader } from '../../components/typography/SubHeader'; +import { ExpandableBottomLayout } from '../../layouts/ExpandableBottomLayout'; +import { useSettingStore } from '../../stores/settingStore'; +import { black, white } from '../../utils/colors'; +import { confirmTap, notificationWarning } from '../../utils/haptic'; const DisclaimerScreen: React.FC = () => { const navigation = useNavigation(); diff --git a/app/src/screens/HomeScreen.tsx b/app/src/screens/home/HomeScreen.tsx similarity index 79% rename from app/src/screens/HomeScreen.tsx rename to app/src/screens/home/HomeScreen.tsx index 2be93bf1f..36fd9bb25 100644 --- a/app/src/screens/HomeScreen.tsx +++ b/app/src/screens/home/HomeScreen.tsx @@ -3,17 +3,23 @@ import React from 'react'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { Button, styled, YStack } from 'tamagui'; -import { pressedStyle } from '../components/buttons/pressedStyle'; -import { BodyText } from '../components/typography/BodyText'; -import { Caption } from '../components/typography/Caption'; -import { useAppUpdates } from '../hooks/useAppUpdates'; -import useConnectionModal from '../hooks/useConnectionModal'; -import useHapticNavigation from '../hooks/useHapticNavigation'; -import SelfCard from '../images/card-style-1.svg'; -import ScanIcon from '../images/icons/qr_scan.svg'; -import WarnIcon from '../images/icons/warning.svg'; -import { useSettingStore } from '../stores/settingStore'; -import { amber500, black, neutral700, slate800, white } from '../utils/colors'; +import { pressedStyle } from '../../components/buttons/pressedStyle'; +import { BodyText } from '../../components/typography/BodyText'; +import { Caption } from '../../components/typography/Caption'; +import { useAppUpdates } from '../../hooks/useAppUpdates'; +import useConnectionModal from '../../hooks/useConnectionModal'; +import useHapticNavigation from '../../hooks/useHapticNavigation'; +import SelfCard from '../../images/card-style-1.svg'; +import ScanIcon from '../../images/icons/qr_scan.svg'; +import WarnIcon from '../../images/icons/warning.svg'; +import { useSettingStore } from '../../stores/settingStore'; +import { + amber500, + black, + neutral700, + slate800, + white, +} from '../../utils/colors'; const ScanButton = styled(Button, { borderRadius: 20, diff --git a/app/src/screens/Onboarding/PassportCameraScreen.tsx b/app/src/screens/passport/PassportCameraScreen.tsx similarity index 100% rename from app/src/screens/Onboarding/PassportCameraScreen.tsx rename to app/src/screens/passport/PassportCameraScreen.tsx diff --git a/app/src/screens/Onboarding/PassportCameraTrouble.tsx b/app/src/screens/passport/PassportCameraTroubleScreen.tsx similarity index 100% rename from app/src/screens/Onboarding/PassportCameraTrouble.tsx rename to app/src/screens/passport/PassportCameraTroubleScreen.tsx diff --git a/app/src/screens/Onboarding/PassportNFCScanScreen.tsx b/app/src/screens/passport/PassportNFCScanScreen.tsx similarity index 99% rename from app/src/screens/Onboarding/PassportNFCScanScreen.tsx rename to app/src/screens/passport/PassportNFCScanScreen.tsx index f4b8a50af..a0e70e309 100644 --- a/app/src/screens/Onboarding/PassportNFCScanScreen.tsx +++ b/app/src/screens/passport/PassportNFCScanScreen.tsx @@ -30,7 +30,7 @@ import useUserStore from '../../stores/userStore'; import analytics from '../../utils/analytics'; import { black, slate100, white } from '../../utils/colors'; import { buttonTap } from '../../utils/haptic'; -import { parseScanResponse, scan } from '../../utils/nfcScannerNew'; +import { parseScanResponse, scan } from '../../utils/nfcScanner'; const { trackEvent } = analytics(); diff --git a/app/src/screens/Onboarding/PassportNFCTrouble.tsx b/app/src/screens/passport/PassportNFCTroubleScreen.tsx similarity index 100% rename from app/src/screens/Onboarding/PassportNFCTrouble.tsx rename to app/src/screens/passport/PassportNFCTroubleScreen.tsx diff --git a/app/src/screens/Onboarding/PassportOnboardingScreen.tsx b/app/src/screens/passport/PassportOnboardingScreen.tsx similarity index 100% rename from app/src/screens/Onboarding/PassportOnboardingScreen.tsx rename to app/src/screens/passport/PassportOnboardingScreen.tsx diff --git a/app/src/screens/Onboarding/UnsupportedPassport.tsx b/app/src/screens/passport/UnsupportedPassportScreen.tsx similarity index 96% rename from app/src/screens/Onboarding/UnsupportedPassport.tsx rename to app/src/screens/passport/UnsupportedPassportScreen.tsx index ae7ae6cd5..14dc47b4e 100644 --- a/app/src/screens/Onboarding/UnsupportedPassport.tsx +++ b/app/src/screens/passport/UnsupportedPassportScreen.tsx @@ -10,7 +10,7 @@ import useHapticNavigation from '../../hooks/useHapticNavigation'; import { ExpandableBottomLayout } from '../../layouts/ExpandableBottomLayout'; import { black, white } from '../../utils/colors'; import { notificationError } from '../../utils/haptic'; -import { styles } from '../ProveFlow/ProofRequestStatusScreen'; +import { styles } from '../prove/ProofRequestStatusScreen'; const UnsupportedPassportScreen: React.FC = () => { const onPress = useHapticNavigation('Launch'); diff --git a/app/src/screens/Onboarding/ConfirmBelongingScreen.tsx b/app/src/screens/prove/ConfirmBelongingScreen.tsx similarity index 98% rename from app/src/screens/Onboarding/ConfirmBelongingScreen.tsx rename to app/src/screens/prove/ConfirmBelongingScreen.tsx index eea31ecbb..6c0a21dfd 100644 --- a/app/src/screens/Onboarding/ConfirmBelongingScreen.tsx +++ b/app/src/screens/prove/ConfirmBelongingScreen.tsx @@ -12,7 +12,7 @@ import { ExpandableBottomLayout } from '../../layouts/ExpandableBottomLayout'; import { black, white } from '../../utils/colors'; import { notificationSuccess } from '../../utils/haptic'; import { useProvingStore } from '../../utils/proving/provingMachine'; -import { styles } from '../ProveFlow/ProofRequestStatusScreen'; +import { styles } from './ProofRequestStatusScreen'; type ConfirmBelongingScreenProps = StaticScreenProps< | { diff --git a/app/src/screens/ProveFlow/ProofRequestStatusScreen.tsx b/app/src/screens/prove/ProofRequestStatusScreen.tsx similarity index 100% rename from app/src/screens/ProveFlow/ProofRequestStatusScreen.tsx rename to app/src/screens/prove/ProofRequestStatusScreen.tsx diff --git a/app/src/screens/ProveFlow/ProveScreen.tsx b/app/src/screens/prove/ProveScreen.tsx similarity index 100% rename from app/src/screens/ProveFlow/ProveScreen.tsx rename to app/src/screens/prove/ProveScreen.tsx diff --git a/app/src/screens/ProveFlow/QRCodeTrouble.tsx b/app/src/screens/prove/QRCodeTroubleScreen.tsx similarity index 100% rename from app/src/screens/ProveFlow/QRCodeTrouble.tsx rename to app/src/screens/prove/QRCodeTroubleScreen.tsx diff --git a/app/src/screens/ProveFlow/ViewFinder.tsx b/app/src/screens/prove/ViewFinderScreen.tsx similarity index 100% rename from app/src/screens/ProveFlow/ViewFinder.tsx rename to app/src/screens/prove/ViewFinderScreen.tsx diff --git a/app/src/screens/AccountFlow/AccountRecoveryChoiceScreen.tsx b/app/src/screens/recovery/AccountRecoveryChoiceScreen.tsx similarity index 100% rename from app/src/screens/AccountFlow/AccountRecoveryChoiceScreen.tsx rename to app/src/screens/recovery/AccountRecoveryChoiceScreen.tsx diff --git a/app/src/screens/AccountFlow/AccountRecoveryScreen.tsx b/app/src/screens/recovery/AccountRecoveryScreen.tsx similarity index 100% rename from app/src/screens/AccountFlow/AccountRecoveryScreen.tsx rename to app/src/screens/recovery/AccountRecoveryScreen.tsx diff --git a/app/src/screens/AccountFlow/AccountVerifiedSuccessScreen.tsx b/app/src/screens/recovery/AccountVerifiedSuccessScreen.tsx similarity index 96% rename from app/src/screens/AccountFlow/AccountVerifiedSuccessScreen.tsx rename to app/src/screens/recovery/AccountVerifiedSuccessScreen.tsx index 9f92e8fa4..37d69b6f2 100644 --- a/app/src/screens/AccountFlow/AccountVerifiedSuccessScreen.tsx +++ b/app/src/screens/recovery/AccountVerifiedSuccessScreen.tsx @@ -10,7 +10,7 @@ import { Title } from '../../components/typography/Title'; import { ExpandableBottomLayout } from '../../layouts/ExpandableBottomLayout'; import { black, white } from '../../utils/colors'; import { buttonTap } from '../../utils/haptic'; -import { styles } from '../ProveFlow/ProofRequestStatusScreen'; +import { styles } from '../prove/ProofRequestStatusScreen'; const AccountVerifiedSuccessScreen: React.FC = ({}) => { const navigation = useNavigation(); diff --git a/app/src/screens/Onboarding/PassportDataNotFound.tsx b/app/src/screens/recovery/PassportDataNotFoundScreen.tsx similarity index 100% rename from app/src/screens/Onboarding/PassportDataNotFound.tsx rename to app/src/screens/recovery/PassportDataNotFoundScreen.tsx diff --git a/app/src/screens/AccountFlow/RecoverWithPhraseScreen.tsx b/app/src/screens/recovery/RecoverWithPhraseScreen.tsx similarity index 100% rename from app/src/screens/AccountFlow/RecoverWithPhraseScreen.tsx rename to app/src/screens/recovery/RecoverWithPhraseScreen.tsx diff --git a/app/src/screens/AccountFlow/SaveRecoveryPhraseScreen.tsx b/app/src/screens/recovery/SaveRecoveryPhraseScreen.tsx similarity index 100% rename from app/src/screens/AccountFlow/SaveRecoveryPhraseScreen.tsx rename to app/src/screens/recovery/SaveRecoveryPhraseScreen.tsx diff --git a/app/src/screens/Settings/CloudBackupScreen.tsx b/app/src/screens/settings/CloudBackupScreen.tsx similarity index 100% rename from app/src/screens/Settings/CloudBackupScreen.tsx rename to app/src/screens/settings/CloudBackupScreen.tsx diff --git a/app/src/screens/Settings/PassportDataInfoScreen.tsx b/app/src/screens/settings/PassportDataInfoScreen.tsx similarity index 100% rename from app/src/screens/Settings/PassportDataInfoScreen.tsx rename to app/src/screens/settings/PassportDataInfoScreen.tsx diff --git a/app/src/screens/ProofHistoryDetailScreen.tsx b/app/src/screens/settings/ProofHistoryDetailScreen.tsx similarity index 98% rename from app/src/screens/ProofHistoryDetailScreen.tsx rename to app/src/screens/settings/ProofHistoryDetailScreen.tsx index 86c4754dc..7837daf0a 100644 --- a/app/src/screens/ProofHistoryDetailScreen.tsx +++ b/app/src/screens/settings/ProofHistoryDetailScreen.tsx @@ -3,7 +3,7 @@ import React, { useMemo } from 'react'; import { ScrollView, StyleSheet } from 'react-native'; import { Card, Image, Text, XStack, YStack } from 'tamagui'; -import { ProofHistory, ProofStatus } from '../stores/proofHistoryStore'; +import { ProofHistory, ProofStatus } from '../../stores/proofHistoryStore'; import { black, blue100, @@ -15,7 +15,7 @@ import { slate700, white, zinc400, -} from '../utils/colors'; +} from '../../utils/colors'; type ProofHistoryDetailScreenProps = { route: { diff --git a/app/src/screens/ProofHistoryScreen.tsx b/app/src/screens/settings/ProofHistoryScreen.tsx similarity index 98% rename from app/src/screens/ProofHistoryScreen.tsx rename to app/src/screens/settings/ProofHistoryScreen.tsx index c082fc244..1e77ae869 100644 --- a/app/src/screens/ProofHistoryScreen.tsx +++ b/app/src/screens/settings/ProofHistoryScreen.tsx @@ -9,11 +9,11 @@ import { } from 'react-native'; import { Card, Image, Text, View, XStack, YStack } from 'tamagui'; -import { BodyText } from '../components/typography/BodyText'; +import { BodyText } from '../../components/typography/BodyText'; import { ProofHistory, useProofHistoryStore, -} from '../stores/proofHistoryStore'; +} from '../../stores/proofHistoryStore'; import { black, blue100, @@ -22,7 +22,7 @@ import { slate300, slate500, white, -} from '../utils/colors'; +} from '../../utils/colors'; type Section = { title: string; diff --git a/app/src/screens/SettingsScreen.tsx b/app/src/screens/settings/SettingsScreen.tsx similarity index 87% rename from app/src/screens/SettingsScreen.tsx rename to app/src/screens/settings/SettingsScreen.tsx index 036396023..9f9ee6b79 100644 --- a/app/src/screens/SettingsScreen.tsx +++ b/app/src/screens/settings/SettingsScreen.tsx @@ -8,29 +8,35 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { SvgProps } from 'react-native-svg'; import { Button, ScrollView, View, XStack, YStack } from 'tamagui'; -import { version } from '../../package.json'; -import { pressedStyle } from '../components/buttons/pressedStyle'; -import { BodyText } from '../components/typography/BodyText'; +import { version } from '../../../package.json'; +import { pressedStyle } from '../../components/buttons/pressedStyle'; +import { BodyText } from '../../components/typography/BodyText'; import { appStoreUrl, gitHubUrl, playStoreUrl, selfUrl, telegramUrl, -} from '../consts/links'; -import Github from '../images/icons/github.svg'; -import Cloud from '../images/icons/settings_cloud_backup.svg'; -import Data from '../images/icons/settings_data.svg'; -import Feedback from '../images/icons/settings_feedback.svg'; -import Lock from '../images/icons/settings_lock.svg'; -import ShareIcon from '../images/icons/share.svg'; -import Star from '../images/icons/star.svg'; -import Telegram from '../images/icons/telegram.svg'; -import Web from '../images/icons/webpage.svg'; -import { RootStackParamList } from '../Navigation'; -import { useSettingStore } from '../stores/settingStore'; -import { amber500, black, neutral700, slate800, white } from '../utils/colors'; -import { impactLight } from '../utils/haptic'; +} from '../../consts/links'; +import Github from '../../images/icons/github.svg'; +import Cloud from '../../images/icons/settings_cloud_backup.svg'; +import Data from '../../images/icons/settings_data.svg'; +import Feedback from '../../images/icons/settings_feedback.svg'; +import Lock from '../../images/icons/settings_lock.svg'; +import ShareIcon from '../../images/icons/share.svg'; +import Star from '../../images/icons/star.svg'; +import Telegram from '../../images/icons/telegram.svg'; +import Web from '../../images/icons/webpage.svg'; +import { RootStackParamList } from '../../Navigation'; +import { useSettingStore } from '../../stores/settingStore'; +import { + amber500, + black, + neutral700, + slate800, + white, +} from '../../utils/colors'; +import { impactLight } from '../../utils/haptic'; interface SettingsScreenProps {} interface MenuButtonProps extends PropsWithChildren { diff --git a/app/src/screens/Settings/ShowRecoveryPhraseScreen.tsx b/app/src/screens/settings/ShowRecoveryPhraseScreen.tsx similarity index 100% rename from app/src/screens/Settings/ShowRecoveryPhraseScreen.tsx rename to app/src/screens/settings/ShowRecoveryPhraseScreen.tsx diff --git a/app/src/screens/LaunchScreen.tsx b/app/src/screens/static/LaunchScreen.tsx similarity index 84% rename from app/src/screens/LaunchScreen.tsx rename to app/src/screens/static/LaunchScreen.tsx index a5faf4cf4..e4b19c0c5 100644 --- a/app/src/screens/LaunchScreen.tsx +++ b/app/src/screens/static/LaunchScreen.tsx @@ -5,17 +5,17 @@ import { Gesture, GestureDetector } from 'react-native-gesture-handler'; import { Anchor, Text, XStack, YStack } from 'tamagui'; import { useWindowDimensions } from 'tamagui'; -import onboardingAnimation from '../assets/animations/launch_onboarding.json'; -import { PrimaryButton } from '../components/buttons/PrimaryButton'; -import { BodyText } from '../components/typography/BodyText'; -import { Caption } from '../components/typography/Caption'; -import { privacyUrl, termsUrl } from '../consts/links'; -import useConnectionModal from '../hooks/useConnectionModal'; -import useHapticNavigation from '../hooks/useHapticNavigation'; -import Logo from '../images/logo.svg'; -import { ExpandableBottomLayout } from '../layouts/ExpandableBottomLayout'; -import { black, slate50, slate100, slate500, white } from '../utils/colors'; -import { advercase, dinot } from '../utils/fonts'; +import onboardingAnimation from '../../assets/animations/launch_onboarding.json'; +import { PrimaryButton } from '../../components/buttons/PrimaryButton'; +import { BodyText } from '../../components/typography/BodyText'; +import { Caption } from '../../components/typography/Caption'; +import { privacyUrl, termsUrl } from '../../consts/links'; +import useConnectionModal from '../../hooks/useConnectionModal'; +import useHapticNavigation from '../../hooks/useHapticNavigation'; +import Logo from '../../images/logo.svg'; +import { ExpandableBottomLayout } from '../../layouts/ExpandableBottomLayout'; +import { black, slate50, slate100, slate500, white } from '../../utils/colors'; +import { advercase, dinot } from '../../utils/fonts'; interface LaunchScreenProps {} diff --git a/app/src/screens/Onboarding/LoadingScreen.tsx b/app/src/screens/static/LoadingScreen.tsx similarity index 100% rename from app/src/screens/Onboarding/LoadingScreen.tsx rename to app/src/screens/static/LoadingScreen.tsx diff --git a/app/src/screens/Settings/ModalScreen.tsx b/app/src/screens/static/ModalScreen.tsx similarity index 100% rename from app/src/screens/Settings/ModalScreen.tsx rename to app/src/screens/static/ModalScreen.tsx diff --git a/app/src/screens/SplashScreen.tsx b/app/src/screens/static/SplashScreen.tsx similarity index 87% rename from app/src/screens/SplashScreen.tsx rename to app/src/screens/static/SplashScreen.tsx index 649579e52..d9bbc5ee4 100644 --- a/app/src/screens/SplashScreen.tsx +++ b/app/src/screens/static/SplashScreen.tsx @@ -3,15 +3,15 @@ import LottieView from 'lottie-react-native'; import React, { useCallback, useEffect, useRef } from 'react'; import { StyleSheet } from 'react-native'; -import { PassportData } from '../../../common/src/utils/types'; -import splashAnimation from '../assets/animations/splash.json'; -import { useAuth } from '../stores/authProvider'; -import { loadPassportDataAndSecret } from '../stores/passportDataProvider'; -import { useProtocolStore } from '../stores/protocolStore'; -import { useSettingStore } from '../stores/settingStore'; -import { black } from '../utils/colors'; -import { impactLight } from '../utils/haptic'; -import { isUserRegistered } from '../utils/proving/validateDocument'; +import { PassportData } from '../../../../common/src/utils/types'; +import splashAnimation from '../../assets/animations/splash.json'; +import { useAuth } from '../../stores/authProvider'; +import { loadPassportDataAndSecret } from '../../stores/passportDataProvider'; +import { useProtocolStore } from '../../stores/protocolStore'; +import { useSettingStore } from '../../stores/settingStore'; +import { black } from '../../utils/colors'; +import { impactLight } from '../../utils/haptic'; +import { isUserRegistered } from '../../utils/proving/validateDocument'; const SplashScreen: React.FC = ({}) => { const navigation = useNavigation(); diff --git a/app/src/utils/deeplinks.ts b/app/src/utils/deeplinks.ts index f09c47fb6..98f0093f9 100644 --- a/app/src/utils/deeplinks.ts +++ b/app/src/utils/deeplinks.ts @@ -1,7 +1,7 @@ import queryString from 'query-string'; import { Linking } from 'react-native'; -import { navigationRef } from '../Navigation'; +import { navigationRef } from '../navigation'; import { useSelfAppStore } from '../stores/selfAppStore'; /** diff --git a/app/src/utils/nfcScannerNew.ts b/app/src/utils/nfcScanner.ts similarity index 100% rename from app/src/utils/nfcScannerNew.ts rename to app/src/utils/nfcScanner.ts diff --git a/app/src/utils/proving/provingMachine.ts b/app/src/utils/proving/provingMachine.ts index f34072377..331bca070 100644 --- a/app/src/utils/proving/provingMachine.ts +++ b/app/src/utils/proving/provingMachine.ts @@ -7,7 +7,7 @@ import { create } from 'zustand'; import { WS_RPC_URL_VC_AND_DISCLOSE } from '../../../../common/src/constants/constants'; import { EndpointType, SelfApp } from '../../../../common/src/utils/appType'; import { getCircuitNameFromPassportData } from '../../../../common/src/utils/circuits/circuitsName'; -import { navigationRef } from '../../Navigation'; +import { navigationRef } from '../../navigation'; import { clearPassportData, loadPassportDataAndSecret, diff --git a/app/tests/__setup__/@env.js b/app/tests/__setup__/@env.js new file mode 100644 index 000000000..4ce881d1f --- /dev/null +++ b/app/tests/__setup__/@env.js @@ -0,0 +1 @@ +export const IS_TEST_BUILD = 'false'; diff --git a/app/tests/src/hooks/useAesopRedesign.test.ts b/app/tests/src/hooks/useAesopRedesign.test.ts new file mode 100644 index 000000000..04252303b --- /dev/null +++ b/app/tests/src/hooks/useAesopRedesign.test.ts @@ -0,0 +1,21 @@ +import { renderHook } from '@testing-library/react-native'; + +import { + shouldShowAesopRedesign, + useAesopRedesign, +} from '../../../src/hooks/useAesopRedesign'; + +describe('useAesopRedesign', () => { + describe('shouldShowAesopRedesign', () => { + it('should return false when IS_TEST_BUILD is false', () => { + expect(shouldShowAesopRedesign()).toBe(false); + }); + }); + + describe('useAesopRedesign hook', () => { + it('should return the same value as shouldShowAesopRedesign', () => { + const { result } = renderHook(() => useAesopRedesign()); + expect(result.current).toBe(shouldShowAesopRedesign()); + }); + }); +}); diff --git a/app/tests/src/navigation.test.ts b/app/tests/src/navigation.test.ts new file mode 100644 index 000000000..50600cb26 --- /dev/null +++ b/app/tests/src/navigation.test.ts @@ -0,0 +1,64 @@ +describe('navigation', () => { + it('should have the correct navigation screens', () => { + const navigationScreens = require('../../src/navigation').navigationScreens; + const listOfScreens = Object.keys(navigationScreens).sort(); + expect(listOfScreens).toEqual([ + 'AccountRecovery', + 'AccountRecoveryChoice', + 'AccountVerifiedSuccess', + 'CloudBackupSettings', + 'ConfirmBelongingScreen', + 'CreateMock', + 'DevHapticFeedback', + 'DevSettings', + 'Disclaimer', + 'Home', + 'Launch', + 'LoadingScreen', + 'Modal', + 'PassportCamera', + 'PassportCameraTrouble', + 'PassportDataInfo', + 'PassportDataNotFound', + 'PassportNFCScan', + 'PassportNFCTrouble', + 'PassportOnboarding', + 'ProofHistory', + 'ProofHistoryDetail', + 'ProofRequestStatusScreen', + 'ProveScreen', + 'QRCodeTrouble', + 'QRCodeViewFinder', + 'RecoverWithPhrase', + 'SaveRecoveryPhrase', + 'Settings', + 'ShowRecoveryPhrase', + 'Splash', + 'UnsupportedPassport', + ]); + }); + + describe('Aesop design screen overrides', () => { + beforeEach(() => { + jest.resetModules(); + }); + + it('should use regular passport screens when shouldShowAesopRedesign is false', () => { + const navigationScreens = + require('../../src/navigation').navigationScreens; + expect( + navigationScreens.PassportOnboarding.options.title, + ).toBeUndefined(); + }); + + it('should use aesop design passport screens when shouldShowAesopRedesign is true', () => { + jest.mock('../../src/hooks/useAesopRedesign', () => ({ + shouldShowAesopRedesign: jest.fn().mockReturnValue(true), + })); + + const navigationScreens = + require('../../src/navigation').navigationScreens; + expect(navigationScreens.PassportOnboarding.options.title).toBeDefined(); + }); + }); +}); diff --git a/app/yarn.lock b/app/yarn.lock index 92834d162..2c2acdbec 100644 --- a/app/yarn.lock +++ b/app/yarn.lock @@ -1019,6 +1019,13 @@ __metadata: languageName: node linkType: hard +"@babel/runtime@npm:^7.12.5": + version: 7.27.1 + resolution: "@babel/runtime@npm:7.27.1" + checksum: 10c0/530a7332f86ac5a7442250456823a930906911d895c0b743bf1852efc88a20a016ed4cd26d442d0ca40ae6d5448111e02a08dd638a4f1064b47d080e2875dc05 + languageName: node + linkType: hard + "@babel/runtime@npm:^7.25.0, @babel/runtime@npm:^7.8.4": version: 7.26.9 resolution: "@babel/runtime@npm:7.26.9" @@ -5797,6 +5804,48 @@ __metadata: languageName: node linkType: hard +"@testing-library/react-hooks@npm:^8.0.1": + version: 8.0.1 + resolution: "@testing-library/react-hooks@npm:8.0.1" + dependencies: + "@babel/runtime": "npm:^7.12.5" + react-error-boundary: "npm:^3.1.0" + peerDependencies: + "@types/react": ^16.9.0 || ^17.0.0 + react: ^16.9.0 || ^17.0.0 + react-dom: ^16.9.0 || ^17.0.0 + react-test-renderer: ^16.9.0 || ^17.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + react-dom: + optional: true + react-test-renderer: + optional: true + checksum: 10c0/83bef2d4c437b84143213b5275ef00ef14e5bcd344f9ded12b162d253dc3c799138ead4428026b9c725e5a38dbebf611f2898aa43f3e43432bcaccbd7bf413e5 + languageName: node + linkType: hard + +"@testing-library/react-native@npm:^13.2.0": + version: 13.2.0 + resolution: "@testing-library/react-native@npm:13.2.0" + dependencies: + chalk: "npm:^4.1.2" + jest-matcher-utils: "npm:^29.7.0" + pretty-format: "npm:^29.7.0" + redent: "npm:^3.0.0" + peerDependencies: + jest: ">=29.0.0" + react: ">=18.2.0" + react-native: ">=0.71" + react-test-renderer: ">=18.2.0" + peerDependenciesMeta: + jest: + optional: true + checksum: 10c0/5ed8e09f82f45c057f12a716008f31abf934e6a3d84955540e2ab96d7534c82b9afdb0af050e986d8b63ae9dd8272f8a752c45ecb847a11e7549f30de3d84427 + languageName: node + linkType: hard + "@trysound/sax@npm:0.2.0": version: 0.2.0 resolution: "@trysound/sax@npm:0.2.0" @@ -6008,6 +6057,25 @@ __metadata: languageName: node linkType: hard +"@types/react-test-renderer@npm:^18": + version: 18.3.1 + resolution: "@types/react-test-renderer@npm:18.3.1" + dependencies: + "@types/react": "npm:^18" + checksum: 10c0/9fc8467ff1a3f14be6cc3498a75fc788d2c92c0fffa7bf21269ed5d9d82db9195bf2178ddc42ea16a0836995c1b77601c6be8abb27bd1864668c418c6d0e5a3b + languageName: node + linkType: hard + +"@types/react@npm:^18": + version: 18.3.21 + resolution: "@types/react@npm:18.3.21" + dependencies: + "@types/prop-types": "npm:*" + csstype: "npm:^3.0.2" + checksum: 10c0/b33424c62f01ab2404c60abef995e05aa1a696a636bdd77a34ef6c942d171c673b1e451d9dba7f9a169a83c9eef0ddfaf1ba08f6cef542df9404290199a73967 + languageName: node + linkType: hard + "@types/react@npm:^18.2.6": version: 18.3.18 resolution: "@types/react@npm:18.3.18" @@ -9345,6 +9413,13 @@ __metadata: languageName: node linkType: hard +"indent-string@npm:^4.0.0": + version: 4.0.0 + resolution: "indent-string@npm:4.0.0" + checksum: 10c0/1e1904ddb0cb3d6cce7cd09e27a90184908b7a5d5c21b92e232c93579d314f0b83c246ffb035493d0504b1e9147ba2c9b21df0030f48673fba0496ecd698161f + languageName: node + linkType: hard + "inflight@npm:^1.0.4": version: 1.0.6 resolution: "inflight@npm:1.0.6" @@ -11381,6 +11456,13 @@ __metadata: languageName: node linkType: hard +"min-indent@npm:^1.0.0": + version: 1.0.1 + resolution: "min-indent@npm:1.0.1" + checksum: 10c0/7e207bd5c20401b292de291f02913230cb1163abca162044f7db1d951fa245b174dc00869d40dd9a9f32a885ad6a5f3e767ee104cf278f399cb4e92d3f582d5c + languageName: node + linkType: hard + "minimalistic-assert@npm:^1.0.0, minimalistic-assert@npm:^1.0.1": version: 1.0.1 resolution: "minimalistic-assert@npm:1.0.1" @@ -11935,6 +12017,8 @@ __metadata: "@tamagui/lucide-icons": "npm:1.110.0" "@tamagui/toast": "npm:1.110.0" "@tamagui/types": "npm:1.110.0" + "@testing-library/react-hooks": "npm:^8.0.1" + "@testing-library/react-native": "npm:^13.2.0" "@tsconfig/react-native": "npm:^3.0.0" "@types/add": "npm:^2" "@types/elliptic": "npm:^6" @@ -11946,6 +12030,7 @@ __metadata: "@types/react-native": "npm:^0.73.0" "@types/react-native-dotenv": "npm:^0.2.0" "@types/react-native-sqlite-storage": "npm:^6.0.5" + "@types/react-test-renderer": "npm:^18" "@xstate/react": "npm:^5.0.3" add: "npm:^2.0.6" asn1js: "npm:^3.0.5" @@ -11989,6 +12074,7 @@ __metadata: react-native-sqlite-storage: "npm:^6.0.1" react-native-svg: "npm:^15.11.1" react-native-svg-transformer: "npm:^1.5.0" + react-test-renderer: "npm:^18.3.1" socket.io-client: "npm:^4.7.5" stream-browserify: "npm:^3.0.0" tamagui: "npm:1.110.0" @@ -12500,6 +12586,17 @@ __metadata: languageName: node linkType: hard +"react-error-boundary@npm:^3.1.0": + version: 3.1.4 + resolution: "react-error-boundary@npm:3.1.4" + dependencies: + "@babel/runtime": "npm:^7.12.5" + peerDependencies: + react: ">=16.13.1" + checksum: 10c0/f977ca61823e43de2381d53dd7aa8b4d79ff6a984c9afdc88dc44f9973b99de7fd382d2f0f91f2688e24bb987c0185bf45d0b004f22afaaab0f990a830253bfb + languageName: node + linkType: hard + "react-freeze@npm:^1.0.0, react-freeze@npm:^1.0.3": version: 1.0.4 resolution: "react-freeze@npm:1.0.4" @@ -12509,6 +12606,13 @@ __metadata: languageName: node linkType: hard +"react-is@npm:^16.12.0 || ^17.0.0 || ^18.0.0, react-is@npm:^18.0.0, react-is@npm:^18.2.0, react-is@npm:^18.3.1": + version: 18.3.1 + resolution: "react-is@npm:18.3.1" + checksum: 10c0/f2f1e60010c683479e74c63f96b09fb41603527cd131a9959e2aee1e5a8b0caf270b365e5ca77d4a6b18aae659b60a86150bb3979073528877029b35aecd2072 + languageName: node + linkType: hard + "react-is@npm:^16.13.1, react-is@npm:^16.7.0": version: 16.13.1 resolution: "react-is@npm:16.13.1" @@ -12523,13 +12627,6 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^18.0.0, react-is@npm:^18.2.0": - version: 18.3.1 - resolution: "react-is@npm:18.3.1" - checksum: 10c0/f2f1e60010c683479e74c63f96b09fb41603527cd131a9959e2aee1e5a8b0caf270b365e5ca77d4a6b18aae659b60a86150bb3979073528877029b35aecd2072 - languageName: node - linkType: hard - "react-native-biometrics@npm:^3.0.1": version: 3.0.1 resolution: "react-native-biometrics@npm:3.0.1" @@ -12908,6 +13005,18 @@ __metadata: languageName: node linkType: hard +"react-shallow-renderer@npm:^16.15.0": + version: 16.15.0 + resolution: "react-shallow-renderer@npm:16.15.0" + dependencies: + object-assign: "npm:^4.1.1" + react-is: "npm:^16.12.0 || ^17.0.0 || ^18.0.0" + peerDependencies: + react: ^16.0.0 || ^17.0.0 || ^18.0.0 + checksum: 10c0/c194d741792e86043a4ae272f7353c1cb9412bc649945c4220c6a101a6ea5410cceb3d65d5a4d750f11a24f7426e8eec7977e8a4e3ad5d3ee235ca2b18166fa8 + languageName: node + linkType: hard + "react-style-singleton@npm:^2.2.1, react-style-singleton@npm:^2.2.2": version: 2.2.3 resolution: "react-style-singleton@npm:2.2.3" @@ -12924,6 +13033,19 @@ __metadata: languageName: node linkType: hard +"react-test-renderer@npm:^18.3.1": + version: 18.3.1 + resolution: "react-test-renderer@npm:18.3.1" + dependencies: + react-is: "npm:^18.3.1" + react-shallow-renderer: "npm:^16.15.0" + scheduler: "npm:^0.23.2" + peerDependencies: + react: ^18.3.1 + checksum: 10c0/c633558ef9af33bc68f0c4dbb5163a004c4fb9eade7bd0a7cfc0355fb367f36bd9d96533c90b7e85a146be6c525113a15f58683d269e0177ad77e2b04d4fe51c + languageName: node + linkType: hard + "react@npm:^18.2.0 || ^19.0.0": version: 19.0.0 resolution: "react@npm:19.0.0" @@ -13011,6 +13133,16 @@ __metadata: languageName: node linkType: hard +"redent@npm:^3.0.0": + version: 3.0.0 + resolution: "redent@npm:3.0.0" + dependencies: + indent-string: "npm:^4.0.0" + strip-indent: "npm:^3.0.0" + checksum: 10c0/d64a6b5c0b50eb3ddce3ab770f866658a2b9998c678f797919ceb1b586bab9259b311407280bd80b804e2a7c7539b19238ae6a2a20c843f1a7fcff21d48c2eae + languageName: node + linkType: hard + "reflect-metadata@npm:^0.2.2": version: 0.2.2 resolution: "reflect-metadata@npm:0.2.2" @@ -13371,6 +13503,15 @@ __metadata: languageName: node linkType: hard +"scheduler@npm:^0.23.2": + version: 0.23.2 + resolution: "scheduler@npm:0.23.2" + dependencies: + loose-envify: "npm:^1.1.0" + checksum: 10c0/26383305e249651d4c58e6705d5f8425f153211aef95f15161c151f7b8de885f24751b377e4a0b3dd42cce09aad3f87a61dab7636859c0d89b7daf1a1e2a5c78 + languageName: node + linkType: hard + "selfsigned@npm:^2.4.1": version: 2.4.1 resolution: "selfsigned@npm:2.4.1" @@ -14035,6 +14176,15 @@ __metadata: languageName: node linkType: hard +"strip-indent@npm:^3.0.0": + version: 3.0.0 + resolution: "strip-indent@npm:3.0.0" + dependencies: + min-indent: "npm:^1.0.0" + checksum: 10c0/ae0deaf41c8d1001c5d4fbe16cb553865c1863da4fae036683b474fa926af9fc121e155cb3fc57a68262b2ae7d5b8420aa752c97a6428c315d00efe2a3875679 + languageName: node + linkType: hard + "strip-json-comments@npm:^3.1.1": version: 3.1.1 resolution: "strip-json-comments@npm:3.1.1"