Skip to content

Commit e571d71

Browse files
feat(android): add testID support to date (not time) picker (#705)
* add testid support * switch tests to use testID for picker * adjust docs to explain testID working on android * remove accidental var * fix accidentally broken matcher * Rephrase testID docs to be more generic instad of focused on detox * docs: review --------- Co-authored-by: Maurice Döpke <mauricedoepkeoutlook.de> Co-authored-by: Vojtech Novak <[email protected]>
1 parent 4bd4586 commit e571d71

File tree

10 files changed

+30
-3
lines changed

10 files changed

+30
-3
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,15 @@ Alternatively, use the `themeVariant` prop.
517517

518518
If true, the user won't be able to interact with the view.
519519

520+
#### `testID` (`optional`)
521+
522+
Usually used by app automation frameworks.
523+
Fully supported on iOS. On Android, only supported for `mode="date"`.
524+
525+
```js
526+
<RNDateTimePicker testID="datePicker" />
527+
```
528+
520529
#### `View Props` (`optional`, `iOS only`)
521530

522531
On iOS, you can pass any [View props](https://reactnative.dev/docs/view#props) to the component. Given that the underlying component is a native view, not all of them are guaranteed to be supported, but `testID` and `onLayout` are known to work.

android/src/main/java/com/reactcommunity/rndatetimepicker/DatePickerModule.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@ public void dismiss(Promise promise) {
135135
* <li>
136136
* {@code display} To set the date picker display to 'calendar/spinner/default'
137137
* </li>
138+
* <li>
139+
* {@code testID} testID for testing with e.g. detox.
140+
* </li>
138141
* </ul>
139142
*
140143
* @param promise This will be invoked with parameters action, year,
@@ -198,6 +201,9 @@ private Bundle createFragmentArguments(ReadableMap options) {
198201
if (options.hasKey(RNConstants.ARG_TZOFFSET_MINS) && !options.isNull(RNConstants.ARG_TZOFFSET_MINS)) {
199202
args.putLong(RNConstants.ARG_TZOFFSET_MINS, (long) options.getDouble(RNConstants.ARG_TZOFFSET_MINS));
200203
}
204+
if (options.hasKey(RNConstants.ARG_TESTID) && !options.isNull(RNConstants.ARG_TESTID)) {
205+
args.putString(RNConstants.ARG_TESTID, options.getString(RNConstants.ARG_TESTID));
206+
}
201207
return args;
202208
}
203209
}

android/src/main/java/com/reactcommunity/rndatetimepicker/RNConstants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public final class RNConstants {
1212
public static final String ARG_DISPLAY = "display";
1313
public static final String ARG_DIALOG_BUTTONS = "dialogButtons";
1414
public static final String ARG_TZOFFSET_MINS = "timeZoneOffsetInMinutes";
15+
public static final String ARG_TESTID = "testID";
1516
public static final String ACTION_DATE_SET = "dateSetAction";
1617
public static final String ACTION_TIME_SET = "timeSetAction";
1718
public static final String ACTION_DISMISSED = "dismissedAction";

android/src/main/java/com/reactcommunity/rndatetimepicker/RNDatePickerDialogFragment.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,10 @@ private DatePickerDialog createDialog(Bundle args) {
145145
datePicker.setOnDateChangedListener(new KeepDateInRangeListener(args));
146146
}
147147

148+
if (args != null && args.containsKey(RNConstants.ARG_TESTID)) {
149+
datePicker.setTag(args.getString(RNConstants.ARG_TESTID));
150+
}
151+
148152
return dialog;
149153
}
150154

example/e2e/detoxTest.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ describe('e2e tests', () => {
7474
const calendarHorizontalScrollView = element(
7575
by
7676
.type('android.widget.ScrollView')
77-
.withAncestor(by.type('android.widget.DatePicker')),
77+
.withAncestor(by.id('dateTimePicker')),
7878
);
7979
await calendarHorizontalScrollView.swipe('left', 'fast', 1);
8080
await calendarHorizontalScrollView.tap({x: 50, y: 200});

example/e2e/utils/matchers.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ const getInlineTimePickerIOS = () => element(by.label('Time Picker'));
1010

1111
const getDateTimePickerControlIOS = () => element(by.type('UIDatePicker'));
1212

13-
const getDatePickerAndroid = () =>
14-
element(by.type('android.widget.DatePicker'));
13+
const getDatePickerAndroid = () => element(by.id('dateTimePicker'));
1514

1615
module.exports = {
1716
getTimeText,

src/DateTimePickerAndroid.android.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ function open(props: AndroidNativeProps) {
4444
neutralButtonLabel,
4545
positiveButtonLabel,
4646
negativeButtonLabel,
47+
testID,
4748
} = props;
4849
validateAndroidProps(props);
4950
invariant(originalValue, 'A date or time must be specified as `value` prop.');
@@ -84,6 +85,7 @@ function open(props: AndroidNativeProps) {
8485
minuteInterval,
8586
timeZoneOffsetInMinutes,
8687
dialogButtons,
88+
testID,
8789
});
8890

8991
switch (action) {

src/androidUtils.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ type OpenParams = {
2424
maximumDate: AndroidNativeProps['maximumDate'],
2525
minuteInterval: AndroidNativeProps['minuteInterval'],
2626
timeZoneOffsetInMinutes: AndroidNativeProps['timeZoneOffsetInMinutes'],
27+
testID: AndroidNativeProps['testID'],
2728
dialogButtons: {
2829
positive: ProcessedButton,
2930
negative: ProcessedButton,
@@ -64,6 +65,7 @@ function getOpenPicker(
6465
maximumDate,
6566
timeZoneOffsetInMinutes,
6667
dialogButtons,
68+
testID,
6769
}: OpenParams) =>
6870
// $FlowFixMe - `AbstractComponent` [1] is not an instance type.
6971
pickers[ANDROID_MODE.date].open({
@@ -73,6 +75,7 @@ function getOpenPicker(
7375
maximumDate,
7476
timeZoneOffsetInMinutes,
7577
dialogButtons,
78+
testID,
7679
});
7780
}
7881
}

src/datepicker.android.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export default class DatePickerAndroid {
2121
* - `value` (`Date` object) - date to show by default
2222
* - `minimumDate` (`Date` object) - minimum date that can be selected
2323
* - `maximumDate` (`Date` object) - maximum date that can be selected
24+
* - `testID` (`string`) - Sets view tag for use with automation frameworks
2425
* - `display` (`enum('calendar', 'spinner', 'default')`) - To set the date-picker display to calendar/spinner/default
2526
* - 'calendar': Show a date picker in calendar mode.
2627
* - 'spinner': Show a date picker in spinner mode.

src/datetimepicker.android.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export default function RNDateTimePickerAndroid(
3030
positiveButtonLabel,
3131
negativeButtonLabel,
3232
neutralButtonLabel,
33+
testID,
3334
} = props;
3435
const valueTimestamp = value.getTime();
3536

@@ -58,6 +59,7 @@ export default function RNDateTimePickerAndroid(
5859
positiveButtonLabel,
5960
negativeButtonLabel,
6061
neutralButtonLabel,
62+
testID,
6163
};
6264
DateTimePickerAndroid.open(params);
6365
},

0 commit comments

Comments
 (0)