Skip to content

Commit b600b3b

Browse files
fix(ai): fixes reattaching the same file by always triggering the onC… (#5776)
* fix(ai): fixes reattaching the same file by always triggering the onChange event * Create thin-pants-turn.md * Update packages/react-ai/src/components/AIConversation/views/default/Form.tsx Co-authored-by: Danny Banks <djb@amazon.com> * fix changeset comment --------- Co-authored-by: Danny Banks <djb@amazon.com>
1 parent 52082ae commit b600b3b

File tree

3 files changed

+63
-1
lines changed

3 files changed

+63
-1
lines changed

.changeset/thin-pants-turn.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@aws-amplify/ui-react-ai": patch
3+
---
4+
5+
fix(ai): fixes reattaching the same file by always triggering the onChange event

packages/react-ai/src/components/AIConversation/views/default/Form.tsx

+6-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ function isHTMLFormElement(target: EventTarget): target is HTMLFormElement {
1616
return 'form' in target;
1717
}
1818

19-
export const Form: ControlsContextProps['Form'] = ({
19+
export const Form: NonNullable<ControlsContextProps['Form']> = ({
2020
setInput,
2121
input,
2222
handleSubmit,
@@ -47,6 +47,9 @@ export const Form: ControlsContextProps['Form'] = ({
4747
className={ComponentClassName.AIConversationFormAttach}
4848
onClick={() => {
4949
hiddenInput?.current?.click();
50+
if (hiddenInput?.current) {
51+
hiddenInput.current.value = '';
52+
}
5053
}}
5154
>
5255
<span>{attachIcon}</span>
@@ -67,6 +70,7 @@ export const Form: ControlsContextProps['Form'] = ({
6770
}}
6871
multiple
6972
accept="*"
73+
data-testid="hidden-file-input"
7074
/>
7175
</VisuallyHidden>
7276
</Button>
@@ -78,6 +82,7 @@ export const Form: ControlsContextProps['Form'] = ({
7882
flex="1"
7983
rows={1}
8084
value={input?.text ?? ''}
85+
testId="text-input"
8186
onKeyDown={(e) => {
8287
// Submit on enter key if shift is not pressed also
8388
const shouldSubmit = !e.shiftKey && e.key === 'Enter';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import React from 'react';
2+
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
3+
import { Form } from '../Form';
4+
5+
const setInput = jest.fn();
6+
const input = {};
7+
const handleSubmit = jest.fn();
8+
9+
describe('Form', () => {
10+
beforeEach(() => {
11+
setInput.mockClear();
12+
handleSubmit.mockClear();
13+
});
14+
15+
it('renders a Form component with the correct elements', () => {
16+
const result = render(
17+
<Form setInput={setInput} input={input} handleSubmit={handleSubmit} />
18+
);
19+
expect(result.container).toBeDefined();
20+
21+
const form = screen.findByRole('form');
22+
const buttons = screen.getAllByRole('button');
23+
const textInput = screen.getByTestId('text-input');
24+
const fileInput = screen.getByTestId('hidden-file-input');
25+
26+
expect(form).toBeDefined();
27+
expect(buttons).toHaveLength(2);
28+
expect(textInput).toBeDefined();
29+
expect(fileInput).toBeDefined();
30+
});
31+
32+
it('can upload files to the input', async () => {
33+
const result = render(
34+
<Form setInput={setInput} input={input} handleSubmit={handleSubmit} />
35+
);
36+
expect(result.container).toBeDefined();
37+
38+
const fileInput: HTMLInputElement = screen.getByTestId('hidden-file-input');
39+
const testFile = new File(['file content'], 'file.txt', {
40+
type: 'text/plain',
41+
});
42+
File.prototype.text = jest.fn().mockResolvedValueOnce('foo.txt');
43+
await waitFor(() =>
44+
fireEvent.change(fileInput, {
45+
target: { files: [testFile] },
46+
})
47+
);
48+
expect(setInput).toHaveBeenCalledTimes(1);
49+
expect(fileInput.files).not.toBeNull();
50+
expect(fileInput.files![0]).toStrictEqual(testFile);
51+
});
52+
});

0 commit comments

Comments
 (0)