calabash 1.9.9.pre3 → 2.0.0.prelegacy

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +10 -33
  3. data/bin/calabash +45 -36
  4. data/lib/calabash.rb +137 -13
  5. data/lib/calabash/android.rb +6 -0
  6. data/lib/calabash/android/adb.rb +25 -1
  7. data/lib/calabash/android/application.rb +14 -3
  8. data/lib/calabash/android/build/builder.rb +16 -3
  9. data/lib/calabash/android/build/java_keystore.rb +10 -0
  10. data/lib/calabash/android/build/resigner.rb +23 -1
  11. data/lib/calabash/android/build/test_server.rb +2 -0
  12. data/lib/calabash/android/defaults.rb +1 -0
  13. data/lib/calabash/android/device.rb +55 -3
  14. data/lib/calabash/android/environment.rb +10 -0
  15. data/lib/calabash/android/interactions.rb +106 -3
  16. data/lib/calabash/android/legacy.rb +143 -0
  17. data/lib/calabash/android/lib/TestServer.apk +0 -0
  18. data/lib/calabash/android/life_cycle.rb +6 -4
  19. data/lib/calabash/android/physical_buttons.rb +12 -1
  20. data/lib/calabash/android/screenshot.rb +1 -0
  21. data/lib/calabash/android/scroll.rb +115 -0
  22. data/lib/calabash/android/server.rb +3 -1
  23. data/lib/calabash/android/text.rb +16 -25
  24. data/lib/calabash/application.rb +29 -0
  25. data/lib/calabash/cli/build.rb +15 -1
  26. data/lib/calabash/cli/console.rb +9 -5
  27. data/lib/calabash/cli/generate.rb +5 -0
  28. data/lib/calabash/cli/helpers.rb +7 -1
  29. data/lib/calabash/cli/resign.rb +1 -0
  30. data/lib/calabash/cli/run.rb +10 -6
  31. data/lib/calabash/cli/setup_keystore.rb +2 -0
  32. data/lib/calabash/color.rb +7 -0
  33. data/lib/calabash/console_helpers.rb +4 -2
  34. data/lib/calabash/defaults.rb +1 -0
  35. data/lib/calabash/device.rb +8 -9
  36. data/lib/calabash/environment.rb +5 -0
  37. data/lib/calabash/gestures.rb +159 -66
  38. data/lib/calabash/http/retriable_client.rb +3 -1
  39. data/lib/calabash/interactions.rb +68 -5
  40. data/lib/calabash/ios.rb +4 -0
  41. data/lib/calabash/ios/application.rb +8 -1
  42. data/lib/calabash/ios/conditions.rb +3 -1
  43. data/lib/calabash/ios/date_picker.rb +412 -0
  44. data/lib/calabash/ios/defaults.rb +1 -0
  45. data/lib/calabash/ios/device.rb +1 -0
  46. data/lib/calabash/ios/device/device_implementation.rb +33 -16
  47. data/lib/calabash/ios/device/gestures_mixin.rb +202 -48
  48. data/lib/calabash/ios/device/ipad_1x_2x_mixin.rb +253 -0
  49. data/lib/calabash/ios/device/keyboard_mixin.rb +2 -0
  50. data/lib/calabash/ios/device/rotation_mixin.rb +11 -8
  51. data/lib/calabash/ios/device/routes/condition_route_mixin.rb +1 -0
  52. data/lib/calabash/ios/device/routes/handle_route_mixin.rb +5 -1
  53. data/lib/calabash/ios/device/routes/map_route_mixin.rb +1 -0
  54. data/lib/calabash/ios/device/routes/response_parser.rb +1 -0
  55. data/lib/calabash/ios/device/routes/uia_route_mixin.rb +44 -6
  56. data/lib/calabash/ios/device/runtime_attributes.rb +4 -5
  57. data/lib/calabash/ios/device/text_mixin.rb +2 -0
  58. data/lib/calabash/ios/device/uia_keyboard_mixin.rb +9 -0
  59. data/lib/calabash/ios/device/uia_mixin.rb +1 -0
  60. data/lib/calabash/ios/gestures.rb +82 -8
  61. data/lib/calabash/ios/interactions.rb +30 -1
  62. data/lib/calabash/ios/orientation.rb +21 -21
  63. data/lib/calabash/ios/runtime.rb +154 -2
  64. data/lib/calabash/ios/slider.rb +70 -0
  65. data/lib/calabash/ios/text.rb +11 -47
  66. data/lib/calabash/ios/uia.rb +24 -2
  67. data/lib/calabash/legacy.rb +7 -0
  68. data/lib/calabash/lib/skeleton/config/cucumber.yml +1 -3
  69. data/lib/calabash/lib/skeleton/features/support/dry_run.rb +8 -0
  70. data/lib/calabash/lib/skeleton/features/support/env.rb +15 -1
  71. data/lib/calabash/life_cycle.rb +78 -32
  72. data/lib/calabash/location.rb +2 -1
  73. data/lib/calabash/orientation.rb +0 -1
  74. data/lib/calabash/page.rb +51 -5
  75. data/lib/calabash/patch.rb +1 -0
  76. data/lib/calabash/patch/array.rb +7 -7
  77. data/lib/calabash/query.rb +17 -2
  78. data/lib/calabash/query_result.rb +14 -0
  79. data/lib/calabash/screenshot.rb +28 -8
  80. data/lib/calabash/text.rb +105 -8
  81. data/lib/calabash/utility.rb +6 -6
  82. data/lib/calabash/version.rb +1 -1
  83. data/lib/calabash/wait.rb +37 -11
  84. metadata +14 -7
@@ -0,0 +1,70 @@
1
+ module Calabash
2
+ module IOS
3
+
4
+ # An interface for interacting with UISliders.
5
+ module Slider
6
+
7
+ # Sets the value of the first UISliders matched by `query` to `value`.
8
+ #
9
+ # If `query` matches a view that is not a UISlider or UISlider subclass,
10
+ # an error will be raised.
11
+ #
12
+ # An error will be raised if more than on view is matched by `query`.
13
+ #
14
+ # To avoid matching more than one UISlider (or subclass):
15
+ # * Make the query more specific: "UISlider marked:'volume'"
16
+ # * Use the index language feature: "UISlider index:0"
17
+ #
18
+ # @example
19
+ # slider_set_value("UISlider marked:'office slider'", 2)
20
+ # slider_set_value("slider marked:'weather slider'", -1)
21
+ # slider_set_value("UISlider", 11)
22
+ #
23
+ # @param [String, Hash, Calabash::Query] query A query to that indicates
24
+ # in which slider to set the value.
25
+ # @param [Numeric] value The value to set the slider to. value.to_s should
26
+ # produce a String representation of a Number.
27
+ #
28
+ # @param [options] options Options to control the behavior of the gesture.
29
+ # @option options [Boolean] :animate (true) Animate the change.
30
+ # @option options [Boolean] :notify_targets (true) Simulate a UIEvent by
31
+ # calling every target/action pair defined on the UISlider matching
32
+ # `query`.
33
+ #
34
+ # @raise [RuntimeError] When `query` does not match exactly one slider.
35
+ # @raise [RuntimeError] When setting the value of the slider matched by
36
+ # `query` is not successful.
37
+ def slider_set_value(query, value, options={})
38
+ Query.ensure_valid_query(query)
39
+
40
+ default_options = {
41
+ :animate => true,
42
+ :notify_targets => true
43
+ }
44
+
45
+ merged_options = default_options.merge(options)
46
+
47
+ found_none = "Expected '#{query}' to match exactly one view, but found no matches."
48
+ query_object = Query.new(query)
49
+ wait_for(found_none) do
50
+ results = query(query_object)
51
+ if results.length > 1
52
+ message = [
53
+ "Expected '#{query}' to match exactly one view, but found '#{results.length}'",
54
+ results.join("\n")
55
+ ].join("\n")
56
+ fail(message)
57
+ else
58
+ results.length == 1
59
+ end
60
+ end
61
+
62
+ value_str = value.to_s
63
+
64
+ args = [merged_options[:animate], merged_options[:notify_targets]]
65
+
66
+ Device.default.map_route(query, :changeSlider, value_str, *args)
67
+ end
68
+ end
69
+ end
70
+ end
@@ -1,7 +1,6 @@
1
1
  module Calabash
2
2
  module IOS
3
3
  # Methods for entering text and interacting with iOS keyboards.
4
- # @!visibility private
5
4
  module Text
6
5
  # @!visibility private
7
6
  def _enter_text(text)
@@ -74,43 +73,6 @@ module Calabash
74
73
  Device.default.split_keyboard_visible?
75
74
  end
76
75
 
77
- # Returns true if there is a visible keyboard.
78
- #
79
- # @return [Boolean] Returns true if there is a visible keyboard.
80
- def keyboard_visible?
81
- docked_keyboard_visible? || undocked_keyboard_visible? || split_keyboard_visible?
82
- end
83
-
84
- # Waits for a keyboard to appear.
85
- #
86
- # @see Calabash::Wait.default_options
87
- #
88
- # @param [Number] timeout How long to wait for the keyboard.
89
- # @raise [Calabash::Wait::TimeoutError] Raises error if no keyboard
90
- # appears.
91
- def wait_for_keyboard(timeout=nil)
92
- keyboard_timeout = keyboard_wait_timeout(timeout)
93
- message = "Timed out after #{keyboard_timeout} seconds waiting for the keyboard to appear"
94
- wait_for(message, timeout: keyboard_timeout) do
95
- keyboard_visible?
96
- end
97
- end
98
-
99
- # Waits for the keyboard to disappear.
100
- #
101
- # @see Calabash::Wait.default_options
102
- #
103
- # @param [Number] timeout How log to wait for the keyboard to disappear.
104
- # @raise [Calabash::Wait::TimeoutError] Raises error if any keyboard is
105
- # visible after the `timeout`.
106
- def wait_for_no_keyboard(timeout=nil)
107
- keyboard_timeout = keyboard_wait_timeout(timeout)
108
- message = "Timed out after #{keyboard_timeout} seconds waiting for the keyboard to disappear"
109
- wait_for(message, timeout: keyboard_timeout) do
110
- !keyboard_visible?
111
- end
112
- end
113
-
114
76
  # Touches the keyboard action key.
115
77
  #
116
78
  # The action key depends on the keyboard. Some examples include:
@@ -128,11 +90,21 @@ module Calabash
128
90
  # @todo Refactor uia_route to a public API call
129
91
  # @todo Move this documentation to the public method
130
92
  # @!visibility private
131
- def _tap_current_keyboard_action_key
93
+ def _tap_keyboard_action_key(action_key)
94
+ unless action_key.nil?
95
+ raise ArgumentError,
96
+ "An iOS keyboard does not have multiple action keys"
97
+ end
98
+
132
99
  char_sequence = ESCAPED_KEYBOARD_CHARACTERS[:action]
133
100
  Device.default.uia_route("uia.keyboard().typeString('#{char_sequence}')")
134
101
  end
135
102
 
103
+ # @!visibility private
104
+ def _keyboard_visible?
105
+ docked_keyboard_visible? || undocked_keyboard_visible? || split_keyboard_visible?
106
+ end
107
+
136
108
  # Touches the keyboard delete key.
137
109
  #
138
110
  # The 'delete' key difficult to find and touch because its behavior
@@ -238,14 +210,6 @@ module Calabash
238
210
  #'International' => nil,
239
211
  #'More' => nil,
240
212
  }
241
-
242
- def keyboard_wait_timeout(timeout)
243
- if timeout.nil?
244
- Calabash::Gestures::DEFAULT_GESTURE_WAIT_TIMEOUT
245
- else
246
- timeout
247
- end
248
- end
249
213
  end
250
214
  end
251
215
  end
@@ -1,22 +1,44 @@
1
1
  module Calabash
2
2
  module IOS
3
- # @!visibility private
3
+
4
+ # Methods for interacting directly with Apple's UIAutomation API.
5
+ #
6
+ # https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/UsingtheAutomationInstrument/UsingtheAutomationInstrument.html
7
+ # https://developer.apple.com/library/ios/documentation/DeveloperTools/Reference/UIAutomationRef/
8
+ #
9
+ # Calabash iOS uses this API to perform gestures. It is sometimes helpful
10
+ # to drop down into this API to explore your app.
4
11
  module UIA
5
12
 
6
- # Evaluates `script` with Apple's UIAutomation API.
13
+ # Evaluates `script` using Apples's UIAutomation API.
7
14
  #
15
+ # @example
16
+ # uia("UIATarget.localTarget().shake()")
17
+ # uia("UIATarget.localTarget().frontMostApp().keyboard().buttons()['Delete']")
18
+ # uia("UIATarget.localTarget().frontMostApp().mainWindow().elements()")
8
19
  def uia(script)
9
20
  Device.default.evaluate_uia(script)
10
21
  end
11
22
 
23
+ # Evaluates `script` after prefixing with "UIATarget.localTarget()"
24
+ #
25
+ # @example
26
+ # uia_with_target("shake()")
12
27
  def uia_with_target(script)
13
28
  uia("UIATarget.localTarget().#{script}")
14
29
  end
15
30
 
31
+ # Evaluates `script` after prefixing with
32
+ # "UIATarget.localTarget().frontMostApp()"
33
+ #
34
+ # @example
35
+ # uia_with_app("keyboard().buttons()['Delete'])
16
36
  def uia_with_app(script)
17
37
  uia("UIATarget.localTarget().frontMostApp().#{script}")
18
38
  end
19
39
 
40
+ # Evaluates `script` after prefixing with
41
+ # "UIATarget.localTarget().frontMostApp().mainWindow()"
20
42
  def uia_with_main_window(script)
21
43
  uia("UIATarget.localTarget().frontMostApp().mainWindow().#{script}")
22
44
  end
@@ -0,0 +1,7 @@
1
+ module Calabash
2
+ class Application
3
+ def md5_checksum
4
+ 'samplechecksum'
5
+ end
6
+ end
7
+ end
@@ -1,6 +1,4 @@
1
1
  # config/cucumber.yml
2
2
  ##YAML Template
3
3
  ---
4
- # Platform
5
- android: PLATFORM=android -r features
6
- ios: PLATFORM=ios -r features
4
+ default: -r features
@@ -0,0 +1,8 @@
1
+ # Cucumber does not load env.rb when running a dry-run. As the pages inherit
2
+ # from Calabash::Page and assert that the scopes IOS and Android are defined,
3
+ # we should require calabash.
4
+
5
+ if ARGV.include?('--dry-run')
6
+ require 'calabash/android'
7
+ require 'calabash/ios'
8
+ end
@@ -1,7 +1,21 @@
1
1
  require 'calabash'
2
+ require 'calabash/android/application'
3
+ require 'calabash/ios/application'
2
4
 
3
5
  platform = ENV['PLATFORM']
4
6
 
7
+ unless platform
8
+ application = Calabash::Application.default_from_environment
9
+
10
+ if application.android_application?
11
+ platform = 'android'
12
+ elsif application.ios_application?
13
+ platform = 'ios'
14
+ else
15
+ raise "Application '#{application}' is neither an Android app or an iOS app"
16
+ end
17
+ end
18
+
5
19
  case platform
6
20
  when 'android'
7
21
  require 'calabash/android'
@@ -26,7 +40,7 @@ case platform
26
40
  [
27
41
  'ERROR! Unable to start the cucumber test:',
28
42
  message,
29
- "Use the profile 'android' or 'ios', or run cucumber using $ calabash run"
43
+ "Run cucumber with the ENV variable 'CAL_APP', or run cucumber using $ calabash run"
30
44
  ]
31
45
 
32
46
  Calabash::Logger.error(failure_messages.join("\n"))
@@ -1,58 +1,93 @@
1
1
  module Calabash
2
- # @!visibility private
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
3
10
  module LifeCycle
4
- def start_app(path_or_application = nil, **opt)
5
- path_or_application ||= Application.default
11
+ # Start the given application (and its test-server) on the port of
12
+ # {Calabash::Defaults#default_server Calabash.default_server}.
13
+ # This method will **not** install the application specified. If no
14
+ # application is given, it will start
15
+ # {Calabash::Defaults#default_application Calabash.default_application}
16
+ #
17
+ # @note This method will fail if the application (and test-server for
18
+ # Android) is not installed, or if the application installed is not the
19
+ # same as the one specified.
20
+ #
21
+ # @note On Android, if a test-server is already running on the port of
22
+ # {Calabash::Defaults#default_server Calabash.default_server} then that
23
+ # application will be shut down.
24
+ #
25
+ # @param [String, Calabash::Application] path_or_application A path to the
26
+ # application, or an instance of {Calabash::Application}.
27
+ # Defaults to
28
+ # {Calabash::Defaults#default_application Calabash.default_application}
29
+ # @param [Hash] options Options for specifying the details the app start
30
+ # @option options [Hash] :activity Android-only. Specify which activity
31
+ # to start. If none is given, launch the default launchable activity.
32
+ # @option options [Hash] :extras Android-only. Specify the extras for the
33
+ # startup intent.
34
+ def start_app(path_or_application = nil, **options)
35
+ path_or_application ||= Calabash.default_application
6
36
 
7
37
  unless path_or_application
8
- raise 'No application given, and Application.default is not set'
38
+ raise 'No application given, and Calabash.default_application is not set'
9
39
  end
10
40
 
11
- Device.default.start_app(path_or_application, opt.dup)
41
+ Device.default.start_app(path_or_application, options.dup)
12
42
  end
13
43
 
44
+ # Stop the app running on
45
+ # {Calabash::Defaults#default_server Calabash.default_server}
14
46
  def stop_app
15
47
  Device.default.stop_app
16
48
  end
17
49
 
18
50
  # Installs the given application. If the application is already installed,
19
51
  # the application will be uninstalled, and installed afterwards. If no
20
- # application is given, it will install `Application.default`.
52
+ # application is given, it will install
53
+ # {Calabash::Defaults#default_application Calabash.default_application}
21
54
  #
22
55
  # If the given application is an instance of
23
- # `Calabash::Android::Application`, the same procedure is executed for the
56
+ # {Calabash::Android::Application}, the same procedure is executed for the
24
57
  # test-server of the application, if it is set.
25
58
  #
26
59
  # @param [String, Calabash::Application] path_or_application A path to the
27
- # application, or an instance of `Calabash::Application`. Defaults to
28
- # `Application.default`
60
+ # application, or an instance of {Calabash::Application}.
61
+ # Defaults to
62
+ # {Calabash::Defaults#default_application Calabash.default_application}
29
63
  def install_app(path_or_application = nil)
30
- path_or_application ||= Application.default
64
+ path_or_application ||= Calabash.default_application
31
65
 
32
66
  unless path_or_application
33
- raise 'No application given, and Application.default is not set'
67
+ raise 'No application given, and Calabash.default_application is not set'
34
68
  end
35
69
 
36
70
  Device.default.install_app(path_or_application)
37
71
  end
38
72
 
39
73
  # Installs the given application *if it is not already installed*. If no
40
- # application is given, it will ensure `Application.default` is installed.
74
+ # application is given, it will ensure `Calabash.default_application` is installed.
41
75
  # If the application has changed, it will be installed using the same
42
- # approach as #{Calabash::LifeCycle#install_app}.
76
+ # approach as {#install_app}.
43
77
  #
44
78
  # If the given application is an instance of
45
- # `Calabash::Android::Application`, the same procedure is executed for the
79
+ # {Calabash::Android::Application}, the same procedure is executed for the
46
80
  # test-server of the application, if it is set.
47
81
  #
48
82
  # @param [String, Calabash::Application] path_or_application A path to the
49
- # application, or an instance of `Calabash::Application`. Defaults to
50
- # `Application.default`
83
+ # application, or an instance of {Calabash::Application}.
84
+ # Defaults to
85
+ # {Calabash::Defaults#default_application Calabash.default_application}
51
86
  def ensure_app_installed(path_or_application = nil)
52
- path_or_application ||= Application.default
87
+ path_or_application ||= Calabash.default_application
53
88
 
54
89
  unless path_or_application
55
- raise 'No application given, and Application.default is not set'
90
+ raise 'No application given, and Calabash.default_application is not set'
56
91
  end
57
92
 
58
93
  Device.default.ensure_app_installed(path_or_application)
@@ -60,16 +95,17 @@ module Calabash
60
95
 
61
96
  # Uninstalls the given application. Does nothing if the application is
62
97
  # already uninstalled. If no application is given, it will uninstall
63
- # `Application.default`.
98
+ # {Calabash::Defaults#default_application Calabash.default_application}
64
99
  #
65
100
  # @param [String, Calabash::Application] path_or_application A path to the
66
- # application, or an instance of `Calabash::Application`. Defaults to
67
- # `Application.default`
101
+ # application, or an instance of {Calabash::Application}.
102
+ # Defaults to
103
+ # {Calabash::Defaults#default_application Calabash.default_application}
68
104
  def uninstall_app(path_or_application = nil)
69
- path_or_application ||= Application.default
105
+ path_or_application ||= Calabash.default_application
70
106
 
71
107
  unless path_or_application
72
- raise 'No application given, and Application.default is not set'
108
+ raise 'No application given, and Calabash.default_application is not set'
73
109
  end
74
110
 
75
111
  Device.default.uninstall_app(path_or_application)
@@ -77,27 +113,37 @@ module Calabash
77
113
 
78
114
  # Clears the contents of the given application. This is roughly equivalent to
79
115
  # reinstalling the application. If no application is given, it will clear
80
- # `Application.default`.
116
+ # {Calabash::Defaults#default_application Calabash.default_application}.
81
117
  #
82
118
  # @param [String, Calabash::Application] path_or_application A path to the
83
- # application, or an instance of `Calabash::Application`. Defaults to
84
- # `Application.default`
119
+ # application, or an instance of {Calabash::Application}.
120
+ # Defaults to
121
+ # {Calabash::Defaults#default_application Calabash.default_application}
85
122
  def clear_app_data(path_or_application = nil)
86
- path_or_application ||= Application.default
123
+ path_or_application ||= Calabash.default_application
87
124
 
88
125
  unless path_or_application
89
- raise 'No application given, and Application.default is not set'
126
+ raise 'No application given, and Calabash.default_application is not set'
90
127
  end
91
128
 
92
129
  Device.default.clear_app_data(path_or_application)
93
130
  end
94
131
 
95
132
  # Sends the current app to the background and resumes it after
96
- # `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).
138
+ #
139
+ # On Android you can control the app lifecycle more granularity using
140
+ # {Calabash::Android::Interactions#go_home \#go_home} and
141
+ # {Calabash::Android::LifeCycle#resume_app \#resume_app}.
142
+ #
143
+ # @param [Numeric] for_seconds How long to keep the app to the background.
97
144
  #
98
- # On Android you can control the app lifecycle more granularly using
99
- # #{Calabash::Android::Interactions#go_home} and
100
- # #{Calabash::Android::LifeCycle#resume_app}.
145
+ # @raise [ArgumentError] On iOS, if number of seconds is less than 1 and
146
+ # more than 60 seconds.
101
147
  def send_current_app_to_background(for_seconds = 10)
102
148
  _send_current_app_to_background(for_seconds)
103
149