calabash 1.2.1 → 1.9.9.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (137) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +39 -0
  3. data/LICENSE +204 -21
  4. data/README.md +36 -6
  5. data/VERSIONING.md +16 -0
  6. data/bin/calabash +95 -0
  7. data/lib/calabash.rb +185 -1
  8. data/lib/calabash/android.rb +64 -0
  9. data/lib/calabash/android/adb.rb +277 -0
  10. data/lib/calabash/android/application.rb +110 -0
  11. data/lib/calabash/android/build.rb +12 -0
  12. data/lib/calabash/android/build/application.rb +13 -0
  13. data/lib/calabash/android/build/build_error.rb +11 -0
  14. data/lib/calabash/android/build/builder.rb +119 -0
  15. data/lib/calabash/android/build/java_keystore.rb +177 -0
  16. data/lib/calabash/android/build/resigner.rb +56 -0
  17. data/lib/calabash/android/build/test_server.rb +27 -0
  18. data/lib/calabash/android/console_helpers.rb +44 -0
  19. data/lib/calabash/android/cucumber.rb +3 -0
  20. data/lib/calabash/android/device.rb +965 -0
  21. data/lib/calabash/android/environment.rb +470 -0
  22. data/lib/calabash/android/gestures.rb +369 -0
  23. data/lib/calabash/android/interactions.rb +45 -0
  24. data/lib/calabash/android/lib/.irbrc +55 -0
  25. data/lib/calabash/android/lib/AndroidManifest.xml +51 -0
  26. data/lib/calabash/android/lib/TestServer.apk +0 -0
  27. data/lib/calabash/android/lib/calmd5/arm64-v8a/calmd5 +0 -0
  28. data/lib/calabash/android/lib/calmd5/arm64-v8a/calmd5-pie +0 -0
  29. data/lib/calabash/android/lib/calmd5/armeabi-v7a/calmd5 +0 -0
  30. data/lib/calabash/android/lib/calmd5/armeabi-v7a/calmd5-pie +0 -0
  31. data/lib/calabash/android/lib/calmd5/armeabi/calmd5 +0 -0
  32. data/lib/calabash/android/lib/calmd5/armeabi/calmd5-pie +0 -0
  33. data/lib/calabash/android/lib/calmd5/mips/calmd5 +0 -0
  34. data/lib/calabash/android/lib/calmd5/mips/calmd5-pie +0 -0
  35. data/lib/calabash/android/lib/calmd5/mips64/calmd5 +0 -0
  36. data/lib/calabash/android/lib/calmd5/mips64/calmd5-pie +0 -0
  37. data/lib/calabash/android/lib/calmd5/x86/calmd5 +0 -0
  38. data/lib/calabash/android/lib/calmd5/x86/calmd5-pie +0 -0
  39. data/lib/calabash/android/lib/calmd5/x86_64/calmd5 +0 -0
  40. data/lib/calabash/android/lib/calmd5/x86_64/calmd5-pie +0 -0
  41. data/lib/calabash/android/lib/screenshot_taker.jar +0 -0
  42. data/lib/calabash/android/life_cycle.rb +37 -0
  43. data/lib/calabash/android/orientation.rb +30 -0
  44. data/lib/calabash/android/physical_buttons.rb +39 -0
  45. data/lib/calabash/android/screenshot.rb +9 -0
  46. data/lib/calabash/android/scroll.rb +5 -0
  47. data/lib/calabash/android/server.rb +10 -0
  48. data/lib/calabash/android/text.rb +54 -0
  49. data/lib/calabash/application.rb +74 -0
  50. data/lib/calabash/cli.rb +12 -0
  51. data/lib/calabash/cli/build.rb +33 -0
  52. data/lib/calabash/cli/console.rb +90 -0
  53. data/lib/calabash/cli/generate.rb +110 -0
  54. data/lib/calabash/cli/helpers.rb +130 -0
  55. data/lib/calabash/cli/resign.rb +33 -0
  56. data/lib/calabash/cli/run.rb +99 -0
  57. data/lib/calabash/cli/setup_keystore.rb +39 -0
  58. data/lib/calabash/color.rb +32 -0
  59. data/lib/calabash/console_helpers.rb +90 -0
  60. data/lib/calabash/defaults.rb +56 -0
  61. data/lib/calabash/device.rb +401 -0
  62. data/lib/calabash/environment.rb +75 -0
  63. data/lib/calabash/gestures.rb +384 -0
  64. data/lib/calabash/http.rb +8 -0
  65. data/lib/calabash/http/error.rb +15 -0
  66. data/lib/calabash/http/request.rb +42 -0
  67. data/lib/calabash/http/retriable_client.rb +156 -0
  68. data/lib/calabash/interactions.rb +105 -0
  69. data/lib/calabash/ios.rb +37 -0
  70. data/lib/calabash/ios/application.rb +119 -0
  71. data/lib/calabash/ios/conditions.rb +79 -0
  72. data/lib/calabash/ios/console_helpers.rb +72 -0
  73. data/lib/calabash/ios/device.rb +24 -0
  74. data/lib/calabash/ios/device/device_implementation.rb +779 -0
  75. data/lib/calabash/ios/device/gestures_mixin.rb +167 -0
  76. data/lib/calabash/ios/device/keyboard_mixin.rb +133 -0
  77. data/lib/calabash/ios/device/physical_device_mixin.rb +266 -0
  78. data/lib/calabash/ios/device/rotation_mixin.rb +124 -0
  79. data/lib/calabash/ios/device/routes/backdoor_route_mixin.rb +86 -0
  80. data/lib/calabash/ios/device/routes/condition_route_mixin.rb +62 -0
  81. data/lib/calabash/ios/device/routes/error.rb +8 -0
  82. data/lib/calabash/ios/device/routes/handle_route_mixin.rb +102 -0
  83. data/lib/calabash/ios/device/routes/map_route_mixin.rb +38 -0
  84. data/lib/calabash/ios/device/routes/playback_route_mixin.rb +70 -0
  85. data/lib/calabash/ios/device/routes/response_parser.rb +48 -0
  86. data/lib/calabash/ios/device/routes/uia_route_mixin.rb +238 -0
  87. data/lib/calabash/ios/device/runtime_attributes.rb +184 -0
  88. data/lib/calabash/ios/device/status_bar_mixin.rb +17 -0
  89. data/lib/calabash/ios/device/text_mixin.rb +19 -0
  90. data/lib/calabash/ios/device/uia_keyboard_mixin.rb +188 -0
  91. data/lib/calabash/ios/device/uia_mixin.rb +12 -0
  92. data/lib/calabash/ios/environment.rb +41 -0
  93. data/lib/calabash/ios/interactions.rb +10 -0
  94. data/lib/calabash/ios/lib/.irbrc +55 -0
  95. data/lib/calabash/ios/lib/recordings/rotate_left_home_down_ipad.base64 +2 -0
  96. data/lib/calabash/ios/lib/recordings/rotate_left_home_down_iphone.base64 +2 -0
  97. data/lib/calabash/ios/lib/recordings/rotate_left_home_left_ipad.base64 +2 -0
  98. data/lib/calabash/ios/lib/recordings/rotate_left_home_left_iphone.base64 +2 -0
  99. data/lib/calabash/ios/lib/recordings/rotate_left_home_right_ipad.base64 +2 -0
  100. data/lib/calabash/ios/lib/recordings/rotate_left_home_right_iphone.base64 +2 -0
  101. data/lib/calabash/ios/lib/recordings/rotate_left_home_up_ipad.base64 +2 -0
  102. data/lib/calabash/ios/lib/recordings/rotate_left_home_up_iphone.base64 +2 -0
  103. data/lib/calabash/ios/lib/recordings/rotate_right_home_down_ipad.base64 +2 -0
  104. data/lib/calabash/ios/lib/recordings/rotate_right_home_down_iphone.base64 +2 -0
  105. data/lib/calabash/ios/lib/recordings/rotate_right_home_left_ipad.base64 +2 -0
  106. data/lib/calabash/ios/lib/recordings/rotate_right_home_left_iphone.base64 +2 -0
  107. data/lib/calabash/ios/lib/recordings/rotate_right_home_right_ipad.base64 +2 -0
  108. data/lib/calabash/ios/lib/recordings/rotate_right_home_right_iphone.base64 +2 -0
  109. data/lib/calabash/ios/lib/recordings/rotate_right_home_up_ipad.base64 +2 -0
  110. data/lib/calabash/ios/lib/recordings/rotate_right_home_up_iphone.base64 +2 -0
  111. data/lib/calabash/ios/orientation.rb +117 -0
  112. data/lib/calabash/ios/scroll.rb +504 -0
  113. data/lib/calabash/ios/server.rb +73 -0
  114. data/lib/calabash/ios/text.rb +248 -0
  115. data/lib/calabash/ios/uia.rb +24 -0
  116. data/lib/calabash/lib/skeleton/config/cucumber.yml +6 -0
  117. data/lib/calabash/lib/skeleton/features/sample.feature +5 -0
  118. data/lib/calabash/lib/skeleton/features/step_definitions/calabash_steps.rb +29 -0
  119. data/lib/calabash/lib/skeleton/features/support/env.rb +54 -0
  120. data/lib/calabash/lib/skeleton/features/support/hooks.rb +83 -0
  121. data/lib/calabash/life_cycle.rb +111 -0
  122. data/lib/calabash/location.rb +51 -0
  123. data/lib/calabash/logger.rb +87 -0
  124. data/lib/calabash/orientation.rb +84 -0
  125. data/lib/calabash/page.rb +35 -0
  126. data/lib/calabash/patch.rb +14 -0
  127. data/lib/calabash/patch/array.rb +16 -0
  128. data/lib/calabash/patch/run_loop.rb +90 -0
  129. data/lib/calabash/query.rb +160 -0
  130. data/lib/calabash/query_result.rb +85 -0
  131. data/lib/calabash/screenshot.rb +89 -0
  132. data/lib/calabash/server.rb +16 -0
  133. data/lib/calabash/text.rb +76 -0
  134. data/lib/calabash/utility.rb +58 -0
  135. data/lib/calabash/version.rb +3 -1
  136. data/lib/calabash/wait.rb +474 -0
  137. metadata +462 -24
@@ -0,0 +1,17 @@
1
+ module Calabash
2
+ module IOS
3
+ # @!visibility private
4
+ module StatusBarMixin
5
+
6
+ # Returns the home button position relative to the status bar.
7
+ #
8
+ # @note This method works even if a status bar is not visible.
9
+ #
10
+ # @return [String] Returns the device orientation as one of
11
+ # `{'down' | 'up' | 'left' | 'right'}`.
12
+ def status_bar_orientation
13
+ map_route(nil, :orientation, :status_bar).first
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,19 @@
1
+ module Calabash
2
+ module IOS
3
+ # @!visibility private
4
+ module TextMixin
5
+
6
+ def enter_text(text)
7
+ wait_for_keyboard(Calabash::Wait.default_options[:timeout])
8
+ existing_text = text_from_keyboard_first_responder
9
+ options = { existing_text: existing_text }
10
+ uia_type_string(text, options)
11
+ end
12
+
13
+ def _enter_text_in(query, text)
14
+ _tap(query)
15
+ enter_text(text)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,188 @@
1
+ module Calabash
2
+ module IOS
3
+
4
+ # @!visibility private
5
+ module UIAKeyboardMixin
6
+
7
+ # @param [Hash] options Control behavior of this method.
8
+ # @option options [String] :existing_text ('') Text that exists in the
9
+ # view before this method is called. Passing this option ensures that
10
+ # the existing text is _appended_ rather than cleared and helps the
11
+ # underlying JavaScript handle various bugs in UIAutomation's
12
+ # typeString JavaScript API.
13
+ # @option options [Boolean] :escape_backslashes (true) When try, this
14
+ # method escapes '\' characters in the `string` before sending the
15
+ # string over UIA. The only time you don't want to escape the '\'
16
+ # character is when you are trying to send a single character like '\n'
17
+ # or '\d'.
18
+ def uia_type_string(string, options={})
19
+ default_options =
20
+ {
21
+ existing_text: '',
22
+ escape_backslashes: true
23
+ }
24
+ merged_options = default_options.merge(options)
25
+
26
+ if merged_options[:escape_backslashes]
27
+ string_to_type = UIATypeStringHandler.escape_backslashes_in_string(string)
28
+ else
29
+ string_to_type = string.dup
30
+ end
31
+
32
+ existing_text = merged_options[:existing_text]
33
+
34
+ result = uia_serialize_and_call(:typeString, string_to_type, existing_text)
35
+
36
+ handler = uia_type_string_handler(string,
37
+ string_to_type,
38
+ existing_text,
39
+ result,
40
+ logger)
41
+ handler.handle_result
42
+ end
43
+
44
+ private
45
+
46
+ def uia_type_string_handler(string, escaped_string, existing_text, result, logger)
47
+ UIATypeStringHandler.new(string,
48
+ escaped_string,
49
+ existing_text,
50
+ result,
51
+ logger)
52
+ end
53
+
54
+ # @!visibility private
55
+ class UIATypeStringHandler
56
+
57
+ attr_reader :string, :escaped_string, :existing_text, :result, :logger
58
+
59
+ # The result returned should be a Hash.
60
+ #
61
+ # The result should have these keys. The 'value' key may or may not
62
+ # exist. The range of the 'value' key is not well understood; it varies
63
+ # depending on the context in which you are typing.
64
+ #
65
+ # :status => 'success' or 'error'
66
+ # :value => A hash of the view that was typed in, :nil', or nil.
67
+ # :index => This value is not important; ignore it.
68
+ def initialize(string, escaped_string, existing_text, result, logger)
69
+ @string = string
70
+ @escaped_string = escaped_string
71
+ @existing_text = existing_text
72
+ @result = result
73
+ @logger = logger
74
+ end
75
+
76
+ def self.escape_backslashes_in_string(string)
77
+ return string if string.index(/\\/)
78
+
79
+ escaped_string = string.dup
80
+
81
+ indexes = escaped_string.enum_for(:scan, /\\/).map { Regexp.last_match.begin(0) }
82
+ indexes.reverse.each { |idx| escaped_string = escaped_string.insert(idx, '\\') }
83
+
84
+ escaped_string
85
+ end
86
+
87
+ # Valid values: 'success' or 'error'
88
+ def status
89
+ result['status']
90
+ end
91
+
92
+ # A Hash of the view that was typed in or :nil. Other values are
93
+ # possible, but we don't have an enumeration of the possible values.
94
+ def value
95
+ result['value']
96
+ end
97
+
98
+ def log(message)
99
+ logger.log(Color.blue(message), :info)
100
+ end
101
+
102
+ def log_preamble
103
+ log('When typing:')
104
+ log(" raw string: #{string}")
105
+ log(" escaped: #{escaped_string}")
106
+ log("existing text: #{existing_text}")
107
+ end
108
+
109
+ def log_epilogue
110
+ log(" result: #{result}")
111
+ log('')
112
+ log('Please report this!')
113
+ log('https://github.com/calabash/calabash-ios/issues/374')
114
+ end
115
+
116
+ def handle_result
117
+ the_status = status
118
+ if the_status == 'error'
119
+ handle_error
120
+ elsif the_status == 'success'
121
+ handle_success
122
+ elsif result.is_a? Hash
123
+ if ['label', 'hit-point', 'el', 'rect'].all? { |key| result.has_key?(key) }
124
+ result
125
+ else
126
+ handle_unknown_status
127
+ end
128
+ else
129
+ handle_unknown_status
130
+ end
131
+ end
132
+
133
+ def handle_error
134
+ log_preamble
135
+ if result.has_key? 'value'
136
+ raise "Could not type '#{string}' - UIAutomation returned an error: '#{result['error']}'"
137
+ else
138
+ raise "Could not type '#{string}' - UIAutomation returned '#{result}'"
139
+ end
140
+ end
141
+
142
+ # When 'status' == 'success', we can get a variety of valid 'values'
143
+ #
144
+ # For example, typing on UIWebViews returns['value'] => ':nil'.
145
+ #
146
+ # The expected value is a Hash representation of the view that was
147
+ # typed in.
148
+ #
149
+ # We are interested in loggin situations where:
150
+ #
151
+ # 1. The 'value' key is not present in the result.
152
+ # 2. The 'value' key has a nil value.
153
+ def handle_success
154
+ the_value = value
155
+ if the_value.is_a? Hash
156
+ the_value
157
+ elsif the_value == ':nil'
158
+ true
159
+ else
160
+ handle_success_with_incident
161
+ end
162
+ end
163
+
164
+ def handle_success_with_incident
165
+ log_preamble
166
+ if value.nil?
167
+ if result.has_key? 'value'
168
+ log("received a 'success' response with no key for 'value'")
169
+ else
170
+ log("received a 'success' response with a 'nil' for key 'value'")
171
+ end
172
+ else
173
+ log("received a 'success' response with an unknown value for key 'value' => '#{value}'")
174
+ end
175
+ log_epilogue
176
+ false
177
+ end
178
+
179
+ def handle_unknown_status
180
+ log_preamble
181
+ log("receive response with an unknown value for 'status' key: '#{status}'")
182
+ log_epilogue
183
+ false
184
+ end
185
+ end
186
+ end
187
+ end
188
+ end
@@ -0,0 +1,12 @@
1
+ module Calabash
2
+ module IOS
3
+
4
+ # !@visibility private
5
+ module UIAMixin
6
+
7
+ def evaluate_uia(script)
8
+ uia_route(script)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,41 @@
1
+ module Calabash
2
+ module IOS
3
+
4
+ # Constants that describe the iOS test environment.
5
+ class Environment < Calabash::Environment
6
+
7
+ # A URI that points to the embedded Calabash server in the app under test.
8
+ #
9
+ # The default value is 'http://localhost:37265'.
10
+ #
11
+ # You can control the value of this variable by setting the `CAL_ENDPOINT`
12
+ # variable.
13
+ #
14
+ # @todo Maybe rename this to CAL_SERVER_URL or CAL_SERVER?
15
+ DEVICE_ENDPOINT = URI.parse((variable('CAL_ENDPOINT') || 'http://localhost:37265'))
16
+
17
+ # The strategy use when interacting with UIAutomation. Calabash iOS
18
+ # supports 3 strategies:
19
+ #
20
+ # 1. preferences: Fast, but only works on simulators and on devices < 8.0.
21
+ # 2. shared: Fast, but has limited functionality. For example, you
22
+ # can't send apps to the background.
23
+ # 3. host: Slow, but the only option for devices >= 8.0.
24
+ #
25
+ # Calabash and run-loop will work together to figure out the fastest,
26
+ # most feature complete strategy to use at runtime.
27
+ #
28
+ # This is an advanced feature. Don't set this variable unless you know
29
+ # what you are doing.
30
+ UIA_STRATEGY = lambda do
31
+ strategy = variable('CAL_UIA_STRATEGY')
32
+ if strategy
33
+ strategy.to_sym
34
+ else
35
+ nil
36
+ end
37
+ end.call
38
+ end
39
+ end
40
+ end
41
+
@@ -0,0 +1,10 @@
1
+ module Calabash
2
+ module IOS
3
+ module Interactions
4
+ # @!visibility private
5
+ def _evaluate_javascript_in(query, javascript)
6
+ query(query, calabashStringByEvaluatingJavaScript: javascript)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,55 @@
1
+ begin
2
+ require 'irb/completion'
3
+ require 'irb/ext/save-history'
4
+
5
+ begin
6
+ require 'awesome_print'
7
+ rescue LoadError => e
8
+ msg = ["Caught a LoadError: could not load 'awesome_print'",
9
+ "#{e}",
10
+ '',
11
+ 'Use bundler (recommended) or uninstall awesome_print.',
12
+ '',
13
+ '# Use bundler (recommended)',
14
+ '$ bundle update',
15
+ '$ bundle exec calabash console [path to apk]',
16
+ '',
17
+ '# Uninstall',
18
+ '$ gem update --system',
19
+ '$ gem uninstall -Vax --force --no-abort-on-dependent awesome_print']
20
+ puts msg
21
+ exit(1)
22
+ end
23
+
24
+ AwesomePrint.irb!
25
+
26
+ ARGV.concat [ '--readline',
27
+ '--prompt-mode',
28
+ 'simple']
29
+
30
+ # 50 entries in the list
31
+ IRB.conf[:SAVE_HISTORY] = 50
32
+
33
+ # Store results in home directory with specified file name
34
+ IRB.conf[:HISTORY_FILE] = '.irb-history'
35
+
36
+ require 'calabash/ios'
37
+
38
+ extend Calabash::IOS
39
+ extend Calabash::ConsoleHelpers
40
+
41
+ Calabash::Application.default = Calabash::IOS::Application.default_from_environment
42
+
43
+ identifier = Calabash::IOS::Device.default_identifier_for_application(Calabash::Application.default)
44
+ server = Calabash::IOS::Server.default
45
+
46
+ Calabash::Device.default = Calabash::IOS::Device.new(identifier, server)
47
+
48
+ Calabash.new_embed_method!(lambda {|*_| Calabash::Logger.info 'Embed is not available in the console.'})
49
+ Calabash::Screenshot.screenshot_directory_prefix = 'console_'
50
+ rescue Exception => e
51
+ puts 'Unable to start console:'
52
+ puts "#{e.class}: #{e.message}"
53
+ puts "#{e.backtrace.join("\n")}"
54
+ exit(1)
55
+ end
@@ -0,0 +1,2 @@
1
+ YnBsaXN0MDChAdMCBAYDBQdURGF0YUQDAAAAoFRUaW1lEwAAAbhNBUVUVFR5cGUQ
2
+ MggKERYcISovAAAAAAAAAQEAAAAAAAAACAAAAAAAAAAAAAAAAAAAADE=
@@ -0,0 +1,2 @@
1
+ YnBsaXN0MDChAdMCBAYDBQdURGF0YUQDAAAAoFRUaW1lEwAAAbhNBUVUVFR5cGUQ
2
+ MggKERYcISovAAAAAAAAAQEAAAAAAAAACAAAAAAAAAAAAAAAAAAAADE=
@@ -0,0 +1,2 @@
1
+ YnBsaXN0MDChAdMCBAYDBQdURGF0YUQBAAAAoFRUaW1lEwAAAbCIbyvaVFR5cGUQ
2
+ MggKERYcISovAAAAAAAAAQEAAAAAAAAACAAAAAAAAAAAAAAAAAAAADE=
@@ -0,0 +1,2 @@
1
+ YnBsaXN0MDChAdMCBAYDBQdURGF0YUQBAAAAoFRUaW1lEwAAAbCIbyvaVFR5cGUQ
2
+ MggKERYcISovAAAAAAAAAQEAAAAAAAAACAAAAAAAAAAAAAAAAAAAADE=
@@ -0,0 +1,2 @@
1
+ YnBsaXN0MDChAdMCBAYDBQdURGF0YUQCAAAAoFRUaW1lEwAAAbpMnOcWVFR5cGUQ
2
+ MggKERYcISovAAAAAAAAAQEAAAAAAAAACAAAAAAAAAAAAAAAAAAAADE=
@@ -0,0 +1,2 @@
1
+ YnBsaXN0MDChAdMCBAYDBQdURGF0YUQCAAAAoFRUaW1lEwAAAbpMnOcWVFR5cGUQ
2
+ MggKERYcISovAAAAAAAAAQEAAAAAAAAACAAAAAAAAAAAAAAAAAAAADE=
@@ -0,0 +1,2 @@
1
+ YnBsaXN0MDChAdMCBAYDBQdURGF0YUQEAAAAoFRUaW1lEwAAAa01e7C+VFR5cGUQ
2
+ MggKERYcISovAAAAAAAAAQEAAAAAAAAACAAAAAAAAAAAAAAAAAAAADE=
@@ -0,0 +1,2 @@
1
+ YnBsaXN0MDChAdMCBAYDBQdURGF0YUQEAAAAoFRUaW1lEwAAAa01e7C+VFR5cGUQ
2
+ MggKERYcISovAAAAAAAAAQEAAAAAAAAACAAAAAAAAAAAAAAAAAAAADE=
@@ -0,0 +1,2 @@
1
+ YnBsaXN0MDChAdMCBAYDBQdURGF0YUQEAAAAoFRUaW1lEwAAAaVlqJreVFR5cGUQ
2
+ MggKERYcISovAAAAAAAAAQEAAAAAAAAACAAAAAAAAAAAAAAAAAAAADE=
@@ -0,0 +1,2 @@
1
+ YnBsaXN0MDChAdMCBAYDBQdURGF0YUQEAAAAoFRUaW1lEwAAAaVlqJreVFR5cGUQ
2
+ MggKERYcISovAAAAAAAAAQEAAAAAAAAACAAAAAAAAAAAAAAAAAAAADE=
@@ -0,0 +1,2 @@
1
+ YnBsaXN0MDChAdMCBAYDBQdURGF0YUQCAAAAoFRUaW1lEwAAAaoeCDODVFR5cGUQ
2
+ MggKERYcISovAAAAAAAAAQEAAAAAAAAACAAAAAAAAAAAAAAAAAAAADE=
@@ -0,0 +1,2 @@
1
+ YnBsaXN0MDChAdMCBAYDBQdURGF0YUQCAAAAoFRUaW1lEwAAAaoeCDODVFR5cGUQ
2
+ MggKERYcISovAAAAAAAAAQEAAAAAAAAACAAAAAAAAAAAAAAAAAAAADE=
@@ -0,0 +1,2 @@
1
+ YnBsaXN0MDChAdMCBAYDBQdURGF0YUQBAAAAoFRUaW1lEwAAAcBXpQXHVFR5cGUQ
2
+ MggKERYcISovAAAAAAAAAQEAAAAAAAAACAAAAAAAAAAAAAAAAAAAADE=
@@ -0,0 +1,2 @@
1
+ YnBsaXN0MDChAdMCBAYDBQdURGF0YUQBAAAAoFRUaW1lEwAAAcBXpQXHVFR5cGUQ
2
+ MggKERYcISovAAAAAAAAAQEAAAAAAAAACAAAAAAAAAAAAAAAAAAAADE=
@@ -0,0 +1,2 @@
1
+ YnBsaXN0MDChAdMCBAYDBQdURGF0YUQDAAAAoFRUaW1lEwAAAbyCAvDjVFR5cGUQ
2
+ MggKERYcISovAAAAAAAAAQEAAAAAAAAACAAAAAAAAAAAAAAAAAAAADE=
@@ -0,0 +1,2 @@
1
+ YnBsaXN0MDChAdMCBAYDBQdURGF0YUQDAAAAoFRUaW1lEwAAAbyCAvDjVFR5cGUQ
2
+ MggKERYcISovAAAAAAAAAQEAAAAAAAAACAAAAAAAAAAAAAAAAAAAADE=
@@ -0,0 +1,117 @@
1
+ module Calabash
2
+ module IOS
3
+
4
+ # On iOS, the presenting view controller must respond to rotation events.
5
+ # If the presenting view controller does not respond to rotation events,
6
+ # then no rotation will be performed.
7
+ module Orientation
8
+
9
+ # Returns the home button position relative to the status bar.
10
+ #
11
+ # @note This method works even if a status bar is not visible.
12
+ #
13
+ # @return [String] Returns the device orientation as one of
14
+ # `{'down' | 'up' | 'left' | 'right'}`.
15
+ def status_bar_orientation
16
+ Device.default.status_bar_orientation
17
+ end
18
+
19
+ # Rotates the device in the direction indicated by `direction`.
20
+ #
21
+ # @example
22
+ # > rotate('left')
23
+ # > rotate('right')
24
+ #
25
+ # @note
26
+ # The presenting view controller must respond to rotation events.
27
+ # If the presenting view controller does not respond to rotation events,
28
+ # then no rotation will be performed.
29
+ #
30
+ # @param [String] direction The direction in which to rotate.
31
+ # Valid arguments are :left and :right
32
+ #
33
+ # @raise [ArgumentError] If an invalid direction is given.
34
+ # @return [String] The position of the home button relative to the status
35
+ # bar after the rotation. Can be one of 'down', 'left', 'right', 'up'.
36
+ def rotate(direction)
37
+ unless direction == 'left' || direction == 'right'
38
+ raise ArgumentError, "Expected '#{direction}' to be 'left' or 'right'"
39
+ end
40
+
41
+ Device.default.rotate(direction.to_sym)
42
+ wait_for_animations
43
+ status_bar_orientation
44
+ end
45
+
46
+ # Rotates the home button to a position relative to the status bar.
47
+ #
48
+ # @example portrait
49
+ # rotate_home_button_to 'down'
50
+ # rotate_home_button_to 'bottom'
51
+ #
52
+ # @example upside down
53
+ # rotate_home_button_to 'top'
54
+ # rotate_home_button_to 'up'
55
+ #
56
+ # @example landscape with left home button AKA: _right_ landscape
57
+ # rotate_home_button_to 'left'
58
+ #
59
+ # @example landscape with right home button AKA: _left_ landscape
60
+ # rotate_home_button_to 'right'
61
+ #
62
+ # @note Refer to Apple's documentation for clarification about left vs.
63
+ # right landscape orientations.
64
+ #
65
+ # @note
66
+ # The presenting view controller must respond to rotation events.
67
+ # If the presenting view controller does not respond to rotation events,
68
+ # then no rotation will be performed.
69
+ #
70
+ # @raise [ArgumentError] If an invalid position is given.
71
+ #
72
+ # @return [String] The position of the home button relative to the status
73
+ # bar after the rotation. Can be one of 'down', 'left', 'right', 'up'.
74
+ def rotate_home_button_to(position)
75
+ valid_positions = ['down', 'bottom', 'top', 'up', 'left', 'right']
76
+ unless valid_positions.include?(position)
77
+ raise ArgumentError,
78
+ "Expected '#{position}' to be one of #{valid_positions.join(', ')}"
79
+ end
80
+
81
+ canonical_position = position
82
+ canonical_position = 'down' if position == 'bottom'
83
+ canonical_position = 'up' if position == 'top'
84
+
85
+ Calabash::Device.default.rotate_home_button_to(canonical_position)
86
+ end
87
+
88
+ # @!visibility private
89
+ def _set_orientation_landscape
90
+ orientation = status_bar_orientation
91
+ return orientation if landscape?
92
+
93
+ rotate_home_button_to 'right'
94
+ end
95
+
96
+ # @!visibility private
97
+ def _set_orientation_portrait
98
+ orientation = status_bar_orientation
99
+ return orientation if portrait?
100
+
101
+ rotate_home_button_to 'down'
102
+ end
103
+
104
+ # @!visibility private
105
+ def _portrait?
106
+ orientation = status_bar_orientation
107
+ orientation.eql?('up') || orientation.eql?('down')
108
+ end
109
+
110
+ # @!visibility private
111
+ def _landscape?
112
+ orientation = status_bar_orientation
113
+ orientation.eql?('right') || orientation.eql?('left')
114
+ end
115
+ end
116
+ end
117
+ end