mirror of
https://github.com/selfxyz/self.git
synced 2026-04-05 03:00:53 -04:00
SELF-1938 sumsub integration (#1661)
* Sumsub: Update keychain and types * sumsub: ProvingMachine changes - WIP * fix: remove duplicate identifier * update proving machine * Refactor && Continue onchain registration if user left the app * fix register flow * Add hooks to KycSuccessScreen * Integrate KycVerifiedScreen (#1686) * Integrate KycVerifiedScreen & Fix race conditions * yarn lint * lint * lint * add mock kyc * fix disclose flow * yarn lint * Feat/add kyc home screen card design (#1708) * feat: add new designs to the kycIdCard * refactor: Update KycIdCard design to match IdCard styling * feat: update document cards + dev document * feat: update empty id card for new design * feat: update pending document card design * feat: update expired doc + unregistered doc cards from new design * fix: unregisted id card button links to continue registration screen * fix: logo design on document cards * feat: add 6 different backgrounds for ids deterministically shows 1 of 6 backgrounds for each document | fix: fixed document designs not displaying correctly. * chore: trigger CI rebuild * feat: Integrate PendingIdCard to Homescreen * fix KycIdCard.tsx --------- Co-authored-by: seshanthS <seshanth@protonmail.com> * lint * fix tests * fix: cleanup only on unmount * coderabbit comments * fix: cleanup unused code * fix: edge case for German Passports with D<< nationality code * fix tests * review comments * review comments * lint * Hide duplicated cards in Homescreen * remove console.log * fix patch * remove unused vars * agent updates * agent feedback * abstract colors and formatting * agent feedback * Regenerate Sumsub patch-package patch * fix: handle malformed kyc payload in card background selector * re-add for clean up --------- Co-authored-by: Evi Nova <66773372+Tranquil-Flow@users.noreply.github.com> Co-authored-by: Evi Nova <tranquil_flow@protonmail.com> Co-authored-by: Justin Hernandez <justin.hernandez@self.xyz>
This commit is contained in:
@@ -113,7 +113,6 @@ describe('navigation', () => {
|
||||
'ShowRecoveryPhrase',
|
||||
'Splash',
|
||||
'StarfallPushCode',
|
||||
'SumsubTest',
|
||||
'WebView',
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
import React from 'react';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import { fireEvent, render } from '@testing-library/react-native';
|
||||
import { fireEvent, render, waitFor } from '@testing-library/react-native';
|
||||
|
||||
import * as haptics from '@/integrations/haptics';
|
||||
import KYCVerifiedScreen from '@/screens/kyc/KYCVerifiedScreen';
|
||||
@@ -35,6 +34,9 @@ jest.mock('react-native-safe-area-context', () => ({
|
||||
|
||||
jest.mock('@react-navigation/native', () => ({
|
||||
useNavigation: jest.fn(),
|
||||
useRoute: jest.fn(() => ({
|
||||
params: { documentId: 'test-document-id' },
|
||||
})),
|
||||
}));
|
||||
|
||||
// Mock Tamagui components
|
||||
@@ -81,19 +83,33 @@ jest.mock('@/config/sentry', () => ({
|
||||
captureException: jest.fn(),
|
||||
}));
|
||||
|
||||
const mockUseNavigation = useNavigation as jest.MockedFunction<
|
||||
typeof useNavigation
|
||||
>;
|
||||
const mockEmit = jest.fn();
|
||||
const mockSelfClient = { emit: mockEmit };
|
||||
|
||||
jest.mock('@selfxyz/mobile-sdk-alpha', () => ({
|
||||
useSelfClient: jest.fn(() => mockSelfClient),
|
||||
loadSelectedDocument: jest.fn(() =>
|
||||
Promise.resolve({ documentCategory: 'kyc' }),
|
||||
),
|
||||
SdkEvents: {
|
||||
DOCUMENT_OWNERSHIP_CONFIRMED: 'DOCUMENT_OWNERSHIP_CONFIRMED',
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('@/stores/pendingKycStore', () => ({
|
||||
usePendingKycStore: jest.fn(() => ({
|
||||
pendingVerifications: [],
|
||||
removePendingVerification: jest.fn(),
|
||||
})),
|
||||
}));
|
||||
|
||||
jest.mock('@/providers/passportDataProvider', () => ({
|
||||
setSelectedDocument: jest.fn(() => Promise.resolve()),
|
||||
}));
|
||||
|
||||
describe('KYCVerifiedScreen', () => {
|
||||
const mockNavigate = jest.fn();
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
||||
mockUseNavigation.mockReturnValue({
|
||||
navigate: mockNavigate,
|
||||
} as any);
|
||||
});
|
||||
|
||||
it('should render the screen without errors', () => {
|
||||
@@ -140,17 +156,23 @@ describe('KYCVerifiedScreen', () => {
|
||||
expect(haptics.buttonTap).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should navigate to ProvingScreenRouter when "Generate proof" is pressed', () => {
|
||||
it('should emit DOCUMENT_OWNERSHIP_CONFIRMED when "Generate proof" is pressed', async () => {
|
||||
const { root } = render(<KYCVerifiedScreen />);
|
||||
const button = root.findAllByType('button')[0];
|
||||
|
||||
fireEvent.press(button);
|
||||
|
||||
expect(mockNavigate).toHaveBeenCalledWith('ProvingScreenRouter');
|
||||
await waitFor(() => {
|
||||
expect(mockEmit).toHaveBeenCalledWith(
|
||||
'DOCUMENT_OWNERSHIP_CONFIRMED',
|
||||
expect.objectContaining({ documentCategory: 'kyc' }),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('should have navigation available', () => {
|
||||
render(<KYCVerifiedScreen />);
|
||||
expect(mockUseNavigation).toHaveBeenCalled();
|
||||
it('should use the documentId from route params', () => {
|
||||
const { root } = render(<KYCVerifiedScreen />);
|
||||
// Component should render without errors when documentId is provided
|
||||
expect(root).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -25,12 +25,33 @@ jest.mock('react-native', () => ({
|
||||
},
|
||||
View: ({ children, ...props }: any) => <div {...props}>{children}</div>,
|
||||
Text: ({ children, ...props }: any) => <span {...props}>{children}</span>,
|
||||
AppState: {
|
||||
addEventListener: jest.fn(() => ({ remove: jest.fn() })),
|
||||
currentState: 'active',
|
||||
},
|
||||
NativeModules: {
|
||||
NativeLoggerBridge: {},
|
||||
RNPassportReader: {},
|
||||
},
|
||||
NativeEventEmitter: jest.fn(() => ({
|
||||
addListener: jest.fn(() => ({ remove: jest.fn() })),
|
||||
removeAllListeners: jest.fn(),
|
||||
})),
|
||||
requireNativeComponent: jest.fn(() => 'NativeComponent'),
|
||||
}));
|
||||
|
||||
jest.mock('react-native-edge-to-edge', () => ({
|
||||
SystemBars: () => null,
|
||||
}));
|
||||
|
||||
jest.mock('@/hooks/useSumsubWebSocket', () => ({
|
||||
useSumsubWebSocket: jest.fn(() => ({
|
||||
subscribe: jest.fn(),
|
||||
unsubscribe: jest.fn(),
|
||||
unsubscribeAll: jest.fn(),
|
||||
})),
|
||||
}));
|
||||
|
||||
jest.mock('react-native-safe-area-context', () => ({
|
||||
useSafeAreaInsets: jest.fn(() => ({ top: 0, bottom: 0 })),
|
||||
}));
|
||||
@@ -45,6 +66,7 @@ jest.mock('tamagui', () => ({
|
||||
YStack: ({ children, ...props }: any) => <div {...props}>{children}</div>,
|
||||
View: ({ children, ...props }: any) => <div {...props}>{children}</div>,
|
||||
Text: ({ children, ...props }: any) => <span {...props}>{children}</span>,
|
||||
styled: (Component: any) => (props: any) => <Component {...props} />,
|
||||
}));
|
||||
|
||||
jest.mock('@selfxyz/mobile-sdk-alpha/constants/colors', () => ({
|
||||
@@ -108,7 +130,10 @@ jest.mock('@selfxyz/mobile-sdk-alpha', () => ({
|
||||
}));
|
||||
|
||||
jest.mock('@/stores/settingStore', () => ({
|
||||
useSettingStore: jest.fn(),
|
||||
useSettingStore: Object.assign(jest.fn(), {
|
||||
getState: jest.fn(() => ({ loggingSeverity: 'info' })),
|
||||
subscribe: jest.fn(() => jest.fn()),
|
||||
}),
|
||||
}));
|
||||
|
||||
const mockUseNavigation = useNavigation as jest.MockedFunction<
|
||||
|
||||
62
app/tests/src/utils/cardBackgroundSelector.test.ts
Normal file
62
app/tests/src/utils/cardBackgroundSelector.test.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
// 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.
|
||||
|
||||
import type { IDDocument } from '@selfxyz/common';
|
||||
import { serializeKycData } from '@selfxyz/common';
|
||||
|
||||
import { getBackgroundIndex } from '@/utils/cardBackgroundSelector';
|
||||
|
||||
const BACKGROUND_COUNT = 6;
|
||||
|
||||
function createKycDocument(serializedApplicantInfo: string): IDDocument {
|
||||
return {
|
||||
documentCategory: 'kyc',
|
||||
documentType: 'drivers_licence',
|
||||
mock: false,
|
||||
serializedApplicantInfo,
|
||||
signature: '',
|
||||
pubkey: [],
|
||||
};
|
||||
}
|
||||
|
||||
describe('getBackgroundIndex', () => {
|
||||
it('returns a deterministic index for a valid KYC payload', () => {
|
||||
const serializedData = serializeKycData({
|
||||
country: 'USA',
|
||||
idType: 'passport',
|
||||
idNumber: 'P1234567',
|
||||
issuanceDate: '2020-01-01',
|
||||
expiryDate: '2030-01-01',
|
||||
fullName: 'Jane Doe',
|
||||
dob: '1990-01-01',
|
||||
photoHash: 'photohash',
|
||||
phoneNumber: '+1234567890',
|
||||
gender: 'F',
|
||||
address: '123 Main St',
|
||||
});
|
||||
const serializedApplicantInfo = Buffer.from(
|
||||
serializedData,
|
||||
'utf-8',
|
||||
).toString('base64');
|
||||
|
||||
const document = createKycDocument(serializedApplicantInfo);
|
||||
|
||||
const firstIndex = getBackgroundIndex(document);
|
||||
const secondIndex = getBackgroundIndex(document);
|
||||
|
||||
expect(firstIndex).toBe(secondIndex);
|
||||
expect(firstIndex).toBeGreaterThanOrEqual(1);
|
||||
expect(firstIndex).toBeLessThanOrEqual(BACKGROUND_COUNT);
|
||||
});
|
||||
|
||||
it('does not throw for malformed KYC payload and still returns a valid index', () => {
|
||||
const document = createKycDocument(undefined as unknown as string);
|
||||
|
||||
expect(() => getBackgroundIndex(document)).not.toThrow();
|
||||
|
||||
const index = getBackgroundIndex(document);
|
||||
expect(index).toBeGreaterThanOrEqual(1);
|
||||
expect(index).toBeLessThanOrEqual(BACKGROUND_COUNT);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user