@widergy/mobile-ui 1.47.0 → 1.48.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 +7 -0
- package/lib/components/CaptionLabel/README.md +30 -8
- package/lib/components/CaptionLabel/index.js +2 -1
- package/lib/components/CaptionLabel/propTypes.js +1 -0
- package/lib/components/Checkbox/README.md +93 -25
- package/lib/components/Checkbox/index.js +14 -1
- package/lib/components/Checkbox/propTypes.js +1 -0
- package/lib/components/Label/index.js +2 -1
- package/lib/components/Label/propTypes.js +1 -0
- package/lib/components/RadioGroup/components/RadioButton/index.js +29 -18
- package/lib/components/RadioGroup/index.js +19 -5
- package/lib/components/Touchable/index.js +3 -1
- package/lib/components/Touchable/propTypes.js +1 -0
- package/lib/components/UTBadge/index.js +3 -1
- package/lib/components/UTBaseInputField/README.md +41 -19
- package/lib/components/UTBaseInputField/components/ActionAdornment/index.js +10 -3
- package/lib/components/UTBaseInputField/components/BadgeAdornment/index.js +6 -1
- package/lib/components/UTBaseInputField/components/IconAdornment/index.js +8 -1
- package/lib/components/UTBaseInputField/components/PrefixAdornment/index.js +8 -2
- package/lib/components/UTBaseInputField/components/SuffixAdornment/index.js +6 -1
- package/lib/components/UTBaseInputField/components/TooltipAdornment/index.js +16 -3
- package/lib/components/UTBaseInputField/index.js +15 -4
- package/lib/components/UTBottomSheet/README.md +94 -23
- package/lib/components/UTBottomSheet/index.js +27 -4
- package/lib/components/UTButton/index.js +18 -4
- package/lib/components/UTButton/proptypes.js +1 -0
- package/lib/components/UTCheckBox/README.md +47 -0
- package/lib/components/UTCheckBox/index.js +24 -3
- package/lib/components/UTCheckBox/proptypes.js +1 -0
- package/lib/components/UTCheckList/README.MD +63 -0
- package/lib/components/UTCheckList/index.js +25 -2
- package/lib/components/UTCheckList/proptypes.js +1 -0
- package/lib/components/UTDetailDrawer/README.md +60 -10
- package/lib/components/UTDetailDrawer/index.js +11 -1
- package/lib/components/UTDetailDrawer/propTypes.js +1 -0
- package/lib/components/UTFieldLabel/README.md +99 -0
- package/lib/components/UTFieldLabel/index.js +19 -2
- package/lib/components/UTIcon/README.md +25 -2
- package/lib/components/UTIcon/index.js +3 -1
- package/lib/components/UTLabel/README.md +26 -0
- package/lib/components/UTLabel/index.js +2 -0
- package/lib/components/UTLabel/proptypes.js +1 -0
- package/lib/components/UTMenu/README.md +275 -0
- package/lib/components/UTMenu/components/ListView/index.js +5 -3
- package/lib/components/UTMenu/components/ListView/proptypes.js +2 -1
- package/lib/components/UTMenu/components/MenuOption/index.js +5 -3
- package/lib/components/UTMenu/index.js +18 -3
- package/lib/components/UTMenu/proptypes.js +2 -1
- package/lib/components/UTModal/README.md +193 -0
- package/lib/components/UTModal/index.js +22 -2
- package/lib/components/UTModal/proptypes.js +1 -0
- package/lib/components/UTPhoneInput/index.js +25 -2
- package/lib/components/UTRoundView/README.md +158 -0
- package/lib/components/UTRoundView/index.js +12 -1
- package/lib/components/UTRoundView/propTypes.js +4 -2
- package/lib/components/UTSearchField/README.md +64 -14
- package/lib/components/UTSearchField/index.js +3 -1
- package/lib/components/UTSearchField/proptypes.js +2 -1
- package/lib/components/UTSelect/versions/V0/README.md +216 -0
- package/lib/components/UTSelect/versions/V0/componentes/MultipleItem/index.js +4 -2
- package/lib/components/UTSelect/versions/V0/index.js +5 -2
- package/lib/components/UTSelect/versions/V0/proptypes.js +2 -1
- package/lib/components/UTSelect/versions/V1/README.md +94 -0
- package/lib/components/UTSelect/versions/V1/index.js +28 -6
- package/lib/components/UTSelect/versions/V1/proptypes.js +1 -0
- package/lib/components/UTSelectableCard/README.md +85 -0
- package/lib/components/UTSelectableCard/index.js +52 -4
- package/lib/components/UTTextInput/versions/V0/components/BaseInput/index.js +5 -1
- package/lib/components/UTTextInput/versions/V0/components/InputLabel/index.js +4 -1
- package/lib/components/UTTextInput/versions/V0/flavors/FilledInput/index.js +9 -1
- package/lib/components/UTTextInput/versions/V0/flavors/OutlinedInput/index.js +9 -1
- package/lib/components/UTTextInput/versions/V0/flavors/StandardInput/index.js +9 -1
- package/lib/components/UTTextInput/versions/V1/components/TextInputField/index.js +3 -0
- package/lib/components/UTTextInput/versions/V1/index.js +20 -3
- package/lib/components/UTTooltip/README.md +99 -0
- package/lib/components/UTTooltip/index.js +2 -0
- package/lib/components/UTTooltip/proptypes.js +2 -1
- package/lib/components/UTValidation/index.js +26 -4
- package/lib/constants/testIds.js +44 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [1.48.0](https://github.com/widergy/mobile-ui/compare/v1.47.0...v1.48.0) (2025-06-02)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* [AUT-706] auth test ids history ([#437](https://github.com/widergy/mobile-ui/issues/437)) ([928bf83](https://github.com/widergy/mobile-ui/commit/928bf8311b5c6cea9c249ef4a7f96a735b756d50)), closes [#436](https://github.com/widergy/mobile-ui/issues/436)
|
|
7
|
+
|
|
1
8
|
# [1.47.0](https://github.com/widergy/mobile-ui/compare/v1.46.1...v1.47.0) (2025-05-28)
|
|
2
9
|
|
|
3
10
|
|
|
@@ -4,24 +4,46 @@ One line height small label to show helper text and errors below inputs.
|
|
|
4
4
|
|
|
5
5
|
### Props
|
|
6
6
|
|
|
7
|
+
| NAME | TYPE | REQUIRED | DESCRIPTION |
|
|
8
|
+
| ---------- | -------------- | -------- | ----------------------------------------------- |
|
|
9
|
+
| children | string | No | Helper message to show. |
|
|
10
|
+
| dataTestId | string | No | Test ID for automated testing. |
|
|
11
|
+
| error | string or bool | No | If a not empty string, show this message error. |
|
|
12
|
+
| style | textStyleProp | No | Styles to add to the label. |
|
|
7
13
|
|
|
8
|
-
|
|
9
|
-
| --- | --- | --- | --- |
|
|
10
|
-
| children | string | No | Helper message to show. |
|
|
11
|
-
| error | string or bool | No | If a not empty string, show this message error. |
|
|
12
|
-
| style | textStyleProp | No | Styles to add to the label. |
|
|
14
|
+
## Test IDs
|
|
13
15
|
|
|
16
|
+
When `dataTestId` is provided, the component applies the test ID to its element:
|
|
14
17
|
|
|
18
|
+
| Element | Test ID | Condition |
|
|
19
|
+
| ------- | --------------- | --------------------------------- |
|
|
20
|
+
| Label | `${dataTestId}` | Always when `dataTestId` provided |
|
|
15
21
|
|
|
22
|
+
### Test ID Details
|
|
23
|
+
|
|
24
|
+
- **Label**: The main caption text element that displays helper text or error messages
|
|
25
|
+
|
|
26
|
+
The CaptionLabel component applies the test ID directly to its root text element, making it easy to identify and interact with in automated tests.
|
|
16
27
|
|
|
17
28
|
#### Example
|
|
18
29
|
|
|
19
30
|
```js
|
|
20
31
|
<View>
|
|
21
32
|
<TextInput onSubmit={this.handleSubmit} />
|
|
22
|
-
<CaptionLabel error={error}>
|
|
23
|
-
{helperText}
|
|
24
|
-
</CaptionLabel>
|
|
33
|
+
<CaptionLabel error={error}>{helperText}</CaptionLabel>
|
|
25
34
|
</View>
|
|
26
35
|
```
|
|
27
36
|
|
|
37
|
+
#### Example with Test IDs
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
<View>
|
|
41
|
+
<TextInput onSubmit={this.handleSubmit} />
|
|
42
|
+
<CaptionLabel dataTestId="emailHelper" error={emailError}>
|
|
43
|
+
{emailHelperText}
|
|
44
|
+
</CaptionLabel>
|
|
45
|
+
</View>
|
|
46
|
+
|
|
47
|
+
// Generated test IDs:
|
|
48
|
+
// emailHelper (caption label text)
|
|
49
|
+
```
|
|
@@ -5,9 +5,10 @@ import Label from '../Label';
|
|
|
5
5
|
import constants from './constants';
|
|
6
6
|
import propTypes from './propTypes';
|
|
7
7
|
|
|
8
|
-
const CaptionLabel = ({ color, children, error, errorColor, style, textProps }) => (
|
|
8
|
+
const CaptionLabel = ({ color, children, dataTestId, error, errorColor, style, textProps }) => (
|
|
9
9
|
<Label
|
|
10
10
|
color={!error ? color : errorColor}
|
|
11
|
+
dataTestId={dataTestId}
|
|
11
12
|
error={error && !errorColor}
|
|
12
13
|
primary={!error && !color}
|
|
13
14
|
xsmall
|
|
@@ -1,40 +1,108 @@
|
|
|
1
1
|
# Checkbox
|
|
2
2
|
|
|
3
|
+
**⚠️ DEPRECATION WARNING:** The Checkbox component is deprecated and will be removed in a future release. Please use the UTCheckBox component instead.
|
|
4
|
+
|
|
3
5
|
## Checkbox
|
|
4
6
|
|
|
5
7
|
Simple, presentational checkbox component. Supports a label and sublabel text.
|
|
6
8
|
|
|
7
9
|
### Props
|
|
8
10
|
|
|
9
|
-
| NAME | TYPE
|
|
10
|
-
|
|
|
11
|
-
| LabelComponent | node
|
|
12
|
-
| boldLabel | bool
|
|
13
|
-
| boldSublabel | bool
|
|
14
|
-
| checked | bool
|
|
15
|
-
| checkedColor | string
|
|
16
|
-
| checkedLabelColor | string
|
|
17
|
-
| checkedSublabelColor | string
|
|
18
|
-
| coloredText | bool
|
|
19
|
-
|
|
|
20
|
-
|
|
|
21
|
-
|
|
|
22
|
-
|
|
|
23
|
-
|
|
|
24
|
-
|
|
|
25
|
-
|
|
|
26
|
-
|
|
|
27
|
-
|
|
|
28
|
-
|
|
|
29
|
-
|
|
|
30
|
-
|
|
|
31
|
-
|
|
|
32
|
-
|
|
|
11
|
+
| NAME | TYPE | REQUIRED | DESCRIPTION |
|
|
12
|
+
| ---------------------- | --------- | -------- | -------------------------------------------------------------------------------------------- |
|
|
13
|
+
| LabelComponent | node | No | Component to use to override LabelComponent (it will receive label text as children). |
|
|
14
|
+
| boldLabel | bool | No | If the checkbox is checked, sets label text to bold. |
|
|
15
|
+
| boldSublabel | bool | No | If the checkbox is checked, sets sublabel text to bold. |
|
|
16
|
+
| checked | bool | Yes | Toggles the checkbox between checked and unchecked. |
|
|
17
|
+
| checkedColor | string | No | Color for the checkbox when checked and not disabled. |
|
|
18
|
+
| checkedLabelColor | string | No | Color for the checkbox label when checked and `coloredText` is true and not disabled. |
|
|
19
|
+
| checkedSublabelColor | string | No | Color for the checkbox sublabel when checked and `coloredText` is true and not disabled. |
|
|
20
|
+
| coloredText | bool | No | Text should be colored. |
|
|
21
|
+
| dataTestId | string | No | Unique identifier for testing purposes. Creates hierarchical test IDs for child elements. |
|
|
22
|
+
| disabled | bool | No | Checkbox should be disabled. |
|
|
23
|
+
| effectColor | string | No | Effect color for the touchable. |
|
|
24
|
+
| iconSize | number | No | Size for the icon. |
|
|
25
|
+
| iconStyle | ViewStyle | No | Styles for the icon. |
|
|
26
|
+
| label | string | Yes | Label text shown besides the checkbox. |
|
|
27
|
+
| onPress | func | Yes | Callback function to pass to the `Touchable`. |
|
|
28
|
+
| reversed | bool | No | Checkbox should have labels before the icon. |
|
|
29
|
+
| uncheckedColor | string | No | Color for the checkbox when not checked and not disabled. |
|
|
30
|
+
| uncheckedLabelColor | string | No | Color for the checkbox label when not checked and `coloredText` is true and not disabled. |
|
|
31
|
+
| uncheckedSublabelColor | string | No | Color for the checkbox sublabel when not checked and `coloredText` is true and not disabled. |
|
|
32
|
+
| style | ViewStyle | No | Optional styles to be applied to the checkbox item container. |
|
|
33
|
+
| subLabel | string | No | Smaller text shown below the label. |
|
|
34
|
+
| disabledCheckedColor | string | No | color for disabled checked icon |
|
|
35
|
+
| textProps | object | No | labels textProps |
|
|
36
|
+
|
|
33
37
|
#### Example
|
|
34
38
|
|
|
35
39
|
```js
|
|
36
40
|
import React from 'react';
|
|
37
41
|
import { Checkbox } from '@widergy/mobile-ui';
|
|
38
42
|
|
|
39
|
-
<Checkbox onPress={this.handleOnPress} checked={checked} label={label} subLabel={subLabel}
|
|
43
|
+
<Checkbox onPress={this.handleOnPress} checked={checked} label={label} subLabel={subLabel} />;
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Testing
|
|
47
|
+
|
|
48
|
+
The `Checkbox` component supports comprehensive test ID assignment through the `dataTestId` prop. When provided, it creates a hierarchical structure of test IDs for all interactive and meaningful elements.
|
|
49
|
+
|
|
50
|
+
### Test ID Structure
|
|
51
|
+
|
|
52
|
+
When you provide `dataTestId="provided.testId"`, the following test IDs are automatically generated:
|
|
53
|
+
|
|
54
|
+
| Element | Test ID | When Available |
|
|
55
|
+
| ------------------ | -------------------------- | --------------------------------------------------------- |
|
|
56
|
+
| Checkbox container | `provided.testId` | Always (when dataTestId is provided) |
|
|
57
|
+
| Checkbox icon | `provided.testId.icon` | Always (when dataTestId is provided) |
|
|
58
|
+
| Label text | `provided.testId.label` | When label prop is provided and no LabelComponent is used |
|
|
59
|
+
| Sub-label text | `provided.testId.subLabel` | When subLabel prop is provided |
|
|
60
|
+
|
|
61
|
+
**Note:** When using a custom `LabelComponent`, the `dataTestId` is not automatically passed to it. Use the `textProps` prop to pass custom test IDs to your custom label component.
|
|
62
|
+
|
|
63
|
+
### Example Usage
|
|
64
|
+
|
|
65
|
+
```jsx
|
|
66
|
+
// Basic test ID usage
|
|
67
|
+
<Checkbox
|
|
68
|
+
dataTestId="privacyCheckbox"
|
|
69
|
+
checked={privacyAccepted}
|
|
70
|
+
onPress={() => setPrivacyAccepted(!privacyAccepted)}
|
|
71
|
+
label="I accept the privacy policy"
|
|
72
|
+
/>
|
|
73
|
+
|
|
74
|
+
// Creates the following test IDs:
|
|
75
|
+
// - privacyCheckbox (main container)
|
|
76
|
+
// - privacyCheckbox.icon (checkbox icon)
|
|
77
|
+
// - privacyCheckbox.label (label text)
|
|
78
|
+
|
|
79
|
+
// With sub-label
|
|
80
|
+
<Checkbox
|
|
81
|
+
dataTestId="newsletterCheckbox"
|
|
82
|
+
checked={subscribed}
|
|
83
|
+
onPress={() => setSubscribed(!subscribed)}
|
|
84
|
+
label="Subscribe to newsletter"
|
|
85
|
+
subLabel="Get weekly updates and promotions"
|
|
86
|
+
/>
|
|
87
|
+
|
|
88
|
+
// Creates test IDs:
|
|
89
|
+
// - newsletterCheckbox
|
|
90
|
+
// - newsletterCheckbox.icon
|
|
91
|
+
// - newsletterCheckbox.label
|
|
92
|
+
// - newsletterCheckbox.subLabel
|
|
93
|
+
|
|
94
|
+
// With custom LabelComponent
|
|
95
|
+
<Checkbox
|
|
96
|
+
dataTestId="customCheckbox"
|
|
97
|
+
checked={customChecked}
|
|
98
|
+
onPress={() => setCustomChecked(!customChecked)}
|
|
99
|
+
LabelComponent={CustomLabel}
|
|
100
|
+
label="Custom label text"
|
|
101
|
+
textProps={{ dataTestId: "customCheckbox.customLabel" }}
|
|
102
|
+
/>
|
|
103
|
+
|
|
104
|
+
// Creates test IDs:
|
|
105
|
+
// - customCheckbox (main container)
|
|
106
|
+
// - customCheckbox.icon (checkbox icon)
|
|
107
|
+
// - customCheckbox.customLabel (passed via textProps to CustomLabel)
|
|
40
108
|
```
|
|
@@ -5,11 +5,14 @@ import Label from '../Label';
|
|
|
5
5
|
import Icon from '../Icon';
|
|
6
6
|
import Touchable from '../Touchable';
|
|
7
7
|
import { withTheme } from '../../theming';
|
|
8
|
+
import { TEST_ID_CONSTANTS } from '../../constants/testIds';
|
|
8
9
|
|
|
9
10
|
import propTypes from './propTypes';
|
|
10
11
|
import styles from './styles';
|
|
11
12
|
import { CHECKED_ICON, UNCHECKED_ICON } from './constants';
|
|
12
13
|
|
|
14
|
+
const { label: labelTestId, subLabel: subLabelTestId, icon } = TEST_ID_CONSTANTS;
|
|
15
|
+
|
|
13
16
|
const Checkbox = ({
|
|
14
17
|
LabelComponent,
|
|
15
18
|
backgroundColor,
|
|
@@ -20,6 +23,7 @@ const Checkbox = ({
|
|
|
20
23
|
checkedLabelColor,
|
|
21
24
|
checkedSublabelColor,
|
|
22
25
|
coloredText,
|
|
26
|
+
dataTestId,
|
|
23
27
|
disabled,
|
|
24
28
|
effectColor,
|
|
25
29
|
iconSize,
|
|
@@ -42,6 +46,7 @@ const Checkbox = ({
|
|
|
42
46
|
const RenderComponent = children || (
|
|
43
47
|
<View style={[styles.containerLabel, labelsContainerStyle]}>
|
|
44
48
|
<Component
|
|
49
|
+
{...(!LabelComponent && dataTestId && { dataTestId: `${dataTestId}.${labelTestId}` })}
|
|
45
50
|
bold={checked && boldLabel}
|
|
46
51
|
color={coloredText && (checked ? checkedLabelColor || theme.colors.primary : uncheckedLabelColor)}
|
|
47
52
|
disabled={disabled}
|
|
@@ -52,6 +57,7 @@ const Checkbox = ({
|
|
|
52
57
|
</Component>
|
|
53
58
|
{!!subLabel && (
|
|
54
59
|
<Label
|
|
60
|
+
dataTestId={dataTestId ? `${dataTestId}.${subLabelTestId}` : undefined}
|
|
55
61
|
bold={checked && boldSublabel}
|
|
56
62
|
color={coloredText && (checked ? checkedSublabelColor : uncheckedSublabelColor)}
|
|
57
63
|
disabled={disabled}
|
|
@@ -63,9 +69,16 @@ const Checkbox = ({
|
|
|
63
69
|
</View>
|
|
64
70
|
);
|
|
65
71
|
return (
|
|
66
|
-
<Touchable
|
|
72
|
+
<Touchable
|
|
73
|
+
dataTestId={dataTestId}
|
|
74
|
+
disabled={disabled}
|
|
75
|
+
effectColor={effectColor}
|
|
76
|
+
onPress={onPress}
|
|
77
|
+
style={{ backgroundColor }}
|
|
78
|
+
>
|
|
67
79
|
<View style={[styles.container, reversed ? styles.containerReversed : styles.containerDefault, style]}>
|
|
68
80
|
<Icon
|
|
81
|
+
testID={dataTestId ? `${dataTestId}.${icon}` : undefined}
|
|
69
82
|
color={
|
|
70
83
|
disabled
|
|
71
84
|
? disabledCheckedColor || theme.colors.disabled
|
|
@@ -12,6 +12,7 @@ import propTypes from './propTypes';
|
|
|
12
12
|
const Label = ({
|
|
13
13
|
children,
|
|
14
14
|
color,
|
|
15
|
+
dataTestId,
|
|
15
16
|
style,
|
|
16
17
|
textProps,
|
|
17
18
|
theme,
|
|
@@ -59,7 +60,7 @@ const Label = ({
|
|
|
59
60
|
};
|
|
60
61
|
}, [allowFontScaling, children, onLinkPress, textProps, theme.allowFontScaling, useMarkdown]);
|
|
61
62
|
|
|
62
|
-
return <LabelRenderer style={styles} {...propsByComponent} {...props} />;
|
|
63
|
+
return <LabelRenderer style={styles} testID={dataTestId} {...propsByComponent} {...props} />;
|
|
63
64
|
};
|
|
64
65
|
|
|
65
66
|
Label.displayName = 'Label';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { Component, Fragment } from 'react';
|
|
2
2
|
import { ViewPropTypes } from 'deprecated-react-native-prop-types';
|
|
3
3
|
import { View } from 'react-native';
|
|
4
|
-
import
|
|
4
|
+
import { bool, func, node, number, object, oneOfType, shape, string } from 'prop-types';
|
|
5
5
|
|
|
6
6
|
import { withTheme, themeType } from '../../../../theming';
|
|
7
7
|
import Icon from '../../../Icon';
|
|
@@ -21,6 +21,7 @@ class RadioButton extends Component {
|
|
|
21
21
|
|
|
22
22
|
render() {
|
|
23
23
|
const {
|
|
24
|
+
dataTestId,
|
|
24
25
|
status,
|
|
25
26
|
style,
|
|
26
27
|
label,
|
|
@@ -35,12 +36,17 @@ class RadioButton extends Component {
|
|
|
35
36
|
} = this.props;
|
|
36
37
|
return (
|
|
37
38
|
<Fragment>
|
|
38
|
-
<Touchable
|
|
39
|
+
<Touchable
|
|
40
|
+
dataTestId={dataTestId ? `${dataTestId}` : undefined}
|
|
41
|
+
onPress={this.handlePress}
|
|
42
|
+
disabled={disabled}
|
|
43
|
+
>
|
|
39
44
|
<View style={[styles.container, style]}>
|
|
40
45
|
{descriptionComponent ? (
|
|
41
46
|
<View style={styles.descriptionComponentContainer}>
|
|
42
47
|
{descriptionComponent}
|
|
43
48
|
<Icon
|
|
49
|
+
testID={dataTestId ? `${dataTestId}.icon` : undefined}
|
|
44
50
|
name={status ? RADIO_CHECKED_ICON : RADIO_UNCHECKED_ICON}
|
|
45
51
|
color={theme.colors.primary}
|
|
46
52
|
style={styles.iconSpacing}
|
|
@@ -50,6 +56,7 @@ class RadioButton extends Component {
|
|
|
50
56
|
) : (
|
|
51
57
|
<Fragment>
|
|
52
58
|
<Icon
|
|
59
|
+
testID={dataTestId ? `${dataTestId}.icon` : undefined}
|
|
53
60
|
name={status ? RADIO_CHECKED_ICON : RADIO_UNCHECKED_ICON}
|
|
54
61
|
color={status ? theme.colors.primary : theme.colors.disabled}
|
|
55
62
|
style={styles.iconSpacing}
|
|
@@ -59,6 +66,7 @@ class RadioButton extends Component {
|
|
|
59
66
|
<View>
|
|
60
67
|
<View style={[styles.label, labelComponent && styles.labelComponent]}>
|
|
61
68
|
<UTLabel
|
|
69
|
+
dataTestId={dataTestId ? `${dataTestId}.label` : undefined}
|
|
62
70
|
variant="xsmall"
|
|
63
71
|
weight={status ? 'bold' : 'regular'}
|
|
64
72
|
{...labelContainerStyles.title}
|
|
@@ -69,6 +77,7 @@ class RadioButton extends Component {
|
|
|
69
77
|
</View>
|
|
70
78
|
{(sublabel || sublabel === 0) && (
|
|
71
79
|
<UTLabel
|
|
80
|
+
dataTestId={dataTestId ? `${dataTestId}.sublabel` : undefined}
|
|
72
81
|
colorTheme="gray"
|
|
73
82
|
variant="xsmall"
|
|
74
83
|
weight={status ? 'bold' : 'regular'}
|
|
@@ -81,6 +90,7 @@ class RadioButton extends Component {
|
|
|
81
90
|
</View>
|
|
82
91
|
{labelValue && (
|
|
83
92
|
<UTLabel
|
|
93
|
+
dataTestId={dataTestId ? `${dataTestId}.labelValue` : undefined}
|
|
84
94
|
colorTheme={status ? 'accent' : 'dark'}
|
|
85
95
|
variant="small"
|
|
86
96
|
weight={status ? 'bold' : 'regular'}
|
|
@@ -99,25 +109,26 @@ class RadioButton extends Component {
|
|
|
99
109
|
}
|
|
100
110
|
|
|
101
111
|
RadioButton.propTypes = {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
112
|
+
dataTestId: string,
|
|
113
|
+
label: string.isRequired,
|
|
114
|
+
sublabel: oneOfType([string, number]),
|
|
115
|
+
labelValue: oneOfType([string, number]),
|
|
116
|
+
onPress: func.isRequired,
|
|
117
|
+
status: bool,
|
|
118
|
+
style: ViewPropTypes,
|
|
119
|
+
option: shape({
|
|
120
|
+
label: string.isRequired,
|
|
121
|
+
sublabel: string
|
|
111
122
|
}),
|
|
112
123
|
theme: themeType,
|
|
113
|
-
labelComponent:
|
|
114
|
-
labelContainerStyles:
|
|
115
|
-
title:
|
|
116
|
-
subtitle:
|
|
124
|
+
labelComponent: node,
|
|
125
|
+
labelContainerStyles: shape({
|
|
126
|
+
title: object,
|
|
127
|
+
subtitle: object
|
|
117
128
|
}),
|
|
118
|
-
descriptionComponent:
|
|
119
|
-
showSeparatorBar:
|
|
120
|
-
disabled:
|
|
129
|
+
descriptionComponent: node,
|
|
130
|
+
showSeparatorBar: bool,
|
|
131
|
+
disabled: bool
|
|
121
132
|
};
|
|
122
133
|
|
|
123
134
|
export default withTheme(RadioButton);
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import React, { Component } from 'react';
|
|
2
2
|
import { ViewPropTypes } from 'deprecated-react-native-prop-types';
|
|
3
3
|
import { View } from 'react-native';
|
|
4
|
-
import PropTypes from 'prop-types';
|
|
4
|
+
import PropTypes, { string } from 'prop-types';
|
|
5
5
|
|
|
6
6
|
import UTLabel from '../UTLabel';
|
|
7
|
+
import { TEST_ID_CONSTANTS } from '../../constants/testIds';
|
|
7
8
|
|
|
8
9
|
import RadioButton from './components/RadioButton';
|
|
9
10
|
import { DEFAULT_KEY_FIELD } from './constants';
|
|
10
11
|
import styles from './styles';
|
|
11
12
|
|
|
13
|
+
const { title: titleTestId, error: errorTestId } = TEST_ID_CONSTANTS;
|
|
14
|
+
|
|
12
15
|
class RadioGroup extends Component {
|
|
13
16
|
handleOptionSelected = option => {
|
|
14
17
|
const { onOptionChange, keyField } = this.props;
|
|
@@ -16,10 +19,11 @@ class RadioGroup extends Component {
|
|
|
16
19
|
};
|
|
17
20
|
|
|
18
21
|
renderOptions = option => {
|
|
19
|
-
const { selectedOption, radioProps, keyField, disabled } = this.props;
|
|
22
|
+
const { selectedOption, radioProps, keyField, disabled, dataTestId } = this.props;
|
|
20
23
|
return (
|
|
21
24
|
<RadioButton
|
|
22
25
|
style={styles.radio}
|
|
26
|
+
dataTestId={dataTestId ? `${dataTestId}.radioButton_${option.id}` : undefined}
|
|
23
27
|
option={option}
|
|
24
28
|
key={option.id}
|
|
25
29
|
label={option.label}
|
|
@@ -36,18 +40,27 @@ class RadioGroup extends Component {
|
|
|
36
40
|
};
|
|
37
41
|
|
|
38
42
|
render() {
|
|
39
|
-
const { title, options, titleProps, error } = this.props;
|
|
43
|
+
const { title, options, titleProps, error, dataTestId } = this.props;
|
|
40
44
|
return (
|
|
41
45
|
<View style={styles.container}>
|
|
42
46
|
{title && (
|
|
43
47
|
<View style={styles.titleContainer}>
|
|
44
|
-
<UTLabel
|
|
48
|
+
<UTLabel
|
|
49
|
+
dataTestId={dataTestId ? `${dataTestId}.${titleTestId}` : undefined}
|
|
50
|
+
variant="medium"
|
|
51
|
+
{...titleProps}
|
|
52
|
+
>
|
|
45
53
|
{title}
|
|
46
54
|
</UTLabel>
|
|
47
55
|
</View>
|
|
48
56
|
)}
|
|
49
57
|
{options.map(this.renderOptions)}
|
|
50
|
-
<UTLabel
|
|
58
|
+
<UTLabel
|
|
59
|
+
dataTestId={dataTestId ? `${dataTestId}.${errorTestId}` : undefined}
|
|
60
|
+
colorTheme="error"
|
|
61
|
+
shade="05"
|
|
62
|
+
variant="body"
|
|
63
|
+
>
|
|
51
64
|
{error}
|
|
52
65
|
</UTLabel>
|
|
53
66
|
</View>
|
|
@@ -57,6 +70,7 @@ class RadioGroup extends Component {
|
|
|
57
70
|
|
|
58
71
|
RadioGroup.propTypes = {
|
|
59
72
|
title: PropTypes.string.isRequired,
|
|
73
|
+
dataTestId: string,
|
|
60
74
|
error: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
|
|
61
75
|
options: PropTypes.arrayOf(
|
|
62
76
|
PropTypes.shape({
|
|
@@ -7,7 +7,7 @@ import { withTheme } from '../../theming';
|
|
|
7
7
|
import styles, { getEffectColor } from './styles';
|
|
8
8
|
import propTypes from './propTypes';
|
|
9
9
|
|
|
10
|
-
const Touchable = ({ borderless, children, disabled, onPress, style, theme, ...props }) => {
|
|
10
|
+
const Touchable = ({ borderless, children, dataTestId, disabled, onPress, style, theme, ...props }) => {
|
|
11
11
|
const useForeground = USE_FOREGROUND && borderless; // Workaround for ripple on Android Pie (https://github.com/facebook/react-native/issues/6480)
|
|
12
12
|
const isDisabled = disabled || !onPress;
|
|
13
13
|
const { effectColor } = getEffectColor(props, theme);
|
|
@@ -22,6 +22,7 @@ const Touchable = ({ borderless, children, disabled, onPress, style, theme, ...p
|
|
|
22
22
|
<TouchableNativeFeedback
|
|
23
23
|
{...props}
|
|
24
24
|
background={TouchableNativeFeedback.Ripple(effectColor, borderless)}
|
|
25
|
+
testID={dataTestId}
|
|
25
26
|
delayPressIn={0}
|
|
26
27
|
delayPressOut={0}
|
|
27
28
|
disabled={isDisabled}
|
|
@@ -37,6 +38,7 @@ const Touchable = ({ borderless, children, disabled, onPress, style, theme, ...p
|
|
|
37
38
|
{...props}
|
|
38
39
|
delayPressIn={0}
|
|
39
40
|
delayPressOut={0}
|
|
41
|
+
testID={dataTestId}
|
|
40
42
|
disabled={isDisabled}
|
|
41
43
|
onPress={onPress}
|
|
42
44
|
style={[borderless && styles.borderless, style]}
|
|
@@ -8,7 +8,7 @@ import UTLabel from '../UTLabel';
|
|
|
8
8
|
import { DEFAULT_PROPS } from './constants';
|
|
9
9
|
import { retrieveStyle } from './theme';
|
|
10
10
|
|
|
11
|
-
const UTBadge = ({ children, colorTheme, style }) => {
|
|
11
|
+
const UTBadge = ({ children, colorTheme, dataTestId, style }) => {
|
|
12
12
|
const theme = useTheme();
|
|
13
13
|
|
|
14
14
|
const classes = retrieveStyle({ theme, children, colorTheme });
|
|
@@ -16,6 +16,7 @@ const UTBadge = ({ children, colorTheme, style }) => {
|
|
|
16
16
|
return (
|
|
17
17
|
<Component
|
|
18
18
|
colorTheme={classes.textColorTheme}
|
|
19
|
+
{...(children ? { dataTestId } : { testID: dataTestId })}
|
|
19
20
|
style={[classes.root, style]}
|
|
20
21
|
variant="xsmall"
|
|
21
22
|
weight="medium"
|
|
@@ -30,6 +31,7 @@ UTBadge.defaultProps = DEFAULT_PROPS;
|
|
|
30
31
|
UTBadge.propTypes = {
|
|
31
32
|
children: oneOfType([string, number]),
|
|
32
33
|
colorTheme: string,
|
|
34
|
+
dataTestId: string,
|
|
33
35
|
style: object
|
|
34
36
|
};
|
|
35
37
|
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
| alwaysShowPlaceholder | bool | false | Whether to always show the placeholder text, even when the field is focused. |
|
|
12
12
|
| autoCapitalize | oneOf('none','sentences','words','characters') | 'sentences' | Defines how to automatically capitalize certain characters. |
|
|
13
13
|
| blurOnSubmit | bool | | If true, the input will be blurred when the user submits the text. |
|
|
14
|
+
| dataTestId | string | | Test ID for automated testing. Enables hierarchical test ID structure. |
|
|
14
15
|
| disabled | bool | | Whether the input field is disabled. |
|
|
15
16
|
| editable | bool | true | Whether the input field is editable. If false, it behaves like a disabled field. |
|
|
16
17
|
| error | oneOfType([bool, string]) | | Error message to display, or `true` to indicate an error state without a message. |
|
|
@@ -33,6 +34,28 @@
|
|
|
33
34
|
| type | string | | Type of the input field (e.g., text, email, numeric, password). |
|
|
34
35
|
| variant | string | 'white' | Variant of the input field. One of: `white`, `gray`. |
|
|
35
36
|
|
|
37
|
+
## Test IDs
|
|
38
|
+
|
|
39
|
+
When `dataTestId` is provided, the component creates a hierarchical test ID structure:
|
|
40
|
+
|
|
41
|
+
| Element | Test ID | Condition |
|
|
42
|
+
| ---------------- | ------------------------------ | --------------------------------- |
|
|
43
|
+
| Input field | `${dataTestId}` | Always when `dataTestId` provided |
|
|
44
|
+
| Left adornments | `${dataTestId}.left` | When left adornments are present |
|
|
45
|
+
| Right adornments | `${dataTestId}.right` | When right adornments are present |
|
|
46
|
+
| Character count | `${dataTestId}.characterCount` | When `showCharacterCount` is true |
|
|
47
|
+
|
|
48
|
+
### Test ID Structure Details
|
|
49
|
+
|
|
50
|
+
- **Input field**: The main TextInput element gets the base `dataTestId`
|
|
51
|
+
- **Left adornments**: All left-side adornments share the `.left` test ID
|
|
52
|
+
- **Right adornments**: All right-side adornments share the `.right` test ID
|
|
53
|
+
- **Character count**: The character count display when enabled
|
|
54
|
+
|
|
55
|
+
### Adornment Test IDs
|
|
56
|
+
|
|
57
|
+
Individual adornments within the left/right containers inherit the adornment test ID and may create their own hierarchical structure based on their component type (e.g., UTIcon, UTButton, etc.).
|
|
58
|
+
|
|
36
59
|
## Input Types
|
|
37
60
|
|
|
38
61
|
The `type` prop can be one of these values:
|
|
@@ -176,31 +199,30 @@ Displays a tooltip with an icon.
|
|
|
176
199
|
<UTBaseInputField rightAdornments={[{ name: 'Tooltip', props: { tooltip: 'Tooltip Text' } }]} />
|
|
177
200
|
```
|
|
178
201
|
|
|
179
|
-
### Example
|
|
202
|
+
### Example with Test IDs
|
|
180
203
|
|
|
181
204
|
```javascript
|
|
182
|
-
//
|
|
183
|
-
<UTBaseInputField
|
|
184
|
-
leftAdornments={[{ name: 'Prefix', props: { text: 'Prefix Text' } }]}
|
|
185
|
-
/>
|
|
186
|
-
|
|
187
|
-
// Example of SuffixAdornment usage
|
|
188
|
-
<UTBaseInputField
|
|
189
|
-
rightAdornments={[{ name: 'Suffix', props: { text: 'Suffix Text' } }]}
|
|
190
|
-
/>
|
|
191
|
-
|
|
192
|
-
// Example of IconAdornment usage
|
|
205
|
+
// Basic input with test ID
|
|
193
206
|
<UTBaseInputField
|
|
194
|
-
|
|
207
|
+
dataTestId="userEmail"
|
|
208
|
+
placeholder="Enter your email"
|
|
209
|
+
type="email"
|
|
195
210
|
/>
|
|
196
211
|
|
|
197
|
-
//
|
|
212
|
+
// Input with adornments and test IDs
|
|
198
213
|
<UTBaseInputField
|
|
199
|
-
|
|
214
|
+
dataTestId="searchField"
|
|
215
|
+
placeholder="Search products..."
|
|
216
|
+
leftAdornments={[{ name: 'Icon', props: { Icon: 'IconSearch' } }]}
|
|
217
|
+
rightAdornments={[{ name: 'Action', props: { action: { text: 'Search', onPress: handleSearch } } }]}
|
|
218
|
+
showCharacterCount
|
|
219
|
+
maxLength={100}
|
|
200
220
|
/>
|
|
201
221
|
|
|
202
|
-
//
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
222
|
+
// Generated test IDs:
|
|
223
|
+
// userEmail (input field)
|
|
224
|
+
// searchField (input field)
|
|
225
|
+
// searchField.left (left adornments container)
|
|
226
|
+
// searchField.right (right adornments container)
|
|
227
|
+
// searchField.characterCount (character count display)
|
|
206
228
|
```
|