Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions app/jest.setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -382,3 +382,29 @@ jest.mock('react-native-localize', () => ({
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' })),
};
});

Comment on lines +386 to +404
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Fix createNavigationContainerRef mock to match real API (prevent isReady/navigate undefined).

Your mock omits common methods invoked on the ref (isReady, navigate, dispatch, resetRoot). This can cause runtime errors in tests/components that call them.

Apply:

-    createNavigationContainerRef: jest.fn(() => ({
-      current: null,
-      getCurrentRoute: jest.fn(),
-    })),
+    createNavigationContainerRef: jest.fn(() => {
+      const ref = {
+        current: null,
+        isReady: jest.fn(() => true),
+        getCurrentRoute: jest.fn(),
+        navigate: jest.fn(),
+        dispatch: jest.fn(),
+        resetRoot: jest.fn(),
+      };
+      return ref;
+    }),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// 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' })),
};
});
// 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(() => {
const ref = {
current: null,
isReady: jest.fn(() => true),
getCurrentRoute: jest.fn(),
navigate: jest.fn(),
dispatch: jest.fn(),
resetRoot: jest.fn(),
};
return ref;
}),
createStaticNavigation: jest.fn(() => ({ displayName: 'MockNavigation' })),
};
});
🤖 Prompt for AI Agents
In app/jest.setup.js around lines 386 to 404, the createNavigationContainerRef
mock is missing methods used by real refs (isReady, navigate, dispatch,
resetRoot) which can cause tests to see undefined calls; update the mock
returned by createNavigationContainerRef to include a current object and methods
isReady (returns boolean), navigate (jest.fn), dispatch (jest.fn), resetRoot
(jest.fn) and keep getCurrentRoute, so the mock matches the real API and
prevents runtime errors in tests/components that call those methods.

jest.mock('@react-navigation/native-stack', () => ({
createNativeStackNavigator: jest.fn(() => ({
displayName: 'MockStackNavigator',
})),
createNavigatorFactory: jest.fn(),
}));
Comment on lines +405 to +410
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Mock createNativeStackNavigator with Navigator/Screen components to avoid JSX crashes.

Returning a plain object with displayName breaks usages like <Stack.Navigator>. Provide minimal components that render children.

Apply:

-jest.mock('@react-navigation/native-stack', () => ({
-  createNativeStackNavigator: jest.fn(() => ({
-    displayName: 'MockStackNavigator',
-  })),
-  createNavigatorFactory: jest.fn(),
-}));
+jest.mock('@react-navigation/native-stack', () => {
+  const React = require('react');
+  return {
+    createNativeStackNavigator: jest.fn(() => {
+      const Navigator = ({ children }) =>
+        React.createElement(React.Fragment, null, children);
+      const Screen = ({ children }) =>
+        React.createElement(React.Fragment, null, children);
+      return { Navigator, Screen };
+    }),
+    createNavigatorFactory: jest.fn(),
+  };
+});
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
jest.mock('@react-navigation/native-stack', () => ({
createNativeStackNavigator: jest.fn(() => ({
displayName: 'MockStackNavigator',
})),
createNavigatorFactory: jest.fn(),
}));
// In app/jest.setup.js around line 405:
jest.mock('@react-navigation/native-stack', () => {
const React = require('react');
return {
createNativeStackNavigator: jest.fn(() => {
const Navigator = ({ children }) =>
React.createElement(React.Fragment, null, children);
const Screen = ({ children }) =>
React.createElement(React.Fragment, null, children);
return { Navigator, Screen };
}),
createNavigatorFactory: jest.fn(),
};
});
🤖 Prompt for AI Agents
In app/jest.setup.js around lines 405 to 410, the mock for
createNativeStackNavigator currently returns a plain object with only
displayName which causes JSX usages like <Stack.Navigator> and <Stack.Screen> to
crash; replace the mock so createNativeStackNavigator returns an object with
functional Navigator and Screen components (they should accept props and render
children) and preserve displayName, and make createNavigatorFactory return a
factory that yields that same object so tests that render <Stack.Navigator> and
<Stack.Screen> work without crashing.

8 changes: 8 additions & 0 deletions app/tests/src/hooks/useAppUpdates.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ jest.mock('@react-navigation/native', () => ({
useNavigation: jest.fn(),
}));

jest.mock('@/navigation', () => ({
navigationRef: {
isReady: jest.fn(() => true),
navigate: jest.fn(),
getCurrentRoute: jest.fn(),
},
}));

jest.mock('react-native-check-version', () => ({
checkVersion: jest.fn(),
}));
Expand Down
11 changes: 7 additions & 4 deletions app/tests/src/providers/remoteConfigProvider.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,16 @@ describe('RemoteConfigProvider', () => {
expect(getByTestId('error')).toHaveTextContent('none');

// Wait for initialization to complete
await waitFor(() => {
expect(getByTestId('initialized')).toHaveTextContent('true');
});
await waitFor(
() => {
expect(getByTestId('initialized')).toHaveTextContent('true');
},
{ timeout: 10000 },
);

expect(getByTestId('error')).toHaveTextContent('none');
expect(mockInitRemoteConfig).toHaveBeenCalledTimes(1);
});
}, 15000);

it('should handle initialization errors gracefully', async () => {
const errorMessage = 'Firebase initialization failed';
Expand Down
94 changes: 84 additions & 10 deletions app/tests/utils/proving/provingMachine.generatePayload.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ jest.mock('@/utils/analytics', () => () => ({

// Mock the proving inputs to return predictable data
jest.mock('@/utils/proving/provingInputs', () => ({
generateTEEInputsDisclose: jest.fn(() => ({
inputs: { s: 1 },
circuitName: 'vc_and_disclose',
endpointType: 'https',
endpoint: 'https://dis',
})),
}));

// Mock the common register/dsc inputs where provingMachine actually imports from
jest.mock('@selfxyz/common/utils/circuits/registerInputs', () => ({
generateTEEInputsRegister: jest.fn(() => ({
inputs: { r: 1 },
circuitName: 'reg',
Expand All @@ -31,12 +41,6 @@ jest.mock('@/utils/proving/provingInputs', () => ({
endpointType: 'celo',
endpoint: 'https://dsc',
})),
generateTEEInputsDisclose: jest.fn(() => ({
inputs: { s: 1 },
circuitName: 'vc_and_disclose',
endpointType: 'https',
endpoint: 'https://dis',
})),
}));

// Mock the proving utils
Expand All @@ -53,22 +57,92 @@ jest.mock('@selfxyz/common/utils/proving', () => {
};
});

// Mock the tree utils to avoid CSCA tree issues
jest.mock('@selfxyz/common/utils/trees', () => {
const actual = jest.requireActual('@selfxyz/common/utils/trees') as any;
return {
...actual,
getCscaTreeInclusionProof: jest.fn(() => [
'123', // root as string (BigInt toString)
['0', '1', '0'], // path indices as strings
['10', '20', '30'], // siblings as strings
]),
};
});

// Mock the passport utils to avoid signature processing issues
jest.mock('@selfxyz/common/utils/passports/passport', () => {
const actual = jest.requireActual(
'@selfxyz/common/utils/passports/passport',
) as any;
return {
...actual,
getPassportSignatureInfos: jest.fn(() => ({
pubKey: [1, 2, 3, 4],
signature: [5, 6, 7, 8],
signatureAlgorithmFullName: 'rsa_pss_rsae_sha256_65537_2048',
})),
};
});

const {
getPayload,
encryptAES256GCM,
} = require('@selfxyz/common/utils/proving');
const { generateTEEInputsDisclose } = require('@/utils/proving/provingInputs');
const {
generateTEEInputsRegister,
generateTEEInputsDSC,
generateTEEInputsDisclose,
} = require('@/utils/proving/provingInputs');
} = require('@selfxyz/common/utils/circuits/registerInputs');

describe('_generatePayload', () => {
beforeEach(() => {
jest.clearAllMocks();
useProvingStore.setState({
circuitType: 'register',
passportData: { documentCategory: 'passport', mock: false },
passportData: {
documentCategory: 'passport',
mock: false,
dsc_parsed: {
hashAlgorithm: 'sha256',
tbsBytes: [1, 2, 3, 4],
serialNumber: '123',
issuer: 'Test Issuer',
subject: 'Test Subject',
validFrom: new Date('2020-01-01'),
validTo: new Date('2030-01-01'),
publicKey: new Uint8Array([5, 6, 7, 8]),
signature: new Uint8Array([9, 10, 11, 12]),
signatureAlgorithm: 'sha256WithRSAEncryption',
publicKeyDetails: {
bits: 2048,
exponent: 65537,
modulus:
'abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890',
},
},
csca_parsed: {
tbsBytes: [13, 14, 15, 16],
hashAlgorithm: 'sha256',
serialNumber: '456',
issuer: 'Test CSCA Issuer',
subject: 'Test CSCA Subject',
validFrom: new Date('2019-01-01'),
validTo: new Date('2031-01-01'),
publicKey: new Uint8Array([17, 18, 19, 20]),
signature: new Uint8Array([21, 22, 23, 24]),
signatureAlgorithm: 'sha256WithRSAEncryption',
},
dsc: new Uint8Array([25, 26, 27, 28]),
csca: new Uint8Array([29, 30, 31, 32]),
passportMetadata: {
signatureAlgorithm: 'rsa_pss_rsae_sha256',
signedAttrHashFunction: 'sha256',
issuer: 'Test Country',
validFrom: new Date('2020-01-01'),
validTo: new Date('2030-01-01'),
},
},
secret: 'sec',
uuid: '123',
sharedKey: Buffer.alloc(32, 1),
Expand Down Expand Up @@ -96,7 +170,7 @@ describe('_generatePayload', () => {
useProtocolStore.setState({
passport: {
dsc_tree: 'tree',
csca_tree: [['a']],
csca_tree: [[new Uint8Array([29, 30, 31, 32])]],
commitment_tree: null,
deployed_circuits: null,
circuits_dns_mapping: null,
Expand Down
2 changes: 1 addition & 1 deletion common/src/constants/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ export const MAX_PADDED_ECONTENT_LEN: Partial<Record<(typeof hashAlgos)[number],
export const MAX_PADDED_SIGNED_ATTR_LEN: Record<(typeof hashAlgos)[number], number> = {
sha1: 128,
sha224: 128,
sha256: 256,
sha256: 128,
sha384: 256,
sha512: 256,
};
Expand Down
Loading