briar 0.0.7 → 0.0.8
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.
- checksums.yaml +8 -8
- data/Rakefile +6 -11
- data/bin/briar +58 -0
- data/bin/briar_helpers.rb +28 -2
- data/briar.gemspec +3 -2
- data/features/step_definitions/alerts_and_sheets/action_sheet_steps.rb +10 -4
- data/features/step_definitions/alerts_and_sheets/alert_view_steps.rb +3 -10
- data/features/step_definitions/bars/navbar_steps.rb +1 -9
- data/features/step_definitions/bars/tabbar_steps.rb +2 -4
- data/features/step_definitions/bars/toolbar_steps.rb +2 -11
- data/features/step_definitions/control/button_steps.rb +3 -8
- data/features/step_definitions/control/segmented_control_steps.rb +20 -58
- data/features/step_definitions/email_steps.rb +10 -7
- data/features/step_definitions/keyboard_steps.rb +7 -2
- data/features/step_definitions/picker/date_picker_steps.rb +21 -177
- data/features/step_definitions/table_steps.rb +35 -71
- data/features/step_definitions/text_field_steps.rb +1 -5
- data/features/step_definitions/text_view_steps.rb +2 -2
- data/install-calabash-framework.sh.example +10 -0
- data/lib/briar.rb +31 -5
- data/lib/briar/alerts_and_sheets/action_sheet.rb +99 -0
- data/lib/briar/alerts_and_sheets/alert_view.rb +25 -4
- data/lib/briar/bars/navbar.rb +30 -19
- data/lib/briar/bars/tabbar.rb +7 -4
- data/lib/briar/bars/toolbar.rb +14 -1
- data/lib/briar/briar_core.rb +46 -15
- data/lib/briar/control/button.rb +35 -1
- data/lib/briar/control/segmented_control.rb +69 -8
- data/lib/briar/control/slider.rb +2 -2
- data/lib/briar/cucumber.rb +3 -1
- data/lib/briar/email.rb +19 -13
- data/lib/briar/keyboard.rb +50 -10
- data/lib/briar/label.rb +20 -0
- data/lib/briar/picker/date_picker.rb +88 -584
- data/lib/briar/picker/date_picker_core.rb +293 -0
- data/lib/briar/picker/date_picker_manipulation.rb +255 -0
- data/lib/briar/picker/picker.rb +10 -0
- data/lib/briar/table.rb +261 -93
- data/lib/briar/version.rb +1 -1
- data/spec/spec_helper.rb +0 -2
- metadata +14 -13
- data/lib/briar/gestalt.rb +0 -87
- data/spec/briar/gestalt_spec.rb +0 -66
data/lib/briar/control/button.rb
CHANGED
@@ -24,7 +24,7 @@ module Briar
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def button_is_enabled (name)
|
27
|
-
enabled = query("button marked:'#{name}' isEnabled:1",
|
27
|
+
enabled = query("button marked:'#{name}' isEnabled:1", AI).first
|
28
28
|
enabled.eql? name
|
29
29
|
end
|
30
30
|
|
@@ -40,6 +40,40 @@ module Briar
|
|
40
40
|
touch("button marked:'#{name}'")
|
41
41
|
step_pause
|
42
42
|
end
|
43
|
+
|
44
|
+
def touch_button_and_wait_for_view (button_id, view_id)
|
45
|
+
touch_transition("button marked:'#{button_id}'",
|
46
|
+
"view marked:'#{view_id}'",
|
47
|
+
{:timeout=>TOUCH_TRANSITION_TIMEOUT,
|
48
|
+
:retry_frequency=>TOUCH_TRANSITION_RETRY_FREQ})
|
49
|
+
end
|
50
|
+
|
51
|
+
def touch_button_and_wait_for_view_to_disappear (button_id, view_id, timeout=1.0)
|
52
|
+
touch_button button_id
|
53
|
+
wait_for_view_to_disappear view_id, timeout
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
def wait_for_button (button_id, timeout=1.0)
|
58
|
+
msg = "waited for '#{timeout}' seconds but did not see button '#{button_id}'"
|
59
|
+
wait_for(:timeout => timeout,
|
60
|
+
:retry_frequency => 0.2,
|
61
|
+
:post_timeout => 0.1,
|
62
|
+
:timeout_message => msg ) do
|
63
|
+
button_exists? button_id
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def wait_for_button_with_title (button_id, title, timeout=1.0)
|
68
|
+
msg = "waited for '#{timeout}' seconds but did not see button '#{button_id}' with title '#{title}'"
|
69
|
+
wait_for(:timeout => timeout,
|
70
|
+
:retry_frequency => 0.2,
|
71
|
+
:post_timeout => 0.1,
|
72
|
+
:timeout_message => msg ) do
|
73
|
+
button_exists? button_id
|
74
|
+
end
|
75
|
+
should_see_button_with_title(button_id, title)
|
76
|
+
end
|
43
77
|
end
|
44
78
|
end
|
45
79
|
end
|
@@ -1,22 +1,83 @@
|
|
1
|
-
require "calabash-cucumber"
|
2
|
-
|
3
1
|
module Briar
|
4
2
|
module Control
|
5
3
|
module Segmented_Control
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
|
5
|
+
def query_str_for_control (control_id=nil)
|
6
|
+
if control_id.nil?
|
7
|
+
'segmentedControl'
|
8
|
+
else
|
9
|
+
"segmentedControl marked:'#{control_id}'"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def index_of_control_with_id (control_id)
|
14
|
+
controls = query('segmentedControl', AI)
|
15
|
+
controls.index(control_id)
|
9
16
|
end
|
10
17
|
|
11
|
-
def
|
12
|
-
control_idx =
|
18
|
+
def index_of_segment_with_name_in_control_with_id(segment_id, control_id)
|
19
|
+
control_idx = index_of_control_with_id (control_id)
|
13
20
|
if control_idx
|
14
21
|
titles = query("segmentedControl index:#{control_idx} child segment child segmentLabel", :text).reverse
|
15
|
-
titles.index(
|
22
|
+
titles.index(segment_id)
|
16
23
|
else
|
17
24
|
nil
|
18
25
|
end
|
19
26
|
end
|
27
|
+
|
28
|
+
def should_see_segment_with_selected_state (control_id, segment_id, selected_state)
|
29
|
+
@segment_id = segment_id
|
30
|
+
@control_id = control_id
|
31
|
+
control_idx = index_of_control_with_id control_id
|
32
|
+
if control_idx
|
33
|
+
segment_idx = index_of_segment_with_name_in_control_with_id(segment_id, control_id)
|
34
|
+
if segment_idx
|
35
|
+
selected_arr = query("segmentedControl index:#{control_idx} child segment", :isSelected).reverse
|
36
|
+
res = selected_arr[segment_idx]
|
37
|
+
unless res.to_i == selected_state
|
38
|
+
screenshot_and_raise "found segment named #{segment_id} in #{control_id}, but it was _not_ selected"
|
39
|
+
end
|
40
|
+
else
|
41
|
+
screenshot_and_raise "could not find #{segment_id} in #{control_id}"
|
42
|
+
end
|
43
|
+
else
|
44
|
+
screenshot_and_raise "could not find control named #{control_id}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def touch_segment(segment_id, control_id)
|
49
|
+
@segment_id = segment_id
|
50
|
+
@control_id = control_id
|
51
|
+
idx = index_of_control_with_id control_id
|
52
|
+
if idx
|
53
|
+
touch("segmentedControl index:#{idx} child segment child segmentLabel marked:'#{segment_id}'")
|
54
|
+
step_pause
|
55
|
+
else
|
56
|
+
screenshot_and_raise "could not find segmented control with name #{control_id}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def should_see_control_with_segment_titles (control_id, segment_titles)
|
61
|
+
@control_id = control_id
|
62
|
+
should_see_view control_id
|
63
|
+
tokens = segment_titles.split(',')
|
64
|
+
tokens.each do |token|
|
65
|
+
token.strip!
|
66
|
+
end
|
67
|
+
idx = index_of_control_with_id control_id
|
68
|
+
if idx
|
69
|
+
actual_titles = query("segmentedControl index:#{idx} child segment child segmentLabel", :text).reverse
|
70
|
+
counter = 0
|
71
|
+
tokens.zip(actual_titles).each do |expected, actual|
|
72
|
+
unless actual.eql? expected
|
73
|
+
screenshot_and_raise "when inspecting #{control_id} i expected title: #{expected} but found: #{actual} at index #{counter}"
|
74
|
+
end
|
75
|
+
counter = counter + 1
|
76
|
+
end
|
77
|
+
else
|
78
|
+
screenshot_and_raise "could not find segmented control with name #{control_id}"
|
79
|
+
end
|
80
|
+
end
|
20
81
|
end
|
21
82
|
end
|
22
83
|
end
|
data/lib/briar/control/slider.rb
CHANGED
data/lib/briar/cucumber.rb
CHANGED
@@ -7,9 +7,11 @@ World(Briar::Bars)
|
|
7
7
|
World(Briar::Control::Button)
|
8
8
|
World(Briar::Control::Segmented_Control)
|
9
9
|
World(Briar::Control::Slider)
|
10
|
-
World(Briar::Picker::Date)
|
11
10
|
World(Briar::Picker_Shared)
|
12
11
|
World(Briar::Picker)
|
12
|
+
World(Briar::Picker::DateCore)
|
13
|
+
World(Briar::Picker::DateManipulation)
|
14
|
+
World(Briar::Picker::DateSteps)
|
13
15
|
World(Briar::Email)
|
14
16
|
World(Briar::ImageView)
|
15
17
|
World(Briar::Keyboard)
|
data/lib/briar/email.rb
CHANGED
@@ -12,7 +12,7 @@ module Briar
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def email_body_contains? (text)
|
15
|
-
if
|
15
|
+
if device.ios6?
|
16
16
|
warn 'WARN: iOS6 detected - cannot test for email body text https://groups.google.com/d/topic/calabash-ios/Ff3XFsjp-B0/discussion'
|
17
17
|
else
|
18
18
|
!query("view:'MFComposeTextContentView' {text LIKE '*#{text}*'}").empty?
|
@@ -24,7 +24,7 @@ module Briar
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def email_subject_is? (text)
|
27
|
-
if
|
27
|
+
if device.ios6?
|
28
28
|
warn 'WARN: iOS6 detected - cannot test for email subject text https://groups.google.com/d/topic/calabash-ios/Ff3XFsjp-B0/discussion'
|
29
29
|
else
|
30
30
|
email_subject.eql? text
|
@@ -32,7 +32,7 @@ module Briar
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def email_subject_has_text_like? (text)
|
35
|
-
if
|
35
|
+
if device.ios6?
|
36
36
|
warn 'WARN: iOS6 detected - cannot test for email subject text https://groups.google.com/d/topic/calabash-ios/Ff3XFsjp-B0/discussion'
|
37
37
|
else
|
38
38
|
!query("view:'MFComposeSubjectView' {text LIKE '*#{text}*'}").empty?
|
@@ -44,7 +44,7 @@ module Briar
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def email_to_field_is? (text)
|
47
|
-
if
|
47
|
+
if device.ios6?
|
48
48
|
warn 'WARN: iOS6 detected - cannot test for email to field https://groups.google.com/d/topic/calabash-ios/Ff3XFsjp-B0/discussion'
|
49
49
|
else
|
50
50
|
email_to.eql? text
|
@@ -72,27 +72,33 @@ module Briar
|
|
72
72
|
end
|
73
73
|
|
74
74
|
def is_ios6_mail_view
|
75
|
-
|
75
|
+
device.ios6?
|
76
76
|
end
|
77
77
|
|
78
|
-
def should_see_mail_view (
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
78
|
+
def should_see_mail_view (timeout=1.0)
|
79
|
+
if device.ios6?
|
80
|
+
screenshot_and_raise 'iOS6 detected - cannot test for email viewhttps://groups.google.com/d/topic/calabash-ios/Ff3XFsjp-B0/discussion'
|
81
|
+
end
|
82
|
+
|
83
|
+
msg = "waited for '#{timeout}' seconds but did not see email compose view"
|
84
|
+
wait_for(:timeout => timeout,
|
85
|
+
:retry_frequency => 0.2,
|
86
|
+
:post_timeout => 0.1,
|
87
|
+
:timeout_message => msg ) do
|
88
|
+
is_ios5_mail_view
|
83
89
|
end
|
84
90
|
end
|
85
91
|
|
86
92
|
def device_can_send_email
|
87
|
-
return true if
|
93
|
+
return true if device.simulator?
|
88
94
|
backdoor('calabash_backdoor_configured_for_mail:', 'ignorable').eql? 'YES'
|
89
95
|
end
|
90
96
|
|
91
97
|
def delete_draft_and_wait_for (view_id)
|
92
|
-
if
|
98
|
+
if device.ios6?
|
93
99
|
warn_about_ios6_email_view
|
94
100
|
else
|
95
|
-
should_see_mail_view
|
101
|
+
should_see_mail_view
|
96
102
|
touch_navbar_item 'Cancel'
|
97
103
|
wait_for_animation
|
98
104
|
touch_transition("button marked:'Delete Draft'",
|
data/lib/briar/keyboard.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
-
|
1
|
+
|
2
|
+
|
2
3
|
|
3
4
|
module Briar
|
4
5
|
module Keyboard
|
6
|
+
# these are not ready for prime time# the methods for setting auto correct, spell check, etc. are not ready
|
5
7
|
UITextAutocapitalizationTypeNone = 0
|
6
8
|
UITextAutocapitalizationTypeWords = 1
|
7
9
|
UITextAutocapitalizationTypeSentences = 2
|
@@ -13,21 +15,51 @@ module Briar
|
|
13
15
|
UITextSpellCheckingTypeNo = 1
|
14
16
|
UITextSpellCheckingTypeYes = 2
|
15
17
|
|
18
|
+
@text_entered_by_keyboard = ''
|
16
19
|
|
17
|
-
def should_see_keyboard
|
18
|
-
|
19
|
-
|
20
|
-
|
20
|
+
def should_see_keyboard (timeout=1.0)
|
21
|
+
msg = "waited for '#{timeout}' seconds but did not see keyboard"
|
22
|
+
wait_for(:timeout => timeout,
|
23
|
+
:retry_frequency => 0.2,
|
24
|
+
:post_timeout => 0.1,
|
25
|
+
:timeout_message => msg ) do
|
26
|
+
element_exists('keyboardAutomatic')
|
21
27
|
end
|
22
28
|
end
|
23
29
|
|
24
|
-
def should_not_see_keyboard
|
25
|
-
|
26
|
-
|
27
|
-
|
30
|
+
def should_not_see_keyboard (timeout=1.0)
|
31
|
+
msg = "waited for '#{timeout}' seconds but keyboard did not disappear"
|
32
|
+
wait_for(:timeout => timeout,
|
33
|
+
:retry_frequency => 0.2,
|
34
|
+
:post_timeout => 0.1,
|
35
|
+
:timeout_message => msg ) do
|
36
|
+
element_does_not_exist 'keyboardAutomatic'
|
28
37
|
end
|
29
38
|
end
|
30
39
|
|
40
|
+
def briar_keyboard_enter_text (text)
|
41
|
+
if device.ios7?
|
42
|
+
pending('keyboard playback is not available on iOS 7')
|
43
|
+
end
|
44
|
+
@text_entered_by_keyboard = keyboard_enter_text text
|
45
|
+
end
|
46
|
+
|
47
|
+
def briar_keyboard_set_text (text, view_id, &do_for_each_char)
|
48
|
+
unless device.ios7?
|
49
|
+
warn 'this is hack for iOS 7 (playback not available yet) - use briar_keyboard_enter_text'
|
50
|
+
end
|
51
|
+
|
52
|
+
query_str = "view marked:'#{view_id}'"
|
53
|
+
accum = ''
|
54
|
+
text.chars.to_a.each { |char|
|
55
|
+
accum << char
|
56
|
+
query(query_str, {setText:accum})
|
57
|
+
do_for_each_char.call(view_id, accum)
|
58
|
+
@text_entered_by_keyboard = accum
|
59
|
+
sleep(0.05)
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
31
63
|
# is it possible to find what view the keyboard is responding to?
|
32
64
|
def autocapitalization_type ()
|
33
65
|
if !query('textView index:0').empty?
|
@@ -55,7 +87,7 @@ module Briar
|
|
55
87
|
|
56
88
|
def set_autocorrect (type)
|
57
89
|
if !query('textView index:0').empty?
|
58
|
-
query('textView index:0',
|
90
|
+
query('textView index:0', [{setAutocorrectionType:type}])
|
59
91
|
elsif !query('textField index:0').empty?
|
60
92
|
query('textField index:0', [{setAutocorrectionType:type}])
|
61
93
|
else
|
@@ -77,6 +109,14 @@ module Briar
|
|
77
109
|
end
|
78
110
|
end
|
79
111
|
|
112
|
+
|
113
|
+
|
114
|
+
def clear_text(uiquery)
|
115
|
+
text_fields_modified = map(uiquery, :setText, '')
|
116
|
+
screenshot_and_raise "could not find text field #{uiquery}" if text_fields_modified.empty?
|
117
|
+
text_fields_modified
|
118
|
+
end
|
119
|
+
|
80
120
|
#def is_capitalize_none (cap_type)
|
81
121
|
# cap_type == UITextAutocapitalizationTypeNone
|
82
122
|
#end
|
data/lib/briar/label.rb
CHANGED
@@ -30,5 +30,25 @@ module Briar
|
|
30
30
|
screenshot_and_raise "i expected that i would not see '#{text}' in label named '#{name}'"
|
31
31
|
end
|
32
32
|
end
|
33
|
+
|
34
|
+
def wait_for_label (label_id, timeout=1.0)
|
35
|
+
msg = "waited for '#{timeout}' seconds but did not see label '#{label_id}'"
|
36
|
+
wait_for(:timeout => timeout,
|
37
|
+
:retry_frequency => 0.2,
|
38
|
+
:post_timeout => 0.1,
|
39
|
+
:timeout_message => msg ) do
|
40
|
+
label_exists? label_id
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def touch_label (label_id, wait_for_view_id=nil)
|
45
|
+
wait_for_label label_id
|
46
|
+
touch("label marked:'#{label_id}'")
|
47
|
+
if wait_for_view_id != nil
|
48
|
+
wait_for_view wait_for_view_id
|
49
|
+
else
|
50
|
+
step_pause
|
51
|
+
end
|
52
|
+
end
|
33
53
|
end
|
34
54
|
end
|
@@ -1,64 +1,5 @@
|
|
1
|
-
require 'date'
|
2
|
-
require 'calabash-cucumber'
|
3
|
-
|
4
|
-
# 0.2 is too fast because the picker does not pause at the date long enough for
|
5
|
-
# the date to change. 0.3 seems to work, but 0.4 is best i think.
|
6
|
-
PICKER_STEP_PAUSE = 0.4.to_f
|
7
|
-
PICKER_AM = 'AM'
|
8
|
-
PICKER_PM = 'PM'
|
9
|
-
|
10
|
-
# most locales and situations prefer _not_ to have leading zeros on hours in 24h
|
11
|
-
# see usage below to find out when and if the zeros are stripped
|
12
|
-
PICKER_24H_TIME_FMT = '%H:%M'
|
13
|
-
PICKER_12H_TIME_FMT = '%l:%M %p'
|
14
|
-
PICKER_ISO8601_TIME_FMT = '%H:%M'
|
15
|
-
|
16
|
-
PICKER_REMOVE_LEADING_ZERO_REGEX = /\A^0/
|
17
|
-
|
18
|
-
# 24h locales - Fri 16 Nov - 24h locales
|
19
|
-
PICKER_24H_DATE_FMT = '%a %e %b'
|
20
|
-
# common format for US Fri Nov 16
|
21
|
-
PICKER_12H_DATE_FMT = '%a %b %e'
|
22
|
-
|
23
|
-
# our canonical format for testing if two dates are the same
|
24
|
-
PICKER_ISO8601_DATE_FMT = '%Y-%m-%d'
|
25
|
-
PICKER_ISO8601_DATE_TIME_FMT = '%Y-%m-%d %H:%M'
|
26
|
-
|
27
|
-
# when we are using the date picker category, this is the format of the string
|
28
|
-
# we will send to setDateWithString:animated:
|
29
|
-
#
|
30
|
-
# ex. 2012_11_18_16_45
|
31
|
-
PICKER__RUBY___SET_PICKER_DATE__DATE_AND_TIME_FMT_ZONED = '%Y_%m_%d_%H_%M_%z'
|
32
|
-
PICKER__OBJC___SET_PICKER_DATE__DATE_AND_TIME_FMT_ZONED = 'yyyy_MM_dd_HH_mm_Z'
|
33
|
-
PICKER__RUBY___SET_PICKER_DATE__DATE_AND_TIME_FMT = '%Y_%m_%d_%H_%M'
|
34
|
-
PICKER__OBJC___SET_PICKER_DATE__DATE_AND_TIME_FMT = 'yyyy_MM_dd_HH_mm'
|
35
|
-
|
36
|
-
|
37
|
-
# iOS 5
|
38
|
-
PICKER_VIEW_CLASS_IOS5 = 'datePickerView'
|
39
|
-
PICKER_VIEW_CLASS_IOS6 = "view:'_UIDatePickerView'"
|
40
|
-
|
41
|
-
UIDatePickerModeTime = 0
|
42
|
-
UIDatePickerModeDate = 1
|
43
|
-
UIDatePickerModeDateAndTime = 2
|
44
|
-
UIDatePickerModeCountDownTimer = 3
|
45
|
-
|
46
|
-
|
47
|
-
module Briar
|
48
|
-
module Picker
|
49
|
-
module Date
|
50
|
-
include Briar::Picker_Shared
|
51
|
-
=begin
|
52
|
-
TODO use minute interval modes 5,10,15 etc. to test if date is reachable
|
53
|
-
TODO use the max/min dates to determine if a date is reachable
|
54
|
-
TODO when manually moving the picker wheels - speed things up by figuring out which direction to scroll the hour/minutes
|
55
|
-
=end
|
56
|
-
|
57
|
-
|
58
1
|
=begin
|
59
2
|
|
60
|
-
requires: picker_common_step.rb
|
61
|
-
|
62
3
|
examples
|
63
4
|
|
64
5
|
Then I should see that the date picker is in time mode
|
@@ -76,567 +17,130 @@ examples
|
|
76
17
|
Then I change the picker to 2 days ago at "9:30 PM"
|
77
18
|
Then I should see that the "checkin" row has the time I just entered in the "status" label
|
78
19
|
|
79
|
-
|
80
|
-
this file provides 2 ways to manipulate a date picker:
|
81
|
-
|
82
|
-
1. AUTOMATIC <== setting the date directly using a UIDatePicker category method
|
83
|
-
2. MANUAL <== setting the date by manipulating the picker wheels
|
84
|
-
|
85
|
-
there are pros and cons for each approach.
|
86
|
-
|
87
|
-
AUTOMATIC pros
|
88
|
-
1. the date selection happens almost instantly
|
89
|
-
2. there is very little parsing of date and time strings <== fewer errors
|
90
|
-
3. it is accomplished in a small number of lines of code <== fewer errors
|
91
|
-
|
92
|
-
AUTOMATIC cons
|
93
|
-
1. it does not really simulate the user interaction with the picker wheels.
|
94
|
-
|
95
|
-
this is actually very hard to do because there are cases where changing
|
96
|
-
one column will cause another column to change. for example: when in 12h
|
97
|
-
mode, if the user rotates the hour to 12, then the period column will change.
|
98
|
-
this change cannot be detected on the calabash side so either it has to be
|
99
|
-
guarded against (don't rotate past 12) or the AM/PM must be changed last.
|
100
|
-
|
101
|
-
2. requires a category on UIDatePicker <== pollutes the application environment
|
102
|
-
3. uses the query language to make changes to application state <== doesn't seem kosher
|
103
|
-
|
104
|
-
in my mind this is a little like the keyboard_enter_text because that method
|
105
|
-
enters text in a way that no user can (i.e. so fast)
|
106
|
-
|
107
|
-
MANUAL pros
|
108
|
-
1. it directly simulates what a user does
|
109
|
-
|
110
|
-
|
111
|
-
MANUAL cons
|
112
|
-
1. it is very slow <== long tests are a drag
|
113
|
-
2. there is a lot of string <==> date parsing <== more errors
|
114
|
-
3. lots of special case handling <== more errors
|
115
|
-
|
116
|
-
|
117
|
-
to use the automatic mode, include this category in your CALABASH target
|
118
|
-
|
119
|
-
=== BEGIN ===
|
120
|
-
@interface UIDatePicker (CALABASH_ADDITIONS)
|
121
|
-
- (NSString *) hasCalabashAdditions:(NSString *) aSuccessIndicator;
|
122
|
-
- (BOOL) setDateWithString:(NSString *)aString
|
123
|
-
format:(NSString *) aFormat
|
124
|
-
animated:(BOOL) aAnimated;
|
125
|
-
@end
|
126
|
-
|
127
|
-
|
128
|
-
@implementation UIDatePicker (CALABASH_ADDITIONS)
|
129
|
-
- (NSString *) hasCalabashAdditions:(NSString *) aSuccessIndicator {
|
130
|
-
return aSuccessIndicator;
|
131
|
-
}
|
132
|
-
|
133
|
-
- (BOOL) setDateWithString:(NSString *)aString
|
134
|
-
format:(NSString *) aFormat
|
135
|
-
animated:(BOOL) aAnimated {
|
136
|
-
NSDateFormatter *df = [[NSDateFormatter alloc] init];
|
137
|
-
[df setDateFormat:aFormat];
|
138
|
-
NSDate *date = [df dateFromString:aString];
|
139
|
-
if (date == nil) return NO;
|
140
|
-
[self setDate:date animated:aAnimated];
|
141
|
-
return YES;
|
142
|
-
}
|
143
|
-
@end
|
144
|
-
=== END ===
|
145
|
-
|
146
20
|
=end
|
147
21
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
#
|
154
|
-
## most locales and situations prefer _not_ to have leading zeros on hours in 24h
|
155
|
-
## see usage below to find out when and if the zeros are stripped
|
156
|
-
# PICKER_24H_TIME_FMT = '%H:%M'
|
157
|
-
# PICKER_12H_TIME_FMT = '%l:%M %p'
|
158
|
-
# PICKER_ISO8601_TIME_FMT = '%H:%M'
|
159
|
-
#
|
160
|
-
# PICKER_REMOVE_LEADING_ZERO_REGEX = /\A^0/
|
161
|
-
#
|
162
|
-
## 24h locales - Fri 16 Nov - 24h locales
|
163
|
-
# PICKER_24H_DATE_FMT = '%a %e %b'
|
164
|
-
## common format for US Fri Nov 16
|
165
|
-
# PICKER_12H_DATE_FMT = '%a %b %e'
|
166
|
-
#
|
167
|
-
## our canonical format for testing if two dates are the same
|
168
|
-
# PICKER_ISO8601_DATE_FMT = '%Y-%m-%d'
|
169
|
-
# PICKER_ISO8601_DATE_TIME_FMT = '%Y-%m-%d %H:%M'
|
170
|
-
#
|
171
|
-
## when we are using the date picker category, this is the format of the string
|
172
|
-
## we will send to setDateWithString:animated:
|
173
|
-
##
|
174
|
-
## ex. 2012_11_18_16_45
|
175
|
-
# PICKER__RUBY___SET_PICKER_DATE__DATE_AND_TIME_FMT = '%Y_%m_%d_%H_%M_%z'
|
176
|
-
# PICKER__OBJC___SET_PICKER_DATE__DATE_AND_TIME_FMT = 'yyyy_MM_dd_HH_mm_Z'
|
177
|
-
#
|
178
|
-
## iOS 5
|
179
|
-
# PICKER_VIEW_CLASS_IOS5 = 'datePickerView'
|
180
|
-
# PICKER_VIEW_CLASS_IOS6 = "view:'_UIDatePickerView'"
|
181
|
-
|
182
|
-
# testing for existence
|
183
|
-
def should_see_date_picker (picker_id)
|
184
|
-
res = !query("datePicker marked:'#{picker_id}'").empty?
|
185
|
-
unless res
|
186
|
-
screenshot_and_raise "could not find date picker #{picker_id}"
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
# getting dates from the picker
|
191
|
-
|
192
|
-
def picker_date_time
|
193
|
-
res = query('datePicker', :date)
|
194
|
-
screenshot_and_raise 'expected to see a date picker' if res.empty?
|
195
|
-
DateTime.parse(res.first)
|
196
|
-
end
|
197
|
-
|
198
|
-
# appledoc ==> The property is an NSDate object or nil (the default), which
|
199
|
-
# means no maximum date.
|
200
|
-
def picker_maximum_date_time
|
201
|
-
res = query('datePicker', :maximumDate)
|
202
|
-
screenshot_and_raise 'expected to see a date picker' if res.empty?
|
203
|
-
res.first != nil ? DateTime.parse(res.first) : nil
|
204
|
-
end
|
205
|
-
|
206
|
-
# appledoc ==> The property is an NSDate object or nil (the default), which
|
207
|
-
# means no minimum date.
|
208
|
-
def picker_minimum_date_time
|
209
|
-
res = query('datePicker', :minimumDate)
|
210
|
-
screenshot_and_raise 'expected to see a date picker' if res.empty?
|
211
|
-
res.first != nil ? DateTime.parse(res.first) : nil
|
212
|
-
end
|
213
|
-
|
214
|
-
# automatic date setting
|
215
|
-
|
216
|
-
# checking to see if the picker is visible and has the calabash category
|
217
|
-
# additions
|
218
|
-
def picker_has_calabash_additions
|
219
|
-
success_value = '1'
|
220
|
-
res = query('datePicker', [{hasCalabashAdditions:success_value}])
|
221
|
-
screenshot_and_raise 'picker is not visible' if res.empty?
|
222
|
-
res.first.eql? success_value
|
223
|
-
end
|
224
|
-
|
225
|
-
|
226
|
-
def date_time_or_time_str_is_in_24h (date_time_or_time_str)
|
227
|
-
date_time_or_time_str[-1, 1].scan(/^[a-zA-Z]/).empty?
|
228
|
-
end
|
229
|
-
|
230
|
-
def date_str_is_in_24h (date_str)
|
231
|
-
!date_str[-1, 1].scan(/^[a-zA-Z]/).empty?
|
232
|
-
end
|
233
|
-
|
234
|
-
def date_str_to_send_to_picker_from_time_str (time_str, format=PICKER__RUBY___SET_PICKER_DATE__DATE_AND_TIME_FMT)
|
235
|
-
time_in_24h = date_time_or_time_str_is_in_24h time_str
|
236
|
-
time_fmt = time_in_24h ? PICKER_24H_TIME_FMT : PICKER_12H_TIME_FMT
|
237
|
-
date_fmt = time_in_24h ? PICKER_24H_DATE_FMT : PICKER_12H_DATE_FMT
|
238
|
-
date_str = picker_date_time.strftime(date_fmt).squeeze(' ').strip
|
239
|
-
|
240
|
-
date_time_str = "#{date_str} #{time_str}"
|
241
|
-
date_time_fmt = "#{date_fmt} #{time_fmt}"
|
242
|
-
|
243
|
-
date_time = DateTime.strptime(date_time_str, date_time_fmt)
|
244
|
-
date_time.strftime(format).squeeze(' ').strip
|
245
|
-
end
|
246
|
-
|
247
|
-
|
248
|
-
def date_str_to_send_to_picker_from_date_str (date_str, format=PICKER__RUBY___SET_PICKER_DATE__DATE_AND_TIME_FMT)
|
249
|
-
date_in_24h = date_str_is_in_24h (date_str)
|
250
|
-
time_fmt = date_in_24h ? PICKER_24H_TIME_FMT : PICKER_12H_TIME_FMT
|
251
|
-
date_fmt = date_in_24h ? PICKER_24H_DATE_FMT : PICKER_12H_DATE_FMT
|
252
|
-
time_str = picker_date_time.strftime(time_fmt).squeeze(' ').strip
|
253
|
-
date_time_str = "#{date_str} #{time_str}"
|
254
|
-
date_time_fmt = "#{date_fmt} #{time_fmt}"
|
255
|
-
|
256
|
-
date_time = DateTime.strptime(date_time_str, date_time_fmt)
|
257
|
-
|
258
|
-
date_time.strftime(format).squeeze(' ').strip
|
259
|
-
end
|
260
|
-
|
22
|
+
module Briar
|
23
|
+
module Picker
|
24
|
+
module DateSteps
|
25
|
+
include Briar::Picker::DateCore
|
26
|
+
include Briar::Picker::DateManipulation
|
261
27
|
|
262
|
-
|
263
|
-
:objc_format => PICKER__OBJC___SET_PICKER_DATE__DATE_AND_TIME_FMT})
|
28
|
+
# requires a time or date change. picker does not need to be visible
|
264
29
|
|
265
|
-
|
266
|
-
|
267
|
-
|
30
|
+
def should_see_row_has_time_i_just_entered (row_id, label_id, table_id=nil)
|
31
|
+
query_str = query_str_for_row row_id, table_id
|
32
|
+
arr = query("#{query_str} descendant label marked:'#{label_id}'", :text)
|
33
|
+
screenshot_and_raise "could not find '#{label_id}' in the '#{row_id}' row" if arr.empty?
|
34
|
+
actual_text = arr.first
|
268
35
|
|
269
|
-
|
270
|
-
|
271
|
-
screenshot_and_raise "could not set the picker date with '#{date_time_str}' and '#{PICKER__RUBY___SET_PICKER_DATE__DATE_AND_TIME_FMT}'"
|
36
|
+
unless (actual_text.eql? @date_picker_time_12h) or (actual_text.eql? @date_picker_time_24h)
|
37
|
+
screenshot_and_raise "expected to see '#{@date_picker_time_12h}' or '#{@date_picker_time_24h}' in '#{label_id}' but found '#{actual_text}'"
|
272
38
|
end
|
273
|
-
|
274
|
-
# REQUIRED
|
275
|
-
sleep(PICKER_STEP_PAUSE)
|
276
|
-
|
277
|
-
# the query does not create a UIControlEventValueChanged event, so we have to
|
278
|
-
# to a touch event
|
279
|
-
|
280
|
-
# not true :(
|
281
|
-
# if the picker is in time mode, then we dont need to worry about min/max
|
282
|
-
|
283
|
-
# if the picker is date or date time mode, i think the first column is
|
284
|
-
# always scrollable up _and_ it sends an event even if the date is beyond
|
285
|
-
# the maximum date
|
286
|
-
#
|
287
|
-
#picker_max_date = picker_maximum_date_time
|
288
|
-
#picker_min_date = picker_minimum_date_time
|
289
|
-
#target_date = DateTime.strptime(date_time_str, PICKER__RUBY___SET_PICKER_DATE__DATE_AND_TIME_FMT)
|
290
|
-
#
|
291
|
-
#column_one_index = picker_current_index_for_column 0
|
292
|
-
#query('pickerTableView index:0', [{selectRow:column_one_index}, {animated:1}, {notify:1}])
|
293
|
-
|
294
|
-
picker_scroll_down_on_column 0
|
295
|
-
sleep(PICKER_STEP_PAUSE)
|
296
|
-
picker_scroll_up_on_column 0
|
297
|
-
sleep(PICKER_STEP_PAUSE)
|
298
|
-
#if (target_date + 1) > picker_max_date
|
299
|
-
# picker_scroll_down_on_column 0
|
300
|
-
# sleep(PICKER_STEP_PAUSE)
|
301
|
-
# picker_scroll_up_on_column 0
|
302
|
-
#elsif (target_date - 1) < picker_min_date
|
303
|
-
# picker_scroll_up_on_column 0
|
304
|
-
# sleep(PICKER_STEP_PAUSE)
|
305
|
-
# picker_scroll_down_on_column 0
|
306
|
-
#else
|
307
|
-
# screenshot_and_raise "could not figure out which way to rotate the day column to trigger an event"
|
308
|
-
#end
|
309
|
-
|
310
39
|
end
|
311
40
|
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
res = query('datePicker', :minuteInterval)
|
321
|
-
screenshot_and_raise 'expected to see a date picker' if res.empty?
|
322
|
-
@picker_minute_interval = res.first
|
323
|
-
end
|
324
|
-
|
325
|
-
def time_hash_by_add_minutes_until_at_closest_interval (time_str, interval=picker_minute_interval())
|
326
|
-
screenshot_and_raise "interval '#{interval}' is not on (0, 59) which is not allowed" unless (0..59).member?(interval)
|
327
|
-
time = Time.parse(time_str)
|
328
|
-
# normalize to zero
|
329
|
-
time = time - time.sec
|
330
|
-
minute = time.min
|
331
|
-
count = 0
|
332
|
-
unless (minute % interval) == 0
|
333
|
-
begin
|
334
|
-
minute = (minute > 59) ? 0 : minute + 1
|
335
|
-
count = count + 1
|
336
|
-
end
|
337
|
-
end while ((minute % interval) != 0)
|
338
|
-
time = time + (count * 60)
|
339
|
-
|
340
|
-
{:h12 => time.strftime(PICKER_12H_TIME_FMT).squeeze(' ').strip,
|
341
|
-
:h24 => time.strftime(PICKER_24H_TIME_FMT).squeeze(' ').strip.sub(PICKER_REMOVE_LEADING_ZERO_REGEX, ''),
|
342
|
-
:time => time}
|
343
|
-
end
|
344
|
-
|
345
|
-
# picker modes
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
def picker_mode
|
350
|
-
res = query('datePicker', :datePickerMode)
|
351
|
-
screenshot_and_raise 'expected to see a date picker' if res.empty?
|
352
|
-
res.first
|
353
|
-
end
|
354
|
-
|
355
|
-
def picker_is_in_time_mode
|
356
|
-
picker_mode == UIDatePickerModeTime
|
357
|
-
end
|
358
|
-
|
359
|
-
def picker_is_in_date_mode
|
360
|
-
picker_mode == UIDatePickerModeDate
|
361
|
-
end
|
362
|
-
|
363
|
-
def picker_is_in_date_and_time_mode
|
364
|
-
picker_mode == UIDatePickerModeDateAndTime
|
365
|
-
end
|
366
|
-
|
367
|
-
def picker_is_in_countdown_mode
|
368
|
-
picker_mode == UIDatePickerModeCountDownTimer
|
369
|
-
end
|
370
|
-
|
371
|
-
# columns for different modes
|
372
|
-
|
373
|
-
def picker_column_for_hour
|
374
|
-
screenshot_and_raise 'there is no hour column in date mode' if picker_is_in_date_mode
|
375
|
-
screenshot_and_raise 'nyi' if picker_is_in_countdown_mode
|
376
|
-
picker_is_in_time_mode ? 0 : 1
|
377
|
-
end
|
378
|
-
|
379
|
-
def picker_column_for_minute
|
380
|
-
screenshot_and_raise 'there is no minute column in date mode' if picker_is_in_date_mode
|
381
|
-
screenshot_and_raise 'nyi' if picker_is_in_countdown_mode
|
382
|
-
picker_is_in_time_mode ? 1 : 2
|
383
|
-
end
|
384
|
-
|
385
|
-
def picker_column_for_period
|
386
|
-
screenshot_and_raise 'there is no period column in date mode' if picker_is_in_date_mode
|
387
|
-
screenshot_and_raise 'nyi' if picker_is_in_countdown_mode
|
388
|
-
picker_is_in_time_mode ? 2 : 3
|
389
|
-
end
|
390
|
-
|
391
|
-
# 12h or 24h locale
|
392
|
-
|
393
|
-
def picker_is_in_12h_locale
|
394
|
-
screenshot_and_raise '12h/24h mode is not applicable to this mode' if picker_is_in_date_mode or picker_is_in_countdown_mode
|
395
|
-
column = picker_column_for_period
|
396
|
-
!query("pickerTableView index:#{column}").empty?
|
397
|
-
end
|
398
|
-
|
399
|
-
def picker_is_in_24h_locale
|
400
|
-
!picker_is_in_12h_locale
|
401
|
-
end
|
402
|
-
|
403
|
-
# dealing with the period (aka meridian) column
|
404
|
-
|
405
|
-
# this will cause problems with localizations - for example:
|
406
|
-
# pt (lisbon) - a.m./p.m.
|
407
|
-
# de - nach/vor
|
408
|
-
def picker_period
|
409
|
-
screenshot_and_raise 'picker is not in 12h mode' if picker_is_in_24h_locale
|
410
|
-
date = picker_date_time
|
411
|
-
date_str = date.strftime(PICKER_12H_TIME_FMT)
|
412
|
-
tokens = date_str.split(' ')
|
413
|
-
tokens.last
|
414
|
-
end
|
415
|
-
|
416
|
-
def picker_period_is_am?
|
417
|
-
picker_period.eql?('AM')
|
418
|
-
end
|
419
|
-
|
420
|
-
def picker_period_is_pm?
|
421
|
-
picker_period.eql?('PM')
|
422
|
-
end
|
423
|
-
|
424
|
-
# weekday, month, day, etc
|
425
|
-
|
426
|
-
def picker_weekday
|
427
|
-
screenshot_and_raise 'weekday is not applicable to this mode' if picker_is_in_time_mode or picker_is_in_countdown_mode
|
428
|
-
res = query('datePickerWeekMonthDayView', :weekdayLabel, :text)[2]
|
429
|
-
# need to guard against Today showing
|
430
|
-
res == nil ? Date.today.strftime('%a') : res
|
431
|
-
end
|
432
|
-
|
433
|
-
def picker_month_day
|
434
|
-
screenshot_and_raise 'month/day is not applicable to this mode' if picker_is_in_time_mode or picker_is_in_countdown_mode
|
435
|
-
res = query('datePickerWeekMonthDayView', :dateLabel, :text)[2]
|
436
|
-
picker_iso = picker_date_time.strftime(PICKER_ISO8601_DATE_FMT).squeeze(' ').strip
|
437
|
-
today = Date.today
|
438
|
-
today_iso = today.strftime(PICKER_ISO8601_DATE_FMT).squeeze(' ').strip
|
439
|
-
fmt = picker_is_in_24h_locale ? '%e %b' : '%b %e'
|
440
|
-
(picker_iso.eql? today_iso) ? today.strftime(fmt) : res
|
441
|
-
end
|
442
|
-
|
443
|
-
def picker_date_str
|
444
|
-
"#{picker_weekday} #{picker_month_day}".strip.squeeze(' ')
|
445
|
-
end
|
446
|
-
|
447
|
-
def picker_weekday_month_day_is (weekday_month_day)
|
448
|
-
weekday_month_day.eql? picker_date_str
|
449
|
-
end
|
450
|
-
|
451
|
-
# dealing with time
|
452
|
-
|
453
|
-
def picker_hour_24h
|
454
|
-
screenshot_and_raise 'hour is not applicable to this mode' if picker_is_in_countdown_mode or picker_is_in_date_mode
|
455
|
-
# query always returns as 24h
|
456
|
-
res_ios5 = query(PICKER_VIEW_CLASS_IOS5, :hour).first
|
457
|
-
res_ios6 = query(PICKER_VIEW_CLASS_IOS6, :hour).first
|
458
|
-
return res_ios5 != nil ? res_ios5 : res_ios6
|
459
|
-
#query("datePickerView", :hour).first
|
460
|
-
end
|
461
|
-
|
462
|
-
def picker_hour_24h_str
|
463
|
-
screenshot_and_raise 'hour is not applicable to this mode' if picker_is_in_countdown_mode or picker_is_in_date_mode
|
464
|
-
'%02d' % picker_hour_24h
|
465
|
-
end
|
466
|
-
|
467
|
-
def picker_hour_12h
|
468
|
-
screenshot_and_raise 'hour is not applicable to this mode' if picker_is_in_countdown_mode or picker_is_in_date_mode
|
469
|
-
hour_24h = picker_hour_24h
|
470
|
-
return 12 if hour_24h == 0
|
471
|
-
hour_24h > 12 ? hour_24h - 12 : hour_24h
|
472
|
-
end
|
473
|
-
|
474
|
-
def picker_hour_12h_str
|
475
|
-
screenshot_and_raise 'hour is not applicable to this mode' if picker_is_in_countdown_mode or picker_is_in_date_mode
|
476
|
-
"#{picker_hour_12h}"
|
477
|
-
end
|
478
|
-
|
479
|
-
def picker_hour_24h_is (target_hour)
|
480
|
-
target_hour == picker_hour_24h
|
41
|
+
def change_minute_interval_on_picker (target_interval, picker_id=nil)
|
42
|
+
query_str = should_see_date_picker picker_id
|
43
|
+
res = query(query_str, [{setMinuteInterval: target_interval.to_i}])
|
44
|
+
if res.empty?
|
45
|
+
screenshot_and_raise "could not change the minute interval with query '#{query_str}'"
|
46
|
+
end
|
47
|
+
step_pause
|
48
|
+
@picker_minute_interval = target_interval.to_i
|
481
49
|
end
|
482
50
|
|
483
|
-
|
484
|
-
|
485
|
-
|
51
|
+
# does not require a time or date change. picker needs to be visible
|
52
|
+
def should_see_row_has_label_with_time_on_picker(row_id, label_id, options={:picker_id => nil,
|
53
|
+
:table_id => nil})
|
54
|
+
picker_id = options != nil ? options[:picker_id] : nil
|
55
|
+
should_see_date_picker picker_id
|
56
|
+
table_id = options != nil ? options[:table_id] : nil
|
57
|
+
query_str = query_str_for_row_content row_id, table_id
|
58
|
+
arr = query("#{query_str} label marked:'#{label_id}'", :text)
|
486
59
|
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
def picker_minute
|
492
|
-
screenshot_and_raise 'hour is not applicable to this mode' if picker_is_in_countdown_mode or picker_is_in_date_mode
|
493
|
-
res_ios5 = query(PICKER_VIEW_CLASS_IOS5, :minute).first
|
494
|
-
res_ios6 = query(PICKER_VIEW_CLASS_IOS6, :minute).first
|
495
|
-
return res_ios5 != nil ? res_ios5 : res_ios6
|
496
|
-
#query("datePickerView", :minute).first
|
497
|
-
end
|
60
|
+
if arr.empty?
|
61
|
+
screenshot_and_raise "could not find '#{label_id}' in the '#{row_id}'"
|
62
|
+
end
|
498
63
|
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
64
|
+
hash = picker_time_strs_hash picker_id
|
65
|
+
time_str_12h = hash[:h12]
|
66
|
+
time_str_24h = hash[:h24]
|
67
|
+
actual_text = arr.first
|
68
|
+
unless (actual_text.eql? time_str_12h) or (actual_text.eql? time_str_24h)
|
69
|
+
screenshot_and_raise "expected to see '#{time_str_12h}' or '#{time_str_24h}' in '#{label_id}' but found '#{actual_text}'"
|
70
|
+
end
|
503
71
|
end
|
504
72
|
|
505
|
-
|
506
|
-
|
507
|
-
|
73
|
+
# requires picker is visible
|
74
|
+
#noinspection SpellCheckingInspection
|
75
|
+
def should_see_time_on_picker_is_now (options = {:picker_id => nil,
|
76
|
+
:convert_time_to_utc => false})
|
77
|
+
picker_time = ruby_time_from_picker options
|
78
|
+
now_time = Time.now
|
508
79
|
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
80
|
+
convert = convert_to_utc_from_options options
|
81
|
+
if convert
|
82
|
+
now_time = Time.now.utc + now_time.gmt_offset
|
83
|
+
end
|
513
84
|
|
514
|
-
|
515
|
-
|
516
|
-
"#{picker_hour_12h_str}:#{picker_minute_str} #{picker_period}"
|
517
|
-
end
|
85
|
+
# normalize
|
86
|
+
picker_time = picker_time - picker_time.sec
|
518
87
|
|
519
|
-
def picker_time_str
|
520
|
-
screenshot_and_raise 'the time is not applicable for this mode' if picker_is_in_date_mode or picker_is_in_countdown_mode
|
521
|
-
picker_is_in_24h_locale ? picker_time_24h_str : picker_time_12h_str
|
522
|
-
end
|
523
88
|
|
524
|
-
|
525
|
-
time_str = picker_is_in_24h_locale ? picker_time_24h_str : picker_time_12h_str
|
526
|
-
fmt_str = picker_is_in_24h_locale ? PICKER_12H_TIME_FMT : PICKER_24H_TIME_FMT
|
527
|
-
Time.parse(time_str).strftime(fmt_str).squeeze(' ').strip.sub(PICKER_REMOVE_LEADING_ZERO_REGEX, '')
|
528
|
-
end
|
89
|
+
now_time = now_time - now_time.sec
|
529
90
|
|
530
|
-
|
91
|
+
picker_id = picker_id_from_options options
|
92
|
+
minute_interval = picker_minute_interval picker_id
|
531
93
|
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
end
|
94
|
+
if minute_interval == 1 and not (picker_time == now_time)
|
95
|
+
screenshot_and_raise "should see picker with time '#{now_time}' but found '#{picker_time}'"
|
96
|
+
end
|
536
97
|
|
537
|
-
|
538
|
-
|
539
|
-
"#{picker_date_str} #{picker_time_12h_str}"
|
540
|
-
end
|
98
|
+
max_time = now_time + (minute_interval * 60)
|
99
|
+
min_time = now_time - (minute_interval * 60)
|
541
100
|
|
542
|
-
|
543
|
-
|
101
|
+
unless picker_time >= min_time && picker_time <= max_time
|
102
|
+
p " min: '#{min_time}'"
|
103
|
+
p "target: '#{picker_time}'"
|
104
|
+
p " max: '#{max_time}'"
|
105
|
+
screenshot_and_raise "should see picker with time between '#{min_time}' and '#{max_time}' but found '#{picker_time}'"
|
106
|
+
end
|
544
107
|
end
|
545
108
|
|
546
|
-
def
|
547
|
-
|
548
|
-
end
|
109
|
+
def change_time_on_picker_to_minutes_from_now (target_minutes, options={:picker_id => nil,
|
110
|
+
:convert_time_to_utc => false})
|
549
111
|
|
550
|
-
|
112
|
+
picker_id = picker_id_from_options options
|
113
|
+
convert = convert_to_utc_from_options options
|
551
114
|
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
end
|
115
|
+
if convert
|
116
|
+
future = Time.now.gmtime + Time.now.gmtoff + (target_minutes.to_i * 60)
|
117
|
+
else
|
118
|
+
future = Time.new + (60 * target_minutes.to_i)
|
119
|
+
end
|
558
120
|
|
559
|
-
|
560
|
-
|
561
|
-
end
|
121
|
+
opts = {:picker_id => picker_id,
|
122
|
+
:convert_time_to_utc => convert}
|
562
123
|
|
563
|
-
|
564
|
-
now_times_map[:h12]
|
124
|
+
change_time_on_picker_with_time future, opts
|
565
125
|
end
|
566
126
|
|
567
|
-
|
568
|
-
|
569
|
-
def picker_scroll_to_hour (target_hour_int_24h_notation)
|
570
|
-
screenshot_and_raise 'nyi' if picker_is_in_countdown_mode
|
571
|
-
column = picker_column_for_hour
|
572
|
-
limit = 25
|
573
|
-
count = 0
|
574
|
-
unless picker_hour_24h_is target_hour_int_24h_notation
|
575
|
-
begin
|
576
|
-
picker_scroll_up_on_column(column)
|
577
|
-
sleep(PICKER_STEP_PAUSE)
|
578
|
-
count = count + 1
|
579
|
-
end while (not picker_hour_24h_is target_hour_int_24h_notation) and count < limit
|
580
|
-
end
|
581
|
-
unless picker_hour_24h_is target_hour_int_24h_notation
|
582
|
-
screenshot_and_raise "scrolled '#{limit}' but could not change hour to '#{target_hour_int_24h_notation}'"
|
583
|
-
end
|
584
|
-
end
|
127
|
+
def change_time_on_picker_to_minutes_before_now (target_minutes, options={:picker_id => nil,
|
128
|
+
:convert_time_to_utc => false})
|
585
129
|
|
586
|
-
|
587
|
-
|
588
|
-
column = picker_column_for_minute
|
589
|
-
limit = 61
|
590
|
-
count = 0
|
591
|
-
unless picker_minute_is target_minute_int
|
592
|
-
begin
|
593
|
-
picker_scroll_up_on_column(column)
|
594
|
-
sleep(PICKER_STEP_PAUSE)
|
595
|
-
count = count + 1
|
596
|
-
end while (not picker_minute_is target_minute_int) and count < limit
|
597
|
-
end
|
598
|
-
unless picker_minute_is target_minute_int
|
599
|
-
screenshot_and_raise "scrolled '#{limit}' but could not change minute to '#{target_minute_int}'"
|
600
|
-
end
|
601
|
-
end
|
130
|
+
picker_id = options != nil ? options[:picker_id] : nil
|
131
|
+
convert = options != nil ? options[:convert_time_to_utc] : false
|
602
132
|
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
limit = 3
|
608
|
-
count = 0
|
609
|
-
unless picker_period.eql? target_period_str
|
610
|
-
begin
|
611
|
-
if picker_period_is_am?
|
612
|
-
scroll_to_row("pickerTableView index:#{column}", 1)
|
613
|
-
else
|
614
|
-
scroll_to_row("pickerTableView index:#{column}", 0)
|
615
|
-
end
|
616
|
-
sleep(PICKER_STEP_PAUSE)
|
617
|
-
count = count + 1
|
618
|
-
end while (not picker_period.eql? target_period_str) and count < limit
|
133
|
+
if convert
|
134
|
+
past = Time.now.gmtime + Time.now.gmtoff - (target_minutes.to_i * 60)
|
135
|
+
else
|
136
|
+
past = Time.new - (60 * target_minutes.to_i)
|
619
137
|
end
|
620
|
-
unless picker_period.eql? target_period_str
|
621
|
-
screenshot_and_raise "scrolled '#{limit}' but could not change period to '#{target_period_str}'"
|
622
|
-
end
|
623
|
-
end
|
624
138
|
|
139
|
+
opts = {:picker_id => picker_id,
|
140
|
+
:convert_time_to_utc => convert}
|
625
141
|
|
626
|
-
|
627
|
-
|
628
|
-
def time_strings_are_equivalent (a, b)
|
629
|
-
a_iso_str = Time.parse(a).strftime(PICKER_ISO8601_TIME_FMT)
|
630
|
-
b_iso_str = Time.parse(b).strftime(PICKER_ISO8601_TIME_FMT)
|
631
|
-
a_iso_str.eql? b_iso_str
|
632
|
-
end
|
633
|
-
|
634
|
-
def date_time_strings_are_equivalent (a, b)
|
635
|
-
a_iso_str = Date.parse(a).strftime(PICKER_ISO8601_DATE_TIME_FMT)
|
636
|
-
b_iso_str = Date.parse(b).strftime(PICKER_ISO8601_DATE_TIME_FMT)
|
637
|
-
a_iso_str.eql? b_iso_str
|
142
|
+
change_time_on_picker_with_time past, opts
|
638
143
|
end
|
639
|
-
|
640
144
|
end
|
641
145
|
end
|
642
146
|
end
|