sunomono 0.2.0.pre
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 +7 -0
- data/.gitignore +17 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +22 -0
- data/README.md +157 -0
- data/Rakefile +1 -0
- data/bin/suno +3 -0
- data/bin/sunomono +3 -0
- data/lib/aws/android/app_installation_hooks.rb +30 -0
- data/lib/aws/android/app_life_cycle_hooks.rb +13 -0
- data/lib/aws/ios/01_launch.rb +43 -0
- data/lib/helpers/sunomono_helpers.rb +136 -0
- data/lib/helpers/zip_helpers.rb +49 -0
- data/lib/skeleton/.gitignore +9 -0
- data/lib/skeleton/Gemfile +7 -0
- data/lib/skeleton/README.md +165 -0
- data/lib/skeleton/config/cucumber.yml +7 -0
- data/lib/skeleton/config/email/template.html +14 -0
- data/lib/skeleton/config/load_classes.rb +31 -0
- data/lib/skeleton/config/scripts/android/run_tests_all_devices.sh +41 -0
- data/lib/skeleton/config/scripts/android/start_emulators.sh +52 -0
- data/lib/skeleton/config/scripts/android/stop_emulators.sh +13 -0
- data/lib/skeleton/config/scripts/break_build_if_failed.sh +6 -0
- data/lib/skeleton/config/scripts/check_if_tests_failed.sh +11 -0
- data/lib/skeleton/config/scripts/ios/build_app.rb +71 -0
- data/lib/skeleton/config/scripts/ios/build_app.yml +13 -0
- data/lib/skeleton/config/scripts/ios/devices.txt +4 -0
- data/lib/skeleton/config/scripts/ios/run_tests_all_devices.sh +57 -0
- data/lib/skeleton/features/android/features/.gitkeep +0 -0
- data/lib/skeleton/features/android/screens/.gitkeep +0 -0
- data/lib/skeleton/features/android/step_definitions/.gitkeep +0 -0
- data/lib/skeleton/features/android/support/app_installation_hooks.rb +36 -0
- data/lib/skeleton/features/android/support/app_life_cycle_hooks.rb +11 -0
- data/lib/skeleton/features/android/support/hooks.rb +0 -0
- data/lib/skeleton/features/ios/features/.gitkeep +0 -0
- data/lib/skeleton/features/ios/screens/.gitkeep +0 -0
- data/lib/skeleton/features/ios/step_definitions/.gitkeep +0 -0
- data/lib/skeleton/features/ios/support/01_launch.rb +94 -0
- data/lib/skeleton/features/ios/support/02_pre_stop_hooks.rb +0 -0
- data/lib/skeleton/features/support/env.rb +5 -0
- data/lib/skeleton/features/support/exceptions.rb +11 -0
- data/lib/skeleton/screenshots/android/.gitkeep +0 -0
- data/lib/skeleton/screenshots/ios/.gitkeep +0 -0
- data/lib/sunomono.rb +238 -0
- data/lib/sunomono/locales/en.yml +27 -0
- data/lib/sunomono/locales/pt.yml +27 -0
- data/lib/sunomono/version.rb +3 -0
- data/lib/templates/android_screen_base.tt +186 -0
- data/lib/templates/base_steps.tt +48 -0
- data/lib/templates/feature.tt +8 -0
- data/lib/templates/ios_screen_base.tt +249 -0
- data/lib/templates/screen.tt +13 -0
- data/lib/templates/steps.tt +5 -0
- data/sunomono.gemspec +27 -0
- 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,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
|