Files
pwap/mobile/jest.setup.cjs
pezkuwichain 1e1c2310c9 fix: Remove workspace config, fix test suite, update snapshots
- Remove root /home/mamostehp/package.json workspace config
- Each project now independent (aligned with CI workflow)
- Add SafeAreaProvider mock to jest setup
- Add __DEV__ global for React Native tests
- Update 4 snapshots for SafeAreaView changes
- All 29 test suites pass (122 tests)
2026-01-19 15:26:47 +03:00

349 lines
11 KiB
JavaScript

// Jest setup for React Native testing
// @testing-library/react-native v12.4+ includes matchers by default
// Disable Expo's winter module system for tests
process.env.EXPO_USE_STATIC_RENDERING = 'true';
global.__ExpoImportMetaRegistry__ = {};
// Mock navigation context for @react-navigation/core
const mockNavigationObject = {
navigate: jest.fn(),
goBack: jest.fn(),
setOptions: jest.fn(),
addListener: jest.fn(() => () => {}),
removeListener: jest.fn(),
replace: jest.fn(),
reset: jest.fn(),
canGoBack: jest.fn(() => true),
isFocused: jest.fn(() => true),
dispatch: jest.fn(),
getParent: jest.fn(),
getState: jest.fn(() => ({
routes: [],
index: 0,
})),
setParams: jest.fn(),
};
jest.mock('@react-navigation/core', () => {
const actualCore = jest.requireActual('@react-navigation/core');
return {
...actualCore,
useNavigation: () => mockNavigationObject,
useRoute: () => ({
params: {},
key: 'test-route',
name: 'TestScreen',
}),
useFocusEffect: jest.fn(),
useIsFocused: () => true,
};
});
// Mock @react-navigation/native
jest.mock('@react-navigation/native', () => {
const actualNav = jest.requireActual('@react-navigation/native');
return {
...actualNav,
useNavigation: () => mockNavigationObject,
useRoute: () => ({
params: {},
key: 'test-route',
name: 'TestScreen',
}),
useFocusEffect: jest.fn(),
useIsFocused: () => true,
};
});
// Mock PezkuwiContext globally
jest.mock('./src/contexts/PezkuwiContext', () => require('./src/__mocks__/contexts/PezkuwiContext'));
// Mock AuthContext globally
jest.mock('./src/contexts/AuthContext', () => require('./src/__mocks__/contexts/AuthContext'));
// Mock ThemeContext globally
jest.mock('./src/contexts/ThemeContext', () => require('./src/__mocks__/contexts/ThemeContext'));
// Mock BiometricAuthContext globally
jest.mock('./src/contexts/BiometricAuthContext', () => require('./src/__mocks__/contexts/BiometricAuthContext'));
// Mock react-native-safe-area-context
jest.mock('react-native-safe-area-context', () => {
const insets = { top: 0, right: 0, bottom: 0, left: 0 };
return {
SafeAreaProvider: ({ children }) => children,
SafeAreaView: ({ children }) => children,
useSafeAreaInsets: () => insets,
useSafeAreaFrame: () => ({ x: 0, y: 0, width: 390, height: 844 }),
initialWindowMetrics: { insets, frame: { x: 0, y: 0, width: 390, height: 844 } },
};
});
// Mock expo modules
jest.mock('expo-linear-gradient', () => ({
LinearGradient: 'LinearGradient',
}));
// Mock react-native-webview
jest.mock('react-native-webview', () => ({
WebView: 'WebView',
WebViewMessageEvent: {},
}));
jest.mock('expo-secure-store', () => ({
setItemAsync: jest.fn(() => Promise.resolve()),
getItemAsync: jest.fn(() => Promise.resolve(null)),
deleteItemAsync: jest.fn(() => Promise.resolve()),
}));
jest.mock('expo-local-authentication', () => ({
authenticateAsync: jest.fn(() =>
Promise.resolve({ success: true })
),
hasHardwareAsync: jest.fn(() => Promise.resolve(true)),
isEnrolledAsync: jest.fn(() => Promise.resolve(true)),
supportedAuthenticationTypesAsync: jest.fn(() => Promise.resolve([1])), // 1 = FINGERPRINT
AuthenticationType: {
FINGERPRINT: 1,
FACIAL_RECOGNITION: 2,
IRIS: 3,
},
}));
// Mock AsyncStorage
jest.mock('@react-native-async-storage/async-storage', () =>
require('@react-native-async-storage/async-storage/jest/async-storage-mock')
);
// Mock Polkadot.js (virtual: true because package may not be installed in CI)
jest.mock('@polkadot/api', () => ({
ApiPromise: {
create: jest.fn(() =>
Promise.resolve({
isReady: Promise.resolve(true),
query: {},
tx: {},
rpc: {},
disconnect: jest.fn(),
})
),
},
WsProvider: jest.fn(),
}), { virtual: true });
// Mock @pezkuwi packages (aliases for @polkadot packages)
jest.mock('@pezkuwi/api', () => ({
ApiPromise: {
create: jest.fn(() =>
Promise.resolve({
isReady: Promise.resolve(true),
query: {
treasury: {
treasury: jest.fn(() => Promise.resolve({ toString: () => '1000000000000000' })),
proposals: {
entries: jest.fn(() => Promise.resolve([])),
},
},
democracy: {
referendumInfoOf: {
entries: jest.fn(() => Promise.resolve([])),
},
},
dynamicCommissionCollective: {
proposals: jest.fn(() => Promise.resolve([])),
voting: jest.fn(() => Promise.resolve({ isSome: false })),
},
},
tx: {},
rpc: {},
disconnect: jest.fn(),
})
),
},
WsProvider: jest.fn(),
}), { virtual: true });
jest.mock('@pezkuwi/keyring', () => ({
Keyring: jest.fn().mockImplementation(() => ({
addFromUri: jest.fn((mnemonic, meta, type) => ({
address: '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY',
meta: meta || {},
type: type || 'sr25519',
publicKey: new Uint8Array(32),
sign: jest.fn(),
verify: jest.fn(),
})),
addFromMnemonic: jest.fn((mnemonic, meta, type) => ({
address: '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY',
meta: meta || {},
type: type || 'sr25519',
publicKey: new Uint8Array(32),
sign: jest.fn(),
verify: jest.fn(),
})),
getPairs: jest.fn(() => []),
getPair: jest.fn((address) => ({
address: address,
meta: {},
type: 'sr25519',
publicKey: new Uint8Array(32),
sign: jest.fn(),
verify: jest.fn(),
})),
})),
}), { virtual: true });
jest.mock('@pezkuwi/util-crypto', () => ({
cryptoWaitReady: jest.fn(() => Promise.resolve(true)),
mnemonicGenerate: jest.fn(() => 'test test test test test test test test test test test junk'),
mnemonicValidate: jest.fn(() => true),
}), { virtual: true });
// Mock shared lib modules (they use @pezkuwi/api which is not available in CI)
jest.mock('../shared/lib/tiki', () => ({
Tiki: {
Welati: 'Welati',
Parlementer: 'Parlementer',
Serok: 'Serok',
},
RoleAssignmentType: {},
TIKI_DISPLAY_NAMES: {},
TIKI_SCORES: {},
ROLE_CATEGORIES: {},
fetchUserTikis: jest.fn(() => Promise.resolve([])),
isCitizen: jest.fn(() => Promise.resolve(false)),
calculateTikiScore: jest.fn(() => 0),
getPrimaryRole: jest.fn(() => 'Welati'),
getTikiDisplayName: jest.fn((tiki) => tiki),
getUserRoleCategories: jest.fn(() => []),
hasTiki: jest.fn(() => false),
getTikiColor: jest.fn(() => '#22C55E'),
getTikiEmoji: jest.fn(() => '👤'),
getTikiBadgeVariant: jest.fn(() => 'default'),
fetchUserTikiNFTs: jest.fn(() => Promise.resolve([])),
getCitizenNFTDetails: jest.fn(() => Promise.resolve(null)),
getAllTikiNFTDetails: jest.fn(() => Promise.resolve([])),
generateCitizenNumber: jest.fn(() => 'CIT-001'),
}), { virtual: true });
jest.mock('../shared/lib/referral', () => ({
initiateReferral: jest.fn(() => Promise.resolve()),
getPendingReferral: jest.fn(() => Promise.resolve(null)),
getReferralCount: jest.fn(() => Promise.resolve(0)),
getReferralInfo: jest.fn(() => Promise.resolve(null)),
calculateReferralScore: jest.fn(() => 0),
getReferralStats: jest.fn(() => Promise.resolve({ totalReferred: 0, pendingCount: 0, confirmedCount: 0 })),
getMyReferrals: jest.fn(() => Promise.resolve([])),
subscribeToReferralEvents: jest.fn(() => jest.fn()),
}), { virtual: true });
jest.mock('../shared/lib/scores', () => ({
getTrustScore: jest.fn(() => Promise.resolve(0)),
getTrustScoreDetails: jest.fn(() => Promise.resolve(null)),
getReferralScore: jest.fn(() => Promise.resolve(0)),
getReferralCount: jest.fn(() => Promise.resolve(0)),
getStakingScoreFromPallet: jest.fn(() => Promise.resolve(0)),
getTikiScore: jest.fn(() => Promise.resolve(0)),
getAllScores: jest.fn(() => Promise.resolve({
trustScore: 0,
referralScore: 0,
stakingScore: 0,
tikiScore: 0,
totalScore: 0,
})),
getScoreColor: jest.fn(() => '#22C55E'),
getScoreRating: jest.fn(() => 'Good'),
formatScore: jest.fn((score) => String(score)),
}), { virtual: true });
// Mock Supabase
jest.mock('./src/lib/supabase', () => ({
supabase: {
auth: {
signInWithPassword: jest.fn(),
signUp: jest.fn(),
signOut: jest.fn(),
getSession: jest.fn(() => Promise.resolve({ data: { session: null }, error: null })),
onAuthStateChange: jest.fn(() => ({
data: {
subscription: {
unsubscribe: jest.fn(),
},
},
})),
},
from: jest.fn(() => ({
select: jest.fn().mockReturnThis(),
insert: jest.fn().mockReturnThis(),
update: jest.fn().mockReturnThis(),
delete: jest.fn().mockReturnThis(),
eq: jest.fn().mockReturnThis(),
order: jest.fn().mockReturnThis(),
single: jest.fn().mockReturnThis(),
})),
},
}));
// Mock shared blockchain utilities
jest.mock('../shared/blockchain', () => ({
PEZKUWI_NETWORK: {
name: 'Pezkuwi',
endpoint: 'wss://rpc.pezkuwichain.io:9944',
chainId: 'pezkuwi',
},
DEFAULT_ENDPOINT: 'ws://127.0.0.1:9944',
getExplorerUrl: jest.fn((txHash) => `https://explorer.pezkuwichain.app/tx/${txHash}`),
}));
// Mock shared DEX utilities
jest.mock('../shared/utils/dex', () => ({
formatTokenBalance: jest.fn((amount, decimals) => '0.00'),
parseTokenInput: jest.fn((input, decimals) => '0'),
calculatePriceImpact: jest.fn(() => '0'),
getAmountOut: jest.fn(() => '0'),
calculateMinAmount: jest.fn((amount, slippage) => '0'),
fetchPools: jest.fn(() => Promise.resolve([])),
fetchUserPositions: jest.fn(() => Promise.resolve([])),
}));
// Mock shared P2P fiat utilities
jest.mock('../shared/lib/p2p-fiat', () => ({
getActiveOffers: jest.fn(() => Promise.resolve([])),
createOffer: jest.fn(() => Promise.resolve({ id: '123' })),
acceptOffer: jest.fn(() => Promise.resolve(true)),
}));
// Mock shared wallet utilities (handles import.meta)
jest.mock('../shared/lib/wallet', () => ({
formatBalance: jest.fn((amount, decimals) => '0.00'),
parseBalance: jest.fn((amount) => '0'),
NETWORK_ENDPOINTS: {
local: 'ws://127.0.0.1:9944',
testnet: 'wss://testnet.pezkuwichain.io',
mainnet: 'wss://mainnet.pezkuwichain.io',
staging: 'wss://staging.pezkuwichain.io',
beta: 'wss://rpc.pezkuwichain.io:9944',
},
}));
// Mock shared staking utilities (handles import.meta)
jest.mock('../shared/lib/staking', () => ({
formatBalance: jest.fn((amount) => '0.00'),
NETWORK_ENDPOINTS: {},
}));
// Mock shared citizenship workflow (handles polkadot/extension-dapp)
jest.mock('../shared/lib/citizenship-workflow', () => ({
createCitizenshipRequest: jest.fn(() => Promise.resolve({ id: '123' })),
}));
// Note: Alert is mocked in individual test files where needed
// Silence console warnings in tests
global.console = {
...console,
warn: jest.fn(),
error: jest.fn(),
};