Skip to content
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

Merged
merged 34 commits into from
Feb 6, 2023

Conversation

mauricedoepke
Copy link
Contributor

@mauricedoepke mauricedoepke commented Dec 29, 2022

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.

For features/enhancements:

  • I have added/updated the relevant references in the documentation files.

For API changes:

  • I have made the necessary changes in the types index file.

@noomorph
Copy link
Collaborator

noomorph commented Dec 29, 2022

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.

@mauricedoepke mauricedoepke changed the title DRAFT: Add setDatePickerDate support to android Add setDatePickerDate support to android Dec 29, 2022
detox/index.d.ts Outdated Show resolved Hide resolved
docs/api/actions.md Outdated Show resolved Hide resolved
@noomorph noomorph mentioned this pull request Dec 30, 2022
3 tasks

//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");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

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.

@noomorph
Copy link
Collaborator

noomorph commented Jan 3, 2023

@mauricedoepke sure I'll resume tomorrow.

@noomorph noomorph self-assigned this Jan 3, 2023
Copy link
Contributor

@asafkorem asafkorem left a 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/index.d.ts 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);
Copy link
Collaborator

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?

Copy link
Collaborator

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.

Copy link
Contributor Author

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?

Copy link
Collaborator

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? 😕 ❓

Comment on lines 22 to 37
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);
Copy link
Contributor Author

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);
      });

@mauricedoepke
Copy link
Contributor Author

@jonathanmos @asafkorem @noomorph

Can someone with deeper android knowledge have a look at this error?:
https://buildkite.com/wix-mobile-oss/detox/builds/1889#01858831-2d65-4c42-a6b1-8ecbace27c29

I have no idea what this means, how to debug this or if this is even related to this pr.

@jonathanmos
Copy link
Contributor

@jonathanmos @asafkorem @noomorph

Can someone with deeper android knowledge have a look at this error?: https://buildkite.com/wix-mobile-oss/detox/builds/1889#01858831-2d65-4c42-a6b1-8ecbace27c29

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.

Copy link
Collaborator

@noomorph noomorph left a 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 🔴 .

@noomorph
Copy link
Collaborator

@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 2023-01-11T10:41:26Z is parsed alright on my local machine, but it fails on CI. Maybe it is an API level issue, maybe not – let's locate it.

@noomorph noomorph removed their assignment Jan 13, 2023
Copy link
Collaborator

@noomorph noomorph left a 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.

@noomorph noomorph changed the title Add setDatePickerDate support to android feat(android): support setDatePickerDate Jan 13, 2023
@d4vidi
Copy link
Collaborator

d4vidi commented Jan 16, 2023

Hi, I will try to also get into the loop of things here, sometime this week.

@d4vidi
Copy link
Collaborator

d4vidi commented Jan 29, 2023

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 Test Failed: Unparseable date: "2023-01-11T10:41:26Z" problem that @noomorph has mentioned you could be crossing the last mile for getting this thing merged ✅ 🍾
Do you think you could get around to it soon? I am likely to be here to help as needed, as I mentioned.

@d4vidi
Copy link
Collaborator

d4vidi commented Feb 2, 2023

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) {
Copy link
Collaborator

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?

Copy link
Collaborator

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 😄

@d4vidi d4vidi enabled auto-merge (squash) February 5, 2023 17:44
@d4vidi
Copy link
Collaborator

d4vidi commented Feb 5, 2023

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.

@d4vidi
Copy link
Collaborator

d4vidi commented Feb 6, 2023

Buildkite is green after a retry --> merging.

@d4vidi d4vidi disabled auto-merge February 6, 2023 09:02
@d4vidi d4vidi merged commit d34546a into wix:master Feb 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants