Skip to content

Commit b39a482

Browse files
feat(content-sharing): Sharing service updateSharedLink (#4336)
* feat(content-sharing): Sharing service updateSharedLink * fix: expiration date conversion error --------- Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
1 parent c73965b commit b39a482

File tree

11 files changed

+577
-70
lines changed

11 files changed

+577
-70
lines changed

src/elements/content-sharing/ContentSharingV2.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,23 @@ function ContentSharingV2({
4343
const [avatarURLMap, setAvatarURLMap] = React.useState<AvatarURLMap | null>(null);
4444
const [item, setItem] = React.useState<Item | null>(null);
4545
const [sharedLink, setSharedLink] = React.useState<SharedLink | null>(null);
46+
const [sharingServiceProps, setSharingServiceProps] = React.useState(null);
4647
const [currentUser, setCurrentUser] = React.useState<User | null>(null);
4748
const [collaborationRoles, setCollaborationRoles] = React.useState<CollaborationRole[] | null>(null);
4849
const [collaborators, setCollaborators] = React.useState<Collaborator[] | null>(null);
4950
const [collaboratorsData, setCollaboratorsData] = React.useState<Collaborations | null>(null);
5051
const [owner, setOwner] = React.useState({ id: '', email: '', name: '' });
5152

52-
const { sharingService } = useSharingService(api, item, itemID, itemType, setItem, setSharedLink);
53+
const { sharingService } = useSharingService({
54+
api,
55+
item,
56+
itemId: itemID,
57+
itemType,
58+
sharedLink,
59+
sharingServiceProps,
60+
setItem,
61+
setSharedLink,
62+
});
5363

5464
// Handle successful GET requests to /files or /folders
5565
const handleGetItemSuccess = React.useCallback(itemData => {
@@ -58,10 +68,12 @@ function ContentSharingV2({
5868
item: itemFromApi,
5969
ownedBy,
6070
sharedLink: sharedLinkFromApi,
71+
sharingService: sharingServicePropsFromApi,
6172
} = convertItemResponse(itemData);
6273

6374
setItem(itemFromApi);
6475
setSharedLink(sharedLinkFromApi);
76+
setSharingServiceProps(sharingServicePropsFromApi);
6577
setCollaborationRoles(collaborationRolesFromApi);
6678
setOwner({ id: ownedBy.id, email: ownedBy.login, name: ownedBy.name });
6779
}, []);
@@ -92,11 +104,12 @@ function ContentSharingV2({
92104
if (!api || isEmpty(api) || !item || currentUser) return;
93105

94106
const getUserSuccess = userData => {
95-
const { enterprise, id } = userData;
107+
const { id, enterprise, hostname } = userData;
96108
setCurrentUser({
97109
id,
98110
enterprise: { name: enterprise ? enterprise.name : '' },
99111
});
112+
setSharedLink(prevSharedLink => ({ ...prevSharedLink, serverURL: hostname ? `${hostname}v/` : '' }));
100113
};
101114

102115
(async () => {

src/elements/content-sharing/__tests__/ContentSharingV2.test.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ describe('elements/content-sharing/ContentSharingV2', () => {
158158
test('should render UnifiedShareModal when sharingService is available', async () => {
159159
const mockSharingService = {
160160
changeSharedLinkPermission: jest.fn(),
161+
updateSharedLink: jest.fn(),
161162
};
162163

163164
(useSharingService as jest.Mock).mockReturnValue({
Lines changed: 144 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,38 @@
11
import { PERMISSION_CAN_DOWNLOAD, PERMISSION_CAN_PREVIEW } from '../../../constants';
22
import { CONTENT_SHARING_SHARED_LINK_UPDATE_PARAMS } from '../constants';
3-
import { convertSharedLinkPermissions, createSharingService } from '../sharingService';
3+
import { createSharingService } from '../sharingService';
4+
import { convertSharedLinkPermissions, convertSharedLinkSettings } from '../utils';
5+
6+
jest.mock('../utils');
7+
8+
const mockItemApiInstance = {
9+
updateSharedLink: jest.fn(),
10+
};
11+
const options = { id: '123', permissions: { can_set_share_access: true, can_share: true } };
12+
const mockOnSuccess = jest.fn();
413

514
describe('elements/content-sharing/sharingService', () => {
6-
describe('convertSharedLinkPermissions', () => {
7-
test.each([
8-
[PERMISSION_CAN_DOWNLOAD, { [PERMISSION_CAN_DOWNLOAD]: true, [PERMISSION_CAN_PREVIEW]: false }],
9-
[PERMISSION_CAN_PREVIEW, { [PERMISSION_CAN_DOWNLOAD]: false, [PERMISSION_CAN_PREVIEW]: true }],
10-
])('should return correct permissions for download permission level', (permissionLevel, expected) => {
11-
const result = convertSharedLinkPermissions(permissionLevel);
12-
expect(result).toEqual(expected);
15+
beforeEach(() => {
16+
(convertSharedLinkPermissions as jest.Mock).mockReturnValue({
17+
[PERMISSION_CAN_DOWNLOAD]: true,
18+
[PERMISSION_CAN_PREVIEW]: false,
1319
});
14-
15-
test('should handle empty string permission level', () => {
16-
const result = convertSharedLinkPermissions('');
17-
expect(result).toEqual({});
20+
(convertSharedLinkSettings as jest.Mock).mockReturnValue({
21+
unshared_at: null,
22+
vanity_url: 'https://example.com/vanity-url',
1823
});
1924
});
2025

21-
describe('createSharingService', () => {
22-
const mockItemApiInstance = {
23-
updateSharedLink: jest.fn(),
24-
};
25-
const mockItemData = { id: '123' };
26-
const mockOnSuccess = jest.fn();
27-
28-
afterEach(() => {
29-
jest.clearAllMocks();
30-
});
26+
afterEach(() => {
27+
jest.clearAllMocks();
28+
});
3129

30+
describe('changeSharedLinkPermission', () => {
3231
test('should return an object with changeSharedLinkPermission method', () => {
3332
const service = createSharingService({
3433
itemApiInstance: mockItemApiInstance,
35-
itemData: mockItemData,
3634
onSuccess: mockOnSuccess,
35+
options,
3736
});
3837

3938
expect(service).toHaveProperty('changeSharedLinkPermission');
@@ -43,8 +42,8 @@ describe('elements/content-sharing/sharingService', () => {
4342
test('should call updateSharedLink with correct parameters when changeSharedLinkPermission is called', async () => {
4443
const service = createSharingService({
4544
itemApiInstance: mockItemApiInstance,
46-
itemData: mockItemData,
4745
onSuccess: mockOnSuccess,
46+
options,
4847
});
4948

5049
const permissionLevel = PERMISSION_CAN_DOWNLOAD;
@@ -56,12 +55,132 @@ describe('elements/content-sharing/sharingService', () => {
5655
await service.changeSharedLinkPermission(permissionLevel);
5756

5857
expect(mockItemApiInstance.updateSharedLink).toHaveBeenCalledWith(
59-
mockItemData,
58+
options,
6059
{ permissions: expectedPermissions },
6160
mockOnSuccess,
6261
{},
6362
CONTENT_SHARING_SHARED_LINK_UPDATE_PARAMS,
6463
);
6564
});
6665
});
66+
67+
describe('updateSharedLink', () => {
68+
test('should return an object with updateSharedLink method', () => {
69+
const service = createSharingService({
70+
itemApiInstance: mockItemApiInstance,
71+
onSuccess: mockOnSuccess,
72+
options,
73+
});
74+
75+
expect(service).toHaveProperty('updateSharedLink');
76+
expect(typeof service.updateSharedLink).toBe('function');
77+
});
78+
79+
test('should call updateSharedLink with basic shared link settings', async () => {
80+
const service = createSharingService({
81+
itemApiInstance: mockItemApiInstance,
82+
onSuccess: mockOnSuccess,
83+
options,
84+
});
85+
86+
const sharedLinkSettings = {
87+
expiration: null,
88+
isDownloadEnabled: true,
89+
isExpirationEnabled: false,
90+
isPasswordEnabled: false,
91+
password: '',
92+
vanityName: 'vanity-name',
93+
};
94+
95+
const expectedConvertedSettings = {
96+
unshared_at: null,
97+
vanity_url: 'https://example.com/vanity-url',
98+
};
99+
100+
await service.updateSharedLink(sharedLinkSettings);
101+
102+
expect(convertSharedLinkSettings).toHaveBeenCalledWith(
103+
sharedLinkSettings,
104+
undefined, // access
105+
undefined, // isDownloadAvailable
106+
undefined, // serverURL
107+
);
108+
expect(mockItemApiInstance.updateSharedLink).toHaveBeenCalledWith(
109+
options,
110+
expectedConvertedSettings,
111+
mockOnSuccess,
112+
{},
113+
CONTENT_SHARING_SHARED_LINK_UPDATE_PARAMS,
114+
);
115+
});
116+
117+
test('should call updateSharedLink with options including access, isDownloadAvailable, and serverURL', async () => {
118+
const mockConvertedSharedLinkSettings = {
119+
password: 'test-password',
120+
permissions: { can_download: false, can_preview: true },
121+
unshared_at: null,
122+
vanity_url: 'https://example.com/vanity-url',
123+
};
124+
125+
(convertSharedLinkSettings as jest.Mock).mockReturnValue(mockConvertedSharedLinkSettings);
126+
127+
const service = createSharingService({
128+
itemApiInstance: mockItemApiInstance,
129+
onSuccess: mockOnSuccess,
130+
options: {
131+
...options,
132+
access: 'open',
133+
isDownloadAvailable: true,
134+
serverURL: 'https://example.com/server-url',
135+
},
136+
});
137+
138+
const sharedLinkSettings = {
139+
expiration: null,
140+
isDownloadEnabled: false,
141+
isExpirationEnabled: true,
142+
isPasswordEnabled: true,
143+
password: 'test-password',
144+
vanityName: 'vanity-name',
145+
};
146+
147+
await service.updateSharedLink(sharedLinkSettings);
148+
149+
expect(convertSharedLinkSettings).toHaveBeenCalledWith(
150+
sharedLinkSettings,
151+
'open',
152+
true,
153+
'https://example.com/server-url',
154+
);
155+
expect(mockItemApiInstance.updateSharedLink).toHaveBeenCalledWith(
156+
options,
157+
mockConvertedSharedLinkSettings,
158+
mockOnSuccess,
159+
{},
160+
CONTENT_SHARING_SHARED_LINK_UPDATE_PARAMS,
161+
);
162+
});
163+
164+
test('should handle shared link settings correctly', async () => {
165+
const service = createSharingService({
166+
itemApiInstance: mockItemApiInstance,
167+
onSuccess: mockOnSuccess,
168+
options,
169+
});
170+
171+
const expirationDate = new Date('2024-12-31T23:59:59Z');
172+
const sharedLinkSettings = {
173+
expiration: expirationDate,
174+
isDownloadEnabled: false,
175+
isExpirationEnabled: true,
176+
isPasswordEnabled: false,
177+
password: 'test-password',
178+
vanityName: 'vanity-name',
179+
};
180+
181+
await service.updateSharedLink(sharedLinkSettings);
182+
183+
expect(convertSharedLinkSettings).toHaveBeenCalledWith(sharedLinkSettings, undefined, undefined, undefined);
184+
});
185+
});
67186
});

0 commit comments

Comments
 (0)