Skip to content

Commit 950689a

Browse files
committed
fix: control SimpleAttachmentSelector display according to channel capabilities
1 parent eb123de commit 950689a

File tree

2 files changed

+130
-12
lines changed

2 files changed

+130
-12
lines changed

src/components/MessageInput/AttachmentSelector.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export const SimpleAttachmentSelector = () => {
2727
AttachmentSelectorInitiationButtonContents,
2828
FileUploadIcon = DefaultUploadIcon,
2929
} = useComponentContext();
30+
const { channelCapabilities } = useChannelStateContext();
3031
const inputRef = useRef<HTMLInputElement | null>(null);
3132
const [labelElement, setLabelElement] = useState<HTMLLabelElement | null>(null);
3233
const id = useStableId();
@@ -44,6 +45,8 @@ export const SimpleAttachmentSelector = () => {
4445
};
4546
}, [labelElement]);
4647

48+
if (!channelCapabilities['upload-file']) return null;
49+
4750
return (
4851
<div className='str-chat__file-input-container' data-testid='file-upload-button'>
4952
<UploadFileInput id={id} ref={inputRef} />

src/components/MessageInput/__tests__/AttachmentSelector.test.js

Lines changed: 127 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
ChannelActionProvider,
88
ChannelStateProvider,
99
ComponentProvider,
10+
MessageProvider,
1011
TranslationProvider,
1112
TypingProvider,
1213
} from '../../../context';
@@ -25,6 +26,8 @@ const CREATE_POLL_BUTTON_CLASS =
2526
'str-chat__attachment-selector-actions-menu__create-poll-button';
2627
const SHARE_LOCATION_BUTTON_CLASS =
2728
'str-chat__attachment-selector-actions-menu__add-location-button';
29+
const SIMPLE_ATTACHMENT_SELECTOR_TEST_ID = 'file-upload-button';
30+
const UPLOAD_INPUT_TEST_ID = 'file-input';
2831

2932
const translationContext = {
3033
t: (v) => v,
@@ -56,6 +59,7 @@ const renderComponent = async ({
5659
componentContext,
5760
customChannel,
5861
customClient,
62+
message,
5963
messageInputProps,
6064
} = {}) => {
6165
let channel, client;
@@ -72,6 +76,20 @@ const renderComponent = async ({
7276
client = res.client;
7377
}
7478
jest.spyOn(channel, 'getDraft').mockImplementation();
79+
80+
const ThreadOrChannel = () =>
81+
channelStateContext?.thread ? (
82+
<LegacyThreadContext.Provider
83+
value={{
84+
legacyThread: channelStateContext.thread ?? undefined,
85+
}}
86+
>
87+
<MessageInput {...messageInputProps} />
88+
</LegacyThreadContext.Provider>
89+
) : (
90+
<MessageInput {...messageInputProps} />
91+
);
92+
7593
let result;
7694
await act(() => {
7795
result = render(
@@ -88,16 +106,12 @@ const renderComponent = async ({
88106
}}
89107
>
90108
<div id={CHANNEL_CONTAINER_ID}>
91-
{channelStateContext?.thread ? (
92-
<LegacyThreadContext.Provider
93-
value={{
94-
legacyThread: channelStateContext.thread ?? undefined,
95-
}}
96-
>
97-
<MessageInput {...messageInputProps} />
98-
</LegacyThreadContext.Provider>
109+
{message ? (
110+
<MessageProvider value={{ message }}>
111+
<ThreadOrChannel />
112+
</MessageProvider>
99113
) : (
100-
<MessageInput {...messageInputProps} />
114+
<ThreadOrChannel />
101115
)}
102116
</div>
103117
</ChannelStateProvider>
@@ -253,7 +267,7 @@ describe('AttachmentSelector', () => {
253267
expect(
254268
container.querySelector(`.${ATTACHMENT_SELECTOR_CLASS}`),
255269
).not.toBeInTheDocument();
256-
expect(screen.getByTestId('file-upload-button')).toBeInTheDocument();
270+
expect(screen.getByTestId(SIMPLE_ATTACHMENT_SELECTOR_TEST_ID)).toBeInTheDocument();
257271
});
258272

259273
it('does not render SimpleAttachmentSelector neither AttachmentSelector menu if upload permission is granted but file upload disabled', async () => {
@@ -286,7 +300,9 @@ describe('AttachmentSelector', () => {
286300
expect(
287301
screen.queryByTestId('invoke-attachment-selector-button'),
288302
).not.toBeInTheDocument();
289-
expect(screen.queryByTestId('file-upload-button')).not.toBeInTheDocument();
303+
expect(
304+
screen.queryByTestId(SIMPLE_ATTACHMENT_SELECTOR_TEST_ID),
305+
).not.toBeInTheDocument();
290306
});
291307

292308
it('renders SimpleAttachmentSelector if rendered in a thread', async () => {
@@ -321,7 +337,7 @@ describe('AttachmentSelector', () => {
321337
expect(
322338
container.querySelector(`.${ATTACHMENT_SELECTOR_CLASS}`),
323339
).not.toBeInTheDocument();
324-
expect(screen.getByTestId('file-upload-button')).toBeInTheDocument();
340+
expect(screen.getByTestId(SIMPLE_ATTACHMENT_SELECTOR_TEST_ID)).toBeInTheDocument();
325341
});
326342

327343
it('renders AttachmentSelector if upload-file permission is not granted', async () => {
@@ -506,3 +522,102 @@ describe('AttachmentSelector', () => {
506522
});
507523
});
508524
});
525+
526+
const AttachmentSelectorInitiationButtonContents = () => (
527+
<div data-testid={'customAttachmentSelectorInitiationButtonContents'} />
528+
);
529+
const FileUploadIcon = () => <div data-testid={'customFileUploadIcon'} />;
530+
531+
const getSimpleAttachmentSelectorInvokeElement = (container) =>
532+
container.querySelector('.str-chat__file-input-label');
533+
534+
describe('SimpleAttachmentSelector', () => {
535+
const message = generateMessage();
536+
it('renders the button', async () => {
537+
await renderComponent({ message });
538+
expect(screen.getByTestId(SIMPLE_ATTACHMENT_SELECTOR_TEST_ID)).toBeInTheDocument();
539+
});
540+
541+
it('does not render if missing "upload-file" capability', async () => {
542+
await renderComponent({
543+
channelStateContext: { channelCapabilities: { 'send-poll': true } },
544+
message,
545+
});
546+
expect(
547+
screen.queryByTestId(SIMPLE_ATTACHMENT_SELECTOR_TEST_ID),
548+
).not.toBeInTheDocument();
549+
expect(
550+
screen.queryByTestId('invoke-attachment-selector-button'),
551+
).not.toBeInTheDocument();
552+
});
553+
554+
it('opens on Space key up', async () => {
555+
const { container } = await renderComponent({ message });
556+
const inputElement = screen.getByTestId(UPLOAD_INPUT_TEST_ID);
557+
const inputClickSpy = jest.spyOn(inputElement, 'click').mockReturnValue();
558+
const label = getSimpleAttachmentSelectorInvokeElement(container);
559+
560+
fireEvent.keyUp(label, {
561+
code: 'Enter',
562+
key: 'Enter',
563+
});
564+
565+
expect(inputClickSpy).toHaveBeenCalled();
566+
});
567+
568+
it('opens on Space key up', async () => {
569+
const { container } = await renderComponent({ message });
570+
const inputElement = screen.getByTestId(UPLOAD_INPUT_TEST_ID);
571+
const inputClickSpy = jest.spyOn(inputElement, 'click').mockReturnValue();
572+
const label = getSimpleAttachmentSelectorInvokeElement(container);
573+
574+
fireEvent.keyUp(label, {
575+
code: 'Space',
576+
key: ' ',
577+
});
578+
579+
expect(inputClickSpy).toHaveBeenCalled();
580+
});
581+
582+
it('does not open on other key up', async () => {
583+
const { container } = await renderComponent({ message });
584+
const inputElement = screen.getByTestId(UPLOAD_INPUT_TEST_ID);
585+
const inputClickSpy = jest.spyOn(inputElement, 'click').mockReturnValue();
586+
const label = getSimpleAttachmentSelectorInvokeElement(container);
587+
588+
fireEvent.keyUp(label, {
589+
key: 'A',
590+
});
591+
592+
expect(inputClickSpy).not.toHaveBeenCalled();
593+
});
594+
595+
it('render custom AttachmentSelectorInitiationButtonContents', async () => {
596+
await renderComponent({
597+
componentContext: { AttachmentSelectorInitiationButtonContents },
598+
message,
599+
});
600+
expect(
601+
screen.getByTestId('customAttachmentSelectorInitiationButtonContents'),
602+
).toBeInTheDocument();
603+
});
604+
605+
it('render custom FileUploadIcon', async () => {
606+
await renderComponent({
607+
componentContext: { FileUploadIcon },
608+
message,
609+
});
610+
expect(screen.getByTestId('customFileUploadIcon')).toBeInTheDocument();
611+
});
612+
613+
it('renders AttachmentSelectorInitiationButtonContents but not FileUploadIcon', async () => {
614+
await renderComponent({
615+
componentContext: { AttachmentSelectorInitiationButtonContents, FileUploadIcon },
616+
message,
617+
});
618+
expect(
619+
screen.getByTestId('customAttachmentSelectorInitiationButtonContents'),
620+
).toBeInTheDocument();
621+
expect(screen.queryByTestId('customFileUploadIcon')).not.toBeInTheDocument();
622+
});
623+
});

0 commit comments

Comments
 (0)