calabash 1.2.1 → 1.9.9.pre1

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.
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,48 @@
1
+ module Calabash
2
+ module IOS
3
+ # @!visibility private
4
+ module Routes
5
+
6
+ # @!visibility private
7
+ module ResponseParser
8
+
9
+ def parse_response_body(response)
10
+ body = response.body
11
+ begin
12
+ hash = JSON.parse(body)
13
+ rescue TypeError, JSON::ParserError => e
14
+ raise Calabash::IOS::RouteError, "Could not parse response '#{body}: #{e}'"
15
+ end
16
+
17
+ outcome = hash['outcome']
18
+
19
+ case outcome
20
+ when 'FAILURE'
21
+ reason = hash['reason']
22
+ if reason.nil? || reason.empty?
23
+ hash['reason'] = 'Server provided no reason.'
24
+ end
25
+
26
+ details = hash['details']
27
+ if details.nil? || details.empty?
28
+ hash['details'] = 'Server provided no details.'
29
+ end
30
+
31
+ when 'SUCCESS'
32
+ # Backdoor route returns a 'result' key. Grr.
33
+ # Legacy API: will be removed in Calabash iOS Server > 0.14.3
34
+ if !(hash.has_key?('results') || hash.has_key?('result'))
35
+ raise Calabash::IOS::RouteError, "Server responded with '#{outcome}'" \
36
+ "but response #{hash} does not contain 'results' key"
37
+ end
38
+ else
39
+ raise Calabash::IOS::RouteError, 'Server responded with an invalid outcome:' \
40
+ "'#{hash['outcome']}'"
41
+ end
42
+ hash
43
+ end
44
+
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,238 @@
1
+ module Calabash
2
+ module IOS
3
+ # @!visibility private
4
+ module Routes
5
+
6
+ # @!visibility private
7
+ module UIARouteMixin
8
+
9
+ require 'run_loop'
10
+ require 'edn'
11
+
12
+ def uia_route(command)
13
+ unless run_loop
14
+ if defined?(IRB)
15
+ logger.log('', :info)
16
+ logger.log(Color.red('This console is not attached to a run-loop.'), :info)
17
+ logger.log('', :info)
18
+ logger.log(Color.green('If your have not launched your app yet, launch it with:'), :info)
19
+ logger.log('', :info)
20
+ logger.log(Color.cyan('> start_app'), :info)
21
+ logger.log('', :info)
22
+ logger.log('', :info)
23
+ logger.log(Color.green('If your Calabash app is already running, ' \
24
+ "you can attach to it's run-loop:"), :info)
25
+ logger.log('', :info)
26
+ logger.log(Color.cyan('> console_attach # Attaches with the default strategy.'),
27
+ :info)
28
+ logger.log(Color.cyan('> console_attach(uia_strategy) # Attaches with a specific strategy.'),
29
+ :info)
30
+ logger.log('', :info)
31
+ logger.log('', :info)
32
+ raise 'This console is not attached a run-loop.'
33
+ else
34
+ raise 'This device does not have a connection to run-loop. Call start_app first.'
35
+ end
36
+ end
37
+
38
+ strategy = uia_strategy
39
+
40
+ case strategy
41
+ when :preferences
42
+ uia_over_http(command, 'uia')
43
+ when :shared_element
44
+ uia_over_http(command, 'uia-shared')
45
+ when :host
46
+ uia_over_host(command)
47
+ else
48
+ raise Calabash::IOS::RouteError, "Invalid :uia_strategy '#{strategy}'. Valid strategies are: '#{UIA_STRATEGIES}"
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ UIA_STRATEGIES = [:preferences, :host, :shared_element]
55
+
56
+ # Careful. The UIA route can return all manner of weird responses.
57
+ def uia_over_http(command, route)
58
+ request = make_uia_request(command, route)
59
+ response = route_post_request(request)
60
+ parsed = parse_response_body(response)
61
+ handle_uia_results(parsed['results'], command)
62
+ end
63
+
64
+ # Careful. The UIA route can return all manner of weird responses.
65
+ def uia_over_host(command)
66
+ [RunLoop.send_command(run_loop, command)]
67
+ end
68
+
69
+ # Called _after_ route_handle_response or _after_ RunLoop.send_command
70
+ def handle_uia_results(response, command)
71
+ expect_uia_results_is_array(response)
72
+
73
+ expect_uia_results_has_one_element(response)
74
+
75
+ hash = response.first
76
+
77
+ expect_uia_result_has_valid_status_key(hash, response, command)
78
+
79
+ expect_uia_result_has_value_key(hash, response, command)
80
+
81
+ status = hash['status']
82
+ value = hash['value']
83
+
84
+ if status == 'error'
85
+ raise "Executing command '#{command}'\n" \
86
+ "resulted in an error: '#{value}'"
87
+ else
88
+ handle_uia_result_with_success(value)
89
+ end
90
+ end
91
+
92
+ def expect_uia_results_is_array(response)
93
+ if !response.is_a? Array
94
+ raise "Expected '#{response}' to be an array."
95
+ end
96
+ response
97
+ end
98
+
99
+ def expect_uia_results_has_one_element(response)
100
+ if response.length != 1
101
+ raise "Expected '#{response}' to have exactly one element"
102
+ end
103
+ response
104
+ end
105
+
106
+ def expect_uia_response_element_is_hash(hash)
107
+ if !hash.is_a? Hash
108
+ raise "Expected first result of '#{hash}' to be a Hash"
109
+ end
110
+ hash
111
+ end
112
+
113
+ def expect_uia_result_has_valid_status_key(hash, response, command)
114
+ status = hash['status']
115
+
116
+ case status
117
+ when 'error', 'success'
118
+ hash
119
+ else
120
+ raise "Executing command '#{command}'\n" \
121
+ "returned an invalid status key: '#{status}'.\n" \
122
+ "Expected 'error' or 'success'.\n" \
123
+ "The raw response was '#{response}'"
124
+ end
125
+ hash
126
+ end
127
+
128
+ def expect_uia_result_has_value_key(hash, response, command)
129
+ if !hash.has_key? 'value'
130
+ raise "Executing command '#{command}'\n" \
131
+ "returned a value with no 'value' key.\n" \
132
+ "Then raw response was '#{response}'"
133
+ end
134
+ hash
135
+ end
136
+
137
+ def handle_uia_result_with_success(value)
138
+ if value.is_a? Array
139
+ value
140
+ elsif value == ':nil'
141
+ [nil]
142
+ else
143
+ [value]
144
+ end
145
+ end
146
+
147
+ def make_uia_parameters(command)
148
+ {
149
+ :command => command
150
+ }
151
+ end
152
+
153
+ def make_uia_request(command, route)
154
+ parameters = make_uia_parameters(command)
155
+ begin
156
+ Calabash::HTTP::Request.request(route, parameters)
157
+ rescue => e
158
+ raise Calabash::IOS::RouteError, e
159
+ end
160
+ end
161
+
162
+ def uia_serialize_and_call(uia_command, *query_args)
163
+ command = uia_serialize_command(uia_command, *query_args)
164
+ result = uia_route(command)
165
+ result.first
166
+ end
167
+
168
+ # @todo Verify this is the correct way to escape '\n in string
169
+ def uia_escape_string(string)
170
+ Calabash::Text.escape_single_quotes(string).gsub("\n", "\\\\n")
171
+ end
172
+
173
+ def uia_serialize_argument(part)
174
+ if part.is_a?(String)
175
+ "'#{uia_escape_string(part)}'"
176
+ else
177
+ "'#{uia_escape_string(part.to_edn)}'"
178
+ end
179
+ end
180
+
181
+ def uia_serialize_arguments(argument_array)
182
+ argument_array.map do |part|
183
+ uia_serialize_argument(part)
184
+ end
185
+ end
186
+
187
+ def uia_serialize_command(uia_command, *query_args)
188
+ args = uia_serialize_arguments(query_args)
189
+ %Q[uia.#{uia_command}(#{args.join(', ')})]
190
+ end
191
+
192
+ # @todo Move to a translate mixin (or helper)
193
+ # @todo No unit tests for this yet!
194
+ def uia_center_of_view(view_hash)
195
+ rect = view_hash['rect']
196
+
197
+ # Why would the view hash not have a rect?
198
+ unless rect
199
+ raise "Expected '#{view_hash}' to have a 'rect' key"
200
+ end
201
+ {:x => rect['center_x'], :y => rect['center_y']}
202
+ end
203
+
204
+ # @todo Move to a translate mixin (or helper)
205
+ # def point_from(query_result, options={})
206
+ # offset_x = 0
207
+ # offset_y = 0
208
+ # if options[:offset]
209
+ # offset_x += options[:offset][:x] || 0
210
+ # offset_y += options[:offset][:y] || 0
211
+ # end
212
+ # x = offset_x
213
+ # y = offset_y
214
+ # rect = query_result['rect'] || query_result[:rect]
215
+ # if rect
216
+ # x += rect['center_x'] || rect[:center_x] || rect[:x] || 0
217
+ # y += rect['center_y'] || rect[:center_y] || rect[:y] || 0
218
+ # else
219
+ # x += query_result['center_x'] || query_result[:center_x] || query_result[:x] || 0
220
+ # y += query_result['center_y'] || query_result[:center_y] || query_result[:y] || 0
221
+ # end
222
+ #
223
+ # {:x => x, :y => y}
224
+ # end
225
+
226
+ # @todo Is this worth keeping?
227
+ # def uia_result(s)
228
+ # query_result = s.first
229
+ # if query_result['status'] == 'success'
230
+ # query_result['value']
231
+ # else
232
+ # query_result['status']
233
+ # end
234
+ # end
235
+ end
236
+ end
237
+ end
238
+ end
@@ -0,0 +1,184 @@
1
+ module Calabash
2
+ module IOS
3
+
4
+ # @!visibility private
5
+ # This class provides information about the device under test that can
6
+ # only be obtained at run time.
7
+ class RuntimeAttributes
8
+
9
+ require 'run_loop'
10
+
11
+ # @!visibility private
12
+ # Creates a new instance of DeviceRuntimeInfo.
13
+ # @param [Hash] runtime_info The result of calling the version route on
14
+ # on the server
15
+ # @return [Calabash::IOS::RuntimeAttributes] A new info object.
16
+ def initialize(runtime_info)
17
+ @runtime_info = runtime_info
18
+ end
19
+
20
+ # @!visibility private
21
+ # The device family of this device.
22
+ #
23
+ # @example
24
+ # # will be one of
25
+ # iPhone
26
+ # iPod
27
+ # iPad
28
+ #
29
+ # @return [String] the device family
30
+ def device_family
31
+ @device_family ||= lambda do
32
+ return nil if runtime_info.nil?
33
+
34
+ if runtime_info.has_key? 'simulator_device'
35
+ simulator_device = runtime_info['simulator_device']
36
+ if simulator_device && !simulator_device.empty?
37
+ simulator_device
38
+ else
39
+ nil
40
+ end
41
+ else
42
+ physical_device_name = system
43
+ if physical_device_name
44
+ physical_device_name.split(/[\d,.]/).first
45
+ else
46
+ nil
47
+ end
48
+ end
49
+ end.call
50
+ end
51
+
52
+ # @!visibility private
53
+ # The form factor of the device under test.
54
+ #
55
+ # Will be one of:
56
+ #
57
+ # * ipad
58
+ # * iphone 4in
59
+ # * iphone 3.5in
60
+ # * iphone 6
61
+ # * iphone 6+
62
+ # * unknown # if no information can be found.
63
+ #
64
+ # @note iPod is not on this list for a reason! An iPod has an iPhone
65
+ # form factor.
66
+ #
67
+ # @return [String] The form factor of the device under test.
68
+ def form_factor
69
+ @form_factor ||= lambda do
70
+ return nil if runtime_info.nil?
71
+ runtime_info['form_factor']
72
+ end.call
73
+ end
74
+
75
+ # @!visibility private
76
+ # Is the app that is running an iPhone-only app emulated on an iPad?
77
+ #
78
+ # @note If the app is running in emulation mode, there will be a 1x or 2x
79
+ # scale button visible on the iPad.
80
+ #
81
+ # @return [Boolean] true if the app running on this devices is an
82
+ # iPhone-only app emulated on an iPad
83
+ def iphone_app_emulated_on_ipad?
84
+ @iphone_app_emulated_on_ipad ||= lambda do
85
+ return nil if runtime_info.nil?
86
+ runtime_info['iphone_app_emulated_on_ipad']
87
+ end.call
88
+ end
89
+
90
+ # @!visibility private
91
+ # The iOS version on the test device.
92
+ #
93
+ # @return [RunLoop::Version] The major.minor.patch[.pre\d] version of the
94
+ # iOS version on the device.
95
+ def ios_version
96
+ @ios_version ||= lambda do
97
+ return nil if runtime_info.nil?
98
+
99
+ version_string = runtime_info['iOS_version']
100
+
101
+ return nil if version_string.nil? || version_string.empty?
102
+
103
+ begin
104
+ RunLoop::Version.new(version_string)
105
+ rescue => _
106
+ nil
107
+ end
108
+ end.call
109
+ end
110
+
111
+ # @!visibility private
112
+ # Information about the runtime screen dimensions of the app under test.
113
+ #
114
+ # This is a hash of form:
115
+ #
116
+ # ```
117
+ # {
118
+ # :sample => 1,
119
+ # :height => 1334,
120
+ # :width => 750,
121
+ # :scale" => 2
122
+ # }
123
+ # ```
124
+ #
125
+ # @return [Hash] screen dimensions, scale and down/up sampling fraction.
126
+ def screen_dimensions
127
+ @screen_dimensions ||= lambda do
128
+ return nil if runtime_info.nil?
129
+ screen_dimensions = runtime_info['screen_dimensions']
130
+ @screen_dimensions = {}
131
+ screen_dimensions.each_pair do |key,val|
132
+ @screen_dimensions[key.to_sym] = val
133
+ end
134
+ @screen_dimensions
135
+ end.call
136
+ end
137
+
138
+ # @!visibility private
139
+ # The version of the embedded Calabash server that is running in the
140
+ # app under test on this device.
141
+ #
142
+ # @return [RunLoop::Version] The major.minor.patch[.pre\d] version of the
143
+ # embedded Calabash server
144
+ def server_version
145
+ @server_version ||= lambda do
146
+ return nil if runtime_info.nil?
147
+
148
+ version_string = runtime_info['version']
149
+
150
+ return nil if version_string.nil? || version_string.empty?
151
+
152
+ begin
153
+ RunLoop::Version.new(version_string)
154
+ rescue => _
155
+ nil
156
+ end
157
+ end.call
158
+ end
159
+
160
+ private
161
+
162
+ # @!visibility private
163
+ # Details about the device. For iOS Simulators, this will be x86_64,
164
+ # which is not very helpful. For physical devices, this will be the
165
+ # internal Apple device name. For example, the `iPhone 6+` will report
166
+ # `iPhone7,1` and the `iPhone 5s` will report `iPhone6`.
167
+ #
168
+ # @return [String] Information about the device under test.
169
+ def system
170
+ @system ||= lambda do
171
+ return nil if runtime_info.nil?
172
+
173
+ runtime_info['system']
174
+ end.call
175
+ end
176
+
177
+ # @!visibility private
178
+ # The hash passed to initialize.
179
+ attr_reader :runtime_info
180
+
181
+ end
182
+ end
183
+ end
184
+