calabash 1.9.9.pre3 → 2.0.0.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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +14 -0
  3. data/bin/calabash +45 -36
  4. data/lib/calabash/android/build/builder.rb +1 -1
  5. data/lib/calabash/android/build/resigner.rb +19 -1
  6. data/lib/calabash/android/device.rb +13 -2
  7. data/lib/calabash/android/interactions.rb +104 -3
  8. data/lib/calabash/android/lib/TestServer.apk +0 -0
  9. data/lib/calabash/android/life_cycle.rb +5 -4
  10. data/lib/calabash/android/physical_buttons.rb +4 -1
  11. data/lib/calabash/android/scroll.rb +5 -0
  12. data/lib/calabash/android/text.rb +10 -25
  13. data/lib/calabash/android.rb +3 -0
  14. data/lib/calabash/cli/generate.rb +2 -0
  15. data/lib/calabash/console_helpers.rb +4 -2
  16. data/lib/calabash/device.rb +1 -9
  17. data/lib/calabash/environment.rb +4 -0
  18. data/lib/calabash/gestures.rb +159 -66
  19. data/lib/calabash/http/retriable_client.rb +1 -1
  20. data/lib/calabash/interactions.rb +67 -5
  21. data/lib/calabash/ios/conditions.rb +0 -1
  22. data/lib/calabash/ios/device/device_implementation.rb +17 -5
  23. data/lib/calabash/ios/device/gestures_mixin.rb +202 -48
  24. data/lib/calabash/ios/device/rotation_mixin.rb +10 -8
  25. data/lib/calabash/ios/device/routes/handle_route_mixin.rb +5 -1
  26. data/lib/calabash/ios/device/runtime_attributes.rb +4 -5
  27. data/lib/calabash/ios/gestures.rb +82 -8
  28. data/lib/calabash/ios/orientation.rb +21 -21
  29. data/lib/calabash/ios/runtime.rb +146 -2
  30. data/lib/calabash/ios/slider.rb +70 -0
  31. data/lib/calabash/ios/text.rb +6 -2
  32. data/lib/calabash/ios/uia.rb +24 -2
  33. data/lib/calabash/ios.rb +2 -0
  34. data/lib/calabash/lib/skeleton/features/support/dry_run.rb +8 -0
  35. data/lib/calabash/life_cycle.rb +59 -30
  36. data/lib/calabash/location.rb +0 -1
  37. data/lib/calabash/orientation.rb +0 -1
  38. data/lib/calabash/page.rb +38 -5
  39. data/lib/calabash/patch/array.rb +7 -7
  40. data/lib/calabash/query.rb +17 -2
  41. data/lib/calabash/query_result.rb +10 -0
  42. data/lib/calabash/screenshot.rb +28 -8
  43. data/lib/calabash/text.rb +52 -8
  44. data/lib/calabash/utility.rb +3 -3
  45. data/lib/calabash/version.rb +1 -1
  46. data/lib/calabash/wait.rb +33 -11
  47. data/lib/calabash.rb +124 -13
  48. metadata +114 -111
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c93bdf73649617b8de5fe8e2e34fcf03a2f31f2e
4
- data.tar.gz: 187f1e60ca6bf8005efa47ee03a9f6896c169599
3
+ metadata.gz: c5f1a37cf3cb44cfb343b2824ad867a43b8ada5b
4
+ data.tar.gz: 37184436097bcf66b89307857ccddb35e014ecbc
5
5
  SHA512:
6
- metadata.gz: de02fd0467b70c2836fcca4859b803537365bf69ef6ae9c7f70f7f153ee877ecbaa1ec69a5941de2ba816874e9b9ad131af9b79642aef88c17a505d73df15af0
7
- data.tar.gz: cd2a3b11e0ce8dcbc31236346f483440cfd61cdb00b12124ccf9c8922ee0373f5f940d2ea3e902308fca6f47c4bb8405816d5b9c238a2ac3c5ab6ad67e38c438
6
+ metadata.gz: 0737e9ced39e5c585a8a030f1072c537f456bcf3d08f3e11a92fc99c794677fa10f8cbde32a79266ad2dbe25b2081e4abc3c3bca924c9f3162b7f25d423c1d94
7
+ data.tar.gz: 257460621c5e711e222e84e91f52c070da2ae1a12bda33386bd01ebb7148f9b9c5d05231dc3561bb4adee216f73f6d9bf14464dffdbebed5bfe8728fefc71cc0
data/README.md CHANGED
@@ -47,6 +47,20 @@ $ be rake spec # All tests. Launches iOS Simulators, etc.
47
47
  $ be guard # Run unit tests as you develop.
48
48
  ```
49
49
 
50
+ ### Cucumber Android
51
+
52
+ **NOTE** If you find you cannot launch on Android, be sure you run the
53
+ `copy\_repos` and `changing\_old\_files.sh` script.
54
+
55
+ ```
56
+ $ bundle update
57
+ $ rake android:build
58
+ $ cd cucumber/android
59
+ $ be calabash resign ../../spec/resources/android/xtc-android-sample.apk
60
+ $ be calabash build ../../spec/resources/android/xtc-android-sample.apk
61
+ $ be cucumber
62
+ ```
63
+
50
64
  ### Cucumber iOS
51
65
 
52
66
  ```
data/bin/calabash CHANGED
@@ -47,49 +47,58 @@ module Calabash
47
47
  def parse_arguments!
48
48
  argument = @arguments.shift
49
49
 
50
- case argument
51
- when '-v', '--verbose'
52
- @options[:verbose] = true
53
- Logger.log_levels += [:debug]
54
- parse_arguments!
55
- when '--platform'
56
- platform = @arguments.shift.downcase
50
+ begin
51
+ case argument
52
+ when '-v', '--verbose'
53
+ @options[:verbose] = true
54
+ Logger.log_levels += [:debug]
55
+ parse_arguments!
56
+ when '--platform'
57
+ platform = @arguments.shift.downcase
57
58
 
58
- fail("Invalid specified platform '#{platform}'") unless platform == 'android' || platform == 'ios'
59
+ fail("Invalid specified platform '#{platform}'") unless platform == 'android' || platform == 'ios'
59
60
 
60
- set_platform!(platform.to_sym)
61
+ set_platform!(platform.to_sym)
61
62
 
62
- parse_arguments!
63
- when 'version'
64
- puts Calabash::VERSION
65
- when 'build'
66
- parse_build_arguments!
67
- when 'resign'
68
- parse_resign_arguments!
69
- when 'console'
70
- parse_console_arguments!
71
- when 'generate'
72
- parse_generate_arguments!
73
- when 'run'
74
- parse_run_arguments!
75
- when 'setup-keystore'
76
- parse_setup_keystore_arguments!
77
- when 'help'
78
- argument = @arguments.shift
63
+ parse_arguments!
64
+ when 'version'
65
+ puts Calabash::VERSION
66
+ when 'build'
67
+ parse_build_arguments!
68
+ when 'resign'
69
+ parse_resign_arguments!
70
+ when 'console'
71
+ parse_console_arguments!
72
+ when 'generate'
73
+ parse_generate_arguments!
74
+ when 'run'
75
+ parse_run_arguments!
76
+ when 'setup-keystore'
77
+ parse_setup_keystore_arguments!
78
+ when 'help'
79
+ argument = @arguments.shift
79
80
 
80
- if argument.nil?
81
- print_usage
82
- else
83
- if key_for_command(argument)
84
- print_usage_for(key_for_command(argument))
81
+ if argument.nil?
82
+ print_usage
85
83
  else
86
- fail("No such command '#{argument}'")
84
+ if key_for_command(argument)
85
+ print_usage_for(key_for_command(argument))
86
+ else
87
+ fail("No such command '#{argument}'")
88
+ end
87
89
  end
88
- end
89
- when nil
90
- print_usage
90
+ when nil
91
+ print_usage
92
+ else
93
+ fail("Invalid command #{argument}.\n For help use 'calabash help'")
94
+ end
95
+ rescue => e
96
+ if Logger.log_levels.include?(:debug)
97
+ raise e
91
98
  else
92
- fail("Invalid command #{argument}.\n For help use 'calabash help'")
99
+ puts "#{Color.red(e.message)}"
100
+ exit 1
101
+ end
93
102
  end
94
103
  end
95
104
  end
@@ -37,7 +37,7 @@ module Calabash
37
37
  end
38
38
  @logger.log ""
39
39
  @logger.log "You can resign the app with #{keystores.first.location} by running:
40
- calabash resign #{@application_path}"
40
+ calabash resign \"#{@application_path}\""
41
41
 
42
42
  @logger.log ""
43
43
  @logger.log "Notice that resigning an app might break some functionality."
@@ -27,7 +27,25 @@ module Calabash
27
27
  end
28
28
 
29
29
  def unsign(unsigned_path)
30
- files_to_remove = `"#{Environment.aapt_path}" list "#{unsigned_path}"`.lines.collect(&:strip).grep(/^META-INF\//)
30
+ meta_files = `"#{Environment.aapt_path}" list "#{unsigned_path}"`.lines.collect(&:strip).grep(/^META-INF\//)
31
+
32
+ signing_file_names = ['.mf', '.rsa', '.dsa', '.ec', '.sf']
33
+
34
+ files_to_remove = meta_files.select do |file|
35
+ # other will be:
36
+ # META-INF/foo/bar
37
+ # other #=> bar
38
+ directory, file_name, other = file.split('/')
39
+
40
+ if other != nil || file_name.nil?
41
+ false
42
+ else
43
+ if signing_file_names.include?(File.extname(file_name).downcase)
44
+ true
45
+ end
46
+ end
47
+ end
48
+
31
49
  if files_to_remove.empty?
32
50
  @logger.log "App wasn't signed. Will not try to unsign it.", :debug
33
51
  else
@@ -157,7 +157,13 @@ module Calabash
157
157
 
158
158
  request = HTTP::Request.new('map', params_for_request(parameters))
159
159
 
160
- result = JSON.parse(http_client.get(request).body)
160
+ http_result = if method_name == :flash
161
+ http_client.get(request, timeout: 30)
162
+ else
163
+ http_client.get(request)
164
+ end
165
+
166
+ result = JSON.parse(http_result.body)
161
167
 
162
168
  if result['outcome'] != 'SUCCESS'
163
169
  raise "mapping \"#{query}\" with \"#{method_name}\" failed because: #{result['reason']}\n#{result['details']}"
@@ -819,9 +825,14 @@ module Calabash
819
825
  gesture.gestures.first.touches[0].query = query_from
820
826
  gesture.gestures.first.touches[1].query = query_to
821
827
 
822
- execute_gesture(Gestures::Gesture.with_parameters(gesture,
828
+ result = execute_gesture(Gestures::Gesture.with_parameters(gesture,
823
829
  query: query_to,
824
830
  timeout: options[:timeout]))
831
+
832
+ {
833
+ :from => Calabash::QueryResult.create(result[0], query_from),
834
+ :to => Calabash::QueryResult.create(result[1], query_to)
835
+ }
825
836
  end
826
837
 
827
838
  # @!visibility private
@@ -1,10 +1,12 @@
1
+ require 'date'
2
+ require 'time'
3
+
1
4
  module Calabash
2
5
  module Android
3
- # @!visibility private
4
6
  module Interactions
5
- # Go back.
7
+ # Go back. If the keyboard is shown, it will be dismissed.
6
8
  def go_back
7
- dismiss_keyboard
9
+ Device.default.perform_action('hide_soft_keyboard')
8
10
  press_back_button
9
11
  end
10
12
 
@@ -37,6 +39,105 @@ module Calabash
37
39
  Device.default.current_focus[:package]
38
40
  end
39
41
 
42
+ # Sets the date of the first visible date picker widget.
43
+ #
44
+ # @example
45
+ # set_date('2012-04-24')
46
+ #
47
+ # @example
48
+ # date = Date.parse('3rd Feb 2012')
49
+ # set_date(date)
50
+ #
51
+ # @param [Date, String] date The date to set. If given a String,
52
+ # `Date.parse` is called on the string.
53
+ #
54
+ # @see #set_date_in
55
+ def set_date(date)
56
+ set_date_in("android.widget.DatePicker index:0", date)
57
+ end
58
+
59
+ # Sets the date of a date picker widget. If `query` matches multiple date
60
+ # pickers, the date is set for all of them.
61
+ #
62
+ # @param [String, Hash, Calabash::Query] query The query to match the
63
+ # date picker.
64
+ # @param [Date, String] date The date to set. If given a String,
65
+ # `Date.parse` is called on the string.
66
+ # @see #set_date
67
+ def set_date_in(query, date)
68
+ if date.is_a?(String)
69
+ date = Date.parse(date)
70
+ end
71
+
72
+ wait_for_view(query, timeout: Calabash::Gestures::DEFAULT_GESTURE_WAIT_TIMEOUT)
73
+ result = query(query, updateDate: [date.year, date.month, date.day])
74
+
75
+ if result.length != 1
76
+ raise "Failed to set the date of '#{query}'"
77
+ end
78
+
79
+ if result.first.is_a?(Hash) && result.first.has_key?('error')
80
+ raise result.first['error']
81
+ end
82
+
83
+ true
84
+ end
85
+
86
+ # Sets the time of the first visible time picker widget.
87
+ #
88
+ # @example
89
+ # set_time('14:42')
90
+ #
91
+ # @example
92
+ # time = Time.parse('8:30 AM')
93
+ # set_time(time)
94
+ #
95
+ # @param [Time, String] time The time to set. If given a String,
96
+ # `Time.parse` is called on the string.
97
+ #
98
+ # @see #set_time_in
99
+ def set_time(time)
100
+ set_time_in("android.widget.TimePicker index:0", time)
101
+ end
102
+
103
+ # Sets the time of a time picker widget. If `query` matches multiple time
104
+ # pickers, the time is set for all of them.
105
+ #
106
+ # @param [String, Hash, Calabash::Query] query The query to match the
107
+ # time picker.
108
+ # @param [Time, String] time The time to set. If given a String,
109
+ # `Time.parse` is called on the string.
110
+ # @see #set_time
111
+ def set_time_in(query, time)
112
+ if time.is_a?(String)
113
+ time = Time.parse(time)
114
+ end
115
+
116
+ wait_for_view(query, timeout: Calabash::Gestures::DEFAULT_GESTURE_WAIT_TIMEOUT)
117
+ result = query(query, setCurrentHour: time.hour)
118
+
119
+ if result.length != 1
120
+ raise "Failed to set the time of '#{query}'"
121
+ end
122
+
123
+ if result.first.is_a?(Hash) && result.first.has_key?('error')
124
+ raise result.first['error']
125
+ end
126
+
127
+ result = query(query, setCurrentMinute: time.min)
128
+
129
+ if result.length != 1
130
+ raise "Failed to set the time of '#{query}'"
131
+ end
132
+
133
+ if result.first.is_a?(Hash) && result.first.has_key?('error')
134
+ raise result.first['error']
135
+ end
136
+
137
+ true
138
+ end
139
+
140
+
40
141
  # @!visibility private
41
142
  def _evaluate_javascript_in(query, javascript)
42
143
  Device.default.evaluate_javascript_in(query, javascript)
@@ -1,16 +1,18 @@
1
1
  module Calabash
2
2
  module Android
3
- # @!visibility private
4
3
  module LifeCycle
5
4
  # Resume an application. If the application is already focused, nothing
6
5
  # will happen.
7
6
  #
8
7
  # @example
9
8
  # go_home
9
+ # # Do something
10
10
  # resume_app
11
11
  #
12
- # @param [String, Calabash::Application] path_or_application The
13
- # application to resume.
12
+ # @param [String, Calabash::Application] path_or_application A path to the
13
+ # application, or an instance of {Calabash::Application}.
14
+ # Defaults to
15
+ # {Calabash::Defaults#default_application Calabash.default_application}
14
16
  def resume_app(path_or_application = nil)
15
17
  path_or_application ||= Application.default
16
18
 
@@ -23,7 +25,6 @@ module Calabash
23
25
  true
24
26
  end
25
27
 
26
-
27
28
  # @!visibility private
28
29
  def _send_current_app_to_background(for_seconds)
29
30
  package = focused_package
@@ -1,9 +1,12 @@
1
1
  module Calabash
2
2
  module Android
3
+ # Simulates pressing a *physical* button on the device. Use these methods
4
+ # carefully, as only a few devices have hardware key input. They can,
5
+ # however, be very useful for testing behaviour that would be hard to
6
+ # replicate otherwise.
3
7
  # @!visibility private
4
8
  module PhysicalButtons
5
9
 
6
- # @todo: Add note about this class being easily abused
7
10
  def press_button(key)
8
11
  Device.default.perform_action('press_key', key)
9
12
  true
@@ -0,0 +1,5 @@
1
+ module Calabash
2
+ module Android
3
+
4
+ end
5
+ end
@@ -1,31 +1,12 @@
1
1
  module Calabash
2
2
  module Android
3
- # @!visibility private
4
3
  module Text
4
+ # Dismisses the current keyboard. This is equivalent to the user
5
+ # pressing the back button if the keyboard is showing. If the keyboard is
6
+ # already hidden/dismissed, nothing is done.
5
7
  def dismiss_keyboard
6
8
  Device.default.perform_action('hide_soft_keyboard')
7
- end
8
-
9
- # Taps a keyboard action key on the keyboard. Notice that Calabash does
10
- # not ensure that this particular action key is actually available on the
11
- # current keyboard.
12
- #
13
- # @example
14
- # tap_keyboard_action_key(:normal)
15
- # tap_keyboard_action_key(:unspecified)
16
- # tap_keyboard_action_key(:none)
17
- # tap_keyboard_action_key(:go)
18
- # tap_keyboard_action_key(:search)
19
- # tap_keyboard_action_key(:send)
20
- # tap_keyboard_action_key(:next)
21
- # tap_keyboard_action_key(:done)
22
- # tap_keyboard_action_key(:previous)
23
- #
24
- # @see http://developer.android.com/reference/android/view/inputmethod/EditorInfo.html
25
- #
26
- # @param [Symbol] action_key The key to press.
27
- def tap_keyboard_action_key(action_key)
28
- Device.default.perform_action('press_user_action_button', action_key.to_s)
9
+ sleep 0.5
29
10
  end
30
11
 
31
12
  # @!visibility private
@@ -53,8 +34,12 @@ module Calabash
53
34
  end
54
35
 
55
36
  # @!visibility private
56
- def _tap_current_keyboard_action_key
57
- Device.default.perform_action('press_user_action_button')
37
+ def _tap_keyboard_action_key(action_key)
38
+ if action_key.nil?
39
+ Device.default.perform_action('press_user_action_button')
40
+ else
41
+ Device.default.perform_action('press_user_action_button', action_key.to_s)
42
+ end
58
43
  end
59
44
  end
60
45
  end
@@ -1,8 +1,11 @@
1
1
  module Calabash
2
2
  # Contains the Android implementations of the Calabash APIs.
3
3
  module Android
4
+ # @!visibility private
4
5
  TEST_SERVER_CODE_PATH = File.join(File.dirname(__FILE__), '..', '..', 'android', 'test-server')
6
+ # @!visibility private
5
7
  UNSIGNED_TEST_SERVER_APK = File.join(File.dirname(__FILE__), 'android', 'lib', 'TestServer.apk')
8
+ # @!visibility private
6
9
  ANDROID_MANIFEST_PATH = File.join(File.dirname(__FILE__), 'android', 'lib', 'AndroidManifest.xml')
7
10
 
8
11
  require 'calabash'
@@ -22,6 +22,7 @@ module Calabash
22
22
  cucumber_config = File.read(file(File.join('config', 'cucumber.yml')))
23
23
 
24
24
  env = File.read(file(File.join('features', 'support', 'env.rb')))
25
+ dry_run = File.read(file(File.join('features', 'support', 'dry_run.rb')))
25
26
  sample_feature = File.read(file(File.join('features', 'sample.feature')))
26
27
  calabash_steps = File.read(file(File.join('features', 'step_definitions', 'calabash_steps.rb')))
27
28
 
@@ -46,6 +47,7 @@ module Calabash
46
47
  File.open(File.join('features', 'step_definitions', 'calabash_steps.rb'), 'w') {|file| file.write(calabash_steps) }
47
48
  File.open(File.join('features', 'support', 'hooks.rb'), 'w') {|file| file.write(hooks) }
48
49
  File.open(File.join('features', 'support', 'env.rb'), 'w') {|file| file.write(env) }
50
+ File.open(File.join('features', 'support', 'dry_run.rb'), 'w') {|file| file.write(dry_run) }
49
51
 
50
52
  gemfile = File.readlines(file(File.join('Gemfile')))
51
53
 
@@ -4,7 +4,6 @@ module Calabash
4
4
 
5
5
  # Methods you can use in the Calabash console to help you
6
6
  # interact with your app.
7
- # @!visibility private
8
7
  module ConsoleHelpers
9
8
 
10
9
  # Outputs all visible elements as a tree.
@@ -30,13 +29,15 @@ module Calabash
30
29
  true
31
30
  end
32
31
 
33
- # Clear the console.
32
+ # Clear the console history. Note that this also clears the contents
33
+ # given to Calabash::ConsoleHelpers#copy.
34
34
  def clear
35
35
  ConsoleHelpers.clear
36
36
  true
37
37
  end
38
38
 
39
39
  # Puts a message of the day.
40
+ # @!visibility private
40
41
  def message_of_the_day
41
42
  messages = [
42
43
  "Let's get this done!",
@@ -141,6 +142,7 @@ module Calabash
141
142
  readline_history.last(length)
142
143
  end
143
144
 
145
+ # @!visibility private
144
146
  FILTER_REGEX = Regexp.union(/\s*copy(\(|\z)/, /\s*tree(\(|\z)/,
145
147
  /\s*flash(\(|\z)/, /\s*classes(\(|\z)/,
146
148
  /\s*ids(\(|\z)/, /\s*start_app(\(|\z)/,
@@ -138,9 +138,6 @@ module Calabash
138
138
  gesture_options[:at] ||= {}
139
139
  gesture_options[:at][:x] ||= 50
140
140
  gesture_options[:at][:y] ||= 50
141
- gesture_options[:offset] ||= {}
142
- gesture_options[:offset][:x] ||= 0
143
- gesture_options[:offset][:y] ||= 0
144
141
  gesture_options[:timeout] ||= Calabash::Gestures::DEFAULT_GESTURE_WAIT_TIMEOUT
145
142
 
146
143
  _tap(query, gesture_options)
@@ -156,9 +153,6 @@ module Calabash
156
153
  gesture_options[:at] ||= {}
157
154
  gesture_options[:at][:x] ||= 50
158
155
  gesture_options[:at][:y] ||= 50
159
- gesture_options[:offset] ||= {}
160
- gesture_options[:offset][:x] ||= 0
161
- gesture_options[:offset][:y] ||= 0
162
156
  gesture_options[:timeout] ||= Calabash::Gestures::DEFAULT_GESTURE_WAIT_TIMEOUT
163
157
 
164
158
  _double_tap(query, gesture_options)
@@ -174,9 +168,6 @@ module Calabash
174
168
  gesture_options[:at] ||= {}
175
169
  gesture_options[:at][:x] ||= 50
176
170
  gesture_options[:at][:y] ||= 50
177
- gesture_options[:offset] ||= {}
178
- gesture_options[:offset][:x] ||= 0
179
- gesture_options[:offset][:y] ||= 0
180
171
  gesture_options[:timeout] ||= Calabash::Gestures::DEFAULT_GESTURE_WAIT_TIMEOUT
181
172
  gesture_options[:duration] ||= 1
182
173
 
@@ -237,6 +228,7 @@ module Calabash
237
228
  end
238
229
 
239
230
  gesture_options = options.dup
231
+ gesture_options[:duration] ||= 0.5
240
232
  gesture_options[:timeout] ||= Calabash::Gestures::DEFAULT_GESTURE_WAIT_TIMEOUT
241
233
 
242
234
  _pinch(direction, query, gesture_options)
@@ -30,6 +30,10 @@ module Calabash
30
30
  # Is Calabash running in debug mode. True if $CAL_DEBUG is '1'
31
31
  DEBUG = variable('CAL_DEBUG') == '1'
32
32
 
33
+ # @!visibility private
34
+ # Experimental! Print every method that is called in Calabash
35
+ DEBUG_CALLED_METHODS = variable('CAL_DEBUG_CALLED_METHODS') == '1'
36
+
33
37
  # The path of the default app under test. This value is used if no app is
34
38
  # given from the command line. e.g. $ calabash run.
35
39
  #