@availity/feedback 9.1.14 → 10.0.1

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/index.js CHANGED
@@ -1,3 +1,3 @@
1
- export { default } from './src/Feedback';
2
- export { default as FeedbackForm } from './src/FeedbackForm';
3
- export { default as FeedbackModal } from './src/FeedbackModal';
1
+ export { default } from './src/Feedback.jsx';
2
+ export { default as FeedbackForm } from './src/FeedbackForm.jsx';
3
+ export { default as FeedbackModal } from './src/FeedbackModal.jsx';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@availity/feedback",
3
- "version": "9.1.14",
3
+ "version": "10.0.1",
4
4
  "description": "Availity feedback with smiley faces react component.",
5
5
  "keywords": [
6
6
  "react",
@@ -17,33 +17,36 @@
17
17
  "directory": "packages/feedback"
18
18
  },
19
19
  "license": "MIT",
20
+ "type": "module",
20
21
  "author": "Evan Sharp <evan.sharp@availity.com>",
21
- "main": "index.js",
22
- "types": "index.d.ts",
23
22
  "scripts": {
23
+ "build": "tsup index.js --format esm --clean --dts",
24
+ "dev": "tsup index.js --format esm --watch --dts",
25
+ "clean": "rm -rf dist",
24
26
  "publish": "yarn npm publish --tolerate-republish --access public",
25
27
  "publish:canary": "yarn npm publish --access public --tag canary"
26
28
  },
27
29
  "dependencies": {
28
- "@availity/block-ui": "^1.1.7",
29
- "@availity/form": "1.10.7",
30
- "@availity/hooks": "5.2.0",
31
- "@availity/icon": "0.11.11",
32
- "@availity/native-form": "^7.0.12",
33
- "@availity/select": "4.2.13",
30
+ "@availity/block-ui": "^2.0.1",
31
+ "@availity/form": "2.0.1",
32
+ "@availity/hooks": "6.0.1",
33
+ "@availity/icon": "1.0.1",
34
+ "@availity/native-form": "^8.2.0",
35
+ "@availity/select": "5.0.1",
34
36
  "prop-types": "^15.8.1"
35
37
  },
36
38
  "devDependencies": {
37
- "@availity/api-axios": "^12.1.0",
38
- "@availity/yup": "^7.0.1",
39
- "axios": "^1.13.2",
40
- "formik": "^2.4.6",
39
+ "@availity/api-axios": "^13.2.0",
40
+ "@availity/yup": "^7.1.0",
41
+ "axios": "^1.17.0",
42
+ "formik": "^2.4.9",
41
43
  "react": "^18.3.1",
42
44
  "react-dom": "^18.3.1",
43
- "reactstrap": "^8.10.1"
45
+ "reactstrap": "^8.10.1",
46
+ "tsup": "^8.5.1"
44
47
  },
45
48
  "peerDependencies": {
46
- "@availity/api-axios": "^12.0.0",
49
+ "@availity/api-axios": "^12.0.0 || ^13.0.0",
47
50
  "@availity/yup": "^7.0.0",
48
51
  "axios": "^1.13.2",
49
52
  "formik": "^2.4.6",
@@ -52,5 +55,14 @@
52
55
  },
53
56
  "publishConfig": {
54
57
  "access": "public"
58
+ },
59
+ "main": "./dist/index.js",
60
+ "exports": {
61
+ ".": {
62
+ "source": "./index.js",
63
+ "types": "./index.d.ts",
64
+ "import": "./dist/index.js"
65
+ },
66
+ "./package.json": "./package.json"
55
67
  }
56
68
  }
package/project.json CHANGED
@@ -4,10 +4,15 @@
4
4
  "projectType": "library",
5
5
  "targets": {
6
6
  "test": {
7
- "executor": "@nx/jest:jest",
8
- "outputs": ["{workspaceRoot}/coverage/feedback"],
7
+ "executor": "nx:run-commands",
9
8
  "options": {
10
- "jestConfig": "packages/feedback/jest.config.js"
9
+ "command": "vitest run --project=feedback",
10
+ "cwd": "."
11
+ },
12
+ "configurations": {
13
+ "ci": {
14
+ "command": "vitest run --project=feedback --coverage"
15
+ }
11
16
  }
12
17
  },
13
18
  "version": {
@@ -23,17 +28,20 @@
23
28
  "lint": {
24
29
  "executor": "@nx/eslint:lint",
25
30
  "options": {
26
- "eslintConfig": ".eslintrc.yaml",
27
31
  "silent": false,
28
32
  "fix": false,
29
33
  "cache": true,
30
34
  "cacheLocation": "./node_modules/.cache/feedback/.eslintcache",
31
35
  "maxWarnings": -1,
32
36
  "quiet": false,
33
- "noEslintrc": false,
34
- "hasTypeAwareRules": true,
35
37
  "cacheStrategy": "metadata"
36
38
  }
39
+ },
40
+ "build": {
41
+ "command": "tsup index.js --format esm",
42
+ "options": {
43
+ "cwd": "packages/feedback"
44
+ }
37
45
  }
38
46
  }
39
47
  }
@@ -4,8 +4,8 @@ import { Dropdown, DropdownToggle } from 'reactstrap';
4
4
  import { avLogMessagesApiV2 } from '@availity/api-axios';
5
5
  import { useToggle } from '@availity/hooks';
6
6
 
7
- import FeedbackDropdown from './FeedbackDropdown';
8
- import FeedbackModal from './FeedbackModal';
7
+ import FeedbackDropdown from './FeedbackDropdown.jsx';
8
+ import FeedbackModal from './FeedbackModal.jsx';
9
9
 
10
10
  const Feedback = ({
11
11
  appName,
@@ -2,9 +2,9 @@ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { DropdownMenu } from 'reactstrap';
4
4
 
5
- import FeedbackForm from './FeedbackForm';
6
- import SupportModal from './SupportModal';
7
- import SupportDropdown from './SupportDropdown';
5
+ import FeedbackForm from './FeedbackForm.jsx';
6
+ import SupportModal from './SupportModal.jsx';
7
+ import SupportDropdown from './SupportDropdown.jsx';
8
8
 
9
9
  const dropdownStyles = { width: '550px', maxWidth: '90vw', padding: 0 };
10
10
 
@@ -6,7 +6,7 @@ import { Form, Field } from '@availity/form';
6
6
  import { SelectField } from '@availity/select';
7
7
  import * as yup from 'yup';
8
8
 
9
- import SmileField from './SmileField';
9
+ import SmileField from './SmileField.jsx';
10
10
 
11
11
  yup.addMethod(yup.string, 'isRequired', function format(isRequired, msg) {
12
12
  return this.test({
@@ -2,8 +2,8 @@ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { Modal } from 'reactstrap';
4
4
 
5
- import FeedbackForm from './FeedbackForm';
6
- import SupportModal from './SupportModal';
5
+ import FeedbackForm from './FeedbackForm.jsx';
6
+ import SupportModal from './SupportModal.jsx';
7
7
 
8
8
  const FeedbackModal = ({ isOpen, toggle, zIndex, showSupport, supportZIndex, feedbackToggle, ...formOptions }) => {
9
9
  const [supportIsActive, setSupportIsActive] = React.useState(false);
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { useField, useFormikContext } from 'formik';
4
4
 
5
- import FeedbackButton from './FeedbackButton';
5
+ import FeedbackButton from './FeedbackButton.jsx';
6
6
 
7
7
  const btnStyles = { flex: 1, margin: '0 2% 0 2%' };
8
8
  const defaultOptions = [
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
3
3
  import { DropdownMenu } from 'reactstrap';
4
4
  import BlockUi from '@availity/block-ui';
5
5
 
6
- import SupportForm from './SupportForm';
6
+ import SupportForm from './SupportForm.jsx';
7
7
 
8
8
  const dropdownStyles = { width: '550px', maxWidth: '90vw', padding: 0 };
9
9
 
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
3
3
  import { Modal } from 'reactstrap';
4
4
  import BlockUi from '@availity/block-ui';
5
5
 
6
- import SupportForm from './SupportForm';
6
+ import SupportForm from './SupportForm.jsx';
7
7
 
8
8
  const SupportModal = ({ supportIsActive, toggle, supportZIndex, setSupportIsActive, feedbackToggle }) => {
9
9
  const [blocking, setBlocking] = useState(false);
@@ -0,0 +1,228 @@
1
+ import React from 'react';
2
+ import { render, fireEvent, cleanup, waitFor } from '@testing-library/react';
3
+ import Feedback from '../index.js';
4
+
5
+ global.document.createRange = () => ({
6
+ setStart: () => {},
7
+ setEnd: () => {},
8
+ commonAncestorContainer: {
9
+ nodeName: 'BODY',
10
+ ownerDocument: document,
11
+ },
12
+ });
13
+
14
+ afterEach(cleanup);
15
+
16
+ describe('Feedback', () => {
17
+ test('should show form on click', () => {
18
+ const { getByTestId, getByText } = render(<Feedback appName="Test Space" />);
19
+
20
+ fireEvent.click(getByText('Give Feedback'));
21
+
22
+
23
+ expect(getByTestId('feedback-form')).toBeDefined();
24
+ });
25
+
26
+ test('should show modal form on click', () => {
27
+ const { getByTestId, getByText } = render(<Feedback appName="Test Space" modal />);
28
+
29
+ fireEvent.click(getByText('Give Feedback'));
30
+
31
+
32
+ expect(getByTestId('feedbackModal')).toBeDefined();
33
+ });
34
+
35
+ test('should call onClose in form', async () => {
36
+ const onClose = vi.fn();
37
+
38
+ const { getByTestId, getByText } = render(<Feedback appName="Test Space" formProps={{ onClose }} />);
39
+
40
+ fireEvent.click(getByText('Give Feedback'));
41
+
42
+
43
+ expect(getByTestId('feedback-form')).toBeDefined();
44
+
45
+ fireEvent.keyDown(getByText('Close'), {
46
+ key: 'Enter',
47
+ keyCode: 13,
48
+ });
49
+
50
+ await waitFor(() => {
51
+ expect(onClose).toHaveBeenCalledTimes(1);
52
+ });
53
+
54
+ fireEvent.click(getByText('Give Feedback'));
55
+
56
+ fireEvent.click(getByText('Close'));
57
+
58
+ await waitFor(() => {
59
+ expect(onClose).toHaveBeenCalledTimes(2);
60
+ });
61
+ });
62
+
63
+ test('should call onClose in modal', async () => {
64
+ const onClose = vi.fn();
65
+
66
+ const { getByTestId, getByText } = render(<Feedback appName="Test Space" formProps={{ onClose }} modal />);
67
+
68
+ fireEvent.click(getByText('Give Feedback'));
69
+
70
+
71
+ expect(getByTestId('feedbackModal')).toBeDefined();
72
+
73
+ fireEvent.click(getByText('Close'));
74
+
75
+ await waitFor(() => {
76
+ expect(onClose).toHaveBeenCalledTimes(1);
77
+ });
78
+ });
79
+
80
+ test('should have proper ARIA attributes on Give Feedback button', () => {
81
+ const { getByTestId, getByText } = render(<Feedback appName="Test Space" />);
82
+
83
+ const giveFeedbackButton = getByText('Give Feedback');
84
+
85
+ expect(giveFeedbackButton).toHaveAttribute('aria-expanded', 'false');
86
+
87
+ fireEvent.click(giveFeedbackButton);
88
+
89
+
90
+ expect(getByTestId('feedback-form')).toBeDefined();
91
+ expect(giveFeedbackButton).toHaveAttribute('aria-expanded', 'true');
92
+
93
+ fireEvent.click(getByText('Close'));
94
+
95
+ expect(giveFeedbackButton).toHaveAttribute('aria-expanded', 'false');
96
+ });
97
+
98
+ test('should focus FeedbackButton when enter is clicked', async () => {
99
+ const onChange = vi.fn();
100
+
101
+ const { getByTestId, getByText } = render(<Feedback appName="Test Space" formProps={{ onChange }} />);
102
+
103
+ fireEvent.click(getByText('Give Feedback'));
104
+
105
+
106
+ expect(getByTestId('feedback-form')).toBeDefined();
107
+
108
+ fireEvent.keyDown(getByText('Smiley face'), {
109
+ key: 'Enter',
110
+ keyCode: 13,
111
+ });
112
+
113
+ const submitButton = getByText('Send Feedback');
114
+
115
+ expect(submitButton.getAttribute('disabled')).toBe(null);
116
+ });
117
+
118
+ test('should close when first feedbackButton is shift+tabbed', async () => {
119
+ const onClose = vi.fn();
120
+
121
+ const { getByTestId, getByText } = render(<Feedback appName="Test Space" formProps={{ onClose }} />);
122
+
123
+ fireEvent.click(getByText('Give Feedback'));
124
+
125
+
126
+ expect(getByTestId('feedback-form')).toBeDefined();
127
+
128
+ fireEvent.keyDown(getByText('Smiley face'), {
129
+ key: 'Tab',
130
+ keyCode: 9,
131
+ shiftKey: true,
132
+ });
133
+
134
+ await waitFor(() => {
135
+ expect(onClose).toHaveBeenCalledTimes(1);
136
+ });
137
+ });
138
+
139
+ test('should close when the close button is tabbed and give feedback is disabled', async () => {
140
+ const onClose = vi.fn();
141
+
142
+ const { getByTestId, getByText } = render(<Feedback appName="Test Space" formProps={{ onClose }} />);
143
+
144
+ fireEvent.click(getByText('Give Feedback'));
145
+
146
+
147
+ expect(getByTestId('feedback-form')).toBeDefined();
148
+
149
+ fireEvent.keyDown(getByText('Close'), {
150
+ key: 'Tab',
151
+ keyCode: 9,
152
+ });
153
+
154
+ await waitFor(() => {
155
+ expect(onClose).toHaveBeenCalledTimes(1);
156
+ });
157
+ });
158
+
159
+ test('should not close when the close button is tabbed and give feedback is not disabled', async () => {
160
+ const onClose = vi.fn();
161
+
162
+ const { getByTestId, getByText } = render(<Feedback appName="Test Space" formProps={{ onClose }} />);
163
+
164
+ fireEvent.click(getByText('Give Feedback'));
165
+
166
+
167
+ expect(getByTestId('feedback-form')).toBeDefined();
168
+
169
+ fireEvent.click(getByText('Smiley face'));
170
+
171
+ fireEvent.keyDown(getByText('Close'), {
172
+ key: 'Tab',
173
+ keyCode: 9,
174
+ });
175
+
176
+ await waitFor(() => {
177
+ expect(onClose).toHaveBeenCalledTimes(0);
178
+ });
179
+ });
180
+
181
+ test('should close when the send feedback button is tabbed', async () => {
182
+ const onClose = vi.fn();
183
+
184
+ const { getByTestId, getByText } = render(<Feedback appName="Test Space" formProps={{ onClose }} />);
185
+
186
+ fireEvent.click(getByText('Give Feedback'));
187
+
188
+
189
+ expect(getByTestId('feedback-form')).toBeDefined();
190
+
191
+ fireEvent.click(getByText('Smiley face'));
192
+
193
+ fireEvent.keyDown(getByText('Send Feedback'), {
194
+ key: 'Tab',
195
+ keyCode: 9,
196
+ });
197
+
198
+ await waitFor(() => {
199
+ expect(onClose).toHaveBeenCalledTimes(1);
200
+ });
201
+ });
202
+
203
+ test('should render passed text on the button', async () => {
204
+ const displayText = 'This is my Content.';
205
+ const { getByText } = render(<Feedback>{displayText}</Feedback>);
206
+
207
+ const btn = getByText(displayText);
208
+
209
+ expect(btn).toBeDefined();
210
+ });
211
+
212
+ test('should render passed children and text', async () => {
213
+ const displayText = ' User Feedback';
214
+ const { getByRole } = render(
215
+ <Feedback>
216
+ <span className="icon icon-user-plus" />
217
+ {displayText}
218
+ </Feedback>
219
+ );
220
+
221
+ const btn = getByRole('button');
222
+ const span = btn.firstChild;
223
+
224
+ expect(span).toBeDefined();
225
+ expect(span.className).toBe('icon icon-user-plus');
226
+ expect(btn.textContent).toBe(displayText);
227
+ });
228
+ });
@@ -0,0 +1,38 @@
1
+ import React from 'react';
2
+ import { render, cleanup } from '@testing-library/react';
3
+ import FeedbackButton from '../src/FeedbackButton';
4
+
5
+ afterEach(cleanup);
6
+
7
+ describe('Feedback', () => {
8
+ test('should render an icon', () => {
9
+ const { getByTestId } = render(<FeedbackButton icon="home" />);
10
+
11
+
12
+ expect(getByTestId('feedback-icon').className).toContain('icon-home');
13
+ });
14
+
15
+ test('should highlight when active', () => {
16
+ const { container } = render(<FeedbackButton icon="home" active="home" />);
17
+
18
+ expect(container.firstChild.className).toContain('btn-primary');
19
+ });
20
+
21
+ test('should have proper ARIA attributes when active', () => {
22
+ const { container, getByText } = render(
23
+ <FeedbackButton icon="home" active="home">
24
+ Home
25
+ </FeedbackButton>
26
+ );
27
+
28
+ expect(container.firstChild).toHaveAttribute('aria-pressed', 'true');
29
+ expect(getByText('Home')).toHaveClass('sr-only');
30
+ });
31
+
32
+ test('should have proper ARIA attributes', () => {
33
+ const { container, getByText } = render(<FeedbackButton icon="home">Home</FeedbackButton>);
34
+
35
+ expect(container.firstChild).toHaveAttribute('aria-pressed', 'false');
36
+ expect(getByText('Home')).toHaveClass('sr-only');
37
+ });
38
+ });