stream-chat-react-native-core 4.11.1-beta.4 → 4.12.0-beta.3

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 (206) hide show
  1. package/lib/commonjs/components/Attachment/AudioAttachment.js +541 -0
  2. package/lib/commonjs/components/Attachment/AudioAttachment.js.map +1 -0
  3. package/lib/commonjs/components/Attachment/FileAttachmentGroup.js +113 -10
  4. package/lib/commonjs/components/Attachment/FileAttachmentGroup.js.map +1 -1
  5. package/lib/commonjs/components/Attachment/Gallery.js +2 -2
  6. package/lib/commonjs/components/Attachment/Gallery.js.map +1 -1
  7. package/lib/commonjs/components/Attachment/{GallaryImage.js → GalleryImage.js} +3 -3
  8. package/lib/{module/components/Attachment/GallaryImage.js.map → commonjs/components/Attachment/GalleryImage.js.map} +1 -1
  9. package/lib/commonjs/components/Attachment/Giphy.js +1 -1
  10. package/lib/commonjs/components/Attachment/Giphy.js.map +1 -1
  11. package/lib/commonjs/components/Attachment/VideoThumbnail.js +10 -5
  12. package/lib/commonjs/components/Attachment/VideoThumbnail.js.map +1 -1
  13. package/lib/commonjs/components/Avatar/Avatar.js +1 -1
  14. package/lib/commonjs/components/Avatar/Avatar.js.map +1 -1
  15. package/lib/commonjs/components/Avatar/GroupAvatar.js +1 -1
  16. package/lib/commonjs/components/Avatar/GroupAvatar.js.map +1 -1
  17. package/lib/commonjs/components/Channel/Channel.js +18 -13
  18. package/lib/commonjs/components/Channel/Channel.js.map +1 -1
  19. package/lib/commonjs/components/Channel/hooks/useCreateInputMessageInputContext.js +2 -0
  20. package/lib/commonjs/components/Channel/hooks/useCreateInputMessageInputContext.js.map +1 -1
  21. package/lib/commonjs/components/ImageGallery/ImageGallery.js +37 -30
  22. package/lib/commonjs/components/ImageGallery/ImageGallery.js.map +1 -1
  23. package/lib/commonjs/components/ImageGallery/components/AnimatedGalleryImage.js +5 -3
  24. package/lib/commonjs/components/ImageGallery/components/AnimatedGalleryImage.js.map +1 -1
  25. package/lib/commonjs/components/ImageGallery/components/AnimatedGalleryVideo.js +10 -6
  26. package/lib/commonjs/components/ImageGallery/components/AnimatedGalleryVideo.js.map +1 -1
  27. package/lib/commonjs/components/ImageGallery/components/ImageGalleryFooter.js +17 -14
  28. package/lib/commonjs/components/ImageGallery/components/ImageGalleryFooter.js.map +1 -1
  29. package/lib/commonjs/components/ImageGallery/components/ImageGalleryHeader.js +1 -0
  30. package/lib/commonjs/components/ImageGallery/components/ImageGalleryHeader.js.map +1 -1
  31. package/lib/commonjs/components/ImageGallery/components/ImageGalleryOverlay.js +2 -1
  32. package/lib/commonjs/components/ImageGallery/components/ImageGalleryOverlay.js.map +1 -1
  33. package/lib/commonjs/components/ImageGallery/components/ImageGalleryVideoControl.js +37 -18
  34. package/lib/commonjs/components/ImageGallery/components/ImageGalleryVideoControl.js.map +1 -1
  35. package/lib/commonjs/components/ImageGallery/components/ImageGrid.js +3 -1
  36. package/lib/commonjs/components/ImageGallery/components/ImageGrid.js.map +1 -1
  37. package/lib/commonjs/components/ImageGallery/components/ImageGridHandle.js +5 -4
  38. package/lib/commonjs/components/ImageGallery/components/ImageGridHandle.js.map +1 -1
  39. package/lib/commonjs/components/Message/Message.js +8 -6
  40. package/lib/commonjs/components/Message/Message.js.map +1 -1
  41. package/lib/commonjs/components/Message/MessageSimple/utils/parseLinks.js +1 -1
  42. package/lib/commonjs/components/Message/MessageSimple/utils/parseLinks.js.map +1 -1
  43. package/lib/commonjs/components/Message/MessageSimple/utils/parseLinks.test.js +1 -1
  44. package/lib/commonjs/components/Message/MessageSimple/utils/parseLinks.test.js.map +1 -1
  45. package/lib/commonjs/components/MessageInput/FileUploadPreview.js +125 -35
  46. package/lib/commonjs/components/MessageInput/FileUploadPreview.js.map +1 -1
  47. package/lib/{module/components/ImageGallery/components → commonjs/components/ProgressControl}/ProgressControl.js +37 -24
  48. package/lib/commonjs/components/ProgressControl/ProgressControl.js.map +1 -0
  49. package/lib/commonjs/components/index.js +26 -0
  50. package/lib/commonjs/components/index.js.map +1 -1
  51. package/lib/commonjs/contexts/messageInputContext/MessageInputContext.js +5 -2
  52. package/lib/commonjs/contexts/messageInputContext/MessageInputContext.js.map +1 -1
  53. package/lib/commonjs/contexts/messageInputContext/hooks/useCreateMessageInputContext.js +7 -2
  54. package/lib/commonjs/contexts/messageInputContext/hooks/useCreateMessageInputContext.js.map +1 -1
  55. package/lib/commonjs/contexts/themeContext/utils/theme.js +9 -0
  56. package/lib/commonjs/contexts/themeContext/utils/theme.js.map +1 -1
  57. package/lib/commonjs/icons/Pause.js +2 -2
  58. package/lib/commonjs/icons/Pause.js.map +1 -1
  59. package/lib/commonjs/mock-builders/api/channelMocks.js +1 -0
  60. package/lib/commonjs/mock-builders/api/channelMocks.js.map +1 -1
  61. package/lib/commonjs/native.js +13 -5
  62. package/lib/commonjs/native.js.map +1 -1
  63. package/lib/commonjs/version.json +1 -1
  64. package/lib/module/components/Attachment/AudioAttachment.js +541 -0
  65. package/lib/module/components/Attachment/AudioAttachment.js.map +1 -0
  66. package/lib/module/components/Attachment/FileAttachmentGroup.js +113 -10
  67. package/lib/module/components/Attachment/FileAttachmentGroup.js.map +1 -1
  68. package/lib/module/components/Attachment/Gallery.js +2 -2
  69. package/lib/module/components/Attachment/Gallery.js.map +1 -1
  70. package/lib/module/components/Attachment/{GallaryImage.js → GalleryImage.js} +3 -3
  71. package/lib/{commonjs/components/Attachment/GallaryImage.js.map → module/components/Attachment/GalleryImage.js.map} +1 -1
  72. package/lib/module/components/Attachment/Giphy.js +1 -1
  73. package/lib/module/components/Attachment/Giphy.js.map +1 -1
  74. package/lib/module/components/Attachment/VideoThumbnail.js +10 -5
  75. package/lib/module/components/Attachment/VideoThumbnail.js.map +1 -1
  76. package/lib/module/components/Avatar/Avatar.js +1 -1
  77. package/lib/module/components/Avatar/Avatar.js.map +1 -1
  78. package/lib/module/components/Avatar/GroupAvatar.js +1 -1
  79. package/lib/module/components/Avatar/GroupAvatar.js.map +1 -1
  80. package/lib/module/components/Channel/Channel.js +18 -13
  81. package/lib/module/components/Channel/Channel.js.map +1 -1
  82. package/lib/module/components/Channel/hooks/useCreateInputMessageInputContext.js +2 -0
  83. package/lib/module/components/Channel/hooks/useCreateInputMessageInputContext.js.map +1 -1
  84. package/lib/module/components/ImageGallery/ImageGallery.js +37 -30
  85. package/lib/module/components/ImageGallery/ImageGallery.js.map +1 -1
  86. package/lib/module/components/ImageGallery/components/AnimatedGalleryImage.js +5 -3
  87. package/lib/module/components/ImageGallery/components/AnimatedGalleryImage.js.map +1 -1
  88. package/lib/module/components/ImageGallery/components/AnimatedGalleryVideo.js +10 -6
  89. package/lib/module/components/ImageGallery/components/AnimatedGalleryVideo.js.map +1 -1
  90. package/lib/module/components/ImageGallery/components/ImageGalleryFooter.js +17 -14
  91. package/lib/module/components/ImageGallery/components/ImageGalleryFooter.js.map +1 -1
  92. package/lib/module/components/ImageGallery/components/ImageGalleryHeader.js +1 -0
  93. package/lib/module/components/ImageGallery/components/ImageGalleryHeader.js.map +1 -1
  94. package/lib/module/components/ImageGallery/components/ImageGalleryOverlay.js +2 -1
  95. package/lib/module/components/ImageGallery/components/ImageGalleryOverlay.js.map +1 -1
  96. package/lib/module/components/ImageGallery/components/ImageGalleryVideoControl.js +37 -18
  97. package/lib/module/components/ImageGallery/components/ImageGalleryVideoControl.js.map +1 -1
  98. package/lib/module/components/ImageGallery/components/ImageGrid.js +3 -1
  99. package/lib/module/components/ImageGallery/components/ImageGrid.js.map +1 -1
  100. package/lib/module/components/ImageGallery/components/ImageGridHandle.js +5 -4
  101. package/lib/module/components/ImageGallery/components/ImageGridHandle.js.map +1 -1
  102. package/lib/module/components/Message/Message.js +8 -6
  103. package/lib/module/components/Message/Message.js.map +1 -1
  104. package/lib/module/components/Message/MessageSimple/utils/parseLinks.js +1 -1
  105. package/lib/module/components/Message/MessageSimple/utils/parseLinks.js.map +1 -1
  106. package/lib/module/components/Message/MessageSimple/utils/parseLinks.test.js +1 -1
  107. package/lib/module/components/Message/MessageSimple/utils/parseLinks.test.js.map +1 -1
  108. package/lib/module/components/MessageInput/FileUploadPreview.js +125 -35
  109. package/lib/module/components/MessageInput/FileUploadPreview.js.map +1 -1
  110. package/lib/{commonjs/components/ImageGallery/components → module/components/ProgressControl}/ProgressControl.js +37 -24
  111. package/lib/module/components/ProgressControl/ProgressControl.js.map +1 -0
  112. package/lib/module/components/index.js +26 -0
  113. package/lib/module/components/index.js.map +1 -1
  114. package/lib/module/contexts/messageInputContext/MessageInputContext.js +5 -2
  115. package/lib/module/contexts/messageInputContext/MessageInputContext.js.map +1 -1
  116. package/lib/module/contexts/messageInputContext/hooks/useCreateMessageInputContext.js +7 -2
  117. package/lib/module/contexts/messageInputContext/hooks/useCreateMessageInputContext.js.map +1 -1
  118. package/lib/module/contexts/themeContext/utils/theme.js +9 -0
  119. package/lib/module/contexts/themeContext/utils/theme.js.map +1 -1
  120. package/lib/module/icons/Pause.js +2 -2
  121. package/lib/module/icons/Pause.js.map +1 -1
  122. package/lib/module/mock-builders/api/channelMocks.js +1 -0
  123. package/lib/module/mock-builders/api/channelMocks.js.map +1 -1
  124. package/lib/module/native.js +13 -5
  125. package/lib/module/native.js.map +1 -1
  126. package/lib/module/version.json +1 -1
  127. package/lib/typescript/components/Attachment/AudioAttachment.d.ts +26 -0
  128. package/lib/typescript/components/Attachment/FileAttachmentGroup.d.ts +2 -1
  129. package/lib/typescript/components/Attachment/{GallaryImage.d.ts → GalleryImage.d.ts} +0 -0
  130. package/lib/typescript/components/Channel/hooks/useCreateInputMessageInputContext.d.ts +1 -1
  131. package/lib/typescript/components/ImageGallery/__tests__/AnimatedVideoGallery.test.d.ts +1 -0
  132. package/lib/typescript/components/ImageGallery/__tests__/ImageGallery.test.d.ts +1 -0
  133. package/lib/typescript/components/ImageGallery/__tests__/ImageGalleryFooter.test.d.ts +1 -0
  134. package/lib/typescript/components/ImageGallery/__tests__/ImageGalleryGrid.test.d.ts +1 -0
  135. package/lib/typescript/components/ImageGallery/__tests__/ImageGalleryGridHandle.test.d.ts +1 -0
  136. package/lib/typescript/components/ImageGallery/__tests__/ImageGalleryHeader.test.d.ts +1 -0
  137. package/lib/typescript/components/ImageGallery/__tests__/ImageGalleryOverlay.test.d.ts +1 -0
  138. package/lib/typescript/components/ImageGallery/__tests__/ImageGalleryVideoControl.test.d.ts +1 -0
  139. package/lib/typescript/components/ImageGallery/components/AnimatedGalleryImage.d.ts +1 -0
  140. package/lib/typescript/components/ImageGallery/components/AnimatedGalleryVideo.d.ts +2 -3
  141. package/lib/typescript/components/ImageGallery/components/ImageGalleryFooter.d.ts +2 -1
  142. package/lib/typescript/components/ImageGallery/components/ImageGrid.d.ts +2 -3
  143. package/lib/typescript/components/Message/hooks/useMessageActionHandlers.d.ts +1 -1
  144. package/lib/typescript/components/Message/hooks/useMessageActions.d.ts +1 -1
  145. package/lib/typescript/components/MessageInput/FileUploadPreview.d.ts +1 -1
  146. package/lib/typescript/components/MessageInput/__tests__/AudioAttachmentUploadPreviewExpo.test.d.ts +1 -0
  147. package/lib/typescript/components/MessageInput/__tests__/AudioAttachmentUploadPreviewNative.test.d.ts +1 -0
  148. package/lib/typescript/components/ProgressControl/ProgressControl.d.ts +11 -0
  149. package/lib/typescript/components/index.d.ts +2 -0
  150. package/lib/typescript/contexts/messageContext/MessageContext.d.ts +1 -1
  151. package/lib/typescript/contexts/messageInputContext/MessageInputContext.d.ts +7 -1
  152. package/lib/typescript/contexts/messageInputContext/hooks/useCreateMessageInputContext.d.ts +1 -1
  153. package/lib/typescript/contexts/themeContext/utils/theme.d.ts +9 -0
  154. package/lib/typescript/native.d.ts +59 -2
  155. package/package.json +1 -1
  156. package/src/components/Attachment/AudioAttachment.tsx +357 -0
  157. package/src/components/Attachment/FileAttachmentGroup.tsx +96 -7
  158. package/src/components/Attachment/Gallery.tsx +1 -1
  159. package/src/components/Attachment/{GallaryImage.tsx → GalleryImage.tsx} +1 -1
  160. package/src/components/Attachment/Giphy.tsx +1 -1
  161. package/src/components/Attachment/VideoThumbnail.tsx +4 -4
  162. package/src/components/Attachment/__tests__/Gallery.test.js +6 -6
  163. package/src/components/Attachment/__tests__/Giphy.test.js +4 -4
  164. package/src/components/Avatar/Avatar.tsx +1 -1
  165. package/src/components/Avatar/GroupAvatar.tsx +1 -1
  166. package/src/components/Channel/Channel.tsx +3 -0
  167. package/src/components/Channel/hooks/useCreateInputMessageInputContext.ts +2 -0
  168. package/src/components/ImageGallery/ImageGallery.tsx +21 -11
  169. package/src/components/ImageGallery/__tests__/AnimatedVideoGallery.test.tsx +241 -0
  170. package/src/components/ImageGallery/__tests__/ImageGallery.test.tsx +192 -0
  171. package/src/components/ImageGallery/__tests__/ImageGalleryFooter.test.tsx +190 -0
  172. package/src/components/ImageGallery/__tests__/ImageGalleryGrid.test.tsx +98 -0
  173. package/src/components/ImageGallery/__tests__/ImageGalleryGridHandle.test.tsx +79 -0
  174. package/src/components/ImageGallery/__tests__/ImageGalleryHeader.test.tsx +172 -0
  175. package/src/components/ImageGallery/__tests__/ImageGalleryOverlay.test.tsx +94 -0
  176. package/src/components/ImageGallery/__tests__/ImageGalleryVideoControl.test.tsx +84 -0
  177. package/src/components/ImageGallery/components/AnimatedGalleryImage.tsx +3 -0
  178. package/src/components/ImageGallery/components/AnimatedGalleryVideo.tsx +11 -3
  179. package/src/components/ImageGallery/components/ImageGalleryFooter.tsx +9 -2
  180. package/src/components/ImageGallery/components/ImageGalleryHeader.tsx +1 -1
  181. package/src/components/ImageGallery/components/ImageGalleryOverlay.tsx +6 -1
  182. package/src/components/ImageGallery/components/ImageGalleryVideoControl.tsx +27 -9
  183. package/src/components/ImageGallery/components/ImageGrid.tsx +19 -17
  184. package/src/components/ImageGallery/components/ImageGridHandle.tsx +4 -1
  185. package/src/components/Message/Message.tsx +2 -1
  186. package/src/components/Message/MessageSimple/__tests__/MessageContent.test.js +11 -3
  187. package/src/components/Message/MessageSimple/__tests__/__snapshots__/MessageAvatar.test.js.snap +1 -1
  188. package/src/components/Message/MessageSimple/utils/parseLinks.test.ts +4 -0
  189. package/src/components/Message/MessageSimple/utils/parseLinks.ts +1 -1
  190. package/src/components/MessageInput/FileUploadPreview.tsx +162 -66
  191. package/src/components/MessageInput/__tests__/AudioAttachmentUploadPreviewExpo.test.tsx +196 -0
  192. package/src/components/MessageInput/__tests__/AudioAttachmentUploadPreviewNative.test.tsx +212 -0
  193. package/src/components/MessageInput/__tests__/FileUploadPreview.test.js +64 -0
  194. package/src/components/{ImageGallery/components → ProgressControl}/ProgressControl.tsx +37 -19
  195. package/src/components/Thread/__tests__/__snapshots__/Thread.test.js.snap +4 -4
  196. package/src/components/index.ts +3 -0
  197. package/src/contexts/messageInputContext/MessageInputContext.tsx +11 -0
  198. package/src/contexts/messageInputContext/hooks/useCreateMessageInputContext.ts +5 -1
  199. package/src/contexts/themeContext/utils/theme.ts +15 -0
  200. package/src/icons/Pause.tsx +2 -2
  201. package/src/mock-builders/api/channelMocks.tsx +1 -0
  202. package/src/native.ts +67 -7
  203. package/src/version.json +1 -1
  204. package/lib/commonjs/components/ImageGallery/components/ProgressControl.js.map +0 -1
  205. package/lib/module/components/ImageGallery/components/ProgressControl.js.map +0 -1
  206. package/lib/typescript/components/ImageGallery/components/ProgressControl.d.ts +0 -5
@@ -0,0 +1,190 @@
1
+ import React from 'react';
2
+
3
+ import { Text, View } from 'react-native';
4
+ import type { SharedValue } from 'react-native-reanimated';
5
+
6
+ import { act, ReactTestInstance } from 'react-test-renderer';
7
+
8
+ import { fireEvent, render, waitFor } from '@testing-library/react-native';
9
+
10
+ import { Chat } from '../../../components/Chat/Chat';
11
+ import {
12
+ ImageGalleryContext,
13
+ ImageGalleryContextValue,
14
+ } from '../../../contexts/imageGalleryContext/ImageGalleryContext';
15
+ import { OverlayProvider } from '../../../contexts/overlayContext/OverlayProvider';
16
+ import {
17
+ generateImageAttachment,
18
+ generateVideoAttachment,
19
+ } from '../../../mock-builders/generator/attachment';
20
+ import { generateMessage } from '../../../mock-builders/generator/message';
21
+ import { getTestClientWithUser } from '../../../mock-builders/mock';
22
+ import * as NativeUtils from '../../../native';
23
+ import type { DefaultStreamChatGenerics } from '../../../types/types';
24
+ import type { MessageType } from '../../MessageList/hooks/useMessageList';
25
+ import { ImageGallery, ImageGalleryCustomComponents } from '../ImageGallery';
26
+
27
+ jest.mock('../../../native.ts', () => {
28
+ const View = require('react-native/Libraries/Components/View/View');
29
+ return {
30
+ deleteFile: jest.fn(),
31
+ isVideoPackageAvailable: jest.fn(() => true),
32
+ NetInfo: {
33
+ addEventListener: jest.fn(),
34
+ },
35
+ saveFile: jest.fn(),
36
+ shareImage: jest.fn(),
37
+ Video: View,
38
+ };
39
+ });
40
+
41
+ describe('ImageGalleryFooter', () => {
42
+ it('render image gallery footer component with custom component footer props', async () => {
43
+ const chatClient = await getTestClientWithUser({ id: 'testID' });
44
+
45
+ const CustomFooterLeftElement = () => (
46
+ <View>
47
+ <Text>Left element</Text>
48
+ </View>
49
+ );
50
+
51
+ const CustomFooterRightElement = () => (
52
+ <View>
53
+ <Text>Right element</Text>
54
+ </View>
55
+ );
56
+
57
+ const CustomFooterCenterElement = () => (
58
+ <View>
59
+ <Text>Center element</Text>
60
+ </View>
61
+ );
62
+
63
+ const CustomFooterVideoControlElement = () => (
64
+ <View>
65
+ <Text>Video Control element</Text>
66
+ </View>
67
+ );
68
+
69
+ const { queryAllByText } = render(
70
+ <OverlayProvider>
71
+ <ImageGalleryContext.Provider
72
+ value={
73
+ {
74
+ images: [
75
+ generateMessage({
76
+ attachments: [generateVideoAttachment({ type: 'video' })],
77
+ }),
78
+ ] as unknown as MessageType<DefaultStreamChatGenerics>[],
79
+ } as unknown as ImageGalleryContextValue
80
+ }
81
+ >
82
+ <Chat client={chatClient}>
83
+ <ImageGallery
84
+ imageGalleryCustomComponents={
85
+ {
86
+ footer: {
87
+ centerElement: CustomFooterCenterElement,
88
+ leftElement: CustomFooterLeftElement,
89
+ rightElement: CustomFooterRightElement,
90
+ videoControlElement: CustomFooterVideoControlElement,
91
+ },
92
+ } as ImageGalleryCustomComponents['imageGalleryCustomComponents']
93
+ }
94
+ overlayOpacity={{ value: 1 } as SharedValue<number>}
95
+ />
96
+ </Chat>
97
+ </ImageGalleryContext.Provider>
98
+ </OverlayProvider>,
99
+ );
100
+ expect(queryAllByText('Left element')).toHaveLength(1);
101
+ expect(queryAllByText('Right element')).toHaveLength(1);
102
+ expect(queryAllByText('Center element')).toHaveLength(1);
103
+ expect(queryAllByText('Video Control element')).toHaveLength(1);
104
+ });
105
+
106
+ it('render image gallery footer component with custom component footer Grid Icon and Share Icon component', async () => {
107
+ const chatClient = await getTestClientWithUser({ id: 'testID' });
108
+
109
+ const CustomShareIconElement = () => (
110
+ <View>
111
+ <Text>Share Icon element</Text>
112
+ </View>
113
+ );
114
+
115
+ const CustomGridIconElement = () => (
116
+ <View>
117
+ <Text>Grid Icon element</Text>
118
+ </View>
119
+ );
120
+
121
+ const { queryAllByText } = render(
122
+ <OverlayProvider>
123
+ <ImageGalleryContext.Provider
124
+ value={
125
+ {
126
+ images: [
127
+ generateMessage({
128
+ attachments: [generateVideoAttachment({ type: 'video' })],
129
+ }),
130
+ ] as unknown as MessageType<DefaultStreamChatGenerics>[],
131
+ } as unknown as ImageGalleryContextValue
132
+ }
133
+ >
134
+ <Chat client={chatClient}>
135
+ <ImageGallery
136
+ imageGalleryCustomComponents={
137
+ {
138
+ footer: {
139
+ GridIcon: <CustomGridIconElement />,
140
+ ShareIcon: <CustomShareIconElement />,
141
+ },
142
+ } as ImageGalleryCustomComponents['imageGalleryCustomComponents']
143
+ }
144
+ overlayOpacity={{ value: 1 } as SharedValue<number>}
145
+ />
146
+ </Chat>
147
+ </ImageGalleryContext.Provider>
148
+ </OverlayProvider>,
149
+ );
150
+ expect(queryAllByText('Share Icon element')).toHaveLength(1);
151
+ expect(queryAllByText('Grid Icon element')).toHaveLength(1);
152
+ });
153
+
154
+ it('should trigger the share button onPress Handler', async () => {
155
+ const chatClient = await getTestClientWithUser({ id: 'testID' });
156
+ const saveFileMock = jest.spyOn(NativeUtils, 'saveFile');
157
+ const shareImageMock = jest.spyOn(NativeUtils, 'shareImage');
158
+ const deleteFileMock = jest.spyOn(NativeUtils, 'deleteFile');
159
+
160
+ const { queryByA11yLabel } = render(
161
+ <OverlayProvider>
162
+ <ImageGalleryContext.Provider
163
+ value={
164
+ {
165
+ images: [
166
+ generateMessage({
167
+ attachments: [generateImageAttachment()],
168
+ }),
169
+ ] as unknown as MessageType<DefaultStreamChatGenerics>[],
170
+ } as unknown as ImageGalleryContextValue
171
+ }
172
+ >
173
+ <Chat client={chatClient}>
174
+ <ImageGallery overlayOpacity={{ value: 1 } as SharedValue<number>} />
175
+ </Chat>
176
+ </ImageGalleryContext.Provider>
177
+ </OverlayProvider>,
178
+ );
179
+
180
+ act(() => {
181
+ fireEvent(queryByA11yLabel('Share Button') as ReactTestInstance, 'onPress');
182
+ });
183
+
184
+ await waitFor(() => {
185
+ expect(saveFileMock).toHaveBeenCalled();
186
+ expect(shareImageMock).toHaveBeenCalled();
187
+ expect(deleteFileMock).toHaveBeenCalled();
188
+ });
189
+ });
190
+ });
@@ -0,0 +1,98 @@
1
+ import React from 'react';
2
+
3
+ import { Text, View } from 'react-native';
4
+ import { act } from 'react-test-renderer';
5
+
6
+ import { fireEvent, render } from '@testing-library/react-native';
7
+
8
+ import { ThemeProvider } from '../../../contexts/themeContext/ThemeContext';
9
+ import { defaultTheme } from '../../../contexts/themeContext/utils/theme';
10
+ import {
11
+ TranslationContextValue,
12
+ TranslationProvider,
13
+ } from '../../../contexts/translationContext/TranslationContext';
14
+ import {
15
+ generateImageAttachment,
16
+ generateVideoAttachment,
17
+ } from '../../../mock-builders/generator/attachment';
18
+ import { ImageGrid, ImageGridType } from '../components/ImageGrid';
19
+
20
+ jest.mock('@gorhom/bottom-sheet', () => {
21
+ const View = require('react-native/Libraries/Components/View/View');
22
+ const FlatList = require('react-native/Libraries/Lists/FlatList');
23
+ return {
24
+ BottomSheetFlatList: FlatList,
25
+ TouchableOpacity: View,
26
+ };
27
+ });
28
+
29
+ const getComponent = (props: Partial<ImageGridType> = {}) => {
30
+ const t = jest.fn((key) => key);
31
+
32
+ return (
33
+ <TranslationProvider value={{ t } as unknown as TranslationContextValue}>
34
+ <ThemeProvider style={defaultTheme}>
35
+ <ImageGrid {...(props as unknown as ImageGridType)} />
36
+ </ThemeProvider>
37
+ </TranslationProvider>
38
+ );
39
+ };
40
+
41
+ describe('ImageGalleryOverlay', () => {
42
+ it('should render ImageGalleryGrid', () => {
43
+ const { queryAllByA11yLabel } = render(
44
+ getComponent({ photos: [generateImageAttachment(), generateImageAttachment()] }),
45
+ );
46
+
47
+ expect(queryAllByA11yLabel('Image Grid')).toHaveLength(1);
48
+ });
49
+
50
+ it('should render ImageGalleryGrid individual images', () => {
51
+ const { queryAllByA11yLabel } = render(
52
+ getComponent({
53
+ photos: [generateImageAttachment(), generateVideoAttachment({ type: 'video' })],
54
+ }),
55
+ );
56
+
57
+ expect(queryAllByA11yLabel('Grid Image')).toHaveLength(2);
58
+ });
59
+
60
+ it('should render ImageGalleryGrid with custom image component', () => {
61
+ const CustomImageComponent = () => (
62
+ <View>
63
+ <Text>Image Attachment</Text>
64
+ </View>
65
+ );
66
+
67
+ const { queryAllByText } = render(
68
+ getComponent({
69
+ imageComponent: CustomImageComponent,
70
+ photos: [generateImageAttachment(), generateVideoAttachment({ type: 'video' })],
71
+ }),
72
+ );
73
+
74
+ expect(queryAllByText('Image Attachment')).toHaveLength(2);
75
+ });
76
+
77
+ it('should trigger the selectAndClose when the Image item is pressed', () => {
78
+ const closeGridViewMock = jest.fn();
79
+ const setImageMock = jest.fn();
80
+
81
+ const { getAllByA11yLabel } = render(
82
+ getComponent({
83
+ closeGridView: closeGridViewMock,
84
+ photos: [generateImageAttachment(), generateVideoAttachment({ type: 'video' })],
85
+ setImage: setImageMock,
86
+ }),
87
+ );
88
+
89
+ const component = getAllByA11yLabel('Grid Image');
90
+
91
+ act(() => {
92
+ fireEvent(component[0], 'onPress');
93
+ });
94
+
95
+ expect(closeGridViewMock).toHaveBeenCalledTimes(1);
96
+ expect(setImageMock).toHaveBeenCalledTimes(1);
97
+ });
98
+ });
@@ -0,0 +1,79 @@
1
+ import React from 'react';
2
+
3
+ import { Text, View } from 'react-native';
4
+
5
+ import { render } from '@testing-library/react-native';
6
+
7
+ import { ThemeProvider } from '../../../contexts/themeContext/ThemeContext';
8
+ import { defaultTheme } from '../../../contexts/themeContext/utils/theme';
9
+ import {
10
+ TranslationContextValue,
11
+ TranslationProvider,
12
+ } from '../../../contexts/translationContext/TranslationContext';
13
+ import {
14
+ ImageGalleryGridHandleCustomComponentProps,
15
+ ImageGridHandle,
16
+ } from '../components/ImageGridHandle';
17
+
18
+ type ImageGridHandleProps = ImageGalleryGridHandleCustomComponentProps & {
19
+ closeGridView: () => void;
20
+ };
21
+
22
+ jest.mock('@gorhom/bottom-sheet', () => {
23
+ const View = require('react-native/Libraries/Components/View/View');
24
+ return {
25
+ TouchableOpacity: View,
26
+ };
27
+ });
28
+
29
+ const getComponent = (props: Partial<ImageGridHandleProps> = {}) => {
30
+ const t = jest.fn((key) => key);
31
+
32
+ return (
33
+ <TranslationProvider value={{ t } as unknown as TranslationContextValue}>
34
+ <ThemeProvider style={defaultTheme}>
35
+ <ImageGridHandle {...(props as unknown as ImageGridHandleProps)} />
36
+ </ThemeProvider>
37
+ </TranslationProvider>
38
+ );
39
+ };
40
+
41
+ describe('ImageGalleryOverlay', () => {
42
+ it('should render ImageGalleryGridHandle', () => {
43
+ const { queryAllByA11yLabel } = render(getComponent());
44
+
45
+ expect(queryAllByA11yLabel('Image Grid Handle')).toHaveLength(1);
46
+ });
47
+
48
+ it('should render the custom components', () => {
49
+ const CustomLeftComponent = () => (
50
+ <View>
51
+ <Text>Left Element</Text>
52
+ </View>
53
+ );
54
+
55
+ const CustomRightComponent = () => (
56
+ <View>
57
+ <Text>Right Element</Text>
58
+ </View>
59
+ );
60
+
61
+ const CustomCenterComponent = () => (
62
+ <View>
63
+ <Text>Center Element</Text>
64
+ </View>
65
+ );
66
+
67
+ const { queryAllByText } = render(
68
+ getComponent({
69
+ centerComponent: CustomCenterComponent,
70
+ leftComponent: CustomLeftComponent,
71
+ rightComponent: CustomRightComponent,
72
+ }),
73
+ );
74
+
75
+ expect(queryAllByText('Left Element')).toHaveLength(1);
76
+ expect(queryAllByText('Right Element')).toHaveLength(1);
77
+ expect(queryAllByText('Center Element')).toHaveLength(1);
78
+ });
79
+ });
@@ -0,0 +1,172 @@
1
+ import React from 'react';
2
+
3
+ import { Text, View } from 'react-native';
4
+ import type { SharedValue } from 'react-native-reanimated';
5
+
6
+ import { act, ReactTestInstance } from 'react-test-renderer';
7
+
8
+ import { fireEvent, render, waitFor } from '@testing-library/react-native';
9
+
10
+ import { Chat } from '../../../components/Chat/Chat';
11
+ import {
12
+ ImageGalleryContext,
13
+ ImageGalleryContextValue,
14
+ } from '../../../contexts/imageGalleryContext/ImageGalleryContext';
15
+ import {
16
+ OverlayContext,
17
+ OverlayContextValue,
18
+ } from '../../../contexts/overlayContext/OverlayContext';
19
+ import { OverlayProvider } from '../../../contexts/overlayContext/OverlayProvider';
20
+ import {
21
+ generateImageAttachment,
22
+ generateVideoAttachment,
23
+ } from '../../../mock-builders/generator/attachment';
24
+ import { generateMessage } from '../../../mock-builders/generator/message';
25
+ import { getTestClientWithUser } from '../../../mock-builders/mock';
26
+ import type { DefaultStreamChatGenerics } from '../../../types/types';
27
+ import type { MessageType } from '../../MessageList/hooks/useMessageList';
28
+ import { ImageGallery, ImageGalleryCustomComponents } from '../ImageGallery';
29
+
30
+ jest.mock('../../../native.ts', () => {
31
+ const View = require('react-native/Libraries/Components/View/View');
32
+ return {
33
+ isVideoPackageAvailable: jest.fn(() => true),
34
+ NetInfo: {
35
+ addEventListener: jest.fn(),
36
+ },
37
+ Video: View,
38
+ };
39
+ });
40
+
41
+ describe('ImageGalleryHeader', () => {
42
+ it('render image gallery header component with custom component header props', async () => {
43
+ const chatClient = await getTestClientWithUser({ id: 'testID' });
44
+
45
+ const CustomHeaderLeftElement = () => (
46
+ <View>
47
+ <Text>Left element</Text>
48
+ </View>
49
+ );
50
+
51
+ const CustomHeaderRightElement = () => (
52
+ <View>
53
+ <Text>Right element</Text>
54
+ </View>
55
+ );
56
+
57
+ const CustomHeaderCenterElement = () => (
58
+ <View>
59
+ <Text>Center element</Text>
60
+ </View>
61
+ );
62
+
63
+ const { queryAllByText } = render(
64
+ <OverlayProvider>
65
+ <ImageGalleryContext.Provider
66
+ value={
67
+ {
68
+ images: [
69
+ generateMessage({
70
+ attachments: [generateImageAttachment()],
71
+ }),
72
+ ] as unknown as MessageType<DefaultStreamChatGenerics>[],
73
+ } as unknown as ImageGalleryContextValue
74
+ }
75
+ >
76
+ <Chat client={chatClient}>
77
+ <ImageGallery
78
+ imageGalleryCustomComponents={
79
+ {
80
+ header: {
81
+ centerElement: CustomHeaderCenterElement,
82
+ leftElement: CustomHeaderLeftElement,
83
+ rightElement: CustomHeaderRightElement,
84
+ },
85
+ } as ImageGalleryCustomComponents['imageGalleryCustomComponents']
86
+ }
87
+ overlayOpacity={{ value: 1 } as SharedValue<number>}
88
+ />
89
+ </Chat>
90
+ </ImageGalleryContext.Provider>
91
+ </OverlayProvider>,
92
+ );
93
+ expect(queryAllByText('Left element')).toHaveLength(1);
94
+ expect(queryAllByText('Right element')).toHaveLength(1);
95
+ expect(queryAllByText('Center element')).toHaveLength(1);
96
+ });
97
+
98
+ it('render image gallery header component with custom Close Icon component', async () => {
99
+ const chatClient = await getTestClientWithUser({ id: 'testID' });
100
+
101
+ const CustomCloseIconElement = () => (
102
+ <View>
103
+ <Text>Close Icon element</Text>
104
+ </View>
105
+ );
106
+
107
+ const { queryAllByText } = render(
108
+ <OverlayProvider>
109
+ <ImageGalleryContext.Provider
110
+ value={
111
+ {
112
+ images: [
113
+ generateMessage({
114
+ attachments: [generateVideoAttachment({ type: 'video' })],
115
+ }),
116
+ ] as unknown as MessageType<DefaultStreamChatGenerics>[],
117
+ } as unknown as ImageGalleryContextValue
118
+ }
119
+ >
120
+ <Chat client={chatClient}>
121
+ <ImageGallery
122
+ imageGalleryCustomComponents={
123
+ {
124
+ header: {
125
+ CloseIcon: <CustomCloseIconElement />,
126
+ },
127
+ } as ImageGalleryCustomComponents['imageGalleryCustomComponents']
128
+ }
129
+ overlayOpacity={{ value: 1 } as SharedValue<number>}
130
+ />
131
+ </Chat>
132
+ </ImageGalleryContext.Provider>
133
+ </OverlayProvider>,
134
+ );
135
+ expect(queryAllByText('Close Icon element')).toHaveLength(1);
136
+ });
137
+
138
+ it('should trigger the hideOverlay function on button onPress', async () => {
139
+ const chatClient = await getTestClientWithUser({ id: 'testID' });
140
+ const setOverlayMock = jest.fn();
141
+
142
+ const { queryByA11yLabel } = render(
143
+ <OverlayContext.Provider
144
+ value={{ setOverlay: setOverlayMock } as unknown as OverlayContextValue}
145
+ >
146
+ <ImageGalleryContext.Provider
147
+ value={
148
+ {
149
+ images: [
150
+ generateMessage({
151
+ attachments: [generateImageAttachment()],
152
+ }),
153
+ ] as unknown as MessageType<DefaultStreamChatGenerics>[],
154
+ } as unknown as ImageGalleryContextValue
155
+ }
156
+ >
157
+ <Chat client={chatClient}>
158
+ <ImageGallery overlayOpacity={{ value: 1 } as SharedValue<number>} />
159
+ </Chat>
160
+ </ImageGalleryContext.Provider>
161
+ </OverlayContext.Provider>,
162
+ );
163
+
164
+ act(() => {
165
+ fireEvent(queryByA11yLabel('Hide Overlay') as ReactTestInstance, 'onPress');
166
+ });
167
+
168
+ await waitFor(() => {
169
+ expect(setOverlayMock).toHaveBeenCalledWith('none');
170
+ });
171
+ });
172
+ });
@@ -0,0 +1,94 @@
1
+ import React from 'react';
2
+
3
+ import { State } from 'react-native-gesture-handler';
4
+ import type { SharedValue } from 'react-native-reanimated';
5
+
6
+ import { act } from 'react-test-renderer';
7
+
8
+ import { fireEvent, render, waitFor } from '@testing-library/react-native';
9
+
10
+ import { Chat } from '../../../components/Chat/Chat';
11
+ import {
12
+ ImageGalleryContext,
13
+ ImageGalleryContextValue,
14
+ } from '../../../contexts/imageGalleryContext/ImageGalleryContext';
15
+ import {
16
+ OverlayContext,
17
+ OverlayContextValue,
18
+ } from '../../../contexts/overlayContext/OverlayContext';
19
+ import { generateImageAttachment } from '../../../mock-builders/generator/attachment';
20
+ import { generateMessage } from '../../../mock-builders/generator/message';
21
+ import { getTestClientWithUser } from '../../../mock-builders/mock';
22
+ import * as NativeUtils from '../../../native';
23
+ import type { DefaultStreamChatGenerics } from '../../../types/types';
24
+ import type { MessageType } from '../../MessageList/hooks/useMessageList';
25
+ import { ImageGalleryOverlay } from '../components/ImageGalleryOverlay';
26
+
27
+ describe('ImageGalleryOverlay', () => {
28
+ jest.spyOn(NativeUtils, 'isVideoPackageAvailable').mockImplementation(() => true);
29
+
30
+ it('should have currentBottomSheetIndex as a prop', async () => {
31
+ const chatClient = await getTestClientWithUser({ id: 'testID' });
32
+ const setOverlayMock = jest.fn();
33
+
34
+ const { queryByTestId } = render(
35
+ <OverlayContext.Provider
36
+ value={{ setOverlay: setOverlayMock } as unknown as OverlayContextValue}
37
+ >
38
+ <ImageGalleryContext.Provider
39
+ value={
40
+ {
41
+ images: [
42
+ generateMessage({
43
+ attachments: [generateImageAttachment()],
44
+ }),
45
+ ] as unknown as MessageType<DefaultStreamChatGenerics>[],
46
+ } as unknown as ImageGalleryContextValue
47
+ }
48
+ >
49
+ <Chat client={chatClient}>
50
+ <ImageGalleryOverlay
51
+ animatedBottomSheetIndex={{ value: 1 } as SharedValue<number>}
52
+ closeGridView={jest.fn()}
53
+ currentBottomSheetIndex={1}
54
+ />
55
+ </Chat>
56
+ </ImageGalleryContext.Provider>
57
+ </OverlayContext.Provider>,
58
+ );
59
+
60
+ await waitFor(() => {
61
+ const view = queryByTestId('image-gallery-overlay');
62
+ expect(view).not.toBeUndefined();
63
+ });
64
+ });
65
+
66
+ it('should trigger tapEvent on handler state change', async () => {
67
+ const closeGridViewMock = jest.fn();
68
+ const chatClient = await getTestClientWithUser({ id: 'testID' });
69
+
70
+ const { getByTestId } = render(
71
+ <Chat client={chatClient}>
72
+ <ImageGalleryOverlay
73
+ animatedBottomSheetIndex={{ value: 1 } as SharedValue<number>}
74
+ closeGridView={closeGridViewMock}
75
+ currentBottomSheetIndex={1}
76
+ />
77
+ </Chat>,
78
+ );
79
+
80
+ const view = getByTestId('image-gallery-overlay');
81
+
82
+ act(() => {
83
+ fireEvent(view, 'onHandlerStateChange', {
84
+ nativeEvent: {
85
+ state: State.END,
86
+ },
87
+ });
88
+ });
89
+
90
+ await waitFor(() => {
91
+ expect(closeGridViewMock).toHaveBeenCalled();
92
+ });
93
+ });
94
+ });