From 0a4e4042afeaedae92094a21b40ff89c89f065a8 Mon Sep 17 00:00:00 2001 From: reneshen0328 Date: Thu, 9 Oct 2025 15:21:50 -0700 Subject: [PATCH 1/4] feat(content-sharing): Create sharing service changeSharedLinkPermission --- .../content-sharing/ContentSharingV2.tsx | 16 +- .../__tests__/ContentSharingV2.test.tsx | 20 +++ .../__tests__/sharingService.test.ts | 67 +++++++++ .../__tests__/useSharedLink.test.js | 6 +- .../hooks/__tests__/useSharingService.test.ts | 138 ++++++++++++++++++ .../hooks/useSharingService.ts | 44 ++++++ .../content-sharing/sharingService.ts | 27 ++++ .../__tests__/convertItemResponse.test.ts | 4 + .../utils/convertItemResponse.ts | 1 + 9 files changed, 313 insertions(+), 10 deletions(-) create mode 100644 src/elements/content-sharing/__tests__/sharingService.test.ts create mode 100644 src/elements/content-sharing/hooks/__tests__/useSharingService.test.ts create mode 100644 src/elements/content-sharing/hooks/useSharingService.ts create mode 100644 src/elements/content-sharing/sharingService.ts diff --git a/src/elements/content-sharing/ContentSharingV2.tsx b/src/elements/content-sharing/ContentSharingV2.tsx index 03f944cc5c..43221fa39c 100644 --- a/src/elements/content-sharing/ContentSharingV2.tsx +++ b/src/elements/content-sharing/ContentSharingV2.tsx @@ -8,6 +8,7 @@ import API from '../../api'; import Internationalize from '../common/Internationalize'; import Providers from '../common/Providers'; import { fetchAvatars, fetchCollaborators, fetchCurrentUser, fetchItem } from './apis'; +import { useSharingService } from './hooks/useSharingService'; import { convertCollabsResponse, convertItemResponse } from './utils'; import type { Collaborations, ItemType, StringMap } from '../../common/types/core'; @@ -48,18 +49,20 @@ function ContentSharingV2({ const [collaboratorsData, setCollaboratorsData] = React.useState(null); const [owner, setOwner] = React.useState({ id: '', email: '', name: '' }); + const { sharingService } = useSharingService(api, item, itemID, itemType, setItem, setSharedLink); + // Handle successful GET requests to /files or /folders const handleGetItemSuccess = React.useCallback(itemData => { const { - collaborationRoles: collaborationRolesFromAPI, - item: itemFromAPI, + collaborationRoles: collaborationRolesFromApi, + item: itemFromApi, ownedBy, - sharedLink: sharedLinkFromAPI, + sharedLink: sharedLinkFromApi, } = convertItemResponse(itemData); - setItem(itemFromAPI); - setSharedLink(sharedLinkFromAPI); - setCollaborationRoles(collaborationRolesFromAPI); + setItem(itemFromApi); + setSharedLink(sharedLinkFromApi); + setCollaborationRoles(collaborationRolesFromApi); setOwner({ id: ownedBy.id, email: ownedBy.login, name: ownedBy.name }); }, []); @@ -151,6 +154,7 @@ function ContentSharingV2({ currentUser={currentUser} item={item} sharedLink={sharedLink} + sharingService={sharingService} > {children} diff --git a/src/elements/content-sharing/__tests__/ContentSharingV2.test.tsx b/src/elements/content-sharing/__tests__/ContentSharingV2.test.tsx index 74daee3161..1f86f7c99a 100644 --- a/src/elements/content-sharing/__tests__/ContentSharingV2.test.tsx +++ b/src/elements/content-sharing/__tests__/ContentSharingV2.test.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { render, RenderResult, screen, waitFor } from '@testing-library/react'; +import { useSharingService } from '../hooks/useSharingService'; import { DEFAULT_ITEM_API_RESPONSE, DEFAULT_USER_API_RESPONSE, @@ -46,6 +47,10 @@ const defaultAPIMock = createAPIMock( { getCollaborations: getCollaborationsMock }, ); +jest.mock('../hooks/useSharingService', () => ({ + useSharingService: jest.fn().mockReturnValue({ sharingService: null }), +})); + const getWrapper = (props): RenderResult => render( { expect(getAvatarUrlMock).toHaveBeenCalledWith('458', MOCK_ITEM.id); }); }); + + test('should render UnifiedShareModal when sharingService is available', async () => { + const mockSharingService = { + changeSharedLinkPermission: jest.fn(), + }; + + (useSharingService as jest.Mock).mockReturnValue({ + useSharingService: jest.fn().mockReturnValue({ sharingService: mockSharingService }), + }); + + getWrapper({}); + await waitFor(() => { + expect(screen.getByRole('heading', { name: /Box Development Guide.pdf/i })).toBeVisible(); + }); + }); }); diff --git a/src/elements/content-sharing/__tests__/sharingService.test.ts b/src/elements/content-sharing/__tests__/sharingService.test.ts new file mode 100644 index 0000000000..9cf7e278ff --- /dev/null +++ b/src/elements/content-sharing/__tests__/sharingService.test.ts @@ -0,0 +1,67 @@ +import { PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW } from '../../../constants'; +import { CONTENT_SHARING_SHARED_LINK_UPDATE_PARAMS } from '../constants'; +import { convertSharedLinkPermissions, createSharingService } from '../sharingService'; + +describe('content-sharing/sharingService', () => { + describe('convertSharedLinkPermissions', () => { + test.each([ + [PERMISSION_CAN_DOWNLOAD, { [PERMISSION_CAN_DOWNLOAD]: true, [PERMISSION_CAN_PREVIEW]: false }], + [PERMISSION_CAN_PREVIEW, { [PERMISSION_CAN_DOWNLOAD]: false, [PERMISSION_CAN_PREVIEW]: true }], + ])('should return correct permissions for download permission level', (permissionLevel, expected) => { + const result = convertSharedLinkPermissions(permissionLevel); + expect(result).toEqual(expected); + }); + + test('should handle empty string permission level', () => { + const result = convertSharedLinkPermissions(''); + expect(result).toEqual({}); + }); + }); + + describe('createSharingService', () => { + const mockItemApiInstance = { + updateSharedLink: jest.fn(), + }; + const mockItemData = { id: '123' }; + const mockOnSuccess = jest.fn(); + + afterEach(() => { + jest.clearAllMocks(); + }); + + test('should return an object with changeSharedLinkPermission method', () => { + const service = createSharingService({ + itemApiInstance: mockItemApiInstance, + itemData: mockItemData, + onSuccess: mockOnSuccess, + }); + + expect(service).toHaveProperty('changeSharedLinkPermission'); + expect(typeof service.changeSharedLinkPermission).toBe('function'); + }); + + test('should call updateSharedLink with correct parameters when changeSharedLinkPermission is called', async () => { + const service = createSharingService({ + itemApiInstance: mockItemApiInstance, + itemData: mockItemData, + onSuccess: mockOnSuccess, + }); + + const permissionLevel = PERMISSION_CAN_DOWNLOAD; + const expectedPermissions = { + [PERMISSION_CAN_DOWNLOAD]: true, + [PERMISSION_CAN_PREVIEW]: false, + }; + + await service.changeSharedLinkPermission(permissionLevel); + + expect(mockItemApiInstance.updateSharedLink).toHaveBeenCalledWith( + mockItemData, + { permissions: expectedPermissions }, + mockOnSuccess, + {}, + CONTENT_SHARING_SHARED_LINK_UPDATE_PARAMS, + ); + }); + }); +}); diff --git a/src/elements/content-sharing/__tests__/useSharedLink.test.js b/src/elements/content-sharing/__tests__/useSharedLink.test.js index 0d38a1c160..f83db63b20 100644 --- a/src/elements/content-sharing/__tests__/useSharedLink.test.js +++ b/src/elements/content-sharing/__tests__/useSharedLink.test.js @@ -36,10 +36,8 @@ function FakeComponent({ const [changeSharedLinkAccessLevel, setChangeSharedLinkAccessLevel] = React.useState( null, ); - const [ - changeSharedLinkPermissionLevel, - setChangeSharedLinkPermissionLevel, - ] = React.useState(null); + const [changeSharedLinkPermissionLevel, setChangeSharedLinkPermissionLevel] = + React.useState(null); const [onSubmitSettings, setOnSubmitSettings] = React.useState(null); const [generatedFunctions, setGeneratedFunctions] = React.useState(false); diff --git a/src/elements/content-sharing/hooks/__tests__/useSharingService.test.ts b/src/elements/content-sharing/hooks/__tests__/useSharingService.test.ts new file mode 100644 index 0000000000..cb2de99347 --- /dev/null +++ b/src/elements/content-sharing/hooks/__tests__/useSharingService.test.ts @@ -0,0 +1,138 @@ +import { renderHook } from '@testing-library/react'; + +import { TYPE_FILE, TYPE_FOLDER } from '../../../../constants'; +import { createSharingService } from '../../sharingService'; +import { convertItemResponse } from '../../utils/convertItemResponse'; +import { useSharingService } from '../useSharingService'; + +jest.mock('../../utils/convertItemResponse'); +jest.mock('../../sharingService'); + +const mockApi = { + getFileAPI: jest.fn(), + getFolderAPI: jest.fn(), +}; +const mockItemApiInstance = { + updateSharedLink: jest.fn(), +}; +const mockSharingService = { + changeSharedLinkPermission: jest.fn(), +}; + +const mockItemId = '123'; +const mockItem = { + id: mockItemId, + permissions: { + can_download: true, + can_preview: false, + }, +}; + +const mockSetItem = jest.fn(); +const mockSetSharedLink = jest.fn(); + +describe('content-sharing/hooks/useSharingService', () => { + beforeEach(() => { + (createSharingService as jest.Mock).mockReturnValue(mockSharingService); + (convertItemResponse as jest.Mock).mockReturnValue({ + item: mockItem, + sharedLink: {}, + }); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + test('should return null itemApiInstance and sharingService when item is null', () => { + const { result } = renderHook(() => + useSharingService(mockApi, null, mockItemId, TYPE_FILE, mockSetItem, mockSetSharedLink), + ); + + expect(result.current.sharingService).toBeNull(); + expect(mockApi.getFileAPI).not.toHaveBeenCalled(); + expect(mockApi.getFolderAPI).not.toHaveBeenCalled(); + expect(createSharingService).not.toHaveBeenCalled(); + }); + + test('should return null itemApiInstance and sharingService when itemType is neither TYPE_FILE nor TYPE_FOLDER', () => { + const { result } = renderHook(() => + useSharingService(mockApi, mockItem, mockItemId, 'hubs', mockSetItem, mockSetSharedLink), + ); + + expect(result.current.sharingService).toBeNull(); + expect(mockApi.getFileAPI).not.toHaveBeenCalled(); + expect(mockApi.getFolderAPI).not.toHaveBeenCalled(); + expect(createSharingService).not.toHaveBeenCalled(); + }); + + describe('when itemType is TYPE_FILE', () => { + beforeEach(() => { + mockApi.getFileAPI.mockReturnValue(mockItemApiInstance); + }); + + test('should create file API instance and sharing service', () => { + const { result } = renderHook(() => + useSharingService(mockApi, mockItem, mockItemId, TYPE_FILE, mockSetItem, mockSetSharedLink), + ); + + expect(mockApi.getFileAPI).toHaveBeenCalled(); + expect(mockApi.getFolderAPI).not.toHaveBeenCalled(); + expect(result.current.sharingService).toBe(mockSharingService); + expect(createSharingService).toHaveBeenCalledWith({ + itemApiInstance: mockItemApiInstance, + itemData: { + id: mockItemId, + permissions: mockItem.permissions, + }, + onSuccess: expect.any(Function), + }); + }); + + test('should handle success callback correctly', () => { + const mockConvertedData = { + item: { + id: mockItemId, + permissions: { can_download: false }, + }, + sharedLink: {}, + }; + + (convertItemResponse as jest.Mock).mockReturnValue(mockConvertedData); + renderHook(() => + useSharingService(mockApi, mockItem, mockItemId, TYPE_FILE, mockSetItem, mockSetSharedLink), + ); + + // Get the onSuccess callback that was passed to mock createSharingService + const onSuccessCallback = (createSharingService as jest.Mock).mock.calls[0][0].onSuccess; + onSuccessCallback(mockConvertedData); + + expect(mockSetItem).toHaveBeenCalledTimes(1); + expect(mockSetSharedLink).toHaveBeenCalledTimes(1); + }); + }); + + describe('when itemType is TYPE_FOLDER', () => { + beforeEach(() => { + mockApi.getFolderAPI.mockReturnValue(mockItemApiInstance); + }); + + test('should create folder API instance and sharing service', () => { + const { result } = renderHook(() => + useSharingService(mockApi, mockItem, mockItemId, TYPE_FOLDER, mockSetItem, mockSetSharedLink), + ); + + expect(mockApi.getFolderAPI).toHaveBeenCalled(); + expect(mockApi.getFileAPI).not.toHaveBeenCalled(); + expect(result.current.sharingService).toBe(mockSharingService); + expect(createSharingService).toHaveBeenCalledWith({ + itemApiInstance: mockItemApiInstance, + itemData: { + id: mockItemId, + permissions: mockItem.permissions, + }, + onSuccess: expect.any(Function), + }); + }); + }); +}); diff --git a/src/elements/content-sharing/hooks/useSharingService.ts b/src/elements/content-sharing/hooks/useSharingService.ts new file mode 100644 index 0000000000..571cc098a3 --- /dev/null +++ b/src/elements/content-sharing/hooks/useSharingService.ts @@ -0,0 +1,44 @@ +import * as React from 'react'; + +import { TYPE_FILE, TYPE_FOLDER } from '../../../constants'; +import { convertItemResponse } from '../utils/convertItemResponse'; +import { createSharingService } from '../sharingService'; + +export const useSharingService = (api, item, itemId, itemType, setItem, setSharedLink) => { + const itemApiInstance = React.useMemo(() => { + if (!item) { + return null; + } + + if (itemType === TYPE_FILE) { + return api.getFileAPI(); + } + + if (itemType === TYPE_FOLDER) { + return api.getFolderAPI(); + } + + return null; + }, [api, item, itemType]); + + const sharingService = React.useMemo(() => { + if (!itemApiInstance) { + return null; + } + + const itemData = { + id: itemId, + permissions: item.permissions, + }; + + const handleSuccess = updatedItemData => { + const { item: updatedItem, sharedLink: updatedSharedLink } = convertItemResponse(updatedItemData); + setItem(prevItem => ({ ...prevItem, ...updatedItem })); + setSharedLink(prevSharedLink => ({ ...prevSharedLink, ...updatedSharedLink })); + }; + + return createSharingService({ itemApiInstance, itemData, onSuccess: handleSuccess }); + }, [itemApiInstance, item, itemId, setItem, setSharedLink]); + + return { sharingService }; +}; diff --git a/src/elements/content-sharing/sharingService.ts b/src/elements/content-sharing/sharingService.ts new file mode 100644 index 0000000000..d24a9f5afb --- /dev/null +++ b/src/elements/content-sharing/sharingService.ts @@ -0,0 +1,27 @@ +import { PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW } from '../../constants'; +import { CONTENT_SHARING_SHARED_LINK_UPDATE_PARAMS } from './constants'; + +export const convertSharedLinkPermissions = (permissionLevel: string) => { + if (!permissionLevel) return {}; + + return { + [PERMISSION_CAN_DOWNLOAD]: permissionLevel === PERMISSION_CAN_DOWNLOAD, + [PERMISSION_CAN_PREVIEW]: permissionLevel === PERMISSION_CAN_PREVIEW, + }; +}; + +export const createSharingService = ({ itemApiInstance, itemData, onSuccess }) => { + const changeSharedLinkPermission = async (permissionLevel: string) => { + return itemApiInstance.updateSharedLink( + itemData, + { permissions: convertSharedLinkPermissions(permissionLevel) }, + onSuccess, + {}, + CONTENT_SHARING_SHARED_LINK_UPDATE_PARAMS, + ); + }; + + return { + changeSharedLinkPermission, + }; +}; diff --git a/src/elements/content-sharing/utils/__tests__/convertItemResponse.test.ts b/src/elements/content-sharing/utils/__tests__/convertItemResponse.test.ts index b21d1ea1b7..14ad6177aa 100644 --- a/src/elements/content-sharing/utils/__tests__/convertItemResponse.test.ts +++ b/src/elements/content-sharing/utils/__tests__/convertItemResponse.test.ts @@ -33,6 +33,10 @@ describe('convertItemResponse', () => { canInviteCollaborator: true, canSetShareAccess: true, canShare: true, + can_download: true, + can_invite_collaborator: true, + can_set_share_access: true, + can_share: true, }, type: 'file', }, diff --git a/src/elements/content-sharing/utils/convertItemResponse.ts b/src/elements/content-sharing/utils/convertItemResponse.ts index 31e108439e..8b9ca36d6d 100644 --- a/src/elements/content-sharing/utils/convertItemResponse.ts +++ b/src/elements/content-sharing/utils/convertItemResponse.ts @@ -96,6 +96,7 @@ export const convertItemResponse = (itemAPIData: ContentSharingItemAPIResponse): canInviteCollaborator: !!canInvite, canSetShareAccess: canChangeAccessLevel, canShare: !!canShare, + ...permissions, }, type, }, From e97bb3cbd594247b25927233a8ae1ea7b1df4bcf Mon Sep 17 00:00:00 2001 From: reneshen0328 Date: Thu, 9 Oct 2025 17:00:17 -0700 Subject: [PATCH 2/4] feat(content-sharing): Create sharing service changeSharedLinkPermission --- .../__tests__/ContentSharingV2.test.tsx | 15 ++++++++------- .../__tests__/sharingService.test.ts | 2 +- .../hooks/__tests__/useSharingService.test.ts | 2 +- src/elements/content-sharing/sharingService.ts | 4 +++- .../utils/__tests__/convertItemResponse.test.ts | 8 ++++---- .../content-sharing/utils/convertItemResponse.ts | 5 ++++- 6 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/elements/content-sharing/__tests__/ContentSharingV2.test.tsx b/src/elements/content-sharing/__tests__/ContentSharingV2.test.tsx index 1f86f7c99a..afacabe48d 100644 --- a/src/elements/content-sharing/__tests__/ContentSharingV2.test.tsx +++ b/src/elements/content-sharing/__tests__/ContentSharingV2.test.tsx @@ -51,7 +51,7 @@ jest.mock('../hooks/useSharingService', () => ({ useSharingService: jest.fn().mockReturnValue({ sharingService: null }), })); -const getWrapper = (props): RenderResult => +const renderComponent = (props = {}): RenderResult => render( { }); test('should see the correct elements for files', async () => { - getWrapper({}); + renderComponent(); await waitFor(() => { expect(getDefaultFileMock).toHaveBeenCalledWith(MOCK_ITEM.id, expect.any(Function), expect.any(Function), { fields: CONTENT_SHARING_ITEM_FIELDS, @@ -80,7 +80,7 @@ describe('elements/content-sharing/ContentSharingV2', () => { }); test('should see the correct elements for folders', async () => { - getWrapper({ itemType: 'folder' }); + renderComponent({ itemType: 'folder' }); await waitFor(() => { expect(getDefaultFolderMock).toHaveBeenCalledWith( MOCK_ITEM.id, @@ -101,7 +101,7 @@ describe('elements/content-sharing/ContentSharingV2', () => { ...defaultAPIMock, getFileAPI: jest.fn().mockReturnValue({ getFile: getFileMockWithSharedLink }), }; - getWrapper({ api: apiWithSharedLink }); + renderComponent({ api: apiWithSharedLink }); await waitFor(() => { expect(getFileMockWithSharedLink).toHaveBeenCalledWith( MOCK_ITEM.id, @@ -125,7 +125,8 @@ describe('elements/content-sharing/ContentSharingV2', () => { ...defaultAPIMock, getFileAPI: jest.fn().mockReturnValue({ getFile: getFileMockWithClassification }), }; - getWrapper({ api: apiWithClassification }); + + renderComponent({ api: apiWithClassification }); await waitFor(() => { expect(getFileMockWithClassification).toHaveBeenCalledWith( MOCK_ITEM.id, @@ -140,7 +141,7 @@ describe('elements/content-sharing/ContentSharingV2', () => { }); test('should process collaborators with avatars correctly', async () => { - getWrapper({}); + renderComponent(); await waitFor(() => { expect(getCollaborationsMock).toHaveBeenCalledWith( @@ -163,7 +164,7 @@ describe('elements/content-sharing/ContentSharingV2', () => { useSharingService: jest.fn().mockReturnValue({ sharingService: mockSharingService }), }); - getWrapper({}); + renderComponent(); await waitFor(() => { expect(screen.getByRole('heading', { name: /Box Development Guide.pdf/i })).toBeVisible(); }); diff --git a/src/elements/content-sharing/__tests__/sharingService.test.ts b/src/elements/content-sharing/__tests__/sharingService.test.ts index 9cf7e278ff..6936f7e976 100644 --- a/src/elements/content-sharing/__tests__/sharingService.test.ts +++ b/src/elements/content-sharing/__tests__/sharingService.test.ts @@ -2,7 +2,7 @@ import { PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW } from '../../../consta import { CONTENT_SHARING_SHARED_LINK_UPDATE_PARAMS } from '../constants'; import { convertSharedLinkPermissions, createSharingService } from '../sharingService'; -describe('content-sharing/sharingService', () => { +describe('elements/content-sharing/sharingService', () => { describe('convertSharedLinkPermissions', () => { test.each([ [PERMISSION_CAN_DOWNLOAD, { [PERMISSION_CAN_DOWNLOAD]: true, [PERMISSION_CAN_PREVIEW]: false }], diff --git a/src/elements/content-sharing/hooks/__tests__/useSharingService.test.ts b/src/elements/content-sharing/hooks/__tests__/useSharingService.test.ts index cb2de99347..d0d6eb3567 100644 --- a/src/elements/content-sharing/hooks/__tests__/useSharingService.test.ts +++ b/src/elements/content-sharing/hooks/__tests__/useSharingService.test.ts @@ -31,7 +31,7 @@ const mockItem = { const mockSetItem = jest.fn(); const mockSetSharedLink = jest.fn(); -describe('content-sharing/hooks/useSharingService', () => { +describe('elements/content-sharing/hooks/useSharingService', () => { beforeEach(() => { (createSharingService as jest.Mock).mockReturnValue(mockSharingService); (convertItemResponse as jest.Mock).mockReturnValue({ diff --git a/src/elements/content-sharing/sharingService.ts b/src/elements/content-sharing/sharingService.ts index d24a9f5afb..b5a960afed 100644 --- a/src/elements/content-sharing/sharingService.ts +++ b/src/elements/content-sharing/sharingService.ts @@ -2,7 +2,9 @@ import { PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW } from '../../constants import { CONTENT_SHARING_SHARED_LINK_UPDATE_PARAMS } from './constants'; export const convertSharedLinkPermissions = (permissionLevel: string) => { - if (!permissionLevel) return {}; + if (!permissionLevel) { + return null; + } return { [PERMISSION_CAN_DOWNLOAD]: permissionLevel === PERMISSION_CAN_DOWNLOAD, diff --git a/src/elements/content-sharing/utils/__tests__/convertItemResponse.test.ts b/src/elements/content-sharing/utils/__tests__/convertItemResponse.test.ts index 14ad6177aa..fdd3378f88 100644 --- a/src/elements/content-sharing/utils/__tests__/convertItemResponse.test.ts +++ b/src/elements/content-sharing/utils/__tests__/convertItemResponse.test.ts @@ -33,10 +33,6 @@ describe('convertItemResponse', () => { canInviteCollaborator: true, canSetShareAccess: true, canShare: true, - can_download: true, - can_invite_collaborator: true, - can_set_share_access: true, - can_share: true, }, type: 'file', }, @@ -45,6 +41,10 @@ describe('convertItemResponse', () => { login: mockOwnerEmail, name: mockOwnerName, }, + sharingService: { + can_set_share_access: true, + can_share: true, + }, }); }); diff --git a/src/elements/content-sharing/utils/convertItemResponse.ts b/src/elements/content-sharing/utils/convertItemResponse.ts index 8b9ca36d6d..51d1be9060 100644 --- a/src/elements/content-sharing/utils/convertItemResponse.ts +++ b/src/elements/content-sharing/utils/convertItemResponse.ts @@ -96,11 +96,14 @@ export const convertItemResponse = (itemAPIData: ContentSharingItemAPIResponse): canInviteCollaborator: !!canInvite, canSetShareAccess: canChangeAccessLevel, canShare: !!canShare, - ...permissions, }, type, }, sharedLink, + sharingService: { + can_set_share_access: canChangeAccessLevel, + can_share: canShare, + }, ownedBy, }; }; From aa3e67a15c0c2b63519c7b635281289d0bc8640b Mon Sep 17 00:00:00 2001 From: reneshen0328 Date: Thu, 9 Oct 2025 17:09:15 -0700 Subject: [PATCH 3/4] feat(content-sharing): Create sharing service changeSharedLinkPermission --- src/elements/content-sharing/sharingService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/elements/content-sharing/sharingService.ts b/src/elements/content-sharing/sharingService.ts index b5a960afed..8cf61123c7 100644 --- a/src/elements/content-sharing/sharingService.ts +++ b/src/elements/content-sharing/sharingService.ts @@ -3,7 +3,7 @@ import { CONTENT_SHARING_SHARED_LINK_UPDATE_PARAMS } from './constants'; export const convertSharedLinkPermissions = (permissionLevel: string) => { if (!permissionLevel) { - return null; + return {}; } return { From b937d4c87de6976aa00985a53816c8d609aab4b6 Mon Sep 17 00:00:00 2001 From: reneshen0328 Date: Thu, 9 Oct 2025 17:14:32 -0700 Subject: [PATCH 4/4] feat(content-sharing): nits --- .../content-sharing/__tests__/ContentSharingV2.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/elements/content-sharing/__tests__/ContentSharingV2.test.tsx b/src/elements/content-sharing/__tests__/ContentSharingV2.test.tsx index afacabe48d..a1d06a2214 100644 --- a/src/elements/content-sharing/__tests__/ContentSharingV2.test.tsx +++ b/src/elements/content-sharing/__tests__/ContentSharingV2.test.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { render, RenderResult, screen, waitFor } from '@testing-library/react'; +import { render, type RenderResult, screen, waitFor } from '@testing-library/react'; import { useSharingService } from '../hooks/useSharingService'; import { @@ -161,7 +161,7 @@ describe('elements/content-sharing/ContentSharingV2', () => { }; (useSharingService as jest.Mock).mockReturnValue({ - useSharingService: jest.fn().mockReturnValue({ sharingService: mockSharingService }), + sharingService: mockSharingService, }); renderComponent();