@aws-amplify/ui-react-native 1.2.4 → 1.2.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/CHANGELOG.md +20 -0
- package/dist/Authenticator/Authenticator.d.ts +2 -2
- package/dist/Authenticator/Defaults/SetupTOTP/SetupTOTP.js +5 -22
- package/dist/Authenticator/hooks/useFieldValues/useFieldValues.js +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
- package/src/Authenticator/Defaults/SetupTOTP/SetupTOTP.tsx +5 -25
- package/src/Authenticator/Defaults/SetupTOTP/__tests__/SetupTOTP.spec.tsx +18 -65
- package/src/Authenticator/Defaults/SetupTOTP/__tests__/__snapshots__/SetupTOTP.spec.tsx.snap +90 -0
- package/src/Authenticator/hooks/useFieldValues/__tests__/useFieldValues.spec.ts +27 -1
- package/src/Authenticator/hooks/useFieldValues/useFieldValues.ts +1 -1
- package/src/version.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @aws-amplify/ui-react-native
|
|
2
2
|
|
|
3
|
+
## 1.2.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#3333](https://github.com/aws-amplify/amplify-ui/pull/3333) [`4ba0fb5c1`](https://github.com/aws-amplify/amplify-ui/commit/4ba0fb5c13484a36c8f44be5eb41313bf3d676cc) Thanks [@calebpollman](https://github.com/calebpollman)! - fix(authenticator): migrate totpSecretCode generation to state machine
|
|
8
|
+
|
|
9
|
+
- Updated dependencies [[`4ba0fb5c1`](https://github.com/aws-amplify/amplify-ui/commit/4ba0fb5c13484a36c8f44be5eb41313bf3d676cc), [`412538be9`](https://github.com/aws-amplify/amplify-ui/commit/412538be9e37a8dec7cb5e57281895a5b3b63184), [`9ce2d01b0`](https://github.com/aws-amplify/amplify-ui/commit/9ce2d01b09e2f7aa0b218a97bb829a4210350a0a), [`13d0882a8`](https://github.com/aws-amplify/amplify-ui/commit/13d0882a8fe3a9ef63e4b217c5f67cef2c75e148)]:
|
|
10
|
+
- @aws-amplify/ui-react-core@2.1.11
|
|
11
|
+
- @aws-amplify/ui@5.5.3
|
|
12
|
+
|
|
13
|
+
## 1.2.5
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- [#3198](https://github.com/aws-amplify/amplify-ui/pull/3198) [`9cb6696a2`](https://github.com/aws-amplify/amplify-ui/commit/9cb6696a227b7c5b4ce36920c2093289fa45cc95) Thanks [@ioanabrooks](https://github.com/ioanabrooks)! - fix(ui-react-native): Fixes an issue where undefined values end up in the state machine causing internal errors to be exposed to end users.
|
|
18
|
+
|
|
19
|
+
- Updated dependencies [[`57f1a3f43`](https://github.com/aws-amplify/amplify-ui/commit/57f1a3f438b8288ffda46764f7a87e1739e61313), [`dd9de348a`](https://github.com/aws-amplify/amplify-ui/commit/dd9de348abcafdcd721600f543d58353957dac25), [`4d652033e`](https://github.com/aws-amplify/amplify-ui/commit/4d652033e120daa82665b4bb4035b56fa8d33bf8)]:
|
|
20
|
+
- @aws-amplify/ui@5.5.2
|
|
21
|
+
- @aws-amplify/ui-react-core@2.1.10
|
|
22
|
+
|
|
3
23
|
## 1.2.4
|
|
4
24
|
|
|
5
25
|
### Patch Changes
|
|
@@ -93,15 +93,15 @@ declare namespace Authenticator {
|
|
|
93
93
|
style?: import("./Defaults/types").ResetPasswordStyle | undefined;
|
|
94
94
|
}>) & import("@aws-amplify/ui-react-core/dist/types/Authenticator/hooks").ComponentSlots<import("./hooks").TextFieldOptionsType>;
|
|
95
95
|
var SetupTOTP: (React.ComponentClass<import("@aws-amplify/ui-react-core/dist/types/Authenticator/hooks").ComponentSlots<import("./hooks").TextFieldOptionsType> & {
|
|
96
|
-
getTotpSecretCode: import("@aws-amplify/ui-react-core/dist/types/Authenticator/hooks").GetTotpSecretCode;
|
|
97
96
|
toSignIn: (data?: import("@aws-amplify/ui").AuthEventData | undefined) => void;
|
|
97
|
+
totpSecretCode: string | null;
|
|
98
98
|
} & import("@aws-amplify/ui-react-core/dist/types/Authenticator/hooks").CommonRouteProps & {
|
|
99
99
|
fields: import("./hooks").TextFieldOptionsType[];
|
|
100
100
|
} & {
|
|
101
101
|
style?: import("./Defaults/types").SetupTOTPStyle | undefined;
|
|
102
102
|
}, any> | React.FunctionComponent<import("@aws-amplify/ui-react-core/dist/types/Authenticator/hooks").ComponentSlots<import("./hooks").TextFieldOptionsType> & {
|
|
103
|
-
getTotpSecretCode: import("@aws-amplify/ui-react-core/dist/types/Authenticator/hooks").GetTotpSecretCode;
|
|
104
103
|
toSignIn: (data?: import("@aws-amplify/ui").AuthEventData | undefined) => void;
|
|
104
|
+
totpSecretCode: string | null;
|
|
105
105
|
} & import("@aws-amplify/ui-react-core/dist/types/Authenticator/hooks").CommonRouteProps & {
|
|
106
106
|
fields: import("./hooks").TextFieldOptionsType[];
|
|
107
107
|
} & {
|
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import { Logger } from 'aws-amplify';
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
3
2
|
import { authenticatorTextUtil } from '@aws-amplify/ui';
|
|
4
3
|
import { Label } from '../../../primitives';
|
|
5
4
|
import { DefaultContent, DefaultFooter, DefaultTextFormFields, DefaultHeader, } from '../../common';
|
|
6
5
|
import { useFieldValues } from '../../hooks';
|
|
7
6
|
import { styles } from './styles';
|
|
8
7
|
const COMPONENT_NAME = 'SetupTOTP';
|
|
9
|
-
const logger = new Logger('Authenticator');
|
|
10
8
|
const { getBackToSignInText, getConfirmingText, getConfirmText, getSetupTOTPText, getSetupTOTPInstructionsText, } = authenticatorTextUtil;
|
|
11
|
-
const SetupTOTP = ({ fields,
|
|
9
|
+
const SetupTOTP = ({ fields, handleBlur, handleChange, handleSubmit, isPending, toSignIn, totpSecretCode, ...rest }) => {
|
|
12
10
|
const { fields: fieldsWithHandlers, handleFormSubmit } = useFieldValues({
|
|
13
11
|
componentName: COMPONENT_NAME,
|
|
14
12
|
fields,
|
|
@@ -16,32 +14,17 @@ const SetupTOTP = ({ fields, getTotpSecretCode, handleBlur, handleChange, handle
|
|
|
16
14
|
handleChange,
|
|
17
15
|
handleSubmit,
|
|
18
16
|
});
|
|
19
|
-
const [secretKey, setSecretKey] = useState(null);
|
|
20
|
-
const getSecretKey = useCallback(async () => {
|
|
21
|
-
try {
|
|
22
|
-
const newSecretKey = await getTotpSecretCode();
|
|
23
|
-
setSecretKey(newSecretKey);
|
|
24
|
-
}
|
|
25
|
-
catch (error) {
|
|
26
|
-
logger.error(error);
|
|
27
|
-
}
|
|
28
|
-
}, [getTotpSecretCode]);
|
|
29
|
-
useEffect(() => {
|
|
30
|
-
if (!secretKey) {
|
|
31
|
-
getSecretKey();
|
|
32
|
-
}
|
|
33
|
-
}, [getSecretKey, secretKey]);
|
|
34
17
|
const headerText = getSetupTOTPText();
|
|
35
18
|
const primaryButtonText = isPending ? getConfirmingText() : getConfirmText();
|
|
36
19
|
const secondaryButtonText = getBackToSignInText();
|
|
37
|
-
const body =
|
|
20
|
+
const body = (<>
|
|
38
21
|
<Label style={styles.secretKeyText}>
|
|
39
22
|
{getSetupTOTPInstructionsText()}
|
|
40
23
|
</Label>
|
|
41
24
|
<Label selectable style={styles.secretKeyText}>
|
|
42
|
-
{
|
|
25
|
+
{totpSecretCode}
|
|
43
26
|
</Label>
|
|
44
|
-
</>)
|
|
27
|
+
</>);
|
|
45
28
|
const buttons = useMemo(() => ({
|
|
46
29
|
primary: { children: primaryButtonText, onPress: handleFormSubmit },
|
|
47
30
|
links: [{ children: secondaryButtonText, onPress: toSignIn }],
|
|
@@ -62,7 +62,7 @@ export default function useFieldValues({ componentName, fields = [], handleBlur,
|
|
|
62
62
|
const handleFormSubmit = () => {
|
|
63
63
|
const submitValue = isRadioFieldComponent
|
|
64
64
|
? values
|
|
65
|
-
: fieldsWithHandlers.reduce((acc, { name, value, type }) => {
|
|
65
|
+
: fieldsWithHandlers.reduce((acc, { name, value = '', type }) => {
|
|
66
66
|
/*
|
|
67
67
|
For phone numbers pass the first 3 charactes from value as dialCode until we support a dialCode picker
|
|
68
68
|
*/
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "1.2.
|
|
1
|
+
export declare const VERSION = "1.2.6";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = '1.2.
|
|
1
|
+
export const VERSION = '1.2.6';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aws-amplify/ui-react-native",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.6",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"module": "dist/esm/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
"type-fest": "^2.3.4"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@aws-amplify/ui": "5.5.
|
|
47
|
-
"@aws-amplify/ui-react-core": "2.1.
|
|
46
|
+
"@aws-amplify/ui": "5.5.3",
|
|
47
|
+
"@aws-amplify/ui-react-core": "2.1.11"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
50
|
"aws-amplify": ">= 5.0.1",
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
2
|
|
|
3
|
-
import { Logger } from 'aws-amplify';
|
|
4
3
|
import { authenticatorTextUtil } from '@aws-amplify/ui';
|
|
5
4
|
|
|
6
5
|
import { Label } from '../../../primitives';
|
|
@@ -18,8 +17,6 @@ import { styles } from './styles';
|
|
|
18
17
|
|
|
19
18
|
const COMPONENT_NAME = 'SetupTOTP';
|
|
20
19
|
|
|
21
|
-
const logger = new Logger('Authenticator');
|
|
22
|
-
|
|
23
20
|
const {
|
|
24
21
|
getBackToSignInText,
|
|
25
22
|
getConfirmingText,
|
|
@@ -30,12 +27,12 @@ const {
|
|
|
30
27
|
|
|
31
28
|
const SetupTOTP: DefaultSetupTOTPComponent = ({
|
|
32
29
|
fields,
|
|
33
|
-
getTotpSecretCode,
|
|
34
30
|
handleBlur,
|
|
35
31
|
handleChange,
|
|
36
32
|
handleSubmit,
|
|
37
33
|
isPending,
|
|
38
34
|
toSignIn,
|
|
35
|
+
totpSecretCode,
|
|
39
36
|
...rest
|
|
40
37
|
}) => {
|
|
41
38
|
const { fields: fieldsWithHandlers, handleFormSubmit } = useFieldValues({
|
|
@@ -46,37 +43,20 @@ const SetupTOTP: DefaultSetupTOTPComponent = ({
|
|
|
46
43
|
handleSubmit,
|
|
47
44
|
});
|
|
48
45
|
|
|
49
|
-
const [secretKey, setSecretKey] = useState<string | null>(null);
|
|
50
|
-
|
|
51
|
-
const getSecretKey = useCallback(async () => {
|
|
52
|
-
try {
|
|
53
|
-
const newSecretKey = await getTotpSecretCode();
|
|
54
|
-
setSecretKey(newSecretKey);
|
|
55
|
-
} catch (error) {
|
|
56
|
-
logger.error(error);
|
|
57
|
-
}
|
|
58
|
-
}, [getTotpSecretCode]);
|
|
59
|
-
|
|
60
|
-
useEffect(() => {
|
|
61
|
-
if (!secretKey) {
|
|
62
|
-
getSecretKey();
|
|
63
|
-
}
|
|
64
|
-
}, [getSecretKey, secretKey]);
|
|
65
|
-
|
|
66
46
|
const headerText = getSetupTOTPText();
|
|
67
47
|
const primaryButtonText = isPending ? getConfirmingText() : getConfirmText();
|
|
68
48
|
const secondaryButtonText = getBackToSignInText();
|
|
69
49
|
|
|
70
|
-
const body =
|
|
50
|
+
const body = (
|
|
71
51
|
<>
|
|
72
52
|
<Label style={styles.secretKeyText}>
|
|
73
53
|
{getSetupTOTPInstructionsText()}
|
|
74
54
|
</Label>
|
|
75
55
|
<Label selectable style={styles.secretKeyText}>
|
|
76
|
-
{
|
|
56
|
+
{totpSecretCode}
|
|
77
57
|
</Label>
|
|
78
58
|
</>
|
|
79
|
-
)
|
|
59
|
+
);
|
|
80
60
|
|
|
81
61
|
const buttons = useMemo(
|
|
82
62
|
() => ({
|
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { fireEvent, render, waitFor } from '@testing-library/react-native';
|
|
3
3
|
import { authenticatorTextUtil } from '@aws-amplify/ui';
|
|
4
|
-
import { Logger } from 'aws-amplify';
|
|
5
4
|
|
|
6
5
|
import { SetupTOTP } from '..';
|
|
7
|
-
import { GetTotpSecretCode } from '@aws-amplify/ui-react-core/dist/types/Authenticator/hooks';
|
|
8
|
-
|
|
9
|
-
// use empty mockImplementation to turn off console output
|
|
10
|
-
const errorSpy = jest.spyOn(Logger.prototype, 'error').mockImplementation();
|
|
11
6
|
|
|
12
7
|
const code = {
|
|
13
8
|
name: 'code',
|
|
@@ -24,12 +19,12 @@ const props = {
|
|
|
24
19
|
Footer: SetupTOTP.Footer,
|
|
25
20
|
FormFields: SetupTOTP.FormFields,
|
|
26
21
|
Header: SetupTOTP.Header,
|
|
27
|
-
getTotpSecretCode: jest.fn() as unknown as GetTotpSecretCode,
|
|
28
22
|
handleBlur: jest.fn(),
|
|
29
23
|
handleChange: jest.fn(),
|
|
30
24
|
handleSubmit: jest.fn(),
|
|
31
25
|
isPending: false,
|
|
32
26
|
toSignIn,
|
|
27
|
+
totpSecretCode: "Let's keep it hush hush",
|
|
33
28
|
};
|
|
34
29
|
|
|
35
30
|
const {
|
|
@@ -37,54 +32,45 @@ const {
|
|
|
37
32
|
getConfirmingText,
|
|
38
33
|
getConfirmText,
|
|
39
34
|
getSetupTOTPText,
|
|
40
|
-
getSetupTOTPInstructionsText,
|
|
41
35
|
} = authenticatorTextUtil;
|
|
42
36
|
|
|
43
|
-
const SECRET_KEY = 'secretKey';
|
|
44
|
-
const mockGetTotpSecretCode = jest.fn().mockResolvedValue(SECRET_KEY);
|
|
45
|
-
|
|
46
37
|
describe('SetupTOTP', () => {
|
|
47
38
|
beforeEach(() => {
|
|
48
39
|
jest.clearAllMocks();
|
|
49
40
|
});
|
|
50
41
|
|
|
51
|
-
it('renders as expected',
|
|
42
|
+
it('renders as expected', () => {
|
|
52
43
|
const { toJSON, getAllByRole, getByText } = render(
|
|
53
44
|
<SetupTOTP {...props} />
|
|
54
45
|
);
|
|
55
|
-
await waitFor(() => {
|
|
56
|
-
expect(toJSON()).toMatchSnapshot();
|
|
57
46
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
47
|
+
expect(toJSON()).toMatchSnapshot();
|
|
48
|
+
|
|
49
|
+
expect(getAllByRole('header')).toBeDefined();
|
|
50
|
+
expect(getByText(getSetupTOTPText())).toBeDefined();
|
|
51
|
+
expect(getByText(getConfirmText())).toBeDefined();
|
|
63
52
|
});
|
|
64
53
|
|
|
65
|
-
it('renders an error message',
|
|
54
|
+
it('renders an error message', () => {
|
|
66
55
|
const errorMessage = 'Test error message';
|
|
67
56
|
const { toJSON, getByText } = render(
|
|
68
57
|
<SetupTOTP {...props} error={errorMessage} />
|
|
69
58
|
);
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
});
|
|
59
|
+
|
|
60
|
+
expect(toJSON()).toMatchSnapshot();
|
|
61
|
+
expect(getByText(errorMessage)).toBeDefined();
|
|
74
62
|
});
|
|
75
63
|
|
|
76
|
-
it('calls toSignIn an secondary button press',
|
|
77
|
-
const
|
|
78
|
-
const { getByText } = render(<SetupTOTP {...props} error={errorMessage} />);
|
|
79
|
-
await waitFor(() => {
|
|
80
|
-
const secondaryButton = getByText(getBackToSignInText());
|
|
64
|
+
it('calls toSignIn an secondary button press', () => {
|
|
65
|
+
const { getByText } = render(<SetupTOTP {...props} />);
|
|
81
66
|
|
|
82
|
-
|
|
67
|
+
const secondaryButton = getByText(getBackToSignInText());
|
|
83
68
|
|
|
84
|
-
|
|
69
|
+
expect(secondaryButton).toBeDefined();
|
|
85
70
|
|
|
86
|
-
|
|
87
|
-
|
|
71
|
+
fireEvent(secondaryButton, 'press');
|
|
72
|
+
|
|
73
|
+
expect(toSignIn).toHaveBeenCalledTimes(1);
|
|
88
74
|
});
|
|
89
75
|
|
|
90
76
|
it('shows the correct submit button based on isPending', async () => {
|
|
@@ -95,37 +81,4 @@ describe('SetupTOTP', () => {
|
|
|
95
81
|
expect(queryByText(getConfirmText())).toBe(null);
|
|
96
82
|
});
|
|
97
83
|
});
|
|
98
|
-
|
|
99
|
-
it('handles secret code generation as expected', async () => {
|
|
100
|
-
const { getByText, queryByText, rerender } = render(
|
|
101
|
-
<SetupTOTP {...props} getTotpSecretCode={mockGetTotpSecretCode} />
|
|
102
|
-
);
|
|
103
|
-
await waitFor(async () => {
|
|
104
|
-
expect(mockGetTotpSecretCode).toHaveBeenCalledTimes(1);
|
|
105
|
-
expect(getByText(getSetupTOTPInstructionsText())).toBeDefined();
|
|
106
|
-
expect(queryByText(SECRET_KEY)).toBeDefined();
|
|
107
|
-
expect(getByText(SECRET_KEY).props.selectable).toBe(true);
|
|
108
|
-
expect(errorSpy).not.toHaveBeenCalled();
|
|
109
|
-
|
|
110
|
-
rerender(
|
|
111
|
-
<SetupTOTP {...props} getTotpSecretCode={mockGetTotpSecretCode} />
|
|
112
|
-
);
|
|
113
|
-
await waitFor(() => {
|
|
114
|
-
expect(mockGetTotpSecretCode).toHaveBeenCalledTimes(1);
|
|
115
|
-
expect(errorSpy).not.toHaveBeenCalled();
|
|
116
|
-
});
|
|
117
|
-
});
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
it('handles secret code generation errors as expected', async () => {
|
|
121
|
-
mockGetTotpSecretCode.mockImplementationOnce(() => {
|
|
122
|
-
throw new Error('Mock Error');
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
render(<SetupTOTP {...props} getTotpSecretCode={mockGetTotpSecretCode} />);
|
|
126
|
-
await waitFor(() => {
|
|
127
|
-
expect(mockGetTotpSecretCode).toHaveBeenCalledTimes(1);
|
|
128
|
-
expect(errorSpy).toHaveBeenCalledTimes(1);
|
|
129
|
-
});
|
|
130
|
-
});
|
|
131
84
|
});
|
package/src/Authenticator/Defaults/SetupTOTP/__tests__/__snapshots__/SetupTOTP.spec.tsx.snap
CHANGED
|
@@ -23,6 +23,51 @@ Array [
|
|
|
23
23
|
>
|
|
24
24
|
Setup TOTP
|
|
25
25
|
</Text>,
|
|
26
|
+
<Text
|
|
27
|
+
accessibilityRole="text"
|
|
28
|
+
style={
|
|
29
|
+
Array [
|
|
30
|
+
Object {
|
|
31
|
+
"fontSize": 14,
|
|
32
|
+
"fontWeight": "400",
|
|
33
|
+
"lineHeight": 21,
|
|
34
|
+
},
|
|
35
|
+
Object {
|
|
36
|
+
"color": "hsl(210, 50%, 10%)",
|
|
37
|
+
},
|
|
38
|
+
Object {
|
|
39
|
+
"flexWrap": "wrap",
|
|
40
|
+
"marginHorizontal": 8,
|
|
41
|
+
"paddingVertical": 4,
|
|
42
|
+
},
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
>
|
|
46
|
+
Copy and paste the secret key below into an authenticator app and then enter the code in the text field below.
|
|
47
|
+
</Text>,
|
|
48
|
+
<Text
|
|
49
|
+
accessibilityRole="text"
|
|
50
|
+
selectable={true}
|
|
51
|
+
style={
|
|
52
|
+
Array [
|
|
53
|
+
Object {
|
|
54
|
+
"fontSize": 14,
|
|
55
|
+
"fontWeight": "400",
|
|
56
|
+
"lineHeight": 21,
|
|
57
|
+
},
|
|
58
|
+
Object {
|
|
59
|
+
"color": "hsl(210, 50%, 10%)",
|
|
60
|
+
},
|
|
61
|
+
Object {
|
|
62
|
+
"flexWrap": "wrap",
|
|
63
|
+
"marginHorizontal": 8,
|
|
64
|
+
"paddingVertical": 4,
|
|
65
|
+
},
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
>
|
|
69
|
+
Let's keep it hush hush
|
|
70
|
+
</Text>,
|
|
26
71
|
<View
|
|
27
72
|
style={
|
|
28
73
|
Object {
|
|
@@ -302,6 +347,51 @@ Array [
|
|
|
302
347
|
>
|
|
303
348
|
Setup TOTP
|
|
304
349
|
</Text>,
|
|
350
|
+
<Text
|
|
351
|
+
accessibilityRole="text"
|
|
352
|
+
style={
|
|
353
|
+
Array [
|
|
354
|
+
Object {
|
|
355
|
+
"fontSize": 14,
|
|
356
|
+
"fontWeight": "400",
|
|
357
|
+
"lineHeight": 21,
|
|
358
|
+
},
|
|
359
|
+
Object {
|
|
360
|
+
"color": "hsl(210, 50%, 10%)",
|
|
361
|
+
},
|
|
362
|
+
Object {
|
|
363
|
+
"flexWrap": "wrap",
|
|
364
|
+
"marginHorizontal": 8,
|
|
365
|
+
"paddingVertical": 4,
|
|
366
|
+
},
|
|
367
|
+
]
|
|
368
|
+
}
|
|
369
|
+
>
|
|
370
|
+
Copy and paste the secret key below into an authenticator app and then enter the code in the text field below.
|
|
371
|
+
</Text>,
|
|
372
|
+
<Text
|
|
373
|
+
accessibilityRole="text"
|
|
374
|
+
selectable={true}
|
|
375
|
+
style={
|
|
376
|
+
Array [
|
|
377
|
+
Object {
|
|
378
|
+
"fontSize": 14,
|
|
379
|
+
"fontWeight": "400",
|
|
380
|
+
"lineHeight": 21,
|
|
381
|
+
},
|
|
382
|
+
Object {
|
|
383
|
+
"color": "hsl(210, 50%, 10%)",
|
|
384
|
+
},
|
|
385
|
+
Object {
|
|
386
|
+
"flexWrap": "wrap",
|
|
387
|
+
"marginHorizontal": 8,
|
|
388
|
+
"paddingVertical": 4,
|
|
389
|
+
},
|
|
390
|
+
]
|
|
391
|
+
}
|
|
392
|
+
>
|
|
393
|
+
Let's keep it hush hush
|
|
394
|
+
</Text>,
|
|
305
395
|
<View
|
|
306
396
|
style={
|
|
307
397
|
Object {
|
|
@@ -271,6 +271,32 @@ describe('useFieldValues', () => {
|
|
|
271
271
|
});
|
|
272
272
|
});
|
|
273
273
|
|
|
274
|
+
it('does not submit undefined values for fields', () => {
|
|
275
|
+
const textField = {
|
|
276
|
+
label: 'test',
|
|
277
|
+
type: 'default',
|
|
278
|
+
name: 'testDefault',
|
|
279
|
+
} as TextFieldOptionsType;
|
|
280
|
+
const phoneTextField = {
|
|
281
|
+
type: 'phone',
|
|
282
|
+
name: 'testPhone',
|
|
283
|
+
} as TextFieldOptionsType;
|
|
284
|
+
const { result } = renderHook(() =>
|
|
285
|
+
useFieldValues({
|
|
286
|
+
...props,
|
|
287
|
+
fields: [textField, phoneTextField],
|
|
288
|
+
})
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
result.current.handleFormSubmit();
|
|
292
|
+
expect(props.handleSubmit).toHaveBeenCalledTimes(1);
|
|
293
|
+
expect(props.handleSubmit).toHaveBeenCalledWith({
|
|
294
|
+
country_code: '',
|
|
295
|
+
[textField.name]: '',
|
|
296
|
+
[phoneTextField.name]: '',
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
|
|
274
300
|
it('submits the expected values for phone fields', () => {
|
|
275
301
|
const phoneTextField = {
|
|
276
302
|
type: 'phone',
|
|
@@ -294,7 +320,7 @@ describe('useFieldValues', () => {
|
|
|
294
320
|
expect(props.handleSubmit).toHaveBeenCalledTimes(1);
|
|
295
321
|
expect(props.handleSubmit).toHaveBeenCalledWith({
|
|
296
322
|
country_code: mockValue.substring(0, 3),
|
|
297
|
-
[
|
|
323
|
+
[phoneTextField.name]: mockValue.substring(3, mockValue.length),
|
|
298
324
|
});
|
|
299
325
|
});
|
|
300
326
|
});
|
|
@@ -96,7 +96,7 @@ export default function useFieldValues<FieldType extends TypedField>({
|
|
|
96
96
|
const handleFormSubmit = () => {
|
|
97
97
|
const submitValue = isRadioFieldComponent
|
|
98
98
|
? values
|
|
99
|
-
: fieldsWithHandlers.reduce((acc, { name, value, type }) => {
|
|
99
|
+
: fieldsWithHandlers.reduce((acc, { name, value = '', type }) => {
|
|
100
100
|
/*
|
|
101
101
|
For phone numbers pass the first 3 charactes from value as dialCode until we support a dialCode picker
|
|
102
102
|
*/
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = '1.2.
|
|
1
|
+
export const VERSION = '1.2.6';
|