Skip to content

Commit 7830e79

Browse files
committed
Merge remote-tracking branch 'origin/main' into fix/MPT-17762/update-appstore-connect-links
# Conflicts: # app/app.config.js
2 parents fac0a76 + a59aa63 commit 7830e79

26 files changed

+465
-286
lines changed

app/app.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export default {
4040
ios: {
4141
supportsTablet: true,
4242
bundleIdentifier: bundleId,
43-
buildNumber: '5',
43+
buildNumber: '6',
4444
infoPlist: {
4545
ITSAppUsesNonExemptEncryption: false,
4646
},
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
export const mockInvoiceId1 = 'INV-123';
2+
3+
export const mockInvoiceId2 = 'INV-234';
4+
5+
export const mockInvoiceData = {
6+
id: 'INV-123',
7+
name: 'Test Invoice',
8+
status: 'Issued',
9+
};
10+
11+
export const expectedUrl1 =
12+
`/v1/billing/invoices/${mockInvoiceId1}` +
13+
`?select=seller.address.country,statement,statement.ledger.owner,audit`;
14+
export const expectedUrl2 =
15+
`/v1/billing/invoices/${mockInvoiceId2}` +
16+
`?select=seller.address.country,statement,statement.ledger.owner,audit`;
17+
18+
export const mockResponse1 = {
19+
id: 'INV-123',
20+
name: 'Invoice One',
21+
};
22+
23+
export const mockResponse2 = {
24+
id: 'INV-234',
25+
name: 'Invoice Two',
26+
};

app/src/__tests__/navigationPermissions.test.ts

Lines changed: 0 additions & 94 deletions
This file was deleted.

app/src/__tests__/services/billingService.test.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
import { renderHook, act } from '@testing-library/react-native';
22

3+
import { mockNetworkError } from '../__mocks__/services/common';
4+
import {
5+
mockInvoiceId1,
6+
mockInvoiceId2,
7+
mockInvoiceData,
8+
expectedUrl1,
9+
expectedUrl2,
10+
mockResponse1,
11+
mockResponse2,
12+
} from '../__mocks__/services/invoice';
13+
314
import { DEFAULT_OFFSET, DEFAULT_PAGE_SIZE } from '@/constants/api';
415
import { useBillingApi } from '@/services/billingService';
516
import type { PaginatedResponse } from '@/types/api';
@@ -175,3 +186,56 @@ describe('useBillingApi – getCreditMemoDetails', () => {
175186
);
176187
});
177188
});
189+
190+
describe('useBillingApi - getInvoiceData', () => {
191+
beforeEach(() => {
192+
jest.clearAllMocks();
193+
});
194+
195+
it('calls getInvoiceData with correct endpoint and returns data', async () => {
196+
const api = setup();
197+
198+
let res;
199+
200+
mockGet.mockResolvedValueOnce(mockInvoiceData);
201+
202+
await act(async () => {
203+
res = await api.getInvoiceData(mockInvoiceId1);
204+
});
205+
206+
expect(mockGet).toHaveBeenCalledWith(expectedUrl1);
207+
expect(res).toEqual(mockInvoiceData);
208+
});
209+
210+
it('handles API errors correctly', async () => {
211+
const api = setup();
212+
213+
mockGet.mockRejectedValueOnce(mockNetworkError);
214+
215+
await expect(api.getInvoiceData(mockInvoiceId1)).rejects.toThrow('Network error');
216+
});
217+
218+
it('handles multiple calls correctly', async () => {
219+
const api = setup();
220+
221+
let res1;
222+
let res2;
223+
224+
mockGet.mockResolvedValueOnce(mockResponse1);
225+
mockGet.mockResolvedValueOnce(mockResponse2);
226+
227+
await act(async () => {
228+
res1 = await api.getInvoiceData(mockInvoiceId1);
229+
});
230+
231+
await act(async () => {
232+
res2 = await api.getInvoiceData(mockInvoiceId2);
233+
});
234+
235+
expect(mockGet).toHaveBeenNthCalledWith(1, expectedUrl1);
236+
expect(mockGet).toHaveBeenNthCalledWith(2, expectedUrl2);
237+
238+
expect(res1).toEqual(mockResponse1);
239+
expect(res2).toEqual(mockResponse2);
240+
});
241+
});

app/src/__tests__/useFilteredNavigation.test.tsx

Lines changed: 21 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,22 @@ import { renderHook } from '@testing-library/react-native';
22

33
import { useAuth } from '@/context/AuthContext';
44
import { useFilteredNavigation } from '@/hooks/useFilteredNavigation';
5-
import { canShowNavItem } from '@/utils/navigationPermissions';
5+
import { hasModuleAccess } from '@/utils/moduleClaims';
66

77
// Mock dependencies
88
jest.mock('@/context/AuthContext', () => ({
99
useAuth: jest.fn(),
1010
}));
1111

12-
jest.mock('@/utils/navigationPermissions', () => ({
13-
canShowNavItem: jest.fn(),
12+
jest.mock('@/utils/moduleClaims', () => ({
13+
hasModuleAccess: jest.fn(),
1414
}));
1515

16-
jest.mock('@/config/navigation-mapper.json', () => ({}));
17-
1816
describe('useFilteredNavigation', () => {
1917
const mockItems = [
20-
{ name: 'home', component: jest.fn() },
21-
{ name: 'orders', component: jest.fn() },
22-
{ name: 'billing', component: jest.fn() },
18+
{ name: 'home', component: jest.fn(), modules: ['new-marketplace'] },
19+
{ name: 'orders', component: jest.fn(), modules: ['new-marketplace'], roles: ['Client'] },
20+
{ name: 'billing', component: jest.fn(), modules: ['billing'], roles: ['Client'] },
2321
];
2422

2523
beforeEach(() => {
@@ -35,7 +33,7 @@ describe('useFilteredNavigation', () => {
3533
const { result } = renderHook(() => useFilteredNavigation(mockItems));
3634

3735
expect(result.current).toEqual(mockItems);
38-
expect(canShowNavItem).not.toHaveBeenCalled();
36+
expect(hasModuleAccess).not.toHaveBeenCalled();
3937
});
4038

4139
it('should filter items based on permissions', () => {
@@ -44,16 +42,15 @@ describe('useFilteredNavigation', () => {
4442
accountType: 'Client',
4543
});
4644

47-
(canShowNavItem as jest.Mock).mockImplementation((_token, _accountType, navItemId) => {
48-
return navItemId === 'home' || navItemId === 'orders';
45+
(hasModuleAccess as jest.Mock).mockImplementation((_token, module) => {
46+
return module === 'new-marketplace';
4947
});
5048

5149
const { result } = renderHook(() => useFilteredNavigation(mockItems));
5250

5351
expect(result.current).toHaveLength(2);
5452
expect(result.current[0].name).toBe('home');
5553
expect(result.current[1].name).toBe('orders');
56-
expect(canShowNavItem).toHaveBeenCalledTimes(3);
5754
});
5855

5956
it('should return empty array when no items match permissions', () => {
@@ -62,42 +59,37 @@ describe('useFilteredNavigation', () => {
6259
accountType: 'Client',
6360
});
6461

65-
(canShowNavItem as jest.Mock).mockReturnValue(false);
62+
(hasModuleAccess as jest.Mock).mockReturnValue(false);
6663

6764
const { result } = renderHook(() => useFilteredNavigation(mockItems));
6865

6966
expect(result.current).toEqual([]);
7067
});
7168

72-
it('should return all items when all match permissions', () => {
69+
it('should filter by role when user does not have required role', () => {
7370
(useAuth as jest.Mock).mockReturnValue({
7471
tokens: { accessToken: 'mock.token' },
75-
accountType: 'Client',
72+
accountType: 'Operations',
7673
});
7774

78-
(canShowNavItem as jest.Mock).mockReturnValue(true);
75+
(hasModuleAccess as jest.Mock).mockReturnValue(true);
7976

8077
const { result } = renderHook(() => useFilteredNavigation(mockItems));
8178

82-
expect(result.current).toEqual(mockItems);
79+
expect(result.current).toHaveLength(1);
80+
expect(result.current[0].name).toBe('home');
8381
});
8482

85-
it('should handle accountType being null', () => {
83+
it('should handle items without permissions', () => {
84+
const itemsWithoutPerms = [{ name: 'public', component: jest.fn() }];
85+
8686
(useAuth as jest.Mock).mockReturnValue({
8787
tokens: { accessToken: 'mock.token' },
88-
accountType: null,
88+
accountType: 'Client',
8989
});
9090

91-
(canShowNavItem as jest.Mock).mockReturnValue(true);
91+
const { result } = renderHook(() => useFilteredNavigation(itemsWithoutPerms));
9292

93-
const { result } = renderHook(() => useFilteredNavigation(mockItems));
94-
95-
expect(result.current).toEqual(mockItems);
96-
expect(canShowNavItem).toHaveBeenCalledWith(
97-
'mock.token',
98-
null,
99-
expect.any(String),
100-
expect.any(Object),
101-
);
93+
expect(result.current).toEqual(itemsWithoutPerms);
10294
});
10395
});

app/src/config/navigation-mapper.json

Lines changed: 0 additions & 49 deletions
This file was deleted.

0 commit comments

Comments
 (0)