calabash 2.0.0.pre2 → 2.0.0.pre3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -26
  3. data/lib/calabash/android/adb.rb +9 -0
  4. data/lib/calabash/android/build/builder.rb +2 -0
  5. data/lib/calabash/android/build/java_keystore.rb +10 -0
  6. data/lib/calabash/android/build/resigner.rb +4 -0
  7. data/lib/calabash/android/build/test_server.rb +2 -0
  8. data/lib/calabash/android/defaults.rb +1 -0
  9. data/lib/calabash/android/device.rb +18 -0
  10. data/lib/calabash/android/interactions.rb +2 -0
  11. data/lib/calabash/android/lib/TestServer.apk +0 -0
  12. data/lib/calabash/android/life_cycle.rb +1 -0
  13. data/lib/calabash/android/physical_buttons.rb +8 -0
  14. data/lib/calabash/android/screenshot.rb +1 -0
  15. data/lib/calabash/android/server.rb +1 -0
  16. data/lib/calabash/android/text.rb +1 -0
  17. data/lib/calabash/cli/build.rb +1 -0
  18. data/lib/calabash/cli/console.rb +2 -0
  19. data/lib/calabash/cli/generate.rb +3 -0
  20. data/lib/calabash/cli/helpers.rb +6 -0
  21. data/lib/calabash/cli/resign.rb +1 -0
  22. data/lib/calabash/cli/run.rb +2 -0
  23. data/lib/calabash/cli/setup_keystore.rb +2 -0
  24. data/lib/calabash/color.rb +7 -0
  25. data/lib/calabash/defaults.rb +1 -0
  26. data/lib/calabash/device.rb +2 -0
  27. data/lib/calabash/environment.rb +1 -0
  28. data/lib/calabash/http/retriable_client.rb +2 -0
  29. data/lib/calabash/interactions.rb +1 -0
  30. data/lib/calabash/ios/conditions.rb +3 -0
  31. data/lib/calabash/ios/date_picker.rb +412 -0
  32. data/lib/calabash/ios/defaults.rb +1 -0
  33. data/lib/calabash/ios/device/device_implementation.rb +5 -1
  34. data/lib/calabash/ios/device/ipad_1x_2x_mixin.rb +253 -0
  35. data/lib/calabash/ios/device/keyboard_mixin.rb +2 -0
  36. data/lib/calabash/ios/device/rotation_mixin.rb +1 -0
  37. data/lib/calabash/ios/device/routes/condition_route_mixin.rb +1 -0
  38. data/lib/calabash/ios/device/routes/map_route_mixin.rb +1 -0
  39. data/lib/calabash/ios/device/routes/response_parser.rb +1 -0
  40. data/lib/calabash/ios/device/routes/uia_route_mixin.rb +44 -6
  41. data/lib/calabash/ios/device/text_mixin.rb +2 -0
  42. data/lib/calabash/ios/device/uia_keyboard_mixin.rb +9 -0
  43. data/lib/calabash/ios/device/uia_mixin.rb +1 -0
  44. data/lib/calabash/ios/device.rb +1 -0
  45. data/lib/calabash/ios/interactions.rb +30 -1
  46. data/lib/calabash/ios/runtime.rb +8 -0
  47. data/lib/calabash/ios.rb +2 -0
  48. data/lib/calabash/life_cycle.rb +19 -2
  49. data/lib/calabash/location.rb +2 -0
  50. data/lib/calabash/page.rb +13 -0
  51. data/lib/calabash/patch.rb +1 -0
  52. data/lib/calabash/utility.rb +4 -4
  53. data/lib/calabash/version.rb +1 -1
  54. data/lib/calabash/wait.rb +4 -0
  55. data/lib/calabash.rb +6 -4
  56. metadata +113 -112
  57. data/lib/calabash/android/scroll.rb +0 -5
@@ -110,6 +110,7 @@ module Calabash
110
110
  end.call(self)
111
111
  end
112
112
 
113
+ # @!visibility private
113
114
  def query_for_keyboard
114
115
  keyboard_waiter.query(KEYBOARD_QUERY)
115
116
  end
@@ -120,6 +121,7 @@ module Calabash
120
121
  keyboard_waiter.query(KEYBOARD_KEY_QUERY)
121
122
  end
122
123
 
124
+ # @!visibility private
123
125
  def query_for_text_of_first_responder(query)
124
126
  result = keyboard_waiter.query("#{query} isFirstResponder:1", :text)
125
127
  if result.empty?
@@ -4,6 +4,7 @@ module Calabash
4
4
  # @!visibility private
5
5
  module RotationMixin
6
6
 
7
+ # @!visibility private
7
8
  def rotate(direction)
8
9
  # If we are in the console, we want to be able to rotate without
9
10
  # calling start_app. However, if the Device in the console has not
@@ -5,6 +5,7 @@ module Calabash
5
5
  # @!visibility private
6
6
  module ConditionRouteMixin
7
7
 
8
+ # @!visibility private
8
9
  def condition_route(condition, timeout, query)
9
10
  request = make_condition_request(condition, timeout, query)
10
11
  response = route_post_request(request)
@@ -5,6 +5,7 @@ module Calabash
5
5
  # @!visibility private
6
6
  module MapRouteMixin
7
7
 
8
+ # @!visibility private
8
9
  def map_route(query, method_name, *method_args)
9
10
  request = make_map_request(query, method_name, *method_args)
10
11
  response = route_post_request(request)
@@ -6,6 +6,7 @@ module Calabash
6
6
  # @!visibility private
7
7
  module ResponseParser
8
8
 
9
+ # @!visibility private
9
10
  def parse_response_body(response)
10
11
  body = response.body
11
12
  begin
@@ -9,6 +9,7 @@ module Calabash
9
9
  require 'run_loop'
10
10
  require 'edn'
11
11
 
12
+ # @!visibility private
12
13
  def uia_route(command)
13
14
  unless run_loop
14
15
  if defined?(IRB)
@@ -49,6 +50,49 @@ module Calabash
49
50
  end
50
51
  end
51
52
 
53
+ # @!visibility private
54
+ def uia_serialize_and_call(uia_command, *query_args)
55
+ command = uia_serialize_command(uia_command, *query_args)
56
+ result = uia_route(command)
57
+ result.first
58
+ end
59
+
60
+ # @!visibility private
61
+ # @todo Extract argument consing and unit test
62
+ def uia_query_then_make_javascript_calls(uia_command, query_parts, *javascript_parts)
63
+ if javascript_parts.empty?
64
+ uia_serialize_and_call(uia_command, *query_parts)
65
+ else
66
+ javascript_command = uia_serialize_command(uia_command, *query_parts)
67
+
68
+ javascript_args = []
69
+ javascript_parts.each do |invocation|
70
+ javascript_args << case invocation
71
+ when Symbol
72
+ "#{invocation}()"
73
+ when Hash
74
+ method = invocation.keys.first
75
+ method_args = invocation[method]
76
+
77
+ if method_args.is_a?(Array)
78
+ serialized_args = (method_args.map &:to_json).join(',')
79
+ else
80
+ serialized_args = method_args.to_json
81
+ end
82
+
83
+ "#{method}(#{serialized_args})"
84
+ else
85
+ raise Calabash::IOS::RouteError,
86
+ "Invalid invocation spec #{invocation}"
87
+ end
88
+ end
89
+ command = "#{javascript_command}.#{javascript_args.join('.')}"
90
+
91
+ result = uia_route(command)
92
+ result.first
93
+ end
94
+ end
95
+
52
96
  private
53
97
 
54
98
  UIA_STRATEGIES = [:preferences, :host, :shared_element]
@@ -159,12 +203,6 @@ module Calabash
159
203
  end
160
204
  end
161
205
 
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
206
  # @todo Verify this is the correct way to escape '\n in string
169
207
  def uia_escape_string(string)
170
208
  Calabash::Text.escape_single_quotes(string).gsub("\n", "\\\\n")
@@ -3,6 +3,7 @@ module Calabash
3
3
  # @!visibility private
4
4
  module TextMixin
5
5
 
6
+ # @!visibility private
6
7
  def enter_text(text)
7
8
  wait_for_keyboard(Calabash::Wait.default_options[:timeout])
8
9
  existing_text = text_from_keyboard_first_responder
@@ -10,6 +11,7 @@ module Calabash
10
11
  uia_type_string(text, options)
11
12
  end
12
13
 
14
+ # @!visibility private
13
15
  def _enter_text_in(query, text)
14
16
  _tap(query)
15
17
  enter_text(text)
@@ -43,6 +43,7 @@ module Calabash
43
43
 
44
44
  private
45
45
 
46
+ # @!visibility private
46
47
  def uia_type_string_handler(string, escaped_string, existing_text, result, logger)
47
48
  UIATypeStringHandler.new(string,
48
49
  escaped_string,
@@ -73,6 +74,7 @@ module Calabash
73
74
  @logger = logger
74
75
  end
75
76
 
77
+ # @!visibility private
76
78
  def self.escape_backslashes_in_string(string)
77
79
  return string if string.index(/\\/)
78
80
 
@@ -95,10 +97,12 @@ module Calabash
95
97
  result['value']
96
98
  end
97
99
 
100
+ # @!visibility private
98
101
  def log(message)
99
102
  logger.log(Color.blue(message), :info)
100
103
  end
101
104
 
105
+ # @!visibility private
102
106
  def log_preamble
103
107
  log('When typing:')
104
108
  log(" raw string: #{string}")
@@ -106,6 +110,7 @@ module Calabash
106
110
  log("existing text: #{existing_text}")
107
111
  end
108
112
 
113
+ # @!visibility private
109
114
  def log_epilogue
110
115
  log(" result: #{result}")
111
116
  log('')
@@ -113,6 +118,7 @@ module Calabash
113
118
  log('https://github.com/calabash/calabash-ios/issues/374')
114
119
  end
115
120
 
121
+ # @!visibility private
116
122
  def handle_result
117
123
  the_status = status
118
124
  if the_status == 'error'
@@ -130,6 +136,7 @@ module Calabash
130
136
  end
131
137
  end
132
138
 
139
+ # @!visibility private
133
140
  def handle_error
134
141
  log_preamble
135
142
  if result.has_key? 'value'
@@ -161,6 +168,7 @@ module Calabash
161
168
  end
162
169
  end
163
170
 
171
+ # @!visibility private
164
172
  def handle_success_with_incident
165
173
  log_preamble
166
174
  if value.nil?
@@ -176,6 +184,7 @@ module Calabash
176
184
  false
177
185
  end
178
186
 
187
+ # @!visibility private
179
188
  def handle_unknown_status
180
189
  log_preamble
181
190
  log("receive response with an unknown value for 'status' key: '#{status}'")
@@ -4,6 +4,7 @@ module Calabash
4
4
  # @!visibility private
5
5
  module UIAMixin
6
6
 
7
+ # @!visibility private
7
8
  def evaluate_uia(script)
8
9
  uia_route(script)
9
10
  end
@@ -18,6 +18,7 @@ module Calabash
18
18
  require 'calabash/ios/device/uia_keyboard_mixin'
19
19
  require 'calabash/ios/device/text_mixin'
20
20
  require 'calabash/ios/device/uia_mixin'
21
+ require 'calabash/ios/device/ipad_1x_2x_mixin'
21
22
  require 'calabash/ios/device/device_implementation'
22
23
 
23
24
  end
@@ -1,7 +1,36 @@
1
1
  module Calabash
2
2
  module IOS
3
- # @!visibility private
3
+
4
+ # Interactions with your app that are specific to iOS
4
5
  module Interactions
6
+
7
+ # @!visibility private
8
+ # Sends app to background. Simulates pressing the home button.
9
+ #
10
+ # @note Cannot be more than 60 seconds.
11
+ #
12
+ # @param [Numeric] seconds The number of seconds to keep the app
13
+ # in the background
14
+ # @raise [ArgumentError] If number of seconds is less than 1 and more
15
+ # than 60 seconds.
16
+ def _send_current_app_to_background(seconds)
17
+ unless (1..60).member?(seconds)
18
+ raise ArgumentError,
19
+ "Number of seconds: '#{seconds}' must be between 1 and 60"
20
+ end
21
+
22
+ javascript = %Q(
23
+ var x = target.deactivateAppForDuration(#{seconds});
24
+ var MAX_RETRY=5, retry_count = 0;
25
+ while (!x && retry_count < MAX_RETRY) {
26
+ x = target.deactivateAppForDuration(#{seconds});
27
+ retry_count += 1
28
+ };
29
+ x
30
+ )
31
+ uia(javascript)
32
+ end
33
+
5
34
  # @!visibility private
6
35
  def _evaluate_javascript_in(query, javascript)
7
36
  query(query, calabashStringByEvaluatingJavaScript: javascript)
@@ -63,6 +63,14 @@ module Calabash
63
63
  end
64
64
 
65
65
  # Is the device under test an iPhone 3.5in?
66
+ #
67
+ # @note If the app under test is an iPhone app emulated on an iPad then
68
+ # the form factor will _always_ be 'iphone 3.5.in'. If you need to
69
+ # branch on the actual device the app is running on, use the #ipad?
70
+ # method.
71
+ #
72
+ # @see #iphone_app_emulated_on_ipad?
73
+ # @see #ipad?
66
74
  def iphone_35in?
67
75
  Calabash::IOS::Device.default.form_factor == 'iphone 3.5in'
68
76
  end
data/lib/calabash/ios.rb CHANGED
@@ -31,6 +31,7 @@ module Calabash
31
31
  require 'calabash/ios/runtime'
32
32
  require 'calabash/ios/gestures'
33
33
  require 'calabash/ios/slider'
34
+ require 'calabash/ios/date_picker'
34
35
 
35
36
  include Calabash::IOS::Conditions
36
37
  include Calabash::IOS::Orientation
@@ -41,6 +42,7 @@ module Calabash
41
42
  include Calabash::IOS::Runtime
42
43
  include Calabash::IOS::Gestures
43
44
  include Calabash::IOS::Slider
45
+ include Calabash::IOS::DatePicker
44
46
 
45
47
  end
46
48
  end
@@ -1,4 +1,12 @@
1
1
  module Calabash
2
+
3
+ # Methods for managing an app's life cycle.
4
+ #
5
+ # The life cycle of an app includes:
6
+ # * installing / uninstalling
7
+ # * stopping / starting
8
+ # * clearing the application data
9
+ # * sending the application to background and resuming it
2
10
  module LifeCycle
3
11
  # Start the given application (and its test-server) on the port of
4
12
  # {Calabash::Defaults#default_server Calabash.default_server}.
@@ -122,11 +130,20 @@ module Calabash
122
130
  end
123
131
 
124
132
  # Sends the current app to the background and resumes it after
125
- # `for_seconds`. This should not exceed 60 seconds for iOS.
133
+ # `for_seconds`.
134
+ #
135
+ # On iOS, `for_seconds` must be between 1 and 60 seconds.
136
+ #
137
+ # On iOS the _current app_ is the app under test (your app).
126
138
  #
127
- # On Android you can control the app lifecycle more granularly using
139
+ # On Android you can control the app lifecycle more granularity using
128
140
  # {Calabash::Android::Interactions#go_home \#go_home} and
129
141
  # {Calabash::Android::LifeCycle#resume_app \#resume_app}.
142
+ #
143
+ # @param [Numeric] for_seconds How long to keep the app to the background.
144
+ #
145
+ # @raise [ArgumentError] On iOS, if number of seconds is less than 1 and
146
+ # more than 60 seconds.
130
147
  def send_current_app_to_background(for_seconds = 10)
131
148
  _send_current_app_to_background(for_seconds)
132
149
 
@@ -1,6 +1,8 @@
1
1
  require 'geocoder'
2
2
 
3
3
  module Calabash
4
+
5
+ # An API for setting the location of your app.
4
6
  module Location
5
7
  # Simulates gps location of the device/simulator.
6
8
  # @note Seems UIAutomation is broken here on physical devices on iOS 7.1
data/lib/calabash/page.rb CHANGED
@@ -1,8 +1,17 @@
1
1
  module Calabash
2
+
3
+ # A base class for the Page Object Model (POM) or Page Object Pattern.
4
+ #
5
+ # We recommend the POM for testing cross-platform apps.
6
+ #
7
+ # We have a great examples of using the POM in the Calabash 2.0 repository.
8
+ # * https://github.com/calabash/calabash/tree/develop/samples/wordpress
9
+ # * https://github.com/calabash/calabash/tree/develop/samples/shared-page-logic
2
10
  class Page
3
11
  # For auto-completion
4
12
  include Calabash
5
13
 
14
+ # @!visibility private
6
15
  def self.inherited(subclass)
7
16
  # Define the page into global scope
8
17
  full_name = subclass.name
@@ -49,14 +58,18 @@ module Calabash
49
58
 
50
59
  private_class_method :new
51
60
 
61
+ # @!visibility private
52
62
  def initialize(world)
53
63
  @world = world
54
64
  end
55
65
 
66
+ # A query that distinguishes your page.
67
+ # @return [String, Hash, Calabash::Query] A query.
56
68
  def trait
57
69
  raise 'Implement your own trait'
58
70
  end
59
71
 
72
+ # Waits for the page trait to appear.
60
73
  def await(options={})
61
74
  wait_for_view(trait, options)
62
75
  end
@@ -3,6 +3,7 @@ module Calabash
3
3
  module Patch
4
4
  require 'calabash/patch/array'
5
5
 
6
+ # @!visibility private
6
7
  def self.apply_patches!
7
8
  modules = Patch.constants(false)
8
9
 
@@ -5,6 +5,7 @@ module Calabash
5
5
 
6
6
  end
7
7
 
8
+ # Utility methods for testing.
8
9
  module Utility
9
10
 
10
11
  # @!visibility private
@@ -39,17 +40,16 @@ module Calabash
39
40
  alias_method :pct, :percent
40
41
 
41
42
  # A convenience method for creating a coordinate hash that that can be
42
- # passed to gestures.
43
+ # passed to the tap_coordinate gesture.
43
44
  #
44
45
  # @example
45
46
  # # These are equivalent.
46
- # tap(query, offset: coordinate(20, 50))
47
- # tap(query, offset: {x: 20, y: 50})
47
+ # tap_coordinate(coordinate(20, 50)
48
+ # tap_coordinate({x: 20, y: 50})
48
49
  #
49
50
  # @param [Number] x The value of the x.
50
51
  # @param [Number] y The value of the y.
51
52
  # @return [Hash] Representing the given values.
52
- # @!visibility private
53
53
  def coordinate(x, y)
54
54
  {x: x, y: y}
55
55
  end
@@ -1,5 +1,5 @@
1
1
  module Calabash
2
2
 
3
3
  # @!visibility private
4
- VERSION = '2.0.0.pre2'
4
+ VERSION = '2.0.0.pre3'
5
5
  end
data/lib/calabash/wait.rb CHANGED
@@ -27,10 +27,14 @@ module Calabash
27
27
  screenshot_on_error: true
28
28
  }
29
29
 
30
+ # Returns the default wait options.
31
+ # @return [Hash] Key/value pairs describing the wait options.
30
32
  def self.default_options
31
33
  @@default_options
32
34
  end
33
35
 
36
+ # Sets the default wait options.
37
+ # @param [Hash] value The new default wait options.
34
38
  def self.default_options=(value)
35
39
  @@default_options = value
36
40
  end
data/lib/calabash.rb CHANGED
@@ -241,6 +241,7 @@ module Calabash
241
241
  @@has_set_embedding_context
242
242
  end
243
243
 
244
+ # @!visibility private
244
245
  def self.new_embed_method(method)
245
246
  define_method(:embed) do |*args|
246
247
  method.call(*args)
@@ -249,6 +250,7 @@ module Calabash
249
250
  @@has_set_embedding_context = true
250
251
  end
251
252
 
253
+ # @!visibility private
252
254
  def embed(*_)
253
255
  Logger.warn 'Embed is not available in this context. Will not embed.'
254
256
  end
@@ -264,9 +266,9 @@ unless Object.const_defined?(:IOS)
264
266
  end
265
267
 
266
268
  if Calabash::Environment::DEBUG_CALLED_METHODS
267
- $stdout.puts "#{Calabash::Color.red("Will print every Calabash method called!")}"
268
- $stdout.puts "#{Calabash::Color.red("Warning: This might slow down your test drastically")}"
269
- $stdout.puts "#{Calabash::Color.red("and is an experimental feature.")}"
269
+ $stdout.puts "#{Calabash::Color.red('Will print every Calabash method called!')}"
270
+ $stdout.puts "#{Calabash::Color.red('Warning: This might slow down your test drastically')}"
271
+ $stdout.puts "#{Calabash::Color.red('and is an experimental feature.')}"
270
272
 
271
273
  calabash_file = Calabash.method(:extended).source_location.first
272
274
  $__calabash_dir_name = File.dirname(calabash_file)
@@ -274,7 +276,7 @@ if Calabash::Environment::DEBUG_CALLED_METHODS
274
276
  trace_func = lambda do |event, file, line, id, binding, classname|
275
277
  if event == 'call'
276
278
  if classname.to_s.split('::').first == 'Calabash'
277
- binding_caller_locations = binding.eval("caller_locations")
279
+ binding_caller_locations = binding.eval('caller_locations')
278
280
  files = binding_caller_locations[3..-1].map(&:path)
279
281
 
280
282
  calabash_not_in_stacktrace = files.none? do |file|