@availity/mui-controlled-form 0.1.0

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 (50) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +65 -0
  3. package/dist/index.d.mts +20 -0
  4. package/dist/index.d.ts +20 -0
  5. package/dist/index.js +71 -0
  6. package/dist/index.mjs +47 -0
  7. package/docs/propDefinitions.tsx +31 -0
  8. package/introduction.stories.mdx +7 -0
  9. package/jest.config.js +7 -0
  10. package/package.json +66 -0
  11. package/project.json +41 -0
  12. package/src/index.ts +1 -0
  13. package/src/lib/AsyncAutocomplete.stories.tsx +113 -0
  14. package/src/lib/AsyncAutocomplete.test.tsx +162 -0
  15. package/src/lib/AsyncAutocomplete.tsx +92 -0
  16. package/src/lib/Autocomplete.stories.tsx +60 -0
  17. package/src/lib/Autocomplete.test.tsx +70 -0
  18. package/src/lib/Autocomplete.tsx +96 -0
  19. package/src/lib/Checkbox.stories.tsx +67 -0
  20. package/src/lib/Checkbox.test.tsx +73 -0
  21. package/src/lib/Checkbox.tsx +37 -0
  22. package/src/lib/CodesAutocomplete.stories.tsx +79 -0
  23. package/src/lib/CodesAutocomplete.test.tsx +128 -0
  24. package/src/lib/CodesAutocomplete.tsx +76 -0
  25. package/src/lib/ControlledForm.stories.tsx +74 -0
  26. package/src/lib/ControlledForm.test.tsx +77 -0
  27. package/src/lib/ControlledForm.tsx +35 -0
  28. package/src/lib/Datepicker.stories.tsx +63 -0
  29. package/src/lib/Datepicker.test.tsx +73 -0
  30. package/src/lib/Datepicker.tsx +49 -0
  31. package/src/lib/Input.stories.tsx +60 -0
  32. package/src/lib/Input.test.tsx +98 -0
  33. package/src/lib/Input.tsx +54 -0
  34. package/src/lib/OrganizationAutocomplete.stories.tsx +77 -0
  35. package/src/lib/OrganizationAutocomplete.test.tsx +125 -0
  36. package/src/lib/OrganizationAutocomplete.tsx +75 -0
  37. package/src/lib/ProviderAutocomplete.stories.tsx +79 -0
  38. package/src/lib/ProviderAutocomplete.test.tsx +128 -0
  39. package/src/lib/ProviderAutocomplete.tsx +80 -0
  40. package/src/lib/RadioGroup.stories.tsx +63 -0
  41. package/src/lib/RadioGroup.test.tsx +66 -0
  42. package/src/lib/RadioGroup.tsx +68 -0
  43. package/src/lib/Select.stories.tsx +74 -0
  44. package/src/lib/Select.test.tsx +68 -0
  45. package/src/lib/Select.tsx +55 -0
  46. package/src/lib/TextField.stories.tsx +67 -0
  47. package/src/lib/TextField.test.tsx +99 -0
  48. package/src/lib/TextField.tsx +67 -0
  49. package/tsconfig.json +5 -0
  50. package/tsconfig.spec.json +10 -0
@@ -0,0 +1,60 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { ControlledInput, ControlledInputProps } from './Input';
3
+ import { ControlledForm } from './ControlledForm';
4
+ import { Button } from '@availity/mui-button';
5
+ import { useFormContext } from 'react-hook-form';
6
+ import { Paper } from '@availity/mui-paper';
7
+ import { Typography } from '@availity/mui-typography';
8
+ import { Grid } from '@availity/mui-layout';
9
+
10
+ const meta: Meta<typeof ControlledInput> = {
11
+ title: 'Form Components/Controlled Form/ControlledInput',
12
+ component: ControlledInput,
13
+ tags: ['autodocs'],
14
+ };
15
+
16
+ export default meta;
17
+
18
+ export const _ControlledInput: StoryObj<typeof ControlledInput> = {
19
+ render: (args: ControlledInputProps) => {
20
+ const SubmittedValues = () => {
21
+ const {
22
+ getValues,
23
+ formState: { isSubmitSuccessful },
24
+ } = useFormContext();
25
+
26
+ return isSubmitSuccessful ? (
27
+ <Paper sx={{ padding: '1.5rem', marginTop: '1.5rem' }}>
28
+ <Typography variant="h2">Submitted Values</Typography>
29
+ <pre>{JSON.stringify(getValues(), null, 2)}</pre>
30
+ </Paper>
31
+ ) : null;
32
+ };
33
+
34
+ const Actions = () => {
35
+ const {
36
+ reset,
37
+ formState: { isSubmitSuccessful },
38
+ } = useFormContext();
39
+ return (
40
+ <Grid container direction="row" justifyContent="space-between" marginTop={1}>
41
+ <Button disabled={!isSubmitSuccessful} children="Reset" color="secondary" onClick={() => reset()} />
42
+ <Button type="submit" disabled={isSubmitSuccessful} children="Submit" />
43
+ </Grid>
44
+ );
45
+ };
46
+ return (
47
+ <ControlledForm values={{ controlledInput: undefined }} onSubmit={(data) => data}>
48
+ <ControlledInput {...args} />
49
+ <Actions />
50
+ <SubmittedValues />
51
+ </ControlledForm>
52
+ );
53
+ },
54
+ args: {
55
+ name: 'controlledInput',
56
+ required: true,
57
+ maxLength: { value: 10, message: 'Too long' },
58
+ inputProps: { 'aria-label': 'Input Label' },
59
+ },
60
+ };
@@ -0,0 +1,98 @@
1
+ import { render, fireEvent, waitFor } from '@testing-library/react';
2
+ import { useFormContext } from 'react-hook-form';
3
+ import { Paper } from '@availity/mui-paper';
4
+ import { Typography } from '@availity/mui-typography';
5
+ import { Grid } from '@availity/mui-layout';
6
+ import { Button } from '@availity/mui-button';
7
+ import { ControlledForm } from './ControlledForm';
8
+ import { ControlledInput } from './Input';
9
+
10
+ const SubmittedValues = () => {
11
+ const {
12
+ getValues,
13
+ formState: { isSubmitSuccessful },
14
+ } = useFormContext();
15
+
16
+ return isSubmitSuccessful ? (
17
+ <Paper sx={{ padding: '1.5rem', marginTop: '1.5rem' }}>
18
+ <Typography variant="h2">Submitted Values</Typography>
19
+ <pre data-testid="result">{JSON.stringify(getValues(), null, 2)}</pre>
20
+ </Paper>
21
+ ) : null;
22
+ };
23
+
24
+ const Actions = () => {
25
+ const {
26
+ formState: { isSubmitSuccessful },
27
+ } = useFormContext();
28
+ return (
29
+ <Grid container direction="row" justifyContent="space-between">
30
+ <Button type="submit" disabled={isSubmitSuccessful} children="Submit" />
31
+ </Grid>
32
+ );
33
+ };
34
+
35
+ const onSubmit = jest.fn();
36
+
37
+ describe('ControlledInput', () => {
38
+ test('should render the error styling if an error is returned', async () => {
39
+ const screen = render(
40
+ <ControlledForm values={{ controlledInput: undefined }} onSubmit={(data) => data}>
41
+ <ControlledInput
42
+ data-testid="controlledInputWrapper"
43
+ name="controlledInput"
44
+ required="This field is required."
45
+ maxLength={{ value: 10, message: 'Too long' }}
46
+ inputProps={{
47
+ 'data-testid': 'testInput',
48
+ }}
49
+ />
50
+ <Actions />
51
+ <SubmittedValues />
52
+ </ControlledForm>
53
+ );
54
+
55
+ const input = screen.getByTestId('testInput');
56
+
57
+ fireEvent.change(input, { target: { value: 'This is way too much text' } });
58
+
59
+ fireEvent.click(screen.getByText('Submit'));
60
+
61
+ await waitFor(() => expect(onSubmit).toHaveBeenCalledTimes(0));
62
+
63
+ const muiInputBase = screen.getByTestId('controlledInputWrapper');
64
+
65
+ await waitFor(() => expect(muiInputBase.classList).toContain('Mui-error'));
66
+ });
67
+
68
+ test('should render the error styling if an error is returned', async () => {
69
+ const screen = render(
70
+ <ControlledForm values={{ controlledInput: undefined }} onSubmit={onSubmit}>
71
+ <ControlledInput
72
+ name="controlledInput"
73
+ required="This field is required."
74
+ maxLength={{ value: 10, message: 'Too long' }}
75
+ inputProps={{
76
+ 'data-testid': 'testInput',
77
+ }}
78
+ />
79
+ <Actions />
80
+ <SubmittedValues />
81
+ </ControlledForm>
82
+ );
83
+
84
+ const input = screen.getByTestId('testInput');
85
+
86
+ fireEvent.change(input, { target: { value: 'Input Text' } });
87
+
88
+ fireEvent.click(screen.getByText('Submit'));
89
+
90
+ await waitFor(() => expect(onSubmit).toHaveBeenCalledTimes(1));
91
+
92
+ const result = screen.getByTestId('result');
93
+ await waitFor(() => {
94
+ const formValues = JSON.parse(result.innerHTML).controlledInput;
95
+ expect(formValues).toBe('Input Text');
96
+ });
97
+ });
98
+ });
@@ -0,0 +1,54 @@
1
+ import { Input, InputProps } from '@availity/mui-form-utils';
2
+ import { useFormContext, RegisterOptions, FieldValues } from 'react-hook-form';
3
+
4
+ export type ControlledInputProps = Omit<InputProps, 'error' | 'name' | 'required'> & { name: string } & RegisterOptions<
5
+ FieldValues,
6
+ string
7
+ >;
8
+
9
+ export const ControlledInput = ({
10
+ name,
11
+ required,
12
+ maxLength,
13
+ minLength,
14
+ max,
15
+ min,
16
+ pattern,
17
+ validate,
18
+ setValueAs,
19
+ disabled,
20
+ onChange,
21
+ onBlur,
22
+ value,
23
+ shouldUnregister,
24
+ deps,
25
+ ...rest
26
+ }: ControlledInputProps) => {
27
+ const {
28
+ register,
29
+ formState: { errors },
30
+ } = useFormContext();
31
+ return (
32
+ <Input
33
+ {...rest}
34
+ error={!!errors[name]}
35
+ required={!!required}
36
+ {...register(name, {
37
+ required,
38
+ maxLength,
39
+ minLength,
40
+ max,
41
+ min,
42
+ pattern,
43
+ validate,
44
+ setValueAs,
45
+ disabled,
46
+ onChange,
47
+ onBlur,
48
+ value,
49
+ shouldUnregister,
50
+ deps,
51
+ })}
52
+ />
53
+ );
54
+ };
@@ -0,0 +1,77 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { ControlledOrganizationAutocomplete } from './OrganizationAutocomplete';
3
+ import { ControlledForm } from './ControlledForm';
4
+ import { Button } from '@availity/mui-button';
5
+ import { useFormContext } from 'react-hook-form';
6
+ import { Paper } from '@availity/mui-paper';
7
+ import { Typography } from '@availity/mui-typography';
8
+ import { Grid } from '@availity/mui-layout';
9
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
10
+ import { missingRHFprops } from '../../docs/propDefinitions';
11
+
12
+ const meta: Meta<typeof ControlledOrganizationAutocomplete> = {
13
+ title: 'Form Components/Controlled Form/Autocomplete/ControlledOrganizationAutocomplete',
14
+ component: ControlledOrganizationAutocomplete,
15
+ tags: ['autodocs'],
16
+ argTypes: missingRHFprops,
17
+ };
18
+
19
+ export default meta;
20
+
21
+ const client = new QueryClient({
22
+ defaultOptions: {
23
+ queries: {
24
+ refetchOnWindowFocus: false,
25
+ },
26
+ },
27
+ });
28
+
29
+ export const _ControlledOrganizationAutoComplete: StoryObj<typeof ControlledOrganizationAutocomplete> = {
30
+ render: (args) => {
31
+ const SubmittedValues = () => {
32
+ const {
33
+ getValues,
34
+ formState: { isSubmitSuccessful },
35
+ } = useFormContext();
36
+
37
+ return isSubmitSuccessful ? (
38
+ <Paper sx={{ padding: '1.5rem', marginTop: '1.5rem' }}>
39
+ <Typography variant="h2">Submitted Values</Typography>
40
+ <pre>{JSON.stringify(getValues(), null, 2)}</pre>
41
+ </Paper>
42
+ ) : null;
43
+ };
44
+
45
+ const Actions = () => {
46
+ const {
47
+ reset,
48
+ formState: { isSubmitSuccessful },
49
+ } = useFormContext();
50
+ return (
51
+ <Grid container direction="row" justifyContent="space-between" marginTop={1}>
52
+ <Button disabled={!isSubmitSuccessful} children="Reset" color="secondary" onClick={() => reset()} />
53
+ <Button type="submit" disabled={isSubmitSuccessful} children="Submit" />
54
+ </Grid>
55
+ );
56
+ };
57
+ return (
58
+ <QueryClientProvider client={client}>
59
+ <ControlledForm values={{}} onSubmit={(data) => data}>
60
+ <ControlledOrganizationAutocomplete {...args} />
61
+ <Actions />
62
+ <SubmittedValues />
63
+ </ControlledForm>
64
+ </QueryClientProvider>
65
+ );
66
+ },
67
+ args: {
68
+ name: 'controlledOrganizationAutocomplete',
69
+ required: 'This is required.',
70
+ FieldProps: {
71
+ label: 'Organization Select',
72
+ helperText: 'Select an Organization from the list',
73
+ placeholder: 'Select...',
74
+ fullWidth: false,
75
+ },
76
+ },
77
+ };
@@ -0,0 +1,125 @@
1
+ import { fireEvent, render, waitFor } from '@testing-library/react';
2
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
3
+ import { Paper } from '@availity/mui-paper';
4
+ import { Typography } from '@availity/mui-typography';
5
+ import { useFormContext } from 'react-hook-form';
6
+ import { Grid } from '@availity/mui-layout';
7
+ import { Button } from '@availity/mui-button';
8
+ // eslint-disable-next-line @nx/enforce-module-boundaries
9
+ import { server } from '@availity/mock/src/lib/server';
10
+ import { ControlledForm } from './ControlledForm';
11
+ import { ControlledOrganizationAutocomplete } from './OrganizationAutocomplete';
12
+
13
+ const SubmittedValues = () => {
14
+ const {
15
+ getValues,
16
+ formState: { isSubmitSuccessful },
17
+ } = useFormContext();
18
+
19
+ return isSubmitSuccessful ? (
20
+ <Paper sx={{ padding: '1.5rem', marginTop: '1.5rem' }}>
21
+ <Typography variant="h2">Submitted Values</Typography>
22
+ <pre data-testid="result">{JSON.stringify(getValues(), null, 2)}</pre>
23
+ </Paper>
24
+ ) : null;
25
+ };
26
+
27
+ const Actions = () => {
28
+ const {
29
+ formState: { isSubmitSuccessful },
30
+ } = useFormContext();
31
+ return (
32
+ <Grid container direction="row" justifyContent="space-between">
33
+ <Button type="submit" disabled={isSubmitSuccessful} children="Submit" />
34
+ </Grid>
35
+ );
36
+ };
37
+
38
+ const onSubmit = jest.fn();
39
+
40
+ describe('ControlledOrganizationAutocomplete', () => {
41
+ beforeAll(() => {
42
+ // Start the interception.
43
+ server.listen();
44
+ });
45
+
46
+ afterEach(() => {
47
+ // Remove any handlers you may have added
48
+ // in individual tests (runtime handlers).
49
+ server.resetHandlers();
50
+ jest.restoreAllMocks();
51
+ });
52
+
53
+ const client = new QueryClient({
54
+ defaultOptions: {
55
+ queries: {
56
+ refetchOnWindowFocus: false,
57
+ },
58
+ },
59
+ });
60
+
61
+ test('should loadOptions successfully', async () => {
62
+ const screen = render(
63
+ <QueryClientProvider client={client}>
64
+ <ControlledForm values={{}} onSubmit={onSubmit}>
65
+ <ControlledOrganizationAutocomplete
66
+ name="controlledOrganizationAutocomplete"
67
+ FieldProps={{
68
+ label: 'Organization Select',
69
+ helperText: 'Select an Organization from the list',
70
+ placeholder: 'Select...',
71
+ fullWidth: false,
72
+ }}
73
+ />
74
+ <Actions />
75
+ <SubmittedValues />
76
+ </ControlledForm>
77
+ </QueryClientProvider>
78
+ );
79
+
80
+ const dropdown = screen.getByRole('combobox');
81
+ fireEvent.click(dropdown);
82
+ fireEvent.keyDown(dropdown, { key: 'ArrowDown' });
83
+
84
+ await waitFor(() => expect(screen.getByText('Organization 1')).toBeDefined());
85
+ });
86
+
87
+ test('should set the value and submit the form data', async () => {
88
+ const screen = render(
89
+ <QueryClientProvider client={client}>
90
+ <ControlledForm values={{}} onSubmit={onSubmit}>
91
+ <ControlledOrganizationAutocomplete
92
+ name="controlledOrganizationAutocomplete"
93
+ FieldProps={{
94
+ label: 'Organization Select',
95
+ helperText: 'Select an Organization from the list',
96
+ placeholder: 'Select...',
97
+ fullWidth: false,
98
+ }}
99
+ />
100
+ <Actions />
101
+ <SubmittedValues />
102
+ </ControlledForm>
103
+ </QueryClientProvider>
104
+ );
105
+
106
+ const dropdown = screen.getByRole('combobox');
107
+ fireEvent.click(dropdown);
108
+ fireEvent.keyDown(dropdown, { key: 'ArrowDown' });
109
+
110
+ await waitFor(() => screen.getByText('Organization 1'));
111
+
112
+ fireEvent.click(screen.getByText('Organization 1'));
113
+
114
+ fireEvent.click(screen.getByText('Submit'));
115
+
116
+ await waitFor(() => expect(onSubmit).toHaveBeenCalledTimes(1));
117
+ const result = screen.getByTestId('result');
118
+ await waitFor(() => {
119
+ const controlledCodesAutocompleteValue = JSON.parse(result.innerHTML).controlledOrganizationAutocomplete;
120
+ expect(controlledCodesAutocompleteValue.customerId).toBe('1');
121
+ expect(controlledCodesAutocompleteValue.name).toBe('Organization 1');
122
+ expect(controlledCodesAutocompleteValue.id).toBeDefined();
123
+ });
124
+ });
125
+ });
@@ -0,0 +1,75 @@
1
+ import { OrganizationAutocomplete, OrgAutocompleteProps } from '@availity/mui-autocomplete';
2
+ import { useFormContext, Controller, RegisterOptions, FieldValues, ControllerProps } from 'react-hook-form';
3
+
4
+ type ControlledOrgAutocompleteProps = Omit<OrgAutocompleteProps, 'name'> &
5
+ Omit<
6
+ RegisterOptions<FieldValues, string>,
7
+ 'disabled' | 'valueAsNumber' | 'valueAsDate' | 'setValueAs' | 'max' | 'maxLength' | 'min' | 'minLength'
8
+ > &
9
+ Pick<ControllerProps, 'defaultValue' | 'shouldUnregister' | 'name'>;
10
+
11
+ export const ControlledOrganizationAutocomplete = ({
12
+ name,
13
+ defaultValue,
14
+ deps,
15
+ onBlur,
16
+ onChange,
17
+ pattern,
18
+ required,
19
+ shouldUnregister,
20
+ validate,
21
+ value,
22
+ FieldProps,
23
+ ...rest
24
+ }: ControlledOrgAutocompleteProps) => {
25
+ const {
26
+ control,
27
+ formState: { errors },
28
+ } = useFormContext();
29
+ const errorMessage = errors[name]?.message;
30
+ return (
31
+ <Controller
32
+ name={name}
33
+ control={control}
34
+ defaultValue={defaultValue}
35
+ rules={{
36
+ deps,
37
+ onBlur,
38
+ onChange,
39
+ pattern,
40
+ required,
41
+ shouldUnregister,
42
+ validate,
43
+ value,
44
+ }}
45
+ shouldUnregister={shouldUnregister}
46
+ render={({ field: { onChange, value, onBlur } }) => (
47
+ <OrganizationAutocomplete
48
+ {...rest}
49
+ FieldProps={{
50
+ ...FieldProps,
51
+ error: !!errorMessage,
52
+ helperText:
53
+ errorMessage && typeof errorMessage === 'string' ? (
54
+ <>
55
+ {errorMessage}
56
+ <br />
57
+ {FieldProps?.helperText}
58
+ </>
59
+ ) : (
60
+ FieldProps?.helperText
61
+ ),
62
+ }}
63
+ onChange={(event, value, reason) => {
64
+ if (reason === 'clear') {
65
+ onChange(null);
66
+ }
67
+ onChange(value);
68
+ }}
69
+ onBlur={onBlur}
70
+ value={value || null}
71
+ />
72
+ )}
73
+ />
74
+ );
75
+ };
@@ -0,0 +1,79 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { ControlledProviderAutocomplete } from './ProviderAutocomplete';
3
+ import { ControlledForm } from './ControlledForm';
4
+ import { Button } from '@availity/mui-button';
5
+ import { useFormContext } from 'react-hook-form';
6
+ import { Paper } from '@availity/mui-paper';
7
+ import { Typography } from '@availity/mui-typography';
8
+ import { Grid } from '@availity/mui-layout';
9
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
10
+ import { missingRHFprops } from '../../docs/propDefinitions';
11
+
12
+ const meta: Meta<typeof ControlledProviderAutocomplete> = {
13
+ title: 'Form Components/Controlled Form/Autocomplete/ControlledProviderAutocomplete',
14
+ component: ControlledProviderAutocomplete,
15
+ tags: ['autodocs'],
16
+ argTypes: missingRHFprops,
17
+ };
18
+
19
+ export default meta;
20
+
21
+ const client = new QueryClient({
22
+ defaultOptions: {
23
+ queries: {
24
+ refetchOnWindowFocus: false,
25
+ },
26
+ },
27
+ });
28
+
29
+ export const _ControlledProviderAutoComplete: StoryObj<typeof ControlledProviderAutocomplete> = {
30
+ render: (args) => {
31
+ const SubmittedValues = () => {
32
+ const {
33
+ getValues,
34
+ formState: { isSubmitSuccessful },
35
+ } = useFormContext();
36
+
37
+ return isSubmitSuccessful ? (
38
+ <Paper sx={{ padding: '1.5rem', marginTop: '1.5rem' }}>
39
+ <Typography variant="h2">Submitted Values</Typography>
40
+ <pre>{JSON.stringify(getValues(), null, 2)}</pre>
41
+ </Paper>
42
+ ) : null;
43
+ };
44
+
45
+ const Actions = () => {
46
+ const {
47
+ reset,
48
+ formState: { isSubmitSuccessful },
49
+ } = useFormContext();
50
+ return (
51
+ <Grid container direction="row" justifyContent="space-between" marginTop={1}>
52
+ <Button disabled={!isSubmitSuccessful} children="Reset" color="secondary" onClick={() => reset()} />
53
+ <Button type="submit" disabled={isSubmitSuccessful} children="Submit" />
54
+ </Grid>
55
+ );
56
+ };
57
+ return (
58
+ <QueryClientProvider client={client}>
59
+ <ControlledForm values={{ controlledAutocomplete: undefined }} onSubmit={(data) => data}>
60
+ <ControlledProviderAutocomplete {...args} />
61
+ <Actions />
62
+ <SubmittedValues />
63
+ </ControlledForm>
64
+ </QueryClientProvider>
65
+ );
66
+ },
67
+ args: {
68
+ name: 'controlledProviderAutocomplete',
69
+ FieldProps: {
70
+ label: 'Provider Select',
71
+ helperText: 'Select a Provider from the list',
72
+ placeholder: 'Select...',
73
+ fullWidth: false,
74
+ },
75
+ limit: 10,
76
+ customerId: '1234',
77
+ required: 'This is required.',
78
+ },
79
+ };
@@ -0,0 +1,128 @@
1
+ import { fireEvent, render, waitFor } from '@testing-library/react';
2
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
3
+ import { Paper } from '@availity/mui-paper';
4
+ import { Typography } from '@availity/mui-typography';
5
+ import { useFormContext } from 'react-hook-form';
6
+ import { Grid } from '@availity/mui-layout';
7
+ import { Button } from '@availity/mui-button';
8
+ // eslint-disable-next-line @nx/enforce-module-boundaries
9
+ import { server } from '@availity/mock/src/lib/server';
10
+ import { ControlledForm } from './ControlledForm';
11
+ import { ControlledProviderAutocomplete } from './ProviderAutocomplete';
12
+
13
+ const SubmittedValues = () => {
14
+ const {
15
+ getValues,
16
+ formState: { isSubmitSuccessful },
17
+ } = useFormContext();
18
+
19
+ return isSubmitSuccessful ? (
20
+ <Paper sx={{ padding: '1.5rem', marginTop: '1.5rem' }}>
21
+ <Typography variant="h2">Submitted Values</Typography>
22
+ <pre data-testid="result">{JSON.stringify(getValues(), null, 2)}</pre>
23
+ </Paper>
24
+ ) : null;
25
+ };
26
+
27
+ const Actions = () => {
28
+ const {
29
+ formState: { isSubmitSuccessful },
30
+ } = useFormContext();
31
+ return (
32
+ <Grid container direction="row" justifyContent="space-between">
33
+ <Button type="submit" disabled={isSubmitSuccessful} children="Submit" />
34
+ </Grid>
35
+ );
36
+ };
37
+
38
+ const onSubmit = jest.fn();
39
+
40
+ describe('ControlledProviderAutocomplete', () => {
41
+ beforeAll(() => {
42
+ // Start the interception.
43
+ server.listen();
44
+ });
45
+
46
+ afterEach(() => {
47
+ // Remove any handlers you may have added
48
+ // in individual tests (runtime handlers).
49
+ server.resetHandlers();
50
+ jest.restoreAllMocks();
51
+ });
52
+
53
+ const client = new QueryClient({
54
+ defaultOptions: {
55
+ queries: {
56
+ refetchOnWindowFocus: false,
57
+ },
58
+ },
59
+ });
60
+
61
+ test('should loadOptions successfully', async () => {
62
+ const screen = render(
63
+ <QueryClientProvider client={client}>
64
+ <ControlledForm values={{ controlledAutocomplete: undefined }} onSubmit={(data) => data}>
65
+ <ControlledProviderAutocomplete
66
+ name="controlledProviderAutocomplete"
67
+ FieldProps={{
68
+ label: 'Provider Select',
69
+ helperText: 'Select a Provider from the list',
70
+ placeholder: 'Select...',
71
+ fullWidth: false,
72
+ }}
73
+ limit={10}
74
+ customerId="1234"
75
+ />
76
+ <Actions />
77
+ <SubmittedValues />
78
+ </ControlledForm>
79
+ </QueryClientProvider>
80
+ );
81
+
82
+ const dropdown = screen.getByRole('combobox');
83
+ fireEvent.click(dropdown);
84
+ fireEvent.keyDown(dropdown, { key: 'ArrowDown' });
85
+
86
+ await waitFor(() => expect(screen.getByText('Provider 1')).toBeDefined());
87
+ });
88
+
89
+ test('should set the value and submit the form data', async () => {
90
+ const screen = render(
91
+ <QueryClientProvider client={client}>
92
+ <ControlledForm values={{ controlledAutocomplete: undefined }} onSubmit={onSubmit}>
93
+ <ControlledProviderAutocomplete
94
+ name="controlledProviderAutocomplete"
95
+ FieldProps={{
96
+ label: 'Provider Select',
97
+ helperText: 'Select a Provider from the list',
98
+ placeholder: 'Select...',
99
+ fullWidth: false,
100
+ }}
101
+ limit={10}
102
+ customerId="1234"
103
+ />
104
+ <Actions />
105
+ <SubmittedValues />
106
+ </ControlledForm>
107
+ </QueryClientProvider>
108
+ );
109
+
110
+ const dropdown = screen.getByRole('combobox');
111
+ fireEvent.click(dropdown);
112
+ fireEvent.keyDown(dropdown, { key: 'ArrowDown' });
113
+
114
+ await waitFor(() => screen.getByText('Provider 1'));
115
+
116
+ fireEvent.click(screen.getByText('Provider 1'));
117
+
118
+ fireEvent.click(screen.getByText('Submit'));
119
+
120
+ await waitFor(() => expect(onSubmit).toHaveBeenCalledTimes(1));
121
+ const result = screen.getByTestId('result');
122
+ await waitFor(() => {
123
+ const controlledProviderAutocompleteValue = JSON.parse(result.innerHTML).controlledProviderAutocomplete;
124
+ expect(controlledProviderAutocompleteValue.uiDisplayName).toBe('Provider 1');
125
+ expect(controlledProviderAutocompleteValue.id).toBeDefined();
126
+ });
127
+ });
128
+ });