calabash/calabash-ios-server — pull request #23 by jmoody (2013-08-29 09:44:55+00:00)
Title: adds a change date operation for manipulating date pickers

### Motivation

Manipulating UIDatePickers using calabash-ios is difficult.

The forum is littered with questions about and problems with interacting with date pickers.

Dealing with dates is inherently complex.

* time zones
* regional date formats
* 12h/24 clocks
* timers vs clocks
* alarm time vs clock time
* minimum/maximum allow dates

Application features involving dates are often buggy making testing particularly important.

* Can my app display 12h/24h times correctly in a label when the picker is changed?
* Do my Reminders work across time zones?
* When I change the time on view X, does the change show up in view Y?

### Previous Solutions

#### Make a Recording - Do what the user would do.

This does work, but getting it to work well is difficult and time consuming. Consider an app with date pickers, time pickers, date and time pickers, alarms, and support for 12h/24h formats. Recordings need to be made and managed to handle all these modes; some will be the same, but some will not and identifying those edge cases is tedious. From experience, I know that using the `scroll` functions and recordings provided by calabash do not work.

#### Set the Date with `query`

e.g. `query("datePicker", {setDate:})`

This also works, but no UIEvents are generated. The UIDatePicker targets will not receive action messages. The date will change, but the rest of the UI/app will not be aware of the change. This is not ideal.

#### Use a Category on UIDatePicker

```
@interface UIDatePicker (CALABASH_ADDITIONS)
- (NSString *) hasCalabashAdditions:(NSString *) aSuccessIndicator;
- (BOOL) setDateWithString:(NSString *)aString
format:(NSString *) aFormat
animated:(BOOL) aAnimated;
@end
```

This also works, but it requires access to the source code. We want manipulating the UIDatePicker to work out-of-the-box.

#### Use `query` to Manipulate the UIPickerView subviews

I tried this approach in briar. It works, but it takes a lot of code to dig through the view hierarchy and you face the same issues as you do with recordings - there are so many modes and so many edge cases that it difficult to support (and test) all use cases.

### Proposed Solution: `LPDatePickerOperation`

I have been using the operation extensively in my own apps.

It boils down to this:

* send a target date as a string
* send a format string that objc can use to convert the date to an NSDate
* set the date with `UIDatePicker setDate:animated`
* optionally call the picker target/action pairs

It is very simple and very flexible.

`map(query_str, :changeDatePickerDate, target_str, fmt_str, *args)`

I realize this breaks with the 'do what the user would do' maxim, but the reality is that all other solutions are suboptimal.

On the ruby side, I propose that we provide a simple function and a simple predefined step that demonstrate the capabilities - nothing fancy.