@patternfly/chatbot 6.6.0-prerelease.4 → 6.6.0-prerelease.6
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.
- package/dist/cjs/Message/Message.d.ts +6 -0
- package/dist/cjs/Message/Message.js +2 -2
- package/dist/cjs/Message/Message.test.js +109 -0
- package/dist/cjs/ResponseActions/ResponseActions.d.ts +9 -0
- package/dist/cjs/ResponseActions/ResponseActions.js +30 -5
- package/dist/cjs/ResponseActions/ResponseActions.test.js +134 -0
- package/dist/css/main.css +10 -0
- package/dist/css/main.css.map +1 -1
- package/dist/esm/Message/Message.d.ts +6 -0
- package/dist/esm/Message/Message.js +2 -2
- package/dist/esm/Message/Message.test.js +109 -0
- package/dist/esm/ResponseActions/ResponseActions.d.ts +9 -0
- package/dist/esm/ResponseActions/ResponseActions.js +31 -6
- package/dist/esm/ResponseActions/ResponseActions.test.js +135 -1
- package/package.json +1 -1
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithIconSwapping.tsx +22 -0
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithResponseActions.tsx +39 -18
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/Messages.md +18 -6
- package/src/Message/Message.scss +12 -0
- package/src/Message/Message.test.tsx +200 -0
- package/src/Message/Message.tsx +21 -2
- package/src/ResponseActions/ResponseActions.test.tsx +259 -0
- package/src/ResponseActions/ResponseActions.tsx +65 -12
|
@@ -9,6 +9,23 @@ import rehypeExternalLinks from '../__mocks__/rehype-external-links';
|
|
|
9
9
|
import { AlertActionLink, Button, CodeBlockAction } from '@patternfly/react-core';
|
|
10
10
|
import { DeepThinkingProps } from '../DeepThinking';
|
|
11
11
|
|
|
12
|
+
// Mock the icon components
|
|
13
|
+
jest.mock('@patternfly/react-icons', () => ({
|
|
14
|
+
OutlinedThumbsUpIcon: () => <div>OutlinedThumbsUpIcon</div>,
|
|
15
|
+
ThumbsUpIcon: () => <div>ThumbsUpIcon</div>,
|
|
16
|
+
OutlinedThumbsDownIcon: () => <div>OutlinedThumbsDownIcon</div>,
|
|
17
|
+
ThumbsDownIcon: () => <div>ThumbsDownIcon</div>,
|
|
18
|
+
OutlinedCopyIcon: () => <div>OutlinedCopyIcon</div>,
|
|
19
|
+
DownloadIcon: () => <div>DownloadIcon</div>,
|
|
20
|
+
ExternalLinkAltIcon: () => <div>ExternalLinkAltIcon</div>,
|
|
21
|
+
VolumeUpIcon: () => <div>VolumeUpIcon</div>,
|
|
22
|
+
PencilAltIcon: () => <div>PencilAltIcon</div>,
|
|
23
|
+
CheckIcon: () => <div>CheckIcon</div>,
|
|
24
|
+
CloseIcon: () => <div>CloseIcon</div>,
|
|
25
|
+
ExternalLinkSquareAltIcon: () => <div>ExternalLinkSquareAltIcon</div>,
|
|
26
|
+
TimesIcon: () => <div>TimesIcon</div>
|
|
27
|
+
}));
|
|
28
|
+
|
|
12
29
|
const ALL_ACTIONS = [
|
|
13
30
|
{ label: /Good response/i },
|
|
14
31
|
{ label: /Bad response/i },
|
|
@@ -1351,4 +1368,187 @@ describe('Message', () => {
|
|
|
1351
1368
|
render(<Message alignment="end" avatar="./img" role="user" name="User" content="" />);
|
|
1352
1369
|
expect(screen.getByRole('region')).toHaveClass('pf-m-end');
|
|
1353
1370
|
});
|
|
1371
|
+
|
|
1372
|
+
// We're just testing the positive action here to ensure logic passes through as needed, the other actions are
|
|
1373
|
+
// tested in ResponseActions.test.tsx along with other aspects of this functionality
|
|
1374
|
+
it('should not swap icons when useFilledIconsOnClick is omitted', async () => {
|
|
1375
|
+
const user = userEvent.setup();
|
|
1376
|
+
|
|
1377
|
+
render(
|
|
1378
|
+
<Message
|
|
1379
|
+
avatar="./img"
|
|
1380
|
+
role="bot"
|
|
1381
|
+
name="Bot"
|
|
1382
|
+
content="Hi"
|
|
1383
|
+
actions={{
|
|
1384
|
+
positive: { onClick: jest.fn() }
|
|
1385
|
+
}}
|
|
1386
|
+
/>
|
|
1387
|
+
);
|
|
1388
|
+
|
|
1389
|
+
expect(screen.getByText('OutlinedThumbsUpIcon')).toBeInTheDocument();
|
|
1390
|
+
|
|
1391
|
+
await user.click(screen.getByRole('button', { name: /Good response/i }));
|
|
1392
|
+
|
|
1393
|
+
expect(screen.getByText('OutlinedThumbsUpIcon')).toBeInTheDocument();
|
|
1394
|
+
expect(screen.queryByText('ThumbsUpIcon')).not.toBeInTheDocument();
|
|
1395
|
+
});
|
|
1396
|
+
|
|
1397
|
+
it('should swap icons when useFilledIconsOnClick is true', async () => {
|
|
1398
|
+
const user = userEvent.setup();
|
|
1399
|
+
|
|
1400
|
+
render(
|
|
1401
|
+
<Message
|
|
1402
|
+
avatar="./img"
|
|
1403
|
+
role="bot"
|
|
1404
|
+
name="Bot"
|
|
1405
|
+
content="Hi"
|
|
1406
|
+
actions={{
|
|
1407
|
+
positive: { onClick: jest.fn() }
|
|
1408
|
+
}}
|
|
1409
|
+
useFilledIconsOnClick
|
|
1410
|
+
/>
|
|
1411
|
+
);
|
|
1412
|
+
|
|
1413
|
+
await user.click(screen.getByRole('button', { name: /Good response/i }));
|
|
1414
|
+
|
|
1415
|
+
expect(screen.getByText('ThumbsUpIcon')).toBeInTheDocument();
|
|
1416
|
+
expect(screen.queryByText('OutlinedThumbsUpIcon')).not.toBeInTheDocument();
|
|
1417
|
+
});
|
|
1418
|
+
|
|
1419
|
+
it('should apply pf-m-visible-interaction class to response actions when showActionsOnInteraction is true', () => {
|
|
1420
|
+
render(
|
|
1421
|
+
<Message
|
|
1422
|
+
avatar="./img"
|
|
1423
|
+
role="bot"
|
|
1424
|
+
name="Bot"
|
|
1425
|
+
content="Hi"
|
|
1426
|
+
showActionsOnInteraction
|
|
1427
|
+
actions={{
|
|
1428
|
+
positive: { onClick: jest.fn() }
|
|
1429
|
+
}}
|
|
1430
|
+
/>
|
|
1431
|
+
);
|
|
1432
|
+
|
|
1433
|
+
const responseContainer = screen
|
|
1434
|
+
.getByRole('button', { name: 'Good response' })
|
|
1435
|
+
.closest('.pf-chatbot__response-actions');
|
|
1436
|
+
expect(responseContainer).toHaveClass('pf-m-visible-interaction');
|
|
1437
|
+
});
|
|
1438
|
+
|
|
1439
|
+
it('should not apply pf-m-visible-interaction class to response actions when showActionsOnInteraction is false', () => {
|
|
1440
|
+
render(
|
|
1441
|
+
<Message
|
|
1442
|
+
avatar="./img"
|
|
1443
|
+
role="bot"
|
|
1444
|
+
name="Bot"
|
|
1445
|
+
content="Hi"
|
|
1446
|
+
showActionsOnInteraction={false}
|
|
1447
|
+
actions={{
|
|
1448
|
+
positive: { onClick: jest.fn() }
|
|
1449
|
+
}}
|
|
1450
|
+
/>
|
|
1451
|
+
);
|
|
1452
|
+
|
|
1453
|
+
const responseContainer = screen
|
|
1454
|
+
.getByRole('button', { name: 'Good response' })
|
|
1455
|
+
.closest('.pf-chatbot__response-actions');
|
|
1456
|
+
expect(responseContainer).not.toHaveClass('pf-m-visible-interaction');
|
|
1457
|
+
});
|
|
1458
|
+
|
|
1459
|
+
it('should not apply pf-m-visible-interaction class to response actions by default', () => {
|
|
1460
|
+
render(
|
|
1461
|
+
<Message
|
|
1462
|
+
avatar="./img"
|
|
1463
|
+
role="bot"
|
|
1464
|
+
name="Bot"
|
|
1465
|
+
content="Hi"
|
|
1466
|
+
actions={{
|
|
1467
|
+
positive: { onClick: jest.fn() }
|
|
1468
|
+
}}
|
|
1469
|
+
/>
|
|
1470
|
+
);
|
|
1471
|
+
|
|
1472
|
+
const responseContainer = screen
|
|
1473
|
+
.getByRole('button', { name: 'Good response' })
|
|
1474
|
+
.closest('.pf-chatbot__response-actions');
|
|
1475
|
+
expect(responseContainer).not.toHaveClass('pf-m-visible-interaction');
|
|
1476
|
+
});
|
|
1477
|
+
|
|
1478
|
+
it('should apply pf-m-visible-interaction class to grouped actions container when showActionsOnInteraction is true', () => {
|
|
1479
|
+
render(
|
|
1480
|
+
<Message
|
|
1481
|
+
avatar="./img"
|
|
1482
|
+
role="bot"
|
|
1483
|
+
name="Bot"
|
|
1484
|
+
content="Hi"
|
|
1485
|
+
showActionsOnInteraction
|
|
1486
|
+
actions={[
|
|
1487
|
+
{
|
|
1488
|
+
positive: { onClick: jest.fn() },
|
|
1489
|
+
negative: { onClick: jest.fn() }
|
|
1490
|
+
},
|
|
1491
|
+
{
|
|
1492
|
+
copy: { onClick: jest.fn() }
|
|
1493
|
+
}
|
|
1494
|
+
]}
|
|
1495
|
+
/>
|
|
1496
|
+
);
|
|
1497
|
+
|
|
1498
|
+
const responseContainer = screen
|
|
1499
|
+
.getByRole('button', { name: 'Good response' })
|
|
1500
|
+
.closest('.pf-chatbot__response-actions-groups');
|
|
1501
|
+
expect(responseContainer).toHaveClass('pf-m-visible-interaction');
|
|
1502
|
+
});
|
|
1503
|
+
|
|
1504
|
+
it('should not apply pf-m-visible-interaction class to grouped actions container when showActionsOnInteraction is false', () => {
|
|
1505
|
+
render(
|
|
1506
|
+
<Message
|
|
1507
|
+
avatar="./img"
|
|
1508
|
+
role="bot"
|
|
1509
|
+
name="Bot"
|
|
1510
|
+
content="Hi"
|
|
1511
|
+
showActionsOnInteraction={false}
|
|
1512
|
+
actions={[
|
|
1513
|
+
{
|
|
1514
|
+
positive: { onClick: jest.fn() },
|
|
1515
|
+
negative: { onClick: jest.fn() }
|
|
1516
|
+
},
|
|
1517
|
+
{
|
|
1518
|
+
copy: { onClick: jest.fn() }
|
|
1519
|
+
}
|
|
1520
|
+
]}
|
|
1521
|
+
/>
|
|
1522
|
+
);
|
|
1523
|
+
|
|
1524
|
+
const responseContainer = screen
|
|
1525
|
+
.getByRole('button', { name: 'Good response' })
|
|
1526
|
+
.closest('.pf-chatbot__response-actions-groups');
|
|
1527
|
+
expect(responseContainer).not.toHaveClass('pf-m-visible-interaction');
|
|
1528
|
+
});
|
|
1529
|
+
|
|
1530
|
+
it('should not apply pf-m-visible-interaction class to grouped actions container by default', () => {
|
|
1531
|
+
render(
|
|
1532
|
+
<Message
|
|
1533
|
+
avatar="./img"
|
|
1534
|
+
role="bot"
|
|
1535
|
+
name="Bot"
|
|
1536
|
+
content="Hi"
|
|
1537
|
+
actions={[
|
|
1538
|
+
{
|
|
1539
|
+
positive: { onClick: jest.fn() },
|
|
1540
|
+
negative: { onClick: jest.fn() }
|
|
1541
|
+
},
|
|
1542
|
+
{
|
|
1543
|
+
copy: { onClick: jest.fn() }
|
|
1544
|
+
}
|
|
1545
|
+
]}
|
|
1546
|
+
/>
|
|
1547
|
+
);
|
|
1548
|
+
|
|
1549
|
+
const responseContainer = screen
|
|
1550
|
+
.getByRole('button', { name: 'Good response' })
|
|
1551
|
+
.closest('.pf-chatbot__response-actions-groups');
|
|
1552
|
+
expect(responseContainer).not.toHaveClass('pf-m-visible-interaction');
|
|
1553
|
+
});
|
|
1354
1554
|
});
|
package/src/Message/Message.tsx
CHANGED
|
@@ -114,6 +114,10 @@ export interface MessageProps extends Omit<HTMLProps<HTMLDivElement>, 'role'> {
|
|
|
114
114
|
* For finer control of multiple action groups, use persistActionSelection on each group.
|
|
115
115
|
*/
|
|
116
116
|
persistActionSelection?: boolean;
|
|
117
|
+
/** Flag indicating whether the actions container is only visible when a message is hovered or an action would receive focus. Note
|
|
118
|
+
* that setting this to true will append tooltips inline instead of the document.body.
|
|
119
|
+
*/
|
|
120
|
+
showActionsOnInteraction?: boolean;
|
|
117
121
|
/** Sources for message */
|
|
118
122
|
sources?: SourcesCardProps;
|
|
119
123
|
/** Label for the English word "AI," used to tag messages with role "bot" */
|
|
@@ -197,6 +201,8 @@ export interface MessageProps extends Omit<HTMLProps<HTMLDivElement>, 'role'> {
|
|
|
197
201
|
hasNoImagesInUserMessages?: boolean;
|
|
198
202
|
/** Sets background colors to be appropriate on primary chatbot background */
|
|
199
203
|
isPrimary?: boolean;
|
|
204
|
+
/** When true, automatically swaps to filled icon variants when predefined actions are clicked. */
|
|
205
|
+
useFilledIconsOnClick?: boolean;
|
|
200
206
|
}
|
|
201
207
|
|
|
202
208
|
export const MessageBase: FunctionComponent<MessageProps> = ({
|
|
@@ -212,6 +218,7 @@ export const MessageBase: FunctionComponent<MessageProps> = ({
|
|
|
212
218
|
isLoading,
|
|
213
219
|
actions,
|
|
214
220
|
persistActionSelection,
|
|
221
|
+
showActionsOnInteraction = false,
|
|
215
222
|
sources,
|
|
216
223
|
botWord = 'AI',
|
|
217
224
|
loadingWord = 'Loading message',
|
|
@@ -249,6 +256,7 @@ export const MessageBase: FunctionComponent<MessageProps> = ({
|
|
|
249
256
|
toolCall,
|
|
250
257
|
hasNoImagesInUserMessages = true,
|
|
251
258
|
isPrimary,
|
|
259
|
+
useFilledIconsOnClick,
|
|
252
260
|
...props
|
|
253
261
|
}: MessageProps) => {
|
|
254
262
|
const [messageText, setMessageText] = useState(content);
|
|
@@ -379,17 +387,28 @@ export const MessageBase: FunctionComponent<MessageProps> = ({
|
|
|
379
387
|
{!isLoading && !isEditable && actions && (
|
|
380
388
|
<>
|
|
381
389
|
{Array.isArray(actions) ? (
|
|
382
|
-
<div
|
|
390
|
+
<div
|
|
391
|
+
className={css(
|
|
392
|
+
'pf-chatbot__response-actions-groups',
|
|
393
|
+
showActionsOnInteraction && 'pf-m-visible-interaction'
|
|
394
|
+
)}
|
|
395
|
+
>
|
|
383
396
|
{actions.map((actionGroup, index) => (
|
|
384
397
|
<ResponseActions
|
|
385
398
|
key={index}
|
|
386
399
|
actions={actionGroup.actions || actionGroup}
|
|
387
400
|
persistActionSelection={persistActionSelection || actionGroup.persistActionSelection}
|
|
401
|
+
useFilledIconsOnClick={useFilledIconsOnClick}
|
|
388
402
|
/>
|
|
389
403
|
))}
|
|
390
404
|
</div>
|
|
391
405
|
) : (
|
|
392
|
-
<ResponseActions
|
|
406
|
+
<ResponseActions
|
|
407
|
+
actions={actions}
|
|
408
|
+
persistActionSelection={persistActionSelection}
|
|
409
|
+
useFilledIconsOnClick={useFilledIconsOnClick}
|
|
410
|
+
showActionsOnInteraction={showActionsOnInteraction}
|
|
411
|
+
/>
|
|
393
412
|
)}
|
|
394
413
|
</>
|
|
395
414
|
)}
|
|
@@ -5,6 +5,21 @@ import userEvent from '@testing-library/user-event';
|
|
|
5
5
|
import { DownloadIcon, InfoCircleIcon, RedoIcon } from '@patternfly/react-icons';
|
|
6
6
|
import Message from '../Message';
|
|
7
7
|
|
|
8
|
+
// Mock the icon components
|
|
9
|
+
jest.mock('@patternfly/react-icons', () => ({
|
|
10
|
+
OutlinedThumbsUpIcon: () => <div>OutlinedThumbsUpIcon</div>,
|
|
11
|
+
ThumbsUpIcon: () => <div>ThumbsUpIcon</div>,
|
|
12
|
+
OutlinedThumbsDownIcon: () => <div>OutlinedThumbsDownIcon</div>,
|
|
13
|
+
ThumbsDownIcon: () => <div>ThumbsDownIcon</div>,
|
|
14
|
+
OutlinedCopyIcon: () => <div>OutlinedCopyIcon</div>,
|
|
15
|
+
DownloadIcon: () => <div>DownloadIcon</div>,
|
|
16
|
+
InfoCircleIcon: () => <div>InfoCircleIcon</div>,
|
|
17
|
+
RedoIcon: () => <div>RedoIcon</div>,
|
|
18
|
+
ExternalLinkAltIcon: () => <div>ExternalLinkAltIcon</div>,
|
|
19
|
+
VolumeUpIcon: () => <div>VolumeUpIcon</div>,
|
|
20
|
+
PencilAltIcon: () => <div>PencilAltIcon</div>
|
|
21
|
+
}));
|
|
22
|
+
|
|
8
23
|
const ALL_ACTIONS = [
|
|
9
24
|
{ type: 'positive', label: 'Good response', clickedLabel: 'Good response recorded' },
|
|
10
25
|
{ type: 'negative', label: 'Bad response', clickedLabel: 'Bad response recorded' },
|
|
@@ -421,4 +436,248 @@ describe('ResponseActions', () => {
|
|
|
421
436
|
await userEvent.click(customBtn);
|
|
422
437
|
expect(customBtn).not.toHaveClass('pf-chatbot__button--response-action-clicked');
|
|
423
438
|
});
|
|
439
|
+
|
|
440
|
+
it('should apply pf-m-visible-interaction class when showActionsOnInteraction is true', () => {
|
|
441
|
+
render(
|
|
442
|
+
<ResponseActions
|
|
443
|
+
data-testid="test-id"
|
|
444
|
+
actions={{
|
|
445
|
+
positive: { onClick: jest.fn() },
|
|
446
|
+
negative: { onClick: jest.fn() }
|
|
447
|
+
}}
|
|
448
|
+
showActionsOnInteraction
|
|
449
|
+
/>
|
|
450
|
+
);
|
|
451
|
+
|
|
452
|
+
expect(screen.getByTestId('test-id')).toHaveClass('pf-m-visible-interaction');
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
it('should not apply pf-m-visible-interaction class when showActionsOnInteraction is false', () => {
|
|
456
|
+
render(
|
|
457
|
+
<ResponseActions
|
|
458
|
+
data-testid="test-id"
|
|
459
|
+
actions={{
|
|
460
|
+
positive: { onClick: jest.fn() },
|
|
461
|
+
negative: { onClick: jest.fn() }
|
|
462
|
+
}}
|
|
463
|
+
showActionsOnInteraction={false}
|
|
464
|
+
/>
|
|
465
|
+
);
|
|
466
|
+
|
|
467
|
+
expect(screen.getByTestId('test-id')).not.toHaveClass('pf-m-visible-interaction');
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
it('should not apply pf-m-visible-interaction class by default', () => {
|
|
471
|
+
render(
|
|
472
|
+
<ResponseActions
|
|
473
|
+
data-testid="test-id"
|
|
474
|
+
actions={{
|
|
475
|
+
positive: { onClick: jest.fn() },
|
|
476
|
+
negative: { onClick: jest.fn() }
|
|
477
|
+
}}
|
|
478
|
+
/>
|
|
479
|
+
);
|
|
480
|
+
|
|
481
|
+
expect(screen.getByTestId('test-id')).not.toHaveClass('pf-m-visible-interaction');
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
it('should render with custom className', () => {
|
|
485
|
+
render(
|
|
486
|
+
<ResponseActions
|
|
487
|
+
data-testid="test-id"
|
|
488
|
+
actions={{
|
|
489
|
+
positive: { onClick: jest.fn() },
|
|
490
|
+
negative: { onClick: jest.fn() }
|
|
491
|
+
}}
|
|
492
|
+
className="custom-class"
|
|
493
|
+
/>
|
|
494
|
+
);
|
|
495
|
+
|
|
496
|
+
expect(screen.getByTestId('test-id')).toHaveClass('custom-class');
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
describe('icon swapping with useFilledIconsOnClick', () => {
|
|
500
|
+
it('should render outline icons by default', () => {
|
|
501
|
+
render(
|
|
502
|
+
<ResponseActions
|
|
503
|
+
actions={{
|
|
504
|
+
positive: { onClick: jest.fn() },
|
|
505
|
+
negative: { onClick: jest.fn() }
|
|
506
|
+
}}
|
|
507
|
+
/>
|
|
508
|
+
);
|
|
509
|
+
|
|
510
|
+
expect(screen.getByText('OutlinedThumbsUpIcon')).toBeInTheDocument();
|
|
511
|
+
expect(screen.getByText('OutlinedThumbsDownIcon')).toBeInTheDocument();
|
|
512
|
+
|
|
513
|
+
expect(screen.queryByText('ThumbsUpIcon')).not.toBeInTheDocument();
|
|
514
|
+
expect(screen.queryByText('ThumbsDownIcon')).not.toBeInTheDocument();
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
describe('positive actions', () => {
|
|
518
|
+
it('should not swap positive icon when clicked and useFilledIconsOnClick is false', async () => {
|
|
519
|
+
const user = userEvent.setup();
|
|
520
|
+
|
|
521
|
+
render(
|
|
522
|
+
<ResponseActions
|
|
523
|
+
actions={{
|
|
524
|
+
positive: { onClick: jest.fn() }
|
|
525
|
+
}}
|
|
526
|
+
useFilledIconsOnClick={false}
|
|
527
|
+
/>
|
|
528
|
+
);
|
|
529
|
+
|
|
530
|
+
await user.click(screen.getByRole('button', { name: 'Good response' }));
|
|
531
|
+
|
|
532
|
+
expect(screen.getByText('OutlinedThumbsUpIcon')).toBeInTheDocument();
|
|
533
|
+
expect(screen.queryByText('ThumbsUpIcon')).not.toBeInTheDocument();
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
it('should swap positive icon from outline to filled when clicked with useFilledIconsOnClick', async () => {
|
|
537
|
+
const user = userEvent.setup();
|
|
538
|
+
|
|
539
|
+
render(
|
|
540
|
+
<ResponseActions
|
|
541
|
+
actions={{
|
|
542
|
+
positive: { onClick: jest.fn() }
|
|
543
|
+
}}
|
|
544
|
+
useFilledIconsOnClick
|
|
545
|
+
/>
|
|
546
|
+
);
|
|
547
|
+
|
|
548
|
+
await user.click(screen.getByRole('button', { name: 'Good response' }));
|
|
549
|
+
|
|
550
|
+
expect(screen.getByText('ThumbsUpIcon')).toBeInTheDocument();
|
|
551
|
+
expect(screen.queryByText('OutlinedThumbsUpIcon')).not.toBeInTheDocument();
|
|
552
|
+
});
|
|
553
|
+
|
|
554
|
+
it('should revert positive icon to outline icon when clicking outside', async () => {
|
|
555
|
+
const user = userEvent.setup();
|
|
556
|
+
|
|
557
|
+
render(
|
|
558
|
+
<div>
|
|
559
|
+
<ResponseActions
|
|
560
|
+
actions={{
|
|
561
|
+
positive: { onClick: jest.fn() }
|
|
562
|
+
}}
|
|
563
|
+
useFilledIconsOnClick
|
|
564
|
+
/>
|
|
565
|
+
<div data-testid="outside">Outside</div>
|
|
566
|
+
</div>
|
|
567
|
+
);
|
|
568
|
+
|
|
569
|
+
await user.click(screen.getByRole('button', { name: 'Good response' }));
|
|
570
|
+
expect(screen.getByText('ThumbsUpIcon')).toBeInTheDocument();
|
|
571
|
+
|
|
572
|
+
await user.click(screen.getByTestId('outside'));
|
|
573
|
+
expect(screen.getByText('OutlinedThumbsUpIcon')).toBeInTheDocument();
|
|
574
|
+
});
|
|
575
|
+
|
|
576
|
+
it('should not revert positive icon to outline icon when clicking outside if persistActionSelection is true', async () => {
|
|
577
|
+
const user = userEvent.setup();
|
|
578
|
+
|
|
579
|
+
render(
|
|
580
|
+
<div>
|
|
581
|
+
<ResponseActions
|
|
582
|
+
actions={{
|
|
583
|
+
positive: { onClick: jest.fn() }
|
|
584
|
+
}}
|
|
585
|
+
persistActionSelection
|
|
586
|
+
useFilledIconsOnClick
|
|
587
|
+
/>
|
|
588
|
+
<div data-testid="outside">Outside</div>
|
|
589
|
+
</div>
|
|
590
|
+
);
|
|
591
|
+
|
|
592
|
+
await user.click(screen.getByRole('button', { name: 'Good response' }));
|
|
593
|
+
expect(screen.getByText('ThumbsUpIcon')).toBeInTheDocument();
|
|
594
|
+
|
|
595
|
+
await user.click(screen.getByTestId('outside'));
|
|
596
|
+
expect(screen.getByText('ThumbsUpIcon')).toBeInTheDocument();
|
|
597
|
+
});
|
|
598
|
+
|
|
599
|
+
describe('negative actions', () => {
|
|
600
|
+
it('should not swap negative icon when clicked and useFilledIconsOnClick is false', async () => {
|
|
601
|
+
const user = userEvent.setup();
|
|
602
|
+
|
|
603
|
+
render(
|
|
604
|
+
<ResponseActions
|
|
605
|
+
actions={{
|
|
606
|
+
negative: { onClick: jest.fn() }
|
|
607
|
+
}}
|
|
608
|
+
useFilledIconsOnClick={false}
|
|
609
|
+
/>
|
|
610
|
+
);
|
|
611
|
+
|
|
612
|
+
await user.click(screen.getByRole('button', { name: 'Bad response' }));
|
|
613
|
+
|
|
614
|
+
expect(screen.getByText('OutlinedThumbsDownIcon')).toBeInTheDocument();
|
|
615
|
+
expect(screen.queryByText('ThumbsDownIcon')).not.toBeInTheDocument();
|
|
616
|
+
});
|
|
617
|
+
|
|
618
|
+
it('should swap negative icon from outline to filled when clicked with useFilledIconsOnClick', async () => {
|
|
619
|
+
const user = userEvent.setup();
|
|
620
|
+
|
|
621
|
+
render(
|
|
622
|
+
<ResponseActions
|
|
623
|
+
actions={{
|
|
624
|
+
negative: { onClick: jest.fn() }
|
|
625
|
+
}}
|
|
626
|
+
useFilledIconsOnClick
|
|
627
|
+
/>
|
|
628
|
+
);
|
|
629
|
+
|
|
630
|
+
await user.click(screen.getByRole('button', { name: 'Bad response' }));
|
|
631
|
+
|
|
632
|
+
expect(screen.getByText('ThumbsDownIcon')).toBeInTheDocument();
|
|
633
|
+
expect(screen.queryByText('OutlinedThumbsDownIcon')).not.toBeInTheDocument();
|
|
634
|
+
});
|
|
635
|
+
|
|
636
|
+
it('should revert negative icon to outline when clicking outside', async () => {
|
|
637
|
+
const user = userEvent.setup();
|
|
638
|
+
|
|
639
|
+
render(
|
|
640
|
+
<div>
|
|
641
|
+
<ResponseActions
|
|
642
|
+
actions={{
|
|
643
|
+
negative: { onClick: jest.fn() }
|
|
644
|
+
}}
|
|
645
|
+
useFilledIconsOnClick
|
|
646
|
+
/>
|
|
647
|
+
<div data-testid="outside">Outside</div>
|
|
648
|
+
</div>
|
|
649
|
+
);
|
|
650
|
+
|
|
651
|
+
await user.click(screen.getByRole('button', { name: 'Bad response' }));
|
|
652
|
+
expect(screen.getByText('ThumbsDownIcon')).toBeInTheDocument();
|
|
653
|
+
|
|
654
|
+
await user.click(screen.getByTestId('outside'));
|
|
655
|
+
expect(screen.getByText('OutlinedThumbsDownIcon')).toBeInTheDocument();
|
|
656
|
+
});
|
|
657
|
+
|
|
658
|
+
it('should not revert negative icon to outline icon when clicking outside if persistActionSelection is true', async () => {
|
|
659
|
+
const user = userEvent.setup();
|
|
660
|
+
|
|
661
|
+
render(
|
|
662
|
+
<div>
|
|
663
|
+
<ResponseActions
|
|
664
|
+
actions={{
|
|
665
|
+
negative: { onClick: jest.fn() }
|
|
666
|
+
}}
|
|
667
|
+
persistActionSelection
|
|
668
|
+
useFilledIconsOnClick
|
|
669
|
+
/>
|
|
670
|
+
<div data-testid="outside">Outside</div>
|
|
671
|
+
</div>
|
|
672
|
+
);
|
|
673
|
+
|
|
674
|
+
await user.click(screen.getByRole('button', { name: 'Bad response' }));
|
|
675
|
+
expect(screen.getByText('ThumbsDownIcon')).toBeInTheDocument();
|
|
676
|
+
|
|
677
|
+
await user.click(screen.getByTestId('outside'));
|
|
678
|
+
expect(screen.getByText('ThumbsDownIcon')).toBeInTheDocument();
|
|
679
|
+
});
|
|
680
|
+
});
|
|
681
|
+
});
|
|
682
|
+
});
|
|
424
683
|
});
|