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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
349 changes: 184 additions & 165 deletions app/components/UI/Card/Views/CardHome/CardHome.test.tsx

Large diffs are not rendered by default.

8 changes: 3 additions & 5 deletions app/components/UI/Card/Views/CardHome/CardHome.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import { DEPOSIT_SUPPORTED_TOKENS } from '../../constants';
import { useCardSDK } from '../../sdk';
import Routes from '../../../../../constants/navigation/Routes';
import useIsBaanxLoginEnabled from '../../hooks/isBaanxLoginEnabled';
import { selectIsAuthenticatedCard } from '../../../../../core/redux/slices/card';

/**
* CardHome Component
Expand All @@ -70,11 +71,8 @@ const CardHome = () => {
const [openAddFundsBottomSheet, setOpenAddFundsBottomSheet] = useState(false);
const [retries, setRetries] = useState(0);
const sheetRef = useRef<BottomSheetRef>(null);
const {
isAuthenticated,
logoutFromProvider,
isLoading: isSDKLoading,
} = useCardSDK();
const isAuthenticated = useSelector(selectIsAuthenticatedCard);
const { logoutFromProvider, isLoading: isSDKLoading } = useCardSDK();
const isBaanxLoginEnabled = useIsBaanxLoginEnabled();

const { trackEvent, createEventBuilder } = useMetrics();
Expand Down
199 changes: 47 additions & 152 deletions app/components/UI/Card/hooks/isBaanxLoginEnabled.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,187 +9,82 @@ jest.mock('../sdk', () => ({

const mockUseCardSDK = useCardSDK as jest.MockedFunction<typeof useCardSDK>;

const createMockSDK = (isBaanxLoginEnabled: boolean): Partial<CardSDK> => ({
get isBaanxLoginEnabled() {
return isBaanxLoginEnabled;
},
get isCardEnabled() {
return true;
},
get supportedTokens() {
return [];
},
isCardHolder: jest.fn(),
getGeoLocation: jest.fn(),
getSupportedTokensAllowances: jest.fn(),
getPriorityToken: jest.fn(),
});

const mockCardSDKResponse = (sdk: Partial<CardSDK> | null) => {
mockUseCardSDK.mockReturnValue({
sdk: sdk as CardSDK | null,
isLoading: false,
logoutFromProvider: jest.fn(),
userCardLocation: 'international',
});
};

describe('useIsBaanxLoginEnabled', () => {
beforeEach(() => {
jest.clearAllMocks();
});

it('should return false when SDK is null', () => {
mockUseCardSDK.mockReturnValue({
sdk: null,
isAuthenticated: false,
setIsAuthenticated: jest.fn(),
isLoading: false,
logoutFromProvider: jest.fn(),
userCardLocation: 'international',
});

const { result } = renderHook(() => useIsBaanxLoginEnabled());

expect(result.current).toBe(false);
expect(mockUseCardSDK).toHaveBeenCalledTimes(1);
});

it('should return false when SDK is undefined', () => {
mockUseCardSDK.mockReturnValue({
sdk: null,
isAuthenticated: false,
setIsAuthenticated: jest.fn(),
isLoading: false,
logoutFromProvider: jest.fn(),
userCardLocation: 'international',
});
it('returns false when SDK is null', () => {
// Given: SDK is not available
mockCardSDKResponse(null);

// When: hook is rendered
const { result } = renderHook(() => useIsBaanxLoginEnabled());

// Then: should return false
expect(result.current).toBe(false);
expect(mockUseCardSDK).toHaveBeenCalledTimes(1);
});

it('should return true when SDK exists and isBaanxLoginEnabled is true', () => {
const mockSdk = {
get isBaanxLoginEnabled() {
return true;
},
get isCardEnabled() {
return true;
},
get supportedTokens() {
return [];
},
isCardHolder: jest.fn(),
getGeoLocation: jest.fn(),
getSupportedTokensAllowances: jest.fn(),
getPriorityToken: jest.fn(),
};

mockUseCardSDK.mockReturnValue({
sdk: mockSdk as unknown as CardSDK,
isAuthenticated: false,
setIsAuthenticated: jest.fn(),
isLoading: false,
logoutFromProvider: jest.fn(),
userCardLocation: 'international',
});
it('returns true when Baanx login is enabled', () => {
// Given: SDK with Baanx login enabled
mockCardSDKResponse(createMockSDK(true));

// When: hook is rendered
const { result } = renderHook(() => useIsBaanxLoginEnabled());

// Then: should return true
expect(result.current).toBe(true);
expect(mockUseCardSDK).toHaveBeenCalledTimes(1);
});

it('should return false when SDK exists and isBaanxLoginEnabled is false', () => {
const mockSdk = {
get isBaanxLoginEnabled() {
return false;
},
get isCardEnabled() {
return true;
},
get supportedTokens() {
return [];
},
isCardHolder: jest.fn(),
getGeoLocation: jest.fn(),
getSupportedTokensAllowances: jest.fn(),
getPriorityToken: jest.fn(),
};

mockUseCardSDK.mockReturnValue({
sdk: mockSdk as unknown as CardSDK,
isAuthenticated: false,
setIsAuthenticated: jest.fn(),
isLoading: false,
logoutFromProvider: jest.fn(),
userCardLocation: 'international',
});
it('returns false when Baanx login is disabled', () => {
// Given: SDK with Baanx login disabled
mockCardSDKResponse(createMockSDK(false));

// When: hook is rendered
const { result } = renderHook(() => useIsBaanxLoginEnabled());

// Then: should return false
expect(result.current).toBe(false);
expect(mockUseCardSDK).toHaveBeenCalledTimes(1);
});

it('should call useCardSDK hook correctly', () => {
const mockSdk = {
get isBaanxLoginEnabled() {
return true;
},
get isCardEnabled() {
return true;
},
get supportedTokens() {
return [];
},
isCardHolder: jest.fn(),
getGeoLocation: jest.fn(),
getSupportedTokensAllowances: jest.fn(),
getPriorityToken: jest.fn(),
};

mockUseCardSDK.mockReturnValue({
sdk: mockSdk as unknown as CardSDK,
isAuthenticated: false,
setIsAuthenticated: jest.fn(),
isLoading: false,
logoutFromProvider: jest.fn(),
userCardLocation: 'international',
});

renderHook(() => useIsBaanxLoginEnabled());

expect(mockUseCardSDK).toHaveBeenCalledWith();
expect(mockUseCardSDK).toHaveBeenCalledTimes(1);
});

it('should re-render when SDK value changes', () => {
const mockSdk = {
get isBaanxLoginEnabled() {
return false;
},
get isCardEnabled() {
return true;
},
get supportedTokens() {
return [];
},
isCardHolder: jest.fn(),
getGeoLocation: jest.fn(),
getSupportedTokensAllowances: jest.fn(),
getPriorityToken: jest.fn(),
};

mockUseCardSDK.mockReturnValue({
sdk: mockSdk as unknown as CardSDK,
isAuthenticated: false,
setIsAuthenticated: jest.fn(),
isLoading: false,
logoutFromProvider: jest.fn(),
userCardLocation: 'international',
});

it('updates when SDK value changes', () => {
// Given: SDK with Baanx login disabled
mockCardSDKResponse(createMockSDK(false));
const { result, rerender } = renderHook(() => useIsBaanxLoginEnabled());

// Then: should return false initially
expect(result.current).toBe(false);

const updatedMockSdk = {
...mockSdk,
get isBaanxLoginEnabled() {
return true;
},
};

mockUseCardSDK.mockReturnValue({
sdk: updatedMockSdk as unknown as CardSDK,
isAuthenticated: false,
setIsAuthenticated: jest.fn(),
isLoading: false,
logoutFromProvider: jest.fn(),
userCardLocation: 'international',
});

// When: SDK changes to enable Baanx login
mockCardSDKResponse(createMockSDK(true));
rerender();

// Then: should return true
expect(result.current).toBe(true);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,20 @@ import {
} from '../types';
import { CardSDK } from '../sdk/CardSDK';
import { strings } from '../../../../../locales/i18n';
import { useDispatch } from 'react-redux';
import { setIsAuthenticatedCard } from '../../../../core/redux/slices/card';

jest.mock('@sentry/core');
jest.mock('../sdk');
jest.mock('../util/cardTokenVault');
jest.mock('../util/pkceHelpers');
jest.mock('../../../../../locales/i18n');
jest.mock('react-redux', () => ({
useDispatch: jest.fn(),
}));
jest.mock('../../../../core/redux/slices/card', () => ({
setIsAuthenticatedCard: jest.fn(),
}));

const mockUuid4 = uuid4 as jest.MockedFunction<typeof uuid4>;
const mockUseCardSDK = useCardSDK as jest.MockedFunction<typeof useCardSDK>;
Expand All @@ -31,6 +39,9 @@ const mockGenerateState = generateState as jest.MockedFunction<
typeof generateState
>;
const mockStrings = strings as jest.MockedFunction<typeof strings>;
const mockUseDispatch = useDispatch as jest.MockedFunction<typeof useDispatch>;
const mockSetIsAuthenticatedCard =
setIsAuthenticatedCard as jest.MockedFunction<typeof setIsAuthenticatedCard>;

describe('useCardProviderAuthentication', () => {
const mockSdk = {
Expand All @@ -53,7 +64,7 @@ describe('useCardProviderAuthentication', () => {
exchangeToken: jest.fn(),
refreshLocalToken: jest.fn(),
};
const mockSetIsAuthenticated = jest.fn();
const mockDispatch = jest.fn();
const mockStateUuid = 'mock-state-uuid';
const mockCodeVerifier = 'mock-code-verifier';
const mockCodeChallenge = 'mock-code-challenge';
Expand All @@ -68,13 +79,16 @@ describe('useCardProviderAuthentication', () => {
mockGenerateState.mockReturnValue(mockStateUuid);
mockUseCardSDK.mockReturnValue({
sdk: mockSdk as unknown as CardSDK,
isAuthenticated: false,
setIsAuthenticated: mockSetIsAuthenticated,
isLoading: false,
logoutFromProvider: jest.fn(),
userCardLocation: 'international',
});
mockStrings.mockImplementation((key: string) => `mocked_${key}`);
mockUseDispatch.mockReturnValue(mockDispatch);
mockSetIsAuthenticatedCard.mockReturnValue({
type: 'card/setIsAuthenticatedCard',
payload: true,
} as ReturnType<typeof setIsAuthenticatedCard>);
});

describe('initial state', () => {
Expand Down Expand Up @@ -160,7 +174,11 @@ describe('useCardProviderAuthentication', () => {
expiresAt: expect.any(Number),
location: loginParams.location,
});
expect(mockSetIsAuthenticated).toHaveBeenCalledWith(true);
expect(mockSetIsAuthenticatedCard).toHaveBeenCalledWith(true);
expect(mockDispatch).toHaveBeenCalledWith({
type: 'card/setIsAuthenticatedCard',
payload: true,
});
expect(result.current.error).toBeNull();
expect(result.current.loading).toBe(false);
});
Expand Down Expand Up @@ -360,8 +378,6 @@ describe('useCardProviderAuthentication', () => {
it('throws error when SDK is not initialized', async () => {
mockUseCardSDK.mockReturnValue({
sdk: null,
isAuthenticated: false,
setIsAuthenticated: mockSetIsAuthenticated,
isLoading: false,
logoutFromProvider: jest.fn(),
userCardLocation: 'international',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { storeCardBaanxToken } from '../util/cardTokenVault';
import { generatePKCEPair, generateState } from '../util/pkceHelpers';
import { CardError, CardErrorType, CardLocation } from '../types';
import { strings } from '../../../../../locales/i18n';
import { useDispatch } from 'react-redux';
import { setIsAuthenticatedCard as setIsAuthenticatedAction } from '../../../../core/redux/slices/card';

/**
* Maps CardError types to user-friendly localized error messages
Expand Down Expand Up @@ -45,9 +47,10 @@ const useCardProviderAuthentication = (): {
error: string | null;
clearError: () => void;
} => {
const dispatch = useDispatch();
const [error, setError] = useState<string | null>(null);
const [loading, setLoading] = useState(false);
const { sdk, setIsAuthenticated } = useCardSDK();
const { sdk } = useCardSDK();

const clearError = useCallback(() => {
setError(null);
Expand Down Expand Up @@ -105,7 +108,7 @@ const useCardProviderAuthentication = (): {
});

setError(null);
setIsAuthenticated(true);
dispatch(setIsAuthenticatedAction(true));
} catch (err) {
const errorMessage = getErrorMessage(err);
setError(errorMessage);
Expand All @@ -115,7 +118,7 @@ const useCardProviderAuthentication = (): {
setLoading(false);
}
},
[sdk, setIsAuthenticated],
[sdk, dispatch],
);

return useMemo(
Expand Down
Loading
Loading