Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
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
9 changes: 9 additions & 0 deletions .cursor/worktrees.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"setup-worktree": [
"cp $ROOT_WORKTREE_PATH/.js.env .js.env",
"cp $ROOT_WORKTREE_PATH/.ios.env .ios.env",
"cp $ROOT_WORKTREE_PATH/.android.env .android.env",
"cp $ROOT_WORKTREE_PATH/.e2e.env .e2e.env",
"cp -r $ROOT_WORKTREE_PATH/.cursor/plans .cursor/plans"
]
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
diff --git a/node_modules/redux-persist-filesystem-storage/index.d.ts b/node_modules/redux-persist-filesystem-storage/index.d.ts
index b0caa94..76b0442 100644
--- a/node_modules/redux-persist-filesystem-storage/index.d.ts
+++ b/node_modules/redux-persist-filesystem-storage/index.d.ts
diff --git a/index.d.ts b/index.d.ts
index b0caa94ceaa9afaa6c112947a328887e580f76a2..76b0442a7367f39d8ae9300825815edda5b02c44 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -12,6 +12,7 @@ declare module 'redux-persist-filesystem-storage' {
setItem: (
key: string,
Expand All @@ -10,24 +10,30 @@ index b0caa94..76b0442 100644
callback?: (error?: Error) => void,
) => Promise<void>

diff --git a/node_modules/redux-persist-filesystem-storage/index.js b/node_modules/redux-persist-filesystem-storage/index.js
index d69afb6..0ca3a25 100644
--- a/node_modules/redux-persist-filesystem-storage/index.js
+++ b/node_modules/redux-persist-filesystem-storage/index.js
@@ -41,11 +41,14 @@ const FilesystemStorage = {
diff --git a/index.js b/index.js
index d69afb678b3d06760ad59831457cfd5c51fdb89b..8d5ecb060a91f137c865ed21f891b640d3cc65fe 100644
--- a/index.js
+++ b/index.js
@@ -41,11 +41,19 @@ const FilesystemStorage = {
onStorageReady = onStorageReadyFactory(options.storagePath);
},

- setItem: (key: string, value: string, callback?: (error: ?Error) => void) =>
- ReactNativeBlobUtil.fs
+ setItem: (key: string, value: string, isIOS: boolean = false, callback?: (error: ?Error) => void) => {
ReactNativeBlobUtil.fs
+ return ReactNativeBlobUtil.fs
.writeFile(pathForKey(key), value, options.encoding)
- .then(() => callback && callback())
- .catch(error => callback && callback(error)),
+ .then(() => {
+ if (isIOS) ReactNativeBlobUtil.ios.excludeFromBackupKey(pathForKey(key));
+ callback && callback();
+ }).catch(error => callback && callback(error));
+ }).catch((error) => {
+ if (!callback) {
+ throw error;
+ }
+ callback(error);
+ });
+ },

getItem: onStorageReady(
Expand Down
188 changes: 188 additions & 0 deletions app/components/UI/Card/Views/CardHome/CardHome.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,11 @@ jest.mock('../../../../../../locales/i18n', () => ({
'Failed to load PIN. Please try again.',
'card.password_bottomsheet.description_view_pin':
'Enter your wallet password to view your card PIN.',
'card.card_home.manage_card_options.cashback': 'Cashback',
'card.card_home.manage_card_options.cashback_description':
'Earn 1% back on all spending',
'card.card_home.manage_card_options.cashback_description_metal':
'Earn 3% back on all spending',
};
return strings[key] || key;
},
Expand Down Expand Up @@ -5565,4 +5570,187 @@ describe('CardHome Component', () => {
expect(cardDetails.holderName).toBe('Jane Smith');
});
});

describe('Cashback List Item', () => {
it('displays cashback item for authenticated international user with VERIFIED KYC', () => {
// Given: authenticated international user with verified KYC
setupMockSelectors({
isAuthenticated: true,
userLocation: 'international',
});
setupLoadCardDataMock({
isAuthenticated: true,
isBaanxLoginEnabled: true,
cardDetails: { type: CardType.VIRTUAL },
isLoading: false,
kycStatus: { verificationState: 'VERIFIED', userId: 'user-123' },
});

// When: component renders
render();

// Then: cashback item is visible
expect(
screen.getByTestId(CardHomeSelectors.CASHBACK_ITEM),
).toBeOnTheScreen();
});

it('hides cashback item for US users', () => {
// Given: authenticated US user with verified KYC
setupMockSelectors({
isAuthenticated: true,
userLocation: 'us',
});
setupLoadCardDataMock({
isAuthenticated: true,
isBaanxLoginEnabled: true,
cardDetails: { type: CardType.VIRTUAL },
isLoading: false,
kycStatus: { verificationState: 'VERIFIED', userId: 'user-123' },
});

// When: component renders
render();

// Then: cashback item is not rendered
expect(
screen.queryByTestId(CardHomeSelectors.CASHBACK_ITEM),
).not.toBeOnTheScreen();
});

it('hides cashback item when user is not authenticated', () => {
// Given: unauthenticated user
setupMockSelectors({
isAuthenticated: false,
userLocation: 'international',
});
setupLoadCardDataMock({
isAuthenticated: false,
isBaanxLoginEnabled: true,
cardDetails: { type: CardType.VIRTUAL },
isLoading: false,
});

// When: component renders
render();

// Then: cashback item is not rendered
expect(
screen.queryByTestId(CardHomeSelectors.CASHBACK_ITEM),
).not.toBeOnTheScreen();
});

it('hides cashback item when KYC is not verified', () => {
// Given: authenticated international user with pending KYC
setupMockSelectors({
isAuthenticated: true,
userLocation: 'international',
});
setupLoadCardDataMock({
isAuthenticated: true,
isBaanxLoginEnabled: true,
cardDetails: { type: CardType.VIRTUAL },
isLoading: false,
kycStatus: { verificationState: 'PENDING', userId: 'user-123' },
});

// When: component renders
render();

// Then: cashback item is not rendered
expect(
screen.queryByTestId(CardHomeSelectors.CASHBACK_ITEM),
).not.toBeOnTheScreen();
});

it('shows standard cashback description for virtual card', () => {
// Given: authenticated international user with virtual card
setupMockSelectors({
isAuthenticated: true,
userLocation: 'international',
});
setupLoadCardDataMock({
isAuthenticated: true,
isBaanxLoginEnabled: true,
cardDetails: { type: CardType.VIRTUAL },
isLoading: false,
kycStatus: { verificationState: 'VERIFIED', userId: 'user-123' },
});

// When: component renders
render();

// Then: standard description is shown
expect(
screen.getByText('Earn 1% back on all spending'),
).toBeOnTheScreen();
});

it('shows metal cashback description for metal card', () => {
// Given: authenticated international user with metal card
setupMockSelectors({
isAuthenticated: true,
userLocation: 'international',
});
setupLoadCardDataMock({
isAuthenticated: true,
isBaanxLoginEnabled: true,
cardDetails: { type: CardType.METAL },
isLoading: false,
kycStatus: { verificationState: 'VERIFIED', userId: 'user-123' },
});

// When: component renders
render();

// Then: metal description is shown
expect(
screen.getByText('Earn 3% back on all spending'),
).toBeOnTheScreen();
});

it('navigates to cashback screen on press', () => {
// Given: authenticated international user with verified KYC
setupMockSelectors({
isAuthenticated: true,
userLocation: 'international',
});
setupLoadCardDataMock({
isAuthenticated: true,
isBaanxLoginEnabled: true,
cardDetails: { type: CardType.VIRTUAL },
isLoading: false,
kycStatus: { verificationState: 'VERIFIED', userId: 'user-123' },
});

// When: user taps cashback item
render();
fireEvent.press(screen.getByTestId(CardHomeSelectors.CASHBACK_ITEM));

// Then: navigates to cashback route
expect(mockNavigate).toHaveBeenCalled();
});

it('tracks analytics event on press', () => {
// Given: authenticated international user with verified KYC
setupMockSelectors({
isAuthenticated: true,
userLocation: 'international',
});
setupLoadCardDataMock({
isAuthenticated: true,
isBaanxLoginEnabled: true,
cardDetails: { type: CardType.VIRTUAL },
isLoading: false,
kycStatus: { verificationState: 'VERIFIED', userId: 'user-123' },
});

// When: user taps cashback item
render();
fireEvent.press(screen.getByTestId(CardHomeSelectors.CASHBACK_ITEM));

// Then: tracks cashback button event
expect(mockTrackEvent).toHaveBeenCalled();
});
});
});
Loading
Loading