@hero-design/rn-work-uikit 1.2.0-alpha.1 → 1.2.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.
- package/CHANGELOG.md +8 -8
- package/lib/index.js +2102 -186
- package/package.json +2 -2
- package/rollup.config.mjs +0 -1
- package/src/__tests__/__snapshots__/index.spec.tsx.snap +10 -29
- package/src/components/TextInput/FloatingLabel.tsx +8 -2
- package/src/components/TextInput/Group/__tests__/__snapshots__/index.spec.tsx.snap +883 -0
- package/src/components/TextInput/Group/__tests__/index.spec.tsx +179 -0
- package/src/components/TextInput/Group/__tests__/utils.spec.ts +73 -0
- package/src/components/TextInput/Group/index.tsx +102 -0
- package/src/components/TextInput/Group/utils.ts +67 -0
- package/src/components/TextInput/InputRow.tsx +47 -29
- package/src/components/TextInput/MIGRATION.md +133 -0
- package/src/components/TextInput/StyledTextInput.tsx +36 -8
- package/src/components/TextInput/__tests__/FloatingLabel.spec.tsx +36 -46
- package/src/components/TextInput/__tests__/InputRow.spec.tsx +50 -95
- package/src/components/TextInput/__tests__/__snapshots__/index.spec.tsx.snap +559 -544
- package/src/components/TextInput/__tests__/index.spec.tsx +241 -262
- package/src/components/TextInput/index.tsx +39 -17
- package/src/components/TextInput/types.ts +7 -0
|
@@ -5,12 +5,37 @@ export type State = 'default' | 'filled' | 'disabled' | 'readonly' | 'error';
|
|
|
5
5
|
|
|
6
6
|
type Variant = 'text' | 'textarea';
|
|
7
7
|
|
|
8
|
-
const
|
|
8
|
+
const getZIndexByState = ({
|
|
9
|
+
themeFocused,
|
|
10
|
+
themeHasError,
|
|
11
|
+
}: {
|
|
12
|
+
themeFocused: boolean;
|
|
13
|
+
themeHasError: boolean;
|
|
14
|
+
}) => {
|
|
15
|
+
if (themeFocused) {
|
|
16
|
+
return 2;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (themeHasError) {
|
|
20
|
+
return 1;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return 0;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const StyledContainer = styled(Pressable)<{
|
|
27
|
+
themeFocused: boolean;
|
|
28
|
+
themeHasError: boolean;
|
|
29
|
+
themeUseGroupStyleEnabled: boolean;
|
|
30
|
+
}>(({ theme, themeFocused, themeHasError, themeUseGroupStyleEnabled }) => ({
|
|
9
31
|
width: '100%',
|
|
10
32
|
flexDirection: 'row',
|
|
11
33
|
paddingHorizontal: theme.__hd__.textInput.space.containerPadding,
|
|
12
34
|
minHeight: theme.__hd__.textInput.sizes.containerMinHeight,
|
|
13
35
|
marginTop: theme.__hd__.textInput.space.containerMarginTop,
|
|
36
|
+
...(themeUseGroupStyleEnabled && {
|
|
37
|
+
zIndex: getZIndexByState({ themeFocused, themeHasError }),
|
|
38
|
+
}),
|
|
14
39
|
}));
|
|
15
40
|
|
|
16
41
|
const StyledFloatingLabelContainer = styled(Animated.View)<{
|
|
@@ -89,13 +114,16 @@ const StyledInputWrapper = styled(View)(({ theme }) => ({
|
|
|
89
114
|
overflow: 'hidden',
|
|
90
115
|
}));
|
|
91
116
|
|
|
92
|
-
const StyledInputRow = styled(
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
117
|
+
const StyledInputRow = styled(Pressable)<{ themeOpacity: number }>(
|
|
118
|
+
({ theme, themeOpacity }) => ({
|
|
119
|
+
flexDirection: 'row',
|
|
120
|
+
alignItems: 'center',
|
|
121
|
+
flexGrow: 2,
|
|
122
|
+
flexShrink: 1,
|
|
123
|
+
gap: theme.__hd__.textInput.space.prefixAndInputContainerGap,
|
|
124
|
+
opacity: themeOpacity,
|
|
125
|
+
})
|
|
126
|
+
);
|
|
99
127
|
|
|
100
128
|
const StyledErrorAndHelpTextContainer = styled(View)(({ theme }) => ({
|
|
101
129
|
paddingHorizontal:
|
|
@@ -5,16 +5,15 @@ import FloatingLabel from '../FloatingLabel';
|
|
|
5
5
|
describe('FloatingLabel', () => {
|
|
6
6
|
describe('label text display based on required prop', () => {
|
|
7
7
|
it.each`
|
|
8
|
-
required | expectedText
|
|
9
|
-
${true} | ${'Email'}
|
|
10
|
-
${false} | ${'Phone
|
|
8
|
+
required | expectedText | optionalText
|
|
9
|
+
${true} | ${'Email'} | ${null}
|
|
10
|
+
${false} | ${'Phone'} | ${'(Optional)'}
|
|
11
11
|
`(
|
|
12
|
-
'should display $expectedText
|
|
13
|
-
({ required, expectedText,
|
|
14
|
-
const
|
|
15
|
-
const { getByText, queryByText } = renderWithTheme(
|
|
12
|
+
'should display "$expectedText" with "$optionalText" when required is $required',
|
|
13
|
+
({ required, expectedText, optionalText }) => {
|
|
14
|
+
const { getByTestId, queryByText } = renderWithTheme(
|
|
16
15
|
<FloatingLabel
|
|
17
|
-
label={
|
|
16
|
+
label={expectedText}
|
|
18
17
|
variant="text"
|
|
19
18
|
state="default"
|
|
20
19
|
isFocused={false}
|
|
@@ -23,12 +22,11 @@ describe('FloatingLabel', () => {
|
|
|
23
22
|
/>
|
|
24
23
|
);
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
expect(
|
|
25
|
+
const labelComponent = getByTestId('input-label');
|
|
26
|
+
expect(labelComponent).toHaveTextContent(expectedText);
|
|
28
27
|
|
|
29
|
-
if (
|
|
30
|
-
expect(queryByText(
|
|
31
|
-
expect(queryByText('(Optional)')).toBeFalsy();
|
|
28
|
+
if (optionalText) {
|
|
29
|
+
expect(queryByText(optionalText)).toBeVisible();
|
|
32
30
|
}
|
|
33
31
|
}
|
|
34
32
|
);
|
|
@@ -36,39 +34,42 @@ describe('FloatingLabel', () => {
|
|
|
36
34
|
|
|
37
35
|
describe('label behavior based on focus and content state', () => {
|
|
38
36
|
it.each`
|
|
39
|
-
state | isEmptyValue |
|
|
40
|
-
${'focused'} | ${true} | ${
|
|
41
|
-
${'filled'} | ${false} | ${
|
|
37
|
+
state | isEmptyValue | required | expectedText | description
|
|
38
|
+
${'focused'} | ${true} | ${true} | ${'Password'} | ${'user focuses empty input'}
|
|
39
|
+
${'filled'} | ${false} | ${true} | ${'Message'} | ${'user enters text in input'}
|
|
42
40
|
`(
|
|
43
|
-
'should show
|
|
44
|
-
({ state, isEmptyValue }) => {
|
|
45
|
-
const { getByTestId } = renderWithTheme(
|
|
41
|
+
'should show correct label when $description',
|
|
42
|
+
({ state, isEmptyValue, required, expectedText }) => {
|
|
43
|
+
const { getByTestId, queryByText } = renderWithTheme(
|
|
46
44
|
<FloatingLabel
|
|
47
|
-
label={
|
|
45
|
+
label={expectedText}
|
|
48
46
|
variant="text"
|
|
49
47
|
state={state}
|
|
50
48
|
isFocused={state === 'focused'}
|
|
51
|
-
required
|
|
49
|
+
required={required}
|
|
52
50
|
isEmptyValue={isEmptyValue}
|
|
53
51
|
/>
|
|
54
52
|
);
|
|
55
53
|
|
|
56
54
|
// User should see the label behaving appropriately
|
|
57
55
|
const label = getByTestId('input-label');
|
|
58
|
-
expect(label).
|
|
59
|
-
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
56
|
+
expect(label).toHaveTextContent(expectedText);
|
|
57
|
+
|
|
58
|
+
const optionalLabel = queryByText(' (Optional)');
|
|
59
|
+
if (!required) {
|
|
60
|
+
expect(optionalLabel).not.toBeNull();
|
|
61
|
+
} else {
|
|
62
|
+
expect(optionalLabel).toBeNull();
|
|
63
|
+
}
|
|
64
64
|
}
|
|
65
65
|
);
|
|
66
66
|
});
|
|
67
67
|
|
|
68
68
|
describe('variant-specific positioning', () => {
|
|
69
69
|
it.each`
|
|
70
|
-
variant | required | expectedText
|
|
71
|
-
${'textarea'} | ${false} | ${'Description
|
|
70
|
+
variant | required | expectedText | description
|
|
71
|
+
${'textarea'} | ${false} | ${'Description'} | ${'multiline input with optional label'}
|
|
72
|
+
${'textarea'} | ${true} | ${'Description'} | ${'multiline input with required label'}
|
|
72
73
|
`(
|
|
73
74
|
'should position label appropriately for $variant ($description)',
|
|
74
75
|
({ variant, required, expectedText }) => {
|
|
@@ -85,20 +86,16 @@ describe('FloatingLabel', () => {
|
|
|
85
86
|
|
|
86
87
|
// User should see the label with proper variant positioning
|
|
87
88
|
const label = getByTestId('input-label');
|
|
88
|
-
expect(label).
|
|
89
|
-
const { children } = label.props;
|
|
90
|
-
expect(Array.isArray(children) ? children.join('') : children).toBe(
|
|
91
|
-
expectedText
|
|
92
|
-
);
|
|
89
|
+
expect(label).toHaveTextContent(expectedText);
|
|
93
90
|
}
|
|
94
91
|
);
|
|
95
92
|
});
|
|
96
93
|
|
|
97
94
|
describe('when user encounters different input states', () => {
|
|
98
95
|
it.each`
|
|
99
|
-
state | required | expectedText
|
|
100
|
-
${'error'} | ${true} | ${'Email'}
|
|
101
|
-
${'disabled'} | ${false} | ${'Disabled Field
|
|
96
|
+
state | required | expectedText | description
|
|
97
|
+
${'error'} | ${true} | ${'Email'} | ${'validation error with required field'}
|
|
98
|
+
${'disabled'} | ${false} | ${'Disabled Field'} | ${'non-interactive optional field'}
|
|
102
99
|
`(
|
|
103
100
|
'should display appropriate styling for $state state ($description)',
|
|
104
101
|
({ state, required, expectedText }) => {
|
|
@@ -115,11 +112,7 @@ describe('FloatingLabel', () => {
|
|
|
115
112
|
|
|
116
113
|
// User should see the label with appropriate state styling
|
|
117
114
|
const label = getByTestId('input-label');
|
|
118
|
-
expect(label).
|
|
119
|
-
const { children } = label.props;
|
|
120
|
-
expect(
|
|
121
|
-
Array.isArray(children) ? children.filter(Boolean).join('') : children
|
|
122
|
-
).toBe(expectedText);
|
|
115
|
+
expect(label).toHaveTextContent(expectedText);
|
|
123
116
|
}
|
|
124
117
|
);
|
|
125
118
|
});
|
|
@@ -193,10 +186,7 @@ describe('FloatingLabel', () => {
|
|
|
193
186
|
const label = getByTestId('input-label');
|
|
194
187
|
expect(label).toBeTruthy();
|
|
195
188
|
expect(label).toHaveProp('nativeID', 'fullname-label');
|
|
196
|
-
|
|
197
|
-
expect(Array.isArray(children) ? children.join('') : children).toBe(
|
|
198
|
-
'Full Name (Optional)'
|
|
199
|
-
);
|
|
189
|
+
expect(label).toHaveTextContent('Full Name');
|
|
200
190
|
});
|
|
201
191
|
});
|
|
202
192
|
});
|
|
@@ -1,23 +1,20 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Text, TextInput as RNTextInput } from 'react-native';
|
|
3
3
|
import type { TextInputProps as NativeTextInputProps } from 'react-native';
|
|
4
|
+
import { fireEvent, waitFor } from '@testing-library/react-native';
|
|
4
5
|
// import { TextInput as RNTextInput } from 'react-native';
|
|
5
6
|
import renderWithTheme from '../../../../testUtils/renderWithTheme';
|
|
6
7
|
import InputRow from '../InputRow';
|
|
7
8
|
|
|
8
|
-
// Mock the LABEL_ANIMATION_DURATION constant
|
|
9
|
-
jest.mock('../constants', () => ({
|
|
10
|
-
LABEL_ANIMATION_DURATION: 0, // Instant animation for testing
|
|
11
|
-
}));
|
|
12
|
-
|
|
13
9
|
describe('InputRow', () => {
|
|
14
10
|
const defaultProps = {
|
|
15
11
|
state: 'default' as const,
|
|
16
|
-
isFocused: false,
|
|
17
12
|
variant: 'text' as const,
|
|
13
|
+
testID: 'input-row',
|
|
18
14
|
nativeInputProps: {
|
|
19
15
|
value: '',
|
|
20
16
|
placeholder: 'Enter text',
|
|
17
|
+
testID: 'input-row-text-input',
|
|
21
18
|
},
|
|
22
19
|
isEmptyValue: true,
|
|
23
20
|
};
|
|
@@ -26,73 +23,42 @@ describe('InputRow', () => {
|
|
|
26
23
|
jest.clearAllMocks();
|
|
27
24
|
});
|
|
28
25
|
|
|
29
|
-
describe('
|
|
30
|
-
it('should
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
<InputRow {...defaultProps} prefix="search" ref={ref} />
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
// Components should be present but hidden
|
|
37
|
-
const inputWrapper = getByTestId('input-row-input-wrapper');
|
|
38
|
-
expect(inputWrapper).toBeTruthy();
|
|
39
|
-
expect(inputWrapper).toHaveProp('accessibilityElementsHidden', true);
|
|
26
|
+
describe('visibility behavior', () => {
|
|
27
|
+
it('should be hidden when unfocused and empty by default', () => {
|
|
28
|
+
const { getByTestId } = renderWithTheme(<InputRow {...defaultProps} />);
|
|
29
|
+
expect(getByTestId('input-row')).toHaveProp('themeOpacity', 0);
|
|
40
30
|
});
|
|
41
|
-
});
|
|
42
31
|
|
|
43
|
-
|
|
44
|
-
it('should show both prefix and input components with animation', () => {
|
|
45
|
-
const ref = React.createRef<RNTextInput>();
|
|
32
|
+
it('should be visible when unfocused and empty if shouldShowWhenUnfocused is true', () => {
|
|
46
33
|
const { getByTestId } = renderWithTheme(
|
|
47
|
-
<InputRow {...defaultProps}
|
|
34
|
+
<InputRow {...defaultProps} shouldShowWhenUnfocused />
|
|
48
35
|
);
|
|
36
|
+
expect(getByTestId('input-row')).toHaveProp('themeOpacity', 1);
|
|
37
|
+
});
|
|
49
38
|
|
|
50
|
-
|
|
51
|
-
const
|
|
52
|
-
|
|
39
|
+
it('should become visible on focus', async () => {
|
|
40
|
+
const { getByTestId } = renderWithTheme(<InputRow {...defaultProps} />);
|
|
41
|
+
|
|
42
|
+
expect(getByTestId('input-row')).toHaveProp('themeOpacity', 0);
|
|
43
|
+
fireEvent(getByTestId('input-row-text-input'), 'focus');
|
|
44
|
+
|
|
45
|
+
await waitFor(() => {
|
|
46
|
+
expect(getByTestId('input-row')).toHaveProp('themeOpacity', 1);
|
|
47
|
+
});
|
|
53
48
|
});
|
|
54
|
-
});
|
|
55
49
|
|
|
56
|
-
|
|
57
|
-
it('should keep components visible even when not focused', () => {
|
|
58
|
-
const ref = React.createRef<RNTextInput>();
|
|
50
|
+
it('should be visible when it has a value, even if unfocused', () => {
|
|
59
51
|
const { getByTestId } = renderWithTheme(
|
|
60
52
|
<InputRow
|
|
61
53
|
{...defaultProps}
|
|
62
|
-
prefix="search"
|
|
63
|
-
state="filled"
|
|
64
54
|
isEmptyValue={false}
|
|
65
55
|
nativeInputProps={{
|
|
66
56
|
...defaultProps.nativeInputProps,
|
|
67
57
|
value: 'user@example.com',
|
|
68
58
|
}}
|
|
69
|
-
ref={ref}
|
|
70
59
|
/>
|
|
71
60
|
);
|
|
72
|
-
|
|
73
|
-
// User has entered text - components should be visible
|
|
74
|
-
const inputWrapper = getByTestId('input-row-input-wrapper');
|
|
75
|
-
expect(inputWrapper).toHaveProp('accessibilityElementsHidden', false);
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
describe('when user uses input with prefix icon', () => {
|
|
80
|
-
it('should render input wrapper when prefix is provided', () => {
|
|
81
|
-
const ref = React.createRef<RNTextInput>();
|
|
82
|
-
const { getByTestId } = renderWithTheme(
|
|
83
|
-
<InputRow
|
|
84
|
-
{...defaultProps}
|
|
85
|
-
prefix="search"
|
|
86
|
-
isFocused
|
|
87
|
-
isEmptyValue={false}
|
|
88
|
-
ref={ref}
|
|
89
|
-
/>
|
|
90
|
-
);
|
|
91
|
-
|
|
92
|
-
// User should see the input wrapper with prefix
|
|
93
|
-
const inputWrapper = getByTestId('input-row-input-wrapper');
|
|
94
|
-
expect(inputWrapper).toBeTruthy();
|
|
95
|
-
expect(inputWrapper).toHaveProp('accessibilityElementsHidden', false);
|
|
61
|
+
expect(getByTestId('input-row')).toHaveProp('themeOpacity', 1);
|
|
96
62
|
});
|
|
97
63
|
});
|
|
98
64
|
|
|
@@ -105,12 +71,11 @@ describe('InputRow', () => {
|
|
|
105
71
|
<InputRow
|
|
106
72
|
{...defaultProps}
|
|
107
73
|
prefix={<CustomPrefix />}
|
|
108
|
-
isFocused
|
|
109
74
|
isEmptyValue={false}
|
|
110
75
|
ref={ref}
|
|
76
|
+
shouldShowWhenUnfocused
|
|
111
77
|
/>
|
|
112
78
|
);
|
|
113
|
-
|
|
114
79
|
// User should see the custom prefix
|
|
115
80
|
expect(getByTestId('custom-prefix')).toBeTruthy();
|
|
116
81
|
});
|
|
@@ -123,7 +88,6 @@ describe('InputRow', () => {
|
|
|
123
88
|
<InputRow
|
|
124
89
|
{...defaultProps}
|
|
125
90
|
variant="textarea"
|
|
126
|
-
isFocused
|
|
127
91
|
isEmptyValue={false}
|
|
128
92
|
nativeInputProps={{
|
|
129
93
|
...defaultProps.nativeInputProps,
|
|
@@ -131,9 +95,9 @@ describe('InputRow', () => {
|
|
|
131
95
|
numberOfLines: 4,
|
|
132
96
|
}}
|
|
133
97
|
ref={ref}
|
|
98
|
+
shouldShowWhenUnfocused
|
|
134
99
|
/>
|
|
135
100
|
);
|
|
136
|
-
|
|
137
101
|
// User should see the textarea input
|
|
138
102
|
const inputWrapper = getByTestId('input-row-input-wrapper');
|
|
139
103
|
expect(inputWrapper).toBeTruthy();
|
|
@@ -143,27 +107,28 @@ describe('InputRow', () => {
|
|
|
143
107
|
|
|
144
108
|
describe('when user encounters different input states', () => {
|
|
145
109
|
it('should render input wrapper in error state', () => {
|
|
146
|
-
const ref = React.createRef<RNTextInput>();
|
|
147
110
|
const { getByTestId } = renderWithTheme(
|
|
148
111
|
<InputRow
|
|
149
112
|
{...defaultProps}
|
|
150
113
|
state="error"
|
|
151
114
|
isEmptyValue={false}
|
|
152
|
-
|
|
115
|
+
shouldShowWhenUnfocused
|
|
153
116
|
/>
|
|
154
117
|
);
|
|
155
|
-
|
|
156
118
|
// Components should render with error state
|
|
157
119
|
const inputWrapper = getByTestId('input-row-input-wrapper');
|
|
158
120
|
expect(inputWrapper).toBeTruthy();
|
|
159
121
|
});
|
|
160
122
|
|
|
161
123
|
it('should handle disabled state appropriately', () => {
|
|
162
|
-
const ref = React.createRef<RNTextInput>();
|
|
163
124
|
const { getByTestId } = renderWithTheme(
|
|
164
|
-
<InputRow
|
|
125
|
+
<InputRow
|
|
126
|
+
{...defaultProps}
|
|
127
|
+
state="disabled"
|
|
128
|
+
isEmptyValue
|
|
129
|
+
shouldShowWhenUnfocused
|
|
130
|
+
/>
|
|
165
131
|
);
|
|
166
|
-
|
|
167
132
|
// Even disabled inputs should render components
|
|
168
133
|
const inputWrapper = getByTestId('input-row-input-wrapper');
|
|
169
134
|
expect(inputWrapper).toBeTruthy();
|
|
@@ -181,16 +146,15 @@ describe('InputRow', () => {
|
|
|
181
146
|
<InputRow
|
|
182
147
|
{...defaultProps}
|
|
183
148
|
renderInputValue={customRenderer}
|
|
184
|
-
isFocused
|
|
185
149
|
isEmptyValue={false}
|
|
186
150
|
nativeInputProps={{
|
|
187
151
|
...defaultProps.nativeInputProps,
|
|
188
152
|
value: 'test value',
|
|
189
153
|
}}
|
|
190
154
|
ref={ref}
|
|
155
|
+
shouldShowWhenUnfocused
|
|
191
156
|
/>
|
|
192
157
|
);
|
|
193
|
-
|
|
194
158
|
// User should see the custom rendered input
|
|
195
159
|
expect(getByTestId('custom-input-renderer')).toBeTruthy();
|
|
196
160
|
});
|
|
@@ -200,7 +164,12 @@ describe('InputRow', () => {
|
|
|
200
164
|
it('should properly handle input ref', () => {
|
|
201
165
|
const ref = React.createRef<RNTextInput>();
|
|
202
166
|
renderWithTheme(
|
|
203
|
-
<InputRow
|
|
167
|
+
<InputRow
|
|
168
|
+
{...defaultProps}
|
|
169
|
+
isEmptyValue={false}
|
|
170
|
+
ref={ref}
|
|
171
|
+
shouldShowWhenUnfocused
|
|
172
|
+
/>
|
|
204
173
|
);
|
|
205
174
|
expect(ref.current).toBeDefined();
|
|
206
175
|
});
|
|
@@ -208,31 +177,18 @@ describe('InputRow', () => {
|
|
|
208
177
|
|
|
209
178
|
describe('accessibility features', () => {
|
|
210
179
|
it('should provide proper accessibility labels for input wrapper', () => {
|
|
211
|
-
const ref = React.createRef<RNTextInput>();
|
|
212
|
-
const { getByTestId } = renderWithTheme(
|
|
213
|
-
<InputRow {...defaultProps} isFocused isEmptyValue={false} ref={ref} />
|
|
214
|
-
);
|
|
215
|
-
|
|
216
|
-
// User should have proper accessibility support
|
|
217
|
-
const inputWrapper = getByTestId('input-row-input-wrapper');
|
|
218
|
-
expect(inputWrapper).toHaveProp('accessibilityLabel', 'Text input field');
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
it('should hide components from screen readers when not visible', () => {
|
|
222
180
|
const ref = React.createRef<RNTextInput>();
|
|
223
181
|
const { getByTestId } = renderWithTheme(
|
|
224
182
|
<InputRow
|
|
225
183
|
{...defaultProps}
|
|
226
|
-
|
|
227
|
-
state="default"
|
|
228
|
-
isEmptyValue
|
|
184
|
+
isEmptyValue={false}
|
|
229
185
|
ref={ref}
|
|
186
|
+
shouldShowWhenUnfocused
|
|
230
187
|
/>
|
|
231
188
|
);
|
|
232
|
-
|
|
233
|
-
// Components should be hidden from screen readers when not visible
|
|
189
|
+
// User should have proper accessibility support
|
|
234
190
|
const inputWrapper = getByTestId('input-row-input-wrapper');
|
|
235
|
-
expect(inputWrapper).toHaveProp('
|
|
191
|
+
expect(inputWrapper).toHaveProp('accessibilityLabel', 'Text input field');
|
|
236
192
|
});
|
|
237
193
|
});
|
|
238
194
|
|
|
@@ -243,7 +199,6 @@ describe('InputRow', () => {
|
|
|
243
199
|
<InputRow
|
|
244
200
|
{...defaultProps}
|
|
245
201
|
prefix="search"
|
|
246
|
-
isFocused
|
|
247
202
|
isEmptyValue={false}
|
|
248
203
|
nativeInputProps={{
|
|
249
204
|
...defaultProps.nativeInputProps,
|
|
@@ -251,25 +206,25 @@ describe('InputRow', () => {
|
|
|
251
206
|
placeholder: 'Enter email',
|
|
252
207
|
}}
|
|
253
208
|
ref={ref}
|
|
209
|
+
shouldShowWhenUnfocused
|
|
254
210
|
/>
|
|
255
211
|
);
|
|
256
|
-
|
|
257
|
-
// User should see a fully rendered input row
|
|
258
212
|
const inputWrapper = getByTestId('input-row-input-wrapper');
|
|
259
213
|
expect(inputWrapper).toBeTruthy();
|
|
260
|
-
expect(inputWrapper).toHaveProp('accessibilityElementsHidden', false);
|
|
261
214
|
});
|
|
262
215
|
|
|
263
216
|
it('should render without prefix', () => {
|
|
264
217
|
const ref = React.createRef<RNTextInput>();
|
|
265
|
-
const { getByTestId
|
|
266
|
-
<InputRow
|
|
218
|
+
const { getByTestId } = renderWithTheme(
|
|
219
|
+
<InputRow
|
|
220
|
+
{...defaultProps}
|
|
221
|
+
isEmptyValue={false}
|
|
222
|
+
ref={ref}
|
|
223
|
+
shouldShowWhenUnfocused
|
|
224
|
+
/>
|
|
267
225
|
);
|
|
268
|
-
|
|
269
|
-
// User should see input without prefix
|
|
270
226
|
const inputWrapper = getByTestId('input-row-input-wrapper');
|
|
271
227
|
expect(inputWrapper).toBeTruthy();
|
|
272
|
-
expect(queryByText('search')).toBeNull();
|
|
273
228
|
});
|
|
274
229
|
});
|
|
275
230
|
});
|