sunomono 0.2.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +9 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +157 -0
  6. data/Rakefile +1 -0
  7. data/bin/suno +3 -0
  8. data/bin/sunomono +3 -0
  9. data/lib/aws/android/app_installation_hooks.rb +30 -0
  10. data/lib/aws/android/app_life_cycle_hooks.rb +13 -0
  11. data/lib/aws/ios/01_launch.rb +43 -0
  12. data/lib/helpers/sunomono_helpers.rb +136 -0
  13. data/lib/helpers/zip_helpers.rb +49 -0
  14. data/lib/skeleton/.gitignore +9 -0
  15. data/lib/skeleton/Gemfile +7 -0
  16. data/lib/skeleton/README.md +165 -0
  17. data/lib/skeleton/config/cucumber.yml +7 -0
  18. data/lib/skeleton/config/email/template.html +14 -0
  19. data/lib/skeleton/config/load_classes.rb +31 -0
  20. data/lib/skeleton/config/scripts/android/run_tests_all_devices.sh +41 -0
  21. data/lib/skeleton/config/scripts/android/start_emulators.sh +52 -0
  22. data/lib/skeleton/config/scripts/android/stop_emulators.sh +13 -0
  23. data/lib/skeleton/config/scripts/break_build_if_failed.sh +6 -0
  24. data/lib/skeleton/config/scripts/check_if_tests_failed.sh +11 -0
  25. data/lib/skeleton/config/scripts/ios/build_app.rb +71 -0
  26. data/lib/skeleton/config/scripts/ios/build_app.yml +13 -0
  27. data/lib/skeleton/config/scripts/ios/devices.txt +4 -0
  28. data/lib/skeleton/config/scripts/ios/run_tests_all_devices.sh +57 -0
  29. data/lib/skeleton/features/android/features/.gitkeep +0 -0
  30. data/lib/skeleton/features/android/screens/.gitkeep +0 -0
  31. data/lib/skeleton/features/android/step_definitions/.gitkeep +0 -0
  32. data/lib/skeleton/features/android/support/app_installation_hooks.rb +36 -0
  33. data/lib/skeleton/features/android/support/app_life_cycle_hooks.rb +11 -0
  34. data/lib/skeleton/features/android/support/hooks.rb +0 -0
  35. data/lib/skeleton/features/ios/features/.gitkeep +0 -0
  36. data/lib/skeleton/features/ios/screens/.gitkeep +0 -0
  37. data/lib/skeleton/features/ios/step_definitions/.gitkeep +0 -0
  38. data/lib/skeleton/features/ios/support/01_launch.rb +94 -0
  39. data/lib/skeleton/features/ios/support/02_pre_stop_hooks.rb +0 -0
  40. data/lib/skeleton/features/support/env.rb +5 -0
  41. data/lib/skeleton/features/support/exceptions.rb +11 -0
  42. data/lib/skeleton/screenshots/android/.gitkeep +0 -0
  43. data/lib/skeleton/screenshots/ios/.gitkeep +0 -0
  44. data/lib/sunomono.rb +238 -0
  45. data/lib/sunomono/locales/en.yml +27 -0
  46. data/lib/sunomono/locales/pt.yml +27 -0
  47. data/lib/sunomono/version.rb +3 -0
  48. data/lib/templates/android_screen_base.tt +186 -0
  49. data/lib/templates/base_steps.tt +48 -0
  50. data/lib/templates/feature.tt +8 -0
  51. data/lib/templates/ios_screen_base.tt +249 -0
  52. data/lib/templates/screen.tt +13 -0
  53. data/lib/templates/steps.tt +5 -0
  54. data/sunomono.gemspec +27 -0
  55. metadata +184 -0
@@ -0,0 +1,27 @@
1
+ en:
2
+ android_only: "(Android Only)"
3
+ ios_only: "(iOS Only)"
4
+ first_scenario: "First Scenario"
5
+ comments:
6
+ trait: "The screen identificator"
7
+ insert_steps: "Insert steps"
8
+ elements: "Declare all the elements of this screen"
9
+ actions: "Declare all actions of this screen"
10
+ steps:
11
+ drag_until: 'I (?:drag|dragged) the screen (down|up|left|right) until I see the element "(.*?)"'
12
+ page_contains: "I am on a page that contains '(.*?)'"
13
+ drag_number_of_times: 'I drag the screen (left|right|down|up) (\d+) times'
14
+ touch_element: 'I (?:touch|touched) the "(.*?)" element'
15
+ drag_screen: "I drag the screen (down|up|left|right)"
16
+ wait_progress_bar: "I (?:wait|waited) for the progress bar to vanish"
17
+ should_see_page: "I should see the page '(.*?)'"
18
+ should_see_page_that_contains: "I should see a page that contains '(.*?)'"
19
+ take_print: "take picture"
20
+ been_in_page: "I am at (?:page|screen) '(.*?)'"
21
+ move_to_page: "I went to (?:page|screen) '(.*?)'"
22
+ restart_app: "I restart the app"
23
+ directions:
24
+ up: 'up'
25
+ down: 'down'
26
+ left: 'left'
27
+ right: 'right'
@@ -0,0 +1,27 @@
1
+ pt:
2
+ android_only: "(Somente Android)"
3
+ ios_only: "(Somente iOS)"
4
+ first_scenario: "Primeiro Cenario"
5
+ comments:
6
+ trait: "Identificador da tela"
7
+ insert_steps: "Insira os passos"
8
+ elements: "Declare todos os elementos da tela"
9
+ actions: "Declare todas as acoes da tela"
10
+ steps:
11
+ drag_until: 'que Eu (?:arrastei|arrasto) a tela para (baixo|cima|esquerda|direita) ate ver o elemento "(.*?)"'
12
+ page_contains: "que Eu estou em uma pagina que contem '(.*?)'"
13
+ drag_number_of_times: 'Eu arrasto a tela para (esquerda|direita|baixo|cima) (\d+) vezes'
14
+ touch_element: 'Eu (?:clico|cliquei) no elemento "(.*?)"'
15
+ drag_screen: "Eu arrasto a tela para (baixo|cima|esquerda|direita)"
16
+ wait_progress_bar: "Eu (?:espero|esperei) ate a barra de progresso sumir"
17
+ should_see_page: "Eu deveria ver a pagina '(.*?)'"
18
+ should_see_page_that_contains: "Eu deveria ver uma pagina que contem '(.*?)'"
19
+ take_print: "faco um print"
20
+ been_in_page: "que eu (?:estou|estava) na (?:pagina|tela)(?: de|) '(.*?)'"
21
+ move_to_page: "eu (?:devo|deveria) estar na (?:pagina|tela)(?: de|) '(.*?)'"
22
+ restart_app: "(?:Eu |)reiniciar o aplicativo"
23
+ directions:
24
+ up: 'cima'
25
+ down: 'baixo'
26
+ left: 'esquerda'
27
+ right: 'direita'
@@ -0,0 +1,3 @@
1
+ module Sunomono
2
+ VERSION = '0.2.0.pre'.freeze
3
+ end
@@ -0,0 +1,186 @@
1
+ require 'calabash-android/abase'
2
+
3
+ class AndroidScreenBase < Calabash::ABase
4
+ def self.element(element_name, &block)
5
+ define_method(element_name.to_s, *block)
6
+ end
7
+
8
+ class << self
9
+ alias_method :value, :element
10
+ alias_method :action, :element
11
+ alias_method :trait, :element
12
+ end
13
+
14
+ def restart_app
15
+ shutdown_test_server
16
+ start_test_server_in_background
17
+ end
18
+
19
+ def method_missing(method, *args)
20
+ if method.to_s.start_with?('touch_')
21
+ # If method name starts with touch_, executes the touch
22
+ # screen element method using the element name which is the
23
+ # method name without the first 'touch_' chars
24
+ touch_screen_element public_send(method.to_s.sub('touch_', ''))
25
+ elsif method.to_s.start_with?('enter_')
26
+ # If method starts with enter_, execute the enter method using
27
+ # the field name, which is the method name without the initial
28
+ # 'enter_' chars and appended '_field' chars
29
+ enter args[0], public_send("#{method.to_s.sub('enter_', '')}_field")
30
+ elsif method.to_s.end_with?('_visible?')
31
+ # If method ends with _visible?, executes the visible? method
32
+ # The field name is the method name without de ending
33
+ # '_visible? chars
34
+ visible? public_send(method.to_s.sub('_visible?', ''))
35
+ elsif method.to_s.end_with?('_visible!')
36
+ # Do the same as the method above, but throws an exception
37
+ # if the field is not visible
38
+ field_name = method.to_s.sub('_visible!', '')
39
+ .sub('_field', '')
40
+ .sub('_', ' ')
41
+ .capitalize
42
+ raise ElementNotFoundError, "ID: #{field_name}" unless
43
+ visible? public_send(method.to_s.sub('_visible!', ''))
44
+ else
45
+ super(method, args)
46
+ end
47
+ end
48
+
49
+ def visible?(id, query = nil)
50
+ query = "* id:'#{id}'" if query.nil?
51
+ begin
52
+ wait_for(timeout: 3) { element_exists query }
53
+ rescue
54
+ return false
55
+ end
56
+ true
57
+ end
58
+
59
+ element(:loading_screen) { 'insert_loading_view_id' }
60
+
61
+ # The progress bar of the application is a custom view
62
+ def wait_for_progress
63
+ sleep(2)
64
+ wait_for_element_does_not_exist("* id:'#{loading_screen}'",
65
+ timeout: 10)
66
+ end
67
+
68
+ def drag_to(direction)
69
+ positions = [0, 0, 0, 0] # [ 'from_x', 'to_x', 'from_y', 'to_y' ]
70
+
71
+ case(direction)
72
+ when :<%= (I18n.translate "directions.down").to_sym %>
73
+ positions = [30,30,60,30]
74
+ when :<%= (I18n.translate "directions.up").to_sym %>
75
+ positions = [80,80,60,90]
76
+ when :<%= (I18n.translate "directions.left").to_sym %>
77
+ positions = [90,20,80,80]
78
+ when :<%= (I18n.translate "directions.right").to_sym %>
79
+ positions = [20,90,80,80]
80
+ else
81
+ raise 'Direction not known!'
82
+ end
83
+
84
+ # perform_action( 'action', 'from_x', 'to_x', 'from_y', 'to_y',
85
+ # 'number of steps (in this case, velocity of drag' )
86
+ perform_action('drag', positions[0], positions[1],
87
+ positions[2], positions[3], 15)
88
+ sleep(1)
89
+ end
90
+
91
+ def drag_until_element_is_visible_with_special_query(direction, element)
92
+ drag_until_element_is_visible direction, element,
93
+ "* {text CONTAINS[c] '#{element}'}"
94
+ end
95
+
96
+ def drag_until_element_is_visible(direction, element, query = nil, limit = 15)
97
+ i = 0
98
+
99
+ element_query = ''
100
+ if query.nil?
101
+ element_query = "* marked:'#{element}'"
102
+ else
103
+ element_query = query
104
+ end
105
+
106
+ sleep(2)
107
+ while !element_exists(element_query) && i < limit
108
+ drag_to direction
109
+ i += 1
110
+ end
111
+
112
+ fail "Executed #{limit} moviments #{direction} and "\
113
+ "the element '#{element}' was not found on this view!" unless
114
+ i < limit
115
+ end
116
+
117
+ def drag_for_specified_number_of_times(direction, times)
118
+ times.times do
119
+ drag_to direction
120
+ end
121
+ end
122
+
123
+ # Negation indicates that we want a page that doesn't
124
+ # has the message passed as parameter
125
+ def is_on_page?(page_text, negation = '')
126
+ fail 'Error! Invalid query string!' if
127
+ page_text.to_s == ''
128
+
129
+ should_not_have_exception = false
130
+ should_have_exception = false
131
+ begin
132
+ wait_for(timeout: 5) { has_text? page_text }
133
+ # If negation is not nil, we should raise an error
134
+ # if this message was found on the view
135
+ should_not_have_exception = true unless negation == ''
136
+ rescue
137
+ # only raise exception if negation is nil,
138
+ # otherwise this is the expected behaviour
139
+ should_have_exception = true if negation == ''
140
+ end
141
+
142
+ fail "Unexpected Page. The page should not have: '#{page_text}'" if
143
+ should_not_have_exception
144
+
145
+ fail "Unexpected Page. Expected was: '#{page_text}'" if
146
+ should_have_exception
147
+ end
148
+
149
+ def enter(text, element, query = nil)
150
+ if query.nil?
151
+ query("* marked:'#{element}'", setText: text.to_s)
152
+ else
153
+ query(query, setText: text.to_s)
154
+ end
155
+ end
156
+
157
+ def touch_screen_element(element, query = nil)
158
+ query = "* id:'#{element}'" if query.nil?
159
+ begin
160
+ wait_for(timeout: 5) { element_exists(query) }
161
+ touch(query)
162
+ rescue => e
163
+ raise "Problem in touch screen element: '#{element}'\nError Message: #{e.message}"
164
+ end
165
+ end
166
+
167
+ def touch_element_by_index(id, index)
168
+ wait_for(timeout: 5) { element_exists("* id:'#{id}' index:#{index}") }
169
+ touch("* id:'#{id}' index:#{index}")
170
+ end
171
+
172
+ def clear_text_field(field)
173
+ clear_text_in("android.widget.EditText id:'#{field}'}")
174
+ end
175
+
176
+ def select_date_on_date_picker(date, date_picker_field_id)
177
+ # Touch the date picker field
178
+ touch "* id:'#{date_picker_field_id}'"
179
+
180
+ # Setting the date
181
+ set_date 'DatePicker', date.year, date.month, date.day
182
+
183
+ # Clicking in the Done button
184
+ touch "* id:'button1'"
185
+ end
186
+ end
@@ -0,0 +1,48 @@
1
+ ######### <%= I18n.translate( :given ).upcase %> #########
2
+ <%= I18n.translate( :given ).capitalize %>(/^<%= I18n.translate( "steps.drag_until" ) %>$/) do |direction, element|
3
+ @page.drag_until_element_is_visible_with_special_query direction.to_sym, element
4
+ end
5
+
6
+ <%= I18n.translate( :given ).capitalize %>(/^<%= I18n.translate( "steps.page_contains" ) %>$/) do |page_text|
7
+ @page.is_on_page? page_text
8
+ end
9
+
10
+ ######### <%= I18n.translate( :when ).upcase %> #########
11
+
12
+ <%= I18n.translate( :when ).capitalize %>(/^<%= I18n.translate( "steps.drag_number_of_times" ) %>$/) do |direction, times|
13
+ @page.drag_for_specified_number_of_times(direction.to_sym, times.to_i)
14
+ end
15
+
16
+ <%= I18n.translate( :when ).capitalize %>(/^<%= I18n.translate( "steps.touch_element" ) %>$/) do |element|
17
+ @page.touch_screen_element element
18
+ end
19
+
20
+ <%= I18n.translate( :when ).capitalize %>(/^<%= I18n.translate( "steps.drag_screen" ) %>$/) do |direction|
21
+ @page.drag_to direction.to_sym
22
+ end
23
+
24
+ <%= I18n.translate( :when ).capitalize %>(/^<%= I18n.translate( "steps.restart_app" ) %>$/) do
25
+ @page.restart_app
26
+ end
27
+
28
+ ######### <%= I18n.translate( :then ).upcase %> #########
29
+
30
+ <%= I18n.translate( :then ).capitalize %>(/^<%= I18n.translate "steps.wait_progress_bar" %>$/) do
31
+ # wait_for_progress is a method of the base class, so doesn't matter what is
32
+ # the value of the @page variable, because all screens will have this method
33
+ @page.wait_for_progress
34
+ end
35
+
36
+ <%= I18n.translate( :then ).capitalize %>(/^<%= I18n.translate "steps.should_see_page" %>$/) do |page_text|
37
+ @page.is_on_page? page_text
38
+ end
39
+
40
+ <%= I18n.translate( :then ).capitalize %>(/^<%= I18n.translate "steps.should_see_page_that_contains" %>$/) do |page_text|
41
+ @page.is_on_page? page_text
42
+ end
43
+ <% unless I18n.config.default_locale == :en %>
44
+
45
+ <%= I18n.translate( :then ).capitalize %>(/^<%= I18n.translate "steps.take_print" %>$/) do
46
+ screenshot_embed
47
+ end
48
+ <% end %>
@@ -0,0 +1,8 @@
1
+ <%= "# language: #{options[:lang]}" %>
2
+ <%= I18n.translate( :feature ) %>: <%= config[:name] %> <%= !config[:platform].empty? ? I18n.translate( "#{config[:platform].downcase}_only") : "" %>
3
+
4
+ <%= I18n.translate( :background ) %>:
5
+ # <%= I18n.translate( "comments.insert_steps" ) %>
6
+
7
+ <%= I18n.translate( :scenario ) %>: <%= I18n.translate( :first_scenario ) %>
8
+ # <%= I18n.translate( "comments.insert_steps" ) %>
@@ -0,0 +1,249 @@
1
+ require 'calabash-cucumber/ibase'
2
+
3
+ class IOSScreenBase < Calabash::IBase
4
+ def self.element(element_name, &block)
5
+ define_method(element_name.to_s, *block)
6
+ end
7
+
8
+ class << self
9
+ alias_method :value, :element
10
+ alias_method :action, :element
11
+ alias_method :trait, :element
12
+ end
13
+
14
+ def restart_app
15
+ # Relaunch options
16
+ options = { timeout: 3000 }
17
+
18
+ launcher.relaunch(options)
19
+ launcher.calabash_notify(self)
20
+ end
21
+
22
+ def method_missing(method, *args)
23
+ if method.to_s.start_with?('touch_')
24
+ # If method name starts with touch_, executes the touch
25
+ # screen element method using the element name which is the
26
+ # method name without the first 'touch_' chars
27
+ touch_screen_element public_send(method.to_s.sub('touch_', ''))
28
+ elsif method.to_s.start_with?('enter_')
29
+ # If method starts with enter_, execute the enter method using
30
+ # the field name, which is the method name without the initial
31
+ # 'enter_' chars and appended '_field' chars
32
+ enter args[0], public_send("#{method.to_s.sub('enter_', '')}_field")
33
+ elsif method.to_s.end_with?('_visible?')
34
+ # If method ends with _visible?, executes the visible? method
35
+ # The field name is the method name without de ending
36
+ # '_visible? chars
37
+ visible? public_send(method.to_s.sub('_visible?', ''))
38
+ elsif method.to_s.end_with?('_visible!')
39
+ # Do the same as the method above, but throws an exception
40
+ # if the field is not visible
41
+ field_name = method.to_s.sub('_visible!', '')
42
+ .sub('_field', '')
43
+ .sub('_', ' ')
44
+ .capitalize
45
+ raise ElementNotFoundError, "ID: #{field_name}" unless
46
+ visible? public_send(method.to_s.sub('_visible!', ''))
47
+ else
48
+ super(method, args)
49
+ end
50
+ end
51
+
52
+ def visible?(id, query = nil)
53
+ query = "* id:'#{id}'" if query.nil?
54
+ begin
55
+ wait_for(timeout: 3) { element_exists query }
56
+ rescue
57
+ return false
58
+ end
59
+ true
60
+ end
61
+
62
+
63
+ element(:loading_screen) { 'LOADING' }
64
+
65
+ # The progress bar of the application is a custom view
66
+ def wait_for_progress
67
+ sleep(2)
68
+ wait_for(timeout: 10) { element_does_not_exist "* marked:'#{loading_screen}'" }
69
+ end
70
+
71
+ def has_text?(text)
72
+ !query("* {text CONTAINS[c] '#{text}'}").empty? ||
73
+ !query("* {accessibilityLabel CONTAINS[c] '#{text}'}").empty?
74
+ end
75
+
76
+ def drag_to(direction, element = nil)
77
+ element = 'scrollView' if element.nil?
78
+
79
+ case direction
80
+ when :<%= (I18n.translate "directions.down").to_sym %>
81
+ direction = { x: 0, y: -100 }
82
+ when :<%= (I18n.translate "directions.up").to_sym %>
83
+ direction = { x: 0, y: 100 }
84
+ when :<%= (I18n.translate "directions.left").to_sym %>
85
+ direction = { x: 100, y: 0 }
86
+ when :<%= (I18n.translate "directions.right").to_sym %>
87
+ direction = { x: -100, y: 0 }
88
+ else
89
+ raise 'Direction not known!'
90
+ end
91
+
92
+ flick(element, direction)
93
+ sleep(1)
94
+ end
95
+
96
+ # In the iOS, an element could be found from its text or its accessibilityLabel
97
+ # so this function looks for these two properties on the screen. When the query
98
+ # looks for just a part of the text (CONTAINS[c]) then we need to specify if
99
+ # we will look in accessibilityLabel or in any other propertie (marked)
100
+ def ios_element_exists?(query)
101
+ second_query = nil
102
+
103
+ if query.include? 'CONTAINS[c]'
104
+ if query.include? 'marked'
105
+ second_query = query.gsub('marked', 'accessibilityLabel')
106
+ end
107
+ if query.include? 'accessibilityLabel'
108
+ second_query = query.gsub('accessibilityLabel', 'marked')
109
+ end
110
+ end
111
+
112
+ if second_query.nil?
113
+ return element_exists(query)
114
+ else
115
+ element_exists(query) || element_exists(second_query)
116
+ end
117
+ end
118
+
119
+ def drag_until_element_is_visible_with_special_query(direction, element)
120
+ drag_until_element_is_visible direction, element,
121
+ "* {accessibilityLabel CONTAINS[c] '#{element}'}"
122
+ end
123
+
124
+ def drag_until_element_is_visible(direction, element, query = nil, limit = 15)
125
+ i = 0
126
+
127
+ query = "* marked:'#{element}'" if query.nil?
128
+
129
+ sleep(1)
130
+ while !ios_element_exists?(query) && i < limit
131
+ drag_to direction
132
+ i += 1
133
+ end
134
+
135
+ fail "Executed #{limit} moviments #{direction} and the "\
136
+ "element '#{element}' was not found on this view!" unless i < limit
137
+ end
138
+
139
+ def drag_for_specified_number_of_times(direction, times)
140
+ times.times do
141
+ drag_to direction
142
+ end
143
+ end
144
+
145
+ # Negation indicates that we want a page that doesn't has
146
+ # the message passed as parameter
147
+ def is_on_page?(page_text, negation = '')
148
+ fail 'Error! Invalid query string!' if
149
+ page_text.to_s == ''
150
+
151
+ should_not_have_exception = false
152
+ should_have_exception = false
153
+ begin
154
+ wait_for(timeout: 5) { has_text? page_text }
155
+ # If negation is not nil, we should raise an error
156
+ # if this message was found on the view
157
+ should_not_have_exception = true unless negation == ''
158
+ rescue
159
+ # only raise exception if negation is nil,
160
+ # otherwise this is the expected behaviour
161
+ should_have_exception = true if negation == ''
162
+ end
163
+
164
+ fail "Unexpected Page. The page should not have: '#{page_text}'" if
165
+ should_not_have_exception
166
+
167
+ fail "Unexpected Page. Expected was: '#{page_text}'" if
168
+ should_have_exception
169
+ end
170
+
171
+ def enter(text, element, query = nil)
172
+ query = "* marked:'#{element}'" if query.nil?
173
+
174
+ begin
175
+ wait_for(timeout: 5) { element_exists query }
176
+ rescue
177
+ # Just a better exception message
178
+ raise "Element '#{element}' not found on view!"
179
+ end
180
+
181
+ touch query
182
+ # Waits up to 20 seconds for the keyboard to show up
183
+ begin
184
+ wait_for(timeout: 10) { element_exists("view:'UIKeyboardAutomatic'") }
185
+ rescue
186
+ # If the keyboard didn't show up, tries another time
187
+ # before rainsing the error message
188
+ touch query
189
+ wait_for(timeout: 5) { element_exists("view:'UIKeyboardAutomatic'") }
190
+ end
191
+
192
+ keyboard_enter_text text
193
+ end
194
+
195
+ def touch_screen_element(element, query = nil)
196
+ query = "* marked:'#{element}'" if query.nil?
197
+ begin
198
+ wait_for(timeout: 5) { element_exists(query) }
199
+ touch query
200
+ rescue => e
201
+ raise "Problem in touch screen element: '#{element}'\nError Message: #{e.message}"
202
+ end
203
+ end
204
+
205
+ def touch_element_by_index(id, index)
206
+ query = "* marked:'#{id}' index:#{index}"
207
+ wait_for(timeout: 5) { element_exists(query) }
208
+ touch(query)
209
+ end
210
+
211
+ def clear_text_field(field)
212
+ clear_text("textField marked:'#{field}'")
213
+ end
214
+
215
+ def select_date_on_date_picker(date, date_picker_field_id)
216
+ # Touch the date picker element
217
+ touch_screen_element date_picker_field_id
218
+ # Waiting for the date picker to show up
219
+ wait_for(timeout: 5) { element_exists("view:'UIDatePicker'") }
220
+
221
+ # If date is today, then we have nothing to do
222
+ if date.year != DateTime.now.year ||
223
+ date.month != DateTime.now.month ||
224
+ date.day != DateTime.now.day
225
+ # Selecting 'date' on the date picker
226
+ picker_set_date_time date
227
+ end
228
+
229
+ # Touch the OK button
230
+ touch_screen_element 'Ok'
231
+ end
232
+
233
+ def touch_picker_item_by_index(index)
234
+ label = query('pickerView', :delegate,
235
+ [{ pickerView: nil }, { titleForRow: index },
236
+ { forComponent: 0 }])
237
+
238
+ # Exception if element no found
239
+ fail "Picker item index #{index} not found." if label.nil?
240
+ # Label is an array of 1 element. Just picking the first.
241
+ label = label.first
242
+
243
+ # Touching the first item using it's text and Javascript function
244
+ uia(%[uia.selectPickerValues('{0 "#{label}"}')])
245
+
246
+ # Touching the OK button to close the Picker
247
+ touch "* marked:'OK'"
248
+ end
249
+ end