@patternfly/chatbot 6.3.0-prerelease.11 → 6.3.0-prerelease.12

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,6 +1,6 @@
1
1
  import React from 'react';
2
- import { TooltipProps } from '@patternfly/react-core';
3
- export interface ResponseActionButtonProps {
2
+ import { ButtonProps, TooltipProps } from '@patternfly/react-core';
3
+ export interface ResponseActionButtonProps extends ButtonProps {
4
4
  /** Aria-label for the button. Defaults to the value of the tooltipContent if none provided */
5
5
  ariaLabel?: string;
6
6
  /** Aria-label for the button, shown when the button is clicked. Defaults to the value of ariaLabel or tooltipContent if not provided. */
@@ -26,9 +26,12 @@ export interface ActionProps extends Omit<ButtonProps, 'ref'> {
26
26
  /** Id for content controlled by the button, such as the feedback form */
27
27
  'aria-controls'?: string;
28
28
  }
29
+ type ExtendedActionProps = ActionProps & {
30
+ [key: string]: any;
31
+ };
29
32
  export interface ResponseActionProps {
30
33
  /** Props for message actions, such as feedback (positive or negative), copy button, share, and listen */
31
- actions: Record<string, ActionProps | undefined> & {
34
+ actions: Record<string, ExtendedActionProps | undefined> & {
32
35
  positive?: ActionProps;
33
36
  negative?: ActionProps;
34
37
  copy?: ActionProps;
@@ -39,14 +39,14 @@ const ResponseActions = ({ actions }) => {
39
39
  onClick && onClick(e);
40
40
  };
41
41
  return (react_1.default.createElement("div", { ref: responseActions, className: "pf-chatbot__response-actions" },
42
- positive && (react_1.default.createElement(ResponseActionButton_1.default, { ariaLabel: (_a = positive.ariaLabel) !== null && _a !== void 0 ? _a : 'Good response', clickedAriaLabel: (_b = positive.ariaLabel) !== null && _b !== void 0 ? _b : 'Response recorded', onClick: (e) => handleClick(e, 'positive', positive.onClick), className: positive.className, isDisabled: positive.isDisabled, tooltipContent: (_c = positive.tooltipContent) !== null && _c !== void 0 ? _c : 'Good response', clickedTooltipContent: (_d = positive.clickedTooltipContent) !== null && _d !== void 0 ? _d : 'Response recorded', tooltipProps: positive.tooltipProps, icon: react_1.default.createElement(react_icons_1.OutlinedThumbsUpIcon, null), isClicked: activeButton === 'positive', ref: positive.ref, "aria-expanded": positive['aria-expanded'], "aria-controls": positive['aria-controls'] })),
43
- negative && (react_1.default.createElement(ResponseActionButton_1.default, { ariaLabel: (_e = negative.ariaLabel) !== null && _e !== void 0 ? _e : 'Bad response', clickedAriaLabel: (_f = negative.ariaLabel) !== null && _f !== void 0 ? _f : 'Response recorded', onClick: (e) => handleClick(e, 'negative', negative.onClick), className: negative.className, isDisabled: negative.isDisabled, tooltipContent: (_g = negative.tooltipContent) !== null && _g !== void 0 ? _g : 'Bad response', clickedTooltipContent: (_h = negative.clickedTooltipContent) !== null && _h !== void 0 ? _h : 'Response recorded', tooltipProps: negative.tooltipProps, icon: react_1.default.createElement(react_icons_1.OutlinedThumbsDownIcon, null), isClicked: activeButton === 'negative', ref: negative.ref, "aria-expanded": negative['aria-expanded'], "aria-controls": negative['aria-controls'] })),
44
- copy && (react_1.default.createElement(ResponseActionButton_1.default, { ariaLabel: (_j = copy.ariaLabel) !== null && _j !== void 0 ? _j : 'Copy', clickedAriaLabel: (_k = copy.ariaLabel) !== null && _k !== void 0 ? _k : 'Copied', onClick: (e) => handleClick(e, 'copy', copy.onClick), className: copy.className, isDisabled: copy.isDisabled, tooltipContent: (_l = copy.tooltipContent) !== null && _l !== void 0 ? _l : 'Copy', clickedTooltipContent: (_m = copy.clickedTooltipContent) !== null && _m !== void 0 ? _m : 'Copied', tooltipProps: copy.tooltipProps, icon: react_1.default.createElement(react_icons_1.OutlinedCopyIcon, null), isClicked: activeButton === 'copy', ref: copy.ref, "aria-expanded": copy['aria-expanded'], "aria-controls": copy['aria-controls'] })),
45
- share && (react_1.default.createElement(ResponseActionButton_1.default, { ariaLabel: (_o = share.ariaLabel) !== null && _o !== void 0 ? _o : 'Share', clickedAriaLabel: (_p = share.ariaLabel) !== null && _p !== void 0 ? _p : 'Shared', onClick: (e) => handleClick(e, 'share', share.onClick), className: share.className, isDisabled: share.isDisabled, tooltipContent: (_q = share.tooltipContent) !== null && _q !== void 0 ? _q : 'Share', clickedTooltipContent: (_r = share.clickedTooltipContent) !== null && _r !== void 0 ? _r : 'Shared', tooltipProps: share.tooltipProps, icon: react_1.default.createElement(react_icons_1.ExternalLinkAltIcon, null), isClicked: activeButton === 'share', ref: share.ref, "aria-expanded": share['aria-expanded'], "aria-controls": share['aria-controls'] })),
46
- listen && (react_1.default.createElement(ResponseActionButton_1.default, { ariaLabel: (_s = listen.ariaLabel) !== null && _s !== void 0 ? _s : 'Listen', clickedAriaLabel: (_t = listen.ariaLabel) !== null && _t !== void 0 ? _t : 'Listening', onClick: (e) => handleClick(e, 'listen', listen.onClick), className: listen.className, isDisabled: listen.isDisabled, tooltipContent: (_u = listen.tooltipContent) !== null && _u !== void 0 ? _u : 'Listen', clickedTooltipContent: (_v = listen.clickedTooltipContent) !== null && _v !== void 0 ? _v : 'Listening', tooltipProps: listen.tooltipProps, icon: react_1.default.createElement(react_icons_1.VolumeUpIcon, null), isClicked: activeButton === 'listen', ref: listen.ref, "aria-expanded": listen['aria-expanded'], "aria-controls": listen['aria-controls'] })),
42
+ positive && (react_1.default.createElement(ResponseActionButton_1.default, Object.assign({}, positive, { ariaLabel: (_a = positive.ariaLabel) !== null && _a !== void 0 ? _a : 'Good response', clickedAriaLabel: (_b = positive.ariaLabel) !== null && _b !== void 0 ? _b : 'Response recorded', onClick: (e) => handleClick(e, 'positive', positive.onClick), className: positive.className, isDisabled: positive.isDisabled, tooltipContent: (_c = positive.tooltipContent) !== null && _c !== void 0 ? _c : 'Good response', clickedTooltipContent: (_d = positive.clickedTooltipContent) !== null && _d !== void 0 ? _d : 'Response recorded', tooltipProps: positive.tooltipProps, icon: react_1.default.createElement(react_icons_1.OutlinedThumbsUpIcon, null), isClicked: activeButton === 'positive', ref: positive.ref, "aria-expanded": positive['aria-expanded'], "aria-controls": positive['aria-controls'] }))),
43
+ negative && (react_1.default.createElement(ResponseActionButton_1.default, Object.assign({}, negative, { ariaLabel: (_e = negative.ariaLabel) !== null && _e !== void 0 ? _e : 'Bad response', clickedAriaLabel: (_f = negative.ariaLabel) !== null && _f !== void 0 ? _f : 'Response recorded', onClick: (e) => handleClick(e, 'negative', negative.onClick), className: negative.className, isDisabled: negative.isDisabled, tooltipContent: (_g = negative.tooltipContent) !== null && _g !== void 0 ? _g : 'Bad response', clickedTooltipContent: (_h = negative.clickedTooltipContent) !== null && _h !== void 0 ? _h : 'Response recorded', tooltipProps: negative.tooltipProps, icon: react_1.default.createElement(react_icons_1.OutlinedThumbsDownIcon, null), isClicked: activeButton === 'negative', ref: negative.ref, "aria-expanded": negative['aria-expanded'], "aria-controls": negative['aria-controls'] }))),
44
+ copy && (react_1.default.createElement(ResponseActionButton_1.default, Object.assign({}, copy, { ariaLabel: (_j = copy.ariaLabel) !== null && _j !== void 0 ? _j : 'Copy', clickedAriaLabel: (_k = copy.ariaLabel) !== null && _k !== void 0 ? _k : 'Copied', onClick: (e) => handleClick(e, 'copy', copy.onClick), className: copy.className, isDisabled: copy.isDisabled, tooltipContent: (_l = copy.tooltipContent) !== null && _l !== void 0 ? _l : 'Copy', clickedTooltipContent: (_m = copy.clickedTooltipContent) !== null && _m !== void 0 ? _m : 'Copied', tooltipProps: copy.tooltipProps, icon: react_1.default.createElement(react_icons_1.OutlinedCopyIcon, null), isClicked: activeButton === 'copy', ref: copy.ref, "aria-expanded": copy['aria-expanded'], "aria-controls": copy['aria-controls'] }))),
45
+ share && (react_1.default.createElement(ResponseActionButton_1.default, Object.assign({}, share, { ariaLabel: (_o = share.ariaLabel) !== null && _o !== void 0 ? _o : 'Share', clickedAriaLabel: (_p = share.ariaLabel) !== null && _p !== void 0 ? _p : 'Shared', onClick: (e) => handleClick(e, 'share', share.onClick), className: share.className, isDisabled: share.isDisabled, tooltipContent: (_q = share.tooltipContent) !== null && _q !== void 0 ? _q : 'Share', clickedTooltipContent: (_r = share.clickedTooltipContent) !== null && _r !== void 0 ? _r : 'Shared', tooltipProps: share.tooltipProps, icon: react_1.default.createElement(react_icons_1.ExternalLinkAltIcon, null), isClicked: activeButton === 'share', ref: share.ref, "aria-expanded": share['aria-expanded'], "aria-controls": share['aria-controls'] }))),
46
+ listen && (react_1.default.createElement(ResponseActionButton_1.default, Object.assign({}, listen, { ariaLabel: (_s = listen.ariaLabel) !== null && _s !== void 0 ? _s : 'Listen', clickedAriaLabel: (_t = listen.ariaLabel) !== null && _t !== void 0 ? _t : 'Listening', onClick: (e) => handleClick(e, 'listen', listen.onClick), className: listen.className, isDisabled: listen.isDisabled, tooltipContent: (_u = listen.tooltipContent) !== null && _u !== void 0 ? _u : 'Listen', clickedTooltipContent: (_v = listen.clickedTooltipContent) !== null && _v !== void 0 ? _v : 'Listening', tooltipProps: listen.tooltipProps, icon: react_1.default.createElement(react_icons_1.VolumeUpIcon, null), isClicked: activeButton === 'listen', ref: listen.ref, "aria-expanded": listen['aria-expanded'], "aria-controls": listen['aria-controls'] }))),
47
47
  Object.keys(additionalActions).map((action) => {
48
48
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
49
- return (react_1.default.createElement(ResponseActionButton_1.default, { key: action, ariaLabel: (_a = additionalActions[action]) === null || _a === void 0 ? void 0 : _a.ariaLabel, clickedAriaLabel: (_b = additionalActions[action]) === null || _b === void 0 ? void 0 : _b.clickedAriaLabel, onClick: (e) => { var _a; return handleClick(e, action, (_a = additionalActions[action]) === null || _a === void 0 ? void 0 : _a.onClick); }, className: (_c = additionalActions[action]) === null || _c === void 0 ? void 0 : _c.className, isDisabled: (_d = additionalActions[action]) === null || _d === void 0 ? void 0 : _d.isDisabled, tooltipContent: (_e = additionalActions[action]) === null || _e === void 0 ? void 0 : _e.tooltipContent, tooltipProps: (_f = additionalActions[action]) === null || _f === void 0 ? void 0 : _f.tooltipProps, clickedTooltipContent: (_g = additionalActions[action]) === null || _g === void 0 ? void 0 : _g.clickedTooltipContent, icon: (_h = additionalActions[action]) === null || _h === void 0 ? void 0 : _h.icon, isClicked: activeButton === action, ref: (_j = additionalActions[action]) === null || _j === void 0 ? void 0 : _j.ref, "aria-expanded": (_k = additionalActions[action]) === null || _k === void 0 ? void 0 : _k['aria-expanded'], "aria-controls": (_l = additionalActions[action]) === null || _l === void 0 ? void 0 : _l['aria-controls'] }));
49
+ return (react_1.default.createElement(ResponseActionButton_1.default, Object.assign({}, additionalActions[action], { key: action, ariaLabel: (_a = additionalActions[action]) === null || _a === void 0 ? void 0 : _a.ariaLabel, clickedAriaLabel: (_b = additionalActions[action]) === null || _b === void 0 ? void 0 : _b.clickedAriaLabel, onClick: (e) => { var _a; return handleClick(e, action, (_a = additionalActions[action]) === null || _a === void 0 ? void 0 : _a.onClick); }, className: (_c = additionalActions[action]) === null || _c === void 0 ? void 0 : _c.className, isDisabled: (_d = additionalActions[action]) === null || _d === void 0 ? void 0 : _d.isDisabled, tooltipContent: (_e = additionalActions[action]) === null || _e === void 0 ? void 0 : _e.tooltipContent, tooltipProps: (_f = additionalActions[action]) === null || _f === void 0 ? void 0 : _f.tooltipProps, clickedTooltipContent: (_g = additionalActions[action]) === null || _g === void 0 ? void 0 : _g.clickedTooltipContent, icon: (_h = additionalActions[action]) === null || _h === void 0 ? void 0 : _h.icon, isClicked: activeButton === action, ref: (_j = additionalActions[action]) === null || _j === void 0 ? void 0 : _j.ref, "aria-expanded": (_k = additionalActions[action]) === null || _k === void 0 ? void 0 : _k['aria-expanded'], "aria-controls": (_l = additionalActions[action]) === null || _l === void 0 ? void 0 : _l['aria-controls'] })));
50
50
  })));
51
51
  };
52
52
  exports.ResponseActions = ResponseActions;
@@ -52,6 +52,13 @@ const CUSTOM_ACTIONS = [
52
52
  }
53
53
  }
54
54
  ];
55
+ const ALL_ACTIONS_DATA_TEST = [
56
+ { type: 'positive', label: 'Good response', dataTestId: 'positive' },
57
+ { type: 'negative', label: 'Bad response', dataTestId: 'negative' },
58
+ { type: 'copy', label: 'Copy', dataTestId: 'copy' },
59
+ { type: 'share', label: 'Share', dataTestId: 'share' },
60
+ { type: 'listen', label: 'Listen', dataTestId: 'listen' }
61
+ ];
55
62
  describe('ResponseActions', () => {
56
63
  afterEach(() => {
57
64
  jest.clearAllMocks();
@@ -161,6 +168,12 @@ describe('ResponseActions', () => {
161
168
  expect(react_2.screen.getByRole('button', { name: label })).toHaveClass('test');
162
169
  });
163
170
  });
171
+ it('should be able to add custom attributes to buttons', () => {
172
+ ALL_ACTIONS_DATA_TEST.forEach(({ type, dataTestId }) => {
173
+ (0, react_2.render)(react_1.default.createElement(ResponseActions_1.default, { actions: { [type]: { onClick: jest.fn(), 'data-testid': dataTestId } } }));
174
+ expect(react_2.screen.getByTestId(dataTestId)).toBeTruthy();
175
+ });
176
+ });
164
177
  it('should be able to add custom actions', () => {
165
178
  CUSTOM_ACTIONS.forEach((action) => {
166
179
  const key = Object.keys(action)[0];
@@ -170,10 +183,12 @@ describe('ResponseActions', () => {
170
183
  onClick: action[key].onClick,
171
184
  // doing this just because it's easier to test without a regex for the button name
172
185
  ariaLabel: action[key].ariaLabel.toLowerCase(),
173
- icon: action[key].icon
186
+ icon: action[key].icon,
187
+ 'data-testid': action[key]
174
188
  }
175
189
  } }));
176
190
  expect(react_2.screen.getByRole('button', { name: key })).toBeTruthy();
191
+ expect(react_2.screen.getByTestId(action[key])).toBeTruthy();
177
192
  });
178
193
  });
179
194
  });
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
- import { TooltipProps } from '@patternfly/react-core';
3
- export interface ResponseActionButtonProps {
2
+ import { ButtonProps, TooltipProps } from '@patternfly/react-core';
3
+ export interface ResponseActionButtonProps extends ButtonProps {
4
4
  /** Aria-label for the button. Defaults to the value of the tooltipContent if none provided */
5
5
  ariaLabel?: string;
6
6
  /** Aria-label for the button, shown when the button is clicked. Defaults to the value of ariaLabel or tooltipContent if not provided. */
@@ -26,9 +26,12 @@ export interface ActionProps extends Omit<ButtonProps, 'ref'> {
26
26
  /** Id for content controlled by the button, such as the feedback form */
27
27
  'aria-controls'?: string;
28
28
  }
29
+ type ExtendedActionProps = ActionProps & {
30
+ [key: string]: any;
31
+ };
29
32
  export interface ResponseActionProps {
30
33
  /** Props for message actions, such as feedback (positive or negative), copy button, share, and listen */
31
- actions: Record<string, ActionProps | undefined> & {
34
+ actions: Record<string, ExtendedActionProps | undefined> & {
32
35
  positive?: ActionProps;
33
36
  negative?: ActionProps;
34
37
  copy?: ActionProps;
@@ -33,14 +33,14 @@ export const ResponseActions = ({ actions }) => {
33
33
  onClick && onClick(e);
34
34
  };
35
35
  return (React.createElement("div", { ref: responseActions, className: "pf-chatbot__response-actions" },
36
- positive && (React.createElement(ResponseActionButton, { ariaLabel: (_a = positive.ariaLabel) !== null && _a !== void 0 ? _a : 'Good response', clickedAriaLabel: (_b = positive.ariaLabel) !== null && _b !== void 0 ? _b : 'Response recorded', onClick: (e) => handleClick(e, 'positive', positive.onClick), className: positive.className, isDisabled: positive.isDisabled, tooltipContent: (_c = positive.tooltipContent) !== null && _c !== void 0 ? _c : 'Good response', clickedTooltipContent: (_d = positive.clickedTooltipContent) !== null && _d !== void 0 ? _d : 'Response recorded', tooltipProps: positive.tooltipProps, icon: React.createElement(OutlinedThumbsUpIcon, null), isClicked: activeButton === 'positive', ref: positive.ref, "aria-expanded": positive['aria-expanded'], "aria-controls": positive['aria-controls'] })),
37
- negative && (React.createElement(ResponseActionButton, { ariaLabel: (_e = negative.ariaLabel) !== null && _e !== void 0 ? _e : 'Bad response', clickedAriaLabel: (_f = negative.ariaLabel) !== null && _f !== void 0 ? _f : 'Response recorded', onClick: (e) => handleClick(e, 'negative', negative.onClick), className: negative.className, isDisabled: negative.isDisabled, tooltipContent: (_g = negative.tooltipContent) !== null && _g !== void 0 ? _g : 'Bad response', clickedTooltipContent: (_h = negative.clickedTooltipContent) !== null && _h !== void 0 ? _h : 'Response recorded', tooltipProps: negative.tooltipProps, icon: React.createElement(OutlinedThumbsDownIcon, null), isClicked: activeButton === 'negative', ref: negative.ref, "aria-expanded": negative['aria-expanded'], "aria-controls": negative['aria-controls'] })),
38
- copy && (React.createElement(ResponseActionButton, { ariaLabel: (_j = copy.ariaLabel) !== null && _j !== void 0 ? _j : 'Copy', clickedAriaLabel: (_k = copy.ariaLabel) !== null && _k !== void 0 ? _k : 'Copied', onClick: (e) => handleClick(e, 'copy', copy.onClick), className: copy.className, isDisabled: copy.isDisabled, tooltipContent: (_l = copy.tooltipContent) !== null && _l !== void 0 ? _l : 'Copy', clickedTooltipContent: (_m = copy.clickedTooltipContent) !== null && _m !== void 0 ? _m : 'Copied', tooltipProps: copy.tooltipProps, icon: React.createElement(OutlinedCopyIcon, null), isClicked: activeButton === 'copy', ref: copy.ref, "aria-expanded": copy['aria-expanded'], "aria-controls": copy['aria-controls'] })),
39
- share && (React.createElement(ResponseActionButton, { ariaLabel: (_o = share.ariaLabel) !== null && _o !== void 0 ? _o : 'Share', clickedAriaLabel: (_p = share.ariaLabel) !== null && _p !== void 0 ? _p : 'Shared', onClick: (e) => handleClick(e, 'share', share.onClick), className: share.className, isDisabled: share.isDisabled, tooltipContent: (_q = share.tooltipContent) !== null && _q !== void 0 ? _q : 'Share', clickedTooltipContent: (_r = share.clickedTooltipContent) !== null && _r !== void 0 ? _r : 'Shared', tooltipProps: share.tooltipProps, icon: React.createElement(ExternalLinkAltIcon, null), isClicked: activeButton === 'share', ref: share.ref, "aria-expanded": share['aria-expanded'], "aria-controls": share['aria-controls'] })),
40
- listen && (React.createElement(ResponseActionButton, { ariaLabel: (_s = listen.ariaLabel) !== null && _s !== void 0 ? _s : 'Listen', clickedAriaLabel: (_t = listen.ariaLabel) !== null && _t !== void 0 ? _t : 'Listening', onClick: (e) => handleClick(e, 'listen', listen.onClick), className: listen.className, isDisabled: listen.isDisabled, tooltipContent: (_u = listen.tooltipContent) !== null && _u !== void 0 ? _u : 'Listen', clickedTooltipContent: (_v = listen.clickedTooltipContent) !== null && _v !== void 0 ? _v : 'Listening', tooltipProps: listen.tooltipProps, icon: React.createElement(VolumeUpIcon, null), isClicked: activeButton === 'listen', ref: listen.ref, "aria-expanded": listen['aria-expanded'], "aria-controls": listen['aria-controls'] })),
36
+ positive && (React.createElement(ResponseActionButton, Object.assign({}, positive, { ariaLabel: (_a = positive.ariaLabel) !== null && _a !== void 0 ? _a : 'Good response', clickedAriaLabel: (_b = positive.ariaLabel) !== null && _b !== void 0 ? _b : 'Response recorded', onClick: (e) => handleClick(e, 'positive', positive.onClick), className: positive.className, isDisabled: positive.isDisabled, tooltipContent: (_c = positive.tooltipContent) !== null && _c !== void 0 ? _c : 'Good response', clickedTooltipContent: (_d = positive.clickedTooltipContent) !== null && _d !== void 0 ? _d : 'Response recorded', tooltipProps: positive.tooltipProps, icon: React.createElement(OutlinedThumbsUpIcon, null), isClicked: activeButton === 'positive', ref: positive.ref, "aria-expanded": positive['aria-expanded'], "aria-controls": positive['aria-controls'] }))),
37
+ negative && (React.createElement(ResponseActionButton, Object.assign({}, negative, { ariaLabel: (_e = negative.ariaLabel) !== null && _e !== void 0 ? _e : 'Bad response', clickedAriaLabel: (_f = negative.ariaLabel) !== null && _f !== void 0 ? _f : 'Response recorded', onClick: (e) => handleClick(e, 'negative', negative.onClick), className: negative.className, isDisabled: negative.isDisabled, tooltipContent: (_g = negative.tooltipContent) !== null && _g !== void 0 ? _g : 'Bad response', clickedTooltipContent: (_h = negative.clickedTooltipContent) !== null && _h !== void 0 ? _h : 'Response recorded', tooltipProps: negative.tooltipProps, icon: React.createElement(OutlinedThumbsDownIcon, null), isClicked: activeButton === 'negative', ref: negative.ref, "aria-expanded": negative['aria-expanded'], "aria-controls": negative['aria-controls'] }))),
38
+ copy && (React.createElement(ResponseActionButton, Object.assign({}, copy, { ariaLabel: (_j = copy.ariaLabel) !== null && _j !== void 0 ? _j : 'Copy', clickedAriaLabel: (_k = copy.ariaLabel) !== null && _k !== void 0 ? _k : 'Copied', onClick: (e) => handleClick(e, 'copy', copy.onClick), className: copy.className, isDisabled: copy.isDisabled, tooltipContent: (_l = copy.tooltipContent) !== null && _l !== void 0 ? _l : 'Copy', clickedTooltipContent: (_m = copy.clickedTooltipContent) !== null && _m !== void 0 ? _m : 'Copied', tooltipProps: copy.tooltipProps, icon: React.createElement(OutlinedCopyIcon, null), isClicked: activeButton === 'copy', ref: copy.ref, "aria-expanded": copy['aria-expanded'], "aria-controls": copy['aria-controls'] }))),
39
+ share && (React.createElement(ResponseActionButton, Object.assign({}, share, { ariaLabel: (_o = share.ariaLabel) !== null && _o !== void 0 ? _o : 'Share', clickedAriaLabel: (_p = share.ariaLabel) !== null && _p !== void 0 ? _p : 'Shared', onClick: (e) => handleClick(e, 'share', share.onClick), className: share.className, isDisabled: share.isDisabled, tooltipContent: (_q = share.tooltipContent) !== null && _q !== void 0 ? _q : 'Share', clickedTooltipContent: (_r = share.clickedTooltipContent) !== null && _r !== void 0 ? _r : 'Shared', tooltipProps: share.tooltipProps, icon: React.createElement(ExternalLinkAltIcon, null), isClicked: activeButton === 'share', ref: share.ref, "aria-expanded": share['aria-expanded'], "aria-controls": share['aria-controls'] }))),
40
+ listen && (React.createElement(ResponseActionButton, Object.assign({}, listen, { ariaLabel: (_s = listen.ariaLabel) !== null && _s !== void 0 ? _s : 'Listen', clickedAriaLabel: (_t = listen.ariaLabel) !== null && _t !== void 0 ? _t : 'Listening', onClick: (e) => handleClick(e, 'listen', listen.onClick), className: listen.className, isDisabled: listen.isDisabled, tooltipContent: (_u = listen.tooltipContent) !== null && _u !== void 0 ? _u : 'Listen', clickedTooltipContent: (_v = listen.clickedTooltipContent) !== null && _v !== void 0 ? _v : 'Listening', tooltipProps: listen.tooltipProps, icon: React.createElement(VolumeUpIcon, null), isClicked: activeButton === 'listen', ref: listen.ref, "aria-expanded": listen['aria-expanded'], "aria-controls": listen['aria-controls'] }))),
41
41
  Object.keys(additionalActions).map((action) => {
42
42
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
43
- return (React.createElement(ResponseActionButton, { key: action, ariaLabel: (_a = additionalActions[action]) === null || _a === void 0 ? void 0 : _a.ariaLabel, clickedAriaLabel: (_b = additionalActions[action]) === null || _b === void 0 ? void 0 : _b.clickedAriaLabel, onClick: (e) => { var _a; return handleClick(e, action, (_a = additionalActions[action]) === null || _a === void 0 ? void 0 : _a.onClick); }, className: (_c = additionalActions[action]) === null || _c === void 0 ? void 0 : _c.className, isDisabled: (_d = additionalActions[action]) === null || _d === void 0 ? void 0 : _d.isDisabled, tooltipContent: (_e = additionalActions[action]) === null || _e === void 0 ? void 0 : _e.tooltipContent, tooltipProps: (_f = additionalActions[action]) === null || _f === void 0 ? void 0 : _f.tooltipProps, clickedTooltipContent: (_g = additionalActions[action]) === null || _g === void 0 ? void 0 : _g.clickedTooltipContent, icon: (_h = additionalActions[action]) === null || _h === void 0 ? void 0 : _h.icon, isClicked: activeButton === action, ref: (_j = additionalActions[action]) === null || _j === void 0 ? void 0 : _j.ref, "aria-expanded": (_k = additionalActions[action]) === null || _k === void 0 ? void 0 : _k['aria-expanded'], "aria-controls": (_l = additionalActions[action]) === null || _l === void 0 ? void 0 : _l['aria-controls'] }));
43
+ return (React.createElement(ResponseActionButton, Object.assign({}, additionalActions[action], { key: action, ariaLabel: (_a = additionalActions[action]) === null || _a === void 0 ? void 0 : _a.ariaLabel, clickedAriaLabel: (_b = additionalActions[action]) === null || _b === void 0 ? void 0 : _b.clickedAriaLabel, onClick: (e) => { var _a; return handleClick(e, action, (_a = additionalActions[action]) === null || _a === void 0 ? void 0 : _a.onClick); }, className: (_c = additionalActions[action]) === null || _c === void 0 ? void 0 : _c.className, isDisabled: (_d = additionalActions[action]) === null || _d === void 0 ? void 0 : _d.isDisabled, tooltipContent: (_e = additionalActions[action]) === null || _e === void 0 ? void 0 : _e.tooltipContent, tooltipProps: (_f = additionalActions[action]) === null || _f === void 0 ? void 0 : _f.tooltipProps, clickedTooltipContent: (_g = additionalActions[action]) === null || _g === void 0 ? void 0 : _g.clickedTooltipContent, icon: (_h = additionalActions[action]) === null || _h === void 0 ? void 0 : _h.icon, isClicked: activeButton === action, ref: (_j = additionalActions[action]) === null || _j === void 0 ? void 0 : _j.ref, "aria-expanded": (_k = additionalActions[action]) === null || _k === void 0 ? void 0 : _k['aria-expanded'], "aria-controls": (_l = additionalActions[action]) === null || _l === void 0 ? void 0 : _l['aria-controls'] })));
44
44
  })));
45
45
  };
46
46
  export default ResponseActions;
@@ -47,6 +47,13 @@ const CUSTOM_ACTIONS = [
47
47
  }
48
48
  }
49
49
  ];
50
+ const ALL_ACTIONS_DATA_TEST = [
51
+ { type: 'positive', label: 'Good response', dataTestId: 'positive' },
52
+ { type: 'negative', label: 'Bad response', dataTestId: 'negative' },
53
+ { type: 'copy', label: 'Copy', dataTestId: 'copy' },
54
+ { type: 'share', label: 'Share', dataTestId: 'share' },
55
+ { type: 'listen', label: 'Listen', dataTestId: 'listen' }
56
+ ];
50
57
  describe('ResponseActions', () => {
51
58
  afterEach(() => {
52
59
  jest.clearAllMocks();
@@ -156,6 +163,12 @@ describe('ResponseActions', () => {
156
163
  expect(screen.getByRole('button', { name: label })).toHaveClass('test');
157
164
  });
158
165
  });
166
+ it('should be able to add custom attributes to buttons', () => {
167
+ ALL_ACTIONS_DATA_TEST.forEach(({ type, dataTestId }) => {
168
+ render(React.createElement(ResponseActions, { actions: { [type]: { onClick: jest.fn(), 'data-testid': dataTestId } } }));
169
+ expect(screen.getByTestId(dataTestId)).toBeTruthy();
170
+ });
171
+ });
159
172
  it('should be able to add custom actions', () => {
160
173
  CUSTOM_ACTIONS.forEach((action) => {
161
174
  const key = Object.keys(action)[0];
@@ -165,10 +178,12 @@ describe('ResponseActions', () => {
165
178
  onClick: action[key].onClick,
166
179
  // doing this just because it's easier to test without a regex for the button name
167
180
  ariaLabel: action[key].ariaLabel.toLowerCase(),
168
- icon: action[key].icon
181
+ icon: action[key].icon,
182
+ 'data-testid': action[key]
169
183
  }
170
184
  } }));
171
185
  expect(screen.getByRole('button', { name: key })).toBeTruthy();
186
+ expect(screen.getByTestId(action[key])).toBeTruthy();
172
187
  });
173
188
  });
174
189
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patternfly/chatbot",
3
- "version": "6.3.0-prerelease.11",
3
+ "version": "6.3.0-prerelease.12",
4
4
  "description": "This library provides React components based on PatternFly 6 that can be used to build chatbots.",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
- import { Button, Icon, Tooltip, TooltipProps } from '@patternfly/react-core';
2
+ import { Button, ButtonProps, Icon, Tooltip, TooltipProps } from '@patternfly/react-core';
3
3
 
4
- export interface ResponseActionButtonProps {
4
+ export interface ResponseActionButtonProps extends ButtonProps {
5
5
  /** Aria-label for the button. Defaults to the value of the tooltipContent if none provided */
6
6
  ariaLabel?: string;
7
7
  /** Aria-label for the button, shown when the button is clicked. Defaults to the value of ariaLabel or tooltipContent if not provided. */
@@ -41,6 +41,14 @@ const CUSTOM_ACTIONS = [
41
41
  }
42
42
  ];
43
43
 
44
+ const ALL_ACTIONS_DATA_TEST = [
45
+ { type: 'positive', label: 'Good response', dataTestId: 'positive' },
46
+ { type: 'negative', label: 'Bad response', dataTestId: 'negative' },
47
+ { type: 'copy', label: 'Copy', dataTestId: 'copy' },
48
+ { type: 'share', label: 'Share', dataTestId: 'share' },
49
+ { type: 'listen', label: 'Listen', dataTestId: 'listen' }
50
+ ];
51
+
44
52
  describe('ResponseActions', () => {
45
53
  afterEach(() => {
46
54
  jest.clearAllMocks();
@@ -181,6 +189,13 @@ describe('ResponseActions', () => {
181
189
  });
182
190
  });
183
191
 
192
+ it('should be able to add custom attributes to buttons', () => {
193
+ ALL_ACTIONS_DATA_TEST.forEach(({ type, dataTestId }) => {
194
+ render(<ResponseActions actions={{ [type]: { onClick: jest.fn(), 'data-testid': dataTestId } }} />);
195
+ expect(screen.getByTestId(dataTestId)).toBeTruthy();
196
+ });
197
+ });
198
+
184
199
  it('should be able to add custom actions', () => {
185
200
  CUSTOM_ACTIONS.forEach((action) => {
186
201
  const key = Object.keys(action)[0];
@@ -192,12 +207,14 @@ describe('ResponseActions', () => {
192
207
  onClick: action[key].onClick,
193
208
  // doing this just because it's easier to test without a regex for the button name
194
209
  ariaLabel: action[key].ariaLabel.toLowerCase(),
195
- icon: action[key].icon
210
+ icon: action[key].icon,
211
+ 'data-testid': action[key]
196
212
  }
197
213
  }}
198
214
  />
199
215
  );
200
216
  expect(screen.getByRole('button', { name: key })).toBeTruthy();
217
+ expect(screen.getByTestId(action[key])).toBeTruthy();
201
218
  });
202
219
  });
203
220
  });
@@ -36,9 +36,12 @@ export interface ActionProps extends Omit<ButtonProps, 'ref'> {
36
36
  'aria-controls'?: string;
37
37
  }
38
38
 
39
+ type ExtendedActionProps = ActionProps & {
40
+ [key: string]: any;
41
+ };
39
42
  export interface ResponseActionProps {
40
43
  /** Props for message actions, such as feedback (positive or negative), copy button, share, and listen */
41
- actions: Record<string, ActionProps | undefined> & {
44
+ actions: Record<string, ExtendedActionProps | undefined> & {
42
45
  positive?: ActionProps;
43
46
  negative?: ActionProps;
44
47
  copy?: ActionProps;
@@ -78,6 +81,7 @@ export const ResponseActions: React.FunctionComponent<ResponseActionProps> = ({
78
81
  <div ref={responseActions} className="pf-chatbot__response-actions">
79
82
  {positive && (
80
83
  <ResponseActionButton
84
+ {...positive}
81
85
  ariaLabel={positive.ariaLabel ?? 'Good response'}
82
86
  clickedAriaLabel={positive.ariaLabel ?? 'Response recorded'}
83
87
  onClick={(e) => handleClick(e, 'positive', positive.onClick)}
@@ -95,6 +99,7 @@ export const ResponseActions: React.FunctionComponent<ResponseActionProps> = ({
95
99
  )}
96
100
  {negative && (
97
101
  <ResponseActionButton
102
+ {...negative}
98
103
  ariaLabel={negative.ariaLabel ?? 'Bad response'}
99
104
  clickedAriaLabel={negative.ariaLabel ?? 'Response recorded'}
100
105
  onClick={(e) => handleClick(e, 'negative', negative.onClick)}
@@ -112,6 +117,7 @@ export const ResponseActions: React.FunctionComponent<ResponseActionProps> = ({
112
117
  )}
113
118
  {copy && (
114
119
  <ResponseActionButton
120
+ {...copy}
115
121
  ariaLabel={copy.ariaLabel ?? 'Copy'}
116
122
  clickedAriaLabel={copy.ariaLabel ?? 'Copied'}
117
123
  onClick={(e) => handleClick(e, 'copy', copy.onClick)}
@@ -129,6 +135,7 @@ export const ResponseActions: React.FunctionComponent<ResponseActionProps> = ({
129
135
  )}
130
136
  {share && (
131
137
  <ResponseActionButton
138
+ {...share}
132
139
  ariaLabel={share.ariaLabel ?? 'Share'}
133
140
  clickedAriaLabel={share.ariaLabel ?? 'Shared'}
134
141
  onClick={(e) => handleClick(e, 'share', share.onClick)}
@@ -146,6 +153,7 @@ export const ResponseActions: React.FunctionComponent<ResponseActionProps> = ({
146
153
  )}
147
154
  {listen && (
148
155
  <ResponseActionButton
156
+ {...listen}
149
157
  ariaLabel={listen.ariaLabel ?? 'Listen'}
150
158
  clickedAriaLabel={listen.ariaLabel ?? 'Listening'}
151
159
  onClick={(e) => handleClick(e, 'listen', listen.onClick)}
@@ -163,6 +171,7 @@ export const ResponseActions: React.FunctionComponent<ResponseActionProps> = ({
163
171
  )}
164
172
  {Object.keys(additionalActions).map((action) => (
165
173
  <ResponseActionButton
174
+ {...additionalActions[action]}
166
175
  key={action}
167
176
  ariaLabel={additionalActions[action]?.ariaLabel}
168
177
  clickedAriaLabel={additionalActions[action]?.clickedAriaLabel}