Skip to content
Merged
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
92 changes: 77 additions & 15 deletions src/elements/content-sharing/__tests__/sharingService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ const options = { id: '123', permissions: { can_set_share_access: true, can_shar
const mockOnUpdateSharedLink = jest.fn();
const mockOnRemoveSharedLink = jest.fn();

const createSharingServiceWrapper = () => {
const createSharingServiceWrapper = (hasSharedLink = true) => {
return createSharingService({
hasSharedLink,
itemApiInstance: mockItemApiInstance,
onUpdateSharedLink: mockOnUpdateSharedLink,
onRemoveSharedLink: mockOnRemoveSharedLink,
Expand Down Expand Up @@ -63,6 +64,18 @@ describe('elements/content-sharing/sharingService', () => {
CONTENT_SHARING_SHARED_LINK_UPDATE_PARAMS,
);
});

test('should reject with 404 error when hasSharedLink is false', async () => {
const service = createSharingServiceWrapper(false);

await expect(service.changeSharedLinkPermission(PERMISSION_CAN_DOWNLOAD)).rejects.toEqual(
expect.objectContaining({
message: 'Shared link not found',
status: 404,
}),
);
expect(mockItemApiInstance.updateSharedLink).not.toHaveBeenCalled();
});
});

describe('changeSharedLinkAccess', () => {
Expand All @@ -87,6 +100,18 @@ describe('elements/content-sharing/sharingService', () => {
);
},
);

test('should reject with 404 error when hasSharedLink is false', async () => {
const service = createSharingServiceWrapper(false);

await expect(service.changeSharedLinkAccess('open')).rejects.toEqual(
expect.objectContaining({
message: 'Shared link not found',
status: 404,
}),
);
expect(mockItemApiInstance.share).not.toHaveBeenCalled();
});
});

describe('createSharedLink', () => {
Expand All @@ -96,22 +121,25 @@ describe('elements/content-sharing/sharingService', () => {
expect(typeof service.createSharedLink).toBe('function');
});

test('should call share with correct parameters when createSharedLink is called', async () => {
mockItemApiInstance.share.mockImplementation((_options, _access, successCallback) => {
successCallback({ id: '123', shared_link: null });
});
test.each([true, false])(
'should call share with correct parameters when createSharedLink is called',
async hasSharedLink => {
mockItemApiInstance.share.mockImplementation((_options, _access, successCallback) => {
successCallback({ id: '123', shared_link: null });
});

const service = createSharingServiceWrapper();
await service.createSharedLink();
const service = createSharingServiceWrapper(hasSharedLink);
await service.createSharedLink();

expect(mockItemApiInstance.share).toHaveBeenCalledWith(
options,
undefined,
expect.any(Function),
expect.any(Function),
CONTENT_SHARING_SHARED_LINK_UPDATE_PARAMS,
);
});
expect(mockItemApiInstance.share).toHaveBeenCalledWith(
options,
undefined,
expect.any(Function),
expect.any(Function),
CONTENT_SHARING_SHARED_LINK_UPDATE_PARAMS,
);
},
);
});

describe('deleteSharedLink', () => {
Expand All @@ -137,6 +165,18 @@ describe('elements/content-sharing/sharingService', () => {
CONTENT_SHARING_SHARED_LINK_UPDATE_PARAMS,
);
});

test('should reject with 404 error when hasSharedLink is false', async () => {
const service = createSharingServiceWrapper(false);

await expect(service.deleteSharedLink()).rejects.toEqual(
expect.objectContaining({
message: 'Shared link not found',
status: 404,
}),
);
expect(mockItemApiInstance.share).not.toHaveBeenCalled();
});
});

describe('updateSharedLink', () => {
Expand Down Expand Up @@ -200,6 +240,7 @@ describe('elements/content-sharing/sharingService', () => {
(convertSharedLinkSettings as jest.Mock).mockReturnValue(mockConvertedSharedLinkSettings);

const service = createSharingService({
hasSharedLink: true,
itemApiInstance: mockItemApiInstance,
onUpdateSharedLink: mockOnUpdateSharedLink,
onRemoveSharedLink: mockOnRemoveSharedLink,
Expand Down Expand Up @@ -258,6 +299,27 @@ describe('elements/content-sharing/sharingService', () => {

expect(convertSharedLinkSettings).toHaveBeenCalledWith(sharedLinkSettings, undefined, undefined, undefined);
});

test('should reject with 404 error when hasSharedLink is false', async () => {
const service = createSharingServiceWrapper(false);

const sharedLinkSettings = {
expiration: null,
isDownloadEnabled: true,
isExpirationEnabled: false,
isPasswordEnabled: false,
password: '',
vanityName: 'vanity-name',
};

await expect(service.updateSharedLink(sharedLinkSettings)).rejects.toEqual(
expect.objectContaining({
message: 'Shared link not found',
status: 404,
}),
);
expect(mockItemApiInstance.updateSharedLink).not.toHaveBeenCalled();
});
});

describe('error handling', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,24 @@ describe('elements/content-sharing/hooks/useSharingService', () => {
expect(createSharingService).not.toHaveBeenCalled();
});

test('should return null itemApiInstance and sharingService when sharedLink is null', () => {
test('should create sharingService when sharedLink is null', () => {
mockApi.getFileAPI.mockReturnValue({});
const { result } = renderHookWithProps({ sharedLink: null });

expect(result.current.sharingService).toEqual({ sendInvitations: expect.any(Function) });
expect(mockApi.getFileAPI).not.toHaveBeenCalled();
expect(mockApi.getFolderAPI).not.toHaveBeenCalled();
expect(createSharingService).not.toHaveBeenCalled();
expect(result.current.sharingService).toEqual({
...mockSharingService,
sendInvitations: expect.any(Function),
});
expect(mockApi.getFileAPI).toHaveBeenCalled();
expect(createSharingService).toHaveBeenCalledWith(
expect.objectContaining({
hasSharedLink: false,
options: expect.objectContaining({
access: undefined,
isDownloadAvailable: false,
}),
}),
);
});

test('should return null itemApiInstance and sharingService when itemType is neither TYPE_FILE nor TYPE_FOLDER', () => {
Expand All @@ -124,6 +135,21 @@ describe('elements/content-sharing/hooks/useSharingService', () => {
expect(createSharingService).not.toHaveBeenCalled();
});

test('should create sharingService with hasSharedLink true when sharedLink has url', () => {
mockApi.getFileAPI.mockReturnValue({});
const sharedLinkWithUrl = {
...mockSharedLink,
url: 'https://example.com/shared-link',
};
renderHookWithProps({ sharedLink: sharedLinkWithUrl });

expect(createSharingService).toHaveBeenCalledWith(
expect.objectContaining({
hasSharedLink: true,
}),
);
});

describe('when itemType is TYPE_FILE', () => {
beforeEach(() => {
mockApi.getFileAPI.mockReturnValue({});
Expand All @@ -140,6 +166,7 @@ describe('elements/content-sharing/hooks/useSharingService', () => {
sendInvitations: expect.any(Function),
});
expect(createSharingService).toHaveBeenCalledWith({
hasSharedLink: false,
itemApiInstance: {},
onUpdateSharedLink: expect.any(Function),
onRemoveSharedLink: expect.any(Function),
Expand Down Expand Up @@ -196,6 +223,7 @@ describe('elements/content-sharing/hooks/useSharingService', () => {
sendInvitations: expect.any(Function),
});
expect(createSharingService).toHaveBeenCalledWith({
hasSharedLink: false,
itemApiInstance: {},
onUpdateSharedLink: expect.any(Function),
onRemoveSharedLink: expect.any(Function),
Expand Down
9 changes: 5 additions & 4 deletions src/elements/content-sharing/hooks/useSharingService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const useSharingService = ({

// itemApiInstance should only be called once or the API will cause an issue where it gets cancelled
const itemApiInstance = React.useMemo(() => {
if (!item || !sharedLink) {
if (!item) {
return null;
}

Expand All @@ -39,7 +39,7 @@ export const useSharingService = ({
}

return null;
}, [api, item, itemType, sharedLink]);
}, [api, item, itemType]);

const sharingService = React.useMemo(() => {
if (!itemApiInstance) {
Expand All @@ -48,13 +48,13 @@ export const useSharingService = ({

const options = {
id: itemId,
access: sharedLink.access,
access: sharedLink?.access,
permissions: {
can_set_share_access: sharingServiceProps?.can_set_share_access,
can_share: sharingServiceProps?.can_share,
},
serverUrl: sharingServiceProps?.serverUrl,
isDownloadAvailable: sharedLink.settings?.isDownloadAvailable ?? false,
isDownloadAvailable: sharedLink?.settings?.isDownloadAvailable ?? false,
};

const handleUpdateSharedLink = updatedItemData => {
Expand All @@ -70,6 +70,7 @@ export const useSharingService = ({
};

return createSharingService({
hasSharedLink: !!sharedLink?.url,
itemApiInstance,
onUpdateSharedLink: handleUpdateSharedLink,
onRemoveSharedLink: handleRemoveSharedLink,
Expand Down
18 changes: 18 additions & 0 deletions src/elements/content-sharing/sharingService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ export interface Options extends ItemData {
}

export interface CreateSharingServiceArgs {
hasSharedLink: boolean;
itemApiInstance: API;
onUpdateSharedLink: (itemData: ItemData) => void;
onRemoveSharedLink: (itemData: ItemData) => void;
options: Options;
}

export const createSharingService = ({
hasSharedLink,
itemApiInstance,
onUpdateSharedLink,
onRemoveSharedLink,
Expand All @@ -35,6 +37,10 @@ export const createSharingService = ({
const { id, permissions } = options;

const changeSharedLinkAccess = async (access: string): Promise<void> => {
if (!hasSharedLink) {
return Promise.reject(Object.assign(new Error('Shared link not found'), { status: 404 }));
}

return itemApiInstance.share(
{ id, permissions },
access,
Expand All @@ -45,6 +51,10 @@ export const createSharingService = ({
};

const changeSharedLinkPermission = async (permissionLevel: string): Promise<void> => {
if (!hasSharedLink) {
return Promise.reject(Object.assign(new Error('Shared link not found'), { status: 404 }));
}

return itemApiInstance.updateSharedLink(
{ id, permissions },
{ permissions: convertSharedLinkPermissions(permissionLevel) },
Expand All @@ -55,6 +65,10 @@ export const createSharingService = ({
};

const updateSharedLink = async (sharedLinkSettings: SharedLinkSettings) => {
if (!hasSharedLink) {
return Promise.reject(Object.assign(new Error('Shared link not found'), { status: 404 }));
}

const { access, isDownloadAvailable, serverUrl } = options;

return new Promise((resolve, reject) => {
Expand Down Expand Up @@ -91,6 +105,10 @@ export const createSharingService = ({
};

const deleteSharedLink = async () => {
if (!hasSharedLink) {
return Promise.reject(Object.assign(new Error('Shared link not found'), { status: 404 }));
}

return new Promise((resolve, reject) => {
itemApiInstance.share(
{ id, permissions },
Expand Down