@patternfly/chatbot 6.3.0-prerelease.14 → 6.3.0-prerelease.16

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.
@@ -1,9 +1,20 @@
1
1
  import { createRef } from 'react';
2
- import { render, screen, waitFor } from '@testing-library/react';
3
- import { MessageBox } from './MessageBox';
2
+ import { act, fireEvent, render, screen, waitFor } from '@testing-library/react';
3
+ import { MessageBox, MessageBoxHandle } from './MessageBox';
4
4
  import userEvent from '@testing-library/user-event';
5
5
 
6
6
  describe('MessageBox', () => {
7
+ beforeEach(() => {
8
+ jest.spyOn(window, 'requestAnimationFrame').mockImplementation((cb) => {
9
+ cb(0); // Immediately call the callback
10
+ return 0;
11
+ });
12
+ });
13
+
14
+ afterEach(() => {
15
+ jest.restoreAllMocks();
16
+ });
17
+
7
18
  it('should render Message box', () => {
8
19
  render(
9
20
  <MessageBox>
@@ -14,17 +25,25 @@ describe('MessageBox', () => {
14
25
  });
15
26
 
16
27
  it('should assign ref to Message box', () => {
17
- const ref = createRef<HTMLDivElement>();
28
+ const ref = createRef<MessageBoxHandle>();
18
29
  render(
19
- <MessageBox ref={ref}>
30
+ <MessageBox data-testid="message-box" ref={ref}>
20
31
  <div>Test message content</div>
21
32
  </MessageBox>
22
33
  );
23
34
 
35
+ screen.getByText('Test message content');
36
+
24
37
  expect(ref.current).not.toBeNull();
38
+ // should contain custom methods exposed by the ref
39
+ expect(typeof ref.current?.isSmartScrollActive).toBe('function');
40
+ expect(typeof ref.current?.scrollToTop).toBe('function');
41
+ expect(typeof ref.current?.scrollToBottom).toBe('function');
42
+ expect(ref.current?.isSmartScrollActive()).toBe(false);
43
+
25
44
  expect(ref.current).toBeInstanceOf(HTMLDivElement);
26
45
  });
27
- it('should call onScrollToBottomClick when scroll to top button is clicked', async () => {
46
+ it('should call onScrollToBottomClick when scroll to bottom button is clicked', async () => {
28
47
  const spy = jest.fn();
29
48
  render(
30
49
  <MessageBox onScrollToBottomClick={spy}>
@@ -37,7 +56,9 @@ describe('MessageBox', () => {
37
56
  Object.defineProperty(region, 'scrollHeight', { configurable: true, value: 1000 });
38
57
  Object.defineProperty(region, 'clientHeight', { configurable: true, value: 500 });
39
58
  Object.defineProperty(region, 'scrollTop', { configurable: true, value: 0 });
40
- region.dispatchEvent(new Event('scroll'));
59
+ act(() => {
60
+ region.dispatchEvent(new Event('scroll'));
61
+ });
41
62
 
42
63
  await waitFor(() => {
43
64
  userEvent.click(screen.getByRole('button', { name: /Jump bottom/i }));
@@ -60,11 +81,236 @@ describe('MessageBox', () => {
60
81
  configurable: true,
61
82
  value: 500
62
83
  });
63
- region.dispatchEvent(new Event('scroll'));
64
-
84
+ act(() => {
85
+ region.dispatchEvent(new Event('scroll'));
86
+ });
65
87
  await waitFor(() => {
66
88
  userEvent.click(screen.getByRole('button', { name: /Jump top/i }));
67
89
  expect(spy).toHaveBeenCalled();
68
90
  });
69
91
  });
92
+
93
+ it('should call user defined onWheel, onTouchMove and onTouchEnd handlers', async () => {
94
+ const ref = createRef<MessageBoxHandle>();
95
+ const onWheel = jest.fn();
96
+ const onTouchMove = jest.fn();
97
+ const onTouchEnd = jest.fn();
98
+
99
+ render(
100
+ <MessageBox ref={ref} enableSmartScroll onWheel={onWheel} onTouchMove={onTouchMove} onTouchEnd={onTouchEnd}>
101
+ <div>Test message content</div>
102
+ </MessageBox>
103
+ );
104
+
105
+ const element = ref.current!;
106
+ act(() => {
107
+ fireEvent.wheel(element, { deltaY: 10 });
108
+ fireEvent.touchMove(element, { touches: [{ clientY: 700 }] });
109
+ fireEvent.touchEnd(element);
110
+ });
111
+
112
+ expect(onWheel).toHaveBeenCalled();
113
+ expect(onTouchMove).toHaveBeenCalled();
114
+ expect(onTouchEnd).toHaveBeenCalled();
115
+ });
116
+
117
+ it('should scroll to the bottom when the method is called ', async () => {
118
+ const ref = createRef<MessageBoxHandle>();
119
+
120
+ render(
121
+ <MessageBox ref={ref} enableSmartScroll>
122
+ <div>Test message content</div>
123
+ </MessageBox>
124
+ );
125
+ const element = ref.current!;
126
+ const scrollSpy = jest.spyOn(element, 'scrollTo');
127
+
128
+ act(() => {
129
+ ref.current?.scrollToBottom();
130
+ ref.current?.scrollToBottom();
131
+ ref.current?.scrollToBottom();
132
+ });
133
+
134
+ expect(scrollSpy).toHaveBeenCalledWith({ top: element.scrollHeight, behavior: 'smooth' });
135
+ expect(ref.current?.isSmartScrollActive()).toBe(true);
136
+ });
137
+
138
+ it('should scroll to the top when the method is called ', async () => {
139
+ const ref = createRef<MessageBoxHandle>();
140
+
141
+ render(
142
+ <MessageBox ref={ref} enableSmartScroll>
143
+ <div>Test message content</div>
144
+ </MessageBox>
145
+ );
146
+ const element = ref.current!;
147
+ const scrollSpy = jest.spyOn(element, 'scrollTo');
148
+
149
+ act(() => {
150
+ ref.current?.scrollToTop();
151
+ });
152
+
153
+ expect(scrollSpy).toHaveBeenCalledWith({ top: 0, behavior: 'smooth' });
154
+ expect(ref.current?.isSmartScrollActive()).toBe(false);
155
+ });
156
+
157
+ it('should pause automatic scrolling when user scrolls up ', async () => {
158
+ const ref = createRef<MessageBoxHandle>();
159
+
160
+ render(
161
+ <MessageBox ref={ref} enableSmartScroll>
162
+ <div>Test message content</div>
163
+ </MessageBox>
164
+ );
165
+
166
+ expect(ref.current?.isSmartScrollActive()).toBe(true);
167
+
168
+ const element = ref.current!;
169
+
170
+ // Manually set scrollHeight and clientHeight for calculations
171
+ Object.defineProperty(element, 'scrollHeight', { configurable: true, value: 1000 });
172
+ Object.defineProperty(element, 'clientHeight', { configurable: true, value: 300 });
173
+
174
+ // Simulate scroll up by changing scrollTop
175
+ element.scrollTop = 200;
176
+ const scrollEvent = new Event('scroll', { bubbles: true });
177
+
178
+ act(() => {
179
+ element.dispatchEvent(scrollEvent);
180
+ });
181
+
182
+ expect(ref.current?.isSmartScrollActive()).toBe(false);
183
+ });
184
+
185
+ it('should resume automatic scrolling when user scrolls down to the bottom using scroll event', async () => {
186
+ jest.useFakeTimers();
187
+
188
+ const ref = createRef<MessageBoxHandle>();
189
+ render(
190
+ <MessageBox ref={ref} enableSmartScroll>
191
+ <div>Test message content</div>
192
+ </MessageBox>
193
+ );
194
+
195
+ const element = ref.current!;
196
+ // Manually set scrollHeight and clientHeight for calculations
197
+ Object.defineProperty(element, 'scrollHeight', { configurable: true, value: 1000 });
198
+ Object.defineProperty(element, 'clientHeight', { configurable: true, value: 300 });
199
+
200
+ // Simulate scroll up by changing scrollTop
201
+ element.scrollTop = 100;
202
+ const scrollEvent = new Event('scroll', { bubbles: true });
203
+
204
+ act(() => {
205
+ element.dispatchEvent(scrollEvent);
206
+ });
207
+
208
+ expect(ref.current?.isSmartScrollActive()).toBe(false);
209
+
210
+ act(() => {
211
+ // Simulate scroll down by changing scrollTop
212
+ element.scrollTop = 650; // scrollHeight - scrollTop - clientHeight - DELTA_DOWN (50) = 0
213
+ const scrollEvent = new Event('scroll', { bubbles: true });
214
+ element.dispatchEvent(scrollEvent);
215
+ jest.advanceTimersByTime(250);
216
+ });
217
+
218
+ expect(ref.current?.isSmartScrollActive()).toBe(true);
219
+ jest.useRealTimers();
220
+ });
221
+
222
+ it('should resume automatic scrolling when scrollToBottom method is used', async () => {
223
+ const ref = createRef<MessageBoxHandle>();
224
+ render(
225
+ <MessageBox ref={ref} enableSmartScroll>
226
+ <div>Test message content</div>
227
+ </MessageBox>
228
+ );
229
+
230
+ const element = ref.current!;
231
+ // Manually set scrollHeight and clientHeight for calculations
232
+ Object.defineProperty(element, 'scrollHeight', { configurable: true, value: 1000 });
233
+ Object.defineProperty(element, 'clientHeight', { configurable: true, value: 300 });
234
+
235
+ // Simulate scroll up by changing scrollTop
236
+ element.scrollTop = 100;
237
+ const scrollEvent = new Event('scroll', { bubbles: true });
238
+
239
+ act(() => {
240
+ element.dispatchEvent(scrollEvent);
241
+ });
242
+
243
+ expect(ref.current?.isSmartScrollActive()).toBe(false);
244
+
245
+ act(() => {
246
+ ref.current?.scrollToBottom({ resumeSmartScroll: true, behavior: 'auto' }); // resumes auto scroll and scrolls to bottom.
247
+ });
248
+
249
+ expect(ref.current?.isSmartScrollActive()).toBe(true);
250
+ });
251
+
252
+ it('should resume automatic scrolling when mouse wheel event is used', async () => {
253
+ const ref = createRef<MessageBoxHandle>();
254
+ render(
255
+ <MessageBox ref={ref} enableSmartScroll>
256
+ <div>Test message content</div>
257
+ </MessageBox>
258
+ );
259
+
260
+ const element = ref.current!;
261
+ // Manually set scrollHeight and clientHeight for calculations
262
+ Object.defineProperty(element, 'scrollHeight', { configurable: true, value: 1000 });
263
+ Object.defineProperty(element, 'clientHeight', { configurable: true, value: 300 });
264
+ Object.defineProperty(element, 'scrollTop', { configurable: true, value: 350 });
265
+
266
+ const scrollEvent = new Event('scroll', { bubbles: true });
267
+
268
+ act(() => {
269
+ element.dispatchEvent(scrollEvent);
270
+ });
271
+
272
+ expect(ref.current?.isSmartScrollActive()).toBe(false);
273
+
274
+ // Simulate mouse wheel event
275
+ act(() => {
276
+ Object.defineProperty(element, 'scrollTop', { configurable: true, value: 650 });
277
+ fireEvent.wheel(element, { deltaY: 10 });
278
+ });
279
+
280
+ expect(ref.current?.isSmartScrollActive()).toBe(true);
281
+ });
282
+
283
+ it('should resume automatic scrolling when user swipes up in touch screen', async () => {
284
+ const ref = createRef<MessageBoxHandle>();
285
+ render(
286
+ <MessageBox ref={ref} enableSmartScroll>
287
+ <div>Test message content</div>
288
+ </MessageBox>
289
+ );
290
+
291
+ const element = ref.current!;
292
+ // Manually set scrollHeight and clientHeight for calculations
293
+ Object.defineProperty(element, 'scrollHeight', { configurable: true, value: 1000 });
294
+ Object.defineProperty(element, 'clientHeight', { configurable: true, value: 300 });
295
+ Object.defineProperty(element, 'scrollTop', { configurable: true, value: 350 });
296
+
297
+ const scrollEvent = new Event('scroll', { bubbles: true });
298
+
299
+ act(() => {
300
+ element.dispatchEvent(scrollEvent);
301
+ });
302
+
303
+ expect(ref.current?.isSmartScrollActive()).toBe(false);
304
+
305
+ // Simulate touch event - swipe up
306
+ act(() => {
307
+ Object.defineProperty(element, 'scrollTop', { configurable: true, value: 650 });
308
+ fireEvent.touchStart(element, { touches: [{ clientY: 700 }] });
309
+ fireEvent.touchMove(element, { touches: [{ clientY: 700 }] });
310
+ fireEvent.touchMove(element, { touches: [{ clientY: 600 }] });
311
+ fireEvent.touchEnd(element);
312
+ });
313
+
314
+ expect(ref.current?.isSmartScrollActive()).toBe(true);
315
+ });
70
316
  });