From c63faee55276a76a194b13bb07205eaa7f32ebcc Mon Sep 17 00:00:00 2001 From: martincupela Date: Fri, 12 Sep 2025 16:07:03 +0200 Subject: [PATCH] fix: reflect channel config besides user permissions in AttachmentSelector --- .../MessageInput/AttachmentSelector.tsx | 12 +- .../__tests__/AttachmentSelector.test.js | 173 +++++++++++++++++- src/mock-builders/generator/channel.ts | 1 + 3 files changed, 175 insertions(+), 11 deletions(-) diff --git a/src/components/MessageInput/AttachmentSelector.tsx b/src/components/MessageInput/AttachmentSelector.tsx index 1632fc1ae..b440a6d06 100644 --- a/src/components/MessageInput/AttachmentSelector.tsx +++ b/src/components/MessageInput/AttachmentSelector.tsx @@ -163,16 +163,22 @@ const useAttachmentSelectorActionsFiltered = (original: AttachmentSelectorAction } = useComponentContext(); const { channelCapabilities } = useChannelStateContext(); const messageComposer = useMessageComposer(); + const channelConfig = messageComposer.channel.getConfig(); return original .filter((action) => { - if (action.type === 'uploadFile') return channelCapabilities['upload-file']; + if (action.type === 'uploadFile') + return channelCapabilities['upload-file'] && channelConfig?.uploads; if (action.type === 'createPoll') - return channelCapabilities['send-poll'] && !messageComposer.threadId; + return ( + channelCapabilities['send-poll'] && + !messageComposer.threadId && + channelConfig?.polls + ); if (action.type === 'addLocation') { - return messageComposer.config.location.enabled && !messageComposer.threadId; + return channelConfig?.shared_locations && !messageComposer.threadId; } return true; }) diff --git a/src/components/MessageInput/__tests__/AttachmentSelector.test.js b/src/components/MessageInput/__tests__/AttachmentSelector.test.js index da20c8600..364e3ad88 100644 --- a/src/components/MessageInput/__tests__/AttachmentSelector.test.js +++ b/src/components/MessageInput/__tests__/AttachmentSelector.test.js @@ -122,12 +122,129 @@ describe('AttachmentSelector', () => { expect(menu).toHaveTextContent('Location'); }); + it('renders with poll only if only polls are enabled', async () => { + const { + channels: [customChannel], + client: customClient, + } = await initClientWithChannels({ + channelsData: [ + { + channel: { + ...defaultChannelData, + cid: 'type:id', + config: { + polls: true, + shared_locations: false, + uploads: false, + }, + id: 'id', + type: 'type', + }, + }, + ], + }); + await renderComponent({ + channelStateContext: { channelCapabilities: { 'send-poll': true } }, + customChannel, + customClient, + }); + + await invokeMenu(); + const menu = screen.getByTestId(ATTACHMENT_SELECTOR__ACTIONS_MENU_TEST_ID); + expect(menu).toBeInTheDocument(); + expect(menu).not.toHaveTextContent('File'); + expect(menu).toHaveTextContent('Poll'); + expect(menu).not.toHaveTextContent('Location'); + }); + + it('does not render with poll only if polls are not enabled and send-poll permission is granted', async () => { + const { + channels: [customChannel], + client: customClient, + } = await initClientWithChannels({ + channelsData: [ + { + channel: { + ...defaultChannelData, + cid: 'type:id', + config: { + polls: false, + shared_locations: false, + uploads: false, + }, + id: 'id', + type: 'type', + }, + }, + ], + }); + await renderComponent({ + channelStateContext: { channelCapabilities: { 'send-poll': true } }, + customChannel, + customClient, + }); + + expect( + screen.queryByTestId('invoke-attachment-selector-button'), + ).not.toBeInTheDocument(); + }); + + it('renders with location only if only shared_locations are enabled', async () => { + const { + channels: [customChannel], + client: customClient, + } = await initClientWithChannels({ + channelsData: [ + { + channel: { + ...defaultChannelData, + cid: 'type:id', + config: { + polls: false, + shared_locations: true, + uploads: false, + }, + id: 'id', + type: 'type', + }, + }, + ], + }); + await renderComponent({ + channelStateContext: { channelCapabilities: {} }, + customChannel, + customClient, + }); + + await invokeMenu(); + const menu = screen.getByTestId(ATTACHMENT_SELECTOR__ACTIONS_MENU_TEST_ID); + expect(menu).toBeInTheDocument(); + expect(menu).not.toHaveTextContent('File'); + expect(menu).not.toHaveTextContent('Poll'); + expect(menu).toHaveTextContent('Location'); + }); + it('falls back to SimpleAttachmentSelector if only file uploads are enabled', async () => { const { channels: [customChannel], client: customClient, - } = await initClientWithChannels(); - customChannel.messageComposer.updateConfig({ location: { enabled: false } }); + } = await initClientWithChannels({ + channelsData: [ + { + channel: { + ...defaultChannelData, + cid: 'type:id', + config: { + polls: false, + shared_locations: false, + uploads: true, + }, + id: 'id', + type: 'type', + }, + }, + ], + }); const { container } = await renderComponent({ channelStateContext: { channelCapabilities: { 'upload-file': true } }, customChannel, @@ -139,17 +256,54 @@ describe('AttachmentSelector', () => { expect(screen.getByTestId('file-upload-button')).toBeInTheDocument(); }); + it('does not render SimpleAttachmentSelector neither AttachmentSelector menu if upload permission is granted but file upload disabled', async () => { + const { + channels: [customChannel], + client: customClient, + } = await initClientWithChannels({ + channelsData: [ + { + channel: { + ...defaultChannelData, + cid: 'type:id', + config: { + polls: false, + shared_locations: false, + uploads: false, + }, + id: 'id', + type: 'type', + }, + }, + ], + }); + await renderComponent({ + channelStateContext: { channelCapabilities: { 'upload-file': true } }, + customChannel, + customClient, + }); + + expect( + screen.queryByTestId('invoke-attachment-selector-button'), + ).not.toBeInTheDocument(); + expect(screen.queryByTestId('file-upload-button')).not.toBeInTheDocument(); + }); + it('renders SimpleAttachmentSelector if rendered in a thread', async () => { const { - channels: [channel], - client, + channels: [customChannel], + client: customClient, } = await initClientWithChannels({ channelsData: [ { channel: { ...defaultChannelData, cid: 'type:id', - config: defaultConfig, + config: { + polls: false, + shared_locations: false, + uploads: true, + }, id: 'id', type: 'type', }, @@ -157,9 +311,12 @@ describe('AttachmentSelector', () => { ], }); const { container } = await renderComponent({ - channel, - channelStateContext: { thread: generateMessage({ cid: channel.cid }) }, - client, + channelStateContext: { + channelCapabilities: { 'upload-file': true }, + thread: generateMessage({ cid: customChannel.cid }), + }, + customChannel, + customClient, }); expect( container.querySelector(`.${ATTACHMENT_SELECTOR_CLASS}`), diff --git a/src/mock-builders/generator/channel.ts b/src/mock-builders/generator/channel.ts index efac3dedb..38b9b2912 100644 --- a/src/mock-builders/generator/channel.ts +++ b/src/mock-builders/generator/channel.ts @@ -41,6 +41,7 @@ export const generateChannel = (options?: DeepPartial) => { read_events: true, replies: true, search: true, + shared_locations: true, typing_events: true, updated_at: '2020-04-24T11:36:43.859022903Z', uploads: true,