mirror of
https://github.com/mosip/inji-wallet.git
synced 2026-01-06 20:23:52 -05:00
INJIMOB-3246 Code coverage for Inji-Wallet repo increase above 5% (#2108)
* INJIMOB-3246 Code coverage for Inji-Wallet repo increase above 5% Signed-off-by: Kaushik Gupta <kausgpt97@gmail.com> * INJIMOB-3246: added snapshot tests and coverage increased to +4% Signed-off-by: Kaushik Gupta <kausgpt97@gmail.com> * removed duplicated lines Signed-off-by: Kaushik Gupta <kausgpt97@gmail.com> * Added updateCredentialInformation tests Signed-off-by: Kaushik Gupta <kausgpt97@gmail.com> * added code rabbit changes Signed-off-by: Kaushik Gupta <kausgpt97@gmail.com> * removed platform-specific tests without mocking Signed-off-by: Kaushik Gupta <kausgpt97@gmail.com> * standardize mocks in VcItemContainerProfileImage tests Signed-off-by: Kaushik Gupta <kausgpt97@gmail.com> --------- Signed-off-by: Kaushik Gupta <kausgpt97@gmail.com>
This commit is contained in:
42
components/AccountInformation.test.tsx
Normal file
42
components/AccountInformation.test.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {AccountInformation} from './AccountInformation';
|
||||
|
||||
describe('AccountInformation Component', () => {
|
||||
const defaultProps = {
|
||||
email: 'test@example.com',
|
||||
picture: 'https://example.com/avatar.jpg',
|
||||
};
|
||||
|
||||
it('should match snapshot with email and picture', () => {
|
||||
const {toJSON} = render(<AccountInformation {...defaultProps} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with different email', () => {
|
||||
const {toJSON} = render(
|
||||
<AccountInformation {...defaultProps} email="another@test.com" />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with different picture URL', () => {
|
||||
const {toJSON} = render(
|
||||
<AccountInformation
|
||||
{...defaultProps}
|
||||
picture="https://example.com/different-avatar.jpg"
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with long email', () => {
|
||||
const {toJSON} = render(
|
||||
<AccountInformation
|
||||
{...defaultProps}
|
||||
email="very.long.email.address@example-domain.com"
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -19,7 +19,7 @@ describe('ActivityLog', () => {
|
||||
describe('getActionText', () => {
|
||||
let activityLog;
|
||||
let mockIl18nfn;
|
||||
let wellknown = {
|
||||
const wellknown = {
|
||||
credential_configurations_supported: {
|
||||
mockId: {
|
||||
display: [
|
||||
@@ -67,6 +67,7 @@ describe('getActionText', () => {
|
||||
activityLog.getActionText(mockIl18nfn, wellknown);
|
||||
expect(mockIl18nfn).toHaveBeenCalledWith('mockType', {
|
||||
idType: 'fake VC',
|
||||
vcStatus: '',
|
||||
});
|
||||
expect(mockIl18nfn).toHaveBeenCalledTimes(1);
|
||||
// TODO: assert the returned string
|
||||
@@ -81,3 +82,79 @@ describe('getActionText', () => {
|
||||
expect(mockIl18nfn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('VCActivityLog.getLogFromObject', () => {
|
||||
it('should create VCActivityLog instance from object', () => {
|
||||
const mockData = {
|
||||
id: 'test-id',
|
||||
type: 'VC_ADDED',
|
||||
timestamp: 1234567890,
|
||||
deviceName: 'Test Device',
|
||||
};
|
||||
|
||||
const log = VCActivityLog.getLogFromObject(mockData);
|
||||
|
||||
expect(log).toBeInstanceOf(VCActivityLog);
|
||||
expect(log.id).toBe('test-id');
|
||||
expect(log.type).toBe('VC_ADDED');
|
||||
expect(log.timestamp).toBe(1234567890);
|
||||
expect(log.deviceName).toBe('Test Device');
|
||||
});
|
||||
|
||||
it('should create VCActivityLog from empty object', () => {
|
||||
const log = VCActivityLog.getLogFromObject({});
|
||||
|
||||
expect(log).toBeInstanceOf(VCActivityLog);
|
||||
expect(log.timestamp).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('VCActivityLog.getActionLabel', () => {
|
||||
it('should return formatted action label with device name and time', () => {
|
||||
const mockLog = new VCActivityLog({
|
||||
deviceName: 'iPhone 12',
|
||||
timestamp: Date.now() - 60000, // 1 minute ago
|
||||
});
|
||||
|
||||
const label = mockLog.getActionLabel('en');
|
||||
|
||||
expect(label).toContain('iPhone 12');
|
||||
expect(label).toContain('·');
|
||||
expect(label).toContain('ago');
|
||||
});
|
||||
|
||||
it('should return only time when device name is empty', () => {
|
||||
const mockLog = new VCActivityLog({
|
||||
deviceName: '',
|
||||
timestamp: Date.now() - 120000, // 2 minutes ago
|
||||
});
|
||||
|
||||
const label = mockLog.getActionLabel('en');
|
||||
|
||||
expect(label).not.toContain('·');
|
||||
expect(label).toContain('ago');
|
||||
});
|
||||
|
||||
it('should filter out empty labels', () => {
|
||||
const mockLog = new VCActivityLog({
|
||||
deviceName: ' ', // whitespace only
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
|
||||
const label = mockLog.getActionLabel('en');
|
||||
|
||||
expect(label).not.toContain('·');
|
||||
expect(label).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should format time with device name in English locale', () => {
|
||||
const mockLog = new VCActivityLog({
|
||||
deviceName: 'Test Device',
|
||||
timestamp: Date.now() - 300000, // 5 minutes ago
|
||||
});
|
||||
|
||||
const labelEn = mockLog.getActionLabel('en');
|
||||
expect(labelEn).toBeTruthy();
|
||||
expect(labelEn).toContain('Test Device');
|
||||
});
|
||||
});
|
||||
|
||||
65
components/ActivityLogText.test.tsx
Normal file
65
components/ActivityLogText.test.tsx
Normal file
@@ -0,0 +1,65 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {ActivityLogText} from './ActivityLogText';
|
||||
import {VCItemContainerFlowType} from '../shared/Utils';
|
||||
import {VCActivityLog} from './ActivityLogEvent';
|
||||
import {VPShareActivityLog} from './VPShareActivityLogEvent';
|
||||
|
||||
// Mock TextItem
|
||||
jest.mock('./ui/TextItem', () => ({
|
||||
TextItem: jest.fn(() => null),
|
||||
}));
|
||||
|
||||
// Mock HistoryScreenController
|
||||
jest.mock('../screens/History/HistoryScreenController', () => ({
|
||||
useHistoryTab: jest.fn(() => ({
|
||||
getWellKnownIssuerMap: jest.fn(() => ({display: [{name: 'Test Issuer'}]})),
|
||||
})),
|
||||
}));
|
||||
|
||||
// Mock ActivityLogEvent
|
||||
jest.mock('./ActivityLogEvent', () => ({
|
||||
VCActivityLog: {
|
||||
getLogFromObject: jest.fn(obj => ({
|
||||
...obj,
|
||||
getActionLabel: jest.fn(() => 'Shared'),
|
||||
getActionText: jest.fn(() => 'Shared with Test Device'),
|
||||
})),
|
||||
},
|
||||
}));
|
||||
|
||||
// Mock VPShareActivityLogEvent
|
||||
jest.mock('./VPShareActivityLogEvent', () => ({
|
||||
VPShareActivityLog: {
|
||||
getLogFromObject: jest.fn(obj => ({
|
||||
...obj,
|
||||
getActionLabel: jest.fn(() => 'Verified'),
|
||||
getActionText: jest.fn(() => 'Verified by Test Device'),
|
||||
})),
|
||||
},
|
||||
}));
|
||||
|
||||
describe('ActivityLogText Component', () => {
|
||||
const mockActivity = {
|
||||
vcLabel: 'Test VC',
|
||||
timestamp: new Date().toISOString(),
|
||||
deviceName: 'Test Device',
|
||||
vcIdType: 'NationalID',
|
||||
flow: VCItemContainerFlowType.VC_SHARE,
|
||||
issuer: 'test-issuer',
|
||||
} as unknown as VCActivityLog;
|
||||
|
||||
it('should match snapshot with VC activity', () => {
|
||||
const {toJSON} = render(<ActivityLogText activity={mockActivity} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with VP activity', () => {
|
||||
const vpActivity = {
|
||||
...mockActivity,
|
||||
flow: VCItemContainerFlowType.VP_SHARE,
|
||||
} as unknown as VPShareActivityLog;
|
||||
const {toJSON} = render(<ActivityLogText activity={vpActivity} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
43
components/BackupAndRestoreBannerNotification.test.tsx
Normal file
43
components/BackupAndRestoreBannerNotification.test.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {BackupAndRestoreBannerNotification} from './BackupAndRestoreBannerNotification';
|
||||
|
||||
// Mock controllers
|
||||
jest.mock('../screens/backupAndRestore/BackupController', () => ({
|
||||
useBackupScreen: jest.fn(() => ({
|
||||
showBackupInProgress: false,
|
||||
isBackingUpSuccess: false,
|
||||
isBackingUpFailure: false,
|
||||
backupErrorReason: '',
|
||||
DISMISS: jest.fn(),
|
||||
DISMISS_SHOW_BACKUP_IN_PROGRESS: jest.fn(),
|
||||
})),
|
||||
}));
|
||||
|
||||
jest.mock('../screens/Settings/BackupRestoreController', () => ({
|
||||
useBackupRestoreScreen: jest.fn(() => ({
|
||||
showRestoreInProgress: false,
|
||||
isBackUpRestoreSuccess: false,
|
||||
isBackUpRestoreFailure: false,
|
||||
restoreErrorReason: '',
|
||||
DISMISS: jest.fn(),
|
||||
DISMISS_SHOW_RESTORE_IN_PROGRESS: jest.fn(),
|
||||
})),
|
||||
}));
|
||||
|
||||
// Mock BannerNotification
|
||||
jest.mock('./BannerNotification', () => ({
|
||||
BannerNotification: jest.fn(() => null),
|
||||
BannerStatusType: {
|
||||
IN_PROGRESS: 'inProgress',
|
||||
SUCCESS: 'success',
|
||||
ERROR: 'error',
|
||||
},
|
||||
}));
|
||||
|
||||
describe('BackupAndRestoreBannerNotification Component', () => {
|
||||
it('should match snapshot with no banners', () => {
|
||||
const {toJSON} = render(<BackupAndRestoreBannerNotification />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
51
components/BannerNotification.test.tsx
Normal file
51
components/BannerNotification.test.tsx
Normal file
@@ -0,0 +1,51 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {BannerNotification, BannerStatusType} from './BannerNotification';
|
||||
|
||||
describe('BannerNotification Component', () => {
|
||||
const defaultProps = {
|
||||
message: 'Test notification message',
|
||||
onClosePress: jest.fn(),
|
||||
testId: 'bannerTest',
|
||||
type: BannerStatusType.SUCCESS,
|
||||
};
|
||||
|
||||
it('should match snapshot with success status', () => {
|
||||
const {toJSON} = render(<BannerNotification {...defaultProps} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with error status', () => {
|
||||
const {toJSON} = render(
|
||||
<BannerNotification {...defaultProps} type={BannerStatusType.ERROR} />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with in progress status', () => {
|
||||
const {toJSON} = render(
|
||||
<BannerNotification
|
||||
{...defaultProps}
|
||||
type={BannerStatusType.IN_PROGRESS}
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with long message', () => {
|
||||
const {toJSON} = render(
|
||||
<BannerNotification
|
||||
{...defaultProps}
|
||||
message="This is a very long notification message that should wrap to multiple lines and still be displayed correctly"
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with different testId', () => {
|
||||
const {toJSON} = render(
|
||||
<BannerNotification {...defaultProps} testId="customBanner" />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
72
components/BannerNotificationContainer.test.tsx
Normal file
72
components/BannerNotificationContainer.test.tsx
Normal file
@@ -0,0 +1,72 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {BannerNotificationContainer} from './BannerNotificationContainer';
|
||||
|
||||
// Mock all controllers
|
||||
jest.mock('./BannerNotificationController', () => ({
|
||||
UseBannerNotification: jest.fn(() => ({
|
||||
isBindingSuccess: false,
|
||||
verificationStatus: null,
|
||||
isPasscodeUnlock: false,
|
||||
isBiometricUnlock: false,
|
||||
isDownloadingFailed: false,
|
||||
isDownloadingSuccess: false,
|
||||
isReverificationSuccess: {status: false},
|
||||
isReverificationFailed: {status: false},
|
||||
RESET_WALLET_BINDING_SUCCESS: jest.fn(),
|
||||
RESET_VERIFICATION_STATUS: jest.fn(),
|
||||
RESET_DOWNLOADING_FAILED: jest.fn(),
|
||||
RESET_DOWNLOADING_SUCCESS: jest.fn(),
|
||||
RESET_REVIRIFICATION_SUCCESS: jest.fn(),
|
||||
RESET_REVERIFICATION_FAILURE: jest.fn(),
|
||||
DISMISS: jest.fn(),
|
||||
})),
|
||||
}));
|
||||
|
||||
jest.mock('../screens/Scan/ScanScreenController', () => ({
|
||||
useScanScreen: jest.fn(() => ({
|
||||
showQuickShareSuccessBanner: false,
|
||||
DISMISS_QUICK_SHARE_BANNER: jest.fn(),
|
||||
})),
|
||||
}));
|
||||
|
||||
jest.mock('../screens/Settings/SettingScreenController', () => ({
|
||||
useSettingsScreen: jest.fn(() => ({
|
||||
isKeyOrderSet: null,
|
||||
RESET_KEY_ORDER_RESPONSE: jest.fn(),
|
||||
})),
|
||||
}));
|
||||
|
||||
jest.mock('./BackupAndRestoreBannerNotification', () => ({
|
||||
BackupAndRestoreBannerNotification: jest.fn(() => null),
|
||||
}));
|
||||
|
||||
jest.mock('./BannerNotification', () => ({
|
||||
BannerNotification: jest.fn(() => null),
|
||||
BannerStatusType: {
|
||||
IN_PROGRESS: 'inProgress',
|
||||
SUCCESS: 'success',
|
||||
ERROR: 'error',
|
||||
},
|
||||
}));
|
||||
|
||||
describe('BannerNotificationContainer Component', () => {
|
||||
it('should match snapshot with no banners visible', () => {
|
||||
const {toJSON} = render(<BannerNotificationContainer />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with verification banner enabled', () => {
|
||||
const {toJSON} = render(
|
||||
<BannerNotificationContainer showVerificationStatusBanner={true} />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with verification banner disabled', () => {
|
||||
const {toJSON} = render(
|
||||
<BannerNotificationContainer showVerificationStatusBanner={false} />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
51
components/CopilotTooltip.test.tsx
Normal file
51
components/CopilotTooltip.test.tsx
Normal file
@@ -0,0 +1,51 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {CopilotTooltip} from './CopilotTooltip';
|
||||
|
||||
// Mock ui components
|
||||
jest.mock('./ui', () => ({
|
||||
Button: jest.fn(() => null),
|
||||
Column: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
Row: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
Text: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
}));
|
||||
|
||||
// Mock controller
|
||||
jest.mock('./CopilotTooltipController', () => ({
|
||||
UseCopilotTooltip: jest.fn(() => ({
|
||||
copilotEvents: {
|
||||
on: jest.fn(),
|
||||
},
|
||||
SET_TOUR_GUIDE: jest.fn(),
|
||||
ONBOARDING_DONE: jest.fn(),
|
||||
INITIAL_DOWNLOAD_DONE: jest.fn(),
|
||||
CURRENT_STEP: 1,
|
||||
currentStepTitle: 'Step 1 Title',
|
||||
currentStepDescription: 'Step 1 Description',
|
||||
titleTestID: 'stepTitle',
|
||||
descriptionTestID: 'stepDescription',
|
||||
stepCount: '1/5',
|
||||
isFirstStep: true,
|
||||
isLastStep: false,
|
||||
isFinalStep: false,
|
||||
isOnboarding: true,
|
||||
isInitialDownloading: false,
|
||||
goToPrev: jest.fn(),
|
||||
goToNext: jest.fn(),
|
||||
stop: jest.fn(),
|
||||
})),
|
||||
}));
|
||||
|
||||
// Mock settings controller
|
||||
jest.mock('../screens/Settings/SettingScreenController', () => ({
|
||||
useSettingsScreen: jest.fn(() => ({
|
||||
BACK: jest.fn(),
|
||||
})),
|
||||
}));
|
||||
|
||||
describe('CopilotTooltip Component', () => {
|
||||
it('should match snapshot with first step', () => {
|
||||
const {toJSON} = render(<CopilotTooltip />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
39
components/CopyButton.test.tsx
Normal file
39
components/CopyButton.test.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {CopyButton} from './CopyButton';
|
||||
|
||||
// Mock Clipboard
|
||||
jest.mock('@react-native-clipboard/clipboard', () => ({
|
||||
setString: jest.fn(),
|
||||
}));
|
||||
|
||||
// Mock SvgImage
|
||||
jest.mock('./ui/svg', () => ({
|
||||
SvgImage: {
|
||||
copyIcon: jest.fn(() => null),
|
||||
},
|
||||
}));
|
||||
|
||||
describe('CopyButton Component', () => {
|
||||
const defaultProps = {
|
||||
content: 'Test content to copy',
|
||||
};
|
||||
|
||||
it('should match snapshot with default props', () => {
|
||||
const {toJSON} = render(<CopyButton {...defaultProps} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with long content', () => {
|
||||
const {toJSON} = render(
|
||||
<CopyButton content="This is a very long content string that needs to be copied to clipboard for testing purposes" />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with special characters', () => {
|
||||
const specialContent = 'Special: @#$%^&*(){}[]';
|
||||
const {toJSON} = render(<CopyButton content={specialContent} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
85
components/DeviceInfoList.test.tsx
Normal file
85
components/DeviceInfoList.test.tsx
Normal file
@@ -0,0 +1,85 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {DeviceInfoList, DeviceInfo} from './DeviceInfoList';
|
||||
|
||||
describe('DeviceInfoList Component', () => {
|
||||
const mockDeviceInfo: DeviceInfo = {
|
||||
deviceName: 'Samsung Galaxy S21',
|
||||
name: 'John Doe',
|
||||
deviceId: 'device123',
|
||||
};
|
||||
|
||||
it('should render DeviceInfoList component', () => {
|
||||
const {toJSON} = render(<DeviceInfoList deviceInfo={mockDeviceInfo} />);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render with receiver mode', () => {
|
||||
const {toJSON} = render(
|
||||
<DeviceInfoList deviceInfo={mockDeviceInfo} of="receiver" />,
|
||||
);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render with sender mode', () => {
|
||||
const {toJSON} = render(
|
||||
<DeviceInfoList deviceInfo={mockDeviceInfo} of="sender" />,
|
||||
);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render without of prop', () => {
|
||||
const {toJSON} = render(<DeviceInfoList deviceInfo={mockDeviceInfo} />);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should handle different device names', () => {
|
||||
const deviceNames = [
|
||||
'iPhone 14 Pro',
|
||||
'Google Pixel 7',
|
||||
'OnePlus 11',
|
||||
'Samsung Galaxy S23',
|
||||
];
|
||||
|
||||
deviceNames.forEach(deviceName => {
|
||||
const deviceInfo = {...mockDeviceInfo, deviceName};
|
||||
const {toJSON} = render(<DeviceInfoList deviceInfo={deviceInfo} />);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle different user names', () => {
|
||||
const names = ['Alice Smith', 'Bob Johnson', 'Charlie Brown'];
|
||||
|
||||
names.forEach(name => {
|
||||
const deviceInfo = {...mockDeviceInfo, name};
|
||||
const {toJSON} = render(<DeviceInfoList deviceInfo={deviceInfo} />);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle different device IDs', () => {
|
||||
const deviceIds = ['device001', 'device002', 'device003'];
|
||||
|
||||
deviceIds.forEach(deviceId => {
|
||||
const deviceInfo = {...mockDeviceInfo, deviceId};
|
||||
const {toJSON} = render(<DeviceInfoList deviceInfo={deviceInfo} />);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle empty device name', () => {
|
||||
const deviceInfo = {...mockDeviceInfo, deviceName: ''};
|
||||
const {toJSON} = render(<DeviceInfoList deviceInfo={deviceInfo} />);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should handle long device names', () => {
|
||||
const deviceInfo = {
|
||||
...mockDeviceInfo,
|
||||
deviceName: 'Very Long Device Name With Many Characters',
|
||||
};
|
||||
const {toJSON} = render(<DeviceInfoList deviceInfo={deviceInfo} />);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
50
components/DropdownIcon.test.tsx
Normal file
50
components/DropdownIcon.test.tsx
Normal file
@@ -0,0 +1,50 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {DropdownIcon} from './DropdownIcon';
|
||||
|
||||
// Mock Popable
|
||||
jest.mock('react-native-popable', () => ({
|
||||
Popable: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
}));
|
||||
|
||||
describe('DropdownIcon Component', () => {
|
||||
const mockItems = [
|
||||
{label: 'Item 1', onPress: jest.fn(), icon: 'account'},
|
||||
{label: 'Item 2', onPress: jest.fn(), icon: 'settings'},
|
||||
{label: 'Item 3', onPress: jest.fn(), icon: 'delete', idType: 'type1'},
|
||||
];
|
||||
|
||||
const defaultProps = {
|
||||
idType: 'type1',
|
||||
icon: 'dots-vertical',
|
||||
items: mockItems,
|
||||
};
|
||||
|
||||
it('should match snapshot with default props', () => {
|
||||
const {toJSON} = render(<DropdownIcon {...defaultProps} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with different icon', () => {
|
||||
const {toJSON} = render(<DropdownIcon {...defaultProps} icon="menu" />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with empty items', () => {
|
||||
const {toJSON} = render(<DropdownIcon {...defaultProps} items={[]} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with multiple items', () => {
|
||||
const manyItems = [
|
||||
{label: 'Action 1', onPress: jest.fn(), icon: 'edit'},
|
||||
{label: 'Action 2', onPress: jest.fn(), icon: 'share'},
|
||||
{label: 'Action 3', onPress: jest.fn(), icon: 'download'},
|
||||
{label: 'Action 4', onPress: jest.fn(), icon: 'upload'},
|
||||
];
|
||||
const {toJSON} = render(
|
||||
<DropdownIcon {...defaultProps} items={manyItems} />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
83
components/DualMessageOverlay.test.tsx
Normal file
83
components/DualMessageOverlay.test.tsx
Normal file
@@ -0,0 +1,83 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {DualMessageOverlay} from './DualMessageOverlay';
|
||||
import {Text} from 'react-native';
|
||||
|
||||
// Mock react-native-elements
|
||||
jest.mock('react-native-elements', () => ({
|
||||
Overlay: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
Button: jest.fn(({title}) => <>{title}</>),
|
||||
}));
|
||||
|
||||
// Mock ui components
|
||||
jest.mock('./ui', () => ({
|
||||
Button: jest.fn(
|
||||
({title, children}: {title?: string; children?: React.ReactNode}) => (
|
||||
<>{title || children}</>
|
||||
),
|
||||
),
|
||||
Column: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
Row: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
Text: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
}));
|
||||
|
||||
describe('DualMessageOverlay Component', () => {
|
||||
const defaultProps = {
|
||||
isVisible: true,
|
||||
title: 'Confirm Action',
|
||||
message: 'Are you sure you want to proceed?',
|
||||
};
|
||||
|
||||
it('should match snapshot with title and message', () => {
|
||||
const {toJSON} = render(<DualMessageOverlay {...defaultProps} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with both buttons', () => {
|
||||
const {toJSON} = render(
|
||||
<DualMessageOverlay
|
||||
{...defaultProps}
|
||||
onTryAgain={jest.fn()}
|
||||
onIgnore={jest.fn()}
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with only try again button', () => {
|
||||
const {toJSON} = render(
|
||||
<DualMessageOverlay {...defaultProps} onTryAgain={jest.fn()} />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with only ignore button', () => {
|
||||
const {toJSON} = render(
|
||||
<DualMessageOverlay {...defaultProps} onIgnore={jest.fn()} />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with hint text', () => {
|
||||
const {toJSON} = render(
|
||||
<DualMessageOverlay {...defaultProps} hint="Additional information" />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with custom height', () => {
|
||||
const {toJSON} = render(
|
||||
<DualMessageOverlay {...defaultProps} customHeight={300} />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with children', () => {
|
||||
const {toJSON} = render(
|
||||
<DualMessageOverlay {...defaultProps}>
|
||||
<Text>Custom content here</Text>
|
||||
</DualMessageOverlay>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
96
components/EditableListItem.test.tsx
Normal file
96
components/EditableListItem.test.tsx
Normal file
@@ -0,0 +1,96 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {EditableListItem} from './EditableListItem';
|
||||
|
||||
// Mock SvgImage
|
||||
jest.mock('./ui/svg', () => ({
|
||||
SvgImage: {
|
||||
starIcon: jest.fn(() => null),
|
||||
},
|
||||
}));
|
||||
|
||||
// Mock react-native-elements
|
||||
jest.mock('react-native-elements', () => ({
|
||||
Icon: jest.fn(() => null),
|
||||
ListItem: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
Overlay: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
Input: jest.fn(() => null),
|
||||
}));
|
||||
|
||||
// Mock ui components
|
||||
jest.mock('./ui', () => ({
|
||||
Button: jest.fn(() => null),
|
||||
Column: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
Row: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
Text: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
}));
|
||||
|
||||
// Add mock for ListItem.Content and ListItem.Title
|
||||
const ListItem = require('react-native-elements').ListItem;
|
||||
ListItem.Content = ({children}: {children: React.ReactNode}) => <>{children}</>;
|
||||
ListItem.Title = ({children}: {children: React.ReactNode}) => <>{children}</>;
|
||||
|
||||
describe('EditableListItem Component', () => {
|
||||
const mockItems = [
|
||||
{label: 'Email', value: 'test@example.com', testID: 'emailItem'},
|
||||
{label: 'Phone', value: '1234567890', testID: 'phoneItem'},
|
||||
];
|
||||
|
||||
const defaultProps = {
|
||||
testID: 'editableItem',
|
||||
title: 'Contact Information',
|
||||
content: 'Edit your details',
|
||||
items: mockItems,
|
||||
Icon: 'edit',
|
||||
onEdit: jest.fn(),
|
||||
onCancel: jest.fn(),
|
||||
titleColor: '#000000',
|
||||
};
|
||||
|
||||
it('should match snapshot with default props', () => {
|
||||
const {toJSON} = render(<EditableListItem {...defaultProps} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with custom title color', () => {
|
||||
const {toJSON} = render(
|
||||
<EditableListItem {...defaultProps} titleColor="#FF0000" />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with progress indicator', () => {
|
||||
const {toJSON} = render(
|
||||
<EditableListItem {...defaultProps} progress={true} />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with error state', () => {
|
||||
const {toJSON} = render(
|
||||
<EditableListItem
|
||||
{...defaultProps}
|
||||
response="error"
|
||||
errorMessage="Failed to update"
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with success response', () => {
|
||||
const {toJSON} = render(
|
||||
<EditableListItem {...defaultProps} response="success" />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with single item', () => {
|
||||
const {toJSON} = render(
|
||||
<EditableListItem
|
||||
{...defaultProps}
|
||||
items={[{label: 'Name', value: 'John Doe', testID: 'nameItem'}]}
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
49
components/GlobalContextProvider.test.tsx
Normal file
49
components/GlobalContextProvider.test.tsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {GlobalContextProvider} from './GlobalContextProvider';
|
||||
import {Text} from 'react-native';
|
||||
|
||||
// Mock xstate
|
||||
jest.mock('@xstate/react', () => ({
|
||||
useInterpret: jest.fn(() => ({
|
||||
subscribe: jest.fn(),
|
||||
})),
|
||||
}));
|
||||
|
||||
// Mock appMachine
|
||||
jest.mock('../machines/app', () => ({
|
||||
appMachine: {},
|
||||
}));
|
||||
|
||||
// Mock GlobalContext
|
||||
jest.mock('../shared/GlobalContext', () => ({
|
||||
GlobalContext: {
|
||||
Provider: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
},
|
||||
}));
|
||||
|
||||
// Mock commonUtil
|
||||
jest.mock('../shared/commonUtil', () => ({
|
||||
logState: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('GlobalContextProvider Component', () => {
|
||||
it('should match snapshot with children', () => {
|
||||
const {toJSON} = render(
|
||||
<GlobalContextProvider>
|
||||
<Text>Test Child</Text>
|
||||
</GlobalContextProvider>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with multiple children', () => {
|
||||
const {toJSON} = render(
|
||||
<GlobalContextProvider>
|
||||
<Text>Child 1</Text>
|
||||
<Text>Child 2</Text>
|
||||
</GlobalContextProvider>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
60
components/HelpScreen.test.tsx
Normal file
60
components/HelpScreen.test.tsx
Normal file
@@ -0,0 +1,60 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {HelpScreen} from './HelpScreen';
|
||||
import {Text} from 'react-native';
|
||||
|
||||
// Mock Modal
|
||||
jest.mock('./ui/Modal', () => ({
|
||||
Modal: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
}));
|
||||
|
||||
// Mock BannerNotificationContainer
|
||||
jest.mock('./BannerNotificationContainer', () => ({
|
||||
BannerNotificationContainer: jest.fn(() => null),
|
||||
}));
|
||||
|
||||
// Mock API
|
||||
jest.mock('../shared/api', () => ({
|
||||
__esModule: true,
|
||||
default: jest.fn(() =>
|
||||
Promise.resolve({
|
||||
aboutInjiUrl: 'https://docs.inji.io',
|
||||
}),
|
||||
),
|
||||
}));
|
||||
|
||||
describe('HelpScreen Component', () => {
|
||||
const triggerComponent = <Text>Help</Text>;
|
||||
|
||||
it('should match snapshot with Inji source', () => {
|
||||
const {toJSON} = render(
|
||||
<HelpScreen source="Inji" triggerComponent={triggerComponent} />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with BackUp source', () => {
|
||||
const {toJSON} = render(
|
||||
<HelpScreen source="BackUp" triggerComponent={triggerComponent} />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with keyManagement source', () => {
|
||||
const {toJSON} = render(
|
||||
<HelpScreen source="keyManagement" triggerComponent={triggerComponent} />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot when disabled', () => {
|
||||
const {toJSON} = render(
|
||||
<HelpScreen
|
||||
source="Inji"
|
||||
triggerComponent={triggerComponent}
|
||||
isDisabled={true}
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
88
components/KebabPopUp.test.tsx
Normal file
88
components/KebabPopUp.test.tsx
Normal file
@@ -0,0 +1,88 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {KebabPopUp} from './KebabPopUp';
|
||||
import {Text} from 'react-native';
|
||||
|
||||
// Mock controller
|
||||
jest.mock('./KebabPopUpController', () => ({
|
||||
useKebabPopUp: jest.fn(() => ({
|
||||
isScanning: false,
|
||||
})),
|
||||
}));
|
||||
|
||||
// Mock kebabMenuUtils
|
||||
jest.mock('./kebabMenuUtils', () => ({
|
||||
getKebabMenuOptions: jest.fn(() => [
|
||||
{
|
||||
testID: 'pinCard',
|
||||
label: 'Pin Card',
|
||||
onPress: jest.fn(),
|
||||
icon: null,
|
||||
},
|
||||
{
|
||||
testID: 'removeFromWallet',
|
||||
label: 'Remove',
|
||||
onPress: jest.fn(),
|
||||
icon: null,
|
||||
},
|
||||
]),
|
||||
}));
|
||||
|
||||
// Mock react-native-elements
|
||||
jest.mock('react-native-elements', () => ({
|
||||
Icon: jest.fn(() => null),
|
||||
ListItem: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
Overlay: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
}));
|
||||
|
||||
// Mock FlatList
|
||||
jest.mock('react-native-gesture-handler', () => ({
|
||||
FlatList: ({renderItem, data}: any) => (
|
||||
<>{data.map((item: any, index: number) => renderItem({item, index}))}</>
|
||||
),
|
||||
}));
|
||||
|
||||
describe('KebabPopUp Component', () => {
|
||||
const mockService = {} as any;
|
||||
const mockVcMetadata = {
|
||||
id: 'test-vc',
|
||||
vcLabel: 'Test VC',
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
iconName: 'ellipsis-vertical',
|
||||
vcMetadata: mockVcMetadata as any,
|
||||
isVisible: true,
|
||||
onDismiss: jest.fn(),
|
||||
service: mockService,
|
||||
vcHasImage: false,
|
||||
};
|
||||
|
||||
it('should match snapshot with default icon', () => {
|
||||
const {toJSON} = render(<KebabPopUp {...defaultProps} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with custom icon component', () => {
|
||||
const CustomIcon = <Text>Custom</Text>;
|
||||
const {toJSON} = render(<KebabPopUp {...defaultProps} icon={CustomIcon} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with custom icon color', () => {
|
||||
const {toJSON} = render(
|
||||
<KebabPopUp {...defaultProps} iconColor="#FF0000" />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot when not visible', () => {
|
||||
const {toJSON} = render(<KebabPopUp {...defaultProps} isVisible={false} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with VC that has image', () => {
|
||||
const {toJSON} = render(<KebabPopUp {...defaultProps} vcHasImage={true} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
32
components/LanguageSelector.test.tsx
Normal file
32
components/LanguageSelector.test.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {LanguageSelector} from './LanguageSelector';
|
||||
import {Text} from 'react-native';
|
||||
|
||||
// Mock dependencies
|
||||
jest.mock('react-native-restart', () => ({
|
||||
Restart: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('./ui/Picker', () => ({
|
||||
Picker: jest.fn(() => null),
|
||||
}));
|
||||
|
||||
describe('LanguageSelector Component', () => {
|
||||
const defaultTrigger = <Text>Select Language</Text>;
|
||||
|
||||
it('should match snapshot with default trigger', () => {
|
||||
const {toJSON} = render(
|
||||
<LanguageSelector triggerComponent={defaultTrigger} />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with custom trigger component', () => {
|
||||
const customTrigger = <Text>Choose Language</Text>;
|
||||
const {toJSON} = render(
|
||||
<LanguageSelector triggerComponent={customTrigger} />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
20
components/Logo.test.tsx
Normal file
20
components/Logo.test.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {Logo} from './Logo';
|
||||
|
||||
describe('Logo Component', () => {
|
||||
it('should render Logo component', () => {
|
||||
const {toJSON} = render(<Logo />);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render Logo with width and height props', () => {
|
||||
const {toJSON} = render(<Logo width={100} height={100} />);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render Logo with string width and height', () => {
|
||||
const {toJSON} = render(<Logo width="100%" height="50" />);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
43
components/Message.test.tsx
Normal file
43
components/Message.test.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {Message} from './Message';
|
||||
|
||||
// Mock LinearProgress
|
||||
jest.mock('react-native-elements', () => ({
|
||||
LinearProgress: jest.fn(() => null),
|
||||
}));
|
||||
|
||||
// Mock Button from ui
|
||||
jest.mock('./ui', () => ({
|
||||
Button: jest.fn(() => null),
|
||||
Centered: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
Column: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
Text: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
}));
|
||||
|
||||
describe('Message Component', () => {
|
||||
it('should match snapshot with title only', () => {
|
||||
const {toJSON} = render(<Message title="Test Title" />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with message only', () => {
|
||||
const {toJSON} = render(<Message message="Test Message" />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with title and message', () => {
|
||||
const {toJSON} = render(<Message title="Title" message="Message" />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with hint text', () => {
|
||||
const {toJSON} = render(<Message message="Test" hint="Hint text" />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with cancel button', () => {
|
||||
const {toJSON} = render(<Message message="Test" onCancel={jest.fn()} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
99
components/MessageOverlay.test.tsx
Normal file
99
components/MessageOverlay.test.tsx
Normal file
@@ -0,0 +1,99 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {MessageOverlay, ErrorMessageOverlay} from './MessageOverlay';
|
||||
import {Text} from 'react-native';
|
||||
|
||||
// Mock react-native-elements
|
||||
jest.mock('react-native-elements', () => ({
|
||||
Overlay: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
LinearProgress: jest.fn(() => null),
|
||||
}));
|
||||
|
||||
// Mock ui components
|
||||
jest.mock('./ui', () => ({
|
||||
Button: jest.fn(() => null),
|
||||
Column: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
Text: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
}));
|
||||
|
||||
describe('MessageOverlay Component', () => {
|
||||
const defaultProps = {
|
||||
isVisible: true,
|
||||
title: 'Test Title',
|
||||
message: 'Test Message',
|
||||
};
|
||||
|
||||
it('should match snapshot with title and message', () => {
|
||||
const {toJSON} = render(<MessageOverlay {...defaultProps} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with progress indicator', () => {
|
||||
const {toJSON} = render(
|
||||
<MessageOverlay {...defaultProps} progress={true} />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with numeric progress', () => {
|
||||
const {toJSON} = render(
|
||||
<MessageOverlay {...defaultProps} progress={0.75} />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with button', () => {
|
||||
const {toJSON} = render(
|
||||
<MessageOverlay
|
||||
{...defaultProps}
|
||||
buttonText="OK"
|
||||
onButtonPress={jest.fn()}
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with custom children', () => {
|
||||
const {toJSON} = render(
|
||||
<MessageOverlay {...defaultProps}>
|
||||
<Text>Custom Content</Text>
|
||||
</MessageOverlay>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with hint text', () => {
|
||||
const {toJSON} = render(
|
||||
<MessageOverlay {...defaultProps} hint="This is a hint" />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with custom minHeight', () => {
|
||||
const {toJSON} = render(
|
||||
<MessageOverlay {...defaultProps} minHeight={250} />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('ErrorMessageOverlay Component', () => {
|
||||
const errorProps = {
|
||||
isVisible: true,
|
||||
error: 'network',
|
||||
translationPath: 'errors',
|
||||
onDismiss: jest.fn(),
|
||||
};
|
||||
|
||||
it('should match snapshot with error', () => {
|
||||
const {toJSON} = render(<ErrorMessageOverlay {...errorProps} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with testID', () => {
|
||||
const {toJSON} = render(
|
||||
<ErrorMessageOverlay {...errorProps} testID="errorOverlay" />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
58
components/Passcode.test.tsx
Normal file
58
components/Passcode.test.tsx
Normal file
@@ -0,0 +1,58 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {Passcode} from './Passcode';
|
||||
|
||||
// Mock PasscodeVerify
|
||||
jest.mock('./PasscodeVerify', () => ({
|
||||
PasscodeVerify: jest.fn(() => null),
|
||||
}));
|
||||
|
||||
// Mock telemetry
|
||||
jest.mock('../shared/telemetry/TelemetryUtils', () => ({
|
||||
getImpressionEventData: jest.fn(),
|
||||
sendImpressionEvent: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('Passcode Component', () => {
|
||||
const defaultProps = {
|
||||
error: '',
|
||||
storedPasscode: 'hashed-passcode',
|
||||
salt: 'salt-value',
|
||||
onSuccess: jest.fn(),
|
||||
onError: jest.fn(),
|
||||
onDismiss: jest.fn(),
|
||||
};
|
||||
|
||||
it('should match snapshot with default props', () => {
|
||||
const {toJSON} = render(<Passcode {...defaultProps} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with custom message', () => {
|
||||
const {toJSON} = render(
|
||||
<Passcode
|
||||
{...defaultProps}
|
||||
message="Please enter your 6-digit passcode"
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with error message', () => {
|
||||
const {toJSON} = render(
|
||||
<Passcode {...defaultProps} error="Incorrect passcode. Try again." />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with both message and error', () => {
|
||||
const {toJSON} = render(
|
||||
<Passcode
|
||||
{...defaultProps}
|
||||
message="Enter passcode"
|
||||
error="Authentication failed"
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
54
components/PasscodeVerify.test.tsx
Normal file
54
components/PasscodeVerify.test.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {PasscodeVerify} from './PasscodeVerify';
|
||||
|
||||
// Mock PinInput
|
||||
jest.mock('./PinInput', () => ({
|
||||
PinInput: jest.fn(() => null),
|
||||
}));
|
||||
|
||||
// Mock commonUtil
|
||||
jest.mock('../shared/commonUtil', () => ({
|
||||
hashData: jest.fn(() => Promise.resolve('hashed-value')),
|
||||
}));
|
||||
|
||||
// Mock telemetry
|
||||
jest.mock('../shared/telemetry/TelemetryUtils', () => ({
|
||||
getErrorEventData: jest.fn(),
|
||||
sendErrorEvent: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('PasscodeVerify Component', () => {
|
||||
const defaultProps = {
|
||||
passcode: 'stored-hashed-passcode',
|
||||
onSuccess: jest.fn(),
|
||||
onError: jest.fn(),
|
||||
salt: 'test-salt',
|
||||
testID: 'passcodeVerify',
|
||||
};
|
||||
|
||||
it('should match snapshot with default props', () => {
|
||||
const {toJSON} = render(<PasscodeVerify {...defaultProps} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with different testID', () => {
|
||||
const {toJSON} = render(
|
||||
<PasscodeVerify {...defaultProps} testID="customPasscode" />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot without onError handler', () => {
|
||||
const {passcode, onSuccess, salt, testID} = defaultProps;
|
||||
const {toJSON} = render(
|
||||
<PasscodeVerify
|
||||
passcode={passcode}
|
||||
onSuccess={onSuccess}
|
||||
salt={salt}
|
||||
testID={testID}
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
20
components/PendingIcon.test.tsx
Normal file
20
components/PendingIcon.test.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import PendingIcon from './PendingIcon';
|
||||
|
||||
describe('PendingIcon', () => {
|
||||
it('should render PendingIcon component', () => {
|
||||
const {toJSON} = render(<PendingIcon />);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should match snapshot', () => {
|
||||
const {toJSON} = render(<PendingIcon />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should render with custom color', () => {
|
||||
const {toJSON} = render(<PendingIcon color="#FF0000" />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
54
components/PinInput.test.tsx
Normal file
54
components/PinInput.test.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {PinInput} from './PinInput';
|
||||
|
||||
// Mock usePinInput
|
||||
jest.mock('../machines/pinInput', () => ({
|
||||
usePinInput: jest.fn(length => ({
|
||||
state: {
|
||||
context: {
|
||||
inputRefs: Array(length).fill({current: null}),
|
||||
values: Array(length).fill(''),
|
||||
},
|
||||
},
|
||||
send: jest.fn(),
|
||||
events: {
|
||||
UPDATE_INPUT: jest.fn((value, index) => ({
|
||||
type: 'UPDATE_INPUT',
|
||||
value,
|
||||
index,
|
||||
})),
|
||||
FOCUS_INPUT: jest.fn(index => ({type: 'FOCUS_INPUT', index})),
|
||||
KEY_PRESS: jest.fn(key => ({type: 'KEY_PRESS', key})),
|
||||
},
|
||||
})),
|
||||
}));
|
||||
|
||||
describe('PinInput Component', () => {
|
||||
it('should match snapshot with 4 digit PIN', () => {
|
||||
const {toJSON} = render(<PinInput length={4} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with 6 digit PIN', () => {
|
||||
const {toJSON} = render(<PinInput length={6} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with onChange handler', () => {
|
||||
const {toJSON} = render(<PinInput length={4} onChange={jest.fn()} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with onDone and autosubmit', () => {
|
||||
const {toJSON} = render(
|
||||
<PinInput length={4} onDone={jest.fn()} autosubmit={true} />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with custom testID', () => {
|
||||
const {toJSON} = render(<PinInput length={4} testID="customPinInput" />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
50
components/ProfileIcon.test.tsx
Normal file
50
components/ProfileIcon.test.tsx
Normal file
@@ -0,0 +1,50 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {ProfileIcon} from './ProfileIcon';
|
||||
import {View} from 'react-native';
|
||||
|
||||
// Mock SvgImage
|
||||
jest.mock('./ui/svg', () => ({
|
||||
SvgImage: {
|
||||
pinIcon: jest.fn(() => <View testID="mockPinIcon" />),
|
||||
},
|
||||
}));
|
||||
|
||||
describe('ProfileIcon Component', () => {
|
||||
const defaultProps = {
|
||||
profileIconContainerStyles: {},
|
||||
profileIconSize: 40,
|
||||
};
|
||||
|
||||
it('should match snapshot without pinned icon', () => {
|
||||
const {toJSON} = render(<ProfileIcon {...defaultProps} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with pinned icon', () => {
|
||||
const {toJSON} = render(<ProfileIcon {...defaultProps} isPinned={true} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with custom icon size', () => {
|
||||
const {toJSON} = render(
|
||||
<ProfileIcon {...defaultProps} profileIconSize={60} />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with custom container styles', () => {
|
||||
const customStyles = {
|
||||
backgroundColor: 'blue',
|
||||
borderRadius: 10,
|
||||
padding: 5,
|
||||
};
|
||||
const {toJSON} = render(
|
||||
<ProfileIcon
|
||||
{...defaultProps}
|
||||
profileIconContainerStyles={customStyles}
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
100
components/ProgressingModal.test.tsx
Normal file
100
components/ProgressingModal.test.tsx
Normal file
@@ -0,0 +1,100 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {ProgressingModal} from './ProgressingModal';
|
||||
|
||||
// Mock Modal
|
||||
jest.mock('./ui/Modal', () => ({
|
||||
Modal: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
}));
|
||||
|
||||
// Mock Spinner
|
||||
jest.mock('react-native-spinkit', () => 'Spinner');
|
||||
|
||||
// Mock SvgImage
|
||||
jest.mock('./ui/svg', () => ({
|
||||
SvgImage: {
|
||||
ProgressIcon: jest.fn(() => null),
|
||||
},
|
||||
}));
|
||||
|
||||
// Mock ui components
|
||||
jest.mock('./ui', () => ({
|
||||
Button: jest.fn(() => null),
|
||||
Centered: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
Column: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
Text: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
}));
|
||||
|
||||
describe('ProgressingModal Component', () => {
|
||||
const defaultProps = {
|
||||
isVisible: true,
|
||||
isHintVisible: false,
|
||||
title: 'Processing',
|
||||
};
|
||||
|
||||
it('should match snapshot with default props', () => {
|
||||
const {toJSON} = render(<ProgressingModal {...defaultProps} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with progress spinner', () => {
|
||||
const {toJSON} = render(
|
||||
<ProgressingModal {...defaultProps} progress={true} />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with hint visible', () => {
|
||||
const {toJSON} = render(
|
||||
<ProgressingModal
|
||||
{...defaultProps}
|
||||
isHintVisible={true}
|
||||
hint="Please wait..."
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with retry button', () => {
|
||||
const {toJSON} = render(
|
||||
<ProgressingModal
|
||||
{...defaultProps}
|
||||
isHintVisible={true}
|
||||
hint="Connection failed"
|
||||
onRetry={jest.fn()}
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with stay in progress button', () => {
|
||||
const {toJSON} = render(
|
||||
<ProgressingModal
|
||||
{...defaultProps}
|
||||
isHintVisible={true}
|
||||
hint="Taking longer than expected"
|
||||
onStayInProgress={jest.fn()}
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with BLE error visible', () => {
|
||||
const {toJSON} = render(
|
||||
<ProgressingModal
|
||||
{...defaultProps}
|
||||
isHintVisible={true}
|
||||
isBleErrorVisible={true}
|
||||
hint="Bluetooth error occurred"
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot as requester', () => {
|
||||
const {toJSON} = render(
|
||||
<ProgressingModal {...defaultProps} requester={true} />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
94
components/QrCodeOverlay.test.tsx
Normal file
94
components/QrCodeOverlay.test.tsx
Normal file
@@ -0,0 +1,94 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {QrCodeOverlay} from './QrCodeOverlay';
|
||||
import {NativeModules} from 'react-native';
|
||||
|
||||
// Mock QRCode
|
||||
jest.mock('react-native-qrcode-svg', () => 'QRCode');
|
||||
|
||||
// Mock SvgImage
|
||||
jest.mock('./ui/svg', () => ({
|
||||
SvgImage: {
|
||||
MagnifierZoom: jest.fn(() => null),
|
||||
},
|
||||
}));
|
||||
|
||||
// Mock sharing utils
|
||||
jest.mock('../shared/sharing/imageUtils', () => ({
|
||||
shareImageToAllSupportedApps: jest.fn(() => Promise.resolve(true)),
|
||||
}));
|
||||
|
||||
describe('QrCodeOverlay Component', () => {
|
||||
// Setup mocks for native modules
|
||||
beforeAll(() => {
|
||||
// Mock RNSecureKeystoreModule methods
|
||||
NativeModules.RNSecureKeystoreModule.getData = jest.fn(() =>
|
||||
Promise.resolve(['key', 'mocked-qr-data']),
|
||||
);
|
||||
NativeModules.RNSecureKeystoreModule.storeData = jest.fn(() =>
|
||||
Promise.resolve(),
|
||||
);
|
||||
|
||||
// Mock RNPixelpassModule
|
||||
NativeModules.RNPixelpassModule = {
|
||||
generateQRData: jest.fn(() => Promise.resolve('mocked-qr-data')),
|
||||
};
|
||||
});
|
||||
|
||||
// Silence console warnings during tests
|
||||
beforeAll(() => {
|
||||
jest.spyOn(console, 'warn').mockImplementation();
|
||||
jest.spyOn(console, 'error').mockImplementation();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
const mockVC = {
|
||||
credential: {id: 'test-credential'},
|
||||
generatedOn: new Date().toISOString(),
|
||||
};
|
||||
|
||||
const mockMeta = {
|
||||
id: 'test-vc-id',
|
||||
vcLabel: 'Test VC',
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
verifiableCredential: mockVC as any,
|
||||
meta: mockMeta as any,
|
||||
};
|
||||
|
||||
// NOTE: CodeRabbit suggested making these tests async to wait for QR data loading.
|
||||
// However, the component requires native module mocks (RNSecureKeystoreModule.getData)
|
||||
// that are not properly initialized in the test environment, causing the component
|
||||
// to always return null. These tests currently capture empty snapshots.
|
||||
// TODO: Fix native module mocking to properly test the async QR data loading behavior.
|
||||
|
||||
it('should match snapshot with default props', () => {
|
||||
const {toJSON} = render(<QrCodeOverlay {...defaultProps} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with inline QR disabled', () => {
|
||||
const {toJSON} = render(
|
||||
<QrCodeOverlay {...defaultProps} showInlineQr={false} />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with force visible', () => {
|
||||
const {toJSON} = render(
|
||||
<QrCodeOverlay {...defaultProps} forceVisible={true} />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with onClose handler', () => {
|
||||
const {toJSON} = render(
|
||||
<QrCodeOverlay {...defaultProps} onClose={jest.fn()} />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
106
components/QrScanner.test.tsx
Normal file
106
components/QrScanner.test.tsx
Normal file
@@ -0,0 +1,106 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {QrScanner} from './QrScanner';
|
||||
|
||||
// Mock useContext
|
||||
const mockUseContext = jest.fn();
|
||||
jest.spyOn(React, 'useContext').mockImplementation(mockUseContext);
|
||||
|
||||
// Mock GlobalContext
|
||||
jest.mock('../shared/GlobalContext', () => ({
|
||||
GlobalContext: {},
|
||||
}));
|
||||
|
||||
// Mock xstate with a mutable mock function
|
||||
const mockUseSelector = jest.fn();
|
||||
jest.mock('@xstate/react', () => ({
|
||||
useSelector: jest.fn((...args) => mockUseSelector(...args)),
|
||||
}));
|
||||
|
||||
// Before each test, set up the context mock
|
||||
beforeEach(() => {
|
||||
mockUseContext.mockReturnValue({
|
||||
appService: {send: jest.fn()},
|
||||
});
|
||||
mockUseSelector.mockReturnValue(true);
|
||||
});
|
||||
|
||||
// Mock app machine
|
||||
jest.mock('../machines/app', () => ({
|
||||
selectIsActive: jest.fn(),
|
||||
}));
|
||||
|
||||
// Mock SvgImage
|
||||
jest.mock('./ui/svg', () => ({
|
||||
SvgImage: {
|
||||
FlipCameraIcon: jest.fn(() => null),
|
||||
},
|
||||
}));
|
||||
|
||||
// Mock ui components
|
||||
jest.mock('./ui', () => ({
|
||||
Column: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
Row: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
Text: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
}));
|
||||
|
||||
// Mock expo-camera
|
||||
jest.mock('expo-camera', () => ({
|
||||
CameraView: jest.fn(() => null),
|
||||
useCameraPermissions: jest.fn(() => [
|
||||
null,
|
||||
jest.fn(() => Promise.resolve({granted: true})),
|
||||
jest.fn(() => Promise.resolve({status: 'granted'})),
|
||||
]),
|
||||
PermissionStatus: {
|
||||
UNDETERMINED: 'undetermined',
|
||||
GRANTED: 'granted',
|
||||
DENIED: 'denied',
|
||||
},
|
||||
CameraType: {
|
||||
BACK: 'back',
|
||||
FRONT: 'front',
|
||||
},
|
||||
}));
|
||||
|
||||
describe('QrScanner Component', () => {
|
||||
const defaultProps = {
|
||||
onQrFound: jest.fn(),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should match snapshot with default props', () => {
|
||||
const {toJSON} = render(<QrScanner {...defaultProps} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with title', () => {
|
||||
const {toJSON} = render(
|
||||
<QrScanner {...defaultProps} title="Hold phone steady to scan QR code" />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with custom title', () => {
|
||||
const {toJSON} = render(
|
||||
<QrScanner {...defaultProps} title="Scan QR code to share credentials" />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should render with onQrFound callback', () => {
|
||||
const onQrFound = jest.fn();
|
||||
const {toJSON} = render(<QrScanner onQrFound={onQrFound} />);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
expect(onQrFound).not.toHaveBeenCalled(); // Callback not called until QR is scanned
|
||||
});
|
||||
|
||||
it('should render when isActive is false', () => {
|
||||
mockUseSelector.mockReturnValue(false);
|
||||
const {toJSON} = render(<QrScanner {...defaultProps} />);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
99
components/RotatingIcon.test.tsx
Normal file
99
components/RotatingIcon.test.tsx
Normal file
@@ -0,0 +1,99 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {RotatingIcon} from './RotatingIcon';
|
||||
|
||||
describe('RotatingIcon Component', () => {
|
||||
it('should render RotatingIcon component', () => {
|
||||
const {toJSON} = render(
|
||||
<RotatingIcon name="sync" size={24} color="#000000" clockwise={true} />,
|
||||
);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render with clockwise rotation', () => {
|
||||
const {toJSON} = render(
|
||||
<RotatingIcon
|
||||
name="refresh"
|
||||
size={30}
|
||||
color="#FF0000"
|
||||
clockwise={true}
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render with counter-clockwise rotation', () => {
|
||||
const {toJSON} = render(
|
||||
<RotatingIcon
|
||||
name="refresh"
|
||||
size={30}
|
||||
color="#0000FF"
|
||||
clockwise={false}
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render with custom duration', () => {
|
||||
const {toJSON} = render(
|
||||
<RotatingIcon
|
||||
name="sync"
|
||||
size={24}
|
||||
color="#00FF00"
|
||||
clockwise={true}
|
||||
duration={5000}
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render with default duration', () => {
|
||||
const {toJSON} = render(
|
||||
<RotatingIcon
|
||||
name="loading"
|
||||
size={20}
|
||||
color="#CCCCCC"
|
||||
clockwise={true}
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should handle different icon names', () => {
|
||||
const iconNames = ['sync', 'refresh', 'loading', 'autorenew'];
|
||||
|
||||
iconNames.forEach(name => {
|
||||
const {toJSON} = render(
|
||||
<RotatingIcon name={name} size={24} color="#000000" clockwise={true} />,
|
||||
);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle different sizes', () => {
|
||||
const sizes = [16, 24, 32, 48];
|
||||
|
||||
sizes.forEach(size => {
|
||||
const {toJSON} = render(
|
||||
<RotatingIcon
|
||||
name="sync"
|
||||
size={size}
|
||||
color="#000000"
|
||||
clockwise={true}
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle different colors', () => {
|
||||
const colors = ['#FF0000', '#00FF00', '#0000FF', '#FFFFFF'];
|
||||
|
||||
colors.forEach(color => {
|
||||
const {toJSON} = render(
|
||||
<RotatingIcon name="sync" size={24} color={color} clockwise={true} />,
|
||||
);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
70
components/SectionLayout.test.tsx
Normal file
70
components/SectionLayout.test.tsx
Normal file
@@ -0,0 +1,70 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {SectionLayout} from './SectionLayout';
|
||||
import {Text, View} from 'react-native';
|
||||
|
||||
// Mock ui components
|
||||
jest.mock('./ui', () => ({
|
||||
Column: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
Row: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
Text: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
}));
|
||||
|
||||
describe('SectionLayout Component', () => {
|
||||
const defaultProps = {
|
||||
headerIcon: <View testID="headerIcon">Icon</View>,
|
||||
headerText: 'Section Header',
|
||||
children: <Text>Section Content</Text>,
|
||||
testId: 'testSection',
|
||||
};
|
||||
|
||||
it('should match snapshot with default props', () => {
|
||||
const {toJSON} = render(<SectionLayout {...defaultProps} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with custom marginBottom', () => {
|
||||
const {toJSON} = render(
|
||||
<SectionLayout {...defaultProps} marginBottom={20} />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with different header text', () => {
|
||||
const {toJSON} = render(
|
||||
<SectionLayout {...defaultProps} headerText="Custom Section Title" />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with complex children', () => {
|
||||
const {toJSON} = render(
|
||||
<SectionLayout
|
||||
headerIcon={defaultProps.headerIcon}
|
||||
headerText={defaultProps.headerText}
|
||||
testId={defaultProps.testId}>
|
||||
<Text>Line 1</Text>
|
||||
<Text>Line 2</Text>
|
||||
<View>
|
||||
<Text>Nested content</Text>
|
||||
</View>
|
||||
</SectionLayout>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with different icon', () => {
|
||||
const customIcon = <View testID="customIcon">🔍</View>;
|
||||
const {toJSON} = render(
|
||||
<SectionLayout {...defaultProps} headerIcon={customIcon} />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with zero marginBottom', () => {
|
||||
const {toJSON} = render(
|
||||
<SectionLayout {...defaultProps} marginBottom={0} />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
150
components/TextEditOverlay.test.tsx
Normal file
150
components/TextEditOverlay.test.tsx
Normal file
@@ -0,0 +1,150 @@
|
||||
import React from 'react';
|
||||
import {render, fireEvent} from '@testing-library/react-native';
|
||||
import {TextEditOverlay} from './TextEditOverlay';
|
||||
|
||||
// Mock react-native-elements with a more realistic Input
|
||||
jest.mock('react-native-elements', () => {
|
||||
const RN = jest.requireActual('react-native');
|
||||
return {
|
||||
Input: (props: {value: string; onChangeText: (text: string) => void}) => (
|
||||
<RN.TextInput
|
||||
value={props.value}
|
||||
onChangeText={props.onChangeText}
|
||||
testID="text-input"
|
||||
/>
|
||||
),
|
||||
};
|
||||
});
|
||||
|
||||
// Mock ui components with more realistic Button
|
||||
jest.mock('./ui', () => {
|
||||
const RN = jest.requireActual('react-native');
|
||||
const React = jest.requireActual('react');
|
||||
return {
|
||||
Button: (props: {title: string; onPress: () => void}) => (
|
||||
<RN.TouchableOpacity
|
||||
onPress={props.onPress}
|
||||
testID={`button-${props.title}`}>
|
||||
<RN.Text>{props.title}</RN.Text>
|
||||
</RN.TouchableOpacity>
|
||||
),
|
||||
Centered: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
Column: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
Row: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
Text: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
};
|
||||
});
|
||||
|
||||
describe('TextEditOverlay Component', () => {
|
||||
const defaultProps = {
|
||||
isVisible: true,
|
||||
label: 'Edit Name',
|
||||
value: 'John Doe',
|
||||
onSave: jest.fn(),
|
||||
onDismiss: jest.fn(),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should match snapshot with default props', () => {
|
||||
const {toJSON} = render(<TextEditOverlay {...defaultProps} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with different label', () => {
|
||||
const {toJSON} = render(
|
||||
<TextEditOverlay {...defaultProps} label="Edit Email" />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with maxLength', () => {
|
||||
const {toJSON} = render(
|
||||
<TextEditOverlay {...defaultProps} maxLength={50} />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with empty value', () => {
|
||||
const {toJSON} = render(<TextEditOverlay {...defaultProps} value="" />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with long value', () => {
|
||||
const {toJSON} = render(
|
||||
<TextEditOverlay
|
||||
{...defaultProps}
|
||||
value="This is a very long text value that should be editable"
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should call onSave with value when save button is pressed', () => {
|
||||
const onSave = jest.fn();
|
||||
const {getByTestId} = render(
|
||||
<TextEditOverlay {...defaultProps} onSave={onSave} value="Test Value" />,
|
||||
);
|
||||
|
||||
const saveButton = getByTestId('button-save');
|
||||
fireEvent.press(saveButton);
|
||||
|
||||
// onSave should be called with the current value
|
||||
expect(onSave).toHaveBeenCalledTimes(1);
|
||||
expect(typeof onSave.mock.calls[0][0]).toBe('string');
|
||||
});
|
||||
|
||||
it('should call onSave with original value when save is pressed without changes', () => {
|
||||
const onSave = jest.fn();
|
||||
const {getByTestId} = render(
|
||||
<TextEditOverlay {...defaultProps} onSave={onSave} />,
|
||||
);
|
||||
|
||||
const saveButton = getByTestId('button-save');
|
||||
fireEvent.press(saveButton);
|
||||
|
||||
expect(onSave).toHaveBeenCalledWith('John Doe');
|
||||
});
|
||||
|
||||
it('should call onDismiss and reset value when cancel button is pressed', () => {
|
||||
const onDismiss = jest.fn();
|
||||
const {getByTestId} = render(
|
||||
<TextEditOverlay {...defaultProps} onDismiss={onDismiss} />,
|
||||
);
|
||||
|
||||
const input = getByTestId('text-input');
|
||||
// Simulate text change
|
||||
input.props.onChangeText('Modified Text');
|
||||
|
||||
const cancelButton = getByTestId('button-cancel');
|
||||
fireEvent.press(cancelButton);
|
||||
|
||||
expect(onDismiss).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should handle text input changes', () => {
|
||||
const {getByTestId} = render(<TextEditOverlay {...defaultProps} />);
|
||||
|
||||
const input = getByTestId('text-input');
|
||||
|
||||
// Verify input has onChangeText handler
|
||||
expect(input.props.onChangeText).toBeDefined();
|
||||
expect(typeof input.props.onChangeText).toBe('function');
|
||||
});
|
||||
|
||||
it('should not use isVisible prop', () => {
|
||||
// Note: isVisible is defined in the interface but not used in the component
|
||||
// This test documents that the prop exists but has no effect
|
||||
const {toJSON: jsonVisible} = render(
|
||||
<TextEditOverlay {...defaultProps} isVisible={true} />,
|
||||
);
|
||||
const {toJSON: jsonHidden} = render(
|
||||
<TextEditOverlay {...defaultProps} isVisible={false} />,
|
||||
);
|
||||
|
||||
// Both render the same output regardless of isVisible value
|
||||
expect(JSON.stringify(jsonVisible())).toEqual(JSON.stringify(jsonHidden()));
|
||||
});
|
||||
});
|
||||
105
components/TrustModal.test.tsx
Normal file
105
components/TrustModal.test.tsx
Normal file
@@ -0,0 +1,105 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {TrustModal} from './TrustModal';
|
||||
|
||||
// Mock useTranslation hook
|
||||
const mockT = jest.fn((key: string) => {
|
||||
if (key === 'infoPoints' || key === 'verifierInfoPoints') {
|
||||
return ['Point 1', 'Point 2', 'Point 3'];
|
||||
}
|
||||
return key;
|
||||
});
|
||||
|
||||
jest.mock('react-i18next', () => ({
|
||||
...jest.requireActual('react-i18next'),
|
||||
useTranslation: () => ({
|
||||
t: mockT,
|
||||
i18n: {changeLanguage: jest.fn()},
|
||||
}),
|
||||
}));
|
||||
|
||||
// Mock ui components
|
||||
jest.mock('./ui', () => ({
|
||||
Button: jest.fn(() => null),
|
||||
Column: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
Row: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
Text: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
}));
|
||||
|
||||
// Mock react-native components
|
||||
jest.mock('react-native', () => {
|
||||
const ReactNative = jest.requireActual('react-native');
|
||||
return {
|
||||
...ReactNative,
|
||||
Modal: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
View: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
ScrollView: ({children}: {children: React.ReactNode}) => <>{children}</>,
|
||||
Image: jest.fn(() => null),
|
||||
};
|
||||
});
|
||||
|
||||
describe('TrustModal Component', () => {
|
||||
const defaultProps = {
|
||||
isVisible: true,
|
||||
logo: 'https://example.com/logo.png',
|
||||
name: 'Test Issuer',
|
||||
onConfirm: jest.fn(),
|
||||
onCancel: jest.fn(),
|
||||
};
|
||||
|
||||
it('should match snapshot with issuer flow', () => {
|
||||
const {toJSON} = render(<TrustModal {...defaultProps} flowType="issuer" />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with verifier flow', () => {
|
||||
const {toJSON} = render(
|
||||
<TrustModal {...defaultProps} flowType="verifier" />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot when not visible', () => {
|
||||
const {toJSON} = render(<TrustModal {...defaultProps} isVisible={false} />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot without logo', () => {
|
||||
const {toJSON} = render(
|
||||
<TrustModal {...defaultProps} logo={undefined} flowType="issuer" />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot without name', () => {
|
||||
const {toJSON} = render(
|
||||
<TrustModal {...defaultProps} name={''} flowType="issuer" />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot without logo and name', () => {
|
||||
const {toJSON} = render(
|
||||
<TrustModal
|
||||
isVisible={true}
|
||||
logo={undefined}
|
||||
name={''}
|
||||
onConfirm={jest.fn()}
|
||||
onCancel={jest.fn()}
|
||||
flowType="issuer"
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with long name', () => {
|
||||
const {toJSON} = render(
|
||||
<TrustModal
|
||||
{...defaultProps}
|
||||
name="Very Long Issuer Name That Should Wrap Properly"
|
||||
flowType="verifier"
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
75
components/VCVerification.test.tsx
Normal file
75
components/VCVerification.test.tsx
Normal file
@@ -0,0 +1,75 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {VCVerification} from './VCVerification';
|
||||
import {VCMetadata} from '../shared/VCMetadata';
|
||||
import {Display} from './VC/common/VCUtils';
|
||||
|
||||
// Mock the Display class
|
||||
const mockDisplay = {
|
||||
getTextColor: jest.fn((defaultColor: string) => defaultColor),
|
||||
} as unknown as Display;
|
||||
|
||||
describe('VCVerification Component', () => {
|
||||
it('should render for verified and valid credential', () => {
|
||||
const vcMetadata = new VCMetadata({
|
||||
isVerified: true,
|
||||
isExpired: false,
|
||||
});
|
||||
|
||||
const {toJSON} = render(
|
||||
<VCVerification vcMetadata={vcMetadata} display={mockDisplay} />,
|
||||
);
|
||||
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render for verified but expired credential', () => {
|
||||
const vcMetadata = new VCMetadata({
|
||||
isVerified: true,
|
||||
isExpired: true,
|
||||
});
|
||||
|
||||
const {toJSON} = render(
|
||||
<VCVerification vcMetadata={vcMetadata} display={mockDisplay} />,
|
||||
);
|
||||
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render for pending/unverified credential', () => {
|
||||
const vcMetadata = new VCMetadata({
|
||||
isVerified: false,
|
||||
isExpired: false,
|
||||
});
|
||||
|
||||
const {toJSON} = render(
|
||||
<VCVerification vcMetadata={vcMetadata} display={mockDisplay} />,
|
||||
);
|
||||
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render verification status text', () => {
|
||||
const vcMetadata = new VCMetadata({
|
||||
isVerified: true,
|
||||
isExpired: false,
|
||||
});
|
||||
|
||||
const {getByText} = render(
|
||||
<VCVerification vcMetadata={vcMetadata} display={mockDisplay} />,
|
||||
);
|
||||
|
||||
expect(getByText('valid')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should call getTextColor from display prop', () => {
|
||||
const vcMetadata = new VCMetadata({
|
||||
isVerified: true,
|
||||
isExpired: false,
|
||||
});
|
||||
|
||||
render(<VCVerification vcMetadata={vcMetadata} display={mockDisplay} />);
|
||||
|
||||
expect(mockDisplay.getTextColor).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
234
components/VPShareActivityLogEvent.test.ts
Normal file
234
components/VPShareActivityLogEvent.test.ts
Normal file
@@ -0,0 +1,234 @@
|
||||
import {VPShareActivityLog} from './VPShareActivityLogEvent';
|
||||
import {VCItemContainerFlowType} from '../shared/Utils';
|
||||
|
||||
describe('VPShareActivityLog', () => {
|
||||
describe('constructor', () => {
|
||||
it('should create instance with default values', () => {
|
||||
const log = new VPShareActivityLog({});
|
||||
|
||||
expect(log.type).toBe('');
|
||||
expect(log.timestamp).toBeDefined();
|
||||
expect(log.flow).toBe(VCItemContainerFlowType.VP_SHARE);
|
||||
expect(log.info).toBe('');
|
||||
});
|
||||
|
||||
it('should create instance with provided values', () => {
|
||||
const timestamp = Date.now();
|
||||
const log = new VPShareActivityLog({
|
||||
type: 'SHARED_SUCCESSFULLY',
|
||||
timestamp,
|
||||
flow: VCItemContainerFlowType.QR_LOGIN,
|
||||
info: 'Test info',
|
||||
});
|
||||
|
||||
expect(log.type).toBe('SHARED_SUCCESSFULLY');
|
||||
expect(log.timestamp).toBe(timestamp);
|
||||
expect(log.flow).toBe(VCItemContainerFlowType.QR_LOGIN);
|
||||
expect(log.info).toBe('Test info');
|
||||
});
|
||||
|
||||
it('should handle different activity types', () => {
|
||||
const types: Array<
|
||||
| 'SHARED_SUCCESSFULLY'
|
||||
| 'SHARED_WITH_FACE_VERIFIACTION'
|
||||
| 'VERIFIER_AUTHENTICATION_FAILED'
|
||||
| 'INVALID_AUTH_REQUEST'
|
||||
| 'USER_DECLINED_CONSENT'
|
||||
> = [
|
||||
'SHARED_SUCCESSFULLY',
|
||||
'SHARED_WITH_FACE_VERIFIACTION',
|
||||
'VERIFIER_AUTHENTICATION_FAILED',
|
||||
'INVALID_AUTH_REQUEST',
|
||||
'USER_DECLINED_CONSENT',
|
||||
];
|
||||
|
||||
types.forEach(type => {
|
||||
const log = new VPShareActivityLog({type});
|
||||
expect(log.type).toBe(type);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getActionText', () => {
|
||||
it('should return formatted action text', () => {
|
||||
const log = new VPShareActivityLog({
|
||||
type: 'SHARED_SUCCESSFULLY',
|
||||
info: 'Test info',
|
||||
});
|
||||
|
||||
const mockT = jest.fn(key => `Translated: ${key}`);
|
||||
const result = log.getActionText(mockT);
|
||||
|
||||
expect(mockT).toHaveBeenCalledWith(
|
||||
'ActivityLogText:vpSharing:SHARED_SUCCESSFULLY',
|
||||
{info: 'Test info'},
|
||||
);
|
||||
expect(result).toContain('Translated:');
|
||||
});
|
||||
|
||||
it('should handle empty type', () => {
|
||||
const log = new VPShareActivityLog({type: ''});
|
||||
const mockT = jest.fn(key => key);
|
||||
|
||||
log.getActionText(mockT);
|
||||
expect(mockT).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should pass info to translation function', () => {
|
||||
const log = new VPShareActivityLog({
|
||||
type: 'TECHNICAL_ERROR',
|
||||
info: 'Error details',
|
||||
});
|
||||
|
||||
const mockT = jest.fn();
|
||||
log.getActionText(mockT);
|
||||
|
||||
expect(mockT).toHaveBeenCalledWith(
|
||||
expect.any(String),
|
||||
expect.objectContaining({info: 'Error details'}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getLogFromObject', () => {
|
||||
it('should create log from object', () => {
|
||||
const data = {
|
||||
type: 'SHARED_SUCCESSFULLY',
|
||||
timestamp: 1234567890,
|
||||
flow: VCItemContainerFlowType.VP_SHARE,
|
||||
info: 'Test',
|
||||
};
|
||||
|
||||
const log = VPShareActivityLog.getLogFromObject(data);
|
||||
|
||||
expect(log).toBeInstanceOf(VPShareActivityLog);
|
||||
expect(log.type).toBe('SHARED_SUCCESSFULLY');
|
||||
expect(log.timestamp).toBe(1234567890);
|
||||
});
|
||||
|
||||
it('should handle empty object', () => {
|
||||
const log = VPShareActivityLog.getLogFromObject({});
|
||||
|
||||
expect(log).toBeInstanceOf(VPShareActivityLog);
|
||||
expect(log.type).toBe('');
|
||||
});
|
||||
|
||||
it('should handle partial object', () => {
|
||||
const log = VPShareActivityLog.getLogFromObject({
|
||||
type: 'USER_DECLINED_CONSENT',
|
||||
});
|
||||
|
||||
expect(log).toBeInstanceOf(VPShareActivityLog);
|
||||
expect(log.type).toBe('USER_DECLINED_CONSENT');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getActionLabel', () => {
|
||||
it('should return formatted action label in English', () => {
|
||||
const log = new VPShareActivityLog({
|
||||
timestamp: Date.now() - 60000, // 1 minute ago
|
||||
});
|
||||
|
||||
const label = log.getActionLabel('enUS');
|
||||
|
||||
expect(label).toBeDefined();
|
||||
expect(typeof label).toBe('string');
|
||||
expect(label.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('should handle different languages', () => {
|
||||
const log = new VPShareActivityLog({
|
||||
timestamp: Date.now() - 3600000, // 1 hour ago
|
||||
});
|
||||
|
||||
const languages = ['enUS', 'hi', 'kn', 'ta', 'ar'];
|
||||
|
||||
languages.forEach(lang => {
|
||||
const label = log.getActionLabel(lang);
|
||||
expect(label).toBeDefined();
|
||||
expect(typeof label).toBe('string');
|
||||
});
|
||||
});
|
||||
|
||||
it('should show relative time', () => {
|
||||
const recentTimestamp = Date.now() - 5000; // 5 seconds ago
|
||||
const log = new VPShareActivityLog({timestamp: recentTimestamp});
|
||||
|
||||
const label = log.getActionLabel('enUS');
|
||||
|
||||
expect(label).toBeDefined();
|
||||
expect(label.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('should handle old timestamps', () => {
|
||||
const oldTimestamp = Date.now() - 86400000; // 1 day ago
|
||||
const log = new VPShareActivityLog({timestamp: oldTimestamp});
|
||||
|
||||
const label = log.getActionLabel('enUS');
|
||||
|
||||
expect(label).toBeDefined();
|
||||
expect(label).toContain('ago');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Activity Log Types', () => {
|
||||
it('should handle all success types', () => {
|
||||
const successTypes: Array<
|
||||
| 'SHARED_SUCCESSFULLY'
|
||||
| 'SHARED_WITH_FACE_VERIFIACTION'
|
||||
| 'SHARED_AFTER_RETRY'
|
||||
| 'SHARED_WITH_FACE_VERIFICATION_AFTER_RETRY'
|
||||
> = [
|
||||
'SHARED_SUCCESSFULLY',
|
||||
'SHARED_WITH_FACE_VERIFIACTION',
|
||||
'SHARED_AFTER_RETRY',
|
||||
'SHARED_WITH_FACE_VERIFICATION_AFTER_RETRY',
|
||||
];
|
||||
|
||||
successTypes.forEach(type => {
|
||||
const log = new VPShareActivityLog({type});
|
||||
expect(log.type).toBe(type);
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle all error types', () => {
|
||||
const errorTypes: Array<
|
||||
| 'VERIFIER_AUTHENTICATION_FAILED'
|
||||
| 'INVALID_AUTH_REQUEST'
|
||||
| 'RETRY_ATTEMPT_FAILED'
|
||||
| 'MAX_RETRY_ATTEMPT_FAILED'
|
||||
| 'FACE_VERIFICATION_FAILED'
|
||||
| 'TECHNICAL_ERROR'
|
||||
> = [
|
||||
'VERIFIER_AUTHENTICATION_FAILED',
|
||||
'INVALID_AUTH_REQUEST',
|
||||
'RETRY_ATTEMPT_FAILED',
|
||||
'MAX_RETRY_ATTEMPT_FAILED',
|
||||
'FACE_VERIFICATION_FAILED',
|
||||
'TECHNICAL_ERROR',
|
||||
];
|
||||
|
||||
errorTypes.forEach(type => {
|
||||
const log = new VPShareActivityLog({type});
|
||||
expect(log.type).toBe(type);
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle credential-related types', () => {
|
||||
const credentialTypes: Array<
|
||||
| 'NO_SELECTED_VC_HAS_IMAGE'
|
||||
| 'CREDENTIAL_MISMATCH_FROM_KEBAB'
|
||||
| 'NO_CREDENTIAL_MATCHING_REQUEST'
|
||||
> = [
|
||||
'NO_SELECTED_VC_HAS_IMAGE',
|
||||
'CREDENTIAL_MISMATCH_FROM_KEBAB',
|
||||
'NO_CREDENTIAL_MATCHING_REQUEST',
|
||||
];
|
||||
|
||||
credentialTypes.forEach(type => {
|
||||
const log = new VPShareActivityLog({type});
|
||||
expect(log.type).toBe(type);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
71
components/VcItemContainerProfileImage.test.tsx
Normal file
71
components/VcItemContainerProfileImage.test.tsx
Normal file
@@ -0,0 +1,71 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {VcItemContainerProfileImage} from './VcItemContainerProfileImage';
|
||||
import {View} from 'react-native';
|
||||
|
||||
// Mock SvgImage
|
||||
jest.mock('./ui/svg', () => ({
|
||||
SvgImage: {
|
||||
pinIcon: jest.fn(() => <View testID="mockPinIcon" />),
|
||||
},
|
||||
}));
|
||||
|
||||
// Mock ProfileIcon
|
||||
jest.mock('./ProfileIcon', () => ({
|
||||
ProfileIcon: jest.fn(() => <View testID="mockProfileIcon" />),
|
||||
}));
|
||||
|
||||
describe('VcItemContainerProfileImage Component', () => {
|
||||
const vcDataWithImage = {
|
||||
face: 'https://example.com/avatar.jpg',
|
||||
};
|
||||
|
||||
const vcDataWithoutImage = {
|
||||
face: null,
|
||||
};
|
||||
|
||||
it('should match snapshot with face image', () => {
|
||||
const {toJSON} = render(
|
||||
<VcItemContainerProfileImage
|
||||
verifiableCredentialData={vcDataWithImage}
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with face image and pinned', () => {
|
||||
const {toJSON} = render(
|
||||
<VcItemContainerProfileImage
|
||||
verifiableCredentialData={vcDataWithImage}
|
||||
isPinned={true}
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot without face image', () => {
|
||||
const {toJSON} = render(
|
||||
<VcItemContainerProfileImage
|
||||
verifiableCredentialData={vcDataWithoutImage}
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot without face image and pinned', () => {
|
||||
const {toJSON} = render(
|
||||
<VcItemContainerProfileImage
|
||||
verifiableCredentialData={vcDataWithoutImage}
|
||||
isPinned={true}
|
||||
/>,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should match snapshot with empty string face', () => {
|
||||
const {toJSON} = render(
|
||||
<VcItemContainerProfileImage verifiableCredentialData={{face: ''}} />,
|
||||
);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
30
components/VerifiedIcon.test.tsx
Normal file
30
components/VerifiedIcon.test.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import VerifiedIcon from './VerifiedIcon';
|
||||
|
||||
describe('VerifiedIcon', () => {
|
||||
it('should render VerifiedIcon component', () => {
|
||||
const {toJSON} = render(<VerifiedIcon />);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should match snapshot', () => {
|
||||
const {toJSON} = render(<VerifiedIcon />);
|
||||
expect(toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should have proper styling structure', () => {
|
||||
const {toJSON} = render(<VerifiedIcon />);
|
||||
const tree = toJSON();
|
||||
|
||||
// Verify component structure exists
|
||||
expect(tree).toBeTruthy();
|
||||
expect(tree.children).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render with check-circle icon', () => {
|
||||
const {toJSON} = render(<VerifiedIcon />);
|
||||
const tree = toJSON();
|
||||
expect(tree).toBeTruthy();
|
||||
});
|
||||
});
|
||||
821
components/__snapshots__/AccountInformation.test.tsx.snap
Normal file
821
components/__snapshots__/AccountInformation.test.tsx.snap
Normal file
@@ -0,0 +1,821 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`AccountInformation Component should match snapshot with different email 1`] = `
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"columnGap": 11,
|
||||
"marginBottom": 21,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"justifyContent": "center",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<Image
|
||||
accessibilityLabel="associatedAccountPicture"
|
||||
accessible={true}
|
||||
source={
|
||||
{
|
||||
"uri": "https://example.com/avatar.jpg",
|
||||
}
|
||||
}
|
||||
style={
|
||||
{
|
||||
"borderRadius": 45,
|
||||
"height": 40,
|
||||
"width": 40,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<Text
|
||||
accessibilityLabel="associatedAccount"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"lineHeight": 18,
|
||||
},
|
||||
{
|
||||
"fontFamily": "Inter_400Regular",
|
||||
"fontSize": 14,
|
||||
},
|
||||
null,
|
||||
{
|
||||
"textAlign": "left",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"color": "#707070",
|
||||
"fontSize": 12,
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
associatedAccount
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<Text
|
||||
accessibilityLabel="associatedAccountEmail"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"lineHeight": 18,
|
||||
},
|
||||
{
|
||||
"fontFamily": "Inter_400Regular",
|
||||
"fontSize": 14,
|
||||
},
|
||||
null,
|
||||
{
|
||||
"textAlign": "left",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"fontFamily": "Helvetica Neue",
|
||||
"fontSize": 13,
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
another@test.com
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`AccountInformation Component should match snapshot with different picture URL 1`] = `
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"columnGap": 11,
|
||||
"marginBottom": 21,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"justifyContent": "center",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<Image
|
||||
accessibilityLabel="associatedAccountPicture"
|
||||
accessible={true}
|
||||
source={
|
||||
{
|
||||
"uri": "https://example.com/different-avatar.jpg",
|
||||
}
|
||||
}
|
||||
style={
|
||||
{
|
||||
"borderRadius": 45,
|
||||
"height": 40,
|
||||
"width": 40,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<Text
|
||||
accessibilityLabel="associatedAccount"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"lineHeight": 18,
|
||||
},
|
||||
{
|
||||
"fontFamily": "Inter_400Regular",
|
||||
"fontSize": 14,
|
||||
},
|
||||
null,
|
||||
{
|
||||
"textAlign": "left",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"color": "#707070",
|
||||
"fontSize": 12,
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
associatedAccount
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<Text
|
||||
accessibilityLabel="associatedAccountEmail"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"lineHeight": 18,
|
||||
},
|
||||
{
|
||||
"fontFamily": "Inter_400Regular",
|
||||
"fontSize": 14,
|
||||
},
|
||||
null,
|
||||
{
|
||||
"textAlign": "left",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"fontFamily": "Helvetica Neue",
|
||||
"fontSize": 13,
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
test@example.com
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`AccountInformation Component should match snapshot with email and picture 1`] = `
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"columnGap": 11,
|
||||
"marginBottom": 21,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"justifyContent": "center",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<Image
|
||||
accessibilityLabel="associatedAccountPicture"
|
||||
accessible={true}
|
||||
source={
|
||||
{
|
||||
"uri": "https://example.com/avatar.jpg",
|
||||
}
|
||||
}
|
||||
style={
|
||||
{
|
||||
"borderRadius": 45,
|
||||
"height": 40,
|
||||
"width": 40,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<Text
|
||||
accessibilityLabel="associatedAccount"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"lineHeight": 18,
|
||||
},
|
||||
{
|
||||
"fontFamily": "Inter_400Regular",
|
||||
"fontSize": 14,
|
||||
},
|
||||
null,
|
||||
{
|
||||
"textAlign": "left",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"color": "#707070",
|
||||
"fontSize": 12,
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
associatedAccount
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<Text
|
||||
accessibilityLabel="associatedAccountEmail"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"lineHeight": 18,
|
||||
},
|
||||
{
|
||||
"fontFamily": "Inter_400Regular",
|
||||
"fontSize": 14,
|
||||
},
|
||||
null,
|
||||
{
|
||||
"textAlign": "left",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"fontFamily": "Helvetica Neue",
|
||||
"fontSize": 13,
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
test@example.com
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`AccountInformation Component should match snapshot with long email 1`] = `
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"columnGap": 11,
|
||||
"marginBottom": 21,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"justifyContent": "center",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<Image
|
||||
accessibilityLabel="associatedAccountPicture"
|
||||
accessible={true}
|
||||
source={
|
||||
{
|
||||
"uri": "https://example.com/avatar.jpg",
|
||||
}
|
||||
}
|
||||
style={
|
||||
{
|
||||
"borderRadius": 45,
|
||||
"height": 40,
|
||||
"width": 40,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<Text
|
||||
accessibilityLabel="associatedAccount"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"lineHeight": 18,
|
||||
},
|
||||
{
|
||||
"fontFamily": "Inter_400Regular",
|
||||
"fontSize": 14,
|
||||
},
|
||||
null,
|
||||
{
|
||||
"textAlign": "left",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"color": "#707070",
|
||||
"fontSize": 12,
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
associatedAccount
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<Text
|
||||
accessibilityLabel="associatedAccountEmail"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"lineHeight": 18,
|
||||
},
|
||||
{
|
||||
"fontFamily": "Inter_400Regular",
|
||||
"fontSize": 14,
|
||||
},
|
||||
null,
|
||||
{
|
||||
"textAlign": "left",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"fontFamily": "Helvetica Neue",
|
||||
"fontSize": 13,
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
very.long.email.address@example-domain.com
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
5
components/__snapshots__/ActivityLogText.test.tsx.snap
Normal file
5
components/__snapshots__/ActivityLogText.test.tsx.snap
Normal file
@@ -0,0 +1,5 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ActivityLogText Component should match snapshot with VC activity 1`] = `null`;
|
||||
|
||||
exports[`ActivityLogText Component should match snapshot with VP activity 1`] = `null`;
|
||||
@@ -0,0 +1,3 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`BackupAndRestoreBannerNotification Component should match snapshot with no banners 1`] = `null`;
|
||||
851
components/__snapshots__/BannerNotification.test.tsx.snap
Normal file
851
components/__snapshots__/BannerNotification.test.tsx.snap
Normal file
@@ -0,0 +1,851 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`BannerNotification Component should match snapshot with different testId 1`] = `
|
||||
<View
|
||||
accessibilityLabel="customBanner"
|
||||
accessible={true}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
[
|
||||
{
|
||||
"alignItems": "flex-start",
|
||||
"backgroundColor": "#DB2E2E",
|
||||
"columnGap": 7,
|
||||
"justifyContent": "space-between",
|
||||
"marginVertical": 1,
|
||||
"paddingHorizontal": 18,
|
||||
"paddingVertical": 12,
|
||||
"position": "relative",
|
||||
"width": "100%",
|
||||
},
|
||||
{
|
||||
"backgroundColor": "#4B9D20",
|
||||
},
|
||||
],
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
{
|
||||
"flex": 1,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<Text
|
||||
accessibilityLabel="customBannerText"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"lineHeight": 18,
|
||||
},
|
||||
{
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 15,
|
||||
},
|
||||
{
|
||||
"color": "#FFFFFF",
|
||||
},
|
||||
{
|
||||
"textAlign": "left",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 12,
|
||||
"lineHeight": 15,
|
||||
"padding": 1,
|
||||
"textAlignVertical": "center",
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
Test notification message
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessibilityLabel="close"
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"paddingLeft": 9,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`BannerNotification Component should match snapshot with error status 1`] = `
|
||||
<View
|
||||
accessibilityLabel="bannerTest"
|
||||
accessible={true}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
[
|
||||
{
|
||||
"alignItems": "flex-start",
|
||||
"backgroundColor": "#DB2E2E",
|
||||
"columnGap": 7,
|
||||
"justifyContent": "space-between",
|
||||
"marginVertical": 1,
|
||||
"paddingHorizontal": 18,
|
||||
"paddingVertical": 12,
|
||||
"position": "relative",
|
||||
"width": "100%",
|
||||
},
|
||||
{
|
||||
"backgroundColor": "#DB2E2E",
|
||||
},
|
||||
],
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
{
|
||||
"flex": 1,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<Text
|
||||
accessibilityLabel="bannerTestText"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"lineHeight": 18,
|
||||
},
|
||||
{
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 15,
|
||||
},
|
||||
{
|
||||
"color": "#FFFFFF",
|
||||
},
|
||||
{
|
||||
"textAlign": "left",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 12,
|
||||
"lineHeight": 15,
|
||||
"padding": 1,
|
||||
"textAlignVertical": "center",
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
Test notification message
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessibilityLabel="close"
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"paddingLeft": 9,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`BannerNotification Component should match snapshot with in progress status 1`] = `
|
||||
<View
|
||||
accessibilityLabel="bannerTest"
|
||||
accessible={true}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
[
|
||||
{
|
||||
"alignItems": "flex-start",
|
||||
"backgroundColor": "#DB2E2E",
|
||||
"columnGap": 7,
|
||||
"justifyContent": "space-between",
|
||||
"marginVertical": 1,
|
||||
"paddingHorizontal": 18,
|
||||
"paddingVertical": 12,
|
||||
"position": "relative",
|
||||
"width": "100%",
|
||||
},
|
||||
{
|
||||
"backgroundColor": "#D9822B",
|
||||
},
|
||||
],
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
{
|
||||
"flex": 1,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<Text
|
||||
accessibilityLabel="bannerTestText"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"lineHeight": 18,
|
||||
},
|
||||
{
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 15,
|
||||
},
|
||||
{
|
||||
"color": "#FFFFFF",
|
||||
},
|
||||
{
|
||||
"textAlign": "left",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 12,
|
||||
"lineHeight": 15,
|
||||
"padding": 1,
|
||||
"textAlignVertical": "center",
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
Test notification message
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessibilityLabel="close"
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"paddingLeft": 9,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`BannerNotification Component should match snapshot with long message 1`] = `
|
||||
<View
|
||||
accessibilityLabel="bannerTest"
|
||||
accessible={true}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
[
|
||||
{
|
||||
"alignItems": "flex-start",
|
||||
"backgroundColor": "#DB2E2E",
|
||||
"columnGap": 7,
|
||||
"justifyContent": "space-between",
|
||||
"marginVertical": 1,
|
||||
"paddingHorizontal": 18,
|
||||
"paddingVertical": 12,
|
||||
"position": "relative",
|
||||
"width": "100%",
|
||||
},
|
||||
{
|
||||
"backgroundColor": "#4B9D20",
|
||||
},
|
||||
],
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
{
|
||||
"flex": 1,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<Text
|
||||
accessibilityLabel="bannerTestText"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"lineHeight": 18,
|
||||
},
|
||||
{
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 15,
|
||||
},
|
||||
{
|
||||
"color": "#FFFFFF",
|
||||
},
|
||||
{
|
||||
"textAlign": "left",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 12,
|
||||
"lineHeight": 15,
|
||||
"padding": 1,
|
||||
"textAlignVertical": "center",
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
This is a very long notification message that should wrap to multiple lines and still be displayed correctly
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessibilityLabel="close"
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"paddingLeft": 9,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`BannerNotification Component should match snapshot with success status 1`] = `
|
||||
<View
|
||||
accessibilityLabel="bannerTest"
|
||||
accessible={true}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
[
|
||||
{
|
||||
"alignItems": "flex-start",
|
||||
"backgroundColor": "#DB2E2E",
|
||||
"columnGap": 7,
|
||||
"justifyContent": "space-between",
|
||||
"marginVertical": 1,
|
||||
"paddingHorizontal": 18,
|
||||
"paddingVertical": 12,
|
||||
"position": "relative",
|
||||
"width": "100%",
|
||||
},
|
||||
{
|
||||
"backgroundColor": "#4B9D20",
|
||||
},
|
||||
],
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
{
|
||||
"flex": 1,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<Text
|
||||
accessibilityLabel="bannerTestText"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"lineHeight": 18,
|
||||
},
|
||||
{
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 15,
|
||||
},
|
||||
{
|
||||
"color": "#FFFFFF",
|
||||
},
|
||||
{
|
||||
"textAlign": "left",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 12,
|
||||
"lineHeight": 15,
|
||||
"padding": 1,
|
||||
"textAlignVertical": "center",
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
Test notification message
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessibilityLabel="close"
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"paddingLeft": 9,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
@@ -0,0 +1,7 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`BannerNotificationContainer Component should match snapshot with no banners visible 1`] = `null`;
|
||||
|
||||
exports[`BannerNotificationContainer Component should match snapshot with verification banner disabled 1`] = `null`;
|
||||
|
||||
exports[`BannerNotificationContainer Component should match snapshot with verification banner enabled 1`] = `null`;
|
||||
9
components/__snapshots__/CopilotTooltip.test.tsx.snap
Normal file
9
components/__snapshots__/CopilotTooltip.test.tsx.snap
Normal file
@@ -0,0 +1,9 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`CopilotTooltip Component should match snapshot with first step 1`] = `
|
||||
[
|
||||
"Step 1 Title",
|
||||
"Step 1 Description",
|
||||
"1/5",
|
||||
]
|
||||
`;
|
||||
268
components/__snapshots__/CopyButton.test.tsx.snap
Normal file
268
components/__snapshots__/CopyButton.test.tsx.snap
Normal file
@@ -0,0 +1,268 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`CopyButton Component should match snapshot with default props 1`] = `
|
||||
<View
|
||||
accessibilityLabel="clipboard.copyButton"
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={false}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<Text
|
||||
accessibilityLabel="clipboard.copyText"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"lineHeight": 18,
|
||||
},
|
||||
{
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 15,
|
||||
},
|
||||
null,
|
||||
{
|
||||
"textAlign": "center",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"maxWidth": 130,
|
||||
"paddingTop": 0,
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
clipboard.copy
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`CopyButton Component should match snapshot with long content 1`] = `
|
||||
<View
|
||||
accessibilityLabel="clipboard.copyButton"
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={false}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<Text
|
||||
accessibilityLabel="clipboard.copyText"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"lineHeight": 18,
|
||||
},
|
||||
{
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 15,
|
||||
},
|
||||
null,
|
||||
{
|
||||
"textAlign": "center",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"maxWidth": 130,
|
||||
"paddingTop": 0,
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
clipboard.copy
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`CopyButton Component should match snapshot with special characters 1`] = `
|
||||
<View
|
||||
accessibilityLabel="clipboard.copyButton"
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={false}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<Text
|
||||
accessibilityLabel="clipboard.copyText"
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"lineHeight": 18,
|
||||
},
|
||||
{
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 15,
|
||||
},
|
||||
null,
|
||||
{
|
||||
"textAlign": "center",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"maxWidth": 130,
|
||||
"paddingTop": 0,
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
clipboard.copy
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
9
components/__snapshots__/DropdownIcon.test.tsx.snap
Normal file
9
components/__snapshots__/DropdownIcon.test.tsx.snap
Normal file
@@ -0,0 +1,9 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`DropdownIcon Component should match snapshot with default props 1`] = `<View />`;
|
||||
|
||||
exports[`DropdownIcon Component should match snapshot with different icon 1`] = `<View />`;
|
||||
|
||||
exports[`DropdownIcon Component should match snapshot with empty items 1`] = `<View />`;
|
||||
|
||||
exports[`DropdownIcon Component should match snapshot with multiple items 1`] = `<View />`;
|
||||
170
components/__snapshots__/DualMessageOverlay.test.tsx.snap
Normal file
170
components/__snapshots__/DualMessageOverlay.test.tsx.snap
Normal file
@@ -0,0 +1,170 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`DualMessageOverlay Component should match snapshot with both buttons 1`] = `
|
||||
[
|
||||
"Confirm Action",
|
||||
"Are you sure you want to proceed?",
|
||||
<Text
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"lineHeight": 18,
|
||||
},
|
||||
{
|
||||
"fontFamily": "Inter_700Bold",
|
||||
"fontSize": 15,
|
||||
"justifyContent": "center",
|
||||
},
|
||||
{
|
||||
"color": "#FFFFFF",
|
||||
},
|
||||
{
|
||||
"textAlign": "left",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"paddingLeft": 0,
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
tryAgain
|
||||
</Text>,
|
||||
<Text
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"lineHeight": 18,
|
||||
},
|
||||
{
|
||||
"fontFamily": "Inter_700Bold",
|
||||
"fontSize": 15,
|
||||
"justifyContent": "center",
|
||||
},
|
||||
{
|
||||
"color": "#FFFFFF",
|
||||
},
|
||||
{
|
||||
"textAlign": "left",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"paddingLeft": 0,
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
ignore
|
||||
</Text>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`DualMessageOverlay Component should match snapshot with children 1`] = `
|
||||
[
|
||||
"Confirm Action",
|
||||
"Are you sure you want to proceed?",
|
||||
<Text>
|
||||
Custom content here
|
||||
</Text>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`DualMessageOverlay Component should match snapshot with custom height 1`] = `
|
||||
[
|
||||
"Confirm Action",
|
||||
"Are you sure you want to proceed?",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`DualMessageOverlay Component should match snapshot with hint text 1`] = `
|
||||
[
|
||||
"Confirm Action",
|
||||
"Are you sure you want to proceed?",
|
||||
"Additional information",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`DualMessageOverlay Component should match snapshot with only ignore button 1`] = `
|
||||
[
|
||||
"Confirm Action",
|
||||
"Are you sure you want to proceed?",
|
||||
<Text
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"lineHeight": 18,
|
||||
},
|
||||
{
|
||||
"fontFamily": "Inter_700Bold",
|
||||
"fontSize": 15,
|
||||
"justifyContent": "center",
|
||||
},
|
||||
{
|
||||
"color": "#FFFFFF",
|
||||
},
|
||||
{
|
||||
"textAlign": "left",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"paddingLeft": 0,
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
ignore
|
||||
</Text>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`DualMessageOverlay Component should match snapshot with only try again button 1`] = `
|
||||
[
|
||||
"Confirm Action",
|
||||
"Are you sure you want to proceed?",
|
||||
<Text
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"lineHeight": 18,
|
||||
},
|
||||
{
|
||||
"fontFamily": "Inter_700Bold",
|
||||
"fontSize": 15,
|
||||
"justifyContent": "center",
|
||||
},
|
||||
{
|
||||
"color": "#FFFFFF",
|
||||
},
|
||||
{
|
||||
"textAlign": "left",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"paddingLeft": 0,
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
tryAgain
|
||||
</Text>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`DualMessageOverlay Component should match snapshot with title and message 1`] = `
|
||||
[
|
||||
"Confirm Action",
|
||||
"Are you sure you want to proceed?",
|
||||
]
|
||||
`;
|
||||
55
components/__snapshots__/EditableListItem.test.tsx.snap
Normal file
55
components/__snapshots__/EditableListItem.test.tsx.snap
Normal file
@@ -0,0 +1,55 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`EditableListItem Component should match snapshot with custom title color 1`] = `
|
||||
[
|
||||
"Contact Information",
|
||||
"Edit your details",
|
||||
"editLabel",
|
||||
"editLabel",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`EditableListItem Component should match snapshot with default props 1`] = `
|
||||
[
|
||||
"Contact Information",
|
||||
"Edit your details",
|
||||
"editLabel",
|
||||
"editLabel",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`EditableListItem Component should match snapshot with error state 1`] = `
|
||||
[
|
||||
"Contact Information",
|
||||
"Edit your details",
|
||||
"editLabel",
|
||||
"Failed to update",
|
||||
"editLabel",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`EditableListItem Component should match snapshot with progress indicator 1`] = `
|
||||
[
|
||||
"Contact Information",
|
||||
"Edit your details",
|
||||
"editLabel",
|
||||
"editLabel",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`EditableListItem Component should match snapshot with single item 1`] = `
|
||||
[
|
||||
"Contact Information",
|
||||
"Edit your details",
|
||||
"editLabel",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`EditableListItem Component should match snapshot with success response 1`] = `
|
||||
[
|
||||
"Contact Information",
|
||||
"Edit your details",
|
||||
"editLabel",
|
||||
"editLabel",
|
||||
]
|
||||
`;
|
||||
18
components/__snapshots__/GlobalContextProvider.test.tsx.snap
Normal file
18
components/__snapshots__/GlobalContextProvider.test.tsx.snap
Normal file
@@ -0,0 +1,18 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`GlobalContextProvider Component should match snapshot with children 1`] = `
|
||||
<Text>
|
||||
Test Child
|
||||
</Text>
|
||||
`;
|
||||
|
||||
exports[`GlobalContextProvider Component should match snapshot with multiple children 1`] = `
|
||||
[
|
||||
<Text>
|
||||
Child 1
|
||||
</Text>,
|
||||
<Text>
|
||||
Child 2
|
||||
</Text>,
|
||||
]
|
||||
`;
|
||||
6561
components/__snapshots__/HelpScreen.test.tsx.snap
Normal file
6561
components/__snapshots__/HelpScreen.test.tsx.snap
Normal file
File diff suppressed because it is too large
Load Diff
1149
components/__snapshots__/KebabPopUp.test.tsx.snap
Normal file
1149
components/__snapshots__/KebabPopUp.test.tsx.snap
Normal file
File diff suppressed because it is too large
Load Diff
5
components/__snapshots__/LanguageSelector.test.tsx.snap
Normal file
5
components/__snapshots__/LanguageSelector.test.tsx.snap
Normal file
@@ -0,0 +1,5 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`LanguageSelector Component should match snapshot with custom trigger component 1`] = `<View />`;
|
||||
|
||||
exports[`LanguageSelector Component should match snapshot with default trigger 1`] = `<View />`;
|
||||
88
components/__snapshots__/Message.test.tsx.snap
Normal file
88
components/__snapshots__/Message.test.tsx.snap
Normal file
@@ -0,0 +1,88 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Message Component should match snapshot with cancel button 1`] = `
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"backgroundColor": "rgba(0,0,0,.6)",
|
||||
"height": 1334,
|
||||
"position": "absolute",
|
||||
"top": 0,
|
||||
"width": 750,
|
||||
"zIndex": 9,
|
||||
}
|
||||
}
|
||||
>
|
||||
Test
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`Message Component should match snapshot with hint text 1`] = `
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"backgroundColor": "rgba(0,0,0,.6)",
|
||||
"height": 1334,
|
||||
"position": "absolute",
|
||||
"top": 0,
|
||||
"width": 750,
|
||||
"zIndex": 9,
|
||||
}
|
||||
}
|
||||
>
|
||||
Test
|
||||
Hint text
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`Message Component should match snapshot with message only 1`] = `
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"backgroundColor": "rgba(0,0,0,.6)",
|
||||
"height": 1334,
|
||||
"position": "absolute",
|
||||
"top": 0,
|
||||
"width": 750,
|
||||
"zIndex": 9,
|
||||
}
|
||||
}
|
||||
>
|
||||
Test Message
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`Message Component should match snapshot with title and message 1`] = `
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"backgroundColor": "rgba(0,0,0,.6)",
|
||||
"height": 1334,
|
||||
"position": "absolute",
|
||||
"top": 0,
|
||||
"width": 750,
|
||||
"zIndex": 9,
|
||||
}
|
||||
}
|
||||
>
|
||||
Title
|
||||
Message
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`Message Component should match snapshot with title only 1`] = `
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"backgroundColor": "rgba(0,0,0,.6)",
|
||||
"height": 1334,
|
||||
"position": "absolute",
|
||||
"top": 0,
|
||||
"width": 750,
|
||||
"zIndex": 9,
|
||||
}
|
||||
}
|
||||
>
|
||||
Test Title
|
||||
</View>
|
||||
`;
|
||||
68
components/__snapshots__/MessageOverlay.test.tsx.snap
Normal file
68
components/__snapshots__/MessageOverlay.test.tsx.snap
Normal file
@@ -0,0 +1,68 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ErrorMessageOverlay Component should match snapshot with error 1`] = `
|
||||
[
|
||||
"network.title",
|
||||
"network.message",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`ErrorMessageOverlay Component should match snapshot with testID 1`] = `
|
||||
[
|
||||
"network.title",
|
||||
"network.message",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`MessageOverlay Component should match snapshot with button 1`] = `
|
||||
[
|
||||
"Test Title",
|
||||
"Test Message",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`MessageOverlay Component should match snapshot with custom children 1`] = `
|
||||
[
|
||||
"Test Title",
|
||||
"Test Message",
|
||||
<Text>
|
||||
Custom Content
|
||||
</Text>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`MessageOverlay Component should match snapshot with custom minHeight 1`] = `
|
||||
[
|
||||
"Test Title",
|
||||
"Test Message",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`MessageOverlay Component should match snapshot with hint text 1`] = `
|
||||
[
|
||||
"Test Title",
|
||||
"Test Message",
|
||||
"This is a hint",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`MessageOverlay Component should match snapshot with numeric progress 1`] = `
|
||||
[
|
||||
"Test Title",
|
||||
"Test Message",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`MessageOverlay Component should match snapshot with progress indicator 1`] = `
|
||||
[
|
||||
"Test Title",
|
||||
"Test Message",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`MessageOverlay Component should match snapshot with title and message 1`] = `
|
||||
[
|
||||
"Test Title",
|
||||
"Test Message",
|
||||
]
|
||||
`;
|
||||
629
components/__snapshots__/Passcode.test.tsx.snap
Normal file
629
components/__snapshots__/Passcode.test.tsx.snap
Normal file
@@ -0,0 +1,629 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Passcode Component should match snapshot with both message and error 1`] = `
|
||||
<Modal
|
||||
animationType="slide"
|
||||
hardwareAccelerated={false}
|
||||
onRequestClose={[MockFunction]}
|
||||
style={
|
||||
{
|
||||
"height": 1334,
|
||||
"width": 750,
|
||||
}
|
||||
}
|
||||
visible={true}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
{
|
||||
"flex": 1,
|
||||
},
|
||||
{
|
||||
"paddingBottom": 32,
|
||||
"paddingEnd": 32,
|
||||
"paddingStart": 32,
|
||||
"paddingTop": 32,
|
||||
},
|
||||
null,
|
||||
{
|
||||
"backgroundColor": "#FFFFFF",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
{
|
||||
"flex": 1,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"width": "100%",
|
||||
},
|
||||
null,
|
||||
{
|
||||
"justifyContent": "space-between",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<Text
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"lineHeight": 18,
|
||||
},
|
||||
{
|
||||
"fontFamily": "Inter_400Regular",
|
||||
"fontSize": 14,
|
||||
},
|
||||
null,
|
||||
{
|
||||
"textAlign": "center",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
Enter passcode
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
{
|
||||
"flex": 1,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<Text
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"lineHeight": 18,
|
||||
},
|
||||
{
|
||||
"fontFamily": "Inter_400Regular",
|
||||
"fontSize": 14,
|
||||
},
|
||||
{
|
||||
"color": "#D52929",
|
||||
},
|
||||
{
|
||||
"textAlign": "center",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
Authentication failed
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</Modal>
|
||||
`;
|
||||
|
||||
exports[`Passcode Component should match snapshot with custom message 1`] = `
|
||||
<Modal
|
||||
animationType="slide"
|
||||
hardwareAccelerated={false}
|
||||
onRequestClose={[MockFunction]}
|
||||
style={
|
||||
{
|
||||
"height": 1334,
|
||||
"width": 750,
|
||||
}
|
||||
}
|
||||
visible={true}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
{
|
||||
"flex": 1,
|
||||
},
|
||||
{
|
||||
"paddingBottom": 32,
|
||||
"paddingEnd": 32,
|
||||
"paddingStart": 32,
|
||||
"paddingTop": 32,
|
||||
},
|
||||
null,
|
||||
{
|
||||
"backgroundColor": "#FFFFFF",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
{
|
||||
"flex": 1,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"width": "100%",
|
||||
},
|
||||
null,
|
||||
{
|
||||
"justifyContent": "space-between",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<Text
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"lineHeight": 18,
|
||||
},
|
||||
{
|
||||
"fontFamily": "Inter_400Regular",
|
||||
"fontSize": 14,
|
||||
},
|
||||
null,
|
||||
{
|
||||
"textAlign": "center",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
Please enter your 6-digit passcode
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
{
|
||||
"flex": 1,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<Text
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"lineHeight": 18,
|
||||
},
|
||||
{
|
||||
"fontFamily": "Inter_400Regular",
|
||||
"fontSize": 14,
|
||||
},
|
||||
{
|
||||
"color": "#D52929",
|
||||
},
|
||||
{
|
||||
"textAlign": "center",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</Modal>
|
||||
`;
|
||||
|
||||
exports[`Passcode Component should match snapshot with default props 1`] = `
|
||||
<Modal
|
||||
animationType="slide"
|
||||
hardwareAccelerated={false}
|
||||
onRequestClose={[MockFunction]}
|
||||
style={
|
||||
{
|
||||
"height": 1334,
|
||||
"width": 750,
|
||||
}
|
||||
}
|
||||
visible={true}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
{
|
||||
"flex": 1,
|
||||
},
|
||||
{
|
||||
"paddingBottom": 32,
|
||||
"paddingEnd": 32,
|
||||
"paddingStart": 32,
|
||||
"paddingTop": 32,
|
||||
},
|
||||
null,
|
||||
{
|
||||
"backgroundColor": "#FFFFFF",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
{
|
||||
"flex": 1,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"width": "100%",
|
||||
},
|
||||
null,
|
||||
{
|
||||
"justifyContent": "space-between",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<Text
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"lineHeight": 18,
|
||||
},
|
||||
{
|
||||
"fontFamily": "Inter_400Regular",
|
||||
"fontSize": 14,
|
||||
},
|
||||
null,
|
||||
{
|
||||
"textAlign": "center",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
Enter your passcode
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
{
|
||||
"flex": 1,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<Text
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"lineHeight": 18,
|
||||
},
|
||||
{
|
||||
"fontFamily": "Inter_400Regular",
|
||||
"fontSize": 14,
|
||||
},
|
||||
{
|
||||
"color": "#D52929",
|
||||
},
|
||||
{
|
||||
"textAlign": "center",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</Modal>
|
||||
`;
|
||||
|
||||
exports[`Passcode Component should match snapshot with error message 1`] = `
|
||||
<Modal
|
||||
animationType="slide"
|
||||
hardwareAccelerated={false}
|
||||
onRequestClose={[MockFunction]}
|
||||
style={
|
||||
{
|
||||
"height": 1334,
|
||||
"width": 750,
|
||||
}
|
||||
}
|
||||
visible={true}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
{
|
||||
"flex": 1,
|
||||
},
|
||||
{
|
||||
"paddingBottom": 32,
|
||||
"paddingEnd": 32,
|
||||
"paddingStart": 32,
|
||||
"paddingTop": 32,
|
||||
},
|
||||
null,
|
||||
{
|
||||
"backgroundColor": "#FFFFFF",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
{
|
||||
"flex": 1,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"width": "100%",
|
||||
},
|
||||
null,
|
||||
{
|
||||
"justifyContent": "space-between",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<Text
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"lineHeight": 18,
|
||||
},
|
||||
{
|
||||
"fontFamily": "Inter_400Regular",
|
||||
"fontSize": 14,
|
||||
},
|
||||
null,
|
||||
{
|
||||
"textAlign": "center",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
Enter your passcode
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "column",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
{
|
||||
"flex": 1,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<Text
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#000000",
|
||||
"fontSize": 16,
|
||||
"lineHeight": 18,
|
||||
},
|
||||
{
|
||||
"fontFamily": "Inter_400Regular",
|
||||
"fontSize": 14,
|
||||
},
|
||||
{
|
||||
"color": "#D52929",
|
||||
},
|
||||
{
|
||||
"textAlign": "center",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
Incorrect passcode. Try again.
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</Modal>
|
||||
`;
|
||||
7
components/__snapshots__/PasscodeVerify.test.tsx.snap
Normal file
7
components/__snapshots__/PasscodeVerify.test.tsx.snap
Normal file
@@ -0,0 +1,7 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`PasscodeVerify Component should match snapshot with default props 1`] = `null`;
|
||||
|
||||
exports[`PasscodeVerify Component should match snapshot with different testID 1`] = `null`;
|
||||
|
||||
exports[`PasscodeVerify Component should match snapshot without onError handler 1`] = `null`;
|
||||
39
components/__snapshots__/PendingIcon.test.tsx.snap
Normal file
39
components/__snapshots__/PendingIcon.test.tsx.snap
Normal file
@@ -0,0 +1,39 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`PendingIcon should match snapshot 1`] = `
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"marginRight": 3,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"backgroundColor": "white",
|
||||
"borderRadius": 10,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`PendingIcon should render with custom color 1`] = `
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"marginRight": 3,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"backgroundColor": "white",
|
||||
"borderRadius": 10,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
`;
|
||||
719
components/__snapshots__/PinInput.test.tsx.snap
Normal file
719
components/__snapshots__/PinInput.test.tsx.snap
Normal file
@@ -0,0 +1,719 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`PinInput Component should match snapshot with 4 digit PIN 1`] = `
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"width": "66.66666666666667%",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<TextInput
|
||||
contextMenuHidden={true}
|
||||
keyboardType="numeric"
|
||||
maxLength={1}
|
||||
onChangeText={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyPress={[Function]}
|
||||
secureTextEntry={true}
|
||||
selectTextOnFocus={true}
|
||||
selectionColor="#951F6F"
|
||||
style={
|
||||
{
|
||||
"borderBottomWidth": 3,
|
||||
"borderColor": "#951F6F",
|
||||
"color": "#000000",
|
||||
"flex": 1,
|
||||
"fontFamily": "Inter_700Bold",
|
||||
"fontSize": 29,
|
||||
"height": 50,
|
||||
"margin": 8,
|
||||
"textAlign": "center",
|
||||
}
|
||||
}
|
||||
value=""
|
||||
/>
|
||||
<TextInput
|
||||
contextMenuHidden={true}
|
||||
keyboardType="numeric"
|
||||
maxLength={1}
|
||||
onChangeText={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyPress={[Function]}
|
||||
secureTextEntry={true}
|
||||
selectTextOnFocus={true}
|
||||
selectionColor="#951F6F"
|
||||
style={
|
||||
{
|
||||
"borderBottomWidth": 3,
|
||||
"borderColor": "#C7C7C7",
|
||||
"color": "#000000",
|
||||
"flex": 1,
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 33,
|
||||
"height": 50,
|
||||
"lineHeight": 28,
|
||||
"margin": 8,
|
||||
"textAlign": "center",
|
||||
}
|
||||
}
|
||||
value=""
|
||||
/>
|
||||
<TextInput
|
||||
contextMenuHidden={true}
|
||||
keyboardType="numeric"
|
||||
maxLength={1}
|
||||
onChangeText={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyPress={[Function]}
|
||||
secureTextEntry={true}
|
||||
selectTextOnFocus={true}
|
||||
selectionColor="#951F6F"
|
||||
style={
|
||||
{
|
||||
"borderBottomWidth": 3,
|
||||
"borderColor": "#C7C7C7",
|
||||
"color": "#000000",
|
||||
"flex": 1,
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 33,
|
||||
"height": 50,
|
||||
"lineHeight": 28,
|
||||
"margin": 8,
|
||||
"textAlign": "center",
|
||||
}
|
||||
}
|
||||
value=""
|
||||
/>
|
||||
<TextInput
|
||||
contextMenuHidden={true}
|
||||
keyboardType="numeric"
|
||||
maxLength={1}
|
||||
onChangeText={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyPress={[Function]}
|
||||
secureTextEntry={true}
|
||||
selectTextOnFocus={true}
|
||||
selectionColor="#951F6F"
|
||||
style={
|
||||
{
|
||||
"borderBottomWidth": 3,
|
||||
"borderColor": "#C7C7C7",
|
||||
"color": "#000000",
|
||||
"flex": 1,
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 33,
|
||||
"height": 50,
|
||||
"lineHeight": 28,
|
||||
"margin": 8,
|
||||
"textAlign": "center",
|
||||
}
|
||||
}
|
||||
value=""
|
||||
/>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`PinInput Component should match snapshot with 6 digit PIN 1`] = `
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"width": "100%",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<TextInput
|
||||
contextMenuHidden={true}
|
||||
keyboardType="numeric"
|
||||
maxLength={1}
|
||||
onChangeText={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyPress={[Function]}
|
||||
secureTextEntry={true}
|
||||
selectTextOnFocus={true}
|
||||
selectionColor="#951F6F"
|
||||
style={
|
||||
{
|
||||
"borderBottomWidth": 3,
|
||||
"borderColor": "#951F6F",
|
||||
"color": "#000000",
|
||||
"flex": 1,
|
||||
"fontFamily": "Inter_700Bold",
|
||||
"fontSize": 29,
|
||||
"height": 50,
|
||||
"margin": 8,
|
||||
"textAlign": "center",
|
||||
}
|
||||
}
|
||||
value=""
|
||||
/>
|
||||
<TextInput
|
||||
contextMenuHidden={true}
|
||||
keyboardType="numeric"
|
||||
maxLength={1}
|
||||
onChangeText={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyPress={[Function]}
|
||||
secureTextEntry={true}
|
||||
selectTextOnFocus={true}
|
||||
selectionColor="#951F6F"
|
||||
style={
|
||||
{
|
||||
"borderBottomWidth": 3,
|
||||
"borderColor": "#C7C7C7",
|
||||
"color": "#000000",
|
||||
"flex": 1,
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 33,
|
||||
"height": 50,
|
||||
"lineHeight": 28,
|
||||
"margin": 8,
|
||||
"textAlign": "center",
|
||||
}
|
||||
}
|
||||
value=""
|
||||
/>
|
||||
<TextInput
|
||||
contextMenuHidden={true}
|
||||
keyboardType="numeric"
|
||||
maxLength={1}
|
||||
onChangeText={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyPress={[Function]}
|
||||
secureTextEntry={true}
|
||||
selectTextOnFocus={true}
|
||||
selectionColor="#951F6F"
|
||||
style={
|
||||
{
|
||||
"borderBottomWidth": 3,
|
||||
"borderColor": "#C7C7C7",
|
||||
"color": "#000000",
|
||||
"flex": 1,
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 33,
|
||||
"height": 50,
|
||||
"lineHeight": 28,
|
||||
"margin": 8,
|
||||
"textAlign": "center",
|
||||
}
|
||||
}
|
||||
value=""
|
||||
/>
|
||||
<TextInput
|
||||
contextMenuHidden={true}
|
||||
keyboardType="numeric"
|
||||
maxLength={1}
|
||||
onChangeText={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyPress={[Function]}
|
||||
secureTextEntry={true}
|
||||
selectTextOnFocus={true}
|
||||
selectionColor="#951F6F"
|
||||
style={
|
||||
{
|
||||
"borderBottomWidth": 3,
|
||||
"borderColor": "#C7C7C7",
|
||||
"color": "#000000",
|
||||
"flex": 1,
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 33,
|
||||
"height": 50,
|
||||
"lineHeight": 28,
|
||||
"margin": 8,
|
||||
"textAlign": "center",
|
||||
}
|
||||
}
|
||||
value=""
|
||||
/>
|
||||
<TextInput
|
||||
contextMenuHidden={true}
|
||||
keyboardType="numeric"
|
||||
maxLength={1}
|
||||
onChangeText={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyPress={[Function]}
|
||||
secureTextEntry={true}
|
||||
selectTextOnFocus={true}
|
||||
selectionColor="#951F6F"
|
||||
style={
|
||||
{
|
||||
"borderBottomWidth": 3,
|
||||
"borderColor": "#C7C7C7",
|
||||
"color": "#000000",
|
||||
"flex": 1,
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 33,
|
||||
"height": 50,
|
||||
"lineHeight": 28,
|
||||
"margin": 8,
|
||||
"textAlign": "center",
|
||||
}
|
||||
}
|
||||
value=""
|
||||
/>
|
||||
<TextInput
|
||||
contextMenuHidden={true}
|
||||
keyboardType="numeric"
|
||||
maxLength={1}
|
||||
onChangeText={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyPress={[Function]}
|
||||
secureTextEntry={true}
|
||||
selectTextOnFocus={true}
|
||||
selectionColor="#951F6F"
|
||||
style={
|
||||
{
|
||||
"borderBottomWidth": 3,
|
||||
"borderColor": "#C7C7C7",
|
||||
"color": "#000000",
|
||||
"flex": 1,
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 33,
|
||||
"height": 50,
|
||||
"lineHeight": 28,
|
||||
"margin": 8,
|
||||
"textAlign": "center",
|
||||
}
|
||||
}
|
||||
value=""
|
||||
/>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`PinInput Component should match snapshot with custom testID 1`] = `
|
||||
<View
|
||||
accessibilityLabel="customPinInput"
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"width": "66.66666666666667%",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<TextInput
|
||||
contextMenuHidden={true}
|
||||
keyboardType="numeric"
|
||||
maxLength={1}
|
||||
onChangeText={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyPress={[Function]}
|
||||
secureTextEntry={true}
|
||||
selectTextOnFocus={true}
|
||||
selectionColor="#951F6F"
|
||||
style={
|
||||
{
|
||||
"borderBottomWidth": 3,
|
||||
"borderColor": "#951F6F",
|
||||
"color": "#000000",
|
||||
"flex": 1,
|
||||
"fontFamily": "Inter_700Bold",
|
||||
"fontSize": 29,
|
||||
"height": 50,
|
||||
"margin": 8,
|
||||
"textAlign": "center",
|
||||
}
|
||||
}
|
||||
value=""
|
||||
/>
|
||||
<TextInput
|
||||
contextMenuHidden={true}
|
||||
keyboardType="numeric"
|
||||
maxLength={1}
|
||||
onChangeText={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyPress={[Function]}
|
||||
secureTextEntry={true}
|
||||
selectTextOnFocus={true}
|
||||
selectionColor="#951F6F"
|
||||
style={
|
||||
{
|
||||
"borderBottomWidth": 3,
|
||||
"borderColor": "#C7C7C7",
|
||||
"color": "#000000",
|
||||
"flex": 1,
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 33,
|
||||
"height": 50,
|
||||
"lineHeight": 28,
|
||||
"margin": 8,
|
||||
"textAlign": "center",
|
||||
}
|
||||
}
|
||||
value=""
|
||||
/>
|
||||
<TextInput
|
||||
contextMenuHidden={true}
|
||||
keyboardType="numeric"
|
||||
maxLength={1}
|
||||
onChangeText={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyPress={[Function]}
|
||||
secureTextEntry={true}
|
||||
selectTextOnFocus={true}
|
||||
selectionColor="#951F6F"
|
||||
style={
|
||||
{
|
||||
"borderBottomWidth": 3,
|
||||
"borderColor": "#C7C7C7",
|
||||
"color": "#000000",
|
||||
"flex": 1,
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 33,
|
||||
"height": 50,
|
||||
"lineHeight": 28,
|
||||
"margin": 8,
|
||||
"textAlign": "center",
|
||||
}
|
||||
}
|
||||
value=""
|
||||
/>
|
||||
<TextInput
|
||||
contextMenuHidden={true}
|
||||
keyboardType="numeric"
|
||||
maxLength={1}
|
||||
onChangeText={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyPress={[Function]}
|
||||
secureTextEntry={true}
|
||||
selectTextOnFocus={true}
|
||||
selectionColor="#951F6F"
|
||||
style={
|
||||
{
|
||||
"borderBottomWidth": 3,
|
||||
"borderColor": "#C7C7C7",
|
||||
"color": "#000000",
|
||||
"flex": 1,
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 33,
|
||||
"height": 50,
|
||||
"lineHeight": 28,
|
||||
"margin": 8,
|
||||
"textAlign": "center",
|
||||
}
|
||||
}
|
||||
value=""
|
||||
/>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`PinInput Component should match snapshot with onChange handler 1`] = `
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"width": "66.66666666666667%",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<TextInput
|
||||
contextMenuHidden={true}
|
||||
keyboardType="numeric"
|
||||
maxLength={1}
|
||||
onChangeText={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyPress={[Function]}
|
||||
secureTextEntry={true}
|
||||
selectTextOnFocus={true}
|
||||
selectionColor="#951F6F"
|
||||
style={
|
||||
{
|
||||
"borderBottomWidth": 3,
|
||||
"borderColor": "#951F6F",
|
||||
"color": "#000000",
|
||||
"flex": 1,
|
||||
"fontFamily": "Inter_700Bold",
|
||||
"fontSize": 29,
|
||||
"height": 50,
|
||||
"margin": 8,
|
||||
"textAlign": "center",
|
||||
}
|
||||
}
|
||||
value=""
|
||||
/>
|
||||
<TextInput
|
||||
contextMenuHidden={true}
|
||||
keyboardType="numeric"
|
||||
maxLength={1}
|
||||
onChangeText={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyPress={[Function]}
|
||||
secureTextEntry={true}
|
||||
selectTextOnFocus={true}
|
||||
selectionColor="#951F6F"
|
||||
style={
|
||||
{
|
||||
"borderBottomWidth": 3,
|
||||
"borderColor": "#C7C7C7",
|
||||
"color": "#000000",
|
||||
"flex": 1,
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 33,
|
||||
"height": 50,
|
||||
"lineHeight": 28,
|
||||
"margin": 8,
|
||||
"textAlign": "center",
|
||||
}
|
||||
}
|
||||
value=""
|
||||
/>
|
||||
<TextInput
|
||||
contextMenuHidden={true}
|
||||
keyboardType="numeric"
|
||||
maxLength={1}
|
||||
onChangeText={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyPress={[Function]}
|
||||
secureTextEntry={true}
|
||||
selectTextOnFocus={true}
|
||||
selectionColor="#951F6F"
|
||||
style={
|
||||
{
|
||||
"borderBottomWidth": 3,
|
||||
"borderColor": "#C7C7C7",
|
||||
"color": "#000000",
|
||||
"flex": 1,
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 33,
|
||||
"height": 50,
|
||||
"lineHeight": 28,
|
||||
"margin": 8,
|
||||
"textAlign": "center",
|
||||
}
|
||||
}
|
||||
value=""
|
||||
/>
|
||||
<TextInput
|
||||
contextMenuHidden={true}
|
||||
keyboardType="numeric"
|
||||
maxLength={1}
|
||||
onChangeText={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyPress={[Function]}
|
||||
secureTextEntry={true}
|
||||
selectTextOnFocus={true}
|
||||
selectionColor="#951F6F"
|
||||
style={
|
||||
{
|
||||
"borderBottomWidth": 3,
|
||||
"borderColor": "#C7C7C7",
|
||||
"color": "#000000",
|
||||
"flex": 1,
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 33,
|
||||
"height": 50,
|
||||
"lineHeight": 28,
|
||||
"margin": 8,
|
||||
"textAlign": "center",
|
||||
}
|
||||
}
|
||||
value=""
|
||||
/>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`PinInput Component should match snapshot with onDone and autosubmit 1`] = `
|
||||
<View
|
||||
accessible={true}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"alignItems": undefined,
|
||||
"flexDirection": "row",
|
||||
"justifyContent": undefined,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"width": "66.66666666666667%",
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<TextInput
|
||||
contextMenuHidden={true}
|
||||
keyboardType="numeric"
|
||||
maxLength={1}
|
||||
onChangeText={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyPress={[Function]}
|
||||
secureTextEntry={true}
|
||||
selectTextOnFocus={true}
|
||||
selectionColor="#951F6F"
|
||||
style={
|
||||
{
|
||||
"borderBottomWidth": 3,
|
||||
"borderColor": "#951F6F",
|
||||
"color": "#000000",
|
||||
"flex": 1,
|
||||
"fontFamily": "Inter_700Bold",
|
||||
"fontSize": 29,
|
||||
"height": 50,
|
||||
"margin": 8,
|
||||
"textAlign": "center",
|
||||
}
|
||||
}
|
||||
value=""
|
||||
/>
|
||||
<TextInput
|
||||
contextMenuHidden={true}
|
||||
keyboardType="numeric"
|
||||
maxLength={1}
|
||||
onChangeText={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyPress={[Function]}
|
||||
secureTextEntry={true}
|
||||
selectTextOnFocus={true}
|
||||
selectionColor="#951F6F"
|
||||
style={
|
||||
{
|
||||
"borderBottomWidth": 3,
|
||||
"borderColor": "#C7C7C7",
|
||||
"color": "#000000",
|
||||
"flex": 1,
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 33,
|
||||
"height": 50,
|
||||
"lineHeight": 28,
|
||||
"margin": 8,
|
||||
"textAlign": "center",
|
||||
}
|
||||
}
|
||||
value=""
|
||||
/>
|
||||
<TextInput
|
||||
contextMenuHidden={true}
|
||||
keyboardType="numeric"
|
||||
maxLength={1}
|
||||
onChangeText={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyPress={[Function]}
|
||||
secureTextEntry={true}
|
||||
selectTextOnFocus={true}
|
||||
selectionColor="#951F6F"
|
||||
style={
|
||||
{
|
||||
"borderBottomWidth": 3,
|
||||
"borderColor": "#C7C7C7",
|
||||
"color": "#000000",
|
||||
"flex": 1,
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 33,
|
||||
"height": 50,
|
||||
"lineHeight": 28,
|
||||
"margin": 8,
|
||||
"textAlign": "center",
|
||||
}
|
||||
}
|
||||
value=""
|
||||
/>
|
||||
<TextInput
|
||||
contextMenuHidden={true}
|
||||
keyboardType="numeric"
|
||||
maxLength={1}
|
||||
onChangeText={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyPress={[Function]}
|
||||
secureTextEntry={true}
|
||||
selectTextOnFocus={true}
|
||||
selectionColor="#951F6F"
|
||||
style={
|
||||
{
|
||||
"borderBottomWidth": 3,
|
||||
"borderColor": "#C7C7C7",
|
||||
"color": "#000000",
|
||||
"flex": 1,
|
||||
"fontFamily": "Inter_600SemiBold",
|
||||
"fontSize": 33,
|
||||
"height": 50,
|
||||
"lineHeight": 28,
|
||||
"margin": 8,
|
||||
"textAlign": "center",
|
||||
}
|
||||
}
|
||||
value=""
|
||||
/>
|
||||
</View>
|
||||
`;
|
||||
82
components/__snapshots__/ProfileIcon.test.tsx.snap
Normal file
82
components/__snapshots__/ProfileIcon.test.tsx.snap
Normal file
@@ -0,0 +1,82 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ProfileIcon Component should match snapshot with custom container styles 1`] = `
|
||||
<View
|
||||
accessibilityLabel="ProfileIconOuter"
|
||||
accessible={true}
|
||||
style={
|
||||
{
|
||||
"position": "relative",
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessibilityLabel="ProfileIconInner"
|
||||
accessible={true}
|
||||
style={
|
||||
{
|
||||
"backgroundColor": "blue",
|
||||
"borderRadius": 10,
|
||||
"padding": 5,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`ProfileIcon Component should match snapshot with custom icon size 1`] = `
|
||||
<View
|
||||
accessibilityLabel="ProfileIconOuter"
|
||||
accessible={true}
|
||||
style={
|
||||
{
|
||||
"position": "relative",
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessibilityLabel="ProfileIconInner"
|
||||
accessible={true}
|
||||
style={{}}
|
||||
/>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`ProfileIcon Component should match snapshot with pinned icon 1`] = `
|
||||
<View
|
||||
accessibilityLabel="ProfileIconOuter"
|
||||
accessible={true}
|
||||
style={
|
||||
{
|
||||
"position": "relative",
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessibilityLabel="ProfileIconInner"
|
||||
accessible={true}
|
||||
style={{}}
|
||||
/>
|
||||
<View
|
||||
testID="mockPinIcon"
|
||||
/>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`ProfileIcon Component should match snapshot without pinned icon 1`] = `
|
||||
<View
|
||||
accessibilityLabel="ProfileIconOuter"
|
||||
accessible={true}
|
||||
style={
|
||||
{
|
||||
"position": "relative",
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
accessibilityLabel="ProfileIconInner"
|
||||
accessible={true}
|
||||
style={{}}
|
||||
/>
|
||||
</View>
|
||||
`;
|
||||
25
components/__snapshots__/ProgressingModal.test.tsx.snap
Normal file
25
components/__snapshots__/ProgressingModal.test.tsx.snap
Normal file
@@ -0,0 +1,25 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ProgressingModal Component should match snapshot as requester 1`] = `null`;
|
||||
|
||||
exports[`ProgressingModal Component should match snapshot with BLE error visible 1`] = `"Bluetooth error occurred"`;
|
||||
|
||||
exports[`ProgressingModal Component should match snapshot with default props 1`] = `null`;
|
||||
|
||||
exports[`ProgressingModal Component should match snapshot with hint visible 1`] = `"Please wait..."`;
|
||||
|
||||
exports[`ProgressingModal Component should match snapshot with progress spinner 1`] = `
|
||||
<Spinner
|
||||
color="#951F6F"
|
||||
style={
|
||||
{
|
||||
"marginLeft": 6,
|
||||
}
|
||||
}
|
||||
type="ThreeBounce"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`ProgressingModal Component should match snapshot with retry button 1`] = `"Connection failed"`;
|
||||
|
||||
exports[`ProgressingModal Component should match snapshot with stay in progress button 1`] = `"Taking longer than expected"`;
|
||||
9
components/__snapshots__/QrCodeOverlay.test.tsx.snap
Normal file
9
components/__snapshots__/QrCodeOverlay.test.tsx.snap
Normal file
@@ -0,0 +1,9 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`QrCodeOverlay Component should match snapshot with default props 1`] = `null`;
|
||||
|
||||
exports[`QrCodeOverlay Component should match snapshot with force visible 1`] = `null`;
|
||||
|
||||
exports[`QrCodeOverlay Component should match snapshot with inline QR disabled 1`] = `null`;
|
||||
|
||||
exports[`QrCodeOverlay Component should match snapshot with onClose handler 1`] = `null`;
|
||||
7
components/__snapshots__/QrScanner.test.tsx.snap
Normal file
7
components/__snapshots__/QrScanner.test.tsx.snap
Normal file
@@ -0,0 +1,7 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`QrScanner Component should match snapshot with custom title 1`] = `<View />`;
|
||||
|
||||
exports[`QrScanner Component should match snapshot with default props 1`] = `<View />`;
|
||||
|
||||
exports[`QrScanner Component should match snapshot with title 1`] = `<View />`;
|
||||
165
components/__snapshots__/SectionLayout.test.tsx.snap
Normal file
165
components/__snapshots__/SectionLayout.test.tsx.snap
Normal file
@@ -0,0 +1,165 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`SectionLayout Component should match snapshot with complex children 1`] = `
|
||||
<View
|
||||
accessibilityLabel="testSection"
|
||||
accessible={true}
|
||||
style={
|
||||
{
|
||||
"marginBottom": 0,
|
||||
"marginLeft": 18,
|
||||
"marginRight": 18,
|
||||
"marginTop": 16,
|
||||
"rowGap": 2,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
testID="headerIcon"
|
||||
>
|
||||
Icon
|
||||
</View>
|
||||
Section Header
|
||||
<Text>
|
||||
Line 1
|
||||
</Text>
|
||||
<Text>
|
||||
Line 2
|
||||
</Text>
|
||||
<View>
|
||||
<Text>
|
||||
Nested content
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`SectionLayout Component should match snapshot with custom marginBottom 1`] = `
|
||||
<View
|
||||
accessibilityLabel="testSection"
|
||||
accessible={true}
|
||||
style={
|
||||
{
|
||||
"marginBottom": 20,
|
||||
"marginLeft": 18,
|
||||
"marginRight": 18,
|
||||
"marginTop": 16,
|
||||
"rowGap": 2,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
testID="headerIcon"
|
||||
>
|
||||
Icon
|
||||
</View>
|
||||
Section Header
|
||||
<Text>
|
||||
Section Content
|
||||
</Text>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`SectionLayout Component should match snapshot with default props 1`] = `
|
||||
<View
|
||||
accessibilityLabel="testSection"
|
||||
accessible={true}
|
||||
style={
|
||||
{
|
||||
"marginBottom": 0,
|
||||
"marginLeft": 18,
|
||||
"marginRight": 18,
|
||||
"marginTop": 16,
|
||||
"rowGap": 2,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
testID="headerIcon"
|
||||
>
|
||||
Icon
|
||||
</View>
|
||||
Section Header
|
||||
<Text>
|
||||
Section Content
|
||||
</Text>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`SectionLayout Component should match snapshot with different header text 1`] = `
|
||||
<View
|
||||
accessibilityLabel="testSection"
|
||||
accessible={true}
|
||||
style={
|
||||
{
|
||||
"marginBottom": 0,
|
||||
"marginLeft": 18,
|
||||
"marginRight": 18,
|
||||
"marginTop": 16,
|
||||
"rowGap": 2,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
testID="headerIcon"
|
||||
>
|
||||
Icon
|
||||
</View>
|
||||
Custom Section Title
|
||||
<Text>
|
||||
Section Content
|
||||
</Text>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`SectionLayout Component should match snapshot with different icon 1`] = `
|
||||
<View
|
||||
accessibilityLabel="testSection"
|
||||
accessible={true}
|
||||
style={
|
||||
{
|
||||
"marginBottom": 0,
|
||||
"marginLeft": 18,
|
||||
"marginRight": 18,
|
||||
"marginTop": 16,
|
||||
"rowGap": 2,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
testID="customIcon"
|
||||
>
|
||||
🔍
|
||||
</View>
|
||||
Section Header
|
||||
<Text>
|
||||
Section Content
|
||||
</Text>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`SectionLayout Component should match snapshot with zero marginBottom 1`] = `
|
||||
<View
|
||||
accessibilityLabel="testSection"
|
||||
accessible={true}
|
||||
style={
|
||||
{
|
||||
"marginBottom": 0,
|
||||
"marginLeft": 18,
|
||||
"marginRight": 18,
|
||||
"marginTop": 16,
|
||||
"rowGap": 2,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
testID="headerIcon"
|
||||
>
|
||||
Icon
|
||||
</View>
|
||||
Section Header
|
||||
<Text>
|
||||
Section Content
|
||||
</Text>
|
||||
</View>
|
||||
`;
|
||||
501
components/__snapshots__/TextEditOverlay.test.tsx.snap
Normal file
501
components/__snapshots__/TextEditOverlay.test.tsx.snap
Normal file
@@ -0,0 +1,501 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`TextEditOverlay Component should match snapshot with default props 1`] = `
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"backgroundColor": "rgba(0,0,0,.6)",
|
||||
"height": 1334,
|
||||
"position": "absolute",
|
||||
"top": 0,
|
||||
"width": 750,
|
||||
"zIndex": 9,
|
||||
}
|
||||
}
|
||||
>
|
||||
Edit Name
|
||||
<TextInput
|
||||
onChangeText={[MockFunction]}
|
||||
testID="text-input"
|
||||
value="John Doe"
|
||||
/>
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"opacity": 1,
|
||||
}
|
||||
}
|
||||
testID="button-cancel"
|
||||
>
|
||||
<Text>
|
||||
cancel
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"opacity": 1,
|
||||
}
|
||||
}
|
||||
testID="button-save"
|
||||
>
|
||||
<Text>
|
||||
save
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`TextEditOverlay Component should match snapshot with different label 1`] = `
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"backgroundColor": "rgba(0,0,0,.6)",
|
||||
"height": 1334,
|
||||
"position": "absolute",
|
||||
"top": 0,
|
||||
"width": 750,
|
||||
"zIndex": 9,
|
||||
}
|
||||
}
|
||||
>
|
||||
Edit Email
|
||||
<TextInput
|
||||
onChangeText={[MockFunction]}
|
||||
testID="text-input"
|
||||
value="John Doe"
|
||||
/>
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"opacity": 1,
|
||||
}
|
||||
}
|
||||
testID="button-cancel"
|
||||
>
|
||||
<Text>
|
||||
cancel
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"opacity": 1,
|
||||
}
|
||||
}
|
||||
testID="button-save"
|
||||
>
|
||||
<Text>
|
||||
save
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`TextEditOverlay Component should match snapshot with empty value 1`] = `
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"backgroundColor": "rgba(0,0,0,.6)",
|
||||
"height": 1334,
|
||||
"position": "absolute",
|
||||
"top": 0,
|
||||
"width": 750,
|
||||
"zIndex": 9,
|
||||
}
|
||||
}
|
||||
>
|
||||
Edit Name
|
||||
<TextInput
|
||||
onChangeText={[MockFunction]}
|
||||
testID="text-input"
|
||||
value=""
|
||||
/>
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"opacity": 1,
|
||||
}
|
||||
}
|
||||
testID="button-cancel"
|
||||
>
|
||||
<Text>
|
||||
cancel
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"opacity": 1,
|
||||
}
|
||||
}
|
||||
testID="button-save"
|
||||
>
|
||||
<Text>
|
||||
save
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`TextEditOverlay Component should match snapshot with long value 1`] = `
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"backgroundColor": "rgba(0,0,0,.6)",
|
||||
"height": 1334,
|
||||
"position": "absolute",
|
||||
"top": 0,
|
||||
"width": 750,
|
||||
"zIndex": 9,
|
||||
}
|
||||
}
|
||||
>
|
||||
Edit Name
|
||||
<TextInput
|
||||
onChangeText={[MockFunction]}
|
||||
testID="text-input"
|
||||
value="This is a very long text value that should be editable"
|
||||
/>
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"opacity": 1,
|
||||
}
|
||||
}
|
||||
testID="button-cancel"
|
||||
>
|
||||
<Text>
|
||||
cancel
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"opacity": 1,
|
||||
}
|
||||
}
|
||||
testID="button-save"
|
||||
>
|
||||
<Text>
|
||||
save
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`TextEditOverlay Component should match snapshot with maxLength 1`] = `
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"backgroundColor": "rgba(0,0,0,.6)",
|
||||
"height": 1334,
|
||||
"position": "absolute",
|
||||
"top": 0,
|
||||
"width": 750,
|
||||
"zIndex": 9,
|
||||
}
|
||||
}
|
||||
>
|
||||
Edit Name
|
||||
<TextInput
|
||||
onChangeText={[MockFunction]}
|
||||
testID="text-input"
|
||||
value="John Doe"
|
||||
/>
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"opacity": 1,
|
||||
}
|
||||
}
|
||||
testID="button-cancel"
|
||||
>
|
||||
<Text>
|
||||
cancel
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
accessibilityState={
|
||||
{
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessibilityValue={
|
||||
{
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"now": undefined,
|
||||
"text": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
style={
|
||||
{
|
||||
"opacity": 1,
|
||||
}
|
||||
}
|
||||
testID="button-save"
|
||||
>
|
||||
<Text>
|
||||
save
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
1287
components/__snapshots__/TrustModal.test.tsx.snap
Normal file
1287
components/__snapshots__/TrustModal.test.tsx.snap
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,104 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`VcItemContainerProfileImage Component should match snapshot with empty string face 1`] = `
|
||||
<View
|
||||
testID="mockProfileIcon"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`VcItemContainerProfileImage Component should match snapshot with face image 1`] = `
|
||||
<View
|
||||
accessibilityIgnoresInvertColors={true}
|
||||
style={
|
||||
{
|
||||
"borderRadius": 100,
|
||||
"height": 53,
|
||||
"width": 40,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Image
|
||||
source={
|
||||
{
|
||||
"uri": "https://example.com/avatar.jpg",
|
||||
}
|
||||
}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"bottom": 0,
|
||||
"left": 0,
|
||||
"position": "absolute",
|
||||
"right": 0,
|
||||
"top": 0,
|
||||
},
|
||||
{
|
||||
"height": 53,
|
||||
"width": 40,
|
||||
},
|
||||
{
|
||||
"borderRadius": 10,
|
||||
"height": 53,
|
||||
"width": 40,
|
||||
},
|
||||
]
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`VcItemContainerProfileImage Component should match snapshot with face image and pinned 1`] = `
|
||||
<View
|
||||
accessibilityIgnoresInvertColors={true}
|
||||
style={
|
||||
{
|
||||
"borderRadius": 100,
|
||||
"height": 53,
|
||||
"width": 40,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Image
|
||||
source={
|
||||
{
|
||||
"uri": "https://example.com/avatar.jpg",
|
||||
}
|
||||
}
|
||||
style={
|
||||
[
|
||||
{
|
||||
"bottom": 0,
|
||||
"left": 0,
|
||||
"position": "absolute",
|
||||
"right": 0,
|
||||
"top": 0,
|
||||
},
|
||||
{
|
||||
"height": 53,
|
||||
"width": 40,
|
||||
},
|
||||
{
|
||||
"borderRadius": 10,
|
||||
"height": 53,
|
||||
"width": 40,
|
||||
},
|
||||
]
|
||||
}
|
||||
/>
|
||||
<View
|
||||
testID="mockPinIcon"
|
||||
/>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`VcItemContainerProfileImage Component should match snapshot without face image 1`] = `
|
||||
<View
|
||||
testID="mockProfileIcon"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`VcItemContainerProfileImage Component should match snapshot without face image and pinned 1`] = `
|
||||
<View
|
||||
testID="mockProfileIcon"
|
||||
/>
|
||||
`;
|
||||
20
components/__snapshots__/VerifiedIcon.test.tsx.snap
Normal file
20
components/__snapshots__/VerifiedIcon.test.tsx.snap
Normal file
@@ -0,0 +1,20 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`VerifiedIcon should match snapshot 1`] = `
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"marginRight": 3,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
{
|
||||
"backgroundColor": "white",
|
||||
"borderRadius": 10,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
`;
|
||||
120
components/ui/Layout.test.tsx
Normal file
120
components/ui/Layout.test.tsx
Normal file
@@ -0,0 +1,120 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {Column, Row} from './Layout';
|
||||
import {Text} from 'react-native';
|
||||
|
||||
describe('Layout Components', () => {
|
||||
describe('Column Component', () => {
|
||||
it('should render Column component', () => {
|
||||
const {toJSON} = render(
|
||||
<Column>
|
||||
<Text>Test</Text>
|
||||
</Column>,
|
||||
);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render children in column', () => {
|
||||
const {getByText} = render(
|
||||
<Column>
|
||||
<Text>Child 1</Text>
|
||||
<Text>Child 2</Text>
|
||||
</Column>,
|
||||
);
|
||||
|
||||
expect(getByText('Child 1')).toBeTruthy();
|
||||
expect(getByText('Child 2')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render with fill prop', () => {
|
||||
const {getByLabelText} = render(
|
||||
<Column fill testID="fill-column">
|
||||
<Text>Fill Column</Text>
|
||||
</Column>,
|
||||
);
|
||||
expect(getByLabelText('fill-column')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render with multiple layout props', () => {
|
||||
const {getByLabelText} = render(
|
||||
<Column
|
||||
testID="complex-column"
|
||||
fill
|
||||
padding="10"
|
||||
margin="10 20"
|
||||
backgroundColor="#FF0000"
|
||||
align="center"
|
||||
crossAlign="center">
|
||||
<Text>Complex Column</Text>
|
||||
</Column>,
|
||||
);
|
||||
expect(getByLabelText('complex-column')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Row Component', () => {
|
||||
it('should render Row component', () => {
|
||||
const {toJSON} = render(
|
||||
<Row>
|
||||
<Text>Test</Text>
|
||||
</Row>,
|
||||
);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render children in row', () => {
|
||||
const {getByText} = render(
|
||||
<Row>
|
||||
<Text>Item 1</Text>
|
||||
<Text>Item 2</Text>
|
||||
<Text>Item 3</Text>
|
||||
</Row>,
|
||||
);
|
||||
|
||||
expect(getByText('Item 1')).toBeTruthy();
|
||||
expect(getByText('Item 2')).toBeTruthy();
|
||||
expect(getByText('Item 3')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render with fill prop', () => {
|
||||
const {getByLabelText} = render(
|
||||
<Row fill testID="fill-row">
|
||||
<Text>Fill Row</Text>
|
||||
</Row>,
|
||||
);
|
||||
expect(getByLabelText('fill-row')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render with multiple layout props', () => {
|
||||
const {getByLabelText} = render(
|
||||
<Row
|
||||
testID="complex-row"
|
||||
fill
|
||||
padding="10"
|
||||
margin="5"
|
||||
backgroundColor="#0000FF"
|
||||
align="center"
|
||||
crossAlign="center">
|
||||
<Text>Complex Row</Text>
|
||||
</Row>,
|
||||
);
|
||||
expect(getByLabelText('complex-row')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should handle nested layouts', () => {
|
||||
const {getByText} = render(
|
||||
<Row>
|
||||
<Column>
|
||||
<Text>Nested 1</Text>
|
||||
</Column>
|
||||
<Column>
|
||||
<Text>Nested 2</Text>
|
||||
</Column>
|
||||
</Row>,
|
||||
);
|
||||
|
||||
expect(getByText('Nested 1')).toBeTruthy();
|
||||
expect(getByText('Nested 2')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
111
components/ui/TextItem.test.tsx
Normal file
111
components/ui/TextItem.test.tsx
Normal file
@@ -0,0 +1,111 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {TextItem} from './TextItem';
|
||||
|
||||
describe('TextItem', () => {
|
||||
it('should render text without label', () => {
|
||||
const {getByText} = render(<TextItem text="Test Text" />);
|
||||
expect(getByText('Test Text')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render text with label', () => {
|
||||
const {getByText} = render(
|
||||
<TextItem text="Main Text" label="Label Text" />,
|
||||
);
|
||||
expect(getByText('Main Text')).toBeTruthy();
|
||||
expect(getByText('Label Text')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render only text when label is not provided', () => {
|
||||
const {getByText, queryByText} = render(<TextItem text="Only Text" />);
|
||||
expect(getByText('Only Text')).toBeTruthy();
|
||||
expect(queryByText('Label Text')).toBeNull();
|
||||
});
|
||||
|
||||
it('should render with testID prop', () => {
|
||||
const {toJSON} = render(<TextItem text="Test" testID="customTestID" />);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render with divider prop', () => {
|
||||
const {getByText} = render(<TextItem text="Test" divider={true} />);
|
||||
expect(getByText('Test')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render without divider when not specified', () => {
|
||||
const {getByText} = render(<TextItem text="Test" divider={false} />);
|
||||
expect(getByText('Test')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render with topDivider prop', () => {
|
||||
const {getByText} = render(<TextItem text="Test" topDivider={true} />);
|
||||
expect(getByText('Test')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render without topDivider when not specified', () => {
|
||||
const {getByText} = render(<TextItem text="Test" topDivider={false} />);
|
||||
expect(getByText('Test')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render with both dividers', () => {
|
||||
const {getByText} = render(
|
||||
<TextItem text="Test" divider={true} topDivider={true} />,
|
||||
);
|
||||
expect(getByText('Test')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render with custom margin when provided', () => {
|
||||
const {getByText} = render(<TextItem text="Test" margin="10" />);
|
||||
expect(getByText('Test')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render long text correctly', () => {
|
||||
const longText = 'A'.repeat(200);
|
||||
const {getByText} = render(<TextItem text={longText} />);
|
||||
expect(getByText(longText)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should handle empty text', () => {
|
||||
const {toJSON} = render(<TextItem text="" />);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should handle special characters in text', () => {
|
||||
const specialText = '!@#$%^&*()_+-={}[]|:";\'<>?,./';
|
||||
const {getByText} = render(<TextItem text={specialText} />);
|
||||
expect(getByText(specialText)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render with all props combined', () => {
|
||||
const {getByText} = render(
|
||||
<TextItem
|
||||
text="Complete Test"
|
||||
label="All Props"
|
||||
testID="allProps"
|
||||
divider={true}
|
||||
topDivider={true}
|
||||
margin="20"
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(getByText('Complete Test')).toBeTruthy();
|
||||
expect(getByText('All Props')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render multiple TextItems', () => {
|
||||
const {getByText} = render(
|
||||
<>
|
||||
<TextItem text="First" label="One" />
|
||||
<TextItem text="Second" label="Two" />
|
||||
<TextItem text="Third" label="Three" />
|
||||
</>,
|
||||
);
|
||||
|
||||
expect(getByText('First')).toBeTruthy();
|
||||
expect(getByText('Second')).toBeTruthy();
|
||||
expect(getByText('Third')).toBeTruthy();
|
||||
expect(getByText('One')).toBeTruthy();
|
||||
expect(getByText('Two')).toBeTruthy();
|
||||
expect(getByText('Three')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
87
components/ui/Timestamp.test.tsx
Normal file
87
components/ui/Timestamp.test.tsx
Normal file
@@ -0,0 +1,87 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {Timestamp} from './Timestamp';
|
||||
|
||||
describe('Timestamp', () => {
|
||||
it('should render formatted date and time', () => {
|
||||
// March 15, 2024 at 14:30:00
|
||||
const timestamp = new Date(2024, 2, 15, 14, 30, 0).getTime();
|
||||
const {getByText} = render(<Timestamp time={timestamp} testId="test" />);
|
||||
|
||||
const formatted = getByText(/15 March 2024/);
|
||||
expect(formatted).toBeTruthy();
|
||||
expect(formatted.props.children).toContain('PM');
|
||||
});
|
||||
|
||||
it('should format AM time correctly', () => {
|
||||
// March 15, 2024 at 09:15:00
|
||||
const timestamp = new Date(2024, 2, 15, 9, 15, 0).getTime();
|
||||
const {getByText} = render(<Timestamp time={timestamp} testId="morning" />);
|
||||
|
||||
const formatted = getByText(/09:15 AM/);
|
||||
expect(formatted).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should format PM time correctly', () => {
|
||||
// June 20, 2024 at 18:45:00
|
||||
const timestamp = new Date(2024, 5, 20, 18, 45, 0).getTime();
|
||||
const {getByText} = render(<Timestamp time={timestamp} testId="evening" />);
|
||||
|
||||
const formatted = getByText(/06:45 PM/);
|
||||
expect(formatted).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should handle midnight correctly', () => {
|
||||
// January 1, 2024 at 00:00:00
|
||||
const timestamp = new Date(2024, 0, 1, 0, 0, 0).getTime();
|
||||
const {getByText} = render(
|
||||
<Timestamp time={timestamp} testId="midnight" />,
|
||||
);
|
||||
|
||||
const formatted = getByText(/12:00 AM/);
|
||||
expect(formatted).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should handle noon correctly', () => {
|
||||
// December 25, 2023 at 12:00:00
|
||||
const timestamp = new Date(2023, 11, 25, 12, 0, 0).getTime();
|
||||
const {getByText} = render(<Timestamp time={timestamp} testId="noon" />);
|
||||
|
||||
const formatted = getByText(/12:00 PM/);
|
||||
expect(formatted).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should pad single digit minutes with zero', () => {
|
||||
// April 10, 2024 at 15:05:00
|
||||
const timestamp = new Date(2024, 3, 10, 15, 5, 0).getTime();
|
||||
const {getByText} = render(<Timestamp time={timestamp} testId="padded" />);
|
||||
|
||||
const formatted = getByText(/03:05 PM/);
|
||||
expect(formatted).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render with testID prop', () => {
|
||||
const timestamp = new Date(2024, 0, 1, 0, 0, 0).getTime();
|
||||
const {toJSON} = render(<Timestamp time={timestamp} testId="myTest" />);
|
||||
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should display different months correctly', () => {
|
||||
const months = [
|
||||
{month: 0, name: 'January'},
|
||||
{month: 1, name: 'February'},
|
||||
{month: 2, name: 'March'},
|
||||
{month: 6, name: 'July'},
|
||||
{month: 11, name: 'December'},
|
||||
];
|
||||
|
||||
months.forEach(({month, name}) => {
|
||||
const timestamp = new Date(2024, month, 15, 12, 0, 0).getTime();
|
||||
const {getByText} = render(
|
||||
<Timestamp time={timestamp} testId="month-test" />,
|
||||
);
|
||||
expect(getByText(new RegExp(name))).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
65
components/ui/ToastItem.test.tsx
Normal file
65
components/ui/ToastItem.test.tsx
Normal file
@@ -0,0 +1,65 @@
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react-native';
|
||||
import {ToastItem} from './ToastItem';
|
||||
|
||||
describe('ToastItem', () => {
|
||||
it('should render toast message', () => {
|
||||
const {getByText} = render(<ToastItem message="Success!" />);
|
||||
expect(getByText('Success!')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render long message', () => {
|
||||
const longMessage =
|
||||
'This is a very long toast message that should still be displayed properly';
|
||||
const {getByText} = render(<ToastItem message={longMessage} />);
|
||||
expect(getByText(longMessage)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render short message', () => {
|
||||
const {getByText} = render(<ToastItem message="OK" />);
|
||||
expect(getByText('OK')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render empty message', () => {
|
||||
const {toJSON} = render(<ToastItem message="" />);
|
||||
expect(toJSON()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render message with special characters', () => {
|
||||
const message = 'Error: Operation failed! (Code: 500)';
|
||||
const {getByText} = render(<ToastItem message={message} />);
|
||||
expect(getByText(message)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render message with numbers', () => {
|
||||
const message = '123 items processed successfully';
|
||||
const {getByText} = render(<ToastItem message={message} />);
|
||||
expect(getByText(message)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render message with emojis', () => {
|
||||
const message = '✅ Success! 🎉';
|
||||
const {getByText} = render(<ToastItem message={message} />);
|
||||
expect(getByText(message)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render multiline message', () => {
|
||||
const message = 'Line 1\nLine 2\nLine 3';
|
||||
const {getByText} = render(<ToastItem message={message} />);
|
||||
expect(getByText(message)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render different toast messages', () => {
|
||||
const messages = [
|
||||
'Operation completed',
|
||||
'Error occurred',
|
||||
'Warning: Low storage',
|
||||
'Info: Update available',
|
||||
];
|
||||
|
||||
messages.forEach(message => {
|
||||
const {getByText} = render(<ToastItem message={message} />);
|
||||
expect(getByText(message)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
106
components/ui/themes/themes.test.ts
Normal file
106
components/ui/themes/themes.test.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
import {DefaultTheme} from './DefaultTheme';
|
||||
import {PurpleTheme} from './PurpleTheme';
|
||||
|
||||
describe('DefaultTheme', () => {
|
||||
it('should be defined', () => {
|
||||
expect(DefaultTheme).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have Colors property', () => {
|
||||
expect(DefaultTheme.Colors).toBeDefined();
|
||||
expect(typeof DefaultTheme.Colors).toBe('object');
|
||||
});
|
||||
|
||||
it('should have ProfileIconColor', () => {
|
||||
expect(DefaultTheme.Colors.ProfileIconColor).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have TextStyles property', () => {
|
||||
expect(DefaultTheme.TextStyles).toBeDefined();
|
||||
expect(typeof DefaultTheme.TextStyles).toBe('object');
|
||||
});
|
||||
|
||||
it('should have ButtonStyles property', () => {
|
||||
expect(DefaultTheme.ButtonStyles).toBeDefined();
|
||||
expect(typeof DefaultTheme.ButtonStyles).toBe('object');
|
||||
});
|
||||
|
||||
it('should have spacing function', () => {
|
||||
expect(DefaultTheme.spacing).toBeDefined();
|
||||
expect(typeof DefaultTheme.spacing).toBe('function');
|
||||
});
|
||||
|
||||
it('should have elevation function', () => {
|
||||
expect(DefaultTheme.elevation).toBeDefined();
|
||||
expect(typeof DefaultTheme.elevation).toBe('function');
|
||||
});
|
||||
});
|
||||
|
||||
describe('PurpleTheme', () => {
|
||||
it('should be defined', () => {
|
||||
expect(PurpleTheme).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have Colors property', () => {
|
||||
expect(PurpleTheme.Colors).toBeDefined();
|
||||
expect(typeof PurpleTheme.Colors).toBe('object');
|
||||
});
|
||||
|
||||
it('should have ProfileIconColor', () => {
|
||||
expect(PurpleTheme.Colors.ProfileIconColor).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have different colors than Default', () => {
|
||||
expect(PurpleTheme.Colors).not.toEqual(DefaultTheme.Colors);
|
||||
});
|
||||
|
||||
it('should have TextStyles property', () => {
|
||||
expect(PurpleTheme.TextStyles).toBeDefined();
|
||||
expect(typeof PurpleTheme.TextStyles).toBe('object');
|
||||
});
|
||||
|
||||
it('should have ButtonStyles property', () => {
|
||||
expect(PurpleTheme.ButtonStyles).toBeDefined();
|
||||
expect(typeof PurpleTheme.ButtonStyles).toBe('object');
|
||||
});
|
||||
|
||||
it('should have spacing function', () => {
|
||||
expect(PurpleTheme.spacing).toBeDefined();
|
||||
expect(typeof PurpleTheme.spacing).toBe('function');
|
||||
});
|
||||
|
||||
it('should have elevation function', () => {
|
||||
expect(PurpleTheme.elevation).toBeDefined();
|
||||
expect(typeof PurpleTheme.elevation).toBe('function');
|
||||
});
|
||||
|
||||
it('should have same structure as DefaultTheme', () => {
|
||||
const defaultKeys = Object.keys(DefaultTheme);
|
||||
const purpleKeys = Object.keys(PurpleTheme);
|
||||
expect(purpleKeys.sort()).toEqual(defaultKeys.sort());
|
||||
});
|
||||
});
|
||||
|
||||
describe('Theme spacing function', () => {
|
||||
it('should return spacing styles for Default theme', () => {
|
||||
const spacing = DefaultTheme.spacing('margin', 'xs');
|
||||
expect(spacing).toBeDefined();
|
||||
});
|
||||
|
||||
it('should return spacing styles for Purple theme', () => {
|
||||
const spacing = PurpleTheme.spacing('padding', 'sm');
|
||||
expect(spacing).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Theme elevation function', () => {
|
||||
it('should return elevation styles for Default theme', () => {
|
||||
const elevation = DefaultTheme.elevation(2);
|
||||
expect(elevation).toBeDefined();
|
||||
});
|
||||
|
||||
it('should return elevation styles for Purple theme', () => {
|
||||
const elevation = PurpleTheme.elevation(3);
|
||||
expect(elevation).toBeDefined();
|
||||
});
|
||||
});
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable */
|
||||
// jest.config.js
|
||||
const {defaults: tsjPreset} = require('ts-jest/presets');
|
||||
module.exports = {
|
||||
@@ -36,8 +37,8 @@ module.exports = {
|
||||
],
|
||||
transformIgnorePatterns: [
|
||||
'node_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base|react-native-svg|react-native-vector-icons|jsonld|jsonld-signatures|@digitalbazaar/.*)',
|
||||
'node_modules/(?!(@react-native|react-native|react-native-argon2|@react-navigation|react-native-elements|react-native-size-matters|react-native-ratings|expo-constants|base58-universal|@react-native-*|react-native-google-signin|react-native-linear-gradient|expo-camera|base58-universal/*|react-native-*|react-native-vector-icons|jsonld|jsonld-signatures|@digitalbazaar/.*)/).*/',
|
||||
],
|
||||
'node_modules/(?!(@react-native|react-native|react-native-argon2|@react-navigation|react-native-elements|react-native-size-matters|react-native-ratings|expo-constants|base58-universal|@react-native-*|react-native-google-signin|react-native-linear-gradient|expo-camera|base58-universal/*|react-native-*|react-native-vector-icons|jsonld|jsonld-signatures|@digitalbazaar/.*)/).*/',
|
||||
],
|
||||
setupFiles: [
|
||||
'<rootDir>/__mocks__/svg.mock.js',
|
||||
'<rootDir>/__mocks__/jest-init.js',
|
||||
@@ -52,8 +53,8 @@ module.exports = {
|
||||
'<rootDir>/__mocks__/@noble/mock-secp256k1.js',
|
||||
'<rootDir>/__mocks__/@noble/mock-ed25519.js',
|
||||
'<rootDir>/__mocks__/react-native-base64.js',
|
||||
'<rootDir>__mocks__/mockCrytoUtil.js',
|
||||
'<rootDir>__mocks__/text-encoder.js',
|
||||
'<rootDir>/__mocks__/mockCrytoUtil.js',
|
||||
'<rootDir>/__mocks__/text-encoder.js',
|
||||
// https://github.com/react-native-google-signin/google-signin?tab=readme-ov-file#jest-module-mock
|
||||
'<rootDir>/node_modules/@react-native-google-signin/google-signin/jest/build/setup.js',
|
||||
],
|
||||
|
||||
271
machines/Issuers/IssuersEvents.test.ts
Normal file
271
machines/Issuers/IssuersEvents.test.ts
Normal file
@@ -0,0 +1,271 @@
|
||||
import {IssuersEvents} from './IssuersEvents';
|
||||
import {CredentialTypes} from '../VerifiableCredential/VCMetaMachine/vc';
|
||||
|
||||
describe('IssuersEvents', () => {
|
||||
describe('SELECTED_ISSUER', () => {
|
||||
it('should create event with id', () => {
|
||||
const result = IssuersEvents.SELECTED_ISSUER('issuer-123');
|
||||
expect(result).toEqual({id: 'issuer-123'});
|
||||
});
|
||||
|
||||
it('should handle empty id', () => {
|
||||
const result = IssuersEvents.SELECTED_ISSUER('');
|
||||
expect(result).toEqual({id: ''});
|
||||
});
|
||||
});
|
||||
|
||||
describe('DOWNLOAD_ID', () => {
|
||||
it('should create empty event', () => {
|
||||
const result = IssuersEvents.DOWNLOAD_ID();
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('BIOMETRIC_CANCELLED', () => {
|
||||
it('should create event with requester', () => {
|
||||
const result = IssuersEvents.BIOMETRIC_CANCELLED('login');
|
||||
expect(result).toEqual({requester: 'login'});
|
||||
});
|
||||
|
||||
it('should create event without requester', () => {
|
||||
const result = IssuersEvents.BIOMETRIC_CANCELLED();
|
||||
expect(result).toEqual({requester: undefined});
|
||||
});
|
||||
});
|
||||
|
||||
describe('COMPLETED', () => {
|
||||
it('should create empty event', () => {
|
||||
const result = IssuersEvents.COMPLETED();
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('TRY_AGAIN', () => {
|
||||
it('should create empty event', () => {
|
||||
const result = IssuersEvents.TRY_AGAIN();
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('RESET_ERROR', () => {
|
||||
it('should create empty event', () => {
|
||||
const result = IssuersEvents.RESET_ERROR();
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('CHECK_KEY_PAIR', () => {
|
||||
it('should create empty event', () => {
|
||||
const result = IssuersEvents.CHECK_KEY_PAIR();
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('CANCEL', () => {
|
||||
it('should create empty event', () => {
|
||||
const result = IssuersEvents.CANCEL();
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('STORE_RESPONSE', () => {
|
||||
it('should create event with response', () => {
|
||||
const response = {data: 'test'};
|
||||
const result = IssuersEvents.STORE_RESPONSE(response);
|
||||
expect(result).toEqual({response: {data: 'test'}});
|
||||
});
|
||||
|
||||
it('should create event without response', () => {
|
||||
const result = IssuersEvents.STORE_RESPONSE();
|
||||
expect(result).toEqual({response: undefined});
|
||||
});
|
||||
});
|
||||
|
||||
describe('STORE_ERROR', () => {
|
||||
it('should create event with error and requester', () => {
|
||||
const error = new Error('Test error');
|
||||
const result = IssuersEvents.STORE_ERROR(error, 'test-requester');
|
||||
expect(result.error).toBe(error);
|
||||
expect(result.requester).toBe('test-requester');
|
||||
});
|
||||
|
||||
it('should create event with error only', () => {
|
||||
const error = new Error('Test error');
|
||||
const result = IssuersEvents.STORE_ERROR(error);
|
||||
expect(result.error).toBe(error);
|
||||
expect(result.requester).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('RESET_VERIFY_ERROR', () => {
|
||||
it('should create empty event', () => {
|
||||
const result = IssuersEvents.RESET_VERIFY_ERROR();
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('SELECTED_CREDENTIAL_TYPE', () => {
|
||||
it('should create event with credential type', () => {
|
||||
const credType = {} as unknown as CredentialTypes;
|
||||
const result = IssuersEvents.SELECTED_CREDENTIAL_TYPE(credType);
|
||||
expect(result).toEqual({credType});
|
||||
});
|
||||
});
|
||||
|
||||
describe('SCAN_CREDENTIAL_OFFER_QR_CODE', () => {
|
||||
it('should create empty event', () => {
|
||||
const result = IssuersEvents.SCAN_CREDENTIAL_OFFER_QR_CODE();
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('QR_CODE_SCANNED', () => {
|
||||
it('should create event with data', () => {
|
||||
const result = IssuersEvents.QR_CODE_SCANNED('qr-code-data');
|
||||
expect(result).toEqual({data: 'qr-code-data'});
|
||||
});
|
||||
|
||||
it('should handle JSON data', () => {
|
||||
const jsonData = '{"key": "value"}';
|
||||
const result = IssuersEvents.QR_CODE_SCANNED(jsonData);
|
||||
expect(result).toEqual({data: jsonData});
|
||||
});
|
||||
});
|
||||
|
||||
describe('AUTH_ENDPOINT_RECEIVED', () => {
|
||||
it('should create event with auth endpoint', () => {
|
||||
const result = IssuersEvents.AUTH_ENDPOINT_RECEIVED(
|
||||
'https://auth.example.com',
|
||||
);
|
||||
expect(result).toEqual({authEndpoint: 'https://auth.example.com'});
|
||||
});
|
||||
});
|
||||
|
||||
describe('PROOF_REQUEST', () => {
|
||||
it('should create event with all parameters', () => {
|
||||
const accessToken = 'token-123';
|
||||
const cNonce = 'nonce-456';
|
||||
const issuerMetadata = {name: 'Test Issuer'};
|
||||
const issuer = {id: 'issuer-1'} as unknown as any;
|
||||
const credentialtypes = {} as unknown as CredentialTypes;
|
||||
|
||||
const result = IssuersEvents.PROOF_REQUEST(
|
||||
accessToken,
|
||||
cNonce,
|
||||
issuerMetadata,
|
||||
issuer,
|
||||
credentialtypes,
|
||||
);
|
||||
|
||||
expect(result.accessToken).toBe('token-123');
|
||||
expect(result.cNonce).toBe('nonce-456');
|
||||
expect(result.issuerMetadata).toEqual({name: 'Test Issuer'});
|
||||
expect(result.issuer).toEqual({id: 'issuer-1'});
|
||||
expect(result.credentialtypes).toBeDefined();
|
||||
});
|
||||
|
||||
it('should handle undefined cNonce', () => {
|
||||
const result = IssuersEvents.PROOF_REQUEST(
|
||||
'token',
|
||||
undefined,
|
||||
{},
|
||||
{} as unknown as any,
|
||||
{} as unknown as CredentialTypes,
|
||||
);
|
||||
|
||||
expect(result.cNonce).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('TX_CODE_REQUEST', () => {
|
||||
it('should create empty event', () => {
|
||||
const result = IssuersEvents.TX_CODE_REQUEST();
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('TX_CODE_RECEIVED', () => {
|
||||
it('should create event with txCode', () => {
|
||||
const result = IssuersEvents.TX_CODE_RECEIVED('TX123456');
|
||||
expect(result).toEqual({txCode: 'TX123456'});
|
||||
});
|
||||
|
||||
it('should handle empty txCode', () => {
|
||||
const result = IssuersEvents.TX_CODE_RECEIVED('');
|
||||
expect(result).toEqual({txCode: ''});
|
||||
});
|
||||
});
|
||||
|
||||
describe('ON_CONSENT_GIVEN', () => {
|
||||
it('should create empty event', () => {
|
||||
const result = IssuersEvents.ON_CONSENT_GIVEN();
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('TRUST_ISSUER_CONSENT_REQUEST', () => {
|
||||
it('should create event with issuerMetadata', () => {
|
||||
const issuerMetadata = {
|
||||
name: 'Trusted Issuer',
|
||||
url: 'https://issuer.example.com',
|
||||
};
|
||||
const result = IssuersEvents.TRUST_ISSUER_CONSENT_REQUEST(issuerMetadata);
|
||||
expect(result).toEqual({issuerMetadata});
|
||||
});
|
||||
|
||||
it('should handle empty issuerMetadata', () => {
|
||||
const result = IssuersEvents.TRUST_ISSUER_CONSENT_REQUEST({});
|
||||
expect(result).toEqual({issuerMetadata: {}});
|
||||
});
|
||||
});
|
||||
|
||||
describe('TOKEN_REQUEST', () => {
|
||||
it('should create event with tokenRequest', () => {
|
||||
const tokenRequest = {
|
||||
grant_type: 'authorization_code',
|
||||
code: 'auth-code-123',
|
||||
};
|
||||
const result = IssuersEvents.TOKEN_REQUEST(tokenRequest);
|
||||
expect(result).toEqual({tokenRequest});
|
||||
});
|
||||
|
||||
it('should handle empty tokenRequest', () => {
|
||||
const result = IssuersEvents.TOKEN_REQUEST({});
|
||||
expect(result).toEqual({tokenRequest: {}});
|
||||
});
|
||||
});
|
||||
|
||||
describe('IssuersEvents object structure', () => {
|
||||
it('should have all expected event creators', () => {
|
||||
expect(IssuersEvents.SELECTED_ISSUER).toBeDefined();
|
||||
expect(IssuersEvents.DOWNLOAD_ID).toBeDefined();
|
||||
expect(IssuersEvents.BIOMETRIC_CANCELLED).toBeDefined();
|
||||
expect(IssuersEvents.COMPLETED).toBeDefined();
|
||||
expect(IssuersEvents.TRY_AGAIN).toBeDefined();
|
||||
expect(IssuersEvents.RESET_ERROR).toBeDefined();
|
||||
expect(IssuersEvents.CHECK_KEY_PAIR).toBeDefined();
|
||||
expect(IssuersEvents.CANCEL).toBeDefined();
|
||||
expect(IssuersEvents.STORE_RESPONSE).toBeDefined();
|
||||
expect(IssuersEvents.STORE_ERROR).toBeDefined();
|
||||
expect(IssuersEvents.RESET_VERIFY_ERROR).toBeDefined();
|
||||
expect(IssuersEvents.SELECTED_CREDENTIAL_TYPE).toBeDefined();
|
||||
expect(IssuersEvents.SCAN_CREDENTIAL_OFFER_QR_CODE).toBeDefined();
|
||||
expect(IssuersEvents.QR_CODE_SCANNED).toBeDefined();
|
||||
expect(IssuersEvents.AUTH_ENDPOINT_RECEIVED).toBeDefined();
|
||||
expect(IssuersEvents.PROOF_REQUEST).toBeDefined();
|
||||
expect(IssuersEvents.TX_CODE_REQUEST).toBeDefined();
|
||||
expect(IssuersEvents.TX_CODE_RECEIVED).toBeDefined();
|
||||
expect(IssuersEvents.ON_CONSENT_GIVEN).toBeDefined();
|
||||
expect(IssuersEvents.TRUST_ISSUER_CONSENT_REQUEST).toBeDefined();
|
||||
expect(IssuersEvents.TOKEN_REQUEST).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have all event creators be functions', () => {
|
||||
expect(typeof IssuersEvents.SELECTED_ISSUER).toBe('function');
|
||||
expect(typeof IssuersEvents.DOWNLOAD_ID).toBe('function');
|
||||
expect(typeof IssuersEvents.BIOMETRIC_CANCELLED).toBe('function');
|
||||
expect(typeof IssuersEvents.COMPLETED).toBe('function');
|
||||
expect(typeof IssuersEvents.TRY_AGAIN).toBe('function');
|
||||
});
|
||||
});
|
||||
});
|
||||
301
machines/Issuers/IssuersModel.test.ts
Normal file
301
machines/Issuers/IssuersModel.test.ts
Normal file
@@ -0,0 +1,301 @@
|
||||
import {IssuersModel} from './IssuersModel';
|
||||
|
||||
describe('IssuersModel', () => {
|
||||
describe('Model structure', () => {
|
||||
it('should be defined', () => {
|
||||
expect(IssuersModel).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have initialContext', () => {
|
||||
expect(IssuersModel.initialContext).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have events', () => {
|
||||
expect(IssuersModel.events).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Initial Context', () => {
|
||||
const initialContext = IssuersModel.initialContext;
|
||||
|
||||
it('should have issuers as empty array', () => {
|
||||
expect(initialContext.issuers).toEqual([]);
|
||||
expect(Array.isArray(initialContext.issuers)).toBe(true);
|
||||
});
|
||||
|
||||
it('should have selectedIssuerId as empty string', () => {
|
||||
expect(initialContext.selectedIssuerId).toBe('');
|
||||
});
|
||||
|
||||
it('should have qrData as empty string', () => {
|
||||
expect(initialContext.qrData).toBe('');
|
||||
});
|
||||
|
||||
it('should have selectedIssuer as empty object', () => {
|
||||
expect(initialContext.selectedIssuer).toEqual({});
|
||||
});
|
||||
|
||||
it('should have selectedIssuerWellknownResponse as empty object', () => {
|
||||
expect(initialContext.selectedIssuerWellknownResponse).toEqual({});
|
||||
});
|
||||
|
||||
it('should have tokenResponse as empty object', () => {
|
||||
expect(initialContext.tokenResponse).toEqual({});
|
||||
});
|
||||
|
||||
it('should have errorMessage as empty string', () => {
|
||||
expect(initialContext.errorMessage).toBe('');
|
||||
});
|
||||
|
||||
it('should have loadingReason as displayIssuers', () => {
|
||||
expect(initialContext.loadingReason).toBe('displayIssuers');
|
||||
});
|
||||
|
||||
it('should have verifiableCredential as null', () => {
|
||||
expect(initialContext.verifiableCredential).toBeNull();
|
||||
});
|
||||
|
||||
it('should have selectedCredentialType as empty object', () => {
|
||||
expect(initialContext.selectedCredentialType).toEqual({});
|
||||
});
|
||||
|
||||
it('should have supportedCredentialTypes as empty array', () => {
|
||||
expect(initialContext.supportedCredentialTypes).toEqual([]);
|
||||
expect(Array.isArray(initialContext.supportedCredentialTypes)).toBe(true);
|
||||
});
|
||||
|
||||
it('should have credentialWrapper as empty object', () => {
|
||||
expect(initialContext.credentialWrapper).toEqual({});
|
||||
});
|
||||
|
||||
it('should have serviceRefs as empty object', () => {
|
||||
expect(initialContext.serviceRefs).toEqual({});
|
||||
});
|
||||
|
||||
it('should have verificationErrorMessage as empty string', () => {
|
||||
expect(initialContext.verificationErrorMessage).toBe('');
|
||||
});
|
||||
|
||||
it('should have publicKey as empty string', () => {
|
||||
expect(initialContext.publicKey).toBe('');
|
||||
});
|
||||
|
||||
it('should have privateKey as empty string', () => {
|
||||
expect(initialContext.privateKey).toBe('');
|
||||
});
|
||||
|
||||
it('should have vcMetadata as empty object', () => {
|
||||
expect(initialContext.vcMetadata).toEqual({});
|
||||
});
|
||||
|
||||
it('should have keyType as RS256', () => {
|
||||
expect(initialContext.keyType).toBe('RS256');
|
||||
});
|
||||
|
||||
it('should have wellknownKeyTypes as empty array', () => {
|
||||
expect(initialContext.wellknownKeyTypes).toEqual([]);
|
||||
expect(Array.isArray(initialContext.wellknownKeyTypes)).toBe(true);
|
||||
});
|
||||
|
||||
it('should have authEndpointToOpen as false', () => {
|
||||
expect(initialContext.authEndpointToOpen).toBe(false);
|
||||
});
|
||||
|
||||
it('should have isTransactionCodeRequested as false', () => {
|
||||
expect(initialContext.isTransactionCodeRequested).toBe(false);
|
||||
});
|
||||
|
||||
it('should have authEndpoint as empty string', () => {
|
||||
expect(initialContext.authEndpoint).toBe('');
|
||||
});
|
||||
|
||||
it('should have accessToken as empty string', () => {
|
||||
expect(initialContext.accessToken).toBe('');
|
||||
});
|
||||
|
||||
it('should have txCode as empty string', () => {
|
||||
expect(initialContext.txCode).toBe('');
|
||||
});
|
||||
|
||||
it('should have cNonce as empty string', () => {
|
||||
expect(initialContext.cNonce).toBe('');
|
||||
});
|
||||
|
||||
it('should have isConsentRequested as false', () => {
|
||||
expect(initialContext.isConsentRequested).toBe(false);
|
||||
});
|
||||
|
||||
it('should have issuerLogo as empty string', () => {
|
||||
expect(initialContext.issuerLogo).toBe('');
|
||||
});
|
||||
|
||||
it('should have issuerName as empty string', () => {
|
||||
expect(initialContext.issuerName).toBe('');
|
||||
});
|
||||
|
||||
it('should have txCodeInputMode as empty string', () => {
|
||||
expect(initialContext.txCodeInputMode).toBe('');
|
||||
});
|
||||
|
||||
it('should have txCodeDescription as empty string', () => {
|
||||
expect(initialContext.txCodeDescription).toBe('');
|
||||
});
|
||||
|
||||
it('should have txCodeLength as null', () => {
|
||||
expect(initialContext.txCodeLength).toBeNull();
|
||||
});
|
||||
|
||||
it('should have isCredentialOfferFlow as false', () => {
|
||||
expect(initialContext.isCredentialOfferFlow).toBe(false);
|
||||
});
|
||||
|
||||
it('should have tokenRequestObject as empty object', () => {
|
||||
expect(initialContext.tokenRequestObject).toEqual({});
|
||||
});
|
||||
|
||||
it('should have credentialConfigurationId as empty string', () => {
|
||||
expect(initialContext.credentialConfigurationId).toBe('');
|
||||
});
|
||||
|
||||
it('should have all 35 required properties', () => {
|
||||
const properties = Object.keys(initialContext);
|
||||
expect(properties).toHaveLength(35);
|
||||
});
|
||||
});
|
||||
|
||||
describe('String properties', () => {
|
||||
const context = IssuersModel.initialContext;
|
||||
|
||||
it('all empty string properties should be empty', () => {
|
||||
const emptyStrings = [
|
||||
context.selectedIssuerId,
|
||||
context.qrData,
|
||||
context.errorMessage,
|
||||
context.verificationErrorMessage,
|
||||
context.publicKey,
|
||||
context.privateKey,
|
||||
context.authEndpoint,
|
||||
context.accessToken,
|
||||
context.txCode,
|
||||
context.cNonce,
|
||||
context.issuerLogo,
|
||||
context.issuerName,
|
||||
context.txCodeInputMode,
|
||||
context.txCodeDescription,
|
||||
context.credentialConfigurationId,
|
||||
];
|
||||
|
||||
emptyStrings.forEach(str => {
|
||||
expect(str).toBe('');
|
||||
expect(typeof str).toBe('string');
|
||||
});
|
||||
});
|
||||
|
||||
it('loadingReason should be displayIssuers', () => {
|
||||
expect(context.loadingReason).toBe('displayIssuers');
|
||||
expect(typeof context.loadingReason).toBe('string');
|
||||
});
|
||||
|
||||
it('keyType should be RS256', () => {
|
||||
expect(context.keyType).toBe('RS256');
|
||||
expect(typeof context.keyType).toBe('string');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Array properties', () => {
|
||||
const context = IssuersModel.initialContext;
|
||||
|
||||
it('all array properties should be empty arrays', () => {
|
||||
const arrays = [
|
||||
context.issuers,
|
||||
context.supportedCredentialTypes,
|
||||
context.wellknownKeyTypes,
|
||||
];
|
||||
|
||||
arrays.forEach(arr => {
|
||||
expect(Array.isArray(arr)).toBe(true);
|
||||
expect(arr).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Object properties', () => {
|
||||
const context = IssuersModel.initialContext;
|
||||
|
||||
it('all object properties should be empty objects or as specified', () => {
|
||||
const emptyObjects = [
|
||||
context.selectedIssuer,
|
||||
context.selectedIssuerWellknownResponse,
|
||||
context.tokenResponse,
|
||||
context.selectedCredentialType,
|
||||
context.credentialWrapper,
|
||||
context.serviceRefs,
|
||||
context.vcMetadata,
|
||||
context.tokenRequestObject,
|
||||
];
|
||||
|
||||
emptyObjects.forEach(obj => {
|
||||
expect(typeof obj).toBe('object');
|
||||
expect(Object.keys(obj)).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Boolean properties', () => {
|
||||
const context = IssuersModel.initialContext;
|
||||
|
||||
it('all boolean properties should be false initially', () => {
|
||||
const booleans = [
|
||||
context.authEndpointToOpen,
|
||||
context.isTransactionCodeRequested,
|
||||
context.isConsentRequested,
|
||||
context.isCredentialOfferFlow,
|
||||
];
|
||||
|
||||
booleans.forEach(bool => {
|
||||
expect(bool).toBe(false);
|
||||
expect(typeof bool).toBe('boolean');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Null properties', () => {
|
||||
const context = IssuersModel.initialContext;
|
||||
|
||||
it('verifiableCredential should be null', () => {
|
||||
expect(context.verifiableCredential).toBeNull();
|
||||
});
|
||||
|
||||
it('txCodeLength should be null', () => {
|
||||
expect(context.txCodeLength).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Model events', () => {
|
||||
it('should have events object', () => {
|
||||
expect(IssuersModel.events).toBeDefined();
|
||||
expect(typeof IssuersModel.events).toBe('object');
|
||||
});
|
||||
|
||||
it('should have event creators', () => {
|
||||
const eventKeys = Object.keys(IssuersModel.events);
|
||||
expect(eventKeys.length).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Property types', () => {
|
||||
const context = IssuersModel.initialContext;
|
||||
|
||||
it('should have correct types for all properties', () => {
|
||||
expect(typeof context.selectedIssuerId).toBe('string');
|
||||
expect(typeof context.qrData).toBe('string');
|
||||
expect(typeof context.errorMessage).toBe('string');
|
||||
expect(typeof context.loadingReason).toBe('string');
|
||||
expect(typeof context.keyType).toBe('string');
|
||||
expect(typeof context.authEndpointToOpen).toBe('boolean');
|
||||
expect(typeof context.isTransactionCodeRequested).toBe('boolean');
|
||||
expect(Array.isArray(context.issuers)).toBe(true);
|
||||
expect(typeof context.selectedIssuer).toBe('object');
|
||||
});
|
||||
});
|
||||
});
|
||||
372
machines/Issuers/IssuersSelectors.test.ts
Normal file
372
machines/Issuers/IssuersSelectors.test.ts
Normal file
@@ -0,0 +1,372 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import {
|
||||
selectIssuers,
|
||||
selectSelectedIssuer,
|
||||
selectAuthWebViewStatus,
|
||||
selectAuthEndPoint,
|
||||
selectErrorMessageType,
|
||||
selectLoadingReason,
|
||||
selectIsDownloadCredentials,
|
||||
selectIsTxCodeRequested,
|
||||
selectIsConsentRequested,
|
||||
selectIssuerLogo,
|
||||
selectIssuerName,
|
||||
selectTxCodeDisplayDetails,
|
||||
selectIsNonGenericError,
|
||||
selectIsDone,
|
||||
selectIsIdle,
|
||||
selectStoring,
|
||||
selectIsError,
|
||||
selectVerificationErrorMessage,
|
||||
selectSelectingCredentialType,
|
||||
selectSupportedCredentialTypes,
|
||||
selectIsQrScanning,
|
||||
} from './IssuersSelectors';
|
||||
|
||||
describe('IssuersSelectors', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
issuers: [{issuer_id: '1'}, {issuer_id: '2'}],
|
||||
selectedIssuer: {issuer_id: '1', credential_issuer: 'test.example.com'},
|
||||
authEndpointToOpen: 'https://auth.example.com',
|
||||
authEndpoint: 'https://auth.example.com/authorize',
|
||||
errorMessage: 'Test error',
|
||||
loadingReason: 'Loading data',
|
||||
isTransactionCodeRequested: true,
|
||||
isConsentRequested: false,
|
||||
issuerLogo: 'https://example.com/logo.png',
|
||||
issuerName: 'Test Issuer',
|
||||
txCodeInputMode: 'numeric',
|
||||
txCodeDescription: 'Enter transaction code',
|
||||
txCodeLength: 6,
|
||||
},
|
||||
matches: jest.fn(
|
||||
(stateName: string) => stateName === 'downloadCredentials',
|
||||
),
|
||||
};
|
||||
|
||||
describe('selectIssuers', () => {
|
||||
it('should return issuers from context', () => {
|
||||
const result = selectIssuers(mockState);
|
||||
expect(result).toEqual(mockState.context.issuers);
|
||||
});
|
||||
|
||||
it('should return array of issuers', () => {
|
||||
const result = selectIssuers(mockState);
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
expect(result.length).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectSelectedIssuer', () => {
|
||||
it('should return selected issuer from context', () => {
|
||||
const result = selectSelectedIssuer(mockState);
|
||||
expect(result).toEqual(mockState.context.selectedIssuer);
|
||||
});
|
||||
|
||||
it('should return issuer with issuer_id property', () => {
|
||||
const result = selectSelectedIssuer(mockState);
|
||||
expect(result.issuer_id).toBe('1');
|
||||
expect(result.credential_issuer).toBe('test.example.com');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectAuthWebViewStatus', () => {
|
||||
it('should return auth endpoint to open', () => {
|
||||
const result = selectAuthWebViewStatus(mockState);
|
||||
expect(result).toBe('https://auth.example.com');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectAuthEndPoint', () => {
|
||||
it('should return auth endpoint', () => {
|
||||
const result = selectAuthEndPoint(mockState);
|
||||
expect(result).toBe('https://auth.example.com/authorize');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectErrorMessageType', () => {
|
||||
it('should return error message from context', () => {
|
||||
const result = selectErrorMessageType(mockState);
|
||||
expect(result).toBe('Test error');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectLoadingReason', () => {
|
||||
it('should return loading reason from context', () => {
|
||||
const result = selectLoadingReason(mockState);
|
||||
expect(result).toBe('Loading data');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsDownloadCredentials', () => {
|
||||
it('should return true when in downloadCredentials state', () => {
|
||||
const result = selectIsDownloadCredentials(mockState);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with correct state name', () => {
|
||||
selectIsDownloadCredentials(mockState);
|
||||
expect(mockState.matches).toHaveBeenCalledWith('downloadCredentials');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsTxCodeRequested', () => {
|
||||
it('should return transaction code requested status', () => {
|
||||
const result = selectIsTxCodeRequested(mockState);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when not requested', () => {
|
||||
const stateWithFalse: any = {
|
||||
...mockState,
|
||||
context: {...mockState.context, isTransactionCodeRequested: false},
|
||||
};
|
||||
const result = selectIsTxCodeRequested(stateWithFalse);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsConsentRequested', () => {
|
||||
it('should return consent requested status', () => {
|
||||
const result = selectIsConsentRequested(mockState);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true when consent requested', () => {
|
||||
const stateWithConsent: any = {
|
||||
...mockState,
|
||||
context: {...mockState.context, isConsentRequested: true},
|
||||
};
|
||||
const result = selectIsConsentRequested(stateWithConsent);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIssuerLogo', () => {
|
||||
it('should return issuer logo URL', () => {
|
||||
const result = selectIssuerLogo(mockState);
|
||||
expect(result).toBe('https://example.com/logo.png');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIssuerName', () => {
|
||||
it('should return issuer name', () => {
|
||||
const result = selectIssuerName(mockState);
|
||||
expect(result).toBe('Test Issuer');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectTxCodeDisplayDetails', () => {
|
||||
it('should return transaction code display details', () => {
|
||||
const result = selectTxCodeDisplayDetails(mockState);
|
||||
expect(result).toEqual({
|
||||
inputMode: 'numeric',
|
||||
description: 'Enter transaction code',
|
||||
length: 6,
|
||||
});
|
||||
});
|
||||
|
||||
it('should have all required properties', () => {
|
||||
const result = selectTxCodeDisplayDetails(mockState);
|
||||
expect(result).toHaveProperty('inputMode');
|
||||
expect(result).toHaveProperty('description');
|
||||
expect(result).toHaveProperty('length');
|
||||
});
|
||||
|
||||
it('should return correct input mode', () => {
|
||||
const result = selectTxCodeDisplayDetails(mockState);
|
||||
expect(result.inputMode).toBe('numeric');
|
||||
});
|
||||
|
||||
it('should return correct description', () => {
|
||||
const result = selectTxCodeDisplayDetails(mockState);
|
||||
expect(result.description).toBe('Enter transaction code');
|
||||
});
|
||||
|
||||
it('should return correct length', () => {
|
||||
const result = selectTxCodeDisplayDetails(mockState);
|
||||
expect(result.length).toBe(6);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Selectors with empty/null values', () => {
|
||||
const emptyState: any = {
|
||||
context: {
|
||||
issuers: [],
|
||||
selectedIssuer: null,
|
||||
authEndpointToOpen: '',
|
||||
authEndpoint: '',
|
||||
errorMessage: '',
|
||||
loadingReason: '',
|
||||
isTransactionCodeRequested: false,
|
||||
isConsentRequested: false,
|
||||
issuerLogo: '',
|
||||
issuerName: '',
|
||||
txCodeInputMode: '',
|
||||
txCodeDescription: '',
|
||||
txCodeLength: 0,
|
||||
},
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
|
||||
it('should handle empty issuers array', () => {
|
||||
const result = selectIssuers(emptyState);
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
it('should handle null selected issuer', () => {
|
||||
const result = selectSelectedIssuer(emptyState);
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it('should handle empty strings', () => {
|
||||
expect(selectAuthWebViewStatus(emptyState)).toBe('');
|
||||
expect(selectAuthEndPoint(emptyState)).toBe('');
|
||||
expect(selectErrorMessageType(emptyState)).toBe('');
|
||||
expect(selectLoadingReason(emptyState)).toBe('');
|
||||
expect(selectIssuerLogo(emptyState)).toBe('');
|
||||
expect(selectIssuerName(emptyState)).toBe('');
|
||||
});
|
||||
|
||||
it('should handle false boolean values', () => {
|
||||
expect(selectIsTxCodeRequested(emptyState)).toBe(false);
|
||||
expect(selectIsConsentRequested(emptyState)).toBe(false);
|
||||
expect(selectIsDownloadCredentials(emptyState)).toBe(false);
|
||||
});
|
||||
|
||||
it('should handle zero length', () => {
|
||||
const result = selectTxCodeDisplayDetails(emptyState);
|
||||
expect(result.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsNonGenericError', () => {
|
||||
it('should return true when error message is not generic and not empty', () => {
|
||||
const stateWithError: any = {
|
||||
context: {errorMessage: 'NETWORK_ERROR'},
|
||||
};
|
||||
const result = selectIsNonGenericError(stateWithError);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when error message is GENERIC', () => {
|
||||
const stateWithGenericError: any = {
|
||||
context: {errorMessage: 'generic'},
|
||||
};
|
||||
const result = selectIsNonGenericError(stateWithGenericError);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false when error message is empty', () => {
|
||||
const stateWithNoError: any = {
|
||||
context: {errorMessage: ''},
|
||||
};
|
||||
const result = selectIsNonGenericError(stateWithNoError);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsDone', () => {
|
||||
it('should return true when state matches done', () => {
|
||||
const doneState: any = {
|
||||
matches: jest.fn((name: string) => name === 'done'),
|
||||
};
|
||||
const result = selectIsDone(doneState);
|
||||
expect(result).toBe(true);
|
||||
expect(doneState.matches).toHaveBeenCalledWith('done');
|
||||
});
|
||||
|
||||
it('should return false when state does not match done', () => {
|
||||
const notDoneState: any = {
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
const result = selectIsDone(notDoneState);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsIdle', () => {
|
||||
it('should return true when state matches idle', () => {
|
||||
const idleState: any = {
|
||||
matches: jest.fn((name: string) => name === 'idle'),
|
||||
};
|
||||
const result = selectIsIdle(idleState);
|
||||
expect(result).toBe(true);
|
||||
expect(idleState.matches).toHaveBeenCalledWith('idle');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectStoring', () => {
|
||||
it('should return true when state matches storing', () => {
|
||||
const storingState: any = {
|
||||
matches: jest.fn((name: string) => name === 'storing'),
|
||||
};
|
||||
const result = selectStoring(storingState);
|
||||
expect(result).toBe(true);
|
||||
expect(storingState.matches).toHaveBeenCalledWith('storing');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsError', () => {
|
||||
it('should return true when state matches error', () => {
|
||||
const errorState: any = {
|
||||
matches: jest.fn((name: string) => name === 'error'),
|
||||
};
|
||||
const result = selectIsError(errorState);
|
||||
expect(result).toBe(true);
|
||||
expect(errorState.matches).toHaveBeenCalledWith('error');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectVerificationErrorMessage', () => {
|
||||
it('should return verification error message', () => {
|
||||
const stateWithVerificationError: any = {
|
||||
context: {verificationErrorMessage: 'Signature verification failed'},
|
||||
};
|
||||
const result = selectVerificationErrorMessage(stateWithVerificationError);
|
||||
expect(result).toBe('Signature verification failed');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectSelectingCredentialType', () => {
|
||||
it('should return true when selecting credential type', () => {
|
||||
const selectingState: any = {
|
||||
matches: jest.fn((name: string) => name === 'selectingCredentialType'),
|
||||
};
|
||||
const result = selectSelectingCredentialType(selectingState);
|
||||
expect(result).toBe(true);
|
||||
expect(selectingState.matches).toHaveBeenCalledWith(
|
||||
'selectingCredentialType',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectSupportedCredentialTypes', () => {
|
||||
it('should return supported credential types', () => {
|
||||
const stateWithCredTypes: any = {
|
||||
context: {
|
||||
supportedCredentialTypes: [
|
||||
{id: 'type1', name: 'Type 1'},
|
||||
{id: 'type2', name: 'Type 2'},
|
||||
],
|
||||
},
|
||||
};
|
||||
const result = selectSupportedCredentialTypes(stateWithCredTypes);
|
||||
expect(result).toHaveLength(2);
|
||||
expect(result[0].id).toBe('type1');
|
||||
expect(result[1].id).toBe('type2');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsQrScanning', () => {
|
||||
it('should return true when waiting for QR scan', () => {
|
||||
const scanningState: any = {
|
||||
matches: jest.fn((name: string) => name === 'waitingForQrScan'),
|
||||
};
|
||||
const result = selectIsQrScanning(scanningState);
|
||||
expect(result).toBe(true);
|
||||
expect(scanningState.matches).toHaveBeenCalledWith('waitingForQrScan');
|
||||
});
|
||||
});
|
||||
});
|
||||
332
machines/QrLogin/QrLoginModel.test.ts
Normal file
332
machines/QrLogin/QrLoginModel.test.ts
Normal file
@@ -0,0 +1,332 @@
|
||||
import {QrLoginmodel} from './QrLoginModel';
|
||||
import {VCShareFlowType} from '../../shared/Utils';
|
||||
|
||||
describe('QrLoginModel', () => {
|
||||
describe('Model structure', () => {
|
||||
it('should be defined', () => {
|
||||
expect(QrLoginmodel).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have initialContext', () => {
|
||||
expect(QrLoginmodel.initialContext).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have events', () => {
|
||||
expect(QrLoginmodel.events).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Initial Context', () => {
|
||||
const initialContext = QrLoginmodel.initialContext;
|
||||
|
||||
it('should have serviceRefs as empty object', () => {
|
||||
expect(initialContext.serviceRefs).toEqual({});
|
||||
expect(typeof initialContext.serviceRefs).toBe('object');
|
||||
});
|
||||
|
||||
it('should have selectedVc as empty object', () => {
|
||||
expect(initialContext.selectedVc).toEqual({});
|
||||
expect(typeof initialContext.selectedVc).toBe('object');
|
||||
});
|
||||
|
||||
it('should have linkCode as empty string', () => {
|
||||
expect(initialContext.linkCode).toBe('');
|
||||
expect(typeof initialContext.linkCode).toBe('string');
|
||||
});
|
||||
|
||||
it('should have flowType as SIMPLE_SHARE', () => {
|
||||
expect(initialContext.flowType).toBe(VCShareFlowType.SIMPLE_SHARE);
|
||||
});
|
||||
|
||||
it('should have myVcs as empty array', () => {
|
||||
expect(initialContext.myVcs).toEqual([]);
|
||||
expect(Array.isArray(initialContext.myVcs)).toBe(true);
|
||||
expect(initialContext.myVcs).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should have thumbprint as empty string', () => {
|
||||
expect(initialContext.thumbprint).toBe('');
|
||||
expect(typeof initialContext.thumbprint).toBe('string');
|
||||
});
|
||||
|
||||
it('should have linkTransactionResponse as empty object', () => {
|
||||
expect(initialContext.linkTransactionResponse).toEqual({});
|
||||
expect(typeof initialContext.linkTransactionResponse).toBe('object');
|
||||
});
|
||||
|
||||
it('should have authFactors as empty array', () => {
|
||||
expect(initialContext.authFactors).toEqual([]);
|
||||
expect(Array.isArray(initialContext.authFactors)).toBe(true);
|
||||
});
|
||||
|
||||
it('should have authorizeScopes as null', () => {
|
||||
expect(initialContext.authorizeScopes).toBeNull();
|
||||
});
|
||||
|
||||
it('should have clientName as empty object', () => {
|
||||
expect(initialContext.clientName).toEqual({});
|
||||
expect(typeof initialContext.clientName).toBe('object');
|
||||
});
|
||||
|
||||
it('should have configs as empty object', () => {
|
||||
expect(initialContext.configs).toEqual({});
|
||||
expect(typeof initialContext.configs).toBe('object');
|
||||
});
|
||||
|
||||
it('should have essentialClaims as empty array', () => {
|
||||
expect(initialContext.essentialClaims).toEqual([]);
|
||||
expect(Array.isArray(initialContext.essentialClaims)).toBe(true);
|
||||
});
|
||||
|
||||
it('should have linkTransactionId as empty string', () => {
|
||||
expect(initialContext.linkTransactionId).toBe('');
|
||||
expect(typeof initialContext.linkTransactionId).toBe('string');
|
||||
});
|
||||
|
||||
it('should have logoUrl as empty string', () => {
|
||||
expect(initialContext.logoUrl).toBe('');
|
||||
expect(typeof initialContext.logoUrl).toBe('string');
|
||||
});
|
||||
|
||||
it('should have voluntaryClaims as empty array', () => {
|
||||
expect(initialContext.voluntaryClaims).toEqual([]);
|
||||
expect(Array.isArray(initialContext.voluntaryClaims)).toBe(true);
|
||||
});
|
||||
|
||||
it('should have selectedVoluntaryClaims as empty array', () => {
|
||||
expect(initialContext.selectedVoluntaryClaims).toEqual([]);
|
||||
expect(Array.isArray(initialContext.selectedVoluntaryClaims)).toBe(true);
|
||||
});
|
||||
|
||||
it('should have errorMessage as empty string', () => {
|
||||
expect(initialContext.errorMessage).toBe('');
|
||||
expect(typeof initialContext.errorMessage).toBe('string');
|
||||
});
|
||||
|
||||
it('should have domainName as empty string', () => {
|
||||
expect(initialContext.domainName).toBe('');
|
||||
expect(typeof initialContext.domainName).toBe('string');
|
||||
});
|
||||
|
||||
it('should have consentClaims with name and picture', () => {
|
||||
expect(initialContext.consentClaims).toEqual(['name', 'picture']);
|
||||
expect(Array.isArray(initialContext.consentClaims)).toBe(true);
|
||||
expect(initialContext.consentClaims).toHaveLength(2);
|
||||
expect(initialContext.consentClaims).toContain('name');
|
||||
expect(initialContext.consentClaims).toContain('picture');
|
||||
});
|
||||
|
||||
it('should have isSharing as empty object', () => {
|
||||
expect(initialContext.isSharing).toEqual({});
|
||||
expect(typeof initialContext.isSharing).toBe('object');
|
||||
});
|
||||
|
||||
it('should have linkedTransactionId as empty string', () => {
|
||||
expect(initialContext.linkedTransactionId).toBe('');
|
||||
expect(typeof initialContext.linkedTransactionId).toBe('string');
|
||||
});
|
||||
|
||||
it('should have showFaceAuthConsent as true', () => {
|
||||
expect(initialContext.showFaceAuthConsent).toBe(true);
|
||||
expect(typeof initialContext.showFaceAuthConsent).toBe('boolean');
|
||||
});
|
||||
|
||||
it('should have isQrLoginViaDeepLink as false', () => {
|
||||
expect(initialContext.isQrLoginViaDeepLink).toBe(false);
|
||||
expect(typeof initialContext.isQrLoginViaDeepLink).toBe('boolean');
|
||||
});
|
||||
|
||||
it('should have all required properties', () => {
|
||||
const requiredProps = [
|
||||
'serviceRefs',
|
||||
'selectedVc',
|
||||
'linkCode',
|
||||
'flowType',
|
||||
'myVcs',
|
||||
'thumbprint',
|
||||
'linkTransactionResponse',
|
||||
'authFactors',
|
||||
'authorizeScopes',
|
||||
'clientName',
|
||||
'configs',
|
||||
'essentialClaims',
|
||||
'linkTransactionId',
|
||||
'logoUrl',
|
||||
'voluntaryClaims',
|
||||
'selectedVoluntaryClaims',
|
||||
'errorMessage',
|
||||
'domainName',
|
||||
'consentClaims',
|
||||
'isSharing',
|
||||
'linkedTransactionId',
|
||||
'showFaceAuthConsent',
|
||||
'isQrLoginViaDeepLink',
|
||||
];
|
||||
|
||||
requiredProps.forEach(prop => {
|
||||
expect(initialContext).toHaveProperty(prop);
|
||||
});
|
||||
});
|
||||
|
||||
it('should have exactly 23 properties in initial context', () => {
|
||||
const propertyCount = Object.keys(initialContext).length;
|
||||
expect(propertyCount).toBe(23);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Model events', () => {
|
||||
it('should have events object defined', () => {
|
||||
expect(QrLoginmodel.events).toBeDefined();
|
||||
expect(typeof QrLoginmodel.events).toBe('object');
|
||||
});
|
||||
|
||||
it('should have SELECT_VC event', () => {
|
||||
expect(QrLoginmodel.events.SELECT_VC).toBeDefined();
|
||||
expect(typeof QrLoginmodel.events.SELECT_VC).toBe('function');
|
||||
});
|
||||
|
||||
it('should have SCANNING_DONE event', () => {
|
||||
expect(QrLoginmodel.events.SCANNING_DONE).toBeDefined();
|
||||
expect(typeof QrLoginmodel.events.SCANNING_DONE).toBe('function');
|
||||
});
|
||||
|
||||
it('should have STORE_RESPONSE event', () => {
|
||||
expect(QrLoginmodel.events.STORE_RESPONSE).toBeDefined();
|
||||
expect(typeof QrLoginmodel.events.STORE_RESPONSE).toBe('function');
|
||||
});
|
||||
|
||||
it('should have STORE_ERROR event', () => {
|
||||
expect(QrLoginmodel.events.STORE_ERROR).toBeDefined();
|
||||
expect(typeof QrLoginmodel.events.STORE_ERROR).toBe('function');
|
||||
});
|
||||
|
||||
it('should have TOGGLE_CONSENT_CLAIM event', () => {
|
||||
expect(QrLoginmodel.events.TOGGLE_CONSENT_CLAIM).toBeDefined();
|
||||
expect(typeof QrLoginmodel.events.TOGGLE_CONSENT_CLAIM).toBe('function');
|
||||
});
|
||||
|
||||
it('should have DISMISS event', () => {
|
||||
expect(QrLoginmodel.events.DISMISS).toBeDefined();
|
||||
expect(typeof QrLoginmodel.events.DISMISS).toBe('function');
|
||||
});
|
||||
|
||||
it('should have CONFIRM event', () => {
|
||||
expect(QrLoginmodel.events.CONFIRM).toBeDefined();
|
||||
expect(typeof QrLoginmodel.events.CONFIRM).toBe('function');
|
||||
});
|
||||
|
||||
it('should have GET event', () => {
|
||||
expect(QrLoginmodel.events.GET).toBeDefined();
|
||||
expect(typeof QrLoginmodel.events.GET).toBe('function');
|
||||
});
|
||||
|
||||
it('should have VERIFY event', () => {
|
||||
expect(QrLoginmodel.events.VERIFY).toBeDefined();
|
||||
expect(typeof QrLoginmodel.events.VERIFY).toBe('function');
|
||||
});
|
||||
|
||||
it('should have CANCEL event', () => {
|
||||
expect(QrLoginmodel.events.CANCEL).toBeDefined();
|
||||
expect(typeof QrLoginmodel.events.CANCEL).toBe('function');
|
||||
});
|
||||
|
||||
it('should have FACE_VALID event', () => {
|
||||
expect(QrLoginmodel.events.FACE_VALID).toBeDefined();
|
||||
expect(typeof QrLoginmodel.events.FACE_VALID).toBe('function');
|
||||
});
|
||||
|
||||
it('should have FACE_INVALID event', () => {
|
||||
expect(QrLoginmodel.events.FACE_INVALID).toBeDefined();
|
||||
expect(typeof QrLoginmodel.events.FACE_INVALID).toBe('function');
|
||||
});
|
||||
|
||||
it('should have RETRY_VERIFICATION event', () => {
|
||||
expect(QrLoginmodel.events.RETRY_VERIFICATION).toBeDefined();
|
||||
expect(typeof QrLoginmodel.events.RETRY_VERIFICATION).toBe('function');
|
||||
});
|
||||
|
||||
it('should have FACE_VERIFICATION_CONSENT event', () => {
|
||||
expect(QrLoginmodel.events.FACE_VERIFICATION_CONSENT).toBeDefined();
|
||||
expect(typeof QrLoginmodel.events.FACE_VERIFICATION_CONSENT).toBe(
|
||||
'function',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('String properties', () => {
|
||||
const context = QrLoginmodel.initialContext;
|
||||
|
||||
it('all string properties should be empty strings initially', () => {
|
||||
const stringProps = [
|
||||
context.linkCode,
|
||||
context.thumbprint,
|
||||
context.linkTransactionId,
|
||||
context.logoUrl,
|
||||
context.errorMessage,
|
||||
context.domainName,
|
||||
context.linkedTransactionId,
|
||||
];
|
||||
|
||||
stringProps.forEach(prop => {
|
||||
expect(prop).toBe('');
|
||||
expect(typeof prop).toBe('string');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Array properties', () => {
|
||||
const context = QrLoginmodel.initialContext;
|
||||
|
||||
it('empty array properties should have length 0', () => {
|
||||
const emptyArrays = [
|
||||
context.myVcs,
|
||||
context.authFactors,
|
||||
context.essentialClaims,
|
||||
context.voluntaryClaims,
|
||||
context.selectedVoluntaryClaims,
|
||||
];
|
||||
|
||||
emptyArrays.forEach(arr => {
|
||||
expect(Array.isArray(arr)).toBe(true);
|
||||
expect(arr).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('consentClaims should have length 2', () => {
|
||||
expect(context.consentClaims).toHaveLength(2);
|
||||
expect(Array.isArray(context.consentClaims)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Object properties', () => {
|
||||
const context = QrLoginmodel.initialContext;
|
||||
|
||||
it('empty object properties should have no keys', () => {
|
||||
const emptyObjects = [
|
||||
context.serviceRefs,
|
||||
context.selectedVc,
|
||||
context.linkTransactionResponse,
|
||||
context.clientName,
|
||||
context.configs,
|
||||
context.isSharing,
|
||||
];
|
||||
|
||||
emptyObjects.forEach(obj => {
|
||||
expect(typeof obj).toBe('object');
|
||||
expect(Object.keys(obj)).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Boolean properties', () => {
|
||||
const context = QrLoginmodel.initialContext;
|
||||
|
||||
it('showFaceAuthConsent should be true', () => {
|
||||
expect(context.showFaceAuthConsent).toBe(true);
|
||||
});
|
||||
|
||||
it('isQrLoginViaDeepLink should be false', () => {
|
||||
expect(context.isQrLoginViaDeepLink).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
512
machines/QrLogin/QrLoginSelectors.test.ts
Normal file
512
machines/QrLogin/QrLoginSelectors.test.ts
Normal file
@@ -0,0 +1,512 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import {
|
||||
selectMyVcs,
|
||||
selectIsWaitingForData,
|
||||
selectDomainName,
|
||||
selectIsLinkTransaction,
|
||||
selectIsloadMyVcs,
|
||||
selectIsShowingVcList,
|
||||
selectIsisVerifyingIdentity,
|
||||
selectIsInvalidIdentity,
|
||||
selectIsShowError,
|
||||
selectIsRequestConsent,
|
||||
selectIsSendingAuthenticate,
|
||||
selectIsSendingConsent,
|
||||
selectIsVerifyingSuccesful,
|
||||
selectCredential,
|
||||
selectVerifiableCredentialData,
|
||||
selectLinkTransactionResponse,
|
||||
selectEssentialClaims,
|
||||
selectVoluntaryClaims,
|
||||
selectLogoUrl,
|
||||
selectClientName,
|
||||
selectErrorMessage,
|
||||
selectIsSharing,
|
||||
selectIsQrLoginViaDeepLink,
|
||||
selectIsFaceVerificationConsent,
|
||||
} from './QrLoginSelectors';
|
||||
|
||||
describe('QrLoginSelectors', () => {
|
||||
const mockVc = {
|
||||
vcMetadata: {id: 'vc1', displayName: 'Test VC'},
|
||||
credential: {},
|
||||
};
|
||||
|
||||
const mockState: any = {
|
||||
context: {
|
||||
myVcs: [mockVc],
|
||||
domainName: 'example.com',
|
||||
selectedVc: mockVc,
|
||||
senderInfo: {name: 'Test Sender'},
|
||||
linkTransactionResponse: {status: 'success'},
|
||||
verifiableCredentialData: {type: 'VerifiableCredential'},
|
||||
connectionParams: {uri: 'https://connect.example.com'},
|
||||
},
|
||||
matches: jest.fn((stateName: string) => stateName === 'waitingForData'),
|
||||
};
|
||||
|
||||
describe('selectMyVcs', () => {
|
||||
it('should return my VCs from context', () => {
|
||||
const result = selectMyVcs(mockState);
|
||||
expect(result).toEqual([mockVc]);
|
||||
});
|
||||
|
||||
it('should return array of VCs', () => {
|
||||
const result = selectMyVcs(mockState);
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
expect(result.length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsWaitingForData', () => {
|
||||
it('should return true when in waitingForData state', () => {
|
||||
const result = selectIsWaitingForData(mockState);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with correct state', () => {
|
||||
selectIsWaitingForData(mockState);
|
||||
expect(mockState.matches).toHaveBeenCalledWith('waitingForData');
|
||||
});
|
||||
|
||||
it('should return false when not in waitingForData state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
const result = selectIsWaitingForData(state);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectDomainName', () => {
|
||||
it('should return domain name from context', () => {
|
||||
const result = selectDomainName(mockState);
|
||||
expect(result).toBe('example.com');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsLinkTransaction', () => {
|
||||
it('should return true when in linkTransaction state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'linkTransaction'),
|
||||
};
|
||||
const result = selectIsLinkTransaction(state);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with linkTransaction', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
selectIsLinkTransaction(state);
|
||||
expect(state.matches).toHaveBeenCalledWith('linkTransaction');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsloadMyVcs', () => {
|
||||
it('should return true when in loadMyVcs state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'loadMyVcs'),
|
||||
};
|
||||
const result = selectIsloadMyVcs(state);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with loadMyVcs', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
selectIsloadMyVcs(state);
|
||||
expect(state.matches).toHaveBeenCalledWith('loadMyVcs');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsShowingVcList', () => {
|
||||
it('should return true when in showvcList state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'showvcList'),
|
||||
};
|
||||
const result = selectIsShowingVcList(state);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with showvcList', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
selectIsShowingVcList(state);
|
||||
expect(state.matches).toHaveBeenCalledWith('showvcList');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsisVerifyingIdentity', () => {
|
||||
it('should return true when in faceAuth state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'faceAuth'),
|
||||
};
|
||||
const result = selectIsisVerifyingIdentity(state);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with faceAuth', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
selectIsisVerifyingIdentity(state);
|
||||
expect(state.matches).toHaveBeenCalledWith('faceAuth');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsInvalidIdentity', () => {
|
||||
it('should return true when in invalidIdentity state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'invalidIdentity'),
|
||||
};
|
||||
const result = selectIsInvalidIdentity(state);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with invalidIdentity', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
selectIsInvalidIdentity(state);
|
||||
expect(state.matches).toHaveBeenCalledWith('invalidIdentity');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsShowError', () => {
|
||||
it('should return true when in ShowError state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'ShowError'),
|
||||
};
|
||||
const result = selectIsShowError(state);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with ShowError', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
selectIsShowError(state);
|
||||
expect(state.matches).toHaveBeenCalledWith('ShowError');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsRequestConsent', () => {
|
||||
it('should return true when in requestConsent state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'requestConsent'),
|
||||
};
|
||||
const result = selectIsRequestConsent(state);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with requestConsent', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
selectIsRequestConsent(state);
|
||||
expect(state.matches).toHaveBeenCalledWith('requestConsent');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsSendingAuthenticate', () => {
|
||||
it('should return true when in sendingAuthenticate state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'sendingAuthenticate'),
|
||||
};
|
||||
const result = selectIsSendingAuthenticate(state);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with sendingAuthenticate', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
selectIsSendingAuthenticate(state);
|
||||
expect(state.matches).toHaveBeenCalledWith('sendingAuthenticate');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsSendingConsent', () => {
|
||||
it('should return true when in sendingConsent state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'sendingConsent'),
|
||||
};
|
||||
const result = selectIsSendingConsent(state);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with sendingConsent', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
selectIsSendingConsent(state);
|
||||
expect(state.matches).toHaveBeenCalledWith('sendingConsent');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsVerifyingSuccesful', () => {
|
||||
it('should return true when in success state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'success'),
|
||||
};
|
||||
const result = selectIsVerifyingSuccesful(state);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with success', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
selectIsVerifyingSuccesful(state);
|
||||
expect(state.matches).toHaveBeenCalledWith('success');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectCredential', () => {
|
||||
it('should return credential from selectedVc', () => {
|
||||
const result = selectCredential(mockState);
|
||||
expect(result).toBeDefined();
|
||||
});
|
||||
|
||||
it('should handle null selectedVc', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
context: {...mockState.context, selectedVc: null},
|
||||
};
|
||||
const result = selectCredential(state);
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectVerifiableCredentialData', () => {
|
||||
it('should return verifiable credential data', () => {
|
||||
const result = selectVerifiableCredentialData(mockState);
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
expect(result.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should include vcMetadata, issuer, and issuerLogo', () => {
|
||||
const result = selectVerifiableCredentialData(mockState);
|
||||
expect(result[0]).toHaveProperty('vcMetadata');
|
||||
expect(result[0]).toHaveProperty('issuer');
|
||||
expect(result[0]).toHaveProperty('issuerLogo');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectLinkTransactionResponse', () => {
|
||||
it('should return link transaction response from context', () => {
|
||||
const result = selectLinkTransactionResponse(mockState);
|
||||
expect(result).toEqual({status: 'success'});
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectEssentialClaims', () => {
|
||||
const stateWithClaims: any = {
|
||||
...mockState,
|
||||
context: {...mockState.context, essentialClaims: ['name', 'age']},
|
||||
};
|
||||
|
||||
it('should return essential claims from context', () => {
|
||||
const result = selectEssentialClaims(stateWithClaims);
|
||||
expect(result).toEqual(['name', 'age']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectVoluntaryClaims', () => {
|
||||
const stateWithClaims: any = {
|
||||
...mockState,
|
||||
context: {...mockState.context, voluntaryClaims: ['email']},
|
||||
};
|
||||
|
||||
it('should return voluntary claims from context', () => {
|
||||
const result = selectVoluntaryClaims(stateWithClaims);
|
||||
expect(result).toEqual(['email']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectLogoUrl', () => {
|
||||
const stateWithLogo: any = {
|
||||
...mockState,
|
||||
context: {...mockState.context, logoUrl: 'https://example.com/logo.png'},
|
||||
};
|
||||
|
||||
it('should return logo URL from context', () => {
|
||||
const result = selectLogoUrl(stateWithLogo);
|
||||
expect(result).toBe('https://example.com/logo.png');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectClientName', () => {
|
||||
const stateWithClient: any = {
|
||||
...mockState,
|
||||
context: {...mockState.context, clientName: 'Test Client'},
|
||||
};
|
||||
|
||||
it('should return client name from context', () => {
|
||||
const result = selectClientName(stateWithClient);
|
||||
expect(result).toBe('Test Client');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectErrorMessage', () => {
|
||||
const stateWithError: any = {
|
||||
...mockState,
|
||||
context: {...mockState.context, errorMessage: 'Test error'},
|
||||
};
|
||||
|
||||
it('should return error message from context', () => {
|
||||
const result = selectErrorMessage(stateWithError);
|
||||
expect(result).toBe('Test error');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsSharing', () => {
|
||||
const stateWithSharing: any = {
|
||||
...mockState,
|
||||
context: {...mockState.context, isSharing: true},
|
||||
};
|
||||
|
||||
it('should return sharing status from context', () => {
|
||||
const result = selectIsSharing(stateWithSharing);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when not sharing', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
context: {...mockState.context, isSharing: false},
|
||||
};
|
||||
const result = selectIsSharing(state);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsQrLoginViaDeepLink', () => {
|
||||
const stateWithDeepLink: any = {
|
||||
...mockState,
|
||||
context: {...mockState.context, isQrLoginViaDeepLink: true},
|
||||
};
|
||||
|
||||
it('should return deep link status from context', () => {
|
||||
const result = selectIsQrLoginViaDeepLink(stateWithDeepLink);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when not via deep link', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
context: {...mockState.context, isQrLoginViaDeepLink: false},
|
||||
};
|
||||
const result = selectIsQrLoginViaDeepLink(state);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsFaceVerificationConsent', () => {
|
||||
it('should return true when in faceVerificationConsent state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'faceVerificationConsent'),
|
||||
};
|
||||
const result = selectIsFaceVerificationConsent(state);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with faceVerificationConsent', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
selectIsFaceVerificationConsent(state);
|
||||
expect(state.matches).toHaveBeenCalledWith('faceVerificationConsent');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Selectors with empty/null values', () => {
|
||||
const emptyState: any = {
|
||||
context: {
|
||||
myVcs: [],
|
||||
domainName: '',
|
||||
selectedVc: null,
|
||||
linkTransactionResponse: null,
|
||||
essentialClaims: [],
|
||||
voluntaryClaims: [],
|
||||
logoUrl: '',
|
||||
clientName: '',
|
||||
errorMessage: '',
|
||||
isSharing: false,
|
||||
isQrLoginViaDeepLink: false,
|
||||
},
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
|
||||
it('should handle empty VCs array', () => {
|
||||
const result = selectMyVcs(emptyState);
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
it('should handle empty domain name', () => {
|
||||
const result = selectDomainName(emptyState);
|
||||
expect(result).toBe('');
|
||||
});
|
||||
|
||||
it('should handle empty strings', () => {
|
||||
expect(selectLogoUrl(emptyState)).toBe('');
|
||||
expect(selectClientName(emptyState)).toBe('');
|
||||
expect(selectErrorMessage(emptyState)).toBe('');
|
||||
});
|
||||
|
||||
it('should handle null responses', () => {
|
||||
expect(selectLinkTransactionResponse(emptyState)).toBeNull();
|
||||
});
|
||||
|
||||
it('should handle empty arrays', () => {
|
||||
expect(selectEssentialClaims(emptyState)).toEqual([]);
|
||||
expect(selectVoluntaryClaims(emptyState)).toEqual([]);
|
||||
});
|
||||
|
||||
it('should handle false boolean values', () => {
|
||||
expect(selectIsSharing(emptyState)).toBe(false);
|
||||
expect(selectIsQrLoginViaDeepLink(emptyState)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for all state checks', () => {
|
||||
expect(selectIsWaitingForData(emptyState)).toBe(false);
|
||||
expect(selectIsLinkTransaction(emptyState)).toBe(false);
|
||||
expect(selectIsloadMyVcs(emptyState)).toBe(false);
|
||||
expect(selectIsShowingVcList(emptyState)).toBe(false);
|
||||
expect(selectIsisVerifyingIdentity(emptyState)).toBe(false);
|
||||
expect(selectIsInvalidIdentity(emptyState)).toBe(false);
|
||||
expect(selectIsShowError(emptyState)).toBe(false);
|
||||
expect(selectIsRequestConsent(emptyState)).toBe(false);
|
||||
expect(selectIsSendingAuthenticate(emptyState)).toBe(false);
|
||||
expect(selectIsSendingConsent(emptyState)).toBe(false);
|
||||
expect(selectIsVerifyingSuccesful(emptyState)).toBe(false);
|
||||
expect(selectIsFaceVerificationConsent(emptyState)).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
290
machines/VerifiableCredential/VCItemMachine/VCItemModel.test.ts
Normal file
290
machines/VerifiableCredential/VCItemMachine/VCItemModel.test.ts
Normal file
@@ -0,0 +1,290 @@
|
||||
import {VCItemModel} from './VCItemModel';
|
||||
|
||||
describe('VCItemModel', () => {
|
||||
describe('Model structure', () => {
|
||||
it('should be defined', () => {
|
||||
expect(VCItemModel).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have initialContext', () => {
|
||||
expect(VCItemModel.initialContext).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have events', () => {
|
||||
expect(VCItemModel.events).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Initial Context', () => {
|
||||
const initialContext = VCItemModel.initialContext;
|
||||
|
||||
it('should have serviceRefs as empty object', () => {
|
||||
expect(initialContext.serviceRefs).toEqual({});
|
||||
expect(typeof initialContext.serviceRefs).toBe('object');
|
||||
});
|
||||
|
||||
it('should have vcMetadata as empty object', () => {
|
||||
expect(initialContext.vcMetadata).toEqual({});
|
||||
expect(typeof initialContext.vcMetadata).toBe('object');
|
||||
});
|
||||
|
||||
it('should have generatedOn as Date instance', () => {
|
||||
expect(initialContext.generatedOn).toBeInstanceOf(Date);
|
||||
});
|
||||
|
||||
it('should have credential as null', () => {
|
||||
expect(initialContext.credential).toBeNull();
|
||||
});
|
||||
|
||||
it('should have verifiableCredential as null', () => {
|
||||
expect(initialContext.verifiableCredential).toBeNull();
|
||||
});
|
||||
|
||||
it('should have hashedId as empty string', () => {
|
||||
expect(initialContext.hashedId).toBe('');
|
||||
expect(typeof initialContext.hashedId).toBe('string');
|
||||
});
|
||||
|
||||
it('should have publicKey as empty string', () => {
|
||||
expect(initialContext.publicKey).toBe('');
|
||||
expect(typeof initialContext.publicKey).toBe('string');
|
||||
});
|
||||
|
||||
it('should have privateKey as empty string', () => {
|
||||
expect(initialContext.privateKey).toBe('');
|
||||
expect(typeof initialContext.privateKey).toBe('string');
|
||||
});
|
||||
|
||||
it('should have OTP as empty string', () => {
|
||||
expect(initialContext.OTP).toBe('');
|
||||
expect(typeof initialContext.OTP).toBe('string');
|
||||
});
|
||||
|
||||
it('should have error as empty string', () => {
|
||||
expect(initialContext.error).toBe('');
|
||||
expect(typeof initialContext.error).toBe('string');
|
||||
});
|
||||
|
||||
it('should have bindingTransactionId as empty string', () => {
|
||||
expect(initialContext.bindingTransactionId).toBe('');
|
||||
expect(typeof initialContext.bindingTransactionId).toBe('string');
|
||||
});
|
||||
|
||||
it('should have requestId as empty string', () => {
|
||||
expect(initialContext.requestId).toBe('');
|
||||
expect(typeof initialContext.requestId).toBe('string');
|
||||
});
|
||||
|
||||
it('should have downloadCounter as 0', () => {
|
||||
expect(initialContext.downloadCounter).toBe(0);
|
||||
expect(typeof initialContext.downloadCounter).toBe('number');
|
||||
});
|
||||
|
||||
it('should have maxDownloadCount as null', () => {
|
||||
expect(initialContext.maxDownloadCount).toBeNull();
|
||||
});
|
||||
|
||||
it('should have downloadInterval as null', () => {
|
||||
expect(initialContext.downloadInterval).toBeNull();
|
||||
});
|
||||
|
||||
it('should have walletBindingResponse as null', () => {
|
||||
expect(initialContext.walletBindingResponse).toBeNull();
|
||||
});
|
||||
|
||||
it('should have isMachineInKebabPopupState as false', () => {
|
||||
expect(initialContext.isMachineInKebabPopupState).toBe(false);
|
||||
expect(typeof initialContext.isMachineInKebabPopupState).toBe('boolean');
|
||||
});
|
||||
|
||||
it('should have communicationDetails as null', () => {
|
||||
expect(initialContext.communicationDetails).toBeNull();
|
||||
});
|
||||
|
||||
it('should have verificationStatus as null', () => {
|
||||
expect(initialContext.verificationStatus).toBeNull();
|
||||
});
|
||||
|
||||
it('should have showVerificationStatusBanner as false', () => {
|
||||
expect(initialContext.showVerificationStatusBanner).toBe(false);
|
||||
expect(typeof initialContext.showVerificationStatusBanner).toBe(
|
||||
'boolean',
|
||||
);
|
||||
});
|
||||
|
||||
it('should have wellknownResponse as empty object', () => {
|
||||
expect(initialContext.wellknownResponse).toEqual({});
|
||||
expect(typeof initialContext.wellknownResponse).toBe('object');
|
||||
});
|
||||
|
||||
it('should have all 24 required properties', () => {
|
||||
const properties = Object.keys(initialContext);
|
||||
expect(properties).toHaveLength(24);
|
||||
});
|
||||
});
|
||||
|
||||
describe('String properties', () => {
|
||||
const context = VCItemModel.initialContext;
|
||||
|
||||
it('all empty string properties should be empty', () => {
|
||||
const emptyStrings = [
|
||||
context.hashedId,
|
||||
context.publicKey,
|
||||
context.privateKey,
|
||||
context.OTP,
|
||||
context.error,
|
||||
context.bindingTransactionId,
|
||||
context.requestId,
|
||||
];
|
||||
|
||||
emptyStrings.forEach(str => {
|
||||
expect(str).toBe('');
|
||||
expect(typeof str).toBe('string');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Object properties', () => {
|
||||
const context = VCItemModel.initialContext;
|
||||
|
||||
it('empty object properties should be empty objects', () => {
|
||||
const emptyObjects = [
|
||||
context.serviceRefs,
|
||||
context.vcMetadata,
|
||||
context.wellknownResponse,
|
||||
];
|
||||
|
||||
emptyObjects.forEach(obj => {
|
||||
expect(typeof obj).toBe('object');
|
||||
expect(Object.keys(obj)).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Boolean properties', () => {
|
||||
const context = VCItemModel.initialContext;
|
||||
|
||||
it('isMachineInKebabPopupState should be false', () => {
|
||||
expect(context.isMachineInKebabPopupState).toBe(false);
|
||||
expect(typeof context.isMachineInKebabPopupState).toBe('boolean');
|
||||
});
|
||||
|
||||
it('showVerificationStatusBanner should be false', () => {
|
||||
expect(context.showVerificationStatusBanner).toBe(false);
|
||||
expect(typeof context.showVerificationStatusBanner).toBe('boolean');
|
||||
});
|
||||
|
||||
it('all boolean properties should be false initially', () => {
|
||||
const booleans = [
|
||||
context.isMachineInKebabPopupState,
|
||||
context.showVerificationStatusBanner,
|
||||
];
|
||||
|
||||
booleans.forEach(bool => {
|
||||
expect(bool).toBe(false);
|
||||
expect(typeof bool).toBe('boolean');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Null properties', () => {
|
||||
const context = VCItemModel.initialContext;
|
||||
|
||||
it('credential should be null', () => {
|
||||
expect(context.credential).toBeNull();
|
||||
});
|
||||
|
||||
it('verifiableCredential should be null', () => {
|
||||
expect(context.verifiableCredential).toBeNull();
|
||||
});
|
||||
|
||||
it('maxDownloadCount should be null', () => {
|
||||
expect(context.maxDownloadCount).toBeNull();
|
||||
});
|
||||
|
||||
it('downloadInterval should be null', () => {
|
||||
expect(context.downloadInterval).toBeNull();
|
||||
});
|
||||
|
||||
it('walletBindingResponse should be null', () => {
|
||||
expect(context.walletBindingResponse).toBeNull();
|
||||
});
|
||||
|
||||
it('communicationDetails should be null', () => {
|
||||
expect(context.communicationDetails).toBeNull();
|
||||
});
|
||||
|
||||
it('verificationStatus should be null', () => {
|
||||
expect(context.verificationStatus).toBeNull();
|
||||
});
|
||||
|
||||
it('all null properties should be null initially', () => {
|
||||
const nullProps = [
|
||||
context.credential,
|
||||
context.verifiableCredential,
|
||||
context.maxDownloadCount,
|
||||
context.downloadInterval,
|
||||
context.walletBindingResponse,
|
||||
context.communicationDetails,
|
||||
context.verificationStatus,
|
||||
];
|
||||
|
||||
nullProps.forEach(prop => {
|
||||
expect(prop).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Number properties', () => {
|
||||
const context = VCItemModel.initialContext;
|
||||
|
||||
it('downloadCounter should be 0', () => {
|
||||
expect(context.downloadCounter).toBe(0);
|
||||
expect(typeof context.downloadCounter).toBe('number');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Date properties', () => {
|
||||
const context = VCItemModel.initialContext;
|
||||
|
||||
it('generatedOn should be a Date instance', () => {
|
||||
expect(context.generatedOn).toBeInstanceOf(Date);
|
||||
});
|
||||
|
||||
it('generatedOn should be a valid date', () => {
|
||||
expect(context.generatedOn.getTime()).not.toBeNaN();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Model events', () => {
|
||||
it('should have events object', () => {
|
||||
expect(VCItemModel.events).toBeDefined();
|
||||
expect(typeof VCItemModel.events).toBe('object');
|
||||
});
|
||||
|
||||
it('should have event creators', () => {
|
||||
const eventKeys = Object.keys(VCItemModel.events);
|
||||
expect(eventKeys.length).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Property types validation', () => {
|
||||
const context = VCItemModel.initialContext;
|
||||
|
||||
it('should have correct types for all properties', () => {
|
||||
expect(typeof context.hashedId).toBe('string');
|
||||
expect(typeof context.publicKey).toBe('string');
|
||||
expect(typeof context.privateKey).toBe('string');
|
||||
expect(typeof context.OTP).toBe('string');
|
||||
expect(typeof context.error).toBe('string');
|
||||
expect(typeof context.bindingTransactionId).toBe('string');
|
||||
expect(typeof context.requestId).toBe('string');
|
||||
expect(typeof context.downloadCounter).toBe('number');
|
||||
expect(typeof context.isMachineInKebabPopupState).toBe('boolean');
|
||||
expect(typeof context.showVerificationStatusBanner).toBe('boolean');
|
||||
expect(typeof context.serviceRefs).toBe('object');
|
||||
expect(typeof context.vcMetadata).toBe('object');
|
||||
expect(context.generatedOn).toBeInstanceOf(Date);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,451 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import {
|
||||
selectVerificationStatus,
|
||||
selectIsVerificationInProgress,
|
||||
selectIsVerificationCompleted,
|
||||
selectShowVerificationStatusBanner,
|
||||
selectVerifiableCredential,
|
||||
getVerifiableCredential,
|
||||
selectCredential,
|
||||
selectVerifiableCredentialData,
|
||||
selectKebabPopUp,
|
||||
selectContext,
|
||||
selectGeneratedOn,
|
||||
selectWalletBindingSuccess,
|
||||
selectWalletBindingResponse,
|
||||
selectIsCommunicationDetails,
|
||||
selectWalletBindingError,
|
||||
selectBindingAuthFailedError,
|
||||
selectAcceptingBindingOtp,
|
||||
selectWalletBindingInProgress,
|
||||
selectBindingWarning,
|
||||
selectRemoveWalletWarning,
|
||||
selectIsPinned,
|
||||
selectOtpError,
|
||||
selectShowActivities,
|
||||
selectShowWalletBindingError,
|
||||
selectVc,
|
||||
} from './VCItemSelectors';
|
||||
|
||||
describe('VCItemSelectors', () => {
|
||||
describe('selectVerificationStatus', () => {
|
||||
it('should return verification status from context', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
verificationStatus: 'verified',
|
||||
},
|
||||
};
|
||||
expect(selectVerificationStatus(mockState)).toBe('verified');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsVerificationInProgress', () => {
|
||||
it('should return true when in verifyingCredential state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(
|
||||
(state: string) => state === 'verifyState.verifyingCredential',
|
||||
),
|
||||
};
|
||||
expect(selectIsVerificationInProgress(mockState)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when not in verifyingCredential state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
expect(selectIsVerificationInProgress(mockState)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsVerificationCompleted', () => {
|
||||
it('should return true when in verificationCompleted state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(
|
||||
(state: string) => state === 'verifyState.verificationCompleted',
|
||||
),
|
||||
};
|
||||
expect(selectIsVerificationCompleted(mockState)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when not in verificationCompleted state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
expect(selectIsVerificationCompleted(mockState)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectShowVerificationStatusBanner', () => {
|
||||
it('should return showVerificationStatusBanner from context', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
showVerificationStatusBanner: true,
|
||||
},
|
||||
};
|
||||
expect(selectShowVerificationStatusBanner(mockState)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectVerifiableCredential', () => {
|
||||
it('should return verifiableCredential from context', () => {
|
||||
const mockVC = {credential: {id: 'test-123'}};
|
||||
const mockState: any = {
|
||||
context: {
|
||||
verifiableCredential: mockVC,
|
||||
},
|
||||
};
|
||||
expect(selectVerifiableCredential(mockState)).toBe(mockVC);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getVerifiableCredential', () => {
|
||||
it('should return credential property if it exists', () => {
|
||||
const mockCredential = {id: 'cred-123'};
|
||||
const mockVC: any = {
|
||||
credential: mockCredential,
|
||||
};
|
||||
expect(getVerifiableCredential(mockVC)).toBe(mockCredential);
|
||||
});
|
||||
|
||||
it('should return the whole object if credential property does not exist', () => {
|
||||
const mockCredential: any = {id: 'cred-456'};
|
||||
expect(getVerifiableCredential(mockCredential)).toBe(mockCredential);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectCredential', () => {
|
||||
it('should return verifiableCredential from context', () => {
|
||||
const mockVC = {credential: {id: 'test-789'}};
|
||||
const mockState: any = {
|
||||
context: {
|
||||
verifiableCredential: mockVC,
|
||||
},
|
||||
};
|
||||
expect(selectCredential(mockState)).toBe(mockVC);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectVerifiableCredentialData', () => {
|
||||
it('should return formatted verifiable credential data', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
vcMetadata: {
|
||||
id: 'vc-001',
|
||||
issuer: 'Test Issuer',
|
||||
format: 'ldp_vc',
|
||||
},
|
||||
verifiableCredential: {
|
||||
credential: {
|
||||
credentialSubject: {
|
||||
name: 'John Doe',
|
||||
},
|
||||
},
|
||||
issuerLogo: 'https://example.com/logo.png',
|
||||
wellKnown: 'https://example.com/.well-known',
|
||||
credentialConfigurationId: 'config-123',
|
||||
},
|
||||
format: 'ldp_vc',
|
||||
credential: null,
|
||||
},
|
||||
};
|
||||
|
||||
const result = selectVerifiableCredentialData(mockState);
|
||||
expect(result.issuer).toBe('Test Issuer');
|
||||
expect(result.issuerLogo).toBe('https://example.com/logo.png');
|
||||
expect(result.wellKnown).toBe('https://example.com/.well-known');
|
||||
expect(result.credentialConfigurationId).toBe('config-123');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectKebabPopUp', () => {
|
||||
it('should return isMachineInKebabPopupState from context', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
isMachineInKebabPopupState: true,
|
||||
},
|
||||
};
|
||||
expect(selectKebabPopUp(mockState)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectContext', () => {
|
||||
it('should return entire context', () => {
|
||||
const mockContext = {
|
||||
verificationStatus: 'verified',
|
||||
generatedOn: '2023-01-01',
|
||||
};
|
||||
const mockState: any = {
|
||||
context: mockContext,
|
||||
};
|
||||
expect(selectContext(mockState)).toBe(mockContext);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectGeneratedOn', () => {
|
||||
it('should return generatedOn from context', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
generatedOn: '2023-12-25',
|
||||
},
|
||||
};
|
||||
expect(selectGeneratedOn(mockState)).toBe('2023-12-25');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectWalletBindingSuccess', () => {
|
||||
it('should return walletBindingResponse from context', () => {
|
||||
const mockResponse = {walletBindingId: 'binding-123'};
|
||||
const mockState: any = {
|
||||
context: {
|
||||
walletBindingResponse: mockResponse,
|
||||
},
|
||||
};
|
||||
expect(selectWalletBindingSuccess(mockState)).toBe(mockResponse);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectWalletBindingResponse', () => {
|
||||
it('should return walletBindingResponse from context', () => {
|
||||
const mockResponse = {walletBindingId: 'binding-456'};
|
||||
const mockState: any = {
|
||||
context: {
|
||||
walletBindingResponse: mockResponse,
|
||||
},
|
||||
};
|
||||
expect(selectWalletBindingResponse(mockState)).toBe(mockResponse);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsCommunicationDetails', () => {
|
||||
it('should return communicationDetails from context', () => {
|
||||
const mockDetails = {email: 'test@example.com', phone: '1234567890'};
|
||||
const mockState: any = {
|
||||
context: {
|
||||
communicationDetails: mockDetails,
|
||||
},
|
||||
};
|
||||
expect(selectIsCommunicationDetails(mockState)).toBe(mockDetails);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectWalletBindingError', () => {
|
||||
it('should return error from context', () => {
|
||||
const mockError = new Error('Binding failed');
|
||||
const mockState: any = {
|
||||
context: {
|
||||
error: mockError,
|
||||
},
|
||||
};
|
||||
expect(selectWalletBindingError(mockState)).toBe(mockError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectBindingAuthFailedError', () => {
|
||||
it('should return error from context', () => {
|
||||
const mockError = new Error('Auth failed');
|
||||
const mockState: any = {
|
||||
context: {
|
||||
error: mockError,
|
||||
},
|
||||
};
|
||||
expect(selectBindingAuthFailedError(mockState)).toBe(mockError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectAcceptingBindingOtp', () => {
|
||||
it('should return true when in acceptingBindingOTP state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(
|
||||
(state: string) =>
|
||||
state === 'vcUtilitiesState.walletBinding.acceptingBindingOTP',
|
||||
),
|
||||
};
|
||||
expect(selectAcceptingBindingOtp(mockState)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when not in acceptingBindingOTP state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
expect(selectAcceptingBindingOtp(mockState)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectWalletBindingInProgress', () => {
|
||||
it('should return true when in requestingBindingOTP state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(
|
||||
(state: string) =>
|
||||
state === 'vcUtilitiesState.walletBinding.requestingBindingOTP',
|
||||
),
|
||||
};
|
||||
expect(selectWalletBindingInProgress(mockState)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true when in addingWalletBindingId state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(
|
||||
(state: string) =>
|
||||
state === 'vcUtilitiesState.walletBinding.addingWalletBindingId',
|
||||
),
|
||||
};
|
||||
expect(selectWalletBindingInProgress(mockState)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true when in addKeyPair state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(
|
||||
(state: string) =>
|
||||
state === 'vcUtilitiesState.walletBinding.addKeyPair',
|
||||
),
|
||||
};
|
||||
expect(selectWalletBindingInProgress(mockState)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true when in updatingPrivateKey state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(
|
||||
(state: string) =>
|
||||
state === 'vcUtilitiesState.walletBinding.updatingPrivateKey',
|
||||
),
|
||||
};
|
||||
expect(selectWalletBindingInProgress(mockState)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when not in any wallet binding progress state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
expect(selectWalletBindingInProgress(mockState)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectBindingWarning', () => {
|
||||
it('should return true when in showBindingWarning state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(
|
||||
(state: string) =>
|
||||
state === 'vcUtilitiesState.walletBinding.showBindingWarning',
|
||||
),
|
||||
};
|
||||
expect(selectBindingWarning(mockState)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when not in showBindingWarning state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
expect(selectBindingWarning(mockState)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectRemoveWalletWarning', () => {
|
||||
it('should return true when in removeWallet state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(
|
||||
(state: string) =>
|
||||
state === 'vcUtilitiesState.kebabPopUp.removeWallet',
|
||||
),
|
||||
};
|
||||
expect(selectRemoveWalletWarning(mockState)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when not in removeWallet state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
expect(selectRemoveWalletWarning(mockState)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsPinned', () => {
|
||||
it('should return isPinned from vcMetadata', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
vcMetadata: {
|
||||
isPinned: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
expect(selectIsPinned(mockState)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when isPinned is false', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
vcMetadata: {
|
||||
isPinned: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
expect(selectIsPinned(mockState)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectOtpError', () => {
|
||||
it('should return error from context', () => {
|
||||
const mockError = new Error('OTP invalid');
|
||||
const mockState: any = {
|
||||
context: {
|
||||
error: mockError,
|
||||
},
|
||||
};
|
||||
expect(selectOtpError(mockState)).toBe(mockError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectShowActivities', () => {
|
||||
it('should return true when in showActivities state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(
|
||||
(state: string) =>
|
||||
state === 'vcUtilitiesState.kebabPopUp.showActivities',
|
||||
),
|
||||
};
|
||||
expect(selectShowActivities(mockState)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when not in showActivities state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
expect(selectShowActivities(mockState)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectShowWalletBindingError', () => {
|
||||
it('should return true when in showingWalletBindingError state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(
|
||||
(state: string) =>
|
||||
state ===
|
||||
'vcUtilitiesState.walletBinding.showingWalletBindingError',
|
||||
),
|
||||
};
|
||||
expect(selectShowWalletBindingError(mockState)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when not in showingWalletBindingError state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
expect(selectShowWalletBindingError(mockState)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectVc', () => {
|
||||
it('should return context without serviceRefs', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
verificationStatus: 'verified',
|
||||
generatedOn: '2023-01-01',
|
||||
serviceRefs: {ref1: 'service1', ref2: 'service2'},
|
||||
},
|
||||
};
|
||||
const result: any = selectVc(mockState);
|
||||
expect(result.verificationStatus).toBe('verified');
|
||||
expect(result.generatedOn).toBe('2023-01-01');
|
||||
expect(result.serviceRefs).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
288
machines/VerifiableCredential/VCMetaMachine/VCMetaEvents.test.ts
Normal file
288
machines/VerifiableCredential/VCMetaMachine/VCMetaEvents.test.ts
Normal file
@@ -0,0 +1,288 @@
|
||||
import {VcMetaEvents} from './VCMetaEvents';
|
||||
import {VCMetadata} from '../../../shared/VCMetadata';
|
||||
import {VC} from './vc';
|
||||
|
||||
describe('VcMetaEvents', () => {
|
||||
describe('VIEW_VC', () => {
|
||||
it('should create event with vc', () => {
|
||||
const vc = {id: 'vc-123'} as unknown as VC;
|
||||
const result = VcMetaEvents.VIEW_VC(vc);
|
||||
expect(result).toEqual({vc});
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET_VC_ITEM', () => {
|
||||
it('should create event with vcMetadata', () => {
|
||||
const vcMetadata = new VCMetadata();
|
||||
const result = VcMetaEvents.GET_VC_ITEM(vcMetadata);
|
||||
expect(result).toEqual({vcMetadata});
|
||||
});
|
||||
});
|
||||
|
||||
describe('STORE_RESPONSE', () => {
|
||||
it('should create event with response', () => {
|
||||
const response = {data: 'test'};
|
||||
const result = VcMetaEvents.STORE_RESPONSE(response);
|
||||
expect(result).toEqual({response: {data: 'test'}});
|
||||
});
|
||||
|
||||
it('should handle undefined response', () => {
|
||||
const result = VcMetaEvents.STORE_RESPONSE(undefined);
|
||||
expect(result).toEqual({response: undefined});
|
||||
});
|
||||
});
|
||||
|
||||
describe('STORE_ERROR', () => {
|
||||
it('should create event with error', () => {
|
||||
const error = new Error('Test error');
|
||||
const result = VcMetaEvents.STORE_ERROR(error);
|
||||
expect(result).toEqual({error});
|
||||
});
|
||||
});
|
||||
|
||||
describe('VC_ADDED', () => {
|
||||
it('should create event with vcMetadata', () => {
|
||||
const vcMetadata = new VCMetadata();
|
||||
const result = VcMetaEvents.VC_ADDED(vcMetadata);
|
||||
expect(result).toEqual({vcMetadata});
|
||||
});
|
||||
});
|
||||
|
||||
describe('REMOVE_VC_FROM_CONTEXT', () => {
|
||||
it('should create event with vcMetadata', () => {
|
||||
const vcMetadata = new VCMetadata();
|
||||
const result = VcMetaEvents.REMOVE_VC_FROM_CONTEXT(vcMetadata);
|
||||
expect(result).toEqual({vcMetadata});
|
||||
});
|
||||
});
|
||||
|
||||
describe('VC_METADATA_UPDATED', () => {
|
||||
it('should create event with vcMetadata', () => {
|
||||
const vcMetadata = new VCMetadata();
|
||||
const result = VcMetaEvents.VC_METADATA_UPDATED(vcMetadata);
|
||||
expect(result).toEqual({vcMetadata});
|
||||
});
|
||||
});
|
||||
|
||||
describe('VC_DOWNLOADED', () => {
|
||||
it('should create event with vc and vcMetadata', () => {
|
||||
const vc = {id: 'vc-123'} as unknown as VC;
|
||||
const vcMetadata = new VCMetadata();
|
||||
const result = VcMetaEvents.VC_DOWNLOADED(vc, vcMetadata);
|
||||
expect(result.vc).toBe(vc);
|
||||
expect(result.vcMetadata).toBe(vcMetadata);
|
||||
});
|
||||
|
||||
it('should handle undefined vcMetadata', () => {
|
||||
const vc = {id: 'vc-123'} as unknown as VC;
|
||||
const result = VcMetaEvents.VC_DOWNLOADED(vc);
|
||||
expect(result.vc).toBe(vc);
|
||||
expect(result.vcMetadata).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('REFRESH_MY_VCS', () => {
|
||||
it('should create empty event', () => {
|
||||
const result = VcMetaEvents.REFRESH_MY_VCS();
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('REFRESH_MY_VCS_TWO', () => {
|
||||
it('should create event with vc', () => {
|
||||
const vc = {id: 'vc-123'} as unknown as VC;
|
||||
const result = VcMetaEvents.REFRESH_MY_VCS_TWO(vc);
|
||||
expect(result).toEqual({vc});
|
||||
});
|
||||
});
|
||||
|
||||
describe('REFRESH_RECEIVED_VCS', () => {
|
||||
it('should create empty event', () => {
|
||||
const result = VcMetaEvents.REFRESH_RECEIVED_VCS();
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('WALLET_BINDING_SUCCESS', () => {
|
||||
it('should create event with vcKey and vc', () => {
|
||||
const vcKey = 'key-123';
|
||||
const vc = {id: 'vc-123'} as unknown as VC;
|
||||
const result = VcMetaEvents.WALLET_BINDING_SUCCESS(vcKey, vc);
|
||||
expect(result).toEqual({vcKey: 'key-123', vc});
|
||||
});
|
||||
});
|
||||
|
||||
describe('RESET_WALLET_BINDING_SUCCESS', () => {
|
||||
it('should create empty event', () => {
|
||||
const result = VcMetaEvents.RESET_WALLET_BINDING_SUCCESS();
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('ADD_VC_TO_IN_PROGRESS_DOWNLOADS', () => {
|
||||
it('should create event with requestId', () => {
|
||||
const result = VcMetaEvents.ADD_VC_TO_IN_PROGRESS_DOWNLOADS('req-123');
|
||||
expect(result).toEqual({requestId: 'req-123'});
|
||||
});
|
||||
});
|
||||
|
||||
describe('REMOVE_VC_FROM_IN_PROGRESS_DOWNLOADS', () => {
|
||||
it('should create event with vcMetadata', () => {
|
||||
const vcMetadata = new VCMetadata();
|
||||
const result =
|
||||
VcMetaEvents.REMOVE_VC_FROM_IN_PROGRESS_DOWNLOADS(vcMetadata);
|
||||
expect(result).toEqual({vcMetadata});
|
||||
});
|
||||
});
|
||||
|
||||
describe('RESET_IN_PROGRESS_VCS_DOWNLOADED', () => {
|
||||
it('should create empty event', () => {
|
||||
const result = VcMetaEvents.RESET_IN_PROGRESS_VCS_DOWNLOADED();
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('REMOVE_TAMPERED_VCS', () => {
|
||||
it('should create empty event', () => {
|
||||
const result = VcMetaEvents.REMOVE_TAMPERED_VCS();
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('DOWNLOAD_LIMIT_EXPIRED', () => {
|
||||
it('should create event with vcMetadata', () => {
|
||||
const vcMetadata = new VCMetadata();
|
||||
const result = VcMetaEvents.DOWNLOAD_LIMIT_EXPIRED(vcMetadata);
|
||||
expect(result).toEqual({vcMetadata});
|
||||
});
|
||||
});
|
||||
|
||||
describe('DELETE_VC', () => {
|
||||
it('should create empty event', () => {
|
||||
const result = VcMetaEvents.DELETE_VC();
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('VERIFY_VC_FAILED', () => {
|
||||
it('should create event with errorMessage and vcMetadata', () => {
|
||||
const vcMetadata = new VCMetadata();
|
||||
const result = VcMetaEvents.VERIFY_VC_FAILED(
|
||||
'Verification failed',
|
||||
vcMetadata,
|
||||
);
|
||||
expect(result.errorMessage).toBe('Verification failed');
|
||||
expect(result.vcMetadata).toBe(vcMetadata);
|
||||
});
|
||||
|
||||
it('should handle undefined vcMetadata', () => {
|
||||
const result = VcMetaEvents.VERIFY_VC_FAILED('Error occurred');
|
||||
expect(result.errorMessage).toBe('Error occurred');
|
||||
expect(result.vcMetadata).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('RESET_VERIFY_ERROR', () => {
|
||||
it('should create empty event', () => {
|
||||
const result = VcMetaEvents.RESET_VERIFY_ERROR();
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('REFRESH_VCS_METADATA', () => {
|
||||
it('should create empty event', () => {
|
||||
const result = VcMetaEvents.REFRESH_VCS_METADATA();
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('SHOW_TAMPERED_POPUP', () => {
|
||||
it('should create empty event', () => {
|
||||
const result = VcMetaEvents.SHOW_TAMPERED_POPUP();
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('SET_VERIFICATION_STATUS', () => {
|
||||
it('should create event with verificationStatus', () => {
|
||||
const status = {verified: true};
|
||||
const result = VcMetaEvents.SET_VERIFICATION_STATUS(status);
|
||||
expect(result).toEqual({verificationStatus: status});
|
||||
});
|
||||
});
|
||||
|
||||
describe('RESET_VERIFICATION_STATUS', () => {
|
||||
it('should create event with verificationStatus', () => {
|
||||
const status = {message: 'Reset'} as any;
|
||||
const result = VcMetaEvents.RESET_VERIFICATION_STATUS(status);
|
||||
expect(result).toEqual({verificationStatus: status});
|
||||
});
|
||||
|
||||
it('should handle null verificationStatus', () => {
|
||||
const result = VcMetaEvents.RESET_VERIFICATION_STATUS(null);
|
||||
expect(result).toEqual({verificationStatus: null});
|
||||
});
|
||||
});
|
||||
|
||||
describe('VC_DOWNLOADING_FAILED', () => {
|
||||
it('should create empty event', () => {
|
||||
const result = VcMetaEvents.VC_DOWNLOADING_FAILED();
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('RESET_DOWNLOADING_FAILED', () => {
|
||||
it('should create empty event', () => {
|
||||
const result = VcMetaEvents.RESET_DOWNLOADING_FAILED();
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('RESET_DOWNLOADING_SUCCESS', () => {
|
||||
it('should create empty event', () => {
|
||||
const result = VcMetaEvents.RESET_DOWNLOADING_SUCCESS();
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('VcMetaEvents object structure', () => {
|
||||
it('should have all expected event creators', () => {
|
||||
expect(VcMetaEvents.VIEW_VC).toBeDefined();
|
||||
expect(VcMetaEvents.GET_VC_ITEM).toBeDefined();
|
||||
expect(VcMetaEvents.STORE_RESPONSE).toBeDefined();
|
||||
expect(VcMetaEvents.STORE_ERROR).toBeDefined();
|
||||
expect(VcMetaEvents.VC_ADDED).toBeDefined();
|
||||
expect(VcMetaEvents.REMOVE_VC_FROM_CONTEXT).toBeDefined();
|
||||
expect(VcMetaEvents.VC_METADATA_UPDATED).toBeDefined();
|
||||
expect(VcMetaEvents.VC_DOWNLOADED).toBeDefined();
|
||||
expect(VcMetaEvents.REFRESH_MY_VCS).toBeDefined();
|
||||
expect(VcMetaEvents.REFRESH_MY_VCS_TWO).toBeDefined();
|
||||
expect(VcMetaEvents.REFRESH_RECEIVED_VCS).toBeDefined();
|
||||
expect(VcMetaEvents.WALLET_BINDING_SUCCESS).toBeDefined();
|
||||
expect(VcMetaEvents.RESET_WALLET_BINDING_SUCCESS).toBeDefined();
|
||||
expect(VcMetaEvents.ADD_VC_TO_IN_PROGRESS_DOWNLOADS).toBeDefined();
|
||||
expect(VcMetaEvents.REMOVE_VC_FROM_IN_PROGRESS_DOWNLOADS).toBeDefined();
|
||||
expect(VcMetaEvents.RESET_IN_PROGRESS_VCS_DOWNLOADED).toBeDefined();
|
||||
expect(VcMetaEvents.REMOVE_TAMPERED_VCS).toBeDefined();
|
||||
expect(VcMetaEvents.DOWNLOAD_LIMIT_EXPIRED).toBeDefined();
|
||||
expect(VcMetaEvents.DELETE_VC).toBeDefined();
|
||||
expect(VcMetaEvents.VERIFY_VC_FAILED).toBeDefined();
|
||||
expect(VcMetaEvents.RESET_VERIFY_ERROR).toBeDefined();
|
||||
expect(VcMetaEvents.REFRESH_VCS_METADATA).toBeDefined();
|
||||
expect(VcMetaEvents.SHOW_TAMPERED_POPUP).toBeDefined();
|
||||
expect(VcMetaEvents.SET_VERIFICATION_STATUS).toBeDefined();
|
||||
expect(VcMetaEvents.RESET_VERIFICATION_STATUS).toBeDefined();
|
||||
expect(VcMetaEvents.VC_DOWNLOADING_FAILED).toBeDefined();
|
||||
expect(VcMetaEvents.RESET_DOWNLOADING_FAILED).toBeDefined();
|
||||
expect(VcMetaEvents.RESET_DOWNLOADING_SUCCESS).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have all event creators be functions', () => {
|
||||
expect(typeof VcMetaEvents.VIEW_VC).toBe('function');
|
||||
expect(typeof VcMetaEvents.GET_VC_ITEM).toBe('function');
|
||||
expect(typeof VcMetaEvents.STORE_RESPONSE).toBe('function');
|
||||
expect(typeof VcMetaEvents.STORE_ERROR).toBe('function');
|
||||
expect(typeof VcMetaEvents.VC_ADDED).toBe('function');
|
||||
});
|
||||
});
|
||||
});
|
||||
219
machines/VerifiableCredential/VCMetaMachine/VCMetaModel.test.ts
Normal file
219
machines/VerifiableCredential/VCMetaMachine/VCMetaModel.test.ts
Normal file
@@ -0,0 +1,219 @@
|
||||
import {VCMetamodel} from './VCMetaModel';
|
||||
|
||||
describe('VCMetaModel', () => {
|
||||
describe('Model structure', () => {
|
||||
it('should be defined', () => {
|
||||
expect(VCMetamodel).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have initialContext', () => {
|
||||
expect(VCMetamodel.initialContext).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have events', () => {
|
||||
expect(VCMetamodel.events).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Initial Context', () => {
|
||||
const initialContext = VCMetamodel.initialContext;
|
||||
|
||||
it('should have serviceRefs as empty object', () => {
|
||||
expect(initialContext.serviceRefs).toEqual({});
|
||||
expect(typeof initialContext.serviceRefs).toBe('object');
|
||||
});
|
||||
|
||||
it('should have myVcsMetadata as empty array', () => {
|
||||
expect(initialContext.myVcsMetadata).toEqual([]);
|
||||
expect(Array.isArray(initialContext.myVcsMetadata)).toBe(true);
|
||||
expect(initialContext.myVcsMetadata).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should have receivedVcsMetadata as empty array', () => {
|
||||
expect(initialContext.receivedVcsMetadata).toEqual([]);
|
||||
expect(Array.isArray(initialContext.receivedVcsMetadata)).toBe(true);
|
||||
expect(initialContext.receivedVcsMetadata).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should have myVcs as empty object', () => {
|
||||
expect(initialContext.myVcs).toEqual({});
|
||||
expect(typeof initialContext.myVcs).toBe('object');
|
||||
expect(Object.keys(initialContext.myVcs)).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should have receivedVcs as empty object', () => {
|
||||
expect(initialContext.receivedVcs).toEqual({});
|
||||
expect(typeof initialContext.receivedVcs).toBe('object');
|
||||
expect(Object.keys(initialContext.receivedVcs)).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should have inProgressVcDownloads as empty Set', () => {
|
||||
expect(initialContext.inProgressVcDownloads).toBeInstanceOf(Set);
|
||||
expect(initialContext.inProgressVcDownloads.size).toBe(0);
|
||||
});
|
||||
|
||||
it('should have areAllVcsDownloaded as false', () => {
|
||||
expect(initialContext.areAllVcsDownloaded).toBe(false);
|
||||
expect(typeof initialContext.areAllVcsDownloaded).toBe('boolean');
|
||||
});
|
||||
|
||||
it('should have walletBindingSuccess as false', () => {
|
||||
expect(initialContext.walletBindingSuccess).toBe(false);
|
||||
expect(typeof initialContext.walletBindingSuccess).toBe('boolean');
|
||||
});
|
||||
|
||||
it('should have tamperedVcs as empty array', () => {
|
||||
expect(initialContext.tamperedVcs).toEqual([]);
|
||||
expect(Array.isArray(initialContext.tamperedVcs)).toBe(true);
|
||||
expect(initialContext.tamperedVcs).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should have downloadingFailedVcs as empty array', () => {
|
||||
expect(initialContext.downloadingFailedVcs).toEqual([]);
|
||||
expect(Array.isArray(initialContext.downloadingFailedVcs)).toBe(true);
|
||||
expect(initialContext.downloadingFailedVcs).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should have verificationErrorMessage as empty string', () => {
|
||||
expect(initialContext.verificationErrorMessage).toBe('');
|
||||
expect(typeof initialContext.verificationErrorMessage).toBe('string');
|
||||
});
|
||||
|
||||
it('should have verificationStatus as null', () => {
|
||||
expect(initialContext.verificationStatus).toBeNull();
|
||||
});
|
||||
|
||||
it('should have DownloadingCredentialsFailed as false', () => {
|
||||
expect(initialContext.DownloadingCredentialsFailed).toBe(false);
|
||||
expect(typeof initialContext.DownloadingCredentialsFailed).toBe(
|
||||
'boolean',
|
||||
);
|
||||
});
|
||||
|
||||
it('should have DownloadingCredentialsSuccess as false', () => {
|
||||
expect(initialContext.DownloadingCredentialsSuccess).toBe(false);
|
||||
expect(typeof initialContext.DownloadingCredentialsSuccess).toBe(
|
||||
'boolean',
|
||||
);
|
||||
});
|
||||
|
||||
it('should have all required properties', () => {
|
||||
expect(initialContext).toHaveProperty('serviceRefs');
|
||||
expect(initialContext).toHaveProperty('myVcsMetadata');
|
||||
expect(initialContext).toHaveProperty('receivedVcsMetadata');
|
||||
expect(initialContext).toHaveProperty('myVcs');
|
||||
expect(initialContext).toHaveProperty('receivedVcs');
|
||||
expect(initialContext).toHaveProperty('inProgressVcDownloads');
|
||||
expect(initialContext).toHaveProperty('areAllVcsDownloaded');
|
||||
expect(initialContext).toHaveProperty('walletBindingSuccess');
|
||||
expect(initialContext).toHaveProperty('tamperedVcs');
|
||||
expect(initialContext).toHaveProperty('downloadingFailedVcs');
|
||||
expect(initialContext).toHaveProperty('verificationErrorMessage');
|
||||
expect(initialContext).toHaveProperty('verificationStatus');
|
||||
expect(initialContext).toHaveProperty('DownloadingCredentialsFailed');
|
||||
expect(initialContext).toHaveProperty('DownloadingCredentialsSuccess');
|
||||
});
|
||||
|
||||
it('should have exactly 16 properties in initial context', () => {
|
||||
const propertyCount = Object.keys(initialContext).length;
|
||||
expect(propertyCount).toBe(16);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Model events', () => {
|
||||
it('should have events object defined', () => {
|
||||
expect(VCMetamodel.events).toBeDefined();
|
||||
expect(typeof VCMetamodel.events).toBe('object');
|
||||
});
|
||||
|
||||
it('should have non-empty events', () => {
|
||||
const eventKeys = Object.keys(VCMetamodel.events);
|
||||
expect(eventKeys.length).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Type validation', () => {
|
||||
const context = VCMetamodel.initialContext;
|
||||
|
||||
it('myVcsMetadata should accept VCMetadata array', () => {
|
||||
expect(() => {
|
||||
const metadata: typeof context.myVcsMetadata = [];
|
||||
expect(Array.isArray(metadata)).toBe(true);
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('myVcs should accept Record<string, VC>', () => {
|
||||
expect(() => {
|
||||
const vcs: typeof context.myVcs = {};
|
||||
expect(typeof vcs).toBe('object');
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('inProgressVcDownloads should be a Set', () => {
|
||||
expect(context.inProgressVcDownloads).toBeInstanceOf(Set);
|
||||
expect(context.inProgressVcDownloads.constructor.name).toBe('Set');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Boolean flags', () => {
|
||||
const context = VCMetamodel.initialContext;
|
||||
|
||||
it('all boolean flags should be false initially', () => {
|
||||
const booleanFlags = [
|
||||
context.areAllVcsDownloaded,
|
||||
context.walletBindingSuccess,
|
||||
context.DownloadingCredentialsFailed,
|
||||
context.DownloadingCredentialsSuccess,
|
||||
];
|
||||
|
||||
booleanFlags.forEach(flag => {
|
||||
expect(flag).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Array properties', () => {
|
||||
const context = VCMetamodel.initialContext;
|
||||
|
||||
it('all array properties should be empty initially', () => {
|
||||
const arrays = [
|
||||
context.myVcsMetadata,
|
||||
context.receivedVcsMetadata,
|
||||
context.tamperedVcs,
|
||||
context.downloadingFailedVcs,
|
||||
];
|
||||
|
||||
arrays.forEach(arr => {
|
||||
expect(Array.isArray(arr)).toBe(true);
|
||||
expect(arr).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Object properties', () => {
|
||||
const context = VCMetamodel.initialContext;
|
||||
|
||||
it('all object properties should be empty initially', () => {
|
||||
const objects = [context.serviceRefs, context.myVcs, context.receivedVcs];
|
||||
|
||||
objects.forEach(obj => {
|
||||
expect(typeof obj).toBe('object');
|
||||
expect(Object.keys(obj)).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Null/undefined properties', () => {
|
||||
const context = VCMetamodel.initialContext;
|
||||
|
||||
it('verificationStatus should be null', () => {
|
||||
expect(context.verificationStatus).toBeNull();
|
||||
expect(context.verificationStatus).not.toBeUndefined();
|
||||
});
|
||||
|
||||
it('verificationErrorMessage should be empty string, not null', () => {
|
||||
expect(context.verificationErrorMessage).not.toBeNull();
|
||||
expect(context.verificationErrorMessage).toBe('');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,510 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import {
|
||||
selectVerificationStatus,
|
||||
selectMyVcsMetadata,
|
||||
selectShareableVcsMetadata,
|
||||
selectShareableVcs,
|
||||
selectReceivedVcsMetadata,
|
||||
selectIsRefreshingMyVcs,
|
||||
selectIsRefreshingReceivedVcs,
|
||||
selectAreAllVcsDownloaded,
|
||||
selectBindedVcsMetadata,
|
||||
selectInProgressVcDownloads,
|
||||
selectWalletBindingSuccess,
|
||||
selectIsTampered,
|
||||
selectDownloadingFailedVcs,
|
||||
selectMyVcs,
|
||||
selectVerificationErrorMessage,
|
||||
selectIsDownloadingFailed,
|
||||
selectIsDownloadingSuccess,
|
||||
} from './VCMetaSelectors';
|
||||
import {VCMetadata} from '../../../shared/VCMetadata';
|
||||
|
||||
describe('VCMetaSelectors', () => {
|
||||
const mockVcMetadata1 = new VCMetadata({
|
||||
id: 'vc1',
|
||||
idType: 'NationalID',
|
||||
issuer: 'Test Issuer 1',
|
||||
});
|
||||
|
||||
const mockVcMetadata2 = new VCMetadata({
|
||||
id: 'vc2',
|
||||
idType: 'Passport',
|
||||
issuer: 'Test Issuer 2',
|
||||
});
|
||||
|
||||
const mockVcMetadata3 = new VCMetadata({
|
||||
id: 'vc3',
|
||||
idType: 'DriversLicense',
|
||||
issuer: 'Test Issuer 3',
|
||||
});
|
||||
|
||||
const mockVc1 = {
|
||||
verifiableCredential: {credential: {id: 'cred1'}},
|
||||
walletBindingResponse: null,
|
||||
};
|
||||
|
||||
const mockVc2 = {
|
||||
verifiableCredential: {credential: {id: 'cred2'}},
|
||||
walletBindingResponse: {walletBindingId: 'binding123'},
|
||||
};
|
||||
|
||||
const mockVc3 = {
|
||||
verifiableCredential: null,
|
||||
walletBindingResponse: null,
|
||||
};
|
||||
|
||||
const mockState: any = {
|
||||
context: {
|
||||
verificationStatus: 'verified',
|
||||
myVcsMetadata: [mockVcMetadata1, mockVcMetadata2, mockVcMetadata3],
|
||||
receivedVcsMetadata: [mockVcMetadata1],
|
||||
myVcs: {
|
||||
[mockVcMetadata1.getVcKey()]: mockVc1,
|
||||
[mockVcMetadata2.getVcKey()]: mockVc2,
|
||||
[mockVcMetadata3.getVcKey()]: mockVc3,
|
||||
},
|
||||
areAllVcsDownloaded: true,
|
||||
inProgressVcDownloads: [],
|
||||
walletBindingSuccess: false,
|
||||
downloadingFailedVcs: [],
|
||||
},
|
||||
matches: jest.fn((stateName: string) => stateName === 'ready.myVcs'),
|
||||
};
|
||||
|
||||
describe('selectVerificationStatus', () => {
|
||||
it('should return verification status from context', () => {
|
||||
const result = selectVerificationStatus(mockState);
|
||||
expect(result).toBe('verified');
|
||||
});
|
||||
|
||||
it('should handle different status values', () => {
|
||||
const statuses = ['verified', 'pending', 'failed', 'invalid'];
|
||||
statuses.forEach(status => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
context: {...mockState.context, verificationStatus: status},
|
||||
};
|
||||
expect(selectVerificationStatus(state)).toBe(status);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectMyVcsMetadata', () => {
|
||||
it('should return all VCs metadata from context', () => {
|
||||
const result = selectMyVcsMetadata(mockState);
|
||||
expect(result).toHaveLength(3);
|
||||
expect(result).toEqual([
|
||||
mockVcMetadata1,
|
||||
mockVcMetadata2,
|
||||
mockVcMetadata3,
|
||||
]);
|
||||
});
|
||||
|
||||
it('should return empty array when no VCs', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
context: {...mockState.context, myVcsMetadata: []},
|
||||
};
|
||||
const result = selectMyVcsMetadata(state);
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectShareableVcsMetadata', () => {
|
||||
it('should filter VCs that have verifiableCredential', () => {
|
||||
const result = selectShareableVcsMetadata(mockState);
|
||||
expect(result).toHaveLength(2);
|
||||
expect(result).toContain(mockVcMetadata1);
|
||||
expect(result).toContain(mockVcMetadata2);
|
||||
expect(result).not.toContain(mockVcMetadata3);
|
||||
});
|
||||
|
||||
it('should return empty array when no shareable VCs', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
context: {
|
||||
...mockState.context,
|
||||
myVcs: {
|
||||
[mockVcMetadata1.getVcKey()]: {verifiableCredential: null},
|
||||
[mockVcMetadata2.getVcKey()]: {verifiableCredential: null},
|
||||
},
|
||||
},
|
||||
};
|
||||
const result = selectShareableVcsMetadata(state);
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectShareableVcs', () => {
|
||||
it('should filter VCs that have verifiableCredential', () => {
|
||||
const result = selectShareableVcs(mockState);
|
||||
expect(result).toHaveLength(2);
|
||||
expect(result).toContainEqual(mockVc1);
|
||||
expect(result).toContainEqual(mockVc2);
|
||||
expect(result).not.toContainEqual(mockVc3);
|
||||
});
|
||||
|
||||
it('should return empty array when no VCs have verifiableCredential', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
context: {
|
||||
...mockState.context,
|
||||
myVcs: {
|
||||
vc1: {verifiableCredential: null},
|
||||
vc2: {verifiableCredential: null},
|
||||
},
|
||||
},
|
||||
};
|
||||
const result = selectShareableVcs(state);
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectReceivedVcsMetadata', () => {
|
||||
it('should return received VCs metadata', () => {
|
||||
const result = selectReceivedVcsMetadata(mockState);
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result).toContain(mockVcMetadata1);
|
||||
});
|
||||
|
||||
it('should return empty array when no received VCs', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
context: {...mockState.context, receivedVcsMetadata: []},
|
||||
};
|
||||
const result = selectReceivedVcsMetadata(state);
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsRefreshingMyVcs', () => {
|
||||
it('should return true when in ready.myVcs state', () => {
|
||||
const result = selectIsRefreshingMyVcs(mockState);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with ready.myVcs', () => {
|
||||
selectIsRefreshingMyVcs(mockState);
|
||||
expect(mockState.matches).toHaveBeenCalledWith('ready.myVcs');
|
||||
});
|
||||
|
||||
it('should return false when not in ready.myVcs state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
const result = selectIsRefreshingMyVcs(state);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsRefreshingReceivedVcs', () => {
|
||||
it('should return true when in ready.receivedVcs state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'ready.receivedVcs'),
|
||||
};
|
||||
const result = selectIsRefreshingReceivedVcs(state);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with ready.receivedVcs', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
selectIsRefreshingReceivedVcs(state);
|
||||
expect(state.matches).toHaveBeenCalledWith('ready.receivedVcs');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectAreAllVcsDownloaded', () => {
|
||||
it('should return true when all VCs are downloaded', () => {
|
||||
const result = selectAreAllVcsDownloaded(mockState);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when not all VCs are downloaded', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
context: {...mockState.context, areAllVcsDownloaded: false},
|
||||
};
|
||||
const result = selectAreAllVcsDownloaded(state);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectBindedVcsMetadata', () => {
|
||||
it('should return VCs with wallet binding', () => {
|
||||
const result = selectBindedVcsMetadata(mockState);
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result).toContain(mockVcMetadata2);
|
||||
expect(result).not.toContain(mockVcMetadata1);
|
||||
expect(result).not.toContain(mockVcMetadata3);
|
||||
});
|
||||
|
||||
it('should filter out VCs with null walletBindingResponse', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
context: {
|
||||
...mockState.context,
|
||||
myVcs: {
|
||||
[mockVcMetadata1.getVcKey()]: {walletBindingResponse: null},
|
||||
[mockVcMetadata2.getVcKey()]: {walletBindingResponse: {}},
|
||||
},
|
||||
},
|
||||
};
|
||||
const result = selectBindedVcsMetadata(state);
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
it('should filter out VCs with empty walletBindingId', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
context: {
|
||||
...mockState.context,
|
||||
myVcs: {
|
||||
[mockVcMetadata1.getVcKey()]: {
|
||||
walletBindingResponse: {walletBindingId: ''},
|
||||
},
|
||||
[mockVcMetadata2.getVcKey()]: {
|
||||
walletBindingResponse: {walletBindingId: null},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const result = selectBindedVcsMetadata(state);
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
it('should return empty array when no binded VCs', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
context: {
|
||||
...mockState.context,
|
||||
myVcs: {
|
||||
[mockVcMetadata1.getVcKey()]: {walletBindingResponse: null},
|
||||
},
|
||||
},
|
||||
};
|
||||
const result = selectBindedVcsMetadata(state);
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectInProgressVcDownloads', () => {
|
||||
it('should return in-progress VC downloads', () => {
|
||||
const downloads = ['vc1', 'vc2'];
|
||||
const state: any = {
|
||||
...mockState,
|
||||
context: {...mockState.context, inProgressVcDownloads: downloads},
|
||||
};
|
||||
const result = selectInProgressVcDownloads(state);
|
||||
expect(result).toEqual(downloads);
|
||||
});
|
||||
|
||||
it('should return empty array when no downloads in progress', () => {
|
||||
const result = selectInProgressVcDownloads(mockState);
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectWalletBindingSuccess', () => {
|
||||
it('should return wallet binding success status', () => {
|
||||
const result = selectWalletBindingSuccess(mockState);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true when wallet binding is successful', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
context: {...mockState.context, walletBindingSuccess: true},
|
||||
};
|
||||
const result = selectWalletBindingSuccess(state);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsTampered', () => {
|
||||
it('should return true when in ready.tamperedVCs state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'ready.tamperedVCs'),
|
||||
};
|
||||
const result = selectIsTampered(state);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with ready.tamperedVCs', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
selectIsTampered(state);
|
||||
expect(state.matches).toHaveBeenCalledWith('ready.tamperedVCs');
|
||||
});
|
||||
|
||||
it('should return false when not in tampered state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
const result = selectIsTampered(state);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectDownloadingFailedVcs', () => {
|
||||
it('should return downloading failed VCs', () => {
|
||||
const failedVcs = ['vc1', 'vc2'];
|
||||
const state: any = {
|
||||
...mockState,
|
||||
context: {...mockState.context, downloadingFailedVcs: failedVcs},
|
||||
};
|
||||
const result = selectDownloadingFailedVcs(state);
|
||||
expect(result).toEqual(failedVcs);
|
||||
});
|
||||
|
||||
it('should return empty array when no failed VCs', () => {
|
||||
const result = selectDownloadingFailedVcs(mockState);
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectMyVcs', () => {
|
||||
it('should return all my VCs object', () => {
|
||||
const result = selectMyVcs(mockState);
|
||||
expect(result).toEqual(mockState.context.myVcs);
|
||||
});
|
||||
|
||||
it('should return object with VC keys', () => {
|
||||
const result = selectMyVcs(mockState);
|
||||
expect(result).toHaveProperty(mockVcMetadata1.getVcKey());
|
||||
expect(result).toHaveProperty(mockVcMetadata2.getVcKey());
|
||||
});
|
||||
|
||||
it('should return empty object when no VCs', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
context: {...mockState.context, myVcs: {}},
|
||||
};
|
||||
const result = selectMyVcs(state);
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Edge cases and boundary conditions', () => {
|
||||
it('should handle undefined values in walletBindingResponse', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
context: {
|
||||
...mockState.context,
|
||||
myVcs: {
|
||||
[mockVcMetadata1.getVcKey()]: {
|
||||
walletBindingResponse: undefined,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const result = selectBindedVcsMetadata(state);
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
it('should handle empty string in walletBindingId', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
context: {
|
||||
...mockState.context,
|
||||
myVcs: {
|
||||
[mockVcMetadata1.getVcKey()]: {
|
||||
walletBindingResponse: {walletBindingId: ''},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const result = selectBindedVcsMetadata(state);
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
it('should handle null verifiableCredential in filtering', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
context: {
|
||||
...mockState.context,
|
||||
myVcs: {
|
||||
[mockVcMetadata1.getVcKey()]: {verifiableCredential: null},
|
||||
},
|
||||
},
|
||||
};
|
||||
const result = selectShareableVcsMetadata(state);
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectVerificationErrorMessage', () => {
|
||||
it('should return verification error message from context', () => {
|
||||
const state: any = {
|
||||
context: {
|
||||
verificationErrorMessage: 'Invalid signature',
|
||||
},
|
||||
};
|
||||
const result = selectVerificationErrorMessage(state);
|
||||
expect(result).toBe('Invalid signature');
|
||||
});
|
||||
|
||||
it('should return empty string when no error', () => {
|
||||
const state: any = {
|
||||
context: {
|
||||
verificationErrorMessage: '',
|
||||
},
|
||||
};
|
||||
const result = selectVerificationErrorMessage(state);
|
||||
expect(result).toBe('');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsDownloadingFailed', () => {
|
||||
it('should return DownloadingCredentialsFailed status', () => {
|
||||
const state: any = {
|
||||
context: {
|
||||
DownloadingCredentialsFailed: true,
|
||||
},
|
||||
};
|
||||
const result = selectIsDownloadingFailed(state);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when downloading not failed', () => {
|
||||
const state: any = {
|
||||
context: {
|
||||
DownloadingCredentialsFailed: false,
|
||||
},
|
||||
};
|
||||
const result = selectIsDownloadingFailed(state);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsDownloadingSuccess', () => {
|
||||
it('should return DownloadingCredentialsSuccess status', () => {
|
||||
const state: any = {
|
||||
context: {
|
||||
DownloadingCredentialsSuccess: true,
|
||||
},
|
||||
};
|
||||
const result = selectIsDownloadingSuccess(state);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when downloading not successful', () => {
|
||||
const state: any = {
|
||||
context: {
|
||||
DownloadingCredentialsSuccess: false,
|
||||
},
|
||||
};
|
||||
const result = selectIsDownloadingSuccess(state);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
151
machines/backupAndRestore/backup/backupModel.test.ts
Normal file
151
machines/backupAndRestore/backup/backupModel.test.ts
Normal file
@@ -0,0 +1,151 @@
|
||||
import {backupModel} from './backupModel';
|
||||
|
||||
describe('backupModel', () => {
|
||||
describe('Model structure', () => {
|
||||
it('should be defined', () => {
|
||||
expect(backupModel).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have initialContext', () => {
|
||||
expect(backupModel.initialContext).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have events', () => {
|
||||
expect(backupModel.events).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Initial Context', () => {
|
||||
const initialContext = backupModel.initialContext;
|
||||
|
||||
it('should have serviceRefs as empty object', () => {
|
||||
expect(initialContext.serviceRefs).toEqual({});
|
||||
expect(typeof initialContext.serviceRefs).toBe('object');
|
||||
});
|
||||
|
||||
it('should have dataFromStorage as empty object', () => {
|
||||
expect(initialContext.dataFromStorage).toEqual({});
|
||||
expect(typeof initialContext.dataFromStorage).toBe('object');
|
||||
});
|
||||
|
||||
it('should have fileName as empty string', () => {
|
||||
expect(initialContext.fileName).toBe('');
|
||||
expect(typeof initialContext.fileName).toBe('string');
|
||||
});
|
||||
|
||||
it('should have lastBackupDetails as null', () => {
|
||||
expect(initialContext.lastBackupDetails).toBeNull();
|
||||
});
|
||||
|
||||
it('should have errorReason as empty string', () => {
|
||||
expect(initialContext.errorReason).toBe('');
|
||||
expect(typeof initialContext.errorReason).toBe('string');
|
||||
});
|
||||
|
||||
it('should have isAutoBackUp as true', () => {
|
||||
expect(initialContext.isAutoBackUp).toBe(true);
|
||||
expect(typeof initialContext.isAutoBackUp).toBe('boolean');
|
||||
});
|
||||
|
||||
it('should have isLoadingBackupDetails as true', () => {
|
||||
expect(initialContext.isLoadingBackupDetails).toBe(true);
|
||||
expect(typeof initialContext.isLoadingBackupDetails).toBe('boolean');
|
||||
});
|
||||
|
||||
it('should have showBackupInProgress as false', () => {
|
||||
expect(initialContext.showBackupInProgress).toBe(false);
|
||||
expect(typeof initialContext.showBackupInProgress).toBe('boolean');
|
||||
});
|
||||
|
||||
it('should have all 8 required properties', () => {
|
||||
const properties = Object.keys(initialContext);
|
||||
expect(properties).toHaveLength(8);
|
||||
});
|
||||
});
|
||||
|
||||
describe('String properties', () => {
|
||||
const context = backupModel.initialContext;
|
||||
|
||||
it('all empty string properties should be empty', () => {
|
||||
const emptyStrings = [context.fileName, context.errorReason];
|
||||
|
||||
emptyStrings.forEach(str => {
|
||||
expect(str).toBe('');
|
||||
expect(typeof str).toBe('string');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Object properties', () => {
|
||||
const context = backupModel.initialContext;
|
||||
|
||||
it('all empty object properties should be empty objects', () => {
|
||||
const emptyObjects = [context.serviceRefs, context.dataFromStorage];
|
||||
|
||||
emptyObjects.forEach(obj => {
|
||||
expect(typeof obj).toBe('object');
|
||||
expect(Object.keys(obj)).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Boolean properties', () => {
|
||||
const context = backupModel.initialContext;
|
||||
|
||||
it('isAutoBackUp should be true', () => {
|
||||
expect(context.isAutoBackUp).toBe(true);
|
||||
expect(typeof context.isAutoBackUp).toBe('boolean');
|
||||
});
|
||||
|
||||
it('isLoadingBackupDetails should be true', () => {
|
||||
expect(context.isLoadingBackupDetails).toBe(true);
|
||||
expect(typeof context.isLoadingBackupDetails).toBe('boolean');
|
||||
});
|
||||
|
||||
it('showBackupInProgress should be false', () => {
|
||||
expect(context.showBackupInProgress).toBe(false);
|
||||
expect(typeof context.showBackupInProgress).toBe('boolean');
|
||||
});
|
||||
|
||||
it('should have correct initial values for boolean properties', () => {
|
||||
expect(context.isAutoBackUp).toBe(true);
|
||||
expect(context.isLoadingBackupDetails).toBe(true);
|
||||
expect(context.showBackupInProgress).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Null properties', () => {
|
||||
const context = backupModel.initialContext;
|
||||
|
||||
it('lastBackupDetails should be null', () => {
|
||||
expect(context.lastBackupDetails).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Model events', () => {
|
||||
it('should have events object', () => {
|
||||
expect(backupModel.events).toBeDefined();
|
||||
expect(typeof backupModel.events).toBe('object');
|
||||
});
|
||||
|
||||
it('should have event creators', () => {
|
||||
const eventKeys = Object.keys(backupModel.events);
|
||||
expect(eventKeys.length).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Property types validation', () => {
|
||||
const context = backupModel.initialContext;
|
||||
|
||||
it('should have correct types for all properties', () => {
|
||||
expect(typeof context.serviceRefs).toBe('object');
|
||||
expect(typeof context.dataFromStorage).toBe('object');
|
||||
expect(typeof context.fileName).toBe('string');
|
||||
expect(context.lastBackupDetails).toBeNull();
|
||||
expect(typeof context.errorReason).toBe('string');
|
||||
expect(typeof context.isAutoBackUp).toBe('boolean');
|
||||
expect(typeof context.isLoadingBackupDetails).toBe('boolean');
|
||||
expect(typeof context.showBackupInProgress).toBe('boolean');
|
||||
});
|
||||
});
|
||||
});
|
||||
214
machines/backupAndRestore/backup/backupSelector.test.ts
Normal file
214
machines/backupAndRestore/backup/backupSelector.test.ts
Normal file
@@ -0,0 +1,214 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import {
|
||||
selectIsBackupInprogress,
|
||||
selectIsLoadingBackupDetails,
|
||||
selectIsBackingUpSuccess,
|
||||
selectIsBackingUpFailure,
|
||||
selectIsNetworkError,
|
||||
lastBackupDetails,
|
||||
selectBackupErrorReason,
|
||||
selectShowBackupInProgress,
|
||||
} from './backupSelector';
|
||||
|
||||
describe('backupSelector', () => {
|
||||
describe('selectIsBackupInprogress', () => {
|
||||
it('should return true when in checkDataAvailabilityForBackup state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(
|
||||
(state: string) =>
|
||||
state === 'backingUp.checkDataAvailabilityForBackup',
|
||||
),
|
||||
};
|
||||
expect(selectIsBackupInprogress(mockState)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true when in checkStorageAvailability state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(
|
||||
(state: string) => state === 'backingUp.checkStorageAvailability',
|
||||
),
|
||||
};
|
||||
expect(selectIsBackupInprogress(mockState)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true when in fetchDataFromDB state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(
|
||||
(state: string) => state === 'backingUp.fetchDataFromDB',
|
||||
),
|
||||
};
|
||||
expect(selectIsBackupInprogress(mockState)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true when in writeDataToFile state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(
|
||||
(state: string) => state === 'backingUp.writeDataToFile',
|
||||
),
|
||||
};
|
||||
expect(selectIsBackupInprogress(mockState)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true when in zipBackupFile state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(
|
||||
(state: string) => state === 'backingUp.zipBackupFile',
|
||||
),
|
||||
};
|
||||
expect(selectIsBackupInprogress(mockState)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true when in uploadBackupFile state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(
|
||||
(state: string) => state === 'backingUp.uploadBackupFile',
|
||||
),
|
||||
};
|
||||
expect(selectIsBackupInprogress(mockState)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when not in any backup progress state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
expect(selectIsBackupInprogress(mockState)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsLoadingBackupDetails', () => {
|
||||
it('should return isLoadingBackupDetails from context', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
isLoadingBackupDetails: true,
|
||||
},
|
||||
};
|
||||
expect(selectIsLoadingBackupDetails(mockState)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when isLoadingBackupDetails is false', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
isLoadingBackupDetails: false,
|
||||
},
|
||||
};
|
||||
expect(selectIsLoadingBackupDetails(mockState)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsBackingUpSuccess', () => {
|
||||
it('should return true when in backingUp.success state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn((state: string) => state === 'backingUp.success'),
|
||||
};
|
||||
expect(selectIsBackingUpSuccess(mockState)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when not in success state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
expect(selectIsBackingUpSuccess(mockState)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsBackingUpFailure', () => {
|
||||
it('should return true when in backingUp.failure state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn((state: string) => state === 'backingUp.failure'),
|
||||
};
|
||||
expect(selectIsBackingUpFailure(mockState)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when not in failure state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
expect(selectIsBackingUpFailure(mockState)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsNetworkError', () => {
|
||||
it('should return true when in fetchLastBackupDetails.noInternet state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(
|
||||
(state: string) => state === 'fetchLastBackupDetails.noInternet',
|
||||
),
|
||||
};
|
||||
expect(selectIsNetworkError(mockState)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when not in network error state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
expect(selectIsNetworkError(mockState)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('lastBackupDetails', () => {
|
||||
it('should return lastBackupDetails from context', () => {
|
||||
const mockDetails = {
|
||||
timestamp: '2024-01-01',
|
||||
size: '10MB',
|
||||
fileName: 'backup_123.zip',
|
||||
};
|
||||
const mockState: any = {
|
||||
context: {
|
||||
lastBackupDetails: mockDetails,
|
||||
},
|
||||
};
|
||||
expect(lastBackupDetails(mockState)).toBe(mockDetails);
|
||||
});
|
||||
|
||||
it('should return undefined when lastBackupDetails is not set', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
lastBackupDetails: undefined,
|
||||
},
|
||||
};
|
||||
expect(lastBackupDetails(mockState)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectBackupErrorReason', () => {
|
||||
it('should return errorReason from context', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
errorReason: 'Insufficient storage space',
|
||||
},
|
||||
};
|
||||
expect(selectBackupErrorReason(mockState)).toBe(
|
||||
'Insufficient storage space',
|
||||
);
|
||||
});
|
||||
|
||||
it('should return null when no error', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
errorReason: null,
|
||||
},
|
||||
};
|
||||
expect(selectBackupErrorReason(mockState)).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectShowBackupInProgress', () => {
|
||||
it('should return showBackupInProgress from context', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
showBackupInProgress: true,
|
||||
},
|
||||
};
|
||||
expect(selectShowBackupInProgress(mockState)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when showBackupInProgress is false', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
showBackupInProgress: false,
|
||||
},
|
||||
};
|
||||
expect(selectShowBackupInProgress(mockState)).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,138 @@
|
||||
import {backupAndRestoreSetupModel} from './backupAndRestoreSetupModel';
|
||||
|
||||
describe('backupAndRestoreSetupModel', () => {
|
||||
describe('Model structure', () => {
|
||||
it('should be defined', () => {
|
||||
expect(backupAndRestoreSetupModel).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have initialContext', () => {
|
||||
expect(backupAndRestoreSetupModel.initialContext).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have events', () => {
|
||||
expect(backupAndRestoreSetupModel.events).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Initial Context', () => {
|
||||
const initialContext = backupAndRestoreSetupModel.initialContext;
|
||||
|
||||
it('should have isLoading as false', () => {
|
||||
expect(initialContext.isLoading).toBe(false);
|
||||
expect(typeof initialContext.isLoading).toBe('boolean');
|
||||
});
|
||||
|
||||
it('should have profileInfo as undefined', () => {
|
||||
expect(initialContext.profileInfo).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should have errorMessage as empty string', () => {
|
||||
expect(initialContext.errorMessage).toBe('');
|
||||
expect(typeof initialContext.errorMessage).toBe('string');
|
||||
});
|
||||
|
||||
it('should have serviceRefs as empty object', () => {
|
||||
expect(initialContext.serviceRefs).toEqual({});
|
||||
expect(typeof initialContext.serviceRefs).toBe('object');
|
||||
});
|
||||
|
||||
it('should have shouldTriggerAutoBackup as false', () => {
|
||||
expect(initialContext.shouldTriggerAutoBackup).toBe(false);
|
||||
expect(typeof initialContext.shouldTriggerAutoBackup).toBe('boolean');
|
||||
});
|
||||
|
||||
it('should have isCloudSignedIn as false', () => {
|
||||
expect(initialContext.isCloudSignedIn).toBe(false);
|
||||
expect(typeof initialContext.isCloudSignedIn).toBe('boolean');
|
||||
});
|
||||
|
||||
it('should have all 6 required properties', () => {
|
||||
const properties = Object.keys(initialContext);
|
||||
expect(properties).toHaveLength(6);
|
||||
});
|
||||
});
|
||||
|
||||
describe('String properties', () => {
|
||||
const context = backupAndRestoreSetupModel.initialContext;
|
||||
|
||||
it('errorMessage should be empty', () => {
|
||||
expect(context.errorMessage).toBe('');
|
||||
expect(typeof context.errorMessage).toBe('string');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Object properties', () => {
|
||||
const context = backupAndRestoreSetupModel.initialContext;
|
||||
|
||||
it('serviceRefs should be empty object', () => {
|
||||
expect(typeof context.serviceRefs).toBe('object');
|
||||
expect(Object.keys(context.serviceRefs)).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Boolean properties', () => {
|
||||
const context = backupAndRestoreSetupModel.initialContext;
|
||||
|
||||
it('isLoading should be false', () => {
|
||||
expect(context.isLoading).toBe(false);
|
||||
expect(typeof context.isLoading).toBe('boolean');
|
||||
});
|
||||
|
||||
it('shouldTriggerAutoBackup should be false', () => {
|
||||
expect(context.shouldTriggerAutoBackup).toBe(false);
|
||||
expect(typeof context.shouldTriggerAutoBackup).toBe('boolean');
|
||||
});
|
||||
|
||||
it('isCloudSignedIn should be false', () => {
|
||||
expect(context.isCloudSignedIn).toBe(false);
|
||||
expect(typeof context.isCloudSignedIn).toBe('boolean');
|
||||
});
|
||||
|
||||
it('should have correct initial values for boolean properties', () => {
|
||||
const falseProps = [
|
||||
context.isLoading,
|
||||
context.shouldTriggerAutoBackup,
|
||||
context.isCloudSignedIn,
|
||||
];
|
||||
|
||||
falseProps.forEach(prop => {
|
||||
expect(prop).toBe(false);
|
||||
expect(typeof prop).toBe('boolean');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Undefined properties', () => {
|
||||
const context = backupAndRestoreSetupModel.initialContext;
|
||||
|
||||
it('profileInfo should be undefined', () => {
|
||||
expect(context.profileInfo).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Model events', () => {
|
||||
it('should have events object', () => {
|
||||
expect(backupAndRestoreSetupModel.events).toBeDefined();
|
||||
expect(typeof backupAndRestoreSetupModel.events).toBe('object');
|
||||
});
|
||||
|
||||
it('should have event creators', () => {
|
||||
const eventKeys = Object.keys(backupAndRestoreSetupModel.events);
|
||||
expect(eventKeys.length).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Property types validation', () => {
|
||||
const context = backupAndRestoreSetupModel.initialContext;
|
||||
|
||||
it('should have correct types for all properties', () => {
|
||||
expect(typeof context.isLoading).toBe('boolean');
|
||||
expect(context.profileInfo).toBeUndefined();
|
||||
expect(typeof context.errorMessage).toBe('string');
|
||||
expect(typeof context.serviceRefs).toBe('object');
|
||||
expect(typeof context.shouldTriggerAutoBackup).toBe('boolean');
|
||||
expect(typeof context.isCloudSignedIn).toBe('boolean');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,289 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import {
|
||||
selectIsLoading,
|
||||
selectProfileInfo,
|
||||
selectIsNetworkError,
|
||||
selectShouldTriggerAutoBackup,
|
||||
selectShowAccountSelectionConfirmation,
|
||||
selectIsSigningIn,
|
||||
selectIsSigningInSuccessful,
|
||||
selectIsSigningFailure,
|
||||
selectIsCloudSignedInFailed,
|
||||
} from './backupAndRestoreSetupSelectors';
|
||||
|
||||
describe('backupAndRestoreSetupSelectors', () => {
|
||||
const mockProfileInfo = {
|
||||
email: 'test@example.com',
|
||||
name: 'Test User',
|
||||
id: 'user123',
|
||||
};
|
||||
|
||||
const mockState: any = {
|
||||
context: {
|
||||
isLoading: false,
|
||||
profileInfo: mockProfileInfo,
|
||||
shouldTriggerAutoBackup: true,
|
||||
},
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
|
||||
describe('selectIsLoading', () => {
|
||||
it('should return loading status from context', () => {
|
||||
const result = selectIsLoading(mockState);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true when loading', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
context: {...mockState.context, isLoading: true},
|
||||
};
|
||||
const result = selectIsLoading(state);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectProfileInfo', () => {
|
||||
it('should return profile info from context', () => {
|
||||
const result = selectProfileInfo(mockState);
|
||||
expect(result).toEqual(mockProfileInfo);
|
||||
});
|
||||
|
||||
it('should return profile with all properties', () => {
|
||||
const result = selectProfileInfo(mockState);
|
||||
expect(result).toHaveProperty('email');
|
||||
expect(result).toHaveProperty('name');
|
||||
expect(result).toHaveProperty('id');
|
||||
});
|
||||
|
||||
it('should handle null profile info', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
context: {...mockState.context, profileInfo: null},
|
||||
};
|
||||
const result = selectProfileInfo(state);
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsNetworkError', () => {
|
||||
it('should return true when in init.noInternet state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'init.noInternet'),
|
||||
};
|
||||
const result = selectIsNetworkError(state);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true when in checkSignIn.noInternet state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'checkSignIn.noInternet'),
|
||||
};
|
||||
const result = selectIsNetworkError(state);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true when in signIn.noInternet state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'signIn.noInternet'),
|
||||
};
|
||||
const result = selectIsNetworkError(state);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when not in any noInternet state', () => {
|
||||
const result = selectIsNetworkError(mockState);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should call matches with all three network error states', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
selectIsNetworkError(state);
|
||||
expect(state.matches).toHaveBeenCalledWith('init.noInternet');
|
||||
expect(state.matches).toHaveBeenCalledWith('checkSignIn.noInternet');
|
||||
expect(state.matches).toHaveBeenCalledWith('signIn.noInternet');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectShouldTriggerAutoBackup', () => {
|
||||
it('should return auto backup trigger flag', () => {
|
||||
const result = selectShouldTriggerAutoBackup(mockState);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when auto backup should not trigger', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
context: {...mockState.context, shouldTriggerAutoBackup: false},
|
||||
};
|
||||
const result = selectShouldTriggerAutoBackup(state);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectShowAccountSelectionConfirmation', () => {
|
||||
it('should return true when in selectCloudAccount state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'selectCloudAccount'),
|
||||
};
|
||||
const result = selectShowAccountSelectionConfirmation(state);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with selectCloudAccount', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
selectShowAccountSelectionConfirmation(state);
|
||||
expect(state.matches).toHaveBeenCalledWith('selectCloudAccount');
|
||||
});
|
||||
|
||||
it('should return false when not in selectCloudAccount state', () => {
|
||||
const result = selectShowAccountSelectionConfirmation(mockState);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsSigningIn', () => {
|
||||
it('should return true when in signIn state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'signIn'),
|
||||
};
|
||||
const result = selectIsSigningIn(state);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with signIn', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
selectIsSigningIn(state);
|
||||
expect(state.matches).toHaveBeenCalledWith('signIn');
|
||||
});
|
||||
|
||||
it('should return false when not signing in', () => {
|
||||
const result = selectIsSigningIn(mockState);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsSigningInSuccessful', () => {
|
||||
it('should return true when in backupAndRestore state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'backupAndRestore'),
|
||||
};
|
||||
const result = selectIsSigningInSuccessful(state);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with backupAndRestore', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
selectIsSigningInSuccessful(state);
|
||||
expect(state.matches).toHaveBeenCalledWith('backupAndRestore');
|
||||
});
|
||||
|
||||
it('should return false when sign in not successful', () => {
|
||||
const result = selectIsSigningInSuccessful(mockState);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsSigningFailure', () => {
|
||||
it('should return true when in signIn.error state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'signIn.error'),
|
||||
};
|
||||
const result = selectIsSigningFailure(state);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true when in checkSignIn.error state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'checkSignIn.error'),
|
||||
};
|
||||
const result = selectIsSigningFailure(state);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when not in error state', () => {
|
||||
const result = selectIsSigningFailure(mockState);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should call matches with both error states', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
selectIsSigningFailure(state);
|
||||
expect(state.matches).toHaveBeenCalledWith('signIn.error');
|
||||
expect(state.matches).toHaveBeenCalledWith('checkSignIn.error');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsCloudSignedInFailed', () => {
|
||||
it('should return true when in checkSignIn.error state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'checkSignIn.error'),
|
||||
};
|
||||
const result = selectIsCloudSignedInFailed(state);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with checkSignIn.error', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
selectIsCloudSignedInFailed(state);
|
||||
expect(state.matches).toHaveBeenCalledWith('checkSignIn.error');
|
||||
});
|
||||
|
||||
it('should return false when cloud sign in did not fail', () => {
|
||||
const result = selectIsCloudSignedInFailed(mockState);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Edge cases', () => {
|
||||
it('should handle empty profile info', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
context: {...mockState.context, profileInfo: {}},
|
||||
};
|
||||
const result = selectProfileInfo(state);
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
|
||||
it('should handle undefined values', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
context: {
|
||||
isLoading: undefined,
|
||||
profileInfo: undefined,
|
||||
shouldTriggerAutoBackup: undefined,
|
||||
},
|
||||
};
|
||||
expect(selectIsLoading(state)).toBeUndefined();
|
||||
expect(selectProfileInfo(state)).toBeUndefined();
|
||||
expect(selectShouldTriggerAutoBackup(state)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
114
machines/backupAndRestore/restore/restoreModel.test.ts
Normal file
114
machines/backupAndRestore/restore/restoreModel.test.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
import {restoreModel} from './restoreModel';
|
||||
|
||||
describe('restoreModel', () => {
|
||||
describe('Model structure', () => {
|
||||
it('should be defined', () => {
|
||||
expect(restoreModel).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have initialContext', () => {
|
||||
expect(restoreModel.initialContext).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have events', () => {
|
||||
expect(restoreModel.events).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Initial Context', () => {
|
||||
const initialContext = restoreModel.initialContext;
|
||||
|
||||
it('should have serviceRefs as empty object', () => {
|
||||
expect(initialContext.serviceRefs).toEqual({});
|
||||
expect(typeof initialContext.serviceRefs).toBe('object');
|
||||
});
|
||||
|
||||
it('should have fileName as empty string', () => {
|
||||
expect(initialContext.fileName).toBe('');
|
||||
expect(typeof initialContext.fileName).toBe('string');
|
||||
});
|
||||
|
||||
it('should have dataFromBackupFile as empty object', () => {
|
||||
expect(initialContext.dataFromBackupFile).toEqual({});
|
||||
expect(typeof initialContext.dataFromBackupFile).toBe('object');
|
||||
});
|
||||
|
||||
it('should have errorReason as empty string', () => {
|
||||
expect(initialContext.errorReason).toBe('');
|
||||
expect(typeof initialContext.errorReason).toBe('string');
|
||||
});
|
||||
|
||||
it('should have showRestoreInProgress as false', () => {
|
||||
expect(initialContext.showRestoreInProgress).toBe(false);
|
||||
expect(typeof initialContext.showRestoreInProgress).toBe('boolean');
|
||||
});
|
||||
|
||||
it('should have all 5 required properties', () => {
|
||||
const properties = Object.keys(initialContext);
|
||||
expect(properties).toHaveLength(5);
|
||||
});
|
||||
});
|
||||
|
||||
describe('String properties', () => {
|
||||
const context = restoreModel.initialContext;
|
||||
|
||||
it('all empty string properties should be empty', () => {
|
||||
const emptyStrings = [context.fileName, context.errorReason];
|
||||
|
||||
emptyStrings.forEach(str => {
|
||||
expect(str).toBe('');
|
||||
expect(typeof str).toBe('string');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Object properties', () => {
|
||||
const context = restoreModel.initialContext;
|
||||
|
||||
it('all empty object properties should be empty objects', () => {
|
||||
const emptyObjects = [context.serviceRefs, context.dataFromBackupFile];
|
||||
|
||||
emptyObjects.forEach(obj => {
|
||||
expect(typeof obj).toBe('object');
|
||||
expect(Object.keys(obj)).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Boolean properties', () => {
|
||||
const context = restoreModel.initialContext;
|
||||
|
||||
it('showRestoreInProgress should be false', () => {
|
||||
expect(context.showRestoreInProgress).toBe(false);
|
||||
expect(typeof context.showRestoreInProgress).toBe('boolean');
|
||||
});
|
||||
|
||||
it('should have correct initial values for boolean properties', () => {
|
||||
expect(context.showRestoreInProgress).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Model events', () => {
|
||||
it('should have events object', () => {
|
||||
expect(restoreModel.events).toBeDefined();
|
||||
expect(typeof restoreModel.events).toBe('object');
|
||||
});
|
||||
|
||||
it('should have event creators', () => {
|
||||
const eventKeys = Object.keys(restoreModel.events);
|
||||
expect(eventKeys.length).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Property types validation', () => {
|
||||
const context = restoreModel.initialContext;
|
||||
|
||||
it('should have correct types for all properties', () => {
|
||||
expect(typeof context.serviceRefs).toBe('object');
|
||||
expect(typeof context.fileName).toBe('string');
|
||||
expect(typeof context.dataFromBackupFile).toBe('object');
|
||||
expect(typeof context.errorReason).toBe('string');
|
||||
expect(typeof context.showRestoreInProgress).toBe('boolean');
|
||||
});
|
||||
});
|
||||
});
|
||||
125
machines/backupAndRestore/restore/restoreSelector.test.ts
Normal file
125
machines/backupAndRestore/restore/restoreSelector.test.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import {
|
||||
selectErrorReason,
|
||||
selectIsBackUpRestoring,
|
||||
selectIsBackUpRestoreSuccess,
|
||||
selectIsBackUpRestoreFailure,
|
||||
selectShowRestoreInProgress,
|
||||
} from './restoreSelector';
|
||||
|
||||
describe('restoreSelector', () => {
|
||||
describe('selectErrorReason', () => {
|
||||
it('should return errorReason from context', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
errorReason: 'Failed to restore backup',
|
||||
},
|
||||
};
|
||||
expect(selectErrorReason(mockState)).toBe('Failed to restore backup');
|
||||
});
|
||||
|
||||
it('should return null when no error', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
errorReason: null,
|
||||
},
|
||||
};
|
||||
expect(selectErrorReason(mockState)).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsBackUpRestoring', () => {
|
||||
it('should return true when in restoreBackup state but not success or failure', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn((state: string) => {
|
||||
if (state === 'restoreBackup') return true;
|
||||
if (state === 'restoreBackup.success') return false;
|
||||
if (state === 'restoreBackup.failure') return false;
|
||||
return false;
|
||||
}),
|
||||
};
|
||||
expect(selectIsBackUpRestoring(mockState)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when in restoreBackup.success state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn((state: string) => {
|
||||
if (state === 'restoreBackup') return true;
|
||||
if (state === 'restoreBackup.success') return true;
|
||||
return false;
|
||||
}),
|
||||
};
|
||||
expect(selectIsBackUpRestoring(mockState)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false when in restoreBackup.failure state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn((state: string) => {
|
||||
if (state === 'restoreBackup') return true;
|
||||
if (state === 'restoreBackup.failure') return true;
|
||||
return false;
|
||||
}),
|
||||
};
|
||||
expect(selectIsBackUpRestoring(mockState)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false when not in restoreBackup state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
expect(selectIsBackUpRestoring(mockState)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsBackUpRestoreSuccess', () => {
|
||||
it('should return true when in restoreBackup.success state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn((state: string) => state === 'restoreBackup.success'),
|
||||
};
|
||||
expect(selectIsBackUpRestoreSuccess(mockState)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when not in success state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
expect(selectIsBackUpRestoreSuccess(mockState)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsBackUpRestoreFailure', () => {
|
||||
it('should return true when in restoreBackup.failure state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn((state: string) => state === 'restoreBackup.failure'),
|
||||
};
|
||||
expect(selectIsBackUpRestoreFailure(mockState)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when not in failure state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
expect(selectIsBackUpRestoreFailure(mockState)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectShowRestoreInProgress', () => {
|
||||
it('should return showRestoreInProgress from context', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
showRestoreInProgress: true,
|
||||
},
|
||||
};
|
||||
expect(selectShowRestoreInProgress(mockState)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when showRestoreInProgress is false', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
showRestoreInProgress: false,
|
||||
},
|
||||
};
|
||||
expect(selectShowRestoreInProgress(mockState)).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
298
machines/bleShare/commonSelectors.test.ts
Normal file
298
machines/bleShare/commonSelectors.test.ts
Normal file
@@ -0,0 +1,298 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import {
|
||||
selectIsCancelling,
|
||||
selectIsReviewing,
|
||||
selectIsAccepted,
|
||||
selectIsRejected,
|
||||
selectIsVerifyingIdentity,
|
||||
selectIsInvalidIdentity,
|
||||
selectIsDisconnected,
|
||||
selectIsBluetoothDenied,
|
||||
selectBleError,
|
||||
selectIsExchangingDeviceInfo,
|
||||
selectIsExchangingDeviceInfoTimeout,
|
||||
selectIsOffline,
|
||||
selectIsHandlingBleError,
|
||||
selectReadyForBluetoothStateCheck,
|
||||
selectIsNearByDevicesPermissionDenied,
|
||||
selectIsBluetoothPermissionDenied,
|
||||
selectIsStartPermissionCheck,
|
||||
selectIsLocationPermissionRationale,
|
||||
} from './commonSelectors';
|
||||
|
||||
describe('commonSelectors', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
bleError: null,
|
||||
readyForBluetoothStateCheck: false,
|
||||
},
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
|
||||
describe('selectIsCancelling', () => {
|
||||
it('should return true when in cancelling state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'cancelling'),
|
||||
};
|
||||
expect(selectIsCancelling(state)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when not cancelling', () => {
|
||||
expect(selectIsCancelling(mockState)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsReviewing', () => {
|
||||
it('should return true when in reviewing state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'reviewing'),
|
||||
};
|
||||
expect(selectIsReviewing(state)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when not reviewing', () => {
|
||||
expect(selectIsReviewing(mockState)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsAccepted', () => {
|
||||
it('should return true when in reviewing.accepted state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'reviewing.accepted'),
|
||||
};
|
||||
expect(selectIsAccepted(state)).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with reviewing.accepted', () => {
|
||||
selectIsAccepted(mockState);
|
||||
expect(mockState.matches).toHaveBeenCalledWith('reviewing.accepted');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsRejected', () => {
|
||||
it('should return true when in reviewing.rejected state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'reviewing.rejected'),
|
||||
};
|
||||
expect(selectIsRejected(state)).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with reviewing.rejected', () => {
|
||||
selectIsRejected(mockState);
|
||||
expect(mockState.matches).toHaveBeenCalledWith('reviewing.rejected');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsVerifyingIdentity', () => {
|
||||
it('should return true when in reviewing.verifyingIdentity state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'reviewing.verifyingIdentity'),
|
||||
};
|
||||
expect(selectIsVerifyingIdentity(state)).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with reviewing.verifyingIdentity', () => {
|
||||
selectIsVerifyingIdentity(mockState);
|
||||
expect(mockState.matches).toHaveBeenCalledWith(
|
||||
'reviewing.verifyingIdentity',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsInvalidIdentity', () => {
|
||||
it('should return true when in reviewing.invalidIdentity state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'reviewing.invalidIdentity'),
|
||||
};
|
||||
expect(selectIsInvalidIdentity(state)).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with reviewing.invalidIdentity', () => {
|
||||
selectIsInvalidIdentity(mockState);
|
||||
expect(mockState.matches).toHaveBeenCalledWith(
|
||||
'reviewing.invalidIdentity',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsDisconnected', () => {
|
||||
it('should return true when in disconnected state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'disconnected'),
|
||||
};
|
||||
expect(selectIsDisconnected(state)).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with disconnected', () => {
|
||||
selectIsDisconnected(mockState);
|
||||
expect(mockState.matches).toHaveBeenCalledWith('disconnected');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsBluetoothDenied', () => {
|
||||
it('should return true when in bluetoothDenied state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'bluetoothDenied'),
|
||||
};
|
||||
expect(selectIsBluetoothDenied(state)).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with bluetoothDenied', () => {
|
||||
selectIsBluetoothDenied(mockState);
|
||||
expect(mockState.matches).toHaveBeenCalledWith('bluetoothDenied');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectBleError', () => {
|
||||
it('should return BLE error from context', () => {
|
||||
const bleError = {code: 'BLE_001', message: 'Connection failed'};
|
||||
const state: any = {
|
||||
...mockState,
|
||||
context: {...mockState.context, bleError},
|
||||
};
|
||||
expect(selectBleError(state)).toEqual(bleError);
|
||||
});
|
||||
|
||||
it('should return null when no BLE error', () => {
|
||||
expect(selectBleError(mockState)).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('TODO selectors (hardcoded)', () => {
|
||||
it('selectIsExchangingDeviceInfo should always return false', () => {
|
||||
expect(selectIsExchangingDeviceInfo()).toBe(false);
|
||||
});
|
||||
|
||||
it('selectIsExchangingDeviceInfoTimeout should always return false', () => {
|
||||
expect(selectIsExchangingDeviceInfoTimeout()).toBe(false);
|
||||
});
|
||||
|
||||
it('selectIsOffline should always return false', () => {
|
||||
expect(selectIsOffline()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsHandlingBleError', () => {
|
||||
it('should return true when in handlingBleError state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'handlingBleError'),
|
||||
};
|
||||
expect(selectIsHandlingBleError(state)).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with handlingBleError', () => {
|
||||
selectIsHandlingBleError(mockState);
|
||||
expect(mockState.matches).toHaveBeenCalledWith('handlingBleError');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectReadyForBluetoothStateCheck', () => {
|
||||
it('should return ready status from context', () => {
|
||||
expect(selectReadyForBluetoothStateCheck(mockState)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true when ready', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
context: {...mockState.context, readyForBluetoothStateCheck: true},
|
||||
};
|
||||
expect(selectReadyForBluetoothStateCheck(state)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsNearByDevicesPermissionDenied', () => {
|
||||
it('should return true when in nearByDevicesPermissionDenied state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'nearByDevicesPermissionDenied'),
|
||||
};
|
||||
expect(selectIsNearByDevicesPermissionDenied(state)).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with nearByDevicesPermissionDenied', () => {
|
||||
selectIsNearByDevicesPermissionDenied(mockState);
|
||||
expect(mockState.matches).toHaveBeenCalledWith(
|
||||
'nearByDevicesPermissionDenied',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsBluetoothPermissionDenied', () => {
|
||||
it('should return true when in bluetoothPermissionDenied state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'bluetoothPermissionDenied'),
|
||||
};
|
||||
expect(selectIsBluetoothPermissionDenied(state)).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with bluetoothPermissionDenied', () => {
|
||||
selectIsBluetoothPermissionDenied(mockState);
|
||||
expect(mockState.matches).toHaveBeenCalledWith(
|
||||
'bluetoothPermissionDenied',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsStartPermissionCheck', () => {
|
||||
it('should return true when in startPermissionCheck state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'startPermissionCheck'),
|
||||
};
|
||||
expect(selectIsStartPermissionCheck(state)).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with startPermissionCheck', () => {
|
||||
selectIsStartPermissionCheck(mockState);
|
||||
expect(mockState.matches).toHaveBeenCalledWith('startPermissionCheck');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsLocationPermissionRationale', () => {
|
||||
it('should return true when in checkingLocationState.LocationPermissionRationale state', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
matches: jest.fn(
|
||||
(s: string) =>
|
||||
s === 'checkingLocationState.LocationPermissionRationale',
|
||||
),
|
||||
};
|
||||
expect(selectIsLocationPermissionRationale(state)).toBe(true);
|
||||
});
|
||||
|
||||
it('should call matches with correct state path', () => {
|
||||
selectIsLocationPermissionRationale(mockState);
|
||||
expect(mockState.matches).toHaveBeenCalledWith(
|
||||
'checkingLocationState.LocationPermissionRationale',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Edge cases', () => {
|
||||
it('should handle undefined bleError', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
context: {...mockState.context, bleError: undefined},
|
||||
};
|
||||
expect(selectBleError(state)).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should handle empty bleError object', () => {
|
||||
const state: any = {
|
||||
...mockState,
|
||||
context: {...mockState.context, bleError: {}},
|
||||
};
|
||||
expect(selectBleError(state)).toEqual({});
|
||||
});
|
||||
});
|
||||
});
|
||||
233
machines/bleShare/request/selectors.test.ts
Normal file
233
machines/bleShare/request/selectors.test.ts
Normal file
@@ -0,0 +1,233 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import {
|
||||
selectSenderInfo,
|
||||
selectCredential,
|
||||
selectVerifiableCredentialData,
|
||||
selectIsReviewingInIdle,
|
||||
selectIsWaitingForConnection,
|
||||
selectIsCheckingBluetoothService,
|
||||
selectIsWaitingForVc,
|
||||
selectIsWaitingForVcTimeout,
|
||||
selectOpenId4VpUri,
|
||||
selectIsAccepting,
|
||||
selectIsDisplayingIncomingVC,
|
||||
selectIsSavingFailedInIdle,
|
||||
selectIsDone,
|
||||
selectIsNavigatingToReceivedCards,
|
||||
selectIsNavigatingToHome,
|
||||
} from './selectors';
|
||||
|
||||
describe('requestMachine selectors', () => {
|
||||
describe('selectSenderInfo', () => {
|
||||
it('should return senderInfo from context', () => {
|
||||
const mockSenderInfo = {name: 'John Doe', deviceId: 'device-123'};
|
||||
const mockState: any = {
|
||||
context: {
|
||||
senderInfo: mockSenderInfo,
|
||||
},
|
||||
};
|
||||
expect(selectSenderInfo(mockState)).toBe(mockSenderInfo);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectCredential', () => {
|
||||
it('should return verifiableCredential from incomingVc', () => {
|
||||
const mockVC = {credential: {id: 'cred-123'}};
|
||||
const mockState: any = {
|
||||
context: {
|
||||
incomingVc: {
|
||||
verifiableCredential: mockVC,
|
||||
},
|
||||
},
|
||||
};
|
||||
expect(selectCredential(mockState)).toBe(mockVC);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectVerifiableCredentialData', () => {
|
||||
it('should return formatted verifiable credential data', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
incomingVc: {
|
||||
vcMetadata: {
|
||||
id: 'vc-001',
|
||||
issuer: 'Test Issuer',
|
||||
},
|
||||
verifiableCredential: {
|
||||
credential: {
|
||||
credentialSubject: {
|
||||
face: 'base64-face-data',
|
||||
},
|
||||
},
|
||||
issuerLogo: 'https://example.com/logo.png',
|
||||
wellKnown: 'https://example.com/.well-known',
|
||||
credentialConfigurationId: 'config-123',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const result = selectVerifiableCredentialData(mockState);
|
||||
expect(result.issuer).toBe('Test Issuer');
|
||||
expect(result.issuerLogo).toBe('https://example.com/logo.png');
|
||||
expect(result.wellKnown).toBe('https://example.com/.well-known');
|
||||
expect(result.credentialConfigurationId).toBe('config-123');
|
||||
expect(result.face).toBe('base64-face-data');
|
||||
});
|
||||
|
||||
it('should use biometrics face when credentialSubject face is not available', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
incomingVc: {
|
||||
vcMetadata: {
|
||||
id: 'vc-002',
|
||||
issuer: 'Mosip',
|
||||
},
|
||||
credential: {
|
||||
biometrics: {
|
||||
face: 'biometric-face-data',
|
||||
},
|
||||
},
|
||||
verifiableCredential: {},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const result = selectVerifiableCredentialData(mockState);
|
||||
expect(result.face).toBe('biometric-face-data');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsReviewingInIdle', () => {
|
||||
it('should return true when in reviewing.idle state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn((state: string) => state === 'reviewing.idle'),
|
||||
};
|
||||
expect(selectIsReviewingInIdle(mockState)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when not in reviewing.idle state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
expect(selectIsReviewingInIdle(mockState)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsWaitingForConnection', () => {
|
||||
it('should return true when in waitingForConnection state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn((state: string) => state === 'waitingForConnection'),
|
||||
};
|
||||
expect(selectIsWaitingForConnection(mockState)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsCheckingBluetoothService', () => {
|
||||
it('should return true when in checkingBluetoothService state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(
|
||||
(state: string) => state === 'checkingBluetoothService',
|
||||
),
|
||||
};
|
||||
expect(selectIsCheckingBluetoothService(mockState)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsWaitingForVc', () => {
|
||||
it('should return true when in waitingForVc.inProgress state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(
|
||||
(state: string) => state === 'waitingForVc.inProgress',
|
||||
),
|
||||
};
|
||||
expect(selectIsWaitingForVc(mockState)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsWaitingForVcTimeout', () => {
|
||||
it('should return true when in waitingForVc.timeout state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn((state: string) => state === 'waitingForVc.timeout'),
|
||||
};
|
||||
expect(selectIsWaitingForVcTimeout(mockState)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectOpenId4VpUri', () => {
|
||||
it('should return openId4VpUri from context', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
openId4VpUri: 'openid4vp://verify?request=abc123',
|
||||
},
|
||||
};
|
||||
expect(selectOpenId4VpUri(mockState)).toBe(
|
||||
'openid4vp://verify?request=abc123',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsAccepting', () => {
|
||||
it('should return true when in reviewing.accepting state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn((state: string) => state === 'reviewing.accepting'),
|
||||
};
|
||||
expect(selectIsAccepting(mockState)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsDisplayingIncomingVC', () => {
|
||||
it('should return true when in reviewing.displayingIncomingVC state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(
|
||||
(state: string) => state === 'reviewing.displayingIncomingVC',
|
||||
),
|
||||
};
|
||||
expect(selectIsDisplayingIncomingVC(mockState)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsSavingFailedInIdle', () => {
|
||||
it('should return true when in reviewing.savingFailed.idle state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(
|
||||
(state: string) => state === 'reviewing.savingFailed.idle',
|
||||
),
|
||||
};
|
||||
expect(selectIsSavingFailedInIdle(mockState)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsDone', () => {
|
||||
it('should return true when in reviewing.navigatingToHistory state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(
|
||||
(state: string) => state === 'reviewing.navigatingToHistory',
|
||||
),
|
||||
};
|
||||
expect(selectIsDone(mockState)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsNavigatingToReceivedCards', () => {
|
||||
it('should return true when in reviewing.navigatingToReceivedCards state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(
|
||||
(state: string) => state === 'reviewing.navigatingToReceivedCards',
|
||||
),
|
||||
};
|
||||
expect(selectIsNavigatingToReceivedCards(mockState)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsNavigatingToHome', () => {
|
||||
it('should return true when in reviewing.navigatingToHome state', () => {
|
||||
const mockState: any = {
|
||||
matches: jest.fn(
|
||||
(state: string) => state === 'reviewing.navigatingToHome',
|
||||
),
|
||||
};
|
||||
expect(selectIsNavigatingToHome(mockState)).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
292
machines/bleShare/scan/scanModel.test.ts
Normal file
292
machines/bleShare/scan/scanModel.test.ts
Normal file
@@ -0,0 +1,292 @@
|
||||
import {ScanModel} from './scanModel';
|
||||
import {VCShareFlowType} from '../../../shared/Utils';
|
||||
|
||||
describe('ScanModel', () => {
|
||||
describe('Model structure', () => {
|
||||
it('should be defined', () => {
|
||||
expect(ScanModel).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have initialContext', () => {
|
||||
expect(ScanModel.initialContext).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have events', () => {
|
||||
expect(ScanModel.events).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Initial Context', () => {
|
||||
const initialContext = ScanModel.initialContext;
|
||||
|
||||
it('should have serviceRefs as empty object', () => {
|
||||
expect(initialContext.serviceRefs).toEqual({});
|
||||
expect(typeof initialContext.serviceRefs).toBe('object');
|
||||
});
|
||||
|
||||
it('should have senderInfo as empty object', () => {
|
||||
expect(initialContext.senderInfo).toEqual({});
|
||||
expect(typeof initialContext.senderInfo).toBe('object');
|
||||
});
|
||||
|
||||
it('should have receiverInfo as empty object', () => {
|
||||
expect(initialContext.receiverInfo).toEqual({});
|
||||
expect(typeof initialContext.receiverInfo).toBe('object');
|
||||
});
|
||||
|
||||
it('should have selectedVc as empty object', () => {
|
||||
expect(initialContext.selectedVc).toEqual({});
|
||||
expect(typeof initialContext.selectedVc).toBe('object');
|
||||
});
|
||||
|
||||
it('should have bleError as empty object', () => {
|
||||
expect(initialContext.bleError).toEqual({});
|
||||
expect(typeof initialContext.bleError).toBe('object');
|
||||
});
|
||||
|
||||
it('should have loggers as empty array', () => {
|
||||
expect(initialContext.loggers).toEqual([]);
|
||||
expect(Array.isArray(initialContext.loggers)).toBe(true);
|
||||
});
|
||||
|
||||
it('should have vcName as empty string', () => {
|
||||
expect(initialContext.vcName).toBe('');
|
||||
expect(typeof initialContext.vcName).toBe('string');
|
||||
});
|
||||
|
||||
it('should have flowType as SIMPLE_SHARE', () => {
|
||||
expect(initialContext.flowType).toBe(VCShareFlowType.SIMPLE_SHARE);
|
||||
});
|
||||
|
||||
it('should have openID4VPFlowType as empty string', () => {
|
||||
expect(initialContext.openID4VPFlowType).toBe('');
|
||||
expect(typeof initialContext.openID4VPFlowType).toBe('string');
|
||||
});
|
||||
|
||||
it('should have verificationImage as empty object', () => {
|
||||
expect(initialContext.verificationImage).toEqual({});
|
||||
expect(typeof initialContext.verificationImage).toBe('object');
|
||||
});
|
||||
|
||||
it('should have openId4VpUri as empty string', () => {
|
||||
expect(initialContext.openId4VpUri).toBe('');
|
||||
expect(typeof initialContext.openId4VpUri).toBe('string');
|
||||
});
|
||||
|
||||
it('should have shareLogType as empty string', () => {
|
||||
expect(initialContext.shareLogType).toBe('');
|
||||
expect(typeof initialContext.shareLogType).toBe('string');
|
||||
});
|
||||
|
||||
it('should have QrLoginRef as empty object', () => {
|
||||
expect(initialContext.QrLoginRef).toEqual({});
|
||||
expect(typeof initialContext.QrLoginRef).toBe('object');
|
||||
});
|
||||
|
||||
it('should have OpenId4VPRef as empty object', () => {
|
||||
expect(initialContext.OpenId4VPRef).toEqual({});
|
||||
expect(typeof initialContext.OpenId4VPRef).toBe('object');
|
||||
});
|
||||
|
||||
it('should have showQuickShareSuccessBanner as false', () => {
|
||||
expect(initialContext.showQuickShareSuccessBanner).toBe(false);
|
||||
expect(typeof initialContext.showQuickShareSuccessBanner).toBe('boolean');
|
||||
});
|
||||
|
||||
it('should have linkCode as empty string', () => {
|
||||
expect(initialContext.linkCode).toBe('');
|
||||
expect(typeof initialContext.linkCode).toBe('string');
|
||||
});
|
||||
|
||||
it('should have authorizationRequest as empty string', () => {
|
||||
expect(initialContext.authorizationRequest).toBe('');
|
||||
expect(typeof initialContext.authorizationRequest).toBe('string');
|
||||
});
|
||||
|
||||
it('should have quickShareData as empty object', () => {
|
||||
expect(initialContext.quickShareData).toEqual({});
|
||||
expect(typeof initialContext.quickShareData).toBe('object');
|
||||
});
|
||||
|
||||
it('should have isQrLoginViaDeepLink as false', () => {
|
||||
expect(initialContext.isQrLoginViaDeepLink).toBe(false);
|
||||
expect(typeof initialContext.isQrLoginViaDeepLink).toBe('boolean');
|
||||
});
|
||||
|
||||
it('should have isOVPViaDeepLink as false', () => {
|
||||
expect(initialContext.isOVPViaDeepLink).toBe(false);
|
||||
expect(typeof initialContext.isOVPViaDeepLink).toBe('boolean');
|
||||
});
|
||||
|
||||
it('should have showFaceAuthConsent as true', () => {
|
||||
expect(initialContext.showFaceAuthConsent).toBe(true);
|
||||
expect(typeof initialContext.showFaceAuthConsent).toBe('boolean');
|
||||
});
|
||||
|
||||
it('should have readyForBluetoothStateCheck as false', () => {
|
||||
expect(initialContext.readyForBluetoothStateCheck).toBe(false);
|
||||
expect(typeof initialContext.readyForBluetoothStateCheck).toBe('boolean');
|
||||
});
|
||||
|
||||
it('should have showFaceCaptureSuccessBanner as false', () => {
|
||||
expect(initialContext.showFaceCaptureSuccessBanner).toBe(false);
|
||||
expect(typeof initialContext.showFaceCaptureSuccessBanner).toBe(
|
||||
'boolean',
|
||||
);
|
||||
});
|
||||
|
||||
it('should have all 23 required properties', () => {
|
||||
const properties = Object.keys(initialContext);
|
||||
expect(properties).toHaveLength(23);
|
||||
});
|
||||
});
|
||||
|
||||
describe('String properties', () => {
|
||||
const context = ScanModel.initialContext;
|
||||
|
||||
it('all empty string properties should be empty', () => {
|
||||
const emptyStrings = [
|
||||
context.vcName,
|
||||
context.openID4VPFlowType,
|
||||
context.openId4VpUri,
|
||||
context.shareLogType,
|
||||
context.linkCode,
|
||||
context.authorizationRequest,
|
||||
];
|
||||
|
||||
emptyStrings.forEach(str => {
|
||||
expect(str).toBe('');
|
||||
expect(typeof str).toBe('string');
|
||||
});
|
||||
});
|
||||
|
||||
it('flowType should be SIMPLE_SHARE enum value', () => {
|
||||
expect(context.flowType).toBe(VCShareFlowType.SIMPLE_SHARE);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Array properties', () => {
|
||||
const context = ScanModel.initialContext;
|
||||
|
||||
it('loggers should be empty array', () => {
|
||||
expect(Array.isArray(context.loggers)).toBe(true);
|
||||
expect(context.loggers).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Object properties', () => {
|
||||
const context = ScanModel.initialContext;
|
||||
|
||||
it('all empty object properties should be empty objects', () => {
|
||||
const emptyObjects = [
|
||||
context.serviceRefs,
|
||||
context.senderInfo,
|
||||
context.receiverInfo,
|
||||
context.selectedVc,
|
||||
context.bleError,
|
||||
context.verificationImage,
|
||||
context.QrLoginRef,
|
||||
context.OpenId4VPRef,
|
||||
context.quickShareData,
|
||||
];
|
||||
|
||||
emptyObjects.forEach(obj => {
|
||||
expect(typeof obj).toBe('object');
|
||||
expect(Object.keys(obj)).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Boolean properties', () => {
|
||||
const context = ScanModel.initialContext;
|
||||
|
||||
it('showQuickShareSuccessBanner should be false', () => {
|
||||
expect(context.showQuickShareSuccessBanner).toBe(false);
|
||||
expect(typeof context.showQuickShareSuccessBanner).toBe('boolean');
|
||||
});
|
||||
|
||||
it('isQrLoginViaDeepLink should be false', () => {
|
||||
expect(context.isQrLoginViaDeepLink).toBe(false);
|
||||
expect(typeof context.isQrLoginViaDeepLink).toBe('boolean');
|
||||
});
|
||||
|
||||
it('isOVPViaDeepLink should be false', () => {
|
||||
expect(context.isOVPViaDeepLink).toBe(false);
|
||||
expect(typeof context.isOVPViaDeepLink).toBe('boolean');
|
||||
});
|
||||
|
||||
it('showFaceAuthConsent should be true', () => {
|
||||
expect(context.showFaceAuthConsent).toBe(true);
|
||||
expect(typeof context.showFaceAuthConsent).toBe('boolean');
|
||||
});
|
||||
|
||||
it('readyForBluetoothStateCheck should be false', () => {
|
||||
expect(context.readyForBluetoothStateCheck).toBe(false);
|
||||
expect(typeof context.readyForBluetoothStateCheck).toBe('boolean');
|
||||
});
|
||||
|
||||
it('showFaceCaptureSuccessBanner should be false', () => {
|
||||
expect(context.showFaceCaptureSuccessBanner).toBe(false);
|
||||
expect(typeof context.showFaceCaptureSuccessBanner).toBe('boolean');
|
||||
});
|
||||
|
||||
it('should have correct initial values for boolean properties', () => {
|
||||
const falseProps = [
|
||||
context.showQuickShareSuccessBanner,
|
||||
context.isQrLoginViaDeepLink,
|
||||
context.isOVPViaDeepLink,
|
||||
context.readyForBluetoothStateCheck,
|
||||
context.showFaceCaptureSuccessBanner,
|
||||
];
|
||||
|
||||
falseProps.forEach(prop => {
|
||||
expect(prop).toBe(false);
|
||||
expect(typeof prop).toBe('boolean');
|
||||
});
|
||||
|
||||
expect(context.showFaceAuthConsent).toBe(true);
|
||||
expect(typeof context.showFaceAuthConsent).toBe('boolean');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Model events', () => {
|
||||
it('should have events object', () => {
|
||||
expect(ScanModel.events).toBeDefined();
|
||||
expect(typeof ScanModel.events).toBe('object');
|
||||
});
|
||||
|
||||
it('should have event creators', () => {
|
||||
const eventKeys = Object.keys(ScanModel.events);
|
||||
expect(eventKeys.length).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Property types validation', () => {
|
||||
const context = ScanModel.initialContext;
|
||||
|
||||
it('should have correct types for all properties', () => {
|
||||
expect(typeof context.vcName).toBe('string');
|
||||
expect(typeof context.openID4VPFlowType).toBe('string');
|
||||
expect(typeof context.openId4VpUri).toBe('string');
|
||||
expect(typeof context.shareLogType).toBe('string');
|
||||
expect(typeof context.linkCode).toBe('string');
|
||||
expect(typeof context.authorizationRequest).toBe('string');
|
||||
expect(Array.isArray(context.loggers)).toBe(true);
|
||||
expect(typeof context.showQuickShareSuccessBanner).toBe('boolean');
|
||||
expect(typeof context.isQrLoginViaDeepLink).toBe('boolean');
|
||||
expect(typeof context.isOVPViaDeepLink).toBe('boolean');
|
||||
expect(typeof context.showFaceAuthConsent).toBe('boolean');
|
||||
expect(typeof context.readyForBluetoothStateCheck).toBe('boolean');
|
||||
expect(typeof context.showFaceCaptureSuccessBanner).toBe('boolean');
|
||||
expect(typeof context.serviceRefs).toBe('object');
|
||||
expect(typeof context.senderInfo).toBe('object');
|
||||
expect(typeof context.receiverInfo).toBe('object');
|
||||
expect(typeof context.selectedVc).toBe('object');
|
||||
expect(typeof context.bleError).toBe('object');
|
||||
expect(typeof context.verificationImage).toBe('object');
|
||||
expect(typeof context.QrLoginRef).toBe('object');
|
||||
expect(typeof context.OpenId4VPRef).toBe('object');
|
||||
expect(typeof context.quickShareData).toBe('object');
|
||||
});
|
||||
});
|
||||
});
|
||||
500
machines/bleShare/scan/scanSelectors.test.ts
Normal file
500
machines/bleShare/scan/scanSelectors.test.ts
Normal file
@@ -0,0 +1,500 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import {
|
||||
selectFlowType,
|
||||
selectOpenID4VPFlowType,
|
||||
selectReceiverInfo,
|
||||
selectVcName,
|
||||
selectCredential,
|
||||
selectVerifiableCredentialData,
|
||||
selectQrLoginRef,
|
||||
selectIsScanning,
|
||||
selectIsQuickShareDone,
|
||||
selectShowQuickShareSuccessBanner,
|
||||
selectIsConnecting,
|
||||
selectIsConnectingTimeout,
|
||||
selectIsSelectingVc,
|
||||
selectIsSendingVc,
|
||||
selectIsSendingVP,
|
||||
selectIsSendingVPError,
|
||||
selectIsSendingVPSuccess,
|
||||
selectIsFaceIdentityVerified,
|
||||
selectIsSendingVcTimeout,
|
||||
selectIsSendingVPTimeout,
|
||||
selectIsSent,
|
||||
selectIsInvalid,
|
||||
selectIsLocationDenied,
|
||||
selectIsLocationDisabled,
|
||||
selectIsShowQrLogin,
|
||||
selectIsQrLoginDone,
|
||||
selectIsQrLoginDoneViaDeeplink,
|
||||
selectIsQrLoginStoring,
|
||||
selectIsDone,
|
||||
selectIsMinimumStorageRequiredForAuditEntryLimitReached,
|
||||
selectIsFaceVerificationConsent,
|
||||
selectIsOVPViaDeepLink,
|
||||
} from './scanSelectors';
|
||||
|
||||
describe('scanSelectors', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
flowType: '',
|
||||
openID4VPFlowType: '',
|
||||
receiverInfo: null,
|
||||
vcName: '',
|
||||
selectedVc: null,
|
||||
QrLoginRef: null,
|
||||
showQuickShareSuccessBanner: false,
|
||||
isOVPViaDeepLink: false,
|
||||
showFaceCaptureSuccessBanner: false,
|
||||
},
|
||||
matches: jest.fn(() => false),
|
||||
};
|
||||
|
||||
describe('selectFlowType', () => {
|
||||
it('should return flowType from context', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
context: {...mockState.context, flowType: 'simple_share'},
|
||||
};
|
||||
expect(selectFlowType(state)).toBe('simple_share');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectOpenID4VPFlowType', () => {
|
||||
it('should return openID4VPFlowType from context', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
context: {...mockState.context, openID4VPFlowType: 'ovp_flow'},
|
||||
};
|
||||
expect(selectOpenID4VPFlowType(state)).toBe('ovp_flow');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectReceiverInfo', () => {
|
||||
it('should return receiverInfo from context', () => {
|
||||
const receiverInfo = {name: 'Test', id: '123'};
|
||||
const state = {
|
||||
...mockState,
|
||||
context: {...mockState.context, receiverInfo},
|
||||
};
|
||||
expect(selectReceiverInfo(state)).toBe(receiverInfo);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectVcName', () => {
|
||||
it('should return vcName from context', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
context: {...mockState.context, vcName: 'National ID'},
|
||||
};
|
||||
expect(selectVcName(state)).toBe('National ID');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectCredential', () => {
|
||||
it('should return credential when verifiableCredential has credential property', () => {
|
||||
const mockCredential = {id: 'cred123'};
|
||||
const state = {
|
||||
...mockState,
|
||||
context: {
|
||||
...mockState.context,
|
||||
selectedVc: {
|
||||
verifiableCredential: {credential: mockCredential},
|
||||
},
|
||||
},
|
||||
};
|
||||
const result = selectCredential(state);
|
||||
expect(result).toEqual([mockCredential]);
|
||||
});
|
||||
|
||||
it('should return verifiableCredential when no credential property', () => {
|
||||
const mockVC = {id: 'vc456'};
|
||||
const state = {
|
||||
...mockState,
|
||||
context: {
|
||||
...mockState.context,
|
||||
selectedVc: {
|
||||
verifiableCredential: mockVC,
|
||||
},
|
||||
},
|
||||
};
|
||||
const result = selectCredential(state);
|
||||
expect(result).toEqual([mockVC]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectVerifiableCredentialData', () => {
|
||||
it('should return formatted credential data with face from credentialSubject', () => {
|
||||
const mockCredential = {
|
||||
credentialSubject: {
|
||||
face: '/9j/4AAQSkZJRgABAQAAAQ...',
|
||||
gender: 'Male',
|
||||
UIN: '123456789',
|
||||
},
|
||||
issuer: 'did:web:example.com',
|
||||
issuanceDate: '2023-01-01T00:00:00Z',
|
||||
};
|
||||
const state = {
|
||||
...mockState,
|
||||
context: {
|
||||
...mockState.context,
|
||||
selectedVc: {
|
||||
verifiableCredential: {credential: mockCredential},
|
||||
vcMetadata: {},
|
||||
credential: mockCredential,
|
||||
format: 'ldp_vc',
|
||||
},
|
||||
},
|
||||
};
|
||||
const result = selectVerifiableCredentialData(state);
|
||||
|
||||
expect(result).toBeDefined();
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
expect(result[0]).toBeDefined();
|
||||
expect(result[0].face).toBeDefined();
|
||||
});
|
||||
|
||||
it('should use biometrics face when credentialSubject face is not available', () => {
|
||||
const mockCredential = {
|
||||
credentialSubject: {
|
||||
gender: 'Male',
|
||||
UIN: '123456789',
|
||||
},
|
||||
biometrics: {
|
||||
face: '/9j/4AAQSkZJRgABAQBBBB...',
|
||||
},
|
||||
issuer: 'did:web:example.com',
|
||||
issuanceDate: '2023-01-01T00:00:00Z',
|
||||
};
|
||||
const state = {
|
||||
...mockState,
|
||||
context: {
|
||||
...mockState.context,
|
||||
selectedVc: {
|
||||
verifiableCredential: {credential: mockCredential},
|
||||
vcMetadata: {},
|
||||
credential: mockCredential,
|
||||
format: 'ldp_vc',
|
||||
},
|
||||
},
|
||||
};
|
||||
const result = selectVerifiableCredentialData(state);
|
||||
|
||||
expect(result).toBeDefined();
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
expect(result[0].face).toBe('/9j/4AAQSkZJRgABAQBBBB...');
|
||||
});
|
||||
|
||||
it('should handle credential without face data', () => {
|
||||
const mockCredential = {
|
||||
credentialSubject: {
|
||||
gender: 'Male',
|
||||
UIN: '123456789',
|
||||
},
|
||||
issuer: 'did:web:example.com',
|
||||
issuanceDate: '2023-01-01T00:00:00Z',
|
||||
};
|
||||
const state = {
|
||||
...mockState,
|
||||
context: {
|
||||
...mockState.context,
|
||||
selectedVc: {
|
||||
verifiableCredential: {credential: mockCredential},
|
||||
vcMetadata: {},
|
||||
credential: mockCredential,
|
||||
format: 'ldp_vc',
|
||||
},
|
||||
},
|
||||
};
|
||||
const result = selectVerifiableCredentialData(state);
|
||||
|
||||
expect(result).toBeDefined();
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
expect(result[0].face).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectQrLoginRef', () => {
|
||||
it('should return QrLoginRef from context', () => {
|
||||
const ref = {current: 'test'};
|
||||
const state = {
|
||||
...mockState,
|
||||
context: {...mockState.context, QrLoginRef: ref},
|
||||
};
|
||||
expect(selectQrLoginRef(state)).toBe(ref);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsScanning', () => {
|
||||
it('should return true when in findingConnection state', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'findingConnection'),
|
||||
};
|
||||
expect(selectIsScanning(state)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when not in findingConnection state', () => {
|
||||
expect(selectIsScanning(mockState)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsQuickShareDone', () => {
|
||||
it('should return true when in loadVCS.navigatingToHome state', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'loadVCS.navigatingToHome'),
|
||||
};
|
||||
expect(selectIsQuickShareDone(state)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when not in state', () => {
|
||||
expect(selectIsQuickShareDone(mockState)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectShowQuickShareSuccessBanner', () => {
|
||||
it('should return showQuickShareSuccessBanner from context', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
context: {...mockState.context, showQuickShareSuccessBanner: true},
|
||||
};
|
||||
expect(selectShowQuickShareSuccessBanner(state)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsConnecting', () => {
|
||||
it('should return true when in connecting.inProgress state', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'connecting.inProgress'),
|
||||
};
|
||||
expect(selectIsConnecting(state)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsConnectingTimeout', () => {
|
||||
it('should return true when in connecting.timeout state', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'connecting.timeout'),
|
||||
};
|
||||
expect(selectIsConnectingTimeout(state)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsSelectingVc', () => {
|
||||
it('should return true when in reviewing.selectingVc state', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'reviewing.selectingVc'),
|
||||
};
|
||||
expect(selectIsSelectingVc(state)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsSendingVc', () => {
|
||||
it('should return true when in reviewing.sendingVc.inProgress state', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'reviewing.sendingVc.inProgress'),
|
||||
};
|
||||
expect(selectIsSendingVc(state)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsSendingVP', () => {
|
||||
it('should return true when in startVPSharing.inProgress state', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'startVPSharing.inProgress'),
|
||||
};
|
||||
expect(selectIsSendingVP(state)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsSendingVPError', () => {
|
||||
it('should return true when in startVPSharing.showError state', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'startVPSharing.showError'),
|
||||
};
|
||||
expect(selectIsSendingVPError(state)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsSendingVPSuccess', () => {
|
||||
it('should return true when in startVPSharing.success state', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'startVPSharing.success'),
|
||||
};
|
||||
expect(selectIsSendingVPSuccess(state)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsFaceIdentityVerified', () => {
|
||||
it('should return true when sendingVc and banner is true', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'reviewing.sendingVc.inProgress'),
|
||||
context: {...mockState.context, showFaceCaptureSuccessBanner: true},
|
||||
};
|
||||
expect(selectIsFaceIdentityVerified(state)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when not in sendingVc state', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
context: {...mockState.context, showFaceCaptureSuccessBanner: true},
|
||||
};
|
||||
expect(selectIsFaceIdentityVerified(state)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsSendingVcTimeout', () => {
|
||||
it('should return true when in reviewing.sendingVc.timeout state', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'reviewing.sendingVc.timeout'),
|
||||
};
|
||||
expect(selectIsSendingVcTimeout(state)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsSendingVPTimeout', () => {
|
||||
it('should return true when in startVPSharing.timeout state', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'startVPSharing.timeout'),
|
||||
};
|
||||
expect(selectIsSendingVPTimeout(state)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsSent', () => {
|
||||
it('should return true when in reviewing.sendingVc.sent state', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'reviewing.sendingVc.sent'),
|
||||
};
|
||||
expect(selectIsSent(state)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsInvalid', () => {
|
||||
it('should return true when in invalid state', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'invalid'),
|
||||
};
|
||||
expect(selectIsInvalid(state)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsLocationDenied', () => {
|
||||
it('should return true when in checkingLocationState.denied state', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'checkingLocationState.denied'),
|
||||
};
|
||||
expect(selectIsLocationDenied(state)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsLocationDisabled', () => {
|
||||
it('should return true when in checkingLocationState.disabled state', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'checkingLocationState.disabled'),
|
||||
};
|
||||
expect(selectIsLocationDisabled(state)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsShowQrLogin', () => {
|
||||
it('should return true when in showQrLogin state', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'showQrLogin'),
|
||||
};
|
||||
expect(selectIsShowQrLogin(state)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsQrLoginDone', () => {
|
||||
it('should return true when in showQrLogin.navigatingToHistory state', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
matches: jest.fn(
|
||||
(s: string) => s === 'showQrLogin.navigatingToHistory',
|
||||
),
|
||||
};
|
||||
expect(selectIsQrLoginDone(state)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsQrLoginDoneViaDeeplink', () => {
|
||||
it('should return true when in showQrLogin.navigatingToHome state', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'showQrLogin.navigatingToHome'),
|
||||
};
|
||||
expect(selectIsQrLoginDoneViaDeeplink(state)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsQrLoginStoring', () => {
|
||||
it('should return true when in showQrLogin.storing state', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'showQrLogin.storing'),
|
||||
};
|
||||
expect(selectIsQrLoginStoring(state)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsDone', () => {
|
||||
it('should return true when in reviewing.disconnect state', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'reviewing.disconnect'),
|
||||
};
|
||||
expect(selectIsDone(state)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsMinimumStorageRequiredForAuditEntryLimitReached', () => {
|
||||
it('should return true when in restrictSharingVc state', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
matches: jest.fn((s: string) => s === 'restrictSharingVc'),
|
||||
};
|
||||
expect(
|
||||
selectIsMinimumStorageRequiredForAuditEntryLimitReached(state),
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsFaceVerificationConsent', () => {
|
||||
it('should return true when in reviewing.faceVerificationConsent state', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
matches: jest.fn(
|
||||
(s: string) => s === 'reviewing.faceVerificationConsent',
|
||||
),
|
||||
};
|
||||
expect(selectIsFaceVerificationConsent(state)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsOVPViaDeepLink', () => {
|
||||
it('should return isOVPViaDeepLink from context', () => {
|
||||
const state = {
|
||||
...mockState,
|
||||
context: {...mockState.context, isOVPViaDeepLink: true},
|
||||
};
|
||||
expect(selectIsOVPViaDeepLink(state)).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
350
machines/openID4VP/openID4VPModel.test.ts
Normal file
350
machines/openID4VP/openID4VPModel.test.ts
Normal file
@@ -0,0 +1,350 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import {openID4VPModel} from './openID4VPModel';
|
||||
import {KeyTypes} from '../../shared/cryptoutil/KeyTypes';
|
||||
|
||||
describe('openID4VPModel', () => {
|
||||
describe('Model context', () => {
|
||||
it('should initialize with default context values', () => {
|
||||
const initialContext = openID4VPModel.initialContext;
|
||||
|
||||
expect(initialContext.urlEncodedAuthorizationRequest).toBe('');
|
||||
expect(initialContext.checkedAll).toBe(false);
|
||||
expect(initialContext.isShareWithSelfie).toBe(false);
|
||||
expect(initialContext.showFaceAuthConsent).toBe(true);
|
||||
expect(initialContext.purpose).toBe('');
|
||||
expect(initialContext.error).toBe('');
|
||||
expect(initialContext.publicKey).toBe('');
|
||||
expect(initialContext.privateKey).toBe('');
|
||||
expect(initialContext.keyType).toBe(KeyTypes.ED25519);
|
||||
expect(initialContext.flowType).toBe('');
|
||||
expect(initialContext.openID4VPRetryCount).toBe(0);
|
||||
expect(initialContext.showFaceCaptureSuccessBanner).toBe(false);
|
||||
expect(initialContext.isFaceVerificationRetryAttempt).toBe(false);
|
||||
expect(initialContext.requestedClaims).toBe('');
|
||||
expect(initialContext.showLoadingScreen).toBe(false);
|
||||
expect(initialContext.isOVPViaDeepLink).toBe(false);
|
||||
expect(initialContext.showTrustConsentModal).toBe(false);
|
||||
});
|
||||
|
||||
it('should initialize with empty object contexts', () => {
|
||||
const initialContext = openID4VPModel.initialContext;
|
||||
|
||||
expect(initialContext.authenticationResponse).toEqual({});
|
||||
expect(initialContext.vcsMatchingAuthRequest).toEqual({});
|
||||
expect(initialContext.selectedVCs).toEqual({});
|
||||
expect(initialContext.selectedDisclosuresByVc).toEqual({});
|
||||
expect(initialContext.miniViewSelectedVC).toEqual({});
|
||||
});
|
||||
|
||||
it('should initialize with empty array contexts', () => {
|
||||
const initialContext = openID4VPModel.initialContext;
|
||||
|
||||
expect(initialContext.trustedVerifiers).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Events', () => {
|
||||
describe('AUTHENTICATE', () => {
|
||||
it('should create AUTHENTICATE event with all parameters', () => {
|
||||
const encodedAuthRequest = 'encoded_request_123';
|
||||
const flowType = 'OpenID4VP';
|
||||
const selectedVC = {id: 'vc123'};
|
||||
const isOVPViaDeepLink = true;
|
||||
|
||||
const event = openID4VPModel.events.AUTHENTICATE(
|
||||
encodedAuthRequest,
|
||||
flowType,
|
||||
selectedVC,
|
||||
isOVPViaDeepLink,
|
||||
);
|
||||
|
||||
expect(event.encodedAuthRequest).toBe(encodedAuthRequest);
|
||||
expect(event.flowType).toBe(flowType);
|
||||
expect(event.selectedVC).toEqual(selectedVC);
|
||||
expect(event.isOVPViaDeepLink).toBe(isOVPViaDeepLink);
|
||||
});
|
||||
|
||||
it('should create AUTHENTICATE event with false deeplink flag', () => {
|
||||
const event = openID4VPModel.events.AUTHENTICATE(
|
||||
'request',
|
||||
'flow',
|
||||
{},
|
||||
false,
|
||||
);
|
||||
|
||||
expect(event.isOVPViaDeepLink).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('DOWNLOADED_VCS', () => {
|
||||
it('should create DOWNLOADED_VCS event with VCs array', () => {
|
||||
const vcs: any[] = [
|
||||
{id: 'vc1', credential: {}},
|
||||
{id: 'vc2', credential: {}},
|
||||
];
|
||||
|
||||
const event = openID4VPModel.events.DOWNLOADED_VCS(vcs);
|
||||
|
||||
expect(event.vcs).toEqual(vcs);
|
||||
expect(event.vcs.length).toBe(2);
|
||||
});
|
||||
|
||||
it('should create DOWNLOADED_VCS event with empty array', () => {
|
||||
const event = openID4VPModel.events.DOWNLOADED_VCS([]);
|
||||
|
||||
expect(event.vcs).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('SELECT_VC', () => {
|
||||
it('should create SELECT_VC event with vcKey and inputDescriptorId', () => {
|
||||
const vcKey = 'vc_key_123';
|
||||
const inputDescriptorId = 'descriptor_456';
|
||||
|
||||
const event = openID4VPModel.events.SELECT_VC(vcKey, inputDescriptorId);
|
||||
|
||||
expect(event.vcKey).toBe(vcKey);
|
||||
expect(event.inputDescriptorId).toBe(inputDescriptorId);
|
||||
});
|
||||
|
||||
it('should create SELECT_VC event with null inputDescriptorId', () => {
|
||||
const event = openID4VPModel.events.SELECT_VC('key', null);
|
||||
|
||||
expect(event.vcKey).toBe('key');
|
||||
expect(event.inputDescriptorId).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('ACCEPT_REQUEST', () => {
|
||||
it('should create ACCEPT_REQUEST event with selectedVCs and disclosures', () => {
|
||||
const selectedVCs = {
|
||||
descriptor1: [{id: 'vc1'}] as any[],
|
||||
descriptor2: [{id: 'vc2'}] as any[],
|
||||
};
|
||||
const selectedDisclosuresByVc = {
|
||||
vc1: ['claim1', 'claim2'],
|
||||
vc2: ['claim3'],
|
||||
};
|
||||
|
||||
const event = openID4VPModel.events.ACCEPT_REQUEST(
|
||||
selectedVCs,
|
||||
selectedDisclosuresByVc,
|
||||
);
|
||||
|
||||
expect(event.selectedVCs).toEqual(selectedVCs);
|
||||
expect(event.selectedDisclosuresByVc).toEqual(selectedDisclosuresByVc);
|
||||
});
|
||||
|
||||
it('should create ACCEPT_REQUEST event with empty objects', () => {
|
||||
const event = openID4VPModel.events.ACCEPT_REQUEST({}, {});
|
||||
|
||||
expect(event.selectedVCs).toEqual({});
|
||||
expect(event.selectedDisclosuresByVc).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('VERIFIER_TRUST_CONSENT_GIVEN', () => {
|
||||
it('should create VERIFIER_TRUST_CONSENT_GIVEN event', () => {
|
||||
const event = openID4VPModel.events.VERIFIER_TRUST_CONSENT_GIVEN();
|
||||
|
||||
expect(event.type).toBe('VERIFIER_TRUST_CONSENT_GIVEN');
|
||||
});
|
||||
});
|
||||
|
||||
describe('VERIFY_AND_ACCEPT_REQUEST', () => {
|
||||
it('should create VERIFY_AND_ACCEPT_REQUEST event with selectedVCs and disclosures', () => {
|
||||
const selectedVCs = {descriptor1: [{id: 'vc1'}] as any[]};
|
||||
const selectedDisclosuresByVc = {vc1: ['claim1']};
|
||||
|
||||
const event = openID4VPModel.events.VERIFY_AND_ACCEPT_REQUEST(
|
||||
selectedVCs,
|
||||
selectedDisclosuresByVc,
|
||||
);
|
||||
|
||||
expect(event.selectedVCs).toEqual(selectedVCs);
|
||||
expect(event.selectedDisclosuresByVc).toEqual(selectedDisclosuresByVc);
|
||||
});
|
||||
});
|
||||
|
||||
describe('CONFIRM', () => {
|
||||
it('should create CONFIRM event', () => {
|
||||
const event = openID4VPModel.events.CONFIRM();
|
||||
|
||||
expect(event.type).toBe('CONFIRM');
|
||||
});
|
||||
});
|
||||
|
||||
describe('CANCEL', () => {
|
||||
it('should create CANCEL event', () => {
|
||||
const event = openID4VPModel.events.CANCEL();
|
||||
|
||||
expect(event.type).toBe('CANCEL');
|
||||
});
|
||||
});
|
||||
|
||||
describe('FACE_VERIFICATION_CONSENT', () => {
|
||||
it('should create FACE_VERIFICATION_CONSENT event with checked flag true', () => {
|
||||
const event = openID4VPModel.events.FACE_VERIFICATION_CONSENT(true);
|
||||
|
||||
expect(event.isDoNotAskAgainChecked).toBe(true);
|
||||
});
|
||||
|
||||
it('should create FACE_VERIFICATION_CONSENT event with checked flag false', () => {
|
||||
const event = openID4VPModel.events.FACE_VERIFICATION_CONSENT(false);
|
||||
|
||||
expect(event.isDoNotAskAgainChecked).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('FACE_VALID', () => {
|
||||
it('should create FACE_VALID event', () => {
|
||||
const event = openID4VPModel.events.FACE_VALID();
|
||||
|
||||
expect(event.type).toBe('FACE_VALID');
|
||||
});
|
||||
});
|
||||
|
||||
describe('FACE_INVALID', () => {
|
||||
it('should create FACE_INVALID event', () => {
|
||||
const event = openID4VPModel.events.FACE_INVALID();
|
||||
|
||||
expect(event.type).toBe('FACE_INVALID');
|
||||
});
|
||||
});
|
||||
|
||||
describe('DISMISS', () => {
|
||||
it('should create DISMISS event', () => {
|
||||
const event = openID4VPModel.events.DISMISS();
|
||||
|
||||
expect(event.type).toBe('DISMISS');
|
||||
});
|
||||
});
|
||||
|
||||
describe('DISMISS_POPUP', () => {
|
||||
it('should create DISMISS_POPUP event', () => {
|
||||
const event = openID4VPModel.events.DISMISS_POPUP();
|
||||
|
||||
expect(event.type).toBe('DISMISS_POPUP');
|
||||
});
|
||||
});
|
||||
|
||||
describe('RETRY_VERIFICATION', () => {
|
||||
it('should create RETRY_VERIFICATION event', () => {
|
||||
const event = openID4VPModel.events.RETRY_VERIFICATION();
|
||||
|
||||
expect(event.type).toBe('RETRY_VERIFICATION');
|
||||
});
|
||||
});
|
||||
|
||||
describe('STORE_RESPONSE', () => {
|
||||
it('should create STORE_RESPONSE event with response object', () => {
|
||||
const response = {
|
||||
status: 'success',
|
||||
data: {id: '123'},
|
||||
};
|
||||
|
||||
const event = openID4VPModel.events.STORE_RESPONSE(response);
|
||||
|
||||
expect(event.response).toEqual(response);
|
||||
});
|
||||
|
||||
it('should create STORE_RESPONSE event with null response', () => {
|
||||
const event = openID4VPModel.events.STORE_RESPONSE(null);
|
||||
|
||||
expect(event.response).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('GO_BACK', () => {
|
||||
it('should create GO_BACK event', () => {
|
||||
const event = openID4VPModel.events.GO_BACK();
|
||||
|
||||
expect(event.type).toBe('GO_BACK');
|
||||
});
|
||||
});
|
||||
|
||||
describe('CHECK_SELECTED_VC', () => {
|
||||
it('should create CHECK_SELECTED_VC event', () => {
|
||||
const event = openID4VPModel.events.CHECK_SELECTED_VC();
|
||||
|
||||
expect(event.type).toBe('CHECK_SELECTED_VC');
|
||||
});
|
||||
});
|
||||
|
||||
describe('SET_SELECTED_VC', () => {
|
||||
it('should create SET_SELECTED_VC event', () => {
|
||||
const event = openID4VPModel.events.SET_SELECTED_VC();
|
||||
|
||||
expect(event.type).toBe('SET_SELECTED_VC');
|
||||
});
|
||||
});
|
||||
|
||||
describe('CHECK_FOR_IMAGE', () => {
|
||||
it('should create CHECK_FOR_IMAGE event', () => {
|
||||
const event = openID4VPModel.events.CHECK_FOR_IMAGE();
|
||||
|
||||
expect(event.type).toBe('CHECK_FOR_IMAGE');
|
||||
});
|
||||
});
|
||||
|
||||
describe('RETRY', () => {
|
||||
it('should create RETRY event', () => {
|
||||
const event = openID4VPModel.events.RETRY();
|
||||
|
||||
expect(event.type).toBe('RETRY');
|
||||
});
|
||||
});
|
||||
|
||||
describe('RESET_RETRY_COUNT', () => {
|
||||
it('should create RESET_RETRY_COUNT event', () => {
|
||||
const event = openID4VPModel.events.RESET_RETRY_COUNT();
|
||||
|
||||
expect(event.type).toBe('RESET_RETRY_COUNT');
|
||||
});
|
||||
});
|
||||
|
||||
describe('RESET_ERROR', () => {
|
||||
it('should create RESET_ERROR event', () => {
|
||||
const event = openID4VPModel.events.RESET_ERROR();
|
||||
|
||||
expect(event.type).toBe('RESET_ERROR');
|
||||
});
|
||||
});
|
||||
|
||||
describe('CLOSE_BANNER', () => {
|
||||
it('should create CLOSE_BANNER event', () => {
|
||||
const event = openID4VPModel.events.CLOSE_BANNER();
|
||||
|
||||
expect(event.type).toBe('CLOSE_BANNER');
|
||||
});
|
||||
});
|
||||
|
||||
describe('LOG_ACTIVITY', () => {
|
||||
it('should create LOG_ACTIVITY event with SHARED_SUCCESSFULLY logType', () => {
|
||||
const event = openID4VPModel.events.LOG_ACTIVITY('SHARED_SUCCESSFULLY');
|
||||
|
||||
expect(event.logType).toBe('SHARED_SUCCESSFULLY');
|
||||
});
|
||||
|
||||
it('should create LOG_ACTIVITY event with USER_DECLINED_CONSENT logType', () => {
|
||||
const event = openID4VPModel.events.LOG_ACTIVITY(
|
||||
'USER_DECLINED_CONSENT',
|
||||
);
|
||||
|
||||
expect(event.logType).toBe('USER_DECLINED_CONSENT');
|
||||
});
|
||||
|
||||
it('should create LOG_ACTIVITY event with TECHNICAL_ERROR logType', () => {
|
||||
const event = openID4VPModel.events.LOG_ACTIVITY('TECHNICAL_ERROR');
|
||||
|
||||
expect(event.logType).toBe('TECHNICAL_ERROR');
|
||||
});
|
||||
|
||||
it('should create LOG_ACTIVITY event with empty string logType', () => {
|
||||
const event = openID4VPModel.events.LOG_ACTIVITY('');
|
||||
|
||||
expect(event.logType).toBe('');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
637
machines/openID4VP/openID4VPSelectors.test.ts
Normal file
637
machines/openID4VP/openID4VPSelectors.test.ts
Normal file
@@ -0,0 +1,637 @@
|
||||
import {
|
||||
selectIsGetVCsSatisfyingAuthRequest,
|
||||
selectVCsMatchingAuthRequest,
|
||||
selectSelectedVCs,
|
||||
selectAreAllVCsChecked,
|
||||
selectIsGetVPSharingConsent,
|
||||
selectIsFaceVerificationConsent,
|
||||
selectIsVerifyingIdentity,
|
||||
selectIsInvalidIdentity,
|
||||
selectIsSharingVP,
|
||||
selectIsShowLoadingScreen,
|
||||
selectCredentials,
|
||||
selectVerifiableCredentialsData,
|
||||
selectPurpose,
|
||||
selectShowConfirmationPopup,
|
||||
selectIsSelectingVcs,
|
||||
selectIsError,
|
||||
selectOpenID4VPRetryCount,
|
||||
selectIsOVPViaDeeplink,
|
||||
selectIsFaceVerifiedInVPSharing,
|
||||
selectVerifierNameInVPSharing,
|
||||
selectRequestedClaimsByVerifier,
|
||||
selectshowTrustConsentModal,
|
||||
selectVerifierNameInTrustModal,
|
||||
selectVerifierLogoInTrustModal,
|
||||
} from './openID4VPSelectors';
|
||||
|
||||
describe('openID4VPSelectors', () => {
|
||||
describe('selectIsGetVCsSatisfyingAuthRequest', () => {
|
||||
it('should return true when in getVCsSatisfyingAuthRequest state', () => {
|
||||
const state = {
|
||||
matches: jest.fn(() => true),
|
||||
context: {},
|
||||
} as any;
|
||||
|
||||
expect(selectIsGetVCsSatisfyingAuthRequest(state)).toBe(true);
|
||||
expect(state.matches).toHaveBeenCalledWith('getVCsSatisfyingAuthRequest');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectVCsMatchingAuthRequest', () => {
|
||||
it('should return vcsMatchingAuthRequest from context', () => {
|
||||
const mockVCs = [{id: 'vc1'}, {id: 'vc2'}];
|
||||
const state = {
|
||||
context: {
|
||||
vcsMatchingAuthRequest: mockVCs,
|
||||
},
|
||||
} as any;
|
||||
|
||||
expect(selectVCsMatchingAuthRequest(state)).toEqual(mockVCs);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectSelectedVCs', () => {
|
||||
it('should return selectedVCs from context', () => {
|
||||
const mockSelectedVCs = {vc1: {data: 'test'}};
|
||||
const state = {
|
||||
context: {
|
||||
selectedVCs: mockSelectedVCs,
|
||||
},
|
||||
} as any;
|
||||
|
||||
expect(selectSelectedVCs(state)).toEqual(mockSelectedVCs);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectAreAllVCsChecked', () => {
|
||||
it('should return checkedAll from context', () => {
|
||||
const state = {
|
||||
context: {
|
||||
checkedAll: true,
|
||||
},
|
||||
} as any;
|
||||
|
||||
expect(selectAreAllVCsChecked(state)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsGetVPSharingConsent', () => {
|
||||
it('should return true when in getConsentForVPSharing state', () => {
|
||||
const state = {
|
||||
matches: jest.fn(() => true),
|
||||
context: {},
|
||||
} as any;
|
||||
|
||||
expect(selectIsGetVPSharingConsent(state)).toBe(true);
|
||||
expect(state.matches).toHaveBeenCalledWith('getConsentForVPSharing');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsFaceVerificationConsent', () => {
|
||||
it('should return true when in faceVerificationConsent state', () => {
|
||||
const state = {
|
||||
matches: jest.fn(() => true),
|
||||
context: {},
|
||||
} as any;
|
||||
|
||||
expect(selectIsFaceVerificationConsent(state)).toBe(true);
|
||||
expect(state.matches).toHaveBeenCalledWith('faceVerificationConsent');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsVerifyingIdentity', () => {
|
||||
it('should return true when in verifyingIdentity state', () => {
|
||||
const state = {
|
||||
matches: jest.fn(() => true),
|
||||
context: {},
|
||||
} as any;
|
||||
|
||||
expect(selectIsVerifyingIdentity(state)).toBe(true);
|
||||
expect(state.matches).toHaveBeenCalledWith('verifyingIdentity');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsInvalidIdentity', () => {
|
||||
it('should return true when in invalidIdentity state', () => {
|
||||
const state = {
|
||||
matches: jest.fn(() => true),
|
||||
context: {},
|
||||
} as any;
|
||||
|
||||
expect(selectIsInvalidIdentity(state)).toBe(true);
|
||||
expect(state.matches).toHaveBeenCalledWith('invalidIdentity');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsSharingVP', () => {
|
||||
it('should return true when in sendingVP state', () => {
|
||||
const state = {
|
||||
matches: jest.fn(() => true),
|
||||
context: {},
|
||||
} as any;
|
||||
|
||||
expect(selectIsSharingVP(state)).toBe(true);
|
||||
expect(state.matches).toHaveBeenCalledWith('sendingVP');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsShowLoadingScreen', () => {
|
||||
it('should return showLoadingScreen from context', () => {
|
||||
const state = {
|
||||
context: {
|
||||
showLoadingScreen: true,
|
||||
},
|
||||
} as any;
|
||||
|
||||
expect(selectIsShowLoadingScreen(state)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectCredentials', () => {
|
||||
it('should return empty array when selectedVCs is empty', () => {
|
||||
const state = {
|
||||
context: {
|
||||
selectedVCs: {},
|
||||
},
|
||||
} as any;
|
||||
|
||||
expect(selectCredentials(state)).toEqual([]);
|
||||
});
|
||||
|
||||
it('should process and return credentials from selectedVCs', () => {
|
||||
const mockCredential = {data: 'test'};
|
||||
const state = {
|
||||
context: {
|
||||
selectedVCs: {
|
||||
key1: {
|
||||
inner1: [
|
||||
{
|
||||
verifiableCredential: {
|
||||
credential: mockCredential,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
} as any;
|
||||
|
||||
const result = selectCredentials(state);
|
||||
expect(result).toEqual([mockCredential]);
|
||||
});
|
||||
|
||||
it('should handle credentials without nested credential property', () => {
|
||||
const mockCredential = {data: 'test'};
|
||||
const state = {
|
||||
context: {
|
||||
selectedVCs: {
|
||||
key1: {
|
||||
inner1: [
|
||||
{
|
||||
verifiableCredential: mockCredential,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
} as any;
|
||||
|
||||
const result = selectCredentials(state);
|
||||
expect(result).toEqual([mockCredential]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectVerifiableCredentialsData', () => {
|
||||
it('should return empty array when no selectedVCs', () => {
|
||||
const state = {
|
||||
context: {
|
||||
selectedVCs: {},
|
||||
},
|
||||
} as any;
|
||||
|
||||
expect(selectVerifiableCredentialsData(state)).toEqual([]);
|
||||
});
|
||||
|
||||
it('should process and return verifiable credentials data', () => {
|
||||
const state = {
|
||||
context: {
|
||||
selectedVCs: {
|
||||
key1: {
|
||||
inner1: [
|
||||
{
|
||||
vcMetadata: {
|
||||
issuer: 'TestIssuer',
|
||||
},
|
||||
verifiableCredential: {
|
||||
issuerLogo: 'logo.png',
|
||||
wellKnown: 'wellknown',
|
||||
credentialTypes: ['type1'],
|
||||
credential: {
|
||||
credentialSubject: {
|
||||
face: 'faceData',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
} as any;
|
||||
|
||||
const result = selectVerifiableCredentialsData(state);
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].issuer).toBe('TestIssuer');
|
||||
expect(result[0].face).toBe('faceData');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectPurpose', () => {
|
||||
it('should return purpose from context', () => {
|
||||
const state = {
|
||||
context: {
|
||||
purpose: 'verification',
|
||||
},
|
||||
} as any;
|
||||
|
||||
expect(selectPurpose(state)).toBe('verification');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectShowConfirmationPopup', () => {
|
||||
it('should return true when in showConfirmationPopup state', () => {
|
||||
const state = {
|
||||
matches: jest.fn(() => true),
|
||||
context: {},
|
||||
} as any;
|
||||
|
||||
expect(selectShowConfirmationPopup(state)).toBe(true);
|
||||
expect(state.matches).toHaveBeenCalledWith('showConfirmationPopup');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsSelectingVcs', () => {
|
||||
it('should return true when in selectingVCs state', () => {
|
||||
const state = {
|
||||
matches: jest.fn(() => true),
|
||||
context: {},
|
||||
} as any;
|
||||
|
||||
expect(selectIsSelectingVcs(state)).toBe(true);
|
||||
expect(state.matches).toHaveBeenCalledWith('selectingVCs');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsError', () => {
|
||||
it('should return error from context', () => {
|
||||
const mockError = new Error('Test error');
|
||||
const state = {
|
||||
context: {
|
||||
error: mockError,
|
||||
},
|
||||
} as any;
|
||||
|
||||
expect(selectIsError(state)).toBe(mockError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectOpenID4VPRetryCount', () => {
|
||||
it('should return openID4VPRetryCount from context', () => {
|
||||
const state = {
|
||||
context: {
|
||||
openID4VPRetryCount: 3,
|
||||
},
|
||||
} as any;
|
||||
|
||||
expect(selectOpenID4VPRetryCount(state)).toBe(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsOVPViaDeeplink', () => {
|
||||
it('should return isOVPViaDeepLink from context', () => {
|
||||
const state = {
|
||||
context: {
|
||||
isOVPViaDeepLink: true,
|
||||
},
|
||||
} as any;
|
||||
|
||||
expect(selectIsOVPViaDeeplink(state)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectIsFaceVerifiedInVPSharing', () => {
|
||||
it('should return true when in sendingVP state and banner shown', () => {
|
||||
const state = {
|
||||
matches: jest.fn(() => true),
|
||||
context: {
|
||||
showFaceCaptureSuccessBanner: true,
|
||||
},
|
||||
} as any;
|
||||
|
||||
expect(selectIsFaceVerifiedInVPSharing(state)).toBe(true);
|
||||
expect(state.matches).toHaveBeenCalledWith('sendingVP');
|
||||
});
|
||||
|
||||
it('should return false when not in sendingVP state', () => {
|
||||
const state = {
|
||||
matches: jest.fn(() => false),
|
||||
context: {
|
||||
showFaceCaptureSuccessBanner: true,
|
||||
},
|
||||
} as any;
|
||||
|
||||
expect(selectIsFaceVerifiedInVPSharing(state)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectVerifierNameInVPSharing', () => {
|
||||
it('should return client_name from client_metadata', () => {
|
||||
const state = {
|
||||
context: {
|
||||
authenticationResponse: {
|
||||
client_metadata: {
|
||||
client_name: 'TestVerifier',
|
||||
},
|
||||
},
|
||||
},
|
||||
} as any;
|
||||
|
||||
expect(selectVerifierNameInVPSharing(state)).toBe('TestVerifier');
|
||||
});
|
||||
|
||||
it('should return client_id when client_name not available', () => {
|
||||
const state = {
|
||||
context: {
|
||||
authenticationResponse: {
|
||||
client_id: 'verifier123',
|
||||
},
|
||||
},
|
||||
} as any;
|
||||
|
||||
expect(selectVerifierNameInVPSharing(state)).toBe('verifier123');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectRequestedClaimsByVerifier', () => {
|
||||
it('should return requestedClaims from context', () => {
|
||||
const mockClaims = ['name', 'age'];
|
||||
const state = {
|
||||
context: {
|
||||
requestedClaims: mockClaims,
|
||||
},
|
||||
} as any;
|
||||
|
||||
expect(selectRequestedClaimsByVerifier(state)).toEqual(mockClaims);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectshowTrustConsentModal', () => {
|
||||
it('should return showTrustConsentModal from context', () => {
|
||||
const state = {
|
||||
context: {
|
||||
showTrustConsentModal: true,
|
||||
},
|
||||
} as any;
|
||||
|
||||
expect(selectshowTrustConsentModal(state)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectVerifierNameInTrustModal', () => {
|
||||
it('should return client_name from client_metadata', () => {
|
||||
const state = {
|
||||
context: {
|
||||
authenticationResponse: {
|
||||
client_metadata: {
|
||||
client_name: 'TrustedVerifier',
|
||||
},
|
||||
},
|
||||
},
|
||||
} as any;
|
||||
|
||||
expect(selectVerifierNameInTrustModal(state)).toBe('TrustedVerifier');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectVerifierLogoInTrustModal', () => {
|
||||
it('should return logo_uri from client_metadata', () => {
|
||||
const state = {
|
||||
context: {
|
||||
authenticationResponse: {
|
||||
client_metadata: {
|
||||
logo_uri: 'https://example.com/logo.png',
|
||||
},
|
||||
},
|
||||
},
|
||||
} as any;
|
||||
|
||||
expect(selectVerifierLogoInTrustModal(state)).toBe(
|
||||
'https://example.com/logo.png',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectCredentials', () => {
|
||||
it('should return array of credentials from selectedVCs', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
selectedVCs: {
|
||||
type1: {
|
||||
vc1: {
|
||||
verifiableCredential: {
|
||||
credential: {id: 'cred-1', name: 'John'},
|
||||
},
|
||||
},
|
||||
},
|
||||
type2: {
|
||||
vc2: {
|
||||
verifiableCredential: {id: 'cred-2', name: 'Jane'},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const result: any = selectCredentials(mockState);
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
expect(result.length).toBe(2);
|
||||
});
|
||||
|
||||
it('should handle verifiableCredential without credential property', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
selectedVCs: {
|
||||
type1: {
|
||||
vc1: {
|
||||
verifiableCredential: {id: 'direct-vc', name: 'Direct'},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const result: any = selectCredentials(mockState);
|
||||
expect(result.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should return undefined when no credentials selected', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
selectedVCs: {},
|
||||
},
|
||||
};
|
||||
|
||||
const result: any = selectCredentials(mockState);
|
||||
expect(Array.isArray(result) ? result.length : result).toBe(0);
|
||||
});
|
||||
|
||||
it('should flatten nested credential structures', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
selectedVCs: {
|
||||
type1: {
|
||||
vc1: {verifiableCredential: {credential: {id: '1'}}},
|
||||
vc2: {verifiableCredential: {credential: {id: '2'}}},
|
||||
},
|
||||
type2: {
|
||||
vc3: {verifiableCredential: {credential: {id: '3'}}},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const result: any = selectCredentials(mockState);
|
||||
expect(result.length).toBe(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectVerifiableCredentialsData', () => {
|
||||
it('should return array of formatted verifiable credential data', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
selectedVCs: {
|
||||
type1: {
|
||||
vc1: {
|
||||
vcMetadata: {
|
||||
id: 'vc-001',
|
||||
issuer: 'Test Issuer',
|
||||
},
|
||||
verifiableCredential: {
|
||||
issuerLogo: 'https://example.com/logo.png',
|
||||
wellKnown: 'https://example.com/.well-known',
|
||||
credentialTypes: ['VerifiableCredential', 'NationalID'],
|
||||
credential: {
|
||||
credentialSubject: {
|
||||
face: 'base64-image-data',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const result = selectVerifiableCredentialsData(mockState);
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
expect(result.length).toBe(1);
|
||||
expect(result[0].issuer).toBe('Test Issuer');
|
||||
expect(result[0].issuerLogo).toBe('https://example.com/logo.png');
|
||||
expect(result[0].wellKnown).toBe('https://example.com/.well-known');
|
||||
});
|
||||
|
||||
it('should use getMosipLogo when issuerLogo is not available', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
selectedVCs: {
|
||||
type1: {
|
||||
vc1: {
|
||||
vcMetadata: {
|
||||
id: 'vc-002',
|
||||
issuer: 'Mosip',
|
||||
},
|
||||
verifiableCredential: {
|
||||
credential: {
|
||||
credentialSubject: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const result = selectVerifiableCredentialsData(mockState);
|
||||
expect(result[0].issuerLogo).toBeDefined();
|
||||
});
|
||||
|
||||
it('should handle face from credential.biometrics.face', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
selectedVCs: {
|
||||
type1: {
|
||||
vc1: {
|
||||
vcMetadata: {
|
||||
id: 'vc-003',
|
||||
issuer: 'Issuer',
|
||||
},
|
||||
credential: {
|
||||
biometrics: {
|
||||
face: 'biometric-face-data',
|
||||
},
|
||||
},
|
||||
verifiableCredential: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const result = selectVerifiableCredentialsData(mockState);
|
||||
expect(result[0].face).toBe('biometric-face-data');
|
||||
});
|
||||
|
||||
it('should handle empty selectedVCs', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
selectedVCs: {},
|
||||
},
|
||||
};
|
||||
|
||||
const result = selectVerifiableCredentialsData(mockState);
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
it('should handle multiple VCs from different types', () => {
|
||||
const mockState: any = {
|
||||
context: {
|
||||
selectedVCs: {
|
||||
type1: {
|
||||
vc1: {
|
||||
vcMetadata: {id: '1', issuer: 'Issuer1'},
|
||||
verifiableCredential: {},
|
||||
},
|
||||
},
|
||||
type2: {
|
||||
vc2: {
|
||||
vcMetadata: {id: '2', issuer: 'Issuer2'},
|
||||
verifiableCredential: {},
|
||||
},
|
||||
vc3: {
|
||||
vcMetadata: {id: '3', issuer: 'Issuer3'},
|
||||
verifiableCredential: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const result = selectVerifiableCredentialsData(mockState);
|
||||
expect(result.length).toBe(3);
|
||||
expect(result[0].issuer).toBe('Issuer1');
|
||||
expect(result[1].issuer).toBe('Issuer2');
|
||||
expect(result[2].issuer).toBe('Issuer3');
|
||||
});
|
||||
});
|
||||
});
|
||||
139
routes/routesConstants.test.ts
Normal file
139
routes/routesConstants.test.ts
Normal file
@@ -0,0 +1,139 @@
|
||||
import {
|
||||
BOTTOM_TAB_ROUTES,
|
||||
SCAN_ROUTES,
|
||||
REQUEST_ROUTES,
|
||||
SETTINGS_ROUTES,
|
||||
AUTH_ROUTES,
|
||||
} from './routesConstants';
|
||||
|
||||
describe('routesConstants', () => {
|
||||
describe('BOTTOM_TAB_ROUTES', () => {
|
||||
it('should be defined', () => {
|
||||
expect(BOTTOM_TAB_ROUTES).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have home route', () => {
|
||||
expect(BOTTOM_TAB_ROUTES.home).toBe('home');
|
||||
});
|
||||
|
||||
it('should have share route', () => {
|
||||
expect(BOTTOM_TAB_ROUTES.share).toBe('share');
|
||||
});
|
||||
|
||||
it('should have history route', () => {
|
||||
expect(BOTTOM_TAB_ROUTES.history).toBe('history');
|
||||
});
|
||||
|
||||
it('should have settings route', () => {
|
||||
expect(BOTTOM_TAB_ROUTES.settings).toBe('settings');
|
||||
});
|
||||
|
||||
it('should have exactly 4 routes', () => {
|
||||
expect(Object.keys(BOTTOM_TAB_ROUTES)).toHaveLength(4);
|
||||
});
|
||||
});
|
||||
|
||||
describe('SCAN_ROUTES', () => {
|
||||
it('should be defined', () => {
|
||||
expect(SCAN_ROUTES).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have ScanScreen route', () => {
|
||||
expect(SCAN_ROUTES.ScanScreen).toBe('ScanScreen');
|
||||
});
|
||||
|
||||
it('should have SendVcScreen route', () => {
|
||||
expect(SCAN_ROUTES.SendVcScreen).toBe('SendVcScreen');
|
||||
});
|
||||
|
||||
it('should have SendVPScreen route', () => {
|
||||
expect(SCAN_ROUTES.SendVPScreen).toBe('SendVPScreen');
|
||||
});
|
||||
|
||||
it('should have exactly 3 routes', () => {
|
||||
expect(Object.keys(SCAN_ROUTES)).toHaveLength(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('REQUEST_ROUTES', () => {
|
||||
it('should be defined', () => {
|
||||
expect(REQUEST_ROUTES).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have Request route', () => {
|
||||
expect(REQUEST_ROUTES.Request).toBe('Request');
|
||||
});
|
||||
|
||||
it('should have RequestScreen route', () => {
|
||||
expect(REQUEST_ROUTES.RequestScreen).toBe('RequestScreen');
|
||||
});
|
||||
|
||||
it('should have ReceiveVcScreen route', () => {
|
||||
expect(REQUEST_ROUTES.ReceiveVcScreen).toBe('ReceiveVcScreen');
|
||||
});
|
||||
|
||||
it('should have exactly 3 routes', () => {
|
||||
expect(Object.keys(REQUEST_ROUTES)).toHaveLength(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('SETTINGS_ROUTES', () => {
|
||||
it('should be defined', () => {
|
||||
expect(SETTINGS_ROUTES).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have KeyManagement route', () => {
|
||||
expect(SETTINGS_ROUTES.KeyManagement).toBe('KeyManagement');
|
||||
});
|
||||
|
||||
it('should have exactly 1 route', () => {
|
||||
expect(Object.keys(SETTINGS_ROUTES)).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('AUTH_ROUTES', () => {
|
||||
it('should be defined', () => {
|
||||
expect(AUTH_ROUTES).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have AuthView route', () => {
|
||||
expect(AUTH_ROUTES.AuthView).toBe('AuthView');
|
||||
});
|
||||
|
||||
it('should have exactly 1 route', () => {
|
||||
expect(Object.keys(AUTH_ROUTES)).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Route constants structure', () => {
|
||||
it('all BOTTOM_TAB_ROUTES values should be strings', () => {
|
||||
Object.values(BOTTOM_TAB_ROUTES).forEach(route => {
|
||||
expect(typeof route).toBe('string');
|
||||
});
|
||||
});
|
||||
|
||||
it('all SCAN_ROUTES values should be strings', () => {
|
||||
Object.values(SCAN_ROUTES).forEach(route => {
|
||||
expect(typeof route).toBe('string');
|
||||
});
|
||||
});
|
||||
|
||||
it('all REQUEST_ROUTES values should be strings', () => {
|
||||
Object.values(REQUEST_ROUTES).forEach(route => {
|
||||
expect(typeof route).toBe('string');
|
||||
});
|
||||
});
|
||||
|
||||
it('all SETTINGS_ROUTES values should be strings', () => {
|
||||
Object.values(SETTINGS_ROUTES).forEach(route => {
|
||||
expect(typeof route).toBe('string');
|
||||
});
|
||||
});
|
||||
|
||||
it('all AUTH_ROUTES values should be strings', () => {
|
||||
Object.values(AUTH_ROUTES).forEach(route => {
|
||||
expect(typeof route).toBe('string');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
405
shared/Utils.test.ts
Normal file
405
shared/Utils.test.ts
Normal file
@@ -0,0 +1,405 @@
|
||||
import {
|
||||
getVCsOrderedByPinStatus,
|
||||
VCShareFlowType,
|
||||
VCItemContainerFlowType,
|
||||
CameraPosition,
|
||||
isMosipVC,
|
||||
parseJSON,
|
||||
isNetworkError,
|
||||
UUID,
|
||||
formatTextWithGivenLimit,
|
||||
DEEPLINK_FLOWS,
|
||||
base64ToByteArray,
|
||||
createCacheObject,
|
||||
isCacheExpired,
|
||||
getVerifierKey,
|
||||
} from './Utils';
|
||||
import {VCMetadata} from './VCMetadata';
|
||||
|
||||
describe('getVCsOrderedByPinStatus', () => {
|
||||
it('should be defined', () => {
|
||||
expect(getVCsOrderedByPinStatus).toBeDefined();
|
||||
});
|
||||
|
||||
it('should return pinned VCs first', () => {
|
||||
const vcMetadatas = [
|
||||
new VCMetadata({id: '1', isPinned: false}),
|
||||
new VCMetadata({id: '2', isPinned: true}),
|
||||
new VCMetadata({id: '3', isPinned: false}),
|
||||
new VCMetadata({id: '4', isPinned: true}),
|
||||
];
|
||||
|
||||
const result = getVCsOrderedByPinStatus(vcMetadatas);
|
||||
|
||||
expect(result[0].isPinned).toBe(true);
|
||||
expect(result[1].isPinned).toBe(true);
|
||||
expect(result[2].isPinned).toBe(false);
|
||||
expect(result[3].isPinned).toBe(false);
|
||||
});
|
||||
|
||||
it('should handle empty array', () => {
|
||||
const result = getVCsOrderedByPinStatus([]);
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
it('should handle all pinned VCs', () => {
|
||||
const vcMetadatas = [
|
||||
new VCMetadata({id: '1', isPinned: true}),
|
||||
new VCMetadata({id: '2', isPinned: true}),
|
||||
];
|
||||
|
||||
const result = getVCsOrderedByPinStatus(vcMetadatas);
|
||||
expect(result.every(vc => vc.isPinned)).toBe(true);
|
||||
});
|
||||
|
||||
it('should handle all unpinned VCs', () => {
|
||||
const vcMetadatas = [
|
||||
new VCMetadata({id: '1', isPinned: false}),
|
||||
new VCMetadata({id: '2', isPinned: false}),
|
||||
];
|
||||
|
||||
const result = getVCsOrderedByPinStatus(vcMetadatas);
|
||||
expect(result.every(vc => !vc.isPinned)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('VCShareFlowType enum', () => {
|
||||
it('should have SIMPLE_SHARE defined', () => {
|
||||
expect(VCShareFlowType.SIMPLE_SHARE).toBe('simple share');
|
||||
});
|
||||
|
||||
it('should have MINI_VIEW_SHARE defined', () => {
|
||||
expect(VCShareFlowType.MINI_VIEW_SHARE).toBe('mini view share');
|
||||
});
|
||||
|
||||
it('should have MINI_VIEW_SHARE_WITH_SELFIE defined', () => {
|
||||
expect(VCShareFlowType.MINI_VIEW_SHARE_WITH_SELFIE).toBe(
|
||||
'mini view share with selfie',
|
||||
);
|
||||
});
|
||||
|
||||
it('should have MINI_VIEW_QR_LOGIN defined', () => {
|
||||
expect(VCShareFlowType.MINI_VIEW_QR_LOGIN).toBe('mini view qr login');
|
||||
});
|
||||
|
||||
it('should have OPENID4VP defined', () => {
|
||||
expect(VCShareFlowType.OPENID4VP).toBe('OpenID4VP');
|
||||
});
|
||||
|
||||
it('should have MINI_VIEW_SHARE_OPENID4VP defined', () => {
|
||||
expect(VCShareFlowType.MINI_VIEW_SHARE_OPENID4VP).toBe(
|
||||
'OpenID4VP share from mini view',
|
||||
);
|
||||
});
|
||||
|
||||
it('should have MINI_VIEW_SHARE_WITH_SELFIE_OPENID4VP defined', () => {
|
||||
expect(VCShareFlowType.MINI_VIEW_SHARE_WITH_SELFIE_OPENID4VP).toBe(
|
||||
'OpenID4VP share with selfie from mini view',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('VCItemContainerFlowType enum', () => {
|
||||
it('should have QR_LOGIN defined', () => {
|
||||
expect(VCItemContainerFlowType.QR_LOGIN).toBe('qr login');
|
||||
});
|
||||
|
||||
it('should have VC_SHARE defined', () => {
|
||||
expect(VCItemContainerFlowType.VC_SHARE).toBe('vc share');
|
||||
});
|
||||
|
||||
it('should have VP_SHARE defined', () => {
|
||||
expect(VCItemContainerFlowType.VP_SHARE).toBe('vp share');
|
||||
});
|
||||
});
|
||||
|
||||
describe('CameraPosition enum', () => {
|
||||
it('should have FRONT defined', () => {
|
||||
expect(CameraPosition.FRONT).toBe('front');
|
||||
});
|
||||
|
||||
it('should have BACK defined', () => {
|
||||
expect(CameraPosition.BACK).toBe('back');
|
||||
});
|
||||
});
|
||||
|
||||
describe('isMosipVC', () => {
|
||||
it('should be defined', () => {
|
||||
expect(isMosipVC).toBeDefined();
|
||||
});
|
||||
|
||||
it('should return true for Mosip issuer', () => {
|
||||
const result = isMosipVC('Mosip');
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true for MosipOtp issuer', () => {
|
||||
const result = isMosipVC('MosipOtp');
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for other issuers', () => {
|
||||
expect(isMosipVC('SomeOtherIssuer')).toBe(false);
|
||||
expect(isMosipVC('')).toBe(false);
|
||||
expect(isMosipVC('mosip')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseJSON', () => {
|
||||
it('should be defined', () => {
|
||||
expect(parseJSON).toBeDefined();
|
||||
});
|
||||
|
||||
it('should parse valid JSON string', () => {
|
||||
const jsonStr = '{"key": "value"}';
|
||||
const result = parseJSON(jsonStr);
|
||||
expect(result).toEqual({key: 'value'});
|
||||
});
|
||||
|
||||
it('should handle object input', () => {
|
||||
const obj = {key: 'value'};
|
||||
const result = parseJSON(obj);
|
||||
expect(result).toEqual({key: 'value'});
|
||||
});
|
||||
|
||||
it('should handle invalid JSON gracefully', () => {
|
||||
const invalidJson = '{invalid json}';
|
||||
const result = parseJSON(invalidJson);
|
||||
expect(result).toBeDefined();
|
||||
});
|
||||
|
||||
it('should handle nested objects', () => {
|
||||
const jsonStr = '{"key": {"nested": "value"}}';
|
||||
const result = parseJSON(jsonStr);
|
||||
expect(result.key.nested).toBe('value');
|
||||
});
|
||||
});
|
||||
|
||||
describe('isNetworkError', () => {
|
||||
it('should be defined', () => {
|
||||
expect(isNetworkError).toBeDefined();
|
||||
});
|
||||
|
||||
it('should return true for network request failed error', () => {
|
||||
const error = 'Network request failed';
|
||||
expect(isNetworkError(error)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for other errors', () => {
|
||||
expect(isNetworkError('Some other error')).toBe(false);
|
||||
expect(isNetworkError('')).toBe(false);
|
||||
});
|
||||
|
||||
it('should handle partial matches', () => {
|
||||
const error = 'Error: Network request failed - timeout';
|
||||
expect(isNetworkError(error)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('UUID', () => {
|
||||
it('should be defined', () => {
|
||||
expect(UUID).toBeDefined();
|
||||
});
|
||||
|
||||
it('should generate a valid UUID', () => {
|
||||
const uuid = UUID.generate();
|
||||
expect(uuid).toBeDefined();
|
||||
expect(typeof uuid).toBe('string');
|
||||
expect(uuid.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('should generate unique UUIDs', () => {
|
||||
const uuid1 = UUID.generate();
|
||||
const uuid2 = UUID.generate();
|
||||
expect(uuid1).not.toBe(uuid2);
|
||||
});
|
||||
|
||||
it('should match UUID format', () => {
|
||||
const uuid = UUID.generate();
|
||||
const uuidRegex =
|
||||
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
||||
expect(uuidRegex.test(uuid)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('formatTextWithGivenLimit', () => {
|
||||
it('should be defined', () => {
|
||||
expect(formatTextWithGivenLimit).toBeDefined();
|
||||
});
|
||||
|
||||
it('should truncate text longer than limit', () => {
|
||||
const text = 'This is a very long text';
|
||||
const result = formatTextWithGivenLimit(text, 10);
|
||||
expect(result).toBe('This is a ...');
|
||||
});
|
||||
|
||||
it('should return text as is if shorter than limit', () => {
|
||||
const text = 'Short text';
|
||||
const result = formatTextWithGivenLimit(text, 15);
|
||||
expect(result).toBe('Short text');
|
||||
});
|
||||
|
||||
it('should use default limit of 15 if not provided', () => {
|
||||
const text = 'This is a longer text than 15 characters';
|
||||
const result = formatTextWithGivenLimit(text);
|
||||
expect(result).toBe('This is a longe...');
|
||||
});
|
||||
|
||||
it('should handle empty string', () => {
|
||||
const result = formatTextWithGivenLimit('', 10);
|
||||
expect(result).toBe('');
|
||||
});
|
||||
|
||||
it('should handle exact limit length', () => {
|
||||
const text = 'Exactly 10';
|
||||
const result = formatTextWithGivenLimit(text, 10);
|
||||
expect(result).toBe('Exactly 10');
|
||||
});
|
||||
});
|
||||
|
||||
describe('DEEPLINK_FLOWS enum', () => {
|
||||
it('should have QR_LOGIN defined', () => {
|
||||
expect(DEEPLINK_FLOWS.QR_LOGIN).toBe('qrLoginFlow');
|
||||
});
|
||||
|
||||
it('should have OVP defined', () => {
|
||||
expect(DEEPLINK_FLOWS.OVP).toBe('ovpFlow');
|
||||
});
|
||||
});
|
||||
|
||||
describe('base64ToByteArray', () => {
|
||||
it('should be defined', () => {
|
||||
expect(base64ToByteArray).toBeDefined();
|
||||
});
|
||||
|
||||
it('should convert base64 string to byte array', () => {
|
||||
const base64 = 'SGVsbG8gV29ybGQ='; // "Hello World"
|
||||
const result = base64ToByteArray(base64);
|
||||
expect(result).toBeInstanceOf(Uint8Array);
|
||||
expect(result.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('should handle base64url encoding', () => {
|
||||
const base64url = 'SGVsbG8gV29ybGQ'; // without padding
|
||||
const result = base64ToByteArray(base64url);
|
||||
expect(result).toBeInstanceOf(Uint8Array);
|
||||
});
|
||||
|
||||
it('should throw error for invalid base64', () => {
|
||||
expect(() => {
|
||||
base64ToByteArray('!!!invalid base64!!!');
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
it('should handle strings with whitespace', () => {
|
||||
const base64 = ' SGVsbG8gV29ybGQ= ';
|
||||
const result = base64ToByteArray(base64);
|
||||
expect(result).toBeInstanceOf(Uint8Array);
|
||||
});
|
||||
|
||||
it('should handle URL-safe base64 characters', () => {
|
||||
const base64 = 'SGVsbG8tV29ybGQ_'; // with - and _
|
||||
const result = base64ToByteArray(base64);
|
||||
expect(result).toBeInstanceOf(Uint8Array);
|
||||
});
|
||||
|
||||
it('should handle empty string', () => {
|
||||
const result = base64ToByteArray('');
|
||||
expect(result).toBeInstanceOf(Uint8Array);
|
||||
expect(result.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('createCacheObject', () => {
|
||||
it('should create cache object with response and timestamp', () => {
|
||||
const response = {data: 'test data'};
|
||||
const result = createCacheObject(response);
|
||||
|
||||
expect(result).toHaveProperty('response');
|
||||
expect(result).toHaveProperty('cachedTime');
|
||||
expect(result.response).toBe(response);
|
||||
expect(typeof result.cachedTime).toBe('number');
|
||||
});
|
||||
|
||||
it('should use current timestamp', () => {
|
||||
const before = Date.now();
|
||||
const result = createCacheObject({});
|
||||
const after = Date.now();
|
||||
|
||||
expect(result.cachedTime).toBeGreaterThanOrEqual(before);
|
||||
expect(result.cachedTime).toBeLessThanOrEqual(after);
|
||||
});
|
||||
|
||||
it('should handle null response', () => {
|
||||
const result = createCacheObject(null);
|
||||
expect(result.response).toBeNull();
|
||||
expect(result.cachedTime).toBeDefined();
|
||||
});
|
||||
|
||||
it('should handle complex objects', () => {
|
||||
const complexResponse = {
|
||||
data: [1, 2, 3],
|
||||
metadata: {key: 'value'},
|
||||
nested: {deep: {value: true}},
|
||||
};
|
||||
const result = createCacheObject(complexResponse);
|
||||
expect(result.response).toBe(complexResponse);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isCacheExpired', () => {
|
||||
it('should return false for recent timestamp', () => {
|
||||
const recentTimestamp = Date.now() - 1000; // 1 second ago
|
||||
expect(isCacheExpired(recentTimestamp)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true for old timestamp', () => {
|
||||
const oldTimestamp = Date.now() - (60 * 60 * 1000 + 1000); // Over 1 hour ago
|
||||
expect(isCacheExpired(oldTimestamp)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for current timestamp', () => {
|
||||
const currentTimestamp = Date.now();
|
||||
expect(isCacheExpired(currentTimestamp)).toBe(false);
|
||||
});
|
||||
|
||||
it('should handle edge case at exact TTL boundary', () => {
|
||||
const boundaryTimestamp = Date.now() - 60 * 60 * 1000; // Exactly 1 hour ago
|
||||
const result = isCacheExpired(boundaryTimestamp);
|
||||
expect(typeof result).toBe('boolean');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getVerifierKey', () => {
|
||||
it('should create verifier key with prefix', () => {
|
||||
const verifier = 'example.com';
|
||||
const result = getVerifierKey(verifier);
|
||||
expect(result).toBe('trusted_verifier_example.com');
|
||||
});
|
||||
|
||||
it('should handle empty string', () => {
|
||||
const result = getVerifierKey('');
|
||||
expect(result).toBe('trusted_verifier_');
|
||||
});
|
||||
|
||||
it('should preserve verifier name exactly', () => {
|
||||
const verifier = 'TestVerifier123';
|
||||
const result = getVerifierKey(verifier);
|
||||
expect(result).toBe('trusted_verifier_TestVerifier123');
|
||||
});
|
||||
|
||||
it('should handle special characters', () => {
|
||||
const verifier = 'verifier-with-dashes_and_underscores';
|
||||
const result = getVerifierKey(verifier);
|
||||
expect(result).toBe(
|
||||
'trusted_verifier_verifier-with-dashes_and_underscores',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('canonicalize', () => {
|
||||
it('should be defined', async () => {
|
||||
const {canonicalize} = await import('./Utils');
|
||||
expect(canonicalize).toBeDefined();
|
||||
});
|
||||
});
|
||||
37
shared/VCFormat.test.ts
Normal file
37
shared/VCFormat.test.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import {VCFormat} from './VCFormat';
|
||||
|
||||
describe('VCFormat', () => {
|
||||
it('should have ldp_vc format', () => {
|
||||
expect(VCFormat.ldp_vc).toBe('ldp_vc');
|
||||
});
|
||||
|
||||
it('should have mso_mdoc format', () => {
|
||||
expect(VCFormat.mso_mdoc).toBe('mso_mdoc');
|
||||
});
|
||||
|
||||
it('should have vc_sd_jwt format', () => {
|
||||
expect(VCFormat.vc_sd_jwt).toBe('vc+sd-jwt');
|
||||
});
|
||||
|
||||
it('should have dc_sd_jwt format', () => {
|
||||
expect(VCFormat.dc_sd_jwt).toBe('dc+sd-jwt');
|
||||
});
|
||||
|
||||
it('should have exactly 4 formats', () => {
|
||||
const formatCount = Object.keys(VCFormat).length;
|
||||
expect(formatCount).toBe(4);
|
||||
});
|
||||
|
||||
it('should allow access via enum key', () => {
|
||||
expect(VCFormat['ldp_vc']).toBe('ldp_vc');
|
||||
expect(VCFormat['mso_mdoc']).toBe('mso_mdoc');
|
||||
expect(VCFormat['vc_sd_jwt']).toBe('vc+sd-jwt');
|
||||
expect(VCFormat['dc_sd_jwt']).toBe('dc+sd-jwt');
|
||||
});
|
||||
|
||||
it('should have all unique values', () => {
|
||||
const values = Object.values(VCFormat);
|
||||
const uniqueValues = new Set(values);
|
||||
expect(uniqueValues.size).toBe(values.length);
|
||||
});
|
||||
});
|
||||
499
shared/VCMetadata.test.ts
Normal file
499
shared/VCMetadata.test.ts
Normal file
@@ -0,0 +1,499 @@
|
||||
import {VCMetadata, parseMetadatas, getVCMetadata} from './VCMetadata';
|
||||
import {VCFormat} from './VCFormat';
|
||||
import {UUID} from './Utils';
|
||||
|
||||
describe('VCMetadata', () => {
|
||||
describe('constructor', () => {
|
||||
it('should create instance with default values', () => {
|
||||
const metadata = new VCMetadata();
|
||||
|
||||
expect(metadata.idType).toBe('');
|
||||
expect(metadata.requestId).toBe('');
|
||||
expect(metadata.isPinned).toBe(false);
|
||||
expect(metadata.id).toBe('');
|
||||
expect(metadata.issuer).toBe('');
|
||||
expect(metadata.protocol).toBe('');
|
||||
expect(metadata.timestamp).toBe('');
|
||||
expect(metadata.isVerified).toBe(false);
|
||||
expect(metadata.mosipIndividualId).toBe('');
|
||||
expect(metadata.format).toBe('');
|
||||
expect(metadata.isExpired).toBe(false);
|
||||
});
|
||||
|
||||
it('should create instance with provided values', () => {
|
||||
const metadata = new VCMetadata({
|
||||
idType: 'UIN',
|
||||
requestId: 'req123',
|
||||
isPinned: true,
|
||||
id: 'id123',
|
||||
issuer: 'TestIssuer',
|
||||
protocol: 'OpenId4VCI',
|
||||
timestamp: '2024-01-01',
|
||||
isVerified: true,
|
||||
mosipIndividualId: 'mosip123',
|
||||
format: 'ldp_vc',
|
||||
downloadKeyType: 'ED25519',
|
||||
isExpired: false,
|
||||
credentialType: 'NationalID',
|
||||
issuerHost: 'https://test.com',
|
||||
});
|
||||
|
||||
expect(metadata.idType).toBe('UIN');
|
||||
expect(metadata.requestId).toBe('req123');
|
||||
expect(metadata.isPinned).toBe(true);
|
||||
expect(metadata.id).toBe('id123');
|
||||
expect(metadata.issuer).toBe('TestIssuer');
|
||||
expect(metadata.protocol).toBe('OpenId4VCI');
|
||||
expect(metadata.timestamp).toBe('2024-01-01');
|
||||
expect(metadata.isVerified).toBe(true);
|
||||
expect(metadata.mosipIndividualId).toBe('mosip123');
|
||||
expect(metadata.format).toBe('ldp_vc');
|
||||
expect(metadata.downloadKeyType).toBe('ED25519');
|
||||
expect(metadata.isExpired).toBe(false);
|
||||
expect(metadata.credentialType).toBe('NationalID');
|
||||
expect(metadata.issuerHost).toBe('https://test.com');
|
||||
});
|
||||
});
|
||||
|
||||
describe('fromVC', () => {
|
||||
it('should create VCMetadata from VC object', () => {
|
||||
const vc = {
|
||||
idType: 'VID',
|
||||
requestId: 'req456',
|
||||
id: 'vc123',
|
||||
issuer: 'Issuer1',
|
||||
format: VCFormat.ldp_vc,
|
||||
};
|
||||
|
||||
const metadata = VCMetadata.fromVC(vc);
|
||||
|
||||
expect(metadata.idType).toBe('VID');
|
||||
expect(metadata.requestId).toBe('req456');
|
||||
expect(metadata.id).toBe('vc123');
|
||||
expect(metadata.issuer).toBe('Issuer1');
|
||||
expect(metadata.format).toBe(VCFormat.ldp_vc);
|
||||
});
|
||||
|
||||
it('should use default format if not provided', () => {
|
||||
const vc = {id: 'vc123'};
|
||||
const metadata = VCMetadata.fromVC(vc);
|
||||
|
||||
expect(metadata.format).toBe(VCFormat.ldp_vc);
|
||||
});
|
||||
|
||||
it('should handle isPinned default value', () => {
|
||||
const vc = {id: 'vc123'};
|
||||
const metadata = VCMetadata.fromVC(vc);
|
||||
|
||||
expect(metadata.isPinned).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('fromVcMetadataString', () => {
|
||||
it('should parse JSON string to VCMetadata', () => {
|
||||
const jsonStr = JSON.stringify({
|
||||
id: 'vc123',
|
||||
issuer: 'TestIssuer',
|
||||
format: 'ldp_vc',
|
||||
});
|
||||
|
||||
const metadata = VCMetadata.fromVcMetadataString(jsonStr);
|
||||
|
||||
expect(metadata.id).toBe('vc123');
|
||||
expect(metadata.issuer).toBe('TestIssuer');
|
||||
expect(metadata.format).toBe('ldp_vc');
|
||||
});
|
||||
|
||||
it('should handle object input', () => {
|
||||
const obj = {
|
||||
id: 'vc456',
|
||||
issuer: 'AnotherIssuer',
|
||||
};
|
||||
|
||||
const metadata = VCMetadata.fromVcMetadataString(obj);
|
||||
|
||||
expect(metadata.id).toBe('vc456');
|
||||
expect(metadata.issuer).toBe('AnotherIssuer');
|
||||
});
|
||||
|
||||
it('should return empty VCMetadata on parse error', () => {
|
||||
const invalidJson = '{invalid json}';
|
||||
const metadata = VCMetadata.fromVcMetadataString(invalidJson);
|
||||
|
||||
expect(metadata).toBeInstanceOf(VCMetadata);
|
||||
expect(metadata.id).toBe('');
|
||||
});
|
||||
});
|
||||
|
||||
describe('isVCKey', () => {
|
||||
it('should return true for valid VC key', () => {
|
||||
expect(VCMetadata.isVCKey('VC_1234567890_abc123')).toBe(true);
|
||||
expect(VCMetadata.isVCKey('VC_timestamp_id')).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for invalid VC key', () => {
|
||||
expect(VCMetadata.isVCKey('INVALID_KEY')).toBe(false);
|
||||
expect(VCMetadata.isVCKey('VC')).toBe(false);
|
||||
expect(VCMetadata.isVCKey('')).toBe(false);
|
||||
expect(VCMetadata.isVCKey('VC_')).toBe(false);
|
||||
});
|
||||
|
||||
it('should handle keys with special characters properly', () => {
|
||||
expect(VCMetadata.isVCKey('VC_123_abc-def')).toBe(true);
|
||||
expect(VCMetadata.isVCKey('VC_123_abc_def')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isFromOpenId4VCI', () => {
|
||||
it('should return true when protocol is OpenId4VCI', () => {
|
||||
const metadata = new VCMetadata({protocol: 'OpenId4VCI'});
|
||||
expect(metadata.isFromOpenId4VCI()).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when protocol is not OpenId4VCI', () => {
|
||||
const metadata = new VCMetadata({protocol: 'OtherProtocol'});
|
||||
expect(metadata.isFromOpenId4VCI()).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false when protocol is empty', () => {
|
||||
const metadata = new VCMetadata();
|
||||
expect(metadata.isFromOpenId4VCI()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getVcKey', () => {
|
||||
it('should generate VC key with timestamp', () => {
|
||||
const metadata = new VCMetadata({
|
||||
timestamp: '1234567890',
|
||||
id: 'abc123',
|
||||
});
|
||||
|
||||
expect(metadata.getVcKey()).toBe('VC_1234567890_abc123');
|
||||
});
|
||||
|
||||
it('should generate VC key without timestamp', () => {
|
||||
const metadata = new VCMetadata({
|
||||
timestamp: '',
|
||||
id: 'xyz789',
|
||||
});
|
||||
|
||||
expect(metadata.getVcKey()).toBe('VC_xyz789');
|
||||
});
|
||||
|
||||
it('should match the VC key regex pattern', () => {
|
||||
const metadata = new VCMetadata({
|
||||
timestamp: '1234567890',
|
||||
id: 'test-id_123',
|
||||
});
|
||||
|
||||
const key = metadata.getVcKey();
|
||||
expect(VCMetadata.isVCKey(key)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('equals', () => {
|
||||
it('should return true for equal VCMetadata instances', () => {
|
||||
const metadata1 = new VCMetadata({
|
||||
timestamp: '1234567890',
|
||||
id: 'abc123',
|
||||
});
|
||||
const metadata2 = new VCMetadata({
|
||||
timestamp: '1234567890',
|
||||
id: 'abc123',
|
||||
});
|
||||
|
||||
expect(metadata1.equals(metadata2)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for different VCMetadata instances', () => {
|
||||
const metadata1 = new VCMetadata({
|
||||
timestamp: '1234567890',
|
||||
id: 'abc123',
|
||||
});
|
||||
const metadata2 = new VCMetadata({
|
||||
timestamp: '0987654321',
|
||||
id: 'xyz789',
|
||||
});
|
||||
|
||||
expect(metadata1.equals(metadata2)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true when comparing instance with itself', () => {
|
||||
const metadata = new VCMetadata({
|
||||
timestamp: '1234567890',
|
||||
id: 'abc123',
|
||||
});
|
||||
|
||||
expect(metadata.equals(metadata)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('vcKeyRegExp', () => {
|
||||
it('should be defined as a RegExp', () => {
|
||||
expect(VCMetadata.vcKeyRegExp).toBeInstanceOf(RegExp);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseMetadatas', () => {
|
||||
it('should be defined', () => {
|
||||
expect(parseMetadatas).toBeDefined();
|
||||
});
|
||||
|
||||
it('should parse array of metadata objects', () => {
|
||||
const metadataObjects = [
|
||||
{id: 'vc1', issuer: 'Issuer1'},
|
||||
{id: 'vc2', issuer: 'Issuer2'},
|
||||
{id: 'vc3', issuer: 'Issuer3'},
|
||||
];
|
||||
|
||||
const result = parseMetadatas(metadataObjects);
|
||||
|
||||
expect(result).toHaveLength(3);
|
||||
expect(result[0]).toBeInstanceOf(VCMetadata);
|
||||
expect(result[0].id).toBe('vc1');
|
||||
expect(result[1].id).toBe('vc2');
|
||||
expect(result[2].id).toBe('vc3');
|
||||
});
|
||||
|
||||
it('should handle empty array', () => {
|
||||
const result = parseMetadatas([]);
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
it('should create VCMetadata instances for each object', () => {
|
||||
const metadataObjects = [
|
||||
{id: 'test1', format: 'ldp_vc', isPinned: true},
|
||||
{id: 'test2', format: 'mso_mdoc', isPinned: false},
|
||||
];
|
||||
|
||||
const result = parseMetadatas(metadataObjects);
|
||||
|
||||
expect(result[0].id).toBe('test1');
|
||||
expect(result[0].format).toBe('ldp_vc');
|
||||
expect(result[0].isPinned).toBe(true);
|
||||
|
||||
expect(result[1].id).toBe('test2');
|
||||
expect(result[1].format).toBe('mso_mdoc');
|
||||
expect(result[1].isPinned).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getVCMetadata', () => {
|
||||
beforeEach(() => {
|
||||
jest.spyOn(UUID, 'generate').mockReturnValue('test-uuid-12345');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('should create VCMetadata with generated credential ID', () => {
|
||||
const mockContext: any = {
|
||||
selectedIssuer: {
|
||||
credential_issuer_host: 'https://issuer.example.com',
|
||||
issuer_id: 'TestIssuer',
|
||||
protocol: 'OpenId4VCI',
|
||||
},
|
||||
timestamp: '1234567890',
|
||||
vcMetadata: {
|
||||
isVerified: false,
|
||||
isExpired: false,
|
||||
},
|
||||
verifiableCredential: null,
|
||||
credentialWrapper: {
|
||||
format: VCFormat.ldp_vc,
|
||||
},
|
||||
selectedCredentialType: null,
|
||||
};
|
||||
|
||||
const result = getVCMetadata(mockContext, 'ED25519');
|
||||
|
||||
expect(result.requestId).toContain('test-uuid-12345');
|
||||
expect(result.requestId).toContain('issuer');
|
||||
expect(result.issuer).toBe('TestIssuer');
|
||||
expect(result.protocol).toBe('OpenId4VCI');
|
||||
expect(result.timestamp).toBe('1234567890');
|
||||
expect(result.downloadKeyType).toBe('ED25519');
|
||||
expect(result.format).toBe(VCFormat.ldp_vc);
|
||||
});
|
||||
|
||||
it('should handle credential_issuer when credential_issuer_host is not available', () => {
|
||||
const mockContext: any = {
|
||||
selectedIssuer: {
|
||||
credential_issuer: 'https://backup.example.com',
|
||||
issuer_id: 'BackupIssuer',
|
||||
protocol: 'OpenId4VCI',
|
||||
},
|
||||
timestamp: '',
|
||||
vcMetadata: {},
|
||||
verifiableCredential: null,
|
||||
credentialWrapper: {
|
||||
format: VCFormat.mso_mdoc,
|
||||
},
|
||||
selectedCredentialType: null,
|
||||
};
|
||||
|
||||
const result = getVCMetadata(mockContext, 'RSA');
|
||||
|
||||
expect(result.issuer).toBe('BackupIssuer');
|
||||
expect(result.issuerHost).toBe('https://backup.example.com');
|
||||
expect(result.format).toBe(VCFormat.mso_mdoc);
|
||||
});
|
||||
|
||||
it('should use credential_issuer as fallback for issuer_id', () => {
|
||||
const mockContext: any = {
|
||||
selectedIssuer: {
|
||||
credential_issuer_host: 'https://issuer.test.com',
|
||||
credential_issuer: 'FallbackIssuer',
|
||||
protocol: 'OIDC',
|
||||
},
|
||||
timestamp: '9876543210',
|
||||
vcMetadata: {
|
||||
isVerified: true,
|
||||
isExpired: false,
|
||||
},
|
||||
verifiableCredential: null,
|
||||
credentialWrapper: {
|
||||
format: VCFormat.vc_sd_jwt,
|
||||
},
|
||||
selectedCredentialType: null,
|
||||
};
|
||||
|
||||
const result = getVCMetadata(mockContext, 'ECDSA');
|
||||
|
||||
expect(result.issuer).toBe('FallbackIssuer');
|
||||
expect(result.isVerified).toBe(true);
|
||||
expect(result.downloadKeyType).toBe('ECDSA');
|
||||
});
|
||||
|
||||
it('should extract issuer name from URL', () => {
|
||||
const mockContext: any = {
|
||||
selectedIssuer: {
|
||||
credential_issuer_host: 'https://subdomain.example.org',
|
||||
issuer_id: 'ExampleOrg',
|
||||
protocol: 'OpenId4VCI',
|
||||
},
|
||||
timestamp: '',
|
||||
vcMetadata: {},
|
||||
verifiableCredential: null,
|
||||
credentialWrapper: {format: VCFormat.ldp_vc},
|
||||
selectedCredentialType: null,
|
||||
};
|
||||
|
||||
const result = getVCMetadata(mockContext, 'ED25519');
|
||||
|
||||
expect(result.requestId).toContain('subdomain');
|
||||
});
|
||||
|
||||
it('should handle invalid URL gracefully', () => {
|
||||
const mockContext: any = {
|
||||
selectedIssuer: {
|
||||
credential_issuer_host: 'not-a-valid-url',
|
||||
issuer_id: 'TestIssuer',
|
||||
protocol: 'OpenId4VCI',
|
||||
},
|
||||
timestamp: '',
|
||||
vcMetadata: {},
|
||||
verifiableCredential: null,
|
||||
credentialWrapper: {format: VCFormat.ldp_vc},
|
||||
selectedCredentialType: null,
|
||||
};
|
||||
|
||||
const result = getVCMetadata(mockContext, 'ED25519');
|
||||
|
||||
expect(result.requestId).toContain('not-a-valid-url');
|
||||
expect(result.issuerHost).toBe('not-a-valid-url');
|
||||
});
|
||||
|
||||
it('should handle Mosip VC with UIN', () => {
|
||||
const mockContext: any = {
|
||||
selectedIssuer: {
|
||||
credential_issuer_host: 'https://mosip.example.com',
|
||||
issuer_id: 'Mosip',
|
||||
protocol: 'OpenId4VCI',
|
||||
},
|
||||
timestamp: '',
|
||||
vcMetadata: {},
|
||||
verifiableCredential: {
|
||||
credential: {
|
||||
credentialSubject: {
|
||||
UIN: '1234567890',
|
||||
},
|
||||
},
|
||||
},
|
||||
credentialWrapper: {format: VCFormat.ldp_vc},
|
||||
selectedCredentialType: null,
|
||||
};
|
||||
|
||||
const result = getVCMetadata(mockContext, 'ED25519');
|
||||
|
||||
expect(result.mosipIndividualId).toBe('1234567890');
|
||||
});
|
||||
|
||||
it('should handle Mosip VC with VID', () => {
|
||||
const mockContext: any = {
|
||||
selectedIssuer: {
|
||||
credential_issuer_host: 'https://mosip.example.com',
|
||||
issuer_id: 'Mosip',
|
||||
protocol: 'OpenId4VCI',
|
||||
},
|
||||
timestamp: '',
|
||||
vcMetadata: {},
|
||||
verifiableCredential: {
|
||||
credential: {
|
||||
credentialSubject: {
|
||||
VID: '9876543210',
|
||||
},
|
||||
},
|
||||
},
|
||||
credentialWrapper: {format: VCFormat.ldp_vc},
|
||||
selectedCredentialType: null,
|
||||
};
|
||||
|
||||
const result = getVCMetadata(mockContext, 'ED25519');
|
||||
|
||||
expect(result.mosipIndividualId).toBe('9876543210');
|
||||
});
|
||||
|
||||
it('should set credential type when provided', () => {
|
||||
const mockContext: any = {
|
||||
selectedIssuer: {
|
||||
credential_issuer_host: 'https://issuer.example.com',
|
||||
issuer_id: 'TestIssuer',
|
||||
protocol: 'OpenId4VCI',
|
||||
},
|
||||
timestamp: '1234567890',
|
||||
vcMetadata: {},
|
||||
verifiableCredential: null,
|
||||
credentialWrapper: {format: VCFormat.mso_mdoc},
|
||||
selectedCredentialType: 'org.iso.18013.5.1.mDL',
|
||||
};
|
||||
|
||||
const result = getVCMetadata(mockContext, 'RSA');
|
||||
|
||||
expect(result.credentialType).toBeDefined();
|
||||
expect(result.format).toBe(VCFormat.mso_mdoc);
|
||||
});
|
||||
|
||||
it('should handle different key types', () => {
|
||||
const mockContext: any = {
|
||||
selectedIssuer: {
|
||||
credential_issuer_host: 'https://issuer.example.com',
|
||||
issuer_id: 'TestIssuer',
|
||||
protocol: 'OpenId4VCI',
|
||||
},
|
||||
timestamp: '',
|
||||
vcMetadata: {},
|
||||
verifiableCredential: null,
|
||||
credentialWrapper: {format: VCFormat.vc_sd_jwt},
|
||||
selectedCredentialType: null,
|
||||
};
|
||||
|
||||
const resultRSA = getVCMetadata(mockContext, 'RS256');
|
||||
expect(resultRSA.downloadKeyType).toBe('RS256');
|
||||
|
||||
const resultEC = getVCMetadata(mockContext, 'ES256');
|
||||
expect(resultEC.downloadKeyType).toBe('ES256');
|
||||
});
|
||||
});
|
||||
216
shared/api.test.ts
Normal file
216
shared/api.test.ts
Normal file
@@ -0,0 +1,216 @@
|
||||
import {API_URLS} from './api';
|
||||
|
||||
describe('API_URLS configuration', () => {
|
||||
describe('trustedVerifiersList', () => {
|
||||
it('should have GET method', () => {
|
||||
expect(API_URLS.trustedVerifiersList.method).toBe('GET');
|
||||
});
|
||||
|
||||
it('should build correct URL', () => {
|
||||
expect(API_URLS.trustedVerifiersList.buildURL()).toBe(
|
||||
'/v1/mimoto/verifiers',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('issuersList', () => {
|
||||
it('should have GET method', () => {
|
||||
expect(API_URLS.issuersList.method).toBe('GET');
|
||||
});
|
||||
|
||||
it('should build correct URL', () => {
|
||||
expect(API_URLS.issuersList.buildURL()).toBe('/v1/mimoto/issuers');
|
||||
});
|
||||
});
|
||||
|
||||
describe('issuerConfig', () => {
|
||||
it('should have GET method', () => {
|
||||
expect(API_URLS.issuerConfig.method).toBe('GET');
|
||||
});
|
||||
|
||||
it('should build correct URL with issuer id', () => {
|
||||
expect(API_URLS.issuerConfig.buildURL('test-issuer')).toBe(
|
||||
'/v1/mimoto/issuers/test-issuer',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('issuerWellknownConfig', () => {
|
||||
it('should have GET method', () => {
|
||||
expect(API_URLS.issuerWellknownConfig.method).toBe('GET');
|
||||
});
|
||||
|
||||
it('should build correct URL with credential issuer', () => {
|
||||
expect(
|
||||
API_URLS.issuerWellknownConfig.buildURL('https://example.com'),
|
||||
).toBe('https://example.com/.well-known/openid-credential-issuer');
|
||||
});
|
||||
});
|
||||
|
||||
describe('authorizationServerMetadataConfig', () => {
|
||||
it('should have GET method', () => {
|
||||
expect(API_URLS.authorizationServerMetadataConfig.method).toBe('GET');
|
||||
});
|
||||
|
||||
it('should build correct URL with authorization server URL', () => {
|
||||
expect(
|
||||
API_URLS.authorizationServerMetadataConfig.buildURL(
|
||||
'https://auth.example.com',
|
||||
),
|
||||
).toBe('https://auth.example.com/.well-known/oauth-authorization-server');
|
||||
});
|
||||
});
|
||||
|
||||
describe('allProperties', () => {
|
||||
it('should have GET method', () => {
|
||||
expect(API_URLS.allProperties.method).toBe('GET');
|
||||
});
|
||||
|
||||
it('should build correct URL', () => {
|
||||
expect(API_URLS.allProperties.buildURL()).toBe(
|
||||
'/v1/mimoto/allProperties',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getIndividualId', () => {
|
||||
it('should have POST method', () => {
|
||||
expect(API_URLS.getIndividualId.method).toBe('POST');
|
||||
});
|
||||
|
||||
it('should build correct URL', () => {
|
||||
expect(API_URLS.getIndividualId.buildURL()).toBe(
|
||||
'/v1/mimoto/aid/get-individual-id',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('reqIndividualOTP', () => {
|
||||
it('should have POST method', () => {
|
||||
expect(API_URLS.reqIndividualOTP.method).toBe('POST');
|
||||
});
|
||||
|
||||
it('should build correct URL', () => {
|
||||
expect(API_URLS.reqIndividualOTP.buildURL()).toBe(
|
||||
'/v1/mimoto/req/individualId/otp',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('walletBinding', () => {
|
||||
it('should have POST method', () => {
|
||||
expect(API_URLS.walletBinding.method).toBe('POST');
|
||||
});
|
||||
|
||||
it('should build correct URL', () => {
|
||||
expect(API_URLS.walletBinding.buildURL()).toBe(
|
||||
'/v1/mimoto/wallet-binding',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('bindingOtp', () => {
|
||||
it('should have POST method', () => {
|
||||
expect(API_URLS.bindingOtp.method).toBe('POST');
|
||||
});
|
||||
|
||||
it('should build correct URL', () => {
|
||||
expect(API_URLS.bindingOtp.buildURL()).toBe('/v1/mimoto/binding-otp');
|
||||
});
|
||||
});
|
||||
|
||||
describe('requestOtp', () => {
|
||||
it('should have POST method', () => {
|
||||
expect(API_URLS.requestOtp.method).toBe('POST');
|
||||
});
|
||||
|
||||
it('should build correct URL', () => {
|
||||
expect(API_URLS.requestOtp.buildURL()).toBe('/v1/mimoto/req/otp');
|
||||
});
|
||||
});
|
||||
|
||||
describe('credentialRequest', () => {
|
||||
it('should have POST method', () => {
|
||||
expect(API_URLS.credentialRequest.method).toBe('POST');
|
||||
});
|
||||
|
||||
it('should build correct URL', () => {
|
||||
expect(API_URLS.credentialRequest.buildURL()).toBe(
|
||||
'/v1/mimoto/credentialshare/request',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('credentialStatus', () => {
|
||||
it('should have GET method', () => {
|
||||
expect(API_URLS.credentialStatus.method).toBe('GET');
|
||||
});
|
||||
|
||||
it('should build correct URL with id', () => {
|
||||
expect(API_URLS.credentialStatus.buildURL('request-123')).toBe(
|
||||
'/v1/mimoto/credentialshare/request/status/request-123',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('credentialDownload', () => {
|
||||
it('should have POST method', () => {
|
||||
expect(API_URLS.credentialDownload.method).toBe('POST');
|
||||
});
|
||||
|
||||
it('should build correct URL', () => {
|
||||
expect(API_URLS.credentialDownload.buildURL()).toBe(
|
||||
'/v1/mimoto/credentialshare/download',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('linkTransaction', () => {
|
||||
it('should have POST method', () => {
|
||||
expect(API_URLS.linkTransaction.method).toBe('POST');
|
||||
});
|
||||
|
||||
it('should build correct URL', () => {
|
||||
expect(API_URLS.linkTransaction.buildURL()).toBe(
|
||||
'/v1/esignet/linked-authorization/v2/link-transaction',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('authenticate', () => {
|
||||
it('should have POST method', () => {
|
||||
expect(API_URLS.authenticate.method).toBe('POST');
|
||||
});
|
||||
|
||||
it('should build correct URL', () => {
|
||||
expect(API_URLS.authenticate.buildURL()).toBe(
|
||||
'/v1/esignet/linked-authorization/v2/authenticate',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('sendConsent', () => {
|
||||
it('should have POST method', () => {
|
||||
expect(API_URLS.sendConsent.method).toBe('POST');
|
||||
});
|
||||
|
||||
it('should build correct URL', () => {
|
||||
expect(API_URLS.sendConsent.buildURL()).toBe(
|
||||
'/v1/esignet/linked-authorization/v2/consent',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('googleAccountProfileInfo', () => {
|
||||
it('should have GET method', () => {
|
||||
expect(API_URLS.googleAccountProfileInfo.method).toBe('GET');
|
||||
});
|
||||
|
||||
it('should build correct URL with access token', () => {
|
||||
const accessToken = 'test-token-123';
|
||||
expect(API_URLS.googleAccountProfileInfo.buildURL(accessToken)).toBe(
|
||||
`https://www.googleapis.com/oauth2/v1/userinfo?alt=json&access_token=${accessToken}`,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,4 +1,3 @@
|
||||
import {useState} from 'react';
|
||||
import testIDProps, {
|
||||
bytesToMB,
|
||||
faceMatchConfig,
|
||||
@@ -12,8 +11,20 @@ import testIDProps, {
|
||||
logState,
|
||||
removeWhiteSpace,
|
||||
sleep,
|
||||
getRandomInt,
|
||||
getMosipIdentifier,
|
||||
isTranslationKeyFound,
|
||||
getAccountType,
|
||||
BYTES_IN_MEGABYTE,
|
||||
} from './commonUtil';
|
||||
import {argon2iConfig} from './constants';
|
||||
import {
|
||||
argon2iConfig,
|
||||
GOOGLE_DRIVE_NAME,
|
||||
ICLOUD_DRIVE_NAME,
|
||||
GMAIL,
|
||||
APPLE,
|
||||
} from './constants';
|
||||
import {CredentialSubject} from '../machines/VerifiableCredential/VCMetaMachine/vc.d';
|
||||
|
||||
describe('hashData', () => {
|
||||
it('should expose a function', () => {
|
||||
@@ -74,6 +85,27 @@ describe('removeWhiteSpace', () => {
|
||||
const response = removeWhiteSpace('React Native Unit Testing');
|
||||
expect(response).toBe('ReactNativeUnitTesting');
|
||||
});
|
||||
|
||||
it('should handle empty string', () => {
|
||||
expect(removeWhiteSpace('')).toBe('');
|
||||
});
|
||||
|
||||
it('should handle string with only spaces', () => {
|
||||
expect(removeWhiteSpace(' ')).toBe('');
|
||||
});
|
||||
|
||||
it('should handle string with tabs and newlines', () => {
|
||||
expect(removeWhiteSpace('Hello\tWorld\n')).toBe('HelloWorld');
|
||||
});
|
||||
|
||||
it('should handle string with multiple types of whitespace', () => {
|
||||
expect(removeWhiteSpace(' Test \t String \n ')).toBe('TestString');
|
||||
});
|
||||
|
||||
it('should remove all whitespace from string', () => {
|
||||
const result = removeWhiteSpace('Hello World Test');
|
||||
expect(result).toBe('HelloWorldTest');
|
||||
});
|
||||
});
|
||||
|
||||
describe('logState', () => {
|
||||
@@ -97,17 +129,27 @@ describe('getMaskedText', () => {
|
||||
const maskedTxt = getMaskedText(id);
|
||||
expect(maskedTxt).toBe('******7890');
|
||||
});
|
||||
});
|
||||
|
||||
describe('faceMatchConfig', () => {
|
||||
it('should expose a function', () => {
|
||||
expect(faceMatchConfig).toBeDefined();
|
||||
it('should handle exactly 4 characters', () => {
|
||||
expect(getMaskedText('1234')).toBe('1234');
|
||||
});
|
||||
|
||||
// it('faceMatchConfig should return expected output', () => {
|
||||
// // const retValue = faceMatchConfig(resp);
|
||||
// expect(false).toBeTruthy();
|
||||
// });
|
||||
it('should handle long strings', () => {
|
||||
const longString = '12345678901234567890';
|
||||
const masked = getMaskedText(longString);
|
||||
expect(masked.endsWith('7890')).toBe(true);
|
||||
expect(masked.length).toBe(longString.length);
|
||||
});
|
||||
|
||||
it('should handle short strings', () => {
|
||||
const result = getMaskedText('ABCDEF');
|
||||
expect(result).toBe('**CDEF');
|
||||
});
|
||||
|
||||
it('should handle exactly 4 characters (ABCD)', () => {
|
||||
const result = getMaskedText('ABCD');
|
||||
expect(result).toBe('ABCD');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getBackupFileName', () => {
|
||||
@@ -116,26 +158,19 @@ describe('getBackupFileName', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('bytesToMB', () => {
|
||||
it('bytesToMB returns a string', () => {
|
||||
expect(bytesToMB(0)).toBe('0');
|
||||
});
|
||||
|
||||
it('10^6 bytes is 1MB', () => {
|
||||
expect(bytesToMB(1e6)).toBe('1.000');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getDriveName', () => {
|
||||
it('should expose a function', () => {
|
||||
expect(getDriveName).toBeDefined();
|
||||
});
|
||||
|
||||
it('getDriveName should return Google Drive on Android', () => {
|
||||
expect(getDriveName()).toBe('Google Drive');
|
||||
it('should return a string', () => {
|
||||
const result = getDriveName();
|
||||
expect(typeof result).toBe('string');
|
||||
});
|
||||
it('getDriveName should return Google Drive on Android', () => {
|
||||
expect(getDriveName()).toBe('Google Drive');
|
||||
|
||||
it('should return Google Drive for Android or iCloud for iOS', () => {
|
||||
const result = getDriveName();
|
||||
expect([GOOGLE_DRIVE_NAME, ICLOUD_DRIVE_NAME]).toContain(result);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -149,6 +184,19 @@ describe('sleep : The promise resolves after a certain time', () => {
|
||||
const promise = sleep(time);
|
||||
expect(promise).toBeInstanceOf(Promise);
|
||||
});
|
||||
|
||||
it('should delay for specified milliseconds', async () => {
|
||||
const start = Date.now();
|
||||
await sleep(100);
|
||||
const end = Date.now();
|
||||
const elapsed = end - start;
|
||||
expect(elapsed).toBeGreaterThanOrEqual(90); // Allow small margin
|
||||
});
|
||||
|
||||
it('should resolve after timeout', async () => {
|
||||
const promise = sleep(50);
|
||||
await expect(promise).resolves.toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getScreenHeight', () => {
|
||||
@@ -160,4 +208,240 @@ describe('getScreenHeight', () => {
|
||||
const height = getScreenHeight();
|
||||
expect(typeof height).toBe('object');
|
||||
});
|
||||
|
||||
it('should return a value', () => {
|
||||
const height = getScreenHeight();
|
||||
expect(height).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getRandomInt', () => {
|
||||
it('should expose a function', () => {
|
||||
expect(getRandomInt).toBeDefined();
|
||||
});
|
||||
|
||||
it('should return a number within the specified range', () => {
|
||||
const min = 1;
|
||||
const max = 10;
|
||||
const result = getRandomInt(min, max);
|
||||
expect(result).toBeGreaterThanOrEqual(min);
|
||||
expect(result).toBeLessThanOrEqual(max);
|
||||
expect(Number.isInteger(result)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return min when min and max are equal', () => {
|
||||
const value = 5;
|
||||
const result = getRandomInt(value, value);
|
||||
expect(result).toBe(value);
|
||||
});
|
||||
|
||||
it('should handle negative ranges', () => {
|
||||
const result = getRandomInt(-10, -1);
|
||||
expect(result).toBeGreaterThanOrEqual(-10);
|
||||
expect(result).toBeLessThanOrEqual(-1);
|
||||
});
|
||||
|
||||
it('should handle larger ranges', () => {
|
||||
const result = getRandomInt(100, 200);
|
||||
expect(result).toBeGreaterThanOrEqual(100);
|
||||
expect(result).toBeLessThanOrEqual(200);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getMosipIdentifier', () => {
|
||||
it('should expose a function', () => {
|
||||
expect(getMosipIdentifier).toBeDefined();
|
||||
});
|
||||
|
||||
it('should return UIN when UIN is present', () => {
|
||||
const credentialSubject = {
|
||||
UIN: '123456789',
|
||||
VID: '987654321',
|
||||
} as Partial<CredentialSubject>;
|
||||
const result = getMosipIdentifier(credentialSubject as CredentialSubject);
|
||||
expect(result).toBe('123456789');
|
||||
});
|
||||
|
||||
it('should return VID when UIN is not present', () => {
|
||||
const credentialSubject = {VID: '987654321'} as Partial<CredentialSubject>;
|
||||
const result = getMosipIdentifier(credentialSubject as CredentialSubject);
|
||||
expect(result).toBe('987654321');
|
||||
});
|
||||
|
||||
it('should return undefined when neither UIN nor VID is present', () => {
|
||||
const credentialSubject = {} as Partial<CredentialSubject>;
|
||||
const result = getMosipIdentifier(credentialSubject as CredentialSubject);
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should prioritize UIN over VID', () => {
|
||||
const credSubject = {
|
||||
UIN: '1111111111',
|
||||
VID: '2222222222',
|
||||
} as CredentialSubject;
|
||||
expect(getMosipIdentifier(credSubject)).toBe('1111111111');
|
||||
});
|
||||
});
|
||||
|
||||
describe('isTranslationKeyFound', () => {
|
||||
it('should expose a function', () => {
|
||||
expect(isTranslationKeyFound).toBeDefined();
|
||||
});
|
||||
|
||||
it('should return true when translation key is found', () => {
|
||||
const mockT = jest.fn(() => 'Translated text');
|
||||
const result = isTranslationKeyFound('someKey', mockT);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when translation key is not found', () => {
|
||||
const mockT = jest.fn((key: string) => key);
|
||||
const result = isTranslationKeyFound('someKey', mockT);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true when key is translated', () => {
|
||||
const mockT = () => 'Translated value';
|
||||
expect(isTranslationKeyFound('any.key', mockT)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when translation key not found', () => {
|
||||
const mockT = (key: string) => key; // returns same key
|
||||
expect(isTranslationKeyFound('some.unknown.key', mockT)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true for errors.notFound key when translation is found', () => {
|
||||
const mockT = (key: string) => {
|
||||
if (key === 'errors.notFound') return 'Error Not Found';
|
||||
return key;
|
||||
};
|
||||
expect(isTranslationKeyFound('errors.notFound', mockT)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAccountType', () => {
|
||||
it('should expose a function', () => {
|
||||
expect(getAccountType).toBeDefined();
|
||||
});
|
||||
|
||||
it('should return a string', () => {
|
||||
const result = getAccountType();
|
||||
expect(typeof result).toBe('string');
|
||||
});
|
||||
|
||||
it('should return Gmail for Android or Apple for iOS', () => {
|
||||
const result = getAccountType();
|
||||
expect([GMAIL, APPLE]).toContain(result);
|
||||
});
|
||||
});
|
||||
|
||||
describe('faceMatchConfig', () => {
|
||||
it('should expose a function', () => {
|
||||
expect(faceMatchConfig).toBeDefined();
|
||||
});
|
||||
|
||||
it('should return a valid configuration object', () => {
|
||||
const config = faceMatchConfig();
|
||||
expect(config).toBeDefined();
|
||||
expect(config.withFace).toBeDefined();
|
||||
expect(config.withFace.encoder).toBeDefined();
|
||||
expect(config.withFace.matcher).toBeDefined();
|
||||
expect(config.withFace.encoder.tfModel).toBeDefined();
|
||||
expect(config.withFace.matcher.threshold).toBe(1);
|
||||
});
|
||||
|
||||
it('should return config with correct structure', () => {
|
||||
const config = faceMatchConfig();
|
||||
expect(config).toHaveProperty('withFace');
|
||||
expect(config.withFace).toHaveProperty('encoder');
|
||||
expect(config.withFace).toHaveProperty('matcher');
|
||||
expect(config.withFace.encoder.tfModel).toHaveProperty('path');
|
||||
expect(config.withFace.encoder.tfModel).toHaveProperty('modelChecksum');
|
||||
expect(config.withFace.matcher.threshold).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('BYTES_IN_MEGABYTE', () => {
|
||||
it('should be defined', () => {
|
||||
expect(BYTES_IN_MEGABYTE).toBeDefined();
|
||||
});
|
||||
|
||||
it('should equal 1,000,000', () => {
|
||||
expect(BYTES_IN_MEGABYTE).toBe(1000000);
|
||||
});
|
||||
|
||||
it('should be 1000 * 1000', () => {
|
||||
expect(BYTES_IN_MEGABYTE).toBe(1000 * 1000);
|
||||
});
|
||||
|
||||
it('should be a number', () => {
|
||||
expect(typeof BYTES_IN_MEGABYTE).toBe('number');
|
||||
});
|
||||
|
||||
it('should be positive', () => {
|
||||
expect(BYTES_IN_MEGABYTE).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('bytesToMB', () => {
|
||||
it('bytesToMB returns a string', () => {
|
||||
expect(bytesToMB(0)).toBe('0');
|
||||
});
|
||||
|
||||
it('10^6 bytes is 1MB', () => {
|
||||
expect(bytesToMB(1e6)).toBe('1.000');
|
||||
});
|
||||
|
||||
it('should return "0" for negative bytes', () => {
|
||||
expect(bytesToMB(-100)).toBe('0');
|
||||
});
|
||||
|
||||
it('should convert 1,000,000 bytes to "1.000" MB', () => {
|
||||
expect(bytesToMB(1000000)).toBe('1.000');
|
||||
});
|
||||
|
||||
it('should convert 2,500,000 bytes to "2.500" MB', () => {
|
||||
expect(bytesToMB(2500000)).toBe('2.500');
|
||||
});
|
||||
|
||||
it('should convert 500,000 bytes to "0.500" MB', () => {
|
||||
expect(bytesToMB(500000)).toBe('0.500');
|
||||
});
|
||||
|
||||
it('should handle large byte values', () => {
|
||||
expect(bytesToMB(10000000)).toBe('10.000');
|
||||
});
|
||||
|
||||
it('should handle small byte values', () => {
|
||||
expect(bytesToMB(1000)).toBe('0.001');
|
||||
});
|
||||
|
||||
it('should return three decimal places', () => {
|
||||
const result = bytesToMB(1234567);
|
||||
expect(result).toMatch(/^\d+\.\d{3}$/);
|
||||
});
|
||||
|
||||
it('should handle fractional megabytes', () => {
|
||||
expect(bytesToMB(1234567)).toBe('1.235');
|
||||
});
|
||||
|
||||
it('should handle very small values', () => {
|
||||
expect(bytesToMB(100)).toBe('0.000');
|
||||
});
|
||||
|
||||
it('should handle exactly one byte', () => {
|
||||
expect(bytesToMB(1)).toBe('0.000');
|
||||
});
|
||||
|
||||
it('should convert bytes to megabytes', () => {
|
||||
const bytes = BYTES_IN_MEGABYTE * 5; // 5 MB
|
||||
const result = bytesToMB(bytes);
|
||||
expect(result).toBe('5.000');
|
||||
});
|
||||
|
||||
it('should handle fractional megabytes with BYTES_IN_MEGABYTE constant', () => {
|
||||
const bytes = BYTES_IN_MEGABYTE * 2.5;
|
||||
const result = bytesToMB(bytes);
|
||||
expect(result).toBe('2.500');
|
||||
});
|
||||
});
|
||||
|
||||
37
shared/cryptoutil/KeyTypes.test.ts
Normal file
37
shared/cryptoutil/KeyTypes.test.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import {KeyTypes} from './KeyTypes';
|
||||
|
||||
describe('KeyTypes', () => {
|
||||
it('should have RS256 key type', () => {
|
||||
expect(KeyTypes.RS256).toBe('RS256');
|
||||
});
|
||||
|
||||
it('should have ES256 key type', () => {
|
||||
expect(KeyTypes.ES256).toBe('ES256');
|
||||
});
|
||||
|
||||
it('should have ES256K key type', () => {
|
||||
expect(KeyTypes.ES256K).toBe('ES256K');
|
||||
});
|
||||
|
||||
it('should have ED25519 key type', () => {
|
||||
expect(KeyTypes.ED25519).toBe('Ed25519');
|
||||
});
|
||||
|
||||
it('should have exactly 4 key types', () => {
|
||||
const keyTypeCount = Object.keys(KeyTypes).length;
|
||||
expect(keyTypeCount).toBe(4);
|
||||
});
|
||||
|
||||
it('should allow access via enum key', () => {
|
||||
expect(KeyTypes['RS256']).toBe('RS256');
|
||||
expect(KeyTypes['ES256']).toBe('ES256');
|
||||
expect(KeyTypes['ES256K']).toBe('ES256K');
|
||||
expect(KeyTypes['ED25519']).toBe('Ed25519');
|
||||
});
|
||||
|
||||
it('should have all unique values', () => {
|
||||
const values = Object.values(KeyTypes);
|
||||
const uniqueValues = new Set(values);
|
||||
expect(uniqueValues.size).toBe(values.length);
|
||||
});
|
||||
});
|
||||
31
shared/error/BiometricCancellationError.test.ts
Normal file
31
shared/error/BiometricCancellationError.test.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import {BiometricCancellationError} from './BiometricCancellationError';
|
||||
|
||||
describe('BiometricCancellationError', () => {
|
||||
it('should create an error instance with the correct message', () => {
|
||||
const errorMessage = 'User cancelled biometric authentication';
|
||||
const error = new BiometricCancellationError(errorMessage);
|
||||
|
||||
expect(error).toBeInstanceOf(Error);
|
||||
expect(error).toBeInstanceOf(BiometricCancellationError);
|
||||
expect(error.message).toBe(errorMessage);
|
||||
});
|
||||
|
||||
it('should have the correct error name', () => {
|
||||
const error = new BiometricCancellationError('Test error');
|
||||
|
||||
expect(error.name).toBe('BiometricCancellationError');
|
||||
});
|
||||
|
||||
it('should maintain the error stack trace', () => {
|
||||
const error = new BiometricCancellationError('Stack trace test');
|
||||
|
||||
expect(error.stack).toBeDefined();
|
||||
});
|
||||
|
||||
it('should handle empty message', () => {
|
||||
const error = new BiometricCancellationError('');
|
||||
|
||||
expect(error.message).toBe('');
|
||||
expect(error.name).toBe('BiometricCancellationError');
|
||||
});
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user