stream-chat-react-native-core 4.9.0-beta.3 → 4.9.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/lib/commonjs/components/Attachment/Gallery.js +11 -9
  2. package/lib/commonjs/components/Attachment/Gallery.js.map +1 -1
  3. package/lib/commonjs/components/Attachment/VideoThumbnail.js +11 -5
  4. package/lib/commonjs/components/Attachment/VideoThumbnail.js.map +1 -1
  5. package/lib/commonjs/components/Attachment/utils/buildGallery/buildThumbnail.js +1 -0
  6. package/lib/commonjs/components/Attachment/utils/buildGallery/buildThumbnail.js.map +1 -1
  7. package/lib/commonjs/components/Message/Message.js +7 -6
  8. package/lib/commonjs/components/Message/Message.js.map +1 -1
  9. package/lib/commonjs/contexts/messageInputContext/MessageInputContext.js +20 -27
  10. package/lib/commonjs/contexts/messageInputContext/MessageInputContext.js.map +1 -1
  11. package/lib/commonjs/mock-builders/generator/attachment.js +3 -2
  12. package/lib/commonjs/mock-builders/generator/attachment.js.map +1 -1
  13. package/lib/commonjs/utils/getUrlOfImageAttachment.js +1 -1
  14. package/lib/commonjs/utils/getUrlOfImageAttachment.js.map +1 -1
  15. package/lib/commonjs/version.json +1 -1
  16. package/lib/module/components/Attachment/Gallery.js +11 -9
  17. package/lib/module/components/Attachment/Gallery.js.map +1 -1
  18. package/lib/module/components/Attachment/VideoThumbnail.js +11 -5
  19. package/lib/module/components/Attachment/VideoThumbnail.js.map +1 -1
  20. package/lib/module/components/Attachment/utils/buildGallery/buildThumbnail.js +1 -0
  21. package/lib/module/components/Attachment/utils/buildGallery/buildThumbnail.js.map +1 -1
  22. package/lib/module/components/Message/Message.js +7 -6
  23. package/lib/module/components/Message/Message.js.map +1 -1
  24. package/lib/module/contexts/messageInputContext/MessageInputContext.js +20 -27
  25. package/lib/module/contexts/messageInputContext/MessageInputContext.js.map +1 -1
  26. package/lib/module/mock-builders/generator/attachment.js +3 -2
  27. package/lib/module/mock-builders/generator/attachment.js.map +1 -1
  28. package/lib/module/utils/getUrlOfImageAttachment.js +1 -1
  29. package/lib/module/utils/getUrlOfImageAttachment.js.map +1 -1
  30. package/lib/module/version.json +1 -1
  31. package/lib/typescript/components/Attachment/VideoThumbnail.d.ts +3 -1
  32. package/lib/typescript/components/Attachment/utils/buildGallery/types.d.ts +1 -0
  33. package/lib/typescript/contexts/messageInputContext/MessageInputContext.d.ts +1 -0
  34. package/lib/typescript/contexts/messageInputContext/__tests__/MessageInputContext.test.d.ts +1 -0
  35. package/lib/typescript/contexts/messageInputContext/__tests__/isValidMessage.test.d.ts +1 -0
  36. package/lib/typescript/contexts/messageInputContext/__tests__/pickFile.test.d.ts +1 -0
  37. package/lib/typescript/contexts/messageInputContext/__tests__/removeFile.test.d.ts +1 -0
  38. package/lib/typescript/contexts/messageInputContext/__tests__/removeImage.test.d.ts +1 -0
  39. package/lib/typescript/contexts/messageInputContext/__tests__/sendMessage.test.d.ts +1 -0
  40. package/lib/typescript/contexts/messageInputContext/__tests__/sendMessageAsync.test.d.ts +1 -0
  41. package/lib/typescript/contexts/messageInputContext/__tests__/updateMessage.test.d.ts +1 -0
  42. package/lib/typescript/contexts/messageInputContext/__tests__/uploadFile.test.d.ts +1 -0
  43. package/lib/typescript/contexts/messageInputContext/__tests__/uploadImage.test.d.ts +1 -0
  44. package/lib/typescript/contexts/messageInputContext/__tests__/useMessageDetailsForState.test.d.ts +1 -0
  45. package/lib/typescript/mock-builders/generator/attachment.d.ts +10 -0
  46. package/lib/typescript/mock-builders/generator/channel.d.ts +13 -13
  47. package/lib/typescript/mock-builders/generator/message.d.ts +38 -0
  48. package/lib/typescript/mock-builders/generator/user.d.ts +9 -9
  49. package/package.json +5 -4
  50. package/src/components/Attachment/Gallery.tsx +2 -1
  51. package/src/components/Attachment/VideoThumbnail.tsx +12 -5
  52. package/src/components/Attachment/__tests__/Attachment.test.js +12 -0
  53. package/src/components/Attachment/__tests__/Gallery.test.js +23 -1
  54. package/src/components/Attachment/utils/buildGallery/buildThumbnail.ts +1 -0
  55. package/src/components/Attachment/utils/buildGallery/types.ts +1 -0
  56. package/src/components/Message/Message.tsx +5 -1
  57. package/src/contexts/messageInputContext/MessageInputContext.tsx +3 -4
  58. package/src/contexts/messageInputContext/__tests__/MessageInputContext.test.tsx +208 -0
  59. package/src/contexts/messageInputContext/__tests__/__snapshots__/sendMessage.test.tsx.snap +109 -0
  60. package/src/contexts/messageInputContext/__tests__/__snapshots__/sendMessageAsync.test.tsx.snap +33 -0
  61. package/src/contexts/messageInputContext/__tests__/isValidMessage.test.tsx +71 -0
  62. package/src/contexts/messageInputContext/__tests__/pickFile.test.tsx +67 -0
  63. package/src/contexts/messageInputContext/__tests__/removeFile.test.tsx +82 -0
  64. package/src/contexts/messageInputContext/__tests__/removeImage.test.tsx +80 -0
  65. package/src/contexts/messageInputContext/__tests__/sendMessage.test.tsx +286 -0
  66. package/src/contexts/messageInputContext/__tests__/sendMessageAsync.test.tsx +124 -0
  67. package/src/contexts/messageInputContext/__tests__/updateMessage.test.tsx +92 -0
  68. package/src/contexts/messageInputContext/__tests__/uploadFile.test.tsx +76 -0
  69. package/src/contexts/messageInputContext/__tests__/uploadImage.test.tsx +55 -0
  70. package/src/contexts/messageInputContext/__tests__/useMessageDetailsForState.test.tsx +62 -0
  71. package/src/mock-builders/generator/attachment.js +4 -2
  72. package/src/utils/getUrlOfImageAttachment.ts +1 -1
  73. package/src/version.json +1 -1
@@ -31,20 +31,20 @@ export function generateChannel(customValues: any): {
31
31
  created_by: {
32
32
  banned: boolean;
33
33
  created_at: string;
34
- id: any;
35
- image: any;
36
- name: any;
34
+ id: string;
35
+ image: string;
36
+ name: string;
37
37
  online: boolean;
38
38
  role: string;
39
39
  updated_at: string;
40
40
  };
41
41
  frozen: boolean;
42
- id: any;
42
+ id: string;
43
43
  own_capabilities: string[];
44
44
  type: string;
45
45
  updated_at: string;
46
46
  };
47
- id: any;
47
+ id: string;
48
48
  state: {
49
49
  members: {};
50
50
  messages: never[];
@@ -54,18 +54,18 @@ export function generateChannel(customValues: any): {
54
54
  };
55
55
  export function generateChannelResponse(customValues?: {
56
56
  channel: {};
57
- id: any;
57
+ id: string;
58
58
  type: string;
59
59
  }): {
60
60
  channel: {
61
- id: any;
61
+ id: string;
62
62
  type: string;
63
63
  user: {
64
64
  banned: boolean;
65
65
  created_at: string;
66
- id: any;
67
- image: any;
68
- name: any;
66
+ id: string;
67
+ image: string;
68
+ name: string;
69
69
  online: boolean;
70
70
  role: string;
71
71
  updated_at: string;
@@ -100,9 +100,9 @@ export function generateChannelResponse(customValues?: {
100
100
  created_by: {
101
101
  banned: boolean;
102
102
  created_at: string;
103
- id: any;
104
- image: any;
105
- name: any;
103
+ id: string;
104
+ image: string;
105
+ name: string;
106
106
  online: boolean;
107
107
  role: string;
108
108
  updated_at: string;
@@ -0,0 +1,38 @@
1
+ export function generateMessage(options?: {}): {
2
+ attachments: never[];
3
+ created_at: any;
4
+ html: string;
5
+ id: string;
6
+ text: string;
7
+ type: string;
8
+ updated_at: any;
9
+ user: {
10
+ banned: boolean;
11
+ created_at: string;
12
+ id: string;
13
+ image: string;
14
+ name: string;
15
+ online: boolean;
16
+ role: string;
17
+ updated_at: string;
18
+ };
19
+ };
20
+ export function generateStaticMessage(seed: any, options: any, date: any): {
21
+ attachments: never[];
22
+ created_at: any;
23
+ html: string;
24
+ id: string;
25
+ text: string;
26
+ type: string;
27
+ updated_at: any;
28
+ user: {
29
+ banned: boolean;
30
+ created_at: string;
31
+ id: string;
32
+ image: string;
33
+ name: string;
34
+ online: boolean;
35
+ role: string;
36
+ updated_at: string;
37
+ };
38
+ };
@@ -1,9 +1,9 @@
1
1
  export function getUserDefaults(): {
2
2
  banned: boolean;
3
3
  created_at: string;
4
- id: any;
5
- image: any;
6
- name: any;
4
+ id: string;
5
+ image: string;
6
+ name: string;
7
7
  online: boolean;
8
8
  role: string;
9
9
  updated_at: string;
@@ -11,9 +11,9 @@ export function getUserDefaults(): {
11
11
  export function generateUser(options?: {}): {
12
12
  banned: boolean;
13
13
  created_at: string;
14
- id: any;
15
- image: any;
16
- name: any;
14
+ id: string;
15
+ image: string;
16
+ name: string;
17
17
  online: boolean;
18
18
  role: string;
19
19
  updated_at: string;
@@ -21,9 +21,9 @@ export function generateUser(options?: {}): {
21
21
  export function generateStaticUser(userNumber: any): {
22
22
  banned: boolean;
23
23
  created_at: string;
24
- id: any;
25
- image: any;
26
- name: any;
24
+ id: string;
25
+ image: string;
26
+ name: string;
27
27
  online: boolean;
28
28
  role: string;
29
29
  updated_at: string;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "stream-chat-react-native-core",
3
3
  "description": "The official React Native and Expo components for Stream Chat, a service for building chat applications",
4
- "version": "4.9.0-beta.3",
4
+ "version": "4.9.0-beta.4",
5
5
  "author": {
6
6
  "company": "Stream.io Inc",
7
7
  "name": "Stream.io Inc"
@@ -80,7 +80,7 @@
80
80
  "react-art": "^17.0.2",
81
81
  "react-native-markdown-package": "1.8.1",
82
82
  "react-native-url-polyfill": "^1.3.0",
83
- "stream-chat": "6.2.0"
83
+ "stream-chat": "6.7.0"
84
84
  },
85
85
  "peerDependencies": {
86
86
  "react-native-svg": "^12.1.0"
@@ -88,18 +88,18 @@
88
88
  "devDependencies": {
89
89
  "@babel/cli": "^7.12.17",
90
90
  "@babel/core": "^7.12.9",
91
- "@babel/runtime": "^7.12.5",
92
91
  "@babel/plugin-proposal-object-rest-spread": "7.13.8",
93
92
  "@babel/plugin-transform-runtime": "7.13.10",
94
93
  "@babel/polyfill": "7.12.1",
95
94
  "@babel/preset-env": "7.13.12",
96
95
  "@babel/preset-typescript": "7.13.0",
96
+ "@babel/runtime": "^7.12.5",
97
97
  "@react-native-community/eslint-config": "2.0.0",
98
98
  "@react-native-community/eslint-plugin": "1.1.0",
99
99
  "@react-native-community/netinfo": "6.0.0",
100
100
  "@testing-library/jest-native": "4.0.4",
101
- "@testing-library/react-native": "9.0.0",
102
101
  "@testing-library/react-hooks": "7.0.2",
102
+ "@testing-library/react-native": "9.0.0",
103
103
  "@types/eslint": "7.2.10",
104
104
  "@types/jest": "26.0.23",
105
105
  "@types/lodash": "4.14.169",
@@ -107,6 +107,7 @@
107
107
  "@types/react": "17.0.5",
108
108
  "@types/react-native": "0.67.3",
109
109
  "@types/react-test-renderer": "17.0.1",
110
+ "@types/uuid": "^8.3.4",
110
111
  "@typescript-eslint/eslint-plugin": "^5.7.0",
111
112
  "@typescript-eslint/parser": "^5.7.0",
112
113
  "babel-eslint": "10.1.0",
@@ -212,7 +212,7 @@ const GalleryWithContext = <
212
212
  ]}
213
213
  testID={`gallery-${invertedDirections ? 'row' : 'column'}-${colIndex}`}
214
214
  >
215
- {rows.map(({ height, resizeMode, type, url, width }, rowIndex) => {
215
+ {rows.map(({ height, resizeMode, thumb_url, type, url, width }, rowIndex) => {
216
216
  const openImageViewer = () => {
217
217
  if (!legacyImageViewerSwipeBehaviour && message) {
218
218
  // Added if-else to keep the logic readable, instead of DRY.
@@ -307,6 +307,7 @@ const GalleryWithContext = <
307
307
  width: width - 1,
308
308
  },
309
309
  ]}
310
+ thumb_url={thumb_url}
310
311
  />
311
312
  ) : (
312
313
  <View style={styles.imageContainerStyle}>
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { StyleSheet, View, ViewProps } from 'react-native';
2
+ import { ImageBackground, StyleSheet, View, ViewProps } from 'react-native';
3
3
 
4
4
  import { useTheme } from '../../contexts/themeContext/ThemeContext';
5
5
  import { Play } from '../../icons';
@@ -24,7 +24,9 @@ const styles = StyleSheet.create({
24
24
  },
25
25
  });
26
26
 
27
- export type VideoThumbnailProps = ViewProps;
27
+ export type VideoThumbnailProps = ViewProps & {
28
+ thumb_url?: string;
29
+ };
28
30
 
29
31
  export const VideoThumbnail: React.FC<VideoThumbnailProps> = (props) => {
30
32
  const {
@@ -34,12 +36,17 @@ export const VideoThumbnail: React.FC<VideoThumbnailProps> = (props) => {
34
36
  },
35
37
  },
36
38
  } = useTheme();
37
- const { style, ...rest } = props;
39
+ const { style, thumb_url, ...rest } = props;
38
40
  return (
39
- <View {...rest} style={[styles.container, container, style]}>
41
+ <ImageBackground
42
+ accessibilityLabel='video-thumbnail'
43
+ source={{ uri: thumb_url }}
44
+ {...rest}
45
+ style={[styles.container, container, style]}
46
+ >
40
47
  <View style={[styles.roundedView, roundedView]}>
41
48
  <Play height={24} pathFill={'#000'} width={24} />
42
49
  </View>
43
- </View>
50
+ </ImageBackground>
44
51
  );
45
52
  };
@@ -11,8 +11,10 @@ import {
11
11
  generateAudioAttachment,
12
12
  generateFileAttachment,
13
13
  generateImageAttachment,
14
+ generateVideoAttachment,
14
15
  } from '../../../mock-builders/generator/attachment';
15
16
  import { generateMessage } from '../../../mock-builders/generator/message';
17
+ import * as NativeUtils from '../../../native';
16
18
 
17
19
  import { ImageLoadingFailedIndicator } from '../../Attachment/ImageLoadingFailedIndicator';
18
20
  import { ImageLoadingIndicator } from '../../Attachment/ImageLoadingIndicator';
@@ -47,6 +49,16 @@ describe('Attachment', () => {
47
49
  });
48
50
  });
49
51
 
52
+ it('should render File component for "video" type attachment', async () => {
53
+ jest.spyOn(NativeUtils, 'isVideoPackageAvailable').mockImplementation(jest.fn(() => false));
54
+ const attachment = generateVideoAttachment();
55
+ const { getByTestId } = render(getAttachmentComponent({ attachment }));
56
+
57
+ await waitFor(() => {
58
+ expect(getByTestId('file-attachment')).toBeTruthy();
59
+ });
60
+ });
61
+
50
62
  it('should render File component for "file" type attachment', async () => {
51
63
  const attachment = generateFileAttachment();
52
64
  const { getByTestId } = render(getAttachmentComponent({ attachment }));
@@ -11,12 +11,16 @@ import { OverlayProvider } from '../../../contexts/overlayContext/OverlayProvide
11
11
 
12
12
  import { getOrCreateChannelApi } from '../../../mock-builders/api/getOrCreateChannel';
13
13
  import { useMockedApis } from '../../../mock-builders/api/useMockedApis';
14
- import { generateImageAttachment } from '../../../mock-builders/generator/attachment';
14
+ import {
15
+ generateImageAttachment,
16
+ generateVideoAttachment,
17
+ } from '../../../mock-builders/generator/attachment';
15
18
  import { generateChannelResponse } from '../../../mock-builders/generator/channel';
16
19
  import { generateMember } from '../../../mock-builders/generator/member';
17
20
  import { generateMessage } from '../../../mock-builders/generator/message';
18
21
  import { generateUser } from '../../../mock-builders/generator/user';
19
22
  import { getTestClientWithUser } from '../../../mock-builders/mock';
23
+ import * as NativeUtils from '../../../native';
20
24
  import { Channel } from '../../Channel/Channel';
21
25
  import { Chat } from '../../Chat/Chat';
22
26
  import { MessageList } from '../../MessageList/MessageList';
@@ -75,6 +79,24 @@ describe('Gallery', () => {
75
79
  });
76
80
  });
77
81
 
82
+ it('should render one image and one video attachment', async () => {
83
+ jest.spyOn(NativeUtils, 'isVideoPackageAvailable').mockImplementation(jest.fn(() => true));
84
+ const attachment1 = generateImageAttachment({
85
+ original_height: 600,
86
+ original_width: 400,
87
+ });
88
+ const attachment2 = generateVideoAttachment();
89
+ const component = await getComponent([attachment1, attachment2]);
90
+ const { getAllByA11yLabel, queryAllByTestId } = render(component);
91
+
92
+ await waitFor(() => {
93
+ expect(queryAllByTestId('gallery-row-0').length).toBe(1);
94
+
95
+ expect(queryAllByTestId('gallery-row-0-item-0').length).toBe(1);
96
+ expect(getAllByA11yLabel('video-thumbnail').length).toBe(1);
97
+ });
98
+ });
99
+
78
100
  it('should render portrait and landscape image in two rows', async () => {
79
101
  const attachment1 = generateImageAttachment({
80
102
  original_height: 600,
@@ -36,6 +36,7 @@ export function buildThumbnail<
36
36
  resizeMode: resizeMode
37
37
  ? resizeMode
38
38
  : ((image.original_height && image.original_width ? 'contain' : 'cover') as ImageResizeMode),
39
+ thumb_url: image.thumb_url,
39
40
  type: image.type,
40
41
  url: shouldResize
41
42
  ? getResizedImageUrl({
@@ -6,6 +6,7 @@ export type Thumbnail = {
6
6
  url: string;
7
7
  width: number;
8
8
  id?: string;
9
+ thumb_url?: string;
9
10
  type?: string;
10
11
  };
11
12
 
@@ -333,7 +333,11 @@ const MessageWithContext = <
333
333
  acc.files.push(cur);
334
334
  acc.other = []; // remove other attachments if a file exists
335
335
  } else if (cur.type === 'video' && !cur.og_scrape_url && isVideoPackageAvailable()) {
336
- acc.videos.push({ image_url: cur.asset_url, type: 'video' });
336
+ acc.videos.push({
337
+ image_url: cur.asset_url,
338
+ thumb_url: cur.thumb_url,
339
+ type: 'video',
340
+ });
337
341
  acc.other = [];
338
342
  } else if (cur.type === 'video' && !cur.og_scrape_url) {
339
343
  acc.files.push(cur);
@@ -62,6 +62,7 @@ export type FileUpload = {
62
62
  file: File;
63
63
  id: string;
64
64
  state: FileStateValue;
65
+ thumb_url?: string;
65
66
  url?: string;
66
67
  };
67
68
 
@@ -710,6 +711,7 @@ export const MessageInputProvider = <
710
711
  duration: file.file.duration,
711
712
  file_size: file.file.size,
712
713
  mime_type: file.file.type,
714
+ thumb_url: file.thumb_url,
713
715
  title: file.file.name,
714
716
  type: 'video',
715
717
  } as Attachment<StreamChatGenerics>);
@@ -897,9 +899,6 @@ export const MessageInputProvider = <
897
899
  };
898
900
 
899
901
  const uploadFile = async ({ newFile }: { newFile: FileUpload }) => {
900
- if (!newFile) {
901
- return;
902
- }
903
902
  const { file, id } = newFile;
904
903
 
905
904
  setFileUploads(getUploadSetStateAction(id, FileState.UPLOADING));
@@ -911,7 +910,7 @@ export const MessageInputProvider = <
911
910
  } else if (channel && file.uri) {
912
911
  response = await channel.sendFile(file.uri, file.name, file.type);
913
912
  }
914
- const extraData: Partial<FileUpload> = { url: response.file };
913
+ const extraData: Partial<FileUpload> = { thumb_url: response.thumb_url, url: response.file };
915
914
  setFileUploads(getUploadSetStateAction(id, FileState.UPLOADED, extraData));
916
915
  } catch (error: unknown) {
917
916
  handleFileOrImageUploadError(error, false, id);
@@ -0,0 +1,208 @@
1
+ import React, { PropsWithChildren } from 'react';
2
+
3
+ import type { TextInput } from 'react-native';
4
+
5
+ import { act, renderHook } from '@testing-library/react-hooks';
6
+
7
+ import type { AppSettingsAPIResponse, StreamChat } from 'stream-chat';
8
+
9
+ import { ChatContextValue, ChatProvider } from '../../../contexts/chatContext/ChatContext';
10
+
11
+ import {
12
+ generateFileAttachment,
13
+ generateImageAttachment,
14
+ } from '../../../mock-builders/generator/attachment';
15
+
16
+ import { generateMessage } from '../../../mock-builders/generator/message';
17
+ import { generateUser } from '../../../mock-builders/generator/user';
18
+
19
+ import * as NativeUtils from '../../../native';
20
+ import type { DefaultStreamChatGenerics } from '../../../types/types';
21
+ import { FileState } from '../../../utils/utils';
22
+ import {
23
+ InputMessageInputContextValue,
24
+ MessageInputContextValue,
25
+ MessageInputProvider,
26
+ useMessageInputContext,
27
+ } from '../MessageInputContext';
28
+
29
+ type WrapperType<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics> =
30
+ Partial<InputMessageInputContextValue<StreamChatGenerics>>;
31
+
32
+ afterEach(jest.clearAllMocks);
33
+
34
+ describe('MessageInputContext', () => {
35
+ const Wrapper = <
36
+ StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
37
+ >({
38
+ children,
39
+ ...rest
40
+ }: PropsWithChildren<WrapperType<StreamChatGenerics>>) => (
41
+ <ChatProvider
42
+ value={
43
+ {
44
+ appSettings: {
45
+ app: {
46
+ file_upload_config: {
47
+ blocked_file_extensions: ['.mp3'],
48
+ blocked_mime_types: ['video/mp4'],
49
+ },
50
+ image_upload_config: {
51
+ blocked_file_extensions: ['.png'],
52
+ blocked_mime_types: ['image/png'],
53
+ },
54
+ },
55
+ } as unknown as AppSettingsAPIResponse<StreamChatGenerics>,
56
+ client: {
57
+ updateMessage: jest.fn().mockResolvedValue({ message: generateMessage() }),
58
+ } as unknown as StreamChat<StreamChatGenerics>,
59
+ } as ChatContextValue<StreamChatGenerics>
60
+ }
61
+ >
62
+ <MessageInputProvider
63
+ value={
64
+ {
65
+ ...rest,
66
+ } as MessageInputContextValue<StreamChatGenerics>
67
+ }
68
+ >
69
+ {children}
70
+ </MessageInputProvider>
71
+ </ChatProvider>
72
+ );
73
+
74
+ it('appendText works', () => {
75
+ const { result } = renderHook(() => useMessageInputContext(), {
76
+ initialProps: {
77
+ editing: true,
78
+ hasImagePicker: true,
79
+ },
80
+ wrapper: Wrapper,
81
+ });
82
+
83
+ act(() => {
84
+ result.current.setFileUploads([]);
85
+ result.current.setImageUploads([]);
86
+ result.current.setMentionedUsers([]);
87
+ result.current.setText('dummy');
88
+ result.current.appendText('text');
89
+ });
90
+
91
+ expect(result.current.text).toBe('dummytext');
92
+ });
93
+
94
+ it('uploadNewImage with blocked image extensions to be not supported', () => {
95
+ const { result } = renderHook(() => useMessageInputContext(), {
96
+ initialProps: {
97
+ editing: true,
98
+ maxNumberOfFiles: 2,
99
+ },
100
+ wrapper: Wrapper,
101
+ });
102
+
103
+ act(() => {
104
+ result.current.uploadNewImage(
105
+ generateImageAttachment({
106
+ uri: 'https://www.bastiaanmulder.nl/wp-content/uploads/2013/11/dummy-image-square.png',
107
+ }),
108
+ );
109
+ });
110
+
111
+ expect(result.current.imageUploads[0].state).toBe(FileState.NOT_SUPPORTED);
112
+ });
113
+
114
+ it('onSelectItem works', () => {
115
+ const mentioned_user = generateUser();
116
+ const initialUsers = [mentioned_user.id];
117
+
118
+ const { result } = renderHook(() => useMessageInputContext(), {
119
+ initialProps: {
120
+ editing: true,
121
+ hasImagePicker: true,
122
+ },
123
+ wrapper: Wrapper,
124
+ });
125
+
126
+ act(() => {
127
+ result.current.setFileUploads([]);
128
+ result.current.setImageUploads([]);
129
+ result.current.setMentionedUsers(initialUsers);
130
+ result.current.onSelectItem(mentioned_user);
131
+ });
132
+
133
+ expect(result.current.mentionedUsers.length).toBe(2);
134
+ });
135
+
136
+ it('setInputBoxRef works', () => {
137
+ const setInputRefMock = jest.fn();
138
+ const inputRef = React.createRef<TextInput | null>();
139
+ const { result } = renderHook(() => useMessageInputContext(), {
140
+ initialProps: {
141
+ editing: true,
142
+ setInputRef: setInputRefMock,
143
+ },
144
+ wrapper: Wrapper,
145
+ });
146
+
147
+ act(() => {
148
+ result.current.setInputBoxRef(inputRef.current);
149
+ });
150
+
151
+ expect(setInputRefMock).toHaveBeenCalled();
152
+ });
153
+
154
+ it('openCommandsPicker works', () => {
155
+ const { result } = renderHook(() => useMessageInputContext(), {
156
+ initialProps: {
157
+ editing: true,
158
+ hasImagePicker: true,
159
+ },
160
+ wrapper: Wrapper,
161
+ });
162
+
163
+ act(() => {
164
+ result.current.openCommandsPicker();
165
+ });
166
+
167
+ expect(result.current.text).toBe('/');
168
+ });
169
+
170
+ it('openMentionPicker works', () => {
171
+ const { result } = renderHook(() => useMessageInputContext(), {
172
+ initialProps: {
173
+ editing: true,
174
+ hasImagePicker: true,
175
+ },
176
+ wrapper: Wrapper,
177
+ });
178
+
179
+ act(() => {
180
+ result.current.openMentionsPicker();
181
+ });
182
+
183
+ expect(result.current.text).toBe('@');
184
+ });
185
+
186
+ it('openAttachmentPicker works', async () => {
187
+ jest.spyOn(NativeUtils, 'pickDocument').mockImplementation(
188
+ jest.fn().mockResolvedValue({
189
+ cancelled: false,
190
+ docs: [generateFileAttachment(), generateImageAttachment()],
191
+ }),
192
+ );
193
+ const { result } = renderHook(() => useMessageInputContext(), {
194
+ initialProps: {
195
+ editing: true,
196
+ hasFilePicker: true,
197
+ hasImagePicker: false,
198
+ },
199
+ wrapper: Wrapper,
200
+ });
201
+
202
+ act(() => {
203
+ result.current.openAttachmentPicker();
204
+ });
205
+
206
+ expect(await result.current.pickFile()).toBe(undefined);
207
+ });
208
+ });