-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(android): support setDatePickerDate #3790
feat(android): support setDatePickerDate #3790
Conversation
Looks good to me, at least at the first glance! There is some missing unit test coverage, but I hope it is trivial enough to add it. Could you post here a screenshot of the updated DatePicker screen? If you need some help or have questions, let us know. |
detox/test/e2e/17.datePicker.test.js
Outdated
|
||
//rn-datepicker does not support testId's on android, so by.type is the only way to match the datepicker right now | ||
//@see https://github.com/react-native-datetimepicker/datetimepicker#view-props-optional-ios-only | ||
await element(by.type('android.widget.DatePicker')).setDatePickerDate('2019-02-06T05:10:00-08:00', "ISO8601"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see an error like that on CI:
https://buildkite.com/wix-mobile-oss/detox/builds/1871#018563a8-6f16-438e-ac69-4f1785fe8ec3/6-4104
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Weird. It worked on my machine. One possible explanation I can think of is, that detox's auto waiting might not work well together with how android updates the datepicker value.
This might cause the test to work on some systems, but not on others due to timing issues.
I will try to use a waitFor to verify this hypothesis.
@mauricedoepke sure I'll resume tomorrow. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mauricedoepke Thank you for your contribution to the project! Your code will be a valuable addition. We appreciate your support and for taking the time to open a pull request.
detox/android/detox/src/full/java/com/wix/detox/espresso/DetoxAction.java
Outdated
Show resolved
Hide resolved
ZonedDateTime date = ZonedDateTime.parse(dateString); | ||
return PickerActions.setDate(date.getYear(), date.getMonthValue(), date.getDayOfMonth()); | ||
} | ||
date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").parse(dateString); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it work with custom time zones? +10:00
etc?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I see you changed it again . Probably this is not relevant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the Z seems to support this case.
But now that I saw your commit that removes ms in the ios implementation, I think the android implementation does not support ms either. So maybe we can generalize removing the millis in a way that it does it for both ios and android?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the android implementation does not support ms either.
Well, it does not throw errors and it passes the tests. Do you think we need any extra action items in such case? 😕 ❓
detox/test/e2e/17.datePicker.test.js
Outdated
test.each([ | ||
['ISO8601', new Date(2019, 1, 6, 14, 10, 0).toISOString()], | ||
['yyyy/MM/dd HH:mm', '2019/02/06 14:10'], | ||
])('can select dates in %j format', async (formatString, dateString) => { | ||
if (platform === 'ios') { | ||
await element(by.id('datePicker')).setDatePickerDate(dateString, formatString); | ||
await expect(element(by.id('localDateLabel'))).toHaveText('Date (Local): Feb 6th, 2019'); | ||
await expect(element(by.id('localTimeLabel'))).toHaveText('Time (Local): 2:10 PM'); | ||
} else { | ||
await element(by.id('openDatePicker')).tap(); | ||
//rn-datepicker does not support testId's on android, so by.type is the only way to match the datepicker right now | ||
//@see https://github.com/react-native-datetimepicker/datetimepicker#view-props-optional-ios-only | ||
await element(by.type('android.widget.DatePicker')).setDatePickerDate('2019-02-06T05:10:00-08:00', 'ISO8601'); | ||
await element(by.text('OK')).tap(); | ||
|
||
if(failed === false) { | ||
throw new Error('Test should have thrown an error, but did not'); | ||
await waitFor(element(by.id('utcDateLabel'))).toHaveText('Date (UTC): Feb 6th, 2019').withTimeout(3000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@noomorph
This does not test the custom pattern feature on android, does it?
Also what I learned during my local testing, when I ran the tests between 00:00 and 01:00 is that I think you have to check against:
- utc for iso datestrings or custom patterns that contain explicit timezones
- local time for patterns that don't contain patterns.
Otherwise tests can fail due to timezone errors.
The reason is when:
- using a iso string, you let the device parse the date with an explicit format. When you then display it in the local format and the local format differs from utc, you can have a day off error around midnight. When you hoever display it in utc, the results will be stable.
- using a pattern without timezone you parse it in local time. When you now display it in utc, the result can vary when the device has a non utc timezone. So in this case the result will only be stable when you also output it as local time.
As this is quite complex, I think it is easier to remove the loop, even though the resulting code duplication is not so nice.
This was my suggestion, you may have not seen it because we worked on similar times on this:
it(':ios: can select dates on a UIDatePicker, format: ISO8601', async () => {
await element(by.id('datePicker')).setDatePickerDate('2019-02-06T05:10:00-08:00', 'ISO8601');
await expect(element(by.id('utcDateLabel'))).toHaveText('Date (UTC): Feb 6th, 2019');
await expect(element(by.id('utcTimeLabel'))).toHaveText('Time (UTC): 1:10 PM');
});
it(':ios: can select dates on a UIDatePicker, format: yyyy/MM/dd HH:mm', async () => {
await element(by.id('datePicker')).setDatePickerDate('2019/02/06 13:10', 'yyyy/MM/dd HH:mm');
await expect(element(by.id('localDateLabel'))).toHaveText('Date (Local): Feb 6th, 2019');
await expect(element(by.id('localTimeLabel'))).toHaveText('Time (Local): 1:10 PM');
});
it(':android: can select dates on a UIDatePicker, format: ISO8601', async () => {
//rn-datepicker does not support testId's on android, so by.type is the only way to match the datepicker right now
//@see https://github.com/react-native-datetimepicker/datetimepicker#view-props-optional-ios-only
await element(by.type('android.widget.DatePicker')).setDatePickerDate('2019-02-06T05:10:00-08:00', 'ISO8601');
await element(by.text('OK')).tap();
await waitFor(element(by.id('utcDateLabel'))).toHaveText('Date (UTC): Feb 6th, 2019').withTimeout(3000);
});
it(':android: can select dates on a UIDatePicker, format: yyyy/MM/dd', async () => {
await element(by.type('android.widget.DatePicker')).setDatePickerDate('2019/02/06', 'yyyy/MM/dd');
await element(by.text('OK')).tap();
await waitFor(element(by.id('localDateLabel'))).toHaveText('Date (Local): Feb 6th, 2019').withTimeout(3000);
});
@jonathanmos @asafkorem @noomorph Can someone with deeper android knowledge have a look at this error?: I have no idea what this means, how to debug this or if this is even related to this pr. |
As discussed on Discord, could you remove the two androidTestImplementations of espresso-contrib and com.google.truth from examples/demo-pure-native-android/app/build.gradle? This will fix the error on buildkite. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, from my side, I see only one remaining question:
How much work is left to add time support (hh:mm:ss) for Android? Maybe we could do it now and land the complete feature? 🙏
As for the actual issues, it looks like the simple date formatter cannot handle 2023-01-11T10:41:26Z
for some reason, while it perfectly handles 2019-02-06T05:10:00-08:00
. The test fails with Unparseable date: "2023-01-11T10:41:26Z"
. The build is red 🔴 .
@jonathanmos, I'm removing myself as an assignee for now – all JavaScript-related comments from my side are resolved at the moment. Let's come up with the final resolution for that Zoned/Simple date formatter, and maybe let's cover that logic as a unit test in Java/Kotlin. Interesting that |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approving it all except for the Test Failed: Unparseable date: "2023-01-11T10:41:26Z"
issue.
Hi, I will try to also get into the loop of things here, sometime this week. |
I'm finally back into the loop of things - planning to high-prioritize this for the upcoming 2-week iteration. @mauricedoepke It's starting to seem that by getting the |
Well hopefully I've fixed the case of ISO-8601 with no time-zone. I'm nonetheless not 100% satisfied with the documentation, so I'm inclined to hold back the merge a bit longer till this gets sorted out too, even if all tests pass. |
@@ -233,6 +233,18 @@ class DetoxAction { | |||
}; | |||
} | |||
|
|||
static parseDateISO8601(dateString) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@d4vidi looks like we need to remove private
methods generation, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, we have to switch to invoke2
😄
Suggestion for a future rearchitecture: JS (node) should take on the single responsibility of converting the various formats to the unified time/date representation - which is in fact a unix time stamp. The JS will then deliver the various formats into the various native environments (android / iOS) in a unified way, and the native-side handling code will then be rendered super-simple. |
Buildkite is green after a retry --> merging. |
Description
In this pull request, I have extended the setDatePickerDate action to work on android as well.
setDatePickerDate is already working for android in this pr and I also updated one relevant test.
I have yet to investigate whether more tests need changes.
I also have yet to update the docs.
Feel free to comment on how to improve this implementation.