calabash 1.9.9.pre3 → 2.0.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
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
  #